/* ======================================================================== Routine Description: MLME kernel thread. Arguments: *Context the pAd, driver control block pointer Return Value: 0 close the thread Note: ======================================================================== */ INT MlmeThread( IN ULONG Context) { RTMP_ADAPTER *pAd; RTMP_OS_TASK *pTask; int status; status = 0; pTask = (RTMP_OS_TASK *)Context; pAd = (PRTMP_ADAPTER)pTask->priv; RtmpOSTaskCustomize(pTask); while(!pTask->task_killed) { #ifdef KTHREAD_SUPPORT RTMP_WAIT_EVENT_INTERRUPTIBLE(pAd, pTask); #else RTMP_SEM_EVENT_WAIT(&(pTask->taskSema), status); /* unlock the device pointers */ if (status != 0) { RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS); break; } #endif /* lock the device pointers , need to check if required*/ //down(&(pAd->usbdev_semaphore)); if (!pAd->PM_FlgSuspend) MlmeHandler(pAd); } /* notify the exit routine that we're actually exiting now * * complete()/wait_for_completion() is similar to up()/down(), * except that complete() is safe in the case where the structure * is getting deleted in a parallel mode of execution (i.e. just * after the down() -- that's necessary for the thread-shutdown * case. * * complete_and_exit() goes even further than this -- it is safe in * the case that the thread of the caller is going away (not just * the structure) -- this is necessary for the module-remove case. * This is important in preemption kernels, which transfer the flow * of execution immediately upon a complete(). */ DBGPRINT(RT_DEBUG_TRACE,( "<---%s\n",__FUNCTION__)); #ifndef KTHREAD_SUPPORT pTask->taskPID = THREAD_PID_INIT_VALUE; complete_and_exit (&pTask->taskComplete, 0); #endif return 0; }
/* ======================================================================== Routine Description: MLME kernel thread. Arguments: *Context the pAd, driver control block pointer Return Value: 0 close the thread Note: ======================================================================== */ INT MlmeThread( IN ULONG Context) { RTMP_ADAPTER *pAd; RTMP_OS_TASK *pTask; int status; status = 0; pTask = (RTMP_OS_TASK *)Context; pAd = (PRTMP_ADAPTER)RTMP_OS_TASK_DATA_GET(pTask); if (pAd == NULL) goto LabelExit; /* avoid compile warning */ RtmpOSTaskCustomize(pTask); while(!RTMP_OS_TASK_IS_KILLED(pTask)) { if (RtmpOSTaskWait(pAd, pTask, &status) == FALSE) { DBGPRINT_ERR(("RtmpOSTaskWait returned false in MlmeThread, setting halt in progress flag!\n")); RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS); break; } /* lock the device pointers , need to check if required*/ /*down(&(pAd->usbdev_semaphore)); */ if (!pAd->PM_FlgSuspend) MlmeHandler(pAd); } /* notify the exit routine that we're actually exiting now * * complete()/wait_for_completion() is similar to up()/down(), * except that complete() is safe in the case where the structure * is getting deleted in a parallel mode of execution (i.e. just * after the down() -- that's necessary for the thread-shutdown * case. * * complete_and_exit() goes even further than this -- it is safe in * the case that the thread of the caller is going away (not just * the structure) -- this is necessary for the module-remove case. * This is important in preemption kernels, which transfer the flow * of execution immediately upon a complete(). */ LabelExit: DBGPRINT(RT_DEBUG_TRACE,( "<---%s\n",__FUNCTION__)); RtmpOSTaskNotifyToExit(pTask); return 0; }
INT MlmeThread( IN void * Context) { PRTMP_ADAPTER pAd = (PRTMP_ADAPTER)Context; //2007/12/11:KH modified to fix compiled failed #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) daemonize(); #else daemonize("rt73"); #endif #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) allow_signal(SIGTERM); #endif current->flags |= PF_NOFREEZE; /* signal that we've started the thread */ complete(&(pAd->MlmeThreadNotify)); while (1) { int status; status = down_interruptible(&pAd->mlme_semaphore); if (status != 0) continue; if (mlme_kill) break; MlmeHandler(pAd); } /* notify the exit routine that we're actually exiting now * * complete()/wait_for_completion() is similar to up()/down(), * except that complete() is safe in the case where the structure * is getting deleted in a parallel mode of execution (i.e. just * after the down() -- that's necessary for the thread-shutdown * case. * * complete_and_exit() goes even further than this -- it is safe in * the case that the thread of the caller is going away (not just * the structure) -- this is necessary for the module-remove case. * This is important in preemption kernels, which transfer the flow * of execution immediately upon a complete(). */ complete_and_exit (&pAd->MlmeThreadNotify, 0); DBGPRINT(RT_DEBUG_TRACE, "<---MlmeThread\n"); }
VOID PeerP2pPresReqAction( IN PRTMP_ADAPTER pAd, IN MLME_QUEUE_ELEM *Elem) { MLME_P2P_ACTION_STRUCT P2PActReq; MAC_TABLE_ENTRY *pEntry; PFRAME_P2P_ACTION pFrame; PP2P_NOA_DESC pNoADesc; pFrame = (PFRAME_P2P_ACTION)Elem->Msg; if (Elem->Wcid >= MAX_LEN_OF_MAC_TABLE) { DBGPRINT(RT_DEBUG_ERROR, ("PeerP2pPresReqAction. unknown Elem->Wcid = %d \n", Elem->Wcid )); } DBGPRINT(RT_DEBUG_ERROR, ("PeerP2pPresReqAction. Send back to Elem->Wcid = %d \n", Elem->Wcid )); pEntry = &pAd->MacTab.Content[Elem->Wcid]; pNoADesc = (PP2P_NOA_DESC)(&Elem->Msg[11 + sizeof(FRAME_P2P_ACTION)]); pEntry->P2pInfo.NoADesc[0].Count = pNoADesc->Count; pEntry->P2pInfo.NoADesc[0].Duration = *(PULONG)&pNoADesc->Duration[0]; pEntry->P2pInfo.NoADesc[0].Interval = *(PULONG)&pNoADesc->Interval[0]; pEntry->P2pInfo.NoADesc[0].StartTime = *(PULONG)&pNoADesc->StartTime[0]; DBGPRINT(RT_DEBUG_ERROR,(" pP2pEntry->NoADesc[0].Count = %d, \n", pEntry->P2pInfo.NoADesc[0].Count)); DBGPRINT(RT_DEBUG_ERROR,(" pP2pEntry->NoADesc[0].Duration = %d, \n", pEntry->P2pInfo.NoADesc[0].Duration)); DBGPRINT(RT_DEBUG_ERROR,(" pP2pEntry->NoADesc[0].Interval = %d, \n", pEntry->P2pInfo.NoADesc[0].Interval)); DBGPRINT(RT_DEBUG_ERROR,(" pP2pEntry->NoADesc[0].StartTime = %d, \n", pEntry->P2pInfo.NoADesc[0].StartTime)); DBGPRINT(RT_DEBUG_ERROR,("pFrame->Token = %d \n", pFrame->Token)); pEntry->P2pInfo.NoAToken = pFrame->Token; /* pP2pEntry->NoADesc[0].Duration = Elem->Msg; */ NdisZeroMemory(&P2PActReq, sizeof(P2PActReq)); COPY_MAC_ADDR(P2PActReq.Addr, pEntry->Addr); P2PActReq.TabIndex = Elem->Wcid; MlmeEnqueue(pAd, P2P_ACTION_STATE_MACHINE, MT2_MLME_P2P_PRESENCE_RSP, sizeof(MLME_P2P_ACTION_STRUCT), (PVOID)&P2PActReq, 0); MlmeHandler(pAd); }
/* ========================================================================== Description: When waiting joining the (I)BSS, beacon received from external ========================================================================== */ static VOID ApCliPeerProbeRspAtJoinAction( IN PRTMP_ADAPTER pAd, IN MLME_QUEUE_ELEM *Elem) { USHORT LenVIE; UCHAR *VarIE = NULL; NDIS_802_11_VARIABLE_IEs *pVIE = NULL; APCLI_CTRL_MSG_STRUCT ApCliCtrlMsg; PAPCLI_STRUCT pApCliEntry = NULL; #ifdef DOT11_N_SUPPORT UCHAR CentralChannel; #endif /* DOT11_N_SUPPORT */ USHORT ifIndex = (USHORT)(Elem->Priv); PULONG pCurrState = NULL; BCN_IE_LIST *ie_list = NULL; if (ifIndex >= MAX_APCLI_NUM) return; pCurrState = &pAd->ApCfg.ApCliTab[ifIndex].SyncCurrState; /* Init Variable IE structure */ os_alloc_mem(NULL, (UCHAR **)&VarIE, MAX_VIE_LEN); if (VarIE == NULL) { DBGPRINT(RT_DEBUG_ERROR, ("%s: Allocate memory fail!!!\n", __FUNCTION__)); goto LabelErr; } pVIE = (PNDIS_802_11_VARIABLE_IEs) VarIE; pVIE->Length = 0; os_alloc_mem(NULL, (UCHAR **)&ie_list, sizeof(BCN_IE_LIST)); if (ie_list == NULL) { DBGPRINT(RT_DEBUG_ERROR, ("%s: Allocate ie_list fail!!!\n", __FUNCTION__)); goto LabelErr; } NdisZeroMemory(ie_list, sizeof(BCN_IE_LIST)); if (PeerBeaconAndProbeRspSanity(pAd, Elem->Msg, Elem->MsgLen, Elem->Channel, ie_list, &LenVIE, pVIE)) { /* BEACON from desired BSS/IBSS found. We should be able to decide most BSS parameters here. Q. But what happen if this JOIN doesn't conclude a successful ASSOCIATEION? Do we need to receover back all parameters belonging to previous BSS? A. Should be not. There's no back-door recover to previous AP. It still need a new JOIN-AUTH-ASSOC sequence. */ INT ssidEqualFlag = FALSE; INT ssidEmptyFlag = FALSE; INT bssidEqualFlag = FALSE; INT bssidEmptyFlag = FALSE; INT matchFlag = FALSE; pApCliEntry = &pAd->ApCfg.ApCliTab[ifIndex]; /* Check the Probe-Rsp's Bssid. */ if(!MAC_ADDR_EQUAL(pApCliEntry->CfgApCliBssid, ZERO_MAC_ADDR)) bssidEqualFlag = MAC_ADDR_EQUAL(pApCliEntry->CfgApCliBssid, ie_list->Bssid); else bssidEmptyFlag = TRUE; /* Check the Probe-Rsp's Ssid. */ if(pApCliEntry->CfgSsidLen != 0) ssidEqualFlag = SSID_EQUAL(pApCliEntry->CfgSsid, pApCliEntry->CfgSsidLen, ie_list->Ssid, ie_list->SsidLen); else ssidEmptyFlag = TRUE; /* bssid and ssid, Both match. */ if (bssidEqualFlag && ssidEqualFlag) matchFlag = TRUE; /* ssid match but bssid doesn't be indicate. */ else if(ssidEqualFlag && bssidEmptyFlag) matchFlag = TRUE; /* user doesn't indicate any bssid or ssid. AP-Clinet will auto pick a AP to join by most strong siganl strength. */ else if (bssidEmptyFlag && ssidEmptyFlag) matchFlag = TRUE; DBGPRINT(RT_DEBUG_TRACE, ("SYNC - bssidEqualFlag=%d, ssidEqualFlag=%d, matchFlag=%d\n", bssidEqualFlag, ssidEqualFlag, matchFlag)); if (matchFlag) { /* Validate RSN IE if necessary, then copy store this information */ if ((LenVIE > 0) #ifdef WSC_AP_SUPPORT && ((pAd->ApCfg.ApCliTab[ifIndex].WscControl.WscConfMode == WSC_DISABLE) || (pAd->ApCfg.ApCliTab[ifIndex].WscControl.bWscTrigger == FALSE)) #endif /* WSC_AP_SUPPORT */ ) { if (ApCliValidateRSNIE(pAd, (PEID_STRUCT)pVIE, LenVIE, ifIndex)) { pApCliEntry->ApCliMlmeAux.VarIELen = LenVIE; NdisMoveMemory(pApCliEntry->ApCliMlmeAux.VarIEs, pVIE, pApCliEntry->ApCliMlmeAux.VarIELen); } else { /* ignore this response */ pApCliEntry->ApCliMlmeAux.VarIELen = 0; DBGPRINT(RT_DEBUG_ERROR, ("ERROR: The RSN IE of this received Probe-resp is dis-match !!!!!!!!!! \n")); goto LabelErr; } } else { if (pApCliEntry->AuthMode >= Ndis802_11AuthModeWPA #ifdef WSC_AP_SUPPORT && ((pAd->ApCfg.ApCliTab[ifIndex].WscControl.WscConfMode == WSC_DISABLE) || (pAd->ApCfg.ApCliTab[ifIndex].WscControl.bWscTrigger == FALSE)) #endif /* WSC_AP_SUPPORT */ ) { /* ignore this response */ DBGPRINT(RT_DEBUG_ERROR, ("ERROR: The received Probe-resp has empty RSN IE !!!!!!!!!! \n")); goto LabelErr; } pApCliEntry->ApCliMlmeAux.VarIELen = 0; } DBGPRINT(RT_DEBUG_TRACE, ("SYNC - receive desired PROBE_RSP at JoinWaitProbeRsp... Channel = %d\n", ie_list->Channel)); /* if the Bssid doesn't be indicated then you need to decide which AP to connect by most strong Rssi signal strength. */ if (bssidEqualFlag == FALSE) { /* caculate real rssi value. */ CHAR Rssi0 = ConvertToRssi(pAd, Elem->Rssi0, RSSI_0); CHAR Rssi1 = ConvertToRssi(pAd, Elem->Rssi1, RSSI_1); CHAR Rssi2 = ConvertToRssi(pAd, Elem->Rssi2, RSSI_2); LONG RealRssi = (LONG)(RTMPMaxRssi(pAd, Rssi0, Rssi1, Rssi2)); DBGPRINT(RT_DEBUG_TRACE, ("SYNC - previous Rssi = %ld current Rssi=%ld\n", pApCliEntry->ApCliMlmeAux.Rssi, (LONG)RealRssi)); if (pApCliEntry->ApCliMlmeAux.Rssi > (LONG)RealRssi) goto LabelErr; else pApCliEntry->ApCliMlmeAux.Rssi = RealRssi; } else { BOOLEAN Cancelled; RTMPCancelTimer(&pApCliEntry->ApCliMlmeAux.ProbeTimer, &Cancelled); } NdisMoveMemory(pApCliEntry->ApCliMlmeAux.Ssid, ie_list->Ssid, ie_list->SsidLen); pApCliEntry->ApCliMlmeAux.SsidLen = ie_list->SsidLen; NdisMoveMemory(pApCliEntry->ApCliMlmeAux.Bssid, ie_list->Bssid, MAC_ADDR_LEN); pApCliEntry->ApCliMlmeAux.CapabilityInfo = ie_list->CapabilityInfo & SUPPORTED_CAPABILITY_INFO; pApCliEntry->ApCliMlmeAux.BssType = ie_list->BssType; pApCliEntry->ApCliMlmeAux.BeaconPeriod = ie_list->BeaconPeriod; pApCliEntry->ApCliMlmeAux.Channel = ie_list->Channel; pApCliEntry->ApCliMlmeAux.AtimWin = ie_list->AtimWin; pApCliEntry->ApCliMlmeAux.CfpPeriod = ie_list->CfParm.CfpPeriod; pApCliEntry->ApCliMlmeAux.CfpMaxDuration = ie_list->CfParm.CfpMaxDuration; pApCliEntry->ApCliMlmeAux.APRalinkIe = ie_list->RalinkIe; /* Copy AP's supported rate to ApCliMlmeAux for creating assoication request */ /* Also filter out not supported rate */ pApCliEntry->ApCliMlmeAux.SupRateLen = ie_list->SupRateLen; NdisMoveMemory(pApCliEntry->ApCliMlmeAux.SupRate, ie_list->SupRate, ie_list->SupRateLen); RTMPCheckRates(pAd, pApCliEntry->ApCliMlmeAux.SupRate, &pApCliEntry->ApCliMlmeAux.SupRateLen); pApCliEntry->ApCliMlmeAux.ExtRateLen = ie_list->ExtRateLen; NdisMoveMemory(pApCliEntry->ApCliMlmeAux.ExtRate, ie_list->ExtRate, ie_list->ExtRateLen); RTMPCheckRates(pAd, pApCliEntry->ApCliMlmeAux.ExtRate, &pApCliEntry->ApCliMlmeAux.ExtRateLen); #ifdef DOT11_N_SUPPORT NdisZeroMemory(pApCliEntry->RxMcsSet,sizeof(pApCliEntry->RxMcsSet)); /* filter out un-supported ht rates */ if ((ie_list->HtCapabilityLen > 0) && (pApCliEntry->DesiredHtPhyInfo.bHtEnable) && WMODE_CAP_N(pAd->CommonCfg.PhyMode)) { RTMPZeroMemory(&pApCliEntry->ApCliMlmeAux.HtCapability, SIZE_HT_CAP_IE); pApCliEntry->ApCliMlmeAux.NewExtChannelOffset = ie_list->NewExtChannelOffset; pApCliEntry->ApCliMlmeAux.HtCapabilityLen = ie_list->HtCapabilityLen; ApCliCheckHt(pAd, ifIndex, &ie_list->HtCapability, &ie_list->AddHtInfo); if (ie_list->AddHtInfoLen > 0) { CentralChannel = ie_list->AddHtInfo.ControlChan; /* Check again the Bandwidth capability of this AP. */ CentralChannel = get_cent_ch_by_htinfo(pAd, &ie_list->AddHtInfo, &ie_list->HtCapability); DBGPRINT(RT_DEBUG_TRACE, ("PeerBeaconAtJoinAction HT===>Central Channel = %d, Control Channel = %d, .\n", CentralChannel, ie_list->AddHtInfo.ControlChan)); } } else #endif /* DOT11_N_SUPPORT */ { RTMPZeroMemory(&pApCliEntry->ApCliMlmeAux.HtCapability, SIZE_HT_CAP_IE); RTMPZeroMemory(&pApCliEntry->ApCliMlmeAux.AddHtInfo, SIZE_ADD_HT_INFO_IE); pApCliEntry->ApCliMlmeAux.HtCapabilityLen = 0; } ApCliUpdateMlmeRate(pAd, ifIndex); #ifdef DOT11_N_SUPPORT /* copy QOS related information */ if (WMODE_CAP_N(pAd->CommonCfg.PhyMode)) { NdisMoveMemory(&pApCliEntry->ApCliMlmeAux.APEdcaParm, &ie_list->EdcaParm, sizeof(EDCA_PARM)); NdisMoveMemory(&pApCliEntry->ApCliMlmeAux.APQbssLoad, &ie_list->QbssLoad, sizeof(QBSS_LOAD_PARM)); NdisMoveMemory(&pApCliEntry->ApCliMlmeAux.APQosCapability, &ie_list->QosCapability, sizeof(QOS_CAPABILITY_PARM)); } else #endif /* DOT11_N_SUPPORT */ { NdisZeroMemory(&pApCliEntry->ApCliMlmeAux.APEdcaParm, sizeof(EDCA_PARM)); NdisZeroMemory(&pApCliEntry->ApCliMlmeAux.APQbssLoad, sizeof(QBSS_LOAD_PARM)); NdisZeroMemory(&pApCliEntry->ApCliMlmeAux.APQosCapability, sizeof(QOS_CAPABILITY_PARM)); } DBGPRINT(RT_DEBUG_TRACE, ("APCLI SYNC - after JOIN, SupRateLen=%d, ExtRateLen=%d\n", pApCliEntry->ApCliMlmeAux.SupRateLen, pApCliEntry->ApCliMlmeAux.ExtRateLen)); if (ie_list->AironetCellPowerLimit != 0xFF) { /*We need to change our TxPower for CCX 2.0 AP Control of Client Transmit Power */ ChangeToCellPowerLimit(pAd, ie_list->AironetCellPowerLimit); } else /*Used the default TX Power Percentage. */ pAd->CommonCfg.TxPowerPercentage = pAd->CommonCfg.TxPowerDefault; #ifdef WSC_AP_SUPPORT #ifdef DOT11_N_SUPPORT if ((pAd->ApCfg.ApCliTab[ifIndex].WscControl.WscConfMode != WSC_DISABLE) && (pAd->ApCfg.ApCliTab[ifIndex].WscControl.bWscTrigger == TRUE)) { ADD_HTINFO RootApHtInfo, ApHtInfo; ApHtInfo = pAd->CommonCfg.AddHTInfo.AddHtInfo; RootApHtInfo = ie_list->AddHtInfo.AddHtInfo; if ((pAd->CommonCfg.HtCapability.HtCapInfo.ChannelWidth == BW_40) && (RootApHtInfo.RecomWidth) && (RootApHtInfo.ExtChanOffset != ApHtInfo.ExtChanOffset)) { /*STRING ChStr[5] = {0}; */ if (RootApHtInfo.ExtChanOffset == EXTCHA_ABOVE) Set_HtExtcha_Proc(pAd, "1"); else Set_HtExtcha_Proc(pAd, "0"); goto LabelErr; } } #endif /* DOT11_N_SUPPORT */ #endif /* WSC_AP_SUPPORT */ if(bssidEqualFlag == TRUE) { *pCurrState = APCLI_SYNC_IDLE; ApCliCtrlMsg.Status = MLME_SUCCESS; #ifdef MAC_REPEATER_SUPPORT ApCliCtrlMsg.BssIdx = ifIndex; ApCliCtrlMsg.CliIdx = 0xFF; #endif /* MAC_REPEATER_SUPPORT */ MlmeEnqueue(pAd, APCLI_CTRL_STATE_MACHINE, APCLI_CTRL_PROBE_RSP, sizeof(APCLI_CTRL_MSG_STRUCT), &ApCliCtrlMsg, ifIndex); MlmeHandler(pAd); } } /* not to me BEACON, ignored */ } /* sanity check fail, ignore this frame */ LabelErr: if (VarIE != NULL) os_free_mem(NULL, VarIE); if (ie_list != NULL) os_free_mem(NULL, ie_list); return; }