diff --git a/nx/include/switch.h b/nx/include/switch.h index f93296ca..fcc2b4f5 100644 --- a/nx/include/switch.h +++ b/nx/include/switch.h @@ -122,6 +122,7 @@ extern "C" { #include "switch/services/ldn.h" #include "switch/services/lp2p.h" #include "switch/services/news.h" +#include "switch/services/ins.h" #include "switch/display/binder.h" #include "switch/display/parcel.h" diff --git a/nx/include/switch/services/ins.h b/nx/include/switch/services/ins.h new file mode 100644 index 00000000..aba79303 --- /dev/null +++ b/nx/include/switch/services/ins.h @@ -0,0 +1,55 @@ +/** + * @file ins.h + * @brief INS services IPC wrapper. + * @author averne + * @copyright libnx Authors + */ +#pragma once +#include "../types.h" +#include "../kernel/event.h" +#include "../sf/service.h" + +/// Initialize ins:r. +Result insrInitialize(void); + +/// Exit ins:r. +void insrExit(void); + +/// Gets the Service object for the actual ins:r service session. +Service* insrGetServiceSession(void); + +/** + * @brief Retrieves the last system tick the event corresponding to the ID was signaled at. + * @param[in] id Ins request ID (should be 0..4). + * @param[out] tick. + * @return Result code. + * @note The tick is only updated once per second at minimum. + */ +Result insrGetLastTick(u32 id, u64 *tick); + +/** + * @brief Retrieves the event corresponding to the ID. + * @param[in] id Ins request ID (should be 0..4). + * @param[out] out. + * @return Result code. + * @note The event is only signaled once per second at minimum. + */ +Result insrGetReadableEvent(u32 id, Event *out); + +/// Initialize ins:s. +Result inssInitialize(void); + +/// Exit ins:s. +void inssExit(void); + +/// Gets the Service object for the actual ins:s service session. +Service* inssGetServiceSession(void); + +/** + * @brief Retrieves the event corresponding to the ID. + * @param[in] id Ins send ID (should be 0..11). + * @param[out] out. + * @return Result code. + * @note The returned event cannot be waited on, only signaled. Clearing is handled by the service. + */ +Result inssGetWritableEvent(u32 id, Event *out); diff --git a/nx/source/services/ins.c b/nx/source/services/ins.c new file mode 100644 index 00000000..313092e4 --- /dev/null +++ b/nx/source/services/ins.c @@ -0,0 +1,76 @@ +#include "service_guard.h" +#include "services/ins.h" + +static Service g_insrSrv; +static Service g_inssSrv; + +NX_GENERATE_SERVICE_GUARD(insr); + +Result _insrInitialize(void) { + return smGetService(&g_insrSrv, "ins:r"); +} + +void _insrCleanup(void) { + serviceClose(&g_insrSrv); +} + +Service* insrGetServiceSession(void) { + return &g_insrSrv; +} + +Result insrGetLastTick(u32 id, u64 *tick) { + return serviceDispatchInOut(&g_insrSrv, 0, id, *tick); +} + +Result insrGetReadableEvent(u32 id, Event *out) { + Handle tmp_handle; + struct { + u32 id; + u64 unk; + } in = { id, 0 }; + Result rc = serviceDispatchIn(&g_insrSrv, 1, in, + .out_handle_attrs = { SfOutHandleAttr_HipcCopy }, + .out_handles = &tmp_handle, + ); + + if (R_SUCCEEDED(rc)) + eventLoadRemote(out, tmp_handle, false); + + return rc; +} + +NX_GENERATE_SERVICE_GUARD(inss); + +Result _inssInitialize(void) { + return smGetService(&g_inssSrv, "ins:s"); +} + +void _inssCleanup(void) { + serviceClose(&g_inssSrv); +} + +Service* inssGetServiceSession(void) { + return &g_inssSrv; +} + +Result inssGetWritableEvent(u32 id, Event *out) { + Handle tmp_handle; + struct { + u32 id; + u64 unk; + } in = { id, 0 }; + Result rc = serviceDispatchIn(&g_inssSrv, 0, in, + .out_handle_attrs = { SfOutHandleAttr_HipcCopy }, + .out_handles = &tmp_handle, + ); + + if (R_SUCCEEDED(rc)) { + *out = (Event){ + .revent = INVALID_HANDLE, + .wevent = tmp_handle, + .autoclear = false, + }; + } + + return rc; +}