mlme.c

来自「Ralink RT61 SoftAP Driver source code. 」· C语言 代码 · 共 1,669 行 · 第 1/5 页

C
1,669
字号
		UCHAR Rate, MaxDesire = RATE_1, MaxSupport = RATE_1; //, MaxBasicRate = RATE_1;
		
	    // find max desired rate
	    num = 0;
	    for (i=0; i<MAX_LEN_OF_SUPPORTED_RATES; i++)
	    {
	        switch (pAd->PortCfg.MBSSID[j].DesiredRates[i] & 0x7f)
	        {
	            case 2:  Rate = RATE_1;   num++;   break;
	            case 4:  Rate = RATE_2;   num++;   break;
	            case 11: Rate = RATE_5_5; num++;   break;
	            case 22: Rate = RATE_11;  num++;   break;
	            case 12: Rate = RATE_6;   num++;   break;
	            case 18: Rate = RATE_9;   num++;   break;
	            case 24: Rate = RATE_12;  num++;   break;
	            case 36: Rate = RATE_18;  num++;   break;
	            case 48: Rate = RATE_24;  num++;   break;
	            case 72: Rate = RATE_36;  num++;   break;
	            case 96: Rate = RATE_48;  num++;   break;
	            case 108: Rate = RATE_54; num++;   break;
	            default: Rate = RATE_1;   break;
	        }
	        if (MaxDesire < Rate)  MaxDesire = Rate;
	    }

	    // Auto rate switching is enabled only if more than one DESIRED RATES are 
	    // specified; otherwise disabled
	    if (num <= 1)
	        OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_TX_RATE_SWITCH_ENABLED);
	    else
	        OPSTATUS_SET_FLAG(pAd, fOP_STATUS_TX_RATE_SWITCH_ENABLED);

	    // find max supported rate
	    for (i=0; i<pAd->PortCfg.SupportedRatesLen; i++)
	    {
	        switch (pAd->PortCfg.SupportedRates[i] & 0x7f)
	        {
	            case 2: Rate = RATE_1;   
	                    if (pAd->PortCfg.SupportedRates[i] & 0x80) 
	                        BasicRateBitmap |= 0x0001;  
	                    break;
	            case 4: Rate = RATE_2;   
	                    if (pAd->PortCfg.SupportedRates[i] & 0x80) 
	                        BasicRateBitmap |= 0x0002;  
	                    break;
	            case 11: 
	                    Rate = RATE_5_5; 
	                    if (pAd->PortCfg.SupportedRates[i] & 0x80) 
	                        BasicRateBitmap |= 0x0004;  
	                    break;
	            case 22: 
	                    Rate = RATE_11;  
	                    if (pAd->PortCfg.SupportedRates[i] & 0x80) 
	                        BasicRateBitmap |= 0x0008;  
	                    break;
	            case 12: 
	                    Rate = RATE_6;   
	//                    if (pAd->PortCfg.SupportedRates[i] & 0x80) 
	                        BasicRateBitmap |= 0x0010;  
	                    break;
	            case 18: 
	                    Rate = RATE_9;   
	                    if (pAd->PortCfg.SupportedRates[i] & 0x80) 
	                        BasicRateBitmap |= 0x0020;  
	                    break;
	            case 24: 
	                    Rate = RATE_12;  
	//                    if (pAd->PortCfg.SupportedRates[i] & 0x80) 
	                        BasicRateBitmap |= 0x0040;  
	                    break;
	            case 36: 
	                    Rate = RATE_18;  
	                    if (pAd->PortCfg.SupportedRates[i] & 0x80) 
	                        BasicRateBitmap |= 0x0080;  
	                    break;
	            case 48: 
	                    Rate = RATE_24;
	//                    if (pAd->PortCfg.SupportedRates[i] & 0x80) 
	                        BasicRateBitmap |= 0x0100;
	                    break;
	            case 72: 
	                    Rate = RATE_36;  
	                    if (pAd->PortCfg.SupportedRates[i] & 0x80) 
	                        BasicRateBitmap |= 0x0200;  
	                    break;
	            case 96: 
	                    Rate = RATE_48;  
	                    if (pAd->PortCfg.SupportedRates[i] & 0x80) 
	                        BasicRateBitmap |= 0x0400;  
	                    break;
	            case 108: 
	                    Rate = RATE_54; 
	                    if (pAd->PortCfg.SupportedRates[i] & 0x80) 
	                        BasicRateBitmap |= 0x0800;  
	                    break;
	            default:  
	                    Rate = RATE_1;   
	                    break;
	        }
	        if (MaxSupport < Rate)  MaxSupport = Rate;

	        // decide max basic rate, which is used to send MLME frames
	//      if ((pAd->PortCfg.SupportedRates[i] & 0x80) && (MaxBasicRate < Rate))
	//      {
	            // use only 11b CCK as max basic rate when operate in B/G mixed mode, B-only mode
	//          if (Rate < RATE_FIRST_OFDM_RATE)  MaxBasicRate = Rate;
	//      }
	    }

	    // max tx rate = min {max desire rate, max supported rate}
	    if (MaxSupport < MaxDesire)
	        pAd->PortCfg.MBSSID[j].MaxTxRate = pAd->PortCfg.MBSSID[j].TxRate = MaxSupport;
	    else
	        pAd->PortCfg.MBSSID[j].MaxTxRate = pAd->PortCfg.MBSSID[j].TxRate = MaxDesire;
#if 0
		// determine Auto Responder Tx Power
		if (pAd->TxPowerDelta.field.Enable == 1)
		{
		    if (pAd->TxPowerDelta.field.Sign == 1)
		    {
		    	if ((pAd->LatchBBPR94 + pAd->TxPowerDelta.field.Delta) < 12)
		    		AutoRespTxPower = pAd->LatchBBPR94 + pAd->TxPowerDelta.field.Delta;
		    	else
		    		AutoRespTxPower = 12;
		    }
		    else
		    {
		    	if ((pAd->LatchBBPR94 - pAd->TxPowerDelta.field.Delta) > 0)
			    	AutoRespTxPower = pAd->LatchBBPR94 - pAd->TxPowerDelta.field.Delta;
		    	else
		    		AutoRespTxPower = 0;
		    }
		}
		else
		{
			AutoRespTxPower = DEFAULT_BBP_TX_POWER;
		}
#endif
	//  pAd->PortCfg.MaxBasicRate = MaxBasicRate;
//        RTMP_IO_WRITE32(pAd, TXRX_CSR5, (BasicRateBitmap | (AutoRespTxPower << 16)));
		RTMP_IO_WRITE32(pAd, TXRX_CSR5, BasicRateBitmap);

	    // calculate the exptected ACK rate for each TX rate. This info is used to caculate
	    // the DURATION field of outgoing uniicast DATA/MGMT frame
	    for (i=0; i<MAX_LEN_OF_SUPPORTED_RATES; i++)
	    {
	        if (BasicRateBitmap & (0x01 << i))
	            CurrBasicRate = (UCHAR)i;
	        pAd->PortCfg.ExpectedACKRate[i] = CurrBasicRate;
	        DBGPRINT(RT_DEBUG_INFO,"Expected ACK rate for %d Mbps = %d Mbps\n", RateIdToMbps[i], RateIdToMbps[CurrBasicRate]);
	    }

	    switch (pAd->PortCfg.PhyMode)
	    {
	        case PHY_11BG_MIXED:
	        case PHY_11B:
	        case PHY_11G:
	            pAd->PortCfg.MlmeRate = RATE_1;	//pAd->PortCfg.MlmeRate = RATE_2;(To let beacon transmit using RATE_1)
	            pAd->PortCfg.RtsRate = RATE_11;
	            break;
	        case PHY_11A:
	            pAd->PortCfg.MlmeRate = RATE_6;
	            pAd->PortCfg.RtsRate = RATE_6;
	            break;
	        default: // error
	            pAd->PortCfg.MlmeRate = RATE_2;
	            pAd->PortCfg.RtsRate = RATE_2;
	            break;
	    }
	    
	    DBGPRINT(RT_DEBUG_TRACE, "IF(ra%d) MlmeUpdateTxRates (MaxDesire=%d Mbps, MaxSupport=%d Mbps, MaxTxRate=%d Mbps, Rate Switching =%d)\n", j,
	             RateIdToMbps[MaxDesire], RateIdToMbps[MaxSupport], RateIdToMbps[pAd->PortCfg.MBSSID[j].MaxTxRate], OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_TX_RATE_SWITCH_ENABLED));
	}

    DBGPRINT(RT_DEBUG_TRACE, " MlmeUpdateTxRates (RtsRate=%d Mbps, MlmeRate=%d Mbps, BasicRateBitmap=0x%04x)\n", 
         RateIdToMbps[pAd->PortCfg.RtsRate], RateIdToMbps[pAd->PortCfg.MlmeRate], BasicRateBitmap);
}

/*! \brief init the management mac frame header
 *  \param p_hdr mac header
 *  \param subtype subtype of the frame
 *  \param p_ds destination address, don't care if it is a broadcast address
 *  \return none
 *  \pre the station has the following information in the pAd->UserCfg
 *   - bssid
 *   - station address
 *  \post
 *  \note this function initializes the following field
 */
VOID MgtMacHeaderInit(
    IN	PRTMP_ADAPTER	pAd, 
    IN OUT PHEADER_802_11 pHdr80211, 
    IN UCHAR SubType, 
    IN UCHAR ToDs, 
    IN PUCHAR pDA, 
    IN PUCHAR pBssid) 
{
    NdisZeroMemory(pHdr80211, sizeof(HEADER_802_11));
    pHdr80211->FC.Type = BTYPE_MGMT;
    pHdr80211->FC.SubType = SubType;
    pHdr80211->FC.ToDs = ToDs;
    COPY_MAC_ADDR(pHdr80211->Addr1, pDA);
    COPY_MAC_ADDR(pHdr80211->Addr2, pBssid);
    COPY_MAC_ADDR(pHdr80211->Addr3, pBssid);
}

#ifdef APCLI_SUPPORT
/*! \brief init the management mac frame header
 *  \param p_hdr mac header
 *  \param subtype subtype of the frame
 *  \param p_ds destination address, don't care if it is a broadcast address
 *  \return none
 *  \pre the station has the following information in the pAd->UserCfg
 *   - bssid
 *   - station address
 *  \post
 *  \note this function initializes the following field
 */
VOID ApCliMgtMacHeaderInit(
    IN	PRTMP_ADAPTER	pAd, 
    IN OUT PHEADER_802_11 pHdr80211, 
    IN UCHAR SubType, 
    IN UCHAR ToDs, 
    IN PUCHAR pDA, 
    IN PUCHAR pBssid,
    IN USHORT ifIndex)
{
    NdisZeroMemory(pHdr80211, sizeof(HEADER_802_11));
    pHdr80211->FC.Type = BTYPE_MGMT;
    pHdr80211->FC.SubType = SubType;
    pHdr80211->FC.ToDs = ToDs;
    COPY_MAC_ADDR(pHdr80211->Addr1, pDA);
    COPY_MAC_ADDR(pHdr80211->Addr2, pAd->ApCliTab.ApCliEntry[ifIndex].CurrentAddress);
    COPY_MAC_ADDR(pHdr80211->Addr3, pBssid);
}
#endif

// ===========================================================================================
// mem_mgmt.c
// ===========================================================================================

/*!***************************************************************************
 * This routine build an outgoing frame, and fill all information specified 
 * in argument list to the frame body. The actual frame size is the summation 
 * of all arguments.
 * input params:
 *      Buffer - pointer to a pre-allocated memory segment
 *      args - a list of <int arg_size, arg> pairs.
 *      NOTE NOTE NOTE!!!! the last argument must be NULL, otherwise this
 *                         function will FAIL!!!
 * return:
 *      Size of the buffer
 * usage:  
 *      MakeOutgoingFrame(Buffer, output_length, 2, &fc, 2, &dur, 6, p_addr1, 6,p_addr2, END_OF_ARGS);
 ****************************************************************************/
ULONG MakeOutgoingFrame(
    OUT CHAR *Buffer, 
    OUT ULONG *FrameLen, ...) 
{
    CHAR   *p;
    int     leng;
    ULONG   TotLeng;
    va_list Args;

    // calculates the total length
    TotLeng = 0;
    va_start(Args, FrameLen);
    do 
    {
        leng = va_arg(Args, int);
        if (leng == END_OF_ARGS) 
        {
            break;
        }
        p = va_arg(Args, PVOID);
        NdisMoveMemory(&Buffer[TotLeng], p, leng);
        TotLeng = TotLeng + leng;
    } while(TRUE);

    va_end(Args); /* clean up */
    *FrameLen = TotLeng;
    return TotLeng;
}

// ===========================================================================================
// mlme_queue.c
// ===========================================================================================

/*! \brief  Initialize The MLME Queue, used by MLME Functions
 *  \param  *Queue     The MLME Queue
 *  \return Always     Return NDIS_STATE_SUCCESS in this implementation
 *  \pre
 *  \post
 *  \note   Because this is done only once (at the init stage), no need to be locked
 */
NDIS_STATUS MlmeQueueInit(
    IN MLME_QUEUE *Queue) 
{
    INT i;

    NdisAllocateSpinLock(&Queue->Lock);

    Queue->Num  = 0;
    Queue->Head = 0;
    Queue->Tail = 0;

    for (i = 0; i < MAX_LEN_OF_MLME_QUEUE; i++) 
    {
        Queue->Entry[i].Occupied = FALSE;
        Queue->Entry[i].MsgLen = 0;
        NdisZeroMemory(Queue->Entry[i].Msg, MAX_LEN_OF_MLME_BUFFER);
    }

    return NDIS_STATUS_SUCCESS;
}


/*! \brief   Enqueue a message for other threads, if they want to send messages to MLME thread
 *  \param  *Queue    The MLME Queue
 *  \param   Machine  The State Machine Id
 *  \param   MsgType  The Message Type
 *  \param   MsgLen   The Message length
 *  \param  *Msg      The message pointer
 *  \return  TRUE if enqueue is successful, FALSE if the queue is full
 *  \pre
 *  \post
 *  \note    The message has to be initialized
 */
BOOLEAN MlmeEnqueue(
	IN	PRTMP_ADAPTER	pAd,
    IN ULONG Machine, 
    IN ULONG MsgType, 
    IN

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?