diff options
| author | Yang You (UU) <[email protected]> | 2025-11-13 19:29:17 -0800 |
|---|---|---|
| committer | Yang You (UU) <[email protected]> | 2025-11-13 19:29:17 -0800 |
| commit | efa7a263ea3939ecf56e6a1256458d12c400e169 (patch) | |
| tree | 9cdc5d9c7205385a96eb350ad11291bc18700982 /network/wlan/WIFICX/drivercode/wifitransition.cpp | |
| parent | 773e9d01f3348ec31b63eccb6b42bd72d206a32c (diff) | |
move the logic to CPP
Diffstat (limited to 'network/wlan/WIFICX/drivercode/wifitransition.cpp')
| -rw-r--r-- | network/wlan/WIFICX/drivercode/wifitransition.cpp | 314 |
1 files changed, 314 insertions, 0 deletions
diff --git a/network/wlan/WIFICX/drivercode/wifitransition.cpp b/network/wlan/WIFICX/drivercode/wifitransition.cpp index 4e55f39c..9ac857bc 100644 --- a/network/wlan/WIFICX/drivercode/wifitransition.cpp +++ b/network/wlan/WIFICX/drivercode/wifitransition.cpp @@ -1,5 +1,319 @@ #include "wifitransition.h" +// Common TLV parsing helper: computes TLV span, optional dump, calls a parser, converts status. +template<typename Param, typename ParserFn> +NTSTATUS ParseTlvCommon(TransitionContext& ctx, + UINT16 messageId, + ParserFn parser, + Param& outParams, + bool dumpStream = true) +{ + if (ctx.InLen < sizeof(WDI_MESSAGE_HEADER)) + { + return STATUS_INVALID_PARAMETER; + } + + auto* tlvBytes = static_cast<UCHAR*>(ctx.RawBuffer) + sizeof(WDI_MESSAGE_HEADER); + auto tlvLen = static_cast<ULONG>(ctx.InLen - sizeof(WDI_MESSAGE_HEADER)); + + if (dumpStream) + { + DumpMessageTlvByteStream( + messageId, + TRUE, + ctx.DevCtx->TlvContext.PeerVersion, + tlvLen, + tlvBytes, + 0, + nullptr); + } + + auto ndisStatus = parser(tlvLen, tlvBytes, &ctx.DevCtx->TlvContext, &outParams); + return Wifi::ConvertNDISSTATUSToNTSTATUS(ndisStatus); +} + +// Execute two step callables. +// StepM3Fn signature: NTSTATUS (TransitionContext&, Param&, UINT& bytesWritten) +// StepM4Fn signature: NTSTATUS (TransitionContext&, Param&) +// Always calls WifiRequestComplete after StepM3 with the bytesWritten produced by StepM3. +// Skips StepM4 if StepM3 failed +template<typename Param, typename StepM3Fn, typename StepM4Fn> +NTSTATUS ExecuteSteps(TransitionContext& ctx, Param& p, StepM3Fn stepM3, StepM4Fn stepM4) +{ + UINT bytesWritten = sizeof(WDI_MESSAGE_HEADER); // default minimum + NTSTATUS m3Status = stepM3(ctx, p, bytesWritten); + // Report the M3 status back to OS + // OS expects M3 before the M4 + WifiIhvNotifyM3Completion(ctx.WifiRequest, m3Status, bytesWritten); + if (!NT_SUCCESS(m3Status)) + { + return m3Status; + } + return stepM4(ctx, p); +} +// Primary traits template (specialize per MessageId) +template<UINT16 MsgId> +struct TransitionTraits; + +// -------- WDI_TASK_SET_RADIO_STATE -------- +template<> +struct TransitionTraits<WDI_TASK_SET_RADIO_STATE> +{ + using ParamType = WDI_SET_RADIO_STATE_PARAMETERS; + enum : UINT16 { CompleteIndication = WDI_INDICATION_SET_RADIO_STATE_COMPLETE }; + + NTSTATUS Parse(TransitionContext& ctx, ParamType& p) + { + return ParseTlvCommon(ctx, + WDI_TASK_SET_RADIO_STATE, + [](ULONG len, UINT8* bytes, PCTLV_CONTEXT tlvCtx, ParamType* out) + { + return ParseWdiTaskSetRadioState(len, bytes, tlvCtx, out); + }, + p, + true); + } + void Cleanup(ParamType& p) { CleanupParsedWdiTaskSetRadioState(&p); } + + NTSTATUS Handle(TransitionContext& ctx, ParamType& p) + { + return ExecuteSteps(ctx, p, + // STEPM3 + [](TransitionContext&, ParamType&, UINT& bytesWritten) + { + bytesWritten = sizeof(WDI_MESSAGE_HEADER); + return STATUS_SUCCESS; + }, + // STEPM4 + [](TransitionContext& c, ParamType& par) + { + return c.DevCtx->wifiHAL->WifiIhvSetRadioState(par, c.Header); + } + ); + } + bool ShouldSendComplete(NTSTATUS) const { return true; } +}; + +// -------- WDI_TASK_SCAN -------- +template<> +struct TransitionTraits<WDI_TASK_SCAN> +{ + using ParamType = WDI_SCAN_PARAMETERS; + enum : UINT16 { CompleteIndication = WDI_INDICATION_SCAN_COMPLETE }; + + NTSTATUS Parse(TransitionContext& ctx, ParamType& p) + { + return ParseTlvCommon(ctx, + WDI_TASK_SCAN, + [](ULONG len, UINT8* bytes, PCTLV_CONTEXT tlvCtx, ParamType* out) + { + return ParseWdiTaskScan(len, bytes, tlvCtx, out); + }, + p, + true); + } + void Cleanup(ParamType& p) { CleanupParsedWdiTaskScan(&p); } + + NTSTATUS Handle(TransitionContext& ctx, ParamType& p) + { + return ExecuteSteps(ctx, p, + // STEPM3 + [](TransitionContext&, ParamType&, UINT& bytesWritten) + { + bytesWritten = sizeof(WDI_MESSAGE_HEADER); + return STATUS_SUCCESS; + }, + // STEPM4 + [](TransitionContext& c, ParamType& par) + { + return c.DevCtx->wifiHAL->WifiIhvScan(par, c.Header); + } + ); + } + bool ShouldSendComplete(NTSTATUS) const { return true; } +}; + +// -------- WDI_TASK_DOT11_RESET -------- +template<> +struct TransitionTraits<WDI_TASK_DOT11_RESET> +{ + using ParamType = WDI_TASK_DOT11_RESET_PARAMETERS; + enum : UINT16 { CompleteIndication = WDI_INDICATION_DOT11_RESET_COMPLETE }; + + NTSTATUS Parse(TransitionContext& ctx, ParamType& p) + { + return ParseTlvCommon(ctx, + WDI_TASK_DOT11_RESET, + [](ULONG len, UINT8* bytes, PCTLV_CONTEXT tlvCtx, ParamType* out) + { + return ParseWdiTaskDot11Reset(len, bytes, tlvCtx, out); + }, + p, + false); + } + void Cleanup(ParamType& p) { CleanupParsedWdiTaskDot11Reset(&p); } + + NTSTATUS Handle(TransitionContext& ctx, ParamType& p) + { + return ExecuteSteps(ctx, p, + // STEPM3 + [](TransitionContext&, ParamType&, UINT& bytesWritten) + { + bytesWritten = sizeof(WDI_MESSAGE_HEADER); + return STATUS_SUCCESS; + }, + // STEPM4 + [](TransitionContext& c, ParamType& par) + { + return c.DevCtx->wifiHAL->WifiIhvReset(par, c.Header); + }); + } + bool ShouldSendComplete(NTSTATUS) const { return true; } +}; + +// -------- WDI_TASK_CONNECT -------- +template<> +struct TransitionTraits<WDI_TASK_CONNECT> +{ + using ParamType = WDI_TASK_CONNECT_PARAMETERS; + enum : UINT16 { CompleteIndication = WDI_INDICATION_CONNECT_COMPLETE }; + + NTSTATUS Parse(TransitionContext& ctx, ParamType& p) + { + return ParseTlvCommon(ctx, + WDI_TASK_CONNECT, + [](ULONG len, UINT8* bytes, PCTLV_CONTEXT tlvCtx, ParamType* out) + { + return ParseWdiTaskConnect(len, bytes, tlvCtx, out); + }, + p, + true); + } + void Cleanup(ParamType& p) { CleanupParsedWdiTaskConnect(&p); } + + NTSTATUS Handle(TransitionContext& ctx, ParamType& p) + { + return ExecuteSteps(ctx, p, + // STEPM3 + [](TransitionContext&, ParamType&, UINT& bytesWritten) + { + bytesWritten = sizeof(WDI_MESSAGE_HEADER); + return STATUS_SUCCESS; + }, + // STEPM4 + [](TransitionContext& c, ParamType& par) + { + return c.DevCtx->wifiHAL->WifiIhvConnect(par, c.Header); + }); + } + bool ShouldSendComplete(NTSTATUS s) const { return s != STATUS_PENDING; } +}; + +// -------- WDI_TASK_DISCONNECT -------- +template<> +struct TransitionTraits<WDI_TASK_DISCONNECT> +{ + struct ParamType {}; + enum : UINT16 { CompleteIndication = WDI_INDICATION_DISCONNECT_COMPLETE }; + + NTSTATUS Parse(TransitionContext&, ParamType&) { return STATUS_SUCCESS; } + void Cleanup(ParamType&) {} + + NTSTATUS Handle(TransitionContext& ctx, ParamType& p) + { + return ExecuteSteps(ctx, p, + // STEPM3 + [](TransitionContext&, ParamType&, UINT& bytesWritten) + { + bytesWritten = sizeof(WDI_MESSAGE_HEADER); + return STATUS_SUCCESS; + }, + // STEPM4 + [](TransitionContext& c, ParamType&) + { + c.DevCtx->wifiHAL->WifiIhvPerformDisassociation(c.Header, WDI_ASSOC_STATUS_DISASSOCIATED_BY_HOST); + return STATUS_SUCCESS; + }); + } + bool ShouldSendComplete(NTSTATUS) const { return true; } +}; + +// -------- WDI_SET_SAE_AUTH_PARAMS -------- +template<> +struct TransitionTraits<WDI_SET_SAE_AUTH_PARAMS> +{ + using ParamType = WDI_SET_SAE_AUTH_PARAMS_COMMAND; + enum : UINT16 { CompleteIndication = 0 }; + + NTSTATUS Parse(TransitionContext& ctx, ParamType& p) + { + return ParseTlvCommon(ctx, + WDI_SET_SAE_AUTH_PARAMS, + [](ULONG len, UINT8* bytes, PCTLV_CONTEXT tlvCtx, ParamType* out) + { + return ParseWdiSetSaeAuthParams(len, bytes, tlvCtx, out); + }, + p, + /*dumpStream*/ false); + } + + void Cleanup(ParamType& p) + { + CleanupParsedWdiSetSaeAuthParams(&p); + } + + NTSTATUS Handle(TransitionContext& ctx, ParamType& p) + { + return ExecuteSteps(ctx, p, + // Step M3: invoke HAL handler, report bytes written (just header) + [](TransitionContext& c, ParamType& par, UINT& bytesWritten) + { + bytesWritten = sizeof(WDI_MESSAGE_HEADER); + return c.DevCtx->wifiHAL->WifiIhvSetSaeAuthParams(par, c.Header); + }, + // Step M4: no-op (no completion indication for this OID) + [](TransitionContext&, ParamType&) { return STATUS_SUCCESS; }); + } + + bool ShouldSendComplete(NTSTATUS) const + { + // Do not send M4 indication for WDI_SET_SAE_AUTH_PARAMS (original code omitted it). + return false; + } +}; + +// -------- Generic runner (compile-time) -------- +template<UINT16 MsgId> +NTSTATUS RunTransition(TransitionContext& ctx) +{ + TransitionTraits<MsgId> traits; + typename TransitionTraits<MsgId>::ParamType params{}; + NTSTATUS parseStatus = traits.Parse(ctx, params); + if (!NT_SUCCESS(parseStatus)) + { + traits.Cleanup(params); + // Report Failed M3 to OS + // Note: No M4 indication on parse failure + WifiIhvNotifyM3Completion(ctx.WifiRequest, parseStatus, 0); + return parseStatus; + } + + NTSTATUS m4Status = traits.Handle(ctx, params); + + if (traits.ShouldSendComplete(m4Status)) + { + WifiIhvSendM4IndicationToOs( + ctx.Device, + TransitionTraits<MsgId>::CompleteIndication, + ctx.Header, + m4Status); + } + + traits.Cleanup(params); + return m4Status; +} + + // Runtime dispatcher switches on MessageId and invokes the matching compile-time runner. NTSTATUS RunTransitionByMessage(TransitionContext& ctx, UINT16 messageId) { |
