⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 rtusb_data.c

📁 D-link 无线usb网卡的Linux无线网卡驱动程序
💻 C
📖 第 1 页 / 共 5 页
字号:
	// 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 + -