/*
 * 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"

/*---------------------  Static Definitions -------------------------*/

/*---------------------  Static Classes  ----------------------------*/

/*---------------------  Static Variables  --------------------------*/

/*---------------------  Static Functions  --------------------------*/

/*---------------------  Export Variables  --------------------------*/

/*---------------------  Export Functions  --------------------------*/

/*+
 *
 * Description:
 *    Set Operation Mode
 *
 * Parameters:
 *  In:
 *      pMgmtHandle - pointer to management object
 *      eOPMode     - Operation 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) {
		/* 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];
}

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);

		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;
}

unsigned char
VNTWIFIbyGetKeyCypher(
	void *pMgmtHandle,
	bool bGroupKey
)
{
	PSMgmtObject    pMgmt = (PSMgmtObject)pMgmtHandle;

	if (bGroupKey)
		return pMgmt->byCSSGK;
	else
		return pMgmt->byCSSPK;
}

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);

	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)
		IEEE11hbMSRRepTx(pMgmt);

	return true;
}

bool
VNTWIFIbChannelSwitch(
	void *pMgmtObject,
	unsigned char byNewChannel
)
{
	PSMgmtObject    pMgmt = (PSMgmtObject) pMgmtObject;

	pMgmt->uCurrChannel = byNewChannel;
	pMgmt->bSwitchChannel = false;
	return true;
}
