mirror of
https://github.com/switchbrew/libnx.git
synced 2025-07-01 01:02:14 +02:00
ldn: Added *ActionFrame, ldnSetHomeChannel, *TxPower.
This commit is contained in:
parent
18002c9735
commit
70ea18a477
@ -193,6 +193,15 @@ typedef struct {
|
|||||||
u8 reserved_x16[0xA]; ///< Cleared to zero for the tmp struct.
|
u8 reserved_x16[0xA]; ///< Cleared to zero for the tmp struct.
|
||||||
} LdnNetworkConfig;
|
} LdnNetworkConfig;
|
||||||
|
|
||||||
|
/// ActionFrameSettings
|
||||||
|
typedef struct {
|
||||||
|
s64 local_communication_id; ///< LocalCommunicationId (Same handling as LdnNetworkConfig::local_communication_id)
|
||||||
|
u8 reserved[0x34]; ///< Reserved
|
||||||
|
u16 security_mode; ///< SecurityMode (Must be 1-2, internally this is overriden)
|
||||||
|
u16 passphrase_size; ///< PassphraseSize (Must be 0x10-0x40)
|
||||||
|
u8 passphrase[0x40]; ///< Passphrase
|
||||||
|
} LdnActionFrameSettings;
|
||||||
|
|
||||||
///@name ldn:m
|
///@name ldn:m
|
||||||
///@{
|
///@{
|
||||||
|
|
||||||
@ -476,5 +485,71 @@ Result ldnDisconnect(void);
|
|||||||
*/
|
*/
|
||||||
Result ldnSetOperationMode(LdnOperationMode mode);
|
Result ldnSetOperationMode(LdnOperationMode mode);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief EnableActionFrame
|
||||||
|
* @note Only available on [18.0.0+].
|
||||||
|
* @note \ref LdnState must be ::LdnState_Initialized.
|
||||||
|
* @param[in] settings \ref LdnActionFrameSettings
|
||||||
|
*/
|
||||||
|
Result ldnEnableActionFrame(const LdnActionFrameSettings *settings);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief DisableActionFrame
|
||||||
|
* @note Only available on [18.0.0+].
|
||||||
|
* @note \ref LdnState must be ::LdnState_Initialized.
|
||||||
|
*/
|
||||||
|
Result ldnDisableActionFrame(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief SendActionFrame
|
||||||
|
* @note Only available on [18.0.0+].
|
||||||
|
* @note \ref LdnState must be ::LdnState_AccessPointCreated / ::LdnState_StationOpened.
|
||||||
|
* @param[in] data Data buffer.
|
||||||
|
* @param[in] size Data buffer size.
|
||||||
|
* @param[in] destination Destination \ref LdnMacAddress.
|
||||||
|
* @param[in] bssid Bssid \ref LdnMacAddress.
|
||||||
|
* @param[in] channel Channel, must be non-zero.
|
||||||
|
* @param[in] flags MessageFlag bit0 clear = block until the data can be sent, set = return error when the data can't be sent.
|
||||||
|
*/
|
||||||
|
Result ldnSendActionFrame(const void* data, size_t size, LdnMacAddress destination, LdnMacAddress bssid, s16 channel, u32 flags);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief RecvActionFrame
|
||||||
|
* @note Only available on [18.0.0+].
|
||||||
|
* @note \ref ldnEnableActionFrame must be used prior to this.
|
||||||
|
* @param[out] data Output data buffer.
|
||||||
|
* @param[in] size Max size of the data buffer.
|
||||||
|
* @param[out] addr0 First \ref LdnMacAddress.
|
||||||
|
* @param[out] addr1 Second \ref LdnMacAddress.
|
||||||
|
* @param[out] channel Channel
|
||||||
|
* @param[out] out_size Output size.
|
||||||
|
* @param[out] link_level LinkLevel
|
||||||
|
* @param[in] flags MessageFlag bit0 clear = block until data is available, set = return error when data is not available.
|
||||||
|
*/
|
||||||
|
Result ldnRecvActionFrame(void* data, size_t size, LdnMacAddress *addr0, LdnMacAddress *addr1, s16 *channel, u32 *out_size, s32 *link_level, u32 flags);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief SetHomeChannel
|
||||||
|
* @note Only available on [18.0.0+].
|
||||||
|
* @note \ref LdnState must be ::LdnState_StationOpened.
|
||||||
|
* @param[in] channel Channel, must be non-zero.
|
||||||
|
*/
|
||||||
|
Result ldnSetHomeChannel(s16 channel);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief SetTxPower
|
||||||
|
* @note Only available on [18.0.0+].
|
||||||
|
* @note \ref LdnState must be ::LdnState_AccessPoint* / ::LdnState_Station*.
|
||||||
|
* @param[in] power Power, must be 0x0..0xFF.
|
||||||
|
*/
|
||||||
|
Result ldnSetTxPower(s16 power);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief ResetTxPower
|
||||||
|
* @note Only available on [18.0.0+].
|
||||||
|
* @note \ref LdnState must be ::LdnState_AccessPoint* / ::LdnState_Station*.
|
||||||
|
*/
|
||||||
|
Result ldnResetTxPower(void);
|
||||||
|
|
||||||
///@}
|
///@}
|
||||||
|
|
||||||
|
@ -140,6 +140,10 @@ static Result _ldnCmdInU32NoOut(Service* srv, u32 in, u32 cmd_id) {
|
|||||||
return serviceDispatchIn(srv, cmd_id, in);
|
return serviceDispatchIn(srv, cmd_id, in);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static Result _ldnCmdInU16NoOut(Service* srv, u16 in, u32 cmd_id) {
|
||||||
|
return serviceDispatchIn(srv, cmd_id, in);
|
||||||
|
}
|
||||||
|
|
||||||
static Result _ldnCmdNoInOutU32(Service* srv, u32 *out, u32 cmd_id) {
|
static Result _ldnCmdNoInOutU32(Service* srv, u32 *out, u32 cmd_id) {
|
||||||
return serviceDispatchOut(srv, cmd_id, *out);
|
return serviceDispatchOut(srv, cmd_id, *out);
|
||||||
}
|
}
|
||||||
@ -226,6 +230,26 @@ static void _ldnCopyNetworkConfig(const LdnNetworkConfig *in, LdnNetworkConfig *
|
|||||||
out->local_communication_version = in->local_communication_version;
|
out->local_communication_version = in->local_communication_version;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static s16 _ldnChannelToOldBand(s16 channel) {
|
||||||
|
if (channel < 15) return 24;
|
||||||
|
else return 50;
|
||||||
|
}
|
||||||
|
|
||||||
|
static u16 _ldnChannelToChannelBand(s16 channel) {
|
||||||
|
if (!channel) return channel;
|
||||||
|
u16 tmp_channel = channel & 0x3FF; // Official sw just masks with u16.
|
||||||
|
|
||||||
|
u16 band = 0x3F; // Invalid
|
||||||
|
if (tmp_channel < 15) band = 2;
|
||||||
|
else if (tmp_channel >= 32 && tmp_channel < 178) band = 5;
|
||||||
|
|
||||||
|
return channel | (band<<10);
|
||||||
|
}
|
||||||
|
|
||||||
|
static s16 _ldnChannelBandToChannel(u16 val) {
|
||||||
|
return val & 0x3FF;
|
||||||
|
}
|
||||||
|
|
||||||
Result ldnGetState(LdnState *out) {
|
Result ldnGetState(LdnState *out) {
|
||||||
u32 tmp=0;
|
u32 tmp=0;
|
||||||
Result rc = _ldnCmdNoInOutU32(&g_ldnSrv, &tmp, 0);
|
Result rc = _ldnCmdNoInOutU32(&g_ldnSrv, &tmp, 0);
|
||||||
@ -426,3 +450,132 @@ Result ldnSetOperationMode(LdnOperationMode mode) {
|
|||||||
return _ldnCmdInU32NoOut(&g_ldnSrv, mode, 402);
|
return _ldnCmdInU32NoOut(&g_ldnSrv, mode, 402);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Result ldnEnableActionFrame(const LdnActionFrameSettings *settings) {
|
||||||
|
if (!serviceIsActive(&g_ldnSrv) || g_ldnServiceType != LdnServiceType_System)
|
||||||
|
return MAKERESULT(Module_Libnx, LibnxError_NotInitialized);
|
||||||
|
|
||||||
|
if (hosversionBefore(18,0,0))
|
||||||
|
return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer);
|
||||||
|
|
||||||
|
return serviceDispatchIn(&g_ldnSrv, 500, *settings);
|
||||||
|
}
|
||||||
|
|
||||||
|
Result ldnDisableActionFrame(void) {
|
||||||
|
if (!serviceIsActive(&g_ldnSrv) || g_ldnServiceType != LdnServiceType_System)
|
||||||
|
return MAKERESULT(Module_Libnx, LibnxError_NotInitialized);
|
||||||
|
|
||||||
|
if (hosversionBefore(18,0,0))
|
||||||
|
return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer);
|
||||||
|
|
||||||
|
return _ldnCmdNoIO(&g_ldnSrv, 501);
|
||||||
|
}
|
||||||
|
|
||||||
|
Result ldnSendActionFrame(const void* data, size_t size, LdnMacAddress destination, LdnMacAddress bssid, s16 channel, u32 flags) {
|
||||||
|
if (!serviceIsActive(&g_ldnSrv) || g_ldnServiceType != LdnServiceType_System)
|
||||||
|
return MAKERESULT(Module_Libnx, LibnxError_NotInitialized);
|
||||||
|
|
||||||
|
if (hosversionBefore(18,0,0))
|
||||||
|
return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer);
|
||||||
|
|
||||||
|
s16 tmp_band = 0, tmp_channel = 0;
|
||||||
|
if (hosversionBefore(20,0,0)) {
|
||||||
|
tmp_channel = channel;
|
||||||
|
tmp_band = _ldnChannelToOldBand(channel);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
tmp_band = _ldnChannelToChannelBand(channel);
|
||||||
|
|
||||||
|
const struct {
|
||||||
|
LdnMacAddress destination;
|
||||||
|
LdnMacAddress bssid;
|
||||||
|
s16 band; // These are a single u16 with [20.0.0+].
|
||||||
|
s16 channel;
|
||||||
|
u32 flags;
|
||||||
|
} in = { destination, bssid, tmp_band, tmp_channel, flags};
|
||||||
|
|
||||||
|
return serviceDispatchIn(&g_ldnSrv, 502, in,
|
||||||
|
.buffer_attrs = { SfBufferAttr_HipcAutoSelect | SfBufferAttr_In },
|
||||||
|
.buffers = { { data, size } },
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Result ldnRecvActionFrame(void* data, size_t size, LdnMacAddress *addr0, LdnMacAddress *addr1, s16 *channel, u32 *out_size, s32 *link_level, u32 flags) {
|
||||||
|
if (!serviceIsActive(&g_ldnSrv) || g_ldnServiceType != LdnServiceType_System)
|
||||||
|
return MAKERESULT(Module_Libnx, LibnxError_NotInitialized);
|
||||||
|
|
||||||
|
if (hosversionBefore(18,0,0))
|
||||||
|
return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer);
|
||||||
|
|
||||||
|
struct {
|
||||||
|
LdnMacAddress addr0;
|
||||||
|
LdnMacAddress addr1;
|
||||||
|
s16 band; // These are a single u16 with [20.0.0+].
|
||||||
|
s16 channel;
|
||||||
|
u32 size;
|
||||||
|
s32 link_level;
|
||||||
|
} out;
|
||||||
|
|
||||||
|
Result rc = serviceDispatchInOut(&g_ldnSrv, 503, flags, out,
|
||||||
|
.buffer_attrs = { SfBufferAttr_HipcAutoSelect | SfBufferAttr_Out },
|
||||||
|
.buffers = { { data, size } },
|
||||||
|
);
|
||||||
|
if (R_SUCCEEDED(rc)) {
|
||||||
|
if (addr0) *addr0 = out.addr0;
|
||||||
|
if (addr1) *addr1 = out.addr1;
|
||||||
|
if (channel) {
|
||||||
|
if (hosversionBefore(20,0,0))
|
||||||
|
*channel = out.channel;
|
||||||
|
else
|
||||||
|
*channel = _ldnChannelBandToChannel(out.band);
|
||||||
|
}
|
||||||
|
if (out_size) *out_size = out.size;
|
||||||
|
if (link_level) *link_level = out.link_level;
|
||||||
|
}
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
Result ldnSetHomeChannel(s16 channel) {
|
||||||
|
if (!serviceIsActive(&g_ldnSrv) || g_ldnServiceType != LdnServiceType_System)
|
||||||
|
return MAKERESULT(Module_Libnx, LibnxError_NotInitialized);
|
||||||
|
|
||||||
|
if (hosversionBefore(18,0,0))
|
||||||
|
return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer);
|
||||||
|
|
||||||
|
s16 tmp_band = 0, tmp_channel = 0;
|
||||||
|
if (hosversionBefore(20,0,0)) {
|
||||||
|
tmp_channel = channel;
|
||||||
|
tmp_band = _ldnChannelToOldBand(channel);
|
||||||
|
|
||||||
|
const struct {
|
||||||
|
s16 band;
|
||||||
|
s16 channel;
|
||||||
|
} in = { tmp_band, tmp_channel };
|
||||||
|
|
||||||
|
return serviceDispatchIn(&g_ldnSrv, 505, in);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
tmp_band = _ldnChannelToChannelBand(channel);
|
||||||
|
|
||||||
|
return _ldnCmdInU16NoOut(&g_ldnSrv, tmp_band, 505);
|
||||||
|
}
|
||||||
|
|
||||||
|
Result ldnSetTxPower(s16 power) {
|
||||||
|
if (!serviceIsActive(&g_ldnSrv) || g_ldnServiceType != LdnServiceType_System)
|
||||||
|
return MAKERESULT(Module_Libnx, LibnxError_NotInitialized);
|
||||||
|
|
||||||
|
if (hosversionBefore(18,0,0))
|
||||||
|
return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer);
|
||||||
|
|
||||||
|
return _ldnCmdInU16NoOut(&g_ldnSrv, power, 600);
|
||||||
|
}
|
||||||
|
|
||||||
|
Result ldnResetTxPower(void) {
|
||||||
|
if (!serviceIsActive(&g_ldnSrv) || g_ldnServiceType != LdnServiceType_System)
|
||||||
|
return MAKERESULT(Module_Libnx, LibnxError_NotInitialized);
|
||||||
|
|
||||||
|
if (hosversionBefore(18,0,0))
|
||||||
|
return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer);
|
||||||
|
|
||||||
|
return _ldnCmdNoIO(&g_ldnSrv, 601);
|
||||||
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user