/* * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. * All rights reserved. * * 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., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * File: rxtx.c * * Purpose: handle WMAC/802.3/802.11 rx & tx functions * * Author: Lyndon Chen * * Date: May 20, 2003 * * Functions: * s_vGenerateTxParameter - Generate tx dma requried parameter. * s_vGenerateMACHeader - Translate 802.3 to 802.11 header * csBeacon_xmit - beacon tx function * csMgmt_xmit - management tx function * s_uGetDataDuration - get tx data required duration * s_uFillDataHead- fulfill tx data duration header * s_uGetRTSCTSDuration- get rtx/cts requried duration * s_uGetRTSCTSRsvTime- get rts/cts reserved time * s_uGetTxRsvTime- get frame reserved time * s_vFillCTSHead- fulfill CTS ctl header * s_vFillFragParameter- Set fragement ctl parameter. * s_vFillRTSHead- fulfill RTS ctl header * s_vFillTxKey- fulfill tx encrypt key * s_vSWencryption- Software encrypt header * vDMA0_tx_80211- tx 802.11 frame via dma0 * vGenerateFIFOHeader- Generate tx FIFO ctl header * * Revision History: * */ #include "device.h" #include "rxtx.h" #include "tether.h" #include "card.h" #include "bssdb.h" #include "mac.h" #include "baseband.h" #include "michael.h" #include "tkip.h" #include "tcrc.h" #include "wctl.h" #include "hostap.h" #include "rf.h" #include "datarate.h" #include "usbpipe.h" #ifdef WPA_SM_Transtatus #include "iocmd.h" #endif /*--------------------- Static Definitions -------------------------*/ /*--------------------- Static Classes ----------------------------*/ /*--------------------- Static Variables --------------------------*/ //static int msglevel =MSG_LEVEL_DEBUG; static int msglevel =MSG_LEVEL_INFO; /*--------------------- Static Functions --------------------------*/ /*--------------------- Static Definitions -------------------------*/ #define CRITICAL_PACKET_LEN 256 // if packet size < 256 -> in-direct send // packet size >= 256 -> direct send const WORD wTimeStampOff[2][MAX_RATE] = { {384, 288, 226, 209, 54, 43, 37, 31, 28, 25, 24, 23}, // Long Preamble {384, 192, 130, 113, 54, 43, 37, 31, 28, 25, 24, 23}, // Short Preamble }; const WORD wFB_Opt0[2][5] = { {RATE_12M, RATE_18M, RATE_24M, RATE_36M, RATE_48M}, // fallback_rate0 {RATE_12M, RATE_12M, RATE_18M, RATE_24M, RATE_36M}, // fallback_rate1 }; const WORD wFB_Opt1[2][5] = { {RATE_12M, RATE_18M, RATE_24M, RATE_24M, RATE_36M}, // fallback_rate0 {RATE_6M , RATE_6M, RATE_12M, RATE_12M, RATE_18M}, // fallback_rate1 }; #define RTSDUR_BB 0 #define RTSDUR_BA 1 #define RTSDUR_AA 2 #define CTSDUR_BA 3 #define RTSDUR_BA_F0 4 #define RTSDUR_AA_F0 5 #define RTSDUR_BA_F1 6 #define RTSDUR_AA_F1 7 #define CTSDUR_BA_F0 8 #define CTSDUR_BA_F1 9 #define DATADUR_B 10 #define DATADUR_A 11 #define DATADUR_A_F0 12 #define DATADUR_A_F1 13 /*--------------------- Static Functions --------------------------*/ static VOID s_vSaveTxPktInfo( IN PSDevice pDevice, IN BYTE byPktNum, IN PBYTE pbyDestAddr, IN WORD wPktLength, IN WORD wFIFOCtl ); static PVOID s_vGetFreeContext( PSDevice pDevice ); static VOID s_vGenerateTxParameter( IN PSDevice pDevice, IN BYTE byPktType, IN WORD wCurrentRate, IN PVOID pTxBufHead, IN PVOID pvRrvTime, IN PVOID pvRTS, IN PVOID pvCTS, IN UINT cbFrameSize, IN BOOL bNeedACK, IN UINT uDMAIdx, IN PSEthernetHeader psEthHeader ); static UINT s_uFillDataHead ( IN PSDevice pDevice, IN BYTE byPktType, IN WORD wCurrentRate, IN PVOID pTxDataHead, IN UINT cbFrameLength, IN UINT uDMAIdx, IN BOOL bNeedAck, IN UINT uFragIdx, IN UINT cbLastFragmentSize, IN UINT uMACfragNum, IN BYTE byFBOption ); static VOID s_vGenerateMACHeader ( IN PSDevice pDevice, IN PBYTE pbyBufferAddr, IN WORD wDuration, IN PSEthernetHeader psEthHeader, IN BOOL bNeedEncrypt, IN WORD wFragType, IN UINT uDMAIdx, IN UINT uFragIdx ); static VOID s_vFillTxKey( IN PSDevice pDevice, IN PBYTE pbyBuf, IN PBYTE pbyIVHead, IN PSKeyItem pTransmitKey, IN PBYTE pbyHdrBuf, IN WORD wPayloadLen, OUT PBYTE pMICHDR ); static VOID s_vSWencryption ( IN PSDevice pDevice, IN PSKeyItem pTransmitKey, IN PBYTE pbyPayloadHead, IN WORD wPayloadSize ); static UINT s_uGetTxRsvTime ( IN PSDevice pDevice, IN BYTE byPktType, IN UINT cbFrameLength, IN WORD wRate, IN BOOL bNeedAck ); static UINT s_uGetRTSCTSRsvTime ( IN PSDevice pDevice, IN BYTE byRTSRsvType, IN BYTE byPktType, IN UINT cbFrameLength, IN WORD wCurrentRate ); static VOID s_vFillCTSHead ( IN PSDevice pDevice, IN UINT uDMAIdx, IN BYTE byPktType, IN PVOID pvCTS, IN UINT cbFrameLength, IN BOOL bNeedAck, IN BOOL bDisCRC, IN WORD wCurrentRate, IN BYTE byFBOption ); static VOID s_vFillRTSHead( IN PSDevice pDevice, IN BYTE byPktType, IN PVOID pvRTS, IN UINT cbFrameLength, IN BOOL bNeedAck, IN BOOL bDisCRC, IN PSEthernetHeader psEthHeader, IN WORD wCurrentRate, IN BYTE byFBOption ); static UINT s_uGetDataDuration ( IN PSDevice pDevice, IN BYTE byDurType, IN UINT cbFrameLength, IN BYTE byPktType, IN WORD wRate, IN BOOL bNeedAck, IN UINT uFragIdx, IN UINT cbLastFragmentSize, IN UINT uMACfragNum, IN BYTE byFBOption ); static UINT s_uGetRTSCTSDuration ( IN PSDevice pDevice, IN BYTE byDurType, IN UINT cbFrameLength, IN BYTE byPktType, IN WORD wRate, IN BOOL bNeedAck, IN BYTE byFBOption ); /*--------------------- Export Variables --------------------------*/ static PVOID s_vGetFreeContext( PSDevice pDevice ) { PUSB_SEND_CONTEXT pContext = NULL; PUSB_SEND_CONTEXT pReturnContext = NULL; UINT ii; DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"GetFreeContext()\n"); for (ii = 0; ii < pDevice->cbTD; ii++) { pContext = pDevice->apTD[ii]; if (pContext->bBoolInUse == FALSE) { pContext->bBoolInUse = TRUE; pReturnContext = pContext; break; } } if ( ii == pDevice->cbTD ) { DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"No Free Tx Context\n"); } return ((PVOID) pReturnContext); } static VOID s_vSaveTxPktInfo(PSDevice pDevice, BYTE byPktNum, PBYTE pbyDestAddr, WORD wPktLength, WORD wFIFOCtl) { PSStatCounter pStatistic=&(pDevice->scStatistic); if (IS_BROADCAST_ADDRESS(pbyDestAddr)) pStatistic->abyTxPktInfo[byPktNum].byBroadMultiUni = TX_PKT_BROAD; else if (IS_MULTICAST_ADDRESS(pbyDestAddr)) pStatistic->abyTxPktInfo[byPktNum].byBroadMultiUni = TX_PKT_MULTI; else pStatistic->abyTxPktInfo[byPktNum].byBroadMultiUni = TX_PKT_UNI; pStatistic->abyTxPktInfo[byPktNum].wLength = wPktLength; pStatistic->abyTxPktInfo[byPktNum].wFIFOCtl = wFIFOCtl; memcpy(pStatistic->abyTxPktInfo[byPktNum].abyDestAddr, pbyDestAddr, U_ETHER_ADDR_LEN); } static VOID s_vFillTxKey ( IN PSDevice pDevice, IN PBYTE pbyBuf, IN PBYTE pbyIVHead, IN PSKeyItem pTransmitKey, IN PBYTE pbyHdrBuf, IN WORD wPayloadLen, OUT PBYTE pMICHDR ) { PDWORD pdwIV = (PDWORD) pbyIVHead; PDWORD pdwExtIV = (PDWORD) ((PBYTE)pbyIVHead+4); WORD wValue; PS802_11Header pMACHeader = (PS802_11Header)pbyHdrBuf; DWORD dwRevIVCounter; //Fill TXKEY if (pTransmitKey == NULL) return; dwRevIVCounter = cpu_to_le32(pDevice->dwIVCounter); *pdwIV = pDevice->dwIVCounter; pDevice->byKeyIndex = pTransmitKey->dwKeyIndex & 0xf; if (pTransmitKey->byCipherSuite == KEY_CTL_WEP) { if (pTransmitKey->uKeyLength == WLAN_WEP232_KEYLEN ){ memcpy(pDevice->abyPRNG, (PBYTE)&(dwRevIVCounter), 3); memcpy(pDevice->abyPRNG+3, pTransmitKey->abyKey, pTransmitKey->uKeyLength); } else { memcpy(pbyBuf, (PBYTE)&(dwRevIVCounter), 3); memcpy(pbyBuf+3, pTransmitKey->abyKey, pTransmitKey->uKeyLength); if(pTransmitKey->uKeyLength == WLAN_WEP40_KEYLEN) { memcpy(pbyBuf+8, (PBYTE)&(dwRevIVCounter), 3); memcpy(pbyBuf+11, pTransmitKey->abyKey, pTransmitKey->uKeyLength); } memcpy(pDevice->abyPRNG, pbyBuf, 16); } // Append IV after Mac Header *pdwIV &= WEP_IV_MASK;//00000000 11111111 11111111 11111111 *pdwIV |= (pDevice->byKeyIndex << 30); *pdwIV = cpu_to_le32(*pdwIV); pDevice->dwIVCounter++; if (pDevice->dwIVCounter > WEP_IV_MASK) { pDevice->dwIVCounter = 0; } } else if (pTransmitKey->byCipherSuite == KEY_CTL_TKIP) { pTransmitKey->wTSC15_0++; if (pTransmitKey->wTSC15_0 == 0) { pTransmitKey->dwTSC47_16++; } TKIPvMixKey(pTransmitKey->abyKey, pDevice->abyCurrentNetAddr, pTransmitKey->wTSC15_0, pTransmitKey->dwTSC47_16, pDevice->abyPRNG); memcpy(pbyBuf, pDevice->abyPRNG, 16); // Make IV memcpy(pdwIV, pDevice->abyPRNG, 3); *(pbyIVHead+3) = (BYTE)(((pDevice->byKeyIndex << 6) & 0xc0) | 0x20); // 0x20 is ExtIV // Append IV&ExtIV after Mac Header *pdwExtIV = cpu_to_le32(pTransmitKey->dwTSC47_16); DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"vFillTxKey()---- pdwExtIV: %lx\n", *pdwExtIV); } else if (pTransmitKey->byCipherSuite == KEY_CTL_CCMP) { pTransmitKey->wTSC15_0++; if (pTransmitKey->wTSC15_0 == 0) { pTransmitKey->dwTSC47_16++; } memcpy(pbyBuf, pTransmitKey->abyKey, 16); // Make IV *pdwIV = 0; *(pbyIVHead+3) = (BYTE)(((pDevice->byKeyIndex << 6) & 0xc0) | 0x20); // 0x20 is ExtIV *pdwIV |= cpu_to_le16((WORD)(pTransmitKey->wTSC15_0)); //Append IV&ExtIV after Mac Header *pdwExtIV = cpu_to_le32(pTransmitKey->dwTSC47_16); //Fill MICHDR0 *pMICHDR = 0x59; *((PBYTE)(pMICHDR+1)) = 0; // TxPriority memcpy(pMICHDR+2, &(pMACHeader->abyAddr2[0]), 6); *((PBYTE)(pMICHDR+8)) = HIBYTE(HIWORD(pTransmitKey->dwTSC47_16)); *((PBYTE)(pMICHDR+9)) = LOBYTE(HIWORD(pTransmitKey->dwTSC47_16)); *((PBYTE)(pMICHDR+10)) = HIBYTE(LOWORD(pTransmitKey->dwTSC47_16)); *((PBYTE)(pMICHDR+11)) = LOBYTE(LOWORD(pTransmitKey->dwTSC47_16)); *((PBYTE)(pMICHDR+12)) = HIBYTE(pTransmitKey->wTSC15_0); *((PBYTE)(pMICHDR+13)) = LOBYTE(pTransmitKey->wTSC15_0); *((PBYTE)(pMICHDR+14)) = HIBYTE(wPayloadLen); *((PBYTE)(pMICHDR+15)) = LOBYTE(wPayloadLen); //Fill MICHDR1 *((PBYTE)(pMICHDR+16)) = 0; // HLEN[15:8] if (pDevice->bLongHeader) { *((PBYTE)(pMICHDR+17)) = 28; // HLEN[7:0] } else { *((PBYTE)(pMICHDR+17)) = 22; // HLEN[7:0] } wValue = cpu_to_le16(pMACHeader->wFrameCtl & 0xC78F); memcpy(pMICHDR+18, (PBYTE)&wValue, 2); // MSKFRACTL memcpy(pMICHDR+20, &(pMACHeader->abyAddr1[0]), 6); memcpy(pMICHDR+26, &(pMACHeader->abyAddr2[0]), 6); //Fill MICHDR2 memcpy(pMICHDR+32, &(pMACHeader->abyAddr3[0]), 6); wValue = pMACHeader->wSeqCtl; wValue &= 0x000F; wValue = cpu_to_le16(wValue); memcpy(pMICHDR+38, (PBYTE)&wValue, 2); // MSKSEQCTL if (pDevice->bLongHeader) { memcpy(pMICHDR+40, &(pMACHeader->abyAddr4[0]), 6); } } } static VOID s_vSWencryption ( IN PSDevice pDevice, IN PSKeyItem pTransmitKey, IN PBYTE pbyPayloadHead, IN WORD wPayloadSize ) { UINT cbICVlen = 4; DWORD dwICV = 0xFFFFFFFFL; PDWORD pdwICV; if (pTransmitKey == NULL) return; if (pTransmitKey->byCipherSuite == KEY_CTL_WEP) { //======================================================================= // Append ICV after payload dwICV = CRCdwGetCrc32Ex(pbyPayloadHead, wPayloadSize, dwICV);//ICV(Payload) pdwICV = (PDWORD)(pbyPayloadHead + wPayloadSize); // finally, we must invert dwCRC to get the correct answer *pdwICV = cpu_to_le32(~dwICV); // RC4 encryption rc4_init(&pDevice->SBox, pDevice->abyPRNG, pTransmitKey->uKeyLength + 3); rc4_encrypt(&pDevice->SBox, pbyPayloadHead, pbyPayloadHead, wPayloadSize+cbICVlen); //======================================================================= } else if (pTransmitKey->byCipherSuite == KEY_CTL_TKIP) { //======================================================================= //Append ICV after payload dwICV = CRCdwGetCrc32Ex(pbyPayloadHead, wPayloadSize, dwICV);//ICV(Payload) pdwICV = (PDWORD)(pbyPayloadHead + wPayloadSize); // finally, we must invert dwCRC to get the correct answer *pdwICV = cpu_to_le32(~dwICV); // RC4 encryption rc4_init(&pDevice->SBox, pDevice->abyPRNG, TKIP_KEY_LEN); rc4_encrypt(&pDevice->SBox, pbyPayloadHead, pbyPayloadHead, wPayloadSize+cbICVlen); //======================================================================= } } /*byPktType : PK_TYPE_11A 0 PK_TYPE_11B 1 PK_TYPE_11GB 2 PK_TYPE_11GA 3 */ static UINT s_uGetTxRsvTime ( IN PSDevice pDevice, IN BYTE byPktType, IN UINT cbFrameLength, IN WORD wRate, IN BOOL bNeedAck ) { UINT uDataTime, uAckTime; uDataTime = BBuGetFrameTime(pDevice->byPreambleType, byPktType, cbFrameLength, wRate); if (byPktType == PK_TYPE_11B) {//llb,CCK mode uAckTime = BBuGetFrameTime(pDevice->byPreambleType, byPktType, 14, (WORD)pDevice->byTopCCKBasicRate); } else {//11g 2.4G OFDM mode & 11a 5G OFDM mode uAckTime = BBuGetFrameTime(pDevice->byPreambleType, byPktType, 14, (WORD)pDevice->byTopOFDMBasicRate); } if (bNeedAck) { return (uDataTime + pDevice->uSIFS + uAckTime); } else { return uDataTime; } } //byFreqType: 0=>5GHZ 1=>2.4GHZ static UINT s_uGetRTSCTSRsvTime ( IN PSDevice pDevice, IN BYTE byRTSRsvType, IN BYTE byPktType, IN UINT cbFrameLength, IN WORD wCurrentRate ) { UINT uRrvTime , uRTSTime, uCTSTime, uAckTime, uDataTime; uRrvTime = uRTSTime = uCTSTime = uAckTime = uDataTime = 0; uDataTime = BBuGetFrameTime(pDevice->byPreambleType, byPktType, cbFrameLength, wCurrentRate); if (byRTSRsvType == 0) { //RTSTxRrvTime_bb uRTSTime = BBuGetFrameTime(pDevice->byPreambleType, byPktType, 20, pDevice->byTopCCKBasicRate); uCTSTime = uAckTime = BBuGetFrameTime(pDevice->byPreambleType, byPktType, 14, pDevice->byTopCCKBasicRate); } else if (byRTSRsvType == 1){ //RTSTxRrvTime_ba, only in 2.4GHZ uRTSTime = BBuGetFrameTime(pDevice->byPreambleType, byPktType, 20, pDevice->byTopCCKBasicRate); uCTSTime = BBuGetFrameTime(pDevice->byPreambleType, byPktType, 14, pDevice->byTopCCKBasicRate); uAckTime = BBuGetFrameTime(pDevice->byPreambleType, byPktType, 14, pDevice->byTopOFDMBasicRate); } else if (byRTSRsvType == 2) { //RTSTxRrvTime_aa uRTSTime = BBuGetFrameTime(pDevice->byPreambleType, byPktType, 20, pDevice->byTopOFDMBasicRate); uCTSTime = uAckTime = BBuGetFrameTime(pDevice->byPreambleType, byPktType, 14, pDevice->byTopOFDMBasicRate); } else if (byRTSRsvType == 3) { //CTSTxRrvTime_ba, only in 2.4GHZ uCTSTime = BBuGetFrameTime(pDevice->byPreambleType, byPktType, 14, pDevice->byTopCCKBasicRate); uAckTime = BBuGetFrameTime(pDevice->byPreambleType, byPktType, 14, pDevice->byTopOFDMBasicRate); uRrvTime = uCTSTime + uAckTime + uDataTime + 2*pDevice->uSIFS; return uRrvTime; } //RTSRrvTime uRrvTime = uRTSTime + uCTSTime + uAckTime + uDataTime + 3*pDevice->uSIFS; return uRrvTime; } //byFreqType 0: 5GHz, 1:2.4Ghz static UINT s_uGetDataDuration ( IN PSDevice pDevice, IN BYTE byDurType, IN UINT cbFrameLength, IN BYTE byPktType, IN WORD wRate, IN BOOL bNeedAck, IN UINT uFragIdx, IN UINT cbLastFragmentSize, IN UINT uMACfragNum, IN BYTE byFBOption ) { BOOL bLastFrag = 0; UINT uAckTime =0, uNextPktTime = 0; if (uFragIdx == (uMACfragNum-1)) { bLastFrag = 1; } switch (byDurType) { case DATADUR_B: //DATADUR_B if (((uMACfragNum == 1)) || (bLastFrag == 1)) {//Non Frag or Last Frag if (bNeedAck) { uAckTime = BBuGetFrameTime(pDevice->byPreambleType, byPktType, 14, pDevice->byTopCCKBasicRate); return (pDevice->uSIFS + uAckTime); } else { return 0; } } else {//First Frag or Mid Frag if (uFragIdx == (uMACfragNum-2)) { uNextPktTime = s_uGetTxRsvTime(pDevice, byPktType, cbLastFragmentSize, wRate, bNeedAck); } else { uNextPktTime = s_uGetTxRsvTime(pDevice, byPktType, cbFrameLength, wRate, bNeedAck); } if (bNeedAck) { uAckTime = BBuGetFrameTime(pDevice->byPreambleType, byPktType, 14, pDevice->byTopCCKBasicRate); return (pDevice->uSIFS + uAckTime + uNextPktTime); } else { return (pDevice->uSIFS + uNextPktTime); } } break; case DATADUR_A: //DATADUR_A if (((uMACfragNum==1)) || (bLastFrag==1)) {//Non Frag or Last Frag if(bNeedAck){ uAckTime = BBuGetFrameTime(pDevice->byPreambleType, byPktType, 14, pDevice->byTopOFDMBasicRate); return (pDevice->uSIFS + uAckTime); } else { return 0; } } else {//First Frag or Mid Frag if(uFragIdx == (uMACfragNum-2)){ uNextPktTime = s_uGetTxRsvTime(pDevice, byPktType, cbLastFragmentSize, wRate, bNeedAck); } else { uNextPktTime = s_uGetTxRsvTime(pDevice, byPktType, cbFrameLength, wRate, bNeedAck); } if(bNeedAck){ uAckTime = BBuGetFrameTime(pDevice->byPreambleType, byPktType, 14, pDevice->byTopOFDMBasicRate); return (pDevice->uSIFS + uAckTime + uNextPktTime); } else { return (pDevice->uSIFS + uNextPktTime); } } break; case DATADUR_A_F0: //DATADUR_A_F0 if (((uMACfragNum==1)) || (bLastFrag==1)) {//Non Frag or Last Frag if(bNeedAck){ uAckTime = BBuGetFrameTime(pDevice->byPreambleType, byPktType, 14, pDevice->byTopOFDMBasicRate); return (pDevice->uSIFS + uAckTime); } else { return 0; } } else { //First Frag or Mid Frag if (byFBOption == AUTO_FB_0) { if (wRate < RATE_18M) wRate = RATE_18M; else if (wRate > RATE_54M) wRate = RATE_54M; if(uFragIdx == (uMACfragNum-2)){ uNextPktTime = s_uGetTxRsvTime(pDevice, byPktType, cbLastFragmentSize, wFB_Opt0[FB_RATE0][wRate-RATE_18M], bNeedAck); } else { uNextPktTime = s_uGetTxRsvTime(pDevice, byPktType, cbFrameLength, wFB_Opt0[FB_RATE0][wRate-RATE_18M], bNeedAck); } } else { // (byFBOption == AUTO_FB_1) if (wRate < RATE_18M) wRate = RATE_18M; else if (wRate > RATE_54M) wRate = RATE_54M; if(uFragIdx == (uMACfragNum-2)){ uNextPktTime = s_uGetTxRsvTime(pDevice, byPktType, cbLastFragmentSize, wFB_Opt1[FB_RATE0][wRate-RATE_18M], bNeedAck); } else { uNextPktTime = s_uGetTxRsvTime(pDevice, byPktType, cbFrameLength, wFB_Opt1[FB_RATE0][wRate-RATE_18M], bNeedAck); } } if(bNeedAck){ uAckTime = BBuGetFrameTime(pDevice->byPreambleType, byPktType, 14, pDevice->byTopOFDMBasicRate); return (pDevice->uSIFS + uAckTime + uNextPktTime); } else { return (pDevice->uSIFS + uNextPktTime); } } break; case DATADUR_A_F1: //DATADUR_A_F1 if (((uMACfragNum==1)) || (bLastFrag==1)) {//Non Frag or Last Frag if(bNeedAck){ uAckTime = BBuGetFrameTime(pDevice->byPreambleType, byPktType, 14, pDevice->byTopOFDMBasicRate); return (pDevice->uSIFS + uAckTime); } else { return 0; } } else { //First Frag or Mid Frag if (byFBOption == AUTO_FB_0) { if (wRate < RATE_18M) wRate = RATE_18M; else if (wRate > RATE_54M) wRate = RATE_54M; if(uFragIdx == (uMACfragNum-2)){ uNextPktTime = s_uGetTxRsvTime(pDevice, byPktType, cbLastFragmentSize, wFB_Opt0[FB_RATE1][wRate-RATE_18M], bNeedAck); } else { uNextPktTime = s_uGetTxRsvTime(pDevice, byPktType, cbFrameLength, wFB_Opt0[FB_RATE1][wRate-RATE_18M], bNeedAck); } } else { // (byFBOption == AUTO_FB_1) if (wRate < RATE_18M) wRate = RATE_18M; else if (wRate > RATE_54M) wRate = RATE_54M; if(uFragIdx == (uMACfragNum-2)){ uNextPktTime = s_uGetTxRsvTime(pDevice, byPktType, cbLastFragmentSize, wFB_Opt1[FB_RATE1][wRate-RATE_18M], bNeedAck); } else { uNextPktTime = s_uGetTxRsvTime(pDevice, byPktType, cbFrameLength, wFB_Opt1[FB_RATE1][wRate-RATE_18M], bNeedAck); } } if(bNeedAck){ uAckTime = BBuGetFrameTime(pDevice->byPreambleType, byPktType, 14, pDevice->byTopOFDMBasicRate); return (pDevice->uSIFS + uAckTime + uNextPktTime); } else { return (pDevice->uSIFS + uNextPktTime); } } break; default: break; } ASSERT(FALSE); return 0; } //byFreqType: 0=>5GHZ 1=>2.4GHZ static UINT s_uGetRTSCTSDuration ( IN PSDevice pDevice, IN BYTE byDurType, IN UINT cbFrameLength, IN BYTE byPktType, IN WORD wRate, IN BOOL bNeedAck, IN BYTE byFBOption ) { UINT uCTSTime = 0, uDurTime = 0; switch (byDurType) { case RTSDUR_BB: //RTSDuration_bb uCTSTime = BBuGetFrameTime(pDevice->byPreambleType, byPktType, 14, pDevice->byTopCCKBasicRate); uDurTime = uCTSTime + 2*pDevice->uSIFS + s_uGetTxRsvTime(pDevice, byPktType, cbFrameLength, wRate, bNeedAck); break; case RTSDUR_BA: //RTSDuration_ba uCTSTime = BBuGetFrameTime(pDevice->byPreambleType, byPktType, 14, pDevice->byTopCCKBasicRate); uDurTime = uCTSTime + 2*pDevice->uSIFS + s_uGetTxRsvTime(pDevice, byPktType, cbFrameLength, wRate, bNeedAck); break; case RTSDUR_AA: //RTSDuration_aa uCTSTime = BBuGetFrameTime(pDevice->byPreambleType, byPktType, 14, pDevice->byTopOFDMBasicRate); uDurTime = uCTSTime + 2*pDevice->uSIFS + s_uGetTxRsvTime(pDevice, byPktType, cbFrameLength, wRate, bNeedAck); break; case CTSDUR_BA: //CTSDuration_ba uDurTime = pDevice->uSIFS + s_uGetTxRsvTime(pDevice, byPktType, cbFrameLength, wRate, bNeedAck); break; case RTSDUR_BA_F0: //RTSDuration_ba_f0 uCTSTime = BBuGetFrameTime(pDevice->byPreambleType, byPktType, 14, pDevice->byTopCCKBasicRate); if ((byFBOption == AUTO_FB_0) && (wRate >= RATE_18M) && (wRate <=RATE_54M)) { uDurTime = uCTSTime + 2*pDevice->uSIFS + s_uGetTxRsvTime(pDevice, byPktType, cbFrameLength, wFB_Opt0[FB_RATE0][wRate-RATE_18M], bNeedAck); } else if ((byFBOption == AUTO_FB_1) && (wRate >= RATE_18M) && (wRate <=RATE_54M)) { uDurTime = uCTSTime + 2*pDevice->uSIFS + s_uGetTxRsvTime(pDevice, byPktType, cbFrameLength, wFB_Opt1[FB_RATE0][wRate-RATE_18M], bNeedAck); } break; case RTSDUR_AA_F0: //RTSDuration_aa_f0 uCTSTime = BBuGetFrameTime(pDevice->byPreambleType, byPktType, 14, pDevice->byTopOFDMBasicRate); if ((byFBOption == AUTO_FB_0) && (wRate >= RATE_18M) && (wRate <=RATE_54M)) { uDurTime = uCTSTime + 2*pDevice->uSIFS + s_uGetTxRsvTime(pDevice, byPktType, cbFrameLength, wFB_Opt0[FB_RATE0][wRate-RATE_18M], bNeedAck); } else if ((byFBOption == AUTO_FB_1) && (wRate >= RATE_18M) && (wRate <=RATE_54M)) { uDurTime = uCTSTime + 2*pDevice->uSIFS + s_uGetTxRsvTime(pDevice, byPktType, cbFrameLength, wFB_Opt1[FB_RATE0][wRate-RATE_18M], bNeedAck); } break; case RTSDUR_BA_F1: //RTSDuration_ba_f1 uCTSTime = BBuGetFrameTime(pDevice->byPreambleType, byPktType, 14, pDevice->byTopCCKBasicRate); if ((byFBOption == AUTO_FB_0) && (wRate >= RATE_18M) && (wRate <=RATE_54M)) { uDurTime = uCTSTime + 2*pDevice->uSIFS + s_uGetTxRsvTime(pDevice, byPktType, cbFrameLength, wFB_Opt0[FB_RATE1][wRate-RATE_18M], bNeedAck); } else if ((byFBOption == AUTO_FB_1) && (wRate >= RATE_18M) && (wRate <=RATE_54M)) { uDurTime = uCTSTime + 2*pDevice->uSIFS + s_uGetTxRsvTime(pDevice, byPktType, cbFrameLength, wFB_Opt1[FB_RATE1][wRate-RATE_18M], bNeedAck); } break; case RTSDUR_AA_F1: //RTSDuration_aa_f1 uCTSTime = BBuGetFrameTime(pDevice->byPreambleType, byPktType, 14, pDevice->byTopOFDMBasicRate); if ((byFBOption == AUTO_FB_0) && (wRate >= RATE_18M) && (wRate <=RATE_54M)) { uDurTime = uCTSTime + 2*pDevice->uSIFS + s_uGetTxRsvTime(pDevice, byPktType, cbFrameLength, wFB_Opt0[FB_RATE1][wRate-RATE_18M], bNeedAck); } else if ((byFBOption == AUTO_FB_1) && (wRate >= RATE_18M) && (wRate <=RATE_54M)) { uDurTime = uCTSTime + 2*pDevice->uSIFS + s_uGetTxRsvTime(pDevice, byPktType, cbFrameLength, wFB_Opt1[FB_RATE1][wRate-RATE_18M], bNeedAck); } break; case CTSDUR_BA_F0: //CTSDuration_ba_f0 if ((byFBOption == AUTO_FB_0) && (wRate >= RATE_18M) && (wRate <=RATE_54M)) { uDurTime = pDevice->uSIFS + s_uGetTxRsvTime(pDevice, byPktType, cbFrameLength, wFB_Opt0[FB_RATE0][wRate-RATE_18M], bNeedAck); } else if ((byFBOption == AUTO_FB_1) && (wRate >= RATE_18M) && (wRate <=RATE_54M)) { uDurTime = pDevice->uSIFS + s_uGetTxRsvTime(pDevice, byPktType, cbFrameLength, wFB_Opt1[FB_RATE0][wRate-RATE_18M], bNeedAck); } break; case CTSDUR_BA_F1: //CTSDuration_ba_f1 if ((byFBOption == AUTO_FB_0) && (wRate >= RATE_18M) && (wRate <=RATE_54M)) { uDurTime = pDevice->uSIFS + s_uGetTxRsvTime(pDevice, byPktType, cbFrameLength, wFB_Opt0[FB_RATE1][wRate-RATE_18M], bNeedAck); } else if ((byFBOption == AUTO_FB_1) && (wRate >= RATE_18M) && (wRate <=RATE_54M)) { uDurTime = pDevice->uSIFS + s_uGetTxRsvTime(pDevice, byPktType, cbFrameLength, wFB_Opt1[FB_RATE1][wRate-RATE_18M], bNeedAck); } break; default: break; } return uDurTime; } static UINT s_uFillDataHead ( IN PSDevice pDevice, IN BYTE byPktType, IN WORD wCurrentRate, IN PVOID pTxDataHead, IN UINT cbFrameLength, IN UINT uDMAIdx, IN BOOL bNeedAck, IN UINT uFragIdx, IN UINT cbLastFragmentSize, IN UINT uMACfragNum, IN BYTE byFBOption ) { if (pTxDataHead == NULL) { return 0; } if (byPktType == PK_TYPE_11GB || byPktType == PK_TYPE_11GA) { if((uDMAIdx==TYPE_ATIMDMA)||(uDMAIdx==TYPE_BEACONDMA)) { PSTxDataHead_ab pBuf = (PSTxDataHead_ab)pTxDataHead; //Get SignalField,ServiceField,Length BBvCaculateParameter(pDevice, cbFrameLength, wCurrentRate, byPktType, (PWORD)&(pBuf->wTransmitLength), (PBYTE)&(pBuf->byServiceField), (PBYTE)&(pBuf->bySignalField) ); //Get Duration and TimeStampOff pBuf->wDuration = (WORD)s_uGetDataDuration(pDevice, DATADUR_A, cbFrameLength, byPktType, wCurrentRate, bNeedAck, uFragIdx, cbLastFragmentSize, uMACfragNum, byFBOption); //1: 2.4GHz if(uDMAIdx!=TYPE_ATIMDMA) { pBuf->wTimeStampOff = wTimeStampOff[pDevice->byPreambleType%2][wCurrentRate%MAX_RATE]; } return (pBuf->wDuration); } else { // DATA & MANAGE Frame if (byFBOption == AUTO_FB_NONE) { PSTxDataHead_g pBuf = (PSTxDataHead_g)pTxDataHead; //Get SignalField,ServiceField,Length BBvCaculateParameter(pDevice, cbFrameLength, wCurrentRate, byPktType, (PWORD)&(pBuf->wTransmitLength_a), (PBYTE)&(pBuf->byServiceField_a), (PBYTE)&(pBuf->bySignalField_a) ); BBvCaculateParameter(pDevice, cbFrameLength, pDevice->byTopCCKBasicRate, PK_TYPE_11B, (PWORD)&(pBuf->wTransmitLength_b), (PBYTE)&(pBuf->byServiceField_b), (PBYTE)&(pBuf->bySignalField_b) ); //Get Duration and TimeStamp pBuf->wDuration_a = (WORD)s_uGetDataDuration(pDevice, DATADUR_A, cbFrameLength, byPktType, wCurrentRate, bNeedAck, uFragIdx, cbLastFragmentSize, uMACfragNum, byFBOption); //1: 2.4GHz pBuf->wDuration_b = (WORD)s_uGetDataDuration(pDevice, DATADUR_B, cbFrameLength, PK_TYPE_11B, pDevice->byTopCCKBasicRate, bNeedAck, uFragIdx, cbLastFragmentSize, uMACfragNum, byFBOption); //1: 2.4GHz pBuf->wTimeStampOff_a = wTimeStampOff[pDevice->byPreambleType%2][wCurrentRate%MAX_RATE]; pBuf->wTimeStampOff_b = wTimeStampOff[pDevice->byPreambleType%2][pDevice->byTopCCKBasicRate%MAX_RATE]; return (pBuf->wDuration_a); } else { // Auto Fallback PSTxDataHead_g_FB pBuf = (PSTxDataHead_g_FB)pTxDataHead; //Get SignalField,ServiceField,Length BBvCaculateParameter(pDevice, cbFrameLength, wCurrentRate, byPktType, (PWORD)&(pBuf->wTransmitLength_a), (PBYTE)&(pBuf->byServiceField_a), (PBYTE)&(pBuf->bySignalField_a) ); BBvCaculateParameter(pDevice, cbFrameLength, pDevice->byTopCCKBasicRate, PK_TYPE_11B, (PWORD)&(pBuf->wTransmitLength_b), (PBYTE)&(pBuf->byServiceField_b), (PBYTE)&(pBuf->bySignalField_b) ); //Get Duration and TimeStamp pBuf->wDuration_a = (WORD)s_uGetDataDuration(pDevice, DATADUR_A, cbFrameLength, byPktType, wCurrentRate, bNeedAck, uFragIdx, cbLastFragmentSize, uMACfragNum, byFBOption); //1: 2.4GHz pBuf->wDuration_b = (WORD)s_uGetDataDuration(pDevice, DATADUR_B, cbFrameLength, PK_TYPE_11B, pDevice->byTopCCKBasicRate, bNeedAck, uFragIdx, cbLastFragmentSize, uMACfragNum, byFBOption); //1: 2.4GHz pBuf->wDuration_a_f0 = (WORD)s_uGetDataDuration(pDevice, DATADUR_A_F0, cbFrameLength, byPktType, wCurrentRate, bNeedAck, uFragIdx, cbLastFragmentSize, uMACfragNum, byFBOption); //1: 2.4GHz pBuf->wDuration_a_f1 = (WORD)s_uGetDataDuration(pDevice, DATADUR_A_F1, cbFrameLength, byPktType, wCurrentRate, bNeedAck, uFragIdx, cbLastFragmentSize, uMACfragNum, byFBOption); //1: 2.4GHz pBuf->wTimeStampOff_a = wTimeStampOff[pDevice->byPreambleType%2][wCurrentRate%MAX_RATE]; pBuf->wTimeStampOff_b = wTimeStampOff[pDevice->byPreambleType%2][pDevice->byTopCCKBasicRate%MAX_RATE]; return (pBuf->wDuration_a); } //if (byFBOption == AUTO_FB_NONE) } } else if (byPktType == PK_TYPE_11A) { if ((byFBOption != AUTO_FB_NONE) && (uDMAIdx != TYPE_ATIMDMA) && (uDMAIdx != TYPE_BEACONDMA)) { // Auto Fallback PSTxDataHead_a_FB pBuf = (PSTxDataHead_a_FB)pTxDataHead; //Get SignalField,ServiceField,Length BBvCaculateParameter(pDevice, cbFrameLength, wCurrentRate, byPktType, (PWORD)&(pBuf->wTransmitLength), (PBYTE)&(pBuf->byServiceField), (PBYTE)&(pBuf->bySignalField) ); //Get Duration and TimeStampOff pBuf->wDuration = (WORD)s_uGetDataDuration(pDevice, DATADUR_A, cbFrameLength, byPktType, wCurrentRate, bNeedAck, uFragIdx, cbLastFragmentSize, uMACfragNum, byFBOption); //0: 5GHz pBuf->wDuration_f0 = (WORD)s_uGetDataDuration(pDevice, DATADUR_A_F0, cbFrameLength, byPktType, wCurrentRate, bNeedAck, uFragIdx, cbLastFragmentSize, uMACfragNum, byFBOption); //0: 5GHz pBuf->wDuration_f1 = (WORD)s_uGetDataDuration(pDevice, DATADUR_A_F1, cbFrameLength, byPktType, wCurrentRate, bNeedAck, uFragIdx, cbLastFragmentSize, uMACfragNum, byFBOption); //0: 5GHz if(uDMAIdx!=TYPE_ATIMDMA) { pBuf->wTimeStampOff = wTimeStampOff[pDevice->byPreambleType%2][wCurrentRate%MAX_RATE]; } return (pBuf->wDuration); } else { PSTxDataHead_ab pBuf = (PSTxDataHead_ab)pTxDataHead; //Get SignalField,ServiceField,Length BBvCaculateParameter(pDevice, cbFrameLength, wCurrentRate, byPktType, (PWORD)&(pBuf->wTransmitLength), (PBYTE)&(pBuf->byServiceField), (PBYTE)&(pBuf->bySignalField) ); //Get Duration and TimeStampOff pBuf->wDuration = (WORD)s_uGetDataDuration(pDevice, DATADUR_A, cbFrameLength, byPktType, wCurrentRate, bNeedAck, uFragIdx, cbLastFragmentSize, uMACfragNum, byFBOption); if(uDMAIdx!=TYPE_ATIMDMA) { pBuf->wTimeStampOff = wTimeStampOff[pDevice->byPreambleType%2][wCurrentRate%MAX_RATE]; } return (pBuf->wDuration); } } else if (byPktType == PK_TYPE_11B) { PSTxDataHead_ab pBuf = (PSTxDataHead_ab)pTxDataHead; //Get SignalField,ServiceField,Length BBvCaculateParameter(pDevice, cbFrameLength, wCurrentRate, byPktType, (PWORD)&(pBuf->wTransmitLength), (PBYTE)&(pBuf->byServiceField), (PBYTE)&(pBuf->bySignalField) ); //Get Duration and TimeStampOff pBuf->wDuration = (WORD)s_uGetDataDuration(pDevice, DATADUR_B, cbFrameLength, byPktType, wCurrentRate, bNeedAck, uFragIdx, cbLastFragmentSize, uMACfragNum, byFBOption); if (uDMAIdx != TYPE_ATIMDMA) { pBuf->wTimeStampOff = wTimeStampOff[pDevice->byPreambleType%2][wCurrentRate%MAX_RATE]; } return (pBuf->wDuration); } return 0; } static VOID s_vFillRTSHead ( IN PSDevice pDevice, IN BYTE byPktType, IN PVOID pvRTS, IN UINT cbFrameLength, IN BOOL bNeedAck, IN BOOL bDisCRC, IN PSEthernetHeader psEthHeader, IN WORD wCurrentRate, IN BYTE byFBOption ) { UINT uRTSFrameLen = 20; WORD wLen = 0x0000; if (pvRTS == NULL) return; if (bDisCRC) { // When CRCDIS bit is on, H/W forgot to generate FCS for RTS frame, // in this case we need to decrease its length by 4. uRTSFrameLen -= 4; } // Note: So far RTSHead dosen't appear in ATIM & Beacom DMA, so we don't need to take them into account. // Otherwise, we need to modified codes for them. if (byPktType == PK_TYPE_11GB || byPktType == PK_TYPE_11GA) { if (byFBOption == AUTO_FB_NONE) { PSRTS_g pBuf = (PSRTS_g)pvRTS; //Get SignalField,ServiceField,Length BBvCaculateParameter(pDevice, uRTSFrameLen, pDevice->byTopCCKBasicRate, PK_TYPE_11B, (PWORD)&(wLen), (PBYTE)&(pBuf->byServiceField_b), (PBYTE)&(pBuf->bySignalField_b) ); pBuf->wTransmitLength_b = cpu_to_le16(wLen); BBvCaculateParameter(pDevice, uRTSFrameLen, pDevice->byTopOFDMBasicRate, byPktType, (PWORD)&(wLen), (PBYTE)&(pBuf->byServiceField_a), (PBYTE)&(pBuf->bySignalField_a) ); pBuf->wTransmitLength_a = cpu_to_le16(wLen); //Get Duration pBuf->wDuration_bb = cpu_to_le16((WORD)s_uGetRTSCTSDuration(pDevice, RTSDUR_BB, cbFrameLength, PK_TYPE_11B, pDevice->byTopCCKBasicRate, bNeedAck, byFBOption)); //0:RTSDuration_bb, 1:2.4G, 1:CCKData pBuf->wDuration_aa = cpu_to_le16((WORD)s_uGetRTSCTSDuration(pDevice, RTSDUR_AA, cbFrameLength, byPktType, wCurrentRate, bNeedAck, byFBOption)); //2:RTSDuration_aa, 1:2.4G, 2,3: 2.4G OFDMData pBuf->wDuration_ba = cpu_to_le16((WORD)s_uGetRTSCTSDuration(pDevice, RTSDUR_BA, cbFrameLength, byPktType, wCurrentRate, bNeedAck, byFBOption)); //1:RTSDuration_ba, 1:2.4G, 2,3:2.4G OFDM Data pBuf->Data.wDurationID = pBuf->wDuration_aa; //Get RTS Frame body pBuf->Data.wFrameControl = TYPE_CTL_RTS;//0x00B4 if ((pDevice->eOPMode == OP_MODE_ADHOC) || (pDevice->eOPMode == OP_MODE_AP)) { memcpy(&(pBuf->Data.abyRA[0]), &(psEthHeader->abyDstAddr[0]), U_ETHER_ADDR_LEN); } else { memcpy(&(pBuf->Data.abyRA[0]), &(pDevice->abyBSSID[0]), U_ETHER_ADDR_LEN); } if (pDevice->eOPMode == OP_MODE_AP) { memcpy(&(pBuf->Data.abyTA[0]), &(pDevice->abyBSSID[0]), U_ETHER_ADDR_LEN); } else { memcpy(&(pBuf->Data.abyTA[0]), &(psEthHeader->abySrcAddr[0]), U_ETHER_ADDR_LEN); } } else { PSRTS_g_FB pBuf = (PSRTS_g_FB)pvRTS; //Get SignalField,ServiceField,Length BBvCaculateParameter(pDevice, uRTSFrameLen, pDevice->byTopCCKBasicRate, PK_TYPE_11B, (PWORD)&(wLen), (PBYTE)&(pBuf->byServiceField_b), (PBYTE)&(pBuf->bySignalField_b) ); pBuf->wTransmitLength_b = cpu_to_le16(wLen); BBvCaculateParameter(pDevice, uRTSFrameLen, pDevice->byTopOFDMBasicRate, byPktType, (PWORD)&(wLen), (PBYTE)&(pBuf->byServiceField_a), (PBYTE)&(pBuf->bySignalField_a) ); pBuf->wTransmitLength_a = cpu_to_le16(wLen); //Get Duration pBuf->wDuration_bb = cpu_to_le16((WORD)s_uGetRTSCTSDuration(pDevice, RTSDUR_BB, cbFrameLength, PK_TYPE_11B, pDevice->byTopCCKBasicRate, bNeedAck, byFBOption)); //0:RTSDuration_bb, 1:2.4G, 1:CCKData pBuf->wDuration_aa = cpu_to_le16((WORD)s_uGetRTSCTSDuration(pDevice, RTSDUR_AA, cbFrameLength, byPktType, wCurrentRate, bNeedAck, byFBOption)); //2:RTSDuration_aa, 1:2.4G, 2,3:2.4G OFDMData pBuf->wDuration_ba = cpu_to_le16((WORD)s_uGetRTSCTSDuration(pDevice, RTSDUR_BA, cbFrameLength, byPktType, wCurrentRate, bNeedAck, byFBOption)); //1:RTSDuration_ba, 1:2.4G, 2,3:2.4G OFDMData pBuf->wRTSDuration_ba_f0 = cpu_to_le16((WORD)s_uGetRTSCTSDuration(pDevice, RTSDUR_BA_F0, cbFrameLength, byPktType, wCurrentRate, bNeedAck, byFBOption)); //4:wRTSDuration_ba_f0, 1:2.4G, 1:CCKData pBuf->wRTSDuration_aa_f0 = cpu_to_le16((WORD)s_uGetRTSCTSDuration(pDevice, RTSDUR_AA_F0, cbFrameLength, byPktType, wCurrentRate, bNeedAck, byFBOption)); //5:wRTSDuration_aa_f0, 1:2.4G, 1:CCKData pBuf->wRTSDuration_ba_f1 = cpu_to_le16((WORD)s_uGetRTSCTSDuration(pDevice, RTSDUR_BA_F1, cbFrameLength, byPktType, wCurrentRate, bNeedAck, byFBOption)); //6:wRTSDuration_ba_f1, 1:2.4G, 1:CCKData pBuf->wRTSDuration_aa_f1 = cpu_to_le16((WORD)s_uGetRTSCTSDuration(pDevice, RTSDUR_AA_F1, cbFrameLength, byPktType, wCurrentRate, bNeedAck, byFBOption)); //7:wRTSDuration_aa_f1, 1:2.4G, 1:CCKData pBuf->Data.wDurationID = pBuf->wDuration_aa; //Get RTS Frame body pBuf->Data.wFrameControl = TYPE_CTL_RTS;//0x00B4 if ((pDevice->eOPMode == OP_MODE_ADHOC) || (pDevice->eOPMode == OP_MODE_AP)) { memcpy(&(pBuf->Data.abyRA[0]), &(psEthHeader->abyDstAddr[0]), U_ETHER_ADDR_LEN); } else { memcpy(&(pBuf->Data.abyRA[0]), &(pDevice->abyBSSID[0]), U_ETHER_ADDR_LEN); } if (pDevice->eOPMode == OP_MODE_AP) { memcpy(&(pBuf->Data.abyTA[0]), &(pDevice->abyBSSID[0]), U_ETHER_ADDR_LEN); } else { memcpy(&(pBuf->Data.abyTA[0]), &(psEthHeader->abySrcAddr[0]), U_ETHER_ADDR_LEN); } } // if (byFBOption == AUTO_FB_NONE) } else if (byPktType == PK_TYPE_11A) { if (byFBOption == AUTO_FB_NONE) { PSRTS_ab pBuf = (PSRTS_ab)pvRTS; //Get SignalField,ServiceField,Length BBvCaculateParameter(pDevice, uRTSFrameLen, pDevice->byTopOFDMBasicRate, byPktType, (PWORD)&(wLen), (PBYTE)&(pBuf->byServiceField), (PBYTE)&(pBuf->bySignalField) ); pBuf->wTransmitLength = cpu_to_le16(wLen); //Get Duration pBuf->wDuration = cpu_to_le16((WORD)s_uGetRTSCTSDuration(pDevice, RTSDUR_AA, cbFrameLength, byPktType, wCurrentRate, bNeedAck, byFBOption)); //0:RTSDuration_aa, 0:5G, 0: 5G OFDMData pBuf->Data.wDurationID = pBuf->wDuration; //Get RTS Frame body pBuf->Data.wFrameControl = TYPE_CTL_RTS;//0x00B4 if ((pDevice->eOPMode == OP_MODE_ADHOC) || (pDevice->eOPMode == OP_MODE_AP)) { memcpy(&(pBuf->Data.abyRA[0]), &(psEthHeader->abyDstAddr[0]), U_ETHER_ADDR_LEN); } else { memcpy(&(pBuf->Data.abyRA[0]), &(pDevice->abyBSSID[0]), U_ETHER_ADDR_LEN); } if (pDevice->eOPMode == OP_MODE_AP) { memcpy(&(pBuf->Data.abyTA[0]), &(pDevice->abyBSSID[0]), U_ETHER_ADDR_LEN); } else { memcpy(&(pBuf->Data.abyTA[0]), &(psEthHeader->abySrcAddr[0]), U_ETHER_ADDR_LEN); } } else { PSRTS_a_FB pBuf = (PSRTS_a_FB)pvRTS; //Get SignalField,ServiceField,Length BBvCaculateParameter(pDevice, uRTSFrameLen, pDevice->byTopOFDMBasicRate, byPktType, (PWORD)&(wLen), (PBYTE)&(pBuf->byServiceField), (PBYTE)&(pBuf->bySignalField) ); pBuf->wTransmitLength = cpu_to_le16(wLen); //Get Duration pBuf->wDuration = cpu_to_le16((WORD)s_uGetRTSCTSDuration(pDevice, RTSDUR_AA, cbFrameLength, byPktType, wCurrentRate, bNeedAck, byFBOption)); //0:RTSDuration_aa, 0:5G, 0: 5G OFDMData pBuf->wRTSDuration_f0 = cpu_to_le16((WORD)s_uGetRTSCTSDuration(pDevice, RTSDUR_AA_F0, cbFrameLength, byPktType, wCurrentRate, bNeedAck, byFBOption)); //5:RTSDuration_aa_f0, 0:5G, 0: 5G OFDMData pBuf->wRTSDuration_f1 = cpu_to_le16((WORD)s_uGetRTSCTSDuration(pDevice, RTSDUR_AA_F1, cbFrameLength, byPktType, wCurrentRate, bNeedAck, byFBOption)); //7:RTSDuration_aa_f1, 0:5G, 0: pBuf->Data.wDurationID = pBuf->wDuration; //Get RTS Frame body pBuf->Data.wFrameControl = TYPE_CTL_RTS;//0x00B4 if ((pDevice->eOPMode == OP_MODE_ADHOC) || (pDevice->eOPMode == OP_MODE_AP)) { memcpy(&(pBuf->Data.abyRA[0]), &(psEthHeader->abyDstAddr[0]), U_ETHER_ADDR_LEN); } else { memcpy(&(pBuf->Data.abyRA[0]), &(pDevice->abyBSSID[0]), U_ETHER_ADDR_LEN); } if (pDevice->eOPMode == OP_MODE_AP) { memcpy(&(pBuf->Data.abyTA[0]), &(pDevice->abyBSSID[0]), U_ETHER_ADDR_LEN); } else { memcpy(&(pBuf->Data.abyTA[0]), &(psEthHeader->abySrcAddr[0]), U_ETHER_ADDR_LEN); } } } else if (byPktType == PK_TYPE_11B) { PSRTS_ab pBuf = (PSRTS_ab)pvRTS; //Get SignalField,ServiceField,Length BBvCaculateParameter(pDevice, uRTSFrameLen, pDevice->byTopCCKBasicRate, PK_TYPE_11B, (PWORD)&(wLen), (PBYTE)&(pBuf->byServiceField), (PBYTE)&(pBuf->bySignalField) ); pBuf->wTransmitLength = cpu_to_le16(wLen); //Get Duration pBuf->wDuration = cpu_to_le16((WORD)s_uGetRTSCTSDuration(pDevice, RTSDUR_BB, cbFrameLength, byPktType, wCurrentRate, bNeedAck, byFBOption)); //0:RTSDuration_bb, 1:2.4G, 1:CCKData pBuf->Data.wDurationID = pBuf->wDuration; //Get RTS Frame body pBuf->Data.wFrameControl = TYPE_CTL_RTS;//0x00B4 if ((pDevice->eOPMode == OP_MODE_ADHOC) || (pDevice->eOPMode == OP_MODE_AP)) { memcpy(&(pBuf->Data.abyRA[0]), &(psEthHeader->abyDstAddr[0]), U_ETHER_ADDR_LEN); } else { memcpy(&(pBuf->Data.abyRA[0]), &(pDevice->abyBSSID[0]), U_ETHER_ADDR_LEN); } if (pDevice->eOPMode == OP_MODE_AP) { memcpy(&(pBuf->Data.abyTA[0]), &(pDevice->abyBSSID[0]), U_ETHER_ADDR_LEN); } else { memcpy(&(pBuf->Data.abyTA[0]), &(psEthHeader->abySrcAddr[0]), U_ETHER_ADDR_LEN); } } } static VOID s_vFillCTSHead ( IN PSDevice pDevice, IN UINT uDMAIdx, IN BYTE byPktType, IN PVOID pvCTS, IN UINT cbFrameLength, IN BOOL bNeedAck, IN BOOL bDisCRC, IN WORD wCurrentRate, IN BYTE byFBOption ) { UINT uCTSFrameLen = 14; WORD wLen = 0x0000; if (pvCTS == NULL) { return; } if (bDisCRC) { // When CRCDIS bit is on, H/W forgot to generate FCS for CTS frame, // in this case we need to decrease its length by 4. uCTSFrameLen -= 4; } if (byPktType == PK_TYPE_11GB || byPktType == PK_TYPE_11GA) { if (byFBOption != AUTO_FB_NONE && uDMAIdx != TYPE_ATIMDMA && uDMAIdx != TYPE_BEACONDMA) { // Auto Fall back PSCTS_FB pBuf = (PSCTS_FB)pvCTS; //Get SignalField,ServiceField,Length BBvCaculateParameter(pDevice, uCTSFrameLen, pDevice->byTopCCKBasicRate, PK_TYPE_11B, (PWORD)&(wLen), (PBYTE)&(pBuf->byServiceField_b), (PBYTE)&(pBuf->bySignalField_b) ); pBuf->wTransmitLength_b = cpu_to_le16(wLen); pBuf->wDuration_ba = (WORD)s_uGetRTSCTSDuration(pDevice, CTSDUR_BA, cbFrameLength, byPktType, wCurrentRate, bNeedAck, byFBOption); //3:CTSDuration_ba, 1:2.4G, 2,3:2.4G OFDM Data pBuf->wDuration_ba += pDevice->wCTSDuration; pBuf->wDuration_ba = cpu_to_le16(pBuf->wDuration_ba); //Get CTSDuration_ba_f0 pBuf->wCTSDuration_ba_f0 = (WORD)s_uGetRTSCTSDuration(pDevice, CTSDUR_BA_F0, cbFrameLength, byPktType, wCurrentRate, bNeedAck, byFBOption); //8:CTSDuration_ba_f0, 1:2.4G, 2,3:2.4G OFDM Data pBuf->wCTSDuration_ba_f0 += pDevice->wCTSDuration; pBuf->wCTSDuration_ba_f0 = cpu_to_le16(pBuf->wCTSDuration_ba_f0); //Get CTSDuration_ba_f1 pBuf->wCTSDuration_ba_f1 = (WORD)s_uGetRTSCTSDuration(pDevice, CTSDUR_BA_F1, cbFrameLength, byPktType, wCurrentRate, bNeedAck, byFBOption); //9:CTSDuration_ba_f1, 1:2.4G, 2,3:2.4G OFDM Data pBuf->wCTSDuration_ba_f1 += pDevice->wCTSDuration; pBuf->wCTSDuration_ba_f1 = cpu_to_le16(pBuf->wCTSDuration_ba_f1); //Get CTS Frame body pBuf->Data.wDurationID = pBuf->wDuration_ba; pBuf->Data.wFrameControl = TYPE_CTL_CTS;//0x00C4 pBuf->Data.wReserved = 0x0000; memcpy(&(pBuf->Data.abyRA[0]), &(pDevice->abyCurrentNetAddr[0]), U_ETHER_ADDR_LEN); } else { //if (byFBOption != AUTO_FB_NONE && uDMAIdx != TYPE_ATIMDMA && uDMAIdx != TYPE_BEACONDMA) PSCTS pBuf = (PSCTS)pvCTS; //Get SignalField,ServiceField,Length BBvCaculateParameter(pDevice, uCTSFrameLen, pDevice->byTopCCKBasicRate, PK_TYPE_11B, (PWORD)&(wLen), (PBYTE)&(pBuf->byServiceField_b), (PBYTE)&(pBuf->bySignalField_b) ); pBuf->wTransmitLength_b = cpu_to_le16(wLen); //Get CTSDuration_ba pBuf->wDuration_ba = cpu_to_le16((WORD)s_uGetRTSCTSDuration(pDevice, CTSDUR_BA, cbFrameLength, byPktType, wCurrentRate, bNeedAck, byFBOption)); //3:CTSDuration_ba, 1:2.4G, 2,3:2.4G OFDM Data pBuf->wDuration_ba += pDevice->wCTSDuration; pBuf->wDuration_ba = cpu_to_le16(pBuf->wDuration_ba); //Get CTS Frame body pBuf->Data.wDurationID = pBuf->wDuration_ba; pBuf->Data.wFrameControl = TYPE_CTL_CTS;//0x00C4 pBuf->Data.wReserved = 0x0000; memcpy(&(pBuf->Data.abyRA[0]), &(pDevice->abyCurrentNetAddr[0]), U_ETHER_ADDR_LEN); } } } /*+ * * Description: * Generate FIFO control for MAC & Baseband controller * * Parameters: * In: * pDevice - Pointer to adpater * pTxDataHead - Transmit Data Buffer * pTxBufHead - pTxBufHead * pvRrvTime - pvRrvTime * pvRTS - RTS Buffer * pCTS - CTS Buffer * cbFrameSize - Transmit Data Length (Hdr+Payload+FCS) * bNeedACK - If need ACK * uDMAIdx - DMA Index * Out: * none * * Return Value: none * -*/ // UINT cbFrameSize,//Hdr+Payload+FCS static VOID s_vGenerateTxParameter ( IN PSDevice pDevice, IN BYTE byPktType, IN WORD wCurrentRate, IN PVOID pTxBufHead, IN PVOID pvRrvTime, IN PVOID pvRTS, IN PVOID pvCTS, IN UINT cbFrameSize, IN BOOL bNeedACK, IN UINT uDMAIdx, IN PSEthernetHeader psEthHeader ) { UINT cbMACHdLen = WLAN_HDR_ADDR3_LEN; //24 WORD wFifoCtl; BOOL bDisCRC = FALSE; BYTE byFBOption = AUTO_FB_NONE; // WORD wCurrentRate = pDevice->wCurrentRate; //DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"s_vGenerateTxParameter...\n"); PSTxBufHead pFifoHead = (PSTxBufHead)pTxBufHead; pFifoHead->wReserved = wCurrentRate; wFifoCtl = pFifoHead->wFIFOCtl; if (wFifoCtl & FIFOCTL_CRCDIS) { bDisCRC = TRUE; } if (wFifoCtl & FIFOCTL_AUTO_FB_0) { byFBOption = AUTO_FB_0; } else if (wFifoCtl & FIFOCTL_AUTO_FB_1) { byFBOption = AUTO_FB_1; } if (pDevice->bLongHeader) cbMACHdLen = WLAN_HDR_ADDR3_LEN + 6; if (byPktType == PK_TYPE_11GB || byPktType == PK_TYPE_11GA) { if (pvRTS != NULL) { //RTS_need //Fill RsvTime if (pvRrvTime) { PSRrvTime_gRTS pBuf = (PSRrvTime_gRTS)pvRrvTime; pBuf->wRTSTxRrvTime_aa = cpu_to_le16((WORD)s_uGetRTSCTSRsvTime(pDevice, 2, byPktType, cbFrameSize, wCurrentRate));//2:RTSTxRrvTime_aa, 1:2.4GHz pBuf->wRTSTxRrvTime_ba = cpu_to_le16((WORD)s_uGetRTSCTSRsvTime(pDevice, 1, byPktType, cbFrameSize, wCurrentRate));//1:RTSTxRrvTime_ba, 1:2.4GHz pBuf->wRTSTxRrvTime_bb = cpu_to_le16((WORD)s_uGetRTSCTSRsvTime(pDevice, 0, byPktType, cbFrameSize, wCurrentRate));//0:RTSTxRrvTime_bb, 1:2.4GHz pBuf->wTxRrvTime_a = cpu_to_le16((WORD) s_uGetTxRsvTime(pDevice, byPktType, cbFrameSize, wCurrentRate, bNeedACK));//2.4G OFDM pBuf->wTxRrvTime_b = cpu_to_le16((WORD) s_uGetTxRsvTime(pDevice, PK_TYPE_11B, cbFrameSize, pDevice->byTopCCKBasicRate, bNeedACK));//1:CCK } //Fill RTS s_vFillRTSHead(pDevice, byPktType, pvRTS, cbFrameSize, bNeedACK, bDisCRC, psEthHeader, wCurrentRate, byFBOption); } else {//RTS_needless, PCF mode //Fill RsvTime if (pvRrvTime) { PSRrvTime_gCTS pBuf = (PSRrvTime_gCTS)pvRrvTime; pBuf->wTxRrvTime_a = cpu_to_le16((WORD)s_uGetTxRsvTime(pDevice, byPktType, cbFrameSize, wCurrentRate, bNeedACK));//2.4G OFDM pBuf->wTxRrvTime_b = cpu_to_le16((WORD)s_uGetTxRsvTime(pDevice, PK_TYPE_11B, cbFrameSize, pDevice->byTopCCKBasicRate, bNeedACK));//1:CCK pBuf->wCTSTxRrvTime_ba = cpu_to_le16((WORD)s_uGetRTSCTSRsvTime(pDevice, 3, byPktType, cbFrameSize, wCurrentRate));//3:CTSTxRrvTime_Ba, 1:2.4GHz } //Fill CTS s_vFillCTSHead(pDevice, uDMAIdx, byPktType, pvCTS, cbFrameSize, bNeedACK, bDisCRC, wCurrentRate, byFBOption); } } else if (byPktType == PK_TYPE_11A) { if (pvRTS != NULL) {//RTS_need, non PCF mode //Fill RsvTime if (pvRrvTime) { PSRrvTime_ab pBuf = (PSRrvTime_ab)pvRrvTime; pBuf->wRTSTxRrvTime = cpu_to_le16((WORD)s_uGetRTSCTSRsvTime(pDevice, 2, byPktType, cbFrameSize, wCurrentRate));//2:RTSTxRrvTime_aa, 0:5GHz pBuf->wTxRrvTime = cpu_to_le16((WORD)s_uGetTxRsvTime(pDevice, byPktType, cbFrameSize, wCurrentRate, bNeedACK));//0:OFDM } //Fill RTS s_vFillRTSHead(pDevice, byPktType, pvRTS, cbFrameSize, bNeedACK, bDisCRC, psEthHeader, wCurrentRate, byFBOption); } else if (pvRTS == NULL) {//RTS_needless, non PCF mode //Fill RsvTime if (pvRrvTime) { PSRrvTime_ab pBuf = (PSRrvTime_ab)pvRrvTime; pBuf->wTxRrvTime = cpu_to_le16((WORD)s_uGetTxRsvTime(pDevice, PK_TYPE_11A, cbFrameSize, wCurrentRate, bNeedACK)); //0:OFDM } } } else if (byPktType == PK_TYPE_11B) { if ((pvRTS != NULL)) {//RTS_need, non PCF mode //Fill RsvTime if (pvRrvTime) { PSRrvTime_ab pBuf = (PSRrvTime_ab)pvRrvTime; pBuf->wRTSTxRrvTime = cpu_to_le16((WORD)s_uGetRTSCTSRsvTime(pDevice, 0, byPktType, cbFrameSize, wCurrentRate));//0:RTSTxRrvTime_bb, 1:2.4GHz pBuf->wTxRrvTime = cpu_to_le16((WORD)s_uGetTxRsvTime(pDevice, PK_TYPE_11B, cbFrameSize, wCurrentRate, bNeedACK));//1:CCK } //Fill RTS s_vFillRTSHead(pDevice, byPktType, pvRTS, cbFrameSize, bNeedACK, bDisCRC, psEthHeader, wCurrentRate, byFBOption); } else { //RTS_needless, non PCF mode //Fill RsvTime if (pvRrvTime) { PSRrvTime_ab pBuf = (PSRrvTime_ab)pvRrvTime; pBuf->wTxRrvTime = cpu_to_le16((WORD)s_uGetTxRsvTime(pDevice, PK_TYPE_11B, cbFrameSize, wCurrentRate, bNeedACK)); //1:CCK } } } //DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"s_vGenerateTxParameter END.\n"); } /* PBYTE pbyBuffer,//point to pTxBufHead WORD wFragType,//00:Non-Frag, 01:Start, 02:Mid, 03:Last UINT cbFragmentSize,//Hdr+payoad+FCS */ BOOL s_bPacketToWirelessUsb( IN PSDevice pDevice, IN BYTE byPktType, IN PBYTE usbPacketBuf, IN BOOL bNeedEncryption, IN UINT uSkbPacketLen, IN UINT uDMAIdx, IN PSEthernetHeader psEthHeader, IN PBYTE pPacket, IN PSKeyItem pTransmitKey, IN UINT uNodeIndex, IN WORD wCurrentRate, OUT UINT *pcbHeaderLen, OUT UINT *pcbTotalLen ) { PSMgmtObject pMgmt = &(pDevice->sMgmtObj); UINT cbFrameSize,cbFrameBodySize; PTX_BUFFER pTxBufHead; UINT cb802_1_H_len; UINT cbIVlen=0,cbICVlen=0,cbMIClen=0,cbMACHdLen=0,cbFCSlen=4; UINT cbMICHDR = 0; BOOL bNeedACK,bRTS; PBYTE pbyType,pbyMacHdr,pbyIVHead,pbyPayloadHead,pbyTxBufferAddr; BYTE abySNAP_RFC1042[6] = {0xAA, 0xAA, 0x03, 0x00, 0x00, 0x00}; BYTE abySNAP_Bridgetunnel[6] = {0xAA, 0xAA, 0x03, 0x00, 0x00, 0xF8}; UINT uDuration; UINT cbHeaderLength= 0,uPadding = 0; PVOID pvRrvTime; PSMICHDRHead pMICHDR; PVOID pvRTS; PVOID pvCTS; PVOID pvTxDataHd; BYTE byFBOption = AUTO_FB_NONE,byFragType; WORD wTxBufSize; DWORD dwMICKey0,dwMICKey1,dwMIC_Priority,dwCRC; PDWORD pdwMIC_L,pdwMIC_R; BOOL bSoftWEP = FALSE; pvRrvTime = pMICHDR = pvRTS = pvCTS = pvTxDataHd = NULL; if ((bNeedEncryption) && (pTransmitKey != NULL)) { if (((PSKeyTable) (pTransmitKey->pvKeyTable))->bSoftWEP == TRUE) { // WEP 256 bSoftWEP = TRUE; } } pTxBufHead = (PTX_BUFFER) usbPacketBuf; memset(pTxBufHead, 0, sizeof(TX_BUFFER)); // Get pkt type if (ntohs(psEthHeader->wType) > MAX_DATA_LEN) { if (pDevice->dwDiagRefCount == 0) { cb802_1_H_len = 8; } else { cb802_1_H_len = 2; } } else { cb802_1_H_len = 0; } cbFrameBodySize = uSkbPacketLen - U_HEADER_LEN + cb802_1_H_len; //Set packet type pTxBufHead->wFIFOCtl |= (WORD)(byPktType<<8); if (pDevice->dwDiagRefCount != 0) { bNeedACK = FALSE; pTxBufHead->wFIFOCtl = pTxBufHead->wFIFOCtl & (~FIFOCTL_NEEDACK); } else { //if (pDevice->dwDiagRefCount != 0) { if ((pDevice->eOPMode == OP_MODE_ADHOC) || (pDevice->eOPMode == OP_MODE_AP)) { if (IS_MULTICAST_ADDRESS(&(psEthHeader->abyDstAddr[0])) || IS_BROADCAST_ADDRESS(&(psEthHeader->abyDstAddr[0]))) { bNeedACK = FALSE; pTxBufHead->wFIFOCtl = pTxBufHead->wFIFOCtl & (~FIFOCTL_NEEDACK); } else { bNeedACK = TRUE; pTxBufHead->wFIFOCtl |= FIFOCTL_NEEDACK; } } else { // MSDUs in Infra mode always need ACK bNeedACK = TRUE; pTxBufHead->wFIFOCtl |= FIFOCTL_NEEDACK; } } //if (pDevice->dwDiagRefCount != 0) { pTxBufHead->wTimeStamp = DEFAULT_MSDU_LIFETIME_RES_64us; //Set FIFOCTL_LHEAD if (pDevice->bLongHeader) pTxBufHead->wFIFOCtl |= FIFOCTL_LHEAD; if (pDevice->bSoftwareGenCrcErr) { pTxBufHead->wFIFOCtl |= FIFOCTL_CRCDIS; // set tx descriptors to NO hardware CRC } //Set FRAGCTL_MACHDCNT if (pDevice->bLongHeader) { cbMACHdLen = WLAN_HDR_ADDR3_LEN + 6; } else { cbMACHdLen = WLAN_HDR_ADDR3_LEN; } pTxBufHead->wFragCtl |= (WORD)(cbMACHdLen << 10); //Set FIFOCTL_GrpAckPolicy if (pDevice->bGrpAckPolicy == TRUE) {//0000 0100 0000 0000 pTxBufHead->wFIFOCtl |= FIFOCTL_GRPACK; } //Set Auto Fallback Ctl if (wCurrentRate >= RATE_18M) { if (pDevice->byAutoFBCtrl == AUTO_FB_0) { pTxBufHead->wFIFOCtl |= FIFOCTL_AUTO_FB_0; byFBOption = AUTO_FB_0; } else if (pDevice->byAutoFBCtrl == AUTO_FB_1) { pTxBufHead->wFIFOCtl |= FIFOCTL_AUTO_FB_1; byFBOption = AUTO_FB_1; } } if (bSoftWEP != TRUE) { if ((bNeedEncryption) && (pTransmitKey != NULL)) { //WEP enabled if (pTransmitKey->byCipherSuite == KEY_CTL_WEP) { //WEP40 or WEP104 pTxBufHead->wFragCtl |= FRAGCTL_LEGACY; } if (pTransmitKey->byCipherSuite == KEY_CTL_TKIP) { DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Tx Set wFragCtl == FRAGCTL_TKIP\n"); pTxBufHead->wFragCtl |= FRAGCTL_TKIP; } else if (pTransmitKey->byCipherSuite == KEY_CTL_CCMP) { //CCMP pTxBufHead->wFragCtl |= FRAGCTL_AES; } } } if ((bNeedEncryption) && (pTransmitKey != NULL)) { if (pTransmitKey->byCipherSuite == KEY_CTL_WEP) { cbIVlen = 4; cbICVlen = 4; } else if (pTransmitKey->byCipherSuite == KEY_CTL_TKIP) { cbIVlen = 8;//IV+ExtIV cbMIClen = 8; cbICVlen = 4; } if (pTransmitKey->byCipherSuite == KEY_CTL_CCMP) { cbIVlen = 8;//RSN Header cbICVlen = 8;//MIC cbMICHDR = sizeof(SMICHDRHead); } if (bSoftWEP == FALSE) { //MAC Header should be padding 0 to DW alignment. uPadding = 4 - (cbMACHdLen%4); uPadding %= 4; } } cbFrameSize = cbMACHdLen + cbIVlen + (cbFrameBodySize + cbMIClen) + cbICVlen + cbFCSlen; if ( (bNeedACK == FALSE) ||(cbFrameSize < pDevice->wRTSThreshold) ) { bRTS = FALSE; } else { bRTS = TRUE; pTxBufHead->wFIFOCtl |= (FIFOCTL_RTS | FIFOCTL_LRETRY); } pbyTxBufferAddr = (PBYTE) &(pTxBufHead->adwTxKey[0]); wTxBufSize = sizeof(STxBufHead); if (byPktType == PK_TYPE_11GB || byPktType == PK_TYPE_11GA) {//802.11g packet if (byFBOption == AUTO_FB_NONE) { if (bRTS == TRUE) {//RTS_need pvRrvTime = (PSRrvTime_gRTS) (pbyTxBufferAddr + wTxBufSize); pMICHDR = (PSMICHDRHead) (pbyTxBufferAddr + wTxBufSize + sizeof(SRrvTime_gRTS)); pvRTS = (PSRTS_g) (pbyTxBufferAddr + wTxBufSize + sizeof(SRrvTime_gRTS) + cbMICHDR); pvCTS = NULL; pvTxDataHd = (PSTxDataHead_g) (pbyTxBufferAddr + wTxBufSize + sizeof(SRrvTime_gRTS) + cbMICHDR + sizeof(SRTS_g)); cbHeaderLength = wTxBufSize + sizeof(SRrvTime_gRTS) + cbMICHDR + sizeof(SRTS_g) + sizeof(STxDataHead_g); } else { //RTS_needless pvRrvTime = (PSRrvTime_gCTS) (pbyTxBufferAddr + wTxBufSize); pMICHDR = (PSMICHDRHead) (pbyTxBufferAddr + wTxBufSize + sizeof(SRrvTime_gCTS)); pvRTS = NULL; pvCTS = (PSCTS) (pbyTxBufferAddr + wTxBufSize + sizeof(SRrvTime_gCTS) + cbMICHDR); pvTxDataHd = (PSTxDataHead_g) (pbyTxBufferAddr + wTxBufSize + sizeof(SRrvTime_gCTS) + cbMICHDR + sizeof(SCTS)); cbHeaderLength = wTxBufSize + sizeof(SRrvTime_gCTS) + cbMICHDR + sizeof(SCTS) + sizeof(STxDataHead_g); } } else { // Auto Fall Back if (bRTS == TRUE) {//RTS_need pvRrvTime = (PSRrvTime_gRTS) (pbyTxBufferAddr + wTxBufSize); pMICHDR = (PSMICHDRHead) (pbyTxBufferAddr + wTxBufSize + sizeof(SRrvTime_gRTS)); pvRTS = (PSRTS_g_FB) (pbyTxBufferAddr + wTxBufSize + sizeof(SRrvTime_gRTS) + cbMICHDR); pvCTS = NULL; pvTxDataHd = (PSTxDataHead_g_FB) (pbyTxBufferAddr + wTxBufSize + sizeof(SRrvTime_gRTS) + cbMICHDR + sizeof(SRTS_g_FB)); cbHeaderLength = wTxBufSize + sizeof(SRrvTime_gRTS) + cbMICHDR + sizeof(SRTS_g_FB) + sizeof(STxDataHead_g_FB); } else if (bRTS == FALSE) { //RTS_needless pvRrvTime = (PSRrvTime_gCTS) (pbyTxBufferAddr + wTxBufSize); pMICHDR = (PSMICHDRHead) (pbyTxBufferAddr + wTxBufSize + sizeof(SRrvTime_gCTS)); pvRTS = NULL; pvCTS = (PSCTS_FB) (pbyTxBufferAddr + wTxBufSize + sizeof(SRrvTime_gCTS) + cbMICHDR); pvTxDataHd = (PSTxDataHead_g_FB) (pbyTxBufferAddr + wTxBufSize + sizeof(SRrvTime_gCTS) + cbMICHDR + sizeof(SCTS_FB)); cbHeaderLength = wTxBufSize + sizeof(SRrvTime_gCTS) + cbMICHDR + sizeof(SCTS_FB) + sizeof(STxDataHead_g_FB); } } // Auto Fall Back } else {//802.11a/b packet if (byFBOption == AUTO_FB_NONE) { if (bRTS == TRUE) {//RTS_need pvRrvTime = (PSRrvTime_ab) (pbyTxBufferAddr + wTxBufSize); pMICHDR = (PSMICHDRHead) (pbyTxBufferAddr + wTxBufSize + sizeof(SRrvTime_ab)); pvRTS = (PSRTS_ab) (pbyTxBufferAddr + wTxBufSize + sizeof(SRrvTime_ab) + cbMICHDR); pvCTS = NULL; pvTxDataHd = (PSTxDataHead_ab) (pbyTxBufferAddr + wTxBufSize + sizeof(SRrvTime_ab) + cbMICHDR + sizeof(SRTS_ab)); cbHeaderLength = wTxBufSize + sizeof(PSRrvTime_ab) + cbMICHDR + sizeof(SRTS_ab) + sizeof(STxDataHead_ab); } else if (bRTS == FALSE) { //RTS_needless, no MICHDR pvRrvTime = (PSRrvTime_ab) (pbyTxBufferAddr + wTxBufSize); pMICHDR = (PSMICHDRHead) (pbyTxBufferAddr + wTxBufSize + sizeof(SRrvTime_ab)); pvRTS = NULL; pvCTS = NULL; pvTxDataHd = (PSTxDataHead_ab) (pbyTxBufferAddr + wTxBufSize + sizeof(SRrvTime_ab) + cbMICHDR); cbHeaderLength = wTxBufSize + sizeof(SRrvTime_ab) + cbMICHDR + sizeof(STxDataHead_ab); } } else { // Auto Fall Back if (bRTS == TRUE) {//RTS_need pvRrvTime = (PSRrvTime_ab) (pbyTxBufferAddr + wTxBufSize); pMICHDR = (PSMICHDRHead) (pbyTxBufferAddr + wTxBufSize + sizeof(SRrvTime_ab)); pvRTS = (PSRTS_a_FB) (pbyTxBufferAddr + wTxBufSize + sizeof(SRrvTime_ab) + cbMICHDR); pvCTS = NULL; pvTxDataHd = (PSTxDataHead_a_FB) (pbyTxBufferAddr + wTxBufSize + sizeof(SRrvTime_ab) + cbMICHDR + sizeof(SRTS_a_FB)); cbHeaderLength = wTxBufSize + sizeof(PSRrvTime_ab) + cbMICHDR + sizeof(SRTS_a_FB) + sizeof(STxDataHead_a_FB); } else if (bRTS == FALSE) { //RTS_needless pvRrvTime = (PSRrvTime_ab) (pbyTxBufferAddr + wTxBufSize); pMICHDR = (PSMICHDRHead) (pbyTxBufferAddr + wTxBufSize + sizeof(SRrvTime_ab)); pvRTS = NULL; pvCTS = NULL; pvTxDataHd = (PSTxDataHead_a_FB) (pbyTxBufferAddr + wTxBufSize + sizeof(SRrvTime_ab) + cbMICHDR); cbHeaderLength = wTxBufSize + sizeof(SRrvTime_ab) + cbMICHDR + sizeof(STxDataHead_a_FB); } } // Auto Fall Back } pbyMacHdr = (PBYTE)(pbyTxBufferAddr + cbHeaderLength); pbyIVHead = (PBYTE)(pbyMacHdr + cbMACHdLen + uPadding); pbyPayloadHead = (PBYTE)(pbyMacHdr + cbMACHdLen + uPadding + cbIVlen); //========================= // No Fragmentation //========================= DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"No Fragmentation...\n"); byFragType = FRAGCTL_NONFRAG; //uDMAIdx = TYPE_AC0DMA; //pTxBufHead = (PSTxBufHead) &(pTxBufHead->adwTxKey[0]); //Fill FIFO,RrvTime,RTS,and CTS s_vGenerateTxParameter(pDevice, byPktType, wCurrentRate, (PVOID)pbyTxBufferAddr, pvRrvTime, pvRTS, pvCTS, cbFrameSize, bNeedACK, uDMAIdx, psEthHeader); //Fill DataHead uDuration = s_uFillDataHead(pDevice, byPktType, wCurrentRate, pvTxDataHd, cbFrameSize, uDMAIdx, bNeedACK, 0, 0, 1/*uMACfragNum*/, byFBOption); // Generate TX MAC Header s_vGenerateMACHeader(pDevice, pbyMacHdr, (WORD)uDuration, psEthHeader, bNeedEncryption, byFragType, uDMAIdx, 0); if (bNeedEncryption == TRUE) { //Fill TXKEY s_vFillTxKey(pDevice, (PBYTE)(pTxBufHead->adwTxKey), pbyIVHead, pTransmitKey, pbyMacHdr, (WORD)cbFrameBodySize, (PBYTE)pMICHDR); if (pDevice->bEnableHostWEP) { pMgmt->sNodeDBTable[uNodeIndex].dwTSC47_16 = pTransmitKey->dwTSC47_16; pMgmt->sNodeDBTable[uNodeIndex].wTSC15_0 = pTransmitKey->wTSC15_0; } } // 802.1H if (ntohs(psEthHeader->wType) > MAX_DATA_LEN) { if (pDevice->dwDiagRefCount == 0) { if ( (psEthHeader->wType == TYPE_PKT_IPX) || (psEthHeader->wType == cpu_to_le16(0xF380))) { memcpy((PBYTE) (pbyPayloadHead), &abySNAP_Bridgetunnel[0], 6); } else { memcpy((PBYTE) (pbyPayloadHead), &abySNAP_RFC1042[0], 6); } pbyType = (PBYTE) (pbyPayloadHead + 6); memcpy(pbyType, &(psEthHeader->wType), sizeof(WORD)); } else { memcpy((PBYTE) (pbyPayloadHead), &(psEthHeader->wType), sizeof(WORD)); } } if (pPacket != NULL) { // Copy the Packet into a tx Buffer memcpy((pbyPayloadHead + cb802_1_H_len), (pPacket + U_HEADER_LEN), uSkbPacketLen - U_HEADER_LEN ); } else { // while bRelayPacketSend psEthHeader is point to header+payload memcpy((pbyPayloadHead + cb802_1_H_len), ((PBYTE)psEthHeader)+U_HEADER_LEN, uSkbPacketLen - U_HEADER_LEN); } ASSERT(uLength == cbNdisBodySize); if ((bNeedEncryption == TRUE) && (pTransmitKey != NULL) && (pTransmitKey->byCipherSuite == KEY_CTL_TKIP)) { /////////////////////////////////////////////////////////////////// if (pDevice->sMgmtObj.eAuthenMode == WMAC_AUTH_WPANONE) { dwMICKey0 = *(PDWORD)(&pTransmitKey->abyKey[16]); dwMICKey1 = *(PDWORD)(&pTransmitKey->abyKey[20]); } else if ((pTransmitKey->dwKeyIndex & AUTHENTICATOR_KEY) != 0) { dwMICKey0 = *(PDWORD)(&pTransmitKey->abyKey[16]); dwMICKey1 = *(PDWORD)(&pTransmitKey->abyKey[20]); } else { dwMICKey0 = *(PDWORD)(&pTransmitKey->abyKey[24]); dwMICKey1 = *(PDWORD)(&pTransmitKey->abyKey[28]); } // DO Software Michael MIC_vInit(dwMICKey0, dwMICKey1); MIC_vAppend((PBYTE)&(psEthHeader->abyDstAddr[0]), 12); dwMIC_Priority = 0; MIC_vAppend((PBYTE)&dwMIC_Priority, 4); DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"MIC KEY: %lX, %lX\n", dwMICKey0, dwMICKey1); /////////////////////////////////////////////////////////////////// //DBG_PRN_GRP12(("Length:%d, %d\n", cbFrameBodySize, uFromHDtoPLDLength)); //for (ii = 0; ii < cbFrameBodySize; ii++) { // DBG_PRN_GRP12(("%02x ", *((PBYTE)((pbyPayloadHead + cb802_1_H_len) + ii)))); //} //DBG_PRN_GRP12(("\n\n\n")); MIC_vAppend(pbyPayloadHead, cbFrameBodySize); pdwMIC_L = (PDWORD)(pbyPayloadHead + cbFrameBodySize); pdwMIC_R = (PDWORD)(pbyPayloadHead + cbFrameBodySize + 4); MIC_vGetMIC(pdwMIC_L, pdwMIC_R); MIC_vUnInit(); if (pDevice->bTxMICFail == TRUE) { *pdwMIC_L = 0; *pdwMIC_R = 0; pDevice->bTxMICFail = FALSE; } //DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"uLength: %d, %d\n", uLength, cbFrameBodySize); //DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"cbReqCount:%d, %d, %d, %d\n", cbReqCount, cbHeaderLength, uPadding, cbIVlen); //DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"MIC:%lX, %lX\n", *pdwMIC_L, *pdwMIC_R); } if (bSoftWEP == TRUE) { s_vSWencryption(pDevice, pTransmitKey, (pbyPayloadHead), (WORD)(cbFrameBodySize + cbMIClen)); } else if ( ((pDevice->eEncryptionStatus == Ndis802_11Encryption1Enabled) && (bNeedEncryption == TRUE)) || ((pDevice->eEncryptionStatus == Ndis802_11Encryption2Enabled) && (bNeedEncryption == TRUE)) || ((pDevice->eEncryptionStatus == Ndis802_11Encryption3Enabled) && (bNeedEncryption == TRUE)) ) { cbFrameSize -= cbICVlen; } if (pDevice->bSoftwareGenCrcErr == TRUE) { UINT cbLen; PDWORD pdwCRC; dwCRC = 0xFFFFFFFFL; cbLen = cbFrameSize - cbFCSlen; // calculate CRC, and wrtie CRC value to end of TD dwCRC = CRCdwGetCrc32Ex(pbyMacHdr, cbLen, dwCRC); pdwCRC = (PDWORD)(pbyMacHdr + cbLen); // finally, we must invert dwCRC to get the correct answer *pdwCRC = ~dwCRC; // Force Error *pdwCRC -= 1; } else { cbFrameSize -= cbFCSlen; } *pcbHeaderLen = cbHeaderLength; *pcbTotalLen = cbHeaderLength + cbFrameSize ; //Set FragCtl in TxBufferHead pTxBufHead->wFragCtl |= (WORD)byFragType; return TRUE; } /*+ * * Description: * Translate 802.3 to 802.11 header * * Parameters: * In: * pDevice - Pointer to adpater * dwTxBufferAddr - Transmit Buffer * pPacket - Packet from upper layer * cbPacketSize - Transmit Data Length * Out: * pcbHeadSize - Header size of MAC&Baseband control and 802.11 Header * pcbAppendPayload - size of append payload for 802.1H translation * * Return Value: none * -*/ VOID s_vGenerateMACHeader ( IN PSDevice pDevice, IN PBYTE pbyBufferAddr, IN WORD wDuration, IN PSEthernetHeader psEthHeader, IN BOOL bNeedEncrypt, IN WORD wFragType, IN UINT uDMAIdx, IN UINT uFragIdx ) { PS802_11Header pMACHeader = (PS802_11Header)pbyBufferAddr; memset(pMACHeader, 0, (sizeof(S802_11Header))); //- sizeof(pMACHeader->dwIV))); if (uDMAIdx == TYPE_ATIMDMA) { pMACHeader->wFrameCtl = TYPE_802_11_ATIM; } else { pMACHeader->wFrameCtl = TYPE_802_11_DATA; } if (pDevice->eOPMode == OP_MODE_AP) { memcpy(&(pMACHeader->abyAddr1[0]), &(psEthHeader->abyDstAddr[0]), U_ETHER_ADDR_LEN); memcpy(&(pMACHeader->abyAddr2[0]), &(pDevice->abyBSSID[0]), U_ETHER_ADDR_LEN); memcpy(&(pMACHeader->abyAddr3[0]), &(psEthHeader->abySrcAddr[0]), U_ETHER_ADDR_LEN); pMACHeader->wFrameCtl |= FC_FROMDS; } else { if (pDevice->eOPMode == OP_MODE_ADHOC) { memcpy(&(pMACHeader->abyAddr1[0]), &(psEthHeader->abyDstAddr[0]), U_ETHER_ADDR_LEN); memcpy(&(pMACHeader->abyAddr2[0]), &(psEthHeader->abySrcAddr[0]), U_ETHER_ADDR_LEN); memcpy(&(pMACHeader->abyAddr3[0]), &(pDevice->abyBSSID[0]), U_ETHER_ADDR_LEN); } else { memcpy(&(pMACHeader->abyAddr3[0]), &(psEthHeader->abyDstAddr[0]), U_ETHER_ADDR_LEN); memcpy(&(pMACHeader->abyAddr2[0]), &(psEthHeader->abySrcAddr[0]), U_ETHER_ADDR_LEN); memcpy(&(pMACHeader->abyAddr1[0]), &(pDevice->abyBSSID[0]), U_ETHER_ADDR_LEN); pMACHeader->wFrameCtl |= FC_TODS; } } if (bNeedEncrypt) pMACHeader->wFrameCtl |= cpu_to_le16((WORD)WLAN_SET_FC_ISWEP(1)); pMACHeader->wDurationID = cpu_to_le16(wDuration); if (pDevice->bLongHeader) { PWLAN_80211HDR_A4 pMACA4Header = (PWLAN_80211HDR_A4) pbyBufferAddr; pMACHeader->wFrameCtl |= (FC_TODS | FC_FROMDS); memcpy(pMACA4Header->abyAddr4, pDevice->abyBSSID, WLAN_ADDR_LEN); } pMACHeader->wSeqCtl = cpu_to_le16(pDevice->wSeqCounter << 4); //Set FragNumber in Sequence Control pMACHeader->wSeqCtl |= cpu_to_le16((WORD)uFragIdx); if ((wFragType == FRAGCTL_ENDFRAG) || (wFragType == FRAGCTL_NONFRAG)) { pDevice->wSeqCounter++; if (pDevice->wSeqCounter > 0x0fff) pDevice->wSeqCounter = 0; } if ((wFragType == FRAGCTL_STAFRAG) || (wFragType == FRAGCTL_MIDFRAG)) { //StartFrag or MidFrag pMACHeader->wFrameCtl |= FC_MOREFRAG; } } /*+ * * Description: * Request instructs a MAC to transmit a 802.11 management packet through * the adapter onto the medium. * * Parameters: * In: * hDeviceContext - Pointer to the adapter * pPacket - A pointer to a descriptor for the packet to transmit * Out: * none * * Return Value: CMD_STATUS_PENDING if MAC Tx resource avaliable; otherwise FALSE * -*/ CMD_STATUS csMgmt_xmit( IN PSDevice pDevice, IN PSTxMgmtPacket pPacket ) { BYTE byPktType; PBYTE pbyTxBufferAddr; PVOID pvRTS; PSCTS pCTS; PVOID pvTxDataHd; UINT uDuration; UINT cbReqCount; PS802_11Header pMACHeader; UINT cbHeaderSize; UINT cbFrameBodySize; BOOL bNeedACK; BOOL bIsPSPOLL = FALSE; PSTxBufHead pTxBufHead; UINT cbFrameSize; UINT cbIVlen = 0; UINT cbICVlen = 0; UINT cbMIClen = 0; UINT cbFCSlen = 4; UINT uPadding = 0; WORD wTxBufSize; UINT cbMacHdLen; SEthernetHeader sEthHeader; PVOID pvRrvTime; PVOID pMICHDR; PSMgmtObject pMgmt = &(pDevice->sMgmtObj); WORD wCurrentRate = RATE_1M; PTX_BUFFER pTX_Buffer; PUSB_SEND_CONTEXT pContext; pContext = (PUSB_SEND_CONTEXT)s_vGetFreeContext(pDevice); if (NULL == pContext) { DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"ManagementSend TX...NO CONTEXT!\n"); return CMD_STATUS_RESOURCES; } pTX_Buffer = (PTX_BUFFER) (&pContext->Data[0]); pbyTxBufferAddr = (PBYTE)&(pTX_Buffer->adwTxKey[0]); cbFrameBodySize = pPacket->cbPayloadLen; pTxBufHead = (PSTxBufHead) pbyTxBufferAddr; wTxBufSize = sizeof(STxBufHead); memset(pTxBufHead, 0, wTxBufSize); if (pDevice->byBBType == BB_TYPE_11A) { wCurrentRate = RATE_6M; byPktType = PK_TYPE_11A; } else { wCurrentRate = RATE_1M; byPktType = PK_TYPE_11B; } // SetPower will cause error power TX state for OFDM Date packet in TX buffer. // 2004.11.11 Kyle -- Using OFDM power to tx MngPkt will decrease the connection capability. // And cmd timer will wait data pkt TX finish before scanning so it's OK // to set power here. if (pMgmt->eScanState != WMAC_NO_SCANNING) { RFbSetPower(pDevice, wCurrentRate, pDevice->byCurrentCh); } else { RFbSetPower(pDevice, wCurrentRate, pMgmt->uCurrChannel); } pDevice->wCurrentRate = wCurrentRate; //Set packet type if (byPktType == PK_TYPE_11A) {//0000 0000 0000 0000 pTxBufHead->wFIFOCtl = 0; } else if (byPktType == PK_TYPE_11B) {//0000 0001 0000 0000 pTxBufHead->wFIFOCtl |= FIFOCTL_11B; } else if (byPktType == PK_TYPE_11GB) {//0000 0010 0000 0000 pTxBufHead->wFIFOCtl |= FIFOCTL_11GB; } else if (byPktType == PK_TYPE_11GA) {//0000 0011 0000 0000 pTxBufHead->wFIFOCtl |= FIFOCTL_11GA; } pTxBufHead->wFIFOCtl |= FIFOCTL_TMOEN; pTxBufHead->wTimeStamp = cpu_to_le16(DEFAULT_MGN_LIFETIME_RES_64us); if (IS_MULTICAST_ADDRESS(&(pPacket->p80211Header->sA3.abyAddr1[0])) || IS_BROADCAST_ADDRESS(&(pPacket->p80211Header->sA3.abyAddr1[0]))) { bNeedACK = FALSE; } else { bNeedACK = TRUE; pTxBufHead->wFIFOCtl |= FIFOCTL_NEEDACK; }; if ((pMgmt->eCurrMode == WMAC_MODE_ESS_AP) || (pMgmt->eCurrMode == WMAC_MODE_IBSS_STA) ) { pTxBufHead->wFIFOCtl |= FIFOCTL_LRETRY; //Set Preamble type always long //pDevice->byPreambleType = PREAMBLE_LONG; // probe-response don't retry //if ((pPacket->p80211Header->sA4.wFrameCtl & TYPE_SUBTYPE_MASK) == TYPE_MGMT_PROBE_RSP) { // bNeedACK = FALSE; // pTxBufHead->wFIFOCtl &= (~FIFOCTL_NEEDACK); //} } pTxBufHead->wFIFOCtl |= (FIFOCTL_GENINT | FIFOCTL_ISDMA0); if ((pPacket->p80211Header->sA4.wFrameCtl & TYPE_SUBTYPE_MASK) == TYPE_CTL_PSPOLL) { bIsPSPOLL = TRUE; cbMacHdLen = WLAN_HDR_ADDR2_LEN; } else { cbMacHdLen = WLAN_HDR_ADDR3_LEN; } //Set FRAGCTL_MACHDCNT pTxBufHead->wFragCtl |= cpu_to_le16((WORD)(cbMacHdLen << 10)); // Notes: // Although spec says MMPDU can be fragmented; In most case, // no one will send a MMPDU under fragmentation. With RTS may occur. pDevice->bAES = FALSE; //Set FRAGCTL_WEPTYP if (WLAN_GET_FC_ISWEP(pPacket->p80211Header->sA4.wFrameCtl) != 0) { if (pDevice->eEncryptionStatus == Ndis802_11Encryption1Enabled) { cbIVlen = 4; cbICVlen = 4; pTxBufHead->wFragCtl |= FRAGCTL_LEGACY; } else if (pDevice->eEncryptionStatus == Ndis802_11Encryption2Enabled) { cbIVlen = 8;//IV+ExtIV cbMIClen = 8; cbICVlen = 4; pTxBufHead->wFragCtl |= FRAGCTL_TKIP; //We need to get seed here for filling TxKey entry. //TKIPvMixKey(pTransmitKey->abyKey, pDevice->abyCurrentNetAddr, // pTransmitKey->wTSC15_0, pTransmitKey->dwTSC47_16, pDevice->abyPRNG); } else if (pDevice->eEncryptionStatus == Ndis802_11Encryption3Enabled) { cbIVlen = 8;//RSN Header cbICVlen = 8;//MIC pTxBufHead->wFragCtl |= FRAGCTL_AES; pDevice->bAES = TRUE; } //MAC Header should be padding 0 to DW alignment. uPadding = 4 - (cbMacHdLen%4); uPadding %= 4; } cbFrameSize = cbMacHdLen + cbFrameBodySize + cbIVlen + cbMIClen + cbICVlen + cbFCSlen; //Set FIFOCTL_GrpAckPolicy if (pDevice->bGrpAckPolicy == TRUE) {//0000 0100 0000 0000 pTxBufHead->wFIFOCtl |= FIFOCTL_GRPACK; } //the rest of pTxBufHead->wFragCtl:FragTyp will be set later in s_vFillFragParameter() //Set RrvTime/RTS/CTS Buffer if (byPktType == PK_TYPE_11GB || byPktType == PK_TYPE_11GA) {//802.11g packet pvRrvTime = (PSRrvTime_gCTS) (pbyTxBufferAddr + wTxBufSize); pMICHDR = NULL; pvRTS = NULL; pCTS = (PSCTS) (pbyTxBufferAddr + wTxBufSize + sizeof(SRrvTime_gCTS)); pvTxDataHd = (PSTxDataHead_g) (pbyTxBufferAddr + wTxBufSize + sizeof(SRrvTime_gCTS) + sizeof(SCTS)); cbHeaderSize = wTxBufSize + sizeof(SRrvTime_gCTS) + sizeof(SCTS) + sizeof(STxDataHead_g); } else { // 802.11a/b packet pvRrvTime = (PSRrvTime_ab) (pbyTxBufferAddr + wTxBufSize); pMICHDR = NULL; pvRTS = NULL; pCTS = NULL; pvTxDataHd = (PSTxDataHead_ab) (pbyTxBufferAddr + wTxBufSize + sizeof(SRrvTime_ab)); cbHeaderSize = wTxBufSize + sizeof(SRrvTime_ab) + sizeof(STxDataHead_ab); } memset((PVOID)(pbyTxBufferAddr + wTxBufSize), 0, (cbHeaderSize - wTxBufSize)); memcpy(&(sEthHeader.abyDstAddr[0]), &(pPacket->p80211Header->sA3.abyAddr1[0]), U_ETHER_ADDR_LEN); memcpy(&(sEthHeader.abySrcAddr[0]), &(pPacket->p80211Header->sA3.abyAddr2[0]), U_ETHER_ADDR_LEN); //========================= // No Fragmentation //========================= pTxBufHead->wFragCtl |= (WORD)FRAGCTL_NONFRAG; //Fill FIFO,RrvTime,RTS,and CTS s_vGenerateTxParameter(pDevice, byPktType, wCurrentRate, pbyTxBufferAddr, pvRrvTime, pvRTS, pCTS, cbFrameSize, bNeedACK, TYPE_TXDMA0, &sEthHeader); //Fill DataHead uDuration = s_uFillDataHead(pDevice, byPktType, wCurrentRate, pvTxDataHd, cbFrameSize, TYPE_TXDMA0, bNeedACK, 0, 0, 1, AUTO_FB_NONE); pMACHeader = (PS802_11Header) (pbyTxBufferAddr + cbHeaderSize); cbReqCount = cbHeaderSize + cbMacHdLen + uPadding + cbIVlen + cbFrameBodySize; if (WLAN_GET_FC_ISWEP(pPacket->p80211Header->sA4.wFrameCtl) != 0) { PBYTE pbyIVHead; PBYTE pbyPayloadHead; PBYTE pbyBSSID; PSKeyItem pTransmitKey = NULL; pbyIVHead = (PBYTE)(pbyTxBufferAddr + cbHeaderSize + cbMacHdLen + uPadding); pbyPayloadHead = (PBYTE)(pbyTxBufferAddr + cbHeaderSize + cbMacHdLen + uPadding + cbIVlen); do { if ((pDevice->eOPMode == OP_MODE_INFRASTRUCTURE) && (pDevice->bLinkPass == TRUE)) { pbyBSSID = pDevice->abyBSSID; // get pairwise key if (KeybGetTransmitKey(&(pDevice->sKey), pbyBSSID, PAIRWISE_KEY, &pTransmitKey) == FALSE) { // get group key if(KeybGetTransmitKey(&(pDevice->sKey), pbyBSSID, GROUP_KEY, &pTransmitKey) == TRUE) { DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Get GTK.\n"); break; } } else { DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Get PTK.\n"); break; } } // get group key pbyBSSID = pDevice->abyBroadcastAddr; if(KeybGetTransmitKey(&(pDevice->sKey), pbyBSSID, GROUP_KEY, &pTransmitKey) == FALSE) { pTransmitKey = NULL; DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"KEY is NULL. OP Mode[%d]\n", pDevice->eOPMode); } else { DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Get GTK.\n"); } } while(FALSE); //Fill TXKEY s_vFillTxKey(pDevice, (PBYTE)(pTxBufHead->adwTxKey), pbyIVHead, pTransmitKey, (PBYTE)pMACHeader, (WORD)cbFrameBodySize, NULL); memcpy(pMACHeader, pPacket->p80211Header, cbMacHdLen); memcpy(pbyPayloadHead, ((PBYTE)(pPacket->p80211Header) + cbMacHdLen), cbFrameBodySize); } else { // Copy the Packet into a tx Buffer memcpy(pMACHeader, pPacket->p80211Header, pPacket->cbMPDULen); } pMACHeader->wSeqCtl = cpu_to_le16(pDevice->wSeqCounter << 4); pDevice->wSeqCounter++ ; if (pDevice->wSeqCounter > 0x0fff) pDevice->wSeqCounter = 0; if (bIsPSPOLL) { // The MAC will automatically replace the Duration-field of MAC header by Duration-field // of FIFO control header. // This will cause AID-field of PS-POLL packet be incorrect (Because PS-POLL's AID field is // in the same place of other packet's Duration-field). // And it will cause Cisco-AP to issue Disassociation-packet if (byPktType == PK_TYPE_11GB || byPktType == PK_TYPE_11GA) { ((PSTxDataHead_g)pvTxDataHd)->wDuration_a = cpu_to_le16(pPacket->p80211Header->sA2.wDurationID); ((PSTxDataHead_g)pvTxDataHd)->wDuration_b = cpu_to_le16(pPacket->p80211Header->sA2.wDurationID); } else { ((PSTxDataHead_ab)pvTxDataHd)->wDuration = cpu_to_le16(pPacket->p80211Header->sA2.wDurationID); } } pTX_Buffer->wTxByteCount = cpu_to_le16((WORD)(cbReqCount)); pTX_Buffer->byPKTNO = (BYTE) (((wCurrentRate<<4) &0x00F0) | ((pDevice->wSeqCounter - 1) & 0x000F)); pTX_Buffer->byType = 0x00; pContext->pPacket = NULL; pContext->Type = CONTEXT_MGMT_PACKET; pContext->uBufLen = (WORD)cbReqCount + 4; //USB header if (WLAN_GET_FC_TODS(pMACHeader->wFrameCtl) == 0) { s_vSaveTxPktInfo(pDevice, (BYTE) (pTX_Buffer->byPKTNO & 0x0F), &(pMACHeader->abyAddr1[0]),(WORD)cbFrameSize,pTX_Buffer->wFIFOCtl); } else { s_vSaveTxPktInfo(pDevice, (BYTE) (pTX_Buffer->byPKTNO & 0x0F), &(pMACHeader->abyAddr3[0]),(WORD)cbFrameSize,pTX_Buffer->wFIFOCtl); } PIPEnsSendBulkOut(pDevice,pContext); return CMD_STATUS_PENDING; } CMD_STATUS csBeacon_xmit( IN PSDevice pDevice, IN PSTxMgmtPacket pPacket ) { UINT cbFrameSize = pPacket->cbMPDULen + WLAN_FCS_LEN; UINT cbHeaderSize = 0; WORD wTxBufSize = sizeof(STxShortBufHead); PSTxShortBufHead pTxBufHead; PS802_11Header pMACHeader; PSTxDataHead_ab pTxDataHead; WORD wCurrentRate; UINT cbFrameBodySize; UINT cbReqCount; PBEACON_BUFFER pTX_Buffer; PBYTE pbyTxBufferAddr; PUSB_SEND_CONTEXT pContext; CMD_STATUS status; pContext = (PUSB_SEND_CONTEXT)s_vGetFreeContext(pDevice); if (NULL == pContext) { status = CMD_STATUS_RESOURCES; DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"ManagementSend TX...NO CONTEXT!\n"); return status ; } pTX_Buffer = (PBEACON_BUFFER) (&pContext->Data[0]); pbyTxBufferAddr = (PBYTE)&(pTX_Buffer->wFIFOCtl); cbFrameBodySize = pPacket->cbPayloadLen; pTxBufHead = (PSTxShortBufHead) pbyTxBufferAddr; wTxBufSize = sizeof(STxShortBufHead); memset(pTxBufHead, 0, wTxBufSize); if (pDevice->byBBType == BB_TYPE_11A) { wCurrentRate = RATE_6M; pTxDataHead = (PSTxDataHead_ab) (pbyTxBufferAddr + wTxBufSize); //Get SignalField,ServiceField,Length BBvCaculateParameter(pDevice, cbFrameSize, wCurrentRate, PK_TYPE_11A, (PWORD)&(pTxDataHead->wTransmitLength), (PBYTE)&(pTxDataHead->byServiceField), (PBYTE)&(pTxDataHead->bySignalField) ); //Get Duration and TimeStampOff pTxDataHead->wDuration = cpu_to_le16((WORD)s_uGetDataDuration(pDevice, DATADUR_A, cbFrameSize, PK_TYPE_11A, wCurrentRate, FALSE, 0, 0, 1, AUTO_FB_NONE)); pTxDataHead->wTimeStampOff = wTimeStampOff[pDevice->byPreambleType%2][wCurrentRate%MAX_RATE]; cbHeaderSize = wTxBufSize + sizeof(STxDataHead_ab); } else { wCurrentRate = RATE_1M; pTxBufHead->wFIFOCtl |= FIFOCTL_11B; pTxDataHead = (PSTxDataHead_ab) (pbyTxBufferAddr + wTxBufSize); //Get SignalField,ServiceField,Length BBvCaculateParameter(pDevice, cbFrameSize, wCurrentRate, PK_TYPE_11B, (PWORD)&(pTxDataHead->wTransmitLength), (PBYTE)&(pTxDataHead->byServiceField), (PBYTE)&(pTxDataHead->bySignalField) ); //Get Duration and TimeStampOff pTxDataHead->wDuration = cpu_to_le16((WORD)s_uGetDataDuration(pDevice, DATADUR_B, cbFrameSize, PK_TYPE_11B, wCurrentRate, FALSE, 0, 0, 1, AUTO_FB_NONE)); pTxDataHead->wTimeStampOff = wTimeStampOff[pDevice->byPreambleType%2][wCurrentRate%MAX_RATE]; cbHeaderSize = wTxBufSize + sizeof(STxDataHead_ab); } //Generate Beacon Header pMACHeader = (PS802_11Header)(pbyTxBufferAddr + cbHeaderSize); memcpy(pMACHeader, pPacket->p80211Header, pPacket->cbMPDULen); pMACHeader->wDurationID = 0; pMACHeader->wSeqCtl = cpu_to_le16(pDevice->wSeqCounter << 4); pDevice->wSeqCounter++ ; if (pDevice->wSeqCounter > 0x0fff) pDevice->wSeqCounter = 0; cbReqCount = cbHeaderSize + WLAN_HDR_ADDR3_LEN + cbFrameBodySize; pTX_Buffer->wTxByteCount = (WORD)cbReqCount; pTX_Buffer->byPKTNO = (BYTE) (((wCurrentRate<<4) &0x00F0) | ((pDevice->wSeqCounter - 1) & 0x000F)); pTX_Buffer->byType = 0x01; pContext->pPacket = NULL; pContext->Type = CONTEXT_MGMT_PACKET; pContext->uBufLen = (WORD)cbReqCount + 4; //USB header PIPEnsSendBulkOut(pDevice,pContext); return CMD_STATUS_PENDING; } VOID vDMA0_tx_80211(PSDevice pDevice, struct sk_buff *skb) { PSMgmtObject pMgmt = &(pDevice->sMgmtObj); BYTE byPktType; PBYTE pbyTxBufferAddr; PVOID pvRTS; PVOID pvCTS; PVOID pvTxDataHd; UINT uDuration; UINT cbReqCount; PS802_11Header pMACHeader; UINT cbHeaderSize; UINT cbFrameBodySize; BOOL bNeedACK; BOOL bIsPSPOLL = FALSE; PSTxBufHead pTxBufHead; UINT cbFrameSize; UINT cbIVlen = 0; UINT cbICVlen = 0; UINT cbMIClen = 0; UINT cbFCSlen = 4; UINT uPadding = 0; UINT cbMICHDR = 0; UINT uLength = 0; DWORD dwMICKey0, dwMICKey1; DWORD dwMIC_Priority; PDWORD pdwMIC_L; PDWORD pdwMIC_R; WORD wTxBufSize; UINT cbMacHdLen; SEthernetHeader sEthHeader; PVOID pvRrvTime; PVOID pMICHDR; WORD wCurrentRate = RATE_1M; PUWLAN_80211HDR p80211Header; UINT uNodeIndex = 0; BOOL bNodeExist = FALSE; SKeyItem STempKey; PSKeyItem pTransmitKey = NULL; PBYTE pbyIVHead; PBYTE pbyPayloadHead; PBYTE pbyMacHdr; UINT cbExtSuppRate = 0; PTX_BUFFER pTX_Buffer; PUSB_SEND_CONTEXT pContext; // PWLAN_IE pItem; pvRrvTime = pMICHDR = pvRTS = pvCTS = pvTxDataHd = NULL; if(skb->len <= WLAN_HDR_ADDR3_LEN) { cbFrameBodySize = 0; } else { cbFrameBodySize = skb->len - WLAN_HDR_ADDR3_LEN; } p80211Header = (PUWLAN_80211HDR)skb->data; pContext = (PUSB_SEND_CONTEXT)s_vGetFreeContext(pDevice); if (NULL == pContext) { DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"DMA0 TX...NO CONTEXT!\n"); dev_kfree_skb_irq(skb); return ; } pTX_Buffer = (PTX_BUFFER)(&pContext->Data[0]); pbyTxBufferAddr = (PBYTE)(&pTX_Buffer->adwTxKey[0]); pTxBufHead = (PSTxBufHead) pbyTxBufferAddr; wTxBufSize = sizeof(STxBufHead); memset(pTxBufHead, 0, wTxBufSize); if (pDevice->byBBType == BB_TYPE_11A) { wCurrentRate = RATE_6M; byPktType = PK_TYPE_11A; } else { wCurrentRate = RATE_1M; byPktType = PK_TYPE_11B; } // SetPower will cause error power TX state for OFDM Date packet in TX buffer. // 2004.11.11 Kyle -- Using OFDM power to tx MngPkt will decrease the connection capability. // And cmd timer will wait data pkt TX finish before scanning so it's OK // to set power here. if (pMgmt->eScanState != WMAC_NO_SCANNING) { RFbSetPower(pDevice, wCurrentRate, pDevice->byCurrentCh); } else { RFbSetPower(pDevice, wCurrentRate, pMgmt->uCurrChannel); } DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"vDMA0_tx_80211: p80211Header->sA3.wFrameCtl = %x \n", p80211Header->sA3.wFrameCtl); //Set packet type if (byPktType == PK_TYPE_11A) {//0000 0000 0000 0000 pTxBufHead->wFIFOCtl = 0; } else if (byPktType == PK_TYPE_11B) {//0000 0001 0000 0000 pTxBufHead->wFIFOCtl |= FIFOCTL_11B; } else if (byPktType == PK_TYPE_11GB) {//0000 0010 0000 0000 pTxBufHead->wFIFOCtl |= FIFOCTL_11GB; } else if (byPktType == PK_TYPE_11GA) {//0000 0011 0000 0000 pTxBufHead->wFIFOCtl |= FIFOCTL_11GA; } pTxBufHead->wFIFOCtl |= FIFOCTL_TMOEN; pTxBufHead->wTimeStamp = cpu_to_le16(DEFAULT_MGN_LIFETIME_RES_64us); if (IS_MULTICAST_ADDRESS(&(p80211Header->sA3.abyAddr1[0])) || IS_BROADCAST_ADDRESS(&(p80211Header->sA3.abyAddr1[0]))) { bNeedACK = FALSE; if (pDevice->bEnableHostWEP) { uNodeIndex = 0; bNodeExist = TRUE; }; } else { if (pDevice->bEnableHostWEP) { if (BSSbIsSTAInNodeDB(pDevice, (PBYTE)(p80211Header->sA3.abyAddr1), &uNodeIndex)) bNodeExist = TRUE; }; bNeedACK = TRUE; pTxBufHead->wFIFOCtl |= FIFOCTL_NEEDACK; }; if ((pMgmt->eCurrMode == WMAC_MODE_ESS_AP) || (pMgmt->eCurrMode == WMAC_MODE_IBSS_STA) ) { pTxBufHead->wFIFOCtl |= FIFOCTL_LRETRY; //Set Preamble type always long //pDevice->byPreambleType = PREAMBLE_LONG; // probe-response don't retry //if ((p80211Header->sA4.wFrameCtl & TYPE_SUBTYPE_MASK) == TYPE_MGMT_PROBE_RSP) { // bNeedACK = FALSE; // pTxBufHead->wFIFOCtl &= (~FIFOCTL_NEEDACK); //} } pTxBufHead->wFIFOCtl |= (FIFOCTL_GENINT | FIFOCTL_ISDMA0); if ((p80211Header->sA4.wFrameCtl & TYPE_SUBTYPE_MASK) == TYPE_CTL_PSPOLL) { bIsPSPOLL = TRUE; cbMacHdLen = WLAN_HDR_ADDR2_LEN; } else { cbMacHdLen = WLAN_HDR_ADDR3_LEN; } // hostapd deamon ext support rate patch if (WLAN_GET_FC_FSTYPE(p80211Header->sA4.wFrameCtl) == WLAN_FSTYPE_ASSOCRESP) { if (((PWLAN_IE_SUPP_RATES)pMgmt->abyCurrSuppRates)->len != 0) { cbExtSuppRate += ((PWLAN_IE_SUPP_RATES)pMgmt->abyCurrSuppRates)->len + WLAN_IEHDR_LEN; } if (((PWLAN_IE_SUPP_RATES)pMgmt->abyCurrExtSuppRates)->len != 0) { cbExtSuppRate += ((PWLAN_IE_SUPP_RATES)pMgmt->abyCurrExtSuppRates)->len + WLAN_IEHDR_LEN; } if (cbExtSuppRate >0) { cbFrameBodySize = WLAN_ASSOCRESP_OFF_SUPP_RATES; } } //Set FRAGCTL_MACHDCNT pTxBufHead->wFragCtl |= cpu_to_le16((WORD)cbMacHdLen << 10); // Notes: // Although spec says MMPDU can be fragmented; In most case, // no one will send a MMPDU under fragmentation. With RTS may occur. pDevice->bAES = FALSE; //Set FRAGCTL_WEPTYP if (WLAN_GET_FC_ISWEP(p80211Header->sA4.wFrameCtl) != 0) { if (pDevice->eEncryptionStatus == Ndis802_11Encryption1Enabled) { cbIVlen = 4; cbICVlen = 4; pTxBufHead->wFragCtl |= FRAGCTL_LEGACY; } else if (pDevice->eEncryptionStatus == Ndis802_11Encryption2Enabled) { cbIVlen = 8;//IV+ExtIV cbMIClen = 8; cbICVlen = 4; pTxBufHead->wFragCtl |= FRAGCTL_TKIP; //We need to get seed here for filling TxKey entry. //TKIPvMixKey(pTransmitKey->abyKey, pDevice->abyCurrentNetAddr, // pTransmitKey->wTSC15_0, pTransmitKey->dwTSC47_16, pDevice->abyPRNG); } else if (pDevice->eEncryptionStatus == Ndis802_11Encryption3Enabled) { cbIVlen = 8;//RSN Header cbICVlen = 8;//MIC cbMICHDR = sizeof(SMICHDRHead); pTxBufHead->wFragCtl |= FRAGCTL_AES; pDevice->bAES = TRUE; } //MAC Header should be padding 0 to DW alignment. uPadding = 4 - (cbMacHdLen%4); uPadding %= 4; } cbFrameSize = cbMacHdLen + cbFrameBodySize + cbIVlen + cbMIClen + cbICVlen + cbFCSlen + cbExtSuppRate; //Set FIFOCTL_GrpAckPolicy if (pDevice->bGrpAckPolicy == TRUE) {//0000 0100 0000 0000 pTxBufHead->wFIFOCtl |= FIFOCTL_GRPACK; } //the rest of pTxBufHead->wFragCtl:FragTyp will be set later in s_vFillFragParameter() if (byPktType == PK_TYPE_11GB || byPktType == PK_TYPE_11GA) {//802.11g packet pvRrvTime = (PSRrvTime_gCTS) (pbyTxBufferAddr + wTxBufSize); pMICHDR = (PSMICHDRHead) (pbyTxBufferAddr + wTxBufSize + sizeof(SRrvTime_gCTS)); pvRTS = NULL; pvCTS = (PSCTS) (pbyTxBufferAddr + wTxBufSize + sizeof(SRrvTime_gCTS) + cbMICHDR); pvTxDataHd = (PSTxDataHead_g) (pbyTxBufferAddr + wTxBufSize + sizeof(SRrvTime_gCTS) + cbMICHDR + sizeof(SCTS)); cbHeaderSize = wTxBufSize + sizeof(SRrvTime_gCTS) + cbMICHDR + sizeof(SCTS) + sizeof(STxDataHead_g); } else {//802.11a/b packet pvRrvTime = (PSRrvTime_ab) (pbyTxBufferAddr + wTxBufSize); pMICHDR = (PSMICHDRHead) (pbyTxBufferAddr + wTxBufSize + sizeof(SRrvTime_ab)); pvRTS = NULL; pvCTS = NULL; pvTxDataHd = (PSTxDataHead_ab) (pbyTxBufferAddr + wTxBufSize + sizeof(SRrvTime_ab) + cbMICHDR); cbHeaderSize = wTxBufSize + sizeof(SRrvTime_ab) + cbMICHDR + sizeof(STxDataHead_ab); } memset((PVOID)(pbyTxBufferAddr + wTxBufSize), 0, (cbHeaderSize - wTxBufSize)); memcpy(&(sEthHeader.abyDstAddr[0]), &(p80211Header->sA3.abyAddr1[0]), U_ETHER_ADDR_LEN); memcpy(&(sEthHeader.abySrcAddr[0]), &(p80211Header->sA3.abyAddr2[0]), U_ETHER_ADDR_LEN); //========================= // No Fragmentation //========================= pTxBufHead->wFragCtl |= (WORD)FRAGCTL_NONFRAG; //Fill FIFO,RrvTime,RTS,and CTS s_vGenerateTxParameter(pDevice, byPktType, wCurrentRate, pbyTxBufferAddr, pvRrvTime, pvRTS, pvCTS, cbFrameSize, bNeedACK, TYPE_TXDMA0, &sEthHeader); //Fill DataHead uDuration = s_uFillDataHead(pDevice, byPktType, wCurrentRate, pvTxDataHd, cbFrameSize, TYPE_TXDMA0, bNeedACK, 0, 0, 1, AUTO_FB_NONE); pMACHeader = (PS802_11Header) (pbyTxBufferAddr + cbHeaderSize); cbReqCount = cbHeaderSize + cbMacHdLen + uPadding + cbIVlen + (cbFrameBodySize + cbMIClen) + cbExtSuppRate; pbyMacHdr = (PBYTE)(pbyTxBufferAddr + cbHeaderSize); pbyPayloadHead = (PBYTE)(pbyMacHdr + cbMacHdLen + uPadding + cbIVlen); pbyIVHead = (PBYTE)(pbyMacHdr + cbMacHdLen + uPadding); // Copy the Packet into a tx Buffer memcpy(pbyMacHdr, skb->data, cbMacHdLen); // version set to 0, patch for hostapd deamon pMACHeader->wFrameCtl &= cpu_to_le16(0xfffc); memcpy(pbyPayloadHead, (skb->data + cbMacHdLen), cbFrameBodySize); // replace support rate, patch for hostapd deamon( only support 11M) if (WLAN_GET_FC_FSTYPE(p80211Header->sA4.wFrameCtl) == WLAN_FSTYPE_ASSOCRESP) { if (cbExtSuppRate != 0) { if (((PWLAN_IE_SUPP_RATES)pMgmt->abyCurrSuppRates)->len != 0) memcpy((pbyPayloadHead + cbFrameBodySize), pMgmt->abyCurrSuppRates, ((PWLAN_IE_SUPP_RATES)pMgmt->abyCurrSuppRates)->len + WLAN_IEHDR_LEN ); if (((PWLAN_IE_SUPP_RATES)pMgmt->abyCurrExtSuppRates)->len != 0) memcpy((pbyPayloadHead + cbFrameBodySize) + ((PWLAN_IE_SUPP_RATES)pMgmt->abyCurrSuppRates)->len + WLAN_IEHDR_LEN, pMgmt->abyCurrExtSuppRates, ((PWLAN_IE_SUPP_RATES)pMgmt->abyCurrExtSuppRates)->len + WLAN_IEHDR_LEN ); } } // Set wep if (WLAN_GET_FC_ISWEP(p80211Header->sA4.wFrameCtl) != 0) { if (pDevice->bEnableHostWEP) { pTransmitKey = &STempKey; pTransmitKey->byCipherSuite = pMgmt->sNodeDBTable[uNodeIndex].byCipherSuite; pTransmitKey->dwKeyIndex = pMgmt->sNodeDBTable[uNodeIndex].dwKeyIndex; pTransmitKey->uKeyLength = pMgmt->sNodeDBTable[uNodeIndex].uWepKeyLength; pTransmitKey->dwTSC47_16 = pMgmt->sNodeDBTable[uNodeIndex].dwTSC47_16; pTransmitKey->wTSC15_0 = pMgmt->sNodeDBTable[uNodeIndex].wTSC15_0; memcpy(pTransmitKey->abyKey, &pMgmt->sNodeDBTable[uNodeIndex].abyWepKey[0], pTransmitKey->uKeyLength ); } if ((pTransmitKey != NULL) && (pTransmitKey->byCipherSuite == KEY_CTL_TKIP)) { dwMICKey0 = *(PDWORD)(&pTransmitKey->abyKey[16]); dwMICKey1 = *(PDWORD)(&pTransmitKey->abyKey[20]); // DO Software Michael MIC_vInit(dwMICKey0, dwMICKey1); MIC_vAppend((PBYTE)&(sEthHeader.abyDstAddr[0]), 12); dwMIC_Priority = 0; MIC_vAppend((PBYTE)&dwMIC_Priority, 4); DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"DMA0_tx_8021:MIC KEY: %lX, %lX\n", dwMICKey0, dwMICKey1); uLength = cbHeaderSize + cbMacHdLen + uPadding + cbIVlen; MIC_vAppend((pbyTxBufferAddr + uLength), cbFrameBodySize); pdwMIC_L = (PDWORD)(pbyTxBufferAddr + uLength + cbFrameBodySize); pdwMIC_R = (PDWORD)(pbyTxBufferAddr + uLength + cbFrameBodySize + 4); MIC_vGetMIC(pdwMIC_L, pdwMIC_R); MIC_vUnInit(); if (pDevice->bTxMICFail == TRUE) { *pdwMIC_L = 0; *pdwMIC_R = 0; pDevice->bTxMICFail = FALSE; } DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"uLength: %d, %d\n", uLength, cbFrameBodySize); DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"cbReqCount:%d, %d, %d, %d\n", cbReqCount, cbHeaderSize, uPadding, cbIVlen); DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"MIC:%lx, %lx\n", *pdwMIC_L, *pdwMIC_R); } s_vFillTxKey(pDevice, (PBYTE)(pTxBufHead->adwTxKey), pbyIVHead, pTransmitKey, pbyMacHdr, (WORD)cbFrameBodySize, (PBYTE)pMICHDR); if (pDevice->bEnableHostWEP) { pMgmt->sNodeDBTable[uNodeIndex].dwTSC47_16 = pTransmitKey->dwTSC47_16; pMgmt->sNodeDBTable[uNodeIndex].wTSC15_0 = pTransmitKey->wTSC15_0; } if ((pDevice->byLocalID <= REV_ID_VT3253_A1)) { s_vSWencryption(pDevice, pTransmitKey, pbyPayloadHead, (WORD)(cbFrameBodySize + cbMIClen)); } } pMACHeader->wSeqCtl = cpu_to_le16(pDevice->wSeqCounter << 4); pDevice->wSeqCounter++ ; if (pDevice->wSeqCounter > 0x0fff) pDevice->wSeqCounter = 0; if (bIsPSPOLL) { // The MAC will automatically replace the Duration-field of MAC header by Duration-field // of FIFO control header. // This will cause AID-field of PS-POLL packet be incorrect (Because PS-POLL's AID field is // in the same place of other packet's Duration-field). // And it will cause Cisco-AP to issue Disassociation-packet if (byPktType == PK_TYPE_11GB || byPktType == PK_TYPE_11GA) { ((PSTxDataHead_g)pvTxDataHd)->wDuration_a = cpu_to_le16(p80211Header->sA2.wDurationID); ((PSTxDataHead_g)pvTxDataHd)->wDuration_b = cpu_to_le16(p80211Header->sA2.wDurationID); } else { ((PSTxDataHead_ab)pvTxDataHd)->wDuration = cpu_to_le16(p80211Header->sA2.wDurationID); } } pTX_Buffer->wTxByteCount = cpu_to_le16((WORD)(cbReqCount)); pTX_Buffer->byPKTNO = (BYTE) (((wCurrentRate<<4) &0x00F0) | ((pDevice->wSeqCounter - 1) & 0x000F)); pTX_Buffer->byType = 0x00; pContext->pPacket = skb; pContext->Type = CONTEXT_MGMT_PACKET; pContext->uBufLen = (WORD)cbReqCount + 4; //USB header if (WLAN_GET_FC_TODS(pMACHeader->wFrameCtl) == 0) { s_vSaveTxPktInfo(pDevice, (BYTE) (pTX_Buffer->byPKTNO & 0x0F), &(pMACHeader->abyAddr1[0]),(WORD)cbFrameSize,pTX_Buffer->wFIFOCtl); } else { s_vSaveTxPktInfo(pDevice, (BYTE) (pTX_Buffer->byPKTNO & 0x0F), &(pMACHeader->abyAddr3[0]),(WORD)cbFrameSize,pTX_Buffer->wFIFOCtl); } PIPEnsSendBulkOut(pDevice,pContext); return ; } //TYPE_AC0DMA data tx /* * Description: * Tx packet via AC0DMA(DMA1) * * Parameters: * In: * pDevice - Pointer to the adapter * skb - Pointer to tx skb packet * Out: * void * * Return Value: NULL */ NTSTATUS nsDMA_tx_packet( IN PSDevice pDevice, IN UINT uDMAIdx, IN struct sk_buff *skb ) { PSMgmtObject pMgmt = &(pDevice->sMgmtObj); UINT BytesToWrite =0,uHeaderLen = 0; UINT uNodeIndex = 0; BYTE byMask[8] = {1, 2, 4, 8, 0x10, 0x20, 0x40, 0x80}; WORD wAID; BYTE byPktType; BOOL bNeedEncryption = FALSE; PSKeyItem pTransmitKey = NULL; SKeyItem STempKey; UINT ii; BOOL bTKIP_UseGTK = FALSE; BOOL bNeedDeAuth = FALSE; PBYTE pbyBSSID; BOOL bNodeExist = FALSE; PUSB_SEND_CONTEXT pContext; BOOL fConvertedPacket; PTX_BUFFER pTX_Buffer; UINT status; WORD wKeepRate = pDevice->wCurrentRate; struct net_device_stats* pStats = &pDevice->stats; //#ifdef WPA_SM_Transtatus // extern SWPAResult wpa_Result; //#endif BOOL bTxeapol_key = FALSE; if (pMgmt->eCurrMode == WMAC_MODE_ESS_AP) { if (pDevice->uAssocCount == 0) { dev_kfree_skb_irq(skb); return 0; } if (IS_MULTICAST_ADDRESS((PBYTE)(skb->data))) { uNodeIndex = 0; bNodeExist = TRUE; if (pMgmt->sNodeDBTable[0].bPSEnable) { skb_queue_tail(&(pMgmt->sNodeDBTable[0].sTxPSQueue), skb); pMgmt->sNodeDBTable[0].wEnQueueCnt++; // set tx map pMgmt->abyPSTxMap[0] |= byMask[0]; return 0; } // muticast/broadcast data rate if (pDevice->byBBType != BB_TYPE_11A) pDevice->wCurrentRate = RATE_2M; else pDevice->wCurrentRate = RATE_24M; // long preamble type pDevice->byPreambleType = PREAMBLE_SHORT; }else { if (BSSbIsSTAInNodeDB(pDevice, (PBYTE)(skb->data), &uNodeIndex)) { if (pMgmt->sNodeDBTable[uNodeIndex].bPSEnable) { skb_queue_tail(&pMgmt->sNodeDBTable[uNodeIndex].sTxPSQueue, skb); pMgmt->sNodeDBTable[uNodeIndex].wEnQueueCnt++; // set tx map wAID = pMgmt->sNodeDBTable[uNodeIndex].wAID; pMgmt->abyPSTxMap[wAID >> 3] |= byMask[wAID & 7]; DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Set:pMgmt->abyPSTxMap[%d]= %d\n", (wAID >> 3), pMgmt->abyPSTxMap[wAID >> 3]); return 0; } // AP rate decided from node pDevice->wCurrentRate = pMgmt->sNodeDBTable[uNodeIndex].wTxDataRate; // tx preamble decided from node if (pMgmt->sNodeDBTable[uNodeIndex].bShortPreamble) { pDevice->byPreambleType = pDevice->byShortPreamble; }else { pDevice->byPreambleType = PREAMBLE_LONG; } bNodeExist = TRUE; } } if (bNodeExist == FALSE) { DBG_PRT(MSG_LEVEL_DEBUG, KERN_DEBUG"Unknown STA not found in node DB \n"); dev_kfree_skb_irq(skb); return 0; } } pContext = (PUSB_SEND_CONTEXT)s_vGetFreeContext(pDevice); if (pContext == NULL) { DBG_PRT(MSG_LEVEL_DEBUG, KERN_DEBUG" pContext == NULL\n"); dev_kfree_skb_irq(skb); return STATUS_RESOURCES; } memcpy(pDevice->sTxEthHeader.abyDstAddr, (PBYTE)(skb->data), U_HEADER_LEN); //mike add:station mode check eapol-key challenge---> { BYTE Protocol_Version; //802.1x Authentication BYTE Packet_Type; //802.1x Authentication BYTE Descriptor_type; WORD Key_info; Protocol_Version = skb->data[U_HEADER_LEN]; Packet_Type = skb->data[U_HEADER_LEN+1]; Descriptor_type = skb->data[U_HEADER_LEN+1+1+2]; Key_info = (skb->data[U_HEADER_LEN+1+1+2+1] << 8)|(skb->data[U_HEADER_LEN+1+1+2+2]); if (pDevice->sTxEthHeader.wType == TYPE_PKT_802_1x) { if(((Protocol_Version==1) ||(Protocol_Version==2)) && (Packet_Type==3)) { //802.1x OR eapol-key challenge frame transfer bTxeapol_key = TRUE; if(!(Key_info & BIT3) && //WPA or RSN group-key challenge (Key_info & BIT8) && (Key_info & BIT9)) { //send 2/2 key if(Descriptor_type==254) { pDevice->fWPA_Authened = TRUE; PRINT_K("WPA "); } else { pDevice->fWPA_Authened = TRUE; PRINT_K("WPA2(re-keying) "); } PRINT_K("Authentication completed!!\n"); } else if((Key_info & BIT3) && (Descriptor_type==2) && //RSN pairse-key challenge (Key_info & BIT8) && (Key_info & BIT9)) { pDevice->fWPA_Authened = TRUE; PRINT_K("WPA2 Authentication completed!!\n"); } } } } //mike add:station mode check eapol-key challenge<--- if (pDevice->bEncryptionEnable == TRUE) { bNeedEncryption = TRUE; // get Transmit key do { if ((pMgmt->eCurrMode == WMAC_MODE_ESS_STA) && (pMgmt->eCurrState == WMAC_STATE_ASSOC)) { pbyBSSID = pDevice->abyBSSID; // get pairwise key if (KeybGetTransmitKey(&(pDevice->sKey), pbyBSSID, PAIRWISE_KEY, &pTransmitKey) == FALSE) { // get group key if(KeybGetTransmitKey(&(pDevice->sKey), pbyBSSID, GROUP_KEY, &pTransmitKey) == TRUE) { bTKIP_UseGTK = TRUE; DBG_PRT(MSG_LEVEL_DEBUG, KERN_DEBUG"Get GTK.\n"); break; } } else { DBG_PRT(MSG_LEVEL_DEBUG, KERN_DEBUG"Get PTK.\n"); break; } }else if (pMgmt->eCurrMode == WMAC_MODE_IBSS_STA) { pbyBSSID = pDevice->sTxEthHeader.abyDstAddr; //TO_DS = 0 and FROM_DS = 0 --> 802.11 MAC Address1 DBG_PRT(MSG_LEVEL_DEBUG, KERN_DEBUG"IBSS Serach Key: \n"); for (ii = 0; ii< 6; ii++) DBG_PRT(MSG_LEVEL_DEBUG, KERN_DEBUG"%x \n", *(pbyBSSID+ii)); DBG_PRT(MSG_LEVEL_DEBUG, KERN_DEBUG"\n"); // get pairwise key if(KeybGetTransmitKey(&(pDevice->sKey), pbyBSSID, PAIRWISE_KEY, &pTransmitKey) == TRUE) break; } // get group key pbyBSSID = pDevice->abyBroadcastAddr; if(KeybGetTransmitKey(&(pDevice->sKey), pbyBSSID, GROUP_KEY, &pTransmitKey) == FALSE) { pTransmitKey = NULL; if (pMgmt->eCurrMode == WMAC_MODE_IBSS_STA) { DBG_PRT(MSG_LEVEL_DEBUG, KERN_DEBUG"IBSS and KEY is NULL. [%d]\n", pMgmt->eCurrMode); } else DBG_PRT(MSG_LEVEL_DEBUG, KERN_DEBUG"NOT IBSS and KEY is NULL. [%d]\n", pMgmt->eCurrMode); } else { bTKIP_UseGTK = TRUE; DBG_PRT(MSG_LEVEL_DEBUG, KERN_DEBUG"Get GTK.\n"); } } while(FALSE); } if (pDevice->bEnableHostWEP) { DBG_PRT(MSG_LEVEL_DEBUG, KERN_DEBUG"acdma0: STA index %d\n", uNodeIndex); if (pDevice->bEncryptionEnable == TRUE) { pTransmitKey = &STempKey; pTransmitKey->byCipherSuite = pMgmt->sNodeDBTable[uNodeIndex].byCipherSuite; pTransmitKey->dwKeyIndex = pMgmt->sNodeDBTable[uNodeIndex].dwKeyIndex; pTransmitKey->uKeyLength = pMgmt->sNodeDBTable[uNodeIndex].uWepKeyLength; pTransmitKey->dwTSC47_16 = pMgmt->sNodeDBTable[uNodeIndex].dwTSC47_16; pTransmitKey->wTSC15_0 = pMgmt->sNodeDBTable[uNodeIndex].wTSC15_0; memcpy(pTransmitKey->abyKey, &pMgmt->sNodeDBTable[uNodeIndex].abyWepKey[0], pTransmitKey->uKeyLength ); } } byPktType = (BYTE)pDevice->byPacketType; if (pDevice->bFixRate) { if (pDevice->byBBType == BB_TYPE_11B) { if (pDevice->uConnectionRate >= RATE_11M) { pDevice->wCurrentRate = RATE_11M; } else { pDevice->wCurrentRate = (WORD)pDevice->uConnectionRate; } } else { if ((pDevice->byBBType == BB_TYPE_11A) && (pDevice->uConnectionRate <= RATE_6M)) { pDevice->wCurrentRate = RATE_6M; } else { if (pDevice->uConnectionRate >= RATE_54M) pDevice->wCurrentRate = RATE_54M; else pDevice->wCurrentRate = (WORD)pDevice->uConnectionRate; } } } else { if (pDevice->eOPMode == OP_MODE_ADHOC) { // Adhoc Tx rate decided from node DB if (IS_MULTICAST_ADDRESS(&(pDevice->sTxEthHeader.abyDstAddr[0]))) { // Multicast use highest data rate pDevice->wCurrentRate = pMgmt->sNodeDBTable[0].wTxDataRate; // preamble type pDevice->byPreambleType = pDevice->byShortPreamble; } else { if(BSSbIsSTAInNodeDB(pDevice, &(pDevice->sTxEthHeader.abyDstAddr[0]), &uNodeIndex)) { pDevice->wCurrentRate = pMgmt->sNodeDBTable[uNodeIndex].wTxDataRate; if (pMgmt->sNodeDBTable[uNodeIndex].bShortPreamble) { pDevice->byPreambleType = pDevice->byShortPreamble; } else { pDevice->byPreambleType = PREAMBLE_LONG; } DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Found Node Index is [%d] Tx Data Rate:[%d]\n",uNodeIndex, pDevice->wCurrentRate); } else { if (pDevice->byBBType != BB_TYPE_11A) pDevice->wCurrentRate = RATE_2M; else pDevice->wCurrentRate = RATE_24M; // refer to vMgrCreateOwnIBSS()'s // abyCurrExtSuppRates[] pDevice->byPreambleType = PREAMBLE_SHORT; DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Not Found Node use highest basic Rate.....\n"); } } } if (pDevice->eOPMode == OP_MODE_INFRASTRUCTURE) { // Infra STA rate decided from AP Node, index = 0 pDevice->wCurrentRate = pMgmt->sNodeDBTable[0].wTxDataRate; } } if (pDevice->sTxEthHeader.wType == TYPE_PKT_802_1x) { if (pDevice->byBBType != BB_TYPE_11A) { pDevice->wCurrentRate = RATE_1M; pDevice->byACKRate = RATE_1M; pDevice->byTopCCKBasicRate = RATE_1M; pDevice->byTopOFDMBasicRate = RATE_6M; } else { pDevice->wCurrentRate = RATE_6M; pDevice->byACKRate = RATE_6M; pDevice->byTopCCKBasicRate = RATE_1M; pDevice->byTopOFDMBasicRate = RATE_6M; } } DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "dma_tx: pDevice->wCurrentRate = %d \n", pDevice->wCurrentRate); if (wKeepRate != pDevice->wCurrentRate) { bScheduleCommand((HANDLE)pDevice, WLAN_CMD_SETPOWER, NULL); } if (pDevice->wCurrentRate <= RATE_11M) { byPktType = PK_TYPE_11B; } if (bNeedEncryption == TRUE) { DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"ntohs Pkt Type=%04x\n", ntohs(pDevice->sTxEthHeader.wType)); if ((pDevice->sTxEthHeader.wType) == TYPE_PKT_802_1x) { bNeedEncryption = FALSE; DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Pkt Type=%04x\n", (pDevice->sTxEthHeader.wType)); if ((pMgmt->eCurrMode == WMAC_MODE_ESS_STA) && (pMgmt->eCurrState == WMAC_STATE_ASSOC)) { if (pTransmitKey == NULL) { DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Don't Find TX KEY\n"); } else { if (bTKIP_UseGTK == TRUE) { DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"error: KEY is GTK!!~~\n"); } else { DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Find PTK [%lX]\n", pTransmitKey->dwKeyIndex); bNeedEncryption = TRUE; } } } if (pDevice->byCntMeasure == 2) { bNeedDeAuth = TRUE; pDevice->s802_11Counter.TKIPCounterMeasuresInvoked++; } if (pDevice->bEnableHostWEP) { if ((uNodeIndex != 0) && (pMgmt->sNodeDBTable[uNodeIndex].dwKeyIndex & PAIRWISE_KEY)) { DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Find PTK [%lX]\n", pTransmitKey->dwKeyIndex); bNeedEncryption = TRUE; } } } else { #if 0 if((pDevice->fWPA_Authened == FALSE) && ((pMgmt->eAuthenMode == WMAC_AUTH_WPAPSK)||(pMgmt->eAuthenMode = WMAC_AUTH_WPA2PSK))){ dev_kfree_skb_irq(skb); pStats->tx_dropped++; return STATUS_FAILURE; } else if (pTransmitKey == NULL) { DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"return no tx key\n"); dev_kfree_skb_irq(skb); pStats->tx_dropped++; return STATUS_FAILURE; } #else if (pTransmitKey == NULL) { DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"return no tx key\n"); dev_kfree_skb_irq(skb); pStats->tx_dropped++; return STATUS_FAILURE; } #endif } } fConvertedPacket = s_bPacketToWirelessUsb(pDevice, byPktType, (PBYTE)(&pContext->Data[0]), bNeedEncryption, skb->len, uDMAIdx, &pDevice->sTxEthHeader, (PBYTE)skb->data, pTransmitKey, uNodeIndex, pDevice->wCurrentRate, &uHeaderLen, &BytesToWrite ); if (fConvertedPacket == FALSE) { pContext->bBoolInUse = FALSE; dev_kfree_skb_irq(skb); return STATUS_FAILURE; } if ( pDevice->bEnablePSMode == TRUE ) { if ( !pDevice->bPSModeTxBurst ) { bScheduleCommand((HANDLE) pDevice, WLAN_CMD_MAC_DISPOWERSAVING, NULL); pDevice->bPSModeTxBurst = TRUE; } } pTX_Buffer = (PTX_BUFFER)&(pContext->Data[0]); pTX_Buffer->byPKTNO = (BYTE) (((pDevice->wCurrentRate<<4) &0x00F0) | ((pDevice->wSeqCounter - 1) & 0x000F)); pTX_Buffer->wTxByteCount = (WORD)BytesToWrite; pContext->pPacket = skb; pContext->Type = CONTEXT_DATA_PACKET; pContext->uBufLen = (WORD)BytesToWrite + 4 ; //USB header s_vSaveTxPktInfo(pDevice, (BYTE) (pTX_Buffer->byPKTNO & 0x0F), &(pContext->sEthHeader.abyDstAddr[0]),(WORD) (BytesToWrite-uHeaderLen),pTX_Buffer->wFIFOCtl); status = PIPEnsSendBulkOut(pDevice,pContext); if (bNeedDeAuth == TRUE) { WORD wReason = WLAN_MGMT_REASON_MIC_FAILURE; bScheduleCommand((HANDLE) pDevice, WLAN_CMD_DEAUTH, (PBYTE)&wReason); } if(status!=STATUS_PENDING) { pContext->bBoolInUse = FALSE; dev_kfree_skb_irq(skb); return STATUS_FAILURE; } else return 0; } /* * Description: * Relay packet send (AC1DMA) from rx dpc. * * Parameters: * In: * pDevice - Pointer to the adapter * pPacket - Pointer to rx packet * cbPacketSize - rx ethernet frame size * Out: * TURE, FALSE * * Return Value: Return TRUE if packet is copy to dma1; otherwise FALSE */ BOOL bRelayPacketSend ( IN PSDevice pDevice, IN PBYTE pbySkbData, IN UINT uDataLen, IN UINT uNodeIndex ) { PSMgmtObject pMgmt = &(pDevice->sMgmtObj); UINT BytesToWrite =0,uHeaderLen = 0; BYTE byPktType = PK_TYPE_11B; BOOL bNeedEncryption = FALSE; SKeyItem STempKey; PSKeyItem pTransmitKey = NULL; PBYTE pbyBSSID; PUSB_SEND_CONTEXT pContext; BYTE byPktTyp; BOOL fConvertedPacket; PTX_BUFFER pTX_Buffer; UINT status; WORD wKeepRate = pDevice->wCurrentRate; pContext = (PUSB_SEND_CONTEXT)s_vGetFreeContext(pDevice); if (NULL == pContext) { return FALSE; } memcpy(pDevice->sTxEthHeader.abyDstAddr, (PBYTE)pbySkbData, U_HEADER_LEN); if (pDevice->bEncryptionEnable == TRUE) { bNeedEncryption = TRUE; // get group key pbyBSSID = pDevice->abyBroadcastAddr; if(KeybGetTransmitKey(&(pDevice->sKey), pbyBSSID, GROUP_KEY, &pTransmitKey) == FALSE) { pTransmitKey = NULL; DBG_PRT(MSG_LEVEL_DEBUG, KERN_DEBUG"KEY is NULL. [%d]\n", pMgmt->eCurrMode); } else { DBG_PRT(MSG_LEVEL_DEBUG, KERN_DEBUG"Get GTK.\n"); } } if (pDevice->bEnableHostWEP) { if (uNodeIndex >= 0) { pTransmitKey = &STempKey; pTransmitKey->byCipherSuite = pMgmt->sNodeDBTable[uNodeIndex].byCipherSuite; pTransmitKey->dwKeyIndex = pMgmt->sNodeDBTable[uNodeIndex].dwKeyIndex; pTransmitKey->uKeyLength = pMgmt->sNodeDBTable[uNodeIndex].uWepKeyLength; pTransmitKey->dwTSC47_16 = pMgmt->sNodeDBTable[uNodeIndex].dwTSC47_16; pTransmitKey->wTSC15_0 = pMgmt->sNodeDBTable[uNodeIndex].wTSC15_0; memcpy(pTransmitKey->abyKey, &pMgmt->sNodeDBTable[uNodeIndex].abyWepKey[0], pTransmitKey->uKeyLength ); } } if ( bNeedEncryption && (pTransmitKey == NULL) ) { pContext->bBoolInUse = FALSE; return FALSE; } byPktTyp = (BYTE)pDevice->byPacketType; if (pDevice->bFixRate) { if (pDevice->byBBType == BB_TYPE_11B) { if (pDevice->uConnectionRate >= RATE_11M) { pDevice->wCurrentRate = RATE_11M; } else { pDevice->wCurrentRate = (WORD)pDevice->uConnectionRate; } } else { if ((pDevice->byBBType == BB_TYPE_11A) && (pDevice->uConnectionRate <= RATE_6M)) { pDevice->wCurrentRate = RATE_6M; } else { if (pDevice->uConnectionRate >= RATE_54M) pDevice->wCurrentRate = RATE_54M; else pDevice->wCurrentRate = (WORD)pDevice->uConnectionRate; } } } else { pDevice->wCurrentRate = pMgmt->sNodeDBTable[uNodeIndex].wTxDataRate; } if (wKeepRate != pDevice->wCurrentRate) { bScheduleCommand((HANDLE) pDevice, WLAN_CMD_SETPOWER, NULL); } if (pDevice->wCurrentRate <= RATE_11M) byPktType = PK_TYPE_11B; BytesToWrite = uDataLen + U_CRC_LEN; // Convert the packet to an usb frame and copy into our buffer // and send the irp. fConvertedPacket = s_bPacketToWirelessUsb(pDevice, byPktType, (PBYTE)(&pContext->Data[0]), bNeedEncryption, uDataLen, TYPE_AC0DMA, &pDevice->sTxEthHeader, pbySkbData, pTransmitKey, uNodeIndex, pDevice->wCurrentRate, &uHeaderLen, &BytesToWrite ); if (fConvertedPacket == FALSE) { pContext->bBoolInUse = FALSE; return FALSE; } pTX_Buffer = (PTX_BUFFER)&(pContext->Data[0]); pTX_Buffer->byPKTNO = (BYTE) (((pDevice->wCurrentRate<<4) &0x00F0) | ((pDevice->wSeqCounter - 1) & 0x000F)); pTX_Buffer->wTxByteCount = (WORD)BytesToWrite; pContext->pPacket = NULL; pContext->Type = CONTEXT_DATA_PACKET; pContext->uBufLen = (WORD)BytesToWrite + 4 ; //USB header s_vSaveTxPktInfo(pDevice, (BYTE) (pTX_Buffer->byPKTNO & 0x0F), &(pContext->sEthHeader.abyDstAddr[0]),(WORD) (BytesToWrite-uHeaderLen),pTX_Buffer->wFIFOCtl); status = PIPEnsSendBulkOut(pDevice,pContext); return TRUE; }