📄 rtusb_data.c
字号:
/* *************************************************************************** * Ralink Tech Inc. * 4F, No. 2 Technology 5th Rd. * Science-based Industrial Park * Hsin-chu, Taiwan, R.O.C. * * (c) Copyright 2002-2006, Ralink Technology, Inc. * * All rights reserved. Ralink's source code is an unpublished work and the * use of a copyright notice does not imply otherwise. This source code * contains confidential trade secret material of Ralink Tech. Any attemp * or participation in deciphering, decoding, reverse engineering or in any * way altering the source code is stricitly prohibited, unless the prior * written consent of Ralink Technology, Inc. is obtained. *************************************************************************** Module Name: rtmp_data.c Abstract: Ralink USB driver Tx/Rx functions Revision History: Who When What -------- ---------- ----------------------------------------------*/#include "rt_config.h"#include <net/iw_handler.h>extern UCHAR Phy11BGNextRateUpward[]; // defined in mlme.cUCHAR SNAP_802_1H[] = {0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00};UCHAR SNAP_BRIDGE_TUNNEL[] = {0xaa, 0xaa, 0x03, 0x00, 0x00, 0xf8};UCHAR EAPOL_LLC_SNAP[]= {0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00, 0x88, 0x8e};UCHAR EAPOL[] = {0x88, 0x8e};UCHAR IPX[] = {0x81, 0x37};UCHAR APPLE_TALK[] = {0x80, 0xf3};UCHAR RateIdToPlcpSignal[12] = { 0, /* RATE_1 */ 1, /* RATE_2 */ 2, /* RATE_5_5 */ 3, /* RATE_11 */ // see BBP spec 11, /* RATE_6 */ 15, /* RATE_9 */ 10, /* RATE_12 */ 14, /* RATE_18 */ // see IEEE802.11a-1999 p.14 9, /* RATE_24 */ 13, /* RATE_36 */ 8, /* RATE_48 */ 12 /* RATE_54 */ }; // see IEEE802.11a-1999 p.14UCHAR OfdmSignalToRateId[16] = { RATE_54, RATE_54, RATE_54, RATE_54, // OFDM PLCP Signal = 0, 1, 2, 3 respectively RATE_54, RATE_54, RATE_54, RATE_54, // OFDM PLCP Signal = 4, 5, 6, 7 respectively RATE_48, RATE_24, RATE_12, RATE_6, // OFDM PLCP Signal = 8, 9, 10, 11 respectively RATE_54, RATE_36, RATE_18, RATE_9, // OFDM PLCP Signal = 12, 13, 14, 15 respectively};UCHAR default_cwmin[]={CW_MIN_IN_BITS, CW_MIN_IN_BITS, CW_MIN_IN_BITS-1, CW_MIN_IN_BITS-2};UCHAR default_cwmax[]={CW_MAX_IN_BITS, CW_MAX_IN_BITS, CW_MIN_IN_BITS, CW_MIN_IN_BITS-1};UCHAR default_sta_aifsn[]={3,7,2,2};UCHAR MapUserPriorityToAccessCategory[8] = {QID_AC_BE, QID_AC_BK, QID_AC_BK, QID_AC_BE, QID_AC_VI, QID_AC_VI, QID_AC_VO, QID_AC_VO}; // Macro for rx indicationVOID REPORT_ETHERNET_FRAME_TO_LLC( IN PRTMP_ADAPTER pAd, IN PUCHAR p8023hdr, IN PUCHAR pData, IN ULONG DataSize, IN struct net_device *net_dev){ struct sk_buff *pSkb;#ifdef RTMP_EMBEDDED if ((pSkb = __dev_alloc_skb(DataSize + LENGTH_802_3 + 2, GFP_DMA|GFP_ATOMIC)) != NULL)#else if ((pSkb = dev_alloc_skb(DataSize + LENGTH_802_3 + 2)) != NULL)#endif { pSkb->dev = net_dev; skb_reserve(pSkb, 2); // 16 byte align the IP header memcpy(skb_put(pSkb, LENGTH_802_3), p8023hdr, LENGTH_802_3); memcpy(skb_put(pSkb, DataSize), pData, DataSize); pSkb->protocol = eth_type_trans(pSkb, net_dev); netif_rx(pSkb); pAd->net_dev->last_rx = jiffies; pAd->stats.rx_packets++; pAd->Counters8023.GoodReceives++; }}NDIS_STATUS RTMPDecryptPktBySoftware( IN PRTMP_ADAPTER pAd, IN PUCHAR pData, IN PRXD_STRUC pRxD){ UCHAR KeyIdx = pAd->PortCfg.DefaultKeyId; DBGPRINT(RT_DEBUG_INFO, "RTMPDecryptPktBySoftware ==>\n"); // handle WEP decryption if(pAd->PortCfg.WepStatus == Ndis802_11WEPEnabled) { UCHAR *pPayload = (UCHAR *)pData + LENGTH_802_11; if (RTMPDecryptData(pAd, pPayload, pRxD->DataByteCnt - LENGTH_802_11) == FALSE) { DBGPRINT(RT_DEBUG_ERROR, "ERROR : Software decrypt WEP data fails.\n"); return (NDIS_STATUS_FAILURE); } else { pRxD->DataByteCnt -= 8; //Minus IV[4] & ICV[4] pRxD->CipherAlg = CIPHER_WEP64; } DBGPRINT(RT_DEBUG_INFO, "RTMPDecryptData WEP data Complete \n"); } // handle TKIP decryption else if(pAd->PortCfg.WepStatus == Ndis802_11Encryption2Enabled) { if (RTMPSoftDecryptTKIP(pAd, pData, pRxD->DataByteCnt, 0, &pAd->SharedKey[KeyIdx])) { DBGPRINT(RT_DEBUG_INFO, "RTMPSoftDecryptTKIP Complete \n"); pRxD->DataByteCnt -= 20; //Minus 8 bytes MIC, 8 bytes IV/EIV, 4 bytes ICV pRxD->CipherAlg = CIPHER_TKIP; } else { DBGPRINT(RT_DEBUG_ERROR, "ERROR : RTMPSoftDecryptTKIP Failed\n"); return (NDIS_STATUS_FAILURE); } } // handle AES decryption else if(pAd->PortCfg.WepStatus == Ndis802_11Encryption3Enabled) { if (RTMPSoftDecryptAES(pAd, pData, pRxD->DataByteCnt, &pAd->SharedKey[KeyIdx])) { DBGPRINT(RT_DEBUG_INFO, "RTMPSoftDecryptAES Complete \n"); pRxD->DataByteCnt -= 16; //8 bytes MIC, 8 bytes IV/EIV (CCMP Header) pRxD->CipherAlg = CIPHER_AES; } else { DBGPRINT(RT_DEBUG_ERROR, "ERROR : RTMPSoftDecryptAES Failed\n"); return (NDIS_STATUS_FAILURE); } } else { return (NDIS_STATUS_FAILURE); } return (NDIS_STATUS_SUCCESS);}// Enqueue this frame to MLME engine// We need to enqueue the whole frame because MLME need to pass data type// information from 802.11 header// edit by johnli, fix WPAPSK/WPA2PSK bugs for receiving EAPoL fragmentation packets/* #define REPORT_MGMT_FRAME_TO_MLME(_pAd, _pFrame, _FrameSize, _Rssi, _PlcpSignal) \{ \ MlmeEnqueueForRecv(_pAd, (UCHAR)_Rssi, _FrameSize, _pFrame, (UCHAR)_PlcpSignal); \}*/#define REPORT_MGMT_FRAME_TO_MLME(_pAd, _p80211hdr, _pFrame, _FrameSize, _Rssi, _PlcpSignal) \{ \ MlmeEnqueueForRecv(_pAd, (PFRAME_802_11)_p80211hdr, (UCHAR)_Rssi, _FrameSize, _pFrame, (UCHAR)_PlcpSignal); \}// end johnli// NOTE: we do have an assumption here, that Byte0 and Byte1 always reasid at the same // scatter gather bufferNDIS_STATUS Sniff2BytesFromNdisBuffer( IN struct sk_buff *pFirstSkb, IN UCHAR DesiredOffset, OUT PUCHAR pByte0, OUT PUCHAR pByte1){ PUCHAR pBufferVA; ULONG BufferLen, AccumulateBufferLen, BufferBeginOffset; pBufferVA = (PVOID)pFirstSkb->data; BufferLen = pFirstSkb->len; BufferBeginOffset = 0; AccumulateBufferLen = BufferLen; *pByte0 = *(PUCHAR)(pBufferVA + DesiredOffset - BufferBeginOffset); *pByte1 = *(PUCHAR)(pBufferVA + DesiredOffset - BufferBeginOffset + 1); return NDIS_STATUS_SUCCESS;}/* ======================================================================== Routine Description: This routine classifies outgoing frames into several AC (Access Category) and enqueue them into corresponding s/w waiting queues. Arguments: pAd Pointer to our adapter pPacket Pointer to send packet Return Value: None Note: ========================================================================*/NDIS_STATUS RTMPSendPacket( IN PRTMP_ADAPTER pAd, IN struct sk_buff *pSkb){ PUCHAR pSrcBufVA; UINT AllowFragSize; UCHAR NumberOfFrag; UCHAR RTSRequired; UCHAR QueIdx, UserPriority; NDIS_STATUS Status = NDIS_STATUS_SUCCESS; PQUEUE_HEADER pTxQueue; UCHAR PsMode; unsigned long IrqFlags; DBGPRINT(RT_DEBUG_INFO, "====> RTMPSendPacket\n"); // Prepare packet information structure for buffer descriptor pSrcBufVA = (PVOID)pSkb->data; // STEP 1. Check for virtual address allocation, it might fail !!! if (pSrcBufVA == NULL) { // Resourece is low, system did not allocate virtual address // return NDIS_STATUS_FAILURE directly to upper layer return NDIS_STATUS_FAILURE; } // // Check for multicast or broadcast (First byte of DA) // if ((*((PUCHAR) pSrcBufVA) & 0x01) != 0) { // For multicast & broadcast, there is no fragment allowed NumberOfFrag = 1; } else { // Check for payload allowed for each fragment AllowFragSize = (pAd->PortCfg.FragmentThreshold) - LENGTH_802_11 - LENGTH_CRC; // Calculate fragments required NumberOfFrag = ((pSkb->len - LENGTH_802_3 + LENGTH_802_1_H) / AllowFragSize) + 1; // Minus 1 if the size just match to allowable fragment size if (((pSkb->len - LENGTH_802_3 + LENGTH_802_1_H) % AllowFragSize) == 0) { NumberOfFrag--; } } // Save fragment number to Ndis packet reserved field RTMP_SET_PACKET_FRAGMENTS(pSkb, NumberOfFrag); // STEP 2. Check the requirement of RTS: // If multiple fragment required, RTS is required only for the first fragment // if the fragment size large than RTS threshold if (NumberOfFrag > 1) RTSRequired = (pAd->PortCfg.FragmentThreshold > pAd->PortCfg.RtsThreshold) ? 1 : 0; else RTSRequired = (pSkb->len > pAd->PortCfg.RtsThreshold) ? 1 : 0; // // Remove the following lines to avoid confusion. // CTS requirement will not use Flag "RTSRequired", instead moveing the // following lines to RTUSBHardTransmit(..) // // RTS/CTS may also be required in order to protect OFDM frame //if ((pAd->PortCfg.TxRate >= RATE_FIRST_OFDM_RATE) && // OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_BG_PROTECTION_INUSED)) // RTSRequired = 1; // Save RTS requirement to Ndis packet reserved field RTMP_SET_PACKET_RTS(pSkb, RTSRequired); RTMP_SET_PACKET_TXRATE(pSkb, pAd->PortCfg.TxRate); // // STEP 3. Traffic classification. outcome = <UserPriority, QueIdx> // UserPriority = 0; QueIdx = QID_AC_BE; if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_WMM_INUSED)) { USHORT Protocol; UCHAR LlcSnapLen = 0, Byte0, Byte1; do { // get Ethernet protocol field Protocol = (USHORT)((pSrcBufVA[12] << 8) + pSrcBufVA[13]); if (Protocol <= 1500) { // get Ethernet protocol field from LLC/SNAP if (Sniff2BytesFromNdisBuffer(pSkb, LENGTH_802_3 + 6, &Byte0, &Byte1) != NDIS_STATUS_SUCCESS) break; Protocol = (USHORT)((Byte0 << 8) + Byte1); LlcSnapLen = 8; } // always AC_BE for non-IP packet if (Protocol != 0x0800) break; // get IP header if (Sniff2BytesFromNdisBuffer(pSkb, LENGTH_802_3 + LlcSnapLen, &Byte0, &Byte1) != NDIS_STATUS_SUCCESS) break; // return AC_BE if packet is not IPv4 if ((Byte0 & 0xf0) != 0x40) break; UserPriority = (Byte1 & 0xe0) >> 5; QueIdx = MapUserPriorityToAccessCategory[UserPriority]; // TODO: have to check ACM bit. apply TSPEC if ACM is ON // TODO: downgrade UP & QueIdx before passing ACM if (pAd->PortCfg.APEdcaParm.bACM[QueIdx]) { UserPriority = 0; QueIdx = QID_AC_BE; } } while (FALSE); } RTMP_SET_PACKET_UP(pSkb, UserPriority); // Make sure SendTxWait queue resource won't be used by other threads NdisAcquireSpinLock(&pAd->SendTxWaitQueueLock[QueIdx], IrqFlags); pTxQueue = &pAd->SendTxWaitQueue[QueIdx]; if (pTxQueue->Number > pAd->MaxTxQueueSize) {#ifdef BLOCK_NET_IF StopNetIfQueue(pAd, QueIdx, pSkb);#endif // BLOCK_NET_IF // NdisReleaseSpinLock(&pAd->SendTxWaitQueueLock[QueIdx], IrqFlags); return NDIS_STATUS_FAILURE; } // // For infrastructure mode, enqueue this frame immediately to sendwaitqueue // For Ad-hoc mode, check the DA power state, then decide which queue to enqueue // if (INFRA_ON(pAd) ) { // In infrastructure mode, simply enqueue the packet into Tx waiting queue. DBGPRINT(RT_DEBUG_INFO, "Infrastructure -> Enqueue one frame\n"); // Enqueue Ndis packet to end of Tx wait queue InsertTailQueue(pTxQueue, pSkb); Status = NDIS_STATUS_SUCCESS;#ifdef DBG pAd->RalinkCounters.OneSecOsTxCount[QueIdx]++; // TODO: for debug only. to be removed#endif } else { // In IBSS mode, power state of destination should be considered. PsMode = PWR_ACTIVE; // Faked if (PsMode == PWR_ACTIVE) { DBGPRINT(RT_DEBUG_INFO,"Ad-Hoc -> Enqueue one frame\n"); // Enqueue Ndis packet to end of Tx wait queue InsertTailQueue(pTxQueue, pSkb); Status = NDIS_STATUS_SUCCESS;#ifdef DBG pAd->RalinkCounters.OneSecOsTxCount[QueIdx]++; // TODO: for debug only. to be removed#endif } } NdisReleaseSpinLock(&pAd->SendTxWaitQueueLock[QueIdx], IrqFlags); DBGPRINT(RT_DEBUG_INFO, "<==== RTMPSendPacket\n"); return (Status);}/* ======================================================================== Routine Description: SendPackets handler Arguments: skb point to sk_buf which upper layer transmit net_dev point to net_dev Return Value: None Note: ========================================================================*/INT RTMPSendPackets( IN struct sk_buff *pSkb, IN struct net_device *net_dev){ PRTMP_ADAPTER pAd = net_dev->priv; NDIS_STATUS Status = NDIS_STATUS_SUCCESS; INT Index; DBGPRINT(RT_DEBUG_INFO, "===> RTMPSendPackets\n");#ifdef RALINK_ATE if (pAd->ate.Mode != ATE_STASTART) { RTUSBFreeSkbBuffer(pSkb); return 0; }#endif if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS) || RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS)) { // Drop send request since hardware is in reset state RTUSBFreeSkbBuffer(pSkb); return 0; } // Drop packets if no associations else if (!INFRA_ON(pAd) && !ADHOC_ON(pAd) ) { RTUSBFreeSkbBuffer(pSkb); return 0; } else { // Record that orignal packet source is from protocol layer,so that // later on driver knows how to release this skb buffer
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -