diff --git a/nx/include/switch/services/btdrv.h b/nx/include/switch/services/btdrv.h index bdd59211..62cd188f 100644 --- a/nx/include/switch/services/btdrv.h +++ b/nx/include/switch/services/btdrv.h @@ -25,6 +25,13 @@ typedef enum { 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 @@ -296,6 +303,46 @@ Result btdrvGetHidReportEventInfo(void* buffer, size_t size, BtdrvHidEventType * /// Gets the SharedMemory addr for HidReportEventInfo (\ref BtdrvCircularBuffer), only valid when \ref btdrvRegisterHidReportEvent was previously used, on [7.0.0+]. void* btdrvGetHidReportEventInfoSharedmemAddr(void); +/** + * @brief GetLatestPlr + * @param[out] out Output \ref BtdrvPlrList, on pre-9.0.0 this is \ref BtdrvPlrStatistics. + */ +Result btdrvGetLatestPlr(BtdrvPlrList *out); + +/** + * @brief EnableTxPowerBoostSetting + * @note Only available on [3.0.0+]. + * @param[in] flag Input flag. + */ +Result btdrvEnableTxPowerBoostSetting(bool flag); + +/** + * @brief IsTxPowerBoostSettingEnabled + * @note Only available on [3.0.0+]. + * @param[out] out Output flag. + */ +Result btdrvIsTxPowerBoostSettingEnabled(bool *out); + +/** + * @brief EnableAfhSetting + * @note Only available on [3.0.0+]. + * @param[in] flag Input flag. + */ +Result btdrvEnableAfhSetting(bool flag); + +/** + * @brief IsAfhSettingEnabled + * @param[out] out Output flag. + */ +Result btdrvIsAfhSettingEnabled(bool *out); + +/** + * @brief GetChannelMap + * @note Only available on [3.0.0+]. + * @param[out] out \ref BtdrvChannelMapList + */ +Result btdrvGetChannelMap(BtdrvChannelMapList *out); + /** * @brief ReadGattCharacteristic * @note Only available on [5.0.0+]. @@ -385,6 +432,34 @@ Result btdrvGetLeEventInfo(void* buffer, size_t size, u32 *type); */ Result btdrvRegisterBleHidEvent(Event* out_event); +/** + * @brief MoveToSecondaryPiconet + * @note Only available on [10.0.0+]. + * @param[in] addr \ref BtdrvAddress + */ +Result btdrvMoveToSecondaryPiconet(BtdrvAddress addr); + +/** + * @brief IsManufacturingMode + * @note Only available on [5.0.0+]. + * @param[out] out Output flag. + */ +Result btdrvIsManufacturingMode(bool *out); + +/** + * @brief EmulateBluetoothCrash + * @note Only available on [7.0.0+]. + * @param[in] reason \ref BtdrvFatalReason + */ +Result btdrvEmulateBluetoothCrash(BtdrvFatalReason reason); + +/** + * @brief GetBleChannelMap + * @note Only available on [9.0.0+]. + * @param[out] out \ref BtdrvChannelMapList + */ +Result btdrvGetBleChannelMap(BtdrvChannelMapList *out); + ///@name CircularBuffer ///@{ diff --git a/nx/source/services/btdrv.c b/nx/source/services/btdrv.c index beea9801..6ed0ec20 100644 --- a/nx/source/services/btdrv.c +++ b/nx/source/services/btdrv.c @@ -46,6 +46,33 @@ static Result _btdrvCmdGetHandle(Handle* handle_out, u32 cmd_id) { ); } +static Result _btdrvCmdInU8NoOut(u8 inval, u64 cmd_id) { + return serviceDispatchIn(&g_btdrvSrv, cmd_id, inval); +} + +static Result _btdrvCmdInBoolNoOut(bool inval, u32 cmd_id) { + return _btdrvCmdInU8NoOut(inval!=0, cmd_id); +} + +static Result _btdrvCmdInU32NoOut(u32 inval, u32 cmd_id) { + return serviceDispatchIn(&g_btdrvSrv, cmd_id, inval); +} + +static Result _btdrvCmdInAddrNoOut(BtdrvAddress addr, u32 cmd_id) { + return serviceDispatchIn(&g_btdrvSrv, cmd_id, addr); +} + +static Result _btdrvCmdNoInOutU8(u8 *out, u32 cmd_id) { + return serviceDispatchOut(&g_btdrvSrv, cmd_id, *out); +} + +static Result _btdrvCmdNoInOutBool(bool *out, u32 cmd_id) { + u8 tmp=0; + Result rc = _btdrvCmdNoInOutU8(&tmp, cmd_id); + if (R_SUCCEEDED(rc) && out) *out = tmp & 1; + return rc; +} + static Result _btdrvCmdGetEvent(Event* out_event, bool autoclear, u32 cmd_id) { Handle tmp_handle = INVALID_HANDLE; Result rc = 0; @@ -55,6 +82,13 @@ static Result _btdrvCmdGetEvent(Event* out_event, bool autoclear, u32 cmd_id) { return rc; } +static Result _btdrvCmdOutBufAliasFixed(void* buffer, size_t size, u32 cmd_id) { + return serviceDispatch(&g_btdrvSrv, cmd_id, + .buffer_attrs = { SfBufferAttr_HipcMapAlias | SfBufferAttr_Out | SfBufferAttr_FixedSize }, + .buffers = { { buffer, size } }, + ); +} + static Result _btdrvCmdOutU32OutBuf(void* buffer, size_t size, u32 *out, u32 cmd_id) { return serviceDispatchOut(&g_btdrvSrv, cmd_id, *out, .buffer_attrs = { SfBufferAttr_HipcPointer | SfBufferAttr_Out }, @@ -203,6 +237,44 @@ void* btdrvGetHidReportEventInfoSharedmemAddr(void) { return g_btdrvCircularBuffer; } +Result btdrvGetLatestPlr(BtdrvPlrList *out) { + size_t size = hosversionBefore(9,0,0) ? sizeof(BtdrvPlrStatistics) : sizeof(BtdrvPlrList); + + return _btdrvCmdOutBufAliasFixed(out, size, 39); +} + +Result btdrvEnableTxPowerBoostSetting(bool flag) { + if (hosversionBefore(3,0,0)) + return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); + + return _btdrvCmdInBoolNoOut(flag, 42); +} + +Result btdrvIsTxPowerBoostSettingEnabled(bool *out) { + if (hosversionBefore(3,0,0)) + return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); + + return _btdrvCmdNoInOutBool(out, 43); +} + +Result btdrvEnableAfhSetting(bool flag) { + if (hosversionBefore(3,0,0)) + return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); + + return _btdrvCmdInBoolNoOut(flag, 44); +} + +Result btdrvIsAfhSettingEnabled(bool *out) { + return _btdrvCmdNoInOutBool(out, 45); +} + +Result btdrvGetChannelMap(BtdrvChannelMapList *out) { + if (hosversionBefore(3,0,0)) + return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); + + return _btdrvCmdOutBufAliasFixed(out, sizeof(*out), 41); +} + 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); @@ -323,6 +395,35 @@ Result btdrvRegisterBleHidEvent(Event* out_event) { return _btdrvCmdGetEvent(out_event, true, cmd_id); } +Result btdrvMoveToSecondaryPiconet(BtdrvAddress addr) { + if (hosversionBefore(10,0,0)) + return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); + + return _btdrvCmdInAddrNoOut(addr, 99); +} + +Result btdrvIsManufacturingMode(bool *out) { + if (hosversionBefore(5,0,0)) + return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); + + return _btdrvCmdNoInOutBool(out, 256); +} + +Result btdrvEmulateBluetoothCrash(BtdrvFatalReason reason) { + if (hosversionBefore(7,0,0)) + return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); + + u32 inval = reason; + return _btdrvCmdInU32NoOut(inval, 257); +} + +Result btdrvGetBleChannelMap(BtdrvChannelMapList *out) { + if (hosversionBefore(9,0,0)) + return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); + + return _btdrvCmdOutBufAliasFixed(out, sizeof(*out), 258); +} + // CircularBuffer void* btdrvCircularBufferRead(BtdrvCircularBuffer *c) {