Fix issues with static inline headers
This commit is contained in:
parent
2add318826
commit
3256600653
12 changed files with 829 additions and 393 deletions
|
|
@ -1,5 +1,4 @@
|
|||
{.emit:"typedef __uint128_t NU128; typedef __int128_t NI128;".}
|
||||
|
||||
import strutils
|
||||
# Capacity of 42 because it seems
|
||||
# reasonable that the number will fit.
|
||||
# If it doesn't, nim will just allocate
|
||||
|
|
@ -7,11 +6,11 @@
|
|||
const STRING_CAPACITY = 42
|
||||
|
||||
type
|
||||
s128* {.importc: "NI128"} = object
|
||||
s128* {.importc: "__int128_t"} = object
|
||||
high: int64
|
||||
low: uint64
|
||||
|
||||
u128* {.importc: "NU128"} = object
|
||||
u128* {.importc: "__uint128_t"} = object
|
||||
high, low: uint64
|
||||
|
||||
helperInt128 = object
|
||||
|
|
@ -327,6 +326,9 @@ proc `$`*(val: s128): string =
|
|||
|
||||
result = str
|
||||
|
||||
proc toHex*(val: u128): string =
|
||||
result = val.hi.toHex & val.lo.toHex
|
||||
|
||||
proc `$`*(val: u128): string =
|
||||
var v = val
|
||||
|
||||
|
|
|
|||
|
|
@ -6,9 +6,13 @@
|
|||
*/
|
||||
#pragma once
|
||||
#include "../types.h"
|
||||
|
||||
|
||||
/**
|
||||
* @brief Gets the thread local storage buffer.
|
||||
* @return The thread local storage buffer.
|
||||
*/
|
||||
static inline void* armGetTls(void);
|
||||
static inline void* armGetTls(void) {
|
||||
void* ret;
|
||||
__asm__ ("mrs %x[data], tpidrro_el0" : [data] "=r" (ret));
|
||||
return ret;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,13 +7,13 @@
|
|||
*/
|
||||
#pragma once
|
||||
#include "../types.h"
|
||||
|
||||
|
||||
/// Converts red, green, blue, and alpha components to packed RGBA8.
|
||||
#define RGBA8(r,g,b,a) (((r)&0xff)|(((g)&0xff)<<8)|(((b)&0xff)<<16)|(((a)&0xff)<<24))
|
||||
|
||||
|
||||
/// Same as \ref RGBA8 except with alpha=0xff.
|
||||
#define RGBA8_MAXALPHA(r,g,b) RGBA8(r,g,b,0xff)
|
||||
|
||||
|
||||
/// GfxMode set by \ref gfxSetMode. The default is GfxMode_LinearDouble. Note that the text-console (see console.h) sets this to GfxMode_TiledDouble.
|
||||
typedef enum
|
||||
{
|
||||
|
|
@ -21,21 +21,21 @@ typedef enum
|
|||
GfxMode_TiledDouble, ///< Double-buffering with raw tiled (block-linear) framebuffer.
|
||||
GfxMode_LinearDouble ///< Double-buffering with linear framebuffer, which is transferred to the actual framebuffer by \ref gfxFlushBuffers().
|
||||
} GfxMode;
|
||||
|
||||
|
||||
/// Framebuffer pixel-format is RGBA8888, there's no known way to change this.
|
||||
|
||||
|
||||
/**
|
||||
* @brief Initializes the graphics subsystem.
|
||||
* @warning Do not use \ref viInitialize when using this function.
|
||||
*/
|
||||
void gfxInitDefault(void);
|
||||
|
||||
|
||||
/**
|
||||
* @brief Uninitializes the graphics subsystem.
|
||||
* @warning Do not use \ref viExit when using this function.
|
||||
*/
|
||||
void gfxExit(void);
|
||||
|
||||
|
||||
/**
|
||||
* @brief Sets the resolution to be used when initializing the graphics subsystem.
|
||||
* @param[in] width Horizontal resolution, in pixels.
|
||||
|
|
@ -46,10 +46,10 @@ void gfxExit(void);
|
|||
* @note The width and height are aligned to 4.
|
||||
*/
|
||||
void gfxInitResolution(u32 width, u32 height);
|
||||
|
||||
|
||||
/// Wrapper for \ref gfxInitResolution with resolution=1080p. Use this if you want to support 1080p or >720p in docked-mode.
|
||||
void gfxInitResolutionDefault(void);
|
||||
|
||||
|
||||
/// Configure framebuffer crop, by default crop is all-zero. Use all-zero input to reset to default. \ref gfxExit resets this to the default.
|
||||
/// When the input is invalid this returns without changing the crop data, this includes the input values being larger than the framebuf width/height.
|
||||
/// This will update the display width/height returned by \ref gfxGetFramebuffer, with that width/height being reset to the default when required.
|
||||
|
|
@ -57,44 +57,61 @@ void gfxInitResolutionDefault(void);
|
|||
/// The new crop config will not take affect with double-buffering disabled. When used during frame-drawing, this should be called before \ref gfxGetFramebuffer.
|
||||
/// The right and bottom params are aligned to 4.
|
||||
void gfxConfigureCrop(s32 left, s32 top, s32 right, s32 bottom);
|
||||
|
||||
|
||||
/// Wrapper for \ref gfxConfigureCrop. Use this to set the resolution, within the bounds of the maximum resolution. Use all-zero input to reset to default.
|
||||
void gfxConfigureResolution(s32 width, s32 height);
|
||||
|
||||
|
||||
/// If enabled, \ref gfxConfigureResolution will be used with the input resolution for the current OperationMode. Then \ref gfxConfigureResolution will automatically be used with the specified resolution each time OperationMode changes.
|
||||
void gfxConfigureAutoResolution(bool enable, s32 handheld_width, s32 handheld_height, s32 docked_width, s32 docked_height);
|
||||
|
||||
|
||||
/// Wrapper for \ref gfxConfigureAutoResolution. handheld_resolution=720p, docked_resolution={all-zero for using current maximum resolution}.
|
||||
void gfxConfigureAutoResolutionDefault(bool enable);
|
||||
|
||||
|
||||
/// Waits for vertical sync.
|
||||
void gfxWaitForVsync(void);
|
||||
|
||||
|
||||
/// Swaps the framebuffers (for double-buffering).
|
||||
void gfxSwapBuffers(void);
|
||||
|
||||
|
||||
/// Get the current framebuffer address, with optional output ptrs for the display framebuffer width/height. The display width/height is adjusted by \ref gfxConfigureCrop and \ref gfxConfigureResolution.
|
||||
u8* gfxGetFramebuffer(u32* width, u32* height);
|
||||
|
||||
|
||||
/// Get the framebuffer width/height without crop.
|
||||
void gfxGetFramebufferResolution(u32* width, u32* height);
|
||||
|
||||
|
||||
/// Use this to get the actual byte-size of the framebuffer for use with memset/etc.
|
||||
size_t gfxGetFramebufferSize(void);
|
||||
|
||||
|
||||
/// Sets the \ref GfxMode.
|
||||
void gfxSetMode(GfxMode mode);
|
||||
|
||||
|
||||
/// Controls whether a vertical-flip is done when determining the pixel-offset within the actual framebuffer. By default this is enabled.
|
||||
void gfxSetDrawFlip(bool flip);
|
||||
|
||||
|
||||
/// Configures transform. See the NATIVE_WINDOW_TRANSFORM_* enums in buffer_producer.h. The default is NATIVE_WINDOW_TRANSFORM_FLIP_V.
|
||||
void gfxConfigureTransform(u32 transform);
|
||||
|
||||
|
||||
/// Flushes the framebuffer in the data cache. When \ref GfxMode is GfxMode_LinearDouble, this also transfers the linear-framebuffer to the actual framebuffer.
|
||||
void gfxFlushBuffers(void);
|
||||
|
||||
|
||||
/// Use this to get the pixel-offset in the framebuffer. Returned value is in pixels, not bytes.
|
||||
/// This implements tegra blocklinear, with hard-coded constants etc.
|
||||
/// Do not use this when \ref GfxMode is GfxMode_LinearDouble.
|
||||
static inline u32 gfxGetFramebufferDisplayOffset(u32 x, u32 y);
|
||||
static inline u32 gfxGetFramebufferDisplayOffset(u32 x, u32 y) {
|
||||
u32 tmp_pos;
|
||||
|
||||
extern size_t g_gfx_framebuf_aligned_width;
|
||||
extern size_t g_gfx_framebuf_display_height;
|
||||
extern bool g_gfx_drawflip;
|
||||
|
||||
//if (x >= g_gfx_framebuf_width || y >= g_gfx_framebuf_display_height) return (gfxGetFramebufferSize()-4)/4;//Return the last pixel-offset in the buffer, the data located here is not displayed due to alignment. (Disabled for perf)
|
||||
|
||||
if (g_gfx_drawflip) y = g_gfx_framebuf_display_height-1-y;
|
||||
|
||||
tmp_pos = ((y & 127) / 16) + (x/16*8) + ((y/16/8)*(g_gfx_framebuf_aligned_width/16*8));
|
||||
tmp_pos *= 16*16 * 4;
|
||||
|
||||
tmp_pos += ((y%16)/8)*512 + ((x%16)/8)*256 + ((y%8)/2)*64 + ((x%8)/4)*32 + (y%2)*16 + (x%4)*4;//This line is a modified version of code from the Tegra X1 datasheet.
|
||||
|
||||
return tmp_pos / 4;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,46 +2,46 @@
|
|||
|
||||
//The below defines are based on Linux kernel ioctl.h.
|
||||
|
||||
#define UNV_IOC_NRBITS 8
|
||||
#define UNV_IOC_TYPEBITS 8
|
||||
#define UNV_IOC_SIZEBITS 14
|
||||
#define UNV_IOC_DIRBITS 2
|
||||
#define _NV_IOC_NRBITS 8
|
||||
#define _NV_IOC_TYPEBITS 8
|
||||
#define _NV_IOC_SIZEBITS 14
|
||||
#define _NV_IOC_DIRBITS 2
|
||||
|
||||
#define UNV_IOC_NRMASK ((1 << UNV_IOC_NRBITS)-1)
|
||||
#define UNV_IOC_TYPEMASK ((1 << UNV_IOC_TYPEBITS)-1)
|
||||
#define UNV_IOC_SIZEMASK ((1 << UNV_IOC_SIZEBITS)-1)
|
||||
#define UNV_IOC_DIRMASK ((1 << UNV_IOC_DIRBITS)-1)
|
||||
#define _NV_IOC_NRMASK ((1 << _NV_IOC_NRBITS)-1)
|
||||
#define _NV_IOC_TYPEMASK ((1 << _NV_IOC_TYPEBITS)-1)
|
||||
#define _NV_IOC_SIZEMASK ((1 << _NV_IOC_SIZEBITS)-1)
|
||||
#define _NV_IOC_DIRMASK ((1 << _NV_IOC_DIRBITS)-1)
|
||||
|
||||
#define UNV_IOC_NRSHIFT 0
|
||||
#define UNV_IOC_TYPESHIFT (UNV_IOC_NRSHIFT+UNV_IOC_NRBITS)
|
||||
#define UNV_IOC_SIZESHIFT (UNV_IOC_TYPESHIFT+UNV_IOC_TYPEBITS)
|
||||
#define UNV_IOC_DIRSHIFT (UNV_IOC_SIZESHIFT+UNV_IOC_SIZEBITS)
|
||||
#define _NV_IOC_NRSHIFT 0
|
||||
#define _NV_IOC_TYPESHIFT (_NV_IOC_NRSHIFT+_NV_IOC_NRBITS)
|
||||
#define _NV_IOC_SIZESHIFT (_NV_IOC_TYPESHIFT+_NV_IOC_TYPEBITS)
|
||||
#define _NV_IOC_DIRSHIFT (_NV_IOC_SIZESHIFT+_NV_IOC_SIZEBITS)
|
||||
|
||||
/*
|
||||
* Direction bits.
|
||||
*/
|
||||
#define UNV_IOC_NONE 0U
|
||||
#define UNV_IOC_WRITE 1U
|
||||
#define UNV_IOC_READ 2U
|
||||
#define _NV_IOC_NONE 0U
|
||||
#define _NV_IOC_WRITE 1U
|
||||
#define _NV_IOC_READ 2U
|
||||
|
||||
#define UNV_IOC(dir,type,nr,size) \
|
||||
(((dir) << UNV_IOC_DIRSHIFT) | \
|
||||
((type) << UNV_IOC_TYPESHIFT) | \
|
||||
((nr) << UNV_IOC_NRSHIFT) | \
|
||||
((size) << UNV_IOC_SIZESHIFT))
|
||||
#define _NV_IOC(dir,type,nr,size) \
|
||||
(((dir) << _NV_IOC_DIRSHIFT) | \
|
||||
((type) << _NV_IOC_TYPESHIFT) | \
|
||||
((nr) << _NV_IOC_NRSHIFT) | \
|
||||
((size) << _NV_IOC_SIZESHIFT))
|
||||
|
||||
/* used to create numbers */
|
||||
#define UNV_IO(type,nr) UNV_IOC(UNV_IOC_NONE,(type),(nr),0)
|
||||
#define UNV_IOR(type,nr,size) UNV_IOC(UNV_IOC_READ,(type),(nr),sizeof(size))
|
||||
#define UNV_IOW(type,nr,size) UNV_IOC(UNV_IOC_WRITE,(type),(nr),sizeof(size))
|
||||
#define UNV_IOWR(type,nr,size) UNV_IOC(UNV_IOC_READ|UNV_IOC_WRITE,(type),(nr),sizeof(size))
|
||||
#define _NV_IO(type,nr) _NV_IOC(_NV_IOC_NONE,(type),(nr),0)
|
||||
#define _NV_IOR(type,nr,size) _NV_IOC(_NV_IOC_READ,(type),(nr),sizeof(size))
|
||||
#define _NV_IOW(type,nr,size) _NV_IOC(_NV_IOC_WRITE,(type),(nr),sizeof(size))
|
||||
#define _NV_IOWR(type,nr,size) _NV_IOC(_NV_IOC_READ|_NV_IOC_WRITE,(type),(nr),sizeof(size))
|
||||
|
||||
/* used to decode ioctl numbers.. */
|
||||
#define UNV_IOC_DIR(nr) (((nr) >> UNV_IOC_DIRSHIFT) & UNV_IOC_DIRMASK)
|
||||
#define UNV_IOC_TYPE(nr) (((nr) >> UNV_IOC_TYPESHIFT) & UNV_IOC_TYPEMASK)
|
||||
#define UNV_IOC_NR(nr) (((nr) >> UNV_IOC_NRSHIFT) & UNV_IOC_NRMASK)
|
||||
#define UNV_IOC_SIZE(nr) (((nr) >> UNV_IOC_SIZESHIFT) & UNV_IOC_SIZEMASK)
|
||||
#define _NV_IOC_DIR(nr) (((nr) >> _NV_IOC_DIRSHIFT) & _NV_IOC_DIRMASK)
|
||||
#define _NV_IOC_TYPE(nr) (((nr) >> _NV_IOC_TYPESHIFT) & _NV_IOC_TYPEMASK)
|
||||
#define _NV_IOC_NR(nr) (((nr) >> _NV_IOC_NRSHIFT) & _NV_IOC_NRMASK)
|
||||
#define _NV_IOC_SIZE(nr) (((nr) >> _NV_IOC_SIZESHIFT) & _NV_IOC_SIZEMASK)
|
||||
|
||||
#define DUnv_in
|
||||
#define DUnv_out
|
||||
#define DUnv_inout
|
||||
#define __nv_in
|
||||
#define __nv_out
|
||||
#define __nv_inout
|
||||
|
|
|
|||
|
|
@ -6,20 +6,20 @@
|
|||
*/
|
||||
#include "../types.h"
|
||||
#include "../kernel/mutex.h"
|
||||
|
||||
|
||||
/// Condition variable structure.
|
||||
typedef struct {
|
||||
u32 tag;
|
||||
Mutex* mutex;
|
||||
} CondVar;
|
||||
|
||||
|
||||
/**
|
||||
* @brief Initializes a condition variable.
|
||||
* @param[in] c Condition variable object.
|
||||
* @param[in] m Mutex object to use inside the condition variable.
|
||||
*/
|
||||
void condvarInit(CondVar* c, Mutex* m);
|
||||
|
||||
|
||||
/**
|
||||
* @brief Waits on a condition variable with a timeout.
|
||||
* @param[in] c Condition variable object.
|
||||
|
|
@ -28,7 +28,7 @@ void condvarInit(CondVar* c, Mutex* m);
|
|||
* @remark On function return, the underlying mutex is acquired.
|
||||
*/
|
||||
Result condvarWaitTimeout(CondVar* c, u64 timeout);
|
||||
|
||||
|
||||
/**
|
||||
* @brief Waits on a condition variable.
|
||||
* @param[in] c Condition variable object.
|
||||
|
|
@ -36,7 +36,10 @@ Result condvarWaitTimeout(CondVar* c, u64 timeout);
|
|||
* @remark On function return, the underlying mutex is acquired.
|
||||
*/
|
||||
static inline Result condvarWait(CondVar* c)
|
||||
;
|
||||
{
|
||||
return condvarWaitTimeout(c, -1ull);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Wakes up up to the specified number of threads waiting on a condition variable.
|
||||
* @param[in] c Condition variable object.
|
||||
|
|
@ -44,17 +47,23 @@ static inline Result condvarWait(CondVar* c)
|
|||
* @return Result code.
|
||||
*/
|
||||
Result condvarWake(CondVar* c, int num);
|
||||
|
||||
|
||||
/**
|
||||
* @brief Wakes up a single thread waiting on a condition variable.
|
||||
* @param[in] c Condition variable object.
|
||||
* @return Result code.
|
||||
*/
|
||||
static inline Result condvarWakeOne(CondVar* c)
|
||||
;
|
||||
{
|
||||
return condvarWake(c, 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Wakes up all thread waiting on a condition variable.
|
||||
* @param[in] c Condition variable object.
|
||||
* @return Result code.
|
||||
*/
|
||||
static inline Result condvarWakeAll(CondVar* c);
|
||||
static inline Result condvarWakeAll(CondVar* c)
|
||||
{
|
||||
return condvarWake(c, -1);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,35 +8,35 @@
|
|||
#include "../result.h"
|
||||
#include "../arm/tls.h"
|
||||
#include "../kernel/svc.h"
|
||||
|
||||
|
||||
/// IPC input header magic
|
||||
#define SFCI_MAGIC 0x49434653
|
||||
/// IPC output header magic
|
||||
#define SFCO_MAGIC 0x4f434653
|
||||
|
||||
|
||||
/// IPC invalid object ID
|
||||
#define IPC_INVALID_OBJECT_ID UINT32_MAX
|
||||
|
||||
|
||||
///@name IPC request building
|
||||
///@{
|
||||
|
||||
|
||||
/// IPC command (request) structure.
|
||||
#define IPC_MAX_BUFFERS 8
|
||||
#define IPC_MAX_OBJECTS 8
|
||||
|
||||
|
||||
typedef enum {
|
||||
BufferType_Normal=0, ///< Regular buffer.
|
||||
BufferType_Type1=1, ///< Allows ProcessMemory and shared TransferMemory.
|
||||
BufferType_Invalid=2,
|
||||
BufferType_Type3=3 ///< Same as Type1 except remote process is not allowed to use device-mapping.
|
||||
} BufferType;
|
||||
|
||||
|
||||
typedef enum {
|
||||
BufferDirection_Send=0,
|
||||
BufferDirection_Recv=1,
|
||||
BufferDirection_Exch=2,
|
||||
} BufferDirection;
|
||||
|
||||
|
||||
typedef enum {
|
||||
IpcCommandType_Invalid = 0,
|
||||
IpcCommandType_LegacyRequest = 1,
|
||||
|
|
@ -47,7 +47,7 @@ typedef enum {
|
|||
IpcCommandType_RequestWithContext = 6,
|
||||
IpcCommandType_ControlWithContext = 7
|
||||
} IpcCommandType;
|
||||
|
||||
|
||||
typedef struct {
|
||||
size_t NumSend; // A
|
||||
size_t NumRecv; // B
|
||||
|
|
@ -55,47 +55,49 @@ typedef struct {
|
|||
const void* Buffers[IPC_MAX_BUFFERS];
|
||||
size_t BufferSizes[IPC_MAX_BUFFERS];
|
||||
BufferType BufferTypes[IPC_MAX_BUFFERS];
|
||||
|
||||
|
||||
size_t NumStaticIn; // X
|
||||
size_t NumStaticOut; // C
|
||||
const void* Statics[IPC_MAX_BUFFERS];
|
||||
size_t StaticSizes[IPC_MAX_BUFFERS];
|
||||
u8 StaticIndices[IPC_MAX_BUFFERS];
|
||||
|
||||
|
||||
bool SendPid;
|
||||
size_t NumHandlesCopy;
|
||||
size_t NumHandlesMove;
|
||||
Handle Handles[IPC_MAX_OBJECTS];
|
||||
|
||||
|
||||
size_t NumObjectIds;
|
||||
u32 ObjectIds[IPC_MAX_OBJECTS];
|
||||
} IpcCommand;
|
||||
|
||||
|
||||
/**
|
||||
* @brief Initializes an IPC command structure.
|
||||
* @param cmd IPC command structure.
|
||||
*/
|
||||
static inline void ipcInitialize(IpcCommand* cmd);
|
||||
|
||||
static inline void ipcInitialize(IpcCommand* cmd) {
|
||||
*cmd = (IpcCommand){0};
|
||||
}
|
||||
|
||||
/// IPC buffer descriptor.
|
||||
typedef struct {
|
||||
u32 Size; ///< Size of the buffer.
|
||||
u32 Addr; ///< Lower 32-bits of the address of the buffer
|
||||
u32 Packed; ///< Packed data (including higher bits of the address)
|
||||
} IpcBufferDescriptor;
|
||||
|
||||
|
||||
/// IPC static send-buffer descriptor.
|
||||
typedef struct {
|
||||
u32 Packed; ///< Packed data (including higher bits of the address)
|
||||
u32 Addr; ///< Lower 32-bits of the address
|
||||
} IpcStaticSendDescriptor;
|
||||
|
||||
|
||||
/// IPC static receive-buffer descriptor.
|
||||
typedef struct {
|
||||
u32 Addr; ///< Lower 32-bits of the address of the buffer
|
||||
u32 Packed; ///< Packed data (including higher bits of the address)
|
||||
} IpcStaticRecvDescriptor;
|
||||
|
||||
|
||||
/**
|
||||
* @brief Adds a buffer to an IPC command structure.
|
||||
* @param cmd IPC command structure.
|
||||
|
|
@ -103,8 +105,14 @@ typedef struct {
|
|||
* @param size Size of the buffer.
|
||||
* @param type Buffer type.
|
||||
*/
|
||||
static inline void ipcAddSendBuffer(IpcCommand* cmd, const void* buffer, size_t size, BufferType type);
|
||||
|
||||
static inline void ipcAddSendBuffer(IpcCommand* cmd, const void* buffer, size_t size, BufferType type) {
|
||||
size_t off = cmd->NumSend;
|
||||
cmd->Buffers[off] = buffer;
|
||||
cmd->BufferSizes[off] = size;
|
||||
cmd->BufferTypes[off] = type;
|
||||
cmd->NumSend++;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Adds a receive-buffer to an IPC command structure.
|
||||
* @param cmd IPC command structure.
|
||||
|
|
@ -112,8 +120,14 @@ static inline void ipcAddSendBuffer(IpcCommand* cmd, const void* buffer, size_t
|
|||
* @param size Size of the buffer.
|
||||
* @param type Buffer type.
|
||||
*/
|
||||
static inline void ipcAddRecvBuffer(IpcCommand* cmd, void* buffer, size_t size, BufferType type);
|
||||
|
||||
static inline void ipcAddRecvBuffer(IpcCommand* cmd, void* buffer, size_t size, BufferType type) {
|
||||
size_t off = cmd->NumSend + cmd->NumRecv;
|
||||
cmd->Buffers[off] = buffer;
|
||||
cmd->BufferSizes[off] = size;
|
||||
cmd->BufferTypes[off] = type;
|
||||
cmd->NumRecv++;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Adds an exchange-buffer to an IPC command structure.
|
||||
* @param cmd IPC command structure.
|
||||
|
|
@ -121,8 +135,14 @@ static inline void ipcAddRecvBuffer(IpcCommand* cmd, void* buffer, size_t size,
|
|||
* @param size Size of the buffer.
|
||||
* @param type Buffer type.
|
||||
*/
|
||||
static inline void ipcAddExchBuffer(IpcCommand* cmd, void* buffer, size_t size, BufferType type);
|
||||
|
||||
static inline void ipcAddExchBuffer(IpcCommand* cmd, void* buffer, size_t size, BufferType type) {
|
||||
size_t off = cmd->NumSend + cmd->NumRecv + cmd->NumExch;
|
||||
cmd->Buffers[off] = buffer;
|
||||
cmd->BufferSizes[off] = size;
|
||||
cmd->BufferTypes[off] = type;
|
||||
cmd->NumExch++;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Adds a static-buffer to an IPC command structure.
|
||||
* @param cmd IPC command structure.
|
||||
|
|
@ -130,8 +150,14 @@ static inline void ipcAddExchBuffer(IpcCommand* cmd, void* buffer, size_t size,
|
|||
* @param size Size of the buffer.
|
||||
* @param index Index of buffer.
|
||||
*/
|
||||
static inline void ipcAddSendStatic(IpcCommand* cmd, const void* buffer, size_t size, u8 index);
|
||||
|
||||
static inline void ipcAddSendStatic(IpcCommand* cmd, const void* buffer, size_t size, u8 index) {
|
||||
size_t off = cmd->NumStaticIn;
|
||||
cmd->Statics[off] = buffer;
|
||||
cmd->StaticSizes[off] = size;
|
||||
cmd->StaticIndices[off] = index;
|
||||
cmd->NumStaticIn++;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Adds a static-receive-buffer to an IPC command structure.
|
||||
* @param cmd IPC command structure.
|
||||
|
|
@ -139,8 +165,14 @@ static inline void ipcAddSendStatic(IpcCommand* cmd, const void* buffer, size_t
|
|||
* @param size Size of the buffer.
|
||||
* @param index Index of buffer.
|
||||
*/
|
||||
static inline void ipcAddRecvStatic(IpcCommand* cmd, void* buffer, size_t size, u8 index);
|
||||
|
||||
static inline void ipcAddRecvStatic(IpcCommand* cmd, void* buffer, size_t size, u8 index) {
|
||||
size_t off = cmd->NumStaticIn + cmd->NumStaticOut;
|
||||
cmd->Statics[off] = buffer;
|
||||
cmd->StaticSizes[off] = size;
|
||||
cmd->StaticIndices[off] = index;
|
||||
cmd->NumStaticOut++;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Adds a smart-buffer (buffer + static-buffer pair) to an IPC command structure.
|
||||
* @param cmd IPC command structure.
|
||||
|
|
@ -149,8 +181,16 @@ static inline void ipcAddRecvStatic(IpcCommand* cmd, void* buffer, size_t size,
|
|||
* @param size Size of the buffer.
|
||||
* @param index Index of buffer.
|
||||
*/
|
||||
static inline void ipcAddSendSmart(IpcCommand* cmd, size_t ipc_buffer_size, const void* buffer, size_t size, u8 index);
|
||||
|
||||
static inline void ipcAddSendSmart(IpcCommand* cmd, size_t ipc_buffer_size, const void* buffer, size_t size, u8 index) {
|
||||
if (ipc_buffer_size != 0 && size <= ipc_buffer_size) {
|
||||
ipcAddSendBuffer(cmd, NULL, 0, BufferType_Normal);
|
||||
ipcAddSendStatic(cmd, buffer, size, index);
|
||||
} else {
|
||||
ipcAddSendBuffer(cmd, buffer, size, BufferType_Normal);
|
||||
ipcAddSendStatic(cmd, NULL, 0, index);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Adds a smart-receive-buffer (buffer + static-receive-buffer pair) to an IPC command structure.
|
||||
* @param cmd IPC command structure.
|
||||
|
|
@ -159,124 +199,377 @@ static inline void ipcAddSendSmart(IpcCommand* cmd, size_t ipc_buffer_size, cons
|
|||
* @param size Size of the buffer.
|
||||
* @param index Index of buffer.
|
||||
*/
|
||||
static inline void ipcAddRecvSmart(IpcCommand* cmd, size_t ipc_buffer_size, void* buffer, size_t size, u8 index);
|
||||
|
||||
static inline void ipcAddRecvSmart(IpcCommand* cmd, size_t ipc_buffer_size, void* buffer, size_t size, u8 index) {
|
||||
if (ipc_buffer_size != 0 && size <= ipc_buffer_size) {
|
||||
ipcAddRecvBuffer(cmd, NULL, 0, BufferType_Normal);
|
||||
ipcAddRecvStatic(cmd, buffer, size, index);
|
||||
} else {
|
||||
ipcAddRecvBuffer(cmd, buffer, size, BufferType_Normal);
|
||||
ipcAddRecvStatic(cmd, NULL, 0, index);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Tags an IPC command structure to send the PID.
|
||||
* @param cmd IPC command structure.
|
||||
*/
|
||||
static inline void ipcSendPid(IpcCommand* cmd);
|
||||
|
||||
static inline void ipcSendPid(IpcCommand* cmd) {
|
||||
cmd->SendPid = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @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.
|
||||
*/
|
||||
static inline void ipcSendHandleCopy(IpcCommand* cmd, Handle h);
|
||||
|
||||
static inline void ipcSendHandleCopy(IpcCommand* cmd, Handle h) {
|
||||
cmd->Handles[cmd->NumHandlesCopy++] = h;
|
||||
}
|
||||
|
||||
/**
|
||||
* @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.
|
||||
*/
|
||||
static inline void ipcSendHandleMove(IpcCommand* cmd, Handle h);
|
||||
|
||||
static inline void ipcSendHandleMove(IpcCommand* cmd, Handle h) {
|
||||
cmd->Handles[cmd->NumHandlesCopy + cmd->NumHandlesMove++] = h;
|
||||
}
|
||||
|
||||
/**
|
||||
* @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.
|
||||
*/
|
||||
static inline void* ipcPrepareHeader(IpcCommand* cmd, size_t sizeof_raw);
|
||||
|
||||
static inline void* ipcPrepareHeader(IpcCommand* cmd, size_t sizeof_raw) {
|
||||
u32* buf = (u32*)armGetTls();
|
||||
size_t i;
|
||||
*buf++ = IpcCommandType_Request | (cmd->NumStaticIn << 16) | (cmd->NumSend << 20) | (cmd->NumRecv << 24) | (cmd->NumExch << 28);
|
||||
|
||||
u32* fill_in_size_later = buf;
|
||||
|
||||
if (cmd->NumStaticOut > 0) {
|
||||
*buf = (cmd->NumStaticOut + 2) << 10;
|
||||
}
|
||||
else {
|
||||
*buf = 0;
|
||||
}
|
||||
|
||||
if (cmd->SendPid || cmd->NumHandlesCopy > 0 || cmd->NumHandlesMove > 0) {
|
||||
*buf++ |= 0x80000000;
|
||||
*buf++ = (!!cmd->SendPid) | (cmd->NumHandlesCopy << 1) | (cmd->NumHandlesMove << 5);
|
||||
|
||||
if (cmd->SendPid)
|
||||
buf += 2;
|
||||
|
||||
for (i=0; i<(cmd->NumHandlesCopy + cmd->NumHandlesMove); i++)
|
||||
*buf++ = cmd->Handles[i];
|
||||
}
|
||||
else {
|
||||
buf++;
|
||||
}
|
||||
|
||||
for (i=0; i<cmd->NumStaticIn; i++, buf+=2) {
|
||||
IpcStaticSendDescriptor* desc = (IpcStaticSendDescriptor*) buf;
|
||||
|
||||
uintptr_t ptr = (uintptr_t) cmd->Statics[i];
|
||||
desc->Addr = ptr;
|
||||
desc->Packed = cmd->StaticIndices[i] | (cmd->StaticSizes[i] << 16) |
|
||||
(((ptr >> 32) & 15) << 12) | (((ptr >> 36) & 15) << 6);
|
||||
}
|
||||
|
||||
for (i=0; i<(cmd->NumSend + cmd->NumRecv + cmd->NumExch); i++, buf+=3) {
|
||||
IpcBufferDescriptor* desc = (IpcBufferDescriptor*) buf;
|
||||
desc->Size = cmd->BufferSizes[i];
|
||||
|
||||
uintptr_t ptr = (uintptr_t) cmd->Buffers[i];
|
||||
desc->Addr = ptr;
|
||||
desc->Packed = cmd->BufferTypes[i] |
|
||||
(((ptr >> 32) & 15) << 28) | ((ptr >> 36) << 2);
|
||||
}
|
||||
|
||||
u32 padding = ((16 - (((uintptr_t) buf) & 15)) & 15) / 4;
|
||||
u32* raw = (u32*) (buf + padding);
|
||||
|
||||
size_t raw_size = (sizeof_raw/4) + 4;
|
||||
buf += raw_size;
|
||||
|
||||
u16* buf_u16 = (u16*) buf;
|
||||
|
||||
for (i=0; i<cmd->NumStaticOut; i++) {
|
||||
size_t off = cmd->NumStaticIn + i;
|
||||
size_t sz = (uintptr_t) cmd->StaticSizes[off];
|
||||
|
||||
buf_u16[i] = (sz > 0xFFFF) ? 0 : sz;
|
||||
}
|
||||
|
||||
size_t u16s_size = ((2*cmd->NumStaticOut) + 3)/4;
|
||||
buf += u16s_size;
|
||||
raw_size += u16s_size;
|
||||
|
||||
*fill_in_size_later |= raw_size;
|
||||
|
||||
for (i=0; i<cmd->NumStaticOut; i++, buf+=2) {
|
||||
IpcStaticRecvDescriptor* desc = (IpcStaticRecvDescriptor*) buf;
|
||||
size_t off = cmd->NumStaticIn + i;
|
||||
|
||||
uintptr_t ptr = (uintptr_t) cmd->Statics[off];
|
||||
desc->Addr = ptr;
|
||||
desc->Packed = (ptr >> 32) | (cmd->StaticSizes[off] << 16);
|
||||
}
|
||||
|
||||
return (void*) raw;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Dispatches an IPC request.
|
||||
* @param session IPC session handle.
|
||||
* @return Result code.
|
||||
*/
|
||||
static inline Result ipcDispatch(Handle session);
|
||||
|
||||
static inline Result ipcDispatch(Handle session) {
|
||||
return svcSendSyncRequest(session);
|
||||
}
|
||||
|
||||
///@}
|
||||
|
||||
|
||||
///@name IPC response parsing
|
||||
///@{
|
||||
|
||||
|
||||
/// IPC parsed command (response) structure.
|
||||
typedef struct {
|
||||
IpcCommandType CommandType; ///< Type of the command
|
||||
|
||||
bool HasPid; ///< true if the 'Pid' field is filled out.
|
||||
u64 Pid; ///< PID included in the response (only if HasPid is true)
|
||||
|
||||
|
||||
size_t NumHandles; ///< Number of handles copied.
|
||||
Handle Handles[IPC_MAX_OBJECTS]; ///< Handles.
|
||||
bool WasHandleCopied[IPC_MAX_OBJECTS]; ///< true if the handle was moved, false if it was copied.
|
||||
|
||||
|
||||
u32 ThisObjectId; ///< Object ID to call the command on (for domain messages).
|
||||
size_t NumObjectIds; ///< Number of object IDs (for domain messages).
|
||||
u32 ObjectIds[IPC_MAX_OBJECTS]; ///< Object IDs (for domain messages).
|
||||
|
||||
|
||||
size_t NumBuffers; ///< Number of buffers in the response.
|
||||
void* Buffers[IPC_MAX_BUFFERS]; ///< Pointers to the buffers.
|
||||
size_t BufferSizes[IPC_MAX_BUFFERS]; ///< Sizes of the buffers.
|
||||
BufferType BufferTypes[IPC_MAX_BUFFERS]; ///< Types of the buffers.
|
||||
BufferDirection BufferDirections[IPC_MAX_BUFFERS]; ///< Direction of each buffer.
|
||||
|
||||
|
||||
size_t NumStatics; ///< Number of statics in the response.
|
||||
void* Statics[IPC_MAX_BUFFERS]; ///< Pointers to the statics.
|
||||
size_t StaticSizes[IPC_MAX_BUFFERS]; ///< Sizes of the statics.
|
||||
u8 StaticIndices[IPC_MAX_BUFFERS]; ///< Indices of the statics.
|
||||
|
||||
size_t NumStaticsOut; ///< Number of output statics available in the response.
|
||||
|
||||
|
||||
void* Raw; ///< Pointer to the raw embedded data structure in the response.
|
||||
void* RawWithoutPadding; ///< Pointer to the raw embedded data structure, without padding.
|
||||
size_t RawSize; ///< Size of the raw embedded data.
|
||||
} IpcParsedCommand;
|
||||
|
||||
|
||||
/**
|
||||
* @brief Parse an IPC command response into an IPC parsed command structure.
|
||||
* @param IPC parsed command structure to fill in.
|
||||
* @return Result code.
|
||||
*/
|
||||
static inline Result ipcParse(IpcParsedCommand* r);
|
||||
|
||||
static inline Result ipcParse(IpcParsedCommand* r) {
|
||||
u32* buf = (u32*)armGetTls();
|
||||
u32 ctrl0 = *buf++;
|
||||
u32 ctrl1 = *buf++;
|
||||
size_t i;
|
||||
|
||||
r->CommandType = (IpcCommandType) (ctrl0 & 0xffff);
|
||||
r->HasPid = false;
|
||||
r->RawSize = (ctrl1 & 0x1ff) * 4;
|
||||
r->NumHandles = 0;
|
||||
|
||||
r->NumStaticsOut = (ctrl1 >> 10) & 15;
|
||||
if (r->NumStaticsOut >> 1) r->NumStaticsOut--; // Value 2 -> Single descriptor
|
||||
if (r->NumStaticsOut >> 1) r->NumStaticsOut--; // Value 3+ -> (Value - 2) descriptors
|
||||
|
||||
if (ctrl1 & 0x80000000) {
|
||||
u32 ctrl2 = *buf++;
|
||||
|
||||
if (ctrl2 & 1) {
|
||||
r->HasPid = true;
|
||||
r->Pid = *buf++;
|
||||
r->Pid |= ((u64)(*buf++)) << 32;
|
||||
}
|
||||
|
||||
size_t num_handles_copy = ((ctrl2 >> 1) & 15);
|
||||
size_t num_handles_move = ((ctrl2 >> 5) & 15);
|
||||
|
||||
size_t num_handles = num_handles_copy + num_handles_move;
|
||||
u32* buf_after_handles = buf + num_handles;
|
||||
|
||||
if (num_handles > IPC_MAX_OBJECTS)
|
||||
num_handles = IPC_MAX_OBJECTS;
|
||||
|
||||
for (i=0; i<num_handles; i++)
|
||||
{
|
||||
r->Handles[i] = *(buf+i);
|
||||
r->WasHandleCopied[i] = (i < num_handles_copy);
|
||||
}
|
||||
|
||||
r->NumHandles = num_handles;
|
||||
buf = buf_after_handles;
|
||||
}
|
||||
|
||||
size_t num_statics = (ctrl0 >> 16) & 15;
|
||||
u32* buf_after_statics = buf + num_statics*2;
|
||||
|
||||
if (num_statics > IPC_MAX_BUFFERS)
|
||||
num_statics = IPC_MAX_BUFFERS;
|
||||
|
||||
for (i=0; i<num_statics; i++, buf+=2) {
|
||||
IpcStaticSendDescriptor* desc = (IpcStaticSendDescriptor*) buf;
|
||||
u64 packed = (u64) desc->Packed;
|
||||
|
||||
r->Statics[i] = (void*) (desc->Addr | (((packed >> 12) & 15) << 32) | (((packed >> 6) & 15) << 36));
|
||||
r->StaticSizes[i] = packed >> 16;
|
||||
r->StaticIndices[i] = packed & 63;
|
||||
}
|
||||
|
||||
r->NumStatics = num_statics;
|
||||
buf = buf_after_statics;
|
||||
|
||||
size_t num_bufs_send = (ctrl0 >> 20) & 15;
|
||||
size_t num_bufs_recv = (ctrl0 >> 24) & 15;
|
||||
size_t num_bufs_exch = (ctrl0 >> 28) & 15;
|
||||
|
||||
size_t num_bufs = num_bufs_send + num_bufs_recv + num_bufs_exch;
|
||||
r->Raw = (void*)(((uintptr_t)(buf + num_bufs*3) + 15) &~ 15);
|
||||
r->RawWithoutPadding = (void*)((uintptr_t)(buf + num_bufs*3));
|
||||
|
||||
if (num_bufs > IPC_MAX_BUFFERS)
|
||||
num_bufs = IPC_MAX_BUFFERS;
|
||||
|
||||
for (i=0; i<num_bufs; i++, buf+=3) {
|
||||
IpcBufferDescriptor* desc = (IpcBufferDescriptor*) buf;
|
||||
u64 packed = (u64) desc->Packed;
|
||||
|
||||
r->Buffers[i] = (void*) (desc->Addr | ((packed >> 28) << 32) | (((packed >> 2) & 15) << 36));
|
||||
r->BufferSizes[i] = desc->Size;
|
||||
r->BufferTypes[i] = (BufferType) (packed & 3);
|
||||
|
||||
if (i < num_bufs_send)
|
||||
r->BufferDirections[i] = BufferDirection_Send;
|
||||
else if (i < (num_bufs_send + num_bufs_recv))
|
||||
r->BufferDirections[i] = BufferDirection_Recv;
|
||||
else
|
||||
r->BufferDirections[i] = BufferDirection_Exch;
|
||||
}
|
||||
|
||||
r->NumBuffers = num_bufs;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @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.
|
||||
*/
|
||||
static inline Result ipcQueryPointerBufferSize(Handle session, size_t *size);
|
||||
|
||||
static inline Result ipcQueryPointerBufferSize(Handle session, size_t *size) {
|
||||
u32* buf = (u32*)armGetTls();
|
||||
|
||||
buf[0] = IpcCommandType_Control;
|
||||
buf[1] = 8;
|
||||
buf[2] = 0;
|
||||
buf[3] = 0;
|
||||
buf[4] = SFCI_MAGIC;
|
||||
buf[5] = 0;
|
||||
buf[6] = 3;
|
||||
buf[7] = 0;
|
||||
|
||||
Result rc = ipcDispatch(session);
|
||||
|
||||
if (R_SUCCEEDED(rc)) {
|
||||
IpcParsedCommand r;
|
||||
ipcParse(&r);
|
||||
|
||||
struct ipcQueryPointerBufferSizeResponse {
|
||||
u64 magic;
|
||||
u64 result;
|
||||
u32 size;
|
||||
} *raw = (struct ipcQueryPointerBufferSizeResponse*)r.Raw;
|
||||
|
||||
rc = raw->result;
|
||||
|
||||
if (R_SUCCEEDED(rc)) {
|
||||
*size = raw->size & 0xffff;
|
||||
}
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Closes the IPC session with proper clean up.
|
||||
* @param session IPC session handle.
|
||||
* @return Result code.
|
||||
*/
|
||||
static inline Result ipcCloseSession(Handle session);
|
||||
static inline Result ipcCloseSession(Handle session) {
|
||||
u32* buf = (u32*)armGetTls();
|
||||
buf[0] = IpcCommandType_Close;
|
||||
buf[1] = 0;
|
||||
return ipcDispatch(session);
|
||||
}
|
||||
///@}
|
||||
|
||||
|
||||
///@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.
|
||||
*/
|
||||
static inline Result ipcConvertSessionToDomain(Handle session, u32* object_id_out);
|
||||
|
||||
static inline Result ipcConvertSessionToDomain(Handle session, u32* object_id_out) {
|
||||
u32* buf = (u32*)armGetTls();
|
||||
|
||||
buf[0] = IpcCommandType_Control;
|
||||
buf[1] = 8;
|
||||
buf[4] = SFCI_MAGIC;
|
||||
buf[5] = 0;
|
||||
buf[6] = 0;
|
||||
buf[7] = 0;
|
||||
|
||||
Result rc = ipcDispatch(session);
|
||||
|
||||
if (R_SUCCEEDED(rc)) {
|
||||
IpcParsedCommand r;
|
||||
ipcParse(&r);
|
||||
|
||||
struct ipcConvertSessionToDomainResponse {
|
||||
u64 magic;
|
||||
u64 result;
|
||||
u32 object_id;
|
||||
} *raw = (struct ipcConvertSessionToDomainResponse*)r.Raw;
|
||||
|
||||
rc = raw->result;
|
||||
|
||||
if (R_SUCCEEDED(rc)) {
|
||||
*object_id_out = raw->object_id;
|
||||
}
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
/**
|
||||
* @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.
|
||||
*/
|
||||
static inline void ipcSendObjectId(IpcCommand* cmd, u32 object_id);
|
||||
|
||||
static inline void ipcSendObjectId(IpcCommand* cmd, u32 object_id) {
|
||||
cmd->ObjectIds[cmd->NumObjectIds++] = object_id;
|
||||
}
|
||||
|
||||
/// IPC domain message header.
|
||||
typedef struct {
|
||||
u8 Type;
|
||||
|
|
@ -285,7 +578,7 @@ typedef struct {
|
|||
u32 ThisObjectId;
|
||||
u32 Pad[2];
|
||||
} DomainMessageHeader;
|
||||
|
||||
|
||||
/**
|
||||
* @brief Prepares the header of an IPC command structure (domain version).
|
||||
* @param cmd IPC command structure.
|
||||
|
|
@ -293,21 +586,66 @@ typedef struct {
|
|||
* @oaram object_id Domain object ID.
|
||||
* @return Pointer to the raw embedded data structure in the request, ready to be filled out.
|
||||
*/
|
||||
static inline void* ipcPrepareHeaderForDomain(IpcCommand* cmd, size_t sizeof_raw, u32 object_id);
|
||||
|
||||
static inline void* ipcPrepareHeaderForDomain(IpcCommand* cmd, size_t sizeof_raw, u32 object_id) {
|
||||
void* raw = ipcPrepareHeader(cmd, sizeof_raw + sizeof(DomainMessageHeader));
|
||||
DomainMessageHeader* hdr = (DomainMessageHeader*) raw;
|
||||
u32 *object_ids = (u32*)(((uintptr_t) raw) + sizeof(DomainMessageHeader) + sizeof_raw);
|
||||
|
||||
hdr->Type = 1;
|
||||
hdr->NumObjectIds = (u8)cmd->NumObjectIds;
|
||||
hdr->Length = sizeof_raw;
|
||||
hdr->ThisObjectId = object_id;
|
||||
hdr->Pad[0] = hdr->Pad[1] = 0;
|
||||
|
||||
for(size_t i = 0; i < cmd->NumObjectIds; i++)
|
||||
object_ids[i] = cmd->ObjectIds[i];
|
||||
return (void*)(((uintptr_t) raw) + sizeof(DomainMessageHeader));
|
||||
}
|
||||
|
||||
/**
|
||||
* @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.
|
||||
*/
|
||||
static inline Result ipcParseForDomain(IpcParsedCommand* r);
|
||||
|
||||
static inline Result ipcParseForDomain(IpcParsedCommand* r) {
|
||||
Result rc = ipcParse(r);
|
||||
DomainMessageHeader* hdr;
|
||||
u32 *object_ids;
|
||||
if(R_FAILED(rc))
|
||||
return rc;
|
||||
|
||||
hdr = (DomainMessageHeader*) r->Raw;
|
||||
object_ids = (u32*)(((uintptr_t) hdr) + sizeof(DomainMessageHeader) + hdr->Length);
|
||||
r->Raw = (void*)(((uintptr_t) r->Raw) + sizeof(DomainMessageHeader));
|
||||
|
||||
r->ThisObjectId = hdr->ThisObjectId;
|
||||
r->NumObjectIds = hdr->NumObjectIds > 8 ? 8 : hdr->NumObjectIds;
|
||||
for(size_t i = 0; i < r->NumObjectIds; i++)
|
||||
r->ObjectIds[i] = object_ids[i];
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Closes a domain object by ID.
|
||||
* @param session IPC session handle.
|
||||
* @param object_id ID of the object to close.
|
||||
* @return Result code.
|
||||
*/
|
||||
static inline Result ipcCloseObjectById(Handle session, u32 object_id);
|
||||
|
||||
static inline Result ipcCloseObjectById(Handle session, u32 object_id) {
|
||||
IpcCommand c;
|
||||
DomainMessageHeader* hdr;
|
||||
|
||||
ipcInitialize(&c);
|
||||
hdr = (DomainMessageHeader*)ipcPrepareHeader(&c, sizeof(DomainMessageHeader));
|
||||
|
||||
hdr->Type = 2;
|
||||
hdr->NumObjectIds = 0;
|
||||
hdr->Length = 0;
|
||||
hdr->ThisObjectId = object_id;
|
||||
hdr->Pad[0] = hdr->Pad[1] = 0;
|
||||
|
||||
return ipcDispatch(session); // this command has no associated response
|
||||
}
|
||||
|
||||
///@}
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@
|
|||
*/
|
||||
#pragma once
|
||||
#include "../types.h"
|
||||
|
||||
|
||||
/// Shared memory information structure.
|
||||
typedef struct {
|
||||
Handle handle; ///< Kernel object handle.
|
||||
|
|
@ -15,7 +15,7 @@ typedef struct {
|
|||
Permission perm; ///< Permissions.
|
||||
void* map_addr; ///< Address to which the shared memory object is mapped.
|
||||
} SharedMemory;
|
||||
|
||||
|
||||
/**
|
||||
* @brief Creates a shared memory object.
|
||||
* @param s Shared memory information structure which will be filled in.
|
||||
|
|
@ -26,7 +26,7 @@ typedef struct {
|
|||
* @warning This is a privileged operation; in normal circumstances applications cannot use this function.
|
||||
*/
|
||||
Result shmemCreate(SharedMemory* s, size_t size, Permission local_perm, Permission remote_perm);
|
||||
|
||||
|
||||
/**
|
||||
* @brief Loads a shared memory object coming from a remote process.
|
||||
* @param s Shared memory information structure which will be filled in.
|
||||
|
|
@ -35,28 +35,30 @@ Result shmemCreate(SharedMemory* s, size_t size, Permission local_perm, Permissi
|
|||
* @param perm Permissions with which the shared memory object will be mapped in the local process.
|
||||
*/
|
||||
void shmemLoadRemote(SharedMemory* s, Handle handle, size_t size, Permission perm);
|
||||
|
||||
|
||||
/**
|
||||
* @brief Maps a shared memory object.
|
||||
* @param s Shared memory information structure.
|
||||
* @return Result code.
|
||||
*/
|
||||
Result shmemMap(SharedMemory* s);
|
||||
|
||||
|
||||
/**
|
||||
* @brief Unmaps a shared memory object.
|
||||
* @param s Shared memory information structure.
|
||||
* @return Result code.
|
||||
*/
|
||||
Result shmemUnmap(SharedMemory* s);
|
||||
|
||||
|
||||
/**
|
||||
* @brief Retrieves the mapped address of a shared memory object.
|
||||
* @param s Shared memory information structure.
|
||||
* @return Mapped address of the shared memory object.
|
||||
*/
|
||||
static inline void* shmemGetAddr(SharedMemory* s);
|
||||
|
||||
static inline void* shmemGetAddr(SharedMemory* s) {
|
||||
return s->map_addr;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Frees up resources used by a shared memory object, unmapping and closing handles, etc.
|
||||
* @param s Shared memory information structure.
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -1,5 +1,5 @@
|
|||
/**
|
||||
* @file Romfs_dev.h
|
||||
* @file romfs_dev.h
|
||||
* @brief RomFS driver.
|
||||
* @author yellows8
|
||||
* @author mtheall
|
||||
|
|
@ -7,10 +7,10 @@
|
|||
* @copyright libnx Authors
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
|
||||
#include "../../types.h"
|
||||
#include "../../services/fs.h"
|
||||
|
||||
|
||||
/// RomFS header.
|
||||
typedef struct
|
||||
{
|
||||
|
|
@ -24,8 +24,8 @@ typedef struct
|
|||
u64 fileTableOff; ///< Offset of the file table.
|
||||
u64 fileTableSize; ///< Size of the file table.
|
||||
u64 fileDataOff; ///< Offset of the file data.
|
||||
} Romfs_header;
|
||||
|
||||
} romfs_header;
|
||||
|
||||
/// RomFS directory.
|
||||
typedef struct
|
||||
{
|
||||
|
|
@ -36,8 +36,8 @@ typedef struct
|
|||
u32 nextHash; ///< Directory hash table pointer.
|
||||
u32 nameLen; ///< Name length.
|
||||
uint8_t name[]; ///< Name. (UTF-8)
|
||||
} Romfs_dir;
|
||||
|
||||
} romfs_dir;
|
||||
|
||||
/// RomFS file.
|
||||
typedef struct
|
||||
{
|
||||
|
|
@ -48,39 +48,51 @@ typedef struct
|
|||
u32 nextHash; ///< File hash table pointer.
|
||||
u32 nameLen; ///< Name length.
|
||||
uint8_t name[]; ///< Name. (UTF-8)
|
||||
} Romfs_file;
|
||||
|
||||
struct Romfs_mount;
|
||||
|
||||
} romfs_file;
|
||||
|
||||
struct romfs_mount;
|
||||
|
||||
/**
|
||||
* @brief Mounts the Application's RomFS.
|
||||
* @param mount Output mount handle
|
||||
*/
|
||||
Result romfsMount(struct Romfs_mount **mount);
|
||||
Result romfsMount(struct romfs_mount **mount);
|
||||
static inline Result romfsInit(void)
|
||||
;
|
||||
{
|
||||
return romfsMount(NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Mounts RomFS from an open file.
|
||||
* @param file FsFile of the RomFS image.
|
||||
* @param offset Offset of the RomFS within the file.
|
||||
* @param mount Output mount handle
|
||||
*/
|
||||
Result romfsMountFromFile(FsFile file, u64 offset, struct Romfs_mount **mount);
|
||||
Result romfsMountFromFile(FsFile file, u64 offset, struct romfs_mount **mount);
|
||||
static inline Result romfsInitFromFile(FsFile file, u64 offset)
|
||||
;
|
||||
{
|
||||
return romfsMountFromFile(file, offset, NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Mounts RomFS from an open storage.
|
||||
* @param storage FsStorage of the RomFS image.
|
||||
* @param offset Offset of the RomFS within the storage.
|
||||
* @param mount Output mount handle
|
||||
*/
|
||||
Result romfsMountFromStorage(FsStorage storage, u64 offset, struct Romfs_mount **mount);
|
||||
Result romfsMountFromStorage(FsStorage storage, u64 offset, struct romfs_mount **mount);
|
||||
static inline Result romfsInitFromStorage(FsStorage storage, u64 offset)
|
||||
;
|
||||
{
|
||||
return romfsMountFromStorage(storage, offset, NULL);
|
||||
}
|
||||
|
||||
/// Bind the RomFS mount
|
||||
Result romfsBind(struct Romfs_mount *mount);
|
||||
|
||||
Result romfsBind(struct romfs_mount *mount);
|
||||
|
||||
/// Unmounts the RomFS device.
|
||||
Result romfsUnmount(struct Romfs_mount *mount);
|
||||
Result romfsUnmount(struct romfs_mount *mount);
|
||||
static inline Result romfsExit(void)
|
||||
;
|
||||
{
|
||||
return romfsUnmount(NULL);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -353,14 +353,14 @@ typedef struct HidTouchScreenHeader
|
|||
u64 maxEntryIndex;
|
||||
u64 timestamp;
|
||||
} HidTouchScreenHeader;
|
||||
// static_assert(sizeof(HidTouchScreenHeader) == 0x28, "Hid touch screen header structure has incorrect size");
|
||||
static_assert(sizeof(HidTouchScreenHeader) == 0x28, "Hid touch screen header structure has incorrect size");
|
||||
|
||||
typedef struct HidTouchScreenEntryHeader
|
||||
{
|
||||
u64 timestamp;
|
||||
u64 numTouches;
|
||||
} HidTouchScreenEntryHeader;
|
||||
// static_assert(sizeof(HidTouchScreenEntryHeader) == 0x10, "Hid touch screen entry header structure has incorrect size");
|
||||
static_assert(sizeof(HidTouchScreenEntryHeader) == 0x10, "Hid touch screen entry header structure has incorrect size");
|
||||
|
||||
typedef struct HidTouchScreenEntryTouch
|
||||
{
|
||||
|
|
@ -374,7 +374,7 @@ typedef struct HidTouchScreenEntryTouch
|
|||
u32 angle;
|
||||
u32 padding_2;
|
||||
} HidTouchScreenEntryTouch;
|
||||
// static_assert(sizeof(HidTouchScreenEntryTouch) == 0x28, "Hid touch screen touch structure has incorrect size");
|
||||
static_assert(sizeof(HidTouchScreenEntryTouch) == 0x28, "Hid touch screen touch structure has incorrect size");
|
||||
|
||||
typedef struct HidTouchScreenEntry
|
||||
{
|
||||
|
|
@ -382,7 +382,7 @@ typedef struct HidTouchScreenEntry
|
|||
HidTouchScreenEntryTouch touches[16];
|
||||
u64 unk;
|
||||
} HidTouchScreenEntry;
|
||||
// static_assert(sizeof(HidTouchScreenEntry) == 0x298, "Hid touch screen entry structure has incorrect size");
|
||||
static_assert(sizeof(HidTouchScreenEntry) == 0x298, "Hid touch screen entry structure has incorrect size");
|
||||
|
||||
typedef struct HidTouchScreen
|
||||
{
|
||||
|
|
@ -390,7 +390,7 @@ typedef struct HidTouchScreen
|
|||
HidTouchScreenEntry entries[17];
|
||||
u8 padding[0x3c0];
|
||||
} HidTouchScreen;
|
||||
// static_assert(sizeof(HidTouchScreen) == 0x3000, "Hid touch screen structure has incorrect size");
|
||||
static_assert(sizeof(HidTouchScreen) == 0x3000, "Hid touch screen structure has incorrect size");
|
||||
|
||||
// End HidTouchScreen
|
||||
|
||||
|
|
@ -403,7 +403,7 @@ typedef struct HidMouseHeader
|
|||
u64 latestEntry;
|
||||
u64 maxEntryIndex;
|
||||
} HidMouseHeader;
|
||||
// static_assert(sizeof(HidMouseHeader) == 0x20, "Hid mouse header structure has incorrect size");
|
||||
static_assert(sizeof(HidMouseHeader) == 0x20, "Hid mouse header structure has incorrect size");
|
||||
|
||||
typedef struct HidMouseEntry
|
||||
{
|
||||
|
|
@ -412,7 +412,7 @@ typedef struct HidMouseEntry
|
|||
MousePosition position;
|
||||
u64 buttons;
|
||||
} HidMouseEntry;
|
||||
// static_assert(sizeof(HidMouseEntry) == 0x30, "Hid mouse entry structure has incorrect size");
|
||||
static_assert(sizeof(HidMouseEntry) == 0x30, "Hid mouse entry structure has incorrect size");
|
||||
|
||||
typedef struct HidMouse
|
||||
{
|
||||
|
|
@ -420,7 +420,7 @@ typedef struct HidMouse
|
|||
HidMouseEntry entries[17];
|
||||
u8 padding[0xB0];
|
||||
} HidMouse;
|
||||
// static_assert(sizeof(HidMouse) == 0x400, "Hid mouse structure has incorrect size");
|
||||
static_assert(sizeof(HidMouse) == 0x400, "Hid mouse structure has incorrect size");
|
||||
|
||||
// End HidMouse
|
||||
|
||||
|
|
@ -433,7 +433,7 @@ typedef struct HidKeyboardHeader
|
|||
u64 latestEntry;
|
||||
u64 maxEntryIndex;
|
||||
} HidKeyboardHeader;
|
||||
// static_assert(sizeof(HidKeyboardHeader) == 0x20, "Hid keyboard header structure has incorrect size");
|
||||
static_assert(sizeof(HidKeyboardHeader) == 0x20, "Hid keyboard header structure has incorrect size");
|
||||
|
||||
typedef struct HidKeyboardEntry
|
||||
{
|
||||
|
|
@ -442,7 +442,7 @@ typedef struct HidKeyboardEntry
|
|||
u64 modifier;
|
||||
u32 keys[8];
|
||||
} HidKeyboardEntry;
|
||||
// static_assert(sizeof(HidKeyboardEntry) == 0x38, "Hid keyboard entry structure has incorrect size");
|
||||
static_assert(sizeof(HidKeyboardEntry) == 0x38, "Hid keyboard entry structure has incorrect size");
|
||||
|
||||
typedef struct HidKeyboard
|
||||
{
|
||||
|
|
@ -450,7 +450,7 @@ typedef struct HidKeyboard
|
|||
HidKeyboardEntry entries[17];
|
||||
u8 padding[0x28];
|
||||
} HidKeyboard;
|
||||
// static_assert(sizeof(HidKeyboard) == 0x400, "Hid keyboard structure has incorrect size");
|
||||
static_assert(sizeof(HidKeyboard) == 0x400, "Hid keyboard structure has incorrect size");
|
||||
|
||||
// End HidKeyboard
|
||||
|
||||
|
|
@ -463,7 +463,7 @@ typedef struct HidControllerMAC
|
|||
u64 unk;
|
||||
u64 timestamp_2;
|
||||
} HidControllerMAC;
|
||||
// static_assert(sizeof(HidControllerMAC) == 0x20, "Hid controller MAC structure has incorrect size");
|
||||
static_assert(sizeof(HidControllerMAC) == 0x20, "Hid controller MAC structure has incorrect size");
|
||||
|
||||
typedef struct HidControllerHeader
|
||||
{
|
||||
|
|
@ -478,7 +478,7 @@ typedef struct HidControllerHeader
|
|||
u32 rightColorBody;
|
||||
u32 rightColorbuttons;
|
||||
} HidControllerHeader;
|
||||
// static_assert(sizeof(HidControllerHeader) == 0x28, "Hid controller header structure has incorrect size");
|
||||
static_assert(sizeof(HidControllerHeader) == 0x28, "Hid controller header structure has incorrect size");
|
||||
|
||||
typedef struct HidControllerLayoutHeader
|
||||
{
|
||||
|
|
@ -487,7 +487,7 @@ typedef struct HidControllerLayoutHeader
|
|||
u64 latestEntry;
|
||||
u64 maxEntryIndex;
|
||||
} HidControllerLayoutHeader;
|
||||
// static_assert(sizeof(HidControllerLayoutHeader) == 0x20, "Hid controller layout header structure has incorrect size");
|
||||
static_assert(sizeof(HidControllerLayoutHeader) == 0x20, "Hid controller layout header structure has incorrect size");
|
||||
|
||||
typedef struct HidControllerInputEntry
|
||||
{
|
||||
|
|
@ -497,14 +497,14 @@ typedef struct HidControllerInputEntry
|
|||
JoystickPosition joysticks[JOYSTICK_NUM_STICKS];
|
||||
u64 connectionState;
|
||||
} HidControllerInputEntry;
|
||||
// static_assert(sizeof(HidControllerInputEntry) == 0x30, "Hid controller input entry structure has incorrect size");
|
||||
static_assert(sizeof(HidControllerInputEntry) == 0x30, "Hid controller input entry structure has incorrect size");
|
||||
|
||||
typedef struct HidControllerLayout
|
||||
{
|
||||
HidControllerLayoutHeader header;
|
||||
HidControllerInputEntry entries[17];
|
||||
} HidControllerLayout;
|
||||
// static_assert(sizeof(HidControllerLayout) == 0x350, "Hid controller layout structure has incorrect size");
|
||||
static_assert(sizeof(HidControllerLayout) == 0x350, "Hid controller layout structure has incorrect size");
|
||||
|
||||
typedef struct HidController
|
||||
{
|
||||
|
|
@ -515,7 +515,7 @@ typedef struct HidController
|
|||
HidControllerMAC macRight;
|
||||
u8 unk_2[0xDF8];
|
||||
} HidController;
|
||||
// static_assert(sizeof(HidController) == 0x5000, "Hid controller structure has incorrect size");
|
||||
static_assert(sizeof(HidController) == 0x5000, "Hid controller structure has incorrect size");
|
||||
|
||||
// End HidController
|
||||
|
||||
|
|
@ -537,14 +537,14 @@ typedef struct HidSharedMemory
|
|||
HidController controllers[10];
|
||||
u8 unkSection9[0x4600];
|
||||
} HidSharedMemory;
|
||||
// static_assert(sizeof(HidSharedMemory) == 0x40000, "Hid Shared Memory structure has incorrect size");
|
||||
static_assert(sizeof(HidSharedMemory) == 0x40000, "Hid Shared Memory structure has incorrect size");
|
||||
|
||||
typedef struct HidVibrationDeviceInfo
|
||||
{
|
||||
u32 unk_x0;
|
||||
u32 unk_x4; ///< 0x1 for left-joycon, 0x2 for right-joycon.
|
||||
} HidVibrationDeviceInfo;
|
||||
// static_assert(sizeof(HidVibrationDeviceInfo) == 0x8, "Hid VibrationDeviceInfo structure has incorrect size");
|
||||
static_assert(sizeof(HidVibrationDeviceInfo) == 0x8, "Hid VibrationDeviceInfo structure has incorrect size");
|
||||
|
||||
typedef struct HidVibrationValue
|
||||
{
|
||||
|
|
@ -553,7 +553,7 @@ typedef struct HidVibrationValue
|
|||
float amp_high; ///< High Band amplitude. 1.0f: Max amplitude.
|
||||
float freq_high; ///< High Band frequency in Hz.
|
||||
} HidVibrationValue;
|
||||
// static_assert(sizeof(HidVibrationValue) == 0x10, "Hid VibrationValue structure has incorrect size");
|
||||
static_assert(sizeof(HidVibrationValue) == 0x10, "Hid VibrationValue structure has incorrect size");
|
||||
|
||||
Result hidInitialize(void);
|
||||
void hidExit(void);
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@
|
|||
#include "../types.h"
|
||||
#include "../kernel/svc.h"
|
||||
#include "../kernel/ipc.h"
|
||||
|
||||
|
||||
/// Service type.
|
||||
typedef enum {
|
||||
ServiceType_Uninitialized, ///< Uninitialized service.
|
||||
|
|
@ -18,106 +18,155 @@ typedef enum {
|
|||
ServiceType_DomainSubservice, ///< Domain subservice;
|
||||
ServiceType_Override ///< Service overriden in the homebrew environment.
|
||||
} ServiceType;
|
||||
|
||||
|
||||
/// Service object structure.
|
||||
typedef struct {
|
||||
Handle handle;
|
||||
u32 object_id;
|
||||
ServiceType type;
|
||||
} Service;
|
||||
|
||||
|
||||
/**
|
||||
* @brief Returns whether a service is overriden in the homebrew environment.
|
||||
* @param[in] s Service object.
|
||||
* @return true if overriden.
|
||||
*/
|
||||
static inline bool serviceIsOverride(Service* s);
|
||||
|
||||
static inline bool serviceIsOverride(Service* s) {
|
||||
return s->type == ServiceType_Override;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Returns whether a service has been initialized.
|
||||
* @param[in] s Service object.
|
||||
* @return true if initialized.
|
||||
*/
|
||||
static inline bool serviceIsActive(Service* s);
|
||||
|
||||
static inline bool serviceIsActive(Service* s) {
|
||||
return s->type != ServiceType_Uninitialized;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Returns whether a service is a domain.
|
||||
* @param[in] s Service object.
|
||||
* @return true if a domain.
|
||||
*/
|
||||
static inline bool serviceIsDomain(Service* s);
|
||||
|
||||
static inline bool serviceIsDomain(Service* s) {
|
||||
return s->type == ServiceType_Domain;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Returns whether a service is a domain subservice.
|
||||
* @param[in] s Service object.
|
||||
* @return true if a domain subservice.
|
||||
*/
|
||||
static inline bool serviceIsDomainSubservice(Service* s);
|
||||
|
||||
static inline bool serviceIsDomainSubservice(Service* s) {
|
||||
return s->type == ServiceType_DomainSubservice;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief For a domain/domain subservice, return the associated object ID.
|
||||
* @param[in] s Service object, necessarily a domain or domain subservice.
|
||||
* @return The object ID.
|
||||
*/
|
||||
static inline u32 serviceGetObjectId(Service* s);
|
||||
|
||||
static inline u32 serviceGetObjectId(Service* s) {
|
||||
return s->object_id;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Closes a domain object by ID.
|
||||
* @param[in] s Service object, necessarily a domain or domain subservice.
|
||||
* @param object_id ID of the object to close.
|
||||
* @return Result code.
|
||||
*/
|
||||
static inline Result serviceCloseObjectById(Service* s, u32 object_id);
|
||||
|
||||
static inline Result serviceCloseObjectById(Service* s, u32 object_id) {
|
||||
return ipcCloseObjectById(s->handle, object_id);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Dispatches an IPC request to a service.
|
||||
* @param[in] s Service object.
|
||||
* @return Result code.
|
||||
*/
|
||||
static inline Result serviceIpcDispatch(Service* s);
|
||||
|
||||
static inline Result serviceIpcDispatch(Service* s) {
|
||||
return ipcDispatch(s->handle);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Creates a service object from an IPC session handle.
|
||||
* @param[out] s Service object.
|
||||
* @param[in] h IPC session handle.
|
||||
*/
|
||||
static inline void serviceCreate(Service* s, Handle h);
|
||||
|
||||
static inline void serviceCreate(Service* s, Handle h) {
|
||||
s->handle = h;
|
||||
s->type = ServiceType_Normal;
|
||||
s->object_id = IPC_INVALID_OBJECT_ID;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Creates a domain subservice object from a parent service.
|
||||
* @param[out] s Service object.
|
||||
* @param[in] parent Parent service, necessarily a domain or domain subservice.
|
||||
* @param[in] object_id Object ID for this subservice.
|
||||
*/
|
||||
static inline void serviceCreateDomainSubservice(Service* s, Service* parent, u32 object_id);
|
||||
|
||||
static inline void serviceCreateDomainSubservice(Service* s, Service* parent, u32 object_id) {
|
||||
s->handle = parent->handle;
|
||||
s->type = ServiceType_DomainSubservice;
|
||||
s->object_id = object_id;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Converts a regular service to a domain.
|
||||
* @param[in] s Service object.
|
||||
* @return Result code.
|
||||
*/
|
||||
static inline Result serviceConvertToDomain(Service* s);
|
||||
|
||||
static inline Result serviceConvertToDomain(Service* s) {
|
||||
Result rc = ipcConvertSessionToDomain(s->handle, &s->object_id);
|
||||
if(R_SUCCEEDED(rc))
|
||||
s->type = ServiceType_Domain;
|
||||
return rc;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Closes a service.
|
||||
* @param[in] s Service object.
|
||||
*/
|
||||
static inline void serviceClose(Service* s);
|
||||
|
||||
static inline void serviceClose(Service* s) {
|
||||
switch (s->type) {
|
||||
|
||||
case ServiceType_Normal:
|
||||
case ServiceType_Domain:
|
||||
ipcCloseSession(s->handle);
|
||||
svcCloseHandle(s->handle);
|
||||
break;
|
||||
|
||||
case ServiceType_DomainSubservice:
|
||||
serviceCloseObjectById(s, s->object_id);
|
||||
break;
|
||||
|
||||
case ServiceType_Override:
|
||||
// Don't close because we don't own the overridden handle.
|
||||
break;
|
||||
|
||||
case ServiceType_Uninitialized:
|
||||
break;
|
||||
}
|
||||
|
||||
s->type = ServiceType_Uninitialized;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Initializes SM.
|
||||
* @return Result code.
|
||||
* @note This function is already called in the default application startup code (before main() is called).
|
||||
*/
|
||||
Result smInitialize(void);
|
||||
|
||||
|
||||
/**
|
||||
* @brief Uninitializes SM.
|
||||
* @return Result code.
|
||||
* @note This function is already handled in the default application exit code (after main() returns).
|
||||
*/
|
||||
void smExit(void);
|
||||
|
||||
|
||||
/**
|
||||
* @brief Requests a service from SM.
|
||||
* @param[out] service_out Service structure which will be filled in.
|
||||
|
|
@ -125,7 +174,7 @@ void smExit(void);
|
|||
* @return Result code.
|
||||
*/
|
||||
Result smGetService(Service* service_out, const char* name);
|
||||
|
||||
|
||||
/**
|
||||
* @brief Requests a service from SM, as an IPC session handle directly
|
||||
* @param[out] handle_out Variable containing IPC session handle.
|
||||
|
|
@ -133,14 +182,14 @@ Result smGetService(Service* service_out, const char* name);
|
|||
* @return Result code.
|
||||
*/
|
||||
Result smGetServiceOriginal(Handle* handle_out, u64 name);
|
||||
|
||||
|
||||
/**
|
||||
* @brief Retrieves an overriden service in the homebrew environment.
|
||||
* @param[in] name Name of the service to request (as 64-bit integer).
|
||||
* @return IPC session handle.
|
||||
*/
|
||||
Handle smGetServiceOverride(u64 name);
|
||||
|
||||
|
||||
/**
|
||||
* @brief Creates and registers a new service within SM.
|
||||
* @param[out] handle_out Variable containing IPC port handle.
|
||||
|
|
@ -150,27 +199,27 @@ Handle smGetServiceOverride(u64 name);
|
|||
* @return Result code.
|
||||
*/
|
||||
Result smRegisterService(Handle* handle_out, const char* name, bool is_light, int max_sessions);
|
||||
|
||||
|
||||
/**
|
||||
* @brief Unregisters a previously registered service in SM.
|
||||
* @param[in] name Name of the service.
|
||||
* @return Result code.
|
||||
*/
|
||||
Result smUnregisterService(const char* name);
|
||||
|
||||
|
||||
/**
|
||||
* @brief Check whether SM is initialized.
|
||||
* @return true if initialized.
|
||||
*/
|
||||
bool smHasInitialized(void);
|
||||
|
||||
|
||||
/**
|
||||
* @brief Encodes a service name as a 64-bit integer.
|
||||
* @param[in] name Name of the service.
|
||||
* @return Encoded name.
|
||||
*/
|
||||
u64 smEncodeName(const char* name);
|
||||
|
||||
|
||||
/**
|
||||
* @brief Overrides a service with a custom IPC service handle.
|
||||
* @param[in] name Name of the service (as 64-bit integer).
|
||||
|
|
|
|||
|
|
@ -203,4 +203,4 @@ proc smEncodeName*(name: cstring): uint64 {.cdecl, importc: "smEncodeName",
|
|||
##
|
||||
|
||||
proc smAddOverrideHandle*(name: uint64; handle: Handle) {.cdecl,
|
||||
importc: "smAddOverrideHandle", header: headersm.}
|
||||
importc: "smAddOverrideHandle", header: headersm.}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue