📄 rtusb_data.c
字号:
/*************************************************************************** * RT2x00 SourceForge Project - http://rt2x00.serialmonkey.com * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * * * Licensed under the GNU GPL * * Original code supplied under license from RaLink Inc, 2004. * ***************************************************************************//*************************************************************************** * Module Name: rtusb_data.c * * Abstract: Ralink USB driver Tx/Rx functions * * Revision History: * Who When What * -------- ---------- ----------------------------- * idamlaj 05-10-2006 Import rfmon implementation * idamlaj 14-10-2006 RFMONTx (based on MarkW's code) * ***************************************************************************/#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};UINT _11G_RATES[12] = { 0, 0, 0, 0, 6, 9, 12, 18, 24, 36, 48, 54 };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; if ((pSkb = __dev_alloc_skb(DataSize + LENGTH_802_3 + 2, MEM_ALLOC_FLAG)) != NULL) { 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++; } //DBGPRINT(RT_DEBUG_TRACE, "<-- %s: pSkb %s\n", __FUNCTION__, //pSkb? "found": "n/a");}// 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#define REPORT_MGMT_FRAME_TO_MLME(_pAd, _pFrame, _FrameSize, _Rssi, _PlcpSignal) \{ \ MlmeEnqueueForRecv(_pAd, (UCHAR)_Rssi, _FrameSize, _pFrame, (UCHAR)_PlcpSignal); \}// 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; struct sk_buff_head *pTxQueue; UCHAR PsMode; 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; } if (pSkb && pAd->PortCfg.BssType == BSS_MONITOR && pAd->bAcceptRFMONTx == TRUE) { skb_queue_tail(&pAd->SendTxWaitQueue[QID_AC_BE], pSkb); return (NDIS_STATUS_SUCCESS); } // // Check for multicast or broadcast (First byte of DA) // if ((*((PUCHAR) pSrcBufVA) & 0x01) != 0) { // For multicast & broadcast, there is no fragment allowed NumberOfFrag = 1; }#if 0 //AGGREGATION_SUPPORT else if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_AGGREGATION_INUSED)) { NumberOfFrag = 1; // Aggregation overwhelms fragmentation }#endif 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); pTxQueue = &pAd->SendTxWaitQueue[QueIdx]; // // 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 skb_queue_tail(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 skb_queue_tail(pTxQueue, pSkb); Status = NDIS_STATUS_SUCCESS;#ifdef DBG pAd->RalinkCounters.OneSecOsTxCount[QueIdx]++; // TODO: for debug only. to be removed#endif } } 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"); 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) && !(pAd->PortCfg.BssType == BSS_MONITOR && pAd->bAcceptRFMONTx == TRUE)) { RTUSBFreeSkbBuffer(pSkb); return 0; } else { // initial pSkb->data_len=0, we will use this variable to store data size when fragment(in TKIP) // and pSkb->len is actual data len pSkb->data_len = pSkb->len; // Record that orignal packet source is from protocol layer,so that // later on driver knows how to release this skb buffer RTMP_SET_PACKET_SOURCE(pSkb, PKTSRC_NDIS); pAd->RalinkCounters.PendingNdisPacketCount ++; Status = RTMPSendPacket(pAd, pSkb); if (Status != NDIS_STATUS_SUCCESS) { // Errors before enqueue stage RELEASE_NDIS_PACKET(pAd, pSkb); DBGPRINT(RT_DEBUG_TRACE,"<---RTUSBSendPackets not dequeue\n"); return 0; } } RTUSBMlmeUp(pAd); return 0;}/* ======================================================================== Routine Description: Copy frame from waiting queue into relative ring buffer and set appropriate ASIC register to kick hardware encryption before really sent out to air. Arguments: pAd Pointer to our adapter PNDIS_PACKET Pointer to outgoing Ndis frame NumberOfFrag Number of fragment required Return Value: None Note: ========================================================================*/#ifdef BIG_ENDIANstatic inline#endifNDIS_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;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -