/*----------------------------------------------------------------------------*/ VOID aaaFsmRunEventStart(IN P_MSG_HDR_T prMsgHdr) { P_MSG_SAA_JOIN_REQ_T prJoinReqMsg; P_STA_RECORD_T prStaRec; P_AIS_BSS_INFO_T prAisBssInfo; ASSERT(prMsgHdr); prJoinReqMsg = (P_MSG_SAA_JOIN_REQ_T) prMsgHdr; prStaRec = prJoinReqMsg->prStaRec; ASSERT(prStaRec); DBGLOG(SAA, LOUD, ("EVENT-START: Trigger SAA FSM\n")); cnmMemFree(prMsgHdr); /* 4 <1> Validation of SAA Start Event */ if (!IS_AP_STA(prStaRec->eStaType)) { DBGLOG(SAA, ERROR, ("EVENT-START: STA Type - %d was not supported.\n", prStaRec->eStaType)); /* Ignore the return value because don't care the prSwRfb */ saaFsmSendEventJoinComplete(WLAN_STATUS_FAILURE, prStaRec, NULL); return; } /* 4 <2> The previous JOIN process is not completed ? */ if (prStaRec->eAuthAssocState != AA_STATE_IDLE) { DBGLOG(SAA, ERROR, ("EVENT-START: Reentry of SAA Module.\n")); prStaRec->eAuthAssocState = AA_STATE_IDLE; } /* 4 <3> Reset Status Code and Time */ /* Update Station Record - Status/Reason Code */ prStaRec->u2StatusCode = STATUS_CODE_SUCCESSFUL; /* Update the record join time. */ GET_CURRENT_SYSTIME(&prStaRec->rLastJoinTime); prStaRec->ucTxAuthAssocRetryCount = 0; if (prStaRec->prChallengeText) { cnmMemFree(prStaRec->prChallengeText); prStaRec->prChallengeText = (P_IE_CHALLENGE_TEXT_T) NULL; } cnmTimerStopTimer(&prStaRec->rTxReqDoneOrRxRespTimer); prStaRec->ucStaState = STA_STATE_1; /* Trigger SAA MODULE */ saaFsmSteps(prStaRec, SAA_STATE_SEND_AUTH1, (P_SW_RFB_T) NULL); return; } /* end of saaFsmRunEventStart() */
/*----------------------------------------------------------------------------*/ VOID roamingFsmScanResultsUpdate(IN P_ADAPTER_T prAdapter) { P_ROAMING_INFO_T prRoamingFsmInfo; prRoamingFsmInfo = (P_ROAMING_INFO_T) &(prAdapter->rWifiVar.rRoamingInfo); /* Check Roaming Conditions */ ROAMING_ENABLE_CHECK(prRoamingFsmInfo); DBGLOG(ROAMING, LOUD, ("->roamingFsmScanResultsUpdate(): Current Time = %u", kalGetTimeTick())); GET_CURRENT_SYSTIME(&prRoamingFsmInfo->rRoamingDiscoveryUpdateTime); return; } /* end of roamingFsmScanResultsUpdate() */
/*----------------------------------------------------------------------------*/ VOID roamingFsmSteps ( IN P_ADAPTER_T prAdapter, IN ENUM_ROAMING_STATE_T eNextState ) { P_ROAMING_INFO_T prRoamingFsmInfo; ENUM_ROAMING_STATE_T ePreviousState; BOOLEAN fgIsTransition = (BOOLEAN)FALSE; prRoamingFsmInfo = (P_ROAMING_INFO_T)&(prAdapter->rWifiVar.rRoamingInfo); do { /* Do entering Next State */ #if DBG DBGLOG(ROAMING, STATE, ("TRANSITION: [%s] -> [%s]\n", apucDebugRoamingState[prRoamingFsmInfo->eCurrentState], apucDebugRoamingState[eNextState])); #else DBGLOG(ROAMING, STATE, ("[%d] TRANSITION: [%d] -> [%d]\n", DBG_ROAMING_IDX, prRoamingFsmInfo->eCurrentState, eNextState)); #endif /* NOTE(Kevin): This is the only place to change the eCurrentState(except initial) */ ePreviousState = prRoamingFsmInfo->eCurrentState; prRoamingFsmInfo->eCurrentState = eNextState; fgIsTransition = (BOOLEAN)FALSE; /* Do tasks of the State that we just entered */ switch (prRoamingFsmInfo->eCurrentState) { /* NOTE(Kevin): we don't have to rearrange the sequence of following * switch case. Instead I would like to use a common lookup table of array * of function pointer to speed up state search. */ case ROAMING_STATE_IDLE: case ROAMING_STATE_DECISION: break; case ROAMING_STATE_DISCOVERY: { OS_SYSTIME rCurrentTime; GET_CURRENT_SYSTIME(&rCurrentTime); if (CHECK_FOR_TIMEOUT(rCurrentTime, prRoamingFsmInfo->rRoamingDiscoveryUpdateTime, SEC_TO_SYSTIME(ROAMING_DISCOVERY_TIMEOUT_SEC))) { DBGLOG(ROAMING, LOUD, ("roamingFsmSteps: DiscoveryUpdateTime Timeout")); aisFsmRunEventRoamingDiscovery(prAdapter, TRUE); } else { DBGLOG(ROAMING, LOUD, ("roamingFsmSteps: DiscoveryUpdateTime Updated")); aisFsmRunEventRoamingDiscovery(prAdapter, FALSE); } } break; case ROAMING_STATE_ROAM: break; default: ASSERT(0); /* Make sure we have handle all STATEs */ } } while (fgIsTransition); return; } /* end of roamingFsmSteps() */
/*----------------------------------------------------------------------------*/ VOID timerDoTimeOutCheck ( IN P_ADAPTER_T prAdapter ) { P_LINK_T prTimerList; P_LINK_ENTRY_T prLinkEntry; P_TIMER_T prTimer; OS_SYSTIME rCurSysTime; DEBUGFUNC("timerDoTimeOutCheck"); ASSERT(prAdapter); prTimerList= &prAdapter->rTimerList; GET_CURRENT_SYSTIME(&rCurSysTime); /* Set the permitted max timeout value for new one */ prAdapter->rNextExpiredSysTime = rCurSysTime + MGMT_MAX_TIMEOUT_INTERVAL; LINK_FOR_EACH(prLinkEntry, prTimerList) { prTimer = LINK_ENTRY(prLinkEntry, TIMER_T, rLinkEntry); /* Check if this entry is timeout. */ if (!TIME_BEFORE(rCurSysTime, prTimer->rExpiredSysTime)) { timerStopTimer(prAdapter, prTimer); #if CFG_USE_SW_ROOT_TIMER if (prTimer->fgNeedHwAccess) { ARB_ACQUIRE_POWER_CONTROL_FROM_PM(prAdapter); DBGLOG(INIT, INFO, ("Timer Handler: ->%s(): SYS_TIME = %ld\n", prTimer->aucDbgString, u4CurTime)); (prTimer->pfMgmtTimeOutFunc)(prTimer->u4Data); // It may add timer there. DBGLOG(INIT, INFO, ("Timer Handler: <-%s()\n", prTimer->aucDbgString)); ARB_RECLAIM_POWER_CONTROL_TO_PM(prAdapter); } else #endif { DBGLOG(INIT, INFO, ("(NO HW ACCESS)Timer Handler: ->%s(): SYS_TIME = %ld\n", prTimer->aucDbgString, rCurSysTime)); (prTimer->pfMgmtTimeOutFunc)(prTimer->u4Data); // It may add timer there. DBGLOG(INIT, INFO, ("(NO HW ACCESS)Timer Handler: <-%s()\n", prTimer->aucDbgString)); } /* Search entire list again because of nest del and add timers * and current MGMT_TIMER could be volatile after stopped */ prLinkEntry = (P_LINK_ENTRY_T)prTimerList; } else if (TIME_BEFORE(prTimer->rExpiredSysTime, prAdapter->rNextExpiredSysTime)) { prAdapter->rNextExpiredSysTime = prTimer->rExpiredSysTime; } } /* end of for loop */
/*----------------------------------------------------------------------------*/ WLAN_STATUS aaaFsmRunEventRxAssoc(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb) { P_BSS_INFO_T prBssInfo; P_STA_RECORD_T prStaRec = (P_STA_RECORD_T) NULL; UINT_16 u2StatusCode = STATUS_CODE_RESERVED; BOOLEAN fgReplyAssocResp = FALSE; ASSERT(prAdapter); do { /* 4 <1> Check if we have the STA_RECORD_T for incoming Assoc Req */ prStaRec = cnmGetStaRecByIndex(prAdapter, prSwRfb->ucStaRecIdx); /* We should have the corresponding Sta Record. */ if ((!prStaRec) || (!prStaRec->fgIsInUse)) { ASSERT(0); /* Only for debug phase */ break; } if (!IS_CLIENT_STA(prStaRec)) break; if (prStaRec->ucStaState == STA_STATE_3) { /* Do Reassocation */ } else if ((prStaRec->ucStaState == STA_STATE_2) && (prStaRec->eAuthAssocState == AAA_STATE_SEND_AUTH2)) { /* Normal case */ } else { DBGLOG(AAA, INFO, "Previous AuthAssocState (%d) != SEND_AUTH2, ucStaState:%d.\n", prStaRec->eAuthAssocState, prStaRec->ucStaState); /* TODO: Why assoc req event is faster than tx done of auth */ if (prStaRec->eAuthAssocState != AAA_STATE_SEND_AUTH2) break; } /* update RCPI */ prStaRec->ucRCPI = prSwRfb->prHifRxHdr->ucRcpi; /* 4 <2> Check P2P network conditions */ #if CFG_ENABLE_WIFI_DIRECT if ((prAdapter->fgIsP2PRegistered) && (IS_STA_IN_P2P(prStaRec))) { prBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_P2P_INDEX]); if (prBssInfo->fgIsNetActive) { /* 4 <2.1> Validate Assoc Req Frame and get Status Code */ /* Check if for this BSSID */ if (WLAN_STATUS_SUCCESS == assocProcessRxAssocReqFrame(prAdapter, prSwRfb, &u2StatusCode)) { if (STATUS_CODE_SUCCESSFUL == u2StatusCode) { /* 4 <2.2> Validate Assoc Req Frame for Network Specific Conditions */ fgReplyAssocResp = p2pFuncValidateAssocReq(prAdapter, prSwRfb, (PUINT_16) & u2StatusCode); } else { fgReplyAssocResp = TRUE; } break; } } } #endif /* CFG_ENABLE_WIFI_DIRECT */ /* 4 <3> Check BOW network conditions */ #if CFG_ENABLE_BT_OVER_WIFI if (IS_STA_IN_BOW(prStaRec)) { prBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_BOW_INDEX]); if ((prBssInfo->fgIsNetActive) && (OP_MODE_BOW == prBssInfo->eCurrentOPMode)) { /* 4 <3.1> Validate Auth Frame by Auth Algorithm/Transation Seq */ /* Check if for this BSSID */ if (WLAN_STATUS_SUCCESS == assocProcessRxAssocReqFrame(prAdapter, prSwRfb, &u2StatusCode)) { if (STATUS_CODE_SUCCESSFUL == u2StatusCode) { /* 4 <3.2> Validate Auth Frame for Network Specific Conditions */ fgReplyAssocResp = bowValidateAssocReq(prAdapter, prSwRfb, &u2StatusCode); } else { fgReplyAssocResp = TRUE; } /* TODO(Kevin): Allocate a STA_RECORD_T for new client */ break; } } } #endif /* CFG_ENABLE_BT_OVER_WIFI */ return WLAN_STATUS_SUCCESS; /* To release the SW_RFB_T */ } while (FALSE); /* 4 <4> Update STA_RECORD_T and reply Assoc Resp Frame */ if (fgReplyAssocResp) { UINT_16 u2IELength; PUINT_8 pucIE; if ((((P_WLAN_ASSOC_REQ_FRAME_T) (prSwRfb->pvHeader))->u2FrameCtrl & MASK_FRAME_TYPE) == MAC_FRAME_REASSOC_REQ) { u2IELength = prSwRfb->u2PacketLen - (UINT_16) OFFSET_OF(WLAN_REASSOC_REQ_FRAME_T, aucInfoElem[0]); pucIE = ((P_WLAN_REASSOC_REQ_FRAME_T) (prSwRfb->pvHeader))->aucInfoElem; } else { u2IELength = prSwRfb->u2PacketLen - (UINT_16) OFFSET_OF(WLAN_ASSOC_REQ_FRAME_T, aucInfoElem[0]); pucIE = ((P_WLAN_ASSOC_REQ_FRAME_T) (prSwRfb->pvHeader))->aucInfoElem; } rlmProcessAssocReq(prAdapter, prSwRfb, pucIE, u2IELength); /* 4 <4.1> Assign Association ID */ if (u2StatusCode == STATUS_CODE_SUCCESSFUL) { #if CFG_ENABLE_WIFI_DIRECT if ((prAdapter->fgIsP2PRegistered) && (IS_STA_IN_P2P(prStaRec))) { if (p2pRunEventAAAComplete(prAdapter, prStaRec) == WLAN_STATUS_SUCCESS) { prStaRec->u2AssocId = bssAssignAssocID(prStaRec); /* prStaRec->eAuthAssocState = AA_STATE_IDLE; */ prStaRec->eAuthAssocState = AAA_STATE_SEND_ASSOC2;/* NOTE(Kevin): for TX done */ /* NOTE(Kevin): Method A: Change to STATE_3 before handle TX Done */ /* cnmStaRecChangeState(prAdapter, prStaRec, STA_STATE_3); */ } else { /* Client List FULL. */ u2StatusCode = STATUS_CODE_REQ_DECLINED; prStaRec->u2AssocId = 0; /* Invalid Assocation ID */ /* If (Re)association fail, the peer can try Assocation w/o Auth immediately */ prStaRec->eAuthAssocState = AAA_STATE_SEND_AUTH2; /* NOTE(Kevin): Better to change state here, not at TX Done */ cnmStaRecChangeState(prAdapter, prStaRec, STA_STATE_2); } } #endif #if CFG_ENABLE_BT_OVER_WIFI if ((IS_STA_IN_BOW(prStaRec))) { /* if (bowRunEventAAAComplete(prAdapter, prStaRec) == WLAN_STATUS_SUCCESS) { */ prStaRec->u2AssocId = bssAssignAssocID(prStaRec); prStaRec->eAuthAssocState = AAA_STATE_SEND_ASSOC2; /* NOTE(Kevin): for TX done */ /* NOTE(Kevin): Method A: Change to STATE_3 before handle TX Done */ /* cnmStaRecChangeState(prAdapter, prStaRec, STA_STATE_3); */ } #if 0 else { /* Client List FULL. */ u2StatusCode = STATUS_CODE_REQ_DECLINED; prStaRec->u2AssocId = 0; /* Invalid Assocation ID */ /* If (Re)association fail, the peer can try Assocation w/o Auth immediately */ prStaRec->eAuthAssocState = AAA_STATE_SEND_AUTH2; /* NOTE(Kevin): Better to change state here, not at TX Done */ cnmStaRecChangeState(prAdapter, prStaRec, STA_STATE_2); } } #endif #endif } else { prStaRec->u2AssocId = 0; /* Invalid Assocation ID */ /* If (Re)association fail, the peer can try Assocation w/o Auth immediately */ prStaRec->eAuthAssocState = AAA_STATE_SEND_AUTH2; /* NOTE(Kevin): Better to change state here, not at TX Done */ cnmStaRecChangeState(prAdapter, prStaRec, STA_STATE_2); } /* Update the record join time. */ GET_CURRENT_SYSTIME(&prStaRec->rUpdateTime); /* Update Station Record - Status/Reason Code */ prStaRec->u2StatusCode = u2StatusCode; /* NOTE: Ignore the return status for AAA */ /* 4 <4.2> Reply Assoc Resp */ assocSendReAssocRespFrame(prAdapter, prStaRec); }
/*----------------------------------------------------------------------------*/ VOID aaaFsmRunEventRxAuth(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb) { P_BSS_INFO_T prBssInfo; P_STA_RECORD_T prStaRec = (P_STA_RECORD_T) NULL; UINT_16 u2StatusCode; BOOLEAN fgReplyAuth = FALSE; ENUM_NETWORK_TYPE_INDEX_T eNetTypeIndex; ASSERT(prAdapter); do { /* 4 <1> Check P2P network conditions */ #if CFG_ENABLE_WIFI_DIRECT if (prAdapter->fgIsP2PRegistered) { prBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_P2P_INDEX]); if (prBssInfo->fgIsNetActive) { /* 4 <1.1> Validate Auth Frame by Auth Algorithm/Transation Seq */ if (WLAN_STATUS_SUCCESS == authProcessRxAuth1Frame(prAdapter, prSwRfb, prBssInfo->aucBSSID, AUTH_ALGORITHM_NUM_OPEN_SYSTEM, AUTH_TRANSACTION_SEQ_1, &u2StatusCode)) { if (STATUS_CODE_SUCCESSFUL == u2StatusCode) { /* 4 <1.2> Validate Auth Frame for Network Specific Conditions */ fgReplyAuth = p2pFuncValidateAuth(prAdapter, prSwRfb, &prStaRec, &u2StatusCode); } else { fgReplyAuth = TRUE; } eNetTypeIndex = NETWORK_TYPE_P2P_INDEX; break; } } } #endif /* CFG_ENABLE_WIFI_DIRECT */ /* 4 <2> Check BOW network conditions */ #if CFG_ENABLE_BT_OVER_WIFI { prBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_BOW_INDEX]); if ((prBssInfo->fgIsNetActive) && (OP_MODE_BOW == prBssInfo->eCurrentOPMode)) { /* 4 <2.1> Validate Auth Frame by Auth Algorithm/Transation Seq */ /* Check if for this BSSID */ if (WLAN_STATUS_SUCCESS == authProcessRxAuth1Frame(prAdapter, prSwRfb, prBssInfo->aucBSSID, AUTH_ALGORITHM_NUM_OPEN_SYSTEM, AUTH_TRANSACTION_SEQ_1, &u2StatusCode)) { if (STATUS_CODE_SUCCESSFUL == u2StatusCode) { /* 4 <2.2> Validate Auth Frame for Network Specific Conditions */ fgReplyAuth = bowValidateAuth(prAdapter, prSwRfb, &prStaRec, &u2StatusCode); } else { fgReplyAuth = TRUE; } eNetTypeIndex = NETWORK_TYPE_BOW_INDEX; /* TODO(Kevin): Allocate a STA_RECORD_T for new client */ break; } } } #endif /* CFG_ENABLE_BT_OVER_WIFI */ return; } while (FALSE); if (prStaRec) { /* update RCPI */ prStaRec->ucRCPI = prSwRfb->prHifRxHdr->ucRcpi; } /* 4 <3> Update STA_RECORD_T and reply Auth_2(Response to Auth_1) Frame */ if (fgReplyAuth) { if (prStaRec) { if (u2StatusCode == STATUS_CODE_SUCCESSFUL) { if (prStaRec->eAuthAssocState != AA_STATE_IDLE) { DBGLOG(AAA, WARN, "Previous AuthAssocState (%d) != IDLE.\n", prStaRec->eAuthAssocState); } prStaRec->eAuthAssocState = AAA_STATE_SEND_AUTH2; } else { prStaRec->eAuthAssocState = AA_STATE_IDLE; /* NOTE(Kevin): Change to STATE_1 */ cnmStaRecChangeState(prAdapter, prStaRec, STA_STATE_1); } /* Update the record join time. */ GET_CURRENT_SYSTIME(&prStaRec->rUpdateTime); /* Update Station Record - Status/Reason Code */ prStaRec->u2StatusCode = u2StatusCode; prStaRec->ucAuthAlgNum = AUTH_ALGORITHM_NUM_OPEN_SYSTEM; } else { /* NOTE(Kevin): We should have STA_RECORD_T if the status code was successful */ ASSERT(!(u2StatusCode == STATUS_CODE_SUCCESSFUL)); } /* NOTE: Ignore the return status for AAA */ /* 4 <4> Reply Auth */ authSendAuthFrame(prAdapter, prStaRec, eNetTypeIndex, prSwRfb, AUTH_TRANSACTION_SEQ_2, u2StatusCode); } return; } /* end of aaaFsmRunEventRxAuth() */
/*----------------------------------------------------------------------------*/ VOID joinComplete(IN P_ADAPTER_T prAdapter) { P_JOIN_INFO_T prJoinInfo; P_BSS_DESC_T prBssDesc; P_PEER_BSS_INFO_T prPeerBssInfo; P_BSS_INFO_T prBssInfo; P_CONNECTION_SETTINGS_T prConnSettings; P_STA_RECORD_T prStaRec; P_TX_CTRL_T prTxCtrl; #if CFG_SUPPORT_802_11D P_IE_COUNTRY_T prIECountry; #endif DEBUGFUNC("joinComplete"); ASSERT(prAdapter); prJoinInfo = &prAdapter->rJoinInfo; prBssDesc = prJoinInfo->prBssDesc; prPeerBssInfo = &prAdapter->rPeerBssInfo; prBssInfo = &prAdapter->rBssInfo; prConnSettings = &prAdapter->rConnSettings; prTxCtrl = &prAdapter->rTxCtrl; /* 4 <1> Update Connecting & Connected Flag of BSS_DESC_T. */ /* Remove previous AP's Connection Flags if have */ scanRemoveConnectionFlagOfBssDescByBssid(prAdapter, prBssInfo->aucBSSID); prBssDesc->fgIsConnected = TRUE; /* Mask as Connected */ if (prBssDesc->fgIsHiddenSSID) { /* NOTE(Kevin): This is for the case of Passive Scan and the target BSS didn't * broadcast SSID on its Beacon Frame. */ COPY_SSID(prBssDesc->aucSSID, prBssDesc->ucSSIDLen, prAdapter->rConnSettings.aucSSID, prAdapter->rConnSettings.ucSSIDLen); if (prBssDesc->ucSSIDLen) prBssDesc->fgIsHiddenSSID = FALSE; #if DBG else ASSERT(0); #endif /* DBG */ DBGLOG(JOIN, INFO, ("Hidden SSID! - Update SSID : %s\n", prBssDesc->aucSSID)); } /* 4 <2> Update BSS_INFO_T from BSS_DESC_T */ /* 4 <2.A> PHY Type */ prBssInfo->ePhyType = prBssDesc->ePhyType; /* 4 <2.B> BSS Type */ prBssInfo->eBSSType = BSS_TYPE_INFRASTRUCTURE; /* 4 <2.C> BSSID */ COPY_MAC_ADDR(prBssInfo->aucBSSID, prBssDesc->aucBSSID); DBGLOG(JOIN, INFO, ("JOIN to BSSID: [" MACSTR "]\n", MAC2STR(prBssDesc->aucBSSID))); /* 4 <2.D> SSID */ COPY_SSID(prBssInfo->aucSSID, prBssInfo->ucSSIDLen, prBssDesc->aucSSID, prBssDesc->ucSSIDLen); /* 4 <2.E> Channel / Band information. */ prBssInfo->eBand = prBssDesc->eBand; prBssInfo->ucChnl = prBssDesc->ucChannelNum; /* 4 <2.F> RSN/WPA information. */ secFsmRunEventStart(prAdapter); prBssInfo->u4RsnSelectedPairwiseCipher = prBssDesc->u4RsnSelectedPairwiseCipher; prBssInfo->u4RsnSelectedGroupCipher = prBssDesc->u4RsnSelectedGroupCipher; prBssInfo->u4RsnSelectedAKMSuite = prBssDesc->u4RsnSelectedAKMSuite; if (secRsnKeyHandshakeEnabled()) prBssInfo->fgIsWPAorWPA2Enabled = TRUE; else prBssInfo->fgIsWPAorWPA2Enabled = FALSE; /* 4 <2.G> Beacon interval. */ prBssInfo->u2BeaconInterval = prBssDesc->u2BeaconInterval; /* 4 <2.H> DTIM period. */ prBssInfo->ucDtimPeriod = prBssDesc->ucDTIMPeriod; /* 4 <2.I> ERP Information */ if ((prBssInfo->ePhyType == PHY_TYPE_ERP_INDEX) && /* Our BSS's PHY_TYPE is ERP now. */ (prBssDesc->fgIsERPPresent)) { prBssInfo->fgIsERPPresent = TRUE; prBssInfo->ucERP = prBssDesc->ucERP; /* Save the ERP for later check */ } else { /* Some AP, may send ProbeResp without ERP IE. Thus prBssDesc->fgIsERPPresent is FALSE. */ prBssInfo->fgIsERPPresent = FALSE; prBssInfo->ucERP = 0; } #if CFG_SUPPORT_802_11D /* 4 <2.J> Country inforamtion of the associated AP */ if (prConnSettings->fgMultiDomainCapabilityEnabled) { DOMAIN_INFO_ENTRY rDomainInfo; if (domainGetDomainInfoByScanResult(prAdapter, &rDomainInfo)) { if (prBssDesc->prIECountry) { prIECountry = prBssDesc->prIECountry; domainParseCountryInfoElem(prIECountry, &prBssInfo->rDomainInfo); /* use the domain get from the BSS info */ prBssInfo->fgIsCountryInfoPresent = TRUE; nicSetupOpChnlList(prAdapter, prBssInfo->rDomainInfo.u2CountryCode, FALSE); } else { /* use the domain get from the scan result */ prBssInfo->fgIsCountryInfoPresent = TRUE; nicSetupOpChnlList(prAdapter, rDomainInfo.u2CountryCode, FALSE); } } } #endif /* 4 <2.K> Signal Power of the associated AP */ prBssInfo->rRcpi = prBssDesc->rRcpi; prBssInfo->rRssi = RCPI_TO_dBm(prBssInfo->rRcpi); GET_CURRENT_SYSTIME(&prBssInfo->rRssiLastUpdateTime); /* 4 <2.L> Capability Field of the associated AP */ prBssInfo->u2CapInfo = prBssDesc->u2CapInfo; DBGLOG(JOIN, INFO, ("prBssInfo-> fgIsERPPresent = %d, ucERP = %02x, rRcpi = %d, rRssi = %ld\n", prBssInfo->fgIsERPPresent, prBssInfo->ucERP, prBssInfo->rRcpi, prBssInfo->rRssi)); /* 4 <3> Update BSS_INFO_T from PEER_BSS_INFO_T & NIC RATE FUNC */ /* 4 <3.A> Association ID */ prBssInfo->u2AssocId = prPeerBssInfo->u2AssocId; /* 4 <3.B> WMM Infomation */ if (prAdapter->fgIsEnableWMM && (prPeerBssInfo->rWmmInfo.ucWmmFlag & WMM_FLAG_SUPPORT_WMM)) { prBssInfo->fgIsWmmAssoc = TRUE; prTxCtrl->rTxQForVoipAccess = TXQ_AC3; qosWmmInfoInit(&prBssInfo->rWmmInfo, (prBssInfo->ePhyType == PHY_TYPE_HR_DSSS_INDEX) ? TRUE : FALSE); if (prPeerBssInfo->rWmmInfo.ucWmmFlag & WMM_FLAG_AC_PARAM_PRESENT) { kalMemCopy(&prBssInfo->rWmmInfo, &prPeerBssInfo->rWmmInfo, sizeof(WMM_INFO_T)); } else { kalMemCopy(&prBssInfo->rWmmInfo, &prPeerBssInfo->rWmmInfo, sizeof(WMM_INFO_T) - sizeof(prPeerBssInfo->rWmmInfo.arWmmAcParams)); } } else { prBssInfo->fgIsWmmAssoc = FALSE; prTxCtrl->rTxQForVoipAccess = TXQ_AC1; kalMemZero(&prBssInfo->rWmmInfo, sizeof(WMM_INFO_T)); } /* 4 <3.C> Operational Rate Set & BSS Basic Rate Set */ prBssInfo->u2OperationalRateSet = prPeerBssInfo->u2OperationalRateSet; prBssInfo->u2BSSBasicRateSet = prPeerBssInfo->u2BSSBasicRateSet; /* 4 <3.D> Short Preamble */ if (prBssInfo->fgIsERPPresent) { /* NOTE(Kevin 2007/12/24): Truth Table. * Short Preamble Bit in * <AssocReq><AssocResp w/i ERP><BARKER(Long)>Final Driver Setting(Short) * TRUE FALSE FALSE FALSE(shouldn't have such case, use the AssocResp) * TRUE FALSE TRUE FALSE * FALSE FALSE FALSE FALSE(shouldn't have such case, use the AssocResp) * FALSE FALSE TRUE FALSE * TRUE TRUE FALSE TRUE(follow ERP) * TRUE TRUE TRUE FALSE(follow ERP) * FALSE TRUE FALSE FALSE(shouldn't have such case, and we should set to FALSE) * FALSE TRUE TRUE FALSE(we should set to FALSE) */ if ((prPeerBssInfo->fgIsShortPreambleAllowed) && ((prConnSettings->ePreambleType == PREAMBLE_TYPE_SHORT) || /* Short Preamble Option Enable is TRUE */ ((prConnSettings->ePreambleType == PREAMBLE_TYPE_AUTO) && (prBssDesc-> u2CapInfo & CAP_INFO_SHORT_PREAMBLE)))) { prBssInfo->fgIsShortPreambleAllowed = TRUE; if (prBssInfo->ucERP & ERP_INFO_BARKER_PREAMBLE_MODE) prBssInfo->fgUseShortPreamble = FALSE; else prBssInfo->fgUseShortPreamble = TRUE; } else { prBssInfo->fgIsShortPreambleAllowed = FALSE; prBssInfo->fgUseShortPreamble = FALSE; } } else { /* NOTE(Kevin 2007/12/24): Truth Table. * Short Preamble Bit in * <AssocReq> <AssocResp w/o ERP> Final Driver Setting(Short) * TRUE FALSE FALSE * FALSE FALSE FALSE * TRUE TRUE TRUE * FALSE TRUE(status success) TRUE * --> Honor the result of prPeerBssInfo. */ prBssInfo->fgIsShortPreambleAllowed = prBssInfo->fgUseShortPreamble = prPeerBssInfo->fgIsShortPreambleAllowed; } DBGLOG(JOIN, INFO, ("prBssInfo->fgIsShortPreambleAllowed = %d, prBssInfo->fgUseShortPreamble = %d\n", prBssInfo->fgIsShortPreambleAllowed, prBssInfo->fgUseShortPreamble)); /* 4 <3.E> Short Slot Time */ prBssInfo->fgUseShortSlotTime = prPeerBssInfo->fgUseShortSlotTime; /* AP support Short Slot Time */ DBGLOG(JOIN, INFO, ("prBssInfo->fgUseShortSlotTime = %d\n", prBssInfo->fgUseShortSlotTime)); nicSetSlotTime(prAdapter, prBssInfo->ePhyType, ((prConnSettings->fgIsShortSlotTimeOptionEnable && prBssInfo->fgUseShortSlotTime) ? TRUE : FALSE)); /* 4 <3.F> Update Tx Rate for Control Frame */ bssUpdateTxRateForControlFrame(prAdapter); /* 4 <3.G> Save the available Auth Types during Roaming (Design for Fast BSS Transition). */ /* if (prAdapter->fgIsEnableRoaming) */ /* NOTE(Kevin): Always prepare info for roaming */ { if (prJoinInfo->ucCurrAuthAlgNum == AUTH_ALGORITHM_NUM_OPEN_SYSTEM) prJoinInfo->ucRoamingAuthTypes |= AUTH_TYPE_OPEN_SYSTEM; else if (prJoinInfo->ucCurrAuthAlgNum == AUTH_ALGORITHM_NUM_SHARED_KEY) prJoinInfo->ucRoamingAuthTypes |= AUTH_TYPE_SHARED_KEY; prBssInfo->ucRoamingAuthTypes = prJoinInfo->ucRoamingAuthTypes; /* Set the stable time of the associated BSS. We won't do roaming decision * during the stable time. */ SET_EXPIRATION_TIME(prBssInfo->rRoamingStableExpirationTime, SEC_TO_SYSTIME(ROAMING_STABLE_TIMEOUT_SEC)); } /* 4 <3.H> Update Parameter for TX Fragmentation Threshold */ #if CFG_TX_FRAGMENT txFragInfoUpdate(prAdapter); #endif /* CFG_TX_FRAGMENT */ /* 4 <4> Update STA_RECORD_T */ /* Get a Station Record if possible */ prStaRec = staRecGetStaRecordByAddr(prAdapter, prBssDesc->aucBSSID); if (prStaRec) { UINT_16 u2OperationalRateSet, u2DesiredRateSet; /* 4 <4.A> Desired Rate Set */ u2OperationalRateSet = (rPhyAttributes[prBssInfo->ePhyType].u2SupportedRateSet & prBssInfo->u2OperationalRateSet); u2DesiredRateSet = (u2OperationalRateSet & prConnSettings->u2DesiredRateSet); if (u2DesiredRateSet) { prStaRec->u2DesiredRateSet = u2DesiredRateSet; } else { /* For Error Handling - The Desired Rate Set is not covered in Operational Rate Set. */ prStaRec->u2DesiredRateSet = u2OperationalRateSet; } /* Try to set the best initial rate for this entry */ if (!rateGetBestInitialRateIndex(prStaRec->u2DesiredRateSet, prStaRec->rRcpi, &prStaRec->ucCurrRate1Index)) { if (!rateGetLowestRateIndexFromRateSet(prStaRec->u2DesiredRateSet, &prStaRec->ucCurrRate1Index)) { ASSERT(0); } } DBGLOG(JOIN, INFO, ("prStaRec->ucCurrRate1Index = %d\n", prStaRec->ucCurrRate1Index)); /* 4 <4.B> Preamble Mode */ prStaRec->fgIsShortPreambleOptionEnable = prBssInfo->fgUseShortPreamble; /* 4 <4.C> QoS Flag */ prStaRec->fgIsQoS = prBssInfo->fgIsWmmAssoc; } #if DBG else ASSERT(0); #endif /* DBG */ /* 4 <5> Update NIC */ /* 4 <5.A> Update BSSID & Operation Mode */ nicSetupBSS(prAdapter, prBssInfo); /* 4 <5.B> Update WLAN Table. */ if (nicSetHwBySta(prAdapter, prStaRec) == FALSE) ASSERT(FALSE); /* 4 <5.C> Update Desired Rate Set for BT. */ #if CFG_TX_FRAGMENT if (prConnSettings->fgIsEnableTxAutoFragmentForBT) txRateSetInitForBT(prAdapter, prStaRec); #endif /* CFG_TX_FRAGMENT */ /* 4 <5.D> TX AC Parameter and TX/RX Queue Control */ if (prBssInfo->fgIsWmmAssoc) { #if CFG_TX_AGGREGATE_HW_FIFO nicTxAggregateTXQ(prAdapter, FALSE); #endif /* CFG_TX_AGGREGATE_HW_FIFO */ qosUpdateWMMParametersAndAssignAllowedACI(prAdapter, &prBssInfo->rWmmInfo); } else { #if CFG_TX_AGGREGATE_HW_FIFO nicTxAggregateTXQ(prAdapter, TRUE); #endif /* CFG_TX_AGGREGATE_HW_FIFO */ nicTxNonQoSAssignDefaultAdmittedTXQ(prAdapter); nicTxNonQoSUpdateTXQParameters(prAdapter, prBssInfo->ePhyType); } #if CFG_TX_STOP_WRITE_TX_FIFO_UNTIL_JOIN { prTxCtrl->fgBlockTxDuringJoin = FALSE; #if !CFG_TX_AGGREGATE_HW_FIFO /* TX FIFO AGGREGATE already do flush once */ nicTxFlushStopQueues(prAdapter, (UINT_8) TXQ_DATA_MASK, (UINT_8) NULL); #endif /* CFG_TX_AGGREGATE_HW_FIFO */ nicTxRetransmitOfSendWaitQue(prAdapter); if (prTxCtrl->fgIsPacketInOsSendQueue) nicTxRetransmitOfOsSendQue(prAdapter); #if CFG_SDIO_TX_ENHANCE halTxLeftClusteredMpdu(prAdapter); #endif /* CFG_SDIO_TX_ENHANCE */ } #endif /* CFG_TX_STOP_WRITE_TX_FIFO_UNTIL_JOIN */ /* 4 <6> Setup CONNECTION flag. */ prAdapter->eConnectionState = MEDIA_STATE_CONNECTED; prAdapter->eConnectionStateIndicated = MEDIA_STATE_CONNECTED; if (prJoinInfo->fgIsReAssoc) prAdapter->fgBypassPortCtrlForRoaming = TRUE; else prAdapter->fgBypassPortCtrlForRoaming = FALSE; kalIndicateStatusAndComplete(prAdapter->prGlueInfo, WLAN_STATUS_MEDIA_CONNECT, (PVOID) NULL, 0); return; } /* end of joinComplete() */
/*----------------------------------------------------------------------------*/ BOOLEAN nicpmSetDriverOwn(IN P_ADAPTER_T prAdapter) { #define LP_OWN_BACK_TOTAL_DELAY_MS 2048 /* exponential of 2 */ #define LP_OWN_BACK_LOOP_DELAY_MS 1 /* exponential of 2 */ #define LP_OWN_BACK_CLR_OWN_ITERATION 256 /* exponential of 2 */ #define LP_OWN_BACK_FAILED_RETRY_CNT 5 #define LP_OWN_BACK_FAILED_LOG_SKIP_MS 2000 #define LP_OWN_BACK_FAILED_RESET_CNT 5 BOOLEAN fgStatus = TRUE; UINT_32 i, u4CurrTick, u4RegValue = 0; BOOLEAN fgTimeout; ASSERT(prAdapter); if (prAdapter->fgIsFwOwn == FALSE) return fgStatus; DBGLOG(INIT, INFO, ("DRIVER OWN\n")); u4CurrTick = kalGetTimeTick(); i = 0; while (1) { HAL_MCR_RD(prAdapter, MCR_WHLPCR, &u4RegValue); fgTimeout = ((kalGetTimeTick() - u4CurrTick) > LP_OWN_BACK_TOTAL_DELAY_MS) ? TRUE : FALSE; if (u4RegValue & WHLPCR_FW_OWN_REQ_SET) { prAdapter->fgIsFwOwn = FALSE; prAdapter->u4OwnFailedCount = 0; prAdapter->u4OwnFailedLogCount = 0; break; } else if((i > LP_OWN_BACK_FAILED_RETRY_CNT) && (kalIsCardRemoved(prAdapter->prGlueInfo) || fgIsBusAccessFailed || fgTimeout || wlanIsChipNoAck(prAdapter))) { if ((prAdapter->u4OwnFailedCount == 0) || CHECK_FOR_TIMEOUT(u4CurrTick, prAdapter->rLastOwnFailedLogTime, MSEC_TO_SYSTIME(LP_OWN_BACK_FAILED_LOG_SKIP_MS))) { DBGLOG(INIT, ERROR, ("LP cannot be own back, Timeout[%u](%ums), BusAccessError[%u], Reseting[%u], CardRemoved[%u] NoAck[%u] Cnt[%u]\n", fgTimeout, kalGetTimeTick() - u4CurrTick, fgIsBusAccessFailed, kalIsResetting(), kalIsCardRemoved(prAdapter->prGlueInfo), wlanIsChipNoAck(prAdapter), prAdapter->u4OwnFailedCount)); DBGLOG(INIT, INFO, ("Skip LP own back failed log for next %ums\n", LP_OWN_BACK_FAILED_LOG_SKIP_MS)); prAdapter->u4OwnFailedLogCount++; if(prAdapter->u4OwnFailedLogCount > LP_OWN_BACK_FAILED_RESET_CNT) { /* Trigger RESET */ #if CFG_CHIP_RESET_SUPPORT glResetTrigger(prAdapter); #endif } GET_CURRENT_SYSTIME(&prAdapter->rLastOwnFailedLogTime); } prAdapter->u4OwnFailedCount++; fgStatus = FALSE; break; } else { if ((i & (LP_OWN_BACK_CLR_OWN_ITERATION - 1)) == 0) { /* Software get LP ownership - per 256 iterations */ HAL_MCR_WR(prAdapter, MCR_WHLPCR, WHLPCR_FW_OWN_REQ_CLR); } /* Delay for LP engine to complete its operation. */ kalMsleep(LP_OWN_BACK_LOOP_DELAY_MS); i++; } } return fgStatus; }