From e7fbdf9eb170d5eb9564a2aa28870692aae362b8 Mon Sep 17 00:00:00 2001 From: yellows8 Date: Tue, 4 Aug 2020 20:32:15 -0400 Subject: [PATCH] Added btmsys. --- nx/include/switch.h | 1 + nx/include/switch/services/btmsys.h | 82 +++++++++++++++++++ nx/source/services/btmsys.c | 119 ++++++++++++++++++++++++++++ 3 files changed, 202 insertions(+) create mode 100644 nx/include/switch/services/btmsys.h create mode 100644 nx/source/services/btmsys.c diff --git a/nx/include/switch.h b/nx/include/switch.h index f8ea0f27..c3f36f49 100644 --- a/nx/include/switch.h +++ b/nx/include/switch.h @@ -96,6 +96,7 @@ extern "C" { #include "switch/services/bt.h" #include "switch/services/btdrv.h" #include "switch/services/btmu.h" +#include "switch/services/btmsys.h" #include "switch/services/spl.h" #include "switch/services/ncm.h" #include "switch/services/psc.h" diff --git a/nx/include/switch/services/btmsys.h b/nx/include/switch/services/btmsys.h new file mode 100644 index 00000000..ee9af1d5 --- /dev/null +++ b/nx/include/switch/services/btmsys.h @@ -0,0 +1,82 @@ +/** + * @file btmsys.h + * @brief btm:sys (btm system) service IPC wrapper. + * @author yellows8 + */ +#pragma once +#include "../types.h" +#include "../kernel/event.h" +#include "../sf/service.h" + +/// Initialize btm:sys. +Result btmsysInitialize(void); + +/// Exit btm:sys. +void btmsysExit(void); + +/// Gets the Service object for the actual btm:sys service session. This object must be closed by the user once finished using cmds with this. +Result btmsysGetServiceSession(Service* srv_out); + +/// Gets the Service object for IBtmSystemCore. +Service* btmsysGetServiceSession_IBtmSystemCore(void); + +/** + * @brief StartGamepadPairing + */ +Result btmsysStartGamepadPairing(void); + +/** + * @brief CancelGamepadPairing + */ +Result btmsysCancelGamepadPairing(void); + +/** + * @brief ClearGamepadPairingDatabase + */ +Result btmsysClearGamepadPairingDatabase(void); + +/** + * @brief GetPairedGamepadCount + * @param[out] out Output count. + */ +Result btmsysGetPairedGamepadCount(u8 *out); + +/** + * @brief EnableRadio + */ +Result btmsysEnableRadio(void); + +/** + * @brief DisableRadio + */ +Result btmsysDisableRadio(void); + +/** + * @brief GetRadioOnOff + * @param[out] out Output flag. + */ +Result btmsysGetRadioOnOff(bool *out); + +/** + * @brief AcquireRadioEvent + * @note Only available on [3.0.0+]. + * @note The Event must be closed by the user once finished with it. + * @param[out] out_event Output Event with autoclear=true. + */ +Result btmsysAcquireRadioEvent(Event* out_event); + +/** + * @brief AcquireGamepadPairingEvent + * @note Only available on [3.0.0+]. + * @note The Event must be closed by the user once finished with it. + * @param[out] out_event Output Event with autoclear=true. + */ +Result btmsysAcquireGamepadPairingEvent(Event* out_event); + +/** + * @brief IsGamepadPairingStarted + * @note Only available on [3.0.0+]. + * @param[out] out Output flag. + */ +Result btmsysIsGamepadPairingStarted(bool *out); + diff --git a/nx/source/services/btmsys.c b/nx/source/services/btmsys.c new file mode 100644 index 00000000..ceef6060 --- /dev/null +++ b/nx/source/services/btmsys.c @@ -0,0 +1,119 @@ +#define NX_SERVICE_ASSUME_NON_DOMAIN +#include +#include "service_guard.h" +#include "runtime/hosversion.h" +#include "services/btmsys.h" + +static Service g_btmIBtmSystemCore; + +static Result _btmsysGetSession(Service* srv, Service* srv_out, u32 cmd_id); + +NX_GENERATE_SERVICE_GUARD(btmsys); + +Result _btmsysInitialize(void) { + Result rc=0; + Service srv={0}; + + rc = btmsysGetServiceSession(&srv); + if (R_SUCCEEDED(rc)) rc = _btmsysGetSession(&srv, &g_btmIBtmSystemCore, 0); // GetCore + serviceClose(&srv); + return rc; +} + +void _btmsysCleanup(void) { + serviceClose(&g_btmIBtmSystemCore); +} + +Result btmsysGetServiceSession(Service* srv_out) { + return smGetService(srv_out, "btm:sys"); +} + +Service* btmsysGetServiceSession_IBtmSystemCore(void) { + return &g_btmIBtmSystemCore; +} + +static Result _btmsysGetSession(Service* srv, Service* srv_out, u32 cmd_id) { + return serviceDispatch(srv, cmd_id, + .out_num_objects = 1, + .out_objects = srv_out, + ); +} + +static Result _btmsysCmdNoIO(u32 cmd_id) { + return serviceDispatch(&g_btmIBtmSystemCore, cmd_id); +} + +static Result _btmsysCmdNoInOutU8(u8 *out, u32 cmd_id) { + return serviceDispatchOut(&g_btmIBtmSystemCore, cmd_id, *out); +} + +static Result _btmsysCmdNoInOutBool(bool *out, u32 cmd_id) { + u8 tmp=0; + Result rc = _btmsysCmdNoInOutU8(&tmp, cmd_id); + if (R_SUCCEEDED(rc) && out) *out = tmp & 1; + return rc; +} + +static Result _btmsysCmdGetEventOutFlag(Event* out_event, bool autoclear, u32 cmd_id) { + Handle tmp_handle = INVALID_HANDLE; + Result rc = 0; + u8 out=0; + + rc = serviceDispatchOut(&g_btmIBtmSystemCore, cmd_id, out, + .out_handle_attrs = { SfOutHandleAttr_HipcCopy }, + .out_handles = &tmp_handle, + ); + if (R_SUCCEEDED(rc) && !out) rc = MAKERESULT(Module_Libnx, LibnxError_ShouldNotHappen); + if (R_SUCCEEDED(rc)) eventLoadRemote(out_event, tmp_handle, autoclear); + return rc; +} + +Result btmsysStartGamepadPairing(void) { + return _btmsysCmdNoIO(0); +} + +Result btmsysCancelGamepadPairing(void) { + return _btmsysCmdNoIO(1); +} + +Result btmsysClearGamepadPairingDatabase(void) { + return _btmsysCmdNoIO(2); +} + +Result btmsysGetPairedGamepadCount(u8 *out) { + return _btmsysCmdNoInOutU8(out, 3); +} + +Result btmsysEnableRadio(void) { + return _btmsysCmdNoIO(4); +} + +Result btmsysDisableRadio(void) { + return _btmsysCmdNoIO(5); +} + +Result btmsysGetRadioOnOff(bool *out) { + return _btmsysCmdNoInOutBool(out, 6); +} + +Result btmsysAcquireRadioEvent(Event* out_event) { + if (hosversionBefore(3,0,0)) + return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); + + return _btmsysCmdGetEventOutFlag(out_event, true, 7); +} + +Result btmsysAcquireGamepadPairingEvent(Event* out_event) { + if (hosversionBefore(3,0,0)) + return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); + + return _btmsysCmdGetEventOutFlag(out_event, true, 8); +} + +Result btmsysIsGamepadPairingStarted(bool *out) { + if (hosversionBefore(3,0,0)) + return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); + + return _btmsysCmdNoInOutBool(out, 9); +} +