From f6738439d43f32886ff996d6d3ca97b4d2eb4ffe Mon Sep 17 00:00:00 2001 From: ndeadly <24677491+ndeadly@users.noreply.github.com> Date: Sat, 1 Jun 2024 19:44:10 +0200 Subject: [PATCH 1/5] btdrv: change argument from service id to server interface for gatt server functions --- nx/include/switch/services/btdrv.h | 12 ++++++------ nx/source/services/btdrv.c | 18 +++++++++--------- 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/nx/include/switch/services/btdrv.h b/nx/include/switch/services/btdrv.h index c3dcec373..63902b236 100644 --- a/nx/include/switch/services/btdrv.h +++ b/nx/include/switch/services/btdrv.h @@ -1099,31 +1099,31 @@ Result btdrvAddGattService(u8 server_if, const BtdrvGattAttributeUuid *uuid, u8 /** * @brief EnableGattService * @note Only available on [5.0.0+]. - * @param[in] service_id Service ID + * @param[in] server_if Server interface ID * @param[in] uuid \ref BtdrvGattAttributeUuid */ -Result btdrvEnableGattService(u8 service_id, const BtdrvGattAttributeUuid *uuid); +Result btdrvEnableGattService(u8 server_if, const BtdrvGattAttributeUuid *uuid); /** * @brief AddGattCharacteristic * @note Only available on [5.0.0+]. - * @param[in] service_id Service ID + * @param[in] server_if Server interface ID * @param[in] serv_uuid Service UUID \ref BtdrvGattAttributeUuid * @param[in] char_uuid Characteristic UUID \ref BtdrvGattAttributeUuid * @param[in] permissions \ref BtdrvGattAttributePermission * @param[in] property \ref BtdrvGattCharacteristicProperty */ -Result btdrvAddGattCharacteristic(u8 service_id, const BtdrvGattAttributeUuid *serv_uuid, const BtdrvGattAttributeUuid *char_uuid, u8 permissions, u16 property); +Result btdrvAddGattCharacteristic(u8 server_if, const BtdrvGattAttributeUuid *serv_uuid, const BtdrvGattAttributeUuid *char_uuid, u8 permissions, u16 property); /** * @brief AddGattDescriptor * @note Only available on [5.0.0+]. - * @param[in] service_id Service ID + * @param[in] server_if Server interface ID * @param[in] serv_uuid Service UUID \ref BtdrvGattAttributeUuid * @param[in] desc_uuid Descriptor UUID \ref BtdrvGattAttributeUuid * @param[in] permissions \ref BtdrvGattAttributePermission */ -Result btdrvAddGattDescriptor(u8 service_id, const BtdrvGattAttributeUuid *serv_uuid, const BtdrvGattAttributeUuid *desc_uuid, u16 permissions); +Result btdrvAddGattDescriptor(u8 server_if, const BtdrvGattAttributeUuid *serv_uuid, const BtdrvGattAttributeUuid *desc_uuid, u16 permissions); /** * @brief GetBleManagedEventInfo diff --git a/nx/source/services/btdrv.c b/nx/source/services/btdrv.c index ce720c5fa..f83b44b9e 100644 --- a/nx/source/services/btdrv.c +++ b/nx/source/services/btdrv.c @@ -930,47 +930,47 @@ Result btdrvAddGattService(u8 server_if, const BtdrvGattAttributeUuid *uuid, u8 return serviceDispatchIn(&g_btdrvSrv, 75, in); } -Result btdrvEnableGattService(u8 service_id, const BtdrvGattAttributeUuid *uuid) { +Result btdrvEnableGattService(u8 server_if, const BtdrvGattAttributeUuid *uuid) { if (hosversionBefore(5,0,0)) return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); u32 cmd_id = hosversionBefore(5,1,0) ? 74 : 76; const struct { - u8 service_id; + u8 server_if; u8 pad[3]; BtdrvGattAttributeUuid uuid; - } in = { service_id, {0}, *uuid }; + } in = { server_if, {0}, *uuid }; return serviceDispatchIn(&g_btdrvSrv, cmd_id, in); } -Result btdrvAddGattCharacteristic(u8 service_id, const BtdrvGattAttributeUuid *serv_uuid, const BtdrvGattAttributeUuid *char_uuid, u8 permissions, u16 property) { +Result btdrvAddGattCharacteristic(u8 server_if, const BtdrvGattAttributeUuid *serv_uuid, const BtdrvGattAttributeUuid *char_uuid, u8 permissions, u16 property) { if (hosversionBefore(5,0,0)) return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); const struct { - u8 service_id; + u8 server_if; u8 permissions; u16 property; BtdrvGattAttributeUuid serv_uuid; BtdrvGattAttributeUuid char_uuid; - } in = { service_id, permissions, property, *serv_uuid, *char_uuid }; + } in = { server_if, permissions, property, *serv_uuid, *char_uuid }; return serviceDispatchIn(&g_btdrvSrv, 77, in); } -Result btdrvAddGattDescriptor(u8 service_id, const BtdrvGattAttributeUuid *serv_uuid, const BtdrvGattAttributeUuid *desc_uuid, u16 permissions) { +Result btdrvAddGattDescriptor(u8 server_if, const BtdrvGattAttributeUuid *serv_uuid, const BtdrvGattAttributeUuid *desc_uuid, u16 permissions) { if (hosversionBefore(5,0,0)) return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); u32 cmd_id = hosversionBefore(5,1,0) ? 76 : 78; const struct { - u8 service_id; + u8 server_if; u8 pad; u16 permissions; BtdrvGattAttributeUuid serv_uuid; BtdrvGattAttributeUuid desc_uuid; - } in = { service_id, 0, permissions, *serv_uuid, *desc_uuid }; + } in = { server_if, 0, permissions, *serv_uuid, *desc_uuid }; return serviceDispatchIn(&g_btdrvSrv, cmd_id, in); } From ef5329dea62b867272973df7af91ed44d6cbaa10 Mon Sep 17 00:00:00 2001 From: ndeadly <24677491+ndeadly@users.noreply.github.com> Date: Sat, 1 Jun 2024 19:46:18 +0200 Subject: [PATCH 2/5] btdrv: add notes about broken gatt server function implementations --- nx/include/switch/services/btdrv.h | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/nx/include/switch/services/btdrv.h b/nx/include/switch/services/btdrv.h index 63902b236..68a9e959a 100644 --- a/nx/include/switch/services/btdrv.h +++ b/nx/include/switch/services/btdrv.h @@ -1058,6 +1058,7 @@ Result btdrvConfigureAttMtu(u32 conn_id, u16 mtu); /** * @brief RegisterGattServer * @note Only available on [5.0.0+]. + * @note Event data generated by this call contains uninitialized junk instead of the server_if value received internally. * @param[in] uuid \ref BtdrvGattAttributeUuid */ Result btdrvRegisterGattServer(const BtdrvGattAttributeUuid *uuid); @@ -1089,6 +1090,7 @@ Result btdrvDisconnectGattClient(u8 conn_id, BtdrvAddress addr); /** * @brief AddGattService * @note Only available on [5.0.0+]. + * @note Broken behaviour due to internal bugs. * @param[in] server_if Server interface ID * @param[in] uuid \ref BtdrvGattAttributeUuid * @param[in] num_handle Number of handles @@ -1099,6 +1101,7 @@ Result btdrvAddGattService(u8 server_if, const BtdrvGattAttributeUuid *uuid, u8 /** * @brief EnableGattService * @note Only available on [5.0.0+]. + * @note Broken behaviour due to internal bugs. * @param[in] server_if Server interface ID * @param[in] uuid \ref BtdrvGattAttributeUuid */ @@ -1107,6 +1110,7 @@ Result btdrvEnableGattService(u8 server_if, const BtdrvGattAttributeUuid *uuid); /** * @brief AddGattCharacteristic * @note Only available on [5.0.0+]. + * @note Broken behaviour due to internal bugs. * @param[in] server_if Server interface ID * @param[in] serv_uuid Service UUID \ref BtdrvGattAttributeUuid * @param[in] char_uuid Characteristic UUID \ref BtdrvGattAttributeUuid @@ -1118,6 +1122,7 @@ Result btdrvAddGattCharacteristic(u8 server_if, const BtdrvGattAttributeUuid *se /** * @brief AddGattDescriptor * @note Only available on [5.0.0+]. + * @note Broken behaviour due to internal bugs. * @param[in] server_if Server interface ID * @param[in] serv_uuid Service UUID \ref BtdrvGattAttributeUuid * @param[in] desc_uuid Descriptor UUID \ref BtdrvGattAttributeUuid From 12cf2f9ccc4e2f2b7e99ab3e8ca71db969127f66 Mon Sep 17 00:00:00 2001 From: ndeadly <24677491+ndeadly@users.noreply.github.com> Date: Sat, 1 Jun 2024 19:51:04 +0200 Subject: [PATCH 3/5] btdrv: fixed swapped permissions and property parameters for btdrvAddGattCharacteristic function --- nx/include/switch/services/btdrv.h | 2 +- nx/source/services/btdrv.c | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/nx/include/switch/services/btdrv.h b/nx/include/switch/services/btdrv.h index 68a9e959a..e29fdfc9f 100644 --- a/nx/include/switch/services/btdrv.h +++ b/nx/include/switch/services/btdrv.h @@ -1117,7 +1117,7 @@ Result btdrvEnableGattService(u8 server_if, const BtdrvGattAttributeUuid *uuid); * @param[in] permissions \ref BtdrvGattAttributePermission * @param[in] property \ref BtdrvGattCharacteristicProperty */ -Result btdrvAddGattCharacteristic(u8 server_if, const BtdrvGattAttributeUuid *serv_uuid, const BtdrvGattAttributeUuid *char_uuid, u8 permissions, u16 property); +Result btdrvAddGattCharacteristic(u8 server_if, const BtdrvGattAttributeUuid *serv_uuid, const BtdrvGattAttributeUuid *char_uuid, u16 permissions, u8 property); /** * @brief AddGattDescriptor diff --git a/nx/source/services/btdrv.c b/nx/source/services/btdrv.c index f83b44b9e..568f1e823 100644 --- a/nx/source/services/btdrv.c +++ b/nx/source/services/btdrv.c @@ -944,17 +944,17 @@ Result btdrvEnableGattService(u8 server_if, const BtdrvGattAttributeUuid *uuid) return serviceDispatchIn(&g_btdrvSrv, cmd_id, in); } -Result btdrvAddGattCharacteristic(u8 server_if, const BtdrvGattAttributeUuid *serv_uuid, const BtdrvGattAttributeUuid *char_uuid, u8 permissions, u16 property) { +Result btdrvAddGattCharacteristic(u8 server_if, const BtdrvGattAttributeUuid *serv_uuid, const BtdrvGattAttributeUuid *char_uuid, u16 permissions, u8 property) { if (hosversionBefore(5,0,0)) return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); const struct { u8 server_if; - u8 permissions; - u16 property; + u8 property; + u16 permissions; BtdrvGattAttributeUuid serv_uuid; BtdrvGattAttributeUuid char_uuid; - } in = { server_if, permissions, property, *serv_uuid, *char_uuid }; + } in = { server_if, property, permissions, *serv_uuid, *char_uuid }; return serviceDispatchIn(&g_btdrvSrv, 77, in); } From fe4479824ff539214f64e9975acfb3570c74fcd7 Mon Sep 17 00:00:00 2001 From: ndeadly <24677491+ndeadly@users.noreply.github.com> Date: Sat, 1 Jun 2024 22:01:14 +0200 Subject: [PATCH 4/5] btdrv: update gatt server event names to better reflect usage --- nx/include/switch/services/btdrv.h | 8 ++++---- nx/include/switch/services/btdrv_types.h | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/nx/include/switch/services/btdrv.h b/nx/include/switch/services/btdrv.h index e29fdfc9f..b878eed17 100644 --- a/nx/include/switch/services/btdrv.h +++ b/nx/include/switch/services/btdrv.h @@ -439,21 +439,21 @@ typedef struct { u8 property; ///< Characteristic properties. Only set if attr_type is 1 \ref BtdrvGattCharacteristicProperty u8 is_primary; ///< Is a primary service or not u8 pad; ///< Padding - } server_add_characteristic; ///< ::BtdrvBleEventType_ServerAddCharacteristic + } server_add_attribute; ///< ::BtdrvBleEventType_ServerAddAttribute struct { u32 result; ///< 0 for success, non-zero for error. u16 conn_id; ///< Connection ID - u8 unk_x6; ///< Unknown. Always 1 + u8 operation; ///< Operation. 0 = Read, 1 = Write u8 pad; ///< Padding u16 service_id; ///< Service ID u16 attr_id; ///< Attribute ID u8 attr_type; ///< Attribute type \ref BtdrvGattAttributeType - u8 data[0x200]; ///< Data + u8 data[0x200]; ///< Data written during write operation u16 size; ///< Size of the above data u16 offset; ///< Offset u8 pad2[2]; ///< Padding - } server_write; ///< ::BtdrvBleEventType_ServerWrite + } server_attribute_operation; ///< ::BtdrvBleEventType_ServerAttributeOperation }; } BtdrvBleEventInfo; diff --git a/nx/include/switch/services/btdrv_types.h b/nx/include/switch/services/btdrv_types.h index bd1a99c51..29164ee66 100644 --- a/nx/include/switch/services/btdrv_types.h +++ b/nx/include/switch/services/btdrv_types.h @@ -137,8 +137,8 @@ typedef enum { BtdrvBleEventType_ClientCacheSave = 9, ///< GATT client cache save. BtdrvBleEventType_ClientCacheLoad = 10, ///< GATT client cache load. BtdrvBleEventType_ClientConfigureMtu = 11, ///< GATT client configure MTU. - BtdrvBleEventType_ServerAddCharacteristic = 12, ///< GATT server add characteristic. - BtdrvBleEventType_ServerWrite = 13, ///< GATT server write. + BtdrvBleEventType_ServerAddAttribute = 12, ///< GATT server add attribute. + BtdrvBleEventType_ServerAttributeOperation = 13, ///< GATT server attribute operation. } BtdrvBleEventType; /// GattAttributeType From 5fb65cecbbc986f8a1cf7bf03ab439a6126d6da7 Mon Sep 17 00:00:00 2001 From: ndeadly <24677491+ndeadly@users.noreply.github.com> Date: Tue, 4 Jun 2024 10:57:37 +0200 Subject: [PATCH 5/5] btdrv: complete definition of BtdrvBleAdvertisePacketData struct and add supporting enums --- nx/include/switch/services/btdrv_types.h | 117 ++++++++++++++--------- 1 file changed, 71 insertions(+), 46 deletions(-) diff --git a/nx/include/switch/services/btdrv_types.h b/nx/include/switch/services/btdrv_types.h index 29164ee66..fa63fd49e 100644 --- a/nx/include/switch/services/btdrv_types.h +++ b/nx/include/switch/services/btdrv_types.h @@ -193,6 +193,37 @@ typedef enum { BtdrvGattAuthReqType_SignedMitm = 4, } BtdrvGattAuthReqType; +/// BtdrvBleAdBit +typedef enum { + BtdrvBleAdBit_DeviceName = BIT(0), + BtdrvBleAdBit_Flags = BIT(1), + BtdrvBleAdBit_Manufacturer = BIT(2), + BtdrvBleAdBit_TxPower = BIT(3), + BtdrvBleAdBit_Service32 = BIT(4), + BtdrvBleAdBit_IntRange = BIT(5), + BtdrvBleAdBit_Service = BIT(6), + BtdrvBleAdBit_ServiceSol = BIT(7), + BtdrvBleAdBit_ServiceData = BIT(8), + BtdrvBleAdBit_SignData = BIT(9), + BtdrvBleAdBit_Service128Sol = BIT(10), + BtdrvBleAdBit_Appearance = BIT(11), + BtdrvBleAdBit_PublicAddress = BIT(12), + BtdrvBleAdBit_RandomAddress = BIT(13), + BtdrvBleAdBit_Service32Sol = BIT(14), + BtdrvBleAdBit_Proprietary = BIT(15), + BtdrvBleAdBit_Service128 = BIT(16), +} BtdrvBleAdBit; + +/// BtdrvBleAdFlag +typedef enum { + BtdrvBleAdFlag_None = 0, + BtdrvBleAdFlag_LimitedDiscovery = BIT(0), + BtdrvBleAdFlag_GeneralDiscovery = BIT(1), + BtdrvBleAdFlag_BrEdrNotSupported = BIT(2), + BtdrvBleAdFlag_DualModeControllerSupport = BIT(3), + BtdrvBleAdFlag_DualModeHostSupport = BIT(4), +} BtdrvBleAdFlag; + /// AudioEventType typedef enum { BtdrvAudioEventType_None = 0, ///< None @@ -280,6 +311,29 @@ typedef struct { u8 unk_x0[0x88]; ///< Unknown } BtdrvChannelMapList; +/// GattAttributeUuid +typedef struct { + u32 size; ///< UUID size, must be 0x2, 0x4, or 0x10. + u8 uuid[0x10]; ///< UUID with the above size. +} BtdrvGattAttributeUuid; + +/// GattId +typedef struct { + u8 instance_id; ///< InstanceId + u8 pad[3]; ///< Padding + BtdrvGattAttributeUuid uuid; ///< \ref BtdrvGattAttributeUuid +} BtdrvGattId; + +/// GattAttribute +typedef struct { + BtdrvGattId id; ///< \ref BtdrvGattId + u16 type; ///< \ref BtdrvGattAttributeType + u16 handle; + u16 group_end_handle; + u8 property; ///< Only used when type is characteristic. \ref BtdrvGattCharacteristicProperty + bool is_primary; ///< Only used when type is service +} BtdrvGattAttribute; + /// LeConnectionParams [5.0.0-8.1.1] typedef struct { BtdrvAddress addr; ///< \ref BtdrvAddress @@ -303,30 +357,24 @@ typedef struct { u16 supervision_tout; ///< Connection supervision timeout multiplier } BtdrvBleConnectionParameter; -/// BtdrvBleAdvertisePacketDataEntry +/// BtdrvBleAdvertisePacketData typedef struct { - u16 unk_x0; ///< Unknown - u8 unused[0x12]; ///< Unused -} BtdrvBleAdvertisePacketDataEntry; - -/// BleAdvertisePacketData -typedef struct { - u32 unk_x0; ///< Unknown - u8 unk_x4; ///< Unknown - u8 size0; ///< Size of the data at unk_x6. - u8 unk_x6[0x1F]; ///< Unknown, see size0. - u8 pad[3]; ///< Padding - u8 count; ///< Total array entries, see entries. - u8 pad2[7]; ///< Padding - BtdrvBleAdvertisePacketDataEntry entries[0x5]; ///< \ref BtdrvBleAdvertisePacketDataEntry - u8 pad3[0x10]; ///< Padding - u8 size2; ///< Size of the data at unk_xA8. - u8 unk_xA5; ///< Unknown - u8 pad4[2]; ///< Padding - u8 unk_xA8[0x1F]; ///< Unknown, see size2. - u8 unk_xC7; ///< Unknown - u8 unk_xC8; ///< Unknown - u8 pad5[3]; ///< Padding + u32 adv_data_mask; ///< Bitmask of following AD data to be included in advertising packets \ref BtdrvBleAdBit + u8 flag; ///< AD flag value to be advertised \ref BtdrvBleAdFlag. Included with BtdrvBleAdBit_Flags + u8 manu_data_len; ///< Size of manu_data below + u8 manu_data[0x1F]; ///< Manufacturer-specific data to be advertised. Included with BtdrvBleAdBit_Manufacturer + u8 pad[1]; ///< Padding + u16 appearance_data; ///< Device appearance data to be advertised \ref BtdrvAppearanceType. Included with BtdrvBleAdBit_Appearance + u8 num_service; ///< Number of services in uuid_val array below + u8 pad2[3]; ///< Padding + BtdrvGattAttributeUuid uuid_val[0x6]; ///< Array of 16-bit UUIDs to be advertised \ref BtdrvGattAttributeUuid. Included with BtdrvBleAdBit_Service + u8 service_data_len; ///< Size of service_data below + u8 pad3[1]; ///< Padding + u16 service_data_uuid; ///< 16-bit UUID of service_data below + u8 service_data[0x1F]; ///< Service data to be advertised. Included with BtdrvBleAdBit_ServiceData + bool is_scan_rsp; ///< Whether this is an inquiry scan response or advertising data + u8 tx_power; ///< Inquiry transmit power to be advertised. Included with BtdrvBleAdBit_TxPower + u8 pad4[3]; ///< Padding } BtdrvBleAdvertisePacketData; /// BleAdvertisement @@ -366,29 +414,6 @@ typedef struct { u8 pad[2]; ///< Padding } BtdrvBleConnectionInfo; -/// GattAttributeUuid -typedef struct { - u32 size; ///< UUID size, must be 0x2, 0x4, or 0x10. - u8 uuid[0x10]; ///< UUID with the above size. -} BtdrvGattAttributeUuid; - -/// GattId -typedef struct { - u8 instance_id; ///< InstanceId - u8 pad[3]; ///< Padding - BtdrvGattAttributeUuid uuid; ///< \ref BtdrvGattAttributeUuid -} BtdrvGattId; - -/// GattAttribute -typedef struct { - BtdrvGattId id; ///< \ref BtdrvGattId - u16 type; ///< \ref BtdrvGattAttributeType - u16 handle; - u16 group_end_handle; - u8 property; ///< Only used when type is characteristic. \ref BtdrvGattCharacteristicProperty - bool is_primary; ///< Only used when type is service -} BtdrvGattAttribute; - /// LeEventInfo typedef struct { u32 unk_x0; ///< Unknown