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

📄 rtusb_data.c

📁 经过修改的在uClinux2.6上正常运行的ralink rt2571芯片组的设备驱动程序.
💻 C
📖 第 1 页 / 共 5 页
字号:
	Return Value:
		None

	Note:
	
	========================================================================
*/
#ifdef BIG_ENDIAN	
static inline
#endif
NDIS_STATUS RTUSBHardTransmit(
	IN	PRTMP_ADAPTER	pAd,
	IN	struct sk_buff	*pSkb,
	IN	UCHAR			NumberRequired,
	IN	UCHAR			QueIdx)
{
	UINT			LengthQosPAD =0;
	UINT			BytesCopied;
	UINT			TxSize;
	UINT			FreeMpduSize;
	UINT			SrcRemainingBytes;
	USHORT			Protocol;
	UCHAR			FrameGap;
	HEADER_802_11	Header_802_11;
	PHEADER_802_11	pHeader80211;	
	PUCHAR			pDest;
//	PUCHAR			pSrc;
	PTX_CONTEXT		pTxContext;
	PTXD_STRUC		pTxD;
#ifdef BIG_ENDIAN				
	PTXD_STRUC		pDestTxD;
	TXD_STRUC		TxD;
#endif
//	PURB			pUrb;
	BOOLEAN			StartOfFrame;
	BOOLEAN			bEAPOLFrame;
	ULONG			Iv16;
	ULONG			Iv32;
	BOOLEAN			MICFrag;
//	PCIPHER_KEY		pWpaKey = NULL;
	BOOLEAN			Cipher;
	ULONG			TransferBufferLength;
	USHORT			AckDuration = 0;
	USHORT			EncryptionOverhead = 0;
	UCHAR			CipherAlg;
	BOOLEAN			bAckRequired;
	UCHAR			RetryMode = SHORT_RETRY;
	UCHAR			UserPriority;
	UCHAR			MpduRequired, RtsRequired;
	UCHAR			TxRate;		
	PCIPHER_KEY		pKey = NULL ;
	PUCHAR			pSrcBufVA = NULL;
	ULONG			SrcBufLen;
	PUCHAR			pExtraLlcSnapEncap = NULL; // NULL: no extra LLC/SNAP is required
	UCHAR			KeyIdx;
	PUCHAR			pWirelessPacket;
	ULONG			NextMpduSize;
	BOOLEAN			bRTS_CTSFrame = FALSE;


    if ((pAd->PortCfg.bIEEE80211H == 1) && (pAd->PortCfg.RadarDetect.RDMode != RD_NORMAL_MODE))
    {
        DBGPRINT(RT_DEBUG_INFO,"RTUSBHardTransmit --> radar detect not in normal mode !!!\n");
        return (NDIS_STATUS_FAILURE);
    }

	TxRate		 = RTMP_GET_PACKET_TXRATE(pSkb);
	MpduRequired = RTMP_GET_PACKET_FRAGMENTS(pSkb);
	RtsRequired  = RTMP_GET_PACKET_RTS(pSkb);
	UserPriority = RTMP_GET_PACKET_UP(pSkb);
	
	//
	// Prepare packet information structure which will be query for buffer descriptor
	//
	pSrcBufVA = (PVOID)pSkb->data;
	SrcBufLen = pSkb->len;

	// Check for virtual address allocation, it might fail !!!
	if (pSrcBufVA == NULL)
	{
		DBGPRINT_RAW(RT_DEBUG_TRACE, "pSrcBufVA == NULL\n");
		return(NDIS_STATUS_RESOURCES);
	}
	if (SrcBufLen < 14)
	{
		DBGPRINT_RAW(RT_DEBUG_ERROR, "RTUSBHardTransmit --> Skb buffer error !!!\n");
		return (NDIS_STATUS_FAILURE);
	}

	//
	// If DHCP datagram or ARP datagram , we need to send it as Low rates.
	//
	if (pAd->PortCfg.Channel <= 14)
	{
		//
		// Case 802.11 b/g
		// basic channel means that we can use CCKM's low rate as RATE_1.
		//		
		if ((TxRate != RATE_1) && RTMPCheckDHCPFrame(pAd, pSkb))
			TxRate = RATE_1;
	}
	else
	{
		//
		// Case 802.11a
		// We must used OFDM's low rate as RATE_6, note RATE_1 is not allow
		// Only OFDM support on Channel > 14
		//
		if ((TxRate != RATE_6) && RTMPCheckDHCPFrame(pAd, pSkb))
			TxRate = RATE_6;
	}
	
	// ------------------------------------------
	// STEP 0.1 Add 802.1x protocol check.
	// ------------------------------------------
	// For non-WPA network, 802.1x message should not encrypt even privacy is on.
	if (NdisEqualMemory(EAPOL, pSrcBufVA + 12, 2))
	{
		bEAPOLFrame = TRUE;
		if (pAd->PortCfg.MicErrCnt >= 2)
			pAd->PortCfg.MicErrCnt++;
	}
	else
		bEAPOLFrame = FALSE;

	//
	// WPA 802.1x secured port control - drop all non-802.1x frame before port secured
	//
	if (((pAd->PortCfg.AuthMode == Ndis802_11AuthModeWPA)	 || 
		 (pAd->PortCfg.AuthMode == Ndis802_11AuthModeWPAPSK) ||
		 (pAd->PortCfg.AuthMode == Ndis802_11AuthModeWPA2)	 ||
		 (pAd->PortCfg.AuthMode == Ndis802_11AuthModeWPA2PSK)
#if WPA_SUPPLICANT_SUPPORT
		  || (pAd->PortCfg.IEEE8021X == TRUE)		
#endif 		         
         ) &&
		((pAd->PortCfg.PortSecured == WPA_802_1X_PORT_NOT_SECURED) || (pAd->PortCfg.MicErrCnt >= 2)) &&
		(bEAPOLFrame == FALSE))
	{
		DBGPRINT_RAW(RT_DEBUG_INFO, "RTUSBHardTransmit --> Drop packet before port secured !!!\n");
		return (NDIS_STATUS_FAILURE);
	}
	
	if (*pSrcBufVA & 0x01) // Multicast or Broadcast
	{
		bAckRequired = FALSE;
		INC_COUNTER64(pAd->WlanCounters.MulticastTransmittedFrameCount);
		Cipher = pAd->PortCfg.GroupCipher; // Cipher for Multicast or Broadcast
	}
	else
	{
		bAckRequired = TRUE;
		Cipher = pAd->PortCfg.PairCipher; // Cipher for Unicast
	}

	// 1. traditional TX burst
	if (pAd->PortCfg.bEnableTxBurst && (pAd->Sequence & 0x7))
		FrameGap = IFS_SIFS;  
	// 2. frame belonging to AC that has non-zero TXOP
	else if (pAd->PortCfg.APEdcaParm.bValid && pAd->PortCfg.APEdcaParm.Txop[QueIdx])
		FrameGap = IFS_SIFS;
	// 3. otherwise, always BACKOFF before transmission
	else
		FrameGap = IFS_BACKOFF;		// Default frame gap mode

	Protocol = *(pSrcBufVA + 12) * 256 + *(pSrcBufVA + 13);
	// if orginal Ethernet frame contains no LLC/SNAP, then an extra LLC/SNAP encap is required 
	if (Protocol > 1500)
	{
		pExtraLlcSnapEncap = SNAP_802_1H;
		if (NdisEqualMemory(IPX, pSrcBufVA + 12, 2) || 
			NdisEqualMemory(APPLE_TALK, pSrcBufVA + 12, 2))
		{
			pExtraLlcSnapEncap = SNAP_BRIDGE_TUNNEL;
		}
	}
	else
		pExtraLlcSnapEncap = NULL;


    // Update software power save state
	OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_DOZE);
	pAd->PortCfg.Psm = PWR_ACTIVE;
	
	// -----------------------------------------------------------------
	// STEP 2. MAKE A COMMON 802.11 HEADER SHARED BY ENTIRE FRAGMENT BURST.
	// -----------------------------------------------------------------

	pAd->Sequence = ((pAd->Sequence) + 1) & (MAX_SEQ_NUMBER);
	MAKE_802_11_HEADER(pAd, Header_802_11, pSrcBufVA, pAd->Sequence);
#if 0
	if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_WMM_INUSED))
		Header_802_11.FC.SubType = SUBTYPE_QDATA;
#endif

	// --------------------------------------------------------
	// STEP 3. FIND ENCRYPT KEY AND DECIDE CIPHER ALGORITHM
	//		Find the WPA key, either Group or Pairwise Key
	//		LEAP + TKIP also use WPA key.
	// --------------------------------------------------------
	// Decide WEP bit and cipher suite to be used. Same cipher suite should be used for whole fragment burst
	// In Cisco CCX 2.0 Leap Authentication
	//		   WepStatus is Ndis802_11Encryption1Enabled but the key will use PairwiseKey
	//		   Instead of the SharedKey, SharedKey Length may be Zero.
	KeyIdx = 0xff;
	if (bEAPOLFrame)
	{
        ASSERT(pAd->SharedKey[0].CipherAlg <= CIPHER_CKIP128);
        if ((pAd->SharedKey[0].CipherAlg) &&
            (pAd->SharedKey[0].KeyLen) )
        {
            CipherAlg = pAd->SharedKey[0].CipherAlg;
            KeyIdx = 0;
        }
    }
	else if (Cipher == Ndis802_11Encryption1Enabled)
	{
			// standard WEP64 or WEP128
		KeyIdx = pAd->PortCfg.DefaultKeyId;
	}
	else if ((Cipher == Ndis802_11Encryption2Enabled) ||
			 (Cipher == Ndis802_11Encryption3Enabled))
	{
		if (Header_802_11.Addr1[0] & 0x01) // multicast
			KeyIdx = pAd->PortCfg.DefaultKeyId;
		else if (pAd->SharedKey[0].KeyLen)
			KeyIdx = 0;
		else
			KeyIdx = pAd->PortCfg.DefaultKeyId;
	}

	if (KeyIdx == 0xff)
		CipherAlg = CIPHER_NONE;
	else if (pAd->SharedKey[KeyIdx].KeyLen == 0)
		CipherAlg = CIPHER_NONE;
	else
	{
		Header_802_11.FC.Wep = 1;
		CipherAlg = pAd->SharedKey[KeyIdx].CipherAlg;
		pKey = &pAd->SharedKey[KeyIdx];
	}

	DBGPRINT(RT_DEBUG_INFO,"RTUSBHardTransmit(bEAP=%d) - %s key#%d, KeyLen=%d\n", 
		bEAPOLFrame, CipherName[CipherAlg], KeyIdx, pAd->SharedKey[KeyIdx].KeyLen);


	// STEP 3.1 if TKIP is used and fragmentation is required. Driver has to
	//			append TKIP MIC at tail of the scatter buffer (This must be the
	//			ONLY scatter buffer in the skb buffer). 
	//			MAC ASIC will only perform IV/EIV/ICV insertion but no TKIP MIC
	if ((MpduRequired > 1) && (CipherAlg == CIPHER_TKIP))
	{
		pSkb->len += 8;
		CipherAlg = CIPHER_TKIP_NO_MIC;	
	}

	// ----------------------------------------------------------------
	// STEP 4. Make RTS frame or CTS-to-self frame if required
	// ----------------------------------------------------------------

	//
	// calcuate the overhead bytes that encryption algorithm may add. This
	// affects the calculate of "duration" field
	//
	if ((CipherAlg == CIPHER_WEP64) || (CipherAlg == CIPHER_WEP128)) 
		EncryptionOverhead = 8; //WEP: IV[4] + ICV[4];
	else if (CipherAlg == CIPHER_TKIP_NO_MIC)
		EncryptionOverhead = 12;//TKIP: IV[4] + EIV[4] + ICV[4], MIC will be added to TotalPacketLength
	else if (CipherAlg == CIPHER_TKIP)
		EncryptionOverhead = 20;//TKIP: IV[4] + EIV[4] + ICV[4] + MIC[8]
	else if (CipherAlg == CIPHER_AES)
		EncryptionOverhead = 16;	// AES: IV[4] + EIV[4] + MIC[8]
	else
		EncryptionOverhead = 0;

	// decide how much time an ACK/CTS frame will consume in the air
	AckDuration = RTMPCalcDuration(pAd, pAd->PortCfg.ExpectedACKRate[TxRate], 14);

	// If fragment required, MPDU size is maximum fragment size
	// Else, MPDU size should be frame with 802.11 header & CRC
	if (MpduRequired > 1)
		NextMpduSize = pAd->PortCfg.FragmentThreshold;
	else
	{
		NextMpduSize = pSkb->len + LENGTH_802_11 + LENGTH_CRC - LENGTH_802_3;
		if (pExtraLlcSnapEncap)
			NextMpduSize += LENGTH_802_1_H;
	}

	if (RtsRequired || OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_RTS_PROTECTION_ENABLE))
	{
		RTMPSendRTSCTSFrame(pAd, 
							Header_802_11.Addr1, 
							NextMpduSize + EncryptionOverhead, 
							TxRate,
							pAd->PortCfg.RtsRate, 
							AckDuration,
							QueIdx,
							FrameGap,
							SUBTYPE_RTS);
		
		// RTS/CTS-protected frame should use LONG_RETRY (=4) and SIFS
		RetryMode = LONG_RETRY;
		FrameGap = IFS_SIFS;
		bRTS_CTSFrame = TRUE;
		
		if (RtsRequired)
			NumberRequired--;
	}
	else if ((pAd->PortCfg.TxRate >= RATE_FIRST_OFDM_RATE) && OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_BG_PROTECTION_INUSED))
	{
		RTMPSendRTSCTSFrame(pAd, 
							Header_802_11.Addr1, 
							NextMpduSize + EncryptionOverhead, 
							TxRate,
							pAd->PortCfg.RtsRate, 
							AckDuration,
							QueIdx,
							FrameGap,
							SUBTYPE_CTS);
		
		// RTS/CTS-protected frame should use LONG_RETRY (=4) and SIFS
		RetryMode = LONG_RETRY;
		FrameGap = IFS_SIFS;
		bRTS_CTSFrame = TRUE;
	}

	// --------------------------------------------------------
	// STEP 5. START MAKING MPDU(s)
	//		Start Copy Ndis Packet into Ring buffer.
	//		For frame required more than one ring buffer (fragment), all ring buffers
	//		have to be filled before kicking start tx bit.
	//		Make sure TX ring resource won't be used by other threads
	// --------------------------------------------------------
	SrcRemainingBytes = pSkb->len - LENGTH_802_3;
	SrcBufLen		 -= LENGTH_802_3;  // skip 802.3 header


	StartOfFrame = TRUE;
	MICFrag = FALSE;	// Flag to indicate MIC shall spread into two MPDUs

	// Start Copy Ndis Packet into Ring buffer.
	// For frame required more than one ring buffer (fragment), all ring buffers
	// have to be filled before kicking start tx bit.
	do
	{
		//
		// STEP 5.1 Get the Tx Ring descriptor & Dma Buffer address
		//
		pTxContext	= &pAd->TxContext[QueIdx][pAd->NextTxIndex[QueIdx]];
		
		if ((pTxContext->bWaitingBulkOut == TRUE) || (pTxContext->InUse == TRUE) ||
			(pAd->TxRingTotalNumber[QueIdx] >= TX_RING_SIZE))
		{
			DBGPRINT_ERR("RTUSBHardTransmit: TX RING full\n");
			pAd->RalinkCounters.TxRingErrCount++;
			return (NDIS_STATUS_RESOURCES);
		}		
		pTxContext->InUse	= TRUE;		
		
		// Increase & maintain Tx Ring Index
		pAd->NextTxIndex[QueIdx]++;
		if (pAd->NextTxIndex[QueIdx] >= TX_RING_SIZE)
		{
			pAd->NextTxIndex[QueIdx] = 0;
		}

#ifndef BIG_ENDIAN
		pTxD  = (PTXD_STRUC) &pTxContext->TransferBuffer->TxDesc;
#else
		pDestTxD = (PTXD_STRUC) &pTxContext->TransferBuffer->TxDesc;
		TxD = *pDestTxD;
		pTxD = &TxD;
		RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD);
#endif			
		NdisZeroMemory(pTxD, sizeof(TXD_STRUC));
		pWirelessPacket = pTxContext->TransferBuffer->WirelessPacket;

		//
		// STEP 5.2 PUT IVOFFSET, IV, EIV INTO TXD
		//
		pTxD->IvOffset	= LENGTH_802_11;

#if 0
		if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_WMM_INUSED))
			pTxD->IvOffset += 2;  // add QOS CONTROL bytes
#endif
	
		if ((CipherAlg == CIPHER_WEP64) || (CipherAlg == CIPHER_WEP128))
		{
			PUCHAR pTmp;
			pTmp = (PUCHAR) &pTxD->Iv;
			*pTmp		= RandomByte(pAd);
			*(pTmp + 1) = RandomByte(pAd);
			*(pTmp + 2) = RandomByte(pAd);
			*(pTmp + 3) = (KeyIdx << 6);
		}
		else if ((CipherAlg == CIPHER_TKIP) || (CipherAlg == CIPHER_TKIP_NO_MIC))
		{
			RTMPInitTkipEngine(
				pAd,
				pKey->Key,
				KeyIdx,		// This might cause problem when using peer key
				Header_802_11.Addr2,
				pKey->TxMic,
				pKey->TxTsc,
				&Iv16,
				&Iv32);
			
			NdisMoveMemory(&pTxD->Iv, &Iv16, 4);   // Copy IV
			NdisMoveMemory(&pTxD->Eiv, &Iv32, 4);  // Copy EIV
			INC_TX_TSC(pKey->TxTsc);			   // Increase TxTsc for next transmission
		}
		else if (CipherAlg == CIPHER_AES)
		{
			PUCHAR	pTmp;
			pTmp = (PUCHAR) &Iv16;
			*pTmp		= pKey->TxTsc[0];
			*(pTmp + 1) = pKey->TxTsc[1];
			*(pTmp + 2) = 0;
			*(pTmp + 3) = (pAd->PortCfg.DefaultKeyId << 6) | 0x20;
			Iv32 = *(PULONG)(&pKey->TxTsc[2]);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -