📄 rtusb_data.c
字号:
// Release TxSwQueue0 resources
NdisReleaseSpinLock(&pAd->SendTxWaitQueueLock[BulkOutPipeId], (unsigned long)IrqFlags);
NdisAcquireSpinLock(&pAd->DeQueueLock[BulkOutPipeId], (unsigned long)IrqFlags);
pAd->DeQueueRunning[BulkOutPipeId] = FALSE;
NdisReleaseSpinLock(&pAd->DeQueueLock[BulkOutPipeId], (unsigned long)IrqFlags);
}
/*
========================================================================
Description:
This is the completion routine for the USB_RxPacket which submits
a URB to USBD for a transmission.
========================================================================
*/
VOID RTUSBRxPacket(
IN unsigned long data)
{
purbb_t pUrb = (purbb_t)data;
PRTMP_ADAPTER pAd;
PRX_CONTEXT pRxContext;
PRXD_STRUC pRxD;
#ifdef BIG_ENDIAN
PRXD_STRUC pDestRxD;
RXD_STRUC RxD;
#endif
PHEADER_802_11 pHeader;
PUCHAR pData;
PUCHAR pDA, pSA;
NDIS_STATUS Status;
USHORT DataSize, Msdu2Size;
UCHAR Header802_3[14];
PCIPHER_KEY pWpaKey;
// struct sk_buff *pSkb;
BOOLEAN EAPOLFrame;
DBGPRINT_RAW(RT_DEBUG_INFO, "--->RTUSBRxPacket\n");
pRxContext = (PRX_CONTEXT)pUrb->context;
pAd = pRxContext->pAd;
if( RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST) )
return;
do
{
DBGPRINT_RAW(RT_DEBUG_INFO, "BulkIn actual length(%d)\n", pRxContext->pUrb->actual_length);
if (pRxContext->pUrb->actual_length >= sizeof(RXD_STRUC)+ LENGTH_802_11)
{
pData = pRxContext->TransferBuffer;
#ifndef BIG_ENDIAN
pRxD = (PRXD_STRUC) pData;
#else
pDestRxD = (PRXD_STRUC) pData;
RxD = *pDestRxD;
pRxD = &RxD;
RTMPDescriptorEndianChange((PUCHAR)pRxD, TYPE_RXD);
#endif
// Cast to 802.11 header for flags checking
pHeader = (PHEADER_802_11) (pData + sizeof(RXD_STRUC) );
#ifdef BIG_ENDIAN
RTMPFrameEndianChange(pAd, (PUCHAR)pHeader, DIR_READ, FALSE);
#endif
if (pRxD->DataByteCnt < 4)
Status = NDIS_STATUS_FAILURE;
else
{
// Increase Total receive byte counter after real data received no mater any error or not
pAd->RalinkCounters.ReceivedByteCount += (pRxD->DataByteCnt - 4);
pAd->RalinkCounters.RxCount ++;
// Check for all RxD errors
Status = RTMPCheckRxDescriptor(pAd, pHeader, pRxD);
}
if (Status == NDIS_STATUS_SUCCESS)
{
// Apply packet filtering rule based on microsoft requirements.
Status = RTMPApplyPacketFilter(pAd, pRxD, pHeader);
}
// Add receive counters
if (Status == NDIS_STATUS_SUCCESS)
{
// Increase 802.11 counters & general receive counters
INC_COUNTER64(pAd->WlanCounters.ReceivedFragmentCount);
}
else
{
// Increase general counters
pAd->Counters.RxErrors++;
}
// Check for retry bit, if this bit is on, search the cache with SA & sequence
// as index, if matched, discard this frame, otherwise, update cache
// This check only apply to unicast data & management frames
if ((pRxD->U2M) && (Status == NDIS_STATUS_SUCCESS) && (pHeader->FC.Type != BTYPE_CNTL))
{
if (pHeader->FC.Retry)
{
if (RTMPSearchTupleCache(pAd, pHeader) == TRUE)
{
// Found retry frame in tuple cache, Discard this frame / fragment
// Increase 802.11 counters
INC_COUNTER64(pAd->WlanCounters.FrameDuplicateCount);
DBGPRINT_RAW(RT_DEBUG_INFO, "duplicate frame %d\n", pHeader->Sequence);
Status = NDIS_STATUS_FAILURE;
}
else
{
RTMPUpdateTupleCache(pAd, pHeader);
}
}
else // Update Tuple Cache
{
RTMPUpdateTupleCache(pAd, pHeader);
}
}
if ((pRxD->U2M) || ((pHeader->FC.SubType == SUBTYPE_BEACON) && (MAC_ADDR_EQUAL(&pAd->PortCfg.Bssid, &pHeader->Addr2))))
{
if ((pAd->Antenna.field.NumOfAntenna == 2) && (pAd->Antenna.field.TxDefaultAntenna == 0) && (pAd->Antenna.field.RxDefaultAntenna == 0))
{
COLLECT_RX_ANTENNA_AVERAGE_RSSI(pAd, ConvertToRssi(pAd, (UCHAR)pRxD->PlcpRssi, RSSI_NO_1), 0); //Note: RSSI2 not used on RT73
pAd->PortCfg.NumOfAvgRssiSample ++;
}
}
//
// Do RxD release operation for all failure frames
//
if (Status == NDIS_STATUS_SUCCESS)
{
do
{
// pData : Pointer skip the RxD Descriptior and the first 24 bytes, 802.11 HEADER
pData += LENGTH_802_11 + sizeof(RXD_STRUC);
DataSize = (USHORT) pRxD->DataByteCnt - LENGTH_802_11;
//
// CASE I. receive a DATA frame
//
if (pHeader->FC.Type == BTYPE_DATA)
{
if (RTMPEqualMemory(EAPOL, pData + 6, 2))
EAPOLFrame = TRUE;
else
EAPOLFrame = FALSE;
pAd->BulkInDataOneSecCount++;
// before LINK UP, all DATA frames are rejected
if (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED))
{
DBGPRINT(RT_DEBUG_TRACE,"RxDone- drop DATA frame before LINK UP(len=%d)\n",pRxD->DataByteCnt);
break;
}
// Drop not my BSS frame
//
// Not drop EAPOL frame, since this have happen on the first time that we link up
// And need some more time to set BSSID to asic
// So pRxD->MyBss may be 0
//
if ((pRxD->MyBss == 0) && (EAPOLFrame != TRUE))
break; // give up this frame
// Drop NULL (+CF-POLL) (+CF-ACK) data frame
if ((pHeader->FC.SubType & 0x04) == 0x04)
{
DBGPRINT(RT_DEBUG_TRACE,"RxDone- drop NULL frame(subtype=%d)\n",pHeader->FC.SubType);
break;
}
// remove the 2 extra QOS CNTL bytes
if (pHeader->FC.SubType & 0x08)
{
pData += 2;
DataSize -= 2;
}
// remove the 2 extra AGGREGATION bytes
Msdu2Size = 0;
if (pHeader->FC.Order)
{
Msdu2Size = *pData + (*(pData+1) << 8);
if ((Msdu2Size <= 1536) && (Msdu2Size < DataSize))
{
pData += 2;
DataSize -= 2;
}
else
Msdu2Size = 0;
}
// prepare 802.3 header: DA=addr1; SA=addr3 in INFRA mode, DA=addr2 in ADHOC mode
pDA = pHeader->Addr1;
if (INFRA_ON(pAd))
pSA = pHeader->Addr3;
else
pSA = pHeader->Addr2;
if (pHeader->FC.Wep) // frame received in encrypted format
{
if (pRxD->CipherAlg == CIPHER_NONE) // unsupported cipher suite
{
break; // give up this frame
}
else if (pAd->SharedKey[pRxD->KeyIndex].KeyLen == 0)
{
break; // give up this frame since the keylen is invalid.
}
}
else
{ // frame received in clear text
// encryption in-use but receive a non-EAPOL clear text frame, drop it
if (((pAd->PortCfg.WepStatus == Ndis802_11Encryption1Enabled) ||
(pAd->PortCfg.WepStatus == Ndis802_11Encryption2Enabled) ||
(pAd->PortCfg.WepStatus == Ndis802_11Encryption3Enabled)) &&
(pAd->PortCfg.PrivacyFilter == Ndis802_11PrivFilter8021xWEP) &&
(!NdisEqualMemory(EAPOL_LLC_SNAP, pData, LENGTH_802_1_H)))
{
break; // give up this frame
}
}
//
// Case I.1 Process Broadcast & Multicast data frame
//
if (pRxD->Bcast || pRxD->Mcast)
{
PUCHAR pRemovedLLCSNAP;
INC_COUNTER64(pAd->WlanCounters.MulticastReceivedFrameCount);
// Drop Mcast/Bcast frame with fragment bit on
if (pHeader->FC.MoreFrag)
{
break; // give up this frame
}
// Filter out Bcast frame which AP relayed for us
if (pHeader->FC.FrDs && MAC_ADDR_EQUAL(pHeader->Addr3, pAd->CurrentAddress))
{
break; // give up this frame
}
// build 802.3 header and decide if remove the 8-byte LLC/SNAP encapsulation
CONVERT_TO_802_3(Header802_3, pDA, pSA, pData, DataSize, pRemovedLLCSNAP);
REPORT_ETHERNET_FRAME_TO_LLC(pAd,Header802_3, pData, DataSize, pAd->net_dev);
DBGPRINT(RT_DEBUG_TRACE, "!!! report BCAST DATA to LLC (len=%d) !!!\n", DataSize);
}
//
// Case I.2 Process unicast-to-me DATA frame
//
else if (pRxD->U2M)
{
RECORD_LATEST_RX_DATA_RATE(pAd, pRxD);
// Special DATA frame that has to pass to MLME
// 1. EAPOL handshaking frames when driver supplicant enabled, pass to MLME for special process
if (NdisEqualMemory(EAPOL_LLC_SNAP, pData, LENGTH_802_1_H) && (pAd->PortCfg.WpaState != SS_NOTUSE))
{
DataSize += LENGTH_802_11;
REPORT_MGMT_FRAME_TO_MLME(pAd, pHeader, DataSize, pRxD->PlcpRssi, pRxD->PlcpSignal);
DBGPRINT_RAW(RT_DEBUG_TRACE, "!!! report EAPOL/AIRONET DATA to MLME (len=%d) !!!\n", DataSize);
break; // end of processing this frame
}
if (pHeader->Frag == 0) // First or Only fragment
{
PUCHAR pRemovedLLCSNAP;
CONVERT_TO_802_3(Header802_3, pDA, pSA, pData, DataSize, pRemovedLLCSNAP);
pAd->FragFrame.Flags &= 0xFFFFFFFE;
// Firt Fragment & LLC/SNAP been removed. Keep the removed LLC/SNAP for later on
// TKIP MIC verification.
if (pHeader->FC.MoreFrag && pRemovedLLCSNAP)
{
NdisMoveMemory(pAd->FragFrame.Header_LLC, pRemovedLLCSNAP, LENGTH_802_1_H);
pAd->FragFrame.Flags |= 0x01;
}
// One & The only fragment
if (pHeader->FC.MoreFrag == FALSE)
{
if ((pHeader->FC.Order == 1) && (Msdu2Size > 0)) // this is an aggregation
{
USHORT Payload1Size, Payload2Size;
PUCHAR pData2;
pAd->RalinkCounters.OneSecRxAggregationCount ++;
Payload1Size = DataSize - Msdu2Size;
Payload2Size = Msdu2Size - LENGTH_802_3;
REPORT_ETHERNET_FRAME_TO_LLC(pAd, Header802_3, pData, Payload1Size, pAd->net_dev);
DBGPRINT(RT_DEBUG_TRACE, "!!! report segregated MSDU1 to LLC (len=%d, proto=%02x:%02x) %02x:%02x:%02x:%02x-%02x:%02x:%02x:%02x\n",
LENGTH_802_3+Payload1Size, Header802_3[12], Header802_3[13],
*pData, *(pData+1),*(pData+2),*(pData+3),*(pData+4),*(pData+5),*(pData+6),*(pData+7));
pData2 = pData + Payload1Size + LENGTH_802_3;
REPORT_ETHERNET_FRAME_TO_LLC(pAd, pData + Payload1Size, pData2, Payload2Size, pAd->net_dev);
DBGPRINT_RAW(RT_DEBUG_INFO, "!!! report segregated MSDU2 to LLC (len=%d, proto=%02x:%02x) %02x:%02x:%02x:%02x-%02x:%02x:%02x:%02x\n",
LENGTH_802_3+Payload2Size, *(pData2 -2), *(pData2 - 1),
*pData2, *(pData2+1),*(pData2+2),*(pData2+3),*(pData2+4),*(pData2+5),*(pData2+6),*(pData2+7));
}
else
{
REPORT_ETHERNET_FRAME_TO_LLC(pAd, Header802_3, pData, DataSize, pAd->net_dev);
DBGPRINT_RAW(RT_DEBUG_INFO, "!!! report DATA (no frag) to LLC (len=%d, proto=%02x:%02x) %02x:%02x:%02x:%02x-%02x:%02x:%02x:%02x\n",
DataSize, Header802_3[12], Header802_3[13],
*pData, *(pData+1),*(pData+2),*(pData+3),*(pData+4),*(pData+5),*(pData+6),*(pData+7));
}
}
// First fragment - record the 802.3 header and frame body
else
{
NdisMoveMemory(&pAd->FragFrame.Buffer[LENGTH_802_3], pData, DataSize);
NdisMoveMemory(pAd->FragFrame.Header802_3, Header802_3, LENGTH_802_3);
pAd->FragFrame.RxSize = DataSize;
pAd->FragFrame.Sequence = pHeader->Sequence;
pAd->FragFrame.LastFrag = pHeader->Frag; // Should be 0
}
} //First or Only fragment
// Middle & End of fragment burst fragments
else
{
// No LLC-SNAP header in except the first fragment frame
if ((pHeader->Sequence != pAd->FragFrame.Sequence) ||
(pHeader->Frag != (pAd->FragFrame.LastFrag + 1)))
{
// Fragment is not the same sequence or out of fragment number order
// Clear Fragment frame contents
NdisZeroMemory(&pAd->FragFrame, sizeof(FRAGMENT_FRAME));
break;
}
else if ((pAd->FragFrame.RxSize + DataSize) > MAX_FRAME_SIZE)
{
// Fragment frame is too large, it exeeds the maximum frame size.
// Clear Fragment frame contents
NdisZeroMemory(&pAd->FragFrame, sizeof(FRAGMENT_FRAME));
break; // give up this frame
}
// concatenate this fragment into the re-assembly buffer
NdisMoveMemory(&pAd->FragFrame.Buffer[LENGTH_802_3 + pAd->FragFrame.RxSize], pData, DataSize);
pAd->FragFrame.RxSize += DataSize;
pAd->FragFrame.LastFrag = pHeader->Frag; // Update fragment number
// Last fragment
if (pHeader->FC.MoreFrag == FALSE)
{
// For TKIP frame, calculate the MIC value
if (pRxD->CipherAlg == CIPHER_TKIP)
{
pWpaKey = &pAd->SharedKey[pRxD->KeyIndex];
// Minus MIC length
pAd->FragFrame.RxSize -= 8;
if (pAd->FragFrame.Flags & 0x00000001)
{
// originally there's an LLC/SNAP field in the first fragment
// but been removed in re-assembly buffer. here we have to include
// this LLC/SNAP field upon calculating TKIP MIC
// pData = pAd->FragFrame.Header_LLC;
// Copy LLC data to the position in front of real data for MIC calculation
NdisMoveMemory(&pAd->FragFrame.Buffer[LENGTH_802_3 - LENGTH_802_1_H],
pAd->FragFrame.Header_LLC,
LENGTH_802_1_H);
pData = (PUCHAR) &pAd->FragFrame.Buffer[LENGTH_802_3 - LENGTH_802_1_H];
DataSize = (USHORT)pAd->FragFrame.RxSize + LENGTH_802_1_H;
}
else
{
pData = (PUCHAR) &pAd->FragFrame.Buffer[LENGTH_802_3];
DataSize = (USHORT)pAd->FragFrame.RxSize;
}
if (RTMPTkipCompareMICValue(
pAd,
pData,
pDA,
pSA,
pWpaKey->RxMic,
DataSize) == FALSE)
{
DBGPRINT_RAW(RT_DEBUG_ERROR,"Rx MIC Value error 2\n");
RTMPReportMicError(pAd, pWpaKey);
break; // give up this frame
}
}
pData = &pAd->FragFrame.Buffer[LENGTH_802_3];
REPORT_ETHERNET_FRAME_TO_LLC(pAd, pAd->FragFrame.Header802_3, pData, pAd->FragFrame.RxSize, pAd->net_dev);
DBGPRINT(RT_DEBUG_TRACE, "!!! report DATA (fragmented) to LLC (len=%d) !!!\n", pAd->FragFrame.RxSize);
}
}
}
} // FC.Type == BTYPE_DATA
//
// CASE II. receive a MGMT frame
//
else if (pHeader->FC.Type == BTYPE_MGMT)
{
REPORT_MGMT_FRAME_TO_MLME(pAd, pHeader, pRxD->DataByteCnt, pRxD->PlcpRssi, pRxD->PlcpSignal);
break; // end of processing this frame
}
//
// CASE III. receive a CNTL frame
//
else if (pHeader->FC.Type == BTYPE_CNTL)
break; // give up this frame
//
// CASE IV. receive a frame of invalid type
//
else
break; // give up this fra
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -