📄 rtusb_data.c
字号:
NdisMoveMemory(&pTxD->Iv, &Iv16, 4); // Copy IV
NdisMoveMemory(&pTxD->Eiv, &Iv32, 4); // Copy EIV
INC_TX_TSC(pKey->TxTsc); // Increase TxTsc for next transmission
}
//
// STEP 5.3 COPY 802.11 HEADER INTO 1ST DMA BUFFER
//
pDest = pWirelessPacket;
NdisMoveMemory(pDest, &Header_802_11, sizeof(Header_802_11));
pDest += sizeof(Header_802_11);
//
// Fragmentation is not allowed on multicast & broadcast
// So, we need to used the MAX_FRAG_THRESHOLD instead of pAd->PortCfg.FragmentThreshold
// otherwise if pSkb->len > pAd->PortCfg.FragmentThreshold then
// packet will be fragment on multicast & broadcast.
//
// MpduRequired equals to 1 means this could be Aggretaion case.
//
if ((Header_802_11.Addr1[0] & 0x01) || MpduRequired == 1)
{
FreeMpduSize = MAX_FRAG_THRESHOLD - sizeof(Header_802_11) - LENGTH_CRC;
}
else
{
FreeMpduSize = pAd->PortCfg.FragmentThreshold - sizeof(Header_802_11) - LENGTH_CRC;
}
#if 0
if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_WMM_INUSED))
{
// copy QOS CONTROL bytes
*pDest = (UserPriority & 0x0f) | pAd->PortCfg.AckPolicy[QueIdx];
*(pDest+1) = 0;
pDest += 2;
FreeMpduSize -= 2;
if (pAd->PortCfg.AckPolicy[QueIdx] != NORMAL_ACK)
{
bAckRequired = FALSE;
}
}
#endif
//
// STEP 5.4 COPY LLC/SNAP, CKIP MIC INTO 1ST DMA BUFFER ONLY WHEN THIS
// MPDU IS THE 1ST OR ONLY FRAGMENT
//
if (Header_802_11.Frag == 0)
{
if (pExtraLlcSnapEncap)
{
if ((CipherAlg == CIPHER_TKIP_NO_MIC) && (pKey != NULL))
{
// Calculate MSDU MIC Value
RTMPCalculateMICValue(pAd, pSkb, pExtraLlcSnapEncap, pKey);
}
// Insert LLC-SNAP encapsulation
NdisMoveMemory(pDest, pExtraLlcSnapEncap, 6);
pDest += 6;
NdisMoveMemory(pDest, pSrcBufVA + 12, 2);
pDest += 2;
pSrcBufVA += LENGTH_802_3;
FreeMpduSize -= LENGTH_802_1_H;
}
else
{
if ((CipherAlg == CIPHER_TKIP_NO_MIC) && (pKey != NULL))
{
// Calculate MSDU MIC Value
RTMPCalculateMICValue(pAd, pSkb, pExtraLlcSnapEncap, pKey);
}
pSrcBufVA += LENGTH_802_3;
}
}
// Start copying payload
BytesCopied = 0;
do
{
if (SrcBufLen >= FreeMpduSize)
{
// Copy only the free fragment size, and save the pointer
// of current buffer descriptor for next fragment buffer.
NdisMoveMemory(pDest, pSrcBufVA, FreeMpduSize);
BytesCopied += FreeMpduSize;
pSrcBufVA += FreeMpduSize;
pDest += FreeMpduSize;
SrcBufLen -= FreeMpduSize;
break;
}
else
{
// Copy the rest of this buffer descriptor pointed data
// into ring buffer.
NdisMoveMemory(pDest, pSrcBufVA, SrcBufLen);
BytesCopied += SrcBufLen;
pDest += SrcBufLen;
FreeMpduSize -= SrcBufLen;
}
// No more buffer descriptor
// Add MIC value if needed
//if ((pAd->PortCfg.WepStatus == Ndis802_11Encryption2Enabled) &&
// (MICFrag == FALSE) &&
// (pKey != NULL))
if((CipherAlg == CIPHER_TKIP_NO_MIC) &&
(MICFrag == FALSE) &&
(pKey != NULL))
{
// Fregment and TKIP//
INT i;
SrcBufLen = 8; // Set length to MIC length
DBGPRINT_RAW(RT_DEBUG_INFO, "Calculated TX MIC value =");
for (i = 0; i < 8; i++)
{
DBGPRINT_RAW(RT_DEBUG_INFO, "%02x:", pAd->PrivateInfo.Tx.MIC[i]);
}
DBGPRINT_RAW(RT_DEBUG_INFO, "\n");
if (FreeMpduSize >= SrcBufLen)
{
NdisMoveMemory(pDest, pAd->PrivateInfo.Tx.MIC, SrcBufLen);
BytesCopied += SrcBufLen;
pDest += SrcBufLen;
FreeMpduSize -= SrcBufLen;
SrcBufLen = 0;
}
else
{
NdisMoveMemory(pDest, pAd->PrivateInfo.Tx.MIC, FreeMpduSize);
BytesCopied += FreeMpduSize;
pSrcBufVA = pAd->PrivateInfo.Tx.MIC + FreeMpduSize;
pDest += FreeMpduSize;
SrcBufLen -= FreeMpduSize;
MICFrag = TRUE;
}
}
} while (FALSE); // End of copying payload
// Real packet size, No 802.1H header for fragments except the first one.
if ((StartOfFrame == TRUE) && (pExtraLlcSnapEncap != NULL))
{
TxSize = BytesCopied + LENGTH_802_11 + LENGTH_802_1_H + LengthQosPAD;
}
else
{
TxSize = BytesCopied + LENGTH_802_11 + LengthQosPAD;
}
SrcRemainingBytes -= BytesCopied;
//
// STEP 5.6 MODIFY MORE_FRAGMENT BIT & DURATION FIELD. WRITE TXD
//
pHeader80211 = (PHEADER_802_11)pWirelessPacket;
if (SrcRemainingBytes > 0) // more fragment is required
{
ULONG NextMpduSize;
pHeader80211->FC.MoreFrag = 1;
NextMpduSize = min((ULONG)SrcRemainingBytes, (ULONG)pAd->PortCfg.FragmentThreshold);
if (NextMpduSize < pAd->PortCfg.FragmentThreshold)
{
// In this case, we need to include LENGTH_802_11 and LENGTH_CRC for calculating Duration.
pHeader80211->Duration = (3 * pAd->PortCfg.Dsifs) +
(2 * AckDuration) +
RTMPCalcDuration(pAd, TxRate, NextMpduSize + EncryptionOverhead + LENGTH_802_11 + LENGTH_CRC);
}
else
{
pHeader80211->Duration = (3 * pAd->PortCfg.Dsifs) +
(2 * AckDuration) +
RTMPCalcDuration(pAd, TxRate, NextMpduSize + EncryptionOverhead);
}
#ifdef BIG_ENDIAN
RTMPFrameEndianChange(pAd, (PUCHAR)pHeader80211, DIR_WRITE, FALSE);
RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD);
*pDestTxD = TxD;
pTxD = pDestTxD;
#endif
RTUSBWriteTxDescriptor(pAd, pTxD, CipherAlg, 0, KeyIdx, bAckRequired, TRUE, FALSE,
RetryMode, FrameGap, TxRate, TxSize, QueIdx, 0, bRTS_CTSFrame);
FrameGap = IFS_SIFS; // use SIFS for all subsequent fragments
Header_802_11.Frag ++; // increase Frag #
}
else
{
pHeader80211->FC.MoreFrag = 0;
if (pHeader80211->Addr1[0] & 0x01) // multicast/broadcast
pHeader80211->Duration = 0;
else
pHeader80211->Duration = pAd->PortCfg.Dsifs + AckDuration;
if ((bEAPOLFrame) && (TxRate > RATE_6))
TxRate = RATE_6;
#ifdef BIG_ENDIAN
RTMPFrameEndianChange(pAd, (PUCHAR)pHeader80211, DIR_WRITE, FALSE);
RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD);
*pDestTxD = TxD;
pTxD = pDestTxD;
#endif
RTUSBWriteTxDescriptor(pAd, pTxD, CipherAlg, 0, KeyIdx, bAckRequired, FALSE, FALSE,
RetryMode, FrameGap, TxRate, TxSize, QueIdx, 0, bRTS_CTSFrame);
if (pAd->SendTxWaitQueue[QueIdx].Number > 1)
pTxD->Burst = 1;
}
TransferBufferLength = TxSize + sizeof(TXD_STRUC);
if ((TransferBufferLength % 4) == 1)
TransferBufferLength += 3;
else if ((TransferBufferLength % 4) == 2)
TransferBufferLength += 2;
else if ((TransferBufferLength % 4) == 3)
TransferBufferLength += 1;
if ((TransferBufferLength % pAd->BulkOutMaxPacketSize) == 0)
TransferBufferLength += 4;
pTxContext->BulkOutSize = TransferBufferLength;
pTxContext->bWaitingBulkOut = TRUE;
RTUSB_SET_BULK_FLAG(pAd, (fRTUSB_BULK_OUT_DATA_NORMAL << QueIdx));
// Set frame gap for the rest of fragment burst.
// It won't matter if there is only one fragment (single fragment frame).
StartOfFrame = FALSE;
NumberRequired--;
if (NumberRequired == 0)
{
pTxContext->LastOne = TRUE;
}
else
{
pTxContext->LastOne = FALSE;
}
pAd->TxRingTotalNumber[QueIdx]++; // sync. to TxCount
atomic_inc(&pAd->TxCount);
} while (NumberRequired > 0);
//
// Check if MIC error twice within 60 seconds and send EAPOL MIC error to TX queue
// then we enqueue a message for disasociating with the current AP
//
// Check for EAPOL frame sent after MIC countermeasures
if (pAd->PortCfg.MicErrCnt >= 3)
{
MLME_DISASSOC_REQ_STRUCT DisassocReq;
// disassoc from current AP first
printk("<0>MLME - disassociate with current AP after sending second continuous EAPOL frame\n");
DBGPRINT(RT_DEBUG_TRACE, "MLME - disassociate with current AP after sending second continuous EAPOL frame\n");
DisassocParmFill(pAd, &DisassocReq, pAd->PortCfg.Bssid, REASON_MIC_FAILURE);
MlmeEnqueue(pAd, ASSOC_STATE_MACHINE, MT2_MLME_DISASSOC_REQ,
sizeof(MLME_DISASSOC_REQ_STRUCT), &DisassocReq);
pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_DISASSOC;
pAd->PortCfg.bBlockAssoc = TRUE;
printk("<0>bBlockAssoc = %d\n", pAd->PortCfg.bBlockAssoc);
}
// release the skb buffer
RELEASE_NDIS_PACKET(pAd, pSkb);
return (NDIS_STATUS_SUCCESS);
}
/*
========================================================================
Routine Description:
Copy frame from waiting queue into relative ring buffer and set
appropriate ASIC register to kick hardware transmit function
Arguments:
pAd Pointer to our adapter
pBuffer Pointer to memory of outgoing frame
Length Size of outgoing management frame
Return Value:
NDIS_STATUS_FAILURE
NDIS_STATUS_PENDING
NDIS_STATUS_SUCCESS
Note:
========================================================================
*/
VOID RTUSBMlmeHardTransmit(
IN PRTMP_ADAPTER pAd,
IN PMGMT_STRUC pMgmt)
{
PTX_CONTEXT pMLMEContext;
PTXD_STRUC pTxD;
#ifdef BIG_ENDIAN
PTXD_STRUC pDestTxD;
TXD_STRUC TxD;
#endif
PUCHAR pDest;
PHEADER_802_11 pHeader_802_11;
BOOLEAN AckRequired, InsertTimestamp;
ULONG TransferBufferLength;
PVOID pBuffer = pMgmt->pBuffer;
ULONG Length = pMgmt->Length;
UCHAR QueIdx;
UCHAR MlmeRate;
DBGPRINT_RAW(RT_DEBUG_INFO, "--->MlmeHardTransmit\n");
pAd->PrioRingTxCnt++;
pMLMEContext = &pAd->MLMEContext[pAd->NextMLMEIndex];
pMLMEContext->InUse = TRUE;
// Increase & maintain Tx Ring Index
pAd->NextMLMEIndex++;
if (pAd->NextMLMEIndex >= PRIO_RING_SIZE)
{
pAd->NextMLMEIndex = 0;
}
pDest = pMLMEContext->TransferBuffer->WirelessPacket;
#ifndef BIG_ENDIAN
pTxD = (PTXD_STRUC)(pMLMEContext->TransferBuffer);
#else
pDestTxD = (PTXD_STRUC)(pMLMEContext->TransferBuffer);
TxD = *pDestTxD;
pTxD = &TxD;
RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD);
#endif
NdisZeroMemory(pTxD, sizeof(TXD_STRUC));
pHeader_802_11 = (PHEADER_802_11) pBuffer;
// Verify Mlme rate for a / g bands.
if (pHeader_802_11->Addr1[0] & 0x01)
{
MlmeRate = pAd->PortCfg.BasicMlmeRate;
}
else
{
MlmeRate = pAd->PortCfg.MlmeRate;
}
if ((pAd->LatchRfRegs.Channel > 14) && (MlmeRate < RATE_6)) // 11A band
MlmeRate = RATE_6;
DBGPRINT(RT_DEBUG_TRACE, "<---MlmeRate %d Channel %d\n",MlmeRate, pAd->LatchRfRegs.Channel );
// Before radar detection done, mgmt frame can not be sent but probe req
// Because we need to use probe req to trigger driver to send probe req in passive scan
if ((pHeader_802_11->FC.SubType != SUBTYPE_PROBE_REQ) && (pAd->PortCfg.bIEEE80211H == 1) && (pAd->PortCfg.RadarDetect.RDMode != RD_NORMAL_MODE))
{
DBGPRINT(RT_DEBUG_ERROR, "RTUSBMlmeHardTransmit --> radar detect not in normal mode !!!\n");
return;
}
if (pHeader_802_11->FC.PwrMgmt != PWR_SAVE)
{
pHeader_802_11->FC.PwrMgmt = (pAd->PortCfg.Psm == PWR_SAVE);
}
InsertTimestamp = FALSE;
if (pHeader_802_11->FC.Type == BTYPE_CNTL) // must be PS-POLL
{
AckRequired = FALSE;
}
else // BTYPE_MGMT or BMGMT_DATA(must be NULL frame)
{
pAd->Sequence = ((pAd->Sequence) + 1) & (MAX_SEQ_NUMBER);
pHeader_802_11->Sequence = pAd->Sequence;
if (pHeader_802_11->Addr1[0] & 0x01) // MULTICAST, BROADCAST
{
INC_COUNTER64(pAd->WlanCounters.MulticastTransmittedFrameCount);
AckRequired = FALSE;
pHeader_802_11->Duration = 0;
}
else
{
AckRequired = TRUE;
pHeader_802_11->Duration = RTMPCalcDuration(pAd, MlmeRate, 14);
if (pHeader_802_11->FC.SubType == SUBTYPE_PROBE_RSP)
{
InsertTimestamp = TRUE;
}
}
}
NdisMoveMemory(pDest, pBuffer, Length);
// Initialize Priority Descriptor
// For inter-frame gap, the number is for this frame and next frame
// For MLME rate, we will fix as 2Mb to match other vendor's implement
QueIdx = QID_AC_BE;
#ifdef BIG_ENDIAN
RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -