diff --git a/nx/include/switch/services/btdrv.h b/nx/include/switch/services/btdrv.h index 3bf41168..58fb8f98 100644 --- a/nx/include/switch/services/btdrv.h +++ b/nx/include/switch/services/btdrv.h @@ -7,73 +7,10 @@ #pragma once #include "../types.h" #include "../kernel/event.h" +#include "../services/btdrv_types.h" +#include "../services/set.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; - -/// BluetoothHhReportType -/// Bit0-1 directly control the HID bluetooth transaction report-type value. -/// Bit2-3: these directly control the Parameter Reserved field for SetReport, for GetReport these control the Parameter Reserved and Size bits. -typedef enum { - BtdrvBluetoothHhReportType_Other = 0, ///< Other - BtdrvBluetoothHhReportType_Input = 1, ///< Input - BtdrvBluetoothHhReportType_Output = 2, ///< Output - BtdrvBluetoothHhReportType_Feature = 3, ///< Feature -} BtdrvBluetoothHhReportType; - -/// HidEventType -typedef enum { - BtdrvHidEventType_Unknown0 = 0, ///< Unknown. Only used with \ref btdrvGetHidEventInfo. - BtdrvHidEventType_Unknown4 = 4, ///< Unknown. - BtdrvHidEventType_Unknown7 = 7, ///< Unknown. Only used with \ref btdrvGetHidEventInfo. - BtdrvHidEventType_Unknown8 = 8, ///< Unknown. - BtdrvHidEventType_Unknown9 = 9, ///< Unknown. -} BtdrvHidEventType; - -/// This determines the u16 data to write into the CircularBuffer (name "BLE CORE"). -typedef enum { - BtdrvFatalReason_Unknown1 = 1, ///< u16 data = 0x850. - BtdrvFatalReason_Unknown2 = 2, ///< u16 data = 0x851. - BtdrvFatalReason_Unknown3 = 3, ///< Reason values which aren't 1/2: u16 data = 0x852. -} BtdrvFatalReason; - -/// Address -typedef struct { - u8 address[0x6]; ///< Address -} BtdrvAddress; - -/// AdapterProperty -typedef struct { - 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 -typedef struct { - char code[0x10]; ///< PinCode -} BtdrvBluetoothPinCode; - -/// HidData, for pre-9.0.0. -typedef struct { - u16 size; ///< Size of data. - u8 data[0x280]; ///< Data -} BtdrvHidData; - -/// HidReport, for [9.0.0+]. -typedef struct { - u16 size; ///< Size of data. - u8 data[0x2BC]; ///< Data -} BtdrvHidReport; - /// Data for \ref btdrvGetHidReportEventInfo. The data stored here depends on the \ref BtdrvHidEventType. typedef struct { union { @@ -174,90 +111,6 @@ typedef struct { } data; } BtdrvHidReportEventInfoBufferData; -/// PlrStatistics -typedef struct { - u8 unk_x0[0x84]; ///< Unknown -} BtdrvPlrStatistics; - -/// PlrList -typedef struct { - u8 unk_x0[0xA4]; ///< Unknown -} BtdrvPlrList; - -/// ChannelMapList -typedef struct { - u8 unk_x0[0x88]; ///< Unknown -} BtdrvChannelMapList; - -/// LeConnectionParams -typedef struct { - u8 unk_x0[0x14]; ///< Unknown -} BtdrvLeConnectionParams; - -/// BleConnectionParameter -typedef struct { - u8 unk_x0[0xC]; ///< Unknown -} BtdrvBleConnectionParameter; - -/// BtdrvBleAdvertisePacketDataEntry -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 -} BtdrvBleAdvertisePacketData; - -/// BleAdvertiseFilter -typedef struct { - u8 unk_x0[0x3E]; ///< Unknown -} BtdrvBleAdvertiseFilter; - -/// BleAdvertisePacketParameter -typedef struct { - u8 data[0x8]; ///< Unknown -} BtdrvBleAdvertisePacketParameter; - -/// BleScanResult -typedef struct { - u8 unk_x0[0x148]; ///< Unknown -} BtdrvBleScanResult; - -/// BleConnectionInfo -typedef struct { - u32 id; ///< Id, 0xFFFFFFFF ([5.0.0-5.0.2] 0xFFFF) is invalid. - BtdrvAddress addr; ///< \ref BtdrvAddress - 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 unk_x0[0x18]; ///< Unknown -} BtdrvGattId; - /// CircularBuffer typedef struct { Mutex mutex; @@ -279,6 +132,32 @@ void btdrvExit(void); /// Gets the Service object for the actual btdrv service session. Service* btdrvGetServiceSession(void); +/** + * @brief InitializeBluetooth + * @note This is used by btm-sysmodule, this should not be used by other processes. + * @note The Event must be closed by the user once finished with it. + * @param[out] out_event Output Event with autoclear=true. + */ +Result btdrvInitializeBluetooth(Event* out_event); + +/** + * @brief EnableBluetooth + * @note This is used by btm-sysmodule. + */ +Result btdrvEnableBluetooth(void); + +/** + * @brief DisableBluetooth + * @note This is used by btm-sysmodule. + */ +Result btdrvDisableBluetooth(void); + +/** + * @brief FinalizeBluetooth + * @note This is not used by btm-sysmodule, this should not be used by other processes. + */ +Result btdrvFinalizeBluetooth(void); + /** * @brief GetAdapterProperties * @param[out] property \ref BtdrvAdapterProperty @@ -301,6 +180,59 @@ Result btdrvGetAdapterProperty(BtdrvBluetoothPropertyType type, void* buffer, si */ Result btdrvSetAdapterProperty(BtdrvBluetoothPropertyType type, const void* buffer, size_t size); +/** + * @brief StartInquiry + * @note This is used by btm-sysmodule. + */ +Result btdrvStartInquiry(void); + +/** + * @brief StopInquiry + * @note This is used by btm-sysmodule. + */ +Result btdrvStopInquiry(void); + +/** + * @brief CreateBond + * @note This is used by btm-sysmodule. + * @param[in] addr \ref BtdrvAddress + * @param[in] type TransportType + */ +Result btdrvCreateBond(BtdrvAddress addr, u32 type); + +/** + * @brief RemoveBond + * @note This is used by btm-sysmodule. + * @param[in] addr \ref BtdrvAddress + */ +Result btdrvRemoveBond(BtdrvAddress addr); + +/** + * @brief CancelBond + * @note This is used by btm-sysmodule. + * @param[in] addr \ref BtdrvAddress + */ +Result btdrvCancelBond(BtdrvAddress addr); + +/** + * @brief RespondToPinRequest + * @param[in] addr \ref BtdrvAddress + * @param[in] flag Flag + * @param[in] pin_code \ref BtdrvBluetoothPinCode + * @param[in] unk Unknown + */ +Result btdrvRespondToPinRequest(BtdrvAddress addr, bool flag, const BtdrvBluetoothPinCode *pin_code, u8 unk); + +/** + * @brief RespondToSspRequest + * @note This is used by btm-sysmodule. + * @param[in] addr \ref BtdrvAddress + * @param[in] variant BluetoothSspVariant + * @param[in] flag Flag + * @param[in] unk Unknown + */ +Result btdrvRespondToSspRequest(BtdrvAddress addr, u8 variant, bool flag, u32 unk); + /** * @brief GetEventInfo * @note This is used by btm-sysmodule. @@ -310,6 +242,28 @@ Result btdrvSetAdapterProperty(BtdrvBluetoothPropertyType type, const void* buff */ Result btdrvGetEventInfo(void* buffer, size_t size, u32 *type); +/** + * @brief InitializeHid + * @note This is used by btm-sysmodule, this should not be used by other processes. + * @note The Event must be closed by the user once finished with it. + * @param[out] out_event Output Event with autoclear=true. + */ +Result btdrvInitializeHid(Event* out_event); + +/** + * @brief OpenHidConnection + * @note This is used by btm-sysmodule. + * @param[in] addr \ref BtdrvAddress + */ +Result btdrvOpenHidConnection(BtdrvAddress addr); + +/** + * @brief CloseHidConnection + * @note This is used by btm-sysmodule. + * @param[in] addr \ref BtdrvAddress + */ +Result btdrvCloseHidConnection(BtdrvAddress addr); + /** * @brief This sends a HID DATA transaction packet with report-type Output. * @param[in] addr \ref BtdrvAddress @@ -349,6 +303,27 @@ Result btdrvGetHidReport(BtdrvAddress addr, u8 report_id, BtdrvBluetoothHhReport */ Result btdrvTriggerConnection(BtdrvAddress addr, u16 unk); +/** + * @brief AddPairedDeviceInfo + * @note This is used by btm-sysmodule. + * @param[in] settings \ref SetSysBluetoothDevicesSettings + */ +Result btdrvAddPairedDeviceInfo(const SetSysBluetoothDevicesSettings *settings); + +/** + * @brief GetPairedDeviceInfo + * @note This is used by btm-sysmodule. + * @param[in] addr \ref BtdrvAddress + * @param[out] settings \ref SetSysBluetoothDevicesSettings + */ +Result btdrvGetPairedDeviceInfo(BtdrvAddress addr, SetSysBluetoothDevicesSettings *settings); + +/** + * @brief FinalizeHid + * @note This is not used by btm-sysmodule, this should not be used by other processes. + */ +Result btdrvFinalizeHid(void); + /** * @brief GetHidEventInfo * @note This is used by btm-sysmodule. @@ -358,6 +333,73 @@ Result btdrvTriggerConnection(BtdrvAddress addr, u16 unk); */ Result btdrvGetHidEventInfo(void* buffer, size_t size, BtdrvHidEventType *type); +/** + * @brief SetTsi + * @note This is used by btm-sysmodule. + * @param[in] addr \ref BtdrvAddress + * @param[in] unk Unknown + */ +Result btdrvSetTsi(BtdrvAddress addr, u8 unk); + +/** + * @brief EnableBurstMode + * @note This is used by btm-sysmodule. + * @param[in] addr \ref BtdrvAddress + * @param[in] flag Flag + */ +Result btdrvEnableBurstMode(BtdrvAddress addr, bool flag); + +/** + * @brief SetZeroRetransmission + * @note This is used by btm-sysmodule. + * @param[in] addr \ref BtdrvAddress + * @param[in] buf Input buffer containing an array of u8s. + * @param[in] count Total u8s in the input buffer. This can be 0, the max is 5. + */ +Result btdrvSetZeroRetransmission(BtdrvAddress addr, u8 *buf, u8 count); + +/** + * @brief EnableMcMode + * @note This is used by btm-sysmodule. + * @param[in] flag Flag + */ +Result btdrvEnableMcMode(bool flag); + +/** + * @brief EnableLlrScan + * @note This is used by btm-sysmodule. + */ +Result btdrvEnableLlrScan(void); + +/** + * @brief DisableLlrScan + * @note This is used by btm-sysmodule. + */ +Result btdrvDisableLlrScan(void); + +/** + * @brief EnableRadio + * @note This is used by btm-sysmodule. + * @param[in] flag Flag + */ +Result btdrvEnableRadio(bool flag); + +/** + * @brief SetVisibility + * @note This is used by btm-sysmodule. + * @param[in] flag0 Unknown flag. + * @param[in] flag1 Unknown flag. + */ +Result btdrvSetVisibility(bool flag0, bool flag1); + +/** + * @brief EnableTbfcScan + * @note Only available on [4.0.0+]. + * @note This is used by btm-sysmodule. + * @param[in] flag Flag + */ +Result btdrvEnableTbfcScan(bool flag); + /** * @brief RegisterHidReportEvent * @note This also does sharedmem init/handling if needed, on [7.0.0+]. @@ -386,6 +428,13 @@ void* btdrvGetHidReportEventInfoSharedmemAddr(void); */ Result btdrvGetLatestPlr(BtdrvPlrList *out); +/** + * @brief GetPendingConnections + * @note This is used by btm-sysmodule. + * @note Only available on [3.0.0+]. + */ +Result btdrvGetPendingConnections(void); + /** * @brief GetChannelMap * @note Only available on [3.0.0+]. @@ -421,6 +470,35 @@ Result btdrvEnableAfhSetting(bool flag); */ Result btdrvIsAfhSettingEnabled(bool *out); +/** + * @brief InitializeBle + * @note Only available on [5.0.0+]. + * @note This is used by btm-sysmodule. + * @note The Event must be closed by the user once finished with it. + * @param[out] out_event Output Event with autoclear=true. + */ +Result btdrvInitializeBle(Event* out_event); + +/** + * @brief EnableBle + * @note Only available on [5.0.0+]. + * @note This is used by btm-sysmodule. + */ +Result btdrvEnableBle(void); + +/** + * @brief DisableBle + * @note Only available on [5.0.0+]. + * @note This is used by btm-sysmodule. + */ +Result btdrvDisableBle(void); + +/** + * @brief FinalizeBle + * @note Only available on [5.0.0+]. + */ +Result btdrvFinalizeBle(void); + /** * @brief SetBleVisibility * @note Only available on [5.0.0+]. @@ -429,6 +507,36 @@ Result btdrvIsAfhSettingEnabled(bool *out); */ Result btdrvSetBleVisibility(bool flag0, bool flag1); +/** + * @brief SetLeConnectionParameter + * @note Only available on [5.0.0-8.1.1]. This is the older version of \ref btdrvSetBleConnectionParameter. + * @param[in] param \ref BtdrvLeConnectionParams + */ +Result btdrvSetLeConnectionParameter(const BtdrvLeConnectionParams *param); + +/** + * @brief SetBleConnectionParameter + * @note Only available on [9.0.0+]. This is the newer version of \ref btdrvSetLeConnectionParameter. + * @param[in] addr \ref BtdrvAddress + * @param[in] param \ref BtdrvBleConnectionParameter + * @param[in] flag Flag + */ +Result btdrvSetBleConnectionParameter(BtdrvAddress addr, const BtdrvBleConnectionParameter *param, bool flag); + +/** + * @brief SetLeDefaultConnectionParameter + * @note Only available on [5.0.0-8.1.1]. This is the older version of \ref btdrvSetBleDefaultConnectionParameter. + * @param[in] param \ref BtdrvLeConnectionParams + */ +Result btdrvSetLeDefaultConnectionParameter(const BtdrvLeConnectionParams *param); + +/** + * @brief SetBleDefaultConnectionParameter + * @note Only available on [9.0.0+]. This is the newer version of \ref btdrvSetLeDefaultConnectionParameter. + * @param[in] param \ref BtdrvBleConnectionParameter + */ +Result btdrvSetBleDefaultConnectionParameter(const BtdrvBleConnectionParameter *param); + /** * @brief SetBleAdvertiseData * @note Only available on [5.0.0+]. @@ -445,6 +553,58 @@ Result btdrvSetBleAdvertiseData(const BtdrvBleAdvertisePacketData *data); */ Result btdrvSetBleAdvertiseParameter(BtdrvAddress addr, u16 unk0, u16 unk1); +/** + * @brief StartBleScan + * @note Only available on [5.0.0+]. + * @note This is used by btm-sysmodule. + */ +Result btdrvStartBleScan(void); + +/** + * @brief StopBleScan + * @note Only available on [5.0.0+]. + * @note This is used by btm-sysmodule. + */ +Result btdrvStopBleScan(void); + +/** + * @brief AddBleScanFilterCondition + * @note Only available on [5.0.0+]. + * @note This is used by btm-sysmodule. + * @param[in] filter \ref BtdrvBleAdvertiseFilter + */ +Result btdrvAddBleScanFilterCondition(const BtdrvBleAdvertiseFilter *filter); + +/** + * @brief DeleteBleScanFilterCondition + * @note Only available on [5.0.0+]. + * @note This is used by btm-sysmodule. + * @param[in] filter \ref BtdrvBleAdvertiseFilter + */ +Result btdrvDeleteBleScanFilterCondition(const BtdrvBleAdvertiseFilter *filter); + +/** + * @brief DeleteBleScanFilter + * @note Only available on [5.0.0+]. + * @param[in] unk Unknown + */ +Result btdrvDeleteBleScanFilter(u8 unk); + +/** + * @brief ClearBleScanFilters + * @note Only available on [5.0.0+]. + * @note This is used by btm-sysmodule. + */ +Result btdrvClearBleScanFilters(void); + +/** + * @brief EnableBleScanFilter + * @note Only available on [5.0.0+]. + * @note This is used by btm-sysmodule. + * @param[in] flag Flag + */ +Result btdrvEnableBleScanFilter(bool flag); + /** * @brief RegisterGattClient * @note Only available on [5.0.0+]. @@ -466,6 +626,35 @@ Result btdrvUnregisterGattClient(u8 unk); */ Result btdrvUnregisterAllGattClients(void); +/** + * @brief ConnectGattServer + * @note Only available on [5.0.0+]. + * @note This is used by btm-sysmodule. + * @param[in] unk Unknown + * @param[in] addr \ref BtdrvAddress + * @param[in] flag Flag + * @param[in] AppletResourceUserId AppletResourceUserId + */ +Result btdrvConnectGattServer(u8 unk, BtdrvAddress addr, bool flag, u64 AppletResourceUserId); + +/** + * @brief CancelConnectGattServer + * @note Only available on [5.1.0+]. + * @note This is used by btm-sysmodule. + * @param[in] unk Unknown + * @param[in] addr \ref BtdrvAddress + * @param[in] flag Flag + */ +Result btdrvCancelConnectGattServer(u8 unk, BtdrvAddress addr, bool flag); + +/** + * @brief DisconnectGattServer + * @note Only available on [5.0.0+]. + * @note This is used by btm-sysmodule. + * @param[in] unk Unknown + */ +Result btdrvDisconnectGattServer(u32 unk); + /** * @brief GetGattAttribute * @note Only available on [5.0.0+]. @@ -482,6 +671,15 @@ Result btdrvGetGattAttribute(BtdrvAddress addr, u32 unk); */ Result btdrvGetGattService(u32 unk, const BtdrvGattAttributeUuid *uuid); +/** + * @brief ConfigureAttMtu + * @note Only available on [5.0.0+]. + * @note This is used by btm-sysmodule. + * @param[in] unk Unknown + * @param[in] mtu MTU + */ +Result btdrvConfigureAttMtu(u32 unk, u16 mtu); + /** * @brief RegisterGattServer * @note Only available on [5.0.0+]. @@ -748,6 +946,15 @@ Result btdrvGetLeHidEventInfo(void* buffer, size_t size, u32 *type); */ Result btdrvRegisterBleHidEvent(Event* out_event); +/** + * @brief SetBleScanParameter + * @note Only available on [5.1.0+]. + * @note This is used by btm-sysmodule. + * @param[in] unk0 Unknown + * @param[in] unk1 Unknown + */ +Result btdrvSetBleScanParameter(u16 unk0, u16 unk1); + /** * @brief MoveToSecondaryPiconet * @note Only available on [10.0.0+]. diff --git a/nx/include/switch/services/btdrv_types.h b/nx/include/switch/services/btdrv_types.h new file mode 100644 index 00000000..82b09a64 --- /dev/null +++ b/nx/include/switch/services/btdrv_types.h @@ -0,0 +1,158 @@ +/** + * @file btdrv_types.h + * @brief Bluetooth driver (btdrv) service types (see btdrv.h for the rest). + * @author yellows8 + * @copyright libnx Authors + */ +#pragma once +#include "../types.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; + +/// BluetoothHhReportType +/// Bit0-1 directly control the HID bluetooth transaction report-type value. +/// Bit2-3: these directly control the Parameter Reserved field for SetReport, for GetReport these control the Parameter Reserved and Size bits. +typedef enum { + BtdrvBluetoothHhReportType_Other = 0, ///< Other + BtdrvBluetoothHhReportType_Input = 1, ///< Input + BtdrvBluetoothHhReportType_Output = 2, ///< Output + BtdrvBluetoothHhReportType_Feature = 3, ///< Feature +} BtdrvBluetoothHhReportType; + +/// HidEventType +typedef enum { + BtdrvHidEventType_Unknown0 = 0, ///< Unknown. Only used with \ref btdrvGetHidEventInfo. + BtdrvHidEventType_Unknown4 = 4, ///< Unknown. + BtdrvHidEventType_Unknown7 = 7, ///< Unknown. Only used with \ref btdrvGetHidEventInfo. + BtdrvHidEventType_Unknown8 = 8, ///< Unknown. + BtdrvHidEventType_Unknown9 = 9, ///< Unknown. +} BtdrvHidEventType; + +/// This determines the u16 data to write into the CircularBuffer (name "BLE CORE"). +typedef enum { + BtdrvFatalReason_Unknown1 = 1, ///< u16 data = 0x850. + BtdrvFatalReason_Unknown2 = 2, ///< u16 data = 0x851. + BtdrvFatalReason_Unknown3 = 3, ///< Reason values which aren't 1/2: u16 data = 0x852. +} BtdrvFatalReason; + +/// Address +typedef struct { + u8 address[0x6]; ///< Address +} BtdrvAddress; + +/// AdapterProperty +typedef struct { + 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 +typedef struct { + char code[0x10]; ///< PinCode +} BtdrvBluetoothPinCode; + +/// HidData, for pre-9.0.0. +typedef struct { + u16 size; ///< Size of data. + u8 data[0x280]; ///< Data +} BtdrvHidData; + +/// HidReport, for [9.0.0+]. +typedef struct { + u16 size; ///< Size of data. + u8 data[0x2BC]; ///< Data +} BtdrvHidReport; + +/// PlrStatistics +typedef struct { + u8 unk_x0[0x84]; ///< Unknown +} BtdrvPlrStatistics; + +/// PlrList +typedef struct { + u8 unk_x0[0xA4]; ///< Unknown +} BtdrvPlrList; + +/// ChannelMapList +typedef struct { + u8 unk_x0[0x88]; ///< Unknown +} BtdrvChannelMapList; + +/// LeConnectionParams +typedef struct { + u8 unk_x0[0x14]; ///< Unknown +} BtdrvLeConnectionParams; + +/// BleConnectionParameter +typedef struct { + u8 unk_x0[0xC]; ///< Unknown +} BtdrvBleConnectionParameter; + +/// BtdrvBleAdvertisePacketDataEntry +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 +} BtdrvBleAdvertisePacketData; + +/// BleAdvertiseFilter +typedef struct { + u8 unk_x0[0x3E]; ///< Unknown +} BtdrvBleAdvertiseFilter; + +/// BleAdvertisePacketParameter +typedef struct { + u8 data[0x8]; ///< Unknown +} BtdrvBleAdvertisePacketParameter; + +/// BleScanResult +typedef struct { + u8 unk_x0[0x148]; ///< Unknown +} BtdrvBleScanResult; + +/// BleConnectionInfo +typedef struct { + u32 id; ///< Id, 0xFFFFFFFF ([5.0.0-5.0.2] 0xFFFF) is invalid. + BtdrvAddress addr; ///< \ref BtdrvAddress + 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 unk_x0[0x18]; ///< Unknown +} BtdrvGattId; + diff --git a/nx/include/switch/services/btm.h b/nx/include/switch/services/btm.h index f8fc4757..848c779d 100644 --- a/nx/include/switch/services/btm.h +++ b/nx/include/switch/services/btm.h @@ -6,7 +6,7 @@ #pragma once #include "../types.h" #include "../kernel/event.h" -#include "../services/btdrv.h" +#include "../services/btdrv_types.h" #include "../sf/service.h" /// HostDeviceProperty diff --git a/nx/include/switch/services/btmu.h b/nx/include/switch/services/btmu.h index 5b5321c3..36594058 100644 --- a/nx/include/switch/services/btmu.h +++ b/nx/include/switch/services/btmu.h @@ -7,7 +7,7 @@ #pragma once #include "../types.h" #include "../kernel/event.h" -#include "../services/btdrv.h" +#include "../services/btdrv_types.h" #include "../services/btm.h" #include "../sf/service.h" diff --git a/nx/source/services/btdrv.c b/nx/source/services/btdrv.c index 3a31e060..525c3001 100644 --- a/nx/source/services/btdrv.c +++ b/nx/source/services/btdrv.c @@ -54,6 +54,15 @@ static Result _btdrvCmdInBoolNoOut(bool inval, u32 cmd_id) { return _btdrvCmdInU8NoOut(inval!=0, cmd_id); } +static Result _btdrvCmdTwoInBoolsNoOut(bool flag0, bool flag1, u32 cmd_id) { + const struct { + u8 flag; + u8 flag2; + } in = { flag0!=0, flag1!=0 }; + + return serviceDispatchIn(&g_btdrvSrv, cmd_id, in); +} + static Result _btdrvCmdInU32NoOut(u32 inval, u32 cmd_id) { return serviceDispatchIn(&g_btdrvSrv, cmd_id, inval); } @@ -62,6 +71,19 @@ static Result _btdrvCmdInAddrNoOut(BtdrvAddress addr, u32 cmd_id) { return serviceDispatchIn(&g_btdrvSrv, cmd_id, addr); } +static Result _btmCmdInAddrU8NoOut(BtdrvAddress addr, u8 inval, u32 cmd_id) { + const struct { + BtdrvAddress addr; + u8 inval; + } in = { addr, inval }; + + return serviceDispatchIn(&g_btdrvSrv, cmd_id, in); +} + +static Result _btdrvCmdInLeConnectionParameterNoOut(const BtdrvLeConnectionParams *param, u32 cmd_id) { + return serviceDispatchIn(&g_btdrvSrv, cmd_id, *param); +} + static Result _btdrvCmdInUuidNoOut(const BtdrvGattAttributeUuid *uuid, u32 cmd_id) { return serviceDispatchIn(&g_btdrvSrv, cmd_id, *uuid); } @@ -107,6 +129,34 @@ static Result _btdrvCmdOutU32OutBuf(void* buffer, size_t size, u32 *out, u32 cmd ); } +static Result _btdrvGattNotification(bool flag, u32 unk, const BtdrvGattId *id0, const BtdrvGattId *id1, u32 cmd_id) { + const struct { + u8 flag; + u8 pad[3]; + u32 unk; + BtdrvGattId id0; + BtdrvGattId id1; + } in = { flag!=0, {0}, unk, *id0, *id1 }; + + return serviceDispatchIn(&g_btdrvSrv, cmd_id, in); +} + +Result btdrvInitializeBluetooth(Event* out_event) { + return _btdrvCmdGetEvent(out_event, true, 1); +} + +Result btdrvEnableBluetooth(void) { + return _btdrvCmdNoIO(2); +} + +Result btdrvDisableBluetooth(void) { + return _btdrvCmdNoIO(3); +} + +Result btdrvFinalizeBluetooth(void) { + return _btdrvCmdNoIO(4); +} + Result btdrvGetAdapterProperties(BtdrvAdapterProperty *property) { return serviceDispatch(&g_btdrvSrv, 5, .buffer_attrs = { SfBufferAttr_HipcPointer | SfBufferAttr_Out | SfBufferAttr_FixedSize }, @@ -130,10 +180,88 @@ Result btdrvSetAdapterProperty(BtdrvBluetoothPropertyType type, const void* buff ); } +Result btdrvStartInquiry(void) { + return _btdrvCmdNoIO(8); +} + +Result btdrvStopInquiry(void) { + return _btdrvCmdNoIO(9); +} + +Result btdrvCreateBond(BtdrvAddress addr, u32 type) { + if (hosversionBefore(9,0,0)) { + return serviceDispatchIn(&g_btdrvSrv, 10, addr, + .buffer_attrs = { SfBufferAttr_HipcPointer | SfBufferAttr_In | SfBufferAttr_FixedSize }, + .buffers = { { &type, sizeof(type) } }, + ); + } + + const struct { + BtdrvAddress addr; + u8 pad[2]; + u32 type; + } in = { addr, {0}, type }; + + return serviceDispatchIn(&g_btdrvSrv, 10, in); +} + +Result btdrvRemoveBond(BtdrvAddress addr) { + return _btdrvCmdInAddrNoOut(addr, 11); +} + +Result btdrvCancelBond(BtdrvAddress addr) { + return _btdrvCmdInAddrNoOut(addr, 12); +} + +Result btdrvRespondToPinRequest(BtdrvAddress addr, bool flag, const BtdrvBluetoothPinCode *pin_code, u8 unk) { + const struct { + BtdrvAddress addr; + u8 flag; + u8 unk; + BtdrvBluetoothPinCode pin_code; + } in = { addr, flag!=0, unk, *pin_code }; + + return serviceDispatchIn(&g_btdrvSrv, 13, in); +} + +Result btdrvRespondToSspRequest(BtdrvAddress addr, u8 variant, bool flag, u32 unk) { + const struct { + BtdrvAddress addr; + u8 variant; + u8 flag; + u32 unk; + } in = { addr, variant, flag!=0, unk }; + + return serviceDispatchIn(&g_btdrvSrv, 14, in); +} + Result btdrvGetEventInfo(void* buffer, size_t size, u32 *type) { return _btdrvCmdOutU32OutBuf(buffer, size, type, 15); } +Result btdrvInitializeHid(Event* out_event) { + Handle tmp_handle = INVALID_HANDLE; + Result rc = 0; + u16 tmp=0x1; + + if (R_SUCCEEDED(rc)) { + rc = serviceDispatchIn(&g_btdrvSrv, 16, tmp, + .out_handle_attrs = { SfOutHandleAttr_HipcCopy }, + .out_handles = &tmp_handle, + ); + } + if (R_SUCCEEDED(rc)) eventLoadRemote(out_event, tmp_handle, true); + return rc; +} + +Result btdrvOpenHidConnection(BtdrvAddress addr) { + return _btdrvCmdInAddrNoOut(addr, 17); +} + +Result btdrvCloseHidConnection(BtdrvAddress addr) { + return _btdrvCmdInAddrNoOut(addr, 18); +} + Result btdrvWriteHidData(BtdrvAddress addr, BtdrvHidReport *buffer) { size_t size = hosversionBefore(9,0,0) ? sizeof(BtdrvHidData) : sizeof(BtdrvHidReport); return serviceDispatchIn(&g_btdrvSrv, 19, addr, @@ -154,8 +282,9 @@ Result btdrvSetHidReport(BtdrvAddress addr, BtdrvBluetoothHhReportType type, Btd const struct { BtdrvAddress addr; + u8 pad[2]; u32 type; - } in = { addr, type }; + } in = { addr, {0}, type }; return serviceDispatchIn(&g_btdrvSrv, 21, in, .buffer_attrs = { SfBufferAttr_HipcPointer | SfBufferAttr_In | SfBufferAttr_FixedSize }, @@ -185,6 +314,21 @@ Result btdrvTriggerConnection(BtdrvAddress addr, u16 unk) { return serviceDispatchIn(&g_btdrvSrv, 23, in); } +Result btdrvAddPairedDeviceInfo(const SetSysBluetoothDevicesSettings *settings) { + return _btdrvCmdInBufPtrFixed(settings, sizeof(*settings), 24); +} + +Result btdrvGetPairedDeviceInfo(BtdrvAddress addr, SetSysBluetoothDevicesSettings *settings) { + return serviceDispatchIn(&g_btdrvSrv, 25, addr, + .buffer_attrs = { SfBufferAttr_HipcPointer | SfBufferAttr_Out | SfBufferAttr_FixedSize }, + .buffers = { { settings, sizeof(*settings) } }, + ); +} + +Result btdrvFinalizeHid(void) { + return _btdrvCmdNoIO(26); +} + Result btdrvGetHidEventInfo(void* buffer, size_t size, BtdrvHidEventType *type) { u32 tmp=0; Result rc = _btdrvCmdOutU32OutBuf(buffer, size, &tmp, 27); @@ -192,6 +336,48 @@ Result btdrvGetHidEventInfo(void* buffer, size_t size, BtdrvHidEventType *type) return rc; } +Result btdrvSetTsi(BtdrvAddress addr, u8 unk) { + return _btmCmdInAddrU8NoOut(addr, unk, 28); +} + +Result btdrvEnableBurstMode(BtdrvAddress addr, bool flag) { + return _btmCmdInAddrU8NoOut(addr, flag!=0, 29); +} + +Result btdrvSetZeroRetransmission(BtdrvAddress addr, u8 *buf, u8 count) { + return serviceDispatchIn(&g_btdrvSrv, 30, addr, + .buffer_attrs = { SfBufferAttr_HipcPointer | SfBufferAttr_In }, + .buffers = { { buf, count } }, + ); +} + +Result btdrvEnableMcMode(bool flag) { + return _btdrvCmdInBoolNoOut(flag, 31); +} + +Result btdrvEnableLlrScan(void) { + return _btdrvCmdNoIO(32); +} + +Result btdrvDisableLlrScan(void) { + return _btdrvCmdNoIO(33); +} + +Result btdrvEnableRadio(bool flag) { + return _btdrvCmdInBoolNoOut(flag, 34); +} + +Result btdrvSetVisibility(bool flag0, bool flag1) { + return _btdrvCmdTwoInBoolsNoOut(flag0, flag1, 35); +} + +Result btdrvEnableTbfcScan(bool flag) { + if (hosversionBefore(4,0,0)) + return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); + + return _btdrvCmdInBoolNoOut(flag, 36); +} + Result btdrvRegisterHidReportEvent(Event* out_event) { Result rc=0; Handle tmphandle=0; @@ -279,6 +465,14 @@ Result btdrvGetLatestPlr(BtdrvPlrList *out) { return _btdrvCmdOutBufAliasFixed(out, size, cmd_id); } +Result btdrvGetPendingConnections(void) { + if (hosversionBefore(3,0,0)) + return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); + u32 cmd_id = hosversionBefore(4,0,0) ? 39 : 40; + + return _btdrvCmdNoIO(cmd_id); +} + Result btdrvGetChannelMap(BtdrvChannelMapList *out) { if (hosversionBefore(3,0,0)) return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); @@ -319,16 +513,74 @@ Result btdrvIsAfhSettingEnabled(bool *out) { return _btdrvCmdNoInOutBool(out, cmd_id); } +Result btdrvInitializeBle(Event* out_event) { + if (hosversionBefore(5,0,0)) + return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); + + return _btdrvCmdGetEvent(out_event, true, 46); +} + +Result btdrvEnableBle(void) { + if (hosversionBefore(5,0,0)) + return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); + + return _btdrvCmdNoIO(47); +} + +Result btdrvDisableBle(void) { + if (hosversionBefore(5,0,0)) + return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); + + return _btdrvCmdNoIO(48); +} + +Result btdrvFinalizeBle(void) { + if (hosversionBefore(5,0,0)) + return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); + + return _btdrvCmdNoIO(49); +} + Result btdrvSetBleVisibility(bool flag0, bool flag1) { if (hosversionBefore(5,0,0)) return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); - const struct { - u8 flag; - u8 flag2; - } in = { flag0!=0, flag1!=0 }; + return _btdrvCmdTwoInBoolsNoOut(flag0, flag1, 50); +} - return serviceDispatchIn(&g_btdrvSrv, 50, in); +Result btdrvSetLeConnectionParameter(const BtdrvLeConnectionParams *param) { + if (hosversionBefore(5,0,0) || hosversionAtLeast(9,0,0)) + return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); + + return _btdrvCmdInLeConnectionParameterNoOut(param, 51); +} + +Result btdrvSetBleConnectionParameter(BtdrvAddress addr, const BtdrvBleConnectionParameter *param, bool flag) { + if (hosversionBefore(9,0,0)) + return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); + + const struct { + BtdrvAddress addr; + u8 flag; + u8 pad; + BtdrvBleConnectionParameter param; + } in = { addr, flag!=0, 0, *param }; + + return serviceDispatchIn(&g_btdrvSrv, 51, in); +} + +Result btdrvSetLeDefaultConnectionParameter(const BtdrvLeConnectionParams *param) { + if (hosversionBefore(5,0,0) || hosversionAtLeast(9,0,0)) + return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); + + return _btdrvCmdInLeConnectionParameterNoOut(param, 52); +} + +Result btdrvSetBleDefaultConnectionParameter(const BtdrvBleConnectionParameter *param) { + if (hosversionBefore(9,0,0)) + return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); + + return serviceDispatchIn(&g_btdrvSrv, 52, *param); } Result btdrvSetBleAdvertiseData(const BtdrvBleAdvertisePacketData *data) { @@ -351,6 +603,55 @@ Result btdrvSetBleAdvertiseParameter(BtdrvAddress addr, u16 unk0, u16 unk1) { return serviceDispatchIn(&g_btdrvSrv, 54, in); } +Result btdrvStartBleScan(void) { + if (hosversionBefore(5,0,0)) + return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); + + return _btdrvCmdNoIO(55); +} + +Result btdrvStopBleScan(void) { + if (hosversionBefore(5,0,0)) + return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); + + return _btdrvCmdNoIO(56); +} + +Result btdrvAddBleScanFilterCondition(const BtdrvBleAdvertiseFilter *filter) { + if (hosversionBefore(5,0,0)) + return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); + + return _btdrvCmdInBufPtrFixed(filter, sizeof(*filter), 57); +} + +Result btdrvDeleteBleScanFilterCondition(const BtdrvBleAdvertiseFilter *filter) { + if (hosversionBefore(5,0,0)) + return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); + + return _btdrvCmdInBufPtrFixed(filter, sizeof(*filter), 58); +} + +Result btdrvDeleteBleScanFilter(u8 unk) { + if (hosversionBefore(5,0,0)) + return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); + + return _btdrvCmdInU8NoOut(unk, 59); +} + +Result btdrvClearBleScanFilters(void) { + if (hosversionBefore(5,0,0)) + return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); + + return _btdrvCmdNoIO(60); +} + +Result btdrvEnableBleScanFilter(bool flag) { + if (hosversionBefore(5,0,0)) + return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); + + return _btdrvCmdInBoolNoOut(flag, 61); +} + Result btdrvRegisterGattClient(const BtdrvGattAttributeUuid *uuid) { if (hosversionBefore(5,0,0)) return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); @@ -372,10 +673,45 @@ Result btdrvUnregisterAllGattClients(void) { return _btdrvCmdNoIO(64); } +Result btdrvConnectGattServer(u8 unk, BtdrvAddress addr, bool flag, u64 AppletResourceUserId) { + if (hosversionBefore(5,0,0)) + return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); + + const struct { + u8 unk; + BtdrvAddress addr; + u8 flag; + u64 AppletResourceUserId; + } in = { unk, addr, flag!=0, AppletResourceUserId }; + + return serviceDispatchIn(&g_btdrvSrv, 65, in); +} + +Result btdrvCancelConnectGattServer(u8 unk, BtdrvAddress addr, bool flag) { + if (hosversionBefore(5,1,0)) + return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); + + const struct { + u8 unk; + BtdrvAddress addr; + u8 flag; + } in = { unk, addr, flag!=0 }; + + return serviceDispatchIn(&g_btdrvSrv, 66, in); +} + +Result btdrvDisconnectGattServer(u32 unk) { + if (hosversionBefore(5,0,0)) + return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); + u32 cmd_id = hosversionBefore(5,1,0) ? 66 : 67; + + return _btdrvCmdInU32NoOut(unk, cmd_id); +} + Result btdrvGetGattAttribute(BtdrvAddress addr, u32 unk) { if (hosversionBefore(5,0,0)) return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); - u32 cmd_id = hosversionBefore(6,0,0) ? 67 : 68; + u32 cmd_id = hosversionBefore(5,1,0) ? 67 : 68; if (hosversionBefore(9,0,0)) { const struct { @@ -385,13 +721,13 @@ Result btdrvGetGattAttribute(BtdrvAddress addr, u32 unk) { return serviceDispatchIn(&g_btdrvSrv, cmd_id, in); } - return serviceDispatchIn(&g_btdrvSrv, cmd_id, unk); + return _btdrvCmdInU32NoOut(unk, cmd_id); } Result btdrvGetGattService(u32 unk, const BtdrvGattAttributeUuid *uuid) { if (hosversionBefore(5,0,0)) return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); - u32 cmd_id = hosversionBefore(6,0,0) ? 68 : 69; + u32 cmd_id = hosversionBefore(5,1,0) ? 68 : 69; const struct { u32 unk0; @@ -401,10 +737,24 @@ Result btdrvGetGattService(u32 unk, const BtdrvGattAttributeUuid *uuid) { return serviceDispatchIn(&g_btdrvSrv, cmd_id, in); } +Result btdrvConfigureAttMtu(u32 unk, u16 mtu) { + if (hosversionBefore(5,0,0)) + return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); + u32 cmd_id = hosversionBefore(5,1,0) ? 69 : 70; + + const struct { + u16 mtu; + u16 pad; + u32 unk; + } in = { mtu, 0, unk }; + + return serviceDispatchIn(&g_btdrvSrv, cmd_id, in); +} + Result btdrvRegisterGattServer(const BtdrvGattAttributeUuid *uuid) { if (hosversionBefore(5,0,0)) return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); - u32 cmd_id = hosversionBefore(6,0,0) ? 71 : 70; + u32 cmd_id = hosversionBefore(5,1,0) ? 70 : 71; return _btdrvCmdInUuidNoOut(uuid, cmd_id); } @@ -412,7 +762,7 @@ Result btdrvRegisterGattServer(const BtdrvGattAttributeUuid *uuid) { Result btdrvUnregisterGattServer(u8 unk) { if (hosversionBefore(5,0,0)) return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); - u32 cmd_id = hosversionBefore(6,0,0) ? 71 : 72; + u32 cmd_id = hosversionBefore(5,1,0) ? 71 : 72; return _btdrvCmdInU8NoOut(unk, cmd_id); } @@ -420,7 +770,7 @@ Result btdrvUnregisterGattServer(u8 unk) { Result btdrvConnectGattClient(u8 unk, BtdrvAddress addr, bool flag) { if (hosversionBefore(5,0,0)) return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); - u32 cmd_id = hosversionBefore(6,0,0) ? 72 : 73; + u32 cmd_id = hosversionBefore(5,1,0) ? 72 : 73; const struct { u8 unk; @@ -434,7 +784,7 @@ Result btdrvConnectGattClient(u8 unk, BtdrvAddress addr, bool flag) { Result btdrvDisconnectGattClient(u8 unk, BtdrvAddress addr) { if (hosversionBefore(5,0,0)) return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); - u32 cmd_id = hosversionBefore(6,0,0) ? 73 : 74; + u32 cmd_id = hosversionBefore(5,1,0) ? 73 : 74; if (hosversionBefore(9,0,0)) { const struct { @@ -465,7 +815,7 @@ Result btdrvAddGattService(u8 unk0, u8 unk1, bool flag, const BtdrvGattAttribute Result btdrvEnableGattService(u8 unk, const BtdrvGattAttributeUuid *uuid) { if (hosversionBefore(5,0,0)) return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); - u32 cmd_id = hosversionBefore(6,0,0) ? 74 : 76; + u32 cmd_id = hosversionBefore(5,1,0) ? 74 : 76; const struct { u8 unk; @@ -494,7 +844,7 @@ Result btdrvAddGattCharacteristic(u8 unk0, u8 unk1, u16 unk2, const BtdrvGattAtt Result btdrvAddGattDescriptor(u8 unk0, u16 unk1, const BtdrvGattAttributeUuid *uuid0, const BtdrvGattAttributeUuid *uuid1) { if (hosversionBefore(5,0,0)) return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); - u32 cmd_id = hosversionBefore(6,0,0) ? 76 : 78; + u32 cmd_id = hosversionBefore(5,1,0) ? 76 : 78; const struct { u8 unk0; @@ -510,7 +860,7 @@ Result btdrvAddGattDescriptor(u8 unk0, u16 unk1, const BtdrvGattAttributeUuid *u Result btdrvGetBleManagedEventInfo(void* buffer, size_t size, u32 *type) { if (hosversionBefore(5,0,0)) return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); - u32 cmd_id = hosversionBefore(6,0,0) ? 78 : 79; + u32 cmd_id = hosversionBefore(5,1,0) ? 78 : 79; return _btdrvCmdOutU32OutBuf(buffer, size, type, cmd_id); } @@ -518,7 +868,7 @@ Result btdrvGetBleManagedEventInfo(void* buffer, size_t size, u32 *type) { Result btdrvGetGattFirstCharacteristic(bool flag, u32 unk, const BtdrvGattId *id, const BtdrvGattAttributeUuid *uuid, u8 *unk_out, BtdrvGattId *id_out) { if (hosversionBefore(5,0,0)) return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); - u32 cmd_id = hosversionBefore(6,0,0) ? 79 : 80; + u32 cmd_id = hosversionBefore(5,1,0) ? 79 : 80; const struct { u8 flag; @@ -545,7 +895,7 @@ Result btdrvGetGattFirstCharacteristic(bool flag, u32 unk, const BtdrvGattId *id Result btdrvGetGattNextCharacteristic(bool flag, u32 unk, const BtdrvGattId *id0, const BtdrvGattId *id1, const BtdrvGattAttributeUuid *uuid, u8 *unk_out, BtdrvGattId *id_out) { if (hosversionBefore(5,0,0)) return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); - u32 cmd_id = hosversionBefore(6,0,0) ? 80 : 81; + u32 cmd_id = hosversionBefore(5,1,0) ? 80 : 81; const struct { u8 flag; @@ -573,7 +923,7 @@ Result btdrvGetGattNextCharacteristic(bool flag, u32 unk, const BtdrvGattId *id0 Result btdrvGetGattFirstDescriptor(bool flag, u32 unk, const BtdrvGattId *id0, const BtdrvGattId *id1, const BtdrvGattAttributeUuid *uuid, BtdrvGattId *id_out) { if (hosversionBefore(5,0,0)) return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); - u32 cmd_id = hosversionBefore(6,0,0) ? 81 : 82; + u32 cmd_id = hosversionBefore(5,1,0) ? 81 : 82; const struct { u8 flag; @@ -590,7 +940,7 @@ Result btdrvGetGattFirstDescriptor(bool flag, u32 unk, const BtdrvGattId *id0, c Result btdrvGetGattNextDescriptor(bool flag, u32 unk, const BtdrvGattId *id0, const BtdrvGattId *id1, const BtdrvGattId *id2, const BtdrvGattAttributeUuid *uuid, BtdrvGattId *id_out) { if (hosversionBefore(5,0,0)) return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); - u32 cmd_id = hosversionBefore(6,0,0) ? 82 : 83; + u32 cmd_id = hosversionBefore(5,1,0) ? 82 : 83; const struct { u8 flag; @@ -643,7 +993,7 @@ Result btdrvRegisterGattDataPath(const BtdrvGattAttributeUuid *uuid) { Result btdrvUnregisterGattDataPath(const BtdrvGattAttributeUuid *uuid) { if (hosversionBefore(5,0,0)) return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); - u32 cmd_id = hosversionBefore(6,0,0) ? 83 : 89; + u32 cmd_id = hosversionBefore(5,1,0) ? 83 : 89; return _btdrvCmdInUuidNoOut(uuid, cmd_id); } @@ -651,7 +1001,7 @@ Result btdrvUnregisterGattDataPath(const BtdrvGattAttributeUuid *uuid) { 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); - u32 cmd_id = hosversionBefore(6,0,0) ? 89 : 90; + u32 cmd_id = hosversionBefore(5,1,0) ? 89 : 90; const struct { u8 flag; @@ -668,7 +1018,7 @@ Result btdrvReadGattCharacteristic(bool flag, u8 unk, u32 unk2, const BtdrvGattI Result btdrvReadGattDescriptor(bool flag, u8 unk, u32 unk2, const BtdrvGattId *id0, const BtdrvGattId *id1, const BtdrvGattId *id2) { if (hosversionBefore(5,0,0)) return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); - u32 cmd_id = hosversionBefore(6,0,0) ? 90 : 91; + u32 cmd_id = hosversionBefore(5,1,0) ? 90 : 91; const struct { u8 flag; @@ -686,7 +1036,7 @@ Result btdrvReadGattDescriptor(bool flag, u8 unk, u32 unk2, const BtdrvGattId *i Result btdrvWriteGattCharacteristic(bool flag, u8 unk, bool flag2, u32 unk2, const BtdrvGattId *id0, const BtdrvGattId *id1, const void* buffer, size_t size) { if (hosversionBefore(5,0,0)) return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); - u32 cmd_id = hosversionBefore(6,0,0) ? 91 : 92; + u32 cmd_id = hosversionBefore(5,1,0) ? 91 : 92; const struct { u8 flag; @@ -707,7 +1057,7 @@ Result btdrvWriteGattCharacteristic(bool flag, u8 unk, bool flag2, u32 unk2, con Result btdrvWriteGattDescriptor(bool flag, u8 unk, u32 unk2, const BtdrvGattId *id0, const BtdrvGattId *id1, const BtdrvGattId *id2, const void* buffer, size_t size) { if (hosversionBefore(5,0,0)) return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); - u32 cmd_id = hosversionBefore(6,0,0) ? 92 : 93; + u32 cmd_id = hosversionBefore(5,1,0) ? 92 : 93; const struct { u8 flag; @@ -725,18 +1075,6 @@ Result btdrvWriteGattDescriptor(bool flag, u8 unk, u32 unk2, const BtdrvGattId * ); } -static Result _btdrvGattNotification(bool flag, u32 unk, const BtdrvGattId *id0, const BtdrvGattId *id1, u32 cmd_id) { - const struct { - u8 flag; - u8 pad[3]; - u32 unk; - BtdrvGattId id0; - BtdrvGattId id1; - } in = { flag!=0, {0}, unk, *id0, *id1 }; - - return serviceDispatchIn(&g_btdrvSrv, cmd_id, in); -} - Result btdrvRegisterGattNotification(bool flag, u32 unk, const BtdrvGattId *id0, const BtdrvGattId *id1) { if (hosversionBefore(5,0,0)) return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); @@ -747,7 +1085,7 @@ Result btdrvRegisterGattNotification(bool flag, u32 unk, const BtdrvGattId *id0, Result btdrvUnregisterGattNotification(bool flag, u32 unk, const BtdrvGattId *id0, const BtdrvGattId *id1) { if (hosversionBefore(5,0,0)) return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); - u32 cmd_id = hosversionBefore(6,0,0) ? 93 : 95; + u32 cmd_id = hosversionBefore(5,1,0) ? 93 : 95; return _btdrvGattNotification(flag, unk, id0, id1, cmd_id); } @@ -755,7 +1093,7 @@ Result btdrvUnregisterGattNotification(bool flag, u32 unk, const BtdrvGattId *id Result btdrvGetLeHidEventInfo(void* buffer, size_t size, u32 *type) { if (hosversionBefore(5,0,0)) return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); - u32 cmd_id = hosversionBefore(6,0,0) ? 95 : 96; + u32 cmd_id = hosversionBefore(5,1,0) ? 95 : 96; return _btdrvCmdOutU32OutBuf(buffer, size, type, cmd_id); } @@ -763,11 +1101,23 @@ Result btdrvGetLeHidEventInfo(void* buffer, size_t size, u32 *type) { Result btdrvRegisterBleHidEvent(Event* out_event) { if (hosversionBefore(5,0,0)) return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); - u32 cmd_id = hosversionBefore(6,0,0) ? 96 : 97; + u32 cmd_id = hosversionBefore(5,1,0) ? 96 : 97; return _btdrvCmdGetEvent(out_event, true, cmd_id); } +Result btdrvSetBleScanParameter(u16 unk0, u16 unk1) { + if (hosversionBefore(5,1,0)) + return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); + + const struct { + u16 unk0; + u16 unk1; + } in = { unk0, unk1 }; + + return serviceDispatchIn(&g_btdrvSrv, 98, in); +} + Result btdrvMoveToSecondaryPiconet(BtdrvAddress addr) { if (hosversionBefore(10,0,0)) return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer);