/* * 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: vntwifi.c * * Purpose: export functions for vntwifi lib * * Functions: * * Revision History: * * Author: Yiching Chen * * Date: feb. 2, 2005 * */ #include "vntwifi.h" #include "IEEE11h.h" #include "country.h" #include "device.h" #include "wmgr.h" #include "datarate.h" //#define PLICE_DEBUG /*--------------------- Static Definitions -------------------------*/ //static int msglevel =MSG_LEVEL_DEBUG; //static int msglevel =MSG_LEVEL_INFO; /*--------------------- Static Classes ----------------------------*/ /*--------------------- Static Variables --------------------------*/ /*--------------------- Static Functions --------------------------*/ /*--------------------- Export Variables --------------------------*/ /*--------------------- Export Functions --------------------------*/ /*+ * * Description: * Set Operation Mode * * Parameters: * In: * pMgmtHandle - pointer to management object * eOPMode - Opreation Mode * Out: * none * * Return Value: none * -*/ void VNTWIFIvSetOPMode ( void *pMgmtHandle, WMAC_CONFIG_MODE eOPMode ) { PSMgmtObject pMgmt = (PSMgmtObject)pMgmtHandle; pMgmt->eConfigMode = eOPMode; } /*+ * * Description: * Set Operation Mode * * Parameters: * In: * pMgmtHandle - pointer to management object * wBeaconPeriod - Beacon Period * wATIMWindow - ATIM window * uChannel - channel number * Out: * none * * Return Value: none * -*/ void VNTWIFIvSetIBSSParameter ( void *pMgmtHandle, unsigned short wBeaconPeriod, unsigned short wATIMWindow, unsigned int uChannel ) { PSMgmtObject pMgmt = (PSMgmtObject)pMgmtHandle; pMgmt->wIBSSBeaconPeriod = wBeaconPeriod; pMgmt->wIBSSATIMWindow = wATIMWindow; pMgmt->uIBSSChannel = uChannel; } /*+ * * Description: * Get current SSID * * Parameters: * In: * pMgmtHandle - pointer to management object * Out: * none * * Return Value: current SSID pointer. * -*/ PWLAN_IE_SSID VNTWIFIpGetCurrentSSID ( void *pMgmtHandle ) { PSMgmtObject pMgmt = (PSMgmtObject)pMgmtHandle; return((PWLAN_IE_SSID) pMgmt->abyCurrSSID); } /*+ * * Description: * Get current link channel * * Parameters: * In: * pMgmtHandle - pointer to management object * Out: * none * * Return Value: current Channel. * -*/ unsigned int VNTWIFIpGetCurrentChannel ( void *pMgmtHandle ) { PSMgmtObject pMgmt = (PSMgmtObject)pMgmtHandle; if (pMgmtHandle != NULL) { return (pMgmt->uCurrChannel); } return 0; } /*+ * * Description: * Get current Assoc ID * * Parameters: * In: * pMgmtHandle - pointer to management object * Out: * none * * Return Value: current Assoc ID * -*/ unsigned short VNTWIFIwGetAssocID ( void *pMgmtHandle ) { PSMgmtObject pMgmt = (PSMgmtObject)pMgmtHandle; return(pMgmt->wCurrAID); } /*+ * * Description: * This routine return max support rate of IES * * Parameters: * In: * pSupportRateIEs * pExtSupportRateIEs * * Out: * * Return Value: max support rate * -*/ unsigned char VNTWIFIbyGetMaxSupportRate ( PWLAN_IE_SUPP_RATES pSupportRateIEs, PWLAN_IE_SUPP_RATES pExtSupportRateIEs ) { unsigned char byMaxSupportRate = RATE_1M; unsigned char bySupportRate = RATE_1M; unsigned int ii = 0; if (pSupportRateIEs) { for (ii = 0; ii < pSupportRateIEs->len; ii++) { bySupportRate = DATARATEbyGetRateIdx(pSupportRateIEs->abyRates[ii]); if (bySupportRate > byMaxSupportRate) { byMaxSupportRate = bySupportRate; } } } if (pExtSupportRateIEs) { for (ii = 0; ii < pExtSupportRateIEs->len; ii++) { bySupportRate = DATARATEbyGetRateIdx(pExtSupportRateIEs->abyRates[ii]); if (bySupportRate > byMaxSupportRate) { byMaxSupportRate = bySupportRate; } } } return byMaxSupportRate; } /*+ * * Description: * This routine return data rate of ACK packtet * * Parameters: * In: * byRxDataRate * pSupportRateIEs * pExtSupportRateIEs * * Out: * * Return Value: max support rate * -*/ unsigned char VNTWIFIbyGetACKTxRate ( unsigned char byRxDataRate, PWLAN_IE_SUPP_RATES pSupportRateIEs, PWLAN_IE_SUPP_RATES pExtSupportRateIEs ) { unsigned char byMaxAckRate; unsigned char byBasicRate; unsigned int ii; if (byRxDataRate <= RATE_11M) { byMaxAckRate = RATE_1M; } else { // 24M is mandatory for 802.11a and 802.11g byMaxAckRate = RATE_24M; } if (pSupportRateIEs) { for (ii = 0; ii < pSupportRateIEs->len; ii++) { if (pSupportRateIEs->abyRates[ii] & 0x80) { byBasicRate = DATARATEbyGetRateIdx(pSupportRateIEs->abyRates[ii]); if ((byBasicRate <= byRxDataRate) && (byBasicRate > byMaxAckRate)) { byMaxAckRate = byBasicRate; } } } } if (pExtSupportRateIEs) { for (ii = 0; ii < pExtSupportRateIEs->len; ii++) { if (pExtSupportRateIEs->abyRates[ii] & 0x80) { byBasicRate = DATARATEbyGetRateIdx(pExtSupportRateIEs->abyRates[ii]); if ((byBasicRate <= byRxDataRate) && (byBasicRate > byMaxAckRate)) { byMaxAckRate = byBasicRate; } } } } return byMaxAckRate; } /*+ * * Description: * Set Authentication Mode * * Parameters: * In: * pMgmtHandle - pointer to management object * eAuthMode - Authentication mode * Out: * none * * Return Value: none * -*/ void VNTWIFIvSetAuthenticationMode ( void *pMgmtHandle, WMAC_AUTHENTICATION_MODE eAuthMode ) { PSMgmtObject pMgmt = (PSMgmtObject)pMgmtHandle; pMgmt->eAuthenMode = eAuthMode; if ((eAuthMode == WMAC_AUTH_SHAREKEY) || (eAuthMode == WMAC_AUTH_AUTO)) { pMgmt->bShareKeyAlgorithm = true; } else { pMgmt->bShareKeyAlgorithm = false; } } /*+ * * Description: * Set Encryption Mode * * Parameters: * In: * pMgmtHandle - pointer to management object * eAuthMode - Authentication mode * Out: * none * * Return Value: none * -*/ void VNTWIFIvSetEncryptionMode ( void *pMgmtHandle, WMAC_ENCRYPTION_MODE eEncryptionMode ) { PSMgmtObject pMgmt = (PSMgmtObject)pMgmtHandle; pMgmt->eEncryptionMode = eEncryptionMode; if ((eEncryptionMode == WMAC_ENCRYPTION_WEPEnabled) || (eEncryptionMode == WMAC_ENCRYPTION_TKIPEnabled) || (eEncryptionMode == WMAC_ENCRYPTION_AESEnabled) ) { pMgmt->bPrivacyInvoked = true; } else { pMgmt->bPrivacyInvoked = false; } } bool VNTWIFIbConfigPhyMode ( void *pMgmtHandle, CARD_PHY_TYPE ePhyType ) { PSMgmtObject pMgmt = (PSMgmtObject)pMgmtHandle; if ((ePhyType != PHY_TYPE_AUTO) && (ePhyType != pMgmt->eCurrentPHYMode)) { if (CARDbSetPhyParameter(pMgmt->pAdapter, ePhyType, 0, 0, NULL, NULL)==true) { pMgmt->eCurrentPHYMode = ePhyType; } else { return(false); } } pMgmt->eConfigPHYMode = ePhyType; return(true); } void VNTWIFIbGetConfigPhyMode ( void *pMgmtHandle, void *pePhyType ) { PSMgmtObject pMgmt = (PSMgmtObject)pMgmtHandle; if ((pMgmt != NULL) && (pePhyType != NULL)) { *(PCARD_PHY_TYPE)pePhyType = pMgmt->eConfigPHYMode; } } /*+ * * Description: * Clear BSS List Database except current assoc BSS * * Parameters: * In: * pMgmtHandle - Management Object structure * bLinkPass - Current Link status * Out: * * Return Value: None. * -*/ /*+ * * Description: * Query BSS List in management database * * Parameters: * In: * pMgmtHandle - Management Object structure * Out: * puBSSCount - BSS count * pvFirstBSS - pointer to first BSS * * Return Value: None. * -*/ void VNTWIFIvQueryBSSList(void *pMgmtHandle, unsigned int *puBSSCount, void **pvFirstBSS) { unsigned int ii = 0; PSMgmtObject pMgmt = (PSMgmtObject)pMgmtHandle; PKnownBSS pBSS = NULL; unsigned int uCount = 0; *pvFirstBSS = NULL; for (ii = 0; ii < MAX_BSS_NUM; ii++) { pBSS = &(pMgmt->sBSSList[ii]); if (!pBSS->bActive) { continue; } if (*pvFirstBSS == NULL) { *pvFirstBSS = &(pMgmt->sBSSList[ii]); } uCount++; } *puBSSCount = uCount; } void VNTWIFIvGetNextBSS ( void *pMgmtHandle, void *pvCurrentBSS, void **pvNextBSS ) { PKnownBSS pBSS = (PKnownBSS) pvCurrentBSS; PSMgmtObject pMgmt = (PSMgmtObject)pMgmtHandle; *pvNextBSS = NULL; while (*pvNextBSS == NULL) { pBSS++; if (pBSS > &(pMgmt->sBSSList[MAX_BSS_NUM])) { return; } if (pBSS->bActive == true) { *pvNextBSS = pBSS; return; } } } /*+ * * Description: * Update Tx attemps, Tx failure counter in Node DB * * In: * Out: * none * * Return Value: none * -*/ void VNTWIFIvUpdateNodeTxCounter( void *pMgmtHandle, unsigned char *pbyDestAddress, bool bTxOk, unsigned short wRate, unsigned char *pbyTxFailCount ) { PSMgmtObject pMgmt = (PSMgmtObject)pMgmtHandle; unsigned int uNodeIndex = 0; unsigned int ii; if ((pMgmt->eCurrMode == WMAC_MODE_IBSS_STA) || (pMgmt->eCurrMode == WMAC_MODE_ESS_AP)) { if (BSSDBbIsSTAInNodeDB(pMgmt, pbyDestAddress, &uNodeIndex) == false) { return; } } pMgmt->sNodeDBTable[uNodeIndex].uTxAttempts++; if (bTxOk == true) { // transmit success, TxAttempts at least plus one pMgmt->sNodeDBTable[uNodeIndex].uTxOk[MAX_RATE]++; pMgmt->sNodeDBTable[uNodeIndex].uTxOk[wRate]++; } else { pMgmt->sNodeDBTable[uNodeIndex].uTxFailures++; } pMgmt->sNodeDBTable[uNodeIndex].uTxRetry += pbyTxFailCount[MAX_RATE]; for(ii=0;ii<MAX_RATE;ii++) { pMgmt->sNodeDBTable[uNodeIndex].uTxFail[ii] += pbyTxFailCount[ii]; } return; } void VNTWIFIvGetTxRate( void *pMgmtHandle, unsigned char *pbyDestAddress, unsigned short *pwTxDataRate, unsigned char *pbyACKRate, unsigned char *pbyCCKBasicRate, unsigned char *pbyOFDMBasicRate ) { PSMgmtObject pMgmt = (PSMgmtObject)pMgmtHandle; unsigned int uNodeIndex = 0; unsigned short wTxDataRate = RATE_1M; unsigned char byACKRate = RATE_1M; unsigned char byCCKBasicRate = RATE_1M; unsigned char byOFDMBasicRate = RATE_24M; PWLAN_IE_SUPP_RATES pSupportRateIEs = NULL; PWLAN_IE_SUPP_RATES pExtSupportRateIEs = NULL; if ((pMgmt->eCurrMode == WMAC_MODE_IBSS_STA) || (pMgmt->eCurrMode == WMAC_MODE_ESS_AP)) { // Adhoc Tx rate decided from node DB if(BSSDBbIsSTAInNodeDB(pMgmt, pbyDestAddress, &uNodeIndex)) { wTxDataRate = (pMgmt->sNodeDBTable[uNodeIndex].wTxDataRate); pSupportRateIEs = (PWLAN_IE_SUPP_RATES) (pMgmt->sNodeDBTable[uNodeIndex].abyCurrSuppRates); pExtSupportRateIEs = (PWLAN_IE_SUPP_RATES) (pMgmt->sNodeDBTable[uNodeIndex].abyCurrExtSuppRates); } else { if (pMgmt->eCurrentPHYMode != PHY_TYPE_11A) { wTxDataRate = RATE_2M; } else { wTxDataRate = RATE_24M; } pSupportRateIEs = (PWLAN_IE_SUPP_RATES) pMgmt->abyCurrSuppRates; pExtSupportRateIEs = (PWLAN_IE_SUPP_RATES) pMgmt->abyCurrExtSuppRates; } } else { // Infrastructure: rate decided from AP Node, index = 0 wTxDataRate = (pMgmt->sNodeDBTable[0].wTxDataRate); #ifdef PLICE_DEBUG printk(KERN_DEBUG "GetTxRate:AP MAC is %pM,TxRate is %d\n", pMgmt->sNodeDBTable[0].abyMACAddr, wTxDataRate); #endif pSupportRateIEs = (PWLAN_IE_SUPP_RATES) pMgmt->abyCurrSuppRates; pExtSupportRateIEs = (PWLAN_IE_SUPP_RATES) pMgmt->abyCurrExtSuppRates; } byACKRate = VNTWIFIbyGetACKTxRate( (unsigned char) wTxDataRate, pSupportRateIEs, pExtSupportRateIEs ); if (byACKRate > (unsigned char) wTxDataRate) { byACKRate = (unsigned char) wTxDataRate; } byCCKBasicRate = VNTWIFIbyGetACKTxRate( RATE_11M, pSupportRateIEs, pExtSupportRateIEs ); byOFDMBasicRate = VNTWIFIbyGetACKTxRate(RATE_54M, pSupportRateIEs, pExtSupportRateIEs ); *pwTxDataRate = wTxDataRate; *pbyACKRate = byACKRate; *pbyCCKBasicRate = byCCKBasicRate; *pbyOFDMBasicRate = byOFDMBasicRate; return; } unsigned char VNTWIFIbyGetKeyCypher( void *pMgmtHandle, bool bGroupKey ) { PSMgmtObject pMgmt = (PSMgmtObject)pMgmtHandle; if (bGroupKey == true) { return (pMgmt->byCSSGK); } else { return (pMgmt->byCSSPK); } } /* bool VNTWIFIbInit( void *pAdapterHandler, void **pMgmtHandler ) { PSMgmtObject pMgmt = NULL; unsigned int ii; pMgmt = (PSMgmtObject)kmalloc(sizeof(SMgmtObject), (int)GFP_ATOMIC); if (pMgmt == NULL) { *pMgmtHandler = NULL; return false; } memset(pMgmt, 0, sizeof(SMgmtObject)); pMgmt->pAdapter = (void *) pAdapterHandler; // should initial MAC address abyMACAddr for(ii=0;ii<WLAN_BSSID_LEN;ii++) { pMgmt->abyDesireBSSID[ii] = 0xFF; } pMgmt->pbyPSPacketPool = &pMgmt->byPSPacketPool[0]; pMgmt->pbyMgmtPacketPool = &pMgmt->byMgmtPacketPool[0]; pMgmt->byCSSPK = KEY_CTL_NONE; pMgmt->byCSSGK = KEY_CTL_NONE; pMgmt->wIBSSBeaconPeriod = DEFAULT_IBSS_BI; pMgmt->cbFreeCmdQueue = CMD_Q_SIZE; pMgmt->uCmdDequeueIdx = 0; pMgmt->uCmdEnqueueIdx = 0; pMgmt->eCommandState = WLAN_CMD_STATE_IDLE; pMgmt->bCmdStop = false; pMgmt->bCmdRunning = false; *pMgmtHandler = pMgmt; return true; } */ bool VNTWIFIbSetPMKIDCache ( void *pMgmtObject, unsigned long ulCount, void *pPMKIDInfo ) { PSMgmtObject pMgmt = (PSMgmtObject) pMgmtObject; if (ulCount > MAX_PMKID_CACHE) { return (false); } pMgmt->gsPMKIDCache.BSSIDInfoCount = ulCount; memcpy(pMgmt->gsPMKIDCache.BSSIDInfo, pPMKIDInfo, (ulCount*sizeof(PMKIDInfo))); return (true); } unsigned short VNTWIFIwGetMaxSupportRate( void *pMgmtObject ) { unsigned short wRate = RATE_54M; PSMgmtObject pMgmt = (PSMgmtObject) pMgmtObject; for(wRate = RATE_54M; wRate > RATE_1M; wRate--) { if (pMgmt->sNodeDBTable[0].wSuppRate & (1<<wRate)) { return (wRate); } } if (pMgmt->eCurrentPHYMode == PHY_TYPE_11A) { return (RATE_6M); } else { return (RATE_1M); } } void VNTWIFIvSet11h ( void *pMgmtObject, bool b11hEnable ) { PSMgmtObject pMgmt = (PSMgmtObject) pMgmtObject; pMgmt->b11hEnable = b11hEnable; } bool VNTWIFIbMeasureReport( void *pMgmtObject, bool bEndOfReport, void *pvMeasureEID, unsigned char byReportMode, unsigned char byBasicMap, unsigned char byCCAFraction, unsigned char *pbyRPIs ) { PSMgmtObject pMgmt = (PSMgmtObject) pMgmtObject; unsigned char *pbyCurrentEID = (unsigned char *) (pMgmt->pCurrMeasureEIDRep); //spin_lock_irq(&pDevice->lock); if ((pvMeasureEID != NULL) && (pMgmt->uLengthOfRepEIDs < (WLAN_A3FR_MAXLEN - sizeof(MEASEURE_REP) - sizeof(WLAN_80211HDR_A3) - 3)) ) { pMgmt->pCurrMeasureEIDRep->byElementID = WLAN_EID_MEASURE_REP; pMgmt->pCurrMeasureEIDRep->len = 3; pMgmt->pCurrMeasureEIDRep->byToken = ((PWLAN_IE_MEASURE_REQ) pvMeasureEID)->byToken; pMgmt->pCurrMeasureEIDRep->byMode = byReportMode; pMgmt->pCurrMeasureEIDRep->byType = ((PWLAN_IE_MEASURE_REQ) pvMeasureEID)->byType; switch (pMgmt->pCurrMeasureEIDRep->byType) { case MEASURE_TYPE_BASIC : pMgmt->pCurrMeasureEIDRep->len += sizeof(MEASEURE_REP_BASIC); memcpy( &(pMgmt->pCurrMeasureEIDRep->sRep.sBasic), &(((PWLAN_IE_MEASURE_REQ) pvMeasureEID)->sReq), sizeof(MEASEURE_REQ)); pMgmt->pCurrMeasureEIDRep->sRep.sBasic.byMap = byBasicMap; break; case MEASURE_TYPE_CCA : pMgmt->pCurrMeasureEIDRep->len += sizeof(MEASEURE_REP_CCA); memcpy( &(pMgmt->pCurrMeasureEIDRep->sRep.sCCA), &(((PWLAN_IE_MEASURE_REQ) pvMeasureEID)->sReq), sizeof(MEASEURE_REQ)); pMgmt->pCurrMeasureEIDRep->sRep.sCCA.byCCABusyFraction = byCCAFraction; break; case MEASURE_TYPE_RPI : pMgmt->pCurrMeasureEIDRep->len += sizeof(MEASEURE_REP_RPI); memcpy( &(pMgmt->pCurrMeasureEIDRep->sRep.sRPI), &(((PWLAN_IE_MEASURE_REQ) pvMeasureEID)->sReq), sizeof(MEASEURE_REQ)); memcpy(pMgmt->pCurrMeasureEIDRep->sRep.sRPI.abyRPIdensity, pbyRPIs, 8); break; default : break; } pbyCurrentEID += (2 + pMgmt->pCurrMeasureEIDRep->len); pMgmt->uLengthOfRepEIDs += (2 + pMgmt->pCurrMeasureEIDRep->len); pMgmt->pCurrMeasureEIDRep = (PWLAN_IE_MEASURE_REP) pbyCurrentEID; } if (bEndOfReport == true) { IEEE11hbMSRRepTx(pMgmt); } //spin_unlock_irq(&pDevice->lock); return (true); } bool VNTWIFIbChannelSwitch( void *pMgmtObject, unsigned char byNewChannel ) { PSMgmtObject pMgmt = (PSMgmtObject) pMgmtObject; //spin_lock_irq(&pDevice->lock); pMgmt->uCurrChannel = byNewChannel; pMgmt->bSwitchChannel = false; //spin_unlock_irq(&pDevice->lock); return true; } /* bool VNTWIFIbRadarPresent( void *pMgmtObject, unsigned char byChannel ) { PSMgmtObject pMgmt = (PSMgmtObject) pMgmtObject; if ((pMgmt->eCurrMode == WMAC_MODE_IBSS_STA) && (byChannel == (unsigned char) pMgmt->uCurrChannel) && (pMgmt->bSwitchChannel != true) && (pMgmt->b11hEnable == true)) { if (!compare_ether_addr(pMgmt->abyIBSSDFSOwner, CARDpGetCurrentAddress(pMgmt->pAdapter))) { pMgmt->byNewChannel = CARDbyAutoChannelSelect(pMgmt->pAdapter,(unsigned char) pMgmt->uCurrChannel); pMgmt->bSwitchChannel = true; } BEACONbSendBeacon(pMgmt); CARDbChannelSwitch(pMgmt->pAdapter, 0, pMgmt->byNewChannel, 10); } return true; } */