From b88afc509c18e3671de0968709fa5034a69d74fd Mon Sep 17 00:00:00 2001 From: ndeadly <24677491+ndeadly@users.noreply.github.com> Date: Mon, 31 Mar 2025 14:51:12 +0200 Subject: [PATCH] btmsys: add missing 13.0.0 commands --- nx/include/switch/services/btm_types.h | 5 + nx/include/switch/services/btmsys.h | 103 ++++++++++++++++++++ nx/source/services/btmsys.c | 128 +++++++++++++++++++++++++ 3 files changed, 236 insertions(+) diff --git a/nx/include/switch/services/btm_types.h b/nx/include/switch/services/btm_types.h index fd39e1d3..46ceeac4 100644 --- a/nx/include/switch/services/btm_types.h +++ b/nx/include/switch/services/btm_types.h @@ -298,3 +298,8 @@ typedef struct { BtdrvGattAttributeUuid uuid; ///< \ref BtdrvGattAttributeUuid } BtmBleDataPath; +/// AudioDevice +typedef struct { + BtdrvAddress addr; ///< Device address + char name[0xF9]; ///< Device name +} BtmAudioDevice; diff --git a/nx/include/switch/services/btmsys.h b/nx/include/switch/services/btmsys.h index ee9af1d5..553a8003 100644 --- a/nx/include/switch/services/btmsys.h +++ b/nx/include/switch/services/btmsys.h @@ -6,6 +6,8 @@ #pragma once #include "../types.h" #include "../kernel/event.h" +#include "../services/btdrv_types.h" +#include "../services/btm_types.h" #include "../sf/service.h" /// Initialize btm:sys. @@ -80,3 +82,104 @@ Result btmsysAcquireGamepadPairingEvent(Event* out_event); */ Result btmsysIsGamepadPairingStarted(bool *out); +/** + * @brief StartAudioDeviceDiscovery + * @note Only available on [13.0.0+]. + */ +Result btmsysStartAudioDeviceDiscovery(void); + +/** + * @brief StopAudioDeviceDiscovery + * @note Only available on [13.0.0+]. + */ +Result btmsysStopAudioDeviceDiscovery(void); + +/** + * @brief IsDiscoveryingAudioDevice + * @note Only available on [13.0.0+]. + * @param[out] out Output flag. + */ +Result btmsysIsDiscoveryingAudioDevice(bool *out); + +/** + * @brief GetDiscoveredAudioDevice + * @note Only available on [13.0.0+]. + * @param[out] out Output array of \ref BtmAudioDevice. + * @param[in] count Size of the out array in entries. The max is 15. + * @param[out] total_out Total output entries. + */ +Result btmsysGetDiscoveredAudioDevice(BtmAudioDevice *out, s32 count, s32 *total_out); + +/** + * @brief AcquireAudioDeviceConnectionEvent + * @note Only available on [13.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 btmsysAcquireAudioDeviceConnectionEvent(Event* out_event); + +/** + * @brief ConnectAudioDevice + * @note Only available on [13.0.0+]. + * @param[in] addr \ref BtdrvAddress + */ +Result btmsysConnectAudioDevice(BtdrvAddress addr); + +/** + * @brief IsConnectingAudioDevice + * @note Only available on [13.0.0+]. + * @param[out] out Output flag. + */ +Result btmsysIsConnectingAudioDevice(bool *out); + +/** + * @brief GetConnectedAudioDevices + * @note Only available on [13.0.0+]. + * @param[out] out Output array of \ref BtmAudioDevice. + * @param[in] count Size of the out array in entries. The max is 8. + * @param[out] total_out Total output entries. + */ +Result btmsysGetConnectedAudioDevices(BtmAudioDevice *out, s32 count, s32 *total_out); + +/** + * @brief DisconnectAudioDevice + * @note Only available on [13.0.0+]. + * @param[in] addr \ref BtdrvAddress + */ +Result btmsysDisconnectAudioDevice(BtdrvAddress addr); + +/** + * @brief AcquirePairedAudioDeviceInfoChangedEvent + * @note Only available on [13.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 btmsysAcquirePairedAudioDeviceInfoChangedEvent(Event* out_event); + +/** + * @brief GetPairedAudioDevices + * @note Only available on [13.0.0+]. + * @param[out] out Output array of \ref BtmAudioDevice. + * @param[in] count Size of the out array in entries. The max is 10. + * @param[out] total_out Total output entries. + */ +Result btmsysGetPairedAudioDevices(BtmAudioDevice *out, s32 count, s32 *total_out); + +/** + * @brief RemoveAudioDevicePairing + * @note Only available on [13.0.0+]. + * @param[in] addr \ref BtdrvAddress + */ +Result btmsysRemoveAudioDevicePairing(BtdrvAddress addr); + +/** + * @brief RequestAudioDeviceConnectionRejection + * @note Only available on [13.0.0+]. + */ +Result btmsysRequestAudioDeviceConnectionRejection(void); + +/** + * @brief CancelAudioDeviceConnectionRejection + * @note Only available on [13.0.0+]. + */ +Result btmsysCancelAudioDeviceConnectionRejection(void); diff --git a/nx/source/services/btmsys.c b/nx/source/services/btmsys.c index ceef6060..3a85a4b5 100644 --- a/nx/source/services/btmsys.c +++ b/nx/source/services/btmsys.c @@ -2,6 +2,7 @@ #include #include "service_guard.h" #include "runtime/hosversion.h" +#include "services/applet.h" #include "services/btmsys.h" static Service g_btmIBtmSystemCore; @@ -54,6 +55,18 @@ static Result _btmsysCmdNoInOutBool(bool *out, u32 cmd_id) { return rc; } +static Result _btmsysCmdGetEvent(Event* out_event, bool autoclear, u32 cmd_id) { + Handle tmp_handle = INVALID_HANDLE; + Result rc = 0; + + rc = serviceDispatch(&g_btmIBtmSystemCore, cmd_id, + .out_handle_attrs = { SfOutHandleAttr_HipcCopy }, + .out_handles = &tmp_handle, + ); + if (R_SUCCEEDED(rc)) eventLoadRemote(out_event, tmp_handle, autoclear); + return rc; +} + static Result _btmsysCmdGetEventOutFlag(Event* out_event, bool autoclear, u32 cmd_id) { Handle tmp_handle = INVALID_HANDLE; Result rc = 0; @@ -68,6 +81,24 @@ static Result _btmsysCmdGetEventOutFlag(Event* out_event, bool autoclear, u32 cm return rc; } +static Result _btmsysCmdOutBufPtr(void* buffer, size_t size, s32 *total_out, u32 cmd_id) { + return serviceDispatchOut(&g_btmIBtmSystemCore, cmd_id, *total_out, + .buffer_attrs = { SfBufferAttr_HipcPointer | SfBufferAttr_Out }, + .buffers = { {buffer, size} }, + ); +} + +static Result _btmsysCmdInAddrNoOut(BtdrvAddress addr, u32 cmd_id) { + return serviceDispatchIn(&g_btmIBtmSystemCore, cmd_id, addr); +} + +static Result _btmsysCmdAruidNoOutput(u32 cmd_id) { + u64 AppletResourceUserId = appletGetAppletResourceUserId(); + return serviceDispatchIn(&g_btmIBtmSystemCore, cmd_id, AppletResourceUserId, + .in_send_pid = true, + ); +} + Result btmsysStartGamepadPairing(void) { return _btmsysCmdNoIO(0); } @@ -117,3 +148,100 @@ Result btmsysIsGamepadPairingStarted(bool *out) { return _btmsysCmdNoInOutBool(out, 9); } +Result btmsysStartAudioDeviceDiscovery(void) { + if (hosversionBefore(13,0,0)) + return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); + + return _btmsysCmdNoIO(10); +} + +Result btmsysStopAudioDeviceDiscovery(void) { + if (hosversionBefore(13,0,0)) + return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); + + return _btmsysCmdNoIO(11); +} + +Result btmsysIsDiscoveryingAudioDevice(bool *out) { + if (hosversionBefore(13,0,0)) + return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); + + return _btmsysCmdNoInOutBool(out, 12); +} + +Result btmsysGetDiscoveredAudioDevice(BtmAudioDevice *out, s32 count, s32 *total_out) { + if (hosversionBefore(13,0,0)) + return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); + + return _btmsysCmdOutBufPtr(out, sizeof(BtmAudioDevice)*count, total_out, 13); +} + +Result btmsysAcquireAudioDeviceConnectionEvent(Event* out_event) { + if (hosversionBefore(13,0,0)) + return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); + + return _btmsysCmdGetEvent(out_event, true, 14); +} + +Result btmsysConnectAudioDevice(BtdrvAddress addr) { + if (hosversionBefore(13,0,0)) + return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); + + return _btmsysCmdInAddrNoOut(addr, 15); +} + +Result btmsysIsConnectingAudioDevice(bool *out) { + if (hosversionBefore(13,0,0)) + return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); + + return _btmsysCmdNoInOutBool(out, 16); +} + +Result btmsysGetConnectedAudioDevices(BtmAudioDevice *out, s32 count, s32 *total_out) { + if (hosversionBefore(13,0,0)) + return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); + + return _btmsysCmdOutBufPtr(out, sizeof(BtmAudioDevice)*count, total_out, 17); +} + +Result btmsysDisconnectAudioDevice(BtdrvAddress addr) { + if (hosversionBefore(13,0,0)) + return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); + + return _btmsysCmdInAddrNoOut(addr, 18); +} + +Result btmsysAcquirePairedAudioDeviceInfoChangedEvent(Event* out_event) { + if (hosversionBefore(13,0,0)) + return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); + + return _btmsysCmdGetEvent(out_event, true, 19); +} + +Result btmsysGetPairedAudioDevices(BtmAudioDevice *out, s32 count, s32 *total_out) { + if (hosversionBefore(13,0,0)) + return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); + + return _btmsysCmdOutBufPtr(out, sizeof(BtmAudioDevice)*count, total_out, 20); +} + +Result btmsysRemoveAudioDevicePairing(BtdrvAddress addr) { + if (hosversionBefore(13,0,0)) + return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); + + return _btmsysCmdInAddrNoOut(addr, 21); +} + +Result btmsysRequestAudioDeviceConnectionRejection(void) { + if (hosversionBefore(13,0,0)) + return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); + + return _btmsysCmdAruidNoOutput(22); +} + +Result btmsysCancelAudioDeviceConnectionRejection(void) { + if (hosversionBefore(13,0,0)) + return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); + + return _btmsysCmdAruidNoOutput(23); +}