Fix issues with static inline headers

This commit is contained in:
Joey Yakimowich-Payne 2018-06-24 11:59:50 +09:00
commit 3256600653
12 changed files with 829 additions and 393 deletions

View file

@ -1,5 +1,4 @@
{.emit:"typedef __uint128_t NU128; typedef __int128_t NI128;".} import strutils
# Capacity of 42 because it seems # Capacity of 42 because it seems
# reasonable that the number will fit. # reasonable that the number will fit.
# If it doesn't, nim will just allocate # If it doesn't, nim will just allocate
@ -7,11 +6,11 @@
const STRING_CAPACITY = 42 const STRING_CAPACITY = 42
type type
s128* {.importc: "NI128"} = object s128* {.importc: "__int128_t"} = object
high: int64 high: int64
low: uint64 low: uint64
u128* {.importc: "NU128"} = object u128* {.importc: "__uint128_t"} = object
high, low: uint64 high, low: uint64
helperInt128 = object helperInt128 = object
@ -327,6 +326,9 @@ proc `$`*(val: s128): string =
result = str result = str
proc toHex*(val: u128): string =
result = val.hi.toHex & val.lo.toHex
proc `$`*(val: u128): string = proc `$`*(val: u128): string =
var v = val var v = val

View file

@ -11,4 +11,8 @@
* @brief Gets the thread local storage buffer. * @brief Gets the thread local storage buffer.
* @return 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;
}

View file

@ -97,4 +97,21 @@ void gfxFlushBuffers(void);
/// Use this to get the pixel-offset in the framebuffer. Returned value is in pixels, not bytes. /// 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. /// This implements tegra blocklinear, with hard-coded constants etc.
/// Do not use this when \ref GfxMode is GfxMode_LinearDouble. /// 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;
}

View file

@ -2,46 +2,46 @@
//The below defines are based on Linux kernel ioctl.h. //The below defines are based on Linux kernel ioctl.h.
#define UNV_IOC_NRBITS 8 #define _NV_IOC_NRBITS 8
#define UNV_IOC_TYPEBITS 8 #define _NV_IOC_TYPEBITS 8
#define UNV_IOC_SIZEBITS 14 #define _NV_IOC_SIZEBITS 14
#define UNV_IOC_DIRBITS 2 #define _NV_IOC_DIRBITS 2
#define UNV_IOC_NRMASK ((1 << UNV_IOC_NRBITS)-1) #define _NV_IOC_NRMASK ((1 << _NV_IOC_NRBITS)-1)
#define UNV_IOC_TYPEMASK ((1 << UNV_IOC_TYPEBITS)-1) #define _NV_IOC_TYPEMASK ((1 << _NV_IOC_TYPEBITS)-1)
#define UNV_IOC_SIZEMASK ((1 << UNV_IOC_SIZEBITS)-1) #define _NV_IOC_SIZEMASK ((1 << _NV_IOC_SIZEBITS)-1)
#define UNV_IOC_DIRMASK ((1 << UNV_IOC_DIRBITS)-1) #define _NV_IOC_DIRMASK ((1 << _NV_IOC_DIRBITS)-1)
#define UNV_IOC_NRSHIFT 0 #define _NV_IOC_NRSHIFT 0
#define UNV_IOC_TYPESHIFT (UNV_IOC_NRSHIFT+UNV_IOC_NRBITS) #define _NV_IOC_TYPESHIFT (_NV_IOC_NRSHIFT+_NV_IOC_NRBITS)
#define UNV_IOC_SIZESHIFT (UNV_IOC_TYPESHIFT+UNV_IOC_TYPEBITS) #define _NV_IOC_SIZESHIFT (_NV_IOC_TYPESHIFT+_NV_IOC_TYPEBITS)
#define UNV_IOC_DIRSHIFT (UNV_IOC_SIZESHIFT+UNV_IOC_SIZEBITS) #define _NV_IOC_DIRSHIFT (_NV_IOC_SIZESHIFT+_NV_IOC_SIZEBITS)
/* /*
* Direction bits. * Direction bits.
*/ */
#define UNV_IOC_NONE 0U #define _NV_IOC_NONE 0U
#define UNV_IOC_WRITE 1U #define _NV_IOC_WRITE 1U
#define UNV_IOC_READ 2U #define _NV_IOC_READ 2U
#define UNV_IOC(dir,type,nr,size) \ #define _NV_IOC(dir,type,nr,size) \
(((dir) << UNV_IOC_DIRSHIFT) | \ (((dir) << _NV_IOC_DIRSHIFT) | \
((type) << UNV_IOC_TYPESHIFT) | \ ((type) << _NV_IOC_TYPESHIFT) | \
((nr) << UNV_IOC_NRSHIFT) | \ ((nr) << _NV_IOC_NRSHIFT) | \
((size) << UNV_IOC_SIZESHIFT)) ((size) << _NV_IOC_SIZESHIFT))
/* used to create numbers */ /* used to create numbers */
#define UNV_IO(type,nr) UNV_IOC(UNV_IOC_NONE,(type),(nr),0) #define _NV_IO(type,nr) _NV_IOC(_NV_IOC_NONE,(type),(nr),0)
#define UNV_IOR(type,nr,size) UNV_IOC(UNV_IOC_READ,(type),(nr),sizeof(size)) #define _NV_IOR(type,nr,size) _NV_IOC(_NV_IOC_READ,(type),(nr),sizeof(size))
#define UNV_IOW(type,nr,size) UNV_IOC(UNV_IOC_WRITE,(type),(nr),sizeof(size)) #define _NV_IOW(type,nr,size) _NV_IOC(_NV_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_IOWR(type,nr,size) _NV_IOC(_NV_IOC_READ|_NV_IOC_WRITE,(type),(nr),sizeof(size))
/* used to decode ioctl numbers.. */ /* used to decode ioctl numbers.. */
#define UNV_IOC_DIR(nr) (((nr) >> UNV_IOC_DIRSHIFT) & UNV_IOC_DIRMASK) #define _NV_IOC_DIR(nr) (((nr) >> _NV_IOC_DIRSHIFT) & _NV_IOC_DIRMASK)
#define UNV_IOC_TYPE(nr) (((nr) >> UNV_IOC_TYPESHIFT) & UNV_IOC_TYPEMASK) #define _NV_IOC_TYPE(nr) (((nr) >> _NV_IOC_TYPESHIFT) & _NV_IOC_TYPEMASK)
#define UNV_IOC_NR(nr) (((nr) >> UNV_IOC_NRSHIFT) & UNV_IOC_NRMASK) #define _NV_IOC_NR(nr) (((nr) >> _NV_IOC_NRSHIFT) & _NV_IOC_NRMASK)
#define UNV_IOC_SIZE(nr) (((nr) >> UNV_IOC_SIZESHIFT) & UNV_IOC_SIZEMASK) #define _NV_IOC_SIZE(nr) (((nr) >> _NV_IOC_SIZESHIFT) & _NV_IOC_SIZEMASK)
#define DUnv_in #define __nv_in
#define DUnv_out #define __nv_out
#define DUnv_inout #define __nv_inout

View file

@ -36,7 +36,10 @@ Result condvarWaitTimeout(CondVar* c, u64 timeout);
* @remark On function return, the underlying mutex is acquired. * @remark On function return, the underlying mutex is acquired.
*/ */
static inline Result condvarWait(CondVar* c) 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. * @brief Wakes up up to the specified number of threads waiting on a condition variable.
* @param[in] c Condition variable object. * @param[in] c Condition variable object.
@ -51,10 +54,16 @@ Result condvarWake(CondVar* c, int num);
* @return Result code. * @return Result code.
*/ */
static inline Result condvarWakeOne(CondVar* c) static inline Result condvarWakeOne(CondVar* c)
; {
return condvarWake(c, 1);
}
/** /**
* @brief Wakes up all thread waiting on a condition variable. * @brief Wakes up all thread waiting on a condition variable.
* @param[in] c Condition variable object. * @param[in] c Condition variable object.
* @return Result code. * @return Result code.
*/ */
static inline Result condvarWakeAll(CondVar* c); static inline Result condvarWakeAll(CondVar* c)
{
return condvarWake(c, -1);
}

View file

@ -75,7 +75,9 @@ typedef struct {
* @brief Initializes an IPC command structure. * @brief Initializes an IPC command structure.
* @param cmd 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. /// IPC buffer descriptor.
typedef struct { typedef struct {
@ -103,7 +105,13 @@ typedef struct {
* @param size Size of the buffer. * @param size Size of the buffer.
* @param type Buffer type. * @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. * @brief Adds a receive-buffer to an IPC command structure.
@ -112,7 +120,13 @@ static inline void ipcAddSendBuffer(IpcCommand* cmd, const void* buffer, size_t
* @param size Size of the buffer. * @param size Size of the buffer.
* @param type Buffer type. * @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. * @brief Adds an exchange-buffer to an IPC command structure.
@ -121,7 +135,13 @@ static inline void ipcAddRecvBuffer(IpcCommand* cmd, void* buffer, size_t size,
* @param size Size of the buffer. * @param size Size of the buffer.
* @param type Buffer type. * @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. * @brief Adds a static-buffer to an IPC command structure.
@ -130,7 +150,13 @@ static inline void ipcAddExchBuffer(IpcCommand* cmd, void* buffer, size_t size,
* @param size Size of the buffer. * @param size Size of the buffer.
* @param index Index of 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. * @brief Adds a static-receive-buffer to an IPC command structure.
@ -139,7 +165,13 @@ static inline void ipcAddSendStatic(IpcCommand* cmd, const void* buffer, size_t
* @param size Size of the buffer. * @param size Size of the buffer.
* @param index Index of 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. * @brief Adds a smart-buffer (buffer + static-buffer pair) to an IPC command structure.
@ -149,7 +181,15 @@ static inline void ipcAddRecvStatic(IpcCommand* cmd, void* buffer, size_t size,
* @param size Size of the buffer. * @param size Size of the buffer.
* @param index Index of 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. * @brief Adds a smart-receive-buffer (buffer + static-receive-buffer pair) to an IPC command structure.
@ -159,13 +199,23 @@ static inline void ipcAddSendSmart(IpcCommand* cmd, size_t ipc_buffer_size, cons
* @param size Size of the buffer. * @param size Size of the buffer.
* @param index Index of 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. * @brief Tags an IPC command structure to send the PID.
* @param cmd IPC command structure. * @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. * @brief Adds a copy-handle to be sent through an IPC command structure.
@ -173,7 +223,9 @@ static inline void ipcSendPid(IpcCommand* cmd);
* @param h Handle to send. * @param h Handle to send.
* @remark The receiving process gets a copy of the handle. * @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. * @brief Adds a move-handle to be sent through an IPC command structure.
@ -181,7 +233,9 @@ static inline void ipcSendHandleCopy(IpcCommand* cmd, Handle h);
* @param h Handle to send. * @param h Handle to send.
* @remark The sending process loses ownership of the handle, which is transferred to the receiving process. * @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. * @brief Prepares the header of an IPC command structure.
@ -189,14 +243,94 @@ static inline void ipcSendHandleMove(IpcCommand* cmd, Handle h);
* @param sizeof_raw Size in bytes of the raw data structure to embed inside the IPC request * @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. * @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. * @brief Dispatches an IPC request.
* @param session IPC session handle. * @param session IPC session handle.
* @return Result code. * @return Result code.
*/ */
static inline Result ipcDispatch(Handle session); static inline Result ipcDispatch(Handle session) {
return svcSendSyncRequest(session);
}
///@} ///@}
@ -241,7 +375,97 @@ typedef struct {
* @param IPC parsed command structure to fill in. * @param IPC parsed command structure to fill in.
* @return Result code. * @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. * @brief Queries the size of an IPC pointer buffer.
@ -249,14 +473,51 @@ static inline Result ipcParse(IpcParsedCommand* r);
* @param size Output variable in which to store the size. * @param size Output variable in which to store the size.
* @return Result code. * @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. * @brief Closes the IPC session with proper clean up.
* @param session IPC session handle. * @param session IPC session handle.
* @return Result code. * @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 ///@name IPC domain handling
@ -268,14 +529,46 @@ static inline Result ipcCloseSession(Handle session);
* @param object_id_out Output variable in which to store the object ID. * @param object_id_out Output variable in which to store the object ID.
* @return Result code. * @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. * @brief Adds an object ID to be sent through an IPC domain command structure.
* @param cmd IPC domain command structure. * @param cmd IPC domain command structure.
* @param object_id Object ID to send. * @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. /// IPC domain message header.
typedef struct { typedef struct {
@ -293,14 +586,45 @@ typedef struct {
* @oaram object_id Domain object ID. * @oaram object_id Domain object ID.
* @return Pointer to the raw embedded data structure in the request, ready to be filled out. * @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). * @brief Parse an IPC command response into an IPC parsed command structure (domain version).
* @param IPC parsed command structure to fill in. * @param IPC parsed command structure to fill in.
* @return Result code. * @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. * @brief Closes a domain object by ID.
@ -308,6 +632,20 @@ static inline Result ipcParseForDomain(IpcParsedCommand* r);
* @param object_id ID of the object to close. * @param object_id ID of the object to close.
* @return Result code. * @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
}
///@} ///@}

View file

@ -55,7 +55,9 @@ Result shmemUnmap(SharedMemory* s);
* @param s Shared memory information structure. * @param s Shared memory information structure.
* @return Mapped address of the shared memory object. * @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. * @brief Frees up resources used by a shared memory object, unmapping and closing handles, etc.

View file

@ -95,7 +95,7 @@ typedef struct {
/// Secure monitor arguments. /// Secure monitor arguments.
typedef struct { typedef struct {
u64 X[8]; ///< Values of X0 through X7. u64 X[8]; ///< Values of X0 through X7.
} SecmonArgs; } PACKED SecmonArgs;
/// Code memory mapping operations /// Code memory mapping operations
typedef enum { typedef enum {
@ -208,7 +208,7 @@ Result svcQueryMemory(MemoryInfo* meminfo_ptr, u32 *pageinfo, u64 addr);
* @note Syscall number 0x07. * @note Syscall number 0x07.
*/ */
void svcExitProcess(void); void NORETURN svcExitProcess(void);
/** /**
* @brief Creates a thread. * @brief Creates a thread.
@ -228,7 +228,7 @@ Result svcStartThread(Handle handle);
* @brief Exits the current thread. * @brief Exits the current thread.
* @note Syscall number 0x0A. * @note Syscall number 0x0A.
*/ */
void svcExitThread(void); void NORETURN svcExitThread(void);
/** /**
* @brief Sleeps the current thread for the specified amount of time. * @brief Sleeps the current thread for the specified amount of time.
@ -346,7 +346,10 @@ Result svcWaitSynchronization(s32* index, const Handle* handles, s32 handleCount
* @return Result code. * @return Result code.
* @note Wrapper for \ref svcWaitSynchronization. * @note Wrapper for \ref svcWaitSynchronization.
*/ */
static inline Result svcWaitSynchronizationSingle(Handle handle, u64 timeout); static inline Result svcWaitSynchronizationSingle(Handle handle, u64 timeout) {
s32 tmp;
return svcWaitSynchronization(&tmp, &handle, 1, timeout);
}
/** /**
* @brief Waits a \ref svcWaitSynchronization operation being done on a synchronization object in another thread. * @brief Waits a \ref svcWaitSynchronization operation being done on a synchronization object in another thread.

View file

@ -1,5 +1,5 @@
/** /**
* @file Romfs_dev.h * @file romfs_dev.h
* @brief RomFS driver. * @brief RomFS driver.
* @author yellows8 * @author yellows8
* @author mtheall * @author mtheall
@ -24,7 +24,7 @@ typedef struct
u64 fileTableOff; ///< Offset of the file table. u64 fileTableOff; ///< Offset of the file table.
u64 fileTableSize; ///< Size of the file table. u64 fileTableSize; ///< Size of the file table.
u64 fileDataOff; ///< Offset of the file data. u64 fileDataOff; ///< Offset of the file data.
} Romfs_header; } romfs_header;
/// RomFS directory. /// RomFS directory.
typedef struct typedef struct
@ -36,7 +36,7 @@ typedef struct
u32 nextHash; ///< Directory hash table pointer. u32 nextHash; ///< Directory hash table pointer.
u32 nameLen; ///< Name length. u32 nameLen; ///< Name length.
uint8_t name[]; ///< Name. (UTF-8) uint8_t name[]; ///< Name. (UTF-8)
} Romfs_dir; } romfs_dir;
/// RomFS file. /// RomFS file.
typedef struct typedef struct
@ -48,39 +48,51 @@ typedef struct
u32 nextHash; ///< File hash table pointer. u32 nextHash; ///< File hash table pointer.
u32 nameLen; ///< Name length. u32 nameLen; ///< Name length.
uint8_t name[]; ///< Name. (UTF-8) uint8_t name[]; ///< Name. (UTF-8)
} Romfs_file; } romfs_file;
struct Romfs_mount; struct romfs_mount;
/** /**
* @brief Mounts the Application's RomFS. * @brief Mounts the Application's RomFS.
* @param mount Output mount handle * @param mount Output mount handle
*/ */
Result romfsMount(struct Romfs_mount **mount); Result romfsMount(struct romfs_mount **mount);
static inline Result romfsInit(void) static inline Result romfsInit(void)
; {
return romfsMount(NULL);
}
/** /**
* @brief Mounts RomFS from an open file. * @brief Mounts RomFS from an open file.
* @param file FsFile of the RomFS image. * @param file FsFile of the RomFS image.
* @param offset Offset of the RomFS within the file. * @param offset Offset of the RomFS within the file.
* @param mount Output mount handle * @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) static inline Result romfsInitFromFile(FsFile file, u64 offset)
; {
return romfsMountFromFile(file, offset, NULL);
}
/** /**
* @brief Mounts RomFS from an open storage. * @brief Mounts RomFS from an open storage.
* @param storage FsStorage of the RomFS image. * @param storage FsStorage of the RomFS image.
* @param offset Offset of the RomFS within the storage. * @param offset Offset of the RomFS within the storage.
* @param mount Output mount handle * @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) static inline Result romfsInitFromStorage(FsStorage storage, u64 offset)
; {
return romfsMountFromStorage(storage, offset, NULL);
}
/// Bind the RomFS mount /// Bind the RomFS mount
Result romfsBind(struct Romfs_mount *mount); Result romfsBind(struct romfs_mount *mount);
/// Unmounts the RomFS device. /// Unmounts the RomFS device.
Result romfsUnmount(struct Romfs_mount *mount); Result romfsUnmount(struct romfs_mount *mount);
static inline Result romfsExit(void) static inline Result romfsExit(void)
; {
return romfsUnmount(NULL);
}

View file

@ -353,14 +353,14 @@ typedef struct HidTouchScreenHeader
u64 maxEntryIndex; u64 maxEntryIndex;
u64 timestamp; u64 timestamp;
} HidTouchScreenHeader; } 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 typedef struct HidTouchScreenEntryHeader
{ {
u64 timestamp; u64 timestamp;
u64 numTouches; u64 numTouches;
} HidTouchScreenEntryHeader; } 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 typedef struct HidTouchScreenEntryTouch
{ {
@ -374,7 +374,7 @@ typedef struct HidTouchScreenEntryTouch
u32 angle; u32 angle;
u32 padding_2; u32 padding_2;
} HidTouchScreenEntryTouch; } 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 typedef struct HidTouchScreenEntry
{ {
@ -382,7 +382,7 @@ typedef struct HidTouchScreenEntry
HidTouchScreenEntryTouch touches[16]; HidTouchScreenEntryTouch touches[16];
u64 unk; u64 unk;
} HidTouchScreenEntry; } 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 typedef struct HidTouchScreen
{ {
@ -390,7 +390,7 @@ typedef struct HidTouchScreen
HidTouchScreenEntry entries[17]; HidTouchScreenEntry entries[17];
u8 padding[0x3c0]; u8 padding[0x3c0];
} HidTouchScreen; } 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 // End HidTouchScreen
@ -403,7 +403,7 @@ typedef struct HidMouseHeader
u64 latestEntry; u64 latestEntry;
u64 maxEntryIndex; u64 maxEntryIndex;
} HidMouseHeader; } 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 typedef struct HidMouseEntry
{ {
@ -412,7 +412,7 @@ typedef struct HidMouseEntry
MousePosition position; MousePosition position;
u64 buttons; u64 buttons;
} HidMouseEntry; } 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 typedef struct HidMouse
{ {
@ -420,7 +420,7 @@ typedef struct HidMouse
HidMouseEntry entries[17]; HidMouseEntry entries[17];
u8 padding[0xB0]; u8 padding[0xB0];
} HidMouse; } 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 // End HidMouse
@ -433,7 +433,7 @@ typedef struct HidKeyboardHeader
u64 latestEntry; u64 latestEntry;
u64 maxEntryIndex; u64 maxEntryIndex;
} HidKeyboardHeader; } 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 typedef struct HidKeyboardEntry
{ {
@ -442,7 +442,7 @@ typedef struct HidKeyboardEntry
u64 modifier; u64 modifier;
u32 keys[8]; u32 keys[8];
} HidKeyboardEntry; } 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 typedef struct HidKeyboard
{ {
@ -450,7 +450,7 @@ typedef struct HidKeyboard
HidKeyboardEntry entries[17]; HidKeyboardEntry entries[17];
u8 padding[0x28]; u8 padding[0x28];
} HidKeyboard; } 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 // End HidKeyboard
@ -463,7 +463,7 @@ typedef struct HidControllerMAC
u64 unk; u64 unk;
u64 timestamp_2; u64 timestamp_2;
} HidControllerMAC; } 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 typedef struct HidControllerHeader
{ {
@ -478,7 +478,7 @@ typedef struct HidControllerHeader
u32 rightColorBody; u32 rightColorBody;
u32 rightColorbuttons; u32 rightColorbuttons;
} HidControllerHeader; } 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 typedef struct HidControllerLayoutHeader
{ {
@ -487,7 +487,7 @@ typedef struct HidControllerLayoutHeader
u64 latestEntry; u64 latestEntry;
u64 maxEntryIndex; u64 maxEntryIndex;
} HidControllerLayoutHeader; } 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 typedef struct HidControllerInputEntry
{ {
@ -497,14 +497,14 @@ typedef struct HidControllerInputEntry
JoystickPosition joysticks[JOYSTICK_NUM_STICKS]; JoystickPosition joysticks[JOYSTICK_NUM_STICKS];
u64 connectionState; u64 connectionState;
} HidControllerInputEntry; } 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 typedef struct HidControllerLayout
{ {
HidControllerLayoutHeader header; HidControllerLayoutHeader header;
HidControllerInputEntry entries[17]; HidControllerInputEntry entries[17];
} HidControllerLayout; } 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 typedef struct HidController
{ {
@ -515,7 +515,7 @@ typedef struct HidController
HidControllerMAC macRight; HidControllerMAC macRight;
u8 unk_2[0xDF8]; u8 unk_2[0xDF8];
} HidController; } 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 // End HidController
@ -537,14 +537,14 @@ typedef struct HidSharedMemory
HidController controllers[10]; HidController controllers[10];
u8 unkSection9[0x4600]; u8 unkSection9[0x4600];
} HidSharedMemory; } 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 typedef struct HidVibrationDeviceInfo
{ {
u32 unk_x0; u32 unk_x0;
u32 unk_x4; ///< 0x1 for left-joycon, 0x2 for right-joycon. u32 unk_x4; ///< 0x1 for left-joycon, 0x2 for right-joycon.
} HidVibrationDeviceInfo; } 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 typedef struct HidVibrationValue
{ {
@ -553,7 +553,7 @@ typedef struct HidVibrationValue
float amp_high; ///< High Band amplitude. 1.0f: Max amplitude. float amp_high; ///< High Band amplitude. 1.0f: Max amplitude.
float freq_high; ///< High Band frequency in Hz. float freq_high; ///< High Band frequency in Hz.
} HidVibrationValue; } 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); Result hidInitialize(void);
void hidExit(void); void hidExit(void);

View file

@ -31,35 +31,45 @@ typedef struct {
* @param[in] s Service object. * @param[in] s Service object.
* @return true if overriden. * @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. * @brief Returns whether a service has been initialized.
* @param[in] s Service object. * @param[in] s Service object.
* @return true if initialized. * @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. * @brief Returns whether a service is a domain.
* @param[in] s Service object. * @param[in] s Service object.
* @return true if a domain. * @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. * @brief Returns whether a service is a domain subservice.
* @param[in] s Service object. * @param[in] s Service object.
* @return true if a domain subservice. * @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. * @brief For a domain/domain subservice, return the associated object ID.
* @param[in] s Service object, necessarily a domain or domain subservice. * @param[in] s Service object, necessarily a domain or domain subservice.
* @return The object ID. * @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. * @brief Closes a domain object by ID.
@ -67,21 +77,29 @@ static inline u32 serviceGetObjectId(Service* s);
* @param object_id ID of the object to close. * @param object_id ID of the object to close.
* @return Result code. * @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. * @brief Dispatches an IPC request to a service.
* @param[in] s Service object. * @param[in] s Service object.
* @return Result code. * @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. * @brief Creates a service object from an IPC session handle.
* @param[out] s Service object. * @param[out] s Service object.
* @param[in] h IPC session handle. * @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. * @brief Creates a domain subservice object from a parent service.
@ -89,20 +107,51 @@ static inline void serviceCreate(Service* s, Handle h);
* @param[in] parent Parent service, necessarily a domain or domain subservice. * @param[in] parent Parent service, necessarily a domain or domain subservice.
* @param[in] object_id Object ID for this 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. * @brief Converts a regular service to a domain.
* @param[in] s Service object. * @param[in] s Service object.
* @return Result code. * @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. * @brief Closes a service.
* @param[in] s Service object. * @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. * @brief Initializes SM.