Skip to content

btmsys: add missing 13.0.0 commands #664

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions nx/include/switch/services/btm_types.h
Original file line number Diff line number Diff line change
Expand Up @@ -298,3 +298,8 @@ typedef struct {
BtdrvGattAttributeUuid uuid; ///< \ref BtdrvGattAttributeUuid
} BtmBleDataPath;

/// AudioDevice
typedef struct {
BtdrvAddress addr; ///< Device address
char name[0xF9]; ///< Device name
} BtmAudioDevice;
103 changes: 103 additions & 0 deletions nx/include/switch/services/btmsys.h
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -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);
128 changes: 128 additions & 0 deletions nx/source/services/btmsys.c
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
#include <string.h>
#include "service_guard.h"
#include "runtime/hosversion.h"
#include "services/applet.h"
#include "services/btmsys.h"

static Service g_btmIBtmSystemCore;
Expand Down Expand Up @@ -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;
Expand All @@ -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);
}
Expand Down Expand Up @@ -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);
}