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 + -
显示快捷键?