📄 spectrum.c
字号:
MsgLen -= sizeof(HEADER_802_11); // skip category and action code. pFramePtr += 2; MsgLen -= 2; if (pDialogToken == NULL) return result; NdisMoveMemory(pDialogToken, pFramePtr, 1); pFramePtr += 1; MsgLen -= 1; eid_ptr = (PEID_STRUCT)pFramePtr; while (((UCHAR*)eid_ptr + eid_ptr->Len + 1) < ((PUCHAR)pFramePtr + MsgLen)) { switch(eid_ptr->Eid) { case IE_TPC_REQUEST: result = TRUE; break; default: break; } eid_ptr = (PEID_STRUCT)((UCHAR*)eid_ptr + 2 + eid_ptr->Len); } return result; }/* ========================================================================== Description: TPC Report action frame sanity check. Parametrs: 1. MLME message containing the received frame 2. message length. 3. Dialog Token. 4. TPC Report IE. Return : None. ========================================================================== */static BOOLEAN PeerTpcRepSanity( IN PRTMP_ADAPTER pAd, IN VOID *pMsg, IN ULONG MsgLen, OUT PUINT8 pDialogToken, OUT PTPC_REPORT_INFO pTpcRepInfo){ PFRAME_802_11 Fr = (PFRAME_802_11)pMsg; PUCHAR pFramePtr = Fr->Octet; BOOLEAN result = FALSE; PEID_STRUCT eid_ptr; MsgLen -= sizeof(HEADER_802_11); // skip category and action code. pFramePtr += 2; MsgLen -= 2; if (pDialogToken == NULL) return result; NdisMoveMemory(pDialogToken, pFramePtr, 1); pFramePtr += 1; MsgLen -= 1; eid_ptr = (PEID_STRUCT)pFramePtr; while (((UCHAR*)eid_ptr + eid_ptr->Len + 1) < ((PUCHAR)pFramePtr + MsgLen)) { switch(eid_ptr->Eid) { case IE_TPC_REPORT: NdisMoveMemory(&pTpcRepInfo->TxPwr, eid_ptr->Octet, 1); NdisMoveMemory(&pTpcRepInfo->LinkMargin, eid_ptr->Octet + 1, 1); result = TRUE; break; default: break; } eid_ptr = (PEID_STRUCT)((UCHAR*)eid_ptr + 2 + eid_ptr->Len); } return result; }/* ========================================================================== Description: Channel Switch Announcement action frame handler. Parametrs: Elme - MLME message containing the received frame Return : None. ========================================================================== */static VOID PeerChSwAnnAction( IN PRTMP_ADAPTER pAd, IN MLME_QUEUE_ELEM *Elem) { CH_SW_ANN_INFO ChSwAnnInfo; PFRAME_802_11 pFr = (PFRAME_802_11)Elem->Msg;#ifdef CONFIG_STA_SUPPORT UCHAR index = 0, Channel = 0, NewChannel = 0; ULONG Bssidx = 0;#endif // CONFIG_STA_SUPPORT // NdisZeroMemory(&ChSwAnnInfo, sizeof(CH_SW_ANN_INFO)); if (! PeerChSwAnnSanity(pAd, Elem->Msg, Elem->MsgLen, &ChSwAnnInfo)) { DBGPRINT(RT_DEBUG_TRACE, ("Invalid Channel Switch Action Frame.\n")); return; }#ifdef CONFIG_STA_SUPPORT if (pAd->OpMode == OPMODE_STA) { Bssidx = BssTableSearch(&pAd->ScanTab, pFr->Hdr.Addr3, pAd->CommonCfg.Channel); if (Bssidx == BSS_NOT_FOUND) { DBGPRINT(RT_DEBUG_TRACE, ("PeerChSwAnnAction - Bssidx is not found\n")); return; } DBGPRINT(RT_DEBUG_TRACE, ("\n****Bssidx is %d, Channel = %d\n", index, pAd->ScanTab.BssEntry[Bssidx].Channel)); hex_dump("SSID",pAd->ScanTab.BssEntry[Bssidx].Bssid ,6); Channel = pAd->CommonCfg.Channel; NewChannel = ChSwAnnInfo.Channel; if ((pAd->CommonCfg.bIEEE80211H == 1) && (NewChannel != 0) && (Channel != NewChannel)) { // Switching to channel 1 can prevent from rescanning the current channel immediately (by auto reconnection). // In addition, clear the MLME queue and the scan table to discard the RX packets and previous scanning results. AsicSwitchChannel(pAd, 1, FALSE); AsicLockChannel(pAd, 1); LinkDown(pAd, FALSE); MlmeQueueInit(&pAd->Mlme.Queue); BssTableInit(&pAd->ScanTab); RTMPusecDelay(1000000); // use delay to prevent STA do reassoc // channel sanity check for (index = 0 ; index < pAd->ChannelListNum; index++) { if (pAd->ChannelList[index].Channel == NewChannel) { pAd->ScanTab.BssEntry[Bssidx].Channel = NewChannel; pAd->CommonCfg.Channel = NewChannel; AsicSwitchChannel(pAd, pAd->CommonCfg.Channel, FALSE); AsicLockChannel(pAd, pAd->CommonCfg.Channel); DBGPRINT(RT_DEBUG_TRACE, ("&&&&&&&&&&&&&&&&PeerChSwAnnAction - STA receive channel switch announcement IE (New Channel =%d)\n", NewChannel)); break; } } if (index >= pAd->ChannelListNum) { DBGPRINT_ERR(("&&&&&&&&&&&&&&&&&&&&&&&&&&PeerChSwAnnAction(can not find New Channel=%d in ChannelList[%d]\n", pAd->CommonCfg.Channel, pAd->ChannelListNum)); } } }#endif // CONFIG_STA_SUPPORT // return;}/* ========================================================================== Description: Measurement Request action frame handler. Parametrs: Elme - MLME message containing the received frame Return : None. ========================================================================== */static VOID PeerMeasureReqAction( IN PRTMP_ADAPTER pAd, IN MLME_QUEUE_ELEM *Elem){ PFRAME_802_11 pFr = (PFRAME_802_11)Elem->Msg; UINT8 DialogToken; MEASURE_REQ_INFO MeasureReqInfo; MEASURE_REQ MeasureReq; MEASURE_REPORT_MODE ReportMode; if(PeerMeasureReqSanity(pAd, Elem->Msg, Elem->MsgLen, &DialogToken, &MeasureReqInfo, &MeasureReq)) { ReportMode.word = 0; ReportMode.field.Incapable = 1; EnqueueMeasurementRep(pAd, pFr->Hdr.Addr2, DialogToken, MeasureReqInfo.Token, ReportMode.word, MeasureReqInfo.ReqType, 0, NULL); } return;}/* ========================================================================== Description: Measurement Report action frame handler. Parametrs: Elme - MLME message containing the received frame Return : None. ========================================================================== */static VOID PeerMeasureReportAction( IN PRTMP_ADAPTER pAd, IN MLME_QUEUE_ELEM *Elem) { MEASURE_REPORT_INFO MeasureReportInfo; PFRAME_802_11 pFr = (PFRAME_802_11)Elem->Msg; UINT8 DialogToken; PUINT8 pMeasureReportInfo;// if (pAd->CommonCfg.bIEEE80211H != TRUE)// return; if ((pMeasureReportInfo = kmalloc(sizeof(MEASURE_RPI_REPORT), GFP_ATOMIC)) == NULL) { DBGPRINT(RT_DEBUG_ERROR, ("%s unable to alloc memory for measure report buffer (size=%d).\n", __FUNCTION__, sizeof(MEASURE_RPI_REPORT))); return; } NdisZeroMemory(&MeasureReportInfo, sizeof(MEASURE_REPORT_INFO)); NdisZeroMemory(pMeasureReportInfo, sizeof(MEASURE_RPI_REPORT)); if (PeerMeasureReportSanity(pAd, Elem->Msg, Elem->MsgLen, &DialogToken, &MeasureReportInfo, pMeasureReportInfo)) { do { PMEASURE_REQ_ENTRY pEntry = NULL; // Not a autonomous measure report. // check the dialog token field. drop it if the dialog token doesn't match. if ((DialogToken != 0) && ((pEntry = MeasureReqLookUp(pAd, DialogToken)) == NULL)) break; if (pEntry != NULL) MeasureReqDelete(pAd, pEntry->DialogToken); if (MeasureReportInfo.ReportType == RM_BASIC) { PMEASURE_BASIC_REPORT pBasicReport = (PMEASURE_BASIC_REPORT)pMeasureReportInfo; if ((pBasicReport->Map.field.Radar) && (DfsRequirementCheck(pAd, pBasicReport->ChNum) == TRUE)) { NotifyChSwAnnToPeerAPs(pAd, pFr->Hdr.Addr1, pFr->Hdr.Addr2, 1, pBasicReport->ChNum); StartDFSProcedure(pAd, pBasicReport->ChNum, 1); } } } while (FALSE); } else DBGPRINT(RT_DEBUG_TRACE, ("Invalid Measurement Report Frame.\n")); kfree(pMeasureReportInfo); return;}/* ========================================================================== Description: TPC Request action frame handler. Parametrs: Elme - MLME message containing the received frame Return : None. ========================================================================== */static VOID PeerTpcReqAction( IN PRTMP_ADAPTER pAd, IN MLME_QUEUE_ELEM *Elem) { PFRAME_802_11 pFr = (PFRAME_802_11)Elem->Msg; PUCHAR pFramePtr = pFr->Octet; UINT8 DialogToken; UINT8 TxPwr = GetCurTxPwr(pAd, Elem->Wcid); UINT8 LinkMargin = 0; CHAR RealRssi; // link margin: Ratio of the received signal power to the minimum desired by the station (STA). The // STA may incorporate rate information and channel conditions, including interference, into its computation // of link margin. RealRssi = RTMPMaxRssi(pAd, ConvertToRssi(pAd, Elem->Rssi0, RSSI_0), ConvertToRssi(pAd, Elem->Rssi1, RSSI_1), ConvertToRssi(pAd, Elem->Rssi2, RSSI_2)); // skip Category and action code. pFramePtr += 2; // Dialog token. NdisMoveMemory(&DialogToken, pFramePtr, 1); LinkMargin = (RealRssi / MIN_RCV_PWR); if (PeerTpcReqSanity(pAd, Elem->Msg, Elem->MsgLen, &DialogToken)) EnqueueTPCRep(pAd, pFr->Hdr.Addr2, DialogToken, TxPwr, LinkMargin); return;}/* ========================================================================== Description: TPC Report action frame handler. Parametrs: Elme - MLME message containing the received frame Return : None. ========================================================================== */static VOID PeerTpcRepAction( IN PRTMP_ADAPTER pAd, IN MLME_QUEUE_ELEM *Elem) { UINT8 DialogToken; TPC_REPORT_INFO TpcRepInfo; PTPC_REQ_ENTRY pEntry = NULL; NdisZeroMemory(&TpcRepInfo, sizeof(TPC_REPORT_INFO)); if (PeerTpcRepSanity(pAd, Elem->Msg, Elem->MsgLen, &DialogToken, &TpcRepInfo)) { if ((pEntry = TpcReqLookUp(pAd, DialogToken)) != NULL) { TpcReqDelete(pAd, pEntry->DialogToken); DBGPRINT(RT_DEBUG_TRACE, ("%s: DialogToken=%x, TxPwr=%d, LinkMargin=%d\n", __FUNCTION__, DialogToken, TpcRepInfo.TxPwr, TpcRepInfo.LinkMargin)); } } return;}/* ========================================================================== Description: Spectrun action frames Handler such as channel switch annoucement, measurement report, measurement request actions frames. Parametrs: Elme - MLME message containing the received frame Return : None. ========================================================================== */VOID PeerSpectrumAction( IN PRTMP_ADAPTER pAd, IN MLME_QUEUE_ELEM *Elem) { UCHAR Action = Elem->Msg[LENGTH_802_11+1]; if (pAd->CommonCfg.bIEEE80211H != TRUE) return; switch(Action) { case SPEC_MRQ: // current rt2860 unable do such measure specified in Measurement Request. // reject all measurement request. PeerMeasureReqAction(pAd, Elem); break; case SPEC_MRP: PeerMeasureReportAction(pAd, Elem); break; case SPEC_TPCRQ: PeerTpcReqAction(pAd, Elem); break; case SPEC_TPCRP: PeerTpcRepAction(pAd, Elem); break; case SPEC_CHANNEL_SWITCH:#ifdef DOT11N_DRAFT3 { SEC_CHA_OFFSET_IE Secondary; CHA_SWITCH_ANNOUNCE_IE ChannelSwitch; // 802.11h only has Channel Switch Announcement IE. RTMPMoveMemory(&ChannelSwitch, &Elem->Msg[LENGTH_802_11+4], sizeof (CHA_SWITCH_ANNOUNCE_IE)); // 802.11n D3.03 adds secondary channel offset element in the end. if (Elem->MsgLen == (LENGTH_802_11 + 2 + sizeof (CHA_SWITCH_ANNOUNCE_IE) + sizeof (SEC_CHA_OFFSET_IE))) { RTMPMoveMemory(&Secondary, &Elem->Msg[LENGTH_802_11+9], sizeof (SEC_CHA_OFFSET_IE)); } else { Secondary.SecondaryChannelOffset = 0; } if ((Elem->Msg[LENGTH_802_11+2] == IE_CHANNEL_SWITCH_ANNOUNCEMENT) && (Elem->Msg[LENGTH_802_11+3] == 3)) { ChannelSwitchAction(pAd, Elem->Wcid, ChannelSwitch.NewChannel, Secondary.SecondaryChannelOffset); } }#endif // DOT11N_DRAFT3 // PeerChSwAnnAction(pAd, Elem); break; } return;}/* ========================================================================== Description: Parametrs: Return : None. ========================================================================== */INT Set_MeasureReq_Proc( IN PRTMP_ADAPTER pAd, IN PSTRING arg){ UINT Aid = 1; UINT ArgIdx; PSTRING thisChar; MEASURE_REQ_MODE MeasureReqMode; UINT8 MeasureReqToken = RandomByte(pAd); UINT8 MeasureReqType = RM_BASIC; UINT8 MeasureCh = 1; UINT64 MeasureStartTime = GetCurrentTimeStamp(pAd); MEASURE_REQ MeasureReq; UINT8 TotalLen; HEADER_802_11 ActHdr; PUCHAR pOutBuffer = NULL; NDIS_STATUS NStatus; ULONG FrameLen; NStatus = MlmeAllocateMemory(pAd, (PVOID)&pOutBuffer); //Get an unused nonpaged memory if(NStatus != NDIS_STATUS_SUCCESS) { DBGPRINT(RT_DEBUG_TRACE, ("%s() allocate memory failed \n", __FUNCTION__)); goto END_OF_MEASURE_REQ; } ArgIdx = 1; while ((thisChar = strsep((char **)&arg, "-")) != NULL) { switch(ArgIdx) { case 1: // Aid. Aid = (UINT8) simple_strtol(thisChar, 0, 16); break; case 2: // Measurement Request Type. MeasureReqType = simple_strtol(thisChar, 0, 16); if (MeasureReqType > 3) { DBGPRINT(RT_DEBUG_ERROR, ("%s: unknow MeasureReqType(%d)\n", __FUNCTION__, MeasureReqType)); goto END_OF_MEASURE_REQ; } break; case 3: // Measurement channel. MeasureCh = (UINT8) simple_strtol(thisChar, 0, 16); break; } ArgIdx++; } DBGPRINT(RT_DEBUG_TRACE, ("%s::Aid = %d, MeasureReqType=%d MeasureCh=%d\n", __FUNCTION__, Aid, MeasureReqType, MeasureCh)); if (!VALID_WCID(Aid)) { DBGPRINT(RT_DEBUG_ERROR, ("%s: unknow sta of Aid(%d)\n", __FUNCTION__, Aid)); goto END_OF_MEASURE_REQ; } MeasureReqMode.word = 0; MeasureReqMode.field.Enable = 1; MeasureReqInsert(pAd, MeasureReqToken); // build action frame header. MgtMacHeaderInit(pAd, &ActHdr, SUBTYPE_ACTION, 0, pAd->MacTab.Content[Aid].Addr, pAd->CurrentAddress); NdisMoveMemory(pOutBuffer, (PCHAR)&ActHdr, sizeof(HEADER_802_11)); FrameLen = sizeof(HEADER_802_11); TotalLen = sizeof(MEASURE_REQ_INFO) + sizeof(MEASURE_REQ); MakeMeasurementReqFrame(pAd, pOutBuffer, &FrameLen, sizeof(MEASURE_REQ_INFO), CATEGORY_RM, RM_BASIC, MeasureReqToken, MeasureReqMode.word, MeasureReqType, 0); MeasureReq.ChNum = MeasureCh; MeasureReq.MeasureStartTime = cpu2le64(MeasureStartTime); MeasureReq.MeasureDuration = cpu2le16(2000); { ULONG TempLen; MakeOutgoingFrame( pOutBuffer+FrameLen, &TempLen, sizeof(MEASURE_REQ), &MeasureReq, END_OF_ARGS); FrameLen += TempLen; } MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer, (UINT)FrameLen);END_OF_MEASURE_REQ: MlmeFreeMemory(pAd, pOutBuffer); return TRUE;}INT Set_TpcReq_Proc( IN PRTMP_ADAPTER pAd, IN PSTRING arg){ UINT Aid; UINT8 TpcReqToken = RandomByte(pAd); Aid = (UINT) simple_strtol(arg, 0, 16); DBGPRINT(RT_DEBUG_TRACE, ("%s::Aid = %d\n", __FUNCTION__, Aid)); if (!VALID_WCID(Aid)) { DBGPRINT(RT_DEBUG_ERROR, ("%s: unknow sta of Aid(%d)\n", __FUNCTION__, Aid)); return TRUE; } TpcReqInsert(pAd, TpcReqToken); EnqueueTPCReq(pAd, pAd->MacTab.Content[Aid].Addr, TpcReqToken); return TRUE;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -