diff --git a/nx/include/switch/services/btm.h b/nx/include/switch/services/btm.h index f9192c76..6f8b7c51 100644 --- a/nx/include/switch/services/btm.h +++ b/nx/include/switch/services/btm.h @@ -40,10 +40,19 @@ Result btmGetHostDeviceProperty(BtmHostDeviceProperty *out); Result btmAcquireDeviceConditionEvent(Event* out_event); /** - * @brief GetDeviceCondition + * @brief GetDeviceCondition [1.0.0-12.1.0] * @param[out] out \ref BtmDeviceCondition */ -Result btmGetDeviceCondition(BtmDeviceCondition *out); +Result btmLegacyGetDeviceCondition(BtmDeviceCondition *out); + +/** + * @brief GetDeviceCondition [13.0.0+] + * @param[in] id Id + * @param[out] out \ref BtmConnectedDeviceV13 + * @param[in] count Size of the out array in entries. + * @param[out] total_out Total output entries. + */ +Result btmGetDeviceCondition(u32 id, BtmConnectedDeviceV13 *out, size_t count, s32 *total_out); /** * @brief SetBurstMode @@ -79,10 +88,19 @@ Result btmSetWlanMode(BtmWlanMode mode); Result btmAcquireDeviceInfoEvent(Event* out_event); /** - * @brief GetDeviceInfo + * @brief GetDeviceInfo [1.0.0-12.1.0] * @param[out] out \ref BtmDeviceInfoList */ -Result btmGetDeviceInfo(BtmDeviceInfoList *out); +Result btmLegacyGetDeviceInfo(BtmDeviceInfoList *out); + +/** + * @brief GetDeviceInfo [13.0.0+] + * @param[in] id Id + * @param[out] out \ref BtmDeviceInfo + * @param[in] count Size of the out array in entries. + * @param[out] total_out Total output entries. + */ +Result btmGetDeviceInfo(u32 id, BtmDeviceInfo *out, size_t count, s32 *total_out); /** * @brief AddDeviceInfo diff --git a/nx/include/switch/services/btm_types.h b/nx/include/switch/services/btm_types.h index 9d3436f8..24eefa2f 100644 --- a/nx/include/switch/services/btm_types.h +++ b/nx/include/switch/services/btm_types.h @@ -91,7 +91,7 @@ typedef struct { u8 feature_set; ///< Same as BtdrvAdapterProperty::feature_set. } BtmHostDeviceProperty; -/// BtmConnectedDevice +/// BtmConnectedDevice [1.0.0-12.1.0] typedef struct { BtdrvAddress address; u8 pad[2]; @@ -101,7 +101,17 @@ typedef struct { u16 vid; u16 pid; u8 unk_x4C[0x20]; -} BtmConnectedDevice; +} BtmConnectedDeviceV1; + +/// BtmConnectedDevice [13.0.0+] +typedef struct { + BtdrvAddress address; + u8 pad[2]; + u32 unk_x8; + u8 unk_xC[0x40]; + char name[0x20]; + u8 unk_x6C[0xdc]; +} BtmConnectedDeviceV13; /// DeviceCondition [1.0.0-5.0.2] typedef struct { @@ -111,7 +121,7 @@ typedef struct { u8 unk_x9; u8 max_count; u8 connected_count; - BtmConnectedDevice devices[8]; + BtmConnectedDeviceV1 devices[8]; } BtmDeviceConditionV100; /// DeviceCondition [5.1.0-7.0.1] @@ -123,7 +133,7 @@ typedef struct { u8 max_count; u8 connected_count; u8 pad[3]; - BtmConnectedDevice devices[8]; + BtmConnectedDeviceV1 devices[8]; } BtmDeviceConditionV510; /// DeviceCondition [8.0.0-8.1.1] @@ -134,20 +144,20 @@ typedef struct { u8 unk_x9; u8 max_count; u8 connected_count; - BtmConnectedDevice devices[8]; + BtmConnectedDeviceV1 devices[8]; } BtmDeviceConditionV800; -/// DeviceCondition [9.0.0+] +/// DeviceCondition [9.0.0-12.1.0] typedef struct { u32 unk_x0; u8 unk_x4; u8 unk_x5; u8 max_count; u8 connected_count; - BtmConnectedDevice devices[8]; + BtmConnectedDeviceV1 devices[8]; } BtmDeviceConditionV900; -/// DeviceCondition +/// DeviceCondition [1.0.0-12.1.0] typedef union { BtmDeviceConditionV100 v100; BtmDeviceConditionV510 v510; diff --git a/nx/source/services/btm.c b/nx/source/services/btm.c index 3623ccd2..525811f5 100644 --- a/nx/source/services/btm.c +++ b/nx/source/services/btm.c @@ -108,6 +108,13 @@ static Result _btmCmdOutBufPtrFixed(void* buffer, size_t size, u32 cmd_id) { ); } +static Result _btmCmdInIdOutBufPtr(u32 id, void* buffer, size_t size, s32 *total_out, u32 cmd_id) { + return serviceDispatchInOut(&g_btmSrv, cmd_id, id, *total_out, + .buffer_attrs = { SfBufferAttr_HipcPointer | SfBufferAttr_Out }, + .buffers = { {buffer, size} }, + ); +} + static Result _btmGetBleScanResults(BtdrvBleScanResult *results, u8 count, u8 *total_out, u32 cmd_id) { return serviceDispatchOut(&g_btmSrv, cmd_id, *total_out, .buffer_attrs = { SfBufferAttr_HipcMapAlias | SfBufferAttr_Out }, @@ -156,7 +163,10 @@ Result btmAcquireDeviceConditionEvent(Event* out_event) { return _btmCmdGetEventOutFlag(out_event, true, 2); } -Result btmGetDeviceCondition(BtmDeviceCondition *out) { +Result btmLegacyGetDeviceCondition(BtmDeviceCondition *out) { + if (hosversionAtLeast(13,0,0)) + return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); + size_t buff_size; if (hosversionAtLeast(9,0,0)) buff_size = sizeof(BtmDeviceConditionV900); else if (hosversionAtLeast(8,0,0)) buff_size = sizeof(BtmDeviceConditionV800); @@ -165,6 +175,13 @@ Result btmGetDeviceCondition(BtmDeviceCondition *out) { return _btmCmdOutBufPtrFixed(out, buff_size, 3); } +Result btmGetDeviceCondition(u32 id, BtmConnectedDeviceV13 *out, size_t count, s32 *total_out) { + if (hosversionBefore(13,0,0)) + return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); + + return _btmCmdInIdOutBufPtr(id, out, sizeof(BtmConnectedDeviceV13)*count, total_out, 3); +} + Result btmSetBurstMode(BtdrvAddress addr, bool flag) { return _btmCmdInAddrBoolNoOut(addr, flag, 4); } @@ -188,10 +205,20 @@ Result btmAcquireDeviceInfoEvent(Event* out_event) { return _btmCmdGetEventOutFlag(out_event, true, 8); } -Result btmGetDeviceInfo(BtmDeviceInfoList *out) { +Result btmLegacyGetDeviceInfo(BtmDeviceInfoList *out) { + if (hosversionAtLeast(13,0,0)) + return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); + return _btmCmdOutBufPtrFixed(out, sizeof(*out), 9); } +Result btmGetDeviceInfo(u32 id, BtmDeviceInfo *out, size_t count, s32 *total_out) { + if (hosversionBefore(13,0,0)) + return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); + + return _btmCmdInIdOutBufPtr(id, out, sizeof(BtmDeviceInfo)*count, total_out, 9); +} + Result btmAddDeviceInfo(const BtmDeviceInfo *info) { return serviceDispatchIn(&g_btmSrv, 10, *info); }