Skip to content
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

btdrv: misc. fixes and updates to BLE related functions and type definitions #658

Merged
merged 5 commits into from
Jan 26, 2025
Merged
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
25 changes: 15 additions & 10 deletions nx/include/switch/services/btdrv.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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
Expand All @@ -1099,31 +1101,34 @@ Result btdrvAddGattService(u8 server_if, const BtdrvGattAttributeUuid *uuid, u8
/**
* @brief EnableGattService
* @note Only available on [5.0.0+].
* @param[in] service_id Service ID
* @note Broken behaviour due to internal bugs.
* @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
* @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
* @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, u16 permissions, u8 property);

/**
* @brief AddGattDescriptor
* @note Only available on [5.0.0+].
* @param[in] service_id Service ID
* @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
* @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
Expand Down
121 changes: 73 additions & 48 deletions nx/include/switch/services/btdrv_types.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand All @@ -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
Expand Down Expand Up @@ -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
Expand Down
22 changes: 11 additions & 11 deletions nx/source/services/btdrv.c
Original file line number Diff line number Diff line change
Expand Up @@ -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, u16 permissions, u8 property) {
if (hosversionBefore(5,0,0))
return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer);

const struct {
u8 service_id;
u8 permissions;
u16 property;
u8 server_if;
u8 property;
u16 permissions;
BtdrvGattAttributeUuid serv_uuid;
BtdrvGattAttributeUuid char_uuid;
} in = { service_id, permissions, property, *serv_uuid, *char_uuid };
} in = { server_if, property, permissions, *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);
}
Expand Down
Loading