Esempio n. 1
0
/*----------------------------------------------------------------------------*/
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() */
Esempio n. 2
0
/*----------------------------------------------------------------------------*/
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() */
Esempio n. 3
0
/*----------------------------------------------------------------------------*/
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() */
Esempio n. 4
0
/*----------------------------------------------------------------------------*/
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 */
Esempio n. 5
0
/*----------------------------------------------------------------------------*/
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);

}
Esempio n. 6
0
/*----------------------------------------------------------------------------*/
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() */
Esempio n. 7
0
/*----------------------------------------------------------------------------*/
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;
}