/*************************************************************************** 
 * RT2x00 SourceForge Project - http://rt2x00.sourceforge.net              * 
 *                                                                         * 
 *   This program is free software; you can redistribute it and/or modify  * 
 *   it under the terms of the GNU General Public License as published by  * 
 *   the Free Software Foundation; either version 2 of the License, or     * 
 *   (at your option) any later version.                                   * 
 *                                                                         * 
 *   This program is distributed in the hope that it will be useful,       * 
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        * 
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         * 
 *   GNU General Public License for more details.                          * 
 *                                                                         * 
 *   You should have received a copy of the GNU General Public License     * 
 *   along with this program; if not, write to the                         * 
 *   Free Software Foundation, Inc.,                                       * 
 *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             * 
 *                                                                         * 
 *   Licensed under the GNU GPL                                            * 
 *   Original code supplied under license from RaLink Inc, 2004.           * 
 ***************************************************************************/

/*************************************************************************
 *
 *	Module Name:	rtusb_info.c
 *
 *	Abstract:	
 *
 *	Revision History:
 *	Who		When		What
 *	--------	----------	-------------------------
 *	Name		Date		Modification logs
 *	Jan Lee		2005-06-01	Release
 *	RobinC		02-06-2005	RFMON Mode added
 *	RobinC		02-06-2005	Fix frequency reporting
 *      MarkW           13-07-2005      Fix ESSID reporting
 *************************************************************************/

#include "rt_config.h"
#include <net/iw_handler.h>


#define NR_WEP_KEYS 4
#define WEP_SMALL_KEY_LEN (40/8)
#define WEP_LARGE_KEY_LEN (104/8)


#define     MAP_CHANNEL_ID_TO_KHZ(ch, khz)  {               \
                switch (ch)                                 \
                {                                           \
                    case 1:     khz = 2412000;   break;     \
                    case 2:     khz = 2417000;   break;     \
                    case 3:     khz = 2422000;   break;     \
                    case 4:     khz = 2427000;   break;     \
                    case 5:     khz = 2432000;   break;     \
                    case 6:     khz = 2437000;   break;     \
                    case 7:     khz = 2442000;   break;     \
                    case 8:     khz = 2447000;   break;     \
                    case 9:     khz = 2452000;   break;     \
                    case 10:    khz = 2457000;   break;     \
                    case 11:    khz = 2462000;   break;     \
                    case 12:    khz = 2467000;   break;     \
                    case 13:    khz = 2472000;   break;     \
                    case 14:    khz = 2484000;   break;     \
                    case 36:  /* UNII */  khz = 5180000;   break;     \
                    case 40:  /* UNII */  khz = 5200000;   break;     \
                    case 44:  /* UNII */  khz = 5220000;   break;     \
                    case 48:  /* UNII */  khz = 5240000;   break;     \
                    case 52:  /* UNII */  khz = 5260000;   break;     \
                    case 56:  /* UNII */  khz = 5280000;   break;     \
                    case 60:  /* UNII */  khz = 5300000;   break;     \
                    case 64:  /* UNII */  khz = 5320000;   break;     \
                    case 149: /* UNII */  khz = 5745000;   break;     \
                    case 153: /* UNII */  khz = 5765000;   break;     \
                    case 157: /* UNII */  khz = 5785000;   break;     \
                    case 161: /* UNII */  khz = 5805000;   break;     \
                    case 100: /* HiperLAN2 */  khz = 5500000;   break;     \
                    case 104: /* HiperLAN2 */  khz = 5520000;   break;     \
                    case 108: /* HiperLAN2 */  khz = 5540000;   break;     \
                    case 112: /* HiperLAN2 */  khz = 5560000;   break;     \
                    case 116: /* HiperLAN2 */  khz = 5580000;   break;     \
                    case 120: /* HiperLAN2 */  khz = 5600000;   break;     \
                    case 124: /* HiperLAN2 */  khz = 5620000;   break;     \
                    case 128: /* HiperLAN2 */  khz = 5640000;   break;     \
                    case 132: /* HiperLAN2 */  khz = 5660000;   break;     \
                    case 136: /* HiperLAN2 */  khz = 5680000;   break;     \
                    case 140: /* HiperLAN2 */  khz = 5700000;   break;     \
                    case 34:  /* Japan MMAC */   khz = 5170000;   break;   \
                    case 38:  /* Japan MMAC */   khz = 5190000;   break;   \
                    case 42:  /* Japan MMAC */   khz = 5210000;   break;   \
                    case 46:  /* Japan MMAC */   khz = 5230000;   break;   \
                    default:    khz = 2412000;   break;     \
                }                                           \
            }

#define 	MAP_KHZ_TO_CHANNEL_ID(khz, ch)	{				\
				switch (khz)								\
				{											\
					case 2412000:	 ch = 1;	 break; 	\
					case 2417000:	 ch = 2;	 break; 	\
					case 2422000:	 ch = 3;	 break; 	\
					case 2427000:	 ch = 4;	 break; 	\
					case 2432000:	 ch = 5;	 break; 	\
					case 2437000:	 ch = 6;	 break; 	\
					case 2442000:	 ch = 7;	 break; 	\
					case 2447000:	 ch = 8;	 break; 	\
					case 2452000:	 ch = 9;	 break; 	\
					case 2457000:	 ch = 10;	 break; 	\
					case 2462000:	 ch = 11;	 break; 	\
					case 2467000:	 ch = 12;	 break; 	\
					case 2472000:	 ch = 13;	 break; 	\
					case 2484000:	 ch = 14;	 break; 	\
					case 5180000:	 ch = 36;  /* UNII */  break;	  \
					case 5200000:	 ch = 40;  /* UNII */  break;	  \
					case 5220000:	 ch = 44;  /* UNII */  break;	  \
					case 5240000:	 ch = 48;  /* UNII */  break;	  \
					case 5260000:	 ch = 52;  /* UNII */  break;	  \
					case 5280000:	 ch = 56;  /* UNII */  break;	  \
					case 5300000:	 ch = 60;  /* UNII */  break;	  \
					case 5320000:	 ch = 64;  /* UNII */  break;	  \
					case 5745000:	 ch = 149; /* UNII */  break;	  \
					case 5765000:	 ch = 153; /* UNII */  break;	  \
					case 5785000:	 ch = 157; /* UNII */  break;	  \
					case 5805000:	 ch = 161; /* UNII */  break;	  \
					case 5500000:	 ch = 100; /* HiperLAN2 */	break;	   \
					case 5520000:	 ch = 104; /* HiperLAN2 */	break;	   \
					case 5540000:	 ch = 108; /* HiperLAN2 */	break;	   \
					case 5560000:	 ch = 112; /* HiperLAN2 */	break;	   \
					case 5580000:	 ch = 116; /* HiperLAN2 */	break;	   \
					case 5600000:	 ch = 120; /* HiperLAN2 */	break;	   \
					case 5620000:	 ch = 124; /* HiperLAN2 */	break;	   \
					case 5640000:	 ch = 128; /* HiperLAN2 */	break;	   \
					case 5660000:	 ch = 132; /* HiperLAN2 */	break;	   \
					case 5680000:	 ch = 136; /* HiperLAN2 */	break;	   \
					case 5700000:	 ch = 140; /* HiperLAN2 */	break;	   \
					case 5170000:	 ch = 34;  /* Japan MMAC */   break;   \
					case 5190000:	 ch = 38;  /* Japan MMAC */   break;   \
					case 5210000:	 ch = 42;  /* Japan MMAC */   break;   \
					case 5230000:	 ch = 46;  /* Japan MMAC */   break;   \
					default:		 ch = 1;	 break; 	\
				}											\
			}


#if 0

static struct {
	char *name;
	int (*set_proc)(PRT2570ADAPTER pAdapter, PUCHAR arg);
} *PRTMP_PRIVATE_SET_PROC, RTMP_PRIVATE_SUPPORT_PROC[] = {
	{"CountryRegion", Set_CountryRegion_Proc },
	{"SSID", Set_SSID_Proc},
	{"WirelessMode", Set_WirelessMode_Proc},
	{"TxRate", Set_TxRate_Proc},
	{"Channel", Set_Channel_Proc},
	{"BGProtection", Set_BGProtection_Proc},
	{"TxPreamble", Set_TxPreamble_Proc},
	{"RTSThreshold", Set_RTSThreshold_Proc},
	{"FragThreshold", Set_FragThreshold_Proc},
	{"TxBurst", Set_TxBurst_Proc},
	{"TurboRate", Set_TurboRate_Proc},
	{"AuthMode", Set_AuthMode_Proc},
	{"EncrypType", Set_EncrypType_Proc},
	{"DefaultKeyID", Set_DefaultKeyID_Proc},
	{"Key1", Set_Key1_Proc},
	{"Key2", Set_Key2_Proc},
	{"Key3", Set_Key3_Proc},
	{"Key4", Set_Key4_Proc},
	{"WPAPSK", Set_WPAPSK_Proc},
	{"bb", Set_R17_Proc},
	{"rr", Read_R17_Proc},
	{NULL,}
};

#endif

int
rtusb_ioctl_giwname(struct net_device *dev,
		   struct iw_request_info *info,
		   char *name, char *extra)
{
	strncpy(name, "RT2500USB WLAN", IFNAMSIZ);
	return 0;
}

int rtusb_ioctl_siwfreq(struct net_device *dev,
			struct iw_request_info *info,
			struct iw_freq *freq, char *extra)
{
	PRT2570ADAPTER pAdapter = (PRT2570ADAPTER) dev->priv;
	int 	chan = -1;

	if (freq->e > 1)
		return -EINVAL;

	if((freq->e == 0) && (freq->m <= 1000))
		chan = freq->m;	// Setting by channel number 
	else
		MAP_KHZ_TO_CHANNEL_ID( (freq->m /100) , chan); // Setting by frequency - search the table , like 2.412G, 2.422G, 
	pAdapter->PortCfg.IbssConfig.Channel = chan;
	DBGPRINT(RT_DEBUG_ERROR, "<==SIOCSIWFREQ[cmd=0x%x] (Channel=%d)\n", SIOCSIWFREQ, pAdapter->PortCfg.IbssConfig.Channel);

	// CD: setting the channel in Monitor mode is unrelated to RFMONTx

	if (pAdapter->PortCfg.BssType == BSS_MONITOR)
	{
		pAdapter->PortCfg.Channel = pAdapter->PortCfg.IbssConfig.Channel;
		AsicSwitchChannel(pAdapter, pAdapter->PortCfg.Channel);
		AsicLockChannel(pAdapter, pAdapter->PortCfg.Channel);
	}

	return 0;
}
int rtusb_ioctl_giwfreq(struct net_device *dev,
		   struct iw_request_info *info,
		   struct iw_freq *freq, char *extra)
{
	PRT2570ADAPTER pAdapter = (PRT2570ADAPTER) dev->priv;
	DBGPRINT(RT_DEBUG_TRACE,"==>IOCTL::rtusb_ioctl_giwfreq  %d\n",pAdapter->PortCfg.Channel);
	
	if (INFRA_ON(pAdapter) || ADHOC_ON(pAdapter))
	{	 
	    MAP_CHANNEL_ID_TO_KHZ(pAdapter->PortCfg.Channel, freq->m);
	}
	else
	{
		 MAP_CHANNEL_ID_TO_KHZ(pAdapter->PortCfg.IbssConfig.Channel, freq->m );
	}
	
	freq->e = 3;
	freq->i = 0;
	return 0;
}

int rtusb_ioctl_siwmode(struct net_device *dev,
		   struct iw_request_info *info,
		   __u32 *mode, char *extra)
{
	PRT2570ADAPTER pAdapter = (PRT2570ADAPTER) dev->priv;

	switch (*mode)
	{
		case IW_MODE_ADHOC:
			if (pAdapter->PortCfg.BssType != BSS_INDEP)
			{
				// Config has changed
				if INFRA_ON(pAdapter)
				{
					RTUSBEnqueueInternalCmd(pAdapter, RT_OID_LINK_DOWN);
					// First cancel linkdown timer
					DBGPRINT(RT_DEBUG_TRACE, "NDIS_STATUS_MEDIA_DISCONNECT Event BB!\n");							
				}
				pAdapter->bConfigChanged = TRUE;
			}
			pAdapter->net->type = 1;
			pAdapter->PortCfg.BssType = BSS_INDEP;
			DBGPRINT(RT_DEBUG_TRACE, "ioctl::SIOCSIWMODE (AD-HOC)\n");
			break;
		case IW_MODE_INFRA:
			if (pAdapter->PortCfg.BssType != BSS_INFRA)
			{
				// Config has changed
				if (pAdapter->PortCfg.BssType != BSS_INFRA)
				{
					// Config has changed
					// pAdapter->bConfigChanged = TRUE;
					if ADHOC_ON(pAdapter)
						RTUSBEnqueueInternalCmd(pAdapter, RT_OID_LINK_DOWN);
				}
				pAdapter->bConfigChanged = TRUE;
			}
		        pAdapter->net->type = 1;
			pAdapter->PortCfg.BssType = BSS_INFRA;
			DBGPRINT(RT_DEBUG_TRACE, "ioctl::SIOCSIWMODE (INFRA)\n");
			break;
		case IW_MODE_MONITOR:
			pAdapter->PortCfg.BssType=BSS_MONITOR;
			RTUSBEnqueueInternalCmd(pAdapter, RT_OID_LINK_DOWN);
			pAdapter->bConfigChanged = TRUE;
			if (pAdapter->PortCfg.MallowRFMONTx == TRUE)
				pAdapter->net->type = 801; // ARPHRD_IEEE80211
			else
				pAdapter->net->type = 802; // ARPHRD_IEEE80211_PRISM
			RTUSBWriteMACRegister(pAdapter, TXRX_CSR2, 0x4e);
			break;	
		default:
			DBGPRINT(RT_DEBUG_TRACE, "ioctl::SIOCSIWMODE (unknown)\n");
			return -EINVAL;
	}
	
	// Reset Ralink supplicant to not use, it will be set to start when UI set PMK key
	pAdapter->PortCfg.WpaState = SS_NOTUSE;

	return 0;
}

int rtusb_ioctl_giwmode(struct net_device *dev,
		   struct iw_request_info *info,
		   __u32 *mode, char *extra)
{
	PRT2570ADAPTER pAdapter = (PRT2570ADAPTER) dev->priv;
	if (pAdapter->PortCfg.BssType == BSS_MONITOR)
		*mode = IW_MODE_MONITOR;
	else
	{
		if (ADHOC_ON(pAdapter))
			*mode = IW_MODE_ADHOC;
		else
			*mode = IW_MODE_INFRA;
	}
	DBGPRINT(RT_DEBUG_TEMP,"--->rtusb_ioctl_giwmode\n");		
	return 0;
}

int rtusb_ioctl_siwsens(struct net_device *dev,
		   struct iw_request_info *info,
		   char *name, char *extra)
{
	return 0;
}

int rtusb_ioctl_giwsens(struct net_device *dev,
		   struct iw_request_info *info,
		   char *name, char *extra)
{
	return 0;
}
/*
This is required for LinEX2004/kernel2.6.7 to provide iwlist scanning function
*/
int rtusb_ioctl_giwrange(struct net_device *dev,
		   struct iw_request_info *info,
		   struct iw_point *data, char *extra)
{
	PRT2570ADAPTER pAdapter = (PRT2570ADAPTER) dev->priv;
	struct iw_range *range = (struct iw_range *) extra;
	u16 val;
	int i;
	ULONG	m;
	
	data->length = sizeof(struct iw_range);
	memset(range, 0, sizeof(struct iw_range));

	range->txpower_capa = IW_TXPOW_DBM;

	if (INFRA_ON(pAdapter)||ADHOC_ON(pAdapter))
	{
		range->min_pmp = 1 * 1024;
		range->max_pmp = 65535 * 1024;
		range->min_pmt = 1 * 1024;
		range->max_pmt = 1000 * 1024;
		range->pmp_flags = IW_POWER_PERIOD;
		range->pmt_flags = IW_POWER_TIMEOUT;
		range->pm_capa = IW_POWER_PERIOD | IW_POWER_TIMEOUT |
			IW_POWER_UNICAST_R | IW_POWER_ALL_R;
	}
	

	range->we_version_compiled = WIRELESS_EXT;
	range->we_version_source = 16;

	range->retry_capa = IW_RETRY_LIMIT;
	range->retry_flags = IW_RETRY_LIMIT;
	range->min_retry = 0;
	range->max_retry = 255;

	range->num_channels =  pAdapter->PortCfg.ChannelListNum;

	val = 0;
	for (i = 0; i < pAdapter->PortCfg.SupportedRatesLen; i++) {
			range->freq[val].i =(pAdapter->PortCfg.SupportedRates[i] & 0x7f)/2;
			range->freq[val].m = (pAdapter->PortCfg.SupportedRates[i] & 0x7f)/2 * 100000;
			range->freq[val].e = 1;
			val++;
		if (val == IW_MAX_FREQUENCIES)
			break;
	}
	
	range->num_frequency = 0;
	for (i = 1; i <= range->num_channels; i++)
	{
		range->freq[range->num_frequency].i = i;
		MAP_CHANNEL_ID_TO_KHZ(i, m);

		range->freq[range->num_frequency].m = m;
		range->freq[range->num_frequency].e = 3;
		if (++range->num_frequency == IW_MAX_FREQUENCIES)
		break;
	}

	range->max_qual.qual = 100; /* percentage */ 
	range->max_qual.level = 0; /* dB */
	range->max_qual.noise = 0; /* dB */

	/* What would be suitable values for "average/typical" qual? */
	range->avg_qual.qual = 20;
	range->avg_qual.level = -60;
	range->avg_qual.noise = -95;
	range->sensitivity = 3;

	range->max_encoding_tokens = NR_WEP_KEYS;
	range->num_encoding_sizes = 2;
	range->encoding_size[0] = 5;
	range->encoding_size[1] = 13;

#if 0
	over2 = 0;
	len = prism2_get_datarates(dev, rates);
	range->num_bitrates = 0;
	for (i = 0; i < len; i++) {
		if (range->num_bitrates < IW_MAX_BITRATES) {
			range->bitrate[range->num_bitrates] =
				rates[i] * 500000;
			range->num_bitrates++;
		}
		if (rates[i] == 0x0b || rates[i] == 0x16)
			over2 = 1;
	}
	/* estimated maximum TCP throughput values (bps) */
	range->throughput = over2 ? 5500000 : 1500000;
    #endif
	range->min_rts = 0;
	range->max_rts = 2347;
	range->min_frag = 256;
	range->max_frag = 2346;

	return 0;
}

int rtusb_ioctl_giwap(struct net_device *dev,
		      struct iw_request_info *info,
		      struct sockaddr *ap_addr, char *extra)
{

	PRT2570ADAPTER pAdapter = (PRT2570ADAPTER) dev->priv;

	if (INFRA_ON(pAdapter) || ADHOC_ON(pAdapter))
	{
		ap_addr->sa_family = ARPHRD_ETHER;
		memcpy(ap_addr->sa_data, &pAdapter->PortCfg.Bssid, ETH_ALEN);
	}
	else
	{
		DBGPRINT(RT_DEBUG_TRACE, "ioctl::SIOCGIWAP(=EMPTY)\n");
		return -ENOTCONN;
	}

	return 0;
}

/*
 * Units are in db above the noise floor. That means the
 * rssi values reported in the tx/rx descriptors in the
 * driver are the SNR expressed in db.
 *
 * If you assume that the noise floor is -95, which is an
 * excellent assumption 99.5 % of the time, then you can
 * derive the absolute signal level (i.e. -95 + rssi). 
 * There are some other slight factors to take into account
 * depending on whether the rssi measurement is from 11b,
 * 11g, or 11a.   These differences are at most 2db and
 * can be documented.
 *
 * NB: various calculations are based on the orinoco/wavelan
 *     drivers for compatibility
 */
static void
set_quality(struct iw_quality *iq, u_int rssi)
{
	iq->qual = rssi;
	/* NB: max is 94 because noise is hardcoded to 161 */
	if (iq->qual > 94)
		iq->qual = 94;

	iq->noise = RSSI_TO_DBM_OFFSET;		/* -95dBm */
	iq->level = iq->noise + iq->qual;
	iq->updated = 7;
}
int rtusb_ioctl_iwaplist(struct net_device *dev,
			struct iw_request_info *info,
			struct iw_point *data, char *extra)
{

	PRT2570ADAPTER pAdapter = (PRT2570ADAPTER) dev->priv;
	struct sockaddr addr[IW_MAX_AP];
	struct iw_quality qual[IW_MAX_AP];
	int i;
	
	for (i = 0; i <IW_MAX_AP ; i++)
	{
		if (i >=  pAdapter->PortCfg.BssTab.BssNr)
			break;
		addr[i].sa_family = ARPHRD_ETHER;
			memcpy(addr[i].sa_data, &pAdapter->PortCfg.BssTab.BssEntry[i].Bssid, MAC_ADDR_LEN);
		set_quality(&qual[i], pAdapter->PortCfg.BssTab.BssEntry[i].Rssi);
	}
	data->length = i;
	memcpy(extra, &addr, i*sizeof(addr[0]));
	data->flags = 1;		/* signal quality present (sort of) */
	memcpy(extra + i*sizeof(addr[0]), &qual, i*sizeof(qual[i]));

	return 0;
}
#ifdef SIOCGIWSCAN

int rtusb_ioctl_siwscan(struct net_device *dev,
			struct iw_request_info *info,
			struct iw_point *data, char *extra)
{
	PRT2570ADAPTER pAdapter = (PRT2570ADAPTER) dev->priv;
	int Status = STATUS_SUCCESS;

    	do{
		if (RTMP_TEST_FLAG(pAdapter, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS))
			return 0;
		if (RTMP_TEST_FLAG(pAdapter, fRTMP_ADAPTER_RADIO_OFF))
			return 0;

#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 5, 0)
		if ((pAdapter->Mlme.CntlMachine.CurrState != CNTL_IDLE) && (pAdapter->MLMEThr_pid > 0))
#else
		if ((pAdapter->Mlme.CntlMachine.CurrState != CNTL_IDLE) && (pAdapter->MLMEThr_active))
#endif
		{
			DBGPRINT(RT_DEBUG_ERROR, "!!! MLME busy, reset MLME state machine !!!\n");
			MlmeRestartStateMachine(pAdapter);
			MlmePostRestartStateMachine(pAdapter);
			return (RTUSBEnqueueCmdFromNdis(pAdapter, OID_802_11_BSSID_LIST_SCAN, TRUE, NULL, 0));
			
		}
		 
		pAdapter->Mlme.CntlAux.CurrReqIsFromNdis = FALSE;
		// Reset Missed scan number
		pAdapter->PortCfg.IgnoredScanNumber = 0;

		MlmeEnqueue(pAdapter, 
				MLME_CNTL_STATE_MACHINE, 
				OID_802_11_BSSID_LIST_SCAN, 
				0, 
				NULL);
		RTUSBUp(pAdapter, (&(pAdapter->mlme_semaphore)));

		Status = NDIS_STATUS_SUCCESS;
	}while(0);
	return 0;
}
int
rtusb_ioctl_giwscan(struct net_device *dev,
			struct iw_request_info *info,
			struct iw_point *data, char *extra)
{

	PRT2570ADAPTER pAdapter = (PRT2570ADAPTER) dev->priv;
	int i=2, j;
	char *current_ev = extra;
	char *end_buf = extra + IW_SCAN_MAX_DATA;
	char *current_val;
	struct iw_event iwe;

        if (RTMP_TEST_FLAG(pAdapter, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS)){
                /*
                 * Still scanning, indicate the caller should try again.
                 */
                return -EAGAIN;
        }

	for (i = 0; i < pAdapter->PortCfg.BssTab.BssNr; i++) 
	{
		if (current_ev >= end_buf)
			break;

		//================================
		memset(&iwe, 0, sizeof(iwe));
		iwe.cmd = SIOCGIWAP;
		iwe.u.ap_addr.sa_family = ARPHRD_ETHER;
				memcpy(iwe.u.ap_addr.sa_data, &pAdapter->PortCfg.BssTab.BssEntry[i].Bssid, ETH_ALEN);
			current_ev = iwe_stream_add_event(current_ev,end_buf, &iwe, IW_EV_ADDR_LEN);
		//================================
		memset(&iwe, 0, sizeof(iwe));
		iwe.cmd = SIOCGIWMODE;
		if (pAdapter->PortCfg.BssTab.BssEntry[i].BssType == Ndis802_11IBSS)
		{
			iwe.u.mode = IW_MODE_ADHOC;
		}
		else if (pAdapter->PortCfg.BssTab.BssEntry[i].BssType == Ndis802_11Infrastructure)
		{
			iwe.u.mode = IW_MODE_INFRA;
		}
		else
		{
			iwe.u.mode = IW_MODE_AUTO;
		}

		iwe.len = IW_EV_UINT_LEN;
		current_ev = iwe_stream_add_event(current_ev, end_buf, &iwe,  IW_EV_UINT_LEN);
		//================================
		memset(&iwe, 0, sizeof(iwe));
		iwe.cmd = SIOCGIWESSID;
		iwe.u.data.length = pAdapter->PortCfg.BssTab.BssEntry[i].SsidLen;
		iwe.u.data.flags = 1;
		current_ev = iwe_stream_add_point(current_ev,end_buf, &iwe, pAdapter->PortCfg.BssTab.BssEntry[i].Ssid);
		//================================
		memset(&iwe, 0, sizeof(iwe));
		iwe.cmd = SIOCGIWENCODE;
		if (CAP_IS_PRIVACY_ON (pAdapter->PortCfg.BssTab.BssEntry[i].CapabilityInfo ))
			iwe.u.data.flags =IW_ENCODE_ENABLED | IW_ENCODE_NOKEY;
		else
			iwe.u.data.flags = IW_ENCODE_DISABLED;
		current_ev = iwe_stream_add_point(current_ev, end_buf,&iwe,  pAdapter->PortCfg.BssTab.BssEntry[i].Ssid);

		//================================
		memset(&iwe, 0, sizeof(iwe));
		iwe.cmd = SIOCGIWRATE;
		current_val = current_ev + IW_EV_LCP_LEN;
		//for (j = 0; j < pAdapter->PortCfg.BssTab.BssEntry[i].RatesLen;j++)
		for (j = 0; j < 1;j++)
		{
			iwe.u.bitrate.value = RateIdToMbps[pAdapter->PortCfg.BssTab.BssEntry[i].Rates[i]/2] * 1000000;
			iwe.u.bitrate.disabled = 0;
			current_val = iwe_stream_add_value(current_ev,
				current_val, end_buf, &iwe,
				IW_EV_PARAM_LEN);
		}
		//================================
		memset(&iwe, 0, sizeof(iwe));
		iwe.cmd = SIOCGIWFREQ;
		if (INFRA_ON(pAdapter) || ADHOC_ON(pAdapter))
			iwe.u.freq.m = pAdapter->PortCfg.BssTab.BssEntry[i].Channel;
		else
			iwe.u.freq.m = pAdapter->PortCfg.BssTab.BssEntry[i].Channel;
		iwe.u.freq.e = 0;
		iwe.u.freq.i = 0;
		current_ev = iwe_stream_add_event(current_ev,end_buf, &iwe, IW_EV_FREQ_LEN);
		//================================
		memset(&iwe, 0, sizeof(iwe));

	}
	data->length = current_ev - extra;
	DBGPRINT(RT_DEBUG_TRACE,"rtusb_ioctl_giwscan. %d BSS returned\n",pAdapter->PortCfg.BssTab.BssNr);						
	return 0;
}
#endif
int rtusb_ioctl_siwessid(struct net_device *dev,
			 struct iw_request_info *info,
			 struct iw_point *data, char *essid)
{
	PRT2570ADAPTER pAdapter = (PRT2570ADAPTER) dev->priv;
	NDIS_802_11_SSID					Ssid, *pSsid=NULL;

	memset(&Ssid, 0x00, sizeof(NDIS_802_11_SSID));
	if (data->flags)
	{
		if (data->length > IW_ESSID_MAX_SIZE)
		{
			return -E2BIG;
		}

		memcpy(Ssid.Ssid, essid, (data->length - 1));
		Ssid.SsidLength = data->length - 1;	//minus null character.
		memcpy(pAdapter->PortCfg.Ssid, essid, (data->length - 1));
		pAdapter->PortCfg.SsidLen = data->length - 1;
	}
	else
		Ssid.SsidLength = 0;  // ANY ssid 

	pSsid = &Ssid;

	 // tell CNTL state machine to call NdisMSetInformationComplete() after completing
	// this request, because this request is initiated by NDIS.
	pAdapter->Mlme.CntlAux.CurrReqIsFromNdis = FALSE; 
	DBGPRINT(RT_DEBUG_TRACE,"--->Ssid.SsidLength = %d, %s\n",Ssid.SsidLength, Ssid.Ssid);		
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 5, 0)
	if (pAdapter->MLMEThr_pid > 0)
#else
	if (!IS_ERR(pAdapter->MLMEThr))
#endif
		MlmeEnqueue(pAdapter, 
				MLME_CNTL_STATE_MACHINE, 
				OID_802_11_SSID,
				sizeof(NDIS_802_11_SSID),
				(VOID *)pSsid
				);

	RTUSBUp(pAdapter, (&(pAdapter->mlme_semaphore)));
	return 0;
}

int rtusb_ioctl_giwessid(struct net_device *dev,
			 struct iw_request_info *info,
			 struct iw_point *data, char *essid)
{
	PRT2570ADAPTER pAdapter = (PRT2570ADAPTER) dev->priv;

	data->flags = 1;		/* active */
	DBGPRINT(RT_DEBUG_TRACE,"MediaState is connected\n");
	data->length = pAdapter->PortCfg.SsidLen;
	memcpy(essid, pAdapter->PortCfg.Ssid, pAdapter->PortCfg.SsidLen);
	pAdapter->PortCfg.Ssid[pAdapter->PortCfg.SsidLen] = '\0';
	DBGPRINT(RT_DEBUG_TRACE,"pAdapter->PortCfg.Ssid=%s , Ssidlen = %d\n",pAdapter->PortCfg.Ssid, pAdapter->PortCfg.SsidLen);

	DBGPRINT(RT_DEBUG_TRACE, "<==rtusb_ioctl_giwessid:: (Len=%d, ssid=%s...)\n", pAdapter->PortCfg.SsidLen, pAdapter->PortCfg.Ssid);

	return 0;

}

int rtusb_ioctl_siwnickn(struct net_device *dev,
			 struct iw_request_info *info,
			 struct iw_point *data, char *nickname)
{
	PRT2570ADAPTER pAdapter = (PRT2570ADAPTER) dev->priv;

	if (data->length > IEEE80211_NWID_LEN)
		return -EINVAL;

	memset(pAdapter->nickn, 0, IEEE80211_NWID_LEN);
	memcpy(pAdapter->nickn, nickname, data->length);
	pAdapter->nicknamelen = data->length;


	return 0;
}

int rtusb_ioctl_giwnickn(struct net_device *dev,
			 struct iw_request_info *info,
			 struct iw_point *data, char *nickname)
{
	PRT2570ADAPTER pAdapter = (PRT2570ADAPTER) dev->priv;

	if (data->length > pAdapter->nicknamelen + 1)
		data->length = pAdapter->nicknamelen + 1;
	if (data->length > 0) {
		memcpy(nickname, pAdapter->nickn, data->length-1);
		nickname[data->length-1] = '\0';
	}
	return 0;
}


int rtusb_ioctl_siwrts(struct net_device *dev,
		       struct iw_request_info *info,
		       struct iw_param *rts, char *extra)
{
	PRT2570ADAPTER pAdapter = (PRT2570ADAPTER) dev->priv;
	u16 val;

	if (rts->disabled)
		val = MAX_RTS_THRESHOLD;
	else if (1 > rts->value || rts->value > MAX_RTS_THRESHOLD)
		return -EINVAL;
	else
		val = rts->value;
	
	if (val != pAdapter->PortCfg.RtsThreshold)
		pAdapter->PortCfg.RtsThreshold = val;

	return 0;
}

int rtusb_ioctl_giwrts(struct net_device *dev,
		       struct iw_request_info *info,
		       struct iw_param *rts, char *extra)
{
	PRT2570ADAPTER pAdapter = (PRT2570ADAPTER) dev->priv;

	rts->value = pAdapter->PortCfg.RtsThreshold;
	rts->disabled = (rts->value == MAX_RTS_THRESHOLD);
	rts->fixed = 1;

	return 0;
}


int rtusb_ioctl_siwfrag(struct net_device *dev,
			struct iw_request_info *info,
			struct iw_param *rts, char *extra)
{
	PRT2570ADAPTER pAdapter = (PRT2570ADAPTER) dev->priv;
	u16 val;

	if (rts->disabled)
		val = MAX_FRAG_THRESHOLD;
	else if (rts->value < 256 || rts->value > MAX_FRAG_THRESHOLD)
		return -EINVAL;
	else
		val = __cpu_to_le16(rts->value & ~0x1); /* even numbers only */

	pAdapter->PortCfg.FragmentThreshold = val;
	return 0;
}

int rtusb_ioctl_giwfrag(struct net_device *dev,
			struct iw_request_info *info,
			struct iw_param *rts, char *extra)
{
	PRT2570ADAPTER pAdapter = (PRT2570ADAPTER) dev->priv;

	rts->value = pAdapter->PortCfg.FragmentThreshold;
	rts->disabled = (rts->value == 2346);
	rts->fixed = 1;

	return 0;
}

int rtusb_ioctl_siwencode(struct net_device *dev,
			  struct iw_request_info *info,
			  struct iw_point *erq, char *extra)
{
	PRT2570ADAPTER pAdapter = (PRT2570ADAPTER) dev->priv;
	NDIS_802_11_WEP	WepKey;
	int 	index, len;
	CHAR	kid = 0;
	memset(&WepKey, 0, sizeof(NDIS_802_11_WEP));

	if (erq->flags & IW_ENCODE_DISABLED)
	{
		pAdapter->PortCfg.PairCipher = Ndis802_11WEPDisabled;
		pAdapter->PortCfg.GroupCipher = Ndis802_11WEPDisabled;
		pAdapter->PortCfg.WepStatus = Ndis802_11WEPDisabled;
	}
	else
	{
		pAdapter->PortCfg.PairCipher = Ndis802_11WEPEnabled;
		pAdapter->PortCfg.GroupCipher = Ndis802_11WEPEnabled;
		pAdapter->PortCfg.WepStatus = Ndis802_11WEPEnabled;
	}

	if (erq->flags & IW_ENCODE_RESTRICTED)
		pAdapter->PortCfg.AuthMode = Ndis802_11AuthModeShared;
	else if(erq->flags & IW_ENCODE_OPEN)
		pAdapter->PortCfg.AuthMode = Ndis802_11AuthModeOpen;

	if(pAdapter->PortCfg.WepStatus == Ndis802_11WEPDisabled)
		pAdapter->PortCfg.AuthMode = Ndis802_11AuthModeOpen;
    
	if ((erq->flags & IW_ENCODE_DISABLED) == 0 && erq->pointer) 
	{
		/* Enable crypto. */
		if (erq->length > IFNAMSIZ)
			return -EINVAL;

		/* Old solution to take  default key  */
		index = (erq->flags & IW_ENCODE_INDEX) ;
		if((index < 0) || (index > NR_WEP_KEYS))
			return -EINVAL;     
			DBGPRINT(RT_DEBUG_TRACE," erq->flags = %x\n",erq->flags);
		
		if (index != 0)
		{
			pAdapter->PortCfg.DefaultKeyId = index -1;
		}
		
		if ((erq->length == 1) && (index == 0))
		{
			/* New solution to take  default key  when old way not work, not change KeyMaterial*/
			memcpy(&kid, erq->pointer, 1 );
			if((index < 0) || (index >= NR_WEP_KEYS))
				return -EINVAL;     
			//WepKey.KeyIndex = 0x80000000 + index;
			DBGPRINT(RT_DEBUG_TRACE,"kid = %d , erq->length = %d\n",kid, erq->length);
			if (kid > 0)
				pAdapter->PortCfg.DefaultKeyId = kid-1;
			else 
				pAdapter->PortCfg.DefaultKeyId = 0;
		}
		else
		{
			DBGPRINT(RT_DEBUG_TRACE,"DefaultKeyId = %d , erq->length = %d, flags 0x%x\n",pAdapter->PortCfg.DefaultKeyId, erq->length,erq->flags);
			len = erq->length;
			if(len > WEP_LARGE_KEY_LEN)
				len = WEP_LARGE_KEY_LEN;
			// If this instruction default key
			memset(pAdapter->PortCfg.SharedKey[pAdapter->PortCfg.DefaultKeyId].Key,  0, MAX_LEN_OF_KEY);
			memcpy(pAdapter->PortCfg.SharedKey[pAdapter->PortCfg.DefaultKeyId].Key, erq->pointer, len);
			memcpy(WepKey.KeyMaterial, erq->pointer, len);
			WepKey.KeyIndex = 0x80000000 + pAdapter->PortCfg.DefaultKeyId; 
			WepKey.KeyLength = len;
			pAdapter->PortCfg.SharedKey[pAdapter->PortCfg.DefaultKeyId].KeyLen =(UCHAR) (len <= WEP_SMALL_KEY_LEN ? WEP_SMALL_KEY_LEN : WEP_LARGE_KEY_LEN);
			// need to enqueue cmd to thread
			RTUSBEnqueueCmdFromNdis(pAdapter, OID_802_11_ADD_WEP, TRUE, &WepKey, sizeof(WepKey));
		}
		
	}
	DBGPRINT(RT_DEBUG_TRACE, "==>AuthMode=%x\n",pAdapter->PortCfg.AuthMode);
	DBGPRINT(RT_DEBUG_TRACE, "==>DefaultKeyId=%x, KeyLen = %d\n",pAdapter->PortCfg.DefaultKeyId , pAdapter->PortCfg.SharedKey[pAdapter->PortCfg.DefaultKeyId].KeyLen);
	DBGPRINT(RT_DEBUG_TRACE, "==>WepStatus=%x\n",pAdapter->PortCfg.WepStatus);
	return 0;
}

int
rtusb_ioctl_giwencode(struct net_device *dev,
			  struct iw_request_info *info,
			  struct iw_point *erq, char *key)
{
	PRT2570ADAPTER pAdapter = (PRT2570ADAPTER) dev->priv;
	int kid;
	
	kid = erq->flags & IW_ENCODE_INDEX;
	DBGPRINT(RT_DEBUG_TRACE, "===>rtusb_ioctl_giwencode %d\n", erq->flags & IW_ENCODE_INDEX);

	if (pAdapter->PortCfg.WepStatus == Ndis802_11WEPDisabled)
	{
		erq->length = 0;
		erq->flags = IW_ENCODE_DISABLED;
		return 0;
	}

	erq->flags = IW_ENCODE_ENABLED;

	if (pAdapter->PortCfg.AuthMode == Ndis802_11AuthModeShared)
		erq->flags |= IW_ENCODE_RESTRICTED;
	else
		erq->flags |= IW_ENCODE_OPEN;

	if ((kid > 0) && (kid <=4))
	{
		// copy wep key
		erq->flags |= kid & IW_ENCODE_INDEX;			/* NB: base 1 */
		if (erq->length > pAdapter->PortCfg.SharedKey[kid-1].KeyLen)
			erq->length = pAdapter->PortCfg.SharedKey[kid-1].KeyLen;
		memcpy(key, pAdapter->PortCfg.SharedKey[kid-1].Key, erq->length);
	}
	else if (kid == 0)
	{
		// copy default key ID
		erq->flags |= (pAdapter->PortCfg.DefaultKeyId + 1) & IW_ENCODE_INDEX;		/* NB: base 1 */
		erq->length = pAdapter->PortCfg.SharedKey[pAdapter->PortCfg.DefaultKeyId].KeyLen;
		memcpy(key, pAdapter->PortCfg.SharedKey[pAdapter->PortCfg.DefaultKeyId].Key, erq->length);
	}
		
	return 0;

}

static int
rtusb_ioctl_setauth(struct net_device *dev, struct iw_request_info *info,
			 void *w, char *extra)
{
	PRT2570ADAPTER pAdapter = (PRT2570ADAPTER) dev->priv;
	int param = *(int *) extra;
  
	switch(param)
	{
		case 1:
			pAdapter->PortCfg.AuthMode = Ndis802_11AuthModeOpen;
			DBGPRINT(RT_DEBUG_TRACE, "===>rtusb_ioctl_setauth RTPRIV802_11AuthModeOpen\n");
			break;
		case 2:
			pAdapter->PortCfg.AuthMode = Ndis802_11AuthModeShared;
			DBGPRINT(RT_DEBUG_TRACE, "===>rtusb_ioctl_setauth RTPRIV802_11AuthModeShared\n");
			break;
		case 3:
			pAdapter->PortCfg.AuthMode = Ndis802_11AuthModeWPAPSK;
			pAdapter->PortCfg.WpaState = SS_START;
			DBGPRINT(RT_DEBUG_TRACE, "===>rtusb_ioctl_setauth RTPRIV802_11AuthModeWPAPSK\n");
			break;
		case 4:
			pAdapter->PortCfg.AuthMode = Ndis802_11AuthModeWPANone;
			DBGPRINT(RT_DEBUG_TRACE, "===>rtusb_ioctl_setauth Ndis802_11AuthModeWPANone\n");
			break;
		default:
			return -EOPNOTSUPP;

	}


	pAdapter->PortCfg.PortSecured = WPA_802_1X_PORT_NOT_SECURED;

	return 0;
}
#if 0
static int rtusb_ioctl_setkeyid(struct net_device *dev, struct iw_request_info *info,
			 void *w, char *extra)
{

	PRT2570ADAPTER pAdapter = (PRT2570ADAPTER) dev->priv;
  	int param = *(int *)extra;
	USHORT	Value;

	switch(param)
	{
		case 1:
			pAdapter->PortCfg.DefaultKeyId = 0;
			break;
		case 2:
			pAdapter->PortCfg.DefaultKeyId = 1;
			break;
		case 3:
			pAdapter->PortCfg.DefaultKeyId = 2;
			break;
		case 4:
			pAdapter->PortCfg.DefaultKeyId = 3;
			break;
		default:
			return -EOPNOTSUPP;

	}


	if (pAdapter->PortCfg.SharedKey[pAdapter->PortCfg.DefaultKeyId].KeyLen == 5)
		pAdapter->PortCfg.CipherAlg = CIPHER_WEP64;
	else
		pAdapter->PortCfg.CipherAlg = CIPHER_WEP128;
					
	RTUSBReadMACRegister(pAdapter, TXRX_CSR0, &Value);
	Value &= 0xfe00;
	Value |= ((LENGTH_802_11 << 3) | (pAdapter->PortCfg.CipherAlg));
	RTUSBWriteMACRegister(pAdapter, TXRX_CSR0, Value);
        
	DBGPRINT(RT_DEBUG_TRACE, "===>DefaultKeyId = [%d]\n",pAdapter->PortCfg.DefaultKeyId);

	return 0;
}
#endif
static int
rtusb_ioctl_setencryp(struct net_device *dev, struct iw_request_info *info,
			 void *w, char *extra)
{

	PRT2570ADAPTER pAdapter = (PRT2570ADAPTER) dev->priv;
	int param = *(int *)extra;
	NDIS_802_11_WEP_STATUS				WepStatus;//set by OID_802_11_WEP_STATUS
	DBGPRINT(RT_DEBUG_TRACE, "===>setencryp\n");
	DBGPRINT(RT_DEBUG_TRACE, "===>info->cmd 0x%x   \n",(info->cmd));
	DBGPRINT(RT_DEBUG_TRACE, "===>info->flags 0x%x  , param %x , extra %x\n",(info->flags), param,*extra);
	switch(param)
	{
		case 1:
			pAdapter->PortCfg.WepStatus= Ndis802_11WEPDisabled;
			pAdapter->PortCfg.PairCipher= Ndis802_11WEPDisabled;
			pAdapter->PortCfg.GroupCipher= Ndis802_11WEPDisabled;
			pAdapter->PortCfg.CipherAlg = CIPHER_NONE;
			WepStatus = Ndis802_11WEPDisabled;
			break;
		case 2:
			pAdapter->PortCfg.WepStatus= Ndis802_11Encryption1Enabled;
			pAdapter->PortCfg.PairCipher= Ndis802_11Encryption1Enabled;
			pAdapter->PortCfg.GroupCipher= Ndis802_11Encryption1Enabled;
			WepStatus = Ndis802_11Encryption1Enabled;
			break;
		case 3:
			pAdapter->PortCfg.WepStatus= Ndis802_11Encryption2Enabled;
			pAdapter->PortCfg.PairCipher= Ndis802_11Encryption2Enabled;
			pAdapter->PortCfg.GroupCipher= Ndis802_11Encryption2Enabled;
			pAdapter->PortCfg.CipherAlg = CIPHER_TKIP;
			WepStatus = Ndis802_11Encryption2Enabled;
			break;
		default:
			return -EOPNOTSUPP;

	}
	RTUSBEnqueueCmdFromNdis(pAdapter, OID_802_11_WEP_STATUS, TRUE, &WepStatus, sizeof(WepStatus));

	return 0;
}
static int
rtusb_ioctl_setwpapsk(struct net_device *dev, struct iw_request_info *info,
			 void *w, char *extra)
{
	PRT2570ADAPTER pAdapter = (PRT2570ADAPTER) dev->priv;
	NDIS_802_11_KEY                    Key;
	// rtusb_ioctl_setwpapsk accept > 16 chars, so data is passed through w instead of extra.
	struct iw_point *iwp = (struct iw_point *)w;
	UCHAR                               keyMaterial[80];
	UCHAR                               keyMaterial2[80];
	INT			Status = NDIS_STATUS_SUCCESS;
	int	i;

	DBGPRINT(RT_DEBUG_TRACE, "===>\n");
	DBGPRINT(RT_DEBUG_TRACE, "===>info->cmd 0x%x   \n",(info->cmd));
	DBGPRINT(RT_DEBUG_TRACE, "===>info->flags 0x%x   \n",(info->flags));
	memset(Key.KeyMaterial, 0, 64);
	memset(keyMaterial2, 0, 80);
	memcpy(Key.BSSID, pAdapter->PortCfg.Bssid.Octet, 6);
	//memcpy(&Key.KeyRSC, pMsg3->KeyDesc.KeyRsc, LEN_KEY_DESC_RSC);
	if (iwp->length < 64)
	{
		if(copy_from_user(&keyMaterial2, iwp->pointer, iwp->length))
			Status = -EINVAL;

		PasswordHash(keyMaterial2, pAdapter->Mlme.CntlAux.Ssid, pAdapter->Mlme.CntlAux.SsidLen, keyMaterial);

		Key.Length    = sizeof(Key);
		Key.KeyIndex  = 0x80000000;           
		Key.KeyLength = 32;
		DBGPRINT_RAW(RT_DEBUG_TEMP,"pAdapter->Mlme.CntlAux.Ssid: ");
		for(i = 0; i < pAdapter->Mlme.CntlAux.SsidLen; i++)
			DBGPRINT_RAW(RT_DEBUG_TEMP,"%c ", pAdapter->Mlme.CntlAux.Ssid[i]);
		DBGPRINT_RAW(RT_DEBUG_TEMP,"\n");

		memcpy(pAdapter->PortCfg.PskKey.Key, keyMaterial, 32);
		memcpy(Key.KeyMaterial, keyMaterial, 32);
		DBGPRINT_RAW(RT_DEBUG_TEMP,"WPAPSK Key : ");
		for(i = 0; i < 32; i++)
			DBGPRINT_RAW(RT_DEBUG_TEMP,"%x ", Key.KeyMaterial[i]);
		DBGPRINT_RAW(RT_DEBUG_TEMP,"\n");

	}
	else if (iwp->length == 64)
	{
                if(copy_from_user(&keyMaterial2, iwp->pointer, iwp->length))
			Status = -EINVAL;

		AtoH(Key.KeyMaterial, keyMaterial, 32);

		DBGPRINT_RAW(RT_DEBUG_TEMP,"WPAPSK Key : ");
		for(i = 0; i < 32; i++)
			DBGPRINT_RAW(RT_DEBUG_TEMP,"%x ", keyMaterial[i]);
		DBGPRINT_RAW(RT_DEBUG_TEMP,"\n");

		memcpy(pAdapter->PortCfg.PskKey.Key, keyMaterial, 32);
		memcpy(Key.KeyMaterial, keyMaterial, 32);

	}
	
	else
		return -EOPNOTSUPP;


	RTUSBEnqueueCmdFromNdis(pAdapter, OID_802_11_ADD_KEY, TRUE, &Key, sizeof(Key));

	pAdapter->PortCfg.WepStatus= Ndis802_11Encryption2Enabled;
	pAdapter->PortCfg.PairCipher= Ndis802_11Encryption2Enabled;
	pAdapter->PortCfg.GroupCipher= Ndis802_11Encryption2Enabled;
	pAdapter->PortCfg.CipherAlg= CIPHER_TKIP;
	// Start STA supplicant state machine
	
	return 0;

}

static int rtusb_ioctl_setrfmontx(struct net_device *dev,
                                  struct iw_request_info *info,
                                  struct iw_point *data, char *extra)
{
	PRT2570ADAPTER pAdapter = (PRT2570ADAPTER) dev->priv;
	int param;
	char value;	

        if (extra) { /* Change the state if there's param. */
           param = *(int *)extra;
           switch(param)
           {
             case 1:
                pAdapter->PortCfg.MallowRFMONTx = TRUE;
                pAdapter->net->type = 801; // ARPHRD_IEEE80211
                break;
             case 0:
                pAdapter->PortCfg.MallowRFMONTx = FALSE;
                pAdapter->net->type = 802; // ARPHRD_IEEE80211_PRISM
                break;
             default:
                return -EOPNOTSUPP;
           }
	}

        value = pAdapter->PortCfg.MallowRFMONTx == TRUE ? '1' : '0';

        data->length = sizeof (char);
        if (data->pointer != NULL && copy_to_user (data->pointer, &value, data->length))
             DBGPRINT (RT_DEBUG_ERROR, "rtusb_ioctl_setrfmontx - copy to user failure.\n");

	return 0;
}

static int rtusb_ioctl_setadhocmode(struct net_device *dev,
                                  struct iw_request_info *info,
                                  struct iw_point *data, char *extra)
{
	PRT2570ADAPTER pAdapter = (PRT2570ADAPTER) dev->priv;
	int param = *(int *)extra;

	switch(param)
	{
	case 0:
			pAdapter->PortCfg.AdhocMode = 0;
			break;
		case 1:
			pAdapter->PortCfg.AdhocMode = 1;
			break;
		case 2:
			pAdapter->PortCfg.AdhocMode = 2;
		break;
		default:
			return -EOPNOTSUPP;
	}

	return 0;
}

static int rtusb_ioctl_setpsm(struct net_device *dev, struct iw_request_info *info,
			 void *w, char *extra)
{

	PRT2570ADAPTER pAdapter = (PRT2570ADAPTER) dev->priv;
	int param = *(int *)extra;

	switch(param)
	{
		case 0:
			// clear PSM bit immediately
			MlmeSetPsmBit(pAdapter, PWR_ACTIVE);
			pAdapter->PortCfg.RecvDtim = TRUE;
			pAdapter->PortCfg.WindowsPowerMode = Ndis802_11PowerModeCAM;
			break;
        
	        case 1:
			// do NOT turn on PSM bit here, wait until MlmeCheckForPsmChange()
			// to exclude certain situations.
			pAdapter->PortCfg.RecvDtim = TRUE;
			pAdapter->PortCfg.WindowsPowerMode = Ndis802_11PowerModeMAX_PSP;
			pAdapter->PortCfg.DefaultListenCount = 3;
			break;
	        	
		default:
			return -EOPNOTSUPP;

    	}
    
	return 0;

}
static const iw_handler rtusb_handler[] =
{
	(iw_handler) NULL,				/* SIOCSIWCOMMIT */
	(iw_handler) rtusb_ioctl_giwname,			/* SIOCGIWNAME	1 */	 
	(iw_handler) NULL,				/* SIOCSIWNWID */
	(iw_handler) NULL,				/* SIOCGIWNWID */
	(iw_handler) rtusb_ioctl_siwfreq,		/* SIOCSIWFREQ */
	(iw_handler) rtusb_ioctl_giwfreq,		/* SIOCGIWFREQ 5*/
	(iw_handler) rtusb_ioctl_siwmode,		/* SIOCSIWMODE */
	(iw_handler) rtusb_ioctl_giwmode,		/* SIOCGIWMODE */
	(iw_handler) NULL,		/* SIOCSIWSENS */
	(iw_handler) NULL,		/* SIOCGIWSENS */
	(iw_handler) NULL /* not used */,		/* SIOCSIWRANGE */
	(iw_handler) rtusb_ioctl_giwrange,		/* SIOCGIWRANGE 	11 */
	(iw_handler) NULL /* not used */,		/* SIOCSIWPRIV */
	(iw_handler) NULL /* kernel code */,		/* SIOCGIWPRIV */
	(iw_handler) NULL /* not used */,		/* SIOCSIWSTATS */
	(iw_handler) NULL /* kernel code */,		/* SIOCGIWSTATS 	f*/
	(iw_handler) NULL,		/* SIOCSIWSPY */
	(iw_handler) NULL,		/* SIOCGIWSPY */
	(iw_handler) NULL,				/* -- hole -- */
	(iw_handler) NULL,				/* -- hole -- */
	(iw_handler) NULL,		/* SIOCSIWAP */
	(iw_handler) rtusb_ioctl_giwap,		/* SIOCGIWAP	0x15*/
	(iw_handler) NULL,				/* -- hole --	0x16 */
	(iw_handler) rtusb_ioctl_iwaplist,		/* SIOCGIWAPLIST */
#ifdef SIOCGIWSCAN
	(iw_handler) rtusb_ioctl_siwscan,		/* SIOCSIWSCAN		0x18*/
	(iw_handler) rtusb_ioctl_giwscan,		/* SIOCGIWSCAN */
#else
	(iw_handler) NULL,				/* SIOCSIWSCAN */
	(iw_handler) NULL,				/* SIOCGIWSCAN */
#endif /* SIOCGIWSCAN */
	(iw_handler) rtusb_ioctl_siwessid,		/* SIOCSIWESSID */
	(iw_handler) rtusb_ioctl_giwessid,		/* SIOCGIWESSID */
	(iw_handler) rtusb_ioctl_siwnickn,		/* SIOCSIWNICKN */
	(iw_handler) rtusb_ioctl_giwnickn,		/* SIOCGIWNICKN 1d*/
	(iw_handler) NULL,				/* -- hole -- */
	(iw_handler) NULL,				/* -- hole -- */
	(iw_handler) NULL,		/* SIOCSIWRATE 20*/
	(iw_handler) NULL,		/* SIOCGIWRATE */
	(iw_handler) rtusb_ioctl_siwrts,		/* SIOCSIWRTS */
	(iw_handler) rtusb_ioctl_giwrts,		/* SIOCGIWRTS */
	(iw_handler) rtusb_ioctl_siwfrag,		/* SIOCSIWFRAG */
	(iw_handler) rtusb_ioctl_giwfrag,		/* SIOCGIWFRAG 25*/
	(iw_handler) NULL,		/* SIOCSIWTXPOW */
	(iw_handler) NULL,		/* SIOCGIWTXPOW */
	(iw_handler) NULL,		/* SIOCSIWRETRY */
	(iw_handler) NULL,		/* SIOCGIWRETRY 29*/
	(iw_handler) rtusb_ioctl_siwencode,		/* SIOCSIWENCODE 2a*/
	(iw_handler) rtusb_ioctl_giwencode,		/* SIOCGIWENCODE 2b*/
	(iw_handler) NULL,		/* SIOCSIWPOWER 2c*/
	(iw_handler) NULL,		/* SIOCGIWPOWER 2d*/
};
static const iw_handler rtusb_priv_handlers[] = {
	(iw_handler) rtusb_ioctl_setauth,		/* SIOCWFIRSTPRIV+0 */
	(iw_handler) rtusb_ioctl_setencryp,		/* SIOCWFIRSTPRIV+1 */
	(iw_handler) rtusb_ioctl_setwpapsk,		/* SIOCWFIRSTPRIV+2 */
	(iw_handler) rtusb_ioctl_setpsm,		/* SIOCWFIRSTPRIV+3 */
	(iw_handler) rtusb_ioctl_setadhocmode,		/* SIOCWFIRSTPRIV+4 */
	(iw_handler) rtusb_ioctl_setrfmontx,		/* SIOCWFIRSTPRIV+5 */
};

#define MAX_WPAPSK_STRING 64
static const struct iw_priv_args privtab[] = {
	{ RTPRIV_IOCTL_AUTH, 
	  IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0,  "auth"},
	{ RTPRIV_IOCTL_WEPSTATUS, 
	  IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0,  "enc"},
	{ RTPRIV_IOCTL_WPAPSK, 
	  IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | MAX_WPAPSK_STRING,
	  0,  "wpapsk"},  // Variable arg count  
	{ RTPRIV_IOCTL_PSM, 
	  IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0,  "psm"},  // Variable arg count  
	{ RTPRIV_IOCTL_ADHOCMODE,
	  IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0,  "adhocmode"},
	{ RTPRIV_IOCTL_RFMONTX,
	  IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
	  IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | sizeof(char), "rfmontx"}, 
#if 0
	{ RTPRIV_IOCTL_BBP,
	  IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | 1024,
	  "bbp"},
	{ RTPRIV_IOCTL_MAC,
	  IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | 1024,
	  "mac"}
#endif
};

const struct iw_handler_def rt2500usb_iw_handler_def =
{
	.standard		= (iw_handler *) rtusb_handler,
	.num_standard		= sizeof(rtusb_handler) / sizeof(iw_handler),
	.private		= (iw_handler *) rtusb_priv_handlers,
	.num_private		= ARRAY_SIZE(rtusb_handler),
	.private_args		= (struct iw_priv_args *) privtab,
	.num_private_args	= ARRAY_SIZE(privtab),
};

INT RTMPQueryInformation(
	IN	PRT2570ADAPTER pAdapter,
	IN	OUT struct ifreq	*rq,
	IN	INT 				cmd)
{
	struct iwreq						*wrq = (struct iwreq *) rq;
	NDIS_802_11_BSSID_LIST_EX			*pBssidList = NULL;
	PNDIS_WLAN_BSSID_EX 				pBss;
	NDIS_802_11_SSID					Ssid;
	NDIS_802_11_CONFIGURATION			Configuration;
	RT_802_11_LINK_STATUS				LinkStatus;
	NDIS_802_11_STATISTICS				Statistics;
	NDIS_802_11_RTS_THRESHOLD			RtsThresh;
	NDIS_802_11_FRAGMENTATION_THRESHOLD FragThresh;
	NDIS_802_11_POWER_MODE				PowerMode;
	NDIS_802_11_NETWORK_INFRASTRUCTURE	BssType;
	RT_802_11_PREAMBLE					PreamType;
	NDIS_802_11_AUTHENTICATION_MODE 	AuthMode;
	NDIS_802_11_WEP_STATUS				WepStatus;
	RT_VERSION_INFO 					DriverVersionInfo;
	ULONG								BssBufSize;
	ULONG								BssLen;
	ULONG								ulInfo = 0;
	PUCHAR								pBuf = NULL;
	PUCHAR								pPtr;
	INT 								Status = NDIS_STATUS_SUCCESS;
	UCHAR								Padding;
	UINT								i;
	BOOLEAN 							RadioState;
	UCHAR                         LastR17Value;
 
	
	switch(cmd) {
		case RT_OID_DEVICE_NAME:
			DBGPRINT(RT_DEBUG_INFO, "Query::RT_OID_DEVICE_NAME\n");
			wrq->u.data.length = sizeof(NIC_DEVICE_NAME);
			if(copy_to_user(wrq->u.data.pointer, NIC_DEVICE_NAME, wrq->u.data.length))
				Status = -EFAULT;

			break;
		case RT_OID_VERSION_INFO:
			DBGPRINT(RT_DEBUG_INFO, "Query::RT_OID_VERSION_INFO \n");
			DriverVersionInfo.DriverMajorVersion = DRV_MAJORVERSION;
			DriverVersionInfo.DriverMinorVersion = DRV_MINORVERSION;
			DriverVersionInfo.DriverSubVersion = DRV_SUBVERSION;
            		DriverVersionInfo.DriverTestVersion = DRV_TESTVERSION;
			DriverVersionInfo.DriverBuildYear = DRV_YEAR;
			DriverVersionInfo.DriverBuildMonth = DRV_MONTH;
			DriverVersionInfo.DriverBuildDay = DRV_DAY;
			wrq->u.data.length = sizeof(RT_VERSION_INFO);
			if(copy_to_user(wrq->u.data.pointer, &DriverVersionInfo, wrq->u.data.length))
				Status = -EFAULT;

			break;
		case OID_802_11_BSSID_LIST:
		
			DBGPRINT(RT_DEBUG_ERROR, "Query::OID_802_11_BSSID_LIST (%d BSS returned)\n",pAdapter->PortCfg.BssTab.BssNr);
			// Claculate total buffer size required
			BssBufSize = sizeof(ULONG);
			
			for (i = 0; i < pAdapter->PortCfg.BssTab.BssNr; i++) 
			{
				// Align pointer to 4 bytes boundary.
				Padding = 4 - (pAdapter->PortCfg.BssTab.BssEntry[i].VarIELen & 0x0003);
				if (Padding == 4)
					Padding = 0;
				BssBufSize += (sizeof(NDIS_WLAN_BSSID_EX) - 4 + sizeof(NDIS_802_11_FIXED_IEs) + pAdapter->PortCfg.BssTab.BssEntry[i].VarIELen + Padding);
			}

			// For safety issue, we add 256 bytes just in case
			BssBufSize += 256;
			// Allocate the same size as passed from higher layer
			pBuf = kmalloc(BssBufSize, GFP_KERNEL);
			if(pBuf == NULL)
			{
				Status = -ENOMEM;
				break;
			}
			// Init 802_11_BSSID_LIST_EX structure
			memset(pBuf, 0, BssBufSize);

			
			pBssidList = (PNDIS_802_11_BSSID_LIST_EX) pBuf;
			pBssidList->NumberOfItems = pAdapter->PortCfg.BssTab.BssNr;
			
			// Calculate total buffer length
			BssLen = 4; // Consist of NumberOfItems
			// Point to start of NDIS_WLAN_BSSID_EX
			// pPtr = pBuf + sizeof(ULONG);
			pPtr = (PUCHAR) &pBssidList->Bssid[0];
			for (i = 0; i < pAdapter->PortCfg.BssTab.BssNr; i++) 
			{
				pBss = (PNDIS_WLAN_BSSID_EX) pPtr;
				memcpy(&pBss->MacAddress, &pAdapter->PortCfg.BssTab.BssEntry[i].Bssid, MAC_ADDR_LEN);
				if (pAdapter->PortCfg.BssTab.BssEntry[i].Hidden == 1)
				{
					pBss->Ssid.SsidLength = 0;
				}
				else
				{
			pBss->Ssid.SsidLength = pAdapter->PortCfg.BssTab.BssEntry[i].SsidLen;
					memcpy(pBss->Ssid.Ssid, pAdapter->PortCfg.BssTab.BssEntry[i].Ssid, pAdapter->PortCfg.BssTab.BssEntry[i].SsidLen);
				}
				pBss->Privacy = pAdapter->PortCfg.BssTab.BssEntry[i].Privacy;
		  //DBGPRINT(RT_DEBUG_ERROR,"pBss->Privacy=%x\n",(pBss->Privacy));
				pBss->Rssi = pAdapter->PortCfg.BssTab.BssEntry[i].Rssi - RSSI_TO_DBM_OFFSET;
		  //DBGPRINT(RT_DEBUG_ERROR,"pBss->Rssi=%x\n",pBss->Rssi);
				pBss->NetworkTypeInUse = Ndis802_11DS;
		  //DBGPRINT(RT_DEBUG_ERROR,"pBss->NetworkTypeInUse=%x\n",(pBss->NetworkTypeInUse));
				pBss->Configuration.Length = sizeof(NDIS_802_11_CONFIGURATION);
		  //DBGPRINT(RT_DEBUG_ERROR,"pBss->pBss->Configuration.Length=%d\n",pBss->Configuration.Length);
				pBss->Configuration.BeaconPeriod = pAdapter->PortCfg.BssTab.BssEntry[i].BeaconPeriod;
		  //DBGPRINT(RT_DEBUG_ERROR,"pBss->pBss->Configuration.BeaconPeriod=%d\n",pBss->Configuration.BeaconPeriod);
				pBss->Configuration.ATIMWindow = pAdapter->PortCfg.BssTab.BssEntry[i].AtimWin;

				MAP_CHANNEL_ID_TO_KHZ(pAdapter->PortCfg.BssTab.BssEntry[i].Channel, pBss->Configuration.DSConfig);

				if (pAdapter->PortCfg.BssTab.BssEntry[i].BssType == BSS_INFRA) 
					pBss->InfrastructureMode = Ndis802_11Infrastructure;
				else
					pBss->InfrastructureMode = Ndis802_11IBSS;

				memcpy(pBss->SupportedRates, pAdapter->PortCfg.BssTab.BssEntry[i].Rates, pAdapter->PortCfg.BssTab.BssEntry[i].RatesLen);

				//DBGPRINT(RT_DEBUG_ERROR, "BSS#%d - %s, length of ssid=%d,Ch %d = %d Khz\n",
				//			i,pBss->Ssid.Ssid,pBss->Ssid.SsidLength,pAdapter->PortCfg.BssTab.BssEntry[i].Channel,pBss->Configuration.DSConfig);

				if (pAdapter->PortCfg.BssTab.BssEntry[i].VarIELen == 0)
				{
					pBss->IELength = sizeof(NDIS_802_11_FIXED_IEs);
					memcpy(pBss->IEs, &pAdapter->PortCfg.BssTab.BssEntry[i].FixIEs, sizeof(NDIS_802_11_FIXED_IEs));
					pPtr = pPtr + sizeof(NDIS_WLAN_BSSID_EX) - 4 + sizeof(NDIS_802_11_FIXED_IEs);
				}
				else
				{
					pBss->IELength = sizeof(NDIS_802_11_FIXED_IEs) + pAdapter->PortCfg.BssTab.BssEntry[i].VarIELen;
					pPtr = pPtr + sizeof(NDIS_WLAN_BSSID_EX) - 4 + sizeof(NDIS_802_11_FIXED_IEs);
					memcpy(pBss->IEs, &pAdapter->PortCfg.BssTab.BssEntry[i].FixIEs, sizeof(NDIS_802_11_FIXED_IEs));
					memcpy(pPtr, pAdapter->PortCfg.BssTab.BssEntry[i].VarIEs, pAdapter->PortCfg.BssTab.BssEntry[i].VarIELen);
					pPtr += pAdapter->PortCfg.BssTab.BssEntry[i].VarIELen;
				}
				// Align pointer to 4 bytes boundary.
				Padding = 4 - (pAdapter->PortCfg.BssTab.BssEntry[i].VarIELen & 0x0003);
				if (Padding == 4)
					Padding = 0;
				pPtr += Padding;
				pBss->Length = sizeof(NDIS_WLAN_BSSID_EX) - 4 + sizeof(NDIS_802_11_FIXED_IEs) + pAdapter->PortCfg.BssTab.BssEntry[i].VarIELen + Padding;
				BssLen += pBss->Length;
			}
			wrq->u.data.length = BssLen;
			DBGPRINT(RT_DEBUG_INFO,"copy to user in OID_802_11_BSSID_LIST = %d\n",wrq->u.data.length);

			if(copy_to_user(wrq->u.data.pointer, pBssidList, wrq->u.data.length))
				Status = -EFAULT;

			kfree(pBssidList);
			break;
		case OID_802_11_TX_POWER_LEVEL:
			wrq->u.data.length = sizeof(ULONG);
			if(copy_to_user(wrq->u.data.pointer, &pAdapter->PortCfg.TxPower, wrq->u.data.length))
				Status = -EFAULT;

			DBGPRINT(RT_DEBUG_INFO, "Query::OID_802_11_TX_POWER_LEVEL %x\n",pAdapter->PortCfg.TxPower);
			break;
		case OID_802_3_CURRENT_ADDRESS:
			wrq->u.data.length = ETH_LENGTH_OF_ADDRESS;
			if(copy_to_user(wrq->u.data.pointer, &pAdapter->CurrentAddress, wrq->u.data.length))
				Status = -EFAULT;

			DBGPRINT(RT_DEBUG_INFO, "Query::OID_802_3_CURRENT_ADDRESS \n");
			break;
		case OID_GEN_MEDIA_CONNECT_STATUS:
			DBGPRINT(RT_DEBUG_INFO, "Query::OID_GEN_MEDIA_CONNECT_STATUS \n");
			wrq->u.data.length = sizeof(NDIS_MEDIA_STATE);
			if(copy_to_user(wrq->u.data.pointer, &pAdapter->MediaState, wrq->u.data.length))
				Status = -EFAULT;

			break;
		case OID_802_11_BSSID:
			if (INFRA_ON(pAdapter) || ADHOC_ON(pAdapter))
			{
				if(copy_to_user(wrq->u.data.pointer, &pAdapter->PortCfg.Bssid, sizeof(MACADDR)))
					Status = -EFAULT;

				DBGPRINT(RT_DEBUG_INFO, "IOCTL::SIOCGIWAP(=%02x:%02x:%02x:%02x:%02x:%02x)\n",
						pAdapter->PortCfg.Bssid.Octet[0],pAdapter->PortCfg.Bssid.Octet[1],pAdapter->PortCfg.Bssid.Octet[2],
						pAdapter->PortCfg.Bssid.Octet[3],pAdapter->PortCfg.Bssid.Octet[4],pAdapter->PortCfg.Bssid.Octet[5]);

			}
			else
			{
				DBGPRINT(RT_DEBUG_INFO, "Query::OID_802_11_BSSID(=EMPTY)\n");
				Status = -ENOTCONN;
			}
			break;
		case OID_802_11_SSID:
			Ssid.SsidLength = pAdapter->PortCfg.SsidLen;
			memset(Ssid.Ssid, 0, MAX_LEN_OF_SSID);
			memcpy(Ssid.Ssid, pAdapter->PortCfg.Ssid, Ssid.SsidLength);
			wrq->u.data.length = sizeof(NDIS_802_11_SSID);
			if(copy_to_user(wrq->u.data.pointer, &Ssid, wrq->u.data.length))
				Status = -EFAULT;

			DBGPRINT(RT_DEBUG_INFO, "Query::OID_802_11_SSID (Len=%d, ssid=%s)\n", Ssid.SsidLength,Ssid.Ssid);
			break;
		case RT_OID_802_11_QUERY_LINK_STATUS:
			LinkStatus.CurrTxRate = RateIdTo500Kbps[pAdapter->PortCfg.TxRate];	 // unit : 500 kbps
			LinkStatus.ChannelQuality = pAdapter->Mlme.ChannelQuality;
			LinkStatus.RxByteCount = pAdapter->RalinkCounters.ReceivedByteCount;
			LinkStatus.TxByteCount = pAdapter->RalinkCounters.TransmittedByteCount;
			wrq->u.data.length = sizeof(RT_802_11_LINK_STATUS);
			if(copy_to_user(wrq->u.data.pointer, &LinkStatus, wrq->u.data.length))
				Status = -EFAULT;

			DBGPRINT(RT_DEBUG_INFO, "Query::RT_OID_802_11_LINK_STATUS\n");
			break;
		case OID_802_11_CONFIGURATION:
			Configuration.Length = sizeof(NDIS_802_11_CONFIGURATION);
			Configuration.BeaconPeriod = pAdapter->PortCfg.BeaconPeriod;
			Configuration.ATIMWindow = pAdapter->PortCfg.AtimWin;
			if (ADHOC_ON(pAdapter))
				{MAP_CHANNEL_ID_TO_KHZ(pAdapter->PortCfg.IbssConfig.Channel, Configuration.DSConfig);}
			else
				{MAP_CHANNEL_ID_TO_KHZ(pAdapter->PortCfg.Channel, Configuration.DSConfig);}
			wrq->u.data.length = sizeof(NDIS_802_11_CONFIGURATION);
			if(copy_to_user(wrq->u.data.pointer, &Configuration, wrq->u.data.length))
				Status = -EFAULT;

			DBGPRINT(RT_DEBUG_ERROR, "Query::OID_802_11_CONFIGURATION(BeaconPeriod=%d,AtimW=%d,bssidChannel=%d) \n", 
				Configuration.BeaconPeriod, Configuration.ATIMWindow, pAdapter->PortCfg.IbssConfig.Channel);
			break;
		case OID_802_11_RSSI:
			ulInfo = pAdapter->PortCfg.LastRssi;
			wrq->u.data.length = sizeof(UCHAR);
			if(copy_to_user(wrq->u.data.pointer, &ulInfo, wrq->u.data.length))
				Status = -EFAULT;

			DBGPRINT(RT_DEBUG_INFO, "Query::OID_802_11_RSSI(=%d)\n", ulInfo);
			break;
		case OID_802_11_RSSI_TRIGGER:
			ulInfo = pAdapter->PortCfg.LastRssi - RSSI_TO_DBM_OFFSET;
			wrq->u.data.length = sizeof(ulInfo);
			if(copy_to_user(wrq->u.data.pointer, &ulInfo, wrq->u.data.length))
				Status = -EFAULT;

			DBGPRINT(RT_DEBUG_INFO, "Query::OID_802_11_RSSI_TRIGGER(=%d)\n", ulInfo);
			break;
		case OID_802_11_STATISTICS:
			DBGPRINT(RT_DEBUG_INFO, "Query::OID_802_11_STATISTICS \n");
			// Update FCS counters

			// Sanity check for calculation of sucessful count
			if (pAdapter->WlanCounters.TransmittedFragmentCount.QuadPart < pAdapter->WlanCounters.RetryCount.QuadPart)
				pAdapter->WlanCounters.TransmittedFragmentCount.QuadPart = pAdapter->WlanCounters.RetryCount.QuadPart;

			Statistics.TransmittedFragmentCount.QuadPart = pAdapter->WlanCounters.TransmittedFragmentCount.QuadPart;
			Statistics.MulticastTransmittedFrameCount.QuadPart = pAdapter->WlanCounters.MulticastTransmittedFrameCount.QuadPart;
			Statistics.FailedCount.QuadPart = pAdapter->WlanCounters.FailedCount.QuadPart;
			Statistics.RetryCount.QuadPart = pAdapter->WlanCounters.RetryCount.QuadPart;
			Statistics.MultipleRetryCount.QuadPart = pAdapter->WlanCounters.MultipleRetryCount.QuadPart;
			Statistics.RTSSuccessCount.QuadPart = pAdapter->WlanCounters.RTSSuccessCount.QuadPart;
			Statistics.RTSFailureCount.QuadPart = pAdapter->WlanCounters.RTSFailureCount.QuadPart;
			Statistics.ACKFailureCount.QuadPart = pAdapter->WlanCounters.ACKFailureCount.QuadPart;
			Statistics.FrameDuplicateCount.QuadPart = pAdapter->WlanCounters.FrameDuplicateCount.QuadPart;
			Statistics.ReceivedFragmentCount.QuadPart = pAdapter->WlanCounters.ReceivedFragmentCount.QuadPart;
			Statistics.MulticastReceivedFrameCount.QuadPart = pAdapter->WlanCounters.MulticastReceivedFrameCount.QuadPart;
			Statistics.FCSErrorCount.QuadPart = pAdapter->WlanCounters.FCSErrorCount.QuadPart;
			wrq->u.data.length = sizeof(NDIS_802_11_STATISTICS);
			if(copy_to_user(wrq->u.data.pointer, &Statistics, wrq->u.data.length))
				Status = -EFAULT;

			break;
		case OID_GEN_RCV_OK:
			DBGPRINT(RT_DEBUG_INFO, "Query::OID_GEN_RCV_OK \n");
			ulInfo = pAdapter->Counters.GoodReceives;
			wrq->u.data.length = sizeof(ulInfo);
			if(copy_to_user(wrq->u.data.pointer, &ulInfo, wrq->u.data.length))
				Status = -EFAULT;

			break;
		case OID_GEN_RCV_NO_BUFFER:
			DBGPRINT(RT_DEBUG_INFO, "Query::OID_GEN_RCV_NO_BUFFER \n");
			ulInfo = pAdapter->Counters.RxNoBuffer;
			wrq->u.data.length = sizeof(ulInfo);
			if(copy_to_user(wrq->u.data.pointer, &ulInfo, wrq->u.data.length))
				Status = -EFAULT;

			break;
		case RT_OID_802_11_PHY_MODE:
			ulInfo = (ULONG)pAdapter->PortCfg.PhyMode;
			wrq->u.data.length = sizeof(ulInfo);
			if(copy_to_user(wrq->u.data.pointer, &ulInfo, wrq->u.data.length))
				Status = -EFAULT;

			DBGPRINT(RT_DEBUG_INFO, "Query::RT_OID_802_11_PHY_MODE (=%d)\n", ulInfo);
			break;
		case OID_802_11_RTS_THRESHOLD:
			RtsThresh = pAdapter->PortCfg.RtsThreshold;
			wrq->u.data.length = sizeof(RtsThresh);
			if(copy_to_user(wrq->u.data.pointer, &RtsThresh, wrq->u.data.length))
				Status = -EFAULT;

			DBGPRINT(RT_DEBUG_INFO, "Query::OID_802_11_RTS_THRESHOLD(=%d)\n", RtsThresh);
			break;
		case OID_802_11_FRAGMENTATION_THRESHOLD:
			FragThresh = pAdapter->PortCfg.FragmentThreshold;
			if (pAdapter->PortCfg.bFragmentZeroDisable == TRUE)
				FragThresh = 0;
			wrq->u.data.length = sizeof(FragThresh);
			if(copy_to_user(wrq->u.data.pointer, &FragThresh, wrq->u.data.length))
				Status = -EFAULT;

			DBGPRINT(RT_DEBUG_INFO, "Query::OID_802_11_FRAGMENTATION_THRESHOLD(=%d)\n", FragThresh);
			break;
		case OID_802_11_POWER_MODE:
			PowerMode = pAdapter->PortCfg.WindowsPowerMode;
			wrq->u.data.length = sizeof(PowerMode);
			if(copy_to_user(wrq->u.data.pointer, &PowerMode, wrq->u.data.length))
				Status = -EFAULT;

			DBGPRINT(RT_DEBUG_INFO, "Query::OID_802_11_POWER_MODE(=%d)\n", PowerMode);
			break;
		case RT_OID_802_11_RADIO:
			RadioState = (BOOLEAN) pAdapter->PortCfg.bSwRadio;
			wrq->u.data.length = sizeof(RadioState);
			if(copy_to_user(wrq->u.data.pointer, &RadioState, wrq->u.data.length))
				Status = -EFAULT;

			DBGPRINT(RT_DEBUG_INFO, "Query::RT_OID_802_11_QUERY_RADIO (=%d)\n", RadioState);
			break;
		case OID_802_11_INFRASTRUCTURE_MODE:
			if (ADHOC_ON(pAdapter))
				BssType = Ndis802_11IBSS;
			else if (INFRA_ON(pAdapter))
				BssType = Ndis802_11Infrastructure;
			else
				BssType = Ndis802_11AutoUnknown;

			wrq->u.data.length = sizeof(BssType);
			if(copy_to_user(wrq->u.data.pointer, &BssType, wrq->u.data.length))
				Status = -EFAULT;

			DBGPRINT(RT_DEBUG_INFO, "Query::OID_802_11_INFRASTRUCTURE_MODE(=%d)\n", BssType);
			break;
		case RT_OID_802_11_PREAMBLE:
			PreamType = pAdapter->PortCfg.WindowsTxPreamble;
			wrq->u.data.length = sizeof(PreamType);
			if(copy_to_user(wrq->u.data.pointer, &PreamType, wrq->u.data.length))
				Status = -EFAULT;

			DBGPRINT(RT_DEBUG_INFO, "Query::RT_OID_802_11_PREAMBLE(=%d)\n", PreamType);
			break;
		case OID_802_11_AUTHENTICATION_MODE:
			AuthMode = pAdapter->PortCfg.AuthMode;
			wrq->u.data.length = sizeof(AuthMode);
			if(copy_to_user(wrq->u.data.pointer, &AuthMode, wrq->u.data.length))
				Status = -EFAULT;

			DBGPRINT(RT_DEBUG_INFO, "Query::OID_802_11_AUTHENTICATION_MODE(=%d)\n", AuthMode);
			break;
		case OID_802_11_WEP_STATUS:
			WepStatus = pAdapter->PortCfg.WepStatus;
			wrq->u.data.length = sizeof(WepStatus);
			if(copy_to_user(wrq->u.data.pointer, &WepStatus, wrq->u.data.length))
				Status = -EFAULT;

			DBGPRINT(RT_DEBUG_INFO, "Query::OID_802_11_WEP_STATUS(=%d)\n", WepStatus);
			break;
		case RT_OID_802_11_QUERY_NOISE_LEVEL:
			LastR17Value = (pAdapter->PortCfg.LastR17Value > BBP_R17_DYNAMIC_UP_BOUND) ? BBP_R17_DYNAMIC_UP_BOUND : ((ULONG) pAdapter->PortCfg.LastR17Value);
			wrq->u.data.length = sizeof(UCHAR);
			if(copy_to_user(wrq->u.data.pointer, &LastR17Value, wrq->u.data.length))
				Status = -EFAULT;

			DBGPRINT(RT_DEBUG_INFO, "Query::RT_OID_802_11_QUERY_NOISE_LEVEL (=%d)\n", LastR17Value);
			break;
		case RT_OID_802_11_EXTRA_INFO:
			wrq->u.data.length = sizeof(ULONG);
			if(copy_to_user(wrq->u.data.pointer, &pAdapter->ExtraInfo, wrq->u.data.length))
				Status = -EFAULT;

	            DBGPRINT(RT_DEBUG_INFO, "Query::RT_OID_802_11_EXTRA_INFO (=%d)\n", pAdapter->ExtraInfo);
	            break;
		default:
			DBGPRINT(RT_DEBUG_TRACE, "Query::unknown IOCTL's subcmd = 0x%08x\n", cmd);
			Status = -EOPNOTSUPP;
			break;
	}

	return Status;
}



INT RTMPSetInformation(
	IN	PRT2570ADAPTER pAdapter,
	IN	OUT struct ifreq	*rq,
	IN	INT 				cmd)
{
	struct iwreq						*wrq = (struct iwreq *) rq;
	NDIS_802_11_SSID					Ssid, *pSsid=NULL;
	NDIS_802_11_MAC_ADDRESS 			Bssid;
	RT_802_11_PHY_MODE					PhyMode;
	NDIS_802_11_RATES					aryRates;
	RT_802_11_PREAMBLE					Preamble;
	NDIS_802_11_WEP_STATUS				WepStatus;
	NDIS_802_11_AUTHENTICATION_MODE 	AuthMode;
	NDIS_802_11_NETWORK_INFRASTRUCTURE	BssType;
	NDIS_802_11_RTS_THRESHOLD			RtsThresh;
	NDIS_802_11_FRAGMENTATION_THRESHOLD FragThresh;
	NDIS_802_11_POWER_MODE				PowerMode;
	NDIS_802_11_TX_POWER_LEVEL			TxPowerLevel;
	NDIS_802_11_KEY					Key;
	PNDIS_802_11_REMOVE_KEY 			pRemoveKey = NULL;
	NDIS_802_11_CONFIGURATION			Config, *pConfig = NULL;
	ULONG								Now;
	ULONG								KeyIdx;
	INT 								Status = NDIS_STATUS_SUCCESS;
	UCHAR								CountryRegion;
	BOOLEAN 							RadioState;
	NDIS_802_11_PRIVACY_FILTER           Filter;
	NDIS_802_11_RSSI                     RssiTrigger;
	
	DBGPRINT(RT_DEBUG_INFO, "Set::RTMPSetInformation \n");
	
	switch(cmd & 0x7FFF) {
		case OID_802_11_BSSID:
		 	DBGPRINT(RT_DEBUG_ERROR,"enter OID_802_11_BSSID in RTMPSetInformation\n");
			if (wrq->u.data.length != sizeof(NDIS_802_11_MAC_ADDRESS))
				Status	= -EINVAL;
			else
			{
				if(copy_from_user(&Bssid, wrq->u.data.pointer, wrq->u.data.length))
					Status = -EINVAL;

				pAdapter->Mlme.CntlAux.CurrReqIsFromNdis = FALSE;
				Status = RTUSBEnqueueCmdFromNdis(pAdapter, RT_OID_802_11_BSSID, TRUE, &Bssid, wrq->u.data.length);
									
			}
			break;
		case OID_802_11_SSID:
			DBGPRINT(RT_DEBUG_ERROR,"enter OID_802_11_SSID in RTMPSetInformation\n");
			if (wrq->u.data.length != sizeof(NDIS_802_11_SSID))
				Status = -EINVAL;
			else
			{
				if(copy_from_user(&Ssid, wrq->u.data.pointer, wrq->u.data.length))
		    			Status = -EINVAL;
					
				pSsid = &Ssid;

				if (pSsid->SsidLength > MAX_LEN_OF_SSID)
					Status = -EINVAL;
				else
				{
					Status =RTUSBEnqueueCmdFromNdis(pAdapter, OID_802_11_SSID, TRUE, pSsid, sizeof(NDIS_802_11_SSID));
					DBGPRINT(RT_DEBUG_TRACE, "Set::OID_802_11_SSID (Len=%d,Ssid=%s)\n", pSsid->SsidLength, pSsid->Ssid);
				}
			}
			break;
		case OID_802_11_INFRASTRUCTURE_MODE:
			if (wrq->u.data.length != sizeof(NDIS_802_11_NETWORK_INFRASTRUCTURE))
				Status	= -EINVAL;
			else
			{
				if(copy_from_user(&BssType, wrq->u.data.pointer, wrq->u.data.length))
					Status = -EINVAL;

				if (BssType == Ndis802_11IBSS) 
				{
					if (pAdapter->PortCfg.BssType != BSS_INDEP)
					{
						// Config has changed
						if INFRA_ON(pAdapter)
						{
							RTUSBEnqueueInternalCmd(pAdapter, RT_OID_LINK_DOWN);
							// First cancel linkdown timer
							DBGPRINT(RT_DEBUG_TRACE, "NDIS_STATUS_MEDIA_DISCONNECT Event BB!\n");							
						}
					}
					pAdapter->PortCfg.BssType = BSS_INDEP;
					DBGPRINT(RT_DEBUG_TRACE, "Set::OID_802_11_INFRASTRUCTURE_MODE (AD-HOC)\n");
				}
				else if (BssType == Ndis802_11Infrastructure) 
				{
					if (pAdapter->PortCfg.BssType != BSS_INFRA)
					{
						// Config has changed
						// pAdapter->bConfigChanged = TRUE;
						if ADHOC_ON(pAdapter)
							RTUSBEnqueueInternalCmd(pAdapter, RT_OID_LINK_DOWN);
					}
					pAdapter->PortCfg.BssType = BSS_INFRA;
					DBGPRINT(RT_DEBUG_TRACE, "Set::OID_802_11_INFRASTRUCTURE_MODE (INFRA)\n");
				}
				else
				{
					Status	= -EINVAL;
					DBGPRINT(RT_DEBUG_TRACE, "Set::OID_802_11_INFRASTRUCTURE_MODE (unknown)\n");
				}
			}
			// Reset Ralink supplicant to not use, it will be set to start when UI set PMK key
			pAdapter->PortCfg.WpaState = SS_NOTUSE;
			break;
		case OID_802_11_ADD_KEY:
			DBGPRINT(RT_DEBUG_ERROR, "!!!!!!!!!!!!!!!!!!!!!Set::OID_802_11_ADD_KEY !!\n");
			if(copy_from_user(&Key, wrq->u.data.pointer, wrq->u.data.length))
				Status = -EINVAL;
					
			if (Key.Length != wrq->u.data.length)
			{
				Status	= -EINVAL;
				DBGPRINT(RT_DEBUG_TRACE, "Set::OID_802_11_ADD_KEY, Failed!!\n");
			}
			else
			{
				if (pAdapter->PortCfg.AuthMode >= Ndis802_11AuthModeWPA)
				{
					Status = RTUSBEnqueueCmdFromNdis(pAdapter, OID_802_11_ADD_KEY, TRUE, &Key, wrq->u.data.length);
				}
				else	// Old WEP stuff
				{
					KeyIdx = Key.KeyIndex & 0x0fffffff;
					Status = RTMPWPAWepKeySanity(pAdapter, &Key);
					if (Status == NDIS_STATUS_SUCCESS)
						Status = RTUSBEnqueueCmdFromNdis(pAdapter, OID_802_11_ADD_KEY_WEP, TRUE, &Key, wrq->u.data.length);

				}
				DBGPRINT(RT_DEBUG_TRACE, "Set::OID_802_11_ADD_KEY (id=0x%x, Len=%d-byte)\n", Key.KeyIndex, Key.KeyLength);
			}
			break;
		case OID_802_11_REMOVE_KEY:
			DBGPRINT(RT_DEBUG_ERROR, "Set::OID_802_11_REMOVE_KEY!!\n");
			pRemoveKey = kmalloc(wrq->u.data.length, GFP_KERNEL);
			if(copy_from_user(pRemoveKey, wrq->u.data.pointer, wrq->u.data.length))
				Status = -EINVAL;
					
			if (pRemoveKey->Length != wrq->u.data.length)
			{
				Status	= -EINVAL;
				DBGPRINT(RT_DEBUG_TRACE, "Set::OID_802_11_REMOVE_KEY, Failed!!\n");
			}
			else
			{
				if (pAdapter->PortCfg.AuthMode >= Ndis802_11AuthModeWPA)
				{
					Status = RTUSBEnqueueCmdFromNdis(pAdapter, OID_802_11_REMOVE_KEY, TRUE, pRemoveKey, wrq->u.data.length);
					DBGPRINT(RT_DEBUG_TRACE, "Set::OID_802_11_REMOVE_KEY, Remove WPA Key!!\n");
				}
				else
				{
					KeyIdx = pRemoveKey->KeyIndex;

					if (KeyIdx & 0x80000000)
					{
						// Should never set default bit when remove key
						Status	= -EINVAL;
						DBGPRINT(RT_DEBUG_TRACE, "Set::OID_802_11_REMOVE_KEY, Failed!!(Should never set default bit when remove key)\n");
					}
					else
					{
						KeyIdx = KeyIdx & 0x0fffffff;
						if (KeyIdx > 3)
						{
							Status	= -EINVAL;
							DBGPRINT(RT_DEBUG_TRACE, "Set::OID_802_11_REMOVE_KEY, Failed!!(KeyId[%d] out of range)\n", KeyIdx);
						}
						else
						{
							pAdapter->PortCfg.SharedKey[KeyIdx].KeyLen = 0;
							DBGPRINT(RT_DEBUG_TRACE, "Set::OID_802_11_REMOVE_KEY (id=0x%x, Len=%d-byte)\n", pRemoveKey->KeyIndex, pRemoveKey->Length);
						}
					}
				}
			}
			kfree(pRemoveKey);
			break;
		case OID_802_11_AUTHENTICATION_MODE:
			if (wrq->u.data.length != sizeof(NDIS_802_11_AUTHENTICATION_MODE)) 
				Status	= -EINVAL;
			else
			{
				if(copy_from_user(&AuthMode, wrq->u.data.pointer, wrq->u.data.length))
					Status = -EINVAL;
					
				if (AuthMode > Ndis802_11AuthModeMax)
				{
					Status	= -EINVAL;
					break;
				}
				else
				{
					if (pAdapter->PortCfg.AuthMode != AuthMode)
					{
						// Config has changed
						pAdapter->bConfigChanged = TRUE;
					}
					pAdapter->PortCfg.AuthMode = AuthMode;
				}
				pAdapter->PortCfg.PortSecured = WPA_802_1X_PORT_NOT_SECURED;
				DBGPRINT(RT_DEBUG_TRACE, "Set::OID_802_11_AUTHENTICATION_MODE (=%d) \n",pAdapter->PortCfg.AuthMode);
			}
			break;
		case OID_802_11_PRIVACY_FILTER:
			if (wrq->u.data.length != sizeof(NDIS_802_11_PRIVACY_FILTER))
				Status = -EINVAL;
			else 
			{
				if(copy_from_user(&Filter, wrq->u.data.pointer, wrq->u.data.length))
					Status = -EINVAL;
					
				if ((Filter == Ndis802_11PrivFilterAcceptAll) || (Filter == Ndis802_11PrivFilter8021xWEP))
					pAdapter->PortCfg.PrivacyFilter = Filter;
				else
					Status = -EINVAL;
			}
			DBGPRINT(RT_DEBUG_TRACE, "Set::OID_802_11_PRIVACY_FILTER (=%d) \n",pAdapter->PortCfg.PrivacyFilter);
			break;
		case OID_802_11_BSSID_LIST_SCAN:
			Now = jiffies;
			DBGPRINT(RT_DEBUG_TRACE, "Set::OID_802_11_BSSID_LIST_SCAN \n");


			if (pAdapter->ScanAllowed == FALSE)
			{
				DBGPRINT(RT_DEBUG_TRACE, "!!! Link UP, ignore this set::OID_802_11_BSSID_LIST_SCAN\n");
				pAdapter->PortCfg.IgnoredScanNumber = 99;
				return NDIS_STATUS_SUCCESS;
			}

			if ((pAdapter->MediaState == NdisMediaStateConnected) &&
				((pAdapter->PortCfg.AuthMode == Ndis802_11AuthModeWPA) || 
				(pAdapter->PortCfg.AuthMode == Ndis802_11AuthModeWPAPSK)) &&
				(pAdapter->PortCfg.PortSecured == WPA_802_1X_PORT_NOT_SECURED))
			{
				DBGPRINT(RT_DEBUG_TRACE, "!!! Link UP, Port Not Secured! ignore this set::OID_802_11_BSSID_LIST_SCAN\n");
				Status = NDIS_STATUS_SUCCESS;
				break;
			}

			Status =RTUSBEnqueueCmdFromNdis(pAdapter, OID_802_11_BSSID_LIST_SCAN, TRUE, NULL, 0);
		 			break;
		case OID_802_11_WEP_STATUS:
			if (wrq->u.data.length != sizeof(NDIS_802_11_WEP_STATUS))
				Status	= -EINVAL;
			else
			{
				if(copy_from_user(&WepStatus, wrq->u.data.pointer, wrq->u.data.length))
					Status = -EINVAL;

				// Since TKIP, AES, WEP are all supported. It should not have any invalid setting
				if (WepStatus <= Ndis802_11Encryption3KeyAbsent)
				{
					Status = RTUSBEnqueueCmdFromNdis(pAdapter, OID_802_11_WEP_STATUS, TRUE, &WepStatus, sizeof(NDIS_802_11_WEP_STATUS));
					pAdapter->PortCfg.WepStatus = WepStatus;
					pAdapter->PortCfg.OrigWepStatus = WepStatus;
					pAdapter->PortCfg.PairCipher = WepStatus;
					pAdapter->PortCfg.GroupCipher = WepStatus;
				}

				DBGPRINT(RT_DEBUG_TRACE, "Set::OID_802_11_WEP_STATUS (=%d)\n",WepStatus);
			}
			break;
		case OID_802_11_TX_POWER_LEVEL:
			if (wrq->u.data.length != sizeof(NDIS_802_11_TX_POWER_LEVEL))
				Status	= -EINVAL;
			else
			{
				if(copy_from_user(&TxPowerLevel, wrq->u.data.pointer, wrq->u.data.length))
					Status = -EINVAL;

				if (TxPowerLevel > MAX_TX_POWER_LEVEL)
					Status	= -EINVAL;
				else
					pAdapter->PortCfg.TxPower = (UCHAR)TxPowerLevel;
			}
			DBGPRINT(RT_DEBUG_TRACE, "Set::OID_802_11_TX_POWER_LEVEL (=%d) \n",TxPowerLevel);
			break;
		case OID_802_11_RSSI_TRIGGER:
			if (wrq->u.data.length != sizeof(NDIS_802_11_RSSI))
				Status = -EINVAL;
			else 
			{
				if(copy_from_user(&RssiTrigger, wrq->u.data.pointer, wrq->u.data.length))
					Status = -EINVAL;

				if (RssiTrigger > MAX_RSSI_TRIGGER || RssiTrigger < MIN_RSSI_TRIGGER) 
					Status = -EINVAL;
				else
				{
					pAdapter->PortCfg.RssiTrigger = (UCHAR)RssiTrigger + pAdapter->BBPTuningParameters.RSSIToDbmOffset;
					if (pAdapter->PortCfg.RssiTrigger > pAdapter->PortCfg.LastRssi)
						pAdapter->PortCfg.RssiTriggerMode = RSSI_TRIGGERED_UPON_BELOW_THRESHOLD;
					else
						pAdapter->PortCfg.RssiTriggerMode = RSSI_TRIGGERED_UPON_EXCCEED_THRESHOLD;
				}
			}
			DBGPRINT(RT_DEBUG_TRACE, "Set::OID_802_11_RSSI_TRIGGER (=%d)\n",RssiTrigger);
			break;
		case OID_802_11_FRAGMENTATION_THRESHOLD:
			if (wrq->u.data.length != sizeof(NDIS_802_11_FRAGMENTATION_THRESHOLD))
				Status	= -EINVAL;
			else
			{
				if(copy_from_user(&FragThresh, wrq->u.data.pointer, wrq->u.data.length))
					Status = -EINVAL;

				pAdapter->PortCfg.bFragmentZeroDisable = FALSE;
				if (FragThresh > MAX_FRAG_THRESHOLD || FragThresh < MIN_FRAG_THRESHOLD)
				{
					if (FragThresh == 0)
					{
						pAdapter->PortCfg.FragmentThreshold = MAX_FRAG_THRESHOLD;
						pAdapter->PortCfg.bFragmentZeroDisable = TRUE;
					}
					else
						Status	= -EINVAL;
				}
				else
					pAdapter->PortCfg.FragmentThreshold = (USHORT)FragThresh;
			}
			DBGPRINT(RT_DEBUG_TRACE, "Set::OID_802_11_FRAGMENTATION_THRESHOLD (=%d) \n",FragThresh);
			break;
		case OID_802_11_RTS_THRESHOLD:
			if (wrq->u.data.length != sizeof(NDIS_802_11_RTS_THRESHOLD))
				Status	= -EINVAL;
			else
			{
				if(copy_from_user(&RtsThresh, wrq->u.data.pointer, wrq->u.data.length))
					Status = -EINVAL;

				if (RtsThresh > MAX_RTS_THRESHOLD)
					Status	= -EINVAL;
				else
					pAdapter->PortCfg.RtsThreshold = (USHORT)RtsThresh;
			}
			DBGPRINT(RT_DEBUG_TRACE, "Set::OID_802_11_RTS_THRESHOLD (=%d)\n",RtsThresh);
			break;
		case OID_802_11_DESIRED_RATES:
			if (wrq->u.data.length != sizeof(NDIS_802_11_RATES))
				Status	= -EINVAL;
			else
			{
				if(copy_from_user(&aryRates, wrq->u.data.pointer, wrq->u.data.length))
					Status = -EINVAL;

				memset(pAdapter->PortCfg.DesiredRates, 0, MAX_LEN_OF_SUPPORTED_RATES);
				memcpy(pAdapter->PortCfg.DesiredRates, &aryRates, sizeof(NDIS_802_11_RATES));
				DBGPRINT(RT_DEBUG_TRACE, "Set::OID_802_11_DESIRED_RATES (%02x,%02x,%02x,%02x,%02x,%02x,%02x,%02x)\n",
					pAdapter->PortCfg.DesiredRates[0],pAdapter->PortCfg.DesiredRates[1],
					pAdapter->PortCfg.DesiredRates[2],pAdapter->PortCfg.DesiredRates[3],
					pAdapter->PortCfg.DesiredRates[4],pAdapter->PortCfg.DesiredRates[5],
					pAdapter->PortCfg.DesiredRates[6],pAdapter->PortCfg.DesiredRates[7] );
				// Changing DesiredRate may affect the MAX TX rate we used to TX frames out
				Status = RTUSBEnqueueCmdFromNdis(pAdapter, RT_OID_UPDATE_TX_RATE, TRUE, NULL, 0);
			}
			break;
		case OID_802_11_CONFIGURATION:
			if (wrq->u.data.length != sizeof(NDIS_802_11_CONFIGURATION))
				Status	= -EINVAL;
			else
			{
				if(copy_from_user(&Config, wrq->u.data.pointer, wrq->u.data.length))
					Status = -EINVAL;

				pConfig = &Config;
				pAdapter->PortCfg.IbssConfig.BeaconPeriod = (USHORT) pConfig->BeaconPeriod;
				pAdapter->PortCfg.IbssConfig.AtimWin = (USHORT) pConfig->ATIMWindow;
				MAP_KHZ_TO_CHANNEL_ID(pConfig->DSConfig, pAdapter->PortCfg.IbssConfig.Channel);
				DBGPRINT(RT_DEBUG_ERROR, "Set::OID_802_11_CONFIGURATION (BeacnPeriod=%d,AtimW=%d,Ch=%d)\n",
					pConfig->BeaconPeriod, pConfig->ATIMWindow, pAdapter->PortCfg.IbssConfig.Channel);
				// Config has changed
				pAdapter->bConfigChanged = TRUE;
			}
			break;
		case OID_802_11_POWER_MODE:
			if (wrq->u.data.length != sizeof(NDIS_802_11_POWER_MODE))
				Status = -EINVAL;
			else
			{
				if(copy_from_user(&PowerMode, wrq->u.data.pointer, wrq->u.data.length))
					Status = -EINVAL;

				// save user's policy here, but not change PortCfg.Psm immediately
				if (PowerMode == Ndis802_11PowerModeCAM) 
				{
					// clear PSM bit immediately
					MlmeSetPsmBit(pAdapter, PWR_ACTIVE);
					pAdapter->PortCfg.RecvDtim = TRUE;
					pAdapter->PortCfg.WindowsPowerMode = PowerMode;
				}
				else if (PowerMode == Ndis802_11PowerModeMAX_PSP) 
				{
					// do NOT turn on PSM bit here, wait until MlmeCheckForPsmChange()
					// to exclude certain situations.
					//	   MlmeSetPsmBit(pAdapter, PWR_SAVE);
					pAdapter->PortCfg.WindowsPowerMode = PowerMode;
					pAdapter->PortCfg.RecvDtim = TRUE;	// FALSE;
					pAdapter->PortCfg.DefaultListenCount = 5;
				}
				else if (PowerMode == Ndis802_11PowerModeFast_PSP) 
				{
					// do NOT turn on PSM bit here, wait until MlmeCheckForPsmChange()
					// to exclude certain situations.
					//	   MlmeSetPsmBit(pAdapter, PWR_SAVE);
					pAdapter->PortCfg.RecvDtim = TRUE;
					pAdapter->PortCfg.WindowsPowerMode = PowerMode;
					pAdapter->PortCfg.DefaultListenCount = 3;
				}
				else
					Status = -EINVAL;
			}
			DBGPRINT(RT_DEBUG_TRACE, "Set::OID_802_11_POWER_MODE (=%d)\n",PowerMode);
			break;
		case RT_OID_802_11_PREAMBLE:
			if (wrq->u.data.length != sizeof(RT_802_11_PREAMBLE))
				Status	= -EINVAL;
			else
			{
				if(copy_from_user(&Preamble, wrq->u.data.pointer, wrq->u.data.length))
					Status = -EINVAL;

				if ((Preamble == Rt802_11PreambleShort) || (Preamble == Rt802_11PreambleLong) || (Preamble == Rt802_11PreambleAuto))
				{
					Status = RTUSBEnqueueCmdFromNdis(pAdapter, RT_OID_802_11_PREAMBLE, TRUE, &Preamble, sizeof(RT_802_11_PREAMBLE));
				}
				else
				{
					Status = EINVAL;
					break;
				}
				DBGPRINT(RT_DEBUG_TRACE, "Set::RT_OID_802_11_SET_PREAMBLE (=%d)\n", Preamble);
			}
			break;
		case RT_OID_802_11_RADIO:
			if (wrq->u.data.length != sizeof(BOOLEAN))
				Status	= -EINVAL;
			else
			{
				Status	= -EINVAL;
				if(copy_from_user(&RadioState, wrq->u.data.pointer, wrq->u.data.length))
					Status = -EINVAL;

				DBGPRINT(RT_DEBUG_TRACE, "Set::RT_OID_802_11_RADIO (=%d)\n", RadioState);
				if (pAdapter->PortCfg.bSwRadio != RadioState)
				{
					pAdapter->PortCfg.bSwRadio = RadioState;
					if (pAdapter->PortCfg.bRadio != (pAdapter->PortCfg.bHwRadio && pAdapter->PortCfg.bSwRadio))
					{
						pAdapter->PortCfg.bRadio = (pAdapter->PortCfg.bHwRadio && pAdapter->PortCfg.bSwRadio);
						Status = RTUSBEnqueueCmdFromNdis(pAdapter, RT_OID_SET_RADIO, TRUE, NULL, 0);
					}
				}
			}
			break;
		case RT_OID_802_11_COUNTRY_REGION:
			if (wrq->u.data.length != sizeof(CountryRegion))
				Status = -EINVAL;
			else if (!(pAdapter->PortCfg.CountryRegion & 0x80))	// Only avaliable when EEPROM not programming
			{
				ULONG	TmpPhy;
				
				if(copy_from_user(&pAdapter->PortCfg.CountryRegion, wrq->u.data.pointer, wrq->u.data.length))
					Status = -EINVAL;

				TmpPhy = pAdapter->PortCfg.PhyMode;
			    	pAdapter->PortCfg.PhyMode = 0xff;
				// Build all corresponding channel information
				Status = RTUSBEnqueueCmdFromNdis(pAdapter, RT_OID_802_11_PHY_MODE, TRUE, &TmpPhy, sizeof(TmpPhy));
				DBGPRINT(RT_DEBUG_ERROR, "Set::RT_OID_802_11_COUNTRY_REGION (=%d) \n", pAdapter->PortCfg.CountryRegion);
			}
			break;
		case RT_OID_802_11_PHY_MODE:
			if (wrq->u.data.length != sizeof(RT_802_11_PHY_MODE))
				Status	= -EINVAL;
			else
			{
				if(copy_from_user(&PhyMode, wrq->u.data.pointer, wrq->u.data.length))
					Status = -EINVAL;

				Status = RTUSBEnqueueCmdFromNdis(pAdapter, RT_OID_802_11_PHY_MODE, TRUE, &PhyMode, sizeof(RT_802_11_PHY_MODE));
				DBGPRINT(RT_DEBUG_ERROR, "Set::RT_OID_802_11_PHY_MODE  (=%d)\n", PhyMode);
			}
			break;
		case RT_OID_802_11_STA_CONFIG:
			if (wrq->u.data.length  != sizeof(RT_802_11_STA_CONFIG))
			{
				Status	= -EINVAL;
			}
			else 
			{
				Status =  (RTUSBEnqueueCmdFromNdis(pAdapter, RT_OID_802_11_STA_CONFIG, TRUE, wrq->u.data.pointer, sizeof(RT_802_11_STA_CONFIG)));
			}
			break;
		case RT_OID_802_11_RESET_COUNTERS:
			memset(&pAdapter->WlanCounters, 0, sizeof(COUNTER_802_11));
			memset(&pAdapter->Counters, 0, sizeof(COUNTER_802_3));
			memset(&pAdapter->RalinkCounters, 0, sizeof(COUNTER_RALINK));
			memset(&pAdapter->Mlme.PrevWlanCounters, 0, sizeof(COUNTER_802_11));
			 {
				return(RTUSBEnqueueCmdFromNdis(pAdapter, RT_OID_802_11_RESET_COUNTERS, TRUE, NULL, 0));
			 }
			DBGPRINT(RT_DEBUG_INFO, "Set::RT_OID_802_11_RESET_COUNTERS \n");
			break;
#if 1
		// For WPA PSK PMK key
		case RT_OID_802_11_ADD_WPA:
			DBGPRINT(RT_DEBUG_ERROR, "!!!!!!!!!!!!!!!!!!!!!Set::RT_OID_802_11_ADD_WPA \n");	
			if (wrq->u.data.length > sizeof(Key))  
				Status = -EINVAL;
            		else
                       {
				if(copy_from_user(&Key, wrq->u.data.pointer, wrq->u.data.length))
					Status = -EINVAL;

				if (Key.Length != wrq->u.data.length)
				{
					Status	= -EINVAL;
					DBGPRINT(RT_DEBUG_TRACE, "Set::RT_OID_802_11_ADD_WPA, Failed!!\n");
				}
				else
				{
					if ((pAdapter->PortCfg.AuthMode != Ndis802_11AuthModeWPAPSK) && (pAdapter->PortCfg.AuthMode != Ndis802_11AuthModeWPANone))
					{
						Status = -EOPNOTSUPP;
						DBGPRINT(RT_DEBUG_TRACE, "Set::RT_OID_802_11_ADD_WPA, Failed!! [AuthMode != WPAPSK]\n");
					}
					else // Only for WPA PSK mode
					{
						pAdapter->PortCfg.PskKey.KeyLen = (UCHAR) Key.KeyLength;
						memcpy(pAdapter->PortCfg.PskKey.Key, Key.KeyMaterial, Key.KeyLength);

						if (pAdapter->PortCfg.AuthMode >= Ndis802_11AuthModeWPA)
						{
							RTMPWPAAddKeyProc(pAdapter, &Key);
						}
						
						// Use RaConfig as PSK agent.
						// Start STA supplicant state machine
						pAdapter->PortCfg.WpaState = SS_START;
#ifdef RT2500_DBG
	{
						int	i;
						DBGPRINT(RT_DEBUG_LOUD, "RT_OID_802_11_ADD_WPA Key => \n");
						DBGPRINT(RT_DEBUG_LOUD, "    ");
						for (i = 0; i < Key.KeyLength; i++)
						{
							DBGPRINT_RAW(RT_DEBUG_LOUD, "%02x:", pAdapter->PortCfg.PskKey.Key[i]);
							if (i%16 == 15) {
								DBGPRINT_RAW(RT_DEBUG_LOUD, "\n");
								DBGPRINT(RT_DEBUG_LOUD, "    ");
							}
						}
						DBGPRINT_RAW(RT_DEBUG_LOUD, "\n");
	}
#endif
						DBGPRINT(RT_DEBUG_TRACE, "Set::RT_OID_802_11_ADD_WPA (id=0x%x, Len=%d-byte)\n", Key.KeyIndex, Key.KeyLength);
					}
				}

			}
		break;
#endif            
		default:
			DBGPRINT(RT_DEBUG_TRACE, "Set::unknown IOCTL's subcmd = 0x%08x\n", cmd);
			Status = -EOPNOTSUPP;
			break;
	}

	return Status;
}



UCHAR	BCAST[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
/*
	========================================================================
	
	Routine Description:
		Add WPA key process

	Arguments:
		pAdapter						Pointer to our adapter
		pBuf							Pointer to the where the key stored

	Return Value:
		NDIS_SUCCESS					Add key successfully

	Note:
		
	========================================================================
*/
NDIS_STATUS	RTMPWPAAddKeyProc(
	IN	PRT2570ADAPTER	pAdapter,
	IN	PVOID			pBuf)
{
	PNDIS_802_11_KEY	pKey;
	ULONG				KeyIdx;
	NDIS_STATUS			Status;
	
	PUCHAR		pTxMic, pRxMic;
	BOOLEAN 	bTxKey; 		// Set the key as transmit key
	BOOLEAN 	bPairwise;		// Indicate the key is pairwise key
	BOOLEAN 	bKeyRSC;		// indicate the receive  SC set by KeyRSC value.
								// Otherwise, it will set by the NIC.
	BOOLEAN 	bAuthenticator; // indicate key is set by authenticator.
	INT 		i, PairwiseIdx;
	TXRX_CSR0_STRUC  TxRxCsr0;
	UCHAR		ZeroKey[4 * 16];
	
	DBGPRINT(RT_DEBUG_TEMP,"===>RTMPWPAAddKeyProc\n" );
	pKey = (PNDIS_802_11_KEY) pBuf;
	KeyIdx = pKey->KeyIndex & 0xff;
	DBGPRINT(RT_DEBUG_TEMP,"RTMPWPAAddKeyProc KeyIdx = %x\n", pKey->KeyIndex );
	// Bit 31 of Add-key, Tx Key
	bTxKey		   = (pKey->KeyIndex & 0x80000000) ? TRUE : FALSE;
	// Bit 30 of Add-key PairwiseKey
	bPairwise	   = (pKey->KeyIndex & 0x40000000) ? TRUE : FALSE;
	// Bit 29 of Add-key KeyRSC
	bKeyRSC 	   = (pKey->KeyIndex & 0x20000000) ? TRUE : FALSE;
	// Bit 28 of Add-key Authenticator
	bAuthenticator = (pKey->KeyIndex & 0x10000000) ? TRUE : FALSE;

	memset(ZeroKey, 0, 4 * 16);
	// 1. Check Group / Pairwise Key
	if (bPairwise)	// Pairwise Key
	{
		// 1. KeyIdx must be 0, otherwise, return NDIS_STATUS_INVALID_DATA
		if (KeyIdx != 0)
			return(NDIS_STATUS_FAILURE);
		
		// 2. Check bTx, it must be true, otherwise, return NDIS_STATUS_INVALID_DATA
		if (bTxKey == FALSE)
			return(NDIS_STATUS_FAILURE);

		// 3. If BSSID is not all 0xff, return NDIS_STATUS_INVALID_DATA
		if ((memcmp(pKey->BSSID, BCAST, 6) == 0))
			return(NDIS_STATUS_FAILURE);
			
		// 4. Selct RxMic / TxMic based on Supp / Authenticator
		if (pAdapter->PortCfg.AuthMode == Ndis802_11AuthModeWPANone)
		{
			// for WPA-None Tx, Rx MIC is the same
			pTxMic = (PUCHAR) (&pKey->KeyMaterial) + 16;
			pRxMic = pTxMic;
		}
		else if (bAuthenticator == TRUE)
		{
			pTxMic = (PUCHAR) (&pKey->KeyMaterial) + 16;
			pRxMic = (PUCHAR) (&pKey->KeyMaterial) + 24;
		}
		else
		{
			pRxMic = (PUCHAR) (&pKey->KeyMaterial) + 16;
			pTxMic = (PUCHAR) (&pKey->KeyMaterial) + 24;
		}
		
		// 5. Find the old entry to overwrite or find an empty entry.
		PairwiseIdx = 0;
		for (i = 0; i < PAIRWISE_KEY_NO; i++)
		{
			if (pAdapter->PortCfg.PairwiseKey[i].KeyLen == 0)
			{
				PairwiseIdx = i;
				break;
			}
			else if ((memcmp(pAdapter->PortCfg.PairwiseKey[i].BssId, pKey->BSSID, 6) == 0))
			{
				// Found the old entry
				PairwiseIdx = i;
				break;
			}
		}
		// If there is no match and no empty pairwise key, we have to replace an old one
		// which will be index 0 in our case.

		// 6. Check RxTsc
		if (bKeyRSC == TRUE)
		{
			memcpy(&pAdapter->PortCfg.PairwiseKey[PairwiseIdx].RxTsc, &pKey->KeyRSC, 6);
		}
		else
		{
			memset(pAdapter->PortCfg.PairwiseKey[PairwiseIdx].RxTsc, 0, 6);
		}
		
		// 7. Copy information into Pairwise Key structure.
		// pKey->KeyLength will include TxMic and RxMic, therefore, we use 16 bytes hardcoded.
		pAdapter->PortCfg.PairwiseKey[PairwiseIdx].KeyLen = 16;		
		memset(pAdapter->PortCfg.PairwiseKey[PairwiseIdx].Key, 0, 16);
		memcpy(pAdapter->PortCfg.PairwiseKey[PairwiseIdx].Key, &pKey->KeyMaterial, 16);
		memcpy(pAdapter->PortCfg.PairwiseKey[PairwiseIdx].RxMic, pRxMic, 8);
		memcpy(pAdapter->PortCfg.PairwiseKey[PairwiseIdx].TxMic, pTxMic, 8);
		memcpy(pAdapter->PortCfg.PairwiseKey[PairwiseIdx].BssId, pKey->BSSID, 6);
		// Init TxTsc to one based on WiFi WPA specs
		pAdapter->PortCfg.PairwiseKey[PairwiseIdx].TxTsc[0] = 1;
		pAdapter->PortCfg.PairwiseKey[PairwiseIdx].TxTsc[1] = 0;
		pAdapter->PortCfg.PairwiseKey[PairwiseIdx].TxTsc[2] = 0;
		pAdapter->PortCfg.PairwiseKey[PairwiseIdx].TxTsc[3] = 0;
		pAdapter->PortCfg.PairwiseKey[PairwiseIdx].TxTsc[4] = 0;
		pAdapter->PortCfg.PairwiseKey[PairwiseIdx].TxTsc[5] = 0;

		RTUSBReadMACRegister(pAdapter, TXRX_CSR0, &TxRxCsr0.value);
		TxRxCsr0.field.KeyID |= (0x01 << KeyIdx);
		RTUSBWriteMACRegister(pAdapter, TXRX_CSR0, TxRxCsr0.value);
		RTUSBMultiWriteMAC(pAdapter, (USHORT)(SEC_CSR0 + KeyIdx * 0x10), pAdapter->PortCfg.PairwiseKey[PairwiseIdx].Key, pAdapter->PortCfg.PairwiseKey[PairwiseIdx].KeyLen);

		Status = NDIS_STATUS_SUCCESS;
		
		DBGPRINT(RT_DEBUG_TEMP,"Add Pairwise TKIP Key %d= ",PairwiseIdx);
		DBGPRINT(RT_DEBUG_TEMP,"Pairwise TKIP Key = ");
		for (i = 0; i < 16; i++)
		{
			DBGPRINT_RAW(RT_DEBUG_INFO,"%02x:", pAdapter->PortCfg.PairwiseKey[PairwiseIdx].Key[i]);
		}
		DBGPRINT_RAW(RT_DEBUG_INFO,"\n");						
		DBGPRINT(RT_DEBUG_INFO,"TKIP Rx MIC Key = ");
		for (i = 0; i < 8; i++)
		{
			DBGPRINT_RAW(RT_DEBUG_INFO,"%02x:", pAdapter->PortCfg.PairwiseKey[PairwiseIdx].RxMic[i]);
		}
		DBGPRINT_RAW(RT_DEBUG_INFO,"\n");						
		DBGPRINT(RT_DEBUG_INFO,"TKIP Tx MIC Key = ");
		for (i = 0; i < 8; i++)
		{
			DBGPRINT_RAW(RT_DEBUG_INFO,"%02x:", pAdapter->PortCfg.PairwiseKey[PairwiseIdx].TxMic[i]);
		}
		DBGPRINT_RAW(RT_DEBUG_INFO,"\n");						
		DBGPRINT(RT_DEBUG_INFO,"TKIP RxTSC = ");
		for (i = 0; i < 6; i++)
		{
			DBGPRINT_RAW(RT_DEBUG_INFO,"%02x:", pAdapter->PortCfg.PairwiseKey[PairwiseIdx].RxTsc[i]);
		}
		DBGPRINT_RAW(RT_DEBUG_INFO,"\n");						
		DBGPRINT(RT_DEBUG_INFO,"BSSID:%02x:%02x:%02x:%02x:%02x:%02x \n",
			pKey->BSSID[0],pKey->BSSID[1],pKey->BSSID[2],pKey->BSSID[3],pKey->BSSID[4],pKey->BSSID[5]);
		
	}
	else	// Group Key
	{
		// 1. Check BSSID, if not current BSSID or Bcast, return NDIS_STATUS_INVALID_DATA
		//if ((memcmp(&pKey->BSSID, &BCAST, 6) != 0) &&
		//	(memcmp(&pKey->BSSID, &pAdapter->PortCfg.Bssid, 6) != 0))
		//	return(NDIS_STATUS_FAILURE);

		// 2. Check Key index for supported Group Key
		if (KeyIdx >= GROUP_KEY_NO)
			return(NDIS_STATUS_FAILURE);
		
		// 3. Set as default Tx Key if bTxKey is TRUE
		if (bTxKey == TRUE)
			pAdapter->PortCfg.DefaultKeyId = (UCHAR) KeyIdx;
		
		// 4. Selct RxMic / TxMic based on Supp / Authenticator
		if (pAdapter->PortCfg.AuthMode == Ndis802_11AuthModeWPANone)
		{
			// for WPA-None Tx, Rx MIC is the same
			pTxMic = (PUCHAR) (&pKey->KeyMaterial) + 16;
			pRxMic = pTxMic;
		}
		else if (bAuthenticator == TRUE)
		{
			pTxMic = (PUCHAR) (&pKey->KeyMaterial) + 16;
			pRxMic = (PUCHAR) (&pKey->KeyMaterial) + 24;
		}
		else
		{
			pRxMic = (PUCHAR) (&pKey->KeyMaterial) + 16;
			pTxMic = (PUCHAR) (&pKey->KeyMaterial) + 24;
		}
		
		// 5. Check RxTsc
		if (bKeyRSC == TRUE)
		{
			memcpy(pAdapter->PortCfg.GroupKey[KeyIdx].RxTsc, &pKey->KeyRSC, 6);
		}
		else
		{
			memset(pAdapter->PortCfg.GroupKey[KeyIdx].RxTsc, 0, 6);
		}

		// 6. Copy information into Group Key structure.
		// pKey->KeyLength will include TxMic and RxMic, therefore, we use 16 bytes hardcoded.
		pAdapter->PortCfg.GroupKey[KeyIdx].KeyLen = 16;		
		memset(pAdapter->PortCfg.GroupKey[KeyIdx].Key, 0, 16);
		memcpy(pAdapter->PortCfg.GroupKey[KeyIdx].Key, &pKey->KeyMaterial, 16);
		memcpy(pAdapter->PortCfg.GroupKey[KeyIdx].RxMic, pRxMic, 8);
		memcpy(pAdapter->PortCfg.GroupKey[KeyIdx].TxMic, pTxMic, 8);
		memcpy(pAdapter->PortCfg.GroupKey[KeyIdx].BssId, pKey->BSSID, 6);
		// Init TxTsc to one based on WiFi WPA specs
		pAdapter->PortCfg.GroupKey[KeyIdx].TxTsc[0] = 1;
		pAdapter->PortCfg.GroupKey[KeyIdx].TxTsc[1] = 0;
		pAdapter->PortCfg.GroupKey[KeyIdx].TxTsc[2] = 0;
		pAdapter->PortCfg.GroupKey[KeyIdx].TxTsc[3] = 0;
		pAdapter->PortCfg.GroupKey[KeyIdx].TxTsc[4] = 0;
		pAdapter->PortCfg.GroupKey[KeyIdx].TxTsc[5] = 0;
		// 802.1x port control
		pAdapter->PortCfg.PortSecured = WPA_802_1X_PORT_SECURED;

		RTUSBReadMACRegister(pAdapter, TXRX_CSR0, &TxRxCsr0.value);
		// a. If BSSID is broadcast, remove all group keys indexed
		TxRxCsr0.field.KeyID |= (0x01 << KeyIdx);
		RTUSBWriteMACRegister(pAdapter, TXRX_CSR0, TxRxCsr0.value);
		if (pAdapter->PortCfg.AuthMode == Ndis802_11AuthModeWPANone)
		{
			RTUSBMultiWriteMAC(pAdapter, (USHORT)(SEC_CSR0 + KeyIdx * 0x10), pAdapter->PortCfg.GroupKey[KeyIdx].Key, 16);
		}
		else
		{
			RTUSBMultiWriteMAC(pAdapter, (USHORT)(SEC_CSR0 + KeyIdx * 0x10), pAdapter->PortCfg.GroupKey[KeyIdx].Key, 16);
		}
		DBGPRINT(RT_DEBUG_TRACE, "AddGroupKey::Use Hardware to decript broadcast/Mulitcast packet.\n");

		Status = NDIS_STATUS_SUCCESS;
		// c. For WEP compatibility
		if (pAdapter->PortCfg.AuthMode == Ndis802_11AuthModeWPANone)
		{
			pAdapter->PortCfg.SharedKey[KeyIdx].KeyLen = 0;
		}

		DBGPRINT(RT_DEBUG_ERROR,"Group TKIP Key =\n ");
		for (i = 0; i < 16; i++)
		{
			DBGPRINT_RAW(RT_DEBUG_ERROR,"%02x:", pAdapter->PortCfg.GroupKey[KeyIdx].Key[i]);
		}
		DBGPRINT_RAW(RT_DEBUG_ERROR,"\n");						
		DBGPRINT(RT_DEBUG_TRACE,"TKIP Rx MIC Key = \n");
		for (i = 0; i < 8; i++)
		{
			DBGPRINT_RAW(RT_DEBUG_TRACE,"%02x:", pAdapter->PortCfg.GroupKey[KeyIdx].RxMic[i]);
		}
		DBGPRINT_RAW(RT_DEBUG_TRACE,"\n");						
		DBGPRINT(RT_DEBUG_TRACE,"TKIP Tx MIC Key = \n");
		for (i = 0; i < 8; i++)
		{
			DBGPRINT_RAW(RT_DEBUG_TRACE,"%02x:", pAdapter->PortCfg.GroupKey[KeyIdx].TxMic[i]);
		}
		DBGPRINT_RAW(RT_DEBUG_TRACE,"\n");						
		DBGPRINT(RT_DEBUG_TRACE,"TKIP RxTSC =\n ");
		for (i = 0; i < 6; i++)
		{
			DBGPRINT_RAW(RT_DEBUG_TRACE,"%02x:", pAdapter->PortCfg.GroupKey[KeyIdx].RxTsc[i]);
		}
		DBGPRINT_RAW(RT_DEBUG_TRACE,"\n");						
		DBGPRINT(RT_DEBUG_INFO,"BSSID:%02x:%02x:%02x:%02x:%02x:%02x \n",
			pKey->BSSID[0],pKey->BSSID[1],pKey->BSSID[2],pKey->BSSID[3],pKey->BSSID[4],pKey->BSSID[5]);
	
		// For WEP compatibility, in case it use OID_ADD_KEY, not OID_ADD_WEP
		if (pAdapter->PortCfg.AuthMode == Ndis802_11AuthModeWPANone)
		{
			pAdapter->PortCfg.SharedKey[KeyIdx].KeyLen = (UCHAR) pKey->KeyLength;
			memcpy(pAdapter->PortCfg.SharedKey[KeyIdx].Key, &pKey->KeyMaterial, pKey->KeyLength);
		}
	}
	return (Status);
}

/*
	========================================================================
	
	Routine Description:
		Remove WPA Key process

	Arguments:
		pAdapter						Pointer to our adapter
		pBuf							Pointer to the where the key stored

	Return Value:
		NDIS_SUCCESS					Add key successfully

	Note:
		
	========================================================================
*/
NDIS_STATUS	RTMPWPARemoveKeyProc(
	IN	PRT2570ADAPTER	pAdapter,
	IN	PVOID			pBuf)
{
	PNDIS_802_11_REMOVE_KEY	pKey;
	ULONG					KeyIdx;
	NDIS_STATUS				Status = NDIS_STATUS_FAILURE;
	
	BOOLEAN 	bTxKey; 		// Set the key as transmit key
	BOOLEAN 	bPairwise;		// Indicate the key is pairwise key
	BOOLEAN 	bKeyRSC;		// indicate the receive  SC set by KeyRSC value.
								// Otherwise, it will set by the NIC.
	BOOLEAN 	bAuthenticator; // indicate key is set by authenticator.
	INT 		i;
	USHORT		temp;
	
	pKey = (PNDIS_802_11_REMOVE_KEY) pBuf;
	KeyIdx = pKey->KeyIndex & 0xff;
	// Bit 31 of Add-key, Tx Key
	bTxKey		   = (pKey->KeyIndex & 0x80000000) ? TRUE : FALSE;
	// Bit 30 of Add-key PairwiseKey
	bPairwise	   = (pKey->KeyIndex & 0x40000000) ? TRUE : FALSE;
	// Bit 29 of Add-key KeyRSC
	bKeyRSC 	   = (pKey->KeyIndex & 0x20000000) ? TRUE : FALSE;
	// Bit 28 of Add-key Authenticator
	bAuthenticator = (pKey->KeyIndex & 0x10000000) ? TRUE : FALSE;

	// 1. If bTx is TRUE, return failure information
	if (bTxKey == TRUE)
		return(NDIS_STATUS_FAILURE);

	// 2. Check Pairwise Key
	if (bPairwise)
	{
		// a. If BSSID is broadcast, remove all pairwise keys.
		if ((memcmp(&pKey->BSSID, &BCAST, 6) == 0))
		{
			for (i = 0; i < PAIRWISE_KEY_NO; i++)
			{
				pAdapter->PortCfg.PairwiseKey[i].KeyLen = 0;
			}
			Status = NDIS_STATUS_SUCCESS;
//			RTUSBReadMACRegister(pAdapter, TXRX_CSR0, &temp);
//			RTUSBReadMACRegister(pAdapter, TXRX_CSR0, temp & 0xfdff);
		}

		// b. If not broadcast, remove the pairwise specified by BSSID
		else
		{
			for (i = 0; i < PAIRWISE_KEY_NO; i++)
			{
				if ((memcmp(pAdapter->PortCfg.PairwiseKey[i].BssId, pKey->BSSID, 6) == 0))
				{
					pAdapter->PortCfg.PairwiseKey[i].KeyLen = 0;
//					RTUSBReadMACRegister(pAdapter, TXRX_CSR0, &temp);
//					RTUSBReadMACRegister(pAdapter, TXRX_CSR0, temp & 0xfdff);
					Status = NDIS_STATUS_SUCCESS;
					break;
				}
			}
			
		}
		// c. If no pairwise supported, delete Group Key 0.
		//	  The will be false since we do support pairwise keys.
	}
	// 3. Group Key
	else
	{
		// a. If BSSID is broadcast, remove all group keys indexed
		if ((memcmp(&pKey->BSSID, &BCAST, 6) == 0))
		{
			pAdapter->PortCfg.GroupKey[KeyIdx].KeyLen = 0;
			RTUSBReadMACRegister(pAdapter, TXRX_CSR0, &temp);
			RTUSBWriteMACRegister(pAdapter, TXRX_CSR0, temp & (~(0x200 << KeyIdx)));
			Status = NDIS_STATUS_SUCCESS;
		}

		// b. If BSSID matched, delte the group key indexed.
		else if ((memcmp(pAdapter->PortCfg.GroupKey[KeyIdx].BssId, pKey->BSSID, 6) == 0))
		{
			pAdapter->PortCfg.GroupKey[KeyIdx].KeyLen = 0;
			RTUSBReadMACRegister(pAdapter, TXRX_CSR0, &temp);
			RTUSBWriteMACRegister(pAdapter, TXRX_CSR0, temp & (~(0x200 << KeyIdx)));
			Status = NDIS_STATUS_SUCCESS;
		}
	}
	
	return (Status);
}


/*
	========================================================================
	
	Routine Description:
		Remove All WPA Keys

	Arguments:
		pAdapter						Pointer to our adapter

	Return Value:
		None

	Note:
		
	========================================================================
*/
VOID	RTMPWPARemoveAllKeys(
	IN	PRT2570ADAPTER	pAdapter)
{
	INT i;
	USHORT	temp;

	// For WPA-None, there is no need to remove it, since WinXP won't set it again after
	// Link up. And it will be replaced if user changed it.
	if (pAdapter->PortCfg.AuthMode == Ndis802_11AuthModeWPANone)
		return;
	
	for (i = 0; i < PAIRWISE_KEY_NO; i++)
	{
		pAdapter->PortCfg.PairwiseKey[i].KeyLen = 0;
	}
	
	for (i = 0; i < GROUP_KEY_NO; i++)
	{
		pAdapter->PortCfg.GroupKey[i].KeyLen = 0;
	}

	RTUSBReadMACRegister(pAdapter, TXRX_CSR0, &temp);
	RTUSBWriteMACRegister(pAdapter, TXRX_CSR0, temp & 0xe1ff);
}

/*
	========================================================================
	Routine Description:
		Change NIC PHY mode. Re-association may be necessary. possible settings
		include - PHY_11B, PHY_11BG_MIXED, PHY_11A, and PHY_11ABG_MIXED 

	Arguments:
		pAdapter - Pointer to our adapter
		phymode  - 
	========================================================================
*/
VOID	RTMPSetPhyMode(
	IN	PRT2570ADAPTER	pAdapter,
	IN	ULONG phymode)
{
	DBGPRINT(RT_DEBUG_ERROR,"RTMPSetPhyMode(=%d)\n", phymode);
	
	// the selected phymode must be supported by the RF IC encoded in E2PROM
	if (pAdapter->PortCfg.RfType == RFIC_2426)
	{
		phymode = PHY_11B;
	}
	else if (pAdapter->PortCfg.RfType < RFIC_5222)
	{
		if (phymode == PHY_11A)
			phymode = PHY_11BG_MIXED;
	}
		
	// if no change, do nothing
	if (pAdapter->PortCfg.PhyMode == phymode)
		return;

	pAdapter->PortCfg.PhyMode = (UCHAR)phymode;
	BuildChannelList(pAdapter);
	pAdapter->PortCfg.IbssConfig.Channel = FirstChannel(pAdapter);
	pAdapter->PortCfg.Channel = FirstChannel(pAdapter);
	AsicSwitchChannel(pAdapter, pAdapter->PortCfg.Channel);
	AsicLockChannel(pAdapter, pAdapter->PortCfg.Channel);
	
	switch (phymode) {
		case PHY_11B:
	DBGPRINT(RT_DEBUG_TEMP,"PHY_11B\n");
			pAdapter->PortCfg.IbssConfig.SupportedRates[0]	= 0x82;    // 1 mbps, in units of 0.5 Mbps, basic rate
			pAdapter->PortCfg.IbssConfig.SupportedRates[1]	= 0x84;    // 2 mbps, in units of 0.5 Mbps, basic rate
			pAdapter->PortCfg.IbssConfig.SupportedRates[2]	= 0x8B;    // 5.5 mbps, in units of 0.5 Mbps, basic rate
			pAdapter->PortCfg.IbssConfig.SupportedRates[3]	= 0x96;    // 11 mbps, in units of 0.5 Mbps, basic rate
			pAdapter->PortCfg.IbssConfig.SupportedRatesLen	= 4;
			pAdapter->PortCfg.SupportedRates[0]  = 0x82;	// 1 mbps, in units of 0.5 Mbps, basic rate
			pAdapter->PortCfg.SupportedRates[1]  = 0x84;	// 2 mbps, in units of 0.5 Mbps, basic rate
			pAdapter->PortCfg.SupportedRates[2]  = 0x8B;	// 5.5 mbps, in units of 0.5 Mbps
			pAdapter->PortCfg.SupportedRates[3]  = 0x96;	// 11 mbps, in units of 0.5 Mbps, basic rate
			pAdapter->PortCfg.SupportedRatesLen  = 4;
			pAdapter->PortCfg.DesiredRates[0]  = 2; 	// 1 mbps, in units of 0.5 Mbps
			pAdapter->PortCfg.DesiredRates[1]  = 4; 	// 2 mbps, in units of 0.5 Mbps
			pAdapter->PortCfg.DesiredRates[2]  = 11;	// 5.5 mbps, in units of 0.5 Mbps
			pAdapter->PortCfg.DesiredRates[3]  = 22;	// 11 mbps, in units of 0.5 Mbps
			pAdapter->PortCfg.DesiredRates[4]  = 0;
			pAdapter->PortCfg.DesiredRates[5]  = 0;
			pAdapter->PortCfg.DesiredRates[6]  = 0;
			pAdapter->PortCfg.DesiredRates[7]  = 0;
			pAdapter->PortCfg.DesiredRates[8]  = 0;
			pAdapter->PortCfg.DesiredRates[9]  = 0;
			pAdapter->PortCfg.DesiredRates[10] = 0;
			pAdapter->PortCfg.DesiredRates[11] = 0;
			break;
			
		case PHY_11BG_MIXED:
		case PHY_11ABG_MIXED:
	DBGPRINT(RT_DEBUG_TEMP,"PHY_11BG_MIXED\n");
			pAdapter->PortCfg.IbssConfig.SupportedRates[0]	= 0x82;    // 1 mbps, in units of 0.5 Mbps, basic rate
			pAdapter->PortCfg.IbssConfig.SupportedRates[1]	= 0x84;    // 2 mbps, in units of 0.5 Mbps, basic rate
			pAdapter->PortCfg.IbssConfig.SupportedRates[2]	= 0x8B;    // 5.5 mbps, in units of 0.5 Mbps, basic rate
			pAdapter->PortCfg.IbssConfig.SupportedRates[3]	= 0x96;    // 11 mbps, in units of 0.5 Mbps, basic rate
			pAdapter->PortCfg.IbssConfig.SupportedRates[4]	= 0x8C;    // 6 mbps, in units of 0.5 Mbps, basic rate
			pAdapter->PortCfg.IbssConfig.SupportedRates[5]	= 0x12;    // 9 mbps, in units of 0.5 Mbps
			pAdapter->PortCfg.IbssConfig.SupportedRates[6]	= 0x98;    // 12 mbps, in units of 0.5 Mbps, basic rate
			pAdapter->PortCfg.IbssConfig.SupportedRates[7]	= 0x24;    // 18 mbps, in units of 0.5 Mbps
			pAdapter->PortCfg.IbssConfig.SupportedRates[8]	= 0xb0;    // 24 mbps, in units of 0.5 Mbps, basic rate
			pAdapter->PortCfg.IbssConfig.SupportedRates[9]	= 0x48;    // 36 mbps, in units of 0.5 Mbps
			pAdapter->PortCfg.IbssConfig.SupportedRates[10] = 0x60;    // 48 mbps, in units of 0.5 Mbps
			pAdapter->PortCfg.IbssConfig.SupportedRates[11] = 0x6c;    // 54 mbps, in units of 0.5 Mbps
			pAdapter->PortCfg.IbssConfig.SupportedRatesLen	= 12;
			pAdapter->PortCfg.SupportedRates[0]  = 0x82;	// 1 mbps, in units of 0.5 Mbps, basic rate
			pAdapter->PortCfg.SupportedRates[1]  = 0x84;	// 2 mbps, in units of 0.5 Mbps, basic rate
			pAdapter->PortCfg.SupportedRates[2]  = 0x8B;	// 5.5 mbps, in units of 0.5 Mbps, basic rate
			pAdapter->PortCfg.SupportedRates[3]  = 0x96;	// 11 mbps, in units of 0.5 Mbps, basic rate
			pAdapter->PortCfg.SupportedRates[4]  = 0x8C;	// 6 mbps, in units of 0.5 Mbps, basic rate
			pAdapter->PortCfg.SupportedRates[5]  = 0x12;	// 9 mbps, in units of 0.5 Mbps
			pAdapter->PortCfg.SupportedRates[6]  = 0x98;	// 12 mbps, in units of 0.5 Mbps, basic rate
			pAdapter->PortCfg.SupportedRates[7]  = 0x24;	// 18 mbps, in units of 0.5 Mbps
			pAdapter->PortCfg.SupportedRates[8]  = 0xb0;	// 24 mbps, in units of 0.5 Mbps, basic rate
			pAdapter->PortCfg.SupportedRates[9]  = 0x48;	// 36 mbps, in units of 0.5 Mbps
			pAdapter->PortCfg.SupportedRates[10] = 0x60;	// 48 mbps, in units of 0.5 Mbps
			pAdapter->PortCfg.SupportedRates[11] = 0x6c;	// 54 mbps, in units of 0.5 Mbps
			pAdapter->PortCfg.SupportedRatesLen  = 12;
			pAdapter->PortCfg.DesiredRates[0]  = 2; 	// 1 mbps, in units of 0.5 Mbps
			pAdapter->PortCfg.DesiredRates[1]  = 4; 	// 2 mbps, in units of 0.5 Mbps
			pAdapter->PortCfg.DesiredRates[2]  = 11;	// 5.5 mbps, in units of 0.5 Mbps
			pAdapter->PortCfg.DesiredRates[3]  = 22;	// 11 mbps, in units of 0.5 Mbps
			pAdapter->PortCfg.DesiredRates[4]  = 12;	// 6 mbps, in units of 0.5 Mbps
			pAdapter->PortCfg.DesiredRates[5]  = 18;	// 9 mbps, in units of 0.5 Mbps
			pAdapter->PortCfg.DesiredRates[6]  = 24;	// 12 mbps, in units of 0.5 Mbps
			pAdapter->PortCfg.DesiredRates[7]  = 36;	// 18 mbps, in units of 0.5 Mbps
			pAdapter->PortCfg.DesiredRates[8]  = 48;	// 24 mbps, in units of 0.5 Mbps
			pAdapter->PortCfg.DesiredRates[9]  = 72;	// 36 mbps, in units of 0.5 Mbps
			pAdapter->PortCfg.DesiredRates[10] = 96;	// 48 mbps, in units of 0.5 Mbps
			pAdapter->PortCfg.DesiredRates[11] = 108;	// 54 mbps, in units of 0.5 Mbps
			break;
			
		case PHY_11A:
	DBGPRINT(RT_DEBUG_TEMP,"PHY_11A\n");
			pAdapter->PortCfg.IbssConfig.SupportedRates[0]	= 0x8C;    // 6 mbps, in units of 0.5 Mbps, basic rate
			pAdapter->PortCfg.IbssConfig.SupportedRates[1]	= 0x12;    // 9 mbps, in units of 0.5 Mbps
			pAdapter->PortCfg.IbssConfig.SupportedRates[2]	= 0x98;    // 12 mbps, in units of 0.5 Mbps, basic rate
			pAdapter->PortCfg.IbssConfig.SupportedRates[3]	= 0x24;    // 18 mbps, in units of 0.5 Mbps
			pAdapter->PortCfg.IbssConfig.SupportedRates[4]	= 0xb0;    // 24 mbps, in units of 0.5 Mbps, basic rate
			pAdapter->PortCfg.IbssConfig.SupportedRates[5]	= 0x48;    // 36 mbps, in units of 0.5 Mbps
			pAdapter->PortCfg.IbssConfig.SupportedRates[6]	= 0x60;    // 48 mbps, in units of 0.5 Mbps
			pAdapter->PortCfg.IbssConfig.SupportedRates[7]	= 0x6c;    // 54 mbps, in units of 0.5 Mbps
			pAdapter->PortCfg.IbssConfig.SupportedRates[8]	= 0;
			pAdapter->PortCfg.IbssConfig.SupportedRates[9]	= 0;
			pAdapter->PortCfg.IbssConfig.SupportedRates[10] = 0;
			pAdapter->PortCfg.IbssConfig.SupportedRates[11] = 0;
			pAdapter->PortCfg.IbssConfig.SupportedRatesLen	= 8;
			pAdapter->PortCfg.SupportedRates[0]  = 0x8C;	// 6 mbps, in units of 0.5 Mbps, basic rate
			pAdapter->PortCfg.SupportedRates[1]  = 0x12;	// 9 mbps, in units of 0.5 Mbps
			pAdapter->PortCfg.SupportedRates[2]  = 0x98;	// 12 mbps, in units of 0.5 Mbps, basic rate
			pAdapter->PortCfg.SupportedRates[3]  = 0x24;	// 18 mbps, in units of 0.5 Mbps
			pAdapter->PortCfg.SupportedRates[4]  = 0xb0;	// 24 mbps, in units of 0.5 Mbps, basic rate
			pAdapter->PortCfg.SupportedRates[5]  = 0x48;	// 36 mbps, in units of 0.5 Mbps
			pAdapter->PortCfg.SupportedRates[6]  = 0x60;	// 48 mbps, in units of 0.5 Mbps
			pAdapter->PortCfg.SupportedRates[7]  = 0x6c;	// 54 mbps, in units of 0.5 Mbps
			pAdapter->PortCfg.SupportedRates[8]  = 0;
			pAdapter->PortCfg.SupportedRates[9]  = 0;
			pAdapter->PortCfg.SupportedRates[10] = 0;
			pAdapter->PortCfg.SupportedRates[11] = 0;
			pAdapter->PortCfg.SupportedRatesLen  = 8;
			pAdapter->PortCfg.DesiredRates[0]  = 12;	// 6 mbps, in units of 0.5 Mbps
			pAdapter->PortCfg.DesiredRates[1]  = 18;	// 9 mbps, in units of 0.5 Mbps
			pAdapter->PortCfg.DesiredRates[2]  = 24;	// 12 mbps, in units of 0.5 Mbps
			pAdapter->PortCfg.DesiredRates[3]  = 36;	// 18 mbps, in units of 0.5 Mbps
			pAdapter->PortCfg.DesiredRates[4]  = 48;	// 24 mbps, in units of 0.5 Mbps
			pAdapter->PortCfg.DesiredRates[5]  = 72;	// 36 mbps, in units of 0.5 Mbps
			pAdapter->PortCfg.DesiredRates[6]  = 96;	// 48 mbps, in units of 0.5 Mbps
			pAdapter->PortCfg.DesiredRates[7]  = 108;	// 54 mbps, in units of 0.5 Mbps
			pAdapter->PortCfg.DesiredRates[8]  = 0;
			pAdapter->PortCfg.DesiredRates[9]  = 0;
			pAdapter->PortCfg.DesiredRates[10] = 0;
			pAdapter->PortCfg.DesiredRates[11] = 0;
			break;
			
		default:
	DBGPRINT(RT_DEBUG_TEMP,"default\n");
			break;
	}
	
	MlmeUpdateTxRates(pAdapter, FALSE);
	AsicSetSlotTime(pAdapter, FALSE);
	MakeIbssBeacon(pAdapter);	 // supported rates may change
}


VOID	RT2570SetDesiredRates(
	IN	PRT2570ADAPTER	pAdapter,
	IN	LONG			Rates)
{
#if 1
	NDIS_802_11_RATES aryRates;
	ULONG	rate_mapping[12] = {1, 2, 5, 11, 6, 9, 12, 18, 24, 36, 48, 54}; //according to README
	DBGPRINT(RT_DEBUG_TEMP, "1.RT2570SetDesiredRates::(Rates=%d)\n",	Rates );
	
	DBGPRINT(RT_DEBUG_ERROR, "2.RT2570SetDesiredRates::(Rates=%d)\n",	Rates );
	if (Rates < 13 && (Rates > 0))
		Rates = rate_mapping[Rates-1] * 1000000;
	
	memset(&aryRates, 0x00, sizeof(NDIS_802_11_RATES));
	switch (pAdapter->PortCfg.PhyMode)
	{
		case PHY_11A: // A only
			switch (Rates)
			{
				case 6000000: //6M
					aryRates[0] = 0x0c; // 6M
					break;
				case 9000000: //9M
					aryRates[0] = 0x12; // 9M
					break;
				case 12000000: //12M
					aryRates[0] = 0x18; // 12M
					break;
				case 18000000: //18M
					aryRates[0] = 0x24; // 18M
					break;
				case 24000000: //24M
					aryRates[0] = 0x30; // 24M
					break;
				case 36000000: //36M
					aryRates[0] = 0x48; // 36M
					break;
				case 48000000: //48M
					aryRates[0] = 0x60; // 48M
					break;
				case 54000000: //54M
					aryRates[0] = 0x6c; // 54M
					break;
				case -1: //Auto
				default:
					aryRates[0] = 0x6c; // 54Mbps
					aryRates[1] = 0x60; // 48Mbps
					aryRates[2] = 0x48; // 36Mbps
					aryRates[3] = 0x30; // 24Mbps
					aryRates[4] = 0x24; // 18M
					aryRates[5] = 0x18; // 12M
					aryRates[6] = 0x12; // 9M
					aryRates[7] = 0x0c; // 6M
					break;
			}
			break;
		case PHY_11B: // B only
			switch (Rates)
			{
				case 1000000: //6M
				aryRates[0] = 0x02;
					break;
				case 2000000: //6M
					aryRates[0] = 0x04;
					break;
				case 5000000: //5.5M
					aryRates[0] = 0x0b; // 5.5M
					break;
				case 11000000: //11M
					aryRates[0] = 0x16; // 11M
					break;
				case -1: //Auto
				default:
						aryRates[0] = 0x16; // 11Mbps
						aryRates[1] = 0x0b; // 5.5Mbps
						aryRates[2] = 0x04; // 2Mbps
						aryRates[3] = 0x02; // 1Mbps
					break;
			}
			break;
		case PHY_11BG_MIXED: // B/G Mixed
		case PHY_11ABG_MIXED: // A/B/G Mixed
		default:
			switch (Rates)
			{
				case 1000000: //6M
					aryRates[0] = 0x02;
					break;
				case 2000000: //6M
					aryRates[0] = 0x04;
					break;
				case 5000000: //5.5M
					aryRates[0] = 0x0b; // 5.5M
					break;
				case 11000000: //11M
					aryRates[0] = 0x16; // 11M
					break;
				case 6000000: //6M
					aryRates[0] = 0x0c; // 6M
					break;
				case 9000000: //9M
					aryRates[0] = 0x12; // 9M
					break;
				case 12000000: //12M
					aryRates[0] = 0x18; // 12M
					break;
				case 18000000: //18M
					aryRates[0] = 0x24; // 18M
					break;
				case 24000000: //24M
					aryRates[0] = 0x30; // 24M
					break;
				case 36000000: //36M
					aryRates[0] = 0x48; // 36M
					break;
				case 48000000: //48M
					aryRates[0] = 0x60; // 48M
					break;
				case 54000000: //54M
					aryRates[0] = 0x6c; // 54M
					break;
				case -1: //Auto
				default:
					if (pAdapter->PortCfg.PhyMode == PHY_11B)
					{ //B Only
						aryRates[0] = 0x16; // 11Mbps
						aryRates[1] = 0x0b; // 5.5Mbps
						aryRates[2] = 0x04; // 2Mbps
						aryRates[3] = 0x02; // 1Mbps
					}
					else
					{ //(B/G) Mixed or (A/B/G) Mixed
						aryRates[0] = 0x6c; // 54Mbps
						aryRates[1] = 0x60; // 48Mbps
						aryRates[2] = 0x48; // 36Mbps
						aryRates[3] = 0x30; // 24Mbps
						aryRates[4] = 0x16; // 11Mbps
						aryRates[5] = 0x0b; // 5.5Mbps
						aryRates[6] = 0x04; // 2Mbps
						aryRates[7] = 0x02; // 1Mbps
					}
					break;
			}
			break;
	}

	memset(pAdapter->PortCfg.DesiredRates, 0, MAX_LEN_OF_SUPPORTED_RATES);
	memcpy(pAdapter->PortCfg.DesiredRates, &aryRates, sizeof(NDIS_802_11_RATES));
	DBGPRINT(RT_DEBUG_TEMP, " RTMPSetDesiredRates (%02x,%02x,%02x,%02x,%02x,%02x,%02x,%02x)\n",
		pAdapter->PortCfg.DesiredRates[0],pAdapter->PortCfg.DesiredRates[1],
		pAdapter->PortCfg.DesiredRates[2],pAdapter->PortCfg.DesiredRates[3],
		pAdapter->PortCfg.DesiredRates[4],pAdapter->PortCfg.DesiredRates[5],
		pAdapter->PortCfg.DesiredRates[6],pAdapter->PortCfg.DesiredRates[7] );
	// Changing DesiredRate may affect the MAX TX rate we used to TX frames out
	MlmeUpdateTxRates(pAdapter, FALSE);
#endif
}

INT Set_R17_Proc(
	IN	PRT2570ADAPTER	 pAdapter, 
	IN	PUCHAR			arg)
{

	ULONG								TUNN;
	UINT	i = 0;
	UCHAR	Value = 0x0;
	int 								success = TRUE;
	
	TUNN = simple_strtol(arg, 0, 10);
	i = (TUNN/100);
	Value = TUNN%100;
	DBGPRINT(RT_DEBUG_TEMP, "Set_R17_Proc -->TUNN = 0x%x id = %d, Value=ox%x!!!\n",TUNN,i,Value);
	RTUSBWriteBBPRegister(pAdapter, i, Value);

	return success;
}
INT Read_R17_Proc(
	IN	PRT2570ADAPTER	 pAdapter, 
	IN	PUCHAR			arg)

{

	UINT	i = 0;
	UCHAR	Value = 0x0;
	int 								success = TRUE;
	for ( i = 0 ; i<70; i++)
	{
		
		 RTUSBReadBBPRegister(pAdapter, i, &Value);
		DBGPRINT(RT_DEBUG_TEMP,"Read_BBP_Proc R%d = 0x%x\n",i,Value);
	}
	return success;

}
/* 
	==========================================================================
	Description:
		Set Country Region
	Return:
		TRUE if all parameters are OK, FALSE otherwise
	==========================================================================
*/
INT Set_CountryRegion_Proc(
	IN	PRT2570ADAPTER	 pAdapter, 
	IN	PUCHAR			arg)
{
	ULONG								region;
	int 								success = TRUE;

	region = simple_strtol(arg, 0, 10);
	if( (region >= REGION_MIN) && (region <= REGION_MAX) )
	{
		pAdapter->PortCfg.CountryRegion = (UCHAR) region;
		DBGPRINT(RT_DEBUG_TRACE, "Set_CountryRegion_Proc::(CountryRegion=%d)\n", pAdapter->PortCfg.CountryRegion);
		printk("Set_CountryRegion_Proc::(CountryRegion=%d)\n", pAdapter->PortCfg.CountryRegion);
	}
	else
		success = FALSE;

	return success;
}
/* 
	==========================================================================
	Description:
		Set SSID
	Return:
		TRUE if all parameters are OK, FALSE otherwise
	==========================================================================
*/
INT Set_SSID_Proc(
	IN	PRT2570ADAPTER	 pAdapter, 
	IN	PUCHAR			arg)
{
	int 								success = TRUE;
	NDIS_802_11_SSID					Ssid, *pSsid=NULL;
	BOOLEAN 							StateMachineTouched = FALSE;
	if( strlen(arg) <= MAX_LEN_OF_SSID)
	{
		memset(&Ssid, 0, sizeof(NDIS_802_11_SSID));
		memcpy(Ssid.Ssid, arg, strlen(arg));
		Ssid.SsidLength = strlen(arg);
		pSsid = &Ssid;

		if (pAdapter->Mlme.CntlMachine.CurrState != CNTL_IDLE)
		{
			MlmeRestartStateMachine(pAdapter);
			MlmePostRestartStateMachine(pAdapter);
			DBGPRINT(RT_DEBUG_TEMP, "!!! MLME busy, reset MLME state machine !!!\n");
		}
		 // tell CNTL state machine to call NdisMSetInformationComplete() after completing
		// this request, because this request is initiated by NDIS.
		pAdapter->Mlme.CntlAux.CurrReqIsFromNdis = FALSE; 

		MlmeEnqueue(pAdapter, 
					MLME_CNTL_STATE_MACHINE, 
					OID_802_11_SSID,
					sizeof(NDIS_802_11_SSID),
					(VOID *)pSsid);

		StateMachineTouched = TRUE;
		DBGPRINT(RT_DEBUG_TEMP, "Set_SSID_Proc::(Len=%d,Ssid=%s)\n", pAdapter->PortCfg.SsidLen, pAdapter->PortCfg.Ssid);
	}
	else
		success = FALSE;

	RTUSBUp(pAdapter, (&(pAdapter->mlme_semaphore)));
	return success;

}
/* 
	==========================================================================
	Description:
		Set Wireless Mode
	Return:
		TRUE if all parameters are OK, FALSE otherwise
	==========================================================================
*/
INT Set_WirelessMode_Proc(
	IN	PRT2570ADAPTER	 pAdapter, 
	IN	PUCHAR			arg)
{
	int 								success = TRUE;
#if 0
	ULONG								WirelessMode;
	WirelessMode = simple_strtol(arg, 0, 10);

	if ((WirelessMode == PHY_11BG_MIXED) || (WirelessMode == PHY_11B) ||
		(WirelessMode == PHY_11A) || (WirelessMode == PHY_11ABG_MIXED))
	{
		RTMPSetPhyMode(pAdapter, WirelessMode);
		DBGPRINT(RT_DEBUG_TEMP, "Set_WirelessMode_Proc::(=%d)\n", WirelessMode);
	}
	else
		success = FALSE;
#endif
	return success;
}
/* 
	==========================================================================
	Description:
		Set TxRate
	Return:
		TRUE if all parameters are OK, FALSE otherwise
	==========================================================================
*/
INT Set_TxRate_Proc(
	IN	PRT2570ADAPTER	 pAdapter, 
	IN	PUCHAR			arg)
{
	int 								success = TRUE;
#if 0		
	ULONG								TxRate;
	ULONG	rate_mapping[12] = {1, 2, 5, 11, 6, 9, 12, 18, 24, 36, 48, 54}; //according to README
	TxRate = simple_strtol(arg, 0, 10);
		DBGPRINT(RT_DEBUG_TEMP, "Set_TxRate_Proc::(TxRate=%d)\n", TxRate);
	if (TxRate > 12)
		return FALSE;
	
	if (TxRate == 0)
		RT2570SetDesiredRates(pAdapter, -1);
	else
		RT2570SetDesiredRates(pAdapter, (LONG) (rate_mapping[TxRate-1] * 1000000));
#endif

	return success;
}
/* 
	==========================================================================
	Description:
		Set Channel
	Return:
		TRUE if all parameters are OK, FALSE otherwise
	==========================================================================
*/
INT Set_Channel_Proc(
	IN	PRT2570ADAPTER	 pAdapter, 
	IN	PUCHAR			arg)
{
	int 								success = TRUE;
	UCHAR								Channel;

	Channel = (UCHAR) simple_strtol(arg, 0, 10);

	if (ChannelSanity(pAdapter, Channel) == TRUE)
	{
		pAdapter->PortCfg.Channel = Channel;
		DBGPRINT(RT_DEBUG_TRACE, "Set_Channel_Proc::(Channel=%d)\n", Channel);
	}
	else
		success = FALSE;

	return success;
}

/* 
	==========================================================================
	Description:
		Set 11B/11G Protection
	Return:
		TRUE if all parameters are OK, FALSE otherwise
	==========================================================================
*/
INT Set_BGProtection_Proc(
	IN	PRT2570ADAPTER	 pAdapter, 
	IN	PUCHAR			arg)

{
	switch (simple_strtol(arg, 0, 10))
	{
		case 0: //AUTO
			pAdapter->PortCfg.UseBGProtection = 0;
			break;
		case 1: //Always On
			pAdapter->PortCfg.UseBGProtection = 1;
			break;
		case 2: //Always OFF
			pAdapter->PortCfg.UseBGProtection = 2;
			break;		
		default:  //Invalid argument 
			return FALSE;
	}
	DBGPRINT(RT_DEBUG_TEMP, "Set_BGProtection_Proc::(BGProtection=%d)\n", pAdapter->PortCfg.UseBGProtection);

	return TRUE;
}
/* 
	==========================================================================
	Description:
		Set TxPreamble
	Return:
		TRUE if all parameters are OK, FALSE otherwise
	==========================================================================
*/
INT Set_TxPreamble_Proc(
	IN	PRT2570ADAPTER	 pAdapter, 
	IN	PUCHAR			arg)
{
#if 0
	RT_802_11_PREAMBLE					Preamble;
	Preamble = simple_strtol(arg, 0, 10);
	switch (Preamble)
	{
		case Rt802_11PreambleShort:
			pAdapter->PortCfg.WindowsTxPreamble = Preamble;
			MlmeSetTxPreamble(pAdapter, Rt802_11PreambleShort);
			break;
		case Rt802_11PreambleLong:
		case Rt802_11PreambleAuto:
			// if user wants AUTO, initialize to LONG here, then change according to AP's
			// capability upon association.
			pAdapter->PortCfg.WindowsTxPreamble = Preamble;
			MlmeSetTxPreamble(pAdapter, Rt802_11PreambleLong);
			break;
		default: //Invalid argument 
			return FALSE;
	}

	DBGPRINT(RT_DEBUG_TEMP, "Set_TxPreamble_Proc::(TxPreamble=%d)\n", Preamble);
#endif

	return TRUE;
}
/* 
	==========================================================================
	Description:
		Set RTS Threshold
	Return:
		TRUE if all parameters are OK, FALSE otherwise
	==========================================================================
*/
INT Set_RTSThreshold_Proc(
	IN	PRT2570ADAPTER	 pAdapter, 
	IN	PUCHAR			arg)
{
	NDIS_802_11_RTS_THRESHOLD			RtsThresh;

	RtsThresh = simple_strtol(arg, 0, 10);

	if((RtsThresh > 0) && (RtsThresh <= MAX_RTS_THRESHOLD))
		pAdapter->PortCfg.RtsThreshold = (USHORT)RtsThresh;
	else if (RtsThresh == 0)
		pAdapter->PortCfg.RtsThreshold = MAX_RTS_THRESHOLD;
	else
		return FALSE;

	DBGPRINT(RT_DEBUG_TEMP, "Set_RTSThreshold_Proc::(RTSThreshold=%d)\n", pAdapter->PortCfg.RtsThreshold);
	return TRUE;
}
/* 
	==========================================================================
	Description:
		Set Fragment Threshold
	Return:
		TRUE if all parameters are OK, FALSE otherwise
	==========================================================================
*/
INT Set_FragThreshold_Proc(
	IN	PRT2570ADAPTER	 pAdapter, 
	IN	PUCHAR			arg)
{
	NDIS_802_11_FRAGMENTATION_THRESHOLD 	FragThresh;

	FragThresh = simple_strtol(arg, 0, 10);

	if ( (FragThresh >= MIN_FRAG_THRESHOLD) && (FragThresh <= MAX_FRAG_THRESHOLD))
		pAdapter->PortCfg.FragmentThreshold = (USHORT)FragThresh;
	else if (FragThresh == 0)
		pAdapter->PortCfg.FragmentThreshold = MAX_FRAG_THRESHOLD;
	else
		return FALSE; //Invalid argument 

	if (pAdapter->PortCfg.FragmentThreshold == MAX_FRAG_THRESHOLD)
		pAdapter->PortCfg.bFragmentZeroDisable = TRUE;
	else
		pAdapter->PortCfg.bFragmentZeroDisable = FALSE;

	DBGPRINT(RT_DEBUG_TEMP, "Set_FragThreshold_Proc::(FragThreshold=%d)\n", FragThresh);

	return TRUE;
}
/* 
	==========================================================================
	Description:
		Set TxBurst
	Return:
		TRUE if all parameters are OK, FALSE otherwise
	==========================================================================
*/
INT Set_TxBurst_Proc(
	IN	PRT2570ADAPTER	 pAdapter, 
	IN	PUCHAR			arg)
{
	ULONG								TxBurst;

	TxBurst = simple_strtol(arg, 0, 10);

	if (TxBurst == 1)
		pAdapter->PortCfg.EnableTxBurst = TRUE;
	else if (TxBurst == 0)
		pAdapter->PortCfg.EnableTxBurst = FALSE;
	else
		return FALSE;  //Invalid argument 
	
	DBGPRINT(RT_DEBUG_TEMP, "Set_TxBurst_Proc::(TxBurst=%d)\n", pAdapter->PortCfg.EnableTxBurst);

	return TRUE;
}
/* 
	==========================================================================
	Description:
		Set TurboRate Enable or Disable
	Return:
		TRUE if all parameters are OK, FALSE otherwise
	==========================================================================
*/
INT Set_TurboRate_Proc(
	IN	PRT2570ADAPTER	 pAdapter, 
	IN	PUCHAR			arg)
{
	ULONG								TurboRate;

	TurboRate = simple_strtol(arg, 0, 10);

	if (TurboRate == 1)
		pAdapter->PortCfg.EnableTurboRate = TRUE;
	else if (TurboRate == 0)
		pAdapter->PortCfg.EnableTurboRate = FALSE;
	else
		return FALSE;  //Invalid argument 
	
	DBGPRINT(RT_DEBUG_TEMP, "Set_TurboRate_Proc::(TurboRate=%d)\n", pAdapter->PortCfg.EnableTurboRate);

	return TRUE;
}
/* 
	==========================================================================
	Description:
		Set Short Slot Time Enable or Disable
	Return:
		TRUE if all parameters are OK, FALSE otherwise
	==========================================================================
*/
INT Set_ShortSlot_Proc(
	IN	PRT2570ADAPTER	 pAdapter, 
	IN	PUCHAR			arg)
{
	ULONG								ShortSlot;

	ShortSlot = simple_strtol(arg, 0, 10);

	if (ShortSlot == 1)
		pAdapter->PortCfg.UseShortSlotTime = TRUE;
	else if (ShortSlot == 0)
		pAdapter->PortCfg.UseShortSlotTime = FALSE;
	else
		return FALSE;  //Invalid argument 

	DBGPRINT(RT_DEBUG_TEMP, "Set_ShortSlot_Proc::(ShortSlot=%d)\n", pAdapter->PortCfg.UseShortSlotTime);

	return TRUE;
}
/* 
	==========================================================================
	Description:
		Set Authentication mode
	Return:
		TRUE if all parameters are OK, FALSE otherwise
	==========================================================================
*/
INT Set_AuthMode_Proc(
	IN	PRT2570ADAPTER	 pAdapter, 
	IN	PUCHAR			arg)
{
	if ((strcmp(arg, "OPEN") == 0) || (strcmp(arg, "open") == 0))
		pAdapter->PortCfg.AuthMode = Ndis802_11AuthModeOpen;
	else if ((strcmp(arg, "SHARED") == 0) || (strcmp(arg, "shared") == 0))
		pAdapter->PortCfg.AuthMode = Ndis802_11AuthModeShared;
	else if ((strcmp(arg, "WPAPSK") == 0) || (strcmp(arg, "wpapsk") == 0))
		pAdapter->PortCfg.AuthMode = Ndis802_11AuthModeWPAPSK;
	else if ((strcmp(arg, "WPANONE") == 0) || (strcmp(arg, "wpanone") == 0))
		pAdapter->PortCfg.AuthMode = Ndis802_11AuthModeWPANone;
	else
		return FALSE;  

	pAdapter->PortCfg.PortSecured = WPA_802_1X_PORT_NOT_SECURED;

	DBGPRINT(RT_DEBUG_TEMP, "Set_AuthMode_Proc::(AuthMode=%d)\n", pAdapter->PortCfg.AuthMode);

	return TRUE;
}
/* 
	==========================================================================
	Description:
		Set Encryption Type
	Return:
		TRUE if all parameters are OK, FALSE otherwise
	==========================================================================
*/
INT Set_EncrypType_Proc(
	IN	PRT2570ADAPTER	 pAdapter, 
	IN	PUCHAR			arg)
{
	USHORT	Value;
	if ((strcmp(arg, "NONE") == 0) || (strcmp(arg, "none") == 0))
	{
		pAdapter->PortCfg.WepStatus = Ndis802_11WEPDisabled;
		RTUSBReadMACRegister(pAdapter, TXRX_CSR0, &Value);
		Value &= 0xfe00;
		DBGPRINT(RT_DEBUG_INFO,"Set::NONERead  TXRX_CSR0  %x !!!!!!!!!!!!!!!!!\n",Value);
		RTUSBWriteMACRegister(pAdapter, TXRX_CSR0, Value);
	}
	else if ((strcmp(arg, "WEP") == 0) || (strcmp(arg, "wep") == 0))
	{
		pAdapter->PortCfg.WepStatus = Ndis802_11Encryption1Enabled;
		if ((pAdapter->PortCfg.SharedKey[pAdapter->PortCfg.DefaultKeyId].KeyLen == 5) || (pAdapter->PortCfg.SharedKey[pAdapter->PortCfg.DefaultKeyId].KeyLen == 10))
			pAdapter->PortCfg.CipherAlg = CIPHER_WEP64;
		else
			pAdapter->PortCfg.CipherAlg = CIPHER_WEP128;
			
		RTUSBReadMACRegister(pAdapter, TXRX_CSR0, &Value);
		DBGPRINT(RT_DEBUG_TEMP,"Set::WEPRead  TXRX_CSR0  %x !!!!!!!!!!!!!!!!!\n",Value);
		Value &= 0xfe00;
		Value |= ((LENGTH_802_11 << 3) | (pAdapter->PortCfg.CipherAlg));
		DBGPRINT(RT_DEBUG_TEMP,"Set::WEPRead  TXRX_CSR0  %x !!!!!!!!!!!!!!!!!\n",Value);
		RTUSBWriteMACRegister(pAdapter, TXRX_CSR0, Value);
	}
	else if ((strcmp(arg, "TKIP") == 0) || (strcmp(arg, "tkip") == 0))
	{
		pAdapter->PortCfg.WepStatus = Ndis802_11Encryption2Enabled;
		pAdapter->PortCfg.CipherAlg = CIPHER_TKIP;
		RTUSBReadMACRegister(pAdapter, TXRX_CSR0, &Value);
		DBGPRINT(RT_DEBUG_INFO,"Set::Read TXRX_CSR0  %x !!!!!!!!!!!!!!!!!\n",Value);
		Value &= 0xfe00;
		Value |= ((LENGTH_802_11 << 3) | (pAdapter->PortCfg.CipherAlg));
		DBGPRINT(RT_DEBUG_INFO,"Set::Read  TXRX_CSR0  %x !!!!!!!!!!!!!!!!!\n",Value);
		RTUSBWriteMACRegister(pAdapter, TXRX_CSR0, Value);
	}
	else if ((strcmp(arg, "AES") == 0) || (strcmp(arg, "aes") == 0))
	{
		pAdapter->PortCfg.WepStatus = Ndis802_11Encryption3Enabled;
		RTUSBReadMACRegister(pAdapter, TXRX_CSR0, &Value);
		Value &= 0xfe00;
		Value |= ((LENGTH_802_11 << 3) | (pAdapter->PortCfg.CipherAlg));
		RTUSBWriteMACRegister(pAdapter, TXRX_CSR0, Value);
	}
	else
	{
		DBGPRINT(RT_DEBUG_INFO,"Set::EncrypType ERROR !!!!!!!!!!!!!!!!!\n");
		
		return FALSE;
	}

	DBGPRINT(RT_DEBUG_TEMP, "Set_EncrypType_Proc::(EncrypType=%d)\n", pAdapter->PortCfg.WepStatus);


	return TRUE;
}
/* 
	==========================================================================
	Description:
		Set Default Key ID
	Return:
		TRUE if all parameters are OK, FALSE otherwise
	==========================================================================
*/
INT Set_DefaultKeyID_Proc(
	IN	PRT2570ADAPTER	 pAdapter, 
	IN	PUCHAR			arg)
{
	ULONG								KeyIdx;

	KeyIdx = simple_strtol(arg, 0, 10);
	if((KeyIdx >= 1 ) && (KeyIdx <= 4))
		pAdapter->PortCfg.DefaultKeyId = (UCHAR) (KeyIdx - 1 );
	else
		return FALSE;  //Invalid argument 

	DBGPRINT(RT_DEBUG_TEMP, "Set_DefaultKeyID_Proc::(DefaultKeyID=%d)\n", pAdapter->PortCfg.DefaultKeyId);

	return TRUE;
}
/* 
	==========================================================================
	Description:
		Set WEP KEY1
	Return:
		TRUE if all parameters are OK, FALSE otherwise
	==========================================================================
*/
INT Set_Key1_Proc(
	IN	PRT2570ADAPTER	 pAdapter, 
	IN	PUCHAR			arg)
{
	int 								KeyLen;
	int 								i;
	USHORT	Value;

	KeyLen = strlen(arg);

	switch (KeyLen)
	{
		case 5: //wep 40 Ascii type
			pAdapter->PortCfg.SharedKey[0].KeyLen = KeyLen;
			memcpy(pAdapter->PortCfg.SharedKey[0].Key, arg, KeyLen);	
			DBGPRINT(RT_DEBUG_TEMP, "Set_Key1_Proc::(Key1=%s and type=%s)\n", arg, "Ascii");	   
		
			break;
		case 10: //wep 40 Hex type
			for(i=0; i < KeyLen; i++)
			{
				if( !isxdigit(*(arg+i)) )
					return FALSE;  //Not Hex value;
			}
			pAdapter->PortCfg.SharedKey[0].KeyLen = KeyLen / 2 ;
			AtoH(arg, pAdapter->PortCfg.SharedKey[0].Key, KeyLen / 2);
			DBGPRINT(RT_DEBUG_TEMP, "Set_Key1_Proc::(Key1=%s and type=%s)\n", arg, "Hex");	   
		 
			break;
		case 13: //wep 104 Ascii type
			pAdapter->PortCfg.SharedKey[0].KeyLen = KeyLen;
			memcpy(pAdapter->PortCfg.SharedKey[0].Key, arg, KeyLen);	
			DBGPRINT(RT_DEBUG_TEMP, "Set_Key1_Proc::(Key1=%s and type=%s)\n", arg, "Ascii");	   
			break;
		case 26: //wep 104 Hex type
			for(i=0; i < KeyLen; i++)
			{
				if( !isxdigit(*(arg+i)) )
					return FALSE;  //Not Hex value;
			}
			pAdapter->PortCfg.SharedKey[0].KeyLen = KeyLen / 2 ;
			AtoH(arg, pAdapter->PortCfg.SharedKey[0].Key, KeyLen / 2);
			DBGPRINT(RT_DEBUG_TEMP, "Set_Key1_Proc::(Key1=%s and type=%s)\n", arg, "Hex");	   
			break;
		default: //Invalid argument 
			DBGPRINT(RT_DEBUG_TEMP, "Set_Key1_Proc::Invalid argument (=%s)\n", arg);	   
			return FALSE;
	}


	RTUSBMultiWrite(pAdapter, (USHORT)(SEC_CSR0 + 0 * 0x10), pAdapter->PortCfg.SharedKey[0].Key, 16);	

								
								
	// Default key for tx (shared key)
	pAdapter->PortCfg.DefaultKeyId = (UCHAR)0;
								
								
								
	if ( (KeyLen == 5) ||( KeyLen == 10) )
	pAdapter->PortCfg.CipherAlg = CIPHER_WEP64;
	else
	pAdapter->PortCfg.CipherAlg = CIPHER_WEP128;
								
	 RTUSBReadMACRegister(pAdapter, TXRX_CSR0, &Value);
	 Value &= 0xfe00;
	 Value |= ((LENGTH_802_11 << 3) | (pAdapter->PortCfg.CipherAlg));
	 RTUSBWriteMACRegister(pAdapter, TXRX_CSR0, Value);
	
	return TRUE;
}
/* 
	==========================================================================
	Description:
		Set WEP KEY2
	Return:
		TRUE if all parameters are OK, FALSE otherwise
	==========================================================================
*/
INT Set_Key2_Proc(
	IN	PRT2570ADAPTER	 pAdapter, 
	IN	PUCHAR			arg)
{
	int 								KeyLen;
	int 								i;
	USHORT	Value;

	KeyLen = strlen(arg);

	switch (KeyLen)
	{
		case 5: //wep 40 Ascii type
			pAdapter->PortCfg.SharedKey[1].KeyLen = KeyLen;
			memcpy(pAdapter->PortCfg.SharedKey[1].Key, arg, KeyLen);
			DBGPRINT(RT_DEBUG_TRACE, "Set_Key2_Proc::(Key2=%s and type=%s)\n", arg, "Ascii");
			break;
		case 10: //wep 40 Hex type
			for(i=0; i < KeyLen; i++)
			{
				if( !isxdigit(*(arg+i)) )
					return FALSE;  //Not Hex value;
			}
			pAdapter->PortCfg.SharedKey[1].KeyLen = KeyLen / 2 ;
			AtoH(arg, pAdapter->PortCfg.SharedKey[1].Key, KeyLen / 2);
			DBGPRINT(RT_DEBUG_TRACE, "Set_Key2_Proc::(Key2=%s and type=%s)\n", arg, "Hex");
			break;
		case 13: //wep 104 Ascii type
			pAdapter->PortCfg.SharedKey[1].KeyLen = KeyLen;
			memcpy(pAdapter->PortCfg.SharedKey[1].Key, arg, KeyLen);	
			DBGPRINT(RT_DEBUG_TRACE, "Set_Key2_Proc::(Key2=%s and type=%s)\n", arg, "Ascii");
			break;
		case 26: //wep 104 Hex type
			for(i=0; i < KeyLen; i++)
			{
				if( !isxdigit(*(arg+i)) )
					return FALSE;  //Not Hex value;
			}
			pAdapter->PortCfg.SharedKey[1].KeyLen = KeyLen / 2 ;
			AtoH(arg, pAdapter->PortCfg.SharedKey[1].Key, KeyLen / 2);
			DBGPRINT(RT_DEBUG_TRACE, "Set_Key2_Proc::(Key2=%s and type=%s)\n", arg, "Hex");
			break;
		default: //Invalid argument 
			DBGPRINT(RT_DEBUG_TRACE, "Set_Key2_Proc::Invalid argument (=%s)\n", arg);
			return FALSE;
	}

	RTUSBMultiWrite(pAdapter, (USHORT)(SEC_CSR0 + 1 * 0x10), pAdapter->PortCfg.SharedKey[1].Key, 16);	

	
								
								
								
	// Default key for tx (shared key)
	pAdapter->PortCfg.DefaultKeyId = (UCHAR)1;
								
								
								
	if ( (KeyLen == 5) ||( KeyLen == 10) )
	pAdapter->PortCfg.CipherAlg = CIPHER_WEP64;
	else
	pAdapter->PortCfg.CipherAlg = CIPHER_WEP128;
								
	 RTUSBReadMACRegister(pAdapter, TXRX_CSR0, &Value);
	 Value &= 0xfe00;
	 Value |= ((LENGTH_802_11 << 3) | (pAdapter->PortCfg.CipherAlg));
	 RTUSBWriteMACRegister(pAdapter, TXRX_CSR0, Value);

	return TRUE;
}
/* 
	==========================================================================
	Description:
		Set WEP KEY3
	Return:
		TRUE if all parameters are OK, FALSE otherwise
	==========================================================================
*/
INT Set_Key3_Proc(
	IN	PRT2570ADAPTER	 pAdapter, 
	IN	PUCHAR			arg)
{
	int 								KeyLen;
	int 								i;
	USHORT	Value;	

	KeyLen = strlen(arg);

	switch (KeyLen)
	{
		case 5: //wep 40 Ascii type
			pAdapter->PortCfg.SharedKey[2].KeyLen = KeyLen;
			memcpy(pAdapter->PortCfg.SharedKey[2].Key, arg, KeyLen);
			DBGPRINT(RT_DEBUG_TRACE, "Set_Key3_Proc::(Key3=%s and type=%s)\n", arg, "Ascii");
			break;
		case 10: //wep 40 Hex type
			for(i=0; i < KeyLen; i++)
			{
				if( !isxdigit(*(arg+i)) )
					return FALSE;  //Not Hex value;
			}
			pAdapter->PortCfg.SharedKey[2].KeyLen = KeyLen / 2 ;
			AtoH(arg, pAdapter->PortCfg.SharedKey[2].Key, KeyLen / 2);
			DBGPRINT(RT_DEBUG_TRACE, "Set_Key3_Proc::(Key3=%s and type=%s)\n", arg, "Hex");
			break;
		case 13: //wep 104 Ascii type
			pAdapter->PortCfg.SharedKey[2].KeyLen = KeyLen;
			memcpy(pAdapter->PortCfg.SharedKey[2].Key, arg, KeyLen);
			DBGPRINT(RT_DEBUG_TRACE, "Set_Key3_Proc::(Key3=%s and type=%s)\n", arg, "Ascii");
			break;
		case 26: //wep 104 Hex type
			for(i=0; i < KeyLen; i++)
			{
				if( !isxdigit(*(arg+i)) )
					return FALSE;  //Not Hex value;
			}
			pAdapter->PortCfg.SharedKey[2].KeyLen = KeyLen / 2 ;
			AtoH(arg, pAdapter->PortCfg.SharedKey[2].Key, KeyLen / 2);
			DBGPRINT(RT_DEBUG_TRACE, "Set_Key3_Proc::(Key3=%s and type=%s)\n", arg, "Hex");
			break;
		default: //Invalid argument 
			DBGPRINT(RT_DEBUG_TRACE, "Set_Key3_Proc::Invalid argument (=%s)\n", arg);
			return FALSE;
	}

	RTUSBMultiWrite(pAdapter, (USHORT)(SEC_CSR0 + 2 * 0x10), pAdapter->PortCfg.SharedKey[2].Key, 16);	

								
	// Default key for tx (shared key)
	pAdapter->PortCfg.DefaultKeyId = (UCHAR)2;
								
								
								
	if ( (KeyLen == 5) ||( KeyLen == 10) )
	pAdapter->PortCfg.CipherAlg = CIPHER_WEP64;
	else
	pAdapter->PortCfg.CipherAlg = CIPHER_WEP128;
								
	 RTUSBReadMACRegister(pAdapter, TXRX_CSR0, &Value);
	 Value &= 0xfe00;
	 Value |= ((LENGTH_802_11 << 3) | (pAdapter->PortCfg.CipherAlg));
	 RTUSBWriteMACRegister(pAdapter, TXRX_CSR0, Value);

	return TRUE;
}
/* 
	==========================================================================
	Description:
		Set WEP KEY4
	Return:
		TRUE if all parameters are OK, FALSE otherwise
	==========================================================================
*/
INT Set_Key4_Proc(
	IN	PRT2570ADAPTER	 pAdapter, 
	IN	PUCHAR			arg)
{
	int 								KeyLen;
	int 								i;
	USHORT	Value;

	KeyLen = strlen(arg);

	switch (KeyLen)
	{
		case 5: //wep 40 Ascii type
			pAdapter->PortCfg.SharedKey[3].KeyLen = KeyLen;
			memcpy(pAdapter->PortCfg.SharedKey[3].Key, arg, KeyLen);	
			DBGPRINT(RT_DEBUG_TRACE, "Set_Key4_Proc::(Key4=%s and type=%s)\n", arg, "Ascii");
			break;
		case 10: //wep 40 Hex type
			for(i=0; i < KeyLen; i++)
			{
				if( !isxdigit(*(arg+i)) )
					return FALSE;  //Not Hex value;
			}
			pAdapter->PortCfg.SharedKey[3].KeyLen = KeyLen / 2 ;
			AtoH(arg, pAdapter->PortCfg.SharedKey[3].Key, KeyLen / 2);
			DBGPRINT(RT_DEBUG_TRACE, "Set_Key4_Proc::(Key4=%s and type=%s)\n", arg, "Hex");
			break;
		case 13: //wep 104 Ascii type
			pAdapter->PortCfg.SharedKey[3].KeyLen = KeyLen;
			memcpy(pAdapter->PortCfg.SharedKey[3].Key, arg, KeyLen);
			DBGPRINT(RT_DEBUG_TRACE, "Set_Key4_Proc::(Key4=%s and type=%s)\n", arg, "Ascii");
			break;
		case 26: //wep 104 Hex type
			for(i=0; i < KeyLen; i++)
			{
				if( !isxdigit(*(arg+i)) )
					return FALSE;  //Not Hex value;
			}
			pAdapter->PortCfg.SharedKey[3].KeyLen = KeyLen / 2 ;
			AtoH(arg, pAdapter->PortCfg.SharedKey[3].Key, KeyLen / 2);
			DBGPRINT(RT_DEBUG_TRACE, "Set_Key4_Proc::(Key4=%s and type=%s)\n", arg, "Hex");
			break;
		default: //Invalid argument 
			DBGPRINT(RT_DEBUG_TRACE, "Set_Key4_Proc::Invalid argument (=%s)\n", arg);
			return FALSE;
	}

	RTUSBMultiWrite(pAdapter, (USHORT)(SEC_CSR0 + 3 * 0x10), pAdapter->PortCfg.SharedKey[3].Key, 16);	

								
	// Default key for tx (shared key)
	pAdapter->PortCfg.DefaultKeyId = (UCHAR)3;
								
								
								
	if ( (KeyLen == 5) ||( KeyLen == 10) )
	pAdapter->PortCfg.CipherAlg = CIPHER_WEP64;
	else
	pAdapter->PortCfg.CipherAlg = CIPHER_WEP128;
								
	 RTUSBReadMACRegister(pAdapter, TXRX_CSR0, &Value);
	 Value &= 0xfe00;
	 Value |= ((LENGTH_802_11 << 3) | (pAdapter->PortCfg.CipherAlg));
	 RTUSBWriteMACRegister(pAdapter, TXRX_CSR0, Value);

	return TRUE;
}
/* 
	==========================================================================
	Description:
		Set WPA PSK key
	Return:
		TRUE if all parameters are OK, FALSE otherwise
	==========================================================================
*/
INT Set_WPAPSK_Proc(
	IN	PRT2570ADAPTER	 pAdapter, 
	IN	PUCHAR			arg)
{
#if 0
	UCHAR								keyMaterial[40];

	DBGPRINT(RT_DEBUG_TRACE, "Set_WPAPSK_Proc::(WPAPSK=%s)\n", arg);
	if ((strlen(arg) < 8) || (strlen(arg) > 64))
	{
		DBGPRINT(RT_DEBUG_TRACE, "Set failed!!(WPAPSK=%s), WPAPSK key-string required 8 ~ 64 characters \n", arg);
		return FALSE;
	}

	PasswordHash((char *)arg, pAdapter->PortCfg.Ssid, pAdapter->PortCfg.SsidLen, keyMaterial);

	memcpy(pAdapter->PortCfg.PskKey.Key, keyMaterial, 32);

	// Use RaConfig as PSK agent.
	// Start STA supplicant state machine
	pAdapter->PortCfg.WpaState = SS_START;
#ifdef RT2500_DBG
	DBGPRINT(RT_DEBUG_LOUD, "Set_WPAPSK_Proc WPAPSK Key => \n");
	DBGPRINT(RT_DEBUG_LOUD, "    ");
	for (i = 0; i < 32; i++)
	{
		DBGPRINT_RAW(RT_DEBUG_LOUD, "%02x:", pAdapter->PortCfg.PskKey.Key[i]);
		if (i%16 == 15) {
		  DBGPRINT_RAW(RT_DEBUG_LOUD, "\n");
		  DBGPRINT(RT_DEBUG_LOUD, "    ");
		}
	}
	DBGPRINT_RAW(RT_DEBUG_LOUD, "\n");
#endif
#endif
return TRUE;

}


int usb_rt2570_ioctl(struct net_device *net_dev, struct ifreq *rq,
			  int cmd)
{
	PRT2570ADAPTER		pAdapter= net_dev->priv;
	struct iwreq						*wrq = (struct iwreq *) rq;
	struct iw_point 					*erq = NULL;
	struct iw_freq						*frq = NULL;
	NDIS_802_11_NETWORK_INFRASTRUCTURE	BssType = Ndis802_11Infrastructure;
	NDIS_802_11_RTS_THRESHOLD			RtsThresh;
	NDIS_802_11_FRAGMENTATION_THRESHOLD FragThresh;
	NDIS_802_11_MAC_ADDRESS 			Bssid;
	INT 								Status = NDIS_STATUS_SUCCESS;	
	BOOLEAN 							StateMachineTouched = FALSE;
	int 								 chan = -1, index = 0, len = 0;
	USHORT	Value;
	
	if ( (RTMP_TEST_FLAG(pAdapter, fRTMP_ADAPTER_REMOVE_IN_PROGRESS)) || (RTMP_TEST_FLAG(pAdapter, fRTMP_ADAPTER_RESET_IN_PROGRESS)))
	{
		DBGPRINT(RT_DEBUG_TRACE,"INFO::remove in progress!\n");
		return -ENETDOWN;
	}
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 5, 0)
	if (pAdapter->RTUSBCmdThr_pid < 0)
		return -ENETDOWN;
#else
	if (!pAdapter->RTUSBCmdThr_active)
		return -ENETDOWN;
#endif
	
	switch(cmd) {

		case SIOCGIWNAME:
			DBGPRINT(RT_DEBUG_INFO,"IOCTL::SIOCGIWNAME\n");
			strcpy(wrq->u.name,"RT2570 Wireless");	 //Less then 16 bytes. 
			break;
		case SIOCSIWESSID:	//Set ESSID
			DBGPRINT(RT_DEBUG_INFO, "==>ioctl::SIOCSIWESSID\n");

			break;
		case SIOCGIWESSID:	//Get ESSID
			DBGPRINT(RT_DEBUG_INFO, "==>ioctl::SIOCGIWESSID\n");
			break;
		case SIOCSIWFREQ: // set channel/frequency (Hz)
			frq = &(wrq->u.freq);
			if((frq->e == 0) && (frq->m <= 1000))
				chan = frq->m;	// Setting by channel number 
			else
				MAP_KHZ_TO_CHANNEL_ID( (frq->m /100) , chan); // Setting by frequency - search the table , like 2.412G, 2.422G, 
			pAdapter->PortCfg.IbssConfig.Channel = chan;
			DBGPRINT(RT_DEBUG_ERROR, "<==ioctl::SIOCSIWFREQ[cmd=0x%x] (Channel=%d)\n", SIOCSIWFREQ, pAdapter->PortCfg.IbssConfig.Channel);
                break;
		case SIOCGIWFREQ: // get channel/frequency (Hz)
			DBGPRINT(RT_DEBUG_TRACE,"==>IOCTL::SIOCGIWFREQ\n");
			break;
		case SIOCGIWNICKN: //get node name/nickname
			DBGPRINT(RT_DEBUG_TRACE,"==>IOCTL::SIOCGIWNICKN\n");
			erq = &wrq->u.data;
			erq->length = strlen(pAdapter->nickn);
			if(copy_to_user(erq->pointer, pAdapter->nickn, erq->length))
				Status = -EFAULT;

			 DBGPRINT(RT_DEBUG_TRACE,"<==IOCTL::SIOCGIWNICKN\n");
			break;
		case SIOCSIWNICKN: //set node name/nickname
			DBGPRINT(RT_DEBUG_TRACE,"==>IOCTL::SIOCSIWNICKN\n");
			 DBGPRINT(RT_DEBUG_TRACE,"<==IOCTL::SIOCSIWNICKN\n");
			break;
		case SIOCGIWRATE:  //get default bit rate (bps)
			DBGPRINT(RT_DEBUG_TRACE,"==>IOCTL::SIOCGIWRATE\n");
			wrq->u.bitrate.value = RateIdToMbps[pAdapter->PortCfg.TxRate] * 1000000;
			wrq->u.bitrate.disabled = 0;
			 DBGPRINT(RT_DEBUG_TRACE,"<==IOCTL::SIOCGIWRATE\n");
			break;
		case SIOCSIWRATE:  //set default bit rate (bps)
			DBGPRINT(RT_DEBUG_TEMP,"==>IOCTL::SIOCSIWRATE %d\n",wrq->u.bitrate.value);
			RT2570SetDesiredRates(pAdapter, wrq->u.bitrate.value);
			 DBGPRINT(RT_DEBUG_TRACE,"<==IOCTL::SIOCSIWRATE\n");
			break;
		case SIOCGIWRTS:  // get RTS/CTS threshold (bytes)
			DBGPRINT(RT_DEBUG_TRACE,"==>IOCTL::SIOCGIWRTS\n");
			wrq->u.rts.value = (INT) pAdapter->PortCfg.RtsThreshold;
			wrq->u.rts.disabled = (wrq->u.rts.value == MAX_RTS_THRESHOLD);
			wrq->u.rts.fixed = 1;
			 DBGPRINT(RT_DEBUG_TRACE,"<==IOCTL::SIOCGIWRTS\n");
			break;
		case SIOCSIWRTS:  //set RTS/CTS threshold (bytes)
			DBGPRINT(RT_DEBUG_TRACE,"==>IOCTL::SIOCSIWRTS\n");
			RtsThresh = wrq->u.rts.value;
			if (wrq->u.rts.disabled)
				RtsThresh = MAX_RTS_THRESHOLD;

			if((RtsThresh > 0) && (RtsThresh <= MAX_RTS_THRESHOLD))
				pAdapter->PortCfg.RtsThreshold = (USHORT)RtsThresh;
			else if (RtsThresh == 0)
				pAdapter->PortCfg.RtsThreshold = MAX_RTS_THRESHOLD;

			DBGPRINT(RT_DEBUG_TRACE, "<==ioctl::SIOCSIWRTS (=%d)\n", pAdapter->PortCfg.RtsThreshold);
			break;
		case SIOCGIWFRAG:  //get fragmentation thr (bytes)
			DBGPRINT(RT_DEBUG_TRACE,"==>IOCTL::SIOCGIWFRAG\n");
			wrq->u.frag.value = (INT) pAdapter->PortCfg.FragmentThreshold;
			wrq->u.frag.disabled = (wrq->u.frag.value >= MAX_FRAG_THRESHOLD);
			wrq->u.frag.fixed = 1;
			 DBGPRINT(RT_DEBUG_TRACE,"<==IOCTL::SIOCGIWFRAG\n");
			break;
		case SIOCSIWFRAG:  //set fragmentation thr (bytes)
			DBGPRINT(RT_DEBUG_TRACE,"==>IOCTL::SIOCSIWFRAG\n");
			FragThresh = wrq->u.frag.value;
			if (wrq->u.rts.disabled)
				FragThresh = MAX_FRAG_THRESHOLD;

			if ( (FragThresh >= MIN_FRAG_THRESHOLD) && (FragThresh <= MAX_FRAG_THRESHOLD))
				pAdapter->PortCfg.FragmentThreshold = (USHORT)FragThresh;
			else if (FragThresh == 0)
				pAdapter->PortCfg.FragmentThreshold = MAX_FRAG_THRESHOLD;

			if (pAdapter->PortCfg.FragmentThreshold == MAX_FRAG_THRESHOLD)
				pAdapter->PortCfg.bFragmentZeroDisable = TRUE;
			else
				pAdapter->PortCfg.bFragmentZeroDisable = FALSE;

			DBGPRINT(RT_DEBUG_TRACE, "<==ioctl::SIOCSIWFRAG (=%d)\n", pAdapter->PortCfg.FragmentThreshold);
			break;
		case SIOCGIWENCODE:  //get encoding token & mode
			DBGPRINT(RT_DEBUG_TRACE,"==>IOCTL::SIOCGIWENCODE\n");
			index = (wrq->u.encoding.flags & IW_ENCODE_INDEX) - 1;
			if ((index < 0) || (index >= NR_WEP_KEYS))
				index = pAdapter->PortCfg.DefaultKeyId; // Default key for tx (shared key)

			if (pAdapter->PortCfg.AuthMode == Ndis802_11AuthModeOpen)
				wrq->u.encoding.flags = IW_ENCODE_OPEN;
			else if (pAdapter->PortCfg.AuthMode == Ndis802_11AuthModeShared)
				wrq->u.encoding.flags = IW_ENCODE_RESTRICTED;

			if (pAdapter->PortCfg.WepStatus == Ndis802_11WEPDisabled)
				wrq->u.encoding.flags |= IW_ENCODE_DISABLED;
			else
			{
				if(wrq->u.encoding.pointer)
				{
					wrq->u.encoding.length = pAdapter->PortCfg.SharedKey[pAdapter->PortCfg.DefaultKeyId].KeyLen;
					if(copy_to_user(wrq->u.encoding.pointer,
								pAdapter->PortCfg.SharedKey[pAdapter->PortCfg.DefaultKeyId].Key,
								pAdapter->PortCfg.SharedKey[pAdapter->PortCfg.DefaultKeyId].KeyLen))
						Status = -EFAULT;

					wrq->u.encoding.flags |= (pAdapter->PortCfg.DefaultKeyId + 1);
				}
			}
			 DBGPRINT(RT_DEBUG_TEMP,"<==IOCTL::SIOCGIWENCODE , DefaultKeyId=%d\n", pAdapter->PortCfg.DefaultKeyId);
			break;
		case SIOCSIWENCODE:  //set encoding token & mode
			index = (wrq->u.encoding.flags & IW_ENCODE_INDEX) - 1;
			DBGPRINT(RT_DEBUG_TEMP,"==>IOCTL::SIOCSIWENCODE index= %d\n",index);
			/* take the old default key if index is invalid */
			if((index < 0) || (index >= NR_WEP_KEYS))
				index = pAdapter->PortCfg.DefaultKeyId; 	// Default key for tx (shared key)

			if((wrq->u.encoding.pointer) && ((wrq->u.encoding.flags & IW_ENCODE_NOKEY) == 0))
			{
				printk(" !IW_ENCODE_NOKEY \n" );
				len = wrq->u.encoding.length;
				if(len > WEP_LARGE_KEY_LEN)
					len = WEP_LARGE_KEY_LEN;

				memset(pAdapter->PortCfg.SharedKey[index].Key, 0x00, MAX_LEN_OF_KEY);
				if(copy_from_user(pAdapter->PortCfg.SharedKey[index].Key, wrq->u.encoding.pointer, len))
					Status = -EINVAL;

				pAdapter->PortCfg.SharedKey[index].KeyLen = len <= WEP_SMALL_KEY_LEN ? WEP_SMALL_KEY_LEN : WEP_LARGE_KEY_LEN;
			}
			if (wrq->u.encoding.flags & IW_ENCODE_DISABLED)
				pAdapter->PortCfg.WepStatus = Ndis802_11WEPDisabled;
			else
				pAdapter->PortCfg.WepStatus = Ndis802_11WEPEnabled;

			if (wrq->u.encoding.flags & IW_ENCODE_RESTRICTED)
				pAdapter->PortCfg.AuthMode = Ndis802_11AuthModeShared;
			else 
				pAdapter->PortCfg.AuthMode = Ndis802_11AuthModeOpen;

			if(pAdapter->PortCfg.WepStatus == Ndis802_11WEPDisabled)
				pAdapter->PortCfg.AuthMode = Ndis802_11AuthModeOpen;

			if ((wrq->u.encoding.flags & IW_ENCODE_NOKEY) == 0)
			{
				RTUSBMultiWrite(pAdapter, (USHORT)(SEC_CSR0 + index * 0x10), pAdapter->PortCfg.SharedKey[index].Key, 16);	

				pAdapter->PortCfg.DefaultKeyId = (UCHAR) index;
				if ( (len == 5) ||( len == 10) )
					pAdapter->PortCfg.CipherAlg = CIPHER_WEP64;
				else
					pAdapter->PortCfg.CipherAlg = CIPHER_WEP128;
											
				 RTUSBReadMACRegister(pAdapter, TXRX_CSR0, &Value);
				 Value &= 0xfe00;
				 Value |= ((LENGTH_802_11 << 3) | (pAdapter->PortCfg.CipherAlg));
				 RTUSBWriteMACRegister(pAdapter, TXRX_CSR0, Value);

			}

			DBGPRINT(RT_DEBUG_TRACE,"<==IOCTL::SIOCSIWENCODE\n");
			break;
		case SIOCGIWAP:  //get access point MAC addresses
			DBGPRINT(RT_DEBUG_TRACE,"==>IOCTL::SIOCGIWAP\n");
			 DBGPRINT(RT_DEBUG_TEMP,"<==>IOCTL::SIOCGIWAP\n");
			break;
		case SIOCSIWAP:  //set access point MAC addresses
			DBGPRINT(RT_DEBUG_TRACE,"==>IOCTL::SIOCSIWAP\n");
			memcpy(&Bssid, &wrq->u.ap_addr.sa_data, sizeof(NDIS_802_11_MAC_ADDRESS));
			if (pAdapter->Mlme.CntlMachine.CurrState != CNTL_IDLE)
			{
				DBGPRINT(RT_DEBUG_TRACE, "!!! MLME busy, reset MLME state machine !!!\n");
			}

			// tell CNTL state machine to call NdisMSetInformationComplete() after completing
			// this request, because this request is initiated by NDIS.
			pAdapter->Mlme.CntlAux.CurrReqIsFromNdis = FALSE; 

			MlmeEnqueue(pAdapter, 
						MLME_CNTL_STATE_MACHINE, 
						OID_802_11_BSSID, 
						sizeof(NDIS_802_11_MAC_ADDRESS),
						(VOID *)&Bssid);
			Status = NDIS_STATUS_SUCCESS;
			StateMachineTouched = TRUE;
			DBGPRINT(RT_DEBUG_TRACE, "ioctl::SIOCSIWAP %02x:%02x:%02x:%02x:%02x:%02x\n",
									Bssid[0], Bssid[1], Bssid[2], Bssid[3], Bssid[4], Bssid[5]);
			 DBGPRINT(RT_DEBUG_TEMP,"<==IOCTL::SIOCSIWAP\n");
			break;
		case SIOCGIWMODE:  //get operation mode
			DBGPRINT(RT_DEBUG_TRACE,"==>IOCTL::SIOCGIWMODE\n");
			if (ADHOC_ON(pAdapter))
			{
				BssType = Ndis802_11IBSS;
				wrq->u.mode = IW_MODE_ADHOC;
			}
			else if (INFRA_ON(pAdapter))
			{
				BssType = Ndis802_11Infrastructure;
				wrq->u.mode = IW_MODE_INFRA;
			}
			else
			{
				BssType = Ndis802_11AutoUnknown;
				wrq->u.mode = IW_MODE_AUTO;
			}
			DBGPRINT(RT_DEBUG_TRACE, "<==ioctl::SIOCGIWMODE(=%d)\n", BssType);
			break;
		case SIOCSIWMODE:  //set operation mode
			DBGPRINT(RT_DEBUG_TRACE,"==>IOCTL::SIOCSIWMODE\n");
			DBGPRINT(RT_DEBUG_TEMP,"<==IOCTL::SIOCSIWMODE\n");
			break;
		case SIOCGIWSENS:	//get sensitivity (dBm)
		case SIOCSIWSENS:	//set sensitivity (dBm)
		case SIOCGIWPOWER:	//get Power Management settings
		case SIOCSIWPOWER:	//set Power Management settings
		case SIOCGIWTXPOW:	//get transmit power (dBm)
		case SIOCSIWTXPOW:	//set transmit power (dBm)
			DBGPRINT(RT_DEBUG_TRACE,"<==>IOCTL::multi not support\n");
			Status = -EOPNOTSUPP;
			break;
		case SIOCGIWAPLIST:
			DBGPRINT(RT_DEBUG_TEMP, "Query::SIOCGIWAPLIST (%d BSS returned)\n",pAdapter->PortCfg.BssTab.BssNr);
			DBGPRINT(RT_DEBUG_TEMP,"<==>WIRELESS_EXT=%d  IOCTL::SIOCGIWAPLIST \n",WIRELESS_EXT);
			break;

		case SIOCGIWPRIV:
			if (wrq->u.data.pointer) {
				if ( !access_ok(VERIFY_WRITE, wrq->u.data.pointer, sizeof(privtab)) )
					break;
				wrq->u.data.length = sizeof(privtab) / sizeof(privtab[0]);
				if (copy_to_user(wrq->u.data.pointer, privtab, sizeof(privtab)))
					Status = -EFAULT;
			}
			break;
		default:
			DBGPRINT(RT_DEBUG_INFO, "IOCTL::unknown IOCTL's cmd = 0x%08x\n", cmd);
			Status = -EOPNOTSUPP;
			break;
	}

	if(StateMachineTouched) // Upper layer sent a MLME-related operations
		RTUSBUp(pAdapter, (&(pAdapter->mlme_semaphore)));
	
	return Status;
}

