From 2878b97f3a78420d33ba6a0a8942b2886e051758 Mon Sep 17 00:00:00 2001 From: yellows8 Date: Fri, 17 Jul 2020 10:58:36 -0400 Subject: [PATCH] btdrv: Added cmds: btdrvGetAdapterProperties, btdrvGetAdapterProperty, btdrvSetAdapterProperty, btdrvWriteHidData, btdrvWriteHidData2, btdrvSetHidReport, btdrvGetHidReport. Added/updated the required enum/struct. bt(drv): Updated docs. --- nx/include/switch/services/bt.h | 8 ++-- nx/include/switch/services/btdrv.h | 71 ++++++++++++++++++++++++++++-- nx/source/services/btdrv.c | 63 ++++++++++++++++++++++++++ 3 files changed, 135 insertions(+), 7 deletions(-) diff --git a/nx/include/switch/services/bt.h b/nx/include/switch/services/bt.h index 200b1646..13d5d14b 100644 --- a/nx/include/switch/services/bt.h +++ b/nx/include/switch/services/bt.h @@ -52,7 +52,7 @@ Result btLeClientReadDescriptor(bool flag, u8 unk, u32 unk2, const BtdrvGattId * * @param[in] id0 \ref BtdrvGattId * @param[in] id1 \ref BtdrvGattId * @param[in] buffer Input buffer. - * @param[in] size Input buffer size. + * @param[in] size Input buffer size, must be <=0x258. */ Result btLeClientWriteCharacteristic(bool flag, u8 unk, bool flag2, u32 unk2, const BtdrvGattId *id0, const BtdrvGattId *id1, const void* buffer, size_t size); @@ -66,7 +66,7 @@ Result btLeClientWriteCharacteristic(bool flag, u8 unk, bool flag2, u32 unk2, co * @param[in] id1 \ref BtdrvGattId * @param[in] id2 \ref BtdrvGattId * @param[in] buffer Input buffer. - * @param[in] size Input buffer size. + * @param[in] size Input buffer size, must be <=0x258. */ Result btLeClientWriteDescriptor(bool flag, u8 unk, u32 unk2, const BtdrvGattId *id0, const BtdrvGattId *id1, const BtdrvGattId *id2, const void* buffer, size_t size); @@ -96,7 +96,7 @@ Result btLeClientDeregisterNotification(bool flag, u32 unk, const BtdrvGattId *i * @param[in] uuid0 \ref BtdrvGattAttributeUuid * @param[in] uuid1 \ref BtdrvGattAttributeUuid * @param[in] buffer Input buffer. - * @param[in] size Input buffer size. + * @param[in] size Input buffer size, must be <=0x258. */ Result btSetLeResponse(u8 unk, const BtdrvGattAttributeUuid *uuid0, const BtdrvGattAttributeUuid *uuid1, const void* buffer, size_t size); @@ -107,7 +107,7 @@ Result btSetLeResponse(u8 unk, const BtdrvGattAttributeUuid *uuid0, const BtdrvG * @param[in] uuid0 \ref BtdrvGattAttributeUuid * @param[in] uuid1 \ref BtdrvGattAttributeUuid * @param[in] buffer Input buffer. - * @param[in] size Input buffer size. + * @param[in] size Input buffer size, clamped to max size 0x258. */ Result btLeSendIndication(u8 unk, bool flag, const BtdrvGattAttributeUuid *uuid0, const BtdrvGattAttributeUuid *uuid1, const void* buffer, size_t size); diff --git a/nx/include/switch/services/btdrv.h b/nx/include/switch/services/btdrv.h index 40ab163b..a54cb4ee 100644 --- a/nx/include/switch/services/btdrv.h +++ b/nx/include/switch/services/btdrv.h @@ -9,6 +9,15 @@ #include "../kernel/event.h" #include "../sf/service.h" +/// BluetoothPropertyType +typedef enum { + BtdrvBluetoothPropertyType_Name = 1, ///< Name. String, max length 0xF8 excluding NUL-terminator. + BtdrvBluetoothPropertyType_Address = 2, ///< \ref BtdrvAddress + BtdrvBluetoothPropertyType_Unknown3 = 3, ///< Only available with \ref btdrvSetAdapterProperty. Unknown. 3-bytes. + BtdrvBluetoothPropertyType_Unknown5 = 5, ///< Unknown. 3-bytes. + BtdrvBluetoothPropertyType_Unknown6 = 6, ///< Unknown. 1-byte. The default is value 0x68. +} BtdrvBluetoothPropertyType; + /// Address typedef struct { u8 address[0x6]; ///< Address @@ -16,7 +25,10 @@ typedef struct { /// AdapterProperty typedef struct { - u8 unk_x0[0x103]; ///< Unknown + BtdrvAddress addr; ///< Same as the data for ::BtdrvBluetoothPropertyType_Address. + u8 type5[0x3]; ///< Same as the data for ::BtdrvBluetoothPropertyType_Unknown5. + char name[0xF9]; ///< Same as the data for ::BtdrvBluetoothPropertyType_Name (last byte is not initialized). + u8 type6; ///< Set to hard-coded value 0x68 (same as the data for ::BtdrvBluetoothPropertyType_Unknown6). } BtdrvAdapterProperty; /// BluetoothPinCode @@ -90,6 +102,59 @@ void btdrvExit(void); /// Gets the Service object for the actual btdrv service session. Service* btdrvGetServiceSession(void); +/** + * @brief GetAdapterProperties + * @param[out] property \ref BtdrvAdapterProperty + */ +Result btdrvGetAdapterProperties(BtdrvAdapterProperty *property); + +/** + * @brief GetAdapterProperty + * @param[in] type \ref BtdrvBluetoothPropertyType + * @param[out] buffer Output buffer, see \ref BtdrvBluetoothPropertyType for the contents. + * @param[in] size Output buffer size. + */ +Result btdrvGetAdapterProperty(BtdrvBluetoothPropertyType type, void* buffer, size_t size); + +/** + * @brief SetAdapterProperty + * @param[in] type \ref BtdrvBluetoothPropertyType + * @param[in] buffer Input buffer, see \ref BtdrvBluetoothPropertyType for the contents. + * @param[in] size Input buffer size. + */ +Result btdrvSetAdapterProperty(BtdrvBluetoothPropertyType type, const void* buffer, size_t size); + +/** + * @brief WriteHidData + * @param[in] addr \ref BtdrvAddress + * @param[in] buffer Input \ref BtdrvHidReport, on pre-9.0.0 this is \ref BtdrvHidData. + */ +Result btdrvWriteHidData(BtdrvAddress addr, BtdrvHidReport *buffer); + +/** + * @brief WriteHidData2 + * @param[in] addr \ref BtdrvAddress + * @param[in] buffer Input buffer, same as the buffer for \ref btdrvWriteHidData. + * @param[in] size Input buffer size. + */ +Result btdrvWriteHidData2(BtdrvAddress addr, const void* buffer, size_t size); + +/** + * @brief SetHidReport + * @param[in] addr \ref BtdrvAddress + * @param[in] type BluetoothHhReportType + * @param[in] buffer Input \ref BtdrvHidReport, on pre-9.0.0 this is \ref BtdrvHidData. + */ +Result btdrvSetHidReport(BtdrvAddress addr, u32 type, BtdrvHidReport *buffer); + +/** + * @brief GetHidReport + * @param[in] addr \ref BtdrvAddress + * @param[in] unk Unknown + * @param[in] type BluetoothHhReportType + */ +Result btdrvGetHidReport(BtdrvAddress addr, u8 unk, u32 type); + /** * @brief ReadGattCharacteristic * @note Only available on [5.0.0+]. @@ -123,7 +188,7 @@ Result btdrvReadGattDescriptor(bool flag, u8 unk, u32 unk2, const BtdrvGattId *i * @param[in] id0 \ref BtdrvGattId * @param[in] id1 \ref BtdrvGattId * @param[in] buffer Input buffer. - * @param[in] size Input buffer size. + * @param[in] size Input buffer size, must be <=0x258. */ Result btdrvWriteGattCharacteristic(bool flag, u8 unk, bool flag2, u32 unk2, const BtdrvGattId *id0, const BtdrvGattId *id1, const void* buffer, size_t size); @@ -137,7 +202,7 @@ Result btdrvWriteGattCharacteristic(bool flag, u8 unk, bool flag2, u32 unk2, con * @param[in] id1 \ref BtdrvGattId * @param[in] id2 \ref BtdrvGattId * @param[in] buffer Input buffer. - * @param[in] size Input buffer size. + * @param[in] size Input buffer size, must be <=0x258. */ Result btdrvWriteGattDescriptor(bool flag, u8 unk, u32 unk2, const BtdrvGattId *id0, const BtdrvGattId *id1, const BtdrvGattId *id2, const void* buffer, size_t size); diff --git a/nx/source/services/btdrv.c b/nx/source/services/btdrv.c index 1f7e7401..fa365cb0 100644 --- a/nx/source/services/btdrv.c +++ b/nx/source/services/btdrv.c @@ -30,6 +30,69 @@ static Result _btdrvCmdNoIO(u32 cmd_id) { return serviceDispatch(&g_btdrvSrv, cmd_id); } +Result btdrvGetAdapterProperties(BtdrvAdapterProperty *property) { + return serviceDispatch(&g_btdrvSrv, 5, + .buffer_attrs = { SfBufferAttr_HipcPointer | SfBufferAttr_Out | SfBufferAttr_FixedSize }, + .buffers = { { property, sizeof(*property) } }, + ); +} + +Result btdrvGetAdapterProperty(BtdrvBluetoothPropertyType type, void* buffer, size_t size) { + u32 tmp=type; + return serviceDispatchIn(&g_btdrvSrv, 6, tmp, + .buffer_attrs = { SfBufferAttr_HipcPointer | SfBufferAttr_Out }, + .buffers = { { buffer, size } }, + ); +} + +Result btdrvSetAdapterProperty(BtdrvBluetoothPropertyType type, const void* buffer, size_t size) { + u32 tmp=type; + return serviceDispatchIn(&g_btdrvSrv, 7, tmp, + .buffer_attrs = { SfBufferAttr_HipcPointer | SfBufferAttr_In }, + .buffers = { { buffer, size } }, + ); +} + +Result btdrvWriteHidData(BtdrvAddress addr, BtdrvHidReport *buffer) { + size_t size = hosversionBefore(9,0,0) ? sizeof(BtdrvHidData) : sizeof(BtdrvHidReport); + return serviceDispatchIn(&g_btdrvSrv, 19, addr, + .buffer_attrs = { SfBufferAttr_HipcPointer | SfBufferAttr_In | SfBufferAttr_FixedSize }, + .buffers = { { buffer, size } }, + ); +} + +Result btdrvWriteHidData2(BtdrvAddress addr, const void* buffer, size_t size) { + return serviceDispatchIn(&g_btdrvSrv, 20, addr, + .buffer_attrs = { SfBufferAttr_HipcPointer | SfBufferAttr_In }, + .buffers = { { buffer, size } }, + ); +} + +Result btdrvSetHidReport(BtdrvAddress addr, u32 type, BtdrvHidReport *buffer) { + size_t size = hosversionBefore(9,0,0) ? sizeof(BtdrvHidData) : sizeof(BtdrvHidReport); + + const struct { + BtdrvAddress addr; + u32 type; + } in = { addr, type }; + + return serviceDispatchIn(&g_btdrvSrv, 21, in, + .buffer_attrs = { SfBufferAttr_HipcPointer | SfBufferAttr_In | SfBufferAttr_FixedSize }, + .buffers = { { buffer, size } }, + ); +} + +Result btdrvGetHidReport(BtdrvAddress addr, u8 unk, u32 type) { + const struct { + BtdrvAddress addr; + u8 unk; + u8 pad[3]; + u32 type; + } in = { addr, unk, {0}, type }; + + return serviceDispatchIn(&g_btdrvSrv, 22, in); +} + Result btdrvReadGattCharacteristic(bool flag, u8 unk, u32 unk2, const BtdrvGattId *id0, const BtdrvGattId *id1) { if (hosversionBefore(5,0,0)) return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer);