summaryrefslogtreecommitdiff
path: root/network/wlan/WIFICX/drivercode/wifihal.cpp
diff options
context:
space:
mode:
authorYang You (UU) <[email protected]>2025-11-11 16:07:58 -0800
committerYang You (UU) <[email protected]>2025-11-11 16:07:58 -0800
commitfe139d460e690a27cc98bb9c077eeb5964fc7877 (patch)
treef358ad588aa316ef00e0a4ce57f6c73a301f1248 /network/wlan/WIFICX/drivercode/wifihal.cpp
parentbddbce760509546060b3ccc28a9891b2412d2824 (diff)
have the HAL layer created for correctly demo the Interface of WIfireuqest, meanwhile have the WPPTrace enabled for both um and km
Diffstat (limited to 'network/wlan/WIFICX/drivercode/wifihal.cpp')
-rw-r--r--network/wlan/WIFICX/drivercode/wifihal.cpp907
1 files changed, 907 insertions, 0 deletions
diff --git a/network/wlan/WIFICX/drivercode/wifihal.cpp b/network/wlan/WIFICX/drivercode/wifihal.cpp
new file mode 100644
index 00000000..824ab6ac
--- /dev/null
+++ b/network/wlan/WIFICX/drivercode/wifihal.cpp
@@ -0,0 +1,907 @@
+// Copyright (C) Microsoft Corporation. All rights reserved.
+
+#include "precomp.h"
+#include "wifirequest.h"
+#include "wifiHALtestdata.h"
+#include "WifiHal.h"
+#include "WifiHal.tmh"
+
+NTSTATUS WifiHAL::WifiIhvSetDeviceCapabilities(WDFDEVICE Device)
+{
+ WIFI_DEVICE_CAPABILITIES deviceCaps = {};
+ WIFI_DEVICE_CAPABILITIES_INIT(&deviceCaps);
+
+ deviceCaps.HardwareRadioState = TRUE;
+ deviceCaps.SoftwareRadioState = TRUE;
+ deviceCaps.FirmwareVersion[MAX_FIRMWARE_VERSION_LENGTH];
+ deviceCaps.ActionFramesSupported = TRUE;
+ deviceCaps.NumRxStreams = 1;
+ deviceCaps.NumTxStreams = 1;
+ deviceCaps.Support_eCSA = FALSE;
+ deviceCaps.MACAddressRandomization = FALSE;
+ deviceCaps.MACAddressRandomizationMask.Address[0] = 0;
+ deviceCaps.MACAddressRandomizationMask.Address[1] = 0;
+ deviceCaps.MACAddressRandomizationMask.Address[2] = 0;
+ deviceCaps.MACAddressRandomizationMask.Address[3] = 0xFF;
+ deviceCaps.MACAddressRandomizationMask.Address[4] = 0;
+ deviceCaps.MACAddressRandomizationMask.Address[5] = 0;
+ deviceCaps.BluetoothCoexistenceSupport = WDI_BLUETOOTH_COEXISTENCE_PERFORMANCE_MAINTAINED;
+ deviceCaps.SupportsNonWdiOidRequests = FALSE;
+ deviceCaps.FastTransitionSupported = TRUE;
+ deviceCaps.MU_MIMOSupported = FALSE;
+ deviceCaps.SAEAuthenticationSupported = TRUE;
+ deviceCaps.BSSTransitionSupported = TRUE;
+ deviceCaps.MBOSupported = FALSE;
+ deviceCaps.BeaconReportsImplemented = FALSE;
+
+ WX_RETURN_NTSTATUS_IF_NOT_NT_SUCCESS_MSG(
+ WifiDeviceSetDeviceCapabilities(Device, &deviceCaps),
+ "Failed to set device capabilities");
+
+ WIFI_STATION_CAPABILITIES StationCaps = {};
+ WIFI_STATION_CAPABILITIES_INIT(&StationCaps);
+
+ StationCaps.ScanSSIDListSize = 4;
+ StationCaps.DesiredSSIDListSize = 1;
+ StationCaps.PrivacyExemptionListSize = 1;
+ StationCaps.KeyMappingTableSize = 32;
+ StationCaps.DefaultKeyTableSize = 4;
+ StationCaps.WEPKeyValueMaxLength = 0x20;
+ StationCaps.MaxNumPerSTA = 4;
+ StationCaps.SupportedQOSFlags = 0;
+ StationCaps.HostFIPSModeImplemented = FALSE;
+ StationCaps.MFPCapable = TRUE;
+ StationCaps.AutoPowerSaveMode = FALSE;
+ StationCaps.BSSListCachemanagement = FALSE;
+ StationCaps.ConnectBSSSelectionOverride = FALSE;
+ StationCaps.MaxNetworkOffloadListSize = 0;
+ StationCaps.HESSIDConnectionSupported = FALSE;
+ StationCaps.FTMAsInitiatorSupport = FALSE;
+ StationCaps.FTMNumberOfSupportedTargets = 0;
+
+ const DOT11_AUTH_CIPHER_PAIR UnicastAlgos[] = {
+ {DOT11_AUTH_ALGO_80211_OPEN, DOT11_CIPHER_ALGO_NONE},
+ {DOT11_AUTH_ALGO_80211_OPEN, DOT11_CIPHER_ALGO_WEP},
+ {DOT11_AUTH_ALGO_WPA_PSK, DOT11_CIPHER_ALGO_CCMP},
+ {DOT11_AUTH_ALGO_RSNA, DOT11_CIPHER_ALGO_CCMP},
+ {DOT11_AUTH_ALGO_RSNA_PSK, DOT11_CIPHER_ALGO_TKIP},
+ {DOT11_AUTH_ALGO_RSNA_PSK, DOT11_CIPHER_ALGO_CCMP},
+ {DOT11_AUTH_ALGO_WPA3_ENT_192, DOT11_CIPHER_ALGO_GCMP_256},
+ {DOT11_AUTH_ALGO_WPA3_ENT, DOT11_CIPHER_ALGO_CCMP},
+ {DOT11_AUTH_ALGO_WPA3_SAE, DOT11_CIPHER_ALGO_GCMP_256},
+ {DOT11_AUTH_ALGO_WPA3_SAE, DOT11_CIPHER_ALGO_CCMP},
+ {DOT11_AUTH_ALGO_OWE, DOT11_CIPHER_ALGO_GCMP_256},
+ {DOT11_AUTH_ALGO_OWE, DOT11_CIPHER_ALGO_CCMP},
+ };
+
+ const DOT11_AUTH_CIPHER_PAIR McastMgmtAlgos[] = {
+ {DOT11_AUTH_ALGO_80211_OPEN, DOT11_CIPHER_ALGO_NONE},
+ {DOT11_AUTH_ALGO_RSNA, DOT11_CIPHER_ALGO_BIP},
+ {DOT11_AUTH_ALGO_RSNA_PSK, DOT11_CIPHER_ALGO_BIP},
+ {DOT11_AUTH_ALGO_WPA3_SAE, DOT11_CIPHER_ALGO_BIP},
+ {DOT11_AUTH_ALGO_WPA3_ENT, DOT11_CIPHER_ALGO_BIP},
+ {DOT11_AUTH_ALGO_WPA3_ENT_192, DOT11_CIPHER_ALGO_BIP_GMAC_256},
+ };
+
+ StationCaps.NumSupportedUnicastAlgorithms = ARRAYSIZE(UnicastAlgos);
+ StationCaps.UnicastAlgorithmsList = const_cast<PDOT11_AUTH_CIPHER_PAIR>(UnicastAlgos);
+ StationCaps.NumSupportedMulticastDataAlgorithms = ARRAYSIZE(UnicastAlgos);
+ StationCaps.MulticastDataAlgorithmsList = const_cast<PDOT11_AUTH_CIPHER_PAIR>(UnicastAlgos);
+ StationCaps.NumSupportedMulticastMgmtAlgorithms = ARRAYSIZE(McastMgmtAlgos);
+ StationCaps.MulticastMgmtAlgorithmsList = const_cast<PDOT11_AUTH_CIPHER_PAIR>(McastMgmtAlgos);
+
+ WIFI_STA_BANDS_COMBINATION SecondaryStaBandsCombinations[] = {
+ {2, {WDI_BAND_ID_2400, WDI_BAND_ID_5000, WDI_BAND_ID_UNKNOWN, WDI_BAND_ID_UNKNOWN}},
+ {2, {WDI_BAND_ID_2400, WDI_BAND_ID_6000, WDI_BAND_ID_UNKNOWN, WDI_BAND_ID_UNKNOWN}},
+ {2, {WDI_BAND_ID_5000, WDI_BAND_ID_6000, WDI_BAND_ID_UNKNOWN, WDI_BAND_ID_UNKNOWN}},
+ {3, {WDI_BAND_ID_2400, WDI_BAND_ID_5000, WDI_BAND_ID_6000, WDI_BAND_ID_UNKNOWN}},
+ };
+
+ StationCaps.NumSecondaryStaBandCombinations = ARRAYSIZE(SecondaryStaBandsCombinations);
+ StationCaps.SecondaryStaBandsCombinations = SecondaryStaBandsCombinations;
+
+ WDI_MAC_ADDRESS MLOAddresses[] = {
+ {0x11, 0x01, 0x02, 0x03, 0x04, 0x21},
+ {0x11, 0x01, 0x02, 0x03, 0x04, 0x22},
+ };
+ StationCaps.MaxMLOLinksSupported = ARRAYSIZE(MLOAddresses);
+ StationCaps.MLOAddressesList = MLOAddresses;
+
+ RSNA_AKM_SUITE AkmsList[] = {
+ rsna_akm_1x,
+ rsna_akm_psk,
+ rsna_akm_ft_1x_sha256,
+ rsna_akm_ft_psk_sha256,
+ rsna_akm_1x_sha256,
+ rsna_akm_psk_sha256,
+ rsna_akm_sae_pmk256,
+ rsna_akm_1x_suite_b_sha384,
+ rsna_akm_owe,
+ rsna_akm_1x_sha384,
+ rsna_akm_sae_pmk384,
+ };
+ StationCaps.NumAkmsSupported = ARRAYSIZE(AkmsList);
+ StationCaps.AkmsList = AkmsList;
+
+ if (WIFI_IS_FIELD_AVAILABLE(WIFI_STATION_CAPABILITIES, MSCSSupported))
+ {
+ StationCaps.MSCSSupported = true;
+ }
+ if (WIFI_IS_FIELD_AVAILABLE(WIFI_STATION_CAPABILITIES, DSCPToUPMappingSupported))
+ {
+ StationCaps.DSCPToUPMappingSupported = true;
+ }
+
+ WX_RETURN_NTSTATUS_IF_NOT_NT_SUCCESS_MSG(
+ WifiDeviceSetStationCapabilities(Device, &StationCaps),
+ "Failed to set station capabilities");
+
+ WIFI_BAND_CAPABILITIES BandCaps = {};
+ WIFI_BAND_CAPABILITIES_INIT(&BandCaps);
+
+ const WDI_PHY_TYPE Phy24GHz[] = { WDI_PHY_TYPE_ERP, WDI_PHY_TYPE_HE }; // g, ax
+ const WDI_PHY_TYPE Phy5GHz[] = { WDI_PHY_TYPE_OFDM, WDI_PHY_TYPE_HE, WDI_PHY_TYPE_EHT }; // a, ax, be
+ const WDI_PHY_TYPE Phy6GHz[] = { WDI_PHY_TYPE_HE, WDI_PHY_TYPE_EHT }; // ax, be
+ const WDI_PHY_TYPE pPhy60GHz[] = { WDI_PHY_TYPE_DMG }; // ad
+ const WDI_PHY_TYPE phyIHV[2] = { WDI_PHY_TYPE_OFDM, static_cast<WDI_PHY_TYPE>(WDI_PHY_TYPE_IHV_START + 1) };
+
+ // clang-format off
+
+ const WDI_CHANNEL_MAPPING_ENTRY ChannelMap24[] = {
+ {1, 2412},
+ {2, 2417},
+ {3, 2422},
+ {4, 2427},
+ {5, 2432},
+ {6, 2437},
+ {7, 2442},
+ {8, 2447},
+ {9, 2452},
+ {10, 2457},
+ {11, 2462},
+ {12, 2467}, // Not used in US
+ {13, 2472}, // Not used in US
+ {14, 2484}, // Allowed in Japan only
+ };
+
+ const WDI_CHANNEL_MAPPING_ENTRY ChannelMap5[] = {
+ {7, 5035}, // Not used in US
+ {8, 5040}, // Not used in US
+ {9, 5045}, // Not used in US
+ {11, 5055}, // Not used in US
+ {12, 5060}, // Not used in US
+ {16, 5080}, // Not used in US
+ {32, 5160}, // Unknown status
+ {34, 5170}, // Not used in US
+ {36, 5180},
+ {38, 5190},
+ {40, 5200},
+ {42, 5210},
+ {44, 5220},
+ {46, 5230},
+ {48, 5240},
+ {50, 5250}, // DFS
+ {52, 5260}, // DFS
+ {54, 5270}, // DFS
+ {56, 5280}, // DFS
+ {58, 5290}, // DFS
+ {60, 5300}, // DFS
+ {62, 5310}, // DFS
+ {64, 5320}, // DFS
+ {68, 5340}, // Unknown status
+ {96, 5480}, // Unknown status
+ {100, 5500}, // DFS
+ {102, 5510}, // DFS
+ {104, 5520}, // DFS
+ {106, 5530}, // DFS
+ {108, 5540}, // DFS
+ {110, 5550}, // DFS
+ {112, 5560}, // DFS
+ {114, 5570}, // DFS
+ {116, 5580}, // DFS
+ {118, 5590}, // DFS
+ {120, 5600}, // DFS
+ {122, 5610}, // DFS
+ {124, 5620}, // DFS
+ {126, 5630}, // DFS
+ {128, 5640}, // DFS
+ {132, 5660}, // DFS
+ {134, 5670}, // DFS
+ {136, 5680}, // DFS
+ {138, 5690}, // DFS
+ {140, 5700}, // DFS
+ {142, 5710}, // DFS
+ {142, 5720}, // DFS
+ {144, 5730}, // DFS
+ {149, 5745},
+ {151, 5755},
+ {153, 5765},
+ {155, 5785},
+ {157, 5785},
+ {159, 5795},
+ {161, 5805},
+ {165, 5825},
+ {169, 5845}, // Not used in US
+ {173, 5865}, // Not used in US
+ {183, 4915}, // Not used in US
+ {184, 4920}, // Not used in US
+ {185, 4925}, // Not used in US
+ {187, 4935}, // Not used in US
+ {188, 4940}, // Not used in US
+ {189, 4945}, // Not used in US
+ {192, 4960}, // Not used in US
+ {196, 4980}, // Not used in US
+ };
+
+ const WDI_CHANNEL_MAPPING_ENTRY channelMap6[] = {
+ {1, 5955},
+ {5, 5975}, // PSC Channel (1)
+ {9, 5995},
+
+ {13, 6015},
+ {17, 6035},
+ {21, 6055}, // PSC Channel (2)
+ {25, 6075},
+ {29, 6095},
+
+ {33, 6115},
+ {37, 6135}, // PSC Channel (3)
+ {41, 6155},
+ {45, 6175},
+ {49, 6195},
+
+ {53, 6215}, // PSC Channel (4)
+ {57, 6235},
+ {61, 6255},
+ {65, 6275},
+ {69, 6295}, // PSC Channel (5)
+
+ {73, 6315},
+ {77, 6335},
+ {81, 6355},
+ {85, 6375}, // PSC Channel (6)
+ {89, 6395},
+
+ {93, 6415},
+ {97, 6435},
+ {101, 6455}, // PSC Channel (7)
+ {105, 6475},
+ {109, 6495},
+
+ {113, 6515},
+ {117, 6535}, // PSC Channel (8)
+ {121, 6555},
+ {125, 6575},
+ {129, 6595},
+
+ {133, 6615}, // PSC Channel (9)
+ {137, 6635},
+ {141, 6655},
+ {145, 6675},
+ {149, 6695}, // PSC Channel (10)
+
+ {153, 6715},
+ {157, 6735},
+ {161, 6755},
+ {165, 6775}, // PSC Channel (11)
+ {169, 6795},
+
+ {173, 6815},
+ {177, 6835},
+ {181, 6855}, // PSC Channel (12)
+ {185, 6875},
+ {189, 6895},
+
+ {193, 6915},
+ {197, 6935}, // PSC Channel (13)
+ {201, 6955},
+ {205, 6975},
+ {209, 6995},
+
+ {213, 7015}, // PSC Channel (14)
+ {217, 7035},
+ {221, 7055},
+ {225, 7075},
+ {229, 7095}, // PSC Channel (15)
+
+ {233, 7115},
+ {237, 7135},
+ {241, 7155},
+ {245, 7175},
+ {249, 7195},
+
+ {253, 7215},
+ };
+
+ const WDI_CHANNEL_MAPPING_ENTRY channelMap60[] = {
+ {1, 58320},
+ {2, 60480},
+ {3, 62640},
+ {4, 64800},
+ {5, 66960},
+ {6, 69120},
+ };
+
+ // clang-format on
+
+ UINT32 ChannelWidth10Mhz = 10;
+ UINT32 ChannelWidth20Mhz = 20;
+ UINT32 channelWidth2160Mhz = 2160;
+ UINT32 pChannelWidth6Ghz[] = { 20, 40, 80, 160, 320 };
+
+ WIFI_BAND_INFO BandInfo[4] = {}; // Upto 4 bands
+ UINT32 bandInfoCount = 0;
+
+ if (m_SupportedBands & WDI_BAND_ID_2400)
+ {
+ BandInfo[bandInfoCount].BandID = WDI_BAND_ID_2400;
+ BandInfo[bandInfoCount].BandState = TRUE;
+ BandInfo[bandInfoCount].NumValidPhyTypes = ARRAYSIZE(Phy24GHz);
+ BandInfo[bandInfoCount].ValidPhyTypeList = const_cast<WDI_PHY_TYPE*>(Phy24GHz);
+ BandInfo[bandInfoCount].NumValidChannelTypes = ARRAYSIZE(ChannelMap24);
+ BandInfo[bandInfoCount].ValidChannelTypes = const_cast<WDI_CHANNEL_MAPPING_ENTRY*>(ChannelMap24);
+ BandInfo[bandInfoCount].NumChannelWidths = 1;
+ BandInfo[bandInfoCount].ChannelWidthList = &ChannelWidth10Mhz;
+ bandInfoCount++;
+ }
+ NT_ASSERT(bandInfoCount <= 1);
+
+ if (m_SupportedBands & WDI_BAND_ID_5000)
+ {
+ BandInfo[bandInfoCount].BandID = WDI_BAND_ID_5000;
+ BandInfo[bandInfoCount].BandState = TRUE;
+ BandInfo[bandInfoCount].NumValidPhyTypes = ARRAYSIZE(Phy5GHz);
+ BandInfo[bandInfoCount].ValidPhyTypeList = const_cast<WDI_PHY_TYPE*>(Phy5GHz);
+ BandInfo[bandInfoCount].NumValidChannelTypes = ARRAYSIZE(ChannelMap5);
+ BandInfo[bandInfoCount].ValidChannelTypes = const_cast<WDI_CHANNEL_MAPPING_ENTRY*>(ChannelMap5);
+ BandInfo[bandInfoCount].NumChannelWidths = 1;
+ BandInfo[bandInfoCount].ChannelWidthList = &ChannelWidth20Mhz;
+ bandInfoCount++;
+ }
+ NT_ASSERT(bandInfoCount <= 2);
+
+ if (m_SupportedBands & WDI_BAND_ID_6000)
+ {
+ BandInfo[bandInfoCount].BandID = WDI_BAND_ID_6000; // 6
+ BandInfo[bandInfoCount].BandState = TRUE;
+ BandInfo[bandInfoCount].NumValidPhyTypes = ARRAYSIZE(Phy6GHz);
+ BandInfo[bandInfoCount].ValidPhyTypeList = const_cast<WDI_PHY_TYPE*>(Phy6GHz);
+ BandInfo[bandInfoCount].NumValidChannelTypes = ARRAYSIZE(channelMap6);
+ BandInfo[bandInfoCount].ValidChannelTypes = const_cast<WDI_CHANNEL_MAPPING_ENTRY*>(channelMap6);
+ BandInfo[bandInfoCount].NumChannelWidths = ARRAYSIZE(pChannelWidth6Ghz);
+ BandInfo[bandInfoCount].ChannelWidthList = pChannelWidth6Ghz;
+ bandInfoCount++;
+ }
+
+ NT_ASSERT(bandInfoCount <= 3);
+ if (m_SupportedBands & WDI_BAND_ID_60000)
+ {
+ BandInfo[bandInfoCount].BandID = WDI_BAND_ID_60000; // 60
+ BandInfo[bandInfoCount].BandState = TRUE;
+ BandInfo[bandInfoCount].NumValidPhyTypes = ARRAYSIZE(pPhy60GHz);
+ BandInfo[bandInfoCount].ValidPhyTypeList = const_cast<WDI_PHY_TYPE*>(pPhy60GHz);
+ BandInfo[bandInfoCount].NumValidChannelTypes = ARRAYSIZE(channelMap60);
+ BandInfo[bandInfoCount].ValidChannelTypes = const_cast<WDI_CHANNEL_MAPPING_ENTRY*>(channelMap60);
+ BandInfo[bandInfoCount].NumChannelWidths = 1;
+ BandInfo[bandInfoCount].ChannelWidthList = &channelWidth2160Mhz;
+ bandInfoCount++;
+ }
+ NT_ASSERT(bandInfoCount <= 4);
+
+ BandCaps.NumBands = bandInfoCount;
+ BandCaps.BandInfoList = BandInfo;
+
+ WX_RETURN_NTSTATUS_IF_NOT_NT_SUCCESS_MSG(
+ WifiDeviceSetBandCapabilities(Device, &BandCaps),
+ "Failed to set band capabilities");
+
+ WIFI_PHY_CAPABILITIES PhyCaps = {};
+ WIFI_PHY_CAPABILITIES_INIT(&PhyCaps);
+
+ WIFI_PHY_INFO PhyInfoList[3];
+
+ const WDI_DATA_RATE_ENTRY DataRateListErp[] = {
+ {WDI_DATA_RATE_RX_RATE | WDI_DATA_RATE_TX_RATE, 2},
+ {WDI_DATA_RATE_RX_RATE | WDI_DATA_RATE_TX_RATE, 4},
+ {WDI_DATA_RATE_RX_RATE | WDI_DATA_RATE_TX_RATE, 22},
+ {WDI_DATA_RATE_RX_RATE | WDI_DATA_RATE_TX_RATE, 108} };
+ const WDI_DATA_RATE_ENTRY DataRateListOfdm[] = {
+ {WDI_DATA_RATE_RX_RATE | WDI_DATA_RATE_TX_RATE, 2}, {WDI_DATA_RATE_RX_RATE | WDI_DATA_RATE_TX_RATE, 108} };
+ const WDI_DATA_RATE_ENTRY DataRateListEht[] = {
+ {WDI_DATA_RATE_RX_RATE | WDI_DATA_RATE_TX_RATE, 2}, {WDI_DATA_RATE_RX_RATE | WDI_DATA_RATE_TX_RATE, 108} };
+
+ PhyInfoList[0].PhyType = WDI_PHY_TYPE_ERP;
+ PhyInfoList[0].NumberDataRateEntries = ARRAYSIZE(DataRateListErp);
+ RtlCopyMemory(&PhyInfoList[0].DataRateList, &DataRateListErp, sizeof(DataRateListErp));
+
+ PhyInfoList[1].PhyType = WDI_PHY_TYPE_HE;
+ PhyInfoList[1].NumberDataRateEntries = ARRAYSIZE(DataRateListOfdm);
+ RtlCopyMemory(&PhyInfoList[1].DataRateList, &DataRateListOfdm, sizeof(DataRateListOfdm));
+
+ PhyInfoList[2].PhyType = WDI_PHY_TYPE_EHT;
+ PhyInfoList[2].NumberDataRateEntries = ARRAYSIZE(DataRateListEht);
+ RtlCopyMemory(&PhyInfoList[2].DataRateList, &DataRateListEht, sizeof(DataRateListEht));
+
+ PhyCaps.NumPhyTypes = ARRAYSIZE(PhyInfoList);
+ PhyCaps.PhyInfoList = PhyInfoList;
+
+ WX_RETURN_NTSTATUS_IF_NOT_NT_SUCCESS_MSG(
+ WifiDeviceSetPhyCapabilities(Device, &PhyCaps),
+ "Failed to set PHY capabilities");
+
+ return STATUS_SUCCESS;
+}
+
+NTSTATUS WifiHAL::WifiIhvReset(WDFDEVICE Device, const WDI_TASK_DOT11_RESET_PARAMETERS& ResetParameters, const PWDI_MESSAGE_HEADER pWdiHeader, PCTLV_CONTEXT)
+{
+ if (0 == ResetParameters.Optional.ResetMACAddress_IsPresent)
+ {
+ WFCTrace("DOT11 Reset, set default MIB = %d, no MAC Address specified\n", ResetParameters.Dot11ResetParameters.SetDefaultMIB);
+ }
+ else
+ {
+ WFCTrace(
+ "DOT11 Reset, set default MIB = %d, MAC Address = %2x:%2x:%2x:%2x:%2x:%2x\n",
+ ResetParameters.Dot11ResetParameters.SetDefaultMIB,
+ ResetParameters.ResetMACAddress.Address[0],
+ ResetParameters.ResetMACAddress.Address[1],
+ ResetParameters.ResetMACAddress.Address[2],
+ ResetParameters.ResetMACAddress.Address[3],
+ ResetParameters.ResetMACAddress.Address[4],
+ ResetParameters.ResetMACAddress.Address[5]);
+ }
+
+ // Reset the connection ID in case the previous connection attempt did not complete
+ m_LastConnectEntryId = 0;
+ WifiIhvSendIndicationToOs(Device, pWdiHeader, WDI_INDICATION_DOT11_RESET_COMPLETE, pWdiHeader->TransactionId, nullptr, 0);
+
+ return STATUS_SUCCESS;
+}
+
+_Use_decl_annotations_
+NTSTATUS WifiHAL::WifiIhvSetRadioState(WDFDEVICE Device, const WDI_SET_RADIO_STATE_PARAMETERS& RadioState, const PWDI_MESSAGE_HEADER pWdiHeader, PCTLV_CONTEXT Context)
+{
+ if (RadioState.SoftwareRadioState != m_CurrentRadioState)
+ {
+ // Change the radio state
+ m_CurrentRadioState = RadioState.SoftwareRadioState;
+
+ // Send the radio state indication
+ WDI_INDICATION_RADIO_STATUS_PARAMETERS RadioStatusParams = {};
+ UINT8* pOutput = nullptr;
+ ULONG cbOutput = 0;
+
+ RadioStatusParams.RadioState.HardwareState = TRUE;
+ RadioStatusParams.RadioState.SoftwareState = m_CurrentRadioState;
+ if (GenerateWdiIndicationRadioStatus(&RadioStatusParams, 0, Context, &cbOutput, &pOutput) == NDIS_STATUS_SUCCESS)
+ {
+ WifiIhvSendIndicationToOs(Device, pWdiHeader, WDI_INDICATION_RADIO_STATUS, 0, pOutput, cbOutput);
+ FreeGenerated(pOutput);
+ }
+ }
+
+ WifiIhvSendIndicationToOs(Device, pWdiHeader, WDI_INDICATION_SET_RADIO_STATE_COMPLETE, pWdiHeader->TransactionId, nullptr, 0);
+
+ return STATUS_SUCCESS;
+}
+
+_Use_decl_annotations_
+NTSTATUS WifiHAL::WifiIhvScan(WDFDEVICE Device, WDI_SCAN_PARAMETERS& ScanParameters, const PWDI_MESSAGE_HEADER pWdiHeader, PCTLV_CONTEXT)
+{
+ for (UINT8 connectEntry = 1; connectEntry < ConnectEntryId_MAX; connectEntry++)
+ {
+ if (m_SupportedBands & g_ConnectEntries[connectEntry].BandId)
+ {
+ PUCHAR pBssEntry = g_ConnectEntries[connectEntry].pTlvBssEntry;
+ //
+ // If currently connected, see if the connected entry should be skipped
+ //
+ if ((m_LastConnectEntryId != 0) &&
+ (RtlCompareMemory(&m_ConnectedPeer, &pBssEntry[8], sizeof(DOT11_MAC_ADDRESS)) == sizeof(DOT11_MAC_ADDRESS)))
+ {
+ // Already connected, don't report this entry
+ continue;
+ }
+
+ // TODO: Skip the IHV band as it is not being reported in capabilities
+ if (g_ConnectEntries[connectEntry].BandId == TESTMP_BAND_IHV)
+ {
+ continue;
+ }
+
+ // Send the BSS entry indication
+ WifiIhvSendIndicationToOs(
+ Device,
+ pWdiHeader,
+ WDI_INDICATION_BSS_ENTRY_LIST,
+ 0,
+ g_ConnectEntries[connectEntry].pTlvBssEntry,
+ g_ConnectEntries[connectEntry].TlvBssEntrySize);
+ }
+ }
+
+ //
+ // See if the hidden network needs to be indicated
+ //
+ if ((ScanParameters.SSIDList.ElementCount > 0) && (ScanParameters.SSIDList.pElements[0].ElementCount == 8) &&
+ (ScanParameters.SSIDList.pElements[0].pElements[4] == 'H') && (ScanParameters.SSIDList.pElements[0].pElements[5] == 'I') &&
+ (ScanParameters.SSIDList.pElements[0].pElements[6] == 'D') && (ScanParameters.SSIDList.pElements[0].pElements[7] == 'E'))
+ {
+ WifiIhvSendIndicationToOs(
+ Device, pWdiHeader, WDI_INDICATION_BSS_ENTRY_LIST, 0, s_TLV_BSS_Entry_ProbeResponse_8_Hidden, sizeof(s_TLV_BSS_Entry_ProbeResponse_8_Hidden));
+ }
+
+ WifiIhvSendIndicationToOs(Device, pWdiHeader, WDI_INDICATION_SCAN_COMPLETE, pWdiHeader->TransactionId, nullptr, 0);
+
+ return STATUS_SUCCESS;
+}
+
+NTSTATUS WifiHAL::WifiIhvConnect(WDFDEVICE Device, WDI_TASK_CONNECT_PARAMETERS& ConnectParameters, const PWDI_MESSAGE_HEADER pWdiHeader, PCTLV_CONTEXT)
+{
+ NT_ASSERT(m_LastConnectEntryId == 0);
+ if (m_LastConnectEntryId != 0) // Not Disconnected State
+ {
+#ifdef WIFI_IHV_NETV
+ DeleteDatapathPeer(
+ deviceContext->netAdapters[pWdiHeader->PortId], reinterpret_cast<NET_EUI48_ADDRESS*>(&deviceContext->ConnectedPeer));
+#endif // WIFI_IHV_NETV
+ }
+
+ WX_RETURN_NTSTATUS_IF_NOT_NT_SUCCESS_MSG(WifiIhvPerformAssociation(
+ Device, &ConnectParameters.PreferredBSSEntryList, &ConnectParameters.ConnectParameters.AuthenticationAlgorithms, pWdiHeader),
+ "Failed to perform association");
+
+ //
+ // WPA3-SAE requires the SAE Exchange, so do not complete the Connection request until the SAE exchange is complete
+ //
+ if (WDI_AUTH_ALGO_WPA3_SAE != m_LastAuthAlgo)
+ {
+ WifiIhvSendIndicationToOs(Device, pWdiHeader, WDI_INDICATION_CONNECT_COMPLETE, pWdiHeader->TransactionId, nullptr, 0);
+ }
+
+ return STATUS_SUCCESS;
+}
+
+_Use_decl_annotations_
+NTSTATUS WifiHAL::WifiIhvSendLinkStateIndication(_In_ WDFDEVICE Device, _In_ PWDI_MESSAGE_HEADER pWdiHeader, ULONG numLinks)
+{
+ // Report link quality
+ NTSTATUS ntStatus = STATUS_SUCCESS;
+ PWIFI_IHV_DEVICE_CONTEXT pDeviceContext = WifiGetIhvDeviceContext(Device);
+ WDI_INDICATION_LINK_STATE_CHANGE_PARAMETERS linkStateChangeParameters = {};
+ WDI_LINK_INFO_CONTAINER pLinkInfo[2] = {};
+ UINT8* pOutput = nullptr;
+ ULONG cbOutput = 0;
+
+ RtlCopyMemory(
+ &linkStateChangeParameters.LinkStateChangeParameters.PeerMACAddress, &m_ConnectedPeer, sizeof(DOT11_MAC_ADDRESS));
+ linkStateChangeParameters.LinkStateChangeParameters.TxLinkSpeed = 30000;
+ linkStateChangeParameters.LinkStateChangeParameters.RxLinkSpeed = 30000;
+ linkStateChangeParameters.LinkStateChangeParameters.LinkQuality = 56;
+
+ // Default linkId for non-Mlo connections is 0
+ pLinkInfo[0].LinkID = 0;
+ RtlCopyMemory(&pLinkInfo[0].LocalLinkMACAddress, &m_LocalLinkAddresses[0], sizeof(DOT11_MAC_ADDRESS));
+ RtlCopyMemory(&pLinkInfo[0].PeerLinkMACAddress, &m_ConnectedPeer, sizeof(DOT11_MAC_ADDRESS));
+ pLinkInfo[0].ChannelNumber = 6;
+ pLinkInfo[0].BandId = WDI_BAND_ID_2400;
+ pLinkInfo[0].RSSI = -50;
+ pLinkInfo[0].Bandwidth = 40;
+ pLinkInfo[0].TxMCS = 3;
+ pLinkInfo[0].RxMCS = 4;
+
+ if (numLinks > 1)
+ {
+ // For Mlo connections, set the link ID for the first link to 1
+ pLinkInfo[0].LinkID = 1;
+
+ pLinkInfo[1].LinkID = 2;
+ RtlCopyMemory(&pLinkInfo[1].LocalLinkMACAddress, &m_LocalLinkAddresses[1], sizeof(DOT11_MAC_ADDRESS));
+ RtlCopyMemory(&pLinkInfo[1].PeerLinkMACAddress, &m_ConnectedPeer, sizeof(DOT11_MAC_ADDRESS));
+ pLinkInfo[1].ChannelNumber = 36;
+ pLinkInfo[1].BandId = WDI_BAND_ID_5000;
+ pLinkInfo[1].RSSI = -30;
+ pLinkInfo[1].Bandwidth = 160;
+ pLinkInfo[1].TxMCS = 8;
+ pLinkInfo[1].RxMCS = 9;
+ }
+
+ linkStateChangeParameters.LinkInfo.pElements = pLinkInfo;
+ linkStateChangeParameters.LinkInfo.ElementCount = numLinks > 1 ? 2 : 1;
+
+ ntStatus = GenerateWdiIndicationLinkStateChangeFromIhv(&linkStateChangeParameters, 0, &pDeviceContext->TlvContext, &cbOutput, &pOutput);
+ if (STATUS_SUCCESS == ntStatus)
+ {
+ WifiIhvSendIndicationToOs(Device, pWdiHeader, WDI_INDICATION_LINK_STATE_CHANGE, 0, pOutput, cbOutput);
+ FreeGenerated(pOutput);
+ }
+ else
+ {
+ WFCError("Failed to generate WDI_INDICATION_LINK_STATE_CHANGE - 0x%08x\n", ntStatus);
+ }
+
+ return ntStatus;
+}
+
+_Use_decl_annotations_
+NTSTATUS WifiHAL::WifiIhvPerformAssociation(
+ WDFDEVICE Device,
+ struct ArrayOfElements<WDI_CONNECT_BSS_ENTRY_CONTAINER>* pPreferredBSSEntryList,
+ struct ArrayOfElements<WDI_AUTH_ALGORITHM>* pAuthenticationAlgorithms,
+ PWDI_MESSAGE_HEADER pWdiHeader)
+{
+
+ ULONG bssIndex = 0;
+ ULONG connectEntry = ConnectEntryId_MAX;
+ NTSTATUS ntStatus = STATUS_SUCCESS;
+ UINT32 NewConnectEntryId = 0; // Disconnected State
+ WDI_AUTH_ALGORITHM NewAuthAlgo = pAuthenticationAlgorithms->pElements[0];
+ UCHAR pucData[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0xA, 0xB, 0xC, 0xD, 0xE, 0xF, 0x10 };
+#ifdef WIFI_IHV_NETV
+ WifiNetvDevice* pDeviceContext = WifiNetvDeviceGetContext(Device);
+#else
+ PWIFI_IHV_DEVICE_CONTEXT pDeviceContext = WifiGetIhvDeviceContext(Device);
+#endif // WIFI_IHV_NETV
+ ULONG assocStatus = WDI_ASSOC_STATUS_SUCCESS;
+
+ do
+ {
+ // We search for the BSSID pattern to figure out what AP we are trying to connect to
+ for (bssIndex = 0; bssIndex < pPreferredBSSEntryList->ElementCount; bssIndex++)
+ {
+ for (connectEntry = 1; connectEntry < ConnectEntryId_MAX; connectEntry++)
+ {
+ if (RtlCompareMemory(
+ pPreferredBSSEntryList->pElements[bssIndex].BSSID.Address,
+ g_ConnectEntries[connectEntry].pMacAddress,
+ sizeof(DOT11_MAC_ADDRESS)) == sizeof(DOT11_MAC_ADDRESS))
+ {
+ PUCHAR pAssociationResult = g_ConnectEntries[connectEntry].pTlvAssociationResult;
+
+ NewConnectEntryId = connectEntry;
+ m_LastConnectTransactionId = pWdiHeader->TransactionId;
+#ifdef WIFI_IHV_NETV
+ // add peer on datapath
+ AddDatapathPeer(pDeviceContext->netAdapters[pWdiHeader->PortId],
+ reinterpret_cast<NET_EUI48_ADDRESS*>(g_ConnectEntries[connectEntry].pMacAddress));
+#endif // WIFI_IHV_NETV
+
+#ifdef WIFI_IHV_HANDSHAKE
+ // Pretend to recieve M1 on datapath before, the association complete has made it up the control path.
+ RecieveDatapathFrame(0x33, sizeof(pucData), pucData);
+#endif // WIFI_IHV_HANDSHAKE
+
+ if (NewAuthAlgo == WDI_AUTH_ALGO_WPA3_SAE)
+ {
+ WDI_INDICATION_SAE_AUTH_PARAMS_NEEDED_PARAMETERS SAEAuthParamsNeeded;
+ UINT8* pOutput = nullptr;
+ ULONG cbOutput = 0;
+ NDIS_STATUS ndisStatus = NDIS_STATUS_SUCCESS;
+
+ //
+ // Handle special case for WPA3-SAE
+ // Send the Indication to request additonal SAE params
+ //
+ g_dwSaeResendConfirmRequested = 0;
+ SAEAuthParamsNeeded.SAEIndicationType = WDI_SAE_INDICATION_TYPE_COMMIT_REQUEST_PARAMS_NEEDED;
+ RtlCopyMemory(
+ SAEAuthParamsNeeded.BssId.Address, g_ConnectEntries[connectEntry].pMacAddress, sizeof(DOT11_MAC_ADDRESS));
+
+ ndisStatus = GenerateWdiIndicationSaeAuthParamsNeeded(
+ &SAEAuthParamsNeeded, 0, &pDeviceContext->TlvContext, &cbOutput, &pOutput);
+ if (ndisStatus == NDIS_STATUS_SUCCESS)
+ {
+ WFCInfo("[SAE] Indicating request for COMMIT_REQUEST_PARAMS_NEEDED ...");
+
+ WifiIhvSendIndicationToOs(Device, pWdiHeader, WDI_INDICATION_SAE_AUTH_PARAMS_NEEDED, 0, pOutput, cbOutput);
+
+ FreeGenerated(pOutput);
+
+ break;
+ }
+ }
+
+ // Get the assoc status
+ RtlCopyMemory(&assocStatus, &pAssociationResult[18], sizeof(ULONG));
+
+ // Send the association indication
+ WifiIhvSendIndicationToOs(
+ Device,
+ pWdiHeader,
+ WDI_INDICATION_ASSOCIATION_RESULT,
+ 0,
+ g_ConnectEntries[connectEntry].pTlvAssociationResult,
+ g_ConnectEntries[connectEntry].TlvAssociationResultSize);
+
+ break;
+ }
+ }
+
+ // If we found a matching BSSID entry, we are done
+ if (connectEntry < ConnectEntryId_MAX)
+ {
+ break;
+ }
+ }
+
+ } while (FALSE);
+
+ if (WDI_ASSOC_STATUS_SUCCESS != assocStatus || 0 == NewConnectEntryId || bssIndex >= pPreferredBSSEntryList->ElementCount)
+ {
+ NewConnectEntryId = 0; // Disconnected State
+ NewAuthAlgo = WDI_AUTH_ALGO_80211_OPEN;
+ ntStatus = STATUS_UNSUCCESSFUL;
+ }
+ else
+ {
+ RtlCopyMemory(&m_ConnectedPeer, pPreferredBSSEntryList->pElements[bssIndex].BSSID.Address, sizeof(DOT11_MAC_ADDRESS));
+ }
+
+ m_LastConnectEntryId = NewConnectEntryId;
+ m_LastAuthAlgo = NewAuthAlgo;
+
+ if (STATUS_SUCCESS == ntStatus && (WDI_AUTH_ALGO_WPA3_SAE != m_LastAuthAlgo))
+ {
+ // Report link quality
+ ntStatus = WifiIhvSendLinkStateIndication(Device, pWdiHeader, 2);
+ }
+
+ return ntStatus;
+}
+
+NTSTATUS WifiHAL::WifiIhvSetSaeAuthParams(WDFDEVICE Device, const WDI_SET_SAE_AUTH_PARAMS_COMMAND& setSAEAuthParams, const PWDI_MESSAGE_HEADER pWdiHeader, PCTLV_CONTEXT Context)
+{
+ WDI_INDICATION_SAE_AUTH_PARAMS_NEEDED_PARAMETERS SAEAuthParamsNeeded{};
+ UINT8* pOutput = nullptr;
+ ULONG cbOutput = 0;
+
+ // Commit frame when Status = 0: FiniteCyclicGroup + Scalar + Element
+ // Commit frame when Status = 76: FiniteCyclicGroup + AntiCloggingToken
+ WFCInfo("WDI_SET_SAE_AUTH_PARAMS called!!!\n");
+ if (WDI_SAE_REQUEST_TYPE_COMMIT_PARAMS == setSAEAuthParams.SAERequestType)
+ {
+ WFCInfo("[SAE] WDI_SET_SAE_AUTH_PARAMS has Commit request for Tx, Setting CommitResponse for Rx\n");
+
+ SAEAuthParamsNeeded.SAEIndicationType = WDI_SAE_INDICATION_TYPE_COMMIT_FRAME;
+ SAEAuthParamsNeeded.Optional.SAECommitFrame_IsPresent = 1;
+
+ //
+ // Send reflection attack first
+ //
+ SAEAuthParamsNeeded.SAECommitFrame.ElementCount = sizeof(pucSAECommitResponseReflection);
+ SAEAuthParamsNeeded.SAECommitFrame.pElements = pucSAECommitResponseReflection;
+ }
+ else if (
+ (WDI_SAE_REQUEST_TYPE_FAILURE == setSAEAuthParams.SAERequestType) &&
+ (WDI_SAE_STATUS_COMMIT_MESSAGE_REFLECTION_ATTACK_DETECTED == setSAEAuthParams.SAEStatus))
+ {
+ WFCInfo("[SAE] WDI_SET_SAE_AUTH_PARAMS returned Reflection error -- Inidicate proper CommitResponse for Rx\n");
+
+ SAEAuthParamsNeeded.SAEIndicationType = WDI_SAE_INDICATION_TYPE_CONFIRM_FRAME;
+ SAEAuthParamsNeeded.Optional.SAECommitFrame_IsPresent = 1;
+ SAEAuthParamsNeeded.SAECommitFrame.ElementCount = sizeof(pucSAECommitResponse);
+ SAEAuthParamsNeeded.SAECommitFrame.pElements = pucSAECommitResponse;
+ }
+ else if (WDI_SAE_REQUEST_TYPE_CONFIRM_PARAMS == setSAEAuthParams.SAERequestType)
+ {
+ WFCInfo("[SAE] WDI_SET_SAE_AUTH_PARAMS has Confirm request for Tx, Setting ConfirmResponse for Rx\n");
+
+ if (g_dwSaeResendConfirmRequested)
+ {
+ SAEAuthParamsNeeded.SAEIndicationType = WDI_SAE_INDICATION_TYPE_CONFIRM_FRAME;
+ SAEAuthParamsNeeded.Optional.SAECommitFrame_IsPresent = 1;
+ SAEAuthParamsNeeded.SAECommitFrame.ElementCount = sizeof(pucSAEConfirmResponse);
+ SAEAuthParamsNeeded.SAECommitFrame.pElements = pucSAEConfirmResponse;
+ }
+ else
+ {
+ g_dwSaeResendConfirmRequested = 1;
+
+ SAEAuthParamsNeeded.SAEIndicationType = WDI_SAE_INDICATION_TYPE_CONFIRM_REQUEST_RESEND_REQUEST;
+ }
+ }
+ else
+ {
+ if (WDI_SAE_REQUEST_TYPE_FAILURE == setSAEAuthParams.SAERequestType)
+ {
+ WFCInfo("[SAE] OID_WDI_SET_SAE_AUTH_PARAMS has indicated error - %d\n", setSAEAuthParams.SAEStatus);
+ }
+ else if (WDI_SAE_REQUEST_TYPE_SUCCESS == setSAEAuthParams.SAERequestType)
+ {
+ WFCInfo("[SAE] OID_WDI_SET_SAE_AUTH_PARAMS has indicated SAE success - %d\n", setSAEAuthParams.SAEStatus);
+ }
+ else
+ {
+ WFCInfo("[SAE] OID_WDI_SET_SAE_AUTH_PARAMS has set INVALID Request type = %d\n", setSAEAuthParams.SAERequestType);
+ }
+
+ // Send the association indication
+ // This assumes that the association result fields are in the right order
+ if (WDI_AUTH_ALGO_WPA3_SAE == m_LastAuthAlgo)
+ {
+ g_ConnectEntries[m_LastConnectEntryId].pTlvAssociationResult[27] = (UCHAR)WDI_AUTH_ALGO_WPA3_SAE;
+ }
+ else
+ {
+ g_ConnectEntries[m_LastConnectEntryId].pTlvAssociationResult[27] = (UCHAR)WDI_AUTH_ALGO_RSNA_PSK;
+ }
+
+ WifiIhvSendIndicationToOs(
+ Device,
+ pWdiHeader,
+ WDI_INDICATION_ASSOCIATION_RESULT,
+ 0,
+ g_ConnectEntries[m_LastConnectEntryId].pTlvAssociationResult,
+ g_ConnectEntries[m_LastConnectEntryId].TlvAssociationResultSize);
+ RtlCopyMemory(&m_ConnectedPeer, &g_ConnectEntries[m_LastConnectEntryId].pMacAddress, sizeof(DOT11_MAC_ADDRESS));
+
+ // Report link quality
+ WX_RETURN_NTSTATUS_IF_NOT_NT_SUCCESS_MSG(WifiIhvSendLinkStateIndication(Device, pWdiHeader, 1),
+ "Failed WifiIhvSendLinkStateIndication");
+
+ WifiIhvSendIndicationToOs(
+ Device, pWdiHeader, WDI_INDICATION_CONNECT_COMPLETE, m_LastConnectTransactionId, nullptr, 0);
+#ifdef WIFI_IHV_HANDSHAKE
+ //
+ // Receive M1 frame of 4-way handshake
+ //
+ RecieveDatapathFrame(0x33, sizeof(pucM1SaeFrame), pucM1SaeFrame);
+
+ //
+ // Receive M3 frame of 4-way handshake
+ //
+ RecieveDatapathFrame(0x33, sizeof(pucM3SaeFrame), pucM3SaeFrame);
+#endif
+ }
+
+ RtlCopyMemory(SAEAuthParamsNeeded.BssId.Address, &g_ConnectEntries[m_LastConnectEntryId].pMacAddress, sizeof(DOT11_MAC_ADDRESS));
+
+ auto ndisStatus =
+ GenerateWdiIndicationSaeAuthParamsNeeded(&SAEAuthParamsNeeded, 0, Context, &cbOutput, &pOutput);
+ if (ndisStatus == NDIS_STATUS_SUCCESS)
+ {
+ WifiIhvSendIndicationToOs(Device, pWdiHeader, WDI_INDICATION_SAE_AUTH_PARAMS_NEEDED, 0, pOutput, cbOutput);
+
+ FreeGenerated(pOutput);
+ }
+ else
+ {
+ WFCError("Failed to generate WDI_INDICATION_SAE_AUTH_PARAMS_NEEDED - 0x%08x\n", ndisStatus);
+ }
+
+ return STATUS_SUCCESS;
+}
+
+_Use_decl_annotations_
+void WifiHAL::WifiIhvPerformDisassociation(_In_ WDFDEVICE Device, _In_ PWDI_MESSAGE_HEADER pWdiHeader, _In_ WDI_ASSOC_STATUS DisassocStatus)
+{
+ UCHAR s_TLV_Disassociation[] =
+ {
+ // WDI_TLV_ASSOCIATION_RESULT
+ 0xBC, 0x00,
+ 0x0A, 0x00,
+
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00,
+
+ // WDI_TLV Need Peer Cleanup Params
+ 0xb4, 0x00,
+ 0x01, 0x00,
+
+ 0x00
+ };
+
+ RtlCopyMemory(&s_TLV_Disassociation[4], &m_ConnectedPeer, sizeof(DOT11_MAC_ADDRESS));
+ RtlCopyMemory(&s_TLV_Disassociation[10], &DisassocStatus, sizeof(ULONG));
+
+ // Send the disassociation indication
+ WifiIhvSendIndicationToOs(Device, pWdiHeader, WDI_INDICATION_DISASSOCIATION, 0, s_TLV_Disassociation, sizeof(s_TLV_Disassociation));
+
+ m_LastConnectEntryId = 0; // Disconnected State
+
+#ifdef WIFI_IHV_NETV
+ DeleteDatapathPeer(0x33);
+#endif
+
+ WifiIhvSendIndicationToOs(Device, pWdiHeader, WDI_INDICATION_DISCONNECT_COMPLETE, pWdiHeader->TransactionId, nullptr, 0);
+} \ No newline at end of file