diff options
| author | Daiqian Hu <[email protected]> | 2016-11-21 08:54:24 +0800 |
|---|---|---|
| committer | Daiqian Hu <[email protected]> | 2016-11-21 08:54:24 +0800 |
| commit | a95eaad088f61aa55da9d73015cf1ed86e64a67e (patch) | |
| tree | 15b498a08a4aee4b7f8b1627d39c965b3aa3ba98 /network/wlan/WDI/PLATFORM/NDIS6/WDI_Common.c | |
| parent | 1aa0338ec5418345ea0c383e92b4fa19f7c98425 (diff) | |
Re-submit for WDI sample driver to GitHub
Submit WDI sample driver to GitHub for RS1.
Diffstat (limited to 'network/wlan/WDI/PLATFORM/NDIS6/WDI_Common.c')
| -rw-r--r-- | network/wlan/WDI/PLATFORM/NDIS6/WDI_Common.c | 2843 |
1 files changed, 2843 insertions, 0 deletions
diff --git a/network/wlan/WDI/PLATFORM/NDIS6/WDI_Common.c b/network/wlan/WDI/PLATFORM/NDIS6/WDI_Common.c new file mode 100644 index 00000000..1b478b21 --- /dev/null +++ b/network/wlan/WDI/PLATFORM/NDIS6/WDI_Common.c @@ -0,0 +1,2843 @@ +#include "MP_Precomp.h" + +#if WPP_SOFTWARE_TRACE +#include "WDI_Common.tmh" +#endif + +#if (WDI_SUPPORT == 1) + +VOID +wdi_UnsolicitedIndication( + IN PADAPTER pAdapter, + IN BOOLEAN bAdapterObj, + IN PVOID pRequestId, + IN ULONG Indication, + IN NDIS_STATUS status, + IN PUCHAR pInput, + IN ULONG Length + ) +{ + PRT_GEN_TEMP_BUFFER pGenBuffer = NULL; + pu1Byte pIndicateBuffer = NULL; + NDIS_STATUS_INDICATION *indic = NULL; + WDI_MESSAGE_HEADER *wdiHdr = NULL; + NDIS_OID_REQUEST *req = NULL; + + RT_TRACE(COMP_MLME, DBG_LOUD, ("==>wdi_UnsolicitedIndication(): status indication code = %x, length=%d\n", Indication, Length)); + + indic = (NDIS_STATUS_INDICATION *)pInput; + wdiHdr = (WDI_MESSAGE_HEADER *)(pInput + sizeof(*indic)); + + // indication data + PlatformZeroMemory(indic, sizeof(*indic)); + indic->Header.Type = NDIS_OBJECT_TYPE_STATUS_INDICATION; + indic->Header.Size = NDIS_SIZEOF_STATUS_INDICATION_REVISION_1; + indic->Header.Revision = NDIS_STATUS_INDICATION_REVISION_1; + indic->RequestId = pRequestId; + indic->SourceHandle = pAdapter; + indic->PortNumber = 0; + indic->StatusCode = Indication; + indic->StatusBuffer = wdiHdr; + indic->StatusBufferSize = Length - sizeof(*indic); + + // wdi message header + PlatformZeroMemory(wdiHdr, sizeof(*wdiHdr)); + if( bAdapterObj == TRUE ) + { + wdiHdr->PortId = WDI_PORT_ANY; + } + else + { + wdiHdr->PortId = (WDI_PORT_ID)GET_PORT_NUMBER(pAdapter); + } + wdiHdr->Reserved = 0; + wdiHdr->Status = status; + wdiHdr->TransactionId = 0; + wdiHdr->IhvSpecificId = 0; + + NdisMIndicateStatusEx( + pAdapter->pNdisCommon->hNdisAdapter, + indic + ); + + RT_TRACE(COMP_MLME, DBG_LOUD, ("<== wdi_UnsolicitedIndication()\n")); +} + +// +// The following helper functions are used to determined if a +// BSS has the capability of specific wireless mode. +// 2005.01.13, by rcnjko. +// +BOOLEAN +WDIWithWirelessB( + PRT_WLAN_BSS pRtBss) +{ + u2Byte i; + u1Byte rate; + + // Check channels. + if(pRtBss->ChannelNumber > 14) + { + return FALSE; + } + + // Check supported rates. + for(i = 0; i < pRtBss->bdSupportRateEXLen; i++) + { + rate = pRtBss->bdSupportRateEXBuf[i] & 0x7f; + if( MgntIsRateValidForWirelessMode(rate, WIRELESS_MODE_B) ) + { + return TRUE; + } + } + + return FALSE; +} + +BOOLEAN +WDIWithWirelessG( + PRT_WLAN_BSS pRtBss) +{ + u2Byte i; + u1Byte rate; + + // Check channels. + if(pRtBss->ChannelNumber > 14) + { + return FALSE; + } + + // Check supported rates. + for(i = 0; i < pRtBss->bdSupportRateEXLen; i++) + { + rate = pRtBss->bdSupportRateEXBuf[i] & 0x7f; + if( MgntIsRateValidForWirelessMode(rate, WIRELESS_MODE_G) && + !MgntIsRateValidForWirelessMode(rate, WIRELESS_MODE_B) ) + { + return TRUE; + } + } + + // Check if it contains ERP information element. + // <NOTE> Some AP, WAG-302, will not always claim OFDM rates in their ProbeRsp or Beacon + // but it is in G mode. 2005.08.23, by rcnjko. + if(pRtBss->bERPInfoValid) + { + return TRUE; + } + + return FALSE; +} + +BOOLEAN +WDIWithWirelessA( + PRT_WLAN_BSS pRtBss) +{ + u2Byte i; + u1Byte rate; + + // Check channels. + if(pRtBss->ChannelNumber <= 14 || + pRtBss->ChannelNumber > 184 ) + { + return FALSE; + } + + // Check supported rates. + for(i = 0; i < pRtBss->bdSupportRateEXLen; i++) + { + rate = pRtBss->bdSupportRateEXBuf[i] & 0x7f; + if( MgntIsRateValidForWirelessMode(rate, WIRELESS_MODE_A) ) + { + return TRUE; + } + } + + return FALSE; +} + +//// +// This routine determine if we should report the BSS scanned +// to upper layer. +// 2005.01.13, by rcnjko. +// +BOOLEAN +WDIFilterRtBss( + PADAPTER Adapter, + PRT_WLAN_BSS pRtBss + ) +{ + PRT_NDIS6_COMMON pNdisCommon = Adapter->pNdisCommon; + BOOLEAN bAcceptable = TRUE; + BOOLEAN bHasB, bHasG, bHasA; + + // Determine the capability of wireless mode of the BSS. + bHasB = WDIWithWirelessB(pRtBss); + bHasG = WDIWithWirelessG(pRtBss); + bHasA = WDIWithWirelessA(pRtBss); + + // <RJ_TODO> + // 1. Maybe we may need to use a table in the future. + // 2. Currently, we only consider B/G case. + if( bHasB && !bHasG && !bHasA ) + { // The BSS is pure B. + if( pNdisCommon->RegWirelessMode4ScanList == WIRELESS_MODE_G || + pNdisCommon->RegWirelessMode4ScanList == WIRELESS_MODE_A ) + { // We are pure A or pure G. + bAcceptable = FALSE; + } + } + + if(pRtBss->IE.Length <= sizeof(RT_FIXED_IE_FIELD)) + bAcceptable = FALSE; + + return bAcceptable; +} + +static +VOID +wdiext_IndicateP2PDeviceFound( + IN ADAPTER *pAdapter, + IN VOID *pvDev + ) +{ + WDI_INDICATION_BSS_ENTRY_LIST_PARAMETERS param; + WDI_BSS_ENTRY_CONTAINER entry; + LARGE_INTEGER CurrentTime; + + P2P_DEV_LIST_ENTRY *dev = (P2P_DEV_LIST_ENTRY *)pvDev; + P2P_FRAME_INFO *finfo = NULL; + + u1Byte *buf = NULL; + ULONG buflen = 0; + + NDIS_OID_REQUEST *req = NULL; + WDI_MESSAGE_HEADER *reqWdiHdr = NULL; + + u4Byte devSpecCtx = 0x07060504; + + // get info of last rx frame + if(RTIsListEmpty(&dev->rxFrameQ)) + return; + + if(!pAdapter->pPortCommonInfo->WdiData.TaskHandle.pNdisRequest) + return; + + req = pAdapter->pPortCommonInfo->WdiData.TaskHandle.pNdisRequest; + reqWdiHdr = (WDI_MESSAGE_HEADER *)req->DATA.METHOD_INFORMATION.InformationBuffer; + + finfo = (P2P_FRAME_INFO *)RTGetTailList(&dev->rxFrameQ); + + // zero + PlatformZeroMemory(¶m, sizeof(param)); + PlatformZeroMemory(&entry, sizeof(entry)); + + // optional + param.Optional.DeviceDescriptor_IsPresent = TRUE; + + // ArrayOfElementsOfWIFI_BSS_ENTRY_CONTAINER DeviceDescriptor + param.DeviceDescriptor.ElementCount = 1; + param.DeviceDescriptor.pElements = &entry; + + // WIFI_MAC_ADDRESS_CONTAINER BSSID + cpMacAddr(entry.BSSID.Address, finfo->msg->bssid); + + // Get current timestamp + NdisGetCurrentSystemTime(&CurrentTime); + + // WIFI_BYTE_BLOB ProbeResponseFrame, BeaconFrame + if(P2P_FID_BEACON == finfo->type) + { + entry.Optional.BeaconFrame_IsPresent = TRUE; + entry.BeaconFrame.ElementCount = finfo->frameLen - sMacHdrLng; + entry.BeaconFrame.pElements = (UINT8 *)finfo->frame + sMacHdrLng; + } + else if(P2P_FID_PROBE_RSP == finfo->type) + { + entry.Optional.ProbeResponseFrame_IsPresent = TRUE; + entry.ProbeResponseFrame.ElementCount = finfo->frameLen - sMacHdrLng; + entry.ProbeResponseFrame.pElements = (UINT8 *)finfo->frame + sMacHdrLng; + } + else + return; + + // WDI_SIGNAL_INFO_CONTAINER SignalInfo + entry.SignalInfo.RSSI = (INT32)(((finfo->sigStrength + 1) >> 1) - 95); + entry.SignalInfo.LinkQuality = finfo->sigStrength; + + // WDI_CHANNEL_INFO_CONTAINER ChannelInfo + entry.ChannelInfo.ChannelNumber = finfo->channel; + entry.ChannelInfo.BandId = (finfo->channel < 36) ? WDI_BAND_ID_2400 : WDI_BAND_ID_5000; + + // WDI_BYTE_BLOB DeviceSpecificContext, this is OPTIONAL + entry.Optional.DeviceSpecificContext_IsPresent = TRUE; + entry.DeviceSpecificContext.ElementCount = sizeof(devSpecCtx); + entry.DeviceSpecificContext.pElements = (UINT8 *)&devSpecCtx; + + // WDI_AGE_INFO_CONTAINER EntryAgeInfo + entry.EntryAgeInfo.HostTimeStamp = CurrentTime.QuadPart;// [SDIO-482] in JIRA + entry.EntryAgeInfo.CachedInformation = 0; + + // Gen tlv + if(NDIS_STATUS_SUCCESS != GenerateWdiIndicationBssEntryList( + ¶m, + sizeof(NDIS_STATUS_INDICATION) + sizeof(WDI_MESSAGE_HEADER), + &pAdapter->pPortCommonInfo->WdiData.TlvContext, + &buflen, &((UINT8 *)buf))) + return; + + wdi_UnsolicitedIndication(pAdapter, + FALSE, + (PVOID)req->RequestId, + NDIS_STATUS_WDI_INDICATION_BSS_ENTRY_LIST, + NDIS_STATUS_SUCCESS, + buf, + buflen); + + // cleanup + FreeGenerated((UINT8 *)buf); + + return; +} + +VOID +wdiext_IndicateP2PActionFrameReceived( + IN VOID *pvP2PInfo, + IN u4Byte eid, + IN MEMORY_BUFFER *info + ) +{ + P2P_INFO *pP2PInfo = (P2P_INFO *)pvP2PInfo; + ADAPTER *pAdapter = pP2PInfo->pAdapter; + + P2P_EVENT_DATA *evtData = (P2P_EVENT_DATA *)info->Buffer; + u4Byte ieOffset = FRAME_OFFSET_P2P_PUB_ACT_ELEMENTS; + RT_STATUS rtStatus = RT_STATUS_SUCCESS; + NDIS_STATUS status = NDIS_STATUS_SUCCESS; + + u1Byte *buf = NULL; + ULONG buflen = 0; + + WDI_INDICATION_P2P_ACTION_FRAME_RECEIVED_PARAMETERS param = {0}; + + FunctionIn(COMP_OID_SET); + + // prepare structure, ref N63CIndicateReceivedInvitationResponse + rtStatus = (ieOffset < evtData->Packet.Length) ? RT_STATUS_SUCCESS : evtData->rtStatus; + status = NdisStatusFromRtStatus(rtStatus); + + if(NDIS_STATUS_SUCCESS == status) + { + param.FrameInfo.Optional.DeviceContext_IsPresent = FALSE; + + if(P2P_EVENT_RECEIVED_PROVISION_DISCOVERY_REQUEST == eid) + param.FrameInfo.FrameParams.ActionFrameType = WDI_P2P_ACTION_FRAME_PROVISION_DISCOVERY_REQUEST; + else if(P2P_EVENT_RECEIVED_PROVISION_DISCOVERY_RESPONSE == eid) + param.FrameInfo.FrameParams.ActionFrameType = WDI_P2P_ACTION_FRAME_PROVISION_DISCOVERY_RESPONSE; + else if(P2P_EVENT_RECEIVED_GO_NEGOTIATION_REQUEST == eid) + param.FrameInfo.FrameParams.ActionFrameType = WDI_P2P_ACTION_FRAME_GO_NEGOTIATION_REQUEST; + else if(P2P_EVENT_RECEIVED_GO_NEGOTIATION_RESPONSE == eid) + param.FrameInfo.FrameParams.ActionFrameType = WDI_P2P_ACTION_FRAME_GO_NEGOTIATION_RESPONSE; + else if(P2P_EVENT_RECEIVED_GO_NEGOTIATION_CONFIRM == eid) + param.FrameInfo.FrameParams.ActionFrameType = WDI_P2P_ACTION_FRAME_GO_NEGOTIATION_CONFIRM; + else if(P2P_EVENT_RECEIVED_INVITATION_REQUEST == eid) + param.FrameInfo.FrameParams.ActionFrameType = WDI_P2P_ACTION_FRAME_INVITATION_REQUEST; + else if(P2P_EVENT_RECEIVED_INVITATION_RESPONSE == eid) + param.FrameInfo.FrameParams.ActionFrameType = WDI_P2P_ACTION_FRAME_INVITATION_RESPONSE; + else + return; + + cpMacAddr(param.FrameInfo.FrameParams.PeerDeviceAddress.Address, evtData->Packet.Buffer + FRAME_OFFSET_ADDRESS2); + param.FrameInfo.FrameParams.DialogToken = *(evtData->Packet.Buffer + FRAME_OFFSET_P2P_PUB_ACT_DIALOG_TOKEN); + param.FrameInfo.FrameIEs.ElementCount = evtData->Packet.Length - ieOffset; + param.FrameInfo.FrameIEs.pElements = evtData->Packet.Buffer + ieOffset; + } + + // gen TLV + if(NDIS_STATUS_SUCCESS != GenerateWdiIndicationP2pActionFrameReceived( + ¶m, + sizeof(NDIS_STATUS_INDICATION) + sizeof(WDI_MESSAGE_HEADER), + &pAdapter->pPortCommonInfo->WdiData.TlvContext, + &buflen, &((UINT8 *)buf))) + return; + + wdi_UnsolicitedIndication(pAdapter, + FALSE, + NULL, + NDIS_STATUS_WDI_INDICATION_P2P_ACTION_FRAME_RECEIVED, + NDIS_STATUS_SUCCESS, + buf, + buflen); + + // cleanup + FreeGenerated((UINT8 *)buf); + + FunctionOut(COMP_OID_SET); + + return; +} + +VOID +wdiext_IndicateBSSEntry( + IN PADAPTER pAdapter + ) +{ + PMGNT_INFO pMgntInfo = &(pAdapter->MgntInfo); + WDI_INDICATION_BSS_ENTRY_LIST_PARAMETERS param; + WDI_BSS_ENTRY_CONTAINER entry; + RT_802_11_BSSID_LIST RtBssList = {0}; + PRT_WLAN_BSS pRtBss = NULL; + u4Byte i = 0; + ULONG buflen = 0; + u1Byte *buf = NULL; + NDIS_OID_REQUEST *req = NULL; + WDI_MESSAGE_HEADER *reqWdiHdr = NULL; + u4Byte devSpecCtx = 0x07060504; + LARGE_INTEGER CurrentTime; + + if(!pAdapter->pPortCommonInfo->WdiData.TaskHandle.pNdisRequest) + return; + + FunctionIn(COMP_MLME); + + //Get scan list + RtBssList.NumberOfItems = 0; + RtBssList.pbssidentry = pAdapter->bssDescList; + if( (pMgntInfo->bPrepareRoaming == TRUE) && (pMgntInfo->PrepareRoamState ==RT_PREPARE_ROAM_NORMAL_ROAM_BETTER_AP) ) + { + RT_TRACE(COMP_MLME, DBG_LOUD, ("Skip scan triggered by Roam\n")); + FunctionOut(COMP_MLME); + return; + } + else + { +#if BSS_LIST_CACHE + MgntActQuery_802_11_BSSID_LIST(pAdapter, &RtBssList, FALSE); +#else + RT_TRACE(COMP_MLME, DBG_LOUD, ("Indicate actual scan result of BSS list\n")); + MgntActQuery_802_11_BSSID_LIST(pAdapter, &RtBssList, TRUE); +#endif + } + + req = pAdapter->pPortCommonInfo->WdiData.TaskHandle.pNdisRequest; + reqWdiHdr = (WDI_MESSAGE_HEADER *)req->DATA.METHOD_INFORMATION.InformationBuffer; + + //Indicate BSS entry one by one. + for (i=0; i<RtBssList.NumberOfItems; i++) + { + if(RtBssList.pbssidentry[i].IE.Length <= sizeof(RT_FIXED_IE_FIELD)) + { + continue; + } + pRtBss = &(RtBssList.pbssidentry[i]); + + // Determine if we shall report the BSS found by RegWirelessMode4ScanList. + if(!WDIFilterRtBss(pAdapter, pRtBss)) + { + // Skip this BSS. + continue; + } + + // zero + PlatformZeroMemory(¶m, sizeof(param)); + PlatformZeroMemory(&entry, sizeof(entry)); + + // optional + param.Optional.DeviceDescriptor_IsPresent = TRUE; + + // ArrayOfElementsOfWIFI_BSS_ENTRY_CONTAINER DeviceDescriptor + param.DeviceDescriptor.ElementCount = 1; + param.DeviceDescriptor.pElements = &entry; + + // WIFI_MAC_ADDRESS_CONTAINER BSSID + cpMacAddr(entry.BSSID.Address, pRtBss->bdBssIdBuf); + + // WIFI_BYTE_BLOB ProbeResponseFrame, BeaconFrame + if(pRtBss->BssPacketType & BSS_PKT_PROBE_RSP) + { + entry.Optional.ProbeResponseFrame_IsPresent = TRUE; + entry.ProbeResponseFrame.ElementCount = pRtBss->IE.Length; + entry.ProbeResponseFrame.pElements = (UINT8 *)pRtBss->IE.Octet; + } + else if(pRtBss->BssPacketType & BSS_PKT_BEACON) + { + entry.Optional.BeaconFrame_IsPresent = TRUE; + entry.BeaconFrame.ElementCount = pRtBss->IE.Length; + entry.BeaconFrame.pElements = (UINT8 *)pRtBss->IE.Octet; + } + else + { + FunctionOut(COMP_MLME); + return; + } + + // WDI_SIGNAL_INFO_CONTAINER SignalInfo + pRtBss->RecvSignalPower = 0xffffffce; + entry.SignalInfo.RSSI = (INT32)pRtBss->CumRecvSignalPower; + entry.SignalInfo.LinkQuality = (UINT32)pRtBss->RSSI; + + // WDI_CHANNEL_INFO_CONTAINER ChannelInfo + entry.ChannelInfo.ChannelNumber = (UINT32)pRtBss->ChannelNumber; + entry.ChannelInfo.BandId = (pRtBss->ChannelNumber < 36) ? WDI_BAND_ID_2400 : WDI_BAND_ID_5000; + RT_TRACE(COMP_MLME, DBG_LOUD, ("pRtBss->ChannelNumber=%d\n", pRtBss->ChannelNumber)); + + // WDI_BYTE_BLOB DeviceSpecificContext, this is OPTIONAL + entry.Optional.DeviceSpecificContext_IsPresent = TRUE; + entry.DeviceSpecificContext.ElementCount = sizeof(devSpecCtx); + entry.DeviceSpecificContext.pElements = (UINT8 *)&devSpecCtx; + + NdisGetCurrentSystemTime(&CurrentTime); + + // WDI_AGE_INFO_CONTAINER EntryAgeInfo + entry.EntryAgeInfo.HostTimeStamp = CurrentTime.QuadPart;// [SDIO-482] in JIRA + entry.EntryAgeInfo.CachedInformation = 0; + + // Gen tlv + if(NDIS_STATUS_SUCCESS != GenerateWdiIndicationBssEntryList( + ¶m, + sizeof(NDIS_STATUS_INDICATION) + sizeof(WDI_MESSAGE_HEADER), + &pAdapter->pPortCommonInfo->WdiData.TlvContext, + &buflen, &((UINT8 *)buf))) + { + FunctionOut(COMP_MLME); + return; + } + + wdi_UnsolicitedIndication(pAdapter, + FALSE, + (PVOID)req->RequestId, + NDIS_STATUS_WDI_INDICATION_BSS_ENTRY_LIST, + NDIS_STATUS_SUCCESS, + buf, + buflen); + + // cleanup + FreeGenerated((UINT8 *)buf); + } + + FunctionOut(COMP_MLME); + + return; +} + +VOID +wdiext_IndicateBSSEntryBySSID( + IN PADAPTER pAdapter, + IN WDI_SSID *pSSID + ) +{ + PMGNT_INFO pMgntInfo = &(pAdapter->MgntInfo); + WDI_INDICATION_BSS_ENTRY_LIST_PARAMETERS param; + WDI_BSS_ENTRY_CONTAINER entry; + RT_802_11_BSSID_LIST RtBssList = {0}; + PRT_WLAN_BSS pRtBss = NULL; + u4Byte i = 0; + ULONG buflen = 0; + u1Byte *buf = NULL; + NDIS_OID_REQUEST *req = NULL; + WDI_MESSAGE_HEADER *reqWdiHdr = NULL; + u4Byte devSpecCtx = 0x07060504; + BOOL bWildCardSSID = TRUE; + LARGE_INTEGER CurrentTime; + + if(!pAdapter->pPortCommonInfo->WdiData.TaskHandle.pNdisRequest) + return; + + FunctionIn(COMP_MLME); + + if(pSSID->ElementCount != 0) + bWildCardSSID = FALSE; + + //Get scan list + RtBssList.NumberOfItems = 0; + RtBssList.pbssidentry = pAdapter->bssDescList; + if( (pMgntInfo->bPrepareRoaming == TRUE) && (pMgntInfo->PrepareRoamState ==RT_PREPARE_ROAM_NORMAL_ROAM_BETTER_AP) ) + { + RT_TRACE(COMP_MLME, DBG_LOUD, ("Skip scan triggered by Roam\n")); + FunctionOut(COMP_MLME); + return; + } + else + { +#if BSS_LIST_CACHE + MgntActQuery_802_11_BSSID_LIST(pAdapter, &RtBssList, FALSE); +#else + RT_TRACE(COMP_MLME, DBG_LOUD, ("Indicate actual scan result of BSS list\n")); + MgntActQuery_802_11_BSSID_LIST(pAdapter, &RtBssList, TRUE); +#endif + } + + req = pAdapter->pPortCommonInfo->WdiData.TaskHandle.pNdisRequest; + reqWdiHdr = (WDI_MESSAGE_HEADER *)req->DATA.METHOD_INFORMATION.InformationBuffer; + + //Indicate BSS entry one by one. + for (i=0; i<RtBssList.NumberOfItems; i++) + { + if(RtBssList.pbssidentry[i].IE.Length <= sizeof(RT_FIXED_IE_FIELD)) + { + continue; + } + pRtBss = &(RtBssList.pbssidentry[i]); + + // Determine if we shall report the BSS found by RegWirelessMode4ScanList. + if(!WDIFilterRtBss(pAdapter, pRtBss)) + { + // Skip this BSS. + continue; + } + + if(!bWildCardSSID) + { + if(RtBssList.pbssidentry[i].bdSsIdLen != pSSID->ElementCount || + NdisEqualMemory(RtBssList.pbssidentry[i].bdSsIdBuf, pSSID->pElements, pSSID->ElementCount) == 0) + { + //UE specify SSID to update, skip this one + continue; + } + } + + // zero + PlatformZeroMemory(¶m, sizeof(param)); + PlatformZeroMemory(&entry, sizeof(entry)); + + // optional + param.Optional.DeviceDescriptor_IsPresent = TRUE; + + // ArrayOfElementsOfWIFI_BSS_ENTRY_CONTAINER DeviceDescriptor + param.DeviceDescriptor.ElementCount = 1; + param.DeviceDescriptor.pElements = &entry; + + // WIFI_MAC_ADDRESS_CONTAINER BSSID + cpMacAddr(entry.BSSID.Address, pRtBss->bdBssIdBuf); + + // WIFI_BYTE_BLOB ProbeResponseFrame, BeaconFrame + if(pRtBss->BssPacketType & BSS_PKT_PROBE_RSP) + { + entry.Optional.ProbeResponseFrame_IsPresent = TRUE; + entry.ProbeResponseFrame.ElementCount = pRtBss->IE.Length; + entry.ProbeResponseFrame.pElements = (UINT8 *)pRtBss->IE.Octet; + } + else if(pRtBss->BssPacketType & BSS_PKT_BEACON) + { + entry.Optional.BeaconFrame_IsPresent = TRUE; + entry.BeaconFrame.ElementCount = pRtBss->IE.Length; + entry.BeaconFrame.pElements = (UINT8 *)pRtBss->IE.Octet; + } + else + { + FunctionOut(COMP_MLME); + return; + } + + // WDI_SIGNAL_INFO_CONTAINER SignalInfo + pRtBss->RecvSignalPower = 0xffffffce; + entry.SignalInfo.RSSI = (INT32)pRtBss->CumRecvSignalPower; + entry.SignalInfo.LinkQuality = (UINT32)pRtBss->RSSI; + + // WDI_CHANNEL_INFO_CONTAINER ChannelInfo + entry.ChannelInfo.ChannelNumber = (UINT32)pRtBss->ChannelNumber; + entry.ChannelInfo.BandId = (pRtBss->ChannelNumber < 36) ? WDI_BAND_ID_2400 : WDI_BAND_ID_5000; + RT_TRACE(COMP_MLME, DBG_LOUD, ("pRtBss->ChannelNumber=%d\n", pRtBss->ChannelNumber)); + + // WDI_BYTE_BLOB DeviceSpecificContext, this is OPTIONAL + entry.Optional.DeviceSpecificContext_IsPresent = TRUE; + entry.DeviceSpecificContext.ElementCount = sizeof(devSpecCtx); + entry.DeviceSpecificContext.pElements = (UINT8 *)&devSpecCtx; + + NdisGetCurrentSystemTime(&CurrentTime); + + // WDI_AGE_INFO_CONTAINER EntryAgeInfo + entry.EntryAgeInfo.HostTimeStamp = CurrentTime.QuadPart;// [SDIO-482] in JIRA + entry.EntryAgeInfo.CachedInformation = 0; + + // Gen tlv + if(NDIS_STATUS_SUCCESS != GenerateWdiIndicationBssEntryList( + ¶m, + sizeof(NDIS_STATUS_INDICATION) + sizeof(WDI_MESSAGE_HEADER), + &pAdapter->pPortCommonInfo->WdiData.TlvContext, + &buflen, &((UINT8 *)buf))) + { + FunctionOut(COMP_MLME); + return; + } + + wdi_UnsolicitedIndication(pAdapter, + FALSE, + (PVOID)req->RequestId, + NDIS_STATUS_WDI_INDICATION_BSS_ENTRY_LIST, + NDIS_STATUS_SUCCESS, + buf, + buflen); + + // cleanup + FreeGenerated((UINT8 *)buf); + } + + FunctionOut(COMP_MLME); + + return; +} + + +VOID +wdiext_IndicateAssociationResult( + IN PADAPTER pAdapter + ) +{ + PMGNT_INFO pMgntInfo = &(pAdapter->MgntInfo); + WDI_INDICATION_ASSOCIATION_RESULT_LIST AsocResultList; + WDI_ASSOCIATION_RESULT_CONTAINER AsocResult; + RT_AUTH_MODE AuthMode = RT_802_11AuthModeOpen; + u4Byte AuthAlgo = 0, UnicastCipher = 0, McastDataCipher = 0, McastMgntCipher = 0; + u1Byte FourAddrSupport = FALSE, PortAuthorized = FALSE, WMMQos = FALSE; + u4Byte DSInfo = 0, AssocComeBackTime = 0, BandID = 0; + WDI_PHY_TYPE PhyType = WDI_PHY_TYPE_UNKNOWN; + PUCHAR pOutput = NULL; + ULONG length = 0; + NDIS_STATUS ndisStatus = NDIS_STATUS_SUCCESS; + + MgntActQuery_802_11_AUTHENTICATION_MODE( pAdapter, &AuthMode ); + AuthAlgo = N6CAuthModeToDot11( &AuthMode ); + UnicastCipher = N6CEncAlgorithmToDot11( &(pMgntInfo->SecurityInfo.PairwiseEncAlgorithm) ); + McastDataCipher = N6CEncAlgorithmToDot11( &(pMgntInfo->SecurityInfo.GroupEncAlgorithm) ); + if( pMgntInfo->bInBIPMFPMode && TEST_FLAG(pMgntInfo->targetAKMSuite, AKM_RSNA_1X_SHA256 | AKM_RSNA_PSK_SHA256)) + McastMgntCipher = WDI_CIPHER_ALGO_BIP; + else + McastMgntCipher = WDI_CIPHER_ALGO_NONE; // PMF ? + WMMQos = (pMgntInfo->pStaQos->QosCapability > QOS_DISABLE)?TRUE:FALSE; + + RT_TRACE(COMP_MLME, DBG_LOUD, ("wdiext_IndicateAssociationResult WMMQos = %d\n", WMMQos)); + DSInfo = WDI_DS_UNKNOWN; + if( pMgntInfo->RspStatusCode == 30 && pMgntInfo->TIE.Length != 0) + { + if(pMgntInfo->TIE.Octet[0] == 3 ) + { + AssocComeBackTime = (u4Byte)(pMgntInfo->TIE.Octet[1] & 0xff); + AssocComeBackTime += (u4Byte)(pMgntInfo->TIE.Octet[2] << 8) & 0xff; + AssocComeBackTime += (u4Byte)(pMgntInfo->TIE.Octet[3] << 16) & 0xff; + AssocComeBackTime += (u4Byte)(pMgntInfo->TIE.Octet[4] << 24) & 0xff; + } + else + AssocComeBackTime = 0; + } + else + AssocComeBackTime = 0; + if(pMgntInfo->dot11CurrentChannelNumber < 36) + BandID = WDI_BAND_ID_2400; + else + BandID = WDI_BAND_ID_5000; + + switch (pMgntInfo->dot11CurrentWirelessMode) + { + default: + PhyType = WDI_PHY_TYPE_OFDM; + break; + + case WIRELESS_MODE_A: + PhyType = WDI_PHY_TYPE_OFDM; + break; + + case WIRELESS_MODE_G: + PhyType = WDI_PHY_TYPE_ERP; + break; + + case WIRELESS_MODE_B: + PhyType = WDI_PHY_TYPE_HRDSSS; + break; + + case WIRELESS_MODE_N_24G: + case WIRELESS_MODE_N_5G: + case WIRELESS_MODE_AUTO: + PhyType = WDI_PHY_TYPE_HT; + break; + + case WIRELESS_MODE_AC_5G: + case WIRELESS_MODE_AC_ONLY: + case WIRELESS_MODE_AC_24G: + PhyType = WDI_PHY_TYPE_VHT; + break; + + + } + + PlatformZeroMemory(&AsocResult, sizeof(WDI_ASSOCIATION_RESULT_CONTAINER)); + + PlatformMoveMemory(AsocResult.BSSID.Address, pMgntInfo->Bssid, 6); + AsocResultList.AssociationResults.ElementCount = 1; + AsocResultList.AssociationResults.pElements = &AsocResult; + AsocResult.AssociationResultParameters.AssociationStatus = (pMgntInfo->mAssoc)?WDI_ASSOC_STATUS_SUCCESS:WDI_ASSOC_STATUS_FAILURE; + AsocResult.AssociationResultParameters.StatusCode = pMgntInfo->RspStatusCode; + AsocResult.AssociationResultParameters.ReAssociation = pMgntInfo->AsocInfo.FlagReAsocReq; + AsocResult.AssociationResultParameters.AuthAlgorithm = AuthAlgo; + AsocResult.AssociationResultParameters.UnicastCipherAlgorithm = UnicastCipher; + AsocResult.AssociationResultParameters.MulticastDataCipherAlgorithm = McastDataCipher; + AsocResult.AssociationResultParameters.MulticastMgmtCipherAlgorithm = McastMgntCipher; + AsocResult.AssociationResultParameters.FourAddressSupported = FourAddrSupport; + AsocResult.AssociationResultParameters.PortAuthorized = PortAuthorized; + AsocResult.AssociationResultParameters.WMMQoSEnabled = WMMQos; + AsocResult.AssociationResultParameters.DSInfo = DSInfo; + AsocResult.AssociationResultParameters.AssociationComebackTime = AssocComeBackTime; + AsocResult.AssociationResultParameters.BandID = BandID; + AsocResult.Optional.AssociationRequestFrame_IsPresent = TRUE; + AsocResult.AssociationRequestFrame.ElementCount = MMPDU_BODY_LEN(pMgntInfo->AsocInfo.AsocReqLength); + AsocResult.AssociationRequestFrame.pElements = MMPDU_BODY(pMgntInfo->AsocInfo.AsocReq); + AsocResult.Optional.AssociationResponseFrame_IsPresent = TRUE; + AsocResult.AssociationResponseFrame.ElementCount = MMPDU_BODY_LEN(pMgntInfo->AsocInfo.AsocRespLength); + AsocResult.AssociationResponseFrame.pElements = MMPDU_BODY(pMgntInfo->AsocInfo.AsocResp); + AsocResult.Optional.BeaconProbeResponse_IsPresent = TRUE; + AsocResult.BeaconProbeResponse.ElementCount = MMPDU_BODY_LEN(pMgntInfo->AsocInfo.BeaconLength); + AsocResult.BeaconProbeResponse.pElements = MMPDU_BODY(pMgntInfo->AsocInfo.Beacon); + AsocResult.Optional.ActivePhyTypeList_IsPresent = TRUE; + AsocResult.ActivePhyTypeList.ElementCount = 1; + AsocResult.ActivePhyTypeList.pElements = &PhyType; + + ndisStatus = GenerateWdiIndicationAssociationResult( + &AsocResultList, + sizeof(NDIS_STATUS_INDICATION)+sizeof(WDI_MESSAGE_HEADER), + &pAdapter->pPortCommonInfo->WdiData.TlvContext, + &length, + &pOutput); + if(NDIS_STATUS_SUCCESS == ndisStatus) + { + RT_TRACE(COMP_MLME, DBG_LOUD, ("GenerateWdiIndicationAssociationResult(): return length %d\n", length)); + RT_PRINT_DATA(COMP_MLME, DBG_TRACE, ("buffer\n"), pOutput, length); + RT_TRACE(COMP_MLME, DBG_LOUD, ("SendUnsolictedIndication(): EthertypeEncapTable_IsPresent %d\n", AsocResult.Optional.EthertypeEncapTable_IsPresent)); + + ndisStatus = WDI_AddDatapathPeer(pAdapter, AsocResult.BSSID.Address); + + wdi_UnsolicitedIndication(pAdapter, + FALSE, + (PVOID)pAdapter->pPortCommonInfo->WdiData.TaskHandle.pNdisRequest->RequestId, + NDIS_STATUS_WDI_INDICATION_ASSOCIATION_RESULT, + NDIS_STATUS_SUCCESS, + pOutput, + length); + + FreeGenerated(pOutput); + } + else + { + RT_TRACE(COMP_MLME, DBG_LOUD, ("GenerateWdiIndicationAssociationResult(): generate TLV failure\n")); + } + + if( NDIS_STATUS_SUCCESS != ndisStatus ) + { + RT_TRACE(COMP_MLME, DBG_WARNING, ("wdiext_IndicateAssociationResult: fail to create peer, so disconnect with this AP[%2x:%2x:%2x:%2x:%2x:%2x]\n", AsocResult.BSSID.Address[0],AsocResult.BSSID.Address[1],AsocResult.BSSID.Address[2], AsocResult.BSSID.Address[3], AsocResult.BSSID.Address[4], AsocResult.BSSID.Address[5])); + MgntDisconnectAP(pAdapter, inactivity); + } +} + +// +// Description: +// Indicate unsolicited event WDI_INDICATION_FT_ASSOC_PARAMS_NEEDED to WDI. +// +RT_STATUS +wdiext_IndicateFtAssocNeeded( + IN PADAPTER pAdapter + ) +{ + RT_STATUS rtStatus = RT_STATUS_SUCCESS; + NDIS_STATUS ndisStatus = NDIS_STATUS_SUCCESS; + PMGNT_INFO pMgntInfo = &(pAdapter->MgntInfo); + WDI_INDICATION_FT_ASSOC_PARAMS_NEEDED_PARAMETERS param; + pu1Byte pIndicBuf = NULL; + ULONG indicBufLen = 0; + + PlatformZeroMemory(¶m, sizeof(WDI_INDICATION_FT_ASSOC_PARAMS_NEEDED_PARAMETERS)); + + do + { + if(pMgntInfo->AsocInfo.AuthSeq1Length < sMacHdrLng) + { + RT_TRACE_F(COMP_INDIC, DBG_WARNING, ("Too short of AuthSeq2Length = %d\n", pMgntInfo->AsocInfo.AuthSeq1Length)); + rtStatus = RT_STATUS_INVALID_DATA; + break; + } + + if(pMgntInfo->AsocInfo.AuthSeq2Length < sMacHdrLng) + { + RT_TRACE_F(COMP_INDIC, DBG_WARNING, ("Too short of AuthSeq2Length = %d\n", pMgntInfo->AsocInfo.AuthSeq2Length)); + rtStatus = RT_STATUS_INVALID_DATA; + break; + } + + cpMacAddr(param.BssId.Address, pMgntInfo->Bssid); + + param.AuthRequest.ElementCount = MMPDU_BODY_LEN(pMgntInfo->AsocInfo.AuthSeq1Length); + param.AuthRequest.pElements = MMPDU_BODY(pMgntInfo->AsocInfo.AuthSeq1); + + param.AuthResponse.ElementCount = MMPDU_BODY_LEN(pMgntInfo->AsocInfo.AuthSeq2Length); + param.AuthResponse.pElements = MMPDU_BODY(pMgntInfo->AsocInfo.AuthSeq2); + + // Gen tlv + if(NDIS_STATUS_SUCCESS != (ndisStatus = + GenerateWdiIndicationFtAssocParamsNeeded( + ¶m, + sizeof(NDIS_STATUS_INDICATION) + sizeof(WDI_MESSAGE_HEADER), + &pAdapter->pPortCommonInfo->WdiData.TlvContext, + &indicBufLen, + &((UINT8 *)pIndicBuf)))) + { + RT_TRACE_F(COMP_INDIC, DBG_SERIOUS, ("Fail (ndisStatus = 0x%08X) from GenerateWdiIndicationFtAssocParamsNeeded()\n", ndisStatus)); + rtStatus = RT_STATUS_OS_API_FAILED; + break; + } + + RT_PRINT_DATA(COMP_INDIC, DBG_LOUD, "NDIS_STATUS_WDI_INDICATION_FT_ASSOC_PARAMS_NEEDED:\n", pIndicBuf, indicBufLen); + wdi_UnsolicitedIndication(pAdapter, + FALSE, + NULL, + NDIS_STATUS_WDI_INDICATION_FT_ASSOC_PARAMS_NEEDED, + NDIS_STATUS_SUCCESS, + pIndicBuf, + indicBufLen); + }while(FALSE); + + if(pIndicBuf) + { + // cleanup + FreeGenerated((UINT8 *)pIndicBuf); + } + + return rtStatus; +} + +VOID +wdiext_IndicateDisassociation( + IN ADAPTER *pAdapter, + IN u1Byte *addr, + IN u4Byte frameLen, + IN u1Byte *frame, + IN BOOLEAN bDisassoc, + IN u2Byte reason + ) +{ + WDI_INDICATION_DISASSOCIATION_PARAMETERS param; + + u1Byte *buf = NULL; + ULONG buflen = 0; + + if(0 < frameLen && frameLen < sMacHdrLng) + { + RT_TRACE_F(COMP_OID_SET, DBG_LOUD, ("invalid deauth/disassociation len: %u\n", frameLen)); + return; + } + + PlatformZeroMemory(¶m, sizeof(param)); + + param.Optional.DeauthFrame_IsPresent = (FALSE == bDisassoc) && frameLen; + param.Optional.DisassociationFrame_IsPresent = (TRUE == bDisassoc) && frameLen; + param.Optional.NeedPeerStateCleanup_IsPresent = FALSE; + + cpMacAddr(param.DisconnectIndicationParameters.MacAddress.Address, addr); + param.DisconnectIndicationParameters.DisassociationWABIReason = bDisassoc + ? WDI_ASSOC_STATUS_PEER_DISASSOCIATED + : WDI_ASSOC_STATUS_PEER_DEAUTHENTICATED; + + if(frameLen) + { + if(bDisassoc) + { + param.DisassociationFrame.ElementCount = frameLen - sMacHdrLng; + param.DisassociationFrame.pElements = frame + sMacHdrLng; + } + else + { + param.DeauthFrame.ElementCount = frameLen - sMacHdrLng; + param.DeauthFrame.pElements = frame + sMacHdrLng; + } + } + + // Gen tlv + if(NDIS_STATUS_SUCCESS != GenerateWdiIndicationDisassociation( + ¶m, + sizeof(NDIS_STATUS_INDICATION) + sizeof(WDI_MESSAGE_HEADER), + &pAdapter->pPortCommonInfo->WdiData.TlvContext, + &buflen, &((UINT8 *)buf))) + return; + + wdi_UnsolicitedIndication(pAdapter, + FALSE, + NULL, + NDIS_STATUS_WDI_INDICATION_DISASSOCIATION, + NDIS_STATUS_SUCCESS, + buf, + buflen); + + // cleanup + FreeGenerated((UINT8 *)buf); + + return; +} + +VOID +wdiext_IndicateRadioStatus( + IN PADAPTER pAdapter + ) +{ + PMGNT_INFO pMgntInfo = &(pAdapter->MgntInfo); + WDI_INDICATION_RADIO_STATUS_PARAMETERS Params = {0}; + PUCHAR pOutput = NULL; + ULONG length = 0; + NDIS_STATUS ndisStatus = NDIS_STATUS_SUCCESS; + PWDI_DATA_STRUCT pWdi = &(pAdapter->pPortCommonInfo->WdiData); + PRT_OID_HANDLER pOidHandle = &(pWdi->TaskHandle); + + Params.RadioState.SoftwareState = (pMgntInfo->RfOffReason&RF_CHANGE_BY_SW)?0:1; + Params.RadioState.HardwareState = (pMgntInfo->RfOffReason&RF_CHANGE_BY_HW)?0:1; + + RT_TRACE(COMP_RF, DBG_LOUD, ("wdiext_IndicateRadioStatus(): Params.RadioState.SoftwareState is %d, Params.RadioState.HardwareState is %d\n", Params.RadioState.SoftwareState, Params.RadioState.HardwareState)); + + ndisStatus = GenerateWdiIndicationRadioStatus( + &Params, + sizeof(NDIS_STATUS_INDICATION) + sizeof(WDI_MESSAGE_HEADER), + &pAdapter->pPortCommonInfo->WdiData.TlvContext, + &length, + &pOutput); + + if(NDIS_STATUS_SUCCESS == ndisStatus) + { + wdi_UnsolicitedIndication(pAdapter, + TRUE, + NULL, + NDIS_STATUS_WDI_INDICATION_RADIO_STATUS, + NDIS_STATUS_SUCCESS, + pOutput, + length); + + FreeGenerated(pOutput); + pOutput = NULL; + } + ndisStatus = NDIS_STATUS_NOT_SUPPORTED; +} + +VOID +wdiext_IndicateLinkStateChanged( + IN PADAPTER pAdapter, + IN BOOLEAN bForceLinkQuality, + IN u1Byte ucLinkQuality + ) +{ + PMGNT_INFO pMgntInfo = &(pAdapter->MgntInfo); + WDI_INDICATION_LINK_STATE_CHANGE_PARAMETERS Params = {0}; + PUCHAR pOutput = NULL; + ULONG length = 0; + NDIS_STATUS ndisStatus = NDIS_STATUS_SUCCESS; + + if (pMgntInfo->mAssoc || pMgntInfo->mIbss) + { + Params.LinkStateChangeParameters.LinkQuality = GetSignalQuality(pAdapter); + } + else + { + Params.LinkStateChangeParameters.LinkQuality = 0; + } + + if(bForceLinkQuality) + { + Params.LinkStateChangeParameters.LinkQuality = ucLinkQuality; + } + + Params.LinkStateChangeParameters.TxLinkSpeed = MgntActQuery_RT_11N_USER_SHOW_RATES(pAdapter , pMgntInfo->bForcedShowRxRate, FALSE)*1000/2; + Params.LinkStateChangeParameters.RxLinkSpeed = pMgntInfo->HighestOperaRate*1000/2; + cpMacAddr(Params.LinkStateChangeParameters.PeerMACAddress.Address, pMgntInfo->Bssid); + + RT_TRACE(COMP_MLME, DBG_LOUD, ("wdiext_IndicateLinkStateChanged(): Params.LinkStateChangeParameters.TxLinkSpeed is %d\n", Params.LinkStateChangeParameters.TxLinkSpeed)); + RT_TRACE(COMP_MLME, DBG_LOUD, ("wdiext_IndicateLinkStateChanged(): Params.LinkStateChangeParameters.RxLinkSpeed is %d\n", Params.LinkStateChangeParameters.RxLinkSpeed)); + + ndisStatus = GenerateWdiIndicationLinkStateChange( + &Params, + sizeof(NDIS_STATUS_INDICATION)+sizeof(WDI_MESSAGE_HEADER), + &pAdapter->pPortCommonInfo->WdiData.TlvContext, + &length, + &pOutput); + + if(NDIS_STATUS_SUCCESS == ndisStatus) + { + wdi_UnsolicitedIndication(pAdapter, + FALSE, + NULL, + NDIS_STATUS_WDI_INDICATION_LINK_STATE_CHANGE, + ndisStatus, + pOutput, + length); + + FreeGenerated(pOutput); + pOutput = NULL; + } +} + +VOID +wdiext_IndicateRoamingNeeded( + IN PADAPTER pAdapter, + IN u2Byte IndicationReason + ) +{ + PMGNT_INFO pMgntInfo = &(pAdapter->MgntInfo); + WDI_INDICATION_ROAMING_NEEDED_PARAMETERS Params = {0}; + PUCHAR pOutput = NULL; + ULONG length = 0; + NDIS_STATUS ndisStatus = NDIS_STATUS_SUCCESS; + + pMgntInfo->bPrepareRoaming = TRUE; + + Params.RoamingReason = IndicationReason; + RT_TRACE_F(COMP_MLME, DBG_LOUD, ("Params.RoamingReason %d\n", Params.RoamingReason)); + + ndisStatus = GenerateWdiIndicationRoamingNeeded( + &Params, + sizeof(NDIS_STATUS_INDICATION)+sizeof(WDI_MESSAGE_HEADER), + &pAdapter->pPortCommonInfo->WdiData.TlvContext, + &length, + &pOutput); + + if(NDIS_STATUS_SUCCESS == ndisStatus) + { + wdi_UnsolicitedIndication(pAdapter, + FALSE, + NULL, + NDIS_STATUS_WDI_INDICATION_ROAMING_NEEDED, + ndisStatus, + pOutput, + length); + + FreeGenerated(pOutput); + pOutput = NULL; + } +} + +static +VOID +wdiext_IndicateP2POpChnl( + IN ADAPTER *pAdapter, + IN P2P_INFO *pP2PInfo + ) +{ + WDI_INDICATION_P2P_GROUP_OPERATING_CHANNEL_PARAMETERS param; + + u1Byte *buf = NULL; + ULONG buflen = 0; + + NDIS_OID_REQUEST *req = NULL; + WDI_MESSAGE_HEADER *reqWdiHdr = NULL; + + if(!pAdapter->pPortCommonInfo->WdiData.TaskHandle.pNdisRequest) + return; + + req = pAdapter->pPortCommonInfo->WdiData.TaskHandle.pNdisRequest; + reqWdiHdr = (WDI_MESSAGE_HEADER *)req->DATA.METHOD_INFORMATION.InformationBuffer; + + // zero + PlatformZeroMemory(¶m, sizeof(param)); + + // fill + PlatformMoveMemory(param.Channel.CountryOrRegionString, pP2PInfo->CountryString, sizeof(pP2PInfo->CountryString)); + param.Channel.OperatingClass = pP2PInfo->RegulatoryClass; + param.Channel.ChannelNumber = pP2PInfo->OperatingChannel; + + param.IndicateReason = WDI_P2P_CHANNEL_INDICATE_REASON_NEW_CONNECTION; + if(pP2PInfo->bChannelSwitch) + { + param.IndicateReason = pP2PInfo->P2PChannelIndicationReason; + } + + // Gen tlv + if(NDIS_STATUS_SUCCESS != GenerateWdiIndicationP2pGroupOperatingChannel( + ¶m, + sizeof(NDIS_STATUS_INDICATION) + sizeof(WDI_MESSAGE_HEADER), + &pAdapter->pPortCommonInfo->WdiData.TlvContext, + &buflen, &((UINT8 *)buf))) + return; + + wdi_UnsolicitedIndication(pAdapter, + FALSE, + (PVOID)req->RequestId, + NDIS_STATUS_WDI_INDICATION_P2P_GROUP_OPERATING_CHANNEL, + NDIS_STATUS_SUCCESS, + buf, + buflen); + + // cleanup + FreeGenerated((UINT8 *)buf); + + return; +} + + +PVOID +wdi_FindGroupPeerByPort( + IN PADAPTER pAdapter, + IN u2Byte PortNumber +) +{ + PADAPTER pDefaultAdapter = GetDefaultAdapter(pAdapter); + PRT_PEER_ENTRY pPeerEntry = NULL; + u1Byte i; + + for(i = 0; i < MP_DEFAULT_NUMBER_OF_PORT; i++) + { + pPeerEntry = &pDefaultAdapter->RxPeerTable[i]; + if( pPeerEntry->bUsed == TRUE ) + { + if( pPeerEntry->uPortId == PortNumber ) + { + return (PVOID)pPeerEntry; + } + } + } + + return NULL; +} + +PVOID +wdi_FindPeerByAddr( + IN PADAPTER pAdapter, + IN pu1Byte pAddr +) +{ + PADAPTER pDefaultAdapter = GetDefaultAdapter(pAdapter); + PRT_PEER_ENTRY pPeerEntry = NULL; + u1Byte i = 0, count = 0; + + count = pDefaultAdapter->RxPeerUsedCount; + for(i = MP_DEFAULT_NUMBER_OF_PORT; i < MAX_PEER_NUM; i++) + { + if( count == 0 ) + break; + + pPeerEntry = &pDefaultAdapter->RxPeerTable[i]; + if( pPeerEntry->bUsed == TRUE ) + { + count--; + if( PlatformCompareMemory(pPeerEntry->PeerAddr, pAddr, 6) == 0 ) + { + return (PVOID)pPeerEntry; + } + } + } + + return NULL; +} + +PVOID +wdi_GetAvailablePeer( + IN PADAPTER pAdapter, + IN pu1Byte pAddr +) +{ + PADAPTER pDefaultAdapter = GetDefaultAdapter(pAdapter); + WDI_PORT_ID PortId = (WDI_PORT_ID)pAdapter->pNdis62Common->PortNumber; + PRT_PEER_ENTRY pCurPeerEntry = NULL, pPeerEntry = NULL; + u1Byte i = 0, UnusedIndex = 0, count = 0; + BOOLEAN bFound = FALSE; + + FunctionIn(COMP_MLME); + + count = pDefaultAdapter->RxPeerUsedCount; + + for(i = MP_DEFAULT_NUMBER_OF_PORT; i < MAX_PEER_NUM; i++) + { + if( (count == 0) && (bFound == TRUE) ) + break; + + pPeerEntry = &pDefaultAdapter->RxPeerTable[i]; + + if( (pPeerEntry->bUsed == FALSE) && (bFound == FALSE) ) + { + bFound = TRUE; + UnusedIndex = i; + } + else if( pPeerEntry->bUsed == TRUE ) + { + count--; + if( PlatformCompareMemory(pPeerEntry->PeerAddr, pAddr, 6) == 0 ) + { + RT_TRACE(COMP_MLME, DBG_WARNING, ("wdi_GetAvailablePeer: The addres [%2x:%2x:%2x:%2x:%2x:%2x] had associated with specified Peer %d\n", pAddr[0], pAddr[1], pAddr[2], pAddr[3], pAddr[4], pAddr[5], pPeerEntry->uPeerId)); + FunctionOut(COMP_MLME); + return (PVOID)pPeerEntry; + } + } + } + + if( (i == MAX_PEER_NUM) && (bFound == FALSE) ) + { + RT_TRACE(COMP_MLME, DBG_WARNING, ("wdi_GetAvailablePeer: Peer is already full, so cannot find an unused peer to associate [%2x:%2x:%2x:%2x:%2x:%2x]\n", pAddr[0], pAddr[1], pAddr[2], pAddr[3], pAddr[4], pAddr[5])); + FunctionOut(COMP_MLME); + return NULL; + } + + pDefaultAdapter->RxPeerUsedCount++; + + pCurPeerEntry = &pDefaultAdapter->RxPeerTable[UnusedIndex]; + pCurPeerEntry->bUsed = TRUE; + pCurPeerEntry->uPeerId = UnusedIndex; + pCurPeerEntry->uPortId = (u2Byte)PortId; + PlatformMoveMemory(pCurPeerEntry->PeerAddr, pAddr, 6); + + RT_TRACE(COMP_MLME, DBG_LOUD, ("wdi_GetAvailablePeer: Port %d associate the addres [%2x:%2x:%2x:%2x:%2x:%2x] at Peer %d\n", (u2Byte)PortId, pAddr[0], pAddr[1], pAddr[2], pAddr[3], pAddr[4], pAddr[5], UnusedIndex)); + + FunctionOut(COMP_MLME); + + return (PVOID)pCurPeerEntry; +} + +VOID +wdi_NotifyPeerData( + IN PADAPTER pAdapter, + IN u1Byte ExTid, + IN u2Byte Pid, + IN RT_RX_INDICATION_LEVEL level, + IN PNDIS_STATUS pNdisStatus +) +{ + PWDI_DATA_STRUCT pWdi = &(pAdapter->pPortCommonInfo->WdiData); + PADAPTER pDefaultAdapter = GetDefaultAdapter(pAdapter); + PRT_NDIS6_COMMON pDefaultNdisCommon = pDefaultAdapter->pNdisCommon; + PADAPTER pTempAdapter = NULL; + PRT_NDIS6_COMMON pNdisCommon = pAdapter->pNdisCommon; + WDI_PEER_ID PeerId = (WDI_PEER_ID)Pid; + WDI_EXTENDED_TID ExtendTid = (WDI_EXTENDED_TID)ExTid; + KIRQL Irql = 0; + BOOLEAN bLackResource = FALSE; + + PlatformAcquireSpinLock(pAdapter, RT_RX_CONTROL_SPINLOCK); + if( (pNdisCommon->bRxControlState != RT_RX_STOP) && (pDefaultNdisCommon->bRxDataPathState != RT_RX_PAUSE) ) + { + pNdisCommon->bRxControlState = RT_RX_NOTIFYING; + PlatformReleaseSpinLock(pAdapter, RT_RX_CONTROL_SPINLOCK); + + PlatformAcquireSpinLock(pAdapter, RT_RX_SPINLOCK); + bLackResource = RxCheckResource(pAdapter)?FALSE:TRUE; + PlatformReleaseSpinLock(pAdapter, RT_RX_SPINLOCK); + + if( bLackResource ) + RT_TRACE(COMP_RECV, DBG_WARNING, ("wdi_NotifyPeerData(): RFD is less than lower bound (%d)\n", RFD_LOWER_BOUND)); + + Irql = KeGetCurrentIrql(); + // Prefast warning C6387: '_Param_(5)' could be '0': this does not adhere to the specification for the function 'RxInorderDataIndication'. + // False positive, caller gurantee pNdisStatus valid. +#pragma warning( disable:6387 ) + if(Irql > PASSIVE_LEVEL ) + { + RT_TRACE(COMP_RECV, DBG_TRACE, ("wdi_NotifyPeerData(): it is DISPATCH level\n")); + if( bLackResource ) + pWdi->WdiDataApi.RxInorderDataIndication(pWdi->DataPathHandle, WDI_RX_INDICATION_DISPATCH_GENERAL_WITH_LOW_RESOURCES, PeerId, ExtendTid, NULL, pNdisStatus); + else + pWdi->WdiDataApi.RxInorderDataIndication(pWdi->DataPathHandle, WDI_RX_INDICATION_DISPATCH_GENERAL, PeerId, ExtendTid, NULL, pNdisStatus); + } + else + { + RT_TRACE(COMP_RECV, DBG_TRACE, ("wdi_NotifyPeerData(): it is PASSIVE level\n")); + if( bLackResource ) + pWdi->WdiDataApi.RxInorderDataIndication(pWdi->DataPathHandle, WDI_RX_INDICATION_PASSIVE_WITH_LOW_RESOURCES, PeerId, ExtendTid, NULL, pNdisStatus); + else + pWdi->WdiDataApi.RxInorderDataIndication(pWdi->DataPathHandle, WDI_RX_INDICATION_PASSIVE, PeerId, ExtendTid, NULL, pNdisStatus); + } + + PlatformAcquireSpinLock(pAdapter, RT_RX_CONTROL_SPINLOCK); + if( pNdisCommon->bRxControlState == RT_RX_PREPARE_STOP ) + { + RT_TRACE(COMP_INIT, DBG_WARNING, ("Driver change Rx control state to stop mode and stop to notify Rx manager data in queue\n")); + pTempAdapter = GetDefaultAdapter(pAdapter); + do + { + pNdisCommon = pTempAdapter->pNdisCommon; + if( pNdisCommon->bRxControlState == RT_RX_PREPARE_STOP ) + { + pNdisCommon->bRxControlState = RT_RX_STOP; + GLWdiTxRxStatistics.numWdiRxStop++; + } + pTempAdapter = GetNextExtAdapter(pTempAdapter); + }while(pTempAdapter != NULL ); + + PlatformReleaseSpinLock(pAdapter, RT_RX_CONTROL_SPINLOCK); + RT_TRACE(COMP_INIT, DBG_WARNING, ("Driver call RxStopConfirm for Rx manager\n")); + pWdi->WdiDataApi.RxStopConfirm(pWdi->DataPathHandle); + } + else if( pNdisCommon->bRxControlState == RT_RX_NOTIFYING ) + { + pNdisCommon->bRxControlState = RT_RX_NORMAL; + PlatformReleaseSpinLock(pAdapter, RT_RX_CONTROL_SPINLOCK); + } + else + { + RT_TRACE(COMP_INIT, DBG_WARNING, ("wdi_NotifyPeerData: Unknown case and RxControlState is %d\n", pNdisCommon->bRxControlState)); + PlatformReleaseSpinLock(pAdapter, RT_RX_CONTROL_SPINLOCK); + } + } + else + { + PlatformReleaseSpinLock(pAdapter, RT_RX_CONTROL_SPINLOCK); + *pNdisStatus = NDIS_STATUS_MEDIA_BUSY; + RT_TRACE(COMP_RECV, DBG_WARNING, ("Stop to notify Rx manager data in queue\n")); + } +} + +NDIS_STATUS +WDI_Initialize( + IN PDRIVER_OBJECT pDriverObject, + IN PUNICODE_STRING RegistryPath, + IN PNDIS_MINIPORT_DRIVER_CHARACTERISTICS pMChars + ) +{ + NDIS_STATUS Status = NDIS_STATUS_SUCCESS; + NDIS_MINIPORT_DRIVER_WDI_CHARACTERISTICS WdiChar = {0}; + + pMChars->ShutdownHandlerEx = N6SdioShutdown;//ok + pMChars->DevicePnPEventNotifyHandler = N6SdioPnPEventNotify;//ok + pMChars->UnloadHandler = N6SdioUnload;//ok + pMChars->OidRequestHandler = N6SdioOidRequest; + pMChars->CancelOidRequestHandler = N6SdioCancelOidRequest; + pMChars->SetOptionsHandler = N6SdioSetOptions;// MPSetOptions; + pMChars->CheckForHangHandlerEx = NULL; // Need check + pMChars->DirectOidRequestHandler = N6CDirectOidRequest; + pMChars->CancelDirectOidRequestHandler = N6CCancelDirectOidRequest; + + // WorkAround for 0x9F BSOD + pMChars->ResetHandlerEx = N6SdioReset; + + RtlZeroMemory(&WdiChar, sizeof(WdiChar)); + + WdiChar.WdiVersion = WDI_VERSION_LATEST; + + WdiChar.Header.Type = NDIS_OBJECT_TYPE_MINIPORT_WDI_CHARACTERISTICS, + WdiChar.Header.Size = NDIS_SIZEOF_MINIPORT_WDI_CHARACTERISTICS_REVISION_1; + WdiChar.Header.Revision = NDIS_MINIPORT_DRIVER_WDI_CHARACTERISTICS_REVISION_1; + + WdiChar.AllocateAdapterHandler = N6SdioWdi_AllocateAdapter; + WdiChar.FreeAdapterHandler = N6SdioWdi_FreeAdapter; + WdiChar.OpenAdapterHandler = N6SdioWdi_OpenAdapter; + WdiChar.CloseAdapterHandler = N6SdioWdi_CloseAdapter; + WdiChar.TalTxRxInitializeHandler = N6SdioWdi_TalTxRxInitialize; + WdiChar.TalTxRxDeinitializeHandler = N6SdioWdi_TalTxRxDeinitialize; + + WdiChar.HangDiagnoseHandler = N6SdioWdi_HangDiagnose; + + // Optional handler + WdiChar.StartOperationHandler = N6SdioWdi_StartOperation; + WdiChar.StopOperationHandler = N6SdioWdi_StopOperation; + + Status = NdisMRegisterWdiMiniportDriver( + pDriverObject, + RegistryPath, + &GlobalRtDriverContext, + pMChars, + &WdiChar, + &(GlobalRtDriverContext.NdisContext.Ndis6MiniportDriverHandle) + ); + RT_TRACE(COMP_INIT, DBG_LOUD, ("WDI register WDI miniport! Status 0x%x\n", Status)); + + return Status; +} + + +VOID +WDI_DeInitialize( + IN NDIS_HANDLE DriverHandle + ) +{ + NdisMDeregisterWdiMiniportDriver(DriverHandle); +} + +VOID +WDI_InitRxQueue( + IN PADAPTER pAdapter + ) +{ + PADAPTER pDefaultAdapter = GetDefaultAdapter(pAdapter); + u2Byte index = 0; + PRT_PEER_ENTRY pPeerEntry = NULL; + + PlatformAcquireSpinLock(pAdapter, RT_RX_QUEUE_SPINLOCK); + for(index=0; index < MAX_PEER_NUM; index++) + { + RTInitializeSListHead( &(pDefaultAdapter->RxPeerQueue[index]) ); + } + for(index=0; index < MAX_PEER_NUM; index++) + { + pPeerEntry = &pDefaultAdapter->RxPeerTable[index]; + PlatformZeroMemory(pPeerEntry, sizeof(RT_PEER_ENTRY)); + } + pDefaultAdapter->RxPeerUsedCount = 0; + PlatformReleaseSpinLock(pAdapter, RT_RX_QUEUE_SPINLOCK); +} + +VOID +WDI_DeInitRxQueue( + IN PADAPTER pAdapter + ) +{ + PADAPTER pDefaultAdapter = GetDefaultAdapter(pAdapter); + u2Byte index = 0; + PNET_BUFFER_LIST pNetBufferList=NULL; + + RT_TRACE(COMP_INIT, DBG_LOUD, ("[WDI], WDI_DeInitRxQueue() ==> \n")); + PlatformAcquireSpinLock(pAdapter, RT_RX_QUEUE_SPINLOCK); + for(index=0; index<MAX_PEER_NUM; index++) + { + if( !N6CIsNblWaitQueueEmpty(pDefaultAdapter->RxPeerQueue[index]) ) + { + RT_TRACE(COMP_INIT, DBG_LOUD, ("[WDI], Free MDLs/NBLs for Peer ID %d \n", index)); + pNetBufferList = N6CGetHeadNblWaitQueue(pDefaultAdapter->RxPeerQueue[index]); + RTInitializeSListHead( &(pDefaultAdapter->RxPeerQueue[index]) ); + PlatformReleaseSpinLock(pAdapter, RT_RX_QUEUE_SPINLOCK); + WDI_FreeRxFrame(pAdapter, pNetBufferList); + PlatformAcquireSpinLock(pAdapter, RT_RX_QUEUE_SPINLOCK); + } + } + PlatformReleaseSpinLock(pAdapter, RT_RX_QUEUE_SPINLOCK); + RT_TRACE(COMP_INIT, DBG_LOUD, ("[WDI], WDI_DeInitRxQueue() <== \n")); +} + + +VOID +WDI_PnPNotiry( + IN PADAPTER pAdapter + ) +{ + PWDI_DATA_STRUCT pWdi = &(pAdapter->pPortCommonInfo->WdiData); + + if( pWdi->TaskHandle.Status & RT_OID_HANDLER_STATUS_SET ) + { + OidHandle_Complete(pAdapter, OIDHANDLE_TYPE_TASK); + } + + if( pWdi->PropertyHandle.Status & RT_OID_HANDLER_STATUS_SET ) + { + OidHandle_Complete(pAdapter, OIDHANDLE_TYPE_PROPERTY); + } +} + + +NDIS_STATUS +WDI_HandleOidRequest( + IN NDIS_HANDLE MiniportAdapterContext, + IN PNDIS_OID_REQUEST pNdisRequest + ) +{ + return N6WdiHandleOidRequest(MiniportAdapterContext, pNdisRequest); +} + + +VOID +WdiExt_IndicateApAssocReqReceived( + IN ADAPTER *pAdapter, + IN u4Byte assocReqLen, + IN u1Byte *assocReq + ) +{ + WDI_INDICATION_AP_ASSOCIATION_REQUEST_PARAMETERS param; + OCTET_STRING osAssocReq = {0}; + u2Byte ieOffset = 0; + + u1Byte *buf = NULL; + ULONG buflen = 0; + + if(assocReqLen < sMacHdrLng) + { + RT_TRACE_F(COMP_OID_SET, DBG_LOUD, ("invalid assoc req len: %u\n", assocReqLen)); + return; + } + + PlatformZeroMemory(¶m, sizeof(param)); + + cpMacAddr(param.IncomingRequestInfo.AssocRequestParams.PeerMacAddress.Address, + assocReq + FRAME_OFFSET_ADDRESS2 + ); + + param.IncomingRequestInfo.AssocRequestParams.IsReassociationRequest = + (Type_Reasoc_Req == GET_80211_HDR_TYPE(assocReq)) ? TRUE : FALSE; + + FillOctetString(osAssocReq, assocReq, (u2Byte)assocReqLen); + + if(!PacketGetIeOffset(&osAssocReq, &ieOffset)) + { + RT_TRACE_F(COMP_OID_SET, DBG_LOUD, ("PacketGetIeOffset returns FALSE\n")); + return; + } + + param.IncomingRequestInfo.AssocRequestFrame.ElementCount = osAssocReq.Length - sMacHdrLng; + param.IncomingRequestInfo.AssocRequestFrame.pElements = osAssocReq.Octet + sMacHdrLng; + + // Gen tlv + if(NDIS_STATUS_SUCCESS != GenerateWdiIndicationApAssociationRequestReceived( + ¶m, + sizeof(NDIS_STATUS_INDICATION) + sizeof(WDI_MESSAGE_HEADER), + &pAdapter->pPortCommonInfo->WdiData.TlvContext, + &buflen, &((UINT8 *)buf))) + return; + + wdi_UnsolicitedIndication(pAdapter, + FALSE, + NULL, + NDIS_STATUS_WDI_INDICATION_AP_ASSOCIATION_REQUEST_RECEIVED, + NDIS_STATUS_SUCCESS, + buf, + buflen); + + // cleanup + FreeGenerated((UINT8 *)buf); + + return; +} + +VOID +WdiExt_IndicateApAssocRspSent( + IN ADAPTER *pAdapter, + IN u2Byte status + ) +{ + RT_OID_HANDLER *task = &pAdapter->pPortCommonInfo->WdiData.TaskHandle; + + RT_TRACE_F(COMP_OID_SET, DBG_LOUD, ("indicate association rsp sent\n")); + + if(FALSE == OidHandle_VerifyTask(pAdapter, OID_WDI_TASK_SEND_AP_ASSOCIATION_RESPONSE)) + { + RT_TRACE(COMP_OID_SET, DBG_WARNING, + ("WdiExt_IndicateApAssocRspSent(): skip indication because OidHandle_VerifyTask() returns FALSE\n")); + return; + } + + if(task->pvCtx) + { + if(WDI_CMD_SendApAssociationResponseComplete( + pAdapter, + (NDIS_OID_REQUEST *)task->pvCtx, + StatusCode_success == status ? RT_STATUS_SUCCESS : RT_STATUS_FAILURE)) + {// set pvCtx to NULL only when it is freed in WDI_CMD_SendApAssociationResponseComplete + task->pvCtx = NULL; + } + } + + return; +} + +RT_STATUS +WDIAllocateMetaData( + IN PADAPTER pAdapter, + IN PNET_BUFFER_LIST pNBL, + IN PRT_RFD pRfd +) +{ + PWDI_DATA_STRUCT pWdi = &(pAdapter->pPortCommonInfo->WdiData); + PWDI_FRAME_METADATA pWdiFrameMeta = NULL; + + pWdiFrameMeta = pWdi->WdiDataApi.AllocateWiFiFrameMetaData(pWdi->DataPathHandle); + if( pWdiFrameMeta == NULL ) + return RT_STATUS_FAILURE; + + pWdiFrameMeta->u.rxMetaData.PayloadType = WDI_FRAME_MSDU; + pWdiFrameMeta->pNBL = pNBL; + + RT_TRACE(COMP_RECV, DBG_TRACE, ("PayloadType %d\n", pWdiFrameMeta->u.rxMetaData.PayloadType)); + + MP_SET_PACKET_RFD_RESERVED_0(pNBL, pWdiFrameMeta); + + return RT_STATUS_SUCCESS; +} + + +VOID +WDIFreeMetaData( + IN PADAPTER pAdapter, + IN PNET_BUFFER_LIST pNBL +) +{ + PWDI_DATA_STRUCT pWdi = &(pAdapter->pPortCommonInfo->WdiData); + PWDI_FRAME_METADATA pWdiFrameMeta = NULL; + + pWdiFrameMeta = MP_GET_PACKET_RFD_RESERVED_0(pNBL); + + if( pWdiFrameMeta != NULL ) + pWdi->WdiDataApi.FreeWiFiFrameMetaData(pWdi->DataPathHandle, pWdiFrameMeta); + else + return; + + return; +} + +u4Byte +WDI_InsertDataInQueue( + IN PADAPTER pAdapter, + IN PRT_RFD pRfd, + IN PNET_BUFFER_LIST pNBL +) +{ + PADAPTER pDefaultAdapter = GetDefaultAdapter(pAdapter); + u2Byte PortNumber = (u2Byte)pAdapter->pNdis62Common->PortNumber; + OCTET_STRING osMpdu = {NULL, 0}; + u4Byte PeerId = 0; + PRT_PEER_ENTRY pPeerEntry = NULL; + PNET_BUFFER_LIST pCurrNetBufferList = NULL, pNextNetBufferList = NULL; + + FillOctetString(osMpdu, pRfd->Buffer.VirtualAddress + pRfd->FragOffset, pRfd->FragLength); + + PlatformAcquireSpinLock(pAdapter, RT_RX_QUEUE_SPINLOCK); + +/**************************************************************************************************** +* 20150707 Sinda +* We insert frames in queue as below rules +* 1. Can find the peer with MAC address +* 2. Cannot find the peer with MAC address and insert frames in queue of group peer +****************************************************************************************************/ + pPeerEntry = (PRT_PEER_ENTRY)wdi_FindPeerByAddr(pAdapter, Frame_pTaddr(osMpdu)); + if( pPeerEntry != NULL ) + PeerId = pPeerEntry->uPeerId; + else + { + pPeerEntry = (PRT_PEER_ENTRY)wdi_FindGroupPeerByPort(pAdapter, PortNumber); + if( pPeerEntry == NULL ) + { + PlatformReleaseSpinLock(pAdapter, RT_RX_QUEUE_SPINLOCK); + return 0; + } + else + PeerId = pPeerEntry->uPeerId; + } + + if(pPeerEntry->bUsed == TRUE) + { + RT_TRACE(COMP_RECV, DBG_TRACE, ("WDI_InsertDataInQueue: Port %d, PeerId %d\n", PortNumber, PeerId)); + for (pCurrNetBufferList = pNBL; pCurrNetBufferList != NULL; pCurrNetBufferList = pNextNetBufferList) + { + pNextNetBufferList = NET_BUFFER_LIST_NEXT_NBL(pCurrNetBufferList); + NET_BUFFER_LIST_NEXT_NBL(pCurrNetBufferList) = NULL; + N6CAddNblWaitQueue(&pDefaultAdapter->RxPeerQueue[PeerId], pCurrNetBufferList, FALSE); + } + PlatformReleaseSpinLock(pAdapter, RT_RX_QUEUE_SPINLOCK); + return PeerId + 1; + } + else + { + PlatformReleaseSpinLock(pAdapter, RT_RX_QUEUE_SPINLOCK); + return 0; + } +} + +BOOLEAN +WDI_NotifyDataInQueue( + IN PADAPTER pAdapter, + IN u1Byte ExTid, + IN u2Byte PeerId, + IN RT_RX_INDICATION_LEVEL level +) +{ + PADAPTER pDefaultAdapter = GetDefaultAdapter(pAdapter); + PRT_NDIS6_COMMON pDefaultNdisCommon = pDefaultAdapter->pNdisCommon; + NDIS_STATUS status = NDIS_STATUS_SUCCESS; + + RT_TRACE(COMP_RECV, DBG_TRACE, ("WDI_NotifyDataInQueue: PeerId %d, ExTid %d\n", PeerId, ExTid)); + + wdi_NotifyPeerData(pAdapter, ExTid, PeerId, level, &status); + if( status == NDIS_STATUS_PAUSED ) + { + RT_TRACE_F(COMP_INIT, DBG_WARNING, ("Rx manager pause frame and wait for it to be ready. return value (%d)\n", status)); + PlatformAcquireSpinLock(pAdapter, RT_RX_CONTROL_SPINLOCK); + pDefaultNdisCommon->bRxDataPathState = RT_RX_PAUSE; + GLWdiTxRxStatistics.numWdiRxPause++; + PlatformReleaseSpinLock(pAdapter, RT_RX_CONTROL_SPINLOCK); + return FALSE; + } + else + return TRUE; +} + + +VOID +WDI_CompletePacket( + IN PADAPTER pAdapter, + IN PNET_BUFFER_LIST pNBL +) +{ + PWDI_DATA_STRUCT pWdi = &(pAdapter->pPortCommonInfo->WdiData); + u2Byte count = 0; + WDI_FRAME_ID FrameID[100] = {0}; + PWDI_FRAME_METADATA pFrameMeta = NULL; + BOOLEAN bIndicateSendComplete = FALSE; + + GLWdiTxRxStatistics.numWdiCompletePkt++; + + //RT_TRACE(COMP_INIT, DBG_LOUD, ("[WDI], WDI_CompletePacket() ==>\n")); + // complete only one packet + pFrameMeta = (PWDI_FRAME_METADATA)pNBL->MiniportReserved[0]; + NET_BUFFER_LIST_NEXT_NBL(pNBL) = NULL; + NET_BUFFER_LIST_STATUS(pNBL) = NDIS_STATUS_SUCCESS; + FrameID[count] = pFrameMeta->FrameID; + + if(pFrameMeta->u.txMetaData.bTxCompleteRequired == TRUE) + bIndicateSendComplete = TRUE; + + pWdi->WdiDataApi.TxTransferCompleteIndication(pWdi->DataPathHandle,WDI_TxFrameStatus_Ok,pNBL); + if(bIndicateSendComplete) + { + pWdi->WdiDataApi.TxSendCompleteIndication(pWdi->DataPathHandle, WDI_TxFrameStatus_Ok, count, FrameID, NULL); + } +} + + +VOID +WDI_IndicateScanComplete( + PADAPTER pAdapter, + RT_STATUS status + ) +{ + PMGNT_INFO pMgntInfo = &(pAdapter->MgntInfo); + + if(FALSE == OidHandle_VerifyTask(pAdapter, OID_WDI_TASK_SCAN)) + return; + + OidHandle_Complete(pAdapter, OIDHANDLE_TYPE_TASK); +} + +VOID +WDI_IndicateBssList( + PADAPTER pAdapter, + RT_STATUS status + ) +{ + wdiext_IndicateBSSEntry(pAdapter); +} + +VOID +WDI_IndicateBssListBySSID( + PADAPTER pAdapter, + WDI_SSID *pSSID + ) +{ + wdiext_IndicateBSSEntryBySSID(pAdapter, pSSID); +} + +VOID +WDI_IndicateConnectionComplete( + PADAPTER pAdapter, + RT_STATUS status + ) +{ + PMGNT_INFO pMgntInfo = &(pAdapter->MgntInfo); + + if(FALSE == OidHandle_VerifyTask(pAdapter, OID_WDI_TASK_CONNECT)) + return; + + OidHandle_Complete(pAdapter, OIDHANDLE_TYPE_TASK); +} + + +VOID +WDI_IndicateAssociationComplete( + PADAPTER pAdapter, + RT_STATUS status + ) +{ + if( status == RT_STATUS_SUCCESS ) + { + wdiext_IndicateAssociationResult(pAdapter); + wdiext_IndicateLinkStateChanged(pAdapter, FALSE, 0); + } +} + + +VOID +WDI_IndicateDisassociation( + PADAPTER pAdapter, + u2Byte reason, + pu1Byte pAddr +) +{ + PMGNT_INFO pMgntInfo = &(pAdapter->MgntInfo); + + if(ACTING_AS_AP(pAdapter)) + {// AP mode + RT_WLAN_STA *sta = pMgntInfo->pCurrentSta; + + RT_ASSERT(sta, ("%s(): sta is NULL!!!\n", __FUNCTION__)); + + if(NULL == sta) + { + RT_TRACE_F(COMP_AP, DBG_SERIOUS, ("pMgntInfo->pCurrentSta is NULL!\n")); + return; + } + + wdiext_IndicateDisassociation(pAdapter, sta->MacAddr, 0, NULL, TRUE, reason); + } + else + {// Client mode + wdiext_IndicateDisassociation(pAdapter, pMgntInfo->Bssid, 0, NULL, TRUE, reason); + } + + if( pAddr != NULL ) + { + WDI_DeleteDatapathPeer(pAdapter, pAddr); + } +} + +VOID +WDI_IndicateNLODiscovery( + PADAPTER pAdapter + ) +{ + WDI_INDICATION_NLO_DISCOVERY_PARAMETERS param; + PWDI_BSS_ENTRY_CONTAINER pEntry; + + PRT_NLO_INFO pNLOInfo = &(pAdapter->MgntInfo.NLOInfo); + PRT_WLAN_BSS pRtBss = NULL; + RT_802_11_BSSID_LIST RtBssList = {0}; + u4Byte i = 0; + u4Byte j = 0; + u4Byte nBss = 0; + ULONG buflen = 0; + pu1Byte buf = NULL; + pu1Byte pBssList = NULL; + u4Byte devSpecCtx = 0x07060504; + BOOLEAN Hit = FALSE; + LARGE_INTEGER CurrentTime; + + if(!pAdapter->pPortCommonInfo->WdiData.TaskHandle.pNdisRequest) + return; + + FunctionIn(COMP_POWER); + + // zero + PlatformZeroMemory(¶m, sizeof(param)); + + //Get scan list + RtBssList.NumberOfItems = 0; + RtBssList.pbssidentry = pAdapter->bssDescList; + + MgntActQuery_802_11_BSSID_LIST(pAdapter, &RtBssList, FALSE); + + PlatformAllocateMemoryWithZero(pAdapter, (PVOID *)&pEntry, sizeof(WDI_BSS_ENTRY_CONTAINER)*RtBssList.NumberOfItems); + + param.DeviceDescriptor.pElements = pEntry; + nBss = 0; + + + // Indicate those found BSS which we desired + for ( i=0 ; i<RtBssList.NumberOfItems ; i++) + { + Hit = FALSE; + + if(RtBssList.pbssidentry[i].IE.Length <= sizeof(RT_FIXED_IE_FIELD)) + { + continue; + } + + pRtBss = &(RtBssList.pbssidentry[i]); + + // Determine if we shall report the BSS found by RegWirelessMode4ScanList. + if(!WDIFilterRtBss(pAdapter, pRtBss)) + { + // Skip this BSS. + continue; + } + + for( j=0 ; j<pNLOInfo->NumDot11OffloadNetwork ; ++j ) + { + // Compare to check whether it is what we desired or not + if(!PlatformCompareMemory(pNLOInfo->dDot11OffloadNetworkList[j].ssidbuf, pRtBss->bdSsIdBuf, 32)) + { + ++nBss; + Hit = TRUE; + } + } + + if( !Hit ) // This BSS is not we desired. + continue; + + // WIFI_MAC_ADDRESS_CONTAINER BSSID + cpMacAddr(pEntry->BSSID.Address, pRtBss->bdBssIdBuf); + + // WIFI_BYTE_BLOB ProbeResponseFrame, BeaconFrame + if(pRtBss->BssPacketType & BSS_PKT_BEACON) + { + pEntry->Optional.BeaconFrame_IsPresent = TRUE; + pEntry->BeaconFrame.ElementCount = pRtBss->IE.Length; + pEntry->BeaconFrame.pElements = (UINT8 *)pRtBss->IE.Octet; + } + else if(pRtBss->BssPacketType & BSS_PKT_PROBE_RSP) + { + pEntry->Optional.ProbeResponseFrame_IsPresent = TRUE; + pEntry->ProbeResponseFrame.ElementCount = pRtBss->IE.Length; + pEntry->ProbeResponseFrame.pElements = (UINT8 *)pRtBss->IE.Octet; + } + else + { + RT_TRACE(COMP_POWER, DBG_LOUD, ("Unknown BssPacketType: %u\n", pRtBss->BssPacketType)); + FunctionOut(COMP_POWER); + return; + } + + // WDI_SIGNAL_INFO_CONTAINER SignalInfo + pRtBss->RecvSignalPower = 0xffffffce; + pEntry->SignalInfo.RSSI = (INT32)pRtBss->CumRecvSignalPower; + pEntry->SignalInfo.LinkQuality = (UINT32)pRtBss->RSSI; + + // WDI_CHANNEL_INFO_CONTAINER ChannelInfo + pEntry->ChannelInfo.ChannelNumber = (UINT32)pRtBss->ChannelNumber; + pEntry->ChannelInfo.BandId = (pRtBss->ChannelNumber < 36) ? WDI_BAND_ID_2400 : WDI_BAND_ID_5000; + RT_TRACE(COMP_POWER, DBG_LOUD, ("pRtBss->ChannelNumber=%d, ", pRtBss->ChannelNumber)); + RT_TRACE(COMP_POWER, DBG_LOUD, ("%x:%x:%x:%x:%x:%x, ", + pEntry->BSSID.Address[0], pEntry->BSSID.Address[1], + pEntry->BSSID.Address[2], pEntry->BSSID.Address[3], + pEntry->BSSID.Address[4], pEntry->BSSID.Address[5])); + RT_TRACE(COMP_POWER, DBG_LOUD, ("SSID: %s\n", pRtBss->bdSsIdBuf)); + + // WDI_BYTE_BLOB DeviceSpecificContext, this is OPTIONAL + pEntry->Optional.DeviceSpecificContext_IsPresent = TRUE; + pEntry->DeviceSpecificContext.ElementCount = sizeof(devSpecCtx); + pEntry->DeviceSpecificContext.pElements = (UINT8 *)&devSpecCtx; + + // Get current timestamp + NdisGetCurrentSystemTime(&CurrentTime); + + // WDI_AGE_INFO_CONTAINER EntryAgeInfo + pEntry->EntryAgeInfo.HostTimeStamp = CurrentTime.QuadPart; // [SDIO-482] in JIRA + pEntry->EntryAgeInfo.CachedInformation = 0; + } + + if(nBss == 0) + { + RT_TRACE(COMP_POWER, DBG_LOUD, ("WDI_IndicateNLODiscovery(): Error, # of Hit SSID is ZERO.\n")); + FunctionOut(COMP_POWER); + return; + } + + param.DeviceDescriptor.ElementCount = nBss; + + RT_TRACE(COMP_POWER, DBG_LOUD, ("# of BSS Found: %u\n", param.DeviceDescriptor.ElementCount)); + + // Gen tlv + if(NDIS_STATUS_SUCCESS != GenerateWdiIndicationNloDiscovery( + ¶m, + sizeof(NDIS_STATUS_INDICATION) + sizeof(WDI_MESSAGE_HEADER), + &pAdapter->pPortCommonInfo->WdiData.TlvContext, + &buflen, &((UINT8 *)buf))) + { + RT_TRACE(COMP_POWER, DBG_LOUD, ("WDI_IndicateNLODiscovery(): GenerateWdiIndicationNloDiscovery Failed\n")); + FunctionOut(COMP_POWER); + return; + } + + wdi_UnsolicitedIndication( pAdapter, + FALSE, + NULL, + NDIS_STATUS_WDI_INDICATION_NLO_DISCOVERY, + NDIS_STATUS_SUCCESS, + buf, + buflen); + + // cleanup + FreeGenerated((UINT8 *)buf); + + FunctionOut(COMP_POWER); +} + + +VOID +WDI_IndicateCurrentPhyStatus( + PADAPTER pAdapter + ) +{ + wdiext_IndicateRadioStatus(pAdapter); +} + + +VOID +WDI_IndicateP2PEvent( + VOID *pvP2PInfo, + u4Byte EventID, + MEMORY_BUFFER *pInformation + + ) +{ + P2P_INFO *pP2PInfo = (P2P_INFO *)pvP2PInfo; + RT_OID_HANDLER *task = &pP2PInfo->pAdapter->pPortCommonInfo->WdiData.TaskHandle; + + if(P2P_EVENT_DEV_FOUND == EventID) + { + wdiext_IndicateP2PDeviceFound(pP2PInfo->pAdapter, pInformation->Buffer); + } + else if(P2P_EVENT_RECEIVED_PROVISION_DISCOVERY_REQUEST == EventID + || P2P_EVENT_RECEIVED_GO_NEGOTIATION_REQUEST == EventID + || P2P_EVENT_RECEIVED_INVITATION_REQUEST == EventID + ) + {// rx req action + WDI_CMD_PreIndicateRxP2pActionFrameCb(pvP2PInfo, EventID, pInformation); + wdiext_IndicateP2PActionFrameReceived(pvP2PInfo, EventID, pInformation); + WDI_CMD_PostIndicateRxP2pActionFrameCb(pvP2PInfo, EventID, pInformation); + } + else if(P2P_EVENT_RECEIVED_PROVISION_DISCOVERY_RESPONSE == EventID + || P2P_EVENT_RECEIVED_INVITATION_RESPONSE == EventID + || P2P_EVENT_RECEIVED_GO_NEGOTIATION_RESPONSE == EventID + || P2P_EVENT_RECEIVED_GO_NEGOTIATION_CONFIRM == EventID + ) + {// rx rsp action + WDI_CMD_PreIndicateRxP2pActionFrameCb(pvP2PInfo, EventID, pInformation); + + // indicate in the corresp. OffChnlTx complete cb + //wdiext_IndicateP2PActionFrameReceived(pvP2PInfo, EventID, pInformation); + + WDI_CMD_PostIndicateRxP2pActionFrameCb(pvP2PInfo, EventID, pInformation); + } + else if(P2P_EVENT_GO_OPERATING_CHANNEL == EventID) + { + wdiext_IndicateP2POpChnl(pP2PInfo->pAdapter, pP2PInfo); + } + + return; +} + + +BOOLEAN +WDI_CompleteCreateDeleteMac( + IN PADAPTER pAdapter, + IN NDIS_STATUS status + ) +{ + PPORT_HELPER pPortHelper = pAdapter->pPortCommonInfo->pPortHelper; + BOOLEAN bCompleteStatus = FALSE; + + if(pPortHelper->bCreateMac) + bCompleteStatus = WDI_CMD_CreatePortComplete(pAdapter, pPortHelper->pCreateDeleteOID, status); + else if(pPortHelper->bDeleteMac) + bCompleteStatus = WDI_CMD_DeletePortComplete(pAdapter, pPortHelper->pCreateDeleteOID, status); + + return bCompleteStatus; +} + +VOID +WDI_IndicateLinkStateChanged( + PADAPTER pAdapter, + BOOLEAN bForceLinkQuality, + u1Byte ucLinkQuality + ) +{ + wdiext_IndicateLinkStateChanged(pAdapter, bForceLinkQuality, ucLinkQuality); +} + +RT_STATUS +WDI_IndicateActionFrame( + IN PADAPTER pAdapter, + IN POCTET_STRING posMpdu +) +{ + NDIS_STATUS_INDICATION *indic = NULL; + WDI_MESSAGE_HEADER *wdiHdr = NULL; + + u1Byte *buf = NULL; + ULONG buflen = 0; + + WDI_INDICATION_ACTION_FRAME_RECEIVED_PARAMETERS param = {0}; + + RT_TRACE(COMP_OID_SET, DBG_WARNING, ("WDI_IndicateActionFrame +\n")); + + + // TODO: fill the valid info into param + PlatformMoveMemory(param.SourceAddress.Address,Frame_pSaddr(*posMpdu),6); + param.ActionFrameBody.pElements = posMpdu->Octet+24;//get rid of header + param.ActionFrameBody.ElementCount = posMpdu->Length; + + // TODO: double check here to make sure channel correct + param.ChannelInfo.ChannelNumber = RT_GetChannelNumber(pAdapter); + param.ChannelInfo.BandId = WDI_BAND_ID_2400; + + if(NDIS_STATUS_SUCCESS != GenerateWdiIndicationActionFrameReceived( + ¶m, + sizeof(*indic) + sizeof(*wdiHdr), + &pAdapter->pPortCommonInfo->WdiData.TlvContext, + &buflen, &((UINT8 *)buf))) + { + RT_TRACE(COMP_OID_SET, DBG_WARNING, ("ActionFrame generate tlv failed\n")); + return NDIS_STATUS_FAILURE; + } + + indic = (NDIS_STATUS_INDICATION *)buf; + wdiHdr = (WDI_MESSAGE_HEADER *)(buf + sizeof(*indic)); + + PlatformZeroMemory(indic, sizeof(*indic)); + indic->Header.Type = NDIS_OBJECT_TYPE_STATUS_INDICATION; + indic->Header.Size = NDIS_SIZEOF_STATUS_INDICATION_REVISION_1; + indic->Header.Revision = NDIS_STATUS_INDICATION_REVISION_1; + indic->SourceHandle = pAdapter; + indic->PortNumber = 0; + indic->StatusCode = NDIS_STATUS_WDI_INDICATION_ACTION_FRAME_RECEIVED; + indic->RequestId = 0; // ? + indic->StatusBuffer = wdiHdr; + indic->StatusBufferSize = buflen - sizeof(*indic); + + wdiHdr->PortId = (WDI_PORT_ID)(GET_PORT_NUMBER(pAdapter)); + wdiHdr->Reserved = 0; + wdiHdr->Status = NDIS_STATUS_SUCCESS; + wdiHdr->TransactionId = 0; + wdiHdr->IhvSpecificId = 0; + + NdisMIndicateStatusEx(pAdapter->pNdisCommon->hNdisAdapter, indic); + + FreeGenerated((UINT8 *)buf); + + return RT_STATUS_SUCCESS; +} + +VOID +WDI_IndicateWakeReason( + IN PADAPTER pAdapter, + IN BOOLEAN bWakePacket, + IN pu1Byte pBuffer, + IN u2Byte BufferLen + ) +{ + WDI_INDICATION_WAKE_REASON_PARAMETERS param; + + PMGNT_INFO pMgntInfo = &(pAdapter->MgntInfo); + PRT_POWER_SAVE_CONTROL pPSC = GET_POWER_SAVE_CONTROL(pMgntInfo); + pu1Byte pWakePktbuf = NULL; + BOOLEAN bIndicate = TRUE; + u1Byte *buf = NULL; + ULONG buflen = 0; + + PlatformZeroMemory(¶m, sizeof(WDI_INDICATION_WAKE_REASON_PARAMETERS)); + + if(bWakePacket) + { + if(pPSC->WakeUpReason == WOL_REASON_MAGIC_PKT) + param.Optional.WakePacket_IsPresent = 1; + else if(pPSC->WakeUpReason == WOL_REASON_PATTERN_PKT) + param.Optional.WakePacketPatternId_IsPresent = 1; + else + { + RT_TRACE(COMP_POWER, DBG_SERIOUS, ("WDI_IndicateWakeReason(): Unknown pPSC->WakeUpReason(%#x)\n", pPSC->WakeUpReason)); + } + + param.WakeEventCode = WDI_WAKE_REASON_CODE_PACKET; + param.WakePacketPatternId = pPSC->MagicPacketPatternId; + + PlatformAllocateMemoryWithZero(pAdapter, (PVOID *)&pWakePktbuf, BufferLen); + + PlatformMoveMemory(pWakePktbuf, pBuffer, BufferLen); + + param.WakePacket.ElementCount = 1; + param.WakePacket.pElements = pWakePktbuf; + + RT_PRINT_DATA(COMP_POWER, DBG_LOUD, "WDI_IndicateWakeReason(): packet\n", param.WakePacket.pElements, BufferLen); + } + else + { + if(pPSC->WakeUpReason == WOL_REASON_AP_LOST || + pPSC->WakeUpReason == WOL_REASON_DEAUTH || + pPSC->WakeUpReason == WOL_REASON_DISASSOC) + { + param.WakeEventCode = WDI_WAKE_REASON_CODE_AP_ASSOCIATION_LOST; + } + else if(pPSC->WakeUpReason == WOL_REASON_NLO_SSID_MATCH) + { + param.WakeEventCode = WDI_WAKE_REASON_CODE_NLO_DISCOVERY; + } + else if(pPSC->WakeUpReason == WOL_REASON_PTK_UPDATE) + { + param.WakeEventCode = WDI_WAKE_REASON_CODE_4WAY_HANDSHAKE_REQUEST; + } + else + { + param.WakeEventCode = NdisWakeReasonUnspecified; + bIndicate = FALSE; + } + } + + if(bIndicate) + { + RT_TRACE(COMP_POWER, DBG_LOUD, ("WDI_IndicateWakeReason(): WakeEventCode(%#X)\n", param.WakeEventCode)); + + // Gen tlv + if(NDIS_STATUS_SUCCESS != GenerateWdiIndicationWakeReasonFromIhv( + ¶m, + sizeof(NDIS_STATUS_INDICATION) + sizeof(WDI_MESSAGE_HEADER), + &pAdapter->pPortCommonInfo->WdiData.TlvContext, + &buflen, &((UINT8 *)buf))) + { + RT_TRACE(COMP_POWER, DBG_LOUD, ("WDI_IndicateWakeReason(): GenerateWdiIndicationWakeReasonFromIhv Failed\n")); + return; + } + + wdi_UnsolicitedIndication(pAdapter, + FALSE, + NULL, + NDIS_STATUS_WDI_INDICATION_WAKE_REASON, + NDIS_STATUS_SUCCESS, + buf, + buflen); + + // cleanup + FreeGenerated((UINT8 *)buf); + } + +} + + +VOID +WDI_IndicateRoamingNeeded( + PADAPTER pAdapter, + RT_PREPARE_ROAM_TYPE IndicationReason + ) +{ + PMGNT_INFO pMgntInfo = &(pAdapter->MgntInfo); + + pMgntInfo->PrepareRoamState = IndicationReason; + + switch(IndicationReason) + { + case RT_PREPARE_ROAM_DEAUTH_DISASSOC: + wdiext_IndicateRoamingNeeded(pAdapter, WDI_ASSOC_STATUS_PEER_DEAUTHENTICATED); + break; + case RT_PREPARE_ROAM_NORMAL_ROAM_POOR_LINK: + wdiext_IndicateRoamingNeeded(pAdapter, WDI_ASSOC_STATUS_DISASSOCIATE_NOT_VISIBLE); + break; + case RT_PREPARE_ROAM_NORMAL_ROAM_BETTER_AP: + wdiext_IndicateRoamingNeeded(pAdapter, WDI_ASSOC_STATUS_ROAMING_BETTER_AP_FOUND); + break; + default: + break; + } +} + +VOID +WDI_IndicateRoamingComplete( + PADAPTER pAdapter + ) +{ + PMGNT_INFO pMgntInfo = GetDefaultMgntInfo(pAdapter); + + if(FALSE == OidHandle_VerifyTask(pAdapter, OID_WDI_TASK_ROAM)) + return; + + OidHandle_Complete(pAdapter, OIDHANDLE_TYPE_TASK); +} + +VOID +WDI_AddGroupPeer( + IN PADAPTER pAdapter, + IN u2Byte PortNumber + ) +{ + PADAPTER pDefaultAdapter = GetDefaultAdapter(pAdapter); + PWDI_DATA_STRUCT pWdi = &(pAdapter->pPortCommonInfo->WdiData); + WDI_MAC_ADDRESS PeerAddr = {0}; + PRT_PEER_ENTRY pPeerEntry = NULL; + u1Byte i = 0; + + FunctionIn(COMP_INIT); + + PlatformAcquireSpinLock(pAdapter, RT_RX_QUEUE_SPINLOCK); + for(i = 0; i < MP_DEFAULT_NUMBER_OF_PORT; i++) + { + pPeerEntry = &pDefaultAdapter->RxPeerTable[i]; + if( pPeerEntry->bUsed == FALSE ) + { + RT_TRACE(COMP_INIT, DBG_LOUD, ("WDI_AddGroupPeer: create group peer %d for port %d\n", i, PortNumber)); + break; + } + } + + if( i == MP_DEFAULT_NUMBER_OF_PORT ) + { + RT_TRACE(COMP_INIT, DBG_WARNING, ("WDI_AddGroupPeer: there is no available group peer for port %d\n", PortNumber)); + FunctionOut(COMP_INIT); + PlatformReleaseSpinLock(pAdapter, RT_RX_QUEUE_SPINLOCK); + return ; + } + + pPeerEntry->bUsed = TRUE; + pPeerEntry->uPeerId = i; + pPeerEntry->uPortId = PortNumber; + PlatformMoveMemory(pPeerEntry->PeerAddr, MAC_BROADCAST_ADDR, 6); + PlatformMoveMemory(PeerAddr.Address, pPeerEntry->PeerAddr, 6); + pWdi->WdiDataApi.PeerCreateIndication(pWdi->DataPathHandle, (WDI_PORT_ID)pPeerEntry->uPortId, (WDI_PEER_ID)pPeerEntry->uPeerId, PeerAddr); + + PlatformReleaseSpinLock(pAdapter, RT_RX_QUEUE_SPINLOCK); + + FunctionOut(COMP_INIT); +} + +VOID +WDI_DeleteGroupPeer( + IN PADAPTER pAdapter, + IN u2Byte PortNumber + ) +{ + PWDI_DATA_STRUCT pWdi = &(pAdapter->pPortCommonInfo->WdiData); + PADAPTER pDefaultAdapter = GetDefaultAdapter(pAdapter); + NDIS_STATUS ndisStatus = NDIS_STATUS_SUCCESS; + WDI_PEER_ID PeerId = 0; + PRT_PEER_ENTRY pPeerEntry = NULL; + u1Byte i; + + FunctionIn(COMP_INIT); + + PlatformAcquireSpinLock(pAdapter, RT_RX_QUEUE_SPINLOCK); + + pPeerEntry = (PRT_PEER_ENTRY)wdi_FindGroupPeerByPort(pAdapter, PortNumber); + if( pPeerEntry == NULL ) + { + RT_TRACE(COMP_INIT, DBG_WARNING, ("wdi_FindPeerByAddr: Cannot find group peer of port %d\n", PortNumber)); + FunctionOut(COMP_INIT); + PlatformReleaseSpinLock(pAdapter, RT_RX_QUEUE_SPINLOCK); + return ; + } + else + { + PeerId = (WDI_PEER_ID)pPeerEntry->uPeerId; + pPeerEntry->bUsed = FALSE; + + PlatformZeroMemory(pPeerEntry->PeerAddr, 6); + + pWdi->WdiDataApi.PeerDeleteIndication(pWdi->DataPathHandle, (WDI_PORT_ID)PortNumber, PeerId, &ndisStatus); + + WDI_FreeRxFrame(pAdapter, (PNET_BUFFER_LIST)N6CGetHeadNblWaitQueue(pDefaultAdapter->RxPeerQueue[PeerId])); + RTInitializeSListHead(&pDefaultAdapter->RxPeerQueue[PeerId]); + + RT_TRACE(COMP_INIT, DBG_LOUD, ("WDI_DeleteGroupPeer: delete group peer %d of port %d, Status: %d\n", PeerId, PortNumber, ndisStatus)); + } + + PlatformReleaseSpinLock(pAdapter, RT_RX_QUEUE_SPINLOCK); + + FunctionOut(COMP_INIT); +} + +NDIS_STATUS +WDI_AddDatapathPeer( + IN PADAPTER pAdapter, + IN pu1Byte pAddr) +{ + PADAPTER pDefaultAdapter = GetDefaultAdapter(pAdapter); + PWDI_DATA_STRUCT pWdi = &(pAdapter->pPortCommonInfo->WdiData); + WDI_PEER_ID HashPeer = 0, RelocatePeer = 0; + WDI_PORT_ID PortId = (WDI_PORT_ID)pAdapter->pNdis62Common->PortNumber; + WDI_MAC_ADDRESS PeerAddr = {0}; + PRT_PEER_ENTRY pPeerEntry = NULL; + + FunctionIn(COMP_MLME); + + PlatformAcquireSpinLock(pAdapter, RT_RX_QUEUE_SPINLOCK); + + pPeerEntry = (PRT_PEER_ENTRY)wdi_GetAvailablePeer(pAdapter, pAddr); + if( pPeerEntry != NULL ) + { + PlatformMoveMemory(PeerAddr.Address, pPeerEntry->PeerAddr, 6); + pWdi->WdiDataApi.PeerCreateIndication(pWdi->DataPathHandle, (WDI_PORT_ID)pPeerEntry->uPortId, (WDI_PEER_ID)pPeerEntry->uPeerId, PeerAddr); + + PlatformReleaseSpinLock(pAdapter, RT_RX_QUEUE_SPINLOCK); + + FunctionOut(COMP_MLME); + + return NDIS_STATUS_SUCCESS; + } + + PlatformReleaseSpinLock(pAdapter, RT_RX_QUEUE_SPINLOCK); + + FunctionOut(COMP_MLME); + + return NDIS_STATUS_FAILURE; +} + +void WDI_DeleteDatapathPeer( + IN PADAPTER pAdapter, + IN pu1Byte pAddr +) +{ + PWDI_DATA_STRUCT pWdi = &(pAdapter->pPortCommonInfo->WdiData); + PADAPTER pDefaultAdapter = GetDefaultAdapter(pAdapter); + WDI_PORT_ID PortId = 0; + NDIS_STATUS ndisStatus = NDIS_STATUS_SUCCESS; + WDI_PEER_ID PeerId = 0; + PRT_PEER_ENTRY pPeerEntry = NULL; + + FunctionIn(COMP_MLME); + + PlatformAcquireSpinLock(pAdapter, RT_RX_QUEUE_SPINLOCK); + + pPeerEntry = (PRT_PEER_ENTRY)wdi_FindPeerByAddr(pAdapter, pAddr); + if( pPeerEntry == NULL ) + { + RT_TRACE(COMP_MLME, DBG_WARNING, ("wdi_FindPeerByAddr: Cannot find the addres [%2x:%2x:%2x:%2x:%2x:%2x] associated at any peer\n", pAddr[0], pAddr[1], pAddr[2], pAddr[3], pAddr[4], pAddr[5])); + FunctionOut(COMP_MLME); + PlatformReleaseSpinLock(pAdapter, RT_RX_QUEUE_SPINLOCK); + return ; + } + RT_TRACE(COMP_INIT, DBG_LOUD, ("WDI_DeleteDatapathPeer: Find the addres [%2x:%2x:%2x:%2x:%2x:%2x] associated at Peer %d\n", pAddr[0], pAddr[1], pAddr[2], pAddr[3], pAddr[4], pAddr[5], pPeerEntry->uPeerId)); + + pDefaultAdapter->RxPeerUsedCount--; + PeerId = (WDI_PEER_ID)pPeerEntry->uPeerId; + PortId = (WDI_PORT_ID)pPeerEntry->uPortId; + pPeerEntry->bUsed = FALSE; + PlatformZeroMemory(pPeerEntry->PeerAddr, 6); + + pWdi->WdiDataApi.PeerDeleteIndication(pWdi->DataPathHandle, PortId, PeerId, &ndisStatus); + + WDI_FreeRxFrame(pAdapter, (PNET_BUFFER_LIST)N6CGetHeadNblWaitQueue(pDefaultAdapter->RxPeerQueue[PeerId])); + RTInitializeSListHead(&pDefaultAdapter->RxPeerQueue[PeerId]); + + PlatformReleaseSpinLock(pAdapter, RT_RX_QUEUE_SPINLOCK); + + RT_TRACE(COMP_MLME, DBG_LOUD, ("WDI_DeleteDatapathPeer: delete peer %d, Status: %d\n", PeerId, ndisStatus)); + + FunctionOut(COMP_MLME); +} + +VOID +WDI_FetchNBLByPort( + IN PADAPTER pAdapter, + IN u2Byte Port_ID, + OUT PNET_BUFFER_LIST *ppNetBufferList +) +{ + PADAPTER pDefaultAdapter = GetDefaultAdapter(pAdapter); + u2Byte index = 0; + PRT_SINGLE_LIST_ENTRY pFirst = NULL, pTemp = NULL; + + *ppNetBufferList = NULL; + + RT_TRACE(COMP_RECV, DBG_LOUD, ("WDI_FetchNBLByPort: fetch frames of all peers at port %d\n", Port_ID)); + + if( Port_ID != WDI_PORT_ANY ) + { + PlatformAcquireSpinLock(pAdapter, RT_RX_QUEUE_SPINLOCK); + for(index = 0; index < MAX_PEER_NUM; index++) + { + if( (pDefaultAdapter->RxPeerTable[index].bUsed == TRUE) && (pDefaultAdapter->RxPeerTable[index].uPortId == Port_ID) ) + { + if(N6CIsNblWaitQueueEmpty(pDefaultAdapter->RxPeerQueue[index])) + continue; + + pTemp = RTGetHeadSList(&pDefaultAdapter->RxPeerQueue[index]); + if( pFirst == NULL ) + { + pFirst = pTemp; + } + else + { + N6CConcatenateTwoList(pFirst, pTemp); + } + RTInitializeSListHead(&pDefaultAdapter->RxPeerQueue[index]); + } + } + + if( pFirst != NULL ) + { + *ppNetBufferList = RT_GET_NBL_FROM_QUEUE_LINK(pFirst); + } + PlatformReleaseSpinLock(pAdapter, RT_RX_QUEUE_SPINLOCK); + } + else + { + PlatformAcquireSpinLock(pAdapter, RT_RX_QUEUE_SPINLOCK); + for(index = 0; index < MAX_PEER_NUM; index++) + { + if( (pDefaultAdapter->RxPeerTable[index].bUsed == TRUE) ) + { + if(N6CIsNblWaitQueueEmpty(pDefaultAdapter->RxPeerQueue[index])) + continue; + + pTemp = RTGetHeadSList(&pDefaultAdapter->RxPeerQueue[index]); + if( pFirst == NULL ) + { + pFirst = pTemp; + } + else + { + N6CConcatenateTwoList(pFirst, pTemp); + } + RTInitializeSListHead(&pDefaultAdapter->RxPeerQueue[index]); + } + } + + if( pFirst != NULL ) + { + *ppNetBufferList = RT_GET_NBL_FROM_QUEUE_LINK(pFirst); + } + PlatformReleaseSpinLock(pAdapter, RT_RX_QUEUE_SPINLOCK); + } +} + +VOID +WDI_FreeRxFrame( + IN PADAPTER pAdapter, + IN PNET_BUFFER_LIST pNetBufferList +) +{ + PADAPTER pDefaultAdapter = GetDefaultAdapter(pAdapter); + PRT_RFD pRfd = NULL; + PMDL pCurrMdl = NULL, pNextMdl = NULL; + PNET_BUFFER_LIST pNextNBL = NULL; + u4Byte Count; + PRT_NDIS6_COMMON pNdisCommon = pAdapter->pNdisCommon; + + FunctionIn(COMP_RECV); + + if( pNetBufferList == NULL ) + { + RT_TRACE(COMP_RECV, DBG_TRACE, ("WDI_FreeRxFrame: pNetBufferList is NULL\n")); + FunctionOut(COMP_RECV); + return; + } + + do + { + //Get next NBL + pNextNBL = NET_BUFFER_LIST_NEXT_NBL(pNetBufferList); + + //Get RFD from NBL + pRfd = MP_GET_PACKET_RFD(pNetBufferList); + + //Free all MDL + for (pCurrMdl = NET_BUFFER_FIRST_MDL( NET_BUFFER_LIST_FIRST_NB(pNetBufferList) ); + pCurrMdl != NULL; + pCurrMdl = pNextMdl) + { + pNextMdl = NDIS_MDL_LINKAGE(pCurrMdl); + NdisFreeMdl(pCurrMdl); + } + + //Free Rx metadata + WDIFreeMetaData(pAdapter, pNetBufferList); + + //Free NBL + NdisFreeNetBufferList(pNetBufferList); + + //Re-calculate reference count + PlatformAcquireSpinLock(pAdapter, RT_RX_REF_CNT_SPINLOCK); + RT_DEC_RCV_REF(pDefaultAdapter); + Count = RT_GET_RCV_REF(pDefaultAdapter); + GLWdiTxRxStatistics.numRxReturnNBLFromUE++; + PlatformReleaseSpinLock(pAdapter, RT_RX_REF_CNT_SPINLOCK); + + //Return RFD to RFD list + if( pRfd != NULL ) + { + ReturnRFDList(pAdapter, pRfd); + } + + //Assign NextNBL pointer + pNetBufferList = pNextNBL; + }while(pNetBufferList!=NULL); + + if (Count == 0) + { + NdisSetEvent(&pNdisCommon->AllPacketReturnedEvent); + + if(pAdapter->MgntInfo.NdisVersion >= RT_NDIS_VERSION_6_20) + { + PADAPTER pTempAdapter = GetFirstExtAdapter(pAdapter); + while(pTempAdapter != NULL) + { + NdisSetEvent(&pTempAdapter->pNdisCommon->AllPacketReturnedEvent); + pTempAdapter = GetNextExtAdapter(pTempAdapter); + } + } + } + + FunctionOut(COMP_RECV); +} + +VOID +WDI_IndicateTKIPMICFailure( + PADAPTER pAdapter + ) +{ + PMGNT_INFO pMgntInfo; + pMgntInfo = &(pAdapter->MgntInfo); + PUCHAR pOutput = NULL; + ULONG length = 0; + NDIS_STATUS ndisStatus = NDIS_STATUS_SUCCESS; + WDI_INDICATION_TKIP_MIC_FAILURE_PARAMETERS Params={0}; + + FunctionIn(COMP_SEC); + + + Params.FailureInfo.DefaultKeyFailure = FALSE; + Params.FailureInfo.KeyIndex=0; + //WDI_TKIPFailureParam.PeerMacAddress=pMgntInfo->Bssid; + cpMacAddr(Params.FailureInfo.PeerMacAddress.Address, pMgntInfo->Bssid); + + + + ndisStatus = GenerateWdiIndicationTkipMicFailure( + &Params, + sizeof(NDIS_STATUS_INDICATION)+sizeof(WDI_MESSAGE_HEADER), + &pAdapter->pPortCommonInfo->WdiData.TlvContext, + &length, + &pOutput); + + if(NDIS_STATUS_SUCCESS == ndisStatus) + { + wdi_UnsolicitedIndication(pAdapter, + FALSE, + NULL, + NDIS_STATUS_WDI_INDICATION_TKIP_MIC_FAILURE, + ndisStatus, + pOutput, + length); + + FreeGenerated(pOutput); + pOutput = NULL; + } + FunctionOut(COMP_SEC); + + +} + +VOID +WDI_TxCreditCheck( + IN PADAPTER pAdapter + ) +{ + PWDI_DATA_STRUCT pWdi = &(pAdapter->pPortCommonInfo->WdiData); + u4Byte preTxPauseReason; + u2Byte txCredit=0; + + GLWdiTxRxStatistics.numCheckTxPause++; + GLWdiTxRxStatistics.monitorTxPauseReason = pWdi->txPauseReason; + + // First check if we have pause indication before. + // not to acquire tx lock frequently, so we do not acquire tx lock when read, but remember + // we should acquire tx lock when need to change the pause reason. + if(pWdi->txPauseReason) + { + PlatformAcquireSpinLock(pAdapter, RT_TX_SPINLOCK); + + txCredit = *Get_NUM_IDLE_TCB(pAdapter); + preTxPauseReason = pWdi->txPauseReason; + + RT_TRACE(COMP_INIT, DBG_LOUD, ("[WDI], WDI_TxCreditCheck(): txCredit=%d\n", txCredit)); + + if(txCredit > (pAdapter->RT_TCB_NUM/4)) + { + GLWdiTxRxStatistics.numTxResourceAvailable++; + + if( (preTxPauseReason&WDI_TX_PAUSE_REASON_CREDIT) == WDI_TX_PAUSE_REASON_CREDIT) + { + RT_TRACE(COMP_INIT, DBG_LOUD, ("[WDI], WDI_TxCreditCheck(): TxPauseReason = 0x%x!!!\n", preTxPauseReason)); + GLWdiTxRxStatistics.numWdiTxRestartIndicate++; + RT_TRACE(COMP_INIT, DBG_LOUD, ("[WDI], WDI_TxCreditCheck(): TxSendRestart: %d times!!!\n", + GLWdiTxRxStatistics.numWdiTxRestartIndicate)); + + pWdi->txPauseReason &= ~WDI_TX_PAUSE_REASON_CREDIT; + PlatformReleaseSpinLock(pAdapter, RT_TX_SPINLOCK); + + // Before indicate to WDI, release the tx lock. + pWdi->WdiDataApi.TxSendRestartIndication(pWdi->DataPathHandle, + WDI_PORT_ANY, + WDI_PEER_ANY, + WDI_EXT_TID_UNKNOWN, + WDI_TX_PAUSE_REASON_CREDIT); + RT_TRACE(COMP_INIT, DBG_LOUD, ("[WDI], WDI_TxCreditCheck(): pWdi->txPauseReason = 0x%x\n", pWdi->txPauseReason)); + } + else + { + PlatformReleaseSpinLock(pAdapter, RT_TX_SPINLOCK); + } + } + else + { + PlatformReleaseSpinLock(pAdapter, RT_TX_SPINLOCK); + } + } +} + +VOID +WDI_IndicateFWStalled( + IN PADAPTER pAdapter + ) +{ + PWDI_DATA_STRUCT pWdi = &(pAdapter->pPortCommonInfo->WdiData); + NDIS_STATUS_INDICATION statusIndication = {0}; + WDI_MESSAGE_HEADER WdiHeader = {0}; + + if(!pWdi->bWdiLEPLDR) + return; + + RT_TRACE(COMP_OID_SET, DBG_LOUD, ("==> WDI_IndicateFWStalled\n")); + + N6_ASSIGN_OBJECT_HEADER( + statusIndication.Header, + NDIS_OBJECT_TYPE_STATUS_INDICATION, + NDIS_SIZEOF_STATUS_INDICATION_REVISION_1, + NDIS_STATUS_INDICATION_REVISION_1); + + WdiHeader.PortId = 0xFFFF; + WdiHeader.Status = NDIS_STATUS_SUCCESS; + WdiHeader.TransactionId = 0; + + statusIndication.RequestId = NULL; + statusIndication.SourceHandle = pAdapter; + statusIndication.StatusBuffer = &WdiHeader; + statusIndication.StatusBufferSize = sizeof(WDI_MESSAGE_HEADER); + + statusIndication.StatusCode = NDIS_STATUS_WDI_INDICATION_FIRMWARE_STALLED; + + NdisMIndicateStatusEx( + pAdapter->pNdisCommon->hNdisAdapter, + &statusIndication + ); +} + +VOID +WDI_UpdateDefaultSetting( + IN PADAPTER pAdapter + ) +{ + PRT_NDIS_COMMON pNdisCommon = pAdapter->pNdisCommon; + PWDI_DATA_STRUCT pWdi = &(pAdapter->pPortCommonInfo->WdiData); + + // Enable for LE Hang detection and recovery function + pWdi->bWdiLEPLDR = pNdisCommon->RegHangDetection; + + RT_TRACE(COMP_INIT, DBG_LOUD, ("WDI_UpdateDefaultSetting(): bWdiLEPLDR(%d)\n", pWdi->bWdiLEPLDR)); +} + +// +// Description: +// Indicate the specific (non-common for all platform) event/status to WDI. +// Arguments: +// [in] pAdapter - +// The adapter context. +// [in] event - +// The event of the indication. +// [in] pInfoBuffer - +// The pointer to the input information. It can be NULL. +// [in] InfoBruuferLen - +// The length in byte for pInfoBuffer. +// Return: +// It may return RT_STATUS_SUCCESS if this function completes successfully, or RT_STATUS_PENDING +// for the asynchrous process. +// By Bruce, 2015-12-16. +// +RT_STATUS +WDI_IndicateGeneralEvent( + IN PADAPTER pAdapter, + IN u4Byte Event, + IN PVOID pInfoBuffer, + IN u4Byte InfoBruuferLen + ) +{ + RT_STATUS rtStatus = RT_STATUS_SUCCESS; + + switch(Event) + { + default: + { + RT_TRACE_F(COMP_INDIC, DBG_WARNING, ("Unrecognized event = 0x%08X\n", Event)); + rtStatus = RT_STATUS_NOT_RECOGNIZED; + } + break; + + + + + case RT_CUSTOM_EVENT_WDI_FT_ASSOC_NEEDED: + { + rtStatus = wdiext_IndicateFtAssocNeeded(pAdapter); + } + break; + } + return rtStatus; +} + +#endif |
