int
mtk_cfg80211_get_station (
    struct wiphy *wiphy,
    struct net_device *ndev,
    u8 *mac,
    struct station_info *sinfo
    )
{
    P_GLUE_INFO_T prGlueInfo = NULL;
    WLAN_STATUS rStatus;
    PARAM_MAC_ADDRESS arBssid;
    UINT_32 u4BufLen, u4Rate;
    INT_32 i4Rssi;

    prGlueInfo = (P_GLUE_INFO_T) wiphy_priv(wiphy);
    ASSERT(prGlueInfo);

    kalMemZero(arBssid, MAC_ADDR_LEN);
    wlanQueryInformation(prGlueInfo->prAdapter,
            wlanoidQueryBssid,
            &arBssid[0],
            sizeof(arBssid),
            &u4BufLen);

    /* 1. check BSSID */
    if(UNEQUAL_MAC_ADDR(arBssid, mac)) {
        /* wrong MAC address */
        DBGLOG(REQ, WARN, ("incorrect BSSID: ["MACSTR"] currently connected BSSID["MACSTR"]\n", 
                    MAC2STR(mac), MAC2STR(arBssid)));
        return -ENOENT;
    }

    /* 2. fill TX rate */
    rStatus = kalIoctl(prGlueInfo,
        wlanoidQueryLinkSpeed,
        &u4Rate,
        sizeof(u4Rate),
        TRUE,
        FALSE,
        FALSE,
        FALSE,
        &u4BufLen);

    if (rStatus != WLAN_STATUS_SUCCESS) {
        DBGLOG(REQ, WARN, ("unable to retrieve link speed\n"));
    }
    else {
        sinfo->filled |= STATION_INFO_TX_BITRATE;
        sinfo->txrate.legacy = u4Rate / 1000; /* convert from 100bps to 100kbps */
    }

    if(prGlueInfo->eParamMediaStateIndicated != PARAM_MEDIA_STATE_CONNECTED) {
        /* not connected */
        DBGLOG(REQ, WARN, ("not yet connected\n"));
    }
    else {
        /* 3. fill RSSI */
        rStatus = kalIoctl(prGlueInfo,
                wlanoidQueryRssi,
                &i4Rssi,
                sizeof(i4Rssi),
                TRUE,
                FALSE,
                FALSE,
                FALSE,
                &u4BufLen);
        
        if (rStatus != WLAN_STATUS_SUCCESS) {
            DBGLOG(REQ, WARN, ("unable to retrieve link speed\n"));
        }
        else {
            sinfo->filled |= STATION_INFO_SIGNAL;
            sinfo->signal = i4Rssi; /* dBm */
        }
    }

    return 0;
}
/*----------------------------------------------------------------------------*/
WLAN_STATUS
wlanoidSetAddP2PKey(IN P_ADAPTER_T prAdapter,
		    IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen)
{
	CMD_802_11_KEY rCmdKey;
	P_PARAM_KEY_T prNewKey;

	DEBUGFUNC("wlanoidSetAddP2PKey");
	DBGLOG(REQ, INFO, ("\n"));

	ASSERT(prAdapter);
	ASSERT(pvSetBuffer);
	ASSERT(pu4SetInfoLen);

	prNewKey = (P_PARAM_KEY_T) pvSetBuffer;

	/* Verify the key structure length. */
	if (prNewKey->u4Length > u4SetBufferLen) {
		DBGLOG(REQ, WARN,
		       ("Invalid key structure length (%d) greater than total buffer length (%d)\n",
			(UINT_8) prNewKey->u4Length, (UINT_8) u4SetBufferLen));

		*pu4SetInfoLen = u4SetBufferLen;
		return WLAN_STATUS_INVALID_LENGTH;
	}
	/* Verify the key material length for key material buffer */
	else if (prNewKey->u4KeyLength >
		 prNewKey->u4Length - OFFSET_OF(PARAM_KEY_T, aucKeyMaterial)) {
		DBGLOG(REQ, WARN,
		       ("Invalid key material length (%d)\n", (UINT_8) prNewKey->u4KeyLength));
		*pu4SetInfoLen = u4SetBufferLen;
		return WLAN_STATUS_INVALID_DATA;
	}
	/* Exception check */
	else if (prNewKey->u4KeyIndex & 0x0fffff00) {
		return WLAN_STATUS_INVALID_DATA;
	}
	/* Exception check, pairwise key must with transmit bit enabled */
	else if ((prNewKey->u4KeyIndex & BITS(30, 31)) == IS_UNICAST_KEY) {
		return WLAN_STATUS_INVALID_DATA;
	} else if (!(prNewKey->u4KeyLength == CCMP_KEY_LEN)
		   && !(prNewKey->u4KeyLength == TKIP_KEY_LEN)) {
		return WLAN_STATUS_INVALID_DATA;
	}
	/* Exception check, pairwise key must with transmit bit enabled */
	else if ((prNewKey->u4KeyIndex & BITS(30, 31)) == BITS(30, 31)) {
		if (((prNewKey->u4KeyIndex & 0xff) != 0) ||
		    ((prNewKey->arBSSID[0] == 0xff) && (prNewKey->arBSSID[1] == 0xff)
		     && (prNewKey->arBSSID[2] == 0xff) && (prNewKey->arBSSID[3] == 0xff)
		     && (prNewKey->arBSSID[4] == 0xff) && (prNewKey->arBSSID[5] == 0xff))) {
			return WLAN_STATUS_INVALID_DATA;
		}
	}

	*pu4SetInfoLen = u4SetBufferLen;

	/* fill CMD_802_11_KEY */
	kalMemZero(&rCmdKey, sizeof(CMD_802_11_KEY));
	rCmdKey.ucAddRemove = 1;	/* add */
	rCmdKey.ucTxKey = ((prNewKey->u4KeyIndex & IS_TRANSMIT_KEY) == IS_TRANSMIT_KEY) ? 1 : 0;
	rCmdKey.ucKeyType = ((prNewKey->u4KeyIndex & IS_UNICAST_KEY) == IS_UNICAST_KEY) ? 1 : 0;
	if (kalP2PGetRole(prAdapter->prGlueInfo) == 1) {	/* group client */
		rCmdKey.ucIsAuthenticator = 0;
	} else {		/* group owner */
		rCmdKey.ucIsAuthenticator = 1;
	}
	COPY_MAC_ADDR(rCmdKey.aucPeerAddr, prNewKey->arBSSID);
	rCmdKey.ucNetType = NETWORK_TYPE_P2P_INDEX;
	if (prNewKey->u4KeyLength == CCMP_KEY_LEN)
		rCmdKey.ucAlgorithmId = CIPHER_SUITE_CCMP;	/* AES */
	else if (prNewKey->u4KeyLength == TKIP_KEY_LEN)
		rCmdKey.ucAlgorithmId = CIPHER_SUITE_TKIP;	/* TKIP */
	rCmdKey.ucKeyId = (UINT_8) (prNewKey->u4KeyIndex & 0xff);
	rCmdKey.ucKeyLen = (UINT_8) prNewKey->u4KeyLength;
	kalMemCopy(rCmdKey.aucKeyMaterial, (PUINT_8) prNewKey->aucKeyMaterial, rCmdKey.ucKeyLen);

	return wlanoidSendSetQueryP2PCmd(prAdapter,
					 CMD_ID_ADD_REMOVE_KEY,
					 TRUE,
					 FALSE,
					 TRUE,
					 nicCmdEventSetCommon,
					 NULL,
					 sizeof(CMD_802_11_KEY),
					 (PUINT_8) &rCmdKey, pvSetBuffer, u4SetBufferLen);
}
/*----------------------------------------------------------------------------*/
int
mtk_cfg80211_add_key(struct wiphy *wiphy,
		     struct net_device *ndev,
		     u8 key_index, bool pairwise, const u8 *mac_addr, struct key_params *params)
{
	PARAM_KEY_T rKey;
	P_GLUE_INFO_T prGlueInfo = NULL;
	WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS;
	INT_32 i4Rslt = -EINVAL;
	UINT_32 u4BufLen = 0;
	UINT_8 tmp1[8];
	UINT_8 tmp2[8];

	prGlueInfo = (P_GLUE_INFO_T) wiphy_priv(wiphy);
	ASSERT(prGlueInfo);

	kalMemZero(&rKey, sizeof(PARAM_KEY_T));

	rKey.u4KeyIndex = key_index;

	if (mac_addr) {
		COPY_MAC_ADDR(rKey.arBSSID, mac_addr);
		if ((rKey.arBSSID[0] == 0x00) && (rKey.arBSSID[1] == 0x00)
		    && (rKey.arBSSID[2] == 0x00) && (rKey.arBSSID[3] == 0x00)
		    && (rKey.arBSSID[4] == 0x00) && (rKey.arBSSID[5] == 0x00)) {
			rKey.arBSSID[0] = 0xff;
			rKey.arBSSID[1] = 0xff;
			rKey.arBSSID[2] = 0xff;
			rKey.arBSSID[3] = 0xff;
			rKey.arBSSID[4] = 0xff;
			rKey.arBSSID[5] = 0xff;
		}
		if (rKey.arBSSID[0] != 0xFF) {
			rKey.u4KeyIndex |= BIT(31);
			if ((rKey.arBSSID[0] != 0x00) || (rKey.arBSSID[1] != 0x00)
			    || (rKey.arBSSID[2] != 0x00) || (rKey.arBSSID[3] != 0x00)
			    || (rKey.arBSSID[4] != 0x00) || (rKey.arBSSID[5] != 0x00))
				rKey.u4KeyIndex |= BIT(30);
		}
	} else {
		rKey.arBSSID[0] = 0xff;
		rKey.arBSSID[1] = 0xff;
		rKey.arBSSID[2] = 0xff;
		rKey.arBSSID[3] = 0xff;
		rKey.arBSSID[4] = 0xff;
		rKey.arBSSID[5] = 0xff;
		/* rKey.u4KeyIndex |= BIT(31); //Enable BIT 31 will make tx use bc key id, should use pairwise key id 0 */
	}

	if (params->key) {
		/* rKey.aucKeyMaterial[0] = kalMemAlloc(params->key_len, VIR_MEM_TYPE); */
		kalMemCopy(rKey.aucKeyMaterial, params->key, params->key_len);
		if (params->key_len == 32) {
			kalMemCopy(tmp1, &params->key[16], 8);
			kalMemCopy(tmp2, &params->key[24], 8);
			kalMemCopy(&rKey.aucKeyMaterial[16], tmp2, 8);
			kalMemCopy(&rKey.aucKeyMaterial[24], tmp1, 8);
		}
	}

	rKey.u4KeyLength = params->key_len;
	rKey.u4Length = ((UINT_32) &(((P_P2P_PARAM_KEY_T) 0)->aucKeyMaterial)) + rKey.u4KeyLength;

	rStatus = kalIoctl(prGlueInfo,
			   wlanoidSetAddKey,
			   &rKey, rKey.u4Length, FALSE, FALSE, TRUE, FALSE, &u4BufLen);

	if (rStatus == WLAN_STATUS_SUCCESS)
		i4Rslt = 0;

	return i4Rslt;
}
/*----------------------------------------------------------------------------*/
VOID
rlmDomainSendCmd (
    P_ADAPTER_T     prAdapter,
    BOOLEAN         fgIsOid
    )
{
    P_DOMAIN_INFO_ENTRY     prDomainInfo;
    P_CMD_SET_DOMAIN_INFO_T prCmd;
    WLAN_STATUS             rStatus;
    P_DOMAIN_SUBBAND_INFO   prSubBand;
    UINT_8                  i;	


    prDomainInfo = rlmDomainGetDomainInfo(prAdapter);
    ASSERT(prDomainInfo);

    prCmd = cnmMemAlloc(prAdapter, RAM_TYPE_BUF, sizeof(CMD_SET_DOMAIN_INFO_T));
    ASSERT(prCmd);

    /* To do: exception handle */
    if (!prCmd) {
        DBGLOG(RLM, ERROR, ("Domain: no buf to send cmd\n"));
        return;
    }
    kalMemZero(prCmd, sizeof(CMD_SET_DOMAIN_INFO_T));

    /* previous country code == FF : ignore country code,  current country code == FE : resume */    
    if(prAdapter->rWifiVar.rConnSettings.u2CountryCodeBakup == COUNTRY_CODE_FF){
        if (prAdapter->rWifiVar.rConnSettings.u2CountryCode != COUNTRY_CODE_FE){
            DBGLOG(RLM, INFO, ("Domain: skip country code cmd (0x%x)\n",prAdapter->rWifiVar.rConnSettings.u2CountryCode));            
            return;
        }else{
            DBGLOG(RLM, INFO, ("Domain: disable skip country code cmd (0x%x)\n",prAdapter->rWifiVar.rConnSettings.u2CountryCode));            
        }
    }
        
    prAdapter->rWifiVar.rConnSettings.u2CountryCodeBakup = prAdapter->rWifiVar.rConnSettings.u2CountryCode;
    DBGLOG(RLM, INFO, ("Domain: country code backup %x \n",prAdapter->rWifiVar.rConnSettings.u2CountryCodeBakup));

    prCmd->u2CountryCode = prAdapter->rWifiVar.rConnSettings.u2CountryCode;
    prCmd->u2IsSetPassiveScan = 0;
    prCmd->uc2G4Bandwidth = prAdapter->rWifiVar.rConnSettings.uc2G4BandwidthMode;
    prCmd->uc5GBandwidth = prAdapter->rWifiVar.rConnSettings.uc5GBandwidthMode;
	prCmd->aucReserved[0] = 0;
	prCmd->aucReserved[1] = 0;	

    for (i = 0; i < 6; i++) {
        prSubBand = &prDomainInfo->rSubBand[i];

        prCmd->rSubBand[i].ucRegClass = prSubBand->ucRegClass;
        prCmd->rSubBand[i].ucBand = prSubBand->ucBand;

        if (prSubBand->ucBand != BAND_NULL && prSubBand->ucBand < BAND_NUM) {
            prCmd->rSubBand[i].ucChannelSpan = prSubBand->ucChannelSpan;
            prCmd->rSubBand[i].ucFirstChannelNum = prSubBand->ucFirstChannelNum;
            prCmd->rSubBand[i].ucNumChannels = prSubBand->ucNumChannels;
        }
    }
	
	DBGLOG(RLM, INFO, ("rlmDomainSendCmd(), SetQueryCmd\n"));

    /* Update domain info to chip */
    rStatus = wlanSendSetQueryCmd (
                prAdapter,                  /* prAdapter */
                CMD_ID_SET_DOMAIN_INFO,     /* ucCID */
                TRUE,                       /* fgSetQuery */
                FALSE,                      /* fgNeedResp */
                fgIsOid,                    /* fgIsOid */
                NULL,                       /* pfCmdDoneHandler*/
                NULL,                       /* pfCmdTimeoutHandler */
                sizeof(CMD_SET_DOMAIN_INFO_T),    /* u4SetQueryInfoLen */
                (PUINT_8) prCmd,            /* pucInfoBuffer */
                NULL,                       /* pvSetQueryBuffer */
                0                           /* u4SetQueryBufferLen */
                );

    ASSERT(rStatus == WLAN_STATUS_PENDING);

    cnmMemFree(prAdapter, prCmd);

	rlmDomainPassiveScanSendCmd(prAdapter, fgIsOid);
}
void p2pHandleSystemResume(void)
{
    struct net_device *prDev = NULL;
    P_GLUE_INFO_T prGlueInfo = NULL;
    UINT_8  ip[4] = { 0 };
#ifdef  CONFIG_IPV6
    UINT_8  ip6[16] = { 0 };     // FIX ME: avoid to allocate large memory in stack
#endif

    printk(KERN_INFO "*********wlanP2PLateResume************\n");
    if(!wlanExportGlueInfo(&prGlueInfo)) {
        printk(KERN_INFO "*********p2pLateResume ignored************\n");
        return;
    }

    ASSERT(prGlueInfo);
    // <1> Sanity check and acquire the net_device
    prDev = prGlueInfo->prP2PInfo->prDevHandler;
    ASSERT(prDev);

   // <3> get the IPv4 address
    if(!prDev || !(prDev->ip_ptr)||\
        !((struct in_device *)(prDev->ip_ptr))->ifa_list||\
        !(&(((struct in_device *)(prDev->ip_ptr))->ifa_list->ifa_local))){
        printk(KERN_INFO "ip is not avaliable.\n");
        return;
    }

    // <4> copy the IPv4 address
    kalMemCopy(ip, &(((struct in_device *)(prDev->ip_ptr))->ifa_list->ifa_local), sizeof(ip));
    printk(KERN_INFO"ip is %d.%d.%d.%d\n",
            ip[0],ip[1],ip[2],ip[3]);

#ifdef  CONFIG_IPV6
    // <5> get the IPv6 address
    if(!prDev || !(prDev->ip6_ptr)||\
        !((struct in_device *)(prDev->ip6_ptr))->ifa_list||\
        !(&(((struct in_device *)(prDev->ip6_ptr))->ifa_list->ifa_local))){
        printk(KERN_INFO "ipv6 is not avaliable.\n");
        return;
    }
    // <6> copy the IPv6 address
    kalMemCopy(ip6, &(((struct in_device *)(prDev->ip6_ptr))->ifa_list->ifa_local), sizeof(ip6));
    printk(KERN_INFO"ipv6 is %d.%d.%d.%d.%d.%d.%d.%d.%d.%d.%d.%d.%d.%d.%d.%d\n",
            ip6[0],ip6[1],ip6[2],ip6[3],
            ip6[4],ip6[5],ip6[6],ip6[7],
            ip6[8],ip6[9],ip6[10],ip6[11],
            ip6[12],ip6[13],ip6[14],ip6[15]
            );
#endif
    // <7> clear the ARP filter
    {
        WLAN_STATUS rStatus = WLAN_STATUS_FAILURE;
        UINT_32 u4SetInfoLen = 0;
//        UINT_8 aucBuf[32] = {0};
        UINT_32 u4Len = sizeof(PARAM_NETWORK_ADDRESS_LIST);
        P_PARAM_NETWORK_ADDRESS_LIST prParamNetAddrList = (P_PARAM_NETWORK_ADDRESS_LIST)g_aucBufIpAddr;//aucBuf;

        kalMemZero(g_aucBufIpAddr, sizeof(g_aucBufIpAddr));

        prParamNetAddrList->u4AddressCount = 0;
        prParamNetAddrList->u2AddressType = PARAM_PROTOCOL_ID_TCP_IP;

        ASSERT(u4Len <= sizeof(g_aucBufIpAddr/*aucBuf*/));
        rStatus = kalIoctl(prGlueInfo,
                wlanoidSetP2pSetNetworkAddress,
                (PVOID)prParamNetAddrList,
                u4Len,
                FALSE,
                FALSE,
                TRUE,
                TRUE,
                &u4SetInfoLen);

        if (rStatus != WLAN_STATUS_SUCCESS) {
            printk(KERN_INFO DRV_NAME"set HW pattern filter fail 0x%x\n", rStatus);
        }
    }
}
/*----------------------------------------------------------------------------*/
int
mtk_cfg80211_connect (
    struct wiphy *wiphy,
    struct net_device *ndev,
    struct cfg80211_connect_params *sme
    )
{
    P_GLUE_INFO_T prGlueInfo = NULL;
    WLAN_STATUS rStatus;
    UINT_32 u4BufLen;
    ENUM_PARAM_ENCRYPTION_STATUS_T eEncStatus;
    ENUM_PARAM_AUTH_MODE_T eAuthMode;
    UINT_32 cipher;
    PARAM_SSID_T rNewSsid;
    BOOLEAN fgCarryWPSIE = FALSE;
    ENUM_PARAM_OP_MODE_T eOpMode;

    prGlueInfo = (P_GLUE_INFO_T) wiphy_priv(wiphy);
    ASSERT(prGlueInfo);

    if (prGlueInfo->prAdapter->rWifiVar.rConnSettings.eOPMode > NET_TYPE_AUTO_SWITCH)
		eOpMode = NET_TYPE_AUTO_SWITCH;
	else 
	    eOpMode = prGlueInfo->prAdapter->rWifiVar.rConnSettings.eOPMode;
	
	rStatus = kalIoctl(prGlueInfo,
		wlanoidSetInfrastructureMode,
		&eOpMode,
		sizeof(eOpMode),
		FALSE,
		FALSE,
		TRUE,
		FALSE,
		&u4BufLen);

	if (rStatus != WLAN_STATUS_SUCCESS) {
		DBGLOG(INIT, INFO, ("wlanoidSetInfrastructureMode fail 0x%lx\n", rStatus));
		return -EFAULT;
	}

	/* after set operation mode, key table are cleared */

	/* reset wpa info */
	prGlueInfo->rWpaInfo.u4WpaVersion = IW_AUTH_WPA_VERSION_DISABLED;
	prGlueInfo->rWpaInfo.u4KeyMgmt = 0;
	prGlueInfo->rWpaInfo.u4CipherGroup = IW_AUTH_CIPHER_NONE;
	prGlueInfo->rWpaInfo.u4CipherPairwise = IW_AUTH_CIPHER_NONE;
	prGlueInfo->rWpaInfo.u4AuthAlg = IW_AUTH_ALG_OPEN_SYSTEM;
#if CFG_SUPPORT_802_11W
	prGlueInfo->rWpaInfo.u4Mfp = IW_AUTH_MFP_DISABLED;
#endif

    if (sme->crypto.wpa_versions & NL80211_WPA_VERSION_1)
        prGlueInfo->rWpaInfo.u4WpaVersion = IW_AUTH_WPA_VERSION_WPA;
    else if (sme->crypto.wpa_versions & NL80211_WPA_VERSION_2)
        prGlueInfo->rWpaInfo.u4WpaVersion = IW_AUTH_WPA_VERSION_WPA2;
    else
        prGlueInfo->rWpaInfo.u4WpaVersion = IW_AUTH_WPA_VERSION_DISABLED;
 
    switch (sme->auth_type) {
    case NL80211_AUTHTYPE_OPEN_SYSTEM:
        prGlueInfo->rWpaInfo.u4AuthAlg = IW_AUTH_ALG_OPEN_SYSTEM;
        break;
    case NL80211_AUTHTYPE_SHARED_KEY:
        prGlueInfo->rWpaInfo.u4AuthAlg = IW_AUTH_ALG_SHARED_KEY;
        break;
    default:
        prGlueInfo->rWpaInfo.u4AuthAlg = IW_AUTH_ALG_OPEN_SYSTEM | IW_AUTH_ALG_SHARED_KEY;
        break;
    }

    if (sme->crypto.n_ciphers_pairwise) {
        prGlueInfo->prAdapter->rWifiVar.rConnSettings.rRsnInfo.au4PairwiseKeyCipherSuite[0] = sme->crypto.ciphers_pairwise[0];
        switch (sme->crypto.ciphers_pairwise[0]) {
        case WLAN_CIPHER_SUITE_WEP40:
            prGlueInfo->rWpaInfo.u4CipherPairwise = IW_AUTH_CIPHER_WEP40;
            break;
        case WLAN_CIPHER_SUITE_WEP104:
            prGlueInfo->rWpaInfo.u4CipherPairwise = IW_AUTH_CIPHER_WEP104;
            break;
        case WLAN_CIPHER_SUITE_TKIP:
            prGlueInfo->rWpaInfo.u4CipherPairwise = IW_AUTH_CIPHER_TKIP;
            break;
        case WLAN_CIPHER_SUITE_CCMP:
            prGlueInfo->rWpaInfo.u4CipherPairwise = IW_AUTH_CIPHER_CCMP;
            break;
        case WLAN_CIPHER_SUITE_AES_CMAC:
            prGlueInfo->rWpaInfo.u4CipherPairwise = IW_AUTH_CIPHER_CCMP;
            break;
        default:
            DBGLOG(REQ, WARN, ("invalid cipher pairwise (%d)\n",
                   sme->crypto.ciphers_pairwise[0]));
            return -EINVAL;
        }
    }

    if (sme->crypto.cipher_group) {
        prGlueInfo->prAdapter->rWifiVar.rConnSettings.rRsnInfo.u4GroupKeyCipherSuite = sme->crypto.cipher_group;
        switch (sme->crypto.cipher_group) {
        case WLAN_CIPHER_SUITE_WEP40:
            prGlueInfo->rWpaInfo.u4CipherGroup = IW_AUTH_CIPHER_WEP40;
            break;          
        case WLAN_CIPHER_SUITE_WEP104:
            prGlueInfo->rWpaInfo.u4CipherGroup = IW_AUTH_CIPHER_WEP104;
            break;
        case WLAN_CIPHER_SUITE_TKIP:
            prGlueInfo->rWpaInfo.u4CipherGroup = IW_AUTH_CIPHER_TKIP;
            break;
        case WLAN_CIPHER_SUITE_CCMP:
            prGlueInfo->rWpaInfo.u4CipherGroup = IW_AUTH_CIPHER_CCMP;
            break;
        case WLAN_CIPHER_SUITE_AES_CMAC:
            prGlueInfo->rWpaInfo.u4CipherGroup = IW_AUTH_CIPHER_CCMP;
            break;
        default:
            DBGLOG(REQ, WARN, ("invalid cipher group (%d)\n",
                   sme->crypto.cipher_group));
            return -EINVAL;
        }
    }

    if (sme->crypto.n_akm_suites) {
        prGlueInfo->prAdapter->rWifiVar.rConnSettings.rRsnInfo.au4AuthKeyMgtSuite[0] = sme->crypto.akm_suites[0];
        if (prGlueInfo->rWpaInfo.u4WpaVersion == IW_AUTH_WPA_VERSION_WPA) {
            switch (sme->crypto.akm_suites[0]) {
            case WLAN_AKM_SUITE_8021X:
                eAuthMode = AUTH_MODE_WPA;
                break;
            case WLAN_AKM_SUITE_PSK:
                eAuthMode = AUTH_MODE_WPA_PSK;
            break;
            default:
                DBGLOG(REQ, WARN, ("invalid cipher group (%d)\n",
                       sme->crypto.cipher_group));
                return -EINVAL;
            }
        } else if (prGlueInfo->rWpaInfo.u4WpaVersion == IW_AUTH_WPA_VERSION_WPA2) {
            switch (sme->crypto.akm_suites[0]) {
            case WLAN_AKM_SUITE_8021X:
            eAuthMode = AUTH_MODE_WPA2;
            break;
            case WLAN_AKM_SUITE_PSK:
            eAuthMode = AUTH_MODE_WPA2_PSK;
            break;
            default:
                DBGLOG(REQ, WARN, ("invalid cipher group (%d)\n",
                       sme->crypto.cipher_group));
                return -EINVAL;
            }
        }
    }

    if (prGlueInfo->rWpaInfo.u4WpaVersion == IW_AUTH_WPA_VERSION_DISABLED) {
        eAuthMode = (prGlueInfo->rWpaInfo.u4AuthAlg == IW_AUTH_ALG_OPEN_SYSTEM) ?
             AUTH_MODE_OPEN : AUTH_MODE_AUTO_SWITCH;
    }

    prGlueInfo->rWpaInfo.fgPrivacyInvoke = sme->privacy;

    //prGlueInfo->prAdapter->rWifiVar.rConnSettings.fgWapiMode = FALSE;
    //prGlueInfo->prAdapter->prGlueInfo->u2WapiAssocInfoIESz = 0;
    prGlueInfo->fgWpsActive = FALSE;
    //prGlueInfo->prAdapter->prGlueInfo->u2WSCAssocInfoIELen = 0;

    if (sme->ie && sme->ie_len > 0) {
        WLAN_STATUS rStatus;
        UINT_32 u4BufLen;
        PUINT_8 prDesiredIE = NULL;

#if CFG_SUPPORT_WAPI
        rStatus = kalIoctl(prGlueInfo,
                wlanoidSetWapiAssocInfo,
                sme->ie,
                sme->ie_len,
                FALSE,
                FALSE,
                FALSE,
                FALSE,
                &u4BufLen);
        
        if (rStatus != WLAN_STATUS_SUCCESS) {
            DBGLOG(SEC, WARN, ("[wapi] set wapi assoc info error:%lx\n", rStatus));
        }
#endif
#if CFG_SUPPORT_WPS2
        if (wextSrchDesiredWPSIE(sme->ie,
                    sme->ie_len,
                    0xDD,
                    (PUINT_8 *)&prDesiredIE)) {
            prGlueInfo->fgWpsActive = TRUE;
            fgCarryWPSIE = TRUE;

            rStatus = kalIoctl(prGlueInfo,
                    wlanoidSetWSCAssocInfo,
                    prDesiredIE,
                    IE_SIZE(prDesiredIE),
                    FALSE,
                    FALSE,
                    FALSE,
                    FALSE,
                    &u4BufLen);
            if (rStatus != WLAN_STATUS_SUCCESS) {
                DBGLOG(SEC, WARN, ("WSC] set WSC assoc info error:%lx\n", rStatus));
            }
        }
#endif
    }

    /* clear WSC Assoc IE buffer in case WPS IE is not detected */
    if(fgCarryWPSIE == FALSE) {
        kalMemZero(&prGlueInfo->aucWSCAssocInfoIE, 200);
        prGlueInfo->u2WSCAssocInfoIELen = 0;
    }

    rStatus = kalIoctl(prGlueInfo,
            wlanoidSetAuthMode,
            &eAuthMode,
            sizeof(eAuthMode),
            FALSE,
            FALSE,
            FALSE,
            FALSE,
            &u4BufLen);
    if (rStatus != WLAN_STATUS_SUCCESS) {
        DBGLOG(REQ, WARN, ("set auth mode error:%lx\n", rStatus));
    }

    cipher = prGlueInfo->rWpaInfo.u4CipherGroup | prGlueInfo->rWpaInfo.u4CipherPairwise;

    if (prGlueInfo->rWpaInfo.fgPrivacyInvoke) {
        if (cipher & IW_AUTH_CIPHER_CCMP) {
            eEncStatus = ENUM_ENCRYPTION3_ENABLED;
        }
        else if (cipher & IW_AUTH_CIPHER_TKIP) {
            eEncStatus = ENUM_ENCRYPTION2_ENABLED;
        }
        else if (cipher & (IW_AUTH_CIPHER_WEP104 | IW_AUTH_CIPHER_WEP40)) {
            eEncStatus = ENUM_ENCRYPTION1_ENABLED;
        }
        else if (cipher & IW_AUTH_CIPHER_NONE){
            if (prGlueInfo->rWpaInfo.fgPrivacyInvoke)
                eEncStatus = ENUM_ENCRYPTION1_ENABLED;
            else
                eEncStatus = ENUM_ENCRYPTION_DISABLED;
        }
        else {
            eEncStatus = ENUM_ENCRYPTION_DISABLED;
        }
    }
    else {
        eEncStatus = ENUM_ENCRYPTION_DISABLED;
    }
    
    rStatus = kalIoctl(prGlueInfo,
            wlanoidSetEncryptionStatus,
            &eEncStatus,
            sizeof(eEncStatus),
            FALSE,
            FALSE,
            FALSE,
            FALSE,
            &u4BufLen);
    if (rStatus != WLAN_STATUS_SUCCESS) {
        DBGLOG(REQ, WARN, ("set encryption mode error:%lx\n", rStatus));
    }

    if (sme->key_len != 0 && prGlueInfo->rWpaInfo.u4WpaVersion == IW_AUTH_WPA_VERSION_DISABLED) {
        P_PARAM_WEP_T prWepKey = (P_PARAM_WEP_T) wepBuf;
        
        kalMemSet(prWepKey, 0, sizeof(prWepKey));
        prWepKey->u4Length = 12 + sme->key_len;
        prWepKey->u4KeyLength = (UINT_32) sme->key_len;
        prWepKey->u4KeyIndex = (UINT_32) sme->key_idx;
        prWepKey->u4KeyIndex |= BIT(31);
        if (prWepKey->u4KeyLength > 32) {
            DBGLOG(REQ, WARN, ("Too long key length (%u)\n", prWepKey->u4KeyLength));
            return -EINVAL;
        }
        kalMemCopy(prWepKey->aucKeyMaterial, sme->key, prWepKey->u4KeyLength);

        rStatus = kalIoctl(prGlueInfo,
                     wlanoidSetAddWep,
                     prWepKey,
                     prWepKey->u4Length,
                     FALSE,
                     FALSE,
                     TRUE,
                     FALSE,
                     &u4BufLen);
        
        if (rStatus != WLAN_STATUS_SUCCESS) {
            DBGLOG(INIT, INFO, ("wlanoidSetAddWep fail 0x%lx\n", rStatus));
            return -EFAULT;
        }
    }

    if(sme->ssid_len > 0) {
        /* connect by SSID */
        COPY_SSID(rNewSsid.aucSsid, rNewSsid.u4SsidLen, sme->ssid, sme->ssid_len);

        rStatus = kalIoctl(prGlueInfo,
                wlanoidSetSsid,
                (PVOID) &rNewSsid,
                sizeof(PARAM_SSID_T),
                FALSE,
                FALSE,
                TRUE,
                FALSE,
                &u4BufLen);

        if (rStatus != WLAN_STATUS_SUCCESS) {
            DBGLOG(REQ, WARN, ("set SSID:%lx\n", rStatus));
            return -EINVAL;
        }
    }
    else {
        /* connect by BSSID */
        rStatus = kalIoctl(prGlueInfo,
                wlanoidSetBssid,
                (PVOID) sme->bssid,
                sizeof(MAC_ADDR_LEN),
                FALSE,
                FALSE,
                TRUE,
                FALSE,
                &u4BufLen);

        if (rStatus != WLAN_STATUS_SUCCESS) {
            DBGLOG(REQ, WARN, ("set BSSID:%lx\n", rStatus));
            return -EINVAL;
        }
    }

    return 0;
}
int mtk_cfg80211_vendor_set_hotlist(struct wiphy *wiphy, struct wireless_dev *wdev, const void *data, int data_len)
{
	/*WLAN_STATUS rStatus;*/
	P_GLUE_INFO_T prGlueInfo = NULL;
	CMD_SET_PSCAN_ADD_HOTLIST_BSSID rCmdPscnAddHotlist;

	INT_32 i4Status = -EINVAL;
	P_PARAM_WIFI_BSSID_HOTLIST prWifiHotlistCmd = NULL;
	UINT_8 flush = 0;
	/* struct nlattr *attr[GSCAN_ATTRIBUTE_SIGNIFICANT_CHANGE_FLUSH + 1]; */
	struct nlattr **attr = NULL;
	struct nlattr *paplist;
	int i, k;
	UINT_32 len_basic, len_aplist;

	ASSERT(wiphy);
	ASSERT(wdev);
	if ((data == NULL) || !data_len)
		goto nla_put_failure;
	DBGLOG(REQ, INFO, "%s for vendor command: data_len=%d \r\n", __func__, data_len);
	for (i = 0; i < 5; i++)
		DBGLOG(REQ, LOUD, "0x%x 0x%x 0x%x 0x%x \r\n",
			*((UINT_32 *) data + i * 4), *((UINT_32 *) data + i * 4 + 1),
			*((UINT_32 *) data + i * 4 + 2), *((UINT_32 *) data + i * 4 + 3));
	prWifiHotlistCmd = kalMemAlloc(sizeof(PARAM_WIFI_BSSID_HOTLIST), VIR_MEM_TYPE);
	if (prWifiHotlistCmd == NULL)
		goto nla_put_failure;
	kalMemZero(prWifiHotlistCmd, sizeof(PARAM_WIFI_BSSID_HOTLIST));
	attr = kalMemAlloc(sizeof(struct nlattr *) * (GSCAN_ATTRIBUTE_SIGNIFICANT_CHANGE_FLUSH + 1), VIR_MEM_TYPE);
	if (attr == NULL)
		goto nla_put_failure;
	kalMemZero(attr, sizeof(struct nlattr *) * (GSCAN_ATTRIBUTE_SIGNIFICANT_CHANGE_FLUSH + 1));

	if (nla_parse_nested(attr, GSCAN_ATTRIBUTE_NUM_AP, (struct nlattr *)(data - NLA_HDRLEN), nla_parse_policy) < 0)
		goto nla_put_failure;
	len_basic = 0;
	for (k = GSCAN_ATTRIBUTE_HOTLIST_FLUSH; k <= GSCAN_ATTRIBUTE_NUM_AP; k++) {
		if (attr[k]) {
			switch (k) {
			case GSCAN_ATTRIBUTE_LOST_AP_SAMPLE_SIZE:
				prWifiHotlistCmd->lost_ap_sample_size = nla_get_u32(attr[k]);
				len_basic += NLA_ALIGN(attr[k]->nla_len);
				break;
			case GSCAN_ATTRIBUTE_NUM_AP:
				prWifiHotlistCmd->num_ap = nla_get_u16(attr[k]);
				len_basic += NLA_ALIGN(attr[k]->nla_len);
				DBGLOG(REQ, TRACE, "attr=0x%x, num_ap=%d nla_len=%d, \r\n",
				       *(UINT_32 *) attr[k], prWifiHotlistCmd->num_ap, attr[k]->nla_len);
				break;
			case GSCAN_ATTRIBUTE_HOTLIST_FLUSH:
				flush = nla_get_u8(attr[k]);
				len_basic += NLA_ALIGN(attr[k]->nla_len);
				break;
			}
		}
	}
	paplist = (struct nlattr *)((UINT_8 *) data + len_basic);
	DBGLOG(REQ, TRACE, "+++basic attribute size=%d flush=%d\r\n", len_basic, flush);

	if (paplist->nla_type == GSCAN_ATTRIBUTE_HOTLIST_BSSIDS)
		paplist = (struct nlattr *)((UINT_8 *) paplist + NLA_HDRLEN);

	for (i = 0; i < prWifiHotlistCmd->num_ap; i++) {
		if (nla_parse_nested(attr, GSCAN_ATTRIBUTE_RSSI_HIGH, (struct nlattr *)paplist, nla_parse_policy) < 0)
			goto nla_put_failure;
		paplist = (struct nlattr *)((UINT_8 *) paplist + NLA_HDRLEN);
		/* request.attr_start(i) as nested attribute */
		len_aplist = 0;
		for (k = GSCAN_ATTRIBUTE_BSSID; k <= GSCAN_ATTRIBUTE_RSSI_HIGH; k++) {
			if (attr[k]) {
				switch (k) {
				case GSCAN_ATTRIBUTE_BSSID:
					kalMemCopy(prWifiHotlistCmd->ap[i].bssid, nla_data(attr[k]), sizeof(mac_addr));
					len_aplist += NLA_ALIGN(attr[k]->nla_len);
					break;
				case GSCAN_ATTRIBUTE_RSSI_LOW:
					prWifiHotlistCmd->ap[i].low = nla_get_u32(attr[k]);
					len_aplist += NLA_ALIGN(attr[k]->nla_len);
					break;
				case GSCAN_ATTRIBUTE_RSSI_HIGH:
					prWifiHotlistCmd->ap[i].high = nla_get_u32(attr[k]);
					len_aplist += NLA_ALIGN(attr[k]->nla_len);
					break;
				}
			}
		}
		if (((i + 1) % 4 == 0) || (i == prWifiHotlistCmd->num_ap - 1))
			DBGLOG(REQ, TRACE, "ap[%d], len_aplist=%d\n", i, len_aplist);
		else
			DBGLOG(REQ, TRACE, "ap[%d], len_aplist=%d \t", i, len_aplist);
		paplist = (struct nlattr *)((UINT_8 *) paplist + len_aplist);
	}

	DBGLOG(REQ, TRACE,
	"flush=%d, lost_ap_sample_size=%d, Hotlist:ap[0].channel=%d low=%d high=%d, ap[1].channel=%d low=%d high=%d",
		flush, prWifiHotlistCmd->lost_ap_sample_size,
		prWifiHotlistCmd->ap[0].channel, prWifiHotlistCmd->ap[0].low, prWifiHotlistCmd->ap[0].high,
		prWifiHotlistCmd->ap[1].channel, prWifiHotlistCmd->ap[1].low, prWifiHotlistCmd->ap[1].high);

	memcpy(&(rCmdPscnAddHotlist.aucMacAddr), &(prWifiHotlistCmd->ap[0].bssid), 6 * sizeof(UINT_8));
	rCmdPscnAddHotlist.ucFlags = (UINT_8) TRUE;
	prGlueInfo = (P_GLUE_INFO_T) wiphy_priv(wiphy);
	ASSERT(prGlueInfo);

	kalMemFree(prWifiHotlistCmd, VIR_MEM_TYPE, sizeof(PARAM_WIFI_BSSID_HOTLIST));
	kalMemFree(attr, VIR_MEM_TYPE, sizeof(struct nlattr *) * (GSCAN_ATTRIBUTE_SIGNIFICANT_CHANGE_FLUSH + 1));
	return 0;

nla_put_failure:
	if (prWifiHotlistCmd)
		kalMemFree(prWifiHotlistCmd, VIR_MEM_TYPE, sizeof(PARAM_WIFI_BSSID_HOTLIST));
	if (attr)
		kalMemFree(attr, VIR_MEM_TYPE,
			sizeof(struct nlattr *) * (GSCAN_ATTRIBUTE_SIGNIFICANT_CHANGE_FLUSH + 1));
	return i4Status;
}
/*----------------------------------------------------------------------------*/
VOID
kalP2PInvitationIndication (
    IN P_GLUE_INFO_T prGlueInfo,
    IN P_P2P_DEVICE_DESC_T prP2pDevDesc,
    IN PUINT_8 pucSsid,
    IN UINT_8 ucSsidLen,
    IN UINT_8 ucOperatingChnl,
    IN UINT_8 ucInvitationType,
    IN PUINT_8 pucGroupBssid
    )
{
#if 1
    union iwreq_data evt;
    UINT_8 aucBuffer[IW_CUSTOM_MAX];

    ASSERT(prGlueInfo);

    /* buffer peer information for later IOC_P2P_GET_STRUCT access */
    prGlueInfo->prP2PInfo->u4ConnReqNameLength = (UINT_32)((prP2pDevDesc->u2NameLength > 32)? 32 : prP2pDevDesc->u2NameLength);
    kalMemCopy(prGlueInfo->prP2PInfo->aucConnReqDevName,
                    prP2pDevDesc->aucName,
                    prGlueInfo->prP2PInfo->u4ConnReqNameLength);
    COPY_MAC_ADDR(prGlueInfo->prP2PInfo->rConnReqPeerAddr, prP2pDevDesc->aucDeviceAddr);
    COPY_MAC_ADDR(prGlueInfo->prP2PInfo->rConnReqGroupAddr, pucGroupBssid);
    prGlueInfo->prP2PInfo->i4ConnReqConfigMethod = (INT_32)(prP2pDevDesc->u2ConfigMethod);
    prGlueInfo->prP2PInfo->ucOperatingChnl = ucOperatingChnl;
    prGlueInfo->prP2PInfo->ucInvitationType = ucInvitationType;

    // prepare event structure
    memset(&evt, 0, sizeof(evt));

    snprintf(aucBuffer, IW_CUSTOM_MAX-1, "P2P_INV_INDICATE");
    evt.data.length = strlen(aucBuffer);

    /* indicate in IWEVCUSTOM event */
    wireless_send_event(prGlueInfo->prP2PInfo->prDevHandler,
            IWEVCUSTOM,
            &evt,
            aucBuffer);
    return;

#else
    P_MSG_P2P_CONNECTION_REQUEST_T prP2pConnReq = (P_MSG_P2P_CONNECTION_REQUEST_T)NULL;
    P_P2P_SPECIFIC_BSS_INFO_T prP2pSpecificBssInfo = (P_P2P_SPECIFIC_BSS_INFO_T)NULL;
    P_P2P_CONNECTION_SETTINGS_T prP2pConnSettings = (P_P2P_CONNECTION_SETTINGS_T)NULL;

    do {
        ASSERT_BREAK((prGlueInfo != NULL) && (prP2pDevDesc != NULL));


        // Not a real solution

        prP2pSpecificBssInfo = prGlueInfo->prAdapter->rWifiVar.prP2pSpecificBssInfo;
        prP2pConnSettings = prGlueInfo->prAdapter->rWifiVar.prP2PConnSettings;

        prP2pConnReq = (P_MSG_P2P_CONNECTION_REQUEST_T)cnmMemAlloc(prGlueInfo->prAdapter,
                                                                                RAM_TYPE_MSG,
                                                                                sizeof(MSG_P2P_CONNECTION_REQUEST_T));

        if (prP2pConnReq == NULL) {
            break;
        }


        kalMemZero(prP2pConnReq, sizeof(MSG_P2P_CONNECTION_REQUEST_T));

        prP2pConnReq->rMsgHdr.eMsgId = MID_MNY_P2P_CONNECTION_REQ;

        prP2pConnReq->eFormationPolicy = ENUM_P2P_FORMATION_POLICY_AUTO;

        COPY_MAC_ADDR(prP2pConnReq->aucDeviceID, prP2pDevDesc->aucDeviceAddr);

        prP2pConnReq->u2ConfigMethod = prP2pDevDesc->u2ConfigMethod;

        if (ucInvitationType == P2P_INVITATION_TYPE_INVITATION) {
            prP2pConnReq->fgIsPersistentGroup = FALSE;
            prP2pConnReq->fgIsTobeGO = FALSE;

        }

        else if (ucInvitationType == P2P_INVITATION_TYPE_REINVOKE) {
            DBGLOG(P2P, TRACE, ("Re-invoke Persistent Group\n"));
            prP2pConnReq->fgIsPersistentGroup = TRUE;
            prP2pConnReq->fgIsTobeGO = (prGlueInfo->prP2PInfo->ucRole == 2)?TRUE:FALSE;

        }


        p2pFsmRunEventDeviceDiscoveryAbort(prGlueInfo->prAdapter, NULL);

        if (ucOperatingChnl != 0) {
            prP2pSpecificBssInfo->ucPreferredChannel = ucOperatingChnl;
        }

        if ((ucSsidLen < 32) && (pucSsid != NULL)) {
            COPY_SSID(prP2pConnSettings->aucSSID,
                            prP2pConnSettings->ucSSIDLen,
                            pucSsid,
                            ucSsidLen);
        }

        mboxSendMsg(prGlueInfo->prAdapter,
                        MBOX_ID_0,
                        (P_MSG_HDR_T)prP2pConnReq,
                        MSG_SEND_METHOD_BUF);



    } while (FALSE);

    // frog add.
    // TODO: Invitation Indication

    return;
#endif

} /* kalP2PInvitationIndication */
int mtk_cfg80211_vendor_set_scan_config(struct wiphy *wiphy, struct wireless_dev *wdev, const void *data, int data_len)
{
	WLAN_STATUS rStatus;
	UINT_32 u4BufLen;
	P_GLUE_INFO_T prGlueInfo = NULL;

	INT_32 i4Status = -EINVAL;
	/*PARAM_WIFI_GSCAN_CMD_PARAMS rWifiScanCmd;*/
	P_PARAM_WIFI_GSCAN_CMD_PARAMS prWifiScanCmd;
	struct nlattr *attr[GSCAN_ATTRIBUTE_NUM_SCANS_TO_CACHE + 1];
	/* UINT_32 num_scans = 0; */	/* another attribute */
	int k;

	ASSERT(wiphy);
	ASSERT(wdev);
	if ((data == NULL) || !data_len)
		goto nla_put_failure;
	DBGLOG(REQ, INFO, "%s for vendor command: data_len=%d \r\n", __func__, data_len);
	/*kalMemZero(&rWifiScanCmd, sizeof(rWifiScanCmd));*/
	prWifiScanCmd = kalMemAlloc(sizeof(PARAM_WIFI_GSCAN_CMD_PARAMS), VIR_MEM_TYPE);
	if (prWifiScanCmd == NULL)
		goto nla_put_failure;
	kalMemZero(prWifiScanCmd, sizeof(PARAM_WIFI_GSCAN_CMD_PARAMS));
	kalMemZero(attr, sizeof(struct nlattr *) * (GSCAN_ATTRIBUTE_NUM_SCANS_TO_CACHE + 1));

	if (nla_parse_nested(attr, GSCAN_ATTRIBUTE_NUM_SCANS_TO_CACHE,
		(struct nlattr *)(data - NLA_HDRLEN), nla_parse_policy) < 0)
		goto nla_put_failure;
	for (k = GSCAN_ATTRIBUTE_NUM_AP_PER_SCAN; k <= GSCAN_ATTRIBUTE_NUM_SCANS_TO_CACHE; k++) {
		if (attr[k]) {
			switch (k) {
			case GSCAN_ATTRIBUTE_NUM_AP_PER_SCAN:
				prWifiScanCmd->max_ap_per_scan = nla_get_u32(attr[k]);
				break;
			case GSCAN_ATTRIBUTE_REPORT_THRESHOLD:
				prWifiScanCmd->report_threshold = nla_get_u32(attr[k]);
				break;
			case GSCAN_ATTRIBUTE_NUM_SCANS_TO_CACHE:
				prWifiScanCmd->num_scans = nla_get_u32(attr[k]);
				break;
			}
		}
	}
	DBGLOG(REQ, TRACE, "attr=0x%x, attr2=0x%x ", *(UINT_32 *) attr[GSCAN_ATTRIBUTE_NUM_AP_PER_SCAN],
	       *(UINT_32 *) attr[GSCAN_ATTRIBUTE_REPORT_THRESHOLD]);

	DBGLOG(REQ, TRACE, "max_ap_per_scan=%d, report_threshold=%d num_scans=%d \r\n",
	       prWifiScanCmd->max_ap_per_scan, prWifiScanCmd->report_threshold, prWifiScanCmd->num_scans);

	prGlueInfo = (P_GLUE_INFO_T) wiphy_priv(wiphy);
	ASSERT(prGlueInfo);

	rStatus = kalIoctl(prGlueInfo,
			   wlanoidSetGSCNAConfig,
			   prWifiScanCmd, sizeof(PARAM_WIFI_GSCAN_CMD_PARAMS), FALSE, FALSE, TRUE, FALSE, &u4BufLen);
	kalMemFree(prWifiScanCmd, VIR_MEM_TYPE, sizeof(PARAM_WIFI_GSCAN_CMD_PARAMS));
	return 0;

nla_put_failure:
	return i4Status;
}
示例#10
0
int mtk_cfg80211_vendor_set_significant_change(struct wiphy *wiphy, struct wireless_dev *wdev,
					       const void *data, int data_len)
{
	INT_32 i4Status = -EINVAL;
	P_PARAM_WIFI_SIGNIFICANT_CHANGE prWifiChangeCmd = NULL;
	UINT_8 flush = 0;
	/* struct nlattr *attr[GSCAN_ATTRIBUTE_SIGNIFICANT_CHANGE_FLUSH + 1]; */
	struct nlattr **attr = NULL;
	struct nlattr *paplist;
	int i, k;
	UINT_32 len_basic, len_aplist;

	ASSERT(wiphy);
	ASSERT(wdev);
	if ((data == NULL) || !data_len)
		goto nla_put_failure;
	DBGLOG(REQ, INFO, "%s for vendor command: data_len=%d \r\n", __func__, data_len);
	for (i = 0; i < 6; i++)
		DBGLOG(REQ, LOUD, "0x%x 0x%x 0x%x 0x%x \r\n",
			*((UINT_32 *) data + i * 4), *((UINT_32 *) data + i * 4 + 1),
			*((UINT_32 *) data + i * 4 + 2), *((UINT_32 *) data + i * 4 + 3));
	prWifiChangeCmd = kalMemAlloc(sizeof(PARAM_WIFI_SIGNIFICANT_CHANGE), VIR_MEM_TYPE);
	if (prWifiChangeCmd == NULL)
		goto nla_put_failure;
	kalMemZero(prWifiChangeCmd, sizeof(PARAM_WIFI_SIGNIFICANT_CHANGE));
	attr = kalMemAlloc(sizeof(struct nlattr *) * (GSCAN_ATTRIBUTE_SIGNIFICANT_CHANGE_FLUSH + 1), VIR_MEM_TYPE);
	if (attr == NULL)
		goto nla_put_failure;
	kalMemZero(attr, sizeof(struct nlattr *) * (GSCAN_ATTRIBUTE_SIGNIFICANT_CHANGE_FLUSH + 1));

	if (nla_parse_nested(attr, GSCAN_ATTRIBUTE_SIGNIFICANT_CHANGE_FLUSH,
		(struct nlattr *)(data - NLA_HDRLEN), nla_parse_policy) < 0)
		goto nla_put_failure;
	len_basic = 0;
	for (k = GSCAN_ATTRIBUTE_RSSI_SAMPLE_SIZE; k <= GSCAN_ATTRIBUTE_SIGNIFICANT_CHANGE_FLUSH; k++) {
		if (attr[k]) {
			switch (k) {
			case GSCAN_ATTRIBUTE_RSSI_SAMPLE_SIZE:
				prWifiChangeCmd->rssi_sample_size = nla_get_u16(attr[k]);
				len_basic += NLA_ALIGN(attr[k]->nla_len);
				break;
			case GSCAN_ATTRIBUTE_LOST_AP_SAMPLE_SIZE:
				prWifiChangeCmd->lost_ap_sample_size = nla_get_u16(attr[k]);
				len_basic += NLA_ALIGN(attr[k]->nla_len);
				break;
			case GSCAN_ATTRIBUTE_MIN_BREACHING:
				prWifiChangeCmd->min_breaching = nla_get_u16(attr[k]);
				len_basic += NLA_ALIGN(attr[k]->nla_len);
				break;
			case GSCAN_ATTRIBUTE_NUM_AP:
				prWifiChangeCmd->num_ap = nla_get_u16(attr[k]);
				len_basic += NLA_ALIGN(attr[k]->nla_len);
				DBGLOG(REQ, TRACE, "attr=0x%x, num_ap=%d nla_len=%d, \r\n",
				       *(UINT_32 *) attr[k], prWifiChangeCmd->num_ap, attr[k]->nla_len);
				break;
			case GSCAN_ATTRIBUTE_SIGNIFICANT_CHANGE_FLUSH:
				flush = nla_get_u8(attr[k]);
				len_basic += NLA_ALIGN(attr[k]->nla_len);
				break;
			}
		}
	}
	paplist = (struct nlattr *)((UINT_8 *) data + len_basic);
	DBGLOG(REQ, TRACE, "+++basic attribute size=%d flush=%d\r\n", len_basic, flush);

	if (paplist->nla_type == GSCAN_ATTRIBUTE_SIGNIFICANT_CHANGE_BSSIDS)
		paplist = (struct nlattr *)((UINT_8 *) paplist + NLA_HDRLEN);

	for (i = 0; i < prWifiChangeCmd->num_ap; i++) {
		if (nla_parse_nested(attr, GSCAN_ATTRIBUTE_RSSI_HIGH, (struct nlattr *)paplist, nla_parse_policy) < 0)
			goto nla_put_failure;
		paplist = (struct nlattr *)((UINT_8 *) paplist + NLA_HDRLEN);
		/* request.attr_start(i) as nested attribute */
		len_aplist = 0;
		for (k = GSCAN_ATTRIBUTE_BSSID; k <= GSCAN_ATTRIBUTE_RSSI_HIGH; k++) {
			if (attr[k]) {
				switch (k) {
				case GSCAN_ATTRIBUTE_BSSID:
					kalMemCopy(prWifiChangeCmd->ap[i].bssid, nla_data(attr[k]), sizeof(mac_addr));
					len_aplist += NLA_ALIGN(attr[k]->nla_len);
					break;
				case GSCAN_ATTRIBUTE_RSSI_LOW:
					prWifiChangeCmd->ap[i].low = nla_get_u32(attr[k]);
					len_aplist += NLA_ALIGN(attr[k]->nla_len);
					break;
				case GSCAN_ATTRIBUTE_RSSI_HIGH:
					prWifiChangeCmd->ap[i].high = nla_get_u32(attr[k]);
					len_aplist += NLA_ALIGN(attr[k]->nla_len);
					break;
				}
			}
		}
		if (((i + 1) % 4 == 0) || (i == prWifiChangeCmd->num_ap - 1))
			DBGLOG(REQ, TRACE, "ap[%d], len_aplist=%d\n", i, len_aplist);
		else
			DBGLOG(REQ, TRACE, "ap[%d], len_aplist=%d \t", i, len_aplist);
		paplist = (struct nlattr *)((UINT_8 *) paplist + len_aplist);
	}

	DBGLOG(REQ, TRACE,
		"flush=%d, rssi_sample_size=%d lost_ap_sample_size=%d min_breaching=%d",
		flush, prWifiChangeCmd->rssi_sample_size, prWifiChangeCmd->lost_ap_sample_size,
		prWifiChangeCmd->min_breaching);
	DBGLOG(REQ, TRACE,
		"ap[0].channel=%d low=%d high=%d, ap[1].channel=%d low=%d high=%d",
		prWifiChangeCmd->ap[0].channel, prWifiChangeCmd->ap[0].low, prWifiChangeCmd->ap[0].high,
		prWifiChangeCmd->ap[1].channel, prWifiChangeCmd->ap[1].low, prWifiChangeCmd->ap[1].high);
	kalMemFree(prWifiChangeCmd, VIR_MEM_TYPE, sizeof(PARAM_WIFI_SIGNIFICANT_CHANGE));
	kalMemFree(attr, VIR_MEM_TYPE, sizeof(struct nlattr *) * (GSCAN_ATTRIBUTE_SIGNIFICANT_CHANGE_FLUSH + 1));
	return 0;

nla_put_failure:
	if (prWifiChangeCmd)
		kalMemFree(prWifiChangeCmd, VIR_MEM_TYPE, sizeof(PARAM_WIFI_SIGNIFICANT_CHANGE));
	if (attr)
		kalMemFree(attr, VIR_MEM_TYPE,
			sizeof(struct nlattr *) * (GSCAN_ATTRIBUTE_SIGNIFICANT_CHANGE_FLUSH + 1));
	return i4Status;
}
示例#11
0
int mtk_cfg80211_vendor_set_config(struct wiphy *wiphy, struct wireless_dev *wdev, const void *data, int data_len)
{
	WLAN_STATUS rStatus;
	UINT_32 u4BufLen;
	P_GLUE_INFO_T prGlueInfo = NULL;
	/* CMD_GSCN_REQ_T rCmdGscnParam; */

	/* INT_32 i4Status = -EINVAL; */
	P_PARAM_WIFI_GSCAN_CMD_PARAMS prWifiScanCmd;
	struct nlattr *attr[GSCAN_ATTRIBUTE_REPORT_EVENTS + 1];
	struct nlattr *pbucket, *pchannel;
	UINT_32 len_basic, len_bucket, len_channel;
	int i, j, k;

	ASSERT(wiphy);
	ASSERT(wdev);
	if ((data == NULL) || !data_len)
		goto nla_put_failure;

	prWifiScanCmd = (P_PARAM_WIFI_GSCAN_CMD_PARAMS) kalMemAlloc(sizeof(PARAM_WIFI_GSCAN_CMD_PARAMS), VIR_MEM_TYPE);
	if (!prWifiScanCmd) {
		DBGLOG(REQ, ERROR, "Can not alloc memory for PARAM_WIFI_GSCAN_CMD_PARAMS\n");
		return -ENOMEM;
	}

	DBGLOG(REQ, INFO, "%s for vendor command: data_len=%d \r\n", __func__, data_len);
	kalMemZero(prWifiScanCmd, sizeof(PARAM_WIFI_GSCAN_CMD_PARAMS));
	kalMemZero(attr, sizeof(struct nlattr *) * (GSCAN_ATTRIBUTE_REPORT_EVENTS + 1));

	nla_parse_nested(attr, GSCAN_ATTRIBUTE_REPORT_EVENTS, (struct nlattr *)(data - NLA_HDRLEN), nla_parse_policy);
	len_basic = 0;
	for (k = GSCAN_ATTRIBUTE_NUM_BUCKETS; k <= GSCAN_ATTRIBUTE_REPORT_EVENTS; k++) {
		if (attr[k]) {
			switch (k) {
			case GSCAN_ATTRIBUTE_BASE_PERIOD:
				prWifiScanCmd->base_period = nla_get_u32(attr[k]);
				len_basic += NLA_ALIGN(attr[k]->nla_len);
				break;
			case GSCAN_ATTRIBUTE_NUM_BUCKETS:
				prWifiScanCmd->num_buckets = nla_get_u32(attr[k]);
				len_basic += NLA_ALIGN(attr[k]->nla_len);
				DBGLOG(REQ, TRACE, "attr=0x%x, num_buckets=%d nla_len=%d, \r\n",
				       *(UINT_32 *) attr[k], prWifiScanCmd->num_buckets, attr[k]->nla_len);
				break;
			}
		}
	}
	pbucket = (struct nlattr *)((UINT_8 *) data + len_basic);
	DBGLOG(REQ, TRACE, "+++basic attribute size=%d pbucket=%p\r\n", len_basic, pbucket);

	for (i = 0; i < prWifiScanCmd->num_buckets; i++) {
		if (nla_parse_nested(attr, GSCAN_ATTRIBUTE_REPORT_EVENTS, (struct nlattr *)pbucket,
			nla_parse_policy) < 0)
			goto nla_put_failure;
		len_bucket = 0;
		for (k = GSCAN_ATTRIBUTE_NUM_BUCKETS; k <= GSCAN_ATTRIBUTE_REPORT_EVENTS; k++) {
			if (attr[k]) {
				switch (k) {
				case GSCAN_ATTRIBUTE_BUCKETS_BAND:
					prWifiScanCmd->buckets[i].band = nla_get_u32(attr[k]);
					len_bucket += NLA_ALIGN(attr[k]->nla_len);
					break;
				case GSCAN_ATTRIBUTE_BUCKET_ID:
					prWifiScanCmd->buckets[i].bucket = nla_get_u32(attr[k]);
					len_bucket += NLA_ALIGN(attr[k]->nla_len);
					break;
				case GSCAN_ATTRIBUTE_BUCKET_PERIOD:
					prWifiScanCmd->buckets[i].period = nla_get_u32(attr[k]);
					len_bucket += NLA_ALIGN(attr[k]->nla_len);
					break;
				case GSCAN_ATTRIBUTE_REPORT_EVENTS:
					prWifiScanCmd->buckets[i].report_events = nla_get_u32(attr[k]);
					len_bucket += NLA_ALIGN(attr[k]->nla_len);
					break;
				case GSCAN_ATTRIBUTE_BUCKET_NUM_CHANNELS:
					prWifiScanCmd->buckets[i].num_channels = nla_get_u32(attr[k]);
					len_bucket += NLA_ALIGN(attr[k]->nla_len);
					DBGLOG(REQ, TRACE, "bucket%d: attr=0x%x, num_channels=%d nla_len = %d, \r\n",
					       i, *(UINT_32 *) attr[k], nla_get_u32(attr[k]), attr[k]->nla_len);
					break;
				}
			}
		}
		pbucket = (struct nlattr *)((UINT_8 *) pbucket + NLA_HDRLEN);
		/* request.attr_start(i) as nested attribute */
		DBGLOG(REQ, TRACE, "+++pure bucket size=%d pbucket=%p \r\n", len_bucket, pbucket);
		pbucket = (struct nlattr *)((UINT_8 *) pbucket + len_bucket);
		/* pure bucket payload, not include channels */

		/*don't need to use nla_parse_nested to parse channels */
		/* the header of channel in bucket i */
		pchannel = (struct nlattr *)((UINT_8 *) pbucket + NLA_HDRLEN);
		for (j = 0; j < prWifiScanCmd->buckets[i].num_channels; j++) {
			prWifiScanCmd->buckets[i].channels[j].channel = nla_get_u32(pchannel);
			len_channel = NLA_ALIGN(pchannel->nla_len);
			DBGLOG(REQ, TRACE,
				"attr=0x%x, channel=%d, \r\n", *(UINT_32 *) pchannel, nla_get_u32(pchannel));

			pchannel = (struct nlattr *)((UINT_8 *) pchannel + len_channel);
		}
		pbucket = pchannel;
	}

	DBGLOG(REQ, TRACE, "base_period=%d, num_buckets=%d, bucket0: %d %d %d %d",
		prWifiScanCmd->base_period, prWifiScanCmd->num_buckets,
		prWifiScanCmd->buckets[0].bucket, prWifiScanCmd->buckets[0].period,
		prWifiScanCmd->buckets[0].band, prWifiScanCmd->buckets[0].report_events);

	DBGLOG(REQ, TRACE, "num_channels=%d, channel0=%d, channel1=%d; num_channels=%d, channel0=%d, channel1=%d",
		prWifiScanCmd->buckets[0].num_channels,
		prWifiScanCmd->buckets[0].channels[0].channel, prWifiScanCmd->buckets[0].channels[1].channel,
		prWifiScanCmd->buckets[1].num_channels,
		prWifiScanCmd->buckets[1].channels[0].channel, prWifiScanCmd->buckets[1].channels[1].channel);

	prGlueInfo = (P_GLUE_INFO_T) wiphy_priv(wiphy);
	ASSERT(prGlueInfo);

	rStatus = kalIoctl(prGlueInfo,
			   wlanoidSetGSCNAParam,
			   prWifiScanCmd, sizeof(PARAM_WIFI_GSCAN_CMD_PARAMS), FALSE, FALSE, TRUE, FALSE, &u4BufLen);

	return 0;

nla_put_failure:
	return -1;
}
/*----------------------------------------------------------------------------*/
int 
mtk_cfg80211_scan (
    struct wiphy *wiphy,
#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 6, 0)
    struct net_device *ndev,
#endif
    struct cfg80211_scan_request *request
    )
{
    P_GLUE_INFO_T prGlueInfo = NULL;
    WLAN_STATUS rStatus;
    UINT_32 u4BufLen;
    PARAM_SCAN_REQUEST_EXT_T rScanRequest;

    prGlueInfo = (P_GLUE_INFO_T) wiphy_priv(wiphy);
    ASSERT(prGlueInfo);
    
    kalMemZero(&rScanRequest, sizeof(PARAM_SCAN_REQUEST_EXT_T));
    
    /* check if there is any pending scan not yet finished */
    if(prGlueInfo->prScanRequest != NULL) {
        return -EBUSY;
    }

    if(request->n_ssids == 0) {
        rScanRequest.rSsid.u4SsidLen = 0;
    }
    else if(request->n_ssids == 1) {
        COPY_SSID(rScanRequest.rSsid.aucSsid, rScanRequest.rSsid.u4SsidLen, request->ssids[0].ssid, request->ssids[0].ssid_len);
    }
    else {
        return -EINVAL;
    }

    if(request->ie_len > 0) {
        rScanRequest.u4IELength = request->ie_len;
        rScanRequest.pucIE = (PUINT_8)(request->ie);
    }
    else {
        rScanRequest.u4IELength = 0;
    }

    rStatus = kalIoctl(prGlueInfo,
        wlanoidSetBssidListScanExt,
        &rScanRequest,
        sizeof(PARAM_SCAN_REQUEST_EXT_T),
        FALSE,
        FALSE,
        FALSE,
        FALSE,
        &u4BufLen);

    if (rStatus != WLAN_STATUS_SUCCESS) {
        DBGLOG(REQ, WARN, ("scan error:%lx\n", rStatus));
        return -EINVAL;
    }

    prGlueInfo->prScanRequest = request;

    return 0;
}
示例#13
0
VOID rlmDomainPassiveScanSendCmd(    
	P_ADAPTER_T     prAdapter, 
    BOOLEAN         fgIsOid	
)
{
    P_DOMAIN_INFO_ENTRY     prDomainInfo;
	P_CMD_SET_DOMAIN_INFO_T prCmd;
    WLAN_STATUS             rStatus;
    P_DOMAIN_SUBBAND_INFO   prSubBand;
    UINT_8                  i;	


	prCmd = cnmMemAlloc(prAdapter, RAM_TYPE_BUF, sizeof(CMD_SET_DOMAIN_INFO_T));
   	ASSERT(prCmd);


	/* To do: exception handle */
	if (!prCmd) {
	   DBGLOG(RLM, ERROR, ("Domain: no buf to send cmd\n"));
	   return;
	}
	kalMemZero(prCmd, sizeof(CMD_SET_DOMAIN_INFO_T));

	prCmd->u2CountryCode = prAdapter->rWifiVar.rConnSettings.u2CountryCode;
	prCmd->u2IsSetPassiveScan = 1;
	prCmd->uc2G4Bandwidth = prAdapter->rWifiVar.rConnSettings.uc2G4BandwidthMode;
	prCmd->uc5GBandwidth = prAdapter->rWifiVar.rConnSettings.uc5GBandwidthMode;
	prCmd->aucReserved[0] = 0;
	prCmd->aucReserved[1] = 0;


	DBGLOG(RLM, INFO, ("rlmDomainPassiveScanSendCmd(), CountryCode = %x\n", prAdapter->rWifiVar.rConnSettings.u2CountryCode));

	if (prAdapter->rWifiVar.rConnSettings.u2CountryCode == COUNTRY_CODE_UDF){
		prDomainInfo = &arSupportedRegDomains_Passive[REG_DOMAIN_PASSIVE_UDF_IDX];
	}
	else{
		prDomainInfo = &arSupportedRegDomains_Passive[REG_DOMAIN_PASSIVE_DEF_IDX];
	}

	for (i = 0; i < 6; i++) {
	   prSubBand = &prDomainInfo->rSubBand[i];

	   prCmd->rSubBand[i].ucRegClass = prSubBand->ucRegClass;
	   prCmd->rSubBand[i].ucBand = prSubBand->ucBand;

	   if (prSubBand->ucBand != BAND_NULL && prSubBand->ucBand < BAND_NUM) {
		   prCmd->rSubBand[i].ucChannelSpan = prSubBand->ucChannelSpan;
		   prCmd->rSubBand[i].ucFirstChannelNum = prSubBand->ucFirstChannelNum;
		   prCmd->rSubBand[i].ucNumChannels = prSubBand->ucNumChannels;
	   }
	}

	rStatus = wlanSendSetQueryCmd (
				prAdapter,					/* prAdapter */
				CMD_ID_SET_DOMAIN_INFO, 	/* ucCID */
				TRUE,						/* fgSetQuery */
				FALSE,						/* fgNeedResp */
				fgIsOid,					/* fgIsOid */
				NULL,						/* pfCmdDoneHandler*/
				NULL,						/* pfCmdTimeoutHandler */
				sizeof(CMD_SET_DOMAIN_INFO_T),	  /* u4SetQueryInfoLen */
				(PUINT_8) prCmd,			/* pucInfoBuffer */
				NULL,						/* pvSetQueryBuffer */
				0							/* u4SetQueryBufferLen */
				);

	ASSERT(rStatus == WLAN_STATUS_PENDING);

	cnmMemFree(prAdapter, prCmd);			
}
WLAN_STATUS
wlanoidSetUApsdParam(IN P_ADAPTER_T prAdapter,
		     IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen)
{
	P_PARAM_CUSTOM_UAPSD_PARAM_STRUC_T prUapsdParam;
	CMD_CUSTOM_UAPSD_PARAM_STRUC_T rCmdUapsdParam;
	P_PM_PROFILE_SETUP_INFO_T prPmProfSetupInfo;
	P_BSS_INFO_T prBssInfo;


	DEBUGFUNC("wlanoidSetUApsdParam");
	DBGLOG(INIT, TRACE, ("\n"));

	ASSERT(prAdapter);
	ASSERT(pu4SetInfoLen);

	*pu4SetInfoLen = sizeof(PARAM_CUSTOM_UAPSD_PARAM_STRUC_T);

	if (u4SetBufferLen < sizeof(PARAM_CUSTOM_UAPSD_PARAM_STRUC_T)) {
		return WLAN_STATUS_INVALID_LENGTH;
	}

	ASSERT(pvSetBuffer);

	prBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_P2P_INDEX]);
	prPmProfSetupInfo = &prBssInfo->rPmProfSetupInfo;

	prUapsdParam = (P_PARAM_CUSTOM_UAPSD_PARAM_STRUC_T) pvSetBuffer;

	kalMemZero(&rCmdUapsdParam, sizeof(CMD_CUSTOM_OPPPS_PARAM_STRUC_T));
	rCmdUapsdParam.fgEnAPSD = prUapsdParam->fgEnAPSD;
	prAdapter->rWifiVar.fgSupportUAPSD = prUapsdParam->fgEnAPSD;

	rCmdUapsdParam.fgEnAPSD_AcBe = prUapsdParam->fgEnAPSD_AcBe;
	rCmdUapsdParam.fgEnAPSD_AcBk = prUapsdParam->fgEnAPSD_AcBk;
	rCmdUapsdParam.fgEnAPSD_AcVo = prUapsdParam->fgEnAPSD_AcVo;
	rCmdUapsdParam.fgEnAPSD_AcVi = prUapsdParam->fgEnAPSD_AcVi;
	prPmProfSetupInfo->ucBmpDeliveryAC =
	    ((prUapsdParam->fgEnAPSD_AcBe << 0) |
	     (prUapsdParam->fgEnAPSD_AcBk << 1) |
	     (prUapsdParam->fgEnAPSD_AcVi << 2) | (prUapsdParam->fgEnAPSD_AcVo << 3));
	prPmProfSetupInfo->ucBmpTriggerAC =
	    ((prUapsdParam->fgEnAPSD_AcBe << 0) |
	     (prUapsdParam->fgEnAPSD_AcBk << 1) |
	     (prUapsdParam->fgEnAPSD_AcVi << 2) | (prUapsdParam->fgEnAPSD_AcVo << 3));

	rCmdUapsdParam.ucMaxSpLen = prUapsdParam->ucMaxSpLen;
	prPmProfSetupInfo->ucUapsdSp = prUapsdParam->ucMaxSpLen;

#if 0
	return wlanSendSetQueryCmd(prAdapter,
				   CMD_ID_SET_UAPSD_PARAM,
				   TRUE,
				   FALSE,
				   TRUE,
				   nicCmdEventSetCommon,
				   nicOidCmdTimeoutCommon,
				   sizeof(CMD_CUSTOM_OPPPS_PARAM_STRUC_T),
				   (PUINT_8) &rCmdUapsdParam, pvSetBuffer, u4SetBufferLen);
#else
	return wlanoidSendSetQueryP2PCmd(prAdapter,
					 CMD_ID_SET_UAPSD_PARAM,
					 TRUE,
					 FALSE,
					 TRUE,
					 NULL,
					 nicOidCmdTimeoutCommon,
					 sizeof(CMD_CUSTOM_OPPPS_PARAM_STRUC_T),
					 (PUINT_8) &rCmdUapsdParam, pvSetBuffer, u4SetBufferLen);

#endif
}
示例#15
0
int mtk_cfg80211_vendor_get_channel_list(struct wiphy *wiphy, struct wireless_dev *wdev, const void *data, int data_len)
{
	INT_32 i4Status = -EINVAL;
	struct nlattr *attr;
	UINT_32 band = 0;
	UINT_32 num_channel;
	wifi_channel channels[4];
	struct sk_buff *skb;

	ASSERT(wiphy);
	ASSERT(wdev);
	if ((data == NULL) || !data_len)
		return i4Status;
	DBGLOG(REQ, INFO, "%s for vendor command: data_len=%d \r\n", __func__, data_len);

	attr = (struct nlattr *)data;
	if (attr->nla_type == GSCAN_ATTRIBUTE_BAND)
		band = nla_get_u32(attr);
	DBGLOG(REQ, INFO, "get channel list: band=%d \r\n", band);

	skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(wifi_channel) * 4);
	if (!skb) {
		DBGLOG(REQ, TRACE, "%s allocate skb failed:%x\n", __func__, i4Status);
		return -ENOMEM;
	}

	kalMemZero(channels, sizeof(wifi_channel) * 4);
	/*rStatus = kalIoctl(prGlueInfo,
	   wlanoidQueryStatistics,
	   &channel,
	   sizeof(channel),
	   TRUE,
	   TRUE,
	   TRUE,
	   FALSE,
	   &u4BufLen); */

	/* only for test */
	num_channel = 3;
	channels[0] = 2412;
	channels[1] = 2413;
	channels[2] = 2414;
	/*NLA_PUT_U32(skb, GSCAN_ATTRIBUTE_NUM_CHANNELS, num_channel);*/
	{
		unsigned int __tmp = num_channel;

		if (unlikely(nla_put(skb, GSCAN_ATTRIBUTE_NUM_CHANNELS,
			sizeof(unsigned int), &__tmp) < 0))
			goto nla_put_failure;
	}

	/*NLA_PUT(skb, GSCAN_ATTRIBUTE_CHANNEL_LIST, (sizeof(wifi_channel) * num_channel), channels);*/
	if (unlikely(nla_put(skb, GSCAN_ATTRIBUTE_CHANNEL_LIST,
		(sizeof(wifi_channel) * num_channel), channels) < 0))
		goto nla_put_failure;

	i4Status = cfg80211_vendor_cmd_reply(skb);
	return i4Status;

nla_put_failure:
	kfree_skb(skb);
	return i4Status;
}
示例#16
0
int
mtk_cfg80211_testmode_get_sta_statistics(IN struct wiphy *wiphy,
					 IN void *data, IN int len, IN P_GLUE_INFO_T prGlueInfo)
{
#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 8, 0)
#define NLA_PUT(skb, attrtype, attrlen, data) \
	 do { \
		 if (unlikely(nla_put(skb, attrtype, attrlen, data) < 0)) \
			 printk("NLA PUT Error!!!!\n"); \
	 } while (0)

#define NLA_PUT_TYPE(skb, type, attrtype, value) \
	 do { \
		 type __tmp = value; \
		 NLA_PUT(skb, attrtype, sizeof(type), &__tmp); \
	 } while (0)

#define NLA_PUT_U8(skb, attrtype, value) \
	 NLA_PUT_TYPE(skb, u8, attrtype, value)

#define NLA_PUT_U16(skb, attrtype, value) \
	 NLA_PUT_TYPE(skb, u16, attrtype, value)

#define NLA_PUT_U32(skb, attrtype, value) \
	 NLA_PUT_TYPE(skb, u32, attrtype, value)

#endif
	WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS;
	INT_32 i4Status = -EINVAL;
	UINT_32 u4BufLen;
	UINT_32 u4LinkScore;
	UINT_32 u4TotalError;
	UINT_32 u4TxExceedThresholdCount;
	UINT_32 u4TxTotalCount;

	P_NL80211_DRIVER_GET_STA_STATISTICS_PARAMS prParams = NULL;
	PARAM_GET_STA_STA_STATISTICS rQueryStaStatistics;
	struct sk_buff *skb;

	ASSERT(wiphy);
	ASSERT(prGlueInfo);

	if (data && len) {
		prParams = (P_NL80211_DRIVER_GET_STA_STATISTICS_PARAMS) data;
	}

	if (!prParams->aucMacAddr) {
		DBGLOG(QM, TRACE, ("%s MAC Address is NULL\n", __func__));
		i4Status = -EINVAL;
		goto nla_put_failure;
	}

	skb = cfg80211_testmode_alloc_reply_skb(wiphy, sizeof(PARAM_GET_STA_STA_STATISTICS) + 1);

	if (!skb) {
		DBGLOG(QM, TRACE, ("%s allocate skb failed:\n", __func__));
		i4Status = -ENOMEM;
		goto nla_put_failure;
	}

	DBGLOG(QM, TRACE, ("Get [" MACSTR "] STA statistics\n", MAC2STR(prParams->aucMacAddr)));

	kalMemZero(&rQueryStaStatistics, sizeof(rQueryStaStatistics));
	COPY_MAC_ADDR(rQueryStaStatistics.aucMacAddr, prParams->aucMacAddr);

	rStatus = kalIoctl(prGlueInfo,
			   wlanoidQueryStaStatistics,
			   &rQueryStaStatistics,
			   sizeof(rQueryStaStatistics), TRUE, FALSE, TRUE, TRUE, &u4BufLen);

	/* Calcute Link Score */
	u4TxExceedThresholdCount = rQueryStaStatistics.u4TxExceedThresholdCount;
	u4TxTotalCount = rQueryStaStatistics.u4TxTotalCount;
	u4TotalError = rQueryStaStatistics.u4TxFailCount + rQueryStaStatistics.u4TxLifeTimeoutCount;

	/* u4LinkScore 10~100 , ExceedThreshold ratio 0~90 only */
	/* u4LinkScore 0~9    , Drop packet ratio 0~9 and all packets exceed threshold */
	if (u4TxTotalCount) {
		if (u4TxExceedThresholdCount <= u4TxTotalCount) {
			u4LinkScore = (90 - ((u4TxExceedThresholdCount * 90) / u4TxTotalCount));
		} else {
			u4LinkScore = 0;
		}
	} else {
		u4LinkScore = 90;
	}

	u4LinkScore += 10;

	if (u4LinkScore == 10) {

		if (u4TotalError <= u4TxTotalCount) {
			u4LinkScore = (10 - ((u4TotalError * 10) / u4TxTotalCount));
		} else {
			u4LinkScore = 0;
		}

	}

	if (u4LinkScore > 100) {
		u4LinkScore = 100;
	}


	NLA_PUT_U8(skb, NL80211_TESTMODE_STA_STATISTICS_INVALID, 0);
	NLA_PUT_U8(skb, NL80211_TESTMODE_STA_STATISTICS_VERSION, NL80211_DRIVER_TESTMODE_VERSION);
	NLA_PUT(skb, NL80211_TESTMODE_STA_STATISTICS_MAC, MAC_ADDR_LEN, prParams->aucMacAddr);
	NLA_PUT_U8(skb, NL80211_TESTMODE_STA_STATISTICS_LINK_SCORE, u4LinkScore);
	NLA_PUT_U32(skb, NL80211_TESTMODE_STA_STATISTICS_FLAG, rQueryStaStatistics.u4Flag);

	/* FW part STA link status */
	NLA_PUT_U8(skb, NL80211_TESTMODE_STA_STATISTICS_PER, rQueryStaStatistics.ucPer);
	NLA_PUT_U8(skb, NL80211_TESTMODE_STA_STATISTICS_RSSI, rQueryStaStatistics.ucRcpi);
	NLA_PUT_U32(skb, NL80211_TESTMODE_STA_STATISTICS_PHY_MODE, rQueryStaStatistics.u4PhyMode);
	NLA_PUT_U16(skb, NL80211_TESTMODE_STA_STATISTICS_TX_RATE, rQueryStaStatistics.u2LinkSpeed);
	NLA_PUT_U32(skb, NL80211_TESTMODE_STA_STATISTICS_FAIL_CNT,
		    rQueryStaStatistics.u4TxFailCount);
	NLA_PUT_U32(skb, NL80211_TESTMODE_STA_STATISTICS_TIMEOUT_CNT,
		    rQueryStaStatistics.u4TxLifeTimeoutCount);
	NLA_PUT_U32(skb, NL80211_TESTMODE_STA_STATISTICS_AVG_AIR_TIME,
		    rQueryStaStatistics.u4TxAverageAirTime);

	/* Driver part link status */
	NLA_PUT_U32(skb, NL80211_TESTMODE_STA_STATISTICS_TOTAL_CNT,
		    rQueryStaStatistics.u4TxTotalCount);
	NLA_PUT_U32(skb, NL80211_TESTMODE_STA_STATISTICS_THRESHOLD_CNT,
		    rQueryStaStatistics.u4TxExceedThresholdCount);
	NLA_PUT_U32(skb, NL80211_TESTMODE_STA_STATISTICS_AVG_PROCESS_TIME,
		    rQueryStaStatistics.u4TxAverageProcessTime);

	/* Network counter */
	NLA_PUT(skb,
		NL80211_TESTMODE_STA_STATISTICS_TC_EMPTY_CNT_ARRAY,
		sizeof(rQueryStaStatistics.au4TcResourceEmptyCount),
		rQueryStaStatistics.au4TcResourceEmptyCount);

	/* Sta queue length */
	NLA_PUT(skb,
		NL80211_TESTMODE_STA_STATISTICS_TC_QUE_LEN_ARRAY,
		sizeof(rQueryStaStatistics.au4TcQueLen), rQueryStaStatistics.au4TcQueLen);

	/* Global QM counter */
	NLA_PUT(skb,
		NL80211_TESTMODE_STA_STATISTICS_TC_AVG_QUE_LEN_ARRAY,
		sizeof(rQueryStaStatistics.au4TcAverageQueLen),
		rQueryStaStatistics.au4TcAverageQueLen);

	NLA_PUT(skb,
		NL80211_TESTMODE_STA_STATISTICS_TC_CUR_QUE_LEN_ARRAY,
		sizeof(rQueryStaStatistics.au4TcCurrentQueLen),
		rQueryStaStatistics.au4TcCurrentQueLen);

	/* Reserved field */
	NLA_PUT(skb,
		NL80211_TESTMODE_STA_STATISTICS_RESERVED_ARRAY,
		sizeof(rQueryStaStatistics.au4Reserved), rQueryStaStatistics.au4Reserved);

	i4Status = cfg80211_testmode_reply(skb);

 nla_put_failure:
	return i4Status;
}
/*----------------------------------------------------------------------------*/
VOID
kalUpdateReAssocReqInfo(IN P_GLUE_INFO_T prGlueInfo,
			IN PUINT_8 pucFrameBody,
			IN UINT_32 u4FrameBodyLen, IN BOOLEAN fgReassocRequest)
{
	PUINT_8 cp;
	PNDIS_802_11_ASSOCIATION_INFORMATION prNdisAssocInfo;

	if (fgReassocRequest) {
		ASSERT(u4FrameBodyLen >= MIN_REASSOC_REQ_BODY_LEN);

		if (u4FrameBodyLen < MIN_REASSOC_REQ_BODY_LEN) {
			return;
		}
	} else {
		ASSERT(u4FrameBodyLen >= MIN_ASSOC_REQ_BODY_LEN);

		if (u4FrameBodyLen < MIN_ASSOC_REQ_BODY_LEN) {
			return;
		}
	}

	prNdisAssocInfo = &prGlueInfo->rNdisAssocInfo;

	cp = pucFrameBody;

	/* Update the fixed information elements. */
	if (fgReassocRequest) {
		prNdisAssocInfo->AvailableRequestFixedIEs =
		    NDIS_802_11_AI_REQFI_CAPABILITIES |
		    NDIS_802_11_AI_REQFI_LISTENINTERVAL | NDIS_802_11_AI_REQFI_CURRENTAPADDRESS;
	} else {
		prNdisAssocInfo->AvailableRequestFixedIEs =
		    NDIS_802_11_AI_REQFI_CAPABILITIES | NDIS_802_11_AI_REQFI_LISTENINTERVAL;
	}

	kalMemCopy(&prNdisAssocInfo->RequestFixedIEs.Capabilities, cp, 2);
	cp += 2;
	u4FrameBodyLen -= 2;

	kalMemCopy(&prNdisAssocInfo->RequestFixedIEs.ListenInterval, cp, 2);
	cp += 2;
	u4FrameBodyLen -= 2;

	if (fgReassocRequest) {
		kalMemCopy(&prNdisAssocInfo->RequestFixedIEs.CurrentAPAddress, cp, 6);
		cp += 6;
		u4FrameBodyLen -= 6;
	} else {
		kalMemZero(&prNdisAssocInfo->RequestFixedIEs.CurrentAPAddress, 6);
	}

	/* Update the variable length information elements. */
	prNdisAssocInfo->RequestIELength = u4FrameBodyLen;
	prNdisAssocInfo->OffsetRequestIEs = sizeof(NDIS_802_11_ASSOCIATION_INFORMATION);

	kalMemCopy(prGlueInfo->aucNdisAssocInfoIEs, cp, u4FrameBodyLen);

	/* Clear the information for the last association/reassociation response
	   from the AP. */
	prNdisAssocInfo->AvailableResponseFixedIEs = 0;
	prNdisAssocInfo->ResponseFixedIEs.Capabilities = 0;
	prNdisAssocInfo->ResponseFixedIEs.StatusCode = 0;
	prNdisAssocInfo->ResponseFixedIEs.AssociationId = 0;
	prNdisAssocInfo->ResponseIELength = 0;
	prNdisAssocInfo->OffsetResponseIEs =
	    sizeof(NDIS_802_11_ASSOCIATION_INFORMATION) + u4FrameBodyLen;

}				/* kalUpdateReAssocReqInfo */
void p2pHandleSystemSuspend(void)
{
    struct net_device *prDev = NULL;
    P_GLUE_INFO_T prGlueInfo = NULL;
    UINT_8  ip[4] = { 0 };
    UINT_32 u4NumIPv4 = 0;
#ifdef  CONFIG_IPV6
    UINT_8  ip6[16] = { 0 };     // FIX ME: avoid to allocate large memory in stack
    UINT_32 u4NumIPv6 = 0;
#endif
    UINT_32 i;
	P_PARAM_NETWORK_ADDRESS_IP prParamIpAddr;

    printk(KERN_INFO "*********p2pEarlySuspend************\n");

    if(!wlanExportGlueInfo(&prGlueInfo)) {
        printk(KERN_INFO "*********p2pEarlySuspend ignored************\n");
        return;
    }

    ASSERT(prGlueInfo);
    // <1> Sanity check and acquire the net_device
    prDev = prGlueInfo->prP2PInfo->prDevHandler;
    ASSERT(prDev);

    // <3> get the IPv4 address
    if(!prDev || !(prDev->ip_ptr)||\
        !((struct in_device *)(prDev->ip_ptr))->ifa_list||\
        !(&(((struct in_device *)(prDev->ip_ptr))->ifa_list->ifa_local))){
        printk(KERN_INFO "ip is not avaliable.\n");
        return;
    }

    // <4> copy the IPv4 address
    kalMemCopy(ip, &(((struct in_device *)(prDev->ip_ptr))->ifa_list->ifa_local), sizeof(ip));
    printk(KERN_INFO"ip is %d.%d.%d.%d\n",
            ip[0],ip[1],ip[2],ip[3]);

   // todo: traverse between list to find whole sets of IPv4 addresses
    if (!((ip[0] == 0) &&
         (ip[1] == 0) &&
         (ip[2] == 0) &&
         (ip[3] == 0))) {
        u4NumIPv4++;
    }

#ifdef  CONFIG_IPV6
    // <5> get the IPv6 address
    if(!prDev || !(prDev->ip6_ptr)||\
        !((struct in_device *)(prDev->ip6_ptr))->ifa_list||\
        !(&(((struct in_device *)(prDev->ip6_ptr))->ifa_list->ifa_local))){
        printk(KERN_INFO "ipv6 is not avaliable.\n");
        return;
    }
    // <6> copy the IPv6 address
    kalMemCopy(ip6, &(((struct in_device *)(prDev->ip6_ptr))->ifa_list->ifa_local), sizeof(ip6));
    printk(KERN_INFO"ipv6 is %d.%d.%d.%d.%d.%d.%d.%d.%d.%d.%d.%d.%d.%d.%d.%d\n",
            ip6[0],ip6[1],ip6[2],ip6[3],
            ip6[4],ip6[5],ip6[6],ip6[7],
            ip6[8],ip6[9],ip6[10],ip6[11],
            ip6[12],ip6[13],ip6[14],ip6[15]
            );
    // todo: traverse between list to find whole sets of IPv6 addresses

    if (!((ip6[0] == 0) &&
         (ip6[1] == 0) &&
         (ip6[2] == 0) &&
         (ip6[3] == 0) &&
         (ip6[4] == 0) &&
         (ip6[5] == 0))) {
    }

#endif
    // <7> set up the ARP filter
    {
        WLAN_STATUS rStatus = WLAN_STATUS_FAILURE;
        UINT_32 u4SetInfoLen = 0;
//        UINT_8 aucBuf[32] = {0};
        UINT_32 u4Len = OFFSET_OF(PARAM_NETWORK_ADDRESS_LIST, arAddress);
        P_PARAM_NETWORK_ADDRESS_LIST prParamNetAddrList = (P_PARAM_NETWORK_ADDRESS_LIST)g_aucBufIpAddr;//aucBuf;
        P_PARAM_NETWORK_ADDRESS prParamNetAddr = prParamNetAddrList->arAddress;

        kalMemZero(g_aucBufIpAddr, sizeof(g_aucBufIpAddr));

        prParamNetAddrList->u4AddressCount = u4NumIPv4 + u4NumIPv6;
        prParamNetAddrList->u2AddressType = PARAM_PROTOCOL_ID_TCP_IP;
        for (i = 0; i < u4NumIPv4; i++) {
            prParamNetAddr->u2AddressLength = sizeof(PARAM_NETWORK_ADDRESS_IP);//4;;
            prParamNetAddr->u2AddressType = PARAM_PROTOCOL_ID_TCP_IP;;
#if 0
            kalMemCopy(prParamNetAddr->aucAddress, ip, sizeof(ip));
            prParamNetAddr = (P_PARAM_NETWORK_ADDRESS)((UINT_32)prParamNetAddr + sizeof(ip));
            u4Len += OFFSET_OF(PARAM_NETWORK_ADDRESS, aucAddress) + sizeof(ip);
#else
            prParamIpAddr = (P_PARAM_NETWORK_ADDRESS_IP)prParamNetAddr->aucAddress;
            kalMemCopy(&prParamIpAddr->in_addr, ip, sizeof(ip));

//            prParamNetAddr = (P_PARAM_NETWORK_ADDRESS)((UINT_32)prParamNetAddr + sizeof(PARAM_NETWORK_ADDRESS));    // TODO: frog. The pointer is not right.

            prParamNetAddr = (P_PARAM_NETWORK_ADDRESS) ((ULONG) prParamNetAddr +
            (ULONG) (prParamNetAddr->u2AddressLength + OFFSET_OF(PARAM_NETWORK_ADDRESS, aucAddress)));

            u4Len += OFFSET_OF(PARAM_NETWORK_ADDRESS, aucAddress) + sizeof(PARAM_NETWORK_ADDRESS_IP);
#endif
        }
#ifdef  CONFIG_IPV6
        for (i = 0; i < u4NumIPv6; i++) {
            prParamNetAddr->u2AddressLength = 6;;
            prParamNetAddr->u2AddressType = PARAM_PROTOCOL_ID_TCP_IP;;
            kalMemCopy(prParamNetAddr->aucAddress, ip6, sizeof(ip6));
//            prParamNetAddr = (P_PARAM_NETWORK_ADDRESS)((UINT_32)prParamNetAddr + sizeof(ip6));

            prParamNetAddr = (P_PARAM_NETWORK_ADDRESS) ((ULONG) prParamNetAddr +
            (ULONG) (prParamNetAddr->u2AddressLength + OFFSET_OF(PARAM_NETWORK_ADDRESS, aucAddress)));

            u4Len += OFFSET_OF(PARAM_NETWORK_ADDRESS, aucAddress) + sizeof(ip6);
       }
#endif
        ASSERT(u4Len <= sizeof(g_aucBufIpAddr/*aucBuf*/));

        rStatus = kalIoctl(prGlueInfo,
                wlanoidSetP2pSetNetworkAddress,
                (PVOID)prParamNetAddrList,
                u4Len,
                FALSE,
                FALSE,
                TRUE,
                TRUE,
                &u4SetInfoLen);

        if (rStatus != WLAN_STATUS_SUCCESS) {
            printk(KERN_INFO DRV_NAME"set HW pattern filter fail 0x%x\n", rStatus);
        }
    }
}
/*----------------------------------------------------------------------------*/
VOID kalHandleAssocInfo(IN P_GLUE_INFO_T prGlueInfo, IN P_EVENT_ASSOC_INFO prAssocInfo)
{
	UINT_16 u2FrameBodyLen;

	ASSERT(prGlueInfo);

	u2FrameBodyLen = prAssocInfo->u2Length;

	if (prAssocInfo->ucAssocReq) {
		PUINT_8 cp;
		PNDIS_802_11_ASSOCIATION_INFORMATION prNdisAssocInfo;

#if 0
		if (prAssocInfo->ucReassoc) {
			ASSERT(u2FrameBodyLen >= MIN_REASSOC_REQ_BODY_LEN);

			if (u2FrameBodyLen < MIN_REASSOC_REQ_BODY_LEN) {
				return;
			}
		} else {
			ASSERT(u2FrameBodyLen >= MIN_ASSOC_REQ_BODY_LEN);

			if (u2FrameBodyLen < MIN_ASSOC_REQ_BODY_LEN) {
				return;
			}
		}
#endif
		prNdisAssocInfo = &prGlueInfo->rNdisAssocInfo;

		cp = (PUINT_8) &prAssocInfo->pucIe;

		/* Update the fixed information elements. */
		if (prAssocInfo->ucReassoc) {
			prNdisAssocInfo->AvailableRequestFixedIEs =
			    NDIS_802_11_AI_REQFI_CAPABILITIES |
			    NDIS_802_11_AI_REQFI_LISTENINTERVAL |
			    NDIS_802_11_AI_REQFI_CURRENTAPADDRESS;
		} else {
			prNdisAssocInfo->AvailableRequestFixedIEs =
			    NDIS_802_11_AI_REQFI_CAPABILITIES | NDIS_802_11_AI_REQFI_LISTENINTERVAL;
		}
		kalMemCopy(&prNdisAssocInfo->RequestFixedIEs.Capabilities, cp, 2);
		cp += 2;
		u2FrameBodyLen -= 2;

		kalMemCopy(&prNdisAssocInfo->RequestFixedIEs.ListenInterval, cp, 2);
		cp += 2;
		u2FrameBodyLen -= 2;
		if (prAssocInfo->ucReassoc) {
			kalMemCopy(&prNdisAssocInfo->RequestFixedIEs.CurrentAPAddress, cp, 6);
			cp += 6;
			u2FrameBodyLen -= 6;
		} else {
			kalMemZero(&prNdisAssocInfo->RequestFixedIEs.CurrentAPAddress, 6);
		}

		/* Update the variable length information elements. */
		prNdisAssocInfo->RequestIELength = u2FrameBodyLen;
		prNdisAssocInfo->OffsetRequestIEs = sizeof(NDIS_802_11_ASSOCIATION_INFORMATION);

		kalMemCopy(prGlueInfo->aucNdisAssocInfoIEs, cp, u2FrameBodyLen);

		/* Clear the information for the last association/reassociation response
		 * from the AP. */
		prNdisAssocInfo->AvailableResponseFixedIEs = 0;
		prNdisAssocInfo->ResponseFixedIEs.Capabilities = 0;
		prNdisAssocInfo->ResponseFixedIEs.StatusCode = 0;
		prNdisAssocInfo->ResponseFixedIEs.AssociationId = 0;
		prNdisAssocInfo->ResponseIELength = 0;
		prNdisAssocInfo->OffsetResponseIEs =
		    sizeof(NDIS_802_11_ASSOCIATION_INFORMATION) + u2FrameBodyLen;

	} else {

		PUINT_8 cp;
		PNDIS_802_11_ASSOCIATION_INFORMATION prNdisAssocInfo;
		UINT_16 u2AvailableAssocRespIEBufLen;

#if 0
		ASSERT(u2FrameBodyLen >= MIN_REASSOC_RESP_BODY_LEN);

		if (u2FrameBodyLen < MIN_REASSOC_RESP_BODY_LEN) {
			return;
		}
#endif
		prNdisAssocInfo = &prGlueInfo->rNdisAssocInfo;

		cp = (PUINT_8) &prAssocInfo->pucIe;

		/* Update the fixed information elements. */
		prNdisAssocInfo->AvailableResponseFixedIEs =
		    NDIS_802_11_AI_RESFI_CAPABILITIES |
		    NDIS_802_11_AI_RESFI_STATUSCODE | NDIS_802_11_AI_RESFI_ASSOCIATIONID;

		kalMemCopy(&prNdisAssocInfo->ResponseFixedIEs.Capabilities, cp, 2);
		cp += 2;

		kalMemCopy(&prNdisAssocInfo->ResponseFixedIEs.StatusCode, cp, 2);
		cp += 2;

		kalMemCopy(&prNdisAssocInfo->ResponseFixedIEs.AssociationId, cp, 2);
		cp += 2;

		u2FrameBodyLen -= 6;

		/* Update the variable length information elements. */
		u2AvailableAssocRespIEBufLen = (sizeof(prGlueInfo->aucNdisAssocInfoIEs) >
						prNdisAssocInfo->RequestIELength) ?
		    (UINT_16) (sizeof(prGlueInfo->aucNdisAssocInfoIEs) -
			       prNdisAssocInfo->RequestIELength) : 0;

		if (u2FrameBodyLen > u2AvailableAssocRespIEBufLen) {
			ASSERT(u2FrameBodyLen <= u2AvailableAssocRespIEBufLen);
			u2FrameBodyLen = u2AvailableAssocRespIEBufLen;
		}

		prNdisAssocInfo->ResponseIELength = u2FrameBodyLen;
		prNdisAssocInfo->OffsetResponseIEs =
		    sizeof(NDIS_802_11_ASSOCIATION_INFORMATION) + prNdisAssocInfo->RequestIELength;

		if (u2FrameBodyLen) {
			kalMemCopy(&prGlueInfo->
				   aucNdisAssocInfoIEs[prNdisAssocInfo->RequestIELength], cp,
				   u2FrameBodyLen);
		}
	}
}
示例#20
0
/*----------------------------------------------------------------------------*/
VOID
nicRxAddP2pDevice (
    IN P_ADAPTER_T  prAdapter,
    IN P_EVENT_P2P_DEV_DISCOVER_RESULT_T prP2pResult,
    IN PUINT_8 pucRxIEBuf,
    IN UINT_16 u2RxIELength
    )
{
    P_P2P_INFO_T prP2pInfo = (P_P2P_INFO_T)NULL;
    P_EVENT_P2P_DEV_DISCOVER_RESULT_T prTargetResult = (P_EVENT_P2P_DEV_DISCOVER_RESULT_T)NULL;
    UINT_32 u4Idx = 0;
    BOOLEAN bUpdate = FALSE;

    PUINT_8 pucIeBuf = (PUINT_8)NULL;
    UINT_16 u2IELength = 0;
    UINT_8  zeroMac[] = { 0x0, 0x0, 0x0, 0x0, 0x0, 0x0};

    ASSERT(prAdapter);

    prP2pInfo = prAdapter->prP2pInfo;

    for (u4Idx = 0; u4Idx < prP2pInfo->u4DeviceNum; u4Idx++) {
        prTargetResult = &prP2pInfo->arP2pDiscoverResult[u4Idx];

        if (EQUAL_MAC_ADDR(prTargetResult->aucDeviceAddr, prP2pResult->aucDeviceAddr)) {
            bUpdate = TRUE;

            /* Backup OLD buffer result. */
            pucIeBuf = prTargetResult->pucIeBuf;
            u2IELength = prTargetResult->u2IELength;

            /* Update Device Info. */
            // zero
            kalMemZero(prTargetResult, sizeof(EVENT_P2P_DEV_DISCOVER_RESULT_T));

            // then buffer
            kalMemCopy(prTargetResult,
                (PVOID)prP2pResult,
                sizeof(EVENT_P2P_DEV_DISCOVER_RESULT_T));

            /* See if new IE length is longer or not. */
            if ((u2RxIELength > u2IELength) && (u2IELength != 0)) {
                /* Buffer is not enough. */
                u2RxIELength = u2IELength;
            }
            else if ((u2IELength == 0) && (u2RxIELength != 0)) {
                /* RX new IE buf. */
                ASSERT(pucIeBuf == NULL);
                pucIeBuf = prP2pInfo->pucCurrIePtr;

                if (((UINT_32)prP2pInfo->pucCurrIePtr + (UINT_32)u2RxIELength) >
                        (UINT_32)&prP2pInfo->aucCommIePool[CFG_MAX_COMMON_IE_BUF_LEN]) {
                    /* Common Buffer is no enough. */
                    u2RxIELength = (UINT_16)((UINT_32)&prP2pInfo->aucCommIePool[CFG_MAX_COMMON_IE_BUF_LEN] - (UINT_32)prP2pInfo->pucCurrIePtr);
                }

                /* Step to next buffer address. */
                prP2pInfo->pucCurrIePtr = (PUINT_8)((UINT_32)prP2pInfo->pucCurrIePtr + (UINT_32)u2RxIELength);
            }

            /* Restore buffer pointer. */
            prTargetResult->pucIeBuf = pucIeBuf;

            if (pucRxIEBuf) {
                /* If new received IE is availabe.
                  * Replace the old one & update new IE length.
                  */
                kalMemCopy(pucIeBuf, pucRxIEBuf, u2RxIELength);
                prTargetResult->u2IELength = u2RxIELength;
            }
            else {
                /* There is no new IE information, keep the old one. */
                prTargetResult->u2IELength = u2IELength;
            }
        }
    }

    if (!bUpdate) {
        /* We would flush the whole scan result after each scan request is issued.
          * If P2P device is too many, it may over the scan list.
          */
        if ((u4Idx < CFG_MAX_NUM_BSS_LIST) && (UNEQUAL_MAC_ADDR(zeroMac, prP2pResult->aucDeviceAddr))) { /* whsu:XXX */
            prTargetResult = &prP2pInfo->arP2pDiscoverResult[u4Idx];

            // zero
            kalMemZero(prTargetResult, sizeof(EVENT_P2P_DEV_DISCOVER_RESULT_T));

            // then buffer
            kalMemCopy(prTargetResult,
                (PVOID)prP2pResult,
                sizeof(EVENT_P2P_DEV_DISCOVER_RESULT_T));

            //printk("DVC FND %d " MACSTR", " MACSTR "\n", prP2pInfo->u4DeviceNum, MAC2STR(prP2pResult->aucDeviceAddr), MAC2STR(prTargetResult->aucDeviceAddr));

            if (u2RxIELength) {
                prTargetResult->pucIeBuf = prP2pInfo->pucCurrIePtr;

                if (((UINT_32)prP2pInfo->pucCurrIePtr + (UINT_32)u2RxIELength) >
                        (UINT_32)&prP2pInfo->aucCommIePool[CFG_MAX_COMMON_IE_BUF_LEN]) {
                    /* Common Buffer is no enough. */
                    u2IELength = (UINT_16)((UINT_32)&prP2pInfo->aucCommIePool[CFG_MAX_COMMON_IE_BUF_LEN] - (UINT_32)prP2pInfo->pucCurrIePtr);
                }
                else {
                    u2IELength = u2RxIELength;
                }

                prP2pInfo->pucCurrIePtr = (PUINT_8)((UINT_32)prP2pInfo->pucCurrIePtr + (UINT_32)u2IELength);

                kalMemCopy((PVOID)prTargetResult->pucIeBuf, (PVOID)pucRxIEBuf, (UINT_32)u2IELength);
                prTargetResult->u2IELength = u2IELength;
            }
            else {
                prTargetResult->pucIeBuf = NULL;
                prTargetResult->u2IELength = 0;
            }

            prP2pInfo->u4DeviceNum++;

        }
        else {
            // TODO: Fixme to replace an old one. (?)
            ASSERT(FALSE);
        }
    }
} /* nicRxAddP2pDevice */
示例#21
0
/*----------------------------------------------------------------------------*/
void
wpi_mic_compose (
    IN BOOLEAN              fgDir,
    IN UINT_8               ucKeyIdx,
    IN UINT_16              u2PayloadLen,
    P_WLAN_MAC_HEADER_QOS_T prMacHdr,
    IN PUINT_8              pucMicHdr,
    IN BOOLEAN              fgQoS
)
{

    P_WAPI_MAC_HEADER_FOR_MIC_T prMicHdr;
    UINT_8                      ucPadLen1;
    UINT_8                      ucPadLen2;
    UINT_8                      ucMacLen;
    UINT_8                      ucQosIdxLen;

    if (fgQoS) {
        ucMacLen = WLAN_MAC_HEADER_QOS_LEN;
        ucQosIdxLen = KEYID_LEN + KEYID_RSV_LEN + PDU_LEN + 2 ;
    }
    else {
        ucMacLen = WLAN_MAC_HEADER_LEN;
        ucQosIdxLen = KEYID_LEN + KEYID_RSV_LEN + PDU_LEN;
    }

    if (fgDir == 1) {
        ucPadLen2 = 16 - ((u2PayloadLen + LLC_LEN) % 16);
        if (ucPadLen2 == 16)
            ucPadLen2 = 0;
    }
    else {

        u2PayloadLen -= (KEYID_LEN + KEYID_RSV_LEN + PN_LEN);

        ucPadLen2 = 16 - ((u2PayloadLen - WPI_MIC_LEN)% 16);
        if (ucPadLen2 == 16)
            ucPadLen2 = 0;
    }

    ucPadLen1 = 16 - ((sizeof(WAPI_MAC_HEADER_FOR_MIC_T) + ucQosIdxLen) % 16);
    if (ucPadLen1 == 16)
        ucPadLen1 = 0;

    prMicHdr = (P_WAPI_MAC_HEADER_FOR_MIC_T)pucMicHdr;

    kalMemCopy((PUINT_8)&prMicHdr->u2FrameCtrl, (PUINT_8)&prMacHdr->u2FrameCtrl, 2);
    prMicHdr->u2FrameCtrl &= ~BITS(4,6);
    prMicHdr->u2FrameCtrl &= ~BITS(11,13);
    prMicHdr->u2FrameCtrl |= BIT(14);

    kalMemCopy(prMicHdr->aucAddr1, prMacHdr->aucAddr1, MAC_ADDR_LEN);
    kalMemCopy(prMicHdr->aucAddr2, prMacHdr->aucAddr2, MAC_ADDR_LEN);
    kalMemCopy((PUINT_8)&prMicHdr->u2SeqCtrl, (PUINT_8)&prMacHdr->u2SeqCtrl, 2);
    prMicHdr->u2SeqCtrl &= ~BITS(4,15);
    kalMemCopy(prMicHdr->aucAddr3, prMacHdr->aucAddr3, MAC_ADDR_LEN);
    kalMemZero((PUINT_8)prMicHdr->aucAddr4, MAC_ADDR_LEN);
    if (fgQoS) {
        kalMemCopy(&pucMicHdr[sizeof(WAPI_MAC_HEADER_FOR_MIC_T)], (PUINT_8)&prMacHdr->u2QosCtrl, 2);
        pucMicHdr[sizeof(WAPI_MAC_HEADER_FOR_MIC_T) + 2 ] = ucKeyIdx;
        pucMicHdr[sizeof(WAPI_MAC_HEADER_FOR_MIC_T) + 2 + KEYID_LEN] = 0;
        if (fgDir == 1) {
            WLAN_SET_FIELD_16_BE(&pucMicHdr[sizeof(WAPI_MAC_HEADER_FOR_MIC_T) + 2 + KEYID_LEN + KEYID_RSV_LEN],
                                 u2PayloadLen + LLC_LEN);
        }
        else {
            WLAN_SET_FIELD_16_BE(&pucMicHdr[sizeof(WAPI_MAC_HEADER_FOR_MIC_T) + 2 + KEYID_LEN + KEYID_RSV_LEN],
                                 u2PayloadLen - WPI_MIC_LEN);
        }
    }
    else {
        pucMicHdr[sizeof(WAPI_MAC_HEADER_FOR_MIC_T)] = ucKeyIdx;
        pucMicHdr[sizeof(WAPI_MAC_HEADER_FOR_MIC_T) + KEYID_LEN] = 0;
        if (fgDir == 1) {
            WLAN_SET_FIELD_16_BE(&pucMicHdr[sizeof(WAPI_MAC_HEADER_FOR_MIC_T) + KEYID_LEN + KEYID_RSV_LEN],
                                 u2PayloadLen + LLC_LEN);
        }
        else {
            WLAN_SET_FIELD_16_BE(&pucMicHdr[sizeof(WAPI_MAC_HEADER_FOR_MIC_T) + KEYID_LEN + KEYID_RSV_LEN],
                                 u2PayloadLen - WPI_MIC_LEN);
        }
    }

    kalMemZero(&pucMicHdr[sizeof(WAPI_MAC_HEADER_FOR_MIC_T) + ucQosIdxLen], ucPadLen1);
    if (fgDir == 1)
        kalMemZero(&pucMicHdr[sizeof(WAPI_MAC_HEADER_FOR_MIC_T) + ucQosIdxLen + ucPadLen1 + u2PayloadLen + LLC_LEN], ucPadLen2);
    else
        kalMemZero(&pucMicHdr[sizeof(WAPI_MAC_HEADER_FOR_MIC_T) + ucQosIdxLen + ucPadLen1 + u2PayloadLen - WPI_MIC_LEN], ucPadLen2);

}
示例#22
0
/*----------------------------------------------------------------------------*/
VOID
rlmDomainSendCmd (
    P_ADAPTER_T     prAdapter,
    BOOLEAN         fgIsOid
    )
{
    P_DOMAIN_INFO_ENTRY     prDomainInfo;
    P_CMD_SET_DOMAIN_INFO_T prCmd;
    WLAN_STATUS             rStatus;
    UINT_8                  i;
    P_DOMAIN_SUBBAND_INFO   prSubBand;

    prDomainInfo = rlmDomainGetDomainInfo(prAdapter);
    ASSERT(prDomainInfo);

    prCmd = cnmMemAlloc(prAdapter, RAM_TYPE_BUF, sizeof(CMD_SET_DOMAIN_INFO_T));
    ASSERT(prCmd);

    /* To do: exception handle */
    if (!prCmd) {
        DBGLOG(RLM, ERROR, ("Domain: no buf to send cmd\n"));
        return;
    }
    kalMemZero(prCmd, sizeof(CMD_SET_DOMAIN_INFO_T));

    prCmd->u2CountryCode = prAdapter->rWifiVar.rConnSettings.u2CountryCode;
    prCmd->u2Reserved = 0;
    prCmd->uc2G4Bandwidth =
            prAdapter->rWifiVar.rConnSettings.uc2G4BandwidthMode;
    prCmd->uc5GBandwidth =
            prAdapter->rWifiVar.rConnSettings.uc5GBandwidthMode;

    for (i = 0; i < 6; i++) {
        prSubBand = &prDomainInfo->rSubBand[i];

        prCmd->rSubBand[i].ucRegClass = prSubBand->ucRegClass;
        prCmd->rSubBand[i].ucBand = prSubBand->ucBand;

        if (prSubBand->ucBand != BAND_NULL && prSubBand->ucBand < BAND_NUM) {
            prCmd->rSubBand[i].ucChannelSpan = prSubBand->ucChannelSpan;
            prCmd->rSubBand[i].ucFirstChannelNum = prSubBand->ucFirstChannelNum;
            prCmd->rSubBand[i].ucNumChannels = prSubBand->ucNumChannels;
        }
    }

    /* Update domain info to chip */
    rStatus = wlanSendSetQueryCmd (
                prAdapter,                  /* prAdapter */
                CMD_ID_SET_DOMAIN_INFO,     /* ucCID */
                TRUE,                       /* fgSetQuery */
                FALSE,                      /* fgNeedResp */
                fgIsOid,                    /* fgIsOid */
                NULL,                       /* pfCmdDoneHandler*/
                NULL,                       /* pfCmdTimeoutHandler */
                sizeof(CMD_SET_DOMAIN_INFO_T),    /* u4SetQueryInfoLen */
                (PUINT_8) prCmd,            /* pucInfoBuffer */
                NULL,                       /* pvSetQueryBuffer */
                0                           /* u4SetQueryBufferLen */
                );

    ASSERT(rStatus == WLAN_STATUS_PENDING);

    cnmMemFree(prAdapter, prCmd);
}
示例#23
0
/*----------------------------------------------------------------------------*/
static WLAN_STATUS
reqExtQueryConfiguration (
    IN  P_GLUE_INFO_T   prGlueInfo,
    OUT PVOID           pvQueryBuffer,
    IN UINT_32          u4QueryBufferLen,
    OUT PUINT_32        pu4QueryInfoLen
    )
{
    P_PARAM_802_11_CONFIG_T prQueryConfig = (P_PARAM_802_11_CONFIG_T)pvQueryBuffer;
    WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS;
    UINT_32 u4QueryInfoLen = 0;

    DEBUGFUNC("wlanoidQueryConfiguration");


    ASSERT(prGlueInfo);
    ASSERT(pu4QueryInfoLen);

    *pu4QueryInfoLen = sizeof(PARAM_802_11_CONFIG_T);
    if (u4QueryBufferLen < sizeof(PARAM_802_11_CONFIG_T)) {
        return WLAN_STATUS_INVALID_LENGTH;
    }

    ASSERT(pvQueryBuffer);

    kalMemZero(prQueryConfig, sizeof(PARAM_802_11_CONFIG_T));

    /* Update the current radio configuration. */
    prQueryConfig->u4Length = sizeof(PARAM_802_11_CONFIG_T);

#if defined(_HIF_SDIO)
    rStatus = sdio_io_ctrl(prGlueInfo,
                            wlanoidSetBeaconInterval,
                            &prQueryConfig->u4BeaconPeriod,
                            sizeof(UINT_32),
                            TRUE,
                            TRUE,
                            &u4QueryInfoLen);
#else
    rStatus = wlanQueryInformation(prGlueInfo->prAdapter,
                                   wlanoidQueryBeaconInterval,
                                   &prQueryConfig->u4BeaconPeriod,
                                   sizeof(UINT_32),
                                   &u4QueryInfoLen);
#endif
    if (rStatus != WLAN_STATUS_SUCCESS) {
        return rStatus;
    }

#if defined(_HIF_SDIO)
    rStatus = sdio_io_ctrl(prGlueInfo,
                            wlanoidQueryAtimWindow,
                            &prQueryConfig->u4ATIMWindow,
                            sizeof(UINT_32),
                            TRUE,
                            TRUE,
                            &u4QueryInfoLen);
#else
    rStatus = wlanQueryInformation(prGlueInfo->prAdapter,
                                   wlanoidQueryAtimWindow,
                                   &prQueryConfig->u4ATIMWindow,
                                   sizeof(UINT_32),
                                   &u4QueryInfoLen);
#endif
    if (rStatus != WLAN_STATUS_SUCCESS) {
        return rStatus;
    }

#if defined(_HIF_SDIO)
    rStatus = sdio_io_ctrl(prGlueInfo,
                            wlanoidQueryFrequency,
                            &prQueryConfig->u4DSConfig,
                            sizeof(UINT_32),
                            TRUE,
                            TRUE,
                            &u4QueryInfoLen);
#else
    rStatus = wlanQueryInformation(prGlueInfo->prAdapter,
                                   wlanoidQueryFrequency,
                                   &prQueryConfig->u4DSConfig,
                                   sizeof(UINT_32),
                                   &u4QueryInfoLen);
#endif
    if (rStatus != WLAN_STATUS_SUCCESS) {
        return rStatus;
    }

    prQueryConfig->rFHConfig.u4Length = sizeof(PARAM_802_11_CONFIG_FH_T);

    return rStatus;

} /* end of reqExtQueryConfiguration() */
int
mtk_cfg80211_get_station(struct wiphy *wiphy,
			 struct net_device *ndev, u8 *mac, struct station_info *sinfo)
{
	P_GLUE_INFO_T prGlueInfo = NULL;
	WLAN_STATUS rStatus;
	PARAM_MAC_ADDRESS arBssid;
	UINT_32 u4BufLen, u4Rate;
	INT_32 i4Rssi;

	prGlueInfo = (P_GLUE_INFO_T) wiphy_priv(wiphy);
	ASSERT(prGlueInfo);

	kalMemZero(arBssid, MAC_ADDR_LEN);
	wlanQueryInformation(prGlueInfo->prAdapter,
			     wlanoidQueryBssid, &arBssid[0], sizeof(arBssid), &u4BufLen);

	/* 1. check BSSID */
	if (UNEQUAL_MAC_ADDR(arBssid, mac)) {
		/* wrong MAC address */
		DBGLOG(REQ, WARN,
		       ("incorrect BSSID: [" MACSTR "] currently connected BSSID[" MACSTR "]\n",
			MAC2STR(mac), MAC2STR(arBssid)));
		return -ENOENT;
	}

	/* 2. fill TX rate */
	rStatus = kalIoctl(prGlueInfo,
			   wlanoidQueryLinkSpeed,
			   &u4Rate, sizeof(u4Rate), TRUE, FALSE, FALSE, FALSE, &u4BufLen);

	if (rStatus != WLAN_STATUS_SUCCESS) {
		DBGLOG(REQ, WARN, ("unable to retrieve link speed\n"));
	} else {
		sinfo->filled |= STATION_INFO_TX_BITRATE;
		sinfo->txrate.legacy = u4Rate / 1000;	/* convert from 100bps to 100kbps */
	}

	if (prGlueInfo->eParamMediaStateIndicated != PARAM_MEDIA_STATE_CONNECTED) {
		/* not connected */
		DBGLOG(REQ, WARN, ("not yet connected\n"));
	} else {
		/* 3. fill RSSI */
		rStatus = kalIoctl(prGlueInfo,
				   wlanoidQueryRssi,
				   &i4Rssi, sizeof(i4Rssi), TRUE, FALSE, FALSE, FALSE, &u4BufLen);

		if (rStatus != WLAN_STATUS_SUCCESS) {
			DBGLOG(REQ, WARN, ("unable to retrieve link speed\n"));
		} else {
			sinfo->filled |= STATION_INFO_SIGNAL;
			/* in the cfg80211 layer, the signal is a signed char variable. */
			if (i4Rssi < -128)
				sinfo->signal = -128;
			else
				sinfo->signal = i4Rssi;	/* dBm */
		}
	}

	sinfo->rx_packets = prGlueInfo->rNetDevStats.rx_packets;
	sinfo->filled |= STATION_INFO_TX_PACKETS;
	sinfo->tx_packets = prGlueInfo->rNetDevStats.tx_packets;
	sinfo->filled |= STATION_INFO_TX_FAILED;

#if 1
	{
		WLAN_STATUS rStatus;
		UINT_32 u4XmitError = 0;
/* UINT_32 u4XmitOk = 0; */
/* UINT_32 u4RecvError = 0; */
/* UINT_32 u4RecvOk = 0; */
/* UINT_32 u4BufLen; */

		/* @FIX ME: need a more clear way to do this */


		rStatus = kalIoctl(prGlueInfo,
				   wlanoidQueryXmitError,
				   &u4XmitError,
				   sizeof(UINT_32), TRUE, TRUE, TRUE, FALSE, &u4BufLen);

		prGlueInfo->rNetDevStats.tx_errors = u4XmitError;

	}
#else
	prGlueInfo->rNetDevStats.tx_errors = 0;
#endif

	sinfo->tx_failed = prGlueInfo->rNetDevStats.tx_errors;

	return 0;
}
示例#25
0
/*----------------------------------------------------------------------------*/
VOID joinComplete(IN P_ADAPTER_T prAdapter)
{
	P_JOIN_INFO_T prJoinInfo;
	P_BSS_DESC_T prBssDesc;
	P_PEER_BSS_INFO_T prPeerBssInfo;
	P_BSS_INFO_T prBssInfo;
	P_CONNECTION_SETTINGS_T prConnSettings;
	P_STA_RECORD_T prStaRec;
	P_TX_CTRL_T prTxCtrl;
#if CFG_SUPPORT_802_11D
	P_IE_COUNTRY_T prIECountry;
#endif

	DEBUGFUNC("joinComplete");


	ASSERT(prAdapter);
	prJoinInfo = &prAdapter->rJoinInfo;
	prBssDesc = prJoinInfo->prBssDesc;
	prPeerBssInfo = &prAdapter->rPeerBssInfo;
	prBssInfo = &prAdapter->rBssInfo;
	prConnSettings = &prAdapter->rConnSettings;
	prTxCtrl = &prAdapter->rTxCtrl;

/* 4 <1> Update Connecting & Connected Flag of BSS_DESC_T. */
	/* Remove previous AP's Connection Flags if have */
	scanRemoveConnectionFlagOfBssDescByBssid(prAdapter, prBssInfo->aucBSSID);

	prBssDesc->fgIsConnected = TRUE;	/* Mask as Connected */

	if (prBssDesc->fgIsHiddenSSID) {
		/* NOTE(Kevin): This is for the case of Passive Scan and the target BSS didn't
		 * broadcast SSID on its Beacon Frame.
		 */
		COPY_SSID(prBssDesc->aucSSID,
			  prBssDesc->ucSSIDLen,
			  prAdapter->rConnSettings.aucSSID, prAdapter->rConnSettings.ucSSIDLen);

		if (prBssDesc->ucSSIDLen)
			prBssDesc->fgIsHiddenSSID = FALSE;

#if DBG
		else
			ASSERT(0);

#endif				/* DBG */

		DBGLOG(JOIN, INFO, ("Hidden SSID! - Update SSID : %s\n", prBssDesc->aucSSID));
	}

/* 4 <2> Update BSS_INFO_T from BSS_DESC_T */
	/* 4 <2.A> PHY Type */
	prBssInfo->ePhyType = prBssDesc->ePhyType;

	/* 4 <2.B> BSS Type */
	prBssInfo->eBSSType = BSS_TYPE_INFRASTRUCTURE;

	/* 4 <2.C> BSSID */
	COPY_MAC_ADDR(prBssInfo->aucBSSID, prBssDesc->aucBSSID);

	DBGLOG(JOIN, INFO, ("JOIN to BSSID: [" MACSTR "]\n", MAC2STR(prBssDesc->aucBSSID)));


	/* 4 <2.D> SSID */
	COPY_SSID(prBssInfo->aucSSID,
		  prBssInfo->ucSSIDLen, prBssDesc->aucSSID, prBssDesc->ucSSIDLen);

	/* 4 <2.E> Channel / Band information. */
	prBssInfo->eBand = prBssDesc->eBand;
	prBssInfo->ucChnl = prBssDesc->ucChannelNum;

	/* 4 <2.F> RSN/WPA information. */
	secFsmRunEventStart(prAdapter);
	prBssInfo->u4RsnSelectedPairwiseCipher = prBssDesc->u4RsnSelectedPairwiseCipher;
	prBssInfo->u4RsnSelectedGroupCipher = prBssDesc->u4RsnSelectedGroupCipher;
	prBssInfo->u4RsnSelectedAKMSuite = prBssDesc->u4RsnSelectedAKMSuite;

	if (secRsnKeyHandshakeEnabled())
		prBssInfo->fgIsWPAorWPA2Enabled = TRUE;
	else
		prBssInfo->fgIsWPAorWPA2Enabled = FALSE;


	/* 4 <2.G> Beacon interval. */
	prBssInfo->u2BeaconInterval = prBssDesc->u2BeaconInterval;

	/* 4 <2.H> DTIM period. */
	prBssInfo->ucDtimPeriod = prBssDesc->ucDTIMPeriod;

	/* 4 <2.I> ERP Information */
	if ((prBssInfo->ePhyType == PHY_TYPE_ERP_INDEX) &&	/* Our BSS's PHY_TYPE is ERP now. */
	    (prBssDesc->fgIsERPPresent)) {

		prBssInfo->fgIsERPPresent = TRUE;
		prBssInfo->ucERP = prBssDesc->ucERP;	/* Save the ERP for later check */
	} else {
		/* Some AP, may send ProbeResp without ERP IE. Thus prBssDesc->fgIsERPPresent is FALSE. */
		prBssInfo->fgIsERPPresent = FALSE;
		prBssInfo->ucERP = 0;
	}

#if CFG_SUPPORT_802_11D
	/* 4 <2.J> Country inforamtion of the associated AP */
	if (prConnSettings->fgMultiDomainCapabilityEnabled) {
		DOMAIN_INFO_ENTRY rDomainInfo;
		if (domainGetDomainInfoByScanResult(prAdapter, &rDomainInfo)) {
			if (prBssDesc->prIECountry) {
				prIECountry = prBssDesc->prIECountry;

				domainParseCountryInfoElem(prIECountry, &prBssInfo->rDomainInfo);

				/* use the domain get from the BSS info */
				prBssInfo->fgIsCountryInfoPresent = TRUE;
				nicSetupOpChnlList(prAdapter, prBssInfo->rDomainInfo.u2CountryCode,
						   FALSE);
			} else {
				/* use the domain get from the scan result */
				prBssInfo->fgIsCountryInfoPresent = TRUE;
				nicSetupOpChnlList(prAdapter, rDomainInfo.u2CountryCode, FALSE);
			}
		}
	}
#endif

	/* 4 <2.K> Signal Power of the associated AP */
	prBssInfo->rRcpi = prBssDesc->rRcpi;
	prBssInfo->rRssi = RCPI_TO_dBm(prBssInfo->rRcpi);
	GET_CURRENT_SYSTIME(&prBssInfo->rRssiLastUpdateTime);

	/* 4 <2.L> Capability Field of the associated AP */
	prBssInfo->u2CapInfo = prBssDesc->u2CapInfo;

	DBGLOG(JOIN, INFO,
	       ("prBssInfo-> fgIsERPPresent = %d, ucERP = %02x, rRcpi = %d, rRssi = %ld\n",
		prBssInfo->fgIsERPPresent, prBssInfo->ucERP, prBssInfo->rRcpi, prBssInfo->rRssi));


/* 4 <3> Update BSS_INFO_T from PEER_BSS_INFO_T & NIC RATE FUNC */
	/* 4 <3.A> Association ID */
	prBssInfo->u2AssocId = prPeerBssInfo->u2AssocId;

	/* 4 <3.B> WMM Infomation */
	if (prAdapter->fgIsEnableWMM && (prPeerBssInfo->rWmmInfo.ucWmmFlag & WMM_FLAG_SUPPORT_WMM)) {

		prBssInfo->fgIsWmmAssoc = TRUE;
		prTxCtrl->rTxQForVoipAccess = TXQ_AC3;

		qosWmmInfoInit(&prBssInfo->rWmmInfo,
			       (prBssInfo->ePhyType == PHY_TYPE_HR_DSSS_INDEX) ? TRUE : FALSE);

		if (prPeerBssInfo->rWmmInfo.ucWmmFlag & WMM_FLAG_AC_PARAM_PRESENT) {
			kalMemCopy(&prBssInfo->rWmmInfo,
				   &prPeerBssInfo->rWmmInfo, sizeof(WMM_INFO_T));
		} else {
			kalMemCopy(&prBssInfo->rWmmInfo,
				   &prPeerBssInfo->rWmmInfo,
				   sizeof(WMM_INFO_T) -
				   sizeof(prPeerBssInfo->rWmmInfo.arWmmAcParams));
		}
	} else {
		prBssInfo->fgIsWmmAssoc = FALSE;
		prTxCtrl->rTxQForVoipAccess = TXQ_AC1;

		kalMemZero(&prBssInfo->rWmmInfo, sizeof(WMM_INFO_T));
	}


	/* 4 <3.C> Operational Rate Set & BSS Basic Rate Set */
	prBssInfo->u2OperationalRateSet = prPeerBssInfo->u2OperationalRateSet;
	prBssInfo->u2BSSBasicRateSet = prPeerBssInfo->u2BSSBasicRateSet;


	/* 4 <3.D> Short Preamble */
	if (prBssInfo->fgIsERPPresent) {

		/* NOTE(Kevin 2007/12/24): Truth Table.
		 * Short Preamble Bit in
		 * <AssocReq><AssocResp w/i ERP><BARKER(Long)>Final Driver Setting(Short)
		 * TRUE      FALSE              FALSE       FALSE(shouldn't have such case, use the AssocResp)
		 * TRUE      FALSE              TRUE        FALSE
		 * FALSE     FALSE              FALSE       FALSE(shouldn't have such case, use the AssocResp)
		 * FALSE     FALSE              TRUE        FALSE
		 * TRUE      TRUE               FALSE       TRUE(follow ERP)
		 * TRUE      TRUE               TRUE        FALSE(follow ERP)
		 * FALSE     TRUE               FALSE       FALSE(shouldn't have such case, and we should set to FALSE)
		 * FALSE     TRUE               TRUE        FALSE(we should set to FALSE)
		 */
		if ((prPeerBssInfo->fgIsShortPreambleAllowed) &&
			((prConnSettings->ePreambleType == PREAMBLE_TYPE_SHORT) ||
			/* Short Preamble Option Enable is TRUE */
								  ((prConnSettings->ePreambleType ==
								    PREAMBLE_TYPE_AUTO)
								   && (prBssDesc->
								       u2CapInfo &
								       CAP_INFO_SHORT_PREAMBLE)))) {

			prBssInfo->fgIsShortPreambleAllowed = TRUE;

			if (prBssInfo->ucERP & ERP_INFO_BARKER_PREAMBLE_MODE)
				prBssInfo->fgUseShortPreamble = FALSE;
			else
				prBssInfo->fgUseShortPreamble = TRUE;

		} else {
			prBssInfo->fgIsShortPreambleAllowed = FALSE;
			prBssInfo->fgUseShortPreamble = FALSE;
		}
	} else {
		/* NOTE(Kevin 2007/12/24): Truth Table.
		 * Short Preamble Bit in
		 * <AssocReq>     <AssocResp w/o ERP>     Final Driver Setting(Short)
		 * TRUE            FALSE                  FALSE
		 * FALSE           FALSE                  FALSE
		 * TRUE            TRUE                   TRUE
		 * FALSE           TRUE(status success)   TRUE
		 * --> Honor the result of prPeerBssInfo.
		 */

		prBssInfo->fgIsShortPreambleAllowed = prBssInfo->fgUseShortPreamble =
		    prPeerBssInfo->fgIsShortPreambleAllowed;
	}

	DBGLOG(JOIN, INFO,
	       ("prBssInfo->fgIsShortPreambleAllowed = %d, prBssInfo->fgUseShortPreamble = %d\n",
		prBssInfo->fgIsShortPreambleAllowed, prBssInfo->fgUseShortPreamble));


	/* 4 <3.E> Short Slot Time */
	prBssInfo->fgUseShortSlotTime = prPeerBssInfo->fgUseShortSlotTime;	/* AP support Short Slot Time */

	DBGLOG(JOIN, INFO, ("prBssInfo->fgUseShortSlotTime = %d\n", prBssInfo->fgUseShortSlotTime));

	nicSetSlotTime(prAdapter,
		       prBssInfo->ePhyType,
		       ((prConnSettings->fgIsShortSlotTimeOptionEnable &&
			 prBssInfo->fgUseShortSlotTime) ? TRUE : FALSE));


	/* 4 <3.F> Update Tx Rate for Control Frame */
	bssUpdateTxRateForControlFrame(prAdapter);


	/* 4 <3.G> Save the available Auth Types during Roaming (Design for Fast BSS Transition). */
	/* if (prAdapter->fgIsEnableRoaming) */ /* NOTE(Kevin): Always prepare info for roaming */
	{

		if (prJoinInfo->ucCurrAuthAlgNum == AUTH_ALGORITHM_NUM_OPEN_SYSTEM)
			prJoinInfo->ucRoamingAuthTypes |= AUTH_TYPE_OPEN_SYSTEM;
		else if (prJoinInfo->ucCurrAuthAlgNum == AUTH_ALGORITHM_NUM_SHARED_KEY)
			prJoinInfo->ucRoamingAuthTypes |= AUTH_TYPE_SHARED_KEY;


		prBssInfo->ucRoamingAuthTypes = prJoinInfo->ucRoamingAuthTypes;


		/* Set the stable time of the associated BSS. We won't do roaming decision
		 * during the stable time.
		 */
		SET_EXPIRATION_TIME(prBssInfo->rRoamingStableExpirationTime,
				    SEC_TO_SYSTIME(ROAMING_STABLE_TIMEOUT_SEC));
	}


	/* 4 <3.H> Update Parameter for TX Fragmentation Threshold */
#if CFG_TX_FRAGMENT
	txFragInfoUpdate(prAdapter);
#endif				/* CFG_TX_FRAGMENT */


/* 4 <4> Update STA_RECORD_T */
	/* Get a Station Record if possible */
	prStaRec = staRecGetStaRecordByAddr(prAdapter, prBssDesc->aucBSSID);

	if (prStaRec) {
		UINT_16 u2OperationalRateSet, u2DesiredRateSet;

		/* 4 <4.A> Desired Rate Set */
		u2OperationalRateSet = (rPhyAttributes[prBssInfo->ePhyType].u2SupportedRateSet &
					prBssInfo->u2OperationalRateSet);

		u2DesiredRateSet = (u2OperationalRateSet & prConnSettings->u2DesiredRateSet);
		if (u2DesiredRateSet) {
			prStaRec->u2DesiredRateSet = u2DesiredRateSet;
		} else {
			/* For Error Handling - The Desired Rate Set is not covered in Operational Rate Set. */
			prStaRec->u2DesiredRateSet = u2OperationalRateSet;
		}

		/* Try to set the best initial rate for this entry */
		if (!rateGetBestInitialRateIndex(prStaRec->u2DesiredRateSet,
						 prStaRec->rRcpi, &prStaRec->ucCurrRate1Index)) {

			if (!rateGetLowestRateIndexFromRateSet(prStaRec->u2DesiredRateSet,
							       &prStaRec->ucCurrRate1Index)) {
				ASSERT(0);
			}
		}

		DBGLOG(JOIN, INFO, ("prStaRec->ucCurrRate1Index = %d\n",
				    prStaRec->ucCurrRate1Index));

		/* 4 <4.B> Preamble Mode */
		prStaRec->fgIsShortPreambleOptionEnable = prBssInfo->fgUseShortPreamble;

		/* 4 <4.C> QoS Flag */
		prStaRec->fgIsQoS = prBssInfo->fgIsWmmAssoc;
	}
#if DBG
	else
		ASSERT(0);

#endif				/* DBG */


/* 4 <5> Update NIC */
	/* 4 <5.A> Update BSSID & Operation Mode */
	nicSetupBSS(prAdapter, prBssInfo);

	/* 4 <5.B> Update WLAN Table. */
	if (nicSetHwBySta(prAdapter, prStaRec) == FALSE)
		ASSERT(FALSE);

	/* 4 <5.C> Update Desired Rate Set for BT. */
#if CFG_TX_FRAGMENT
	if (prConnSettings->fgIsEnableTxAutoFragmentForBT)
		txRateSetInitForBT(prAdapter, prStaRec);

#endif				/* CFG_TX_FRAGMENT */

	/* 4 <5.D> TX AC Parameter and TX/RX Queue Control */
	if (prBssInfo->fgIsWmmAssoc) {

#if CFG_TX_AGGREGATE_HW_FIFO
		nicTxAggregateTXQ(prAdapter, FALSE);
#endif				/* CFG_TX_AGGREGATE_HW_FIFO */

		qosUpdateWMMParametersAndAssignAllowedACI(prAdapter, &prBssInfo->rWmmInfo);
	} else {

#if CFG_TX_AGGREGATE_HW_FIFO
		nicTxAggregateTXQ(prAdapter, TRUE);
#endif				/* CFG_TX_AGGREGATE_HW_FIFO */

		nicTxNonQoSAssignDefaultAdmittedTXQ(prAdapter);

		nicTxNonQoSUpdateTXQParameters(prAdapter, prBssInfo->ePhyType);
	}

#if CFG_TX_STOP_WRITE_TX_FIFO_UNTIL_JOIN
	{
		prTxCtrl->fgBlockTxDuringJoin = FALSE;

#if !CFG_TX_AGGREGATE_HW_FIFO	/* TX FIFO AGGREGATE already do flush once */
		nicTxFlushStopQueues(prAdapter, (UINT_8) TXQ_DATA_MASK, (UINT_8) NULL);
#endif				/* CFG_TX_AGGREGATE_HW_FIFO */

		nicTxRetransmitOfSendWaitQue(prAdapter);

		if (prTxCtrl->fgIsPacketInOsSendQueue)
			nicTxRetransmitOfOsSendQue(prAdapter);

#if CFG_SDIO_TX_ENHANCE
		halTxLeftClusteredMpdu(prAdapter);
#endif				/* CFG_SDIO_TX_ENHANCE */

	}
#endif				/* CFG_TX_STOP_WRITE_TX_FIFO_UNTIL_JOIN */


/* 4 <6> Setup CONNECTION flag. */
	prAdapter->eConnectionState = MEDIA_STATE_CONNECTED;
	prAdapter->eConnectionStateIndicated = MEDIA_STATE_CONNECTED;

	if (prJoinInfo->fgIsReAssoc)
		prAdapter->fgBypassPortCtrlForRoaming = TRUE;
	else
		prAdapter->fgBypassPortCtrlForRoaming = FALSE;

	kalIndicateStatusAndComplete(prAdapter->prGlueInfo,
				     WLAN_STATUS_MEDIA_CONNECT, (PVOID) NULL, 0);

	return;
}				/* end of joinComplete() */