From abf3600724e8efe84ab83e7c07dc42cf11b31151 Mon Sep 17 00:00:00 2001 From: yellows8 Date: Mon, 10 Aug 2020 11:34:13 -0400 Subject: [PATCH] Added btm, moved btmu structs into btm, and updated docs. --- nx/include/switch.h | 1 + nx/include/switch/services/btm.h | 331 +++++++++++++++++++++++++ nx/include/switch/services/btmu.h | 108 +++++---- nx/source/services/btm.c | 389 ++++++++++++++++++++++++++++++ nx/source/services/btmu.c | 28 +-- 5 files changed, 791 insertions(+), 66 deletions(-) create mode 100644 nx/include/switch/services/btm.h create mode 100644 nx/source/services/btm.c diff --git a/nx/include/switch.h b/nx/include/switch.h index c3f36f49..bec5ae66 100644 --- a/nx/include/switch.h +++ b/nx/include/switch.h @@ -95,6 +95,7 @@ extern "C" { #include "switch/services/lr.h" #include "switch/services/bt.h" #include "switch/services/btdrv.h" +#include "switch/services/btm.h" #include "switch/services/btmu.h" #include "switch/services/btmsys.h" #include "switch/services/spl.h" diff --git a/nx/include/switch/services/btm.h b/nx/include/switch/services/btm.h new file mode 100644 index 00000000..5a968127 --- /dev/null +++ b/nx/include/switch/services/btm.h @@ -0,0 +1,331 @@ +/** + * @file btm.h + * @brief btm service IPC wrapper. + * @author yellows8 + */ +#pragma once +#include "../types.h" +#include "../kernel/event.h" +#include "../services/btdrv.h" +#include "../sf/service.h" + +/// GattClientConditionList +typedef struct { + u8 unk_x0[0x74]; ///< Unknown +} BtmGattClientConditionList; + +/// GattService +typedef struct { + u8 unk_x0[0x4]; ///< Unknown + BtdrvGattAttributeUuid uuid; ///< \ref BtdrvGattAttributeUuid + u16 unk_x18; ///< Unknown + u8 unk_x1A[0x4]; ///< Unknown + u16 unk_x1E; ///< Unknown + u8 unk_x20; ///< Unknown + u8 pad[3]; ///< Padding +} BtmGattService; + +/// GattCharacteristic +typedef struct { + u8 unk_x0[0x24]; ///< Unknown +} BtmGattCharacteristic; + +/// GattDescriptor +typedef struct { + u8 unk_x0[0x20]; ///< Unknown +} BtmGattDescriptor; + +/// BleDataPath +typedef struct { + u8 unk_x0; ///< Unknown + u8 pad[3]; ///< Padding + BtdrvGattAttributeUuid uuid; ///< \ref BtdrvGattAttributeUuid +} BtmBleDataPath; + +/// Initialize btm. +Result btmInitialize(void); + +/// Exit btm. +void btmExit(void); + +/// Gets the Service object for the actual btm service session. +Service* btmGetServiceSession(void); + +/** + * @brief AcquireBleScanEvent + * @note Only available on [5.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 btmAcquireBleScanEvent(Event* out_event); + +/** + * @brief GetBleScanParameterGeneral + * @note Only available on [5.1.0+]. + * @param[in] unk Must be value 0x1 or 0xFFFF. + * @param[out] out \ref BtdrvBleAdvertisePacketParameter + */ +Result btmGetBleScanParameterGeneral(u16 unk, BtdrvBleAdvertisePacketParameter *out); + +/** + * @brief GetBleScanParameterSmartDevice + * @note Only available on [5.1.0+]. + * @param[in] unk Must be value 0x2. + * @param[out] out \ref BtdrvGattAttributeUuid. The first 4-bytes is always 0. + */ +Result btmGetBleScanParameterSmartDevice(u16 unk, BtdrvGattAttributeUuid *out); + +/** + * @brief StartBleScanForGeneral + * @note Only available on [5.1.0+]. + * @param[in] param \ref BtdrvBleAdvertisePacketParameter + */ +Result btmStartBleScanForGeneral(BtdrvBleAdvertisePacketParameter param); + +/** + * @brief StopBleScanForGeneral + * @note Only available on [5.1.0+]. + */ +Result btmStopBleScanForGeneral(void); + +/** + * @brief GetBleScanResultsForGeneral + * @note Only available on [5.1.0+]. + * @param[out] results Output array of \ref BtdrvBleScanResult. + * @param[in] count Size of the results array in entries. The max is 10. + * @param[out] total_out Total output entries. + */ +Result btmGetBleScanResultsForGeneral(BtdrvBleScanResult *results, u8 count, u8 *total_out); + +/** + * @brief StartBleScanForPaired + * @note Only available on [5.1.0+]. + * @param[in] param \ref BtdrvBleAdvertisePacketParameter + */ +Result btmStartBleScanForPaired(BtdrvBleAdvertisePacketParameter param); + +/** + * @brief StopBleScanForPaired + * @note Only available on [5.1.0+]. + */ +Result btmStopBleScanForPaired(void); + +/** + * @brief StartBleScanForSmartDevice + * @note Only available on [5.1.0+]. + * @param[in] uuid \ref BtdrvGattAttributeUuid + */ +Result btmStartBleScanForSmartDevice(const BtdrvGattAttributeUuid *uuid); + +/** + * @brief StopBleScanForSmartDevice + * @note Only available on [5.1.0+]. + */ +Result btmStopBleScanForSmartDevice(void); + +/** + * @brief GetBleScanResultsForSmartDevice + * @note Only available on [5.1.0+]. + * @param[out] results Output array of \ref BtdrvBleScanResult. + * @param[in] count Size of the results array in entries. The max is 10. + * @param[out] total_out Total output entries. + */ +Result btmGetBleScanResultsForSmartDevice(BtdrvBleScanResult *results, u8 count, u8 *total_out); + +/** + * @brief AcquireBleConnectionEvent + * @note Only available on [5.1.0+]. + * @note The Event must be closed by the user once finished with it. + * @param[out] out_event Output Event with autoclear=true. + */ +Result btmAcquireBleConnectionEvent(Event* out_event); + +/** + * @brief BleConnect + * @note Only available on [5.0.0+]. + * @note The \ref BtdrvAddress must not be already connected. A maximum of 4 devices can be connected. + * @param[in] addr \ref BtdrvAddress + */ +Result btmBleConnect(BtdrvAddress addr); + +/** + * @brief BleOverrideConnection + * @note Only available on [5.1.0+]. + * @param[in] id Same as \ref btmBleDisconnect. + */ +Result btmBleOverrideConnection(u32 id); + +/** + * @brief BleDisconnect + * @note Only available on [5.0.0+]. + * @param[in] id This must match a BtdrvBleConnectionInfo::id from \ref btmBleGetConnectionState. [5.1.0+] 0xFFFFFFFF is invalid. + */ +Result btmBleDisconnect(u32 id); + +/** + * @brief BleGetConnectionState + * @note Only available on [5.0.0+]. + * @param[out] info Output array of \ref BtdrvBleConnectionInfo. + * @param[in] count Size of the info array in entries. Other cmds which use this internally use count=4. + * @param[out] total_out Total output entries. + */ +Result btmBleGetConnectionState(BtdrvBleConnectionInfo *info, u8 count, u8 *total_out); + +/** + * @brief BleGetGattClientConditionList + * @note Only available on [5.0.0+]. + * @param[out] list \ref BtmGattClientConditionList + */ +Result btmBleGetGattClientConditionList(BtmGattClientConditionList *list); + +/** + * @brief AcquireBlePairingEvent + * @note Only available on [5.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 btmAcquireBlePairingEvent(Event* out_event); + +/** + * @brief BlePairDevice + * @note Only available on [5.1.0+]. + * @param[in] param \ref BtdrvBleAdvertisePacketParameter + * @param[in] id Same as \ref btmBleDisconnect. + */ +Result btmBlePairDevice(BtdrvBleAdvertisePacketParameter param, u32 id); + +/** + * @brief BleUnpairDeviceOnBoth + * @note Only available on [5.1.0+]. + * @param[in] param \ref BtdrvBleAdvertisePacketParameter + * @param[in] id Same as \ref btmBleDisconnect. + */ +Result btmBleUnpairDeviceOnBoth(BtdrvBleAdvertisePacketParameter param, u32 id); + +/** + * @brief BleUnPairDevice + * @note Only available on [5.1.0+]. + * @param[in] addr \ref BtdrvAddress + * @param[in] param \ref BtdrvBleAdvertisePacketParameter + */ +Result btmBleUnPairDevice(BtdrvAddress addr, BtdrvBleAdvertisePacketParameter param); + +/** + * @brief BleGetPairedAddresses + * @note Only available on [5.1.0+]. + * @param[in] param \ref BtdrvBleAdvertisePacketParameter + * @param[out] addrs Output array of \ref BtdrvAddress. + * @param[in] count Size of the addrs array in entries. + * @param[out] total_out Total output entries. The max is 10. + */ +Result btmBleGetPairedAddresses(BtdrvBleAdvertisePacketParameter param, BtdrvAddress *addrs, u8 count, u8 *total_out); + +/** + * @brief AcquireBleServiceDiscoveryEvent + * @note Only available on [5.1.0+]. + * @note The Event must be closed by the user once finished with it. + * @param[out] out_event Output Event with autoclear=true. + */ +Result btmAcquireBleServiceDiscoveryEvent(Event* out_event); + +/** + * @brief GetGattServices + * @note Only available on [5.0.0+]. + * @param[in] id Same as \ref btmBleDisconnect. + * @param[out] services Output array of \ref BtmGattService. + * @param[in] count Size of the services array in entries. The max is 100. + * @param[out] total_out Total output entries. + */ +Result btmGetGattServices(u32 id, BtmGattService *services, u8 count, u8 *total_out); + +/** + * @brief Same as \ref btmGetGattServices except this only returns the \ref BtmGattService which matches the input \ref BtdrvGattAttributeUuid. + * @note Only available on [5.0.0+]. + * @param[in] id Same as \ref btmBleDisconnect. + * @param[in] uuid \ref BtdrvGattAttributeUuid + * @param[out] service \ref BtmGattService + * @param[out] flag Whether a \ref BtmGattService was returned. + */ +Result btmGetGattService(u32 id, const BtdrvGattAttributeUuid *uuid, BtmGattService *service, bool *flag); + +/** + * @brief Same as \ref btmGetGattServices except this only returns \ref BtmGattService entries where various checks pass with u16 fields. + * @note Only available on [5.0.0+]. + * @param[in] id Same as \ref btmBleDisconnect. + * @param[in] unk1 Unknown + * @param[out] services \ref BtmGattService + * @param[in] count Size of the services array in entries. The max is 100. + * @param[out] out Output value. + */ +Result btmGetGattIncludedServices(u32 id, u16 unk1, BtmGattService *services, u8 count, u8 *out); + +/** + * @brief This is similar to \ref btmGetGattIncludedServices except this only returns 1 \ref BtmGattService. + * @note Only available on [5.0.0+]. + * @param[in] id Same as \ref btmBleDisconnect. + * @param[in] unk1 Unknown + * @param[out] service \ref BtmGattService + * @param[out] flag Whether a \ref BtmGattService was returned. + */ +Result btmGetBelongingService(u32 id, u16 unk1, BtmGattService *service, bool *flag); + +/** + * @brief GetGattCharacteristics + * @note Only available on [5.0.0+]. + * @param[in] id Same as \ref btmBleDisconnect. + * @param[in] unk1 This controls which \ref BtmGattCharacteristic entries to return. + * @param[out] characteristics \ref BtmGattCharacteristic + * @param[in] count Size of the characteristics array in entries. The max is 100. + * @param[out] total_out Total output entries. + */ +Result btmGetGattCharacteristics(u32 id, u16 unk1, BtmGattCharacteristic *characteristics, u8 count, u8 *total_out); + +/** + * @brief GetGattDescriptors + * @note Only available on [5.0.0+]. + * @param[in] id Same as \ref btmBleDisconnect. + * @param[in] unk1 This controls which \ref BtmGattDescriptor entries to return. + * @param[out] descriptors \ref BtmGattDescriptor + * @param[in] count Size of the descriptors array in entries. The max is 100. + * @param[out] total_out Total output entries. + */ +Result btmGetGattDescriptors(u32 id, u16 unk1, BtmGattDescriptor *descriptors, u8 count, u8 *total_out); + +/** + * @brief AcquireBleMtuConfigEvent + * @note Only available on [5.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 btmAcquireBleMtuConfigEvent(Event* out_event); + +/** + * @brief ConfigureBleMtu + * @note Only available on [5.0.0+]. + * @param[in] id Same as \ref btmBleDisconnect. + * @param[in] mtu MTU + */ +Result btmConfigureBleMtu(u32 id, u16 mtu); + +/** + * @brief GetBleMtu + * @note Only available on [5.0.0+]. + * @param[in] id Same as \ref btmBleDisconnect. + * @param[out] out Output MTU. + */ +Result btmGetBleMtu(u32 id, u16 *out); + +/** + * @brief RegisterBleGattDataPath + * @note Only available on [5.0.0+]. + * @param[in] path \ref BtmBleDataPath + */ +Result btmRegisterBleGattDataPath(const BtmBleDataPath *path); + +/** + * @brief UnregisterBleGattDataPath + * @note Only available on [5.0.0+]. + * @param[in] path \ref BtmBleDataPath + */ +Result btmUnregisterBleGattDataPath(const BtmBleDataPath *path); + diff --git a/nx/include/switch/services/btmu.h b/nx/include/switch/services/btmu.h index 1641682c..5b5321c3 100644 --- a/nx/include/switch/services/btmu.h +++ b/nx/include/switch/services/btmu.h @@ -8,36 +8,9 @@ #include "../types.h" #include "../kernel/event.h" #include "../services/btdrv.h" +#include "../services/btm.h" #include "../sf/service.h" -/// GattService -typedef struct { - u8 unk_x0[0x4]; ///< Unknown - BtdrvGattAttributeUuid uuid; ///< \ref BtdrvGattAttributeUuid - u16 unk_x18; ///< Unknown - u8 unk_x1A[0x4]; ///< Unknown - u16 unk_x1E; ///< Unknown - u8 unk_x20; ///< Unknown - u8 pad[3]; ///< Padding -} BtmuGattService; - -/// GattCharacteristic -typedef struct { - u8 unk_x0[0x24]; ///< Unknown -} BtmuGattCharacteristic; - -/// GattDescriptor -typedef struct { - u8 unk_x0[0x20]; ///< Unknown -} BtmuGattDescriptor; - -/// BleDataPath -typedef struct { - u8 unk_x0; ///< Unknown - u8 pad[3]; ///< Padding - BtdrvGattAttributeUuid uuid; ///< \ref BtdrvGattAttributeUuid -} BtmuBleDataPath; - /// Initialize btm:u. Result btmuInitialize(void); @@ -52,6 +25,7 @@ Service* btmuGetServiceSession_IBtmUserCore(void); /** * @brief AcquireBleScanEvent + * @note This is similar to \ref btmAcquireBleScanEvent. * @note The Event must be closed by the user once finished with it. * @param[out] out_event Output Event with autoclear=true. */ @@ -59,6 +33,7 @@ Result btmuAcquireBleScanEvent(Event* out_event); /** * @brief GetBleScanFilterParameter + * @note This is the same as \ref btmGetBleScanParameterGeneral. * @param[in] unk Must be value 0x1 or 0xFFFF. * @param[out] out \ref BtdrvBleAdvertisePacketParameter */ @@ -66,6 +41,7 @@ Result btmuGetBleScanFilterParameter(u16 unk, BtdrvBleAdvertisePacketParameter * /** * @brief GetBleScanFilterParameter2 + * @note This is the same as \ref btmGetBleScanParameterSmartDevice. * @param[in] unk Must be value 0x2. * @param[out] out \ref BtdrvGattAttributeUuid. The first 4-bytes is always 0. */ @@ -73,17 +49,20 @@ Result btmuGetBleScanFilterParameter2(u16 unk, BtdrvGattAttributeUuid *out); /** * @brief StartBleScanForGeneral + * @note This is similar to \ref btmStartBleScanForGeneral. * @param[in] param \ref BtdrvBleAdvertisePacketParameter */ Result btmuStartBleScanForGeneral(BtdrvBleAdvertisePacketParameter param); /** * @brief StopBleScanForGeneral + * @note This is similar to \ref btmStopBleScanForGeneral. */ Result btmuStopBleScanForGeneral(void); /** * @brief GetBleScanResultsForGeneral + * @note This is similar to \ref btmGetBleScanResultsForGeneral. * @param[out] results Output array of \ref BtdrvBleScanResult. * @param[in] count Size of the results array in entries. The max is 10. * @param[out] total_out Total output entries. @@ -92,28 +71,33 @@ Result btmuGetBleScanResultsForGeneral(BtdrvBleScanResult *results, u8 count, u8 /** * @brief StartBleScanForPaired + * @note This is similar to \ref btmStartBleScanForPaired. * @param[in] param \ref BtdrvBleAdvertisePacketParameter */ Result btmuStartBleScanForPaired(BtdrvBleAdvertisePacketParameter param); /** * @brief StopBleScanForPaired + * @note This is similar to \ref btmStopBleScanForPaired. */ Result btmuStopBleScanForPaired(void); /** * @brief StartBleScanForSmartDevice + * @note This is similar to \ref btmStartBleScanForSmartDevice. * @param[in] uuid \ref BtdrvGattAttributeUuid */ Result btmuStartBleScanForSmartDevice(const BtdrvGattAttributeUuid *uuid); /** * @brief StopBleScanForSmartDevice + * @note This is similar to \ref btmStopBleScanForSmartDevice. */ Result btmuStopBleScanForSmartDevice(void); /** * @brief GetBleScanResultsForSmartDevice + * @note This is similar to \ref btmGetBleScanResultsForSmartDevice. * @param[out] results Output array of \ref BtdrvBleScanResult. * @param[in] count Size of the results array in entries. The max is 10. * @param[out] total_out Total output entries. @@ -122,6 +106,7 @@ Result btmuGetBleScanResultsForSmartDevice(BtdrvBleScanResult *results, u8 count /** * @brief AcquireBleConnectionEvent + * @note This is similar to \ref btmAcquireBleConnectionEvent. * @note The Event must be closed by the user once finished with it. * @param[out] out_event Output Event with autoclear=true. */ @@ -129,19 +114,21 @@ Result btmuAcquireBleConnectionEvent(Event* out_event); /** * @brief BleConnect - * @note The \ref BtdrvAddress must not be already connected. A maximum of 4 devices can be connected. + * @note This is similar to \ref btmBleConnect. * @param[in] addr \ref BtdrvAddress */ Result btmuBleConnect(BtdrvAddress addr); /** * @brief BleDisconnect + * @note This is similar to \ref btmBleDisconnect. * @param[in] id This must match a BtdrvBleConnectionInfo::id from \ref btmuBleGetConnectionState. [5.1.0+] 0xFFFFFFFF is invalid. */ Result btmuBleDisconnect(u32 id); /** * @brief BleGetConnectionState + * @note This is similar to \ref btmBleGetConnectionState. * @param[out] info Output array of \ref BtdrvBleConnectionInfo. * @param[in] count Size of the info array in entries. Other cmds which use this internally use count=4. * @param[out] total_out Total output entries. @@ -150,6 +137,7 @@ Result btmuBleGetConnectionState(BtdrvBleConnectionInfo *info, u8 count, u8 *tot /** * @brief AcquireBlePairingEvent + * @note This is similar to \ref btmAcquireBlePairingEvent. * @note The Event must be closed by the user once finished with it. * @param[out] out_event Output Event with autoclear=true. */ @@ -157,6 +145,7 @@ Result btmuAcquireBlePairingEvent(Event* out_event); /** * @brief BlePairDevice + * @note This is similar to \ref btmBlePairDevice. * @param[in] param \ref BtdrvBleAdvertisePacketParameter * @param[in] id Same as \ref btmuBleDisconnect. */ @@ -164,6 +153,7 @@ Result btmuBlePairDevice(BtdrvBleAdvertisePacketParameter param, u32 id); /** * @brief BleUnPairDevice + * @note This is similar to \ref btmBleUnpairDeviceOnBoth. * @param[in] param \ref BtdrvBleAdvertisePacketParameter * @param[in] id Same as \ref btmuBleDisconnect. */ @@ -171,6 +161,7 @@ Result btmuBleUnPairDevice(BtdrvBleAdvertisePacketParameter param, u32 id); /** * @brief BleUnPairDevice2 + * @note This is similar to \ref btmBleUnPairDevice. * @param[in] addr \ref BtdrvAddress * @param[in] param \ref BtdrvBleAdvertisePacketParameter */ @@ -178,6 +169,7 @@ Result btmuBleUnPairDevice2(BtdrvAddress addr, BtdrvBleAdvertisePacketParameter /** * @brief BleGetPairedDevices + * @note This is similar to \ref btmBleGetPairedAddresses. * @param[in] param \ref BtdrvBleAdvertisePacketParameter * @param[out] addrs Output array of \ref BtdrvAddress. * @param[in] count Size of the addrs array in entries. @@ -187,6 +179,7 @@ Result btmuBleGetPairedDevices(BtdrvBleAdvertisePacketParameter param, BtdrvAddr /** * @brief AcquireBleServiceDiscoveryEvent + * @note This is similar to \ref btmAcquireBleServiceDiscoveryEvent. * @note The Event must be closed by the user once finished with it. * @param[out] out_event Output Event with autoclear=true. */ @@ -194,63 +187,70 @@ Result btmuAcquireBleServiceDiscoveryEvent(Event* out_event); /** * @brief GetGattServices + * @note This is similar to \ref btmGetGattServices. * @param[in] id Same as \ref btmuBleDisconnect. - * @param[out] services Output array of \ref BtmuGattService. + * @param[out] services Output array of \ref BtmGattService. * @param[in] count Size of the services array in entries. The max is 100. * @param[out] total_out Total output entries. */ -Result btmuGetGattServices(u32 id, BtmuGattService *services, u8 count, u8 *total_out); +Result btmuGetGattServices(u32 id, BtmGattService *services, u8 count, u8 *total_out); /** - * @brief Same as \ref btmuGetGattServices except this only returns the \ref BtmuGattService which matches the input \ref BtdrvGattAttributeUuid. + * @brief Same as \ref btmuGetGattServices except this only returns the \ref BtmGattService which matches the input \ref BtdrvGattAttributeUuid. + * @note This is similar to \ref btmGetGattService. * @param[in] id Same as \ref btmuBleDisconnect. * @param[in] uuid \ref BtdrvGattAttributeUuid - * @param[out] service \ref BtmuGattService - * @param[out] flag Whether a \ref BtmuGattService was returned. + * @param[out] service \ref BtmGattService + * @param[out] flag Whether a \ref BtmGattService was returned. */ -Result btmuGetGattService(u32 id, const BtdrvGattAttributeUuid *uuid, BtmuGattService *service, bool *flag); +Result btmuGetGattService(u32 id, const BtdrvGattAttributeUuid *uuid, BtmGattService *service, bool *flag); /** - * @brief Same as \ref btmuGetGattServices except this only returns \ref BtmuGattService entries where various checks pass with u16 fields. + * @brief Same as \ref btmuGetGattServices except this only returns \ref BtmGattService entries where various checks pass with u16 fields. + * @note This is similar to \ref btmGetGattIncludedServices. * @param[in] id Same as \ref btmuBleDisconnect. * @param[in] unk1 Unknown - * @param[out] services \ref BtmuGattService + * @param[out] services \ref BtmGattService * @param[in] count Size of the services array in entries. The max is 100. * @param[out] out Output value. */ -Result btmuGetGattIncludedServices(u32 id, u16 unk1, BtmuGattService *services, u8 count, u8 *out); +Result btmuGetGattIncludedServices(u32 id, u16 unk1, BtmGattService *services, u8 count, u8 *out); /** - * @brief This is similar to \ref btmuGetGattIncludedServices except this only returns 1 \ref BtmuGattService. + * @brief This is similar to \ref btmuGetGattIncludedServices except this only returns 1 \ref BtmGattService. + * @note This is similar to \ref btmGetBelongingService. * @param[in] id Same as \ref btmuBleDisconnect. * @param[in] unk1 Unknown - * @param[out] service \ref BtmuGattService - * @param[out] flag Whether a \ref BtmuGattService was returned. + * @param[out] service \ref BtmGattService + * @param[out] flag Whether a \ref BtmGattService was returned. */ -Result btmuGetBelongingGattService(u32 id, u16 unk1, BtmuGattService *service, bool *flag); +Result btmuGetBelongingGattService(u32 id, u16 unk1, BtmGattService *service, bool *flag); /** * @brief GetGattCharacteristics + * @note This is similar to \ref btmGetGattCharacteristics. * @param[in] id Same as \ref btmuBleDisconnect. - * @param[in] unk1 This controls which \ref BtmuGattCharacteristic entries to return. - * @param[out] characteristics \ref BtmuGattCharacteristic + * @param[in] unk1 This controls which \ref BtmGattCharacteristic entries to return. + * @param[out] characteristics \ref BtmGattCharacteristic * @param[in] count Size of the characteristics array in entries. The max is 100. * @param[out] total_out Total output entries. */ -Result btmuGetGattCharacteristics(u32 id, u16 unk1, BtmuGattCharacteristic *characteristics, u8 count, u8 *total_out); +Result btmuGetGattCharacteristics(u32 id, u16 unk1, BtmGattCharacteristic *characteristics, u8 count, u8 *total_out); /** * @brief GetGattDescriptors + * @note This is similar to \ref btmGetGattDescriptors. * @param[in] id Same as \ref btmuBleDisconnect. - * @param[in] unk1 This controls which \ref BtmuGattDescriptor entries to return. - * @param[out] descriptors \ref BtmuGattDescriptor + * @param[in] unk1 This controls which \ref BtmGattDescriptor entries to return. + * @param[out] descriptors \ref BtmGattDescriptor * @param[in] count Size of the descriptors array in entries. The max is 100. * @param[out] total_out Total output entries. */ -Result btmuGetGattDescriptors(u32 id, u16 unk1, BtmuGattDescriptor *descriptors, u8 count, u8 *total_out); +Result btmuGetGattDescriptors(u32 id, u16 unk1, BtmGattDescriptor *descriptors, u8 count, u8 *total_out); /** * @brief AcquireBleMtuConfigEvent + * @note This is similar to \ref btmAcquireBleMtuConfigEvent. * @note The Event must be closed by the user once finished with it. * @param[out] out_event Output Event with autoclear=true. */ @@ -258,6 +258,7 @@ Result btmuAcquireBleMtuConfigEvent(Event* out_event); /** * @brief ConfigureBleMtu + * @note This is similar to \ref btmConfigureBleMtu. * @param[in] id Same as \ref btmuBleDisconnect. * @param[in] mtu MTU */ @@ -265,6 +266,7 @@ Result btmuConfigureBleMtu(u32 id, u16 mtu); /** * @brief GetBleMtu + * @note This is similar to \ref btmGetBleMtu. * @param[in] id Same as \ref btmuBleDisconnect. * @param[out] out Output MTU. */ @@ -272,13 +274,15 @@ Result btmuGetBleMtu(u32 id, u16 *out); /** * @brief RegisterBleGattDataPath - * @param[in] path \ref BtmuBleDataPath + * @note This is similar to \ref btmRegisterBleGattDataPath. + * @param[in] path \ref BtmBleDataPath */ -Result btmuRegisterBleGattDataPath(const BtmuBleDataPath *path); +Result btmuRegisterBleGattDataPath(const BtmBleDataPath *path); /** * @brief UnregisterBleGattDataPath - * @param[in] path \ref BtmuBleDataPath + * @note This is similar to \ref btmUnregisterBleGattDataPath. + * @param[in] path \ref BtmBleDataPath */ -Result btmuUnregisterBleGattDataPath(const BtmuBleDataPath *path); +Result btmuUnregisterBleGattDataPath(const BtmBleDataPath *path); diff --git a/nx/source/services/btm.c b/nx/source/services/btm.c new file mode 100644 index 00000000..c92928e5 --- /dev/null +++ b/nx/source/services/btm.c @@ -0,0 +1,389 @@ +#define NX_SERVICE_ASSUME_NON_DOMAIN +#include +#include "service_guard.h" +#include "runtime/hosversion.h" +#include "services/btm.h" + +static Service g_btmSrv; + +NX_GENERATE_SERVICE_GUARD(btm); + +Result _btmInitialize(void) { + return smGetService(&g_btmSrv, "btm"); +} + +void _btmCleanup(void) { + serviceClose(&g_btmSrv); +} + +Service* btmGetServiceSession(void) { + return &g_btmSrv; +} + +static Result _btmCmdNoIO(u32 cmd_id) { + return serviceDispatch(&g_btmSrv, cmd_id); +} + +static Result _btmCmdGetEventOutFlag(Event* out_event, bool autoclear, u32 cmd_id) { + Handle tmp_handle = INVALID_HANDLE; + Result rc = 0; + + if (hosversionBefore(3,0,0)) { + u8 out=0; + rc = serviceDispatchOut(&g_btmSrv, cmd_id, out, + .out_handle_attrs = { SfOutHandleAttr_HipcCopy }, + .out_handles = &tmp_handle, + ); + if (R_SUCCEEDED(rc) && !out) rc = MAKERESULT(Module_Libnx, LibnxError_ShouldNotHappen); + } + else { + rc = serviceDispatch(&g_btmSrv, 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 _btmCmdInU32NoOut(u32 inval, u32 cmd_id) { + return serviceDispatchIn(&g_btmSrv, cmd_id, inval); +} + +static Result _btmCmdInBleAdvertisePacketParameterNoOut(BtdrvBleAdvertisePacketParameter param, u32 cmd_id) { + return serviceDispatchIn(&g_btmSrv, cmd_id, param); +} + +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 }, + .buffers = { { results, sizeof(BtdrvBleScanResult)*count } }, + ); +} + +static Result _btmBlePairDevice(BtdrvBleAdvertisePacketParameter param, u32 id, u32 cmd_id) { + const struct { + BtdrvBleAdvertisePacketParameter param; + u32 id; + } in = { param, id }; + + return serviceDispatchIn(&g_btmSrv, cmd_id, in); +} + +static Result _btmGetGattServiceData(u32 id, u16 unk1, void* buffer, size_t entrysize, u8 count, u8 *out, u32 cmd_id) { + const struct { + u16 unk1; + u16 pad; + u32 unk0; + } in = { unk1, 0, id }; + + return serviceDispatchInOut(&g_btmSrv, cmd_id, in, *out, + .buffer_attrs = { SfBufferAttr_HipcMapAlias | SfBufferAttr_Out }, + .buffers = { { buffer, entrysize*count } }, + ); +} + +static Result _btmRegisterBleGattDataPath(const BtmBleDataPath *path, u32 cmd_id) { + return serviceDispatchIn(&g_btmSrv, cmd_id, *path); +} + +Result btmAcquireBleScanEvent(Event* out_event) { + if (hosversionBefore(5,0,0)) + return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); + + return _btmCmdGetEventOutFlag(out_event, true, 23); +} + +Result btmGetBleScanParameterGeneral(u16 unk, BtdrvBleAdvertisePacketParameter *out) { + if (hosversionBefore(5,1,0)) + return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); + + return serviceDispatchInOut(&g_btmSrv, 24, unk, *out); +} + +Result btmGetBleScanParameterSmartDevice(u16 unk, BtdrvGattAttributeUuid *out) { + if (hosversionBefore(5,1,0)) + return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); + + return serviceDispatchInOut(&g_btmSrv, 25, unk, *out); +} + +Result btmStartBleScanForGeneral(BtdrvBleAdvertisePacketParameter param) { + if (hosversionBefore(5,1,0)) + return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); + + return _btmCmdInBleAdvertisePacketParameterNoOut(param, 26); +} + +Result btmStopBleScanForGeneral(void) { + if (hosversionBefore(5,1,0)) + return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); + + return _btmCmdNoIO(27); +} + +Result btmGetBleScanResultsForGeneral(BtdrvBleScanResult *results, u8 count, u8 *total_out) { + if (hosversionBefore(5,1,0)) + return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); + + return _btmGetBleScanResults(results, count, total_out, 28); +} + +Result btmStartBleScanForPaired(BtdrvBleAdvertisePacketParameter param) { + if (hosversionBefore(5,1,0)) + return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); + + return _btmCmdInBleAdvertisePacketParameterNoOut(param, 29); +} + +Result btmStopBleScanForPaired(void) { + if (hosversionBefore(5,1,0)) + return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); + + return _btmCmdNoIO(30); +} + +Result btmStartBleScanForSmartDevice(const BtdrvGattAttributeUuid *uuid) { + if (hosversionBefore(5,1,0)) + return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); + + return serviceDispatchIn(&g_btmSrv, 31, *uuid); +} + +Result btmStopBleScanForSmartDevice(void) { + if (hosversionBefore(5,1,0)) + return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); + + return _btmCmdNoIO(32); +} + +Result btmGetBleScanResultsForSmartDevice(BtdrvBleScanResult *results, u8 count, u8 *total_out) { + if (hosversionBefore(5,1,0)) + return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); + + return _btmGetBleScanResults(results, count, total_out, 33); +} + +Result btmAcquireBleConnectionEvent(Event* out_event) { + if (hosversionBefore(5,1,0)) + return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); + + return _btmCmdGetEventOutFlag(out_event, true, 34); +} + +Result btmBleConnect(BtdrvAddress addr) { + if (hosversionBefore(5,0,0)) + return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); + u32 cmd_id = hosversionBefore(5,1,0) ? 24 : 35; + + return serviceDispatchIn(&g_btmSrv, cmd_id, addr); +} + +Result btmBleOverrideConnection(u32 id) { + if (hosversionBefore(5,1,0)) + return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); + + return _btmCmdInU32NoOut(id, 36); +} + +Result btmBleDisconnect(u32 id) { + if (hosversionBefore(5,0,0)) + return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); + u32 cmd_id = hosversionBefore(5,1,0) ? 25 : 37; + + return _btmCmdInU32NoOut(id, cmd_id); +} + +Result btmBleGetConnectionState(BtdrvBleConnectionInfo *info, u8 count, u8 *total_out) { + if (hosversionBefore(5,0,0)) + return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); + u32 cmd_id = hosversionBefore(5,1,0) ? 26 : 38; + + return serviceDispatchOut(&g_btmSrv, cmd_id, *total_out, + .buffer_attrs = { SfBufferAttr_HipcPointer | SfBufferAttr_Out }, + .buffers = { { info, sizeof(BtdrvBleConnectionInfo)*count } }, + ); +} + +Result btmBleGetGattClientConditionList(BtmGattClientConditionList *list) { + if (hosversionBefore(5,0,0)) + return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); + u32 cmd_id = hosversionBefore(5,1,0) ? 27 : 39; + + return serviceDispatch(&g_btmSrv, cmd_id, + .buffer_attrs = { SfBufferAttr_HipcPointer | SfBufferAttr_Out | SfBufferAttr_FixedSize }, + .buffers = { { list, sizeof(*list) } }, + ); +} + +Result btmAcquireBlePairingEvent(Event* out_event) { + if (hosversionBefore(5,0,0)) + return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); + u32 cmd_id = hosversionBefore(5,1,0) ? 28 : 40; + + return _btmCmdGetEventOutFlag(out_event, true, cmd_id); +} + +Result btmBlePairDevice(BtdrvBleAdvertisePacketParameter param, u32 id) { + if (hosversionBefore(5,1,0)) + return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); + + return _btmBlePairDevice(param, id, 41); +} + +Result btmBleUnpairDeviceOnBoth(BtdrvBleAdvertisePacketParameter param, u32 id) { + if (hosversionBefore(5,1,0)) + return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); + + return _btmBlePairDevice(param, id, 42); +} + +Result btmBleUnPairDevice(BtdrvAddress addr, BtdrvBleAdvertisePacketParameter param) { + if (hosversionBefore(5,1,0)) + return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); + + const struct { + BtdrvAddress addr; + BtdrvBleAdvertisePacketParameter param; + } in = { addr, param }; + + return serviceDispatchIn(&g_btmSrv, 43, in); +} + +Result btmBleGetPairedAddresses(BtdrvBleAdvertisePacketParameter param, BtdrvAddress *addrs, u8 count, u8 *total_out) { + if (hosversionBefore(5,1,0)) + return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); + + return serviceDispatchInOut(&g_btmSrv, 44, param, *total_out, + .buffer_attrs = { SfBufferAttr_HipcPointer | SfBufferAttr_Out }, + .buffers = { { addrs, sizeof(BtdrvAddress)*count } }, + ); +} + +Result btmAcquireBleServiceDiscoveryEvent(Event* out_event) { + if (hosversionBefore(5,1,0)) + return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); + + return _btmCmdGetEventOutFlag(out_event, true, 45); +} + +Result btmGetGattServices(u32 id, BtmGattService *services, u8 count, u8 *total_out) { + if (hosversionBefore(5,0,0)) + return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); + u32 cmd_id = hosversionBefore(5,1,0) ? 29 : 46; + + return serviceDispatchInOut(&g_btmSrv, cmd_id, id, *total_out, + .buffer_attrs = { SfBufferAttr_HipcMapAlias | SfBufferAttr_Out }, + .buffers = { { services, sizeof(BtmGattService)*count } }, + ); +} + +Result btmGetGattService(u32 id, const BtdrvGattAttributeUuid *uuid, BtmGattService *service, bool *flag) { + if (hosversionBefore(5,0,0)) + return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); + u32 cmd_id = hosversionBefore(5,1,0) ? 30 : 47; + + const struct { + u32 id; + BtdrvGattAttributeUuid uuid; + } in = { id, *uuid }; + + u8 tmp=0; + Result rc = serviceDispatchInOut(&g_btmSrv, cmd_id, in, tmp, + .buffer_attrs = { SfBufferAttr_HipcPointer | SfBufferAttr_Out | SfBufferAttr_FixedSize }, + .buffers = { { service, sizeof(*service) } }, + ); + if (R_SUCCEEDED(rc) && flag) *flag = tmp & 1; + return rc; +} + +Result btmGetGattIncludedServices(u32 id, u16 unk1, BtmGattService *services, u8 count, u8 *out) { + if (hosversionBefore(5,0,0)) + return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); + u32 cmd_id = hosversionBefore(5,1,0) ? 31 : 48; + + return _btmGetGattServiceData(id, unk1, services, sizeof(BtmGattService), count, out, cmd_id); +} + +Result btmGetBelongingService(u32 id, u16 unk1, BtmGattService *service, bool *flag) { + if (hosversionBefore(5,0,0)) + return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); + u32 cmd_id = hosversionBefore(5,1,0) ? 32 : 49; + + const struct { + u16 unk1; + u16 pad; + u32 id; + } in = { unk1, 0, id }; + + u8 tmp=0; + Result rc = serviceDispatchInOut(&g_btmSrv, cmd_id, in, tmp, + .buffer_attrs = { SfBufferAttr_HipcPointer | SfBufferAttr_Out | SfBufferAttr_FixedSize }, + .buffers = { { service, sizeof(*service) } }, + ); + if (R_SUCCEEDED(rc) && flag) *flag = tmp & 1; + return rc; +} + +Result btmGetGattCharacteristics(u32 id, u16 unk1, BtmGattCharacteristic *characteristics, u8 count, u8 *total_out) { + if (hosversionBefore(5,0,0)) + return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); + u32 cmd_id = hosversionBefore(5,1,0) ? 33 : 50; + + return _btmGetGattServiceData(id, unk1, characteristics, sizeof(BtmGattCharacteristic), count, total_out, cmd_id); +} + +Result btmGetGattDescriptors(u32 id, u16 unk1, BtmGattDescriptor *descriptors, u8 count, u8 *total_out) { + if (hosversionBefore(5,0,0)) + return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); + u32 cmd_id = hosversionBefore(5,1,0) ? 34 : 51; + + return _btmGetGattServiceData(id, unk1, descriptors, sizeof(BtmGattDescriptor), count, total_out, cmd_id); +} + +Result btmAcquireBleMtuConfigEvent(Event* out_event) { + if (hosversionBefore(5,0,0)) + return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); + u32 cmd_id = hosversionBefore(5,1,0) ? 35 : 52; + + return _btmCmdGetEventOutFlag(out_event, true, cmd_id); +} + +Result btmConfigureBleMtu(u32 id, u16 mtu) { + if (hosversionBefore(5,0,0)) + return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); + u32 cmd_id = hosversionBefore(5,1,0) ? 36 : 53; + + const struct { + u16 mtu; + u16 pad; + u32 id; + } in = { mtu, 0, id }; + + return serviceDispatchIn(&g_btmSrv, cmd_id, in); +} + +Result btmGetBleMtu(u32 id, u16 *out) { + if (hosversionBefore(5,0,0)) + return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); + u32 cmd_id = hosversionBefore(5,1,0) ? 37 : 54; + + return serviceDispatchInOut(&g_btmSrv, cmd_id, id, *out); +} + +Result btmRegisterBleGattDataPath(const BtmBleDataPath *path) { + if (hosversionBefore(5,0,0)) + return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); + u32 cmd_id = hosversionBefore(5,1,0) ? 38 : 55; + + return _btmRegisterBleGattDataPath(path, cmd_id); +} + +Result btmUnregisterBleGattDataPath(const BtmBleDataPath *path) { + if (hosversionBefore(5,0,0)) + return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); + u32 cmd_id = hosversionBefore(5,1,0) ? 39 : 56; + + return _btmRegisterBleGattDataPath(path, cmd_id); +} + diff --git a/nx/source/services/btmu.c b/nx/source/services/btmu.c index 70b7d16d..b800c55e 100644 --- a/nx/source/services/btmu.c +++ b/nx/source/services/btmu.c @@ -109,9 +109,9 @@ static Result _btmuGetGattServiceData(u32 id, u16 unk1, void* buffer, size_t ent ); } -static Result _btmuRegisterBleGattDataPath(const BtmuBleDataPath *path, u32 cmd_id) { +static Result _btmuRegisterBleGattDataPath(const BtmBleDataPath *path, u32 cmd_id) { const struct { - BtmuBleDataPath path; + BtmBleDataPath path; u64 AppletResourceUserId; } in = { *path, appletGetAppletResourceUserId() }; @@ -233,7 +233,7 @@ Result btmuAcquireBleServiceDiscoveryEvent(Event* out_event) { return _btmuCmdGetEventOutFlag(out_event, true, 26); } -Result btmuGetGattServices(u32 id, BtmuGattService *services, u8 count, u8 *total_out) { +Result btmuGetGattServices(u32 id, BtmGattService *services, u8 count, u8 *total_out) { const struct { u32 id; u32 pad; @@ -242,12 +242,12 @@ Result btmuGetGattServices(u32 id, BtmuGattService *services, u8 count, u8 *tota return serviceDispatchInOut(&g_btmuIBtmUserCore, 27, in, *total_out, .buffer_attrs = { SfBufferAttr_HipcMapAlias | SfBufferAttr_Out }, - .buffers = { { services, sizeof(BtmuGattService)*count } }, + .buffers = { { services, sizeof(BtmGattService)*count } }, .in_send_pid = true, ); } -Result btmuGetGattService(u32 id, const BtdrvGattAttributeUuid *uuid, BtmuGattService *service, bool *flag) { +Result btmuGetGattService(u32 id, const BtdrvGattAttributeUuid *uuid, BtmGattService *service, bool *flag) { const struct { u32 id; BtdrvGattAttributeUuid uuid; @@ -264,11 +264,11 @@ Result btmuGetGattService(u32 id, const BtdrvGattAttributeUuid *uuid, BtmuGattSe return rc; } -Result btmuGetGattIncludedServices(u32 id, u16 unk1, BtmuGattService *services, u8 count, u8 *out) { - return _btmuGetGattServiceData(id, unk1, services, sizeof(BtmuGattService), count, out, 29); +Result btmuGetGattIncludedServices(u32 id, u16 unk1, BtmGattService *services, u8 count, u8 *out) { + return _btmuGetGattServiceData(id, unk1, services, sizeof(BtmGattService), count, out, 29); } -Result btmuGetBelongingGattService(u32 id, u16 unk1, BtmuGattService *service, bool *flag) { +Result btmuGetBelongingGattService(u32 id, u16 unk1, BtmGattService *service, bool *flag) { const struct { u16 unk1; u16 pad; @@ -286,12 +286,12 @@ Result btmuGetBelongingGattService(u32 id, u16 unk1, BtmuGattService *service, b return rc; } -Result btmuGetGattCharacteristics(u32 id, u16 unk1, BtmuGattCharacteristic *characteristics, u8 count, u8 *total_out) { - return _btmuGetGattServiceData(id, unk1, characteristics, sizeof(BtmuGattCharacteristic), count, total_out, 31); +Result btmuGetGattCharacteristics(u32 id, u16 unk1, BtmGattCharacteristic *characteristics, u8 count, u8 *total_out) { + return _btmuGetGattServiceData(id, unk1, characteristics, sizeof(BtmGattCharacteristic), count, total_out, 31); } -Result btmuGetGattDescriptors(u32 id, u16 unk1, BtmuGattDescriptor *descriptors, u8 count, u8 *total_out) { - return _btmuGetGattServiceData(id, unk1, descriptors, sizeof(BtmuGattDescriptor), count, total_out, 32); +Result btmuGetGattDescriptors(u32 id, u16 unk1, BtmGattDescriptor *descriptors, u8 count, u8 *total_out) { + return _btmuGetGattServiceData(id, unk1, descriptors, sizeof(BtmGattDescriptor), count, total_out, 32); } Result btmuAcquireBleMtuConfigEvent(Event* out_event) { @@ -323,11 +323,11 @@ Result btmuGetBleMtu(u32 id, u16 *out) { ); } -Result btmuRegisterBleGattDataPath(const BtmuBleDataPath *path) { +Result btmuRegisterBleGattDataPath(const BtmBleDataPath *path) { return _btmuRegisterBleGattDataPath(path, 36); } -Result btmuUnregisterBleGattDataPath(const BtmuBleDataPath *path) { +Result btmuUnregisterBleGattDataPath(const BtmBleDataPath *path) { return _btmuRegisterBleGattDataPath(path, 37); }