Linux-2.6.33.2/drivers/staging/otus/80211core/coid.c

Compare this file to the similar file:
Show the results in this format:

/*
 * Copyright (c) 2007-2008 Atheros Communications Inc.
 *
 * Permission to use, copy, modify, and/or distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */
/*                                                                      */
/*  Module Name : iod.c                                                 */
/*                                                                      */
/*  Abstract                                                            */
/*      This module contains OID functions.                             */
/*                                                                      */
/*  NOTES                                                               */
/*      None                                                            */
/*                                                                      */
/************************************************************************/
#include "cprecomp.h"
#include "../hal/hpreg.h"

/************************************************************************/
/*                                                                      */
/*    FUNCTION DESCRIPTION                  zfiWlanQueryMacAddress      */
/*      Query OWN MAC address.                                          */
/*                                                                      */
/*    INPUTS                                                            */
/*      addr : for return MAC address                                   */
/*                                                                      */
/*    OUTPUTS                                                           */
/*      None                                                            */
/*                                                                      */
/*    AUTHOR                                                            */
/*      Stephen Chen        ZyDAS Technology Corporation    2005.10     */
/*                                                                      */
/************************************************************************/
void zfiWlanQueryMacAddress(zdev_t* dev, u8_t* addr)
{
    u16_t vapId = 0;
    zmw_get_wlan_dev(dev);

    vapId = zfwGetVapId(dev);

    addr[0] = (u8_t)(wd->macAddr[0] & 0xff);
    addr[1] = (u8_t)(wd->macAddr[0] >> 8);
    addr[2] = (u8_t)(wd->macAddr[1] & 0xff);
    addr[3] = (u8_t)(wd->macAddr[1] >> 8);
    addr[4] = (u8_t)(wd->macAddr[2] & 0xff);
    if (vapId == 0xffff)
        addr[5] = (u8_t)(wd->macAddr[2] >> 8);
    else
    {
#ifdef ZM_VAPMODE_MULTILE_SSID
        addr[5] = (u8_t)(wd->macAddr[2] >> 8); // Multiple SSID
#else
        addr[5] = vapId + 1 + (u8_t)(wd->macAddr[2] >> 8); //VAP
#endif
    }

    return;
}

void zfiWlanQueryBssList(zdev_t* dev, struct zsBssList* pBssList)
{
    struct zsBssInfo*   pBssInfo;
    struct zsBssInfo*   pDstBssInfo;
    u8_t   i;
    u8_t*  pMemList;
    u8_t*  pMemInfo;

    zmw_get_wlan_dev(dev);

    zmw_declare_for_critical_section();

    pMemList = (u8_t*) pBssList;
    pMemInfo = pMemList + sizeof(struct zsBssList);
    pBssList->head = (struct zsBssInfo*) pMemInfo;

    zmw_enter_critical_section(dev);

    pBssInfo = wd->sta.bssList.head;
    pDstBssInfo = (struct zsBssInfo*) pMemInfo;
    pBssList->bssCount = wd->sta.bssList.bssCount;

    for( i=0; i<wd->sta.bssList.bssCount; i++ )
    {
        zfMemoryCopy((u8_t*)pDstBssInfo, (u8_t*)pBssInfo,
                sizeof(struct zsBssInfo));

        if ( pBssInfo->next != NULL )
        {
            pBssInfo = pBssInfo->next;
            pDstBssInfo->next = pDstBssInfo + 1;
            pDstBssInfo++;
        }
        else
        {
            zm_assert(i==(wd->sta.bssList.bssCount-1));
        }
    }

    zmw_leave_critical_section(dev);

    zfScanMgrScanAck(dev);
}

void zfiWlanQueryBssListV1(zdev_t* dev, struct zsBssListV1* bssListV1)
{
    struct zsBssInfo*   pBssInfo;
    //struct zsBssInfo*   pDstBssInfo;
    u8_t   i, j, bdrop = 0, k = 0, Same_Count = 0;
    u8_t   bssid[6];
    //u8_t*  pMemList;
    //u8_t*  pMemInfo;
    zmw_get_wlan_dev(dev);
    zmw_declare_for_critical_section();

    zmw_enter_critical_section(dev);

    bssListV1->bssCount = wd->sta.bssList.bssCount;

    pBssInfo = wd->sta.bssList.head;
    ZM_MAC_WORD_TO_BYTE(wd->sta.bssid, bssid);

    for( i=0; i<wd->sta.bssList.bssCount; i++ )
    {
        bdrop = 0;
        if ( zfStaIsConnected(dev)
             && (wd->wlanMode == ZM_MODE_INFRASTRUCTURE ) )
        {
			for (j = 0; j < 6; j++)
            {
                if ( pBssInfo->bssid[j] != bssid[j] )
                {
                    break;
                }
            }

            if  ( (j == 6)
                  &&((pBssInfo->ssid[1] == wd->sta.ssidLen) || (pBssInfo->ssid[1] == 0) )&& (pBssInfo->frequency == wd->frequency) )
            {
				if(pBssInfo->ssid[1] == 0)
					pBssInfo->ssid[1] = wd->sta.ssidLen;

				if(Same_Count == 0)
				{//First meet
					Same_Count++;
				}
				else
				{//same one
					bdrop = 1;
					bssListV1->bssCount--;
				}

            }
        }

        if (bdrop == 0)
        {
            zfMemoryCopy((u8_t*)(&bssListV1->bssInfo[k]), (u8_t*)pBssInfo,
                sizeof(struct zsBssInfo));

			if(Same_Count == 1)
			{
				zfMemoryCopy(&(bssListV1->bssInfo[k].ssid[2]), wd->sta.ssid, wd->sta.ssidLen);
				Same_Count++;
			}

			k++;
        }

        if ( pBssInfo->next != NULL )
        {
            pBssInfo = pBssInfo->next;
        }
        else
        {
            zm_assert(i==(wd->sta.bssList.bssCount-1));
        }
    }

    zmw_leave_critical_section(dev);

    zfScanMgrScanAck(dev);
}

void zfiWlanQueryAdHocCreatedBssDesc(zdev_t* dev, struct zsBssInfo *pBssInfo)
{
    zmw_get_wlan_dev(dev);

    zfMemoryCopy((u8_t *)pBssInfo, (u8_t *)&wd->sta.ibssBssDesc, sizeof(struct zsBssInfo));
}

u8_t zfiWlanQueryAdHocIsCreator(zdev_t* dev)
{
    zmw_get_wlan_dev(dev);

    return wd->sta.ibssBssIsCreator;
}

u32_t zfiWlanQuerySupportMode(zdev_t* dev)
{
    zmw_get_wlan_dev(dev);

    return wd->supportMode;
}

u32_t zfiWlanQueryTransmitPower(zdev_t* dev)
{
    u32_t ret = 0;

    zmw_get_wlan_dev(dev);

    if (zfStaIsConnected(dev)) {
        ret = wd->sta.connPowerInHalfDbm;
    } else {
        ret = zfHpGetTransmitPower(dev);
    }

    return ret;
}

/************************************************************************/
/*                                                                      */
/*    FUNCTION DESCRIPTION                  zfiWlanFlushBssList         */
/*      Flush BSSID List.                                               */
/*                                                                      */
/*    INPUTS                                                            */
/*      dev : device pointer                                            */
/*                                                                      */
/*    OUTPUTS                                                           */
/*      none                                                            */
/*                                                                      */
/*    AUTHOR                                                            */
/*      Stephen Chen        Atheros Communications, INC.    2006.12     */
/*                                                                      */
/************************************************************************/
void zfiWlanFlushBssList(zdev_t* dev)
{
    zmw_declare_for_critical_section();

    zmw_enter_critical_section(dev);
    /* Call zfBssInfoRefresh() twice to remove all entry */
    zfBssInfoRefresh(dev, 1);
    zmw_leave_critical_section(dev);
}

void zfiWlanSetWlanMode(zdev_t* dev, u8_t wlanMode)
{
    zmw_get_wlan_dev(dev);

    zmw_declare_for_critical_section();

    zmw_enter_critical_section(dev);
    wd->ws.wlanMode = wlanMode;
    zmw_leave_critical_section(dev);
}

void zfiWlanSetAuthenticationMode(zdev_t* dev, u8_t authMode)
{
    zmw_get_wlan_dev(dev);

    zmw_declare_for_critical_section();

    zmw_enter_critical_section(dev);
    wd->ws.authMode = authMode;
    zmw_leave_critical_section(dev);
}

void zfiWlanSetWepStatus(zdev_t* dev, u8_t wepStatus)
{
    zmw_get_wlan_dev(dev);

    zmw_declare_for_critical_section();

    zmw_enter_critical_section(dev);
    wd->ws.wepStatus = wepStatus;
    zmw_leave_critical_section(dev);

}

void zfiWlanSetSSID(zdev_t* dev, u8_t* ssid, u8_t ssidLength)
{
    u16_t i;
    zmw_get_wlan_dev(dev);

    zmw_declare_for_critical_section();

    if ( ssidLength <= 32 )
    {
        zmw_enter_critical_section(dev);

        wd->ws.ssidLen = ssidLength;
        zfMemoryCopy(wd->ws.ssid, ssid, ssidLength);

        if ( ssidLength < 32 )
        {
            wd->ws.ssid[ssidLength] = 0;
        }

        wd->ws.probingSsidList[0].ssidLen = ssidLength;
        zfMemoryCopy(wd->ws.probingSsidList[0].ssid, ssid, ssidLength);
        for (i=1; i<ZM_MAX_PROBE_HIDDEN_SSID_SIZE; i++)
        {
            wd->ws.probingSsidList[i].ssidLen = 0;
        }

        zmw_leave_critical_section(dev);
    }
}

void zfiWlanSetFragThreshold(zdev_t* dev, u16_t fragThreshold)
{
    zmw_get_wlan_dev(dev);

    zmw_declare_for_critical_section();

    zmw_enter_critical_section(dev);

    if (fragThreshold == 0)
    {   /* fragmentation is disabled */
        wd->fragThreshold = 32767;
    }
    else if (fragThreshold < 256)
    {
        /* Minimum fragment threshold */
        wd->fragThreshold = 256;
    }
    else if (fragThreshold > 2346)
    {
        wd->fragThreshold = 2346;
    }
    else
    {
        wd->fragThreshold = fragThreshold & 0xfffe;
    }

    zmw_leave_critical_section(dev);
}

void zfiWlanSetRtsThreshold(zdev_t* dev, u16_t rtsThreshold)
{
    zmw_get_wlan_dev(dev);

    zmw_declare_for_critical_section();

    zmw_enter_critical_section(dev);
    wd->rtsThreshold = rtsThreshold;
    zmw_leave_critical_section(dev);
}

void zfiWlanSetFrequency(zdev_t* dev, u32_t frequency, u8_t bImmediate)
{
    zmw_get_wlan_dev(dev);

    zmw_declare_for_critical_section();

    if ( bImmediate )
    {
        zmw_enter_critical_section(dev);
        wd->frequency = (u16_t) (frequency/1000);
        zmw_leave_critical_section(dev);
        zfCoreSetFrequency(dev, wd->frequency);
    }
    else
    {
        zmw_enter_critical_section(dev);
        if( frequency == 0 )
        { // Auto select clean channel depend on wireless environment !
            wd->ws.autoSetFrequency = 0;
        }
        wd->ws.frequency = (u16_t) (frequency/1000);
        zmw_leave_critical_section(dev);
    }
}

void zfiWlanSetBssid(zdev_t* dev, u8_t* bssid)
{
    u16_t i;
    zmw_get_wlan_dev(dev);

    zmw_declare_for_critical_section();

    zmw_enter_critical_section(dev);
    for (i=0; i<6; i++)
    {
        wd->ws.desiredBssid[i] = bssid[i];
    }
    wd->ws.bDesiredBssid = TRUE;
    zmw_leave_critical_section(dev);

}

void zfiWlanSetBeaconInterval(zdev_t* dev,
                              u16_t  beaconInterval,
                              u8_t   bImmediate)
{
    zmw_get_wlan_dev(dev);

    zmw_declare_for_critical_section();

    if ( bImmediate )
    {
        zmw_enter_critical_section(dev);
        wd->beaconInterval = beaconInterval;
        zmw_leave_critical_section(dev);

        /* update beacon interval here */
    }
    else
    {
        zmw_enter_critical_section(dev);
        wd->ws.beaconInterval = beaconInterval;
        zmw_leave_critical_section(dev);
    }
}


void zfiWlanSetDtimCount(zdev_t* dev, u8_t  dtim)
{
    zmw_get_wlan_dev(dev);

    zmw_declare_for_critical_section();

    zmw_enter_critical_section(dev);
    if (dtim > 0)
    {
        wd->ws.dtim = dtim;
    }
    zmw_leave_critical_section(dev);
}


void zfiWlanSetAtimWindow(zdev_t* dev, u16_t atimWindow, u8_t bImmediate)
{
    zmw_get_wlan_dev(dev);

    zmw_declare_for_critical_section();

    if ( bImmediate )
    {
        zmw_enter_critical_section(dev);
        wd->sta.atimWindow = atimWindow;
        zmw_leave_critical_section(dev);

        /* atim window here */
    }
    else
    {
        zmw_enter_critical_section(dev);
        wd->ws.atimWindow = atimWindow;
        zmw_leave_critical_section(dev);
    }
}


void zfiWlanSetEncryMode(zdev_t* dev, u8_t encryMode)
{
    zmw_get_wlan_dev(dev);

    zmw_declare_for_critical_section();

    zmw_enter_critical_section(dev);
    if (wd->wlanMode == ZM_MODE_AP)
    {
        /* Hostapd Issue */
        if ((wd->ws.encryMode != ZM_AES) && (wd->ws.encryMode != ZM_TKIP))
            wd->ws.encryMode = encryMode;
    }
    else
        wd->ws.encryMode = encryMode;
    zmw_leave_critical_section(dev);
}

void zfiWlanSetDefaultKeyId(zdev_t* dev, u8_t keyId)
{
    zmw_get_wlan_dev(dev);

    wd->sta.keyId = keyId;
}

u8_t zfiWlanQueryIsPKInstalled(zdev_t *dev, u8_t *staMacAddr)
{
    u8_t isInstalled = 0;

#if 1
//#ifdef ZM_ENABLE_IBSS_WPA2PSK
    u8_t   res, peerIdx;

    zmw_get_wlan_dev(dev);

    zmw_declare_for_critical_section();

    zmw_enter_critical_section(dev);
    res = zfStaFindOppositeByMACAddr(dev, (u16_t *)staMacAddr, &peerIdx);
    if( res == 0 )
    {
        isInstalled = wd->sta.oppositeInfo[peerIdx].pkInstalled;
    }
    zmw_leave_critical_section(dev);
//#endif
#endif

    return isInstalled;
}

u8_t zfiWlanSetKey(zdev_t* dev, struct zsKeyInfo keyInfo)
{
    u16_t  broadcast[3] = {0xffff, 0xffff, 0xffff};
    u32_t* key;
    u8_t   encryMode = ZM_NO_WEP;
#ifdef ZM_ENABLE_IBSS_WPA2PSK
    u8_t   encryType = ZM_NO_WEP;
#endif
    u8_t   micKey[16];
    u16_t  id = 0;
    u8_t   vapId, i, addr[6];
    u8_t   userIdx=0;

#ifdef ZM_ENABLE_IBSS_WPA2PSK
    /* Determine opposite exist or not */
    u8_t   res, peerIdx;
//    u8_t   userIdx=0;

    zmw_get_wlan_dev(dev);

    if ( wd->sta.ibssWpa2Psk == 1 )
    {
        zmw_enter_critical_section(dev);
        res = zfStaFindOppositeByMACAddr(dev, (u16_t*)keyInfo.macAddr, &peerIdx);
        if( res == 0 )
        {
            userIdx = peerIdx;
            if ( wd->sta.oppositeInfo[userIdx].camIdx == 0xff )
                wd->sta.oppositeInfo[userIdx].camIdx = userIdx;
        }
        zmw_leave_critical_section(dev);
    }
#else
    zmw_get_wlan_dev(dev);
#endif

    if ( keyInfo.flag & ZM_KEY_FLAG_AUTHENTICATOR )
    {   /* set key by authenticator */
        /* set pairwise key */
        if (keyInfo.flag & ZM_KEY_FLAG_PK)
        {
            /* Find STA's information */
            if ((id = zfApFindSta(dev, keyInfo.macAddr)) == 0xffff)
            {
                /* Can't STA in the staTable */
                return ZM_STATUS_FAILURE;
            }

            wd->ap.staTable[id].iv16 = 0;
            wd->ap.staTable[id].iv32 = 0;

            if (keyInfo.keyLength == 32)
            {   /* TKIP */
                //u8_t KeyRsc[6] = {0, 0, 0, 0, 0, 0};

                /* In the current AP mode, we set KeyRsc to zero */
                //zfTkipInit(keyInfo.key, (u8_t*) wd->macAddr,
                //           &(wd->ap.staTable[id].txSeed), KeyRsc);
                //zfTkipInit(keyInfo.key, (u8_t*) keyInfo.macAddr,
                //           &(wd->ap.staTable[id].rxSeed), KeyRsc);
#ifdef ZM_ENABLE_CENC
                if (keyInfo.flag & ZM_KEY_FLAG_CENC)
                {
                    zm_debug_msg0("Set CENC pairwise Key");

                    wd->ap.staTable[id].encryMode = ZM_CENC;

                    /* Reset txiv and rxiv */
                    wd->ap.staTable[id].txiv[0] = 0x5c365c37;
                    wd->ap.staTable[id].txiv[1] = 0x5c365c36;
                    wd->ap.staTable[id].txiv[2] = 0x5c365c36;
                    wd->ap.staTable[id].txiv[3] = 0x5c365c36;

                    wd->ap.staTable[id].rxiv[0] = 0x5c365c36;
                    wd->ap.staTable[id].rxiv[1] = 0x5c365c36;
                    wd->ap.staTable[id].rxiv[2] = 0x5c365c36;
                    wd->ap.staTable[id].rxiv[3] = 0x5c365c36;

                    /* Set Key Index */
                    wd->ap.staTable[id].cencKeyIdx = keyInfo.keyIndex;

                    //zfCoreSetKey(dev, id+1, 1, ZM_CENC, (u16_t *)keyInfo.macAddr,
                    //          (u32_t*) &keyInfo.key[16]);
                }
                else
#endif //ZM_ENABLE_CENC
                {
                    wd->ap.staTable[id].encryMode = ZM_TKIP;

                    zfMemoryCopy(micKey, &keyInfo.key[16], 8);
                    zfMemoryCopy(&micKey[8], &keyInfo.key[24], 8);

                    //zfCoreSetKey(dev, id+1, 1, ZM_TKIP, (u16_t *)keyInfo.macAddr,
                    //           (u32_t*) micKey);

                    /* For fragmentation, we use software MIC */
                    zfMemoryCopy((u8_t *)&(wd->ap.staTable[id].txMicKey), &(keyInfo.key[16]), 8);
                    zfMemoryCopy((u8_t *)&(wd->ap.staTable[id].rxMicKey), &(keyInfo.key[24]), 8);

                }
            }
            else if (keyInfo.keyLength == 16)
            {   /* AES */
                wd->ap.staTable[id].encryMode = ZM_AES;
            }
            else if (keyInfo.keyLength == 0)
            {
                /* Clear Key Info */
                zfApClearStaKey(dev, (u16_t *)keyInfo.macAddr);

                return ZM_STATUS_SUCCESS;
            }
            else
            {
                return ZM_STATUS_FAILURE;
            }

            //zfCoreSetKey(dev, id+1, 0, wd->ap.staTable[id].encryMode,
            //      (u16_t *)keyInfo.macAddr, (u32_t*) keyInfo.key);
            zfHpSetApPairwiseKey(dev, (u16_t *)keyInfo.macAddr,
                    wd->ap.staTable[id].encryMode, (u32_t*) keyInfo.key,
                    (u32_t*) &keyInfo.key[16], id+1);
            wd->ap.staTable[id].keyIdx = id + 1 + 4;
        }
        else if (keyInfo.flag & ZM_KEY_FLAG_GK)
        {
            vapId = keyInfo.vapId;

            wd->ap.iv16[vapId] = 0;
            wd->ap.iv32[vapId] = 0;

            if (keyInfo.keyLength == 32)
            {   /* TKIP */
                //u8_t KeyRsc[6] = {0, 0, 0, 0, 0, 0};

                //zfTkipInit(keyInfo.key, (u8_t*) wd->macAddr,
                //           &(wd->ap.bcSeed), KeyRsc);
#ifdef ZM_ENABLE_CENC
                if (keyInfo.flag & ZM_KEY_FLAG_CENC)
                {
                    encryMode = ZM_CENC;
                    zm_debug_msg0("Set CENC group Key");

                    /* Reset txiv and rxiv */
                    wd->ap.txiv[vapId][0] = 0x5c365c36;
                    wd->ap.txiv[vapId][1] = 0x5c365c36;
                    wd->ap.txiv[vapId][2] = 0x5c365c36;
                    wd->ap.txiv[vapId][3] = 0x5c365c36;

                    //zfCoreSetKey(dev, 0, 1, ZM_CENC, keyInfo.vapAddr,
                    //          (u32_t*) &keyInfo.key[16]);
                    key = (u32_t*) keyInfo.key;
                }
                else
#endif //ZM_ENABLE_CENC
                {
                    encryMode = ZM_TKIP;
                    key = (u32_t *)keyInfo.key;

                    /* set MIC key to HMAC */
                    //zfCoreSetKey(dev, 0, 1, ZM_TKIP, broadcast,
                    //         (u32_t*) (&keyInfo.key[16]));
                    //zfCoreSetKey(dev, 0, 1, ZM_TKIP, keyInfo.vapAddr,
                    //           (u32_t*) (&keyInfo.key[16]));

                    zfMicSetKey(&(keyInfo.key[16]), &(wd->ap.bcMicKey[0]));
                    key = (u32_t*) keyInfo.key;
                }
            }
            else if (keyInfo.keyLength == 16)
            {   /* AES */
                encryMode = ZM_AES;
                key = (u32_t *)keyInfo.key;
                zm_debug_msg0("CWY - Set AES Group Key");
            }
            else if (keyInfo.keyLength == 0)
            {
                /* Clear Key Info */
                zfApClearStaKey(dev, broadcast);

                /* Turn off WEP bit in the capability field */
                wd->ap.capab[vapId] &= 0xffef;

                return ZM_STATUS_SUCCESS;
            }
            else
            {   /* WEP */
                if (keyInfo.keyLength == 5)
                {
                    encryMode = ZM_WEP64;
                }
                else if (keyInfo.keyLength == 13)
                {
                    encryMode = ZM_WEP128;
                }
                else if (keyInfo.keyLength == 29)
                {
                    encryMode = ZM_WEP256;
                }

                key = (u32_t*) keyInfo.key;
            }

            // Modification for CAM not support VAP search
            //zfCoreSetKey(dev, 0, 0, encryMode, broadcast, key);
            //zfCoreSetKey(dev, 0, 0, encryMode, wd->macAddr, key);
            //zfCoreSetKey(dev, 0, 0, encryMode, keyInfo.vapAddr, key);
            zfHpSetApGroupKey(dev, wd->macAddr, encryMode,
                    key, (u32_t*) &keyInfo.key[16], vapId);

            //zfiWlanSetEncryMode(dev, encryMode);
            wd->ws.encryMode = encryMode;

            /* set the multicast address encryption type */
            wd->ap.encryMode[vapId] = encryMode;

            /* set the multicast key index */
            wd->ap.bcKeyIndex[vapId] = keyInfo.keyIndex;
            wd->ap.bcHalKeyIdx[vapId] = vapId + 60;

            /* Turn on WEP bit in the capability field */
            wd->ap.capab[vapId] |= 0x10;
        }
    }
    else
    {   /* set by supplicant */

        if ( keyInfo.flag & ZM_KEY_FLAG_PK )
        {   /* set pairwise key */

            //zfTkipInit(keyInfo.key, (u8_t*) wd->macAddr,
            //           &wd->sta.txSeed, keyInfo.initIv);
            //zfTkipInit(keyInfo.key, (u8_t*) wd->sta.bssid,
            //           &wd->sta.rxSeed[keyInfo.keyIndex], keyInfo.initIv);

#ifdef ZM_ENABLE_IBSS_WPA2PSK
            if ( wd->sta.ibssWpa2Psk == 1 )
            {
                /* unicast -- > pairwise key */
                wd->sta.oppositeInfo[userIdx].iv16 = 0;
                wd->sta.oppositeInfo[userIdx].iv32 = 0;
            }
            else
            {
                wd->sta.iv16 = 0;
                wd->sta.iv32 = 0;
            }

            wd->sta.oppositeInfo[userIdx].pkInstalled = 1;
#else
            wd->sta.iv16 = 0;
            wd->sta.iv32 = 0;

            wd->sta.oppositeInfo[userIdx].pkInstalled = 1;
#endif

            if ( keyInfo.keyLength == 32 )
            {   /* TKIP */
                zfTkipInit(keyInfo.key, (u8_t*) wd->macAddr,
                        &wd->sta.txSeed, keyInfo.initIv);
                zfTkipInit(keyInfo.key, (u8_t*) wd->sta.bssid,
                        &wd->sta.rxSeed[keyInfo.keyIndex], keyInfo.initIv);

#ifdef ZM_ENABLE_CENC
                if (keyInfo.flag & ZM_KEY_FLAG_CENC)
                {
                    zm_debug_msg0("Set CENC pairwise Key");

                    wd->sta.encryMode = ZM_CENC;

                    /* Reset txiv and rxiv */
                    wd->sta.txiv[0] = 0x5c365c36;
                    wd->sta.txiv[1] = 0x5c365c36;
                    wd->sta.txiv[2] = 0x5c365c36;
                    wd->sta.txiv[3] = 0x5c365c36;

                    wd->sta.rxiv[0] = 0x5c365c37;
                    wd->sta.rxiv[1] = 0x5c365c36;
                    wd->sta.rxiv[2] = 0x5c365c36;
                    wd->sta.rxiv[3] = 0x5c365c36;

                    /* Set Key Index */
                    wd->sta.cencKeyId = keyInfo.keyIndex;

                    //zfCoreSetKey(dev, id+1, 1, ZM_CENC, (u16_t *)keyInfo.macAddr,
                    //         (u32_t*) &keyInfo.key[16]);
                }
                else
#endif //ZM_ENABLE_CENC
                {
                    wd->sta.encryMode = ZM_TKIP;

                    //zfCoreSetKey(dev, 0, 1, ZM_TKIP, wd->sta.bssid,
                    //         (u32_t*) &keyInfo.key[16]);

                    zfMicSetKey(&keyInfo.key[16], &wd->sta.txMicKey);
                    zfMicSetKey(&keyInfo.key[24],
                                &wd->sta.rxMicKey[keyInfo.keyIndex]);
                }
            }
            else if ( keyInfo.keyLength == 16 )
            {   /* AES */
#ifdef ZM_ENABLE_IBSS_WPA2PSK
                if ( wd->sta.ibssWpa2Psk == 1 )
                {
                    wd->sta.oppositeInfo[userIdx].encryMode = ZM_AES;
                    encryType = wd->sta.oppositeInfo[userIdx].encryMode;
                }
                else
                {
                    wd->sta.encryMode = ZM_AES;
                    encryType = wd->sta.encryMode;
                }
#else
                wd->sta.encryMode = ZM_AES;
#endif
            }
            else
            {
                return ZM_STATUS_FAILURE;
            }

            /* user 0 */
            //zfCoreSetKey(dev, 0, 0, wd->sta.encryMode,
            //         wd->sta.bssid, (u32_t*) keyInfo.key);
            //zfHpSetStaPairwiseKey(dev, wd->sta.bssid, wd->sta.encryMode,
            //    (u32_t*) keyInfo.key, (u32_t*) &keyInfo.key[16]);

#ifdef ZM_ENABLE_IBSS_WPA2PSK
            if ( (keyInfo.keyLength==16) && (wd->sta.ibssWpa2Psk==1) )
            { /* If not AES-CCMP and ibss network , use traditional */
                zfHpSetPerUserKey(dev,
                                userIdx,
                                keyInfo.keyIndex,  // key id == 0 ( Pairwise key = 0 )
                                (u8_t*)keyInfo.macAddr,   // RX need Source Address ( Address 2 )
                                encryType,
//                              wd->sta.encryMode,
                                (u32_t*) keyInfo.key, (u32_t*) &keyInfo.key[16]);

                wd->sta.oppositeInfo[userIdx].wpaState = ZM_STA_WPA_STATE_PK_OK ;
            }
            else
            {/* Big Endian and Little Endian Compatibility */
                for (i = 0; i < 3; i++)
                {
                    addr[2 * i] = wd->sta.bssid[i] & 0xff;
                    addr[2 * i + 1] = wd->sta.bssid[i] >> 8;
                }
                zfHpSetPerUserKey(dev,
                                    ZM_USER_KEY_PK,   // user id
                                    0,                // key id
                                    addr,//(u8_t *)wd->sta.bssid,
                              wd->sta.encryMode,
                              (u32_t*) keyInfo.key, (u32_t*) &keyInfo.key[16]);

                wd->sta.keyId = 4;
            }
#else
            /* Big Endian and Little Endian Compatibility */
            for (i = 0; i < 3; i++)
            {
                addr[2 * i] = wd->sta.bssid[i] & 0xff;
                addr[2 * i + 1] = wd->sta.bssid[i] >> 8;
            }
            zfHpSetPerUserKey(dev,
                              ZM_USER_KEY_PK,   // user id
                              0,                // key id
                              addr,//(u8_t *)wd->sta.bssid,
                              wd->sta.encryMode,
                              (u32_t*) keyInfo.key, (u32_t*) &keyInfo.key[16]);

            wd->sta.keyId = 4;
#endif

            wd->sta.wpaState = ZM_STA_WPA_STATE_PK_OK;
        }
        else if ( keyInfo.flag & ZM_KEY_FLAG_GK )
        {   /* set group key */

            zfTkipInit(keyInfo.key, (u8_t*) wd->sta.bssid,
                       &wd->sta.rxSeed[keyInfo.keyIndex], keyInfo.initIv);

            if ( keyInfo.keyLength == 32 )
            {   /* TKIP */
#ifdef ZM_ENABLE_CENC
                if (keyInfo.flag & ZM_KEY_FLAG_CENC)
                {
                    encryMode = ZM_CENC;
                    zm_debug_msg0("Set CENC group Key");

                    /* Reset txiv and rxiv */
                    wd->sta.rxivGK[0] = 0x5c365c36;
                    wd->sta.rxivGK[1] = 0x5c365c36;
                    wd->sta.rxivGK[2] = 0x5c365c36;
                    wd->sta.rxivGK[3] = 0x5c365c36;

                    //zfCoreSetKey(dev, 0, 1, ZM_CENC, keyInfo.vapAddr,
                    //         (u32_t*) &keyInfo.key[16]);
                    key = (u32_t*) keyInfo.key;
                }
                else
#endif //ZM_ENABLE_CENC
                {
                    encryMode = ZM_TKIP;
                    key = (u32_t*) wd->sta.rxSeed[keyInfo.keyIndex].tk;

                    if ( !(keyInfo.flag & ZM_KEY_FLAG_INIT_IV) )
                    {
                        wd->sta.rxSeed[keyInfo.keyIndex].iv16 = 0;
                        wd->sta.rxSeed[keyInfo.keyIndex].iv32 = 0;
                    }

                    /* set MIC key to HMAC */
                    //zfCoreSetKey(dev, 8, 1, ZM_TKIP, broadcast,
                    //         (u32_t*) (&keyInfo.key[16]));

                    zfMicSetKey(&keyInfo.key[24],
                                &wd->sta.rxMicKey[keyInfo.keyIndex]);
                }
            }
            else if ( keyInfo.keyLength == 16 )
            {   /* AES */
                encryMode = ZM_AES;
                //key = (u32_t*) wd->sta.rxSeed[keyInfo.keyIndex].tk;
            }
            else
            {   /* WEP */
                if ( keyInfo.keyLength == 5 )
                {
                    encryMode = ZM_WEP64;
                }
                else if ( keyInfo.keyLength == 13 )
                {
                    encryMode = ZM_WEP128;
                }
                else if ( keyInfo.keyLength == 29 )
                {
                    encryMode = ZM_WEP256;
                }

                key = (u32_t*) keyInfo.key;
            }

            /* user 8 */
            //zfCoreSetKey(dev, 8, 0, encryMode, broadcast, key);
            //zfHpSetStaGroupKey(dev, broadcast, encryMode,
            //        (u32_t*) keyInfo.key, (u32_t*) (&keyInfo.key[16]));

#ifdef ZM_ENABLE_IBSS_WPA2PSK
            if ( (keyInfo.keyLength==16) && (wd->sta.ibssWpa2Psk==1) )
            {/* If not AES-CCMP and ibss network , use traditional */
                zfHpSetPerUserKey(dev,
                              userIdx,
                              keyInfo.keyIndex,                // key id
                              // (u8_t *)broadcast,                  // for only 2 stations IBSS netwrl ( A2 )
                              (u8_t*)keyInfo.macAddr,   // for multiple ( > 2 ) stations IBSS network ( A2 )
                              encryMode,
                              (u32_t*) keyInfo.key, (u32_t*) &keyInfo.key[16]);
            }
            else
            {
                zfHpSetPerUserKey(dev,
                                ZM_USER_KEY_GK,   // user id
                                0,                // key id
                                (u8_t *)broadcast,
                                encryMode,
                                (u32_t*) keyInfo.key, (u32_t*) &keyInfo.key[16]);

                wd->sta.wpaState = ZM_STA_WPA_STATE_GK_OK;
            }
#else
            zfHpSetPerUserKey(dev,
                              ZM_USER_KEY_GK,   // user id
                              0,                // key id
                              (u8_t *)broadcast,
                              encryMode,
                              (u32_t*) keyInfo.key, (u32_t*) &keyInfo.key[16]);

            wd->sta.wpaState = ZM_STA_WPA_STATE_GK_OK;
#endif
        }
        else
        {   /* legacy WEP */
            zm_debug_msg0("legacy WEP");

            if ( keyInfo.keyIndex >= 4 )
            {
                return ZM_STATUS_FAILURE;
            }

            if ( keyInfo.keyLength == 5 )
            {
                zm_debug_msg0("WEP 64");

                encryMode = ZM_WEP64;
            }
            else if ( keyInfo.keyLength == 13 )
            {
                zm_debug_msg0("WEP 128");

                encryMode = ZM_WEP128;
            }
            else if ( keyInfo.keyLength == 32 )
            {
                /* TKIP */
                #if 0
                // Don't reset the IV since some AP would fail in IV check and drop our connection
                if ( wd->sta.wpaState != ZM_STA_WPA_STATE_PK_OK )
                {
                    wd->sta.iv16 = 0;
                    wd->sta.iv32 = 0;
                }
                #endif

                encryMode = ZM_TKIP;

                zfTkipInit(keyInfo.key, (u8_t*) wd->sta.bssid,
                           &wd->sta.rxSeed[keyInfo.keyIndex], keyInfo.initIv);
                zfMicSetKey(&keyInfo.key[24],
                           &wd->sta.rxMicKey[keyInfo.keyIndex]);
            }
            else if ( keyInfo.keyLength == 16 )
            {
                /* AES */
                #if 0
                // Don't reset the IV since some AP would fail in IV check and drop our connection
                if ( wd->sta.wpaState != ZM_STA_WPA_STATE_PK_OK )
                {
                    /* broadcast -- > group key */
                    /* Only initialize when set our default key ! */
                    wd->sta.iv16 = 0;
                    wd->sta.iv32 = 0;
                }
                #endif

                encryMode = ZM_AES;
            }
            else if ( keyInfo.keyLength == 29 )
            {
                zm_debug_msg0("WEP 256");

                encryMode = ZM_WEP256;
                //zfCoreSetKey(dev, 64, 1, wd->sta.encryMode,
                //         wd->sta.bssid, (u32_t*) (&keyInfo.key[16]));
            }
            else
            {
                return ZM_STATUS_FAILURE;
            }

            {
                u8_t i;

                zm_debug_msg0("key = ");
                for(i = 0; i < keyInfo.keyLength; i++)
                {
                    zm_debug_msg2("", keyInfo.key[i]);
                }
            }

            if ( keyInfo.flag & ZM_KEY_FLAG_DEFAULT_KEY )
            {
                //for WEP default key 1~3 and ATOM platform--CWYang(+)
                vapId = 0;
                wd->ap.bcHalKeyIdx[vapId] = keyInfo.keyIndex;
                wd->ap.bcKeyIndex[vapId] = keyInfo.keyIndex;
                wd->sta.keyId = keyInfo.keyIndex;
            }

			if(encryMode == ZM_TKIP)
			{
				if(wd->TKIP_Group_KeyChanging == 0x1)
				{
					zm_debug_msg0("Countermeasure : Cancel Old Timer ");
					zfTimerCancel(dev,	ZM_EVENT_SKIP_COUNTERMEASURE);
				}
				else
				{
					zm_debug_msg0("Countermeasure : Create New Timer ");
				}

				wd->TKIP_Group_KeyChanging = 0x1;
				zfTimerSchedule(dev, ZM_EVENT_SKIP_COUNTERMEASURE, 150);
			}



			//------------------------------------------------------------------------

            /* use default key */
            //zfCoreSetKey(dev, ZM_USER_KEY_DEFAULT+keyInfo.keyIndex, 0,
            //         wd->sta.encryMode, wd->sta.bssid, (u32_t*) keyInfo.key);

            if ( encryMode == ZM_TKIP ||
                 encryMode == ZM_AES )
            {
                zfHpSetDefaultKey(dev, keyInfo.keyIndex, encryMode,
                                 (u32_t*) keyInfo.key, (u32_t*) &keyInfo.key[16]);

#ifdef ZM_ENABLE_IBSS_WPA2PSK
            if ( (keyInfo.keyLength==16) && (wd->sta.ibssWpa2Psk==1) )
            {/* If not AES-CCMP and ibss network , use traditional */
                wd->sta.wpaState = ZM_STA_WPA_STATE_PK_OK;
            }
            else
            {
                if (wd->sta.wpaState == ZM_STA_WPA_STATE_PK_OK)
                    wd->sta.wpaState = ZM_STA_WPA_STATE_GK_OK;
                else
                {
                    wd->sta.wpaState = ZM_STA_WPA_STATE_PK_OK;
                    wd->sta.encryMode = encryMode;
                    wd->ws.encryMode = encryMode;
                }
            }
#else
                if (wd->sta.wpaState == ZM_STA_WPA_STATE_PK_OK)
                    wd->sta.wpaState = ZM_STA_WPA_STATE_GK_OK;
                else if ( wd->sta.wpaState == ZM_STA_WPA_STATE_INIT )
                {
                    wd->sta.wpaState = ZM_STA_WPA_STATE_PK_OK;
                    wd->sta.encryMode = encryMode;
                    wd->ws.encryMode = encryMode;
                }
#endif
            }
            else
            {
                zfHpSetDefaultKey(dev, keyInfo.keyIndex, encryMode,
                               (u32_t*) keyInfo.key, NULL);

                /* Save key for software WEP */
                zfMemoryCopy(wd->sta.wepKey[keyInfo.keyIndex], keyInfo.key,
                        keyInfo.keyLength);

                /* TODO: Check whether we need to save the SWEncryMode */
                wd->sta.SWEncryMode[keyInfo.keyIndex] = encryMode;

                wd->sta.encryMode = encryMode;
                wd->ws.encryMode = encryMode;
            }
        }
    }

//    wd->sta.flagKeyChanging = 1;
    return ZM_STATUS_SUCCESS;
}

/* PSEUDO test */
u8_t zfiWlanPSEUDOSetKey(zdev_t* dev, struct zsKeyInfo keyInfo)
{
    //u16_t  broadcast[3] = {0xffff, 0xffff, 0xffff};
    //u32_t* key;
    u8_t   micKey[16];

    zmw_get_wlan_dev(dev);

    switch (keyInfo.keyLength)
    {
        case 5:
            wd->sta.encryMode = ZM_WEP64;
            /* use default key */
            zfCoreSetKey(dev, 64, 0, ZM_WEP64, (u16_t *)keyInfo.macAddr, (u32_t*) keyInfo.key);
		          break;

       	case 13:
            wd->sta.encryMode = ZM_WEP128;
            /* use default key */
            zfCoreSetKey(dev, 64, 0, ZM_WEP128, (u16_t *)keyInfo.macAddr, (u32_t*) keyInfo.key);
          		break;

       	case 29:
            wd->sta.encryMode = ZM_WEP256;
            /* use default key */
            zfCoreSetKey(dev, 64, 1, ZM_WEP256,  (u16_t *)keyInfo.macAddr, (u32_t*) (&keyInfo.key[16]));
            zfCoreSetKey(dev, 64, 0, ZM_WEP256, (u16_t *)keyInfo.macAddr, (u32_t*) keyInfo.key);
		          break;

       	case 16:
            wd->sta.encryMode = ZM_AES;
            //zfCoreSetKey(dev, 0, 0, ZM_AES, (u16_t *)keyInfo.macAddr, (u32_t*) keyInfo.key);
            zfCoreSetKey(dev, 64, 0, ZM_AES, (u16_t *)keyInfo.macAddr, (u32_t*) keyInfo.key);
            break;

       	case 32:
#ifdef ZM_ENABLE_CENC
            if (keyInfo.flag & ZM_KEY_FLAG_CENC)
            {
                u16_t boardcastAddr[3] = {0xffff, 0xffff, 0xffff};
                u16_t Addr_a[] = { 0x0000, 0x0080, 0x0901};
                u16_t Addr_b[] = { 0x0000, 0x0080, 0x0902};
                /* CENC test: user0,1 and user2 for boardcast */
                wd->sta.encryMode = ZM_CENC;
                zfCoreSetKey(dev, 0, 1, ZM_CENC, (u16_t *)Addr_a, (u32_t*) (&keyInfo.key[16]));
                zfCoreSetKey(dev, 0, 0, ZM_CENC, (u16_t *)Addr_a, (u32_t*) keyInfo.key);

                zfCoreSetKey(dev, 1, 1, ZM_CENC, (u16_t *)Addr_b, (u32_t*) (&keyInfo.key[16]));
                zfCoreSetKey(dev, 1, 0, ZM_CENC, (u16_t *)Addr_b, (u32_t*) keyInfo.key);

                zfCoreSetKey(dev, 2, 1, ZM_CENC, (u16_t *)boardcastAddr, (u32_t*) (&keyInfo.key[16]));
                zfCoreSetKey(dev, 2, 0, ZM_CENC, (u16_t *)boardcastAddr, (u32_t*) keyInfo.key);

                /* Initialize PN sequence */
                wd->sta.txiv[0] = 0x5c365c36;
                wd->sta.txiv[1] = 0x5c365c36;
                wd->sta.txiv[2] = 0x5c365c36;
                wd->sta.txiv[3] = 0x5c365c36;
            }
            else
#endif //ZM_ENABLE_CENC
            {
                wd->sta.encryMode = ZM_TKIP;
                zfCoreSetKey(dev, 64, 1, ZM_TKIP, (u16_t *)keyInfo.macAddr, (u32_t*) micKey);
                zfCoreSetKey(dev, 64, 0, ZM_TKIP, (u16_t *)keyInfo.macAddr, (u32_t*) keyInfo.key);
            }
            break;
        default:
            wd->sta.encryMode = ZM_NO_WEP;
    }

    return ZM_STATUS_SUCCESS;
}

void zfiWlanSetPowerSaveMode(zdev_t* dev, u8_t mode)
{
#if 0
    zmw_get_wlan_dev(dev);

    wd->sta.powerSaveMode = mode;

    /* send null data with PwrBit to inform AP */
    if ( mode > ZM_STA_PS_NONE )
    {
        if ( wd->wlanMode == ZM_MODE_INFRASTRUCTURE )
        {
            zfSendNullData(dev, 1);
        }

        /* device into PS mode */
        zfPSDeviceSleep(dev);
    }
#endif

    zfPowerSavingMgrSetMode(dev, mode);
}

void zfiWlanSetMacAddress(zdev_t* dev, u16_t* mac)
{
    zmw_get_wlan_dev(dev);

    wd->macAddr[0] = mac[0];
    wd->macAddr[1] = mac[1];
    wd->macAddr[2] = mac[2];

    zfHpSetMacAddress(dev, mac, 0);
}

u8_t zfiWlanQueryWlanMode(zdev_t* dev)
{
    zmw_get_wlan_dev(dev);

    return wd->wlanMode;
}

u8_t zfiWlanQueryAdapterState(zdev_t* dev)
{
    zmw_get_wlan_dev(dev);

    return wd->state;
}

u8_t zfiWlanQueryAuthenticationMode(zdev_t* dev, u8_t bWrapper)
{
    u8_t   authMode;

    zmw_get_wlan_dev(dev);

    if ( bWrapper )
    {
        authMode = wd->ws.authMode;
    }
    else
    {
        //authMode = wd->sta.authMode;
        authMode = wd->sta.currentAuthMode;
    }

    return authMode;
}

u8_t zfiWlanQueryWepStatus(zdev_t* dev, u8_t bWrapper)
{
    u8_t wepStatus;

    zmw_get_wlan_dev(dev);

    if ( bWrapper )
    {
        wepStatus = wd->ws.wepStatus;
    }
    else
    {
        wepStatus = wd->sta.wepStatus;
    }

    return wepStatus;
}

void zfiWlanQuerySSID(zdev_t* dev, u8_t* ssid, u8_t* pSsidLength)
{
    u16_t vapId = 0;
    zmw_get_wlan_dev(dev);

    if (wd->wlanMode == ZM_MODE_AP)
    {
        vapId = zfwGetVapId(dev);

        if (vapId == 0xffff)
        {
            *pSsidLength = wd->ap.ssidLen[0];
            zfMemoryCopy(ssid, wd->ap.ssid[0], wd->ap.ssidLen[0]);
        }
        else
        {
            *pSsidLength = wd->ap.ssidLen[vapId + 1];
            zfMemoryCopy(ssid, wd->ap.ssid[vapId + 1], wd->ap.ssidLen[vapId + 1]);
        }
    }
    else
    {
        *pSsidLength = wd->sta.ssidLen;
        zfMemoryCopy(ssid, wd->sta.ssid, wd->sta.ssidLen);
    }
}

u16_t zfiWlanQueryFragThreshold(zdev_t* dev)
{
    zmw_get_wlan_dev(dev);

    return wd->fragThreshold;
}

u16_t zfiWlanQueryRtsThreshold(zdev_t* dev)
{
    zmw_get_wlan_dev(dev);

    return wd->rtsThreshold;
}

u32_t zfiWlanQueryFrequency(zdev_t* dev)
{
    zmw_get_wlan_dev(dev);

    return (wd->frequency*1000);
}

/***********************************************************
 * Function: zfiWlanQueryCurrentFrequency
 * Return value:
 *   -   0 : no validate current frequency
 *   - (>0): current frequency depend on "qmode"
 * Input:
 *   - qmode:
 *      0: return value depend on the support mode, this
           qmode is use to solve the bug #31223
 *      1: return the actually current frequency
 ***********************************************************/
u32_t zfiWlanQueryCurrentFrequency(zdev_t* dev, u8_t qmode)
{
    u32_t frequency;

    zmw_get_wlan_dev(dev);

    switch (qmode)
    {
    case 0:
        if (wd->sta.currentFrequency > 3000)
        {
            if (wd->supportMode & ZM_WIRELESS_MODE_5)
            {
                frequency = wd->sta.currentFrequency;
            }
            else if (wd->supportMode & ZM_WIRELESS_MODE_24)
            {
                frequency = zfChGetFirst2GhzChannel(dev);
            }
            else
            {
                frequency = 0;
            }
        }
        else
        {
            if (wd->supportMode & ZM_WIRELESS_MODE_24)
            {
                frequency = wd->sta.currentFrequency;
            }
            else if (wd->supportMode & ZM_WIRELESS_MODE_5)
            {
                frequency = zfChGetLast5GhzChannel(dev);
            }
            else
            {
                frequency = 0;
            }
        }
        break;

    case 1:
        frequency = wd->sta.currentFrequency;
        break;

    default:
        frequency = 0;
    }

    return (frequency*1000);
}

u32_t zfiWlanQueryFrequencyAttribute(zdev_t* dev, u32_t freq)
{
    u8_t  i;
    u16_t frequency = (u16_t) (freq/1000);
    u32_t ret = 0;

    zmw_get_wlan_dev(dev);

    for (i = 0; i < wd->regulationTable.allowChannelCnt; i++)
    {
        if ( wd->regulationTable.allowChannel[i].channel == frequency )
        {
            ret = wd->regulationTable.allowChannel[i].channelFlags;
        }
    }

    return ret;
}

/* BandWidth  0=>20  1=>40 */
/* ExtOffset  0=>20  1=>high control 40   3=>low control 40 */
void zfiWlanQueryFrequencyHT(zdev_t* dev, u32_t *bandWidth, u32_t *extOffset)
{
    zmw_get_wlan_dev(dev);

    *bandWidth = wd->BandWidth40;
    *extOffset = wd->ExtOffset;
}

u8_t zfiWlanQueryCWMode(zdev_t* dev)
{
    zmw_get_wlan_dev(dev);

    return wd->cwm.cw_mode;
}

u32_t zfiWlanQueryCWEnable(zdev_t* dev)
{
    zmw_get_wlan_dev(dev);

    return wd->cwm.cw_enable;
}

void zfiWlanQueryBssid(zdev_t* dev, u8_t* bssid)
{
    u8_t   addr[6];

    zmw_get_wlan_dev(dev);

    ZM_MAC_WORD_TO_BYTE(wd->sta.bssid, addr);
    zfMemoryCopy(bssid, addr, 6);
}

u16_t zfiWlanQueryBeaconInterval(zdev_t* dev)
{
    zmw_get_wlan_dev(dev);

    return wd->beaconInterval;
}

u32_t zfiWlanQueryRxBeaconTotal(zdev_t* dev)
{
    zmw_get_wlan_dev(dev);
    wd->sta.rxBeaconTotal += wd->sta.rxBeaconCount;

    return wd->sta.rxBeaconTotal;
}

u16_t zfiWlanQueryAtimWindow(zdev_t* dev)
{
    u16_t atimWindow;

    zmw_get_wlan_dev(dev);

    atimWindow = wd->sta.atimWindow;

    return atimWindow;
}

u8_t zfiWlanQueryEncryMode(zdev_t* dev)
{
    zmw_get_wlan_dev(dev);

    if (wd->wlanMode == ZM_MODE_AP)
        return wd->ap.encryMode[0];
    else
        return wd->sta.encryMode;
}

u16_t zfiWlanQueryCapability(zdev_t* dev)
{
    u16_t capability;

    zmw_get_wlan_dev(dev);

    capability = wd->sta.capability[0] +
                 (((u16_t) wd->sta.capability[1]) << 8);

    return capability;

}

u16_t zfiWlanQueryAid(zdev_t* dev)
{
    zmw_get_wlan_dev(dev);

    return wd->sta.aid;
}

void zfiWlanQuerySupportRate(zdev_t* dev, u8_t* rateArray, u8_t* pLength)
{
    u8_t   i, j=0;

    zmw_get_wlan_dev(dev);

    for( i=0; i<4; i++ )
    {
        if ( wd->bRate & (0x1 << i) )
        {
            rateArray[j] = zg11bRateTbl[i] +
                           ((wd->bRateBasic & (0x1<<i))<<(7-i));
            j++;
        }
    }

    *pLength = j;
}

void zfiWlanQueryExtSupportRate(zdev_t* dev, u8_t* rateArray, u8_t* pLength)
{
    u8_t   i, j=0;

    zmw_get_wlan_dev(dev);

    for( i=0; i<8; i++ )
    {
        if ( wd->gRate & (0x1 << i) )
        {
            rateArray[j] = zg11gRateTbl[i] +
                           ((wd->gRateBasic & (0x1<<i))<<(7-i));
            j++;
        }
    }

    *pLength = j;
}

void zfiWlanQueryRsnIe(zdev_t* dev, u8_t* ie, u8_t* pLength)
{
    u8_t len;

    zmw_get_wlan_dev(dev);

    len = wd->sta.rsnIe[1] + 2;
    zfMemoryCopy(ie, wd->sta.rsnIe, len);
    *pLength = len;
}

void zfiWlanQueryWpaIe(zdev_t* dev, u8_t* ie, u8_t* pLength)
{
    u8_t len;

    zmw_get_wlan_dev(dev);

    len = wd->sta.wpaIe[1] + 2;
    zfMemoryCopy(ie, wd->sta.wpaIe, len);
    *pLength = len;

}

u8_t zfiWlanQueryMulticastCipherAlgo(zdev_t *dev)
{
    zmw_get_wlan_dev(dev);

    switch( wd->sta.currentAuthMode )
    {
        case ZM_AUTH_MODE_WPA2PSK:
        case ZM_AUTH_MODE_WPA2:
            if ( wd->sta.rsnIe[7] == 2 )
            {
                return ZM_TKIP;
            }
            else
            {
                return ZM_AES;
            }
            break;

        case ZM_AUTH_MODE_WPAPSK:
        case ZM_AUTH_MODE_WPA:
            if ( wd->sta.rsnIe[11] == 2 )
            {
                return ZM_TKIP;
            }
            else
            {
                return ZM_AES;
            }
            break;

        default:
            return wd->sta.encryMode;
    }
}

u8_t zfiWlanQueryHTMode(zdev_t* dev)
{
    zmw_get_wlan_dev(dev);
    // 0:Legancy, 1:N
    return wd->sta.EnableHT;
}

u8_t zfiWlanQueryBandWidth40(zdev_t* dev)
{
    zmw_get_wlan_dev(dev);
    // 0:20M, 1:40M
    return wd->BandWidth40;
}

u16_t zfiWlanQueryRegionCode(zdev_t* dev)
{
    zmw_get_wlan_dev(dev);

    return wd->regulationTable.regionCode;
}
void zfiWlanSetWpaIe(zdev_t* dev, u8_t* ie, u8_t Length)
{
    u16_t vapId = 0;
    zmw_get_wlan_dev(dev);

    if (wd->wlanMode == ZM_MODE_AP) // AP Mode
    {
        vapId = zfwGetVapId(dev);

        if (vapId == 0xffff)
            vapId = 0;
        else
            vapId++;

        zm_assert(Length < ZM_MAX_WPAIE_SIZE);
        if (Length < ZM_MAX_WPAIE_SIZE)
        {
            wd->ap.wpaLen[vapId] = Length;
            zfMemoryCopy(wd->ap.wpaIe[vapId], ie, wd->ap.wpaLen[vapId]);
        }

    }
    else
    {
        wd->sta.wpaLen = Length;
        zfMemoryCopy(wd->sta.wpaIe, ie, wd->sta.wpaLen);
    }
    //zfiWlanSetWpaSupport(dev, 1);
    if (wd->wlanMode == ZM_MODE_AP) // AP Mode
    {
        wd->ap.wpaSupport[vapId] = 1;
    }
    else
    {
        wd->sta.wpaSupport = 1;
    }

}

void zfiWlanSetWpaSupport(zdev_t* dev, u8_t WpaSupport)
{
    u16_t vapId = 0;
    zmw_get_wlan_dev(dev);

    if (wd->wlanMode == ZM_MODE_AP) // AP Mode
    {
        vapId = zfwGetVapId(dev);

        if (vapId == 0xffff)
            vapId = 0;
        else
            vapId++;

        wd->ap.wpaSupport[vapId] = WpaSupport;
    }
    else
    {
        wd->sta.wpaSupport = WpaSupport;
    }

}

void zfiWlanSetProtectionMode(zdev_t* dev, u8_t mode)
{
    zmw_get_wlan_dev(dev);

    wd->sta.bProtectionMode = mode;
    if (wd->sta.bProtectionMode == TRUE)
    {
        zfHpSetSlotTime(dev, 0);
    }
    else
    {
        zfHpSetSlotTime(dev, 1);
    }

    zm_msg1_mm(ZM_LV_1, "wd->protectionMode=", wd->sta.bProtectionMode);
}

void zfiWlanSetBasicRate(zdev_t* dev, u8_t bRateSet, u8_t gRateSet,
                         u32_t nRateSet)
{
    zmw_get_wlan_dev(dev);

    wd->ws.bRateBasic = bRateSet;
    wd->ws.gRateBasic = gRateSet;
    wd->ws.nRateBasic = nRateSet;
}

void zfiWlanSetBGMode(zdev_t* dev, u8_t mode)
{
    zmw_get_wlan_dev(dev);

    wd->ws.bgMode = mode;
}

void zfiWlanSetpreambleType(zdev_t* dev, u8_t type)
{
    zmw_get_wlan_dev(dev);

    wd->ws.preambleType = type;
}

u8_t zfiWlanQuerypreambleType(zdev_t* dev)
{
    zmw_get_wlan_dev(dev);

    return wd->ws.preambleType;
}

u8_t zfiWlanQueryPowerSaveMode(zdev_t* dev)
{
    zmw_get_wlan_dev(dev);

    return wd->sta.powerSaveMode;
}

u8_t zfiWlanSetPmkidInfo(zdev_t* dev, u16_t* bssid, u8_t* pmkid)
{
    u32_t  i;

    zmw_get_wlan_dev(dev);

    for(i=0; i<wd->sta.pmkidInfo.bssidCount; i++)
    {
        if ( zfMemoryIsEqual((u8_t*) wd->sta.pmkidInfo.bssidInfo[i].bssid,
                             (u8_t*) bssid, 6) )
        {
            /* matched */
            break;
        }
    }

    if ( i < wd->sta.pmkidInfo.bssidCount )
    {
        /* overwrite the original one */
        zfMemoryCopy(wd->sta.pmkidInfo.bssidInfo[i].pmkid, pmkid, 16);
    }
    else
    {
        if ( i < ZM_PMKID_MAX_BSS_CNT )
        {
            wd->sta.pmkidInfo.bssidInfo[i].bssid[0] = bssid[0];
            wd->sta.pmkidInfo.bssidInfo[i].bssid[1] = bssid[1];
            wd->sta.pmkidInfo.bssidInfo[i].bssid[2] = bssid[2];

            zfMemoryCopy(wd->sta.pmkidInfo.bssidInfo[i].pmkid, pmkid, 16);
            wd->sta.pmkidInfo.bssidCount++;
        }
    }

    return 0;
}

u32_t zfiWlanQueryPmkidInfo(zdev_t* dev, u8_t* buf, u32_t len)
{
    //struct zsPmkidInfo* pPmkidInfo = ( struct zsPmkidInfo* ) buf;
    u32_t  size;

    zmw_get_wlan_dev(dev);

    size = sizeof(u32_t) +
           wd->sta.pmkidInfo.bssidCount * sizeof(struct zsPmkidBssidInfo);

    if ( len < size )
    {
        return wd->sta.pmkidInfo.bssidCount;
    }

    zfMemoryCopy(buf, (u8_t*) &wd->sta.pmkidInfo, (u16_t) size);

    return 0;
}

void zfiWlanSetMulticastList(zdev_t* dev, u8_t size, u8_t* pList)
{
    struct zsMulticastAddr* pMacList = (struct zsMulticastAddr*) pList;
    u8_t   i;
    u8_t   bAllMulticast = 0;
    //u32_t  value;

    zmw_get_wlan_dev(dev);

    wd->sta.multicastList.size = size;
    for(i=0; i<size; i++)
    {
        zfMemoryCopy(wd->sta.multicastList.macAddr[i].addr,
                     pMacList[i].addr, 6);
    }

    if ( wd->sta.osRxFilter & ZM_PACKET_TYPE_ALL_MULTICAST )
        bAllMulticast = 1;
    zfHpSetMulticastList(dev, size, pList, bAllMulticast);

}

void zfiWlanRemoveKey(zdev_t* dev, u8_t keyType, u8_t keyId)
{
    u16_t  fakeMacAddr[3] = {0, 0, 0};
    u32_t  fakeKey[4] = {0, 0, 0, 0};

    zmw_get_wlan_dev(dev);

    if ( keyType == 0 )
    {
        /* remove WEP key */
        zm_debug_msg0("remove WEP key");
        zfCoreSetKey(dev, ZM_USER_KEY_DEFAULT+keyId, 0,
                 ZM_NO_WEP, fakeMacAddr, fakeKey);
        wd->sta.encryMode = ZM_NO_WEP;
    }
    else if ( keyType == 1 )
    {
        /* remove pairwise key */
        zm_debug_msg0("remove pairwise key");
        zfHpRemoveKey(dev, ZM_USER_KEY_PK);
        wd->sta.encryMode = ZM_NO_WEP;
    }
    else
    {
        /* remove group key */
        zm_debug_msg0("remove group key");
        zfHpRemoveKey(dev, ZM_USER_KEY_GK);
    }
}


void zfiWlanQueryRegulationTable(zdev_t* dev, struct zsRegulationTable* pEntry)
{
    zmw_get_wlan_dev(dev);

    zfMemoryCopy((u8_t*) pEntry, (u8_t*) &wd->regulationTable,
                 sizeof(struct zsRegulationTable));
}

/* parameter "time" is specified in ms */
void zfiWlanSetScanTimerPerChannel(zdev_t* dev, u16_t time)
{
    zmw_get_wlan_dev(dev);

    zm_debug_msg1("scan time (ms) = ", time);

    wd->sta.activescanTickPerChannel = time / ZM_MS_PER_TICK;
}

void zfiWlanSetAutoReconnect(zdev_t* dev, u8_t enable)
{
    zmw_get_wlan_dev(dev);

    wd->sta.bAutoReconnect = enable;
    //wd->sta.bAutoReconnectEnabled = enable;
}

void zfiWlanSetStaWme(zdev_t* dev, u8_t enable, u8_t uapsdInfo)
{
    zmw_get_wlan_dev(dev);

    wd->ws.staWmeEnabled = enable & 0x3;
    if ((enable & 0x2) != 0)
    {
        wd->ws.staWmeQosInfo = uapsdInfo & 0x6f;
    }
    else
    {
        wd->ws.staWmeQosInfo = 0;
    }
}

void zfiWlanSetApWme(zdev_t* dev, u8_t enable)
{
    zmw_get_wlan_dev(dev);

    wd->ws.apWmeEnabled = enable;
}

u8_t zfiWlanQuerywmeEnable(zdev_t* dev)
{
    zmw_get_wlan_dev(dev);

    return wd->ws.staWmeEnabled;
}

void zfiWlanSetProbingHiddenSsid(zdev_t* dev, u8_t* ssid, u8_t ssidLen,
    u16_t entry)
{
    zmw_get_wlan_dev(dev);
    zmw_declare_for_critical_section();


    if ((ssidLen <= 32) && (entry < ZM_MAX_PROBE_HIDDEN_SSID_SIZE))
    {
        zmw_enter_critical_section(dev);
        wd->ws.probingSsidList[entry].ssidLen = ssidLen;
        zfMemoryCopy(wd->ws.probingSsidList[entry].ssid, ssid, ssidLen);
        zmw_leave_critical_section(dev);
    }

    return;
}

void zfiWlanSetDisableProbingWithSsid(zdev_t* dev, u8_t mode)
{
    zmw_get_wlan_dev(dev);

    wd->sta.disableProbingWithSsid = mode;

    return;
}

void zfiWlanSetDropUnencryptedPackets(zdev_t* dev, u8_t enable)
{
    zmw_get_wlan_dev(dev);

    wd->ws.dropUnencryptedPkts = enable;
}

void zfiWlanSetStaRxSecurityCheckCb(zdev_t* dev, zfpStaRxSecurityCheckCb pStaRxSecurityCheckCb)
{
    zmw_get_wlan_dev(dev);

    wd->sta.pStaRxSecurityCheckCb = pStaRxSecurityCheckCb;
}

void zfiWlanSetIBSSJoinOnly(zdev_t* dev, u8_t joinOnly)
{
    zmw_get_wlan_dev(dev);

    wd->ws.ibssJoinOnly = joinOnly;
}

/************************************************************************/
/*                                                                      */
/*    FUNCTION DESCRIPTION                  zfiConfigWdsPort            */
/*      Configure WDS port.                                             */
/*                                                                      */
/*    INPUTS                                                            */
/*      dev : device pointer                                            */
/*      wdsPortId : WDS port ID, start from 0                           */
/*      flag : 0=>disable WDS port, 1=>enable WDS port                  */
/*      wdsAddr : WDS neighbor MAC address                              */
/*      encType : encryption type for WDS port                          */
/*      wdsKey : encryption key for WDS port                            */
/*                                                                      */
/*    OUTPUTS                                                           */
/*      Error code                                                      */
/*                                                                      */
/*    AUTHOR                                                            */
/*      Stephen Chen        ZyDAS Technology Corporation    2006.6      */
/*                                                                      */
/************************************************************************/
u16_t zfiConfigWdsPort(zdev_t* dev, u8_t wdsPortId, u16_t flag, u16_t* wdsAddr,
        u16_t encType, u32_t* wdsKey)
{
    u16_t addr[3];
    u32_t key[4];

    zmw_get_wlan_dev(dev);

    if (wdsPortId >= ZM_MAX_WDS_SUPPORT)
    {
        return ZM_ERR_WDS_PORT_ID;
    }

    if (flag == 1)
    {
        /* Enable WDS port */
        wd->ap.wds.macAddr[wdsPortId][0] = wdsAddr[0];
        wd->ap.wds.macAddr[wdsPortId][1] = wdsAddr[1];
        wd->ap.wds.macAddr[wdsPortId][2] = wdsAddr[2];

        wd->ap.wds.wdsBitmap |= (1 << wdsPortId);
        wd->ap.wds.encryMode[wdsPortId] = (u8_t) encType;

        zfCoreSetKey(dev, 10+ZM_MAX_WDS_SUPPORT, 0, (u8_t) encType, wdsAddr, wdsKey);
    }
    else
    {
        /* Disable WDS port */
        addr[0] = addr[1] = addr[2] = 0;
        key[0] = key[1] = key[2] = key[3] = 0;
        wd->ap.wds.wdsBitmap &= (~(1 << wdsPortId));
        zfCoreSetKey(dev, 10+ZM_MAX_WDS_SUPPORT, 0, ZM_NO_WEP, addr, key);
    }

    return ZM_SUCCESS;
}
#ifdef ZM_ENABLE_CENC
/* CENC */
void zfiWlanQueryGSN(zdev_t* dev, u8_t *gsn, u16_t vapId)
{
    //struct zsWlanDev* wd = (struct zsWlanDev*) zmw_wlan_dev(dev);
    u32_t txiv[4];
    zmw_get_wlan_dev(dev);

    /* convert little endian to big endian for 32 bits */
    txiv[3] = wd->ap.txiv[vapId][0];
    txiv[2] = wd->ap.txiv[vapId][1];
    txiv[1] = wd->ap.txiv[vapId][2];
    txiv[0] = wd->ap.txiv[vapId][3];

    zfMemoryCopy(gsn, (u8_t*)txiv, 16);
}
#endif //ZM_ENABLE_CENC
//CWYang(+)
void zfiWlanQuerySignalInfo(zdev_t* dev, u8_t *buffer)
{
    zmw_get_wlan_dev(dev);

    /*Change Signal Strength/Quality Value to Human Sense Here*/

    buffer[0] = wd->SignalStrength;
    buffer[1] = wd->SignalQuality;
}

/* OS-XP */
u16_t zfiStaAddIeWpaRsn(zdev_t* dev, zbuf_t* buf, u16_t offset, u8_t frameType)
{
    return  zfStaAddIeWpaRsn(dev, buf, offset, frameType);
}

/* zfiDebugCmd                                                                        */
/*     cmd       value-description                                                  */
/*         0       schedule timer                                                     */
/*         1       cancel timer                                                         */
/*         2       clear timer                                                           */
/*         3       test timer                                                            */
/*         4                                                                                 */
/*         5                                                                                 */
/*         6       checksum test     0/1                                           */
/*         7       enableProtectionMode                                          */
/*         8       rx packet content dump    0/1                               */

u32_t zfiDebugCmd(zdev_t* dev, u32_t cmd, u32_t value)
{
    u16_t event;
    u32_t tick;
    zmw_get_wlan_dev(dev);

    zmw_declare_for_critical_section();


    zmw_enter_critical_section(dev);

    if ( cmd == 0 )
    {   /* schedule timer */
        event = (u16_t) ((value >> 16) & 0xffff);
        tick = value & 0xffff;
        zfTimerSchedule(dev, event, tick);
    }
    else if ( cmd == 1 )
    {   /* cancel timer */
        event = (u16_t) (value & 0xffff);
        zfTimerCancel(dev, event);
    }
    else if ( cmd == 2 )
    {   /* clear timer */
        zfTimerClear(dev);
    }
    else if ( cmd == 3 )
    {   /* test timer */
        zfTimerSchedule(dev, 1,  500);
        zfTimerSchedule(dev, 2, 1000);
        zfTimerSchedule(dev, 3, 1000);
        zfTimerSchedule(dev, 4, 1000);
        zfTimerSchedule(dev, 5, 1500);
        zfTimerSchedule(dev, 6, 2000);
        zfTimerSchedule(dev, 7, 2200);
        zfTimerSchedule(dev, 6, 2500);
        zfTimerSchedule(dev, 8, 2800);
    }
    else if ( cmd == 4)
    {
        zfTimerSchedule(dev, 1,  500);
        zfTimerSchedule(dev, 2, 1000);
        zfTimerSchedule(dev, 3, 1000);
        zfTimerSchedule(dev, 4, 1000);
        zfTimerSchedule(dev, 5, 1500);
        zfTimerSchedule(dev, 6, 2000);
        zfTimerSchedule(dev, 7, 2200);
        zfTimerSchedule(dev, 6, 2500);
        zfTimerSchedule(dev, 8, 2800);
        zfTimerCancel(dev, 1);
        zfTimerCancel(dev, 3);
        zfTimerCancel(dev, 6);
    }
    else if ( cmd == 5 )
    {
        wd->sta.keyId = (u8_t) value;
    }
	else if ( cmd == 6 )
	{
	    /* 0: normal    1: always set TCP/UDP checksum zero */
        wd->checksumTest = value;
	}
	else if ( cmd == 7 )
	{
        wd->enableProtectionMode = value;
   	    zm_msg1_mm(ZM_LV_1, "wd->enableProtectionMode=", wd->enableProtectionMode);
	}
	else if ( cmd == 8 )
	{
        /* rx packet content dump */
        if (value)
        {
            wd->rxPacketDump = 1;
        }
        else
        {
            wd->rxPacketDump = 0;
        }
	}


    zmw_leave_critical_section(dev);

    return 0;
}

#ifdef ZM_ENABLE_CENC
u8_t zfiWlanSetCencPairwiseKey(zdev_t* dev, u8_t keyid, u32_t *txiv, u32_t *rxiv,
        u8_t *key, u8_t *mic)
{
    struct zsKeyInfo keyInfo;
    u8_t cencKey[32];
    u8_t i;
    u16_t macAddr[3];

    zmw_get_wlan_dev(dev);

    for (i = 0; i < 16; i++)
        cencKey[i] = key[i];
    for (i = 0; i < 16; i++)
        cencKey[i + 16] = mic[i];
    keyInfo.key = cencKey;
    keyInfo.keyLength = 32;
    keyInfo.keyIndex = keyid;
    keyInfo.flag = ZM_KEY_FLAG_CENC | ZM_KEY_FLAG_PK;
    for (i = 0; i < 3; i++)
        macAddr[i] = wd->sta.bssid[i];
    keyInfo.macAddr = macAddr;

    zfiWlanSetKey(dev, keyInfo);

    /* Reset txiv and rxiv */
    //wd->sta.txiv[0] = txiv[0];
    //wd->sta.txiv[1] = txiv[1];
    //wd->sta.txiv[2] = txiv[2];
    //wd->sta.txiv[3] = txiv[3];
    //
    //wd->sta.rxiv[0] = rxiv[0];
    //wd->sta.rxiv[1] = rxiv[1];
    //wd->sta.rxiv[2] = rxiv[2];
    //wd->sta.rxiv[3] = rxiv[3];

    return 0;
}

u8_t zfiWlanSetCencGroupKey(zdev_t* dev, u8_t keyid, u32_t *rxiv,
        u8_t *key, u8_t *mic)
{
    struct zsKeyInfo keyInfo;
    u8_t cencKey[32];
    u8_t i;
    u16_t macAddr[6] = {0xffff, 0xffff, 0xffff};

    zmw_get_wlan_dev(dev);

    for (i = 0; i < 16; i++)
        cencKey[i] = key[i];
    for (i = 0; i < 16; i++)
        cencKey[i + 16] = mic[i];
    keyInfo.key = cencKey;
    keyInfo.keyLength = 32;
    keyInfo.keyIndex = keyid;
    keyInfo.flag = ZM_KEY_FLAG_CENC | ZM_KEY_FLAG_GK;
    keyInfo.vapId = 0;
    for (i = 0; i < 3; i++)
        keyInfo.vapAddr[i] = wd->macAddr[i];
    keyInfo.macAddr = macAddr;

    zfiWlanSetKey(dev, keyInfo);

    /* Reset txiv and rxiv */
    wd->sta.rxivGK[0] = ((rxiv[3] >> 24) & 0xFF)
                      + (((rxiv[3] >> 16) & 0xFF) << 8)
                      + (((rxiv[3] >> 8) & 0xFF) << 16)
                      + ((rxiv[3] & 0xFF) << 24);
    wd->sta.rxivGK[1] = ((rxiv[2] >> 24) & 0xFF)
                      + (((rxiv[2] >> 16) & 0xFF) << 8)
                      + (((rxiv[2] >> 8) & 0xFF) << 16)
                      + ((rxiv[2] & 0xFF) << 24);
    wd->sta.rxivGK[2] = ((rxiv[1] >> 24) & 0xFF)
                      + (((rxiv[1] >> 16) & 0xFF) << 8)
                      + (((rxiv[1] >> 8) & 0xFF) << 16)
                      + ((rxiv[1] & 0xFF) << 24);
    wd->sta.rxivGK[3] = ((rxiv[0] >> 24) & 0xFF)
                      + (((rxiv[0] >> 16) & 0xFF) << 8)
                      + (((rxiv[0] >> 8) & 0xFF) << 16)
                      + ((rxiv[0] & 0xFF) << 24);

    wd->sta.authMode = ZM_AUTH_MODE_CENC;
    wd->sta.currentAuthMode = ZM_AUTH_MODE_CENC;

    return 0;
}
#endif //ZM_ENABLE_CENC

u8_t zfiWlanSetDot11DMode(zdev_t* dev, u8_t mode)
{
    u8_t i;

    zmw_get_wlan_dev(dev);

    wd->sta.b802_11D = mode;
    if (mode) //Enable 802.11d
    {
        wd->regulationTable.regionCode = NO_ENUMRD;
        for (i = 0; i < wd->regulationTable.allowChannelCnt; i++)
            wd->regulationTable.allowChannel[i].channelFlags |= ZM_REG_FLAG_CHANNEL_PASSIVE;
    }
    else //Disable
    {
        for (i = 0; i < wd->regulationTable.allowChannelCnt; i++)
            wd->regulationTable.allowChannel[i].channelFlags &= ~ZM_REG_FLAG_CHANNEL_PASSIVE;
    }

    return 0;
}

u8_t zfiWlanSetDot11HDFSMode(zdev_t* dev, u8_t mode)
{
    zmw_get_wlan_dev(dev);

    //zm_debug_msg0("CWY - Enable 802.11h DFS");

    // TODO : DFS Enable in 5250 to 5350 MHz and 5470 to 5725 MHz .
    //if ( Adapter->ZD80211HSupport &&
    //   Adapter->CardSetting.NetworkTypeInUse == Ndis802_11OFDM5 &&
    //   ((ChannelNo >=52 && ChannelNo <= 64)	||				//5250~5350 MHZ
    //    (ChannelNo >=100 && ChannelNo <= 140))) 			//5470~5725 MHZ
    //{
    //   Adapter->ZD80211HSetting.DFSEnable=TRUE;
    //}
    //else
    //{
    //   Adapter->ZD80211HSetting.DFSEnable=FALSE;
    //}

    wd->sta.DFSEnable = mode;
    if (mode)
        wd->sta.capability[1] |= ZM_BIT_0;
    else
        wd->sta.capability[1] &= (~ZM_BIT_0);

    return 0;
}

u8_t zfiWlanSetDot11HTPCMode(zdev_t* dev, u8_t mode)
{
    zmw_get_wlan_dev(dev);

    // TODO : TPC Enable in 5150~5350 MHz and 5470~5725MHz.
    //if ( Adapter->ZD80211HSupport &&
    //   Adapter->CardSetting.NetworkTypeInUse == Ndis802_11OFDM5 &&
    //   ((ChannelNo == 36 || ChannelNo == 40 || ChannelNo == 44 || ChannelNo == 48) ||	//5150~5250 MHZ , Not Japan
    //    (ChannelNo >=52 && ChannelNo <= 64) ||				//5250~5350 MHZ
    //    (ChannelNo >=100 && ChannelNo <= 140))) 			//5470~5725 MHZ
    //{
    //   Adapter->ZD80211HSetting.TPCEnable=TRUE;
    //}
    //else
    //{
    //   Adapter->ZD80211HSetting.TPCEnable=FALSE;
    //}

    wd->sta.TPCEnable = mode;
    if (mode)
        wd->sta.capability[1] |= ZM_BIT_0;
    else
        wd->sta.capability[1] &= (~ZM_BIT_0);

    return 0;
}

u8_t zfiWlanSetAniMode(zdev_t* dev, u8_t mode)
{
    zmw_get_wlan_dev(dev);

    wd->aniEnable = mode;
    if (mode)
        zfHpAniAttach(dev);

    return 0;
}

#ifdef ZM_OS_LINUX_FUNC
void zfiWlanShowTally(zdev_t* dev)
{
    zmw_get_wlan_dev(dev);

    zm_msg1_mm(ZM_LV_0, "Hw_UnderrunCnt    = ", wd->commTally.Hw_UnderrunCnt);
    zm_msg1_mm(ZM_LV_0, "Hw_TotalRxFrm     = ", wd->commTally.Hw_TotalRxFrm);
    zm_msg1_mm(ZM_LV_0, "Hw_CRC32Cnt       = ", wd->commTally.Hw_CRC32Cnt);
    zm_msg1_mm(ZM_LV_0, "Hw_CRC16Cnt       = ", wd->commTally.Hw_CRC16Cnt);
    zm_msg1_mm(ZM_LV_1, "Hw_DecrypErr_UNI  = ", wd->commTally.Hw_DecrypErr_UNI);
    zm_msg1_mm(ZM_LV_0, "Hw_RxFIFOOverrun  = ", wd->commTally.Hw_RxFIFOOverrun);
    zm_msg1_mm(ZM_LV_1, "Hw_DecrypErr_Mul  = ", wd->commTally.Hw_DecrypErr_Mul);
    zm_msg1_mm(ZM_LV_1, "Hw_RetryCnt       = ", wd->commTally.Hw_RetryCnt);
    zm_msg1_mm(ZM_LV_0, "Hw_TotalTxFrm     = ", wd->commTally.Hw_TotalTxFrm);
    zm_msg1_mm(ZM_LV_0, "Hw_RxTimeOut      = ", wd->commTally.Hw_RxTimeOut);
    zm_msg1_mm(ZM_LV_0, "Tx_MPDU           = ", wd->commTally.Tx_MPDU);
    zm_msg1_mm(ZM_LV_0, "BA_Fail           = ", wd->commTally.BA_Fail);
    zm_msg1_mm(ZM_LV_0, "Hw_Tx_AMPDU       = ", wd->commTally.Hw_Tx_AMPDU);
    zm_msg1_mm(ZM_LV_0, "Hw_Tx_MPDU        = ", wd->commTally.Hw_Tx_MPDU);

    zm_msg1_mm(ZM_LV_1, "Hw_RxMPDU          = ", wd->commTally.Hw_RxMPDU);
    zm_msg1_mm(ZM_LV_1, "Hw_RxDropMPDU      = ", wd->commTally.Hw_RxDropMPDU);
    zm_msg1_mm(ZM_LV_1, "Hw_RxDelMPDU       = ", wd->commTally.Hw_RxDelMPDU);
    zm_msg1_mm(ZM_LV_1, "Hw_RxPhyMiscError  = ", wd->commTally.Hw_RxPhyMiscError);
    zm_msg1_mm(ZM_LV_1, "Hw_RxPhyXRError    = ", wd->commTally.Hw_RxPhyXRError);
    zm_msg1_mm(ZM_LV_1, "Hw_RxPhyOFDMError  = ", wd->commTally.Hw_RxPhyOFDMError);
    zm_msg1_mm(ZM_LV_1, "Hw_RxPhyCCKError   = ", wd->commTally.Hw_RxPhyCCKError);
    zm_msg1_mm(ZM_LV_1, "Hw_RxPhyHTError    = ", wd->commTally.Hw_RxPhyHTError);
    zm_msg1_mm(ZM_LV_1, "Hw_RxPhyTotalCount = ", wd->commTally.Hw_RxPhyTotalCount);

    if (!((wd->commTally.Tx_MPDU == 0) && (wd->commTally.BA_Fail == 0)))
    {
        zm_debug_msg_p("BA Fail Ratio(%)  = ", wd->commTally.BA_Fail * 100,
                (wd->commTally.BA_Fail + wd->commTally.Tx_MPDU));
    }

    if (!((wd->commTally.Hw_Tx_MPDU == 0) && (wd->commTally.Hw_Tx_AMPDU == 0)))
    {
        zm_debug_msg_p("Avg Agg Number    = ",
                wd->commTally.Hw_Tx_MPDU, wd->commTally.Hw_Tx_AMPDU);
    }
}
#endif

void zfiWlanSetMaxTxPower(zdev_t* dev, u8_t power2, u8_t power5)
{
    zmw_get_wlan_dev(dev);

    zmw_declare_for_critical_section();

    zmw_enter_critical_section(dev);
    wd->maxTxPower2 = power2;
    wd->maxTxPower5 = power5;
    zmw_leave_critical_section(dev);
}

void zfiWlanQueryMaxTxPower(zdev_t* dev, u8_t *power2, u8_t *power5)
{
    zmw_get_wlan_dev(dev);

    *power2 = wd->maxTxPower2;
    *power5 = wd->maxTxPower5;
}

void zfiWlanSetConnectMode(zdev_t* dev, u8_t mode)
{
    zmw_get_wlan_dev(dev);

    zmw_declare_for_critical_section();

    zmw_enter_critical_section(dev);
    wd->connectMode = mode;
    zmw_leave_critical_section(dev);
}

void zfiWlanSetSupportMode(zdev_t* dev, u32_t mode)
{
    zmw_get_wlan_dev(dev);

    zmw_declare_for_critical_section();

    zmw_enter_critical_section(dev);
    wd->supportMode = mode;
    zmw_leave_critical_section(dev);
}

void zfiWlanSetAdhocMode(zdev_t* dev, u32_t mode)
{
    zmw_get_wlan_dev(dev);

    wd->ws.adhocMode = mode;
}

u32_t zfiWlanQueryAdhocMode(zdev_t* dev, u8_t bWrapper)
{
    u32_t adhocMode;

    zmw_get_wlan_dev(dev);

    if ( bWrapper )
    {
        adhocMode = wd->ws.adhocMode;
    }
    else
    {
        adhocMode = wd->wfc.bIbssGMode;
    }

    return adhocMode;
}


u8_t zfiWlanSetCountryIsoName(zdev_t* dev, u8_t *countryIsoName, u8_t length)
{
    u8_t buf[5];
    zmw_get_wlan_dev(dev);

    if (length == 4)
    {
        buf[2] = wd->ws.countryIsoName[0] = countryIsoName[2];
        buf[3] = wd->ws.countryIsoName[1] = countryIsoName[1];
        buf[4] = wd->ws.countryIsoName[2] = countryIsoName[0];
    }
    else if (length == 3)
    {
        buf[2] = wd->ws.countryIsoName[0] = countryIsoName[1];
        buf[3] = wd->ws.countryIsoName[1] = countryIsoName[0];
        buf[4] = wd->ws.countryIsoName[2] = '\0';
    }
    else
    {
        return 1;
    }

    return zfHpGetRegulationTablefromISO(dev, buf, length);
}


const char* zfiWlanQueryCountryIsoName(zdev_t* dev)
{
    zmw_get_wlan_dev(dev);

    return wd->ws.countryIsoName;
}



void zfiWlanSetRegulatory(zdev_t* dev, u8_t CCS, u16_t Code, u8_t bfirstChannel)
{
    zmw_get_wlan_dev(dev);

    zmw_declare_for_critical_section();

    if (CCS)
    {
        /* Reset Regulation Table by Country Code */
        zfHpGetRegulationTablefromCountry(dev, Code);
    }
    else
    {
        /* Reset Regulation Table by Region Code */
        zfHpGetRegulationTablefromRegionCode(dev, Code);
    }

    if (bfirstChannel) {
        zmw_enter_critical_section(dev);
        wd->frequency = zfChGetFirstChannel(dev, NULL);
        zmw_leave_critical_section(dev);
        zfCoreSetFrequency(dev, wd->frequency);
    }
}


const char* zfiHpGetisoNamefromregionCode(zdev_t* dev, u16_t regionCode)
{
    return zfHpGetisoNamefromregionCode(dev, regionCode);
}

u16_t zfiWlanChannelToFrequency(zdev_t* dev, u8_t channel)
{
    return zfChNumToFreq(dev, channel, 0);
}

u8_t zfiWlanFrequencyToChannel(zdev_t* dev, u16_t freq)
{
    u8_t is5GBand = 0;

    return zfChFreqToNum(freq, &is5GBand);
}

void zfiWlanDisableDfsChannel(zdev_t* dev, u8_t disableFlag)
{
    zfHpDisableDfsChannel(dev, disableFlag);
    return;
}

void zfiWlanSetLEDCtrlParam(zdev_t* dev, u8_t type, u8_t flag)
{
    zmw_get_wlan_dev(dev);

    zmw_declare_for_critical_section();

    zmw_enter_critical_section(dev);
    wd->ledStruct.LEDCtrlType = type;
    wd->ledStruct.LEDCtrlFlagFromReg  = flag;
    zmw_leave_critical_section(dev);
}

void zfiWlanEnableLeapConfig(zdev_t* dev, u8_t leapEnabled)
{
    zmw_get_wlan_dev(dev);

    wd->sta.leapEnabled = leapEnabled;
}

u32_t zfiWlanQueryHwCapability(zdev_t* dev)
{
    return zfHpCapability(dev);
}

u32_t zfiWlanQueryReceivedPacket(zdev_t* dev)
{
    zmw_get_wlan_dev(dev);

    return wd->sta.ReceivedPktRatePerSecond;
}

void zfiWlanCheckSWEncryption(zdev_t* dev)
{
    zmw_get_wlan_dev(dev);

    if (wd->sta.SWEncryptEnable != 0)
    {
        zfHpSWDecrypt(dev, 1);
    }
}

u16_t zfiWlanQueryAllowChannels(zdev_t* dev, u16_t *channels)
{
    u16_t ii;
    zmw_get_wlan_dev(dev);

    for (ii = 0; ii < wd->regulationTable.allowChannelCnt; ii++)
    {
        channels[ii] = wd->regulationTable.allowChannel[ii].channel;
    }

    return wd->regulationTable.allowChannelCnt;
}

void zfiWlanSetDynamicSIFSParam(zdev_t* dev, u8_t val)
{
    zmw_get_wlan_dev(dev);

    wd->dynamicSIFSEnable = val;

    zm_debug_msg1("wd->dynamicSIFSEnable = ", wd->dynamicSIFSEnable)
}

u16_t zfiWlanGetMulticastAddressCount(zdev_t* dev)
{
    zmw_get_wlan_dev(dev);

    return wd->sta.multicastList.size;
}

void zfiWlanGetMulticastList(zdev_t* dev, u8_t* pMCList)
{
    struct zsMulticastAddr* pMacList = (struct zsMulticastAddr*) pMCList;
    u8_t i;

    zmw_get_wlan_dev(dev);

    for ( i=0; i<wd->sta.multicastList.size; i++ )
    {
        zfMemoryCopy(pMacList[i].addr, wd->sta.multicastList.macAddr[i].addr, 6);
    }
}

void zfiWlanSetPacketFilter(zdev_t* dev, u32_t PacketFilter)
{
    u8_t  bAllMulticast = 0;
    u32_t oldFilter;

    zmw_get_wlan_dev(dev);

    oldFilter = wd->sta.osRxFilter;

    wd->sta.osRxFilter = PacketFilter;

    if ((oldFilter & ZM_PACKET_TYPE_ALL_MULTICAST) !=
        (wd->sta.osRxFilter & ZM_PACKET_TYPE_ALL_MULTICAST))
    {
        if ( wd->sta.osRxFilter & ZM_PACKET_TYPE_ALL_MULTICAST )
            bAllMulticast = 1;
        zfHpSetMulticastList(dev, wd->sta.multicastList.size,
                             (u8_t*)wd->sta.multicastList.macAddr, bAllMulticast);
    }
}

u8_t zfiCompareWithMulticastListAddress(zdev_t* dev, u16_t* dstMacAddr)
{
    u8_t i;
    u8_t bIsInMCListAddr = 0;

    zmw_get_wlan_dev(dev);

    for ( i=0; i<wd->sta.multicastList.size; i++ )
    {
    	if ( zfwMemoryIsEqual((u8_t*)dstMacAddr, (u8_t*)wd->sta.multicastList.macAddr[i].addr, 6) )
    	{
            bIsInMCListAddr = 1;
            break;
    	}
    }

    return bIsInMCListAddr;
}

void zfiWlanSetSafeModeEnabled(zdev_t* dev, u8_t safeMode)
{
    zmw_get_wlan_dev(dev);

    wd->sta.bSafeMode = safeMode;

    if ( safeMode )
    	zfStaEnableSWEncryption(dev, 1);
    else
        zfStaDisableSWEncryption(dev);
}

void zfiWlanSetIBSSAdditionalIELength(zdev_t* dev, u32_t ibssAdditionalIESize, u8_t* ibssAdditionalIE)
{
	zmw_get_wlan_dev(dev);

	if ( ibssAdditionalIESize )
    {
	    wd->sta.ibssAdditionalIESize = ibssAdditionalIESize;
        zfMemoryCopy(wd->sta.ibssAdditionalIE, ibssAdditionalIE, (u16_t)ibssAdditionalIESize);
    }
    else
    	wd->sta.ibssAdditionalIESize = 0;
}