📄 rtusb_data.c
字号:
NdisReleaseSpinLock(&pAd->SendTxWaitQueueLock[BulkOutPipeId], IrqFlags);
Status = RTUSBHardTransmit(pAd, pSkb, FragmentRequired, QueIdx);
// Acquire the resource again, snice we may need to process it in this while-loop.
NdisAcquireSpinLock(&pAd->SendTxWaitQueueLock[BulkOutPipeId], IrqFlags);
if (Status == NDIS_STATUS_FAILURE)
{
// Packet failed due to various Ndis Packet error
RTUSBFreeSkbBuffer(pSkb);
break;
}
else if (Status == NDIS_STATUS_RESOURCES)
{
// Not enough free tx ring, it might happen due to free descriptor inquery might be not correct
// It also might change to NDIS_STATUS_FAILURE to simply drop the frame
// Put the frame back into head of queue
InsertHeadQueue(pQueue, pSkb);
break;
}
Count++;
}
else
{
DBGPRINT(RT_DEBUG_INFO,"--RTMPDeQueuePacket %d queue full !! TxRingTotalNumber= %d !! FragmentRequired=%d !!\n", BulkOutPipeId, (INT)pAd->TxRingTotalNumber[BulkOutPipeId], FragmentRequired);
InsertHeadQueue(pQueue, pSkb);
pAd->PrivateInfo.TxRingFullCnt++;
break;
}
}
// Release TxSwQueue0 resources
NdisReleaseSpinLock(&pAd->SendTxWaitQueueLock[BulkOutPipeId], IrqFlags);
NdisAcquireSpinLock(&pAd->DeQueueLock[BulkOutPipeId], IrqFlags);
pAd->DeQueueRunning[BulkOutPipeId] = FALSE;
NdisReleaseSpinLock(&pAd->DeQueueLock[BulkOutPipeId], 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;
struct net_device *net_dev;
DBGPRINT_RAW(RT_DEBUG_INFO, "--->RTUSBRxPacket\n");
pRxContext = (PRX_CONTEXT)pUrb->context;
pAd = pRxContext->pAd;
net_dev = pAd->net_dev;
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)
{
// 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;
}
pAd->BulkInDataOneSecCount++;
// 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;
}
// 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 (RTMPEqualMemory(EAPOL, pData + 6, 2))
EAPOLFrame = TRUE;
else
EAPOLFrame = FALSE;
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;
}
// 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);
//#if WPA_SUPPLICANT_SUPPORT
if (pAd->PortCfg.WPA_Supplicant == TRUE)
{
// All EAPoL frames have to pass to upper layer (ex. WPA_SUPPLICANT daemon)
// TBD : process fragmented EAPol frames
if(NdisEqualMemory(EAPOL_LLC_SNAP, pData, LENGTH_802_1_H))
{
PUCHAR pRemovedLLCSNAP;
int success = 0;
// In 802.1x mode, if the received frame is EAP-SUCCESS packet, turn on the PortSecured variable
if ( pAd->PortCfg.IEEE8021X == TRUE
&& (EAP_CODE_SUCCESS == RTMPCheckWPAframeForEapCode(pAd, pData, DataSize, LENGTH_802_1_H)))
{
DBGPRINT_RAW(RT_DEBUG_TRACE, "Receive EAP-SUCCESS Packet\n");
pAd->PortCfg.PortSecured = WPA_802_1X_PORT_SECURED;
success = 1;
}
// 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, net_dev);
DBGPRINT_RAW(RT_DEBUG_TRACE, "!!! report EAPoL DATA to LLC (len=%d) !!!\n", DataSize);
if(success)
{
// For static wep mode, need to set wep key to Asic again
if(pAd->PortCfg.IEEE8021x_required_keys == 0)
{
int idx;
idx = pAd->PortCfg.DefaultKeyId;
for (idx=0; idx < 4; idx++)
{
DBGPRINT_RAW(RT_DEBUG_TRACE, "Set WEP key to Asic again =>\n");
if(pAd->PortCfg.DesireSharedKey[idx].KeyLen != 0)
{
union
{
char buf[sizeof(NDIS_802_11_WEP)+MAX_LEN_OF_KEY- 1];
NDIS_802_11_WEP keyinfo;
} WepKey;
int len;
NdisZeroMemory(&WepKey, sizeof(WepKey));
len =pAd->PortCfg.DesireSharedKey[idx].KeyLen;
NdisMoveMemory(WepKey.keyinfo.KeyMaterial,
pAd->PortCfg.DesireSharedKey[idx].Key,
pAd->PortCfg.DesireSharedKey[idx].KeyLen);
WepKey.keyinfo.KeyIndex = 0x80000000 + idx;
WepKey.keyinfo.KeyLength = len;
pAd->SharedKey[idx].KeyLen =(UCHAR) (len <= WEP_SMALL_KEY_LEN ? WEP_SMALL_KEY_LEN : WEP_LARGE_KEY_LEN);
// need to enqueue cmd to thread
RTUSBEnqueueCmdFromNdis(pAd, OID_802_11_ADD_WEP, TRUE, &WepKey, sizeof(WepKey.keyinfo) + len - 1);
}
}
}
}
break;
}
}
else
{
//#else
// 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
}
//#endif
}
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, H
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -