import PULS_20160108
[GitHub/mt8127/android_kernel_alcatel_ttab.git] / drivers / misc / mediatek / connectivity / combo / drv_wlan / mt6628 / wlan / os / linux / gl_wext.c
diff --git a/drivers/misc/mediatek/connectivity/combo/drv_wlan/mt6628/wlan/os/linux/gl_wext.c b/drivers/misc/mediatek/connectivity/combo/drv_wlan/mt6628/wlan/os/linux/gl_wext.c
new file mode 100644 (file)
index 0000000..e0c67ce
--- /dev/null
@@ -0,0 +1,4137 @@
+/*
+** $Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/os/linux/gl_wext.c#3 $
+*/
+
+/*! \file gl_wext.c
+    \brief  ioctl() (mostly Linux Wireless Extensions) routines for STA driver.
+*/
+
+
+
+/*
+** $Log: gl_wext.c $
+ *
+ * 06 13 2012 yuche.tsai
+ * NULL
+ * Update maintrunk driver.
+ * Add support for driver compose assoc request frame.
+ *
+ * 01 16 2012 wh.su
+ * [WCXRP00001170] [MT6620 Wi-Fi][Driver] Adding the related code for set/get band ioctl
+ * Adding the template code for set / get band IOCTL (with ICS supplicant_6)..
+ *
+ * 01 05 2012 wh.su
+ * [WCXRP00001153] [MT6620 Wi-Fi][Driver] Adding the get_ch_list and set_tx_power proto type function
+ * Adding the related ioctl / wlan oid function to set the Tx power cfg.
+ *
+ * 01 02 2012 wh.su
+ * [WCXRP00001153] [MT6620 Wi-Fi][Driver] Adding the get_ch_list and set_tx_power proto type function
+ * Adding the proto type function for set_int set_tx_power and get int get_ch_list.
+ *
+ * 11 10 2011 cp.wu
+ * [WCXRP00001098] [MT6620 Wi-Fi][Driver] Replace printk by DBG LOG macros in linux porting layer
+ * 1. eliminaite direct calls to printk in porting layer.
+ * 2. replaced by DBGLOG, which would be XLOG on ALPS platforms.
+ *
+ * 10 12 2011 wh.su
+ * [WCXRP00001036] [MT6620 Wi-Fi][Driver][FW] Adding the 802.11w code for MFP
+ * adding the 802.11w related function and define .
+ *
+ * 09 23 2011 tsaiyuan.hsu
+ * [WCXRP00000979] [MT6620 Wi-Fi][DRV]] stop attempting to connect to config AP after D3 state
+ * avoid entering D3 state after deep sleep.
+ *
+ * 07 28 2011 chinghwa.yu
+ * [WCXRP00000063] Update BCM CoEx design and settings
+ * Add BWCS cmd and event.
+ *
+ * 07 27 2011 wh.su
+ * [WCXRP00000877] [MT6620 Wi-Fi][Driver] Remove the netif_carry_ok check for avoid the wpa_supplicant fail to query the ap address
+ * Remove the netif check while query bssid and ssid
+ *
+ * 07 26 2011 chinglan.wang
+ * NULL
+ * [MT6620][WiFi Driver] Do not include the WSC IE in the association info packet when not do the wps connection..
+ *
+ * 07 18 2011 chinghwa.yu
+ * [WCXRP00000063] Update BCM CoEx design and settings[WCXRP00000612] [MT6620 Wi-Fi] [FW] CSD update SWRDD algorithm
+ * Add CMD/Event for RDD and BWCS.
+ *
+ * 05 17 2011 eddie.chen
+ * [WCXRP00000603] [MT6620 Wi-Fi][DRV] Fix Klocwork warning
+ * Initilize the vairlabes.
+ *
+ * 05 11 2011 jeffrey.chang
+ * [WCXRP00000718] [MT6620 Wi-Fi] modify the behavior of setting tx power
+ * modify set_tx_pow ioctl
+ *
+ * 03 29 2011 terry.wu
+ * [WCXRP00000610] [MT 6620 Wi-Fi][Driver] Fix klocwork waring
+ * [MT6620 Wi-Fi][Driver] Fix klocwork warning. Add Null pointer check on wext_get_essid. Limit the upper bound of essid storage array.
+ *
+ * 03 21 2011 cp.wu
+ * [WCXRP00000540] [MT5931][Driver] Add eHPI8/eHPI16 support to Linux Glue Layer
+ * improve portability for awareness of early version of linux kernel and wireless extension.
+ *
+ * 03 17 2011 chinglan.wang
+ * [WCXRP00000570] [MT6620 Wi-Fi][Driver] Add Wi-Fi Protected Setup v2.0 feature
+ * .
+ *
+ * 03 07 2011 terry.wu
+ * [WCXRP00000521] [MT6620 Wi-Fi][Driver] Remove non-standard debug message
+ * Toggle non-standard debug messages to comments.
+ *
+ * 02 21 2011 wh.su
+ * [WCXRP00000483] [MT6620 Wi-Fi][Driver] Check the kalIoctl return value before doing the memory copy at linux get essid
+ * fixed the potential error to do a larget memory copy while wlanoid get essid not actually running.
+ *
+ * 02 08 2011 george.huang
+ * [WCXRP00000422] [MT6620 Wi-Fi][Driver] support query power mode OID handler
+ * Support querying power mode OID.
+ *
+ * 01 29 2011 wh.su
+ * [WCXRP00000408] [MT6620 Wi-Fi][Driver] Not doing memory alloc while ioctl set ie with length 0
+ * not doing mem alloc. while set ie length already 0
+ *
+ * 01 20 2011 eddie.chen
+ * [WCXRP00000374] [MT6620 Wi-Fi][DRV] SW debug control
+ * Remove debug text.
+ *
+ * 01 20 2011 eddie.chen
+ * [WCXRP00000374] [MT6620 Wi-Fi][DRV] SW debug control
+ * Adjust OID order.
+ *
+ * 01 20 2011 eddie.chen
+ * [WCXRP00000374] [MT6620 Wi-Fi][DRV] SW debug control
+ * Add Oid for sw control debug command
+ *
+ * 01 11 2011 chinglan.wang
+ * NULL
+ * Modify to reslove the CR :[ALPS00028994] Use WEP security to connect Marvell 11N AP.  Connection establish successfully.
+ * Use the WPS function to connect AP, the privacy bit always is set to 1. .
+ *
+ * 01 07 2011 cm.chang
+ * [WCXRP00000336] [MT6620 Wi-Fi][Driver] Add test mode commands in normal phone operation
+ * Add a new compiling option to control if MCR read/write is permitted
+ *
+ * 01 04 2011 cp.wu
+ * [WCXRP00000338] [MT6620 Wi-Fi][Driver] Separate kalMemAlloc into kmalloc and vmalloc implementations to ease physically continous memory demands
+ * separate kalMemAlloc() into virtually-continous and physically-continous types
+ * to ease slab system pressure
+ *
+ * 01 04 2011 cp.wu
+ * [WCXRP00000338] [MT6620 Wi-Fi][Driver] Separate kalMemAlloc into kmalloc and vmalloc implementations to ease physically continous memory demands
+ * separate kalMemAlloc() into virtually-continous and physically-continous type to ease slab system pressure
+ *
+ * 12 31 2010 cm.chang
+ * [WCXRP00000336] [MT6620 Wi-Fi][Driver] Add test mode commands in normal phone operation
+ * Add some iwpriv commands to support test mode operation
+ *
+ * 12 15 2010 george.huang
+ * [WCXRP00000152] [MT6620 Wi-Fi] AP mode power saving function
+ * Support set PS profile and set WMM-PS related iwpriv.
+ *
+ * 12 15 2010 george.huang
+ * [WCXRP00000152] [MT6620 Wi-Fi] AP mode power saving function
+ * Allow change PS profile function (throught wext_set_power()).
+ *
+ * 12 14 2010 jeffrey.chang
+ * [WCXRP00000262] [MT6620 Wi-Fi][Driver] modify the scan request ioctl to handle hidden SSID
+ * handle hidden SSID
+ *
+ * 12 13 2010 chinglan.wang
+ * NULL
+ * Add WPS 1.0 feature flag to enable the WPS 1.0 function.
+ *
+ * 12 07 2010 cm.chang
+ * [WCXRP00000238] MT6620 Wi-Fi][Driver][FW] Support regulation domain setting from NVRAM and supplicant
+ * Fix compiling error
+ *
+ * 12 07 2010 cm.chang
+ * [WCXRP00000238] MT6620 Wi-Fi][Driver][FW] Support regulation domain setting from NVRAM and supplicant
+ * 1. Country code is from NVRAM or supplicant
+ * 2. Change band definition in CMD/EVENT.
+ *
+ * 11 30 2010 cp.wu
+ * [WCXRP00000213] [MT6620 Wi-Fi][Driver] Implement scanning with specified SSID for wpa_supplicant with ap_scan=1
+ * .
+ *
+ * 11 08 2010 wh.su
+ * [WCXRP00000171] [MT6620 Wi-Fi][Driver] Add message check code same behavior as mt5921
+ * add the message check code from mt5921.
+ *
+ * 10 19 2010 jeffrey.chang
+ * [WCXRP00000121] [MT6620 Wi-Fi][Driver] Temporarily disable set power mode ioctl which may cause 6620 to enter power saving
+ * Temporarily disable set power mode ioctl which may cause MT6620 to enter power saving
+ *
+ * 10 18 2010 jeffrey.chang
+ * [WCXRP00000116] [MT6620 Wi-Fi][Driver] Refine the set_scan ioctl to resolve the Android UI hanging issue
+ * refine the scan ioctl to prevent hanging of Android UI
+ *
+ * 10 01 2010 wh.su
+ * [WCXRP00000067] [MT6620 Wi-Fi][Driver] Support the android+ WAPI function
+ * add the scan result with wapi ie.
+ *
+ * 09 30 2010 wh.su
+ * [WCXRP00000072] [MT6620 Wi-Fi][Driver] Fix TKIP Counter Measure EAPoL callback register issue
+ * fixed the wapi ie assigned issue.
+ *
+ * 09 27 2010 wh.su
+ * NULL
+ * [WCXRP00000067][MT6620 Wi-Fi][Driver] Support the android+ WAPI function.
+ *
+ * 09 21 2010 kevin.huang
+ * [WCXRP00000052] [MT6620 Wi-Fi][Driver] Eliminate Linux Compile Warning
+ * Eliminate Linux Compile Warning
+ *
+ * 09 09 2010 cp.wu
+ * NULL
+ * add WPS/WPA/RSN IE for Wi-Fi Direct scanning result.
+ *
+ * 09 06 2010 cp.wu
+ * NULL
+ * Androi/Linux: return current operating channel information
+ *
+ * 09 01 2010 wh.su
+ * NULL
+ * adding the wapi support for integration test.
+ *
+ * 08 02 2010 jeffrey.chang
+ * NULL
+ * enable remove key ioctl
+ *
+ * 08 02 2010 jeffrey.chang
+ * NULL
+ * 1) modify tx service thread to avoid busy looping
+ * 2) add spin lock declartion for linux build
+ *
+ * 07 28 2010 jeffrey.chang
+ * NULL
+ * 1) enable encyption ioctls
+ * 2) temporarily disable remove keys ioctl to prevent  TX1 busy
+ *
+ * 07 28 2010 jeffrey.chang
+ * NULL
+ * 1) remove unused spinlocks
+ * 2) enable encyption ioctls
+ * 3) fix scan ioctl which may cause supplicant to hang
+ *
+ * 07 19 2010 jeffrey.chang
+ *
+ * add kal api for scanning done
+ *
+ * 07 19 2010 jeffrey.chang
+ *
+ * for linux driver migration
+ *
+ * 07 19 2010 jeffrey.chang
+ *
+ * Linux port modification
+ *
+ * 07 08 2010 cp.wu
+ *
+ * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository.
+ *
+ * 06 06 2010 kevin.huang
+ * [WPD00003832][MT6620 5931] Create driver base
+ * [MT6620 5931] Create driver base
+ *
+ * 05 28 2010 jeffrey.chang
+ * [WPD00003826]Initial import for Linux port
+ * remove unused macro and debug messages
+ *
+ * 05 14 2010 jeffrey.chang
+ * [WPD00003826]Initial import for Linux port
+ * Add dissassoication support for wpa supplicant
+ *
+ * 04 22 2010 jeffrey.chang
+ * [WPD00003826]Initial import for Linux port
+ *
+ * 1) modify rx path code for supporting Wi-Fi direct
+ * 2) modify config.h since Linux dont need to consider retaining packet
+ *
+ * 04 21 2010 jeffrey.chang
+ * [WPD00003826]Initial import for Linux port
+ * add for private ioctl support
+ *
+ * 04 19 2010 jeffrey.chang
+ * [WPD00003826]Initial import for Linux port
+ * Add ioctl of power management
+ *
+ * 04 19 2010 jeffrey.chang
+ * [WPD00003826]Initial import for Linux port
+ * remove debug message
+ *
+ * 04 14 2010 jeffrey.chang
+ * [WPD00003826]Initial import for Linux port
+ * 1) prGlueInfo->pvInformationBuffer and prGlueInfo->u4InformationBufferLength are no longer used
+ *  * 2) fix ioctl
+ *
+ * 04 12 2010 jeffrey.chang
+ * [WPD00003826]Initial import for Linux port
+ * remove debug messages for pre-release
+ *
+ * 04 07 2010 cp.wu
+ * [WPD00001943]Create WiFi test driver framework on WinXP
+ * rWlanInfo should be placed at adapter rather than glue due to most operations
+ *  *  *  *  *  *  *  * are done in adapter layer.
+ *
+ * 04 02 2010 jeffrey.chang
+ * [WPD00003826]Initial import for Linux port
+ * fix ioctl type
+ *
+ * 04 01 2010 jeffrey.chang
+ * [WPD00003826]Initial import for Linux port
+ * enable pmksa cache operation
+ *
+ * 03 31 2010 jeffrey.chang
+ * [WPD00003826]Initial import for Linux port
+ * fix ioctl which may cause cmdinfo memory leak
+ *
+ * 03 31 2010 wh.su
+ * [WPD00003816][MT6620 Wi-Fi] Adding the security support
+ * modify the wapi related code for new driver's design.
+ *
+ * 03 30 2010 jeffrey.chang
+ * [WPD00003826]Initial import for Linux port
+ * emulate NDIS Pending OID facility
+ *
+ * 03 24 2010 jeffrey.chang
+ * [WPD00003826]Initial import for Linux port
+ * initial import for Linux port
+**  \main\maintrunk.MT5921\38 2009-10-08 10:33:22 GMT mtk01090
+**  Avoid accessing private data of net_device directly. Replace with netdev_priv(). Add more checking for input parameters and pointers.
+**  \main\maintrunk.MT5921\37 2009-09-29 16:49:48 GMT mtk01090
+**  Remove unused variables
+**  \main\maintrunk.MT5921\36 2009-09-28 20:19:11 GMT mtk01090
+**  Add private ioctl to carry OID structures. Restructure public/private ioctl interfaces to Linux kernel.
+**  \main\maintrunk.MT5921\35 2009-09-03 11:42:30 GMT mtk01088
+**  adding the wapi ioctl support
+**  \main\maintrunk.MT5921\34 2009-08-18 22:56:50 GMT mtk01090
+**  Add Linux SDIO (with mmc core) support.
+**  Add Linux 2.6.21, 2.6.25, 2.6.26.
+**  Fix compile warning in Linux.
+**  \main\maintrunk.MT5921\33 2009-05-14 22:43:47 GMT mtk01089
+**  fix compiling warning
+**  \main\maintrunk.MT5921\32 2009-05-07 22:26:18 GMT mtk01089
+**  Add mandatory and private IO control for Linux BWCS
+**  \main\maintrunk.MT5921\31 2009-02-07 15:11:14 GMT mtk01088
+**  fixed the compiling error
+**  \main\maintrunk.MT5921\30 2009-02-07 14:46:51 GMT mtk01088
+**  add the privacy setting from linux supplicant ap selection
+**  \main\maintrunk.MT5921\29 2008-11-19 15:18:50 GMT mtk01088
+**  fixed the compling error
+**  \main\maintrunk.MT5921\28 2008-11-19 11:56:18 GMT mtk01088
+**  rename some variable with pre-fix to avoid the misunderstanding
+**  \main\maintrunk.MT5921\27 2008-08-29 16:59:43 GMT mtk01088
+**  fixed compiling error
+**  \main\maintrunk.MT5921\26 2008-08-29 14:55:53 GMT mtk01088
+**  adjust the code for meet the coding style, and add assert check
+**  \main\maintrunk.MT5921\25 2008-06-02 11:15:19 GMT mtk01461
+**  Update after wlanoidSetPowerMode changed
+**  \main\maintrunk.MT5921\24 2008-05-30 15:13:12 GMT mtk01084
+**  rename wlanoid
+**  \main\maintrunk.MT5921\23 2008-03-28 10:40:28 GMT mtk01461
+**  Add set desired rate in Linux STD IOCTL
+**  \main\maintrunk.MT5921\22 2008-03-18 10:31:24 GMT mtk01088
+**  add pmkid ioctl and indicate
+**  \main\maintrunk.MT5921\21 2008-03-11 15:21:24 GMT mtk01461
+**  \main\maintrunk.MT5921\20 2008-03-11 14:50:55 GMT mtk01461
+**  Refine WPS related priv ioctl for unified interface
+**
+**  \main\maintrunk.MT5921\19 2008-03-06 16:30:41 GMT mtk01088
+**  move the configuration code from set essid function,
+**  remove the non-used code
+**  \main\maintrunk.MT5921\18 2008-02-21 15:47:09 GMT mtk01461
+**  Fix CR[489]
+**  \main\maintrunk.MT5921\17 2008-02-12 23:38:31 GMT mtk01461
+**  Add Set Frequency & Channel oid support for Linux
+**  \main\maintrunk.MT5921\16 2008-01-24 12:07:34 GMT mtk01461
+**  \main\maintrunk.MT5921\15 2008-01-24 12:00:10 GMT mtk01461
+**  Modify the wext_essid for set up correct information for IBSS, and fix the wrong input ptr for prAdapter
+**  \main\maintrunk.MT5921\14 2007-12-06 09:30:12 GMT mtk01425
+**  1. Branch Test
+**  \main\maintrunk.MT5921\13 2007-12-04 18:07:59 GMT mtk01461
+**  fix typo
+**  \main\maintrunk.MT5921\12 2007-11-30 17:10:21 GMT mtk01425
+**  1. Fix compiling erros
+**
+**  \main\maintrunk.MT5921\11 2007-11-27 10:43:22 GMT mtk01425
+**  1. Add WMM-PS setting
+**  \main\maintrunk.MT5921\10 2007-11-06 20:33:32 GMT mtk01088
+**  fixed the compiler error
+**  \main\maintrunk.MT5921\9 2007-11-06 19:33:15 GMT mtk01088
+**  add WPS code
+**  \main\maintrunk.MT5921\8 2007-10-30 12:00:44 GMT MTK01425
+**  1. Update wlanQueryInformation
+*/
+
+/*******************************************************************************
+*                         C O M P I L E R   F L A G S
+********************************************************************************
+*/
+
+/*******************************************************************************
+*                    E X T E R N A L   R E F E R E N C E S
+********************************************************************************
+*/
+
+#include "gl_os.h"
+
+#include "config.h"
+#include "wlan_oid.h"
+
+#include "gl_wext.h"
+#include "gl_wext_priv.h"
+
+#include "precomp.h"
+
+#if CFG_SUPPORT_WAPI
+#include "gl_sec.h"
+#endif
+
+/* compatibility to wireless extensions */
+#ifdef WIRELESS_EXT
+
+/*******************************************************************************
+*                              C O N S T A N T S
+********************************************************************************
+*/
+const long channel_freq[] = {
+       2412, 2417, 2422, 2427, 2432, 2437, 2442,
+       2447, 2452, 2457, 2462, 2467, 2472, 2484
+};
+
+#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 165: /* UNII */  khz = 5825000;   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;   \
+                   case 184: /* Japan */   khz = 4920000;   break;   \
+                   case 188: /* Japan */   khz = 4940000;   break;   \
+                   case 192: /* Japan */   khz = 4960000;   break;   \
+                   case 196: /* Japan */   khz = 4980000;   break;   \
+                   case 208: /* Japan, means J08 */   khz = 5040000;   break;   \
+                   case 212: /* Japan, means J12 */   khz = 5060000;   break;   \
+                   case 216: /* Japan, means J16 */   khz = 5080000;   break;   \
+                   default:    khz = 2412000;   break;     \
+               }                                           \
+           }
+
+
+#define NUM_CHANNELS (sizeof(channel_freq) / sizeof(channel_freq[0]))
+
+#define MAX_SSID_LEN    32
+
+
+/*******************************************************************************
+*                             D A T A   T Y P E S
+********************************************************************************
+*/
+
+/*******************************************************************************
+*                            P U B L I C   D A T A
+********************************************************************************
+*/
+/* NOTE: name in iwpriv_args only have 16 bytes */
+static const struct iw_priv_args rIwPrivTable[] = {
+       {IOCTL_SET_INT, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, ""},
+       {IOCTL_GET_INT, 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, ""},
+       {IOCTL_SET_INT, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 3, 0, ""},
+       {IOCTL_GET_INT, 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 3, ""},
+       {IOCTL_SET_INT, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 2, 0, ""},
+
+       {IOCTL_GET_INT, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 2,
+        IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, ""},
+       {IOCTL_GET_INT, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
+        IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, ""},
+
+       {IOCTL_SET_INTS, IW_PRIV_TYPE_INT | 4, 0, ""},
+       {IOCTL_GET_INT, 0, IW_PRIV_TYPE_INT | 50, ""},
+       {IOCTL_GET_INT, 0, IW_PRIV_TYPE_CHAR | 16, ""},
+
+       /* added for set_oid and get_oid */
+       {IOCTL_SET_STRUCT, 256, 0, ""},
+       {IOCTL_GET_STRUCT, 0, 256, ""},
+
+       /* sub-ioctl definitions */
+#if 0
+       {PRIV_CMD_REG_DOMAIN, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "set_reg_domain"},
+       {PRIV_CMD_REG_DOMAIN, 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "get_reg_domain"},
+#endif
+
+#if CFG_TCP_IP_CHKSUM_OFFLOAD
+       {PRIV_CMD_CSUM_OFFLOAD, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "set_tcp_csum"},
+#endif                         /* CFG_TCP_IP_CHKSUM_OFFLOAD */
+
+       {PRIV_CMD_POWER_MODE, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "set_power_mode"},
+       {PRIV_CMD_POWER_MODE, 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "get_power_mode"},
+
+       {PRIV_CMD_WMM_PS, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 3, 0, "set_wmm_ps"},
+
+       {PRIV_CMD_TEST_MODE, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "set_test_mode"},
+       {PRIV_CMD_TEST_CMD, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 2, 0, "set_test_cmd"},
+       {PRIV_CMD_TEST_CMD, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 2,
+        IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "get_test_result"},
+#if CFG_SUPPORT_PRIV_MCR_RW
+       {PRIV_CMD_ACCESS_MCR, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 2, 0, "set_mcr"},
+       {PRIV_CMD_ACCESS_MCR, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
+        IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "get_mcr"},
+#endif
+       {PRIV_CMD_SW_CTRL, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 2, 0, "set_sw_ctrl"},
+       {PRIV_CMD_SW_CTRL, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
+        IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "get_sw_ctrl"},
+
+#if CFG_SUPPORT_BCM && CFG_SUPPORT_BCM_BWCS
+       {PRIV_CUSTOM_BWCS_CMD, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "set_bwcs"},
+       /* GET STRUCT sub-ioctls commands */
+       {PRIV_CUSTOM_BWCS_CMD, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
+        IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "get_bwcs"},
+#endif
+
+       /* SET STRUCT sub-ioctls commands */
+       {PRIV_CMD_OID, 256, 0, "set_oid"},
+       /* GET STRUCT sub-ioctls commands */
+       {PRIV_CMD_OID, 0, 256, "get_oid"},
+
+       {PRIV_CMD_BAND_CONFIG, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "set_band"},
+       {PRIV_CMD_BAND_CONFIG, 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "get_band"},
+
+       {PRIV_CMD_SET_TX_POWER, IW_PRIV_TYPE_INT | 4, 0, "set_txpower"},
+       {PRIV_CMD_GET_CH_LIST, 0, IW_PRIV_TYPE_INT | 50, "get_ch_list"},
+       {PRIV_CMD_DUMP_MEM, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 2,
+        IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "get_mem"},
+
+#if CFG_ENABLE_WIFI_DIRECT
+       {PRIV_CMD_P2P_MODE, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 2, 0, "set_p2p_mode"},
+#endif
+       {PRIV_CMD_GET_BUILD_DATE_CODE, 0, IW_PRIV_TYPE_CHAR | 16, "get_date_code"},
+};
+
+static const iw_handler rIwPrivHandler[] = {
+       [IOCTL_SET_INT - SIOCIWFIRSTPRIV] = priv_set_int,
+       [IOCTL_GET_INT - SIOCIWFIRSTPRIV] = priv_get_int,
+       [IOCTL_SET_ADDRESS - SIOCIWFIRSTPRIV] = NULL,
+       [IOCTL_GET_ADDRESS - SIOCIWFIRSTPRIV] = NULL,
+       [IOCTL_SET_STR - SIOCIWFIRSTPRIV] = NULL,
+       [IOCTL_GET_STR - SIOCIWFIRSTPRIV] = NULL,
+       [IOCTL_SET_KEY - SIOCIWFIRSTPRIV] = NULL,
+       [IOCTL_GET_KEY - SIOCIWFIRSTPRIV] = NULL,
+       [IOCTL_SET_STRUCT - SIOCIWFIRSTPRIV] = priv_set_struct,
+       [IOCTL_GET_STRUCT - SIOCIWFIRSTPRIV] = priv_get_struct,
+       [IOCTL_SET_STRUCT_FOR_EM - SIOCIWFIRSTPRIV] = priv_set_struct,
+       [IOCTL_SET_INTS - SIOCIWFIRSTPRIV] = priv_set_ints,
+       [IOCTL_GET_INTS - SIOCIWFIRSTPRIV] = priv_get_ints,
+};
+
+const struct iw_handler_def wext_handler_def = {
+       .num_standard = 0,
+       .num_private = (__u16) sizeof(rIwPrivHandler) / sizeof(iw_handler),
+       .num_private_args = (__u16) sizeof(rIwPrivTable) / sizeof(struct iw_priv_args),
+       .standard = (iw_handler *) NULL,
+       .private = rIwPrivHandler,
+       .private_args = rIwPrivTable,
+       .get_wireless_stats = wext_get_wireless_stats,
+};
+
+/*******************************************************************************
+*                           P R I V A T E   D A T A
+********************************************************************************
+*/
+
+/*******************************************************************************
+*                                 M A C R O S
+********************************************************************************
+*/
+
+/*******************************************************************************
+*                  F U N C T I O N   D E C L A R A T I O N S
+********************************************************************************
+*/
+
+/*******************************************************************************
+*                              F U N C T I O N S
+********************************************************************************
+*/
+
+/*----------------------------------------------------------------------------*/
+/*!
+* \brief Find the desired WPA/RSN Information Element according to desiredElemID.
+*
+* \param[in] pucIEStart IE starting address.
+* \param[in] i4TotalIeLen Total length of all the IE.
+* \param[in] ucDesiredElemId Desired element ID.
+* \param[out] ppucDesiredIE Pointer to the desired IE.
+*
+* \retval TRUE Find the desired IE.
+* \retval FALSE Desired IE not found.
+*
+* \note
+*/
+/*----------------------------------------------------------------------------*/
+BOOLEAN
+wextSrchDesiredWPAIE(IN PUINT_8 pucIEStart,
+                    IN INT_32 i4TotalIeLen, IN UINT_8 ucDesiredElemId, OUT PUINT_8 * ppucDesiredIE)
+{
+       INT_32 i4InfoElemLen;
+
+       ASSERT(pucIEStart);
+       ASSERT(ppucDesiredIE);
+
+       while (i4TotalIeLen >= 2) {
+               i4InfoElemLen = (INT_32) pucIEStart[1] + 2;
+
+               if (pucIEStart[0] == ucDesiredElemId && i4InfoElemLen <= i4TotalIeLen) {
+                       if (ucDesiredElemId != 0xDD) {
+                               /* Non 0xDD, OK! */
+                               *ppucDesiredIE = &pucIEStart[0];
+                               return TRUE;
+                       } else {
+                               /* EID == 0xDD, check WPA IE */
+                               if (pucIEStart[1] >= 4) {
+                                       if (memcmp(&pucIEStart[2], "\x00\x50\xf2\x01", 4) == 0) {
+                                               *ppucDesiredIE = &pucIEStart[0];
+                                               return TRUE;
+                                       }
+                               }       /* check WPA IE length */
+                       }       /* check EID == 0xDD */
+               }
+
+               /* check desired EID */
+               /* Select next information element. */
+               i4TotalIeLen -= i4InfoElemLen;
+               pucIEStart += i4InfoElemLen;
+       }
+
+       return FALSE;
+}                              /* parseSearchDesiredWPAIE */
+
+
+#if CFG_SUPPORT_WAPI
+/*----------------------------------------------------------------------------*/
+/*!
+* \brief Find the desired WAPI Information Element .
+*
+* \param[in] pucIEStart IE starting address.
+* \param[in] i4TotalIeLen Total length of all the IE.
+* \param[out] ppucDesiredIE Pointer to the desired IE.
+*
+* \retval TRUE Find the desired IE.
+* \retval FALSE Desired IE not found.
+*
+* \note
+*/
+/*----------------------------------------------------------------------------*/
+BOOLEAN
+wextSrchDesiredWAPIIE(IN PUINT_8 pucIEStart, IN INT_32 i4TotalIeLen, OUT PUINT_8 * ppucDesiredIE)
+{
+       INT_32 i4InfoElemLen;
+
+       ASSERT(pucIEStart);
+       ASSERT(ppucDesiredIE);
+
+       while (i4TotalIeLen >= 2) {
+               i4InfoElemLen = (INT_32) pucIEStart[1] + 2;
+
+               if (pucIEStart[0] == ELEM_ID_WAPI && i4InfoElemLen <= i4TotalIeLen) {
+                       *ppucDesiredIE = &pucIEStart[0];
+                       return TRUE;
+               }
+
+               /* check desired EID */
+               /* Select next information element. */
+               i4TotalIeLen -= i4InfoElemLen;
+               pucIEStart += i4InfoElemLen;
+       }
+
+       return FALSE;
+}                              /* wextSrchDesiredWAPIIE */
+#endif
+
+
+#if CFG_SUPPORT_WPS
+/*----------------------------------------------------------------------------*/
+/*!
+* \brief Find the desired WPS Information Element according to desiredElemID.
+*
+* \param[in] pucIEStart IE starting address.
+* \param[in] i4TotalIeLen Total length of all the IE.
+* \param[in] ucDesiredElemId Desired element ID.
+* \param[out] ppucDesiredIE Pointer to the desired IE.
+*
+* \retval TRUE Find the desired IE.
+* \retval FALSE Desired IE not found.
+*
+* \note
+*/
+/*----------------------------------------------------------------------------*/
+BOOLEAN
+wextSrchDesiredWPSIE(IN PUINT_8 pucIEStart,
+                    IN INT_32 i4TotalIeLen, IN UINT_8 ucDesiredElemId, OUT PUINT_8 * ppucDesiredIE)
+{
+       INT_32 i4InfoElemLen;
+
+       ASSERT(pucIEStart);
+       ASSERT(ppucDesiredIE);
+
+       while (i4TotalIeLen >= 2) {
+               i4InfoElemLen = (INT_32) pucIEStart[1] + 2;
+
+               if (pucIEStart[0] == ucDesiredElemId && i4InfoElemLen <= i4TotalIeLen) {
+                       if (ucDesiredElemId != 0xDD) {
+                               /* Non 0xDD, OK! */
+                               *ppucDesiredIE = &pucIEStart[0];
+                               return TRUE;
+                       } else {
+                               /* EID == 0xDD, check WPS IE */
+                               if (pucIEStart[1] >= 4) {
+                                       if (memcmp(&pucIEStart[2], "\x00\x50\xf2\x04", 4) == 0) {
+                                               *ppucDesiredIE = &pucIEStart[0];
+                                               return TRUE;
+                                       }
+                               }       /* check WPS IE length */
+                       }       /* check EID == 0xDD */
+               }
+
+               /* check desired EID */
+               /* Select next information element. */
+               i4TotalIeLen -= i4InfoElemLen;
+               pucIEStart += i4InfoElemLen;
+       }
+
+       return FALSE;
+}                              /* parseSearchDesiredWPSIE */
+#endif
+
+
+/*----------------------------------------------------------------------------*/
+/*!
+* \brief Get the name of the protocol used on the air.
+*
+* \param[in]  prDev Net device requested.
+* \param[in]  prIwrInfo NULL.
+* \param[out] pcName Buffer to store protocol name string
+* \param[in]  pcExtra NULL.
+*
+* \retval 0 For success.
+*
+* \note If netif_carrier_ok, protocol name is returned;
+*       otherwise, "disconnected" is returned.
+*/
+/*----------------------------------------------------------------------------*/
+static int
+wext_get_name(IN struct net_device *prNetDev,
+             IN struct iw_request_info *prIwrInfo, OUT char *pcName, IN char *pcExtra)
+{
+       ENUM_PARAM_NETWORK_TYPE_T eNetWorkType;
+
+       P_GLUE_INFO_T prGlueInfo = NULL;
+       WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS;
+       UINT_32 u4BufLen = 0;
+
+       ASSERT(prNetDev);
+       ASSERT(pcName);
+       if (FALSE == GLUE_CHK_PR2(prNetDev, pcName)) {
+               return -EINVAL;
+       }
+       prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev));
+
+       if (netif_carrier_ok(prNetDev)) {
+
+               rStatus = kalIoctl(prGlueInfo,
+                                  wlanoidQueryNetworkTypeInUse,
+                                  &eNetWorkType,
+                                  sizeof(eNetWorkType), TRUE, FALSE, FALSE, FALSE, &u4BufLen);
+
+               switch (eNetWorkType) {
+               case PARAM_NETWORK_TYPE_DS:
+                       strcpy(pcName, "IEEE 802.11b");
+                       break;
+               case PARAM_NETWORK_TYPE_OFDM24:
+                       strcpy(pcName, "IEEE 802.11bgn");
+                       break;
+               case PARAM_NETWORK_TYPE_AUTOMODE:
+               case PARAM_NETWORK_TYPE_OFDM5:
+                       strcpy(pcName, "IEEE 802.11abgn");
+                       break;
+               case PARAM_NETWORK_TYPE_FH:
+               default:
+                       strcpy(pcName, "IEEE 802.11");
+                       break;
+               }
+       } else {
+               strcpy(pcName, "Disconnected");
+       }
+
+       return 0;
+}                              /* wext_get_name */
+
+/*----------------------------------------------------------------------------*/
+/*!
+* \brief To set the operating channel in the wireless device.
+*
+* \param[in] prDev Net device requested.
+* \param[in] prIwrInfo NULL
+* \param[in] prFreq Buffer to store frequency information
+* \param[in] pcExtra NULL
+*
+* \retval 0 For success.
+* \retval -EOPNOTSUPP If infrastructure mode is not NET NET_TYPE_IBSS.
+* \retval -EINVAL Invalid channel frequency.
+*
+* \note If infrastructure mode is IBSS, new channel frequency is set to device.
+*      The range of channel number depends on different regulatory domain.
+*/
+/*----------------------------------------------------------------------------*/
+static int
+wext_set_freq(IN struct net_device *prNetDev,
+             IN struct iw_request_info *prIwReqInfo, IN struct iw_freq *prIwFreq, IN char *pcExtra)
+{
+
+#if 0
+       UINT_32 u4ChnlFreq;     /* Store channel or frequency information */
+
+       P_GLUE_INFO_T prGlueInfo = NULL;
+       WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS;
+       UINT_32 u4BufLen = 0;
+
+       ASSERT(prNetDev);
+       ASSERT(prIwFreq);
+       if (FALSE == GLUE_CHK_PR2(prNetDev, prIwFreq)) {
+               return -EINVAL;
+       }
+       prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev));
+
+       /*
+          printk("set m:%d, e:%d, i:%d, flags:%d\n",
+          prIwFreq->m, prIwFreq->e, prIwFreq->i, prIwFreq->flags);
+        */
+
+       /* If setting by frequency, convert to a channel */
+       if ((prIwFreq->e == 1) && (prIwFreq->m >= (int)2.412e8) && (prIwFreq->m <= (int)2.484e8)) {
+
+               /* Change to KHz format */
+               u4ChnlFreq = (UINT_32) (prIwFreq->m / (KILO / 10));
+
+               rStatus = kalIoctl(prGlueInfo,
+                                  wlanoidSetFrequency,
+                                  &u4ChnlFreq, sizeof(u4ChnlFreq), FALSE, FALSE, FALSE, &u4BufLen);
+
+               if (WLAN_STATUS_SUCCESS != rStatus) {
+                       return -EINVAL;
+               }
+       }
+       /* Setting by channel number */
+       else if ((prIwFreq->m > KILO) || (prIwFreq->e > 0)) {
+               return -EOPNOTSUPP;
+       } else {
+               /* Change to channel number format */
+               u4ChnlFreq = (UINT_32) prIwFreq->m;
+
+               rStatus = kalIoctl(prGlueInfo,
+                                  wlanoidSetChannel,
+                                  &u4ChnlFreq, sizeof(u4ChnlFreq), FALSE, FALSE, FALSE, &u4BufLen);
+
+
+
+
+               if (WLAN_STATUS_SUCCESS != rStatus) {
+                       return -EINVAL;
+               }
+       }
+
+#endif
+
+       return 0;
+
+}                              /* wext_set_freq */
+
+
+/*----------------------------------------------------------------------------*/
+/*!
+* \brief To get the operating channel in the wireless device.
+*
+* \param[in] prDev Net device requested.
+* \param[in] prIwrInfo NULL.
+* \param[out] prFreq Buffer to store frequency information.
+* \param[in] pcExtra NULL.
+*
+* \retval 0 If netif_carrier_ok.
+* \retval -ENOTCONN Otherwise
+*
+* \note If netif_carrier_ok, channel frequency information is stored in pFreq.
+*/
+/*----------------------------------------------------------------------------*/
+static int
+wext_get_freq(IN struct net_device *prNetDev,
+             IN struct iw_request_info *prIwrInfo, OUT struct iw_freq *prIwFreq, IN char *pcExtra)
+{
+       UINT_32 u4Channel = 0;
+
+
+       P_GLUE_INFO_T prGlueInfo = NULL;
+       WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS;
+       UINT_32 u4BufLen = 0;
+
+       ASSERT(prNetDev);
+       ASSERT(prIwFreq);
+       if (FALSE == GLUE_CHK_PR2(prNetDev, prIwFreq)) {
+               return -EINVAL;
+       }
+       prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev));
+
+       /* GeorgeKuo: TODO skip checking in IBSS mode */
+       if (!netif_carrier_ok(prNetDev)) {
+               return -ENOTCONN;
+       }
+
+       rStatus = kalIoctl(prGlueInfo,
+                          wlanoidQueryFrequency,
+                          &u4Channel, sizeof(u4Channel), TRUE, FALSE, FALSE, FALSE, &u4BufLen);
+
+       prIwFreq->m = (int)u4Channel;   /* freq in KHz */
+       prIwFreq->e = 3;
+
+       return 0;
+
+}                              /* wext_get_freq */
+
+
+/*----------------------------------------------------------------------------*/
+/*!
+* \brief To set operating mode.
+*
+* \param[in] prDev Net device requested.
+* \param[in] prIwrInfo NULL.
+* \param[in] pu4Mode Pointer to new operation mode.
+* \param[in] pcExtra NULL.
+*
+* \retval 0 For success.
+* \retval -EOPNOTSUPP If new mode is not supported.
+*
+* \note Device will run in new operation mode if it is valid.
+*/
+/*----------------------------------------------------------------------------*/
+static int
+wext_set_mode(IN struct net_device *prNetDev,
+             IN struct iw_request_info *prIwReqInfo, IN unsigned int *pu4Mode, IN char *pcExtra)
+{
+       ENUM_PARAM_OP_MODE_T eOpMode;
+
+       P_GLUE_INFO_T prGlueInfo = NULL;
+       WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS;
+       UINT_32 u4BufLen = 0;
+
+       ASSERT(prNetDev);
+       ASSERT(pu4Mode);
+       if (FALSE == GLUE_CHK_PR2(prNetDev, pu4Mode)) {
+               return -EINVAL;
+       }
+       prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev));
+
+       switch (*pu4Mode) {
+       case IW_MODE_AUTO:
+               eOpMode = NET_TYPE_AUTO_SWITCH;
+               break;
+
+       case IW_MODE_ADHOC:
+               eOpMode = NET_TYPE_IBSS;
+               break;
+
+       case IW_MODE_INFRA:
+               eOpMode = NET_TYPE_INFRA;
+               break;
+
+       default:
+               DBGLOG(INIT, INFO, ("%s(): Set UNSUPPORTED Mode = %d.\n", __func__, *pu4Mode));
+               return -EOPNOTSUPP;
+       }
+
+       /* printk("%s(): Set Mode = %d\n", __FUNCTION__, *pu4Mode); */
+
+       rStatus = kalIoctl(prGlueInfo,
+                          wlanoidSetInfrastructureMode,
+                          &eOpMode, sizeof(eOpMode), FALSE, FALSE, TRUE, FALSE, &u4BufLen);
+
+
+       /* after set operation mode, key table are cleared */
+
+       /* reset wpa info */
+       prGlueInfo->rWpaInfo.u4WpaVersion = IW_AUTH_WPA_VERSION_DISABLED;
+       prGlueInfo->rWpaInfo.u4KeyMgmt = 0;
+       prGlueInfo->rWpaInfo.u4CipherGroup = IW_AUTH_CIPHER_NONE;
+       prGlueInfo->rWpaInfo.u4CipherPairwise = IW_AUTH_CIPHER_NONE;
+       prGlueInfo->rWpaInfo.u4AuthAlg = IW_AUTH_ALG_OPEN_SYSTEM;
+#if CFG_SUPPORT_802_11W
+       prGlueInfo->rWpaInfo.u4Mfp = IW_AUTH_MFP_DISABLED;
+#endif
+
+       return 0;
+}                              /* wext_set_mode */
+
+/*----------------------------------------------------------------------------*/
+/*!
+* \brief To get operating mode.
+*
+* \param[in] prNetDev Net device requested.
+* \param[in] prIwReqInfo NULL.
+* \param[out] pu4Mode Buffer to store operating mode information.
+* \param[in] pcExtra NULL.
+*
+* \retval 0 If data is valid.
+* \retval -EINVAL Otherwise.
+*
+* \note If netif_carrier_ok, operating mode information is stored in pu4Mode.
+*/
+/*----------------------------------------------------------------------------*/
+static int
+wext_get_mode(IN struct net_device *prNetDev,
+             IN struct iw_request_info *prIwReqInfo, OUT unsigned int *pu4Mode, IN char *pcExtra)
+{
+       ENUM_PARAM_OP_MODE_T eOpMode;
+
+       P_GLUE_INFO_T prGlueInfo = NULL;
+       WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS;
+       UINT_32 u4BufLen = 0;
+
+       ASSERT(prNetDev);
+       ASSERT(pu4Mode);
+       if (FALSE == GLUE_CHK_PR2(prNetDev, pu4Mode)) {
+               return -EINVAL;
+       }
+       prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev));
+
+       rStatus = kalIoctl(prGlueInfo,
+                          wlanoidQueryInfrastructureMode,
+                          &eOpMode, sizeof(eOpMode), TRUE, FALSE, FALSE, FALSE, &u4BufLen);
+
+
+
+       switch (eOpMode) {
+       case NET_TYPE_IBSS:
+               *pu4Mode = IW_MODE_ADHOC;
+               break;
+
+       case NET_TYPE_INFRA:
+               *pu4Mode = IW_MODE_INFRA;
+               break;
+
+       case NET_TYPE_AUTO_SWITCH:
+               *pu4Mode = IW_MODE_AUTO;
+               break;
+
+       default:
+               DBGLOG(INIT, INFO, ("%s(): Get UNKNOWN Mode.\n", __func__));
+               return -EINVAL;
+       }
+
+       return 0;
+}                              /* wext_get_mode */
+
+/*----------------------------------------------------------------------------*/
+/*!
+* \brief To get the valid range for each configurable STA setting value.
+*
+* \param[in] prDev Net device requested.
+* \param[in] prIwrInfo NULL.
+* \param[in] prData Pointer to iw_point structure, not used.
+* \param[out] pcExtra Pointer to buffer which is allocated by caller of this
+*                     function, wext_support_ioctl() or ioctl_standard_call() in
+*                     wireless.c.
+*
+* \retval 0 If data is valid.
+*
+* \note The extra buffer (pcExtra) is filled with information from driver.
+*/
+/*----------------------------------------------------------------------------*/
+static int
+wext_get_range(IN struct net_device *prNetDev,
+              IN struct iw_request_info *prIwrInfo, IN struct iw_point *prData, OUT char *pcExtra)
+{
+       struct iw_range *prRange = NULL;
+       PARAM_RATES_EX aucSuppRate = { 0 };     /* data buffers */
+       int i = 0;
+
+       P_GLUE_INFO_T prGlueInfo = NULL;
+       WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS;
+       UINT_32 u4BufLen = 0;
+
+       ASSERT(prNetDev);
+       ASSERT(pcExtra);
+       if (FALSE == GLUE_CHK_PR2(prNetDev, pcExtra)) {
+               return -EINVAL;
+       }
+       prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev));
+
+       prRange = (struct iw_range *)pcExtra;
+
+       memset(prRange, 0, sizeof(*prRange));
+       prRange->throughput = 20000000; /* 20Mbps */
+       prRange->min_nwid = 0;  /* not used */
+       prRange->max_nwid = 0;  /* not used */
+
+       /* scan_capa not implemented */
+
+       /* event_capa[6]: kernel + driver capabilities */
+       prRange->event_capa[0] = (IW_EVENT_CAPA_K_0 | IW_EVENT_CAPA_MASK(SIOCGIWAP)
+                                 | IW_EVENT_CAPA_MASK(SIOCGIWSCAN)
+                                 /* can't display meaningful string in iwlist
+                                    | IW_EVENT_CAPA_MASK(SIOCGIWTXPOW)
+                                    | IW_EVENT_CAPA_MASK(IWEVMICHAELMICFAILURE)
+                                    | IW_EVENT_CAPA_MASK(IWEVASSOCREQIE)
+                                    | IW_EVENT_CAPA_MASK(IWEVPMKIDCAND)
+                                  */
+           );
+       prRange->event_capa[1] = IW_EVENT_CAPA_K_1;
+
+       /* report 2.4G channel and frequency only */
+       prRange->num_channels = (__u16) NUM_CHANNELS;
+       prRange->num_frequency = (__u8) NUM_CHANNELS;
+       for (i = 0; i < NUM_CHANNELS; i++) {
+               /* iwlib takes this number as channel number */
+               prRange->freq[i].i = i + 1;
+               prRange->freq[i].m = channel_freq[i];
+               prRange->freq[i].e = 6; /* Values in table in MHz */
+       }
+
+       rStatus = kalIoctl(prGlueInfo,
+                          wlanoidQuerySupportedRates,
+                          &aucSuppRate, sizeof(aucSuppRate), TRUE, FALSE, FALSE, FALSE, &u4BufLen);
+
+
+
+       for (i = 0; i < IW_MAX_BITRATES && i < PARAM_MAX_LEN_RATES_EX; i++) {
+               if (aucSuppRate[i] == 0) {
+                       break;
+               }
+               prRange->bitrate[i] = (aucSuppRate[i] & 0x7F) * 500000; /* 0.5Mbps */
+       }
+       prRange->num_bitrates = i;
+
+       prRange->min_rts = 0;
+       prRange->max_rts = 2347;
+       prRange->min_frag = 256;
+       prRange->max_frag = 2346;
+
+       prRange->min_pmp = 0;   /* power management by driver */
+       prRange->max_pmp = 0;   /* power management by driver */
+       prRange->min_pmt = 0;   /* power management by driver */
+       prRange->max_pmt = 0;   /* power management by driver */
+       prRange->pmp_flags = IW_POWER_RELATIVE; /* pm default flag */
+       prRange->pmt_flags = IW_POWER_ON;       /* pm timeout flag */
+       prRange->pm_capa = IW_POWER_ON; /* power management by driver */
+
+       prRange->encoding_size[0] = 5;  /* wep40 */
+       prRange->encoding_size[1] = 16; /* tkip */
+       prRange->encoding_size[2] = 16; /* ckip */
+       prRange->encoding_size[3] = 16; /* ccmp */
+       prRange->encoding_size[4] = 13; /* wep104 */
+       prRange->encoding_size[5] = 16; /* wep128 */
+       prRange->num_encoding_sizes = 6;
+       prRange->max_encoding_tokens = 6;       /* token? */
+
+#if WIRELESS_EXT < 17
+       prRange->txpower_capa = 0x0002; /* IW_TXPOW_RELATIVE */
+#else
+       prRange->txpower_capa = IW_TXPOW_RELATIVE;
+#endif
+       prRange->num_txpower = 5;
+       prRange->txpower[0] = 0;        /* minimum */
+       prRange->txpower[1] = 25;       /* 25% */
+       prRange->txpower[2] = 50;       /* 50% */
+       prRange->txpower[3] = 100;      /* 100% */
+
+       prRange->we_version_compiled = WIRELESS_EXT;
+       prRange->we_version_source = WIRELESS_EXT;
+
+       prRange->retry_capa = IW_RETRY_LIMIT;
+       prRange->retry_flags = IW_RETRY_LIMIT;
+       prRange->min_retry = 7;
+       prRange->max_retry = 7;
+       prRange->r_time_flags = IW_RETRY_ON;
+       prRange->min_r_time = 0;
+       prRange->max_r_time = 0;
+
+       /* signal strength and link quality */
+       /* Just define range here, reporting value moved to wext_get_stats() */
+       prRange->sensitivity = -83;     /* fixed value */
+       prRange->max_qual.qual = 100;   /* max 100% */
+       prRange->max_qual.level = (__u8) (0x100 - 0);   /* max 0 dbm */
+       prRange->max_qual.noise = (__u8) (0x100 - 0);   /* max 0 dbm */
+
+       /* enc_capa */
+#if WIRELESS_EXT > 17
+       prRange->enc_capa = IW_ENC_CAPA_WPA |
+           IW_ENC_CAPA_WPA2 | IW_ENC_CAPA_CIPHER_TKIP | IW_ENC_CAPA_CIPHER_CCMP;
+#endif
+
+       /* min_pms; Minimal PM saving */
+       /* max_pms; Maximal PM saving */
+       /* pms_flags; How to decode max/min PM saving */
+
+       /* modul_capa; IW_MODUL_* bit field */
+       /* bitrate_capa; Types of bitrates supported */
+
+       return 0;
+}                              /* wext_get_range */
+
+
+/*----------------------------------------------------------------------------*/
+/*!
+* \brief To set BSSID of AP to connect.
+*
+* \param[in] prDev Net device requested.
+* \param[in] prIwrInfo NULL.
+* \param[in] prAddr Pointer to struct sockaddr structure containing AP's BSSID.
+* \param[in] pcExtra NULL.
+*
+* \retval 0 For success.
+*
+* \note Desired AP's BSSID is set to driver.
+*/
+/*----------------------------------------------------------------------------*/
+static int
+wext_set_ap(IN struct net_device *prDev,
+           IN struct iw_request_info *prIwrInfo, IN struct sockaddr *prAddr, IN char *pcExtra)
+{
+       return 0;
+}                              /* wext_set_ap */
+
+
+/*----------------------------------------------------------------------------*/
+/*!
+* \brief To get AP MAC address.
+*
+* \param[in] prDev Net device requested.
+* \param[in] prIwrInfo NULL.
+* \param[out] prAddr Pointer to struct sockaddr structure storing AP's BSSID.
+* \param[in] pcExtra NULL.
+*
+* \retval 0 If netif_carrier_ok.
+* \retval -ENOTCONN Otherwise.
+*
+* \note If netif_carrier_ok, AP's mac address is stored in pAddr->sa_data.
+*/
+/*----------------------------------------------------------------------------*/
+static int
+wext_get_ap(IN struct net_device *prNetDev,
+           IN struct iw_request_info *prIwrInfo, OUT struct sockaddr *prAddr, IN char *pcExtra)
+{
+       P_GLUE_INFO_T prGlueInfo = NULL;
+       WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS;
+       UINT_32 u4BufLen = 0;
+
+       ASSERT(prNetDev);
+       ASSERT(prAddr);
+       if (FALSE == GLUE_CHK_PR2(prNetDev, prAddr)) {
+               return -EINVAL;
+       }
+       prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev));
+
+       /* if (!netif_carrier_ok(prNetDev)) { */
+       /* return -ENOTCONN; */
+       /* } */
+
+       if (prGlueInfo->eParamMediaStateIndicated == PARAM_MEDIA_STATE_DISCONNECTED) {
+               memset(prAddr, 0, 6);
+               return 0;
+       }
+
+       rStatus = kalIoctl(prGlueInfo,
+                          wlanoidQueryBssid,
+                          prAddr->sa_data, ETH_ALEN, TRUE, FALSE, FALSE, FALSE, &u4BufLen);
+
+       return 0;
+}                              /* wext_get_ap */
+
+/*----------------------------------------------------------------------------*/
+/*!
+* \brief To set mlme operation request.
+*
+* \param[in] prDev Net device requested.
+* \param[in] prIwrInfo NULL.
+* \param[in] prData Pointer of iw_point header.
+* \param[in] pcExtra Pointer to iw_mlme structure mlme request information.
+*
+* \retval 0 For success.
+* \retval -EOPNOTSUPP unsupported IW_MLME_ command.
+* \retval -EINVAL Set MLME Fail, different bssid.
+*
+* \note Driver will start mlme operation if valid.
+*/
+/*----------------------------------------------------------------------------*/
+static int
+wext_set_mlme(IN struct net_device *prNetDev,
+             IN struct iw_request_info *prIwrInfo, IN struct iw_point *prData, IN char *pcExtra)
+{
+       struct iw_mlme *prMlme = NULL;
+
+
+       P_GLUE_INFO_T prGlueInfo = NULL;
+       WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS;
+       UINT_32 u4BufLen = 0;
+
+       ASSERT(prNetDev);
+       ASSERT(pcExtra);
+       if (FALSE == GLUE_CHK_PR2(prNetDev, pcExtra)) {
+               return -EINVAL;
+       }
+       prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev));
+
+       prMlme = (struct iw_mlme *)pcExtra;
+       if (prMlme->cmd == IW_MLME_DEAUTH || prMlme->cmd == IW_MLME_DISASSOC) {
+               if (!netif_carrier_ok(prNetDev)) {
+                       DBGLOG(INIT, INFO,
+                              ("[wifi] Set MLME Deauth/Disassoc, but netif_carrier_off\n"));
+                       return 0;
+               }
+
+               rStatus = kalIoctl(prGlueInfo,
+                                  wlanoidSetDisassociate,
+                                  NULL, 0, FALSE, FALSE, TRUE, FALSE, &u4BufLen);
+               return 0;
+       } else {
+               DBGLOG(INIT, INFO, ("[wifi] unsupported IW_MLME_ command :%d\n", prMlme->cmd));
+               return -EOPNOTSUPP;
+       }
+}                              /* wext_set_mlme */
+
+/*----------------------------------------------------------------------------*/
+/*!
+* \brief To issue scan request.
+*
+* \param[in] prDev Net device requested.
+* \param[in] prIwrInfo NULL.
+* \param[in] prData NULL.
+* \param[in] pcExtra NULL.
+*
+* \retval 0 For success.
+* \retval -EFAULT Tx power is off.
+*
+* \note Device will start scanning.
+*/
+/*----------------------------------------------------------------------------*/
+static int
+wext_set_scan(IN struct net_device *prNetDev,
+             IN struct iw_request_info *prIwrInfo, IN union iwreq_data *prData, IN char *pcExtra)
+{
+       P_GLUE_INFO_T prGlueInfo = NULL;
+       WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS;
+       UINT_32 u4BufLen = 0;
+       int essid_len = 0;
+
+       ASSERT(prNetDev);
+       if (FALSE == GLUE_CHK_DEV(prNetDev)) {
+               return -EINVAL;
+       }
+       prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev));
+
+#if WIRELESS_EXT > 17
+       /* retrieve SSID */
+       if (prData) {
+               essid_len =
+                   ((struct iw_scan_req *)(((struct iw_point *)prData)->pointer))->essid_len;
+       }
+#endif
+
+       init_completion(&prGlueInfo->rScanComp);
+
+       /* TODO:  parse flags and issue different scan requests? */
+
+       rStatus = kalIoctl(prGlueInfo,
+                          wlanoidSetBssidListScan,
+                          pcExtra, essid_len, FALSE, FALSE, FALSE, FALSE, &u4BufLen);
+
+       /* wait_for_completion_interruptible_timeout(&prGlueInfo->rScanComp, 2 * KAL_HZ); */
+       /* kalIndicateStatusAndComplete(prGlueInfo, WLAN_STATUS_SCAN_COMPLETE, NULL, 0); */
+
+
+       return 0;
+}                              /* wext_set_scan */
+
+
+/*----------------------------------------------------------------------------*/
+/*!
+* \brief To write the ie to buffer
+*
+*/
+/*----------------------------------------------------------------------------*/
+static inline int snprintf_hex(char *buf, size_t buf_size, const u8 *data, size_t len)
+{
+       size_t i;
+       char *pos = buf, *end = buf + buf_size;
+       int ret;
+
+       if (buf_size == 0)
+               return 0;
+
+       for (i = 0; i < len; i++) {
+               ret = snprintf(pos, end - pos, "%02x", data[i]);
+               if (ret < 0 || ret >= end - pos) {
+                       end[-1] = '\0';
+                       return pos - buf;
+               }
+               pos += ret;
+       }
+       end[-1] = '\0';
+       return pos - buf;
+}
+
+
+/*----------------------------------------------------------------------------*/
+/*!
+* \brief To get scan results, transform results from driver's format to WE's.
+*
+* \param[in] prDev Net device requested.
+* \param[in] prIwrInfo NULL.
+* \param[out] prData Pointer to iw_point structure, pData->length is the size of
+*               pcExtra buffer before used, and is updated after filling scan
+*               results.
+* \param[out] pcExtra Pointer to buffer which is allocated by caller of this
+*                     function, wext_support_ioctl() or ioctl_standard_call() in
+*                     wireless.c.
+*
+* \retval 0 For success.
+* \retval -ENOMEM If dynamic memory allocation fail.
+* \retval -E2BIG Invalid length.
+*
+* \note Scan results is filled into pcExtra buffer, data size is updated in
+*       pData->length.
+*/
+/*----------------------------------------------------------------------------*/
+static int
+wext_get_scan(IN struct net_device *prNetDev,
+             IN struct iw_request_info *prIwrInfo,
+             IN OUT struct iw_point *prData, IN char *pcExtra)
+{
+       UINT_32 i = 0;
+       UINT_32 j = 0;
+       P_PARAM_BSSID_LIST_EX_T prList = NULL;
+       P_PARAM_BSSID_EX_T prBss = NULL;
+       P_PARAM_VARIABLE_IE_T prDesiredIE = NULL;
+       struct iw_event iwEvent;        /* local iw_event buffer */
+
+       /* write pointer of extra buffer */
+       char *pcCur = NULL;
+       /* pointer to the end of  last full entry in extra buffer */
+       char *pcValidEntryEnd = NULL;
+       char *pcEnd = NULL;     /* end of extra buffer */
+
+       UINT_32 u4AllocBufLen = 0;
+
+       /* arrange rate information */
+       UINT_32 u4HighestRate = 0;
+       char aucRatesBuf[64];
+       UINT_32 u4BufIndex;
+
+       /* return value */
+       int ret = 0;
+
+       P_GLUE_INFO_T prGlueInfo = NULL;
+       WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS;
+       UINT_32 u4BufLen = 0;
+
+       ASSERT(prNetDev);
+       ASSERT(prData);
+       ASSERT(pcExtra);
+       if (FALSE == GLUE_CHK_PR3(prNetDev, prData, pcExtra)) {
+               return -EINVAL;
+       }
+       prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev));
+
+       /* Initialize local variables */
+       pcCur = pcExtra;
+       pcValidEntryEnd = pcExtra;
+       pcEnd = pcExtra + prData->length;       /* end of extra buffer */
+
+       /* Allocate another query buffer with the same size of extra buffer */
+       u4AllocBufLen = prData->length;
+       prList = kalMemAlloc(u4AllocBufLen, VIR_MEM_TYPE);
+       if (prList == NULL) {
+               DBGLOG(INIT, INFO, ("[wifi] no memory for scan list:%d\n", prData->length));
+               ret = -ENOMEM;
+               goto error;
+       }
+       prList->u4NumberOfItems = 0;
+
+       /* wait scan done */
+       /* printk ("wait for scan results\n"); */
+       /* wait_for_completion_interruptible_timeout(&prGlueInfo->rScanComp, 4 * KAL_HZ); */
+
+       rStatus = kalIoctl(prGlueInfo,
+                          wlanoidQueryBssidList,
+                          prList, u4AllocBufLen, TRUE, FALSE, FALSE, FALSE, &u4BufLen);
+
+       if (rStatus == WLAN_STATUS_INVALID_LENGTH) {
+               /* Buffer length is not large enough. */
+               /* printk(KERN_INFO "[wifi] buf:%d result:%ld\n", pData->length, u4BufLen); */
+
+#if WIRELESS_EXT >= 17
+               /* This feature is supported in WE-17 or above, limited by iwlist.
+                ** Return -E2BIG and iwlist will request again with a larger buffer.
+                */
+               ret = -E2BIG;
+               /* Update length to give application a hint on result length */
+               prData->length = (__u16) u4BufLen;
+               goto error;
+#else
+               /* Realloc a larger query buffer here, but don't write too much to extra
+                ** buffer when filling it later.
+                */
+               kalMemFree(prList, VIR_MEM_TYPE, u4AllocBufLen);
+
+               u4AllocBufLen = u4BufLen;
+               prList = kalMemAlloc(u4AllocBufLen, VIR_MEM_TYPE);
+               if (prList == NULL) {
+                       DBGLOG(INIT, INFO,
+                              ("[wifi] no memory for larger scan list :%ld\n", u4BufLen));
+                       ret = -ENOMEM;
+                       goto error;
+               }
+               prList->NumberOfItems = 0;
+
+               rStatus = kalIoctl(prGlueInfo,
+                                  wlanoidQueryBssidList,
+                                  prList, u4AllocBufLen, TRUE, FALSE, FALSE, FALSE, &u4BufLen);
+
+               if (rStatus == WLAN_STATUS_INVALID_LENGTH) {
+                       DBGLOG(INIT, INFO,
+                              ("[wifi] larger buf:%d result:%ld\n", u4AllocBufLen, u4BufLen));
+                       ret = -E2BIG;
+                       prData->length = (__u16) u4BufLen;
+                       goto error;
+               }
+#endif                         /* WIRELESS_EXT >= 17 */
+
+       }
+
+
+       if (prList->u4NumberOfItems > CFG_MAX_NUM_BSS_LIST) {
+               DBGLOG(INIT, INFO, ("[wifi] strange scan result count:%ld\n",
+                                   prList->u4NumberOfItems));
+               goto error;
+       }
+
+       /* Copy required data from pList to pcExtra */
+       prBss = &prList->arBssid[0];    /* set to the first entry */
+       for (i = 0; i < prList->u4NumberOfItems; ++i) {
+               /* BSSID */
+               iwEvent.cmd = SIOCGIWAP;
+               iwEvent.len = IW_EV_ADDR_LEN;
+               if ((pcCur + iwEvent.len) > pcEnd)
+                       break;
+               iwEvent.u.ap_addr.sa_family = ARPHRD_ETHER;
+               memcpy(iwEvent.u.ap_addr.sa_data, prBss->arMacAddress, ETH_ALEN);
+               memcpy(pcCur, &iwEvent, IW_EV_ADDR_LEN);
+               pcCur += IW_EV_ADDR_LEN;
+
+               /* SSID */
+               iwEvent.cmd = SIOCGIWESSID;
+               /* Modification to user space pointer(essid.pointer) is not needed. */
+               iwEvent.u.essid.length = (__u16) prBss->rSsid.u4SsidLen;
+               iwEvent.len = IW_EV_POINT_LEN + iwEvent.u.essid.length;
+
+               if ((pcCur + iwEvent.len) > pcEnd)
+                       break;
+               iwEvent.u.essid.flags = 1;
+               iwEvent.u.essid.pointer = NULL;
+
+#if WIRELESS_EXT <= 18
+               memcpy(pcCur, &iwEvent, iwEvent.len);
+#else
+               memcpy(pcCur, &iwEvent, IW_EV_LCP_LEN);
+               memcpy(pcCur + IW_EV_LCP_LEN,
+                      &iwEvent.u.data.length, sizeof(struct iw_point) - IW_EV_POINT_OFF);
+#endif
+               memcpy(pcCur + IW_EV_POINT_LEN, prBss->rSsid.aucSsid, iwEvent.u.essid.length);
+               pcCur += iwEvent.len;
+               /* Frequency */
+               iwEvent.cmd = SIOCGIWFREQ;
+               iwEvent.len = IW_EV_FREQ_LEN;
+               if ((pcCur + iwEvent.len) > pcEnd)
+                       break;
+               iwEvent.u.freq.m = prBss->rConfiguration.u4DSConfig;
+               iwEvent.u.freq.e = 3;   /* (in KHz) */
+               iwEvent.u.freq.i = 0;
+               memcpy(pcCur, &iwEvent, IW_EV_FREQ_LEN);
+               pcCur += IW_EV_FREQ_LEN;
+
+               /* Operation Mode */
+               iwEvent.cmd = SIOCGIWMODE;
+               iwEvent.len = IW_EV_UINT_LEN;
+               if ((pcCur + iwEvent.len) > pcEnd)
+                       break;
+               if (prBss->eOpMode == NET_TYPE_IBSS) {
+                       iwEvent.u.mode = IW_MODE_ADHOC;
+               } else if (prBss->eOpMode == NET_TYPE_INFRA) {
+                       iwEvent.u.mode = IW_MODE_INFRA;
+               } else {
+                       iwEvent.u.mode = IW_MODE_AUTO;
+               }
+               memcpy(pcCur, &iwEvent, IW_EV_UINT_LEN);
+               pcCur += IW_EV_UINT_LEN;
+
+               /* Quality */
+               iwEvent.cmd = IWEVQUAL;
+               iwEvent.len = IW_EV_QUAL_LEN;
+               if ((pcCur + iwEvent.len) > pcEnd)
+                       break;
+               iwEvent.u.qual.qual = 0;        /* Quality not available now */
+               /* -100 < Rssi < -10, normalized by adding 0x100 */
+               iwEvent.u.qual.level = 0x100 + prBss->rRssi;
+               iwEvent.u.qual.noise = 0;       /* Noise not available now */
+               iwEvent.u.qual.updated = IW_QUAL_QUAL_INVALID | IW_QUAL_LEVEL_UPDATED
+                   | IW_QUAL_NOISE_INVALID;
+               memcpy(pcCur, &iwEvent, IW_EV_QUAL_LEN);
+               pcCur += IW_EV_QUAL_LEN;
+
+               /* Security Mode */
+               iwEvent.cmd = SIOCGIWENCODE;
+               iwEvent.len = IW_EV_POINT_LEN;
+               if ((pcCur + iwEvent.len) > pcEnd)
+                       break;
+               iwEvent.u.data.pointer = NULL;
+               iwEvent.u.data.flags = 0;
+               iwEvent.u.data.length = 0;
+               if (!prBss->u4Privacy) {
+                       iwEvent.u.data.flags |= IW_ENCODE_DISABLED;
+               }
+#if WIRELESS_EXT <= 18
+               memcpy(pcCur, &iwEvent, IW_EV_POINT_LEN);
+#else
+               memcpy(pcCur, &iwEvent, IW_EV_LCP_LEN);
+               memcpy(pcCur + IW_EV_LCP_LEN,
+                      &iwEvent.u.data.length, sizeof(struct iw_point) - IW_EV_POINT_OFF);
+#endif
+               pcCur += IW_EV_POINT_LEN;
+
+               /* rearrange rate information */
+               u4BufIndex = sprintf(aucRatesBuf, "Rates (Mb/s):");
+               u4HighestRate = 0;
+               for (j = 0; j < PARAM_MAX_LEN_RATES_EX; ++j) {
+                       UINT_8 curRate = prBss->rSupportedRates[j] & 0x7F;
+                       if (curRate == 0) {
+                               break;
+                       }
+
+                       if (curRate > u4HighestRate) {
+                               u4HighestRate = curRate;
+                       }
+
+                       if (curRate == RATE_5_5M) {
+                               u4BufIndex += sprintf(aucRatesBuf + u4BufIndex, " 5.5");
+                       } else {
+                               u4BufIndex += sprintf(aucRatesBuf + u4BufIndex, " %d", curRate / 2);
+                       }
+#if DBG
+                       if (u4BufIndex > sizeof(aucRatesBuf)) {
+                               /* printk("rate info too long\n"); */
+                               break;
+                       }
+#endif
+               }
+               /* Report Highest Rates */
+               iwEvent.cmd = SIOCGIWRATE;
+               iwEvent.len = IW_EV_PARAM_LEN;
+               if ((pcCur + iwEvent.len) > pcEnd)
+                       break;
+               iwEvent.u.bitrate.value = u4HighestRate * 500000;
+               iwEvent.u.bitrate.fixed = 0;
+               iwEvent.u.bitrate.disabled = 0;
+               iwEvent.u.bitrate.flags = 0;
+               memcpy(pcCur, &iwEvent, iwEvent.len);
+               pcCur += iwEvent.len;
+
+#if WIRELESS_EXT >= 15         /* IWEVCUSTOM is available in WE-15 or above */
+               /* Report Residual Rates */
+               iwEvent.cmd = IWEVCUSTOM;
+               iwEvent.u.data.length = u4BufIndex;
+               iwEvent.len = IW_EV_POINT_LEN + iwEvent.u.data.length;
+               if ((pcCur + iwEvent.len) > pcEnd)
+                       break;
+               iwEvent.u.data.flags = 0;
+#if WIRELESS_EXT <= 18
+               memcpy(pcCur, &iwEvent, IW_EV_POINT_LEN);
+#else
+               memcpy(pcCur, &iwEvent, IW_EV_LCP_LEN);
+               memcpy(pcCur + IW_EV_LCP_LEN,
+                      &iwEvent.u.data.length, sizeof(struct iw_point) - IW_EV_POINT_OFF);
+#endif
+               memcpy(pcCur + IW_EV_POINT_LEN, aucRatesBuf, u4BufIndex);
+               pcCur += iwEvent.len;
+#endif                         /* WIRELESS_EXT >= 15 */
+
+
+               if (wextSrchDesiredWPAIE(&prBss->aucIEs[sizeof(PARAM_FIXED_IEs)],
+                                        prBss->u4IELength - sizeof(PARAM_FIXED_IEs),
+                                        0xDD, (PUINT_8 *) &prDesiredIE)) {
+                       iwEvent.cmd = IWEVGENIE;
+                       iwEvent.u.data.flags = 1;
+                       iwEvent.u.data.length = 2 + (__u16) prDesiredIE->ucLength;
+                       iwEvent.len = IW_EV_POINT_LEN + iwEvent.u.data.length;
+                       if ((pcCur + iwEvent.len) > pcEnd)
+                               break;
+#if WIRELESS_EXT <= 18
+                       memcpy(pcCur, &iwEvent, IW_EV_POINT_LEN);
+#else
+                       memcpy(pcCur, &iwEvent, IW_EV_LCP_LEN);
+                       memcpy(pcCur + IW_EV_LCP_LEN,
+                              &iwEvent.u.data.length, sizeof(struct iw_point) - IW_EV_POINT_OFF);
+#endif
+                       memcpy(pcCur + IW_EV_POINT_LEN, prDesiredIE, 2 + prDesiredIE->ucLength);
+                       pcCur += iwEvent.len;
+               }
+#if CFG_SUPPORT_WPS            /* search WPS IE (0xDD, 221, OUI: 0x0050f204 ) */
+               if (wextSrchDesiredWPSIE(&prBss->aucIEs[sizeof(PARAM_FIXED_IEs)],
+                                        prBss->u4IELength - sizeof(PARAM_FIXED_IEs),
+                                        0xDD, (PUINT_8 *) &prDesiredIE)) {
+                       iwEvent.cmd = IWEVGENIE;
+                       iwEvent.u.data.flags = 1;
+                       iwEvent.u.data.length = 2 + (__u16) prDesiredIE->ucLength;
+                       iwEvent.len = IW_EV_POINT_LEN + iwEvent.u.data.length;
+                       if ((pcCur + iwEvent.len) > pcEnd)
+                               break;
+#if WIRELESS_EXT <= 18
+                       memcpy(pcCur, &iwEvent, IW_EV_POINT_LEN);
+#else
+                       memcpy(pcCur, &iwEvent, IW_EV_LCP_LEN);
+                       memcpy(pcCur + IW_EV_LCP_LEN,
+                              &iwEvent.u.data.length, sizeof(struct iw_point) - IW_EV_POINT_OFF);
+#endif
+                       memcpy(pcCur + IW_EV_POINT_LEN, prDesiredIE, 2 + prDesiredIE->ucLength);
+                       pcCur += iwEvent.len;
+               }
+#endif
+
+
+               /* Search RSN IE (0x30, 48). pBss->IEs starts from timestamp. */
+               /* pBss->IEs starts from timestamp */
+               if (wextSrchDesiredWPAIE(&prBss->aucIEs[sizeof(PARAM_FIXED_IEs)],
+                                        prBss->u4IELength - sizeof(PARAM_FIXED_IEs),
+                                        0x30, (PUINT_8 *) &prDesiredIE)) {
+
+                       iwEvent.cmd = IWEVGENIE;
+                       iwEvent.u.data.flags = 1;
+                       iwEvent.u.data.length = 2 + (__u16) prDesiredIE->ucLength;
+                       iwEvent.len = IW_EV_POINT_LEN + iwEvent.u.data.length;
+                       if ((pcCur + iwEvent.len) > pcEnd)
+                               break;
+#if WIRELESS_EXT <= 18
+                       memcpy(pcCur, &iwEvent, IW_EV_POINT_LEN);
+#else
+                       memcpy(pcCur, &iwEvent, IW_EV_LCP_LEN);
+                       memcpy(pcCur + IW_EV_LCP_LEN,
+                              &iwEvent.u.data.length, sizeof(struct iw_point) - IW_EV_POINT_OFF);
+#endif
+                       memcpy(pcCur + IW_EV_POINT_LEN, prDesiredIE, 2 + prDesiredIE->ucLength);
+                       pcCur += iwEvent.len;
+               }
+#if CFG_SUPPORT_WAPI           /* Android+ */
+               if (wextSrchDesiredWAPIIE(&prBss->aucIEs[sizeof(PARAM_FIXED_IEs)],
+                                         prBss->u4IELength - sizeof(PARAM_FIXED_IEs),
+                                         (PUINT_8 *) &prDesiredIE)) {
+
+#if 0
+                       iwEvent.cmd = IWEVGENIE;
+                       iwEvent.u.data.flags = 1;
+                       iwEvent.u.data.length = 2 + (__u16) prDesiredIE->ucLength;
+                       iwEvent.len = IW_EV_POINT_LEN + iwEvent.u.data.length;
+                       if ((pcCur + iwEvent.len) > pcEnd)
+                               break;
+#if WIRELESS_EXT <= 18
+                       memcpy(pcCur, &iwEvent, IW_EV_POINT_LEN);
+#else
+                       memcpy(pcCur, &iwEvent, IW_EV_LCP_LEN);
+                       memcpy(pcCur + IW_EV_LCP_LEN,
+                              &iwEvent.u.data.length, sizeof(struct iw_point) - IW_EV_POINT_OFF);
+#endif
+                       memcpy(pcCur + IW_EV_POINT_LEN, prDesiredIE, 2 + prDesiredIE->ucLength);
+                       pcCur += iwEvent.len;
+#else
+                       iwEvent.cmd = IWEVCUSTOM;
+                       iwEvent.u.data.length = (2 + prDesiredIE->ucLength) * 2 + 8 /* wapi_ie= */;
+                       iwEvent.len = IW_EV_POINT_LEN + iwEvent.u.data.length;
+                       if ((pcCur + iwEvent.len) > pcEnd)
+                               break;
+                       iwEvent.u.data.flags = 1;
+
+                       memcpy(pcCur, &iwEvent, IW_EV_LCP_LEN);
+                       memcpy(pcCur + IW_EV_LCP_LEN,
+                              &iwEvent.u.data.length, sizeof(struct iw_point) - IW_EV_POINT_OFF);
+
+                       pcCur += (IW_EV_POINT_LEN);
+
+                       pcCur += sprintf(pcCur, "wapi_ie=");
+
+                       snprintf_hex(pcCur, pcEnd - pcCur, (UINT_8 *) prDesiredIE,
+                                    prDesiredIE->ucLength + 2);
+
+                       pcCur += (2 + prDesiredIE->ucLength) * 2 /* iwEvent.len */;
+#endif
+               }
+#endif
+               /* Complete an entry. Update end of valid entry */
+               pcValidEntryEnd = pcCur;
+               /* Extract next bss */
+               prBss = (P_PARAM_BSSID_EX_T) ((char *)prBss + prBss->u4Length);
+       }
+
+       /* Update valid data length for caller function and upper layer
+        * applications.
+        */
+       prData->length = (pcValidEntryEnd - pcExtra);
+       /* printk(KERN_INFO "[wifi] buf:%d result:%ld\n", pData->length, u4BufLen); */
+
+       /* kalIndicateStatusAndComplete(prGlueInfo, WLAN_STATUS_SCAN_COMPLETE, NULL, 0); */
+
+ error :
+       /* free local query buffer */
+       if (prList) {
+               kalMemFree(prList, VIR_MEM_TYPE, u4AllocBufLen);
+       }
+
+       return ret;
+}                              /* wext_get_scan */
+
+/*----------------------------------------------------------------------------*/
+/*!
+* \brief To set desired network name ESSID.
+*
+* \param[in] prDev Net device requested.
+* \param[in] prIwrInfo NULL.
+* \param[in] prEssid Pointer of iw_point header.
+* \param[in] pcExtra Pointer to buffer srtoring essid string.
+*
+* \retval 0 If netif_carrier_ok.
+* \retval -E2BIG Essid string length is too big.
+* \retval -EINVAL pcExtra is null pointer.
+* \retval -EFAULT Driver fail to set new essid.
+*
+* \note If string lengh is ok, device will try connecting to the new network.
+*/
+/*----------------------------------------------------------------------------*/
+static int
+wext_set_essid(IN struct net_device *prNetDev,
+              IN struct iw_request_info *prIwrInfo, IN struct iw_point *prEssid, IN char *pcExtra)
+{
+       PARAM_SSID_T rNewSsid;
+       UINT_32 cipher;
+       ENUM_PARAM_ENCRYPTION_STATUS_T eEncStatus;
+       ENUM_PARAM_AUTH_MODE_T eAuthMode;
+
+       P_GLUE_INFO_T prGlueInfo = NULL;
+       WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS;
+       UINT_32 u4BufLen = 0;
+
+       ASSERT(prNetDev);
+       ASSERT(prEssid);
+       ASSERT(pcExtra);
+       if (FALSE == GLUE_CHK_PR3(prNetDev, prEssid, pcExtra)) {
+               return -EINVAL;
+       }
+       prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev));
+
+       if (prEssid->length > IW_ESSID_MAX_SIZE) {
+               return -E2BIG;
+       }
+
+
+       /* set auth mode */
+       if (prGlueInfo->rWpaInfo.u4WpaVersion == IW_AUTH_WPA_VERSION_DISABLED) {
+               eAuthMode = (prGlueInfo->rWpaInfo.u4AuthAlg == IW_AUTH_ALG_OPEN_SYSTEM) ?
+                   AUTH_MODE_OPEN : AUTH_MODE_AUTO_SWITCH;
+               /* printk(KERN_INFO "IW_AUTH_WPA_VERSION_DISABLED->Param_AuthMode%s\n", */
+               /* (eAuthMode == AUTH_MODE_OPEN) ? "Open" : "Shared"); */
+       } else {
+               /* set auth mode */
+               switch (prGlueInfo->rWpaInfo.u4KeyMgmt) {
+               case IW_AUTH_KEY_MGMT_802_1X:
+                       eAuthMode =
+                           (prGlueInfo->rWpaInfo.u4WpaVersion == IW_AUTH_WPA_VERSION_WPA) ?
+                           AUTH_MODE_WPA : AUTH_MODE_WPA2;
+                       /* printk("IW_AUTH_KEY_MGMT_802_1X->AUTH_MODE_WPA%s\n", */
+                       /* (eAuthMode == AUTH_MODE_WPA) ? "" : "2"); */
+                       break;
+               case IW_AUTH_KEY_MGMT_PSK:
+                       eAuthMode =
+                           (prGlueInfo->rWpaInfo.u4WpaVersion == IW_AUTH_WPA_VERSION_WPA) ?
+                           AUTH_MODE_WPA_PSK : AUTH_MODE_WPA2_PSK;
+                       /* printk("IW_AUTH_KEY_MGMT_PSK->AUTH_MODE_WPA%sPSK\n", */
+                       /* (eAuthMode == AUTH_MODE_WPA_PSK) ? "" : "2"); */
+                       break;
+#if CFG_SUPPORT_WAPI           /* Android+ */
+               case IW_AUTH_KEY_MGMT_WAPI_PSK:
+                       break;
+               case IW_AUTH_KEY_MGMT_WAPI_CERT:
+                       break;
+#endif
+
+/* #if defined (IW_AUTH_KEY_MGMT_WPA_NONE) */
+/* case IW_AUTH_KEY_MGMT_WPA_NONE: */
+/* eAuthMode = AUTH_MODE_WPA_NONE; */
+/* //printk("IW_AUTH_KEY_MGMT_WPA_NONE->AUTH_MODE_WPA_NONE\n"); */
+/* break; */
+/* #endif */
+#if CFG_SUPPORT_802_11W
+               case IW_AUTH_KEY_MGMT_802_1X_SHA256:
+                       eAuthMode = AUTH_MODE_WPA2;
+                       break;
+               case IW_AUTH_KEY_MGMT_PSK_SHA256:
+                       eAuthMode = AUTH_MODE_WPA2_PSK;
+                       break;
+#endif
+               default:
+                       /* printk(KERN_INFO DRV_NAME"strange IW_AUTH_KEY_MGMT : %ld set auto switch\n", */
+                       /* prGlueInfo->rWpaInfo.u4KeyMgmt); */
+                       eAuthMode = AUTH_MODE_AUTO_SWITCH;
+                       break;
+               }
+       }
+
+
+       rStatus = kalIoctl(prGlueInfo,
+                          wlanoidSetAuthMode,
+                          &eAuthMode, sizeof(eAuthMode), FALSE, FALSE, FALSE, FALSE, &u4BufLen);
+
+       /* set encryption status */
+       cipher = prGlueInfo->rWpaInfo.u4CipherGroup | prGlueInfo->rWpaInfo.u4CipherPairwise;
+       if (cipher & IW_AUTH_CIPHER_CCMP) {
+               /* printk("IW_AUTH_CIPHER_CCMP->ENUM_ENCRYPTION3_ENABLED\n"); */
+               eEncStatus = ENUM_ENCRYPTION3_ENABLED;
+       } else if (cipher & IW_AUTH_CIPHER_TKIP) {
+               /* printk("IW_AUTH_CIPHER_TKIP->ENUM_ENCRYPTION2_ENABLED\n"); */
+               eEncStatus = ENUM_ENCRYPTION2_ENABLED;
+       } else if (cipher & (IW_AUTH_CIPHER_WEP104 | IW_AUTH_CIPHER_WEP40)) {
+               /* printk("IW_AUTH_CIPHER_WEPx->ENUM_ENCRYPTION1_ENABLED\n"); */
+               eEncStatus = ENUM_ENCRYPTION1_ENABLED;
+       } else if (cipher & IW_AUTH_CIPHER_NONE) {
+               /* printk("IW_AUTH_CIPHER_NONE->ENUM_ENCRYPTION_DISABLED\n"); */
+               if (prGlueInfo->rWpaInfo.fgPrivacyInvoke)
+                       eEncStatus = ENUM_ENCRYPTION1_ENABLED;
+               else
+                       eEncStatus = ENUM_ENCRYPTION_DISABLED;
+       } else {
+               /* printk("unknown IW_AUTH_CIPHER->Param_EncryptionDisabled\n"); */
+               eEncStatus = ENUM_ENCRYPTION_DISABLED;
+       }
+
+       rStatus = kalIoctl(prGlueInfo,
+                          wlanoidSetEncryptionStatus,
+                          &eEncStatus, sizeof(eEncStatus), FALSE, FALSE, FALSE, FALSE, &u4BufLen);
+
+#if WIRELESS_EXT < 21
+       /* GeorgeKuo: a length error bug exists in (WE < 21) cases, kernel before
+        ** 2.6.19. Cut the trailing '\0'.
+        */
+       rNewSsid.u4SsidLen = (prEssid->length) ? prEssid->length - 1 : 0;
+#else
+       rNewSsid.u4SsidLen = prEssid->length;
+#endif
+       kalMemCopy(rNewSsid.aucSsid, pcExtra, rNewSsid.u4SsidLen);
+
+       /*
+          rNewSsid.aucSsid[rNewSsid.u4SsidLen] = '\0';
+          printk("set ssid(%lu): %s\n", rNewSsid.u4SsidLen, rNewSsid.aucSsid);
+        */
+
+       if (kalIoctl(prGlueInfo,
+                    wlanoidSetSsid,
+                    (PVOID) & rNewSsid,
+                    sizeof(PARAM_SSID_T),
+                    FALSE, FALSE, TRUE, FALSE, &u4BufLen) != WLAN_STATUS_SUCCESS) {
+               /* printk(KERN_WARNING "Fail to set ssid\n"); */
+               return -EFAULT;
+       }
+
+
+       return 0;
+}                              /* wext_set_essid */
+
+/*----------------------------------------------------------------------------*/
+/*!
+* \brief To get current network name ESSID.
+*
+* \param[in] prDev Net device requested.
+* \param[in] prIwrInfo NULL.
+* \param[in] prEssid Pointer to iw_point structure containing essid information.
+* \param[out] pcExtra Pointer to buffer srtoring essid string.
+*
+* \retval 0 If netif_carrier_ok.
+* \retval -ENOTCONN Otherwise.
+*
+* \note If netif_carrier_ok, network essid is stored in pcExtra.
+*/
+/*----------------------------------------------------------------------------*/
+/* static PARAM_SSID_T ssid; */
+static int
+wext_get_essid(IN struct net_device *prNetDev,
+              IN struct iw_request_info *prIwrInfo, IN struct iw_point *prEssid, OUT char *pcExtra)
+{
+       /* PARAM_SSID_T ssid; */
+
+       P_PARAM_SSID_T prSsid;
+       P_GLUE_INFO_T prGlueInfo = NULL;
+       WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS;
+       UINT_32 u4BufLen = 0;
+
+       ASSERT(prNetDev);
+       ASSERT(prEssid);
+       ASSERT(pcExtra);
+
+       if (FALSE == GLUE_CHK_PR3(prNetDev, prEssid, pcExtra)) {
+               return -EINVAL;
+       }
+       prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev));
+
+       /* if (!netif_carrier_ok(prNetDev)) { */
+       /* return -ENOTCONN; */
+       /* } */
+
+       prSsid = kalMemAlloc(sizeof(PARAM_SSID_T), VIR_MEM_TYPE);
+
+       if (!prSsid) {
+               return -ENOMEM;
+       }
+
+       rStatus = kalIoctl(prGlueInfo,
+                          wlanoidQuerySsid,
+                          prSsid, sizeof(PARAM_SSID_T), TRUE, FALSE, FALSE, FALSE, &u4BufLen);
+
+       if ((rStatus == WLAN_STATUS_SUCCESS) && (prSsid->u4SsidLen <= MAX_SSID_LEN)) {
+               kalMemCopy(pcExtra, prSsid->aucSsid, prSsid->u4SsidLen);
+               prEssid->length = prSsid->u4SsidLen;
+               prEssid->flags = 1;
+       }
+
+       kalMemFree(prSsid, VIR_MEM_TYPE, sizeof(PARAM_SSID_T));
+
+       return 0;
+}                              /* wext_get_essid */
+
+
+#if 0
+
+/*----------------------------------------------------------------------------*/
+/*!
+* \brief To set tx desired bit rate. Three cases here
+*        iwconfig wlan0 auto -> Set to origianl supported rate set.
+*        iwconfig wlan0 18M -> Imply "fixed" case, set to 18Mbps as desired rate.
+*        iwconfig wlan0 18M auto -> Set to auto rate lower and equal to 18Mbps
+*
+* \param[in] prNetDev       Pointer to the net_device handler.
+* \param[in] prIwReqInfo    Pointer to the Request Info.
+* \param[in] prRate         Pointer to the Rate Parameter.
+* \param[in] pcExtra        Pointer to the extra buffer.
+*
+* \retval 0         Update desired rate.
+* \retval -EINVAL   Wrong parameter
+*/
+/*----------------------------------------------------------------------------*/
+int
+wext_set_rate(IN struct net_device *prNetDev,
+             IN struct iw_request_info *prIwReqInfo, IN struct iw_param *prRate, IN char *pcExtra)
+{
+       PARAM_RATES_EX aucSuppRate = { 0 };
+       PARAM_RATES_EX aucNewRate = { 0 };
+       UINT_32 u4NewRateLen = 0;
+       UINT_32 i;
+
+       P_GLUE_INFO_T prGlueInfo = NULL;
+       WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS;
+       UINT_32 u4BufLen = 0;
+
+       ASSERT(prNetDev);
+       ASSERT(prRate);
+       if (FALSE == GLUE_CHK_PR2(prNetDev, prRate)) {
+               return -EINVAL;
+       }
+       prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev));
+
+       /*
+          printk("value = %d, fixed = %d, disable = %d, flags = %d\n",
+          prRate->value, prRate->fixed, prRate->disabled, prRate->flags);
+        */
+
+       rStatus = wlanQueryInformation(prGlueInfo->prAdapter,
+                                      wlanoidQuerySupportedRates,
+                                      &aucSuppRate, sizeof(aucSuppRate), &u4BufLen);
+
+       /* Case: AUTO */
+       if (prRate->value < 0) {
+               if (prRate->fixed == 0) {
+                       /* iwconfig wlan0 rate auto */
+
+                       /* set full supported rate to device */
+                       /* printk("wlanoidQuerySupportedRates():u4BufLen = %ld\n", u4BufLen); */
+                       rStatus = wlanSetInformation(prGlueInfo->prAdapter,
+                                                    wlanoidSetDesiredRates,
+                                                    &aucSuppRate, sizeof(aucSuppRate), &u4BufLen);
+                       return 0;
+               } else {
+                       /* iwconfig wlan0 rate fixed */
+
+                       /* fix rate to what? DO NOTHING */
+                       return -EINVAL;
+               }
+       }
+
+
+       aucNewRate[0] = prRate->value / 500000; /* In unit of 500k */
+
+       for (i = 0; i < PARAM_MAX_LEN_RATES_EX; i++) {
+               /* check the given value is supported */
+               if (aucSuppRate[i] == 0) {
+                       break;
+               }
+
+               if (aucNewRate[0] == aucSuppRate[i]) {
+                       u4NewRateLen = 1;
+                       break;
+               }
+       }
+
+       if (u4NewRateLen == 0) {
+               /* the given value is not supported */
+               /* return error or use given rate as upper bound? */
+               return -EINVAL;
+       }
+
+       if (prRate->fixed == 0) {
+               /* add all rates lower than desired rate */
+               for (i = 0; i < PARAM_MAX_LEN_RATES_EX; ++i) {
+                       if (aucSuppRate[i] == 0) {
+                               break;
+                       }
+
+                       if (aucSuppRate[i] < aucNewRate[0]) {
+                               aucNewRate[u4NewRateLen++] = aucSuppRate[i];
+                       }
+               }
+       }
+
+       rStatus = wlanSetInformation(prGlueInfo->prAdapter,
+                                    wlanoidSetDesiredRates,
+                                    &aucNewRate, sizeof(aucNewRate), &u4BufLen);
+       return 0;
+}                              /* wext_set_rate */
+
+#endif
+
+/*----------------------------------------------------------------------------*/
+/*!
+* \brief To get current tx bit rate.
+*
+* \param[in] prDev Net device requested.
+* \param[in] prIwrInfo NULL.
+* \param[out] prRate Pointer to iw_param structure to store current tx rate.
+* \param[in] pcExtra NULL.
+*
+* \retval 0 If netif_carrier_ok.
+* \retval -ENOTCONN Otherwise.
+*
+* \note If netif_carrier_ok, current tx rate is stored in pRate.
+*/
+/*----------------------------------------------------------------------------*/
+static int
+wext_get_rate(IN struct net_device *prNetDev,
+             IN struct iw_request_info *prIwrInfo, OUT struct iw_param *prRate, IN char *pcExtra)
+{
+       P_GLUE_INFO_T prGlueInfo = NULL;
+       WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS;
+       UINT_32 u4BufLen = 0;
+       UINT_32 u4Rate = 0;
+
+       ASSERT(prNetDev);
+       ASSERT(prRate);
+       if (FALSE == GLUE_CHK_PR2(prNetDev, prRate)) {
+               return -EINVAL;
+       }
+       prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev));
+
+       if (!netif_carrier_ok(prNetDev)) {
+               return -ENOTCONN;
+       }
+
+
+       rStatus = kalIoctl(prGlueInfo,
+                          wlanoidQueryLinkSpeed,
+                          &u4Rate, sizeof(u4Rate), TRUE, FALSE, FALSE, FALSE, &u4BufLen);
+
+       if (rStatus != WLAN_STATUS_SUCCESS) {
+               return -EFAULT;
+       }
+
+       prRate->value = u4Rate * 100;   /* u4Rate is in unit of 100bps */
+       prRate->fixed = 0;
+
+       return 0;
+}                              /* wext_get_rate */
+
+
+/*----------------------------------------------------------------------------*/
+/*!
+* \brief To set RTS/CTS theshold.
+*
+* \param[in] prDev Net device requested.
+* \param[in] prIwrInfo NULL.
+* \param[in] prRts Pointer to iw_param structure containing rts threshold.
+* \param[in] pcExtra NULL.
+*
+* \retval 0 For success.
+* \retval -EINVAL Given value is out of range.
+*
+* \note If given value is valid, device will follow the new setting.
+*/
+/*----------------------------------------------------------------------------*/
+static int
+wext_set_rts(IN struct net_device *prNetDev,
+            IN struct iw_request_info *prIwrInfo, IN struct iw_param *prRts, IN char *pcExtra)
+{
+       PARAM_RTS_THRESHOLD u4RtsThresh;
+
+       P_GLUE_INFO_T prGlueInfo = NULL;
+       WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS;
+       UINT_32 u4BufLen = 0;
+
+       ASSERT(prNetDev);
+       ASSERT(prRts);
+       if (FALSE == GLUE_CHK_PR2(prNetDev, prRts)) {
+               return -EINVAL;
+       }
+       prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev));
+
+       if (prRts->disabled == 1) {
+               u4RtsThresh = 2347;
+       } else if (prRts->value < 0 || prRts->value > 2347) {
+               return -EINVAL;
+       } else {
+               u4RtsThresh = (PARAM_RTS_THRESHOLD) prRts->value;
+       }
+
+       rStatus = kalIoctl(prGlueInfo,
+                          wlanoidSetRtsThreshold,
+                          &u4RtsThresh,
+                          sizeof(u4RtsThresh), FALSE, FALSE, FALSE, FALSE, &u4BufLen);
+
+
+
+       prRts->value = (typeof(prRts->value)) u4RtsThresh;
+       prRts->disabled = (prRts->value > 2347) ? 1 : 0;
+       prRts->fixed = 1;
+
+       return 0;
+}                              /* wext_set_rts */
+
+/*----------------------------------------------------------------------------*/
+/*!
+* \brief To get RTS/CTS theshold.
+*
+* \param[in] prDev Net device requested.
+* \param[in] prIwrInfo NULL.
+* \param[out] prRts Pointer to iw_param structure containing rts threshold.
+* \param[in] pcExtra NULL.
+*
+* \retval 0 Success.
+*
+* \note RTS threshold is stored in pRts.
+*/
+/*----------------------------------------------------------------------------*/
+static int
+wext_get_rts(IN struct net_device *prNetDev,
+            IN struct iw_request_info *prIwrInfo, OUT struct iw_param *prRts, IN char *pcExtra)
+{
+       PARAM_RTS_THRESHOLD u4RtsThresh;
+
+       P_GLUE_INFO_T prGlueInfo = NULL;
+       WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS;
+       UINT_32 u4BufLen = 0;
+
+       ASSERT(prNetDev);
+       ASSERT(prRts);
+       if (FALSE == GLUE_CHK_PR2(prNetDev, prRts)) {
+               return -EINVAL;
+       }
+       prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev));
+
+       rStatus = kalIoctl(prGlueInfo,
+                          wlanoidQueryRtsThreshold,
+                          &u4RtsThresh, sizeof(u4RtsThresh), TRUE, FALSE, FALSE, FALSE, &u4BufLen);
+
+
+
+       prRts->value = (typeof(prRts->value)) u4RtsThresh;
+       prRts->disabled = (prRts->value > 2347 || prRts->value < 0) ? 1 : 0;
+       prRts->fixed = 1;
+
+       return 0;
+}                              /* wext_get_rts */
+
+/*----------------------------------------------------------------------------*/
+/*!
+* \brief To get fragmentation threshold.
+*
+* \param[in] prDev Net device requested.
+* \param[in] prIwrInfo NULL.
+* \param[out] prFrag Pointer to iw_param structure containing frag threshold.
+* \param[in] pcExtra NULL.
+*
+* \retval 0 Success.
+*
+* \note RTS threshold is stored in pFrag. Fragmentation is disabled.
+*/
+/*----------------------------------------------------------------------------*/
+static int
+wext_get_frag(IN struct net_device *prNetDev,
+             IN struct iw_request_info *prIwrInfo, OUT struct iw_param *prFrag, IN char *pcExtra)
+{
+       ASSERT(prFrag);
+
+       prFrag->value = 2346;
+       prFrag->fixed = 1;
+       prFrag->disabled = 1;
+       return 0;
+}                              /* wext_get_frag */
+
+#if 1
+/*----------------------------------------------------------------------------*/
+/*!
+* \brief To set TX power, or enable/disable the radio.
+*
+* \param[in] prDev Net device requested.
+* \param[in] prIwrInfo NULL.
+* \param[in] prTxPow Pointer to iw_param structure containing tx power setting.
+* \param[in] pcExtra NULL.
+*
+* \retval 0 Success.
+*
+* \note Tx power is stored in pTxPow. iwconfig wlan0 txpow on/off are used
+*       to enable/disable the radio.
+*/
+/*----------------------------------------------------------------------------*/
+
+static int
+wext_set_txpow(IN struct net_device *prNetDev,
+              IN struct iw_request_info *prIwrInfo, IN struct iw_param *prTxPow, IN char *pcExtra)
+{
+       int ret = 0;
+       /* PARAM_DEVICE_POWER_STATE ePowerState; */
+       ENUM_ACPI_STATE_T ePowerState;
+
+       P_GLUE_INFO_T prGlueInfo = NULL;
+       WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS;
+       UINT_32 u4BufLen = 0;
+
+       ASSERT(prNetDev);
+       ASSERT(prTxPow);
+       if (FALSE == GLUE_CHK_PR2(prNetDev, prTxPow)) {
+               return -EINVAL;
+       }
+       prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev));
+
+       if (prTxPow->disabled) {
+               /* <1> disconnect */
+               rStatus = kalIoctl(prGlueInfo,
+                                  wlanoidSetDisassociate,
+                                  NULL, 0, FALSE, FALSE, TRUE, FALSE, &u4BufLen);
+               if (rStatus != WLAN_STATUS_SUCCESS) {
+                       DBGLOG(INIT, INFO, ("######set disassoc failed\n"));
+               } else {
+                       DBGLOG(INIT, INFO, ("######set assoc ok\n"));
+               }
+
+               /* <2> mark to power state flag */
+               ePowerState = ACPI_STATE_D0;
+               DBGLOG(INIT, INFO, ("set to acpi d3(0)\n"));
+               wlanSetAcpiState(prGlueInfo->prAdapter, ePowerState);
+
+       } else {
+               ePowerState = ACPI_STATE_D0;
+               DBGLOG(INIT, INFO, ("set to acpi d0\n"));
+               wlanSetAcpiState(prGlueInfo->prAdapter, ePowerState);
+       }
+
+       prGlueInfo->ePowerState = ePowerState;
+
+       return ret;
+}                              /* wext_set_txpow */
+
+
+#endif
+
+/*----------------------------------------------------------------------------*/
+/*!
+* \brief To get TX power.
+*
+* \param[in] prDev Net device requested.
+* \param[in] prIwrInfo NULL.
+* \param[out] prTxPow Pointer to iw_param structure containing tx power setting.
+* \param[in] pcExtra NULL.
+*
+* \retval 0 Success.
+*
+* \note Tx power is stored in pTxPow.
+*/
+/*----------------------------------------------------------------------------*/
+static int
+wext_get_txpow(IN struct net_device *prNetDev,
+              IN struct iw_request_info *prIwrInfo, OUT struct iw_param *prTxPow, IN char *pcExtra)
+{
+       /* PARAM_DEVICE_POWER_STATE ePowerState; */
+
+       P_GLUE_INFO_T prGlueInfo = NULL;
+
+       ASSERT(prNetDev);
+       ASSERT(prTxPow);
+       if (FALSE == GLUE_CHK_PR2(prNetDev, prTxPow)) {
+               return -EINVAL;
+       }
+       prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev));
+
+       /* GeorgeKuo: wlanoidQueryAcpiDevicePowerState() reports capability, not
+        * current state. Use GLUE_INFO_T to store state.
+        */
+       /* ePowerState = prGlueInfo->ePowerState; */
+
+       /* TxPow parameters: Fixed at relative 100% */
+#if WIRELESS_EXT < 17
+       prTxPow->flags = 0x0002;        /* IW_TXPOW_RELATIVE */
+#else
+       prTxPow->flags = IW_TXPOW_RELATIVE;
+#endif
+       prTxPow->value = 100;
+       prTxPow->fixed = 1;
+       /* prTxPow->disabled = (ePowerState != ParamDeviceStateD3) ? FALSE : TRUE; */
+       prTxPow->disabled = TRUE;
+
+       return 0;
+}                              /* wext_get_txpow */
+
+
+/*----------------------------------------------------------------------------*/
+/*!
+* \brief To get encryption cipher and key.
+*
+* \param[in] prDev Net device requested.
+* \param[in] prIwrInfo NULL.
+* \param[out] prEnc Pointer to iw_point structure containing securiry information.
+* \param[in] pcExtra Buffer to store key content.
+*
+* \retval 0 Success.
+*
+* \note Securiry information is stored in pEnc except key content.
+*/
+/*----------------------------------------------------------------------------*/
+static int
+wext_get_encode(IN struct net_device *prNetDev,
+               IN struct iw_request_info *prIwrInfo, OUT struct iw_point *prEnc, IN char *pcExtra)
+{
+#if 1
+       /* ENUM_ENCRYPTION_STATUS_T eEncMode; */
+       ENUM_PARAM_ENCRYPTION_STATUS_T eEncMode;
+
+       P_GLUE_INFO_T prGlueInfo = NULL;
+       WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS;
+       UINT_32 u4BufLen = 0;
+
+       ASSERT(prNetDev);
+       ASSERT(prEnc);
+       if (FALSE == GLUE_CHK_PR2(prNetDev, prEnc)) {
+               return -EINVAL;
+       }
+       prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev));
+
+
+       rStatus = kalIoctl(prGlueInfo,
+                          wlanoidQueryEncryptionStatus,
+                          &eEncMode, sizeof(eEncMode), TRUE, FALSE, FALSE, FALSE, &u4BufLen);
+
+
+
+       switch (eEncMode) {
+       case ENUM_WEP_DISABLED:
+               prEnc->flags = IW_ENCODE_DISABLED;
+               break;
+       case ENUM_WEP_ENABLED:
+               prEnc->flags = IW_ENCODE_ENABLED;
+               break;
+       case ENUM_WEP_KEY_ABSENT:
+               prEnc->flags = IW_ENCODE_ENABLED | IW_ENCODE_NOKEY;
+               break;
+       default:
+               prEnc->flags = IW_ENCODE_ENABLED;
+               break;
+       }
+
+       /* Cipher, Key Content, Key ID can't be queried */
+       prEnc->flags |= IW_ENCODE_NOKEY;
+#endif
+       return 0;
+}                              /* wext_get_encode */
+
+
+
+/*----------------------------------------------------------------------------*/
+/*!
+* \brief To set encryption cipher and key.
+*
+* \param[in] prDev Net device requested.
+* \param[in] prIwrInfo NULL.
+* \param[in] prEnc Pointer to iw_point structure containing securiry information.
+* \param[in] pcExtra Pointer to key string buffer.
+*
+* \retval 0 Success.
+* \retval -EINVAL Key ID error for WEP.
+* \retval -EFAULT Setting parameters to driver fail.
+* \retval -EOPNOTSUPP Key size not supported.
+*
+* \note Securiry information is stored in pEnc.
+*/
+/*----------------------------------------------------------------------------*/
+static UINT_8 wepBuf[48];
+
+static int
+wext_set_encode(IN struct net_device *prNetDev,
+               IN struct iw_request_info *prIwrInfo, IN struct iw_point *prEnc, IN char *pcExtra)
+{
+#if 1
+       ENUM_PARAM_ENCRYPTION_STATUS_T eEncStatus;
+       ENUM_PARAM_AUTH_MODE_T eAuthMode;
+       /* UINT_8 wepBuf[48]; */
+       P_PARAM_WEP_T prWepKey = (P_PARAM_WEP_T) wepBuf;
+
+       P_GLUE_INFO_T prGlueInfo = NULL;
+       WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS;
+       UINT_32 u4BufLen = 0;
+
+       ASSERT(prNetDev);
+       ASSERT(prEnc);
+       ASSERT(pcExtra);
+       if (FALSE == GLUE_CHK_PR3(prNetDev, prEnc, pcExtra)) {
+               return -EINVAL;
+       }
+       prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev));
+
+       /* reset to default mode */
+       prGlueInfo->rWpaInfo.u4WpaVersion = IW_AUTH_WPA_VERSION_DISABLED;
+       prGlueInfo->rWpaInfo.u4KeyMgmt = 0;
+       prGlueInfo->rWpaInfo.u4CipherPairwise = IW_AUTH_CIPHER_NONE;
+       prGlueInfo->rWpaInfo.u4CipherGroup = IW_AUTH_CIPHER_NONE;
+       prGlueInfo->rWpaInfo.u4AuthAlg = IW_AUTH_ALG_OPEN_SYSTEM;
+#if CFG_SUPPORT_802_11W
+       prGlueInfo->rWpaInfo.u4Mfp = IW_AUTH_MFP_DISABLED;
+#endif
+
+       /* iwconfig wlan0 key off */
+       if ((prEnc->flags & IW_ENCODE_MODE) == IW_ENCODE_DISABLED) {
+               eAuthMode = AUTH_MODE_OPEN;
+
+               rStatus = kalIoctl(prGlueInfo,
+                                  wlanoidSetAuthMode,
+                                  &eAuthMode,
+                                  sizeof(eAuthMode), FALSE, FALSE, FALSE, FALSE, &u4BufLen);
+
+               eEncStatus = ENUM_ENCRYPTION_DISABLED;
+
+               rStatus = kalIoctl(prGlueInfo,
+                                  wlanoidSetEncryptionStatus,
+                                  &eEncStatus,
+                                  sizeof(eEncStatus), FALSE, FALSE, FALSE, FALSE, &u4BufLen);
+
+               return 0;
+       }
+
+       /* iwconfig wlan0 key 0123456789 */
+       /* iwconfig wlan0 key s:abcde */
+       /* iwconfig wlan0 key 0123456789 [1] */
+       /* iwconfig wlan0 key 01234567890123456789012345 [1] */
+       /* check key size for WEP */
+       if (prEnc->length == 5 || prEnc->length == 13 || prEnc->length == 16) {
+               /* prepare PARAM_WEP key structure */
+               prWepKey->u4KeyIndex = (prEnc->flags & IW_ENCODE_INDEX) ?
+                   (prEnc->flags & IW_ENCODE_INDEX) - 1 : 0;
+               if (prWepKey->u4KeyIndex > 3) {
+                       /* key id is out of range */
+                       return -EINVAL;
+               }
+               prWepKey->u4KeyIndex |= 0x80000000;
+               prWepKey->u4Length = 12 + prEnc->length;
+               prWepKey->u4KeyLength = prEnc->length;
+               kalMemCopy(prWepKey->aucKeyMaterial, pcExtra, prEnc->length);
+
+
+               rStatus = kalIoctl(prGlueInfo,
+                                  wlanoidSetAddWep,
+                                  prWepKey,
+                                  prWepKey->u4Length, FALSE, FALSE, TRUE, FALSE, &u4BufLen);
+
+               if (rStatus != WLAN_STATUS_SUCCESS) {
+                       DBGLOG(INIT, INFO, ("wlanoidSetAddWep fail 0x%lx\n", rStatus));
+                       return -EFAULT;
+               }
+
+               /* change to auto switch */
+               prGlueInfo->rWpaInfo.u4AuthAlg = IW_AUTH_ALG_SHARED_KEY | IW_AUTH_ALG_OPEN_SYSTEM;
+               eAuthMode = AUTH_MODE_AUTO_SWITCH;
+
+               rStatus = kalIoctl(prGlueInfo,
+                                  wlanoidSetAuthMode,
+                                  &eAuthMode,
+                                  sizeof(eAuthMode), FALSE, FALSE, FALSE, FALSE, &u4BufLen);
+
+               if (rStatus != WLAN_STATUS_SUCCESS) {
+                       /* printk(KERN_INFO DRV_NAME"wlanoidSetAuthMode fail 0x%lx\n", rStatus); */
+                       return -EFAULT;
+               }
+
+               prGlueInfo->rWpaInfo.u4CipherPairwise =
+                   IW_AUTH_CIPHER_WEP104 | IW_AUTH_CIPHER_WEP40;
+               prGlueInfo->rWpaInfo.u4CipherGroup = IW_AUTH_CIPHER_WEP104 | IW_AUTH_CIPHER_WEP40;
+
+               eEncStatus = ENUM_WEP_ENABLED;
+
+
+               rStatus = kalIoctl(prGlueInfo,
+                                  wlanoidSetEncryptionStatus,
+                                  &eEncStatus,
+                                  sizeof(ENUM_PARAM_ENCRYPTION_STATUS_T),
+                                  FALSE, FALSE, FALSE, FALSE, &u4BufLen);
+
+               if (rStatus != WLAN_STATUS_SUCCESS) {
+                       /* printk(KERN_INFO DRV_NAME"wlanoidSetEncryptionStatus fail 0x%lx\n", rStatus); */
+                       return -EFAULT;
+               }
+
+               return 0;
+       }
+#endif
+       return -EOPNOTSUPP;
+}                              /* wext_set_encode */
+
+
+/*----------------------------------------------------------------------------*/
+/*!
+* \brief To set power management.
+*
+* \param[in] prDev Net device requested.
+* \param[in] prIwrInfo NULL.
+* \param[in] prPower Pointer to iw_param structure containing tx power setting.
+* \param[in] pcExtra NULL.
+*
+* \retval 0 Success.
+*
+* \note New Power Management Mode is set to driver.
+*/
+/*----------------------------------------------------------------------------*/
+static int
+wext_set_power(IN struct net_device *prNetDev,
+              IN struct iw_request_info *prIwrInfo, IN struct iw_param *prPower, IN char *pcExtra)
+{
+#if 1
+       PARAM_POWER_MODE ePowerMode;
+       INT_32 i4PowerValue;
+
+       P_GLUE_INFO_T prGlueInfo = NULL;
+       WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS;
+       UINT_32 u4BufLen = 0;
+
+       ASSERT(prNetDev);
+       ASSERT(prPower);
+       if (FALSE == GLUE_CHK_PR2(prNetDev, prPower)) {
+               return -EINVAL;
+       }
+       prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev));
+
+       /* printk(KERN_INFO "wext_set_power value(%d) disabled(%d) flag(0x%x)\n", */
+       /* prPower->value, prPower->disabled, prPower->flags); */
+
+       if (prPower->disabled) {
+               ePowerMode = Param_PowerModeCAM;
+       } else {
+               i4PowerValue = prPower->value;
+#if WIRELESS_EXT < 21
+               i4PowerValue /= 1000000;
+#endif
+               if (i4PowerValue == 0) {
+                       ePowerMode = Param_PowerModeCAM;
+               } else if (i4PowerValue == 1) {
+                       ePowerMode = Param_PowerModeMAX_PSP;
+               } else if (i4PowerValue == 2) {
+                       ePowerMode = Param_PowerModeFast_PSP;
+               } else {
+                       DBGLOG(INIT, INFO, ("%s(): unsupported power management mode value = %d.\n",
+                                           __func__, prPower->value));
+
+                       return -EINVAL;
+               }
+       }
+
+
+       rStatus = kalIoctl(prGlueInfo,
+                          wlanoidSet802dot11PowerSaveProfile,
+                          &ePowerMode, sizeof(ePowerMode), FALSE, FALSE, TRUE, FALSE, &u4BufLen);
+
+       if (rStatus != WLAN_STATUS_SUCCESS) {
+               /* printk(KERN_INFO DRV_NAME"wlanoidSet802dot11PowerSaveProfile fail 0x%lx\n", rStatus); */
+               return -EFAULT;
+       }
+#endif
+       return 0;
+}                              /* wext_set_power */
+
+
+/*----------------------------------------------------------------------------*/
+/*!
+* \brief To get power management.
+*
+* \param[in] prDev Net device requested.
+* \param[in] prIwrInfo NULL.
+* \param[out] prPower Pointer to iw_param structure containing tx power setting.
+* \param[in] pcExtra NULL.
+*
+* \retval 0 Success.
+*
+* \note Power management mode is stored in pTxPow->value.
+*/
+/*----------------------------------------------------------------------------*/
+static int
+wext_get_power(IN struct net_device *prNetDev,
+              IN struct iw_request_info *prIwrInfo, OUT struct iw_param *prPower, IN char *pcExtra)
+{
+
+       P_GLUE_INFO_T prGlueInfo = NULL;
+       WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS;
+       UINT_32 u4BufLen = 0;
+       PARAM_POWER_MODE ePowerMode = Param_PowerModeCAM;
+
+       ASSERT(prNetDev);
+       ASSERT(prPower);
+       if (FALSE == GLUE_CHK_PR2(prNetDev, prPower)) {
+               return -EINVAL;
+       }
+       prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev));
+
+#if 0
+#if defined(_HIF_SDIO)
+       rStatus = sdio_io_ctrl(prGlueInfo,
+                              wlanoidQuery802dot11PowerSaveProfile,
+                              &ePowerMode, sizeof(ePowerMode), TRUE, TRUE, &u4BufLen);
+#else
+       rStatus = wlanQueryInformation(prGlueInfo->prAdapter,
+                                      wlanoidQuery802dot11PowerSaveProfile,
+                                      &ePowerMode, sizeof(ePowerMode), &u4BufLen);
+#endif
+#else
+       rStatus = wlanQueryInformation(prGlueInfo->prAdapter,
+                                      wlanoidQuery802dot11PowerSaveProfile,
+                                      &ePowerMode, sizeof(ePowerMode), &u4BufLen);
+#endif
+
+       if (rStatus != WLAN_STATUS_SUCCESS) {
+               return -EFAULT;
+       }
+
+       prPower->value = 0;
+       prPower->disabled = 1;
+
+       if (Param_PowerModeCAM == ePowerMode) {
+               prPower->value = 0;
+               prPower->disabled = 1;
+       } else if (Param_PowerModeMAX_PSP == ePowerMode) {
+               prPower->value = 1;
+               prPower->disabled = 0;
+       } else if (Param_PowerModeFast_PSP == ePowerMode) {
+               prPower->value = 2;
+               prPower->disabled = 0;
+       }
+
+       prPower->flags = IW_POWER_PERIOD | IW_POWER_RELATIVE;
+#if WIRELESS_EXT < 21
+       prPower->value *= 1000000;
+#endif
+
+       /* printk(KERN_INFO "wext_get_power value(%d) disabled(%d) flag(0x%x)\n", */
+       /* prPower->value, prPower->disabled, prPower->flags); */
+
+       return 0;
+}                              /* wext_get_power */
+
+/*----------------------------------------------------------------------------*/
+/*!
+* \brief To set authentication parameters.
+*
+* \param[in] prDev Net device requested.
+* \param[in] prIwrInfo NULL.
+* \param[in] rpAuth Pointer to iw_param structure containing authentication information.
+* \param[in] pcExtra Pointer to key string buffer.
+*
+* \retval 0 Success.
+* \retval -EINVAL Key ID error for WEP.
+* \retval -EFAULT Setting parameters to driver fail.
+* \retval -EOPNOTSUPP Key size not supported.
+*
+* \note Securiry information is stored in pEnc.
+*/
+/*----------------------------------------------------------------------------*/
+static int
+wext_set_auth(IN struct net_device *prNetDev,
+             IN struct iw_request_info *prIwrInfo, IN struct iw_param *prAuth, IN char *pcExtra)
+{
+       P_GLUE_INFO_T prGlueInfo = NULL;
+
+       ASSERT(prNetDev);
+       ASSERT(prAuth);
+       if (FALSE == GLUE_CHK_PR2(prNetDev, prAuth)) {
+               return -EINVAL;
+       }
+       prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev));
+
+       /* Save information to glue info and process later when ssid is set. */
+       switch (prAuth->flags & IW_AUTH_INDEX) {
+       case IW_AUTH_WPA_VERSION:
+#if CFG_SUPPORT_WAPI
+               if (wlanQueryWapiMode(prGlueInfo->prAdapter)) {
+                       prGlueInfo->rWpaInfo.u4WpaVersion = IW_AUTH_WPA_VERSION_DISABLED;
+                       prGlueInfo->rWpaInfo.u4AuthAlg = IW_AUTH_ALG_OPEN_SYSTEM;
+               } else {
+                       prGlueInfo->rWpaInfo.u4WpaVersion = prAuth->value;
+               }
+#else
+               prGlueInfo->rWpaInfo.u4WpaVersion = prAuth->value;
+#endif
+               break;
+
+       case IW_AUTH_CIPHER_PAIRWISE:
+               prGlueInfo->rWpaInfo.u4CipherPairwise = prAuth->value;
+               break;
+
+       case IW_AUTH_CIPHER_GROUP:
+               prGlueInfo->rWpaInfo.u4CipherGroup = prAuth->value;
+               break;
+
+       case IW_AUTH_KEY_MGMT:
+               prGlueInfo->rWpaInfo.u4KeyMgmt = prAuth->value;
+#if CFG_SUPPORT_WAPI
+               if (prGlueInfo->rWpaInfo.u4KeyMgmt == IW_AUTH_KEY_MGMT_WAPI_PSK ||
+                   prGlueInfo->rWpaInfo.u4KeyMgmt == IW_AUTH_KEY_MGMT_WAPI_CERT) {
+                       UINT_32 u4BufLen;
+                       WLAN_STATUS rStatus;
+
+                       rStatus = kalIoctl(prGlueInfo,
+                                          wlanoidSetWapiMode,
+                                          &prAuth->value,
+                                          sizeof(UINT_32), FALSE, FALSE, TRUE, FALSE, &u4BufLen);
+                       DBGLOG(INIT, INFO, ("IW_AUTH_WAPI_ENABLED :%d\n", prAuth->value));
+               }
+#endif
+               if (prGlueInfo->rWpaInfo.u4KeyMgmt == IW_AUTH_KEY_MGMT_WPS)
+                       prGlueInfo->fgWpsActive = TRUE;
+               else
+                       prGlueInfo->fgWpsActive = FALSE;
+               break;
+
+       case IW_AUTH_80211_AUTH_ALG:
+               prGlueInfo->rWpaInfo.u4AuthAlg = prAuth->value;
+               break;
+
+       case IW_AUTH_PRIVACY_INVOKED:
+               prGlueInfo->rWpaInfo.fgPrivacyInvoke = prAuth->value;
+               break;
+#if CFG_SUPPORT_802_11W
+       case IW_AUTH_MFP:
+               /* printk("wext_set_auth IW_AUTH_MFP=%d\n", prAuth->value); */
+               prGlueInfo->rWpaInfo.u4Mfp = prAuth->value;
+               break;
+#endif
+#if CFG_SUPPORT_WAPI
+       case IW_AUTH_WAPI_ENABLED:
+               {
+                       UINT_32 u4BufLen;
+                       WLAN_STATUS rStatus;
+
+                       rStatus = kalIoctl(prGlueInfo,
+                                          wlanoidSetWapiMode,
+                                          &prAuth->value,
+                                          sizeof(UINT_32), FALSE, FALSE, TRUE, FALSE, &u4BufLen);
+               }
+               DBGLOG(INIT, INFO, ("IW_AUTH_WAPI_ENABLED :%d\n", prAuth->value));
+               break;
+#endif
+       default:
+               /*
+                  printk(KERN_INFO "[wifi] unsupported IW_AUTH_INDEX :%d\n", prAuth->flags);
+                */
+               break;
+       }
+       return 0;
+}                              /* wext_set_auth */
+
+
+/*----------------------------------------------------------------------------*/
+/*!
+* \brief To set encryption cipher and key.
+*
+* \param[in] prDev Net device requested.
+* \param[in] prIwrInfo NULL.
+* \param[in] prEnc Pointer to iw_point structure containing securiry information.
+* \param[in] pcExtra Pointer to key string buffer.
+*
+* \retval 0 Success.
+* \retval -EINVAL Key ID error for WEP.
+* \retval -EFAULT Setting parameters to driver fail.
+* \retval -EOPNOTSUPP Key size not supported.
+*
+* \note Securiry information is stored in pEnc.
+*/
+/*----------------------------------------------------------------------------*/
+#if CFG_SUPPORT_WAPI
+UINT_8 keyStructBuf[1024];     /* add/remove key shared buffer */
+#else
+UINT_8 keyStructBuf[100];      /* add/remove key shared buffer */
+#endif
+
+static int
+wext_set_encode_ext(IN struct net_device *prNetDev,
+                   IN struct iw_request_info *prIwrInfo,
+                   IN struct iw_point *prEnc, IN char *pcExtra)
+{
+       P_PARAM_REMOVE_KEY_T prRemoveKey = (P_PARAM_REMOVE_KEY_T) keyStructBuf;
+       P_PARAM_KEY_T prKey = (P_PARAM_KEY_T) keyStructBuf;
+
+
+       P_PARAM_WEP_T prWepKey = (P_PARAM_WEP_T) wepBuf;
+
+       struct iw_encode_ext *prIWEncExt = (struct iw_encode_ext *)pcExtra;
+
+       ENUM_PARAM_ENCRYPTION_STATUS_T eEncStatus;
+       ENUM_PARAM_AUTH_MODE_T eAuthMode;
+       /* ENUM_PARAM_OP_MODE_T eOpMode = NET_TYPE_AUTO_SWITCH; */
+
+#if CFG_SUPPORT_WAPI
+       P_PARAM_WPI_KEY_T prWpiKey = (P_PARAM_WPI_KEY_T) keyStructBuf;
+#endif
+
+       P_GLUE_INFO_T prGlueInfo = NULL;
+       WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS;
+       UINT_32 u4BufLen = 0;
+
+       ASSERT(prNetDev);
+       ASSERT(prEnc);
+       if (FALSE == GLUE_CHK_PR3(prNetDev, prEnc, pcExtra)) {
+               return -EINVAL;
+       }
+       prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev));
+
+       memset(keyStructBuf, 0, sizeof(keyStructBuf));
+
+#if CFG_SUPPORT_WAPI
+       if (prIWEncExt->alg == IW_ENCODE_ALG_SMS4) {
+               if (prEnc->flags & IW_ENCODE_DISABLED) {
+                       /* printk(KERN_INFO "[wapi] IW_ENCODE_DISABLED\n"); */
+                       return 0;
+               }
+               /* KeyID */
+               prWpiKey->ucKeyID = (prEnc->flags & IW_ENCODE_INDEX);
+               prWpiKey->ucKeyID--;
+               if (prWpiKey->ucKeyID > 1) {
+                       /* key id is out of range */
+                       /* printk(KERN_INFO "[wapi] add key error: key_id invalid %d\n", prWpiKey->ucKeyID); */
+                       return -EINVAL;
+               }
+
+               if (prIWEncExt->key_len != 32) {
+                       /* key length not valid */
+                       /* printk(KERN_INFO "[wapi] add key error: key_len invalid %d\n", prIWEncExt->key_len); */
+                       return -EINVAL;
+               }
+               /* printk(KERN_INFO "[wapi] %d ext_flags %d\n", prEnc->flags, prIWEncExt->ext_flags); */
+
+               if (prIWEncExt->ext_flags & IW_ENCODE_EXT_GROUP_KEY) {
+                       prWpiKey->eKeyType = ENUM_WPI_GROUP_KEY;
+                       prWpiKey->eDirection = ENUM_WPI_RX;
+               } else if (prIWEncExt->ext_flags & IW_ENCODE_EXT_SET_TX_KEY) {
+                       prWpiKey->eKeyType = ENUM_WPI_PAIRWISE_KEY;
+                       prWpiKey->eDirection = ENUM_WPI_RX_TX;
+               }
+
+               /* PN */
+               memcpy(prWpiKey->aucPN, prIWEncExt->tx_seq, IW_ENCODE_SEQ_MAX_SIZE);
+               memcpy(prWpiKey->aucPN + IW_ENCODE_SEQ_MAX_SIZE, prIWEncExt->rx_seq,
+                      IW_ENCODE_SEQ_MAX_SIZE);
+
+               /* BSSID */
+               memcpy(prWpiKey->aucAddrIndex, prIWEncExt->addr.sa_data, 6);
+
+               memcpy(prWpiKey->aucWPIEK, prIWEncExt->key, 16);
+               prWpiKey->u4LenWPIEK = 16;
+
+               memcpy(prWpiKey->aucWPICK, &prIWEncExt->key[16], 16);
+               prWpiKey->u4LenWPICK = 16;
+
+               rStatus = kalIoctl(prGlueInfo,
+                                  wlanoidSetWapiKey,
+                                  prWpiKey,
+                                  sizeof(PARAM_WPI_KEY_T), FALSE, FALSE, TRUE, FALSE, &u4BufLen);
+
+               if (rStatus != WLAN_STATUS_SUCCESS) {
+                       /* printk(KERN_INFO "[wapi] add key error:%lx\n", rStatus); */
+               }
+
+       } else
+#endif
+       {
+
+               if ((prEnc->flags & IW_ENCODE_MODE) == IW_ENCODE_DISABLED) {
+                       prRemoveKey->u4Length = sizeof(*prRemoveKey);
+                       memcpy(prRemoveKey->arBSSID, prIWEncExt->addr.sa_data, 6);
+                       /*
+                          printk("IW_ENCODE_DISABLED: ID:%d, Addr:[" MACSTR "]\n",
+                          prRemoveKey->KeyIndex, MAC2STR(prRemoveKey->BSSID));
+                        */
+
+                       rStatus = kalIoctl(prGlueInfo,
+                                          wlanoidSetRemoveKey,
+                                          prRemoveKey,
+                                          prRemoveKey->u4Length,
+                                          FALSE, FALSE, TRUE, FALSE, &u4BufLen);
+
+
+                       if (rStatus != WLAN_STATUS_SUCCESS) {
+                               DBGLOG(INIT, INFO, ("remove key error:%lx\n", rStatus));
+                       }
+                       return 0;
+               }
+               /* return 0; */
+               /* printk ("alg %x\n", prIWEncExt->alg); */
+
+               switch (prIWEncExt->alg) {
+               case IW_ENCODE_ALG_NONE:
+                       break;
+               case IW_ENCODE_ALG_WEP:
+                       /* iwconfig wlan0 key 0123456789 */
+                       /* iwconfig wlan0 key s:abcde */
+                       /* iwconfig wlan0 key 0123456789 [1] */
+                       /* iwconfig wlan0 key 01234567890123456789012345 [1] */
+                       /* check key size for WEP */
+                       if (prIWEncExt->key_len == 5 || prIWEncExt->key_len == 13
+                           || prIWEncExt->key_len == 16) {
+                               /* prepare PARAM_WEP key structure */
+                               prWepKey->u4KeyIndex = (prEnc->flags & IW_ENCODE_INDEX) ?
+                                   (prEnc->flags & IW_ENCODE_INDEX) - 1 : 0;
+                               if (prWepKey->u4KeyIndex > 3) {
+                                       /* key id is out of range */
+                                       return -EINVAL;
+                               }
+                               prWepKey->u4KeyIndex |= 0x80000000;
+                               prWepKey->u4Length = 12 + prIWEncExt->key_len;
+                               prWepKey->u4KeyLength = prIWEncExt->key_len;
+                               /* kalMemCopy(prWepKey->aucKeyMaterial, pcExtra, prIWEncExt->key_len); */
+                               kalMemCopy(prWepKey->aucKeyMaterial, prIWEncExt->key,
+                                          prIWEncExt->key_len);
+
+
+                               rStatus = kalIoctl(prGlueInfo,
+                                                  wlanoidSetAddWep,
+                                                  prWepKey,
+                                                  prWepKey->u4Length,
+                                                  FALSE, FALSE, TRUE, FALSE, &u4BufLen);
+
+                               if (rStatus != WLAN_STATUS_SUCCESS) {
+                                       DBGLOG(INIT, INFO,
+                                              ("wlanoidSetAddWep fail 0x%lx\n", rStatus));
+                                       return -EFAULT;
+                               }
+
+                               /* change to auto switch */
+                               prGlueInfo->rWpaInfo.u4AuthAlg = IW_AUTH_ALG_SHARED_KEY |
+                                   IW_AUTH_ALG_OPEN_SYSTEM;
+                               eAuthMode = AUTH_MODE_AUTO_SWITCH;
+
+                               rStatus = kalIoctl(prGlueInfo,
+                                                  wlanoidSetAuthMode,
+                                                  &eAuthMode,
+                                                  sizeof(eAuthMode),
+                                                  FALSE, FALSE, FALSE, FALSE, &u4BufLen);
+
+                               if (rStatus != WLAN_STATUS_SUCCESS) {
+                                       DBGLOG(INIT, INFO,
+                                              ("wlanoidSetAuthMode fail 0x%lx\n", rStatus));
+                                       return -EFAULT;
+                               }
+
+                               prGlueInfo->rWpaInfo.u4CipherPairwise =
+                                   IW_AUTH_CIPHER_WEP104 | IW_AUTH_CIPHER_WEP40;
+                               prGlueInfo->rWpaInfo.u4CipherGroup =
+                                   IW_AUTH_CIPHER_WEP104 | IW_AUTH_CIPHER_WEP40;
+
+                               eEncStatus = ENUM_WEP_ENABLED;
+
+
+                               rStatus = kalIoctl(prGlueInfo,
+                                                  wlanoidSetEncryptionStatus,
+                                                  &eEncStatus,
+                                                  sizeof(ENUM_PARAM_ENCRYPTION_STATUS_T),
+                                                  FALSE, FALSE, FALSE, FALSE, &u4BufLen);
+
+                               if (rStatus != WLAN_STATUS_SUCCESS) {
+                                       DBGLOG(INIT, INFO,
+                                              ("wlanoidSetEncryptionStatus fail 0x%lx\n",
+                                               rStatus));
+                                       return -EFAULT;
+                               }
+
+                       } else {
+                               DBGLOG(INIT, INFO, ("key length %x\n", prIWEncExt->key_len));
+                               DBGLOG(INIT, INFO, ("key error\n"));
+                       }
+
+                       break;
+               case IW_ENCODE_ALG_TKIP:
+               case IW_ENCODE_ALG_CCMP:
+#if CFG_SUPPORT_802_11W
+               case IW_ENCODE_ALG_AES_CMAC:
+#endif
+                       {
+
+                               /* KeyID */
+                               prKey->u4KeyIndex = (prEnc->flags & IW_ENCODE_INDEX) ?
+                                   (prEnc->flags & IW_ENCODE_INDEX) - 1 : 0;
+#if CFG_SUPPORT_802_11W
+                               if (prKey->u4KeyIndex > 5)
+#else
+                               if (prKey->u4KeyIndex > 3)
+#endif
+                               {
+                                       DBGLOG(INIT, INFO,
+                                              ("key index error:0x%lx\n", prKey->u4KeyIndex));
+                                       /* key id is out of range */
+                                       return -EINVAL;
+                               }
+
+                               /* bit(31) and bit(30) are shared by pKey and pRemoveKey */
+                               /* Tx Key Bit(31) */
+                               if (prIWEncExt->ext_flags & IW_ENCODE_EXT_SET_TX_KEY) {
+                                       prKey->u4KeyIndex |= 0x1UL << 31;
+                               }
+
+                               /* Pairwise Key Bit(30) */
+                               if (prIWEncExt->ext_flags & IW_ENCODE_EXT_GROUP_KEY) {
+                                       /* group key */
+                               } else {
+                                       /* pairwise key */
+                                       prKey->u4KeyIndex |= 0x1UL << 30;
+                               }
+
+                       }
+                       /* Rx SC Bit(29) */
+                       if (prIWEncExt->ext_flags & IW_ENCODE_EXT_RX_SEQ_VALID) {
+                               prKey->u4KeyIndex |= 0x1UL << 29;
+                               memcpy(&prKey->rKeyRSC, prIWEncExt->rx_seq, IW_ENCODE_SEQ_MAX_SIZE);
+                       }
+
+                       /* BSSID */
+                       memcpy(prKey->arBSSID, prIWEncExt->addr.sa_data, 6);
+
+                       /* switch tx/rx MIC key for sta */
+                       if (prIWEncExt->alg == IW_ENCODE_ALG_TKIP && prIWEncExt->key_len == 32) {
+                               memcpy(prKey->aucKeyMaterial, prIWEncExt->key, 16);
+                               memcpy(((PUINT_8) prKey->aucKeyMaterial) + 16, prIWEncExt->key + 24,
+                                      8);
+                               memcpy((prKey->aucKeyMaterial) + 24, prIWEncExt->key + 16, 8);
+                       } else {
+                               memcpy(prKey->aucKeyMaterial, prIWEncExt->key, prIWEncExt->key_len);
+                       }
+
+                       prKey->u4KeyLength = prIWEncExt->key_len;
+                       prKey->u4Length =
+                           ((UINT_32) &(((P_PARAM_KEY_T) 0)->aucKeyMaterial)) +
+                           prKey->u4KeyLength;
+
+
+                       rStatus = kalIoctl(prGlueInfo,
+                                          wlanoidSetAddKey,
+                                          prKey,
+                                          prKey->u4Length, FALSE, FALSE, TRUE, FALSE, &u4BufLen);
+
+                       if (rStatus != WLAN_STATUS_SUCCESS) {
+                               DBGLOG(INIT, INFO, ("add key error:%lx\n", rStatus));
+                               return -EFAULT;
+                       }
+                       break;
+               }
+       }
+
+       return 0;
+}                              /* wext_set_encode_ext */
+
+
+/*----------------------------------------------------------------------------*/
+/*!
+* \brief Set country code
+*
+* \param[in] prDev Net device requested.
+* \param[in] prIwrInfo NULL.
+* \param[in] pu4Mode Pointer to new operation mode.
+* \param[in] pcExtra NULL.
+*
+* \retval 0 For success.
+* \retval -EOPNOTSUPP If new mode is not supported.
+*
+* \note Device will run in new operation mode if it is valid.
+*/
+/*----------------------------------------------------------------------------*/
+static int wext_set_country(IN struct net_device *prNetDev, IN struct iwreq *iwr)
+{
+       P_GLUE_INFO_T prGlueInfo;
+       WLAN_STATUS rStatus;
+       UINT_32 u4BufLen;
+       UINT_8 aucCountry[2];
+
+       ASSERT(prNetDev);
+
+       /* iwr->u.data.pointer should be like "COUNTRY US", "COUNTRY EU"
+        * and "COUNTRY JP"
+        */
+       if (FALSE == GLUE_CHK_PR2(prNetDev, iwr) || !iwr->u.data.pointer || iwr->u.data.length < 10) {
+               return -EINVAL;
+       }
+       prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev));
+
+       aucCountry[0] = *((PUINT_8) iwr->u.data.pointer + 8);
+       aucCountry[1] = *((PUINT_8) iwr->u.data.pointer + 9);
+
+       rStatus = kalIoctl(prGlueInfo,
+                          wlanoidSetCountryCode,
+                          &aucCountry[0], 2, FALSE, FALSE, TRUE, FALSE, &u4BufLen);
+
+       return 0;
+}
+
+/*----------------------------------------------------------------------------*/
+/*!
+* \brief ioctl() (Linux Wireless Extensions) routines
+*
+* \param[in] prDev Net device requested.
+* \param[in] ifr The ifreq structure for seeting the wireless extension.
+* \param[in] i4Cmd The wireless extension ioctl command.
+*
+* \retval zero On success.
+* \retval -EOPNOTSUPP If the cmd is not supported.
+* \retval -EFAULT If copy_to_user goes wrong.
+* \retval -EINVAL If any value's out of range.
+*
+* \note
+*/
+/*----------------------------------------------------------------------------*/
+int wext_support_ioctl(IN struct net_device *prDev, IN struct ifreq *prIfReq, IN int i4Cmd)
+{
+       /* prIfReq is verified in the caller function wlanDoIOCTL() */
+       struct iwreq *iwr = (struct iwreq *)prIfReq;
+       struct iw_request_info rIwReqInfo;
+       int ret = 0;
+       char *prExtraBuf = NULL;
+       UINT_32 u4ExtraSize = 0;
+
+       /* prDev is verified in the caller function wlanDoIOCTL() */
+
+       /* printk("%d CMD:0x%x\n", jiffies_to_msecs(jiffies), i4Cmd); */
+
+       /* Prepare the call */
+       rIwReqInfo.cmd = (__u16) i4Cmd;
+       rIwReqInfo.flags = 0;
+
+       switch (i4Cmd) {
+       case SIOCGIWNAME:       /* 0x8B01, get wireless protocol name */
+               ret = wext_get_name(prDev, &rIwReqInfo, (char *)&iwr->u.name, NULL);
+               break;
+
+               /* case SIOCSIWNWID: 0x8B02, deprecated */
+               /* case SIOCGIWNWID: 0x8B03, deprecated */
+
+       case SIOCSIWFREQ:       /* 0x8B04, set channel */
+               ret = wext_set_freq(prDev, NULL, &iwr->u.freq, NULL);
+               break;
+
+       case SIOCGIWFREQ:       /* 0x8B05, get channel */
+               ret = wext_get_freq(prDev, NULL, &iwr->u.freq, NULL);
+               break;
+
+       case SIOCSIWMODE:       /* 0x8B06, set operation mode */
+               ret = wext_set_mode(prDev, NULL, &iwr->u.mode, NULL);
+               /* ret = 0; */
+               break;
+
+       case SIOCGIWMODE:       /* 0x8B07, get operation mode */
+               ret = wext_get_mode(prDev, NULL, &iwr->u.mode, NULL);
+               break;
+
+               /* case SIOCSIWSENS: 0x8B08, unsupported */
+               /* case SIOCGIWSENS: 0x8B09, unsupported */
+
+               /* case SIOCSIWRANGE: 0x8B0A, unused */
+       case SIOCGIWRANGE:      /* 0x8B0B, get range of parameters */
+               if (iwr->u.data.pointer != NULL) {
+                       /* Buffer size shoule be large enough */
+                       if (iwr->u.data.length < sizeof(struct iw_range)) {
+                               ret = -E2BIG;
+                               break;
+                       }
+
+                       prExtraBuf = kalMemAlloc(sizeof(struct iw_range), VIR_MEM_TYPE);
+                       if (!prExtraBuf) {
+                               ret = -ENOMEM;
+                               break;
+                       }
+
+                       /* reset all fields */
+                       memset(prExtraBuf, 0, sizeof(struct iw_range));
+                       iwr->u.data.length = sizeof(struct iw_range);
+
+                       ret = wext_get_range(prDev, NULL, &iwr->u.data, prExtraBuf);
+                       /* Push up to the caller */
+                       if (copy_to_user(iwr->u.data.pointer, prExtraBuf, iwr->u.data.length)) {
+                               ret = -EFAULT;
+                       }
+
+                       kalMemFree(prExtraBuf, VIR_MEM_TYPE, sizeof(struct iw_range));
+                       prExtraBuf = NULL;
+               } else {
+                       ret = -EINVAL;
+               }
+               break;
+
+       case SIOCSIWPRIV:       /* 0x8B0C, Country */
+               ret = wext_set_country(prDev, iwr);
+               break;
+
+               /* case SIOCGIWPRIV: 0x8B0D, handled in wlan_do_ioctl() */
+               /* caes SIOCSIWSTATS: 0x8B0E, unused */
+               /* case SIOCGIWSTATS:
+                  get statistics, intercepted by wireless_process_ioctl() in wireless.c,
+                  redirected to dev_iwstats(), dev->get_wireless_stats().
+                */
+               /* case SIOCSIWSPY: 0x8B10, unsupported */
+               /* case SIOCGIWSPY: 0x8B11, unsupported */
+               /* case SIOCSIWTHRSPY: 0x8B12, unsupported */
+               /* case SIOCGIWTHRSPY: 0x8B13, unsupported */
+
+       case SIOCSIWAP: /* 0x8B14, set access point MAC addresses (BSSID) */
+               if (iwr->u.ap_addr.sa_data[0] == 0 &&
+                   iwr->u.ap_addr.sa_data[1] == 0 &&
+                   iwr->u.ap_addr.sa_data[2] == 0 &&
+                   iwr->u.ap_addr.sa_data[3] == 0 &&
+                   iwr->u.ap_addr.sa_data[4] == 0 && iwr->u.ap_addr.sa_data[5] == 0) {
+                       /* WPA Supplicant will set 000000000000 in
+                        ** wpa_driver_wext_deinit(), do nothing here or disassoc again?
+                        */
+                       ret = 0;
+                       break;
+               } else {
+                       ret = wext_set_ap(prDev, NULL, &iwr->u.ap_addr, NULL);
+               }
+               break;
+
+       case SIOCGIWAP: /* 0x8B15, get access point MAC addresses (BSSID) */
+               ret = wext_get_ap(prDev, NULL, &iwr->u.ap_addr, NULL);
+               break;
+
+       case SIOCSIWMLME:       /* 0x8B16, request MLME operation */
+               /* Fixed length structure */
+               if (iwr->u.data.length != sizeof(struct iw_mlme)) {
+                       DBGLOG(INIT, INFO, ("MLME buffer strange:%d\n", iwr->u.data.length));
+                       ret = -EINVAL;
+                       break;
+               }
+
+               if (!iwr->u.data.pointer) {
+                       ret = -EINVAL;
+                       break;
+               }
+
+               prExtraBuf = kalMemAlloc(sizeof(struct iw_mlme), VIR_MEM_TYPE);
+               if (!prExtraBuf) {
+                       ret = -ENOMEM;
+                       break;
+               }
+
+               if (copy_from_user(prExtraBuf, iwr->u.data.pointer, sizeof(struct iw_mlme))) {
+                       ret = -EFAULT;
+               } else {
+                       ret = wext_set_mlme(prDev, NULL, &(iwr->u.data), prExtraBuf);
+               }
+
+               kalMemFree(prExtraBuf, VIR_MEM_TYPE, sizeof(struct iw_mlme));
+               prExtraBuf = NULL;
+               break;
+
+               /* case SIOCGIWAPLIST: 0x8B17, deprecated */
+       case SIOCSIWSCAN:       /* 0x8B18, scan request */
+               if (iwr->u.data.pointer == NULL) {
+                       ret = wext_set_scan(prDev, NULL, NULL, NULL);
+               }
+#if WIRELESS_EXT > 17
+               else if (iwr->u.data.length == sizeof(struct iw_scan_req)) {
+                       prExtraBuf = kalMemAlloc(MAX_SSID_LEN, VIR_MEM_TYPE);
+                       if (!prExtraBuf) {
+                               ret = -ENOMEM;
+                               break;
+                       }
+                       if (copy_from_user
+                           (prExtraBuf, ((struct iw_scan_req *)(iwr->u.data.pointer))->essid,
+                            ((struct iw_scan_req *)(iwr->u.data.pointer))->essid_len)) {
+                               ret = -EFAULT;
+                       } else {
+                               ret =
+                                   wext_set_scan(prDev, NULL, (union iwreq_data *)&(iwr->u.data),
+                                                 prExtraBuf);
+                       }
+
+                       kalMemFree(prExtraBuf, VIR_MEM_TYPE, MAX_SSID_LEN);
+                       prExtraBuf = NULL;
+               }
+#endif
+               else {
+                       ret = -EINVAL;
+               }
+               break;
+#if 1
+       case SIOCGIWSCAN:       /* 0x8B19, get scan results */
+               if (!iwr->u.data.pointer || !iwr->u.essid.pointer) {
+                       ret = -EINVAL;
+                       break;
+               }
+
+               u4ExtraSize = iwr->u.data.length;
+               /* allocate the same size of kernel buffer to store scan results. */
+               prExtraBuf = kalMemAlloc(u4ExtraSize, VIR_MEM_TYPE);
+               if (!prExtraBuf) {
+                       ret = -ENOMEM;
+                       break;
+               }
+
+               /* iwr->u.data.length may be updated by wext_get_scan() */
+               ret = wext_get_scan(prDev, NULL, &iwr->u.data, prExtraBuf);
+               if (ret != 0) {
+                       if (ret == -E2BIG) {
+                               DBGLOG(INIT, INFO, ("[wifi] wext_get_scan -E2BIG\n"));
+                       }
+               } else {
+                       /* check updated length is valid */
+                       ASSERT(iwr->u.data.length <= u4ExtraSize);
+                       if (iwr->u.data.length > u4ExtraSize) {
+                               DBGLOG(INIT, INFO,
+                                      ("Updated result length is larger than allocated (%d > %ld)\n",
+                                       iwr->u.data.length, u4ExtraSize));
+                               iwr->u.data.length = u4ExtraSize;
+                       }
+
+                       if (copy_to_user(iwr->u.data.pointer, prExtraBuf, iwr->u.data.length)) {
+                               ret = -EFAULT;
+                       }
+               }
+
+               kalMemFree(prExtraBuf, VIR_MEM_TYPE, u4ExtraSize);
+               prExtraBuf = NULL;
+
+               break;
+
+#endif
+
+#if 1
+       case SIOCSIWESSID:      /* 0x8B1A, set SSID (network name) */
+               if (iwr->u.essid.length > IW_ESSID_MAX_SIZE) {
+                       ret = -E2BIG;
+                       break;
+               }
+               if (!iwr->u.essid.pointer) {
+                       ret = -EINVAL;
+                       break;
+               }
+
+               prExtraBuf = kalMemAlloc(IW_ESSID_MAX_SIZE + 4, VIR_MEM_TYPE);
+               if (!prExtraBuf) {
+                       ret = -ENOMEM;
+                       break;
+               }
+
+               if (copy_from_user(prExtraBuf, iwr->u.essid.pointer, iwr->u.essid.length)) {
+                       ret = -EFAULT;
+               } else {
+                       /* Add trailing '\0' for printk */
+                       /* prExtraBuf[iwr->u.essid.length] = 0; */
+                       /* printk(KERN_INFO "wext_set_essid: %s (%d)\n", prExtraBuf, iwr->u.essid.length); */
+                       ret = wext_set_essid(prDev, NULL, &iwr->u.essid, prExtraBuf);
+                       /* printk ("set essid %d\n", ret); */
+               }
+
+               kalMemFree(prExtraBuf, VIR_MEM_TYPE, IW_ESSID_MAX_SIZE + 4);
+               prExtraBuf = NULL;
+               break;
+
+#endif
+
+       case SIOCGIWESSID:      /* 0x8B1B, get SSID */
+               if (!iwr->u.essid.pointer) {
+                       ret = -EINVAL;
+                       break;
+               }
+
+               if (iwr->u.essid.length < IW_ESSID_MAX_SIZE) {
+                       DBGLOG(INIT, INFO, ("[wifi] iwr->u.essid.length:%d too small\n",
+                                           iwr->u.essid.length));
+                       ret = -E2BIG;   /* let caller try larger buffer */
+                       break;
+               }
+
+               prExtraBuf = kalMemAlloc(IW_ESSID_MAX_SIZE, VIR_MEM_TYPE);
+               if (!prExtraBuf) {
+                       ret = -ENOMEM;
+                       break;
+               }
+
+               /* iwr->u.essid.length is updated by wext_get_essid() */
+
+               ret = wext_get_essid(prDev, NULL, &iwr->u.essid, prExtraBuf);
+               if (ret == 0) {
+                       if (copy_to_user(iwr->u.essid.pointer, prExtraBuf, iwr->u.essid.length)) {
+                               ret = -EFAULT;
+                       }
+               }
+
+               kalMemFree(prExtraBuf, VIR_MEM_TYPE, IW_ESSID_MAX_SIZE);
+               prExtraBuf = NULL;
+
+               break;
+
+               /* case SIOCSIWNICKN: 0x8B1C, not supported */
+               /* case SIOCGIWNICKN: 0x8B1D, not supported */
+
+       case SIOCSIWRATE:       /* 0x8B20, set default bit rate (bps) */
+               /* ret = wext_set_rate(prDev, &rIwReqInfo, &iwr->u.bitrate, NULL); */
+               break;
+
+       case SIOCGIWRATE:       /* 0x8B21, get current bit rate (bps) */
+               ret = wext_get_rate(prDev, NULL, &iwr->u.bitrate, NULL);
+               break;
+
+       case SIOCSIWRTS:        /* 0x8B22, set rts/cts threshold */
+               ret = wext_set_rts(prDev, NULL, &iwr->u.rts, NULL);
+               break;
+
+       case SIOCGIWRTS:        /* 0x8B23, get rts/cts threshold */
+               ret = wext_get_rts(prDev, NULL, &iwr->u.rts, NULL);
+               break;
+
+               /* case SIOCSIWFRAG: 0x8B24, unsupported */
+       case SIOCGIWFRAG:       /* 0x8B25, get frag threshold */
+               ret = wext_get_frag(prDev, NULL, &iwr->u.frag, NULL);
+               break;
+
+       case SIOCSIWTXPOW:      /* 0x8B26, set relative tx power (in %) */
+               ret = wext_set_txpow(prDev, NULL, &iwr->u.txpower, NULL);
+               break;
+
+       case SIOCGIWTXPOW:      /* 0x8B27, get relative tx power (in %) */
+               ret = wext_get_txpow(prDev, NULL, &iwr->u.txpower, NULL);
+               break;
+
+               /* case SIOCSIWRETRY: 0x8B28, unsupported */
+               /* case SIOCGIWRETRY: 0x8B29, unsupported */
+
+#if 1
+       case SIOCSIWENCODE:     /* 0x8B2A, set encoding token & mode */
+               /* Only DISABLED case has NULL pointer and length == 0 */
+               if (iwr->u.encoding.pointer) {
+                       if (iwr->u.encoding.length > 16) {
+                               ret = -E2BIG;
+                               break;
+                       }
+
+                       u4ExtraSize = iwr->u.encoding.length;
+                       prExtraBuf = kalMemAlloc(u4ExtraSize, VIR_MEM_TYPE);
+                       if (!prExtraBuf) {
+                               ret = -ENOMEM;
+                               break;
+                       }
+
+                       if (copy_from_user(prExtraBuf,
+                                          iwr->u.encoding.pointer, iwr->u.encoding.length)) {
+                               ret = -EFAULT;
+                       }
+               } else if (iwr->u.encoding.length != 0) {
+                       ret = -EINVAL;
+                       break;
+               }
+
+               if (ret == 0) {
+                       ret = wext_set_encode(prDev, NULL, &iwr->u.encoding, prExtraBuf);
+               }
+
+               if (prExtraBuf) {
+                       kalMemFree(prExtraBuf, VIR_MEM_TYPE, u4ExtraSize);
+                       prExtraBuf = NULL;
+               }
+               break;
+
+       case SIOCGIWENCODE:     /* 0x8B2B, get encoding token & mode */
+               /* check pointer */
+               ret = wext_get_encode(prDev, NULL, &iwr->u.encoding, NULL);
+               break;
+
+       case SIOCSIWPOWER:      /* 0x8B2C, set power management */
+               ret = wext_set_power(prDev, NULL, &iwr->u.power, NULL);
+               break;
+
+       case SIOCGIWPOWER:      /* 0x8B2D, get power management */
+               ret = wext_get_power(prDev, NULL, &iwr->u.power, NULL);
+               break;
+
+#if WIRELESS_EXT > 17
+       case SIOCSIWGENIE:      /* 0x8B30, set gen ie */
+               if (iwr->u.data.pointer) {
+                       P_GLUE_INFO_T prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev));
+                       if (1 /* wlanQueryWapiMode(prGlueInfo->prAdapter) */) {
+                               /* Fixed length structure */
+#if CFG_SUPPORT_WAPI
+                               if (iwr->u.data.length > 42 /* The max wapi ie buffer */) {
+                                       ret = -EINVAL;
+                                       break;
+                               }
+#endif
+                               u4ExtraSize = iwr->u.data.length;
+                               if (u4ExtraSize) {
+                                       prExtraBuf = kalMemAlloc(u4ExtraSize, VIR_MEM_TYPE);
+                                       if (!prExtraBuf) {
+                                               ret = -ENOMEM;
+                                               break;
+                                       }
+                                       if (copy_from_user(prExtraBuf,
+                                                          iwr->u.data.pointer,
+                                                          iwr->u.data.length)) {
+                                               ret = -EFAULT;
+                                       } else {
+                                               WLAN_STATUS rStatus;
+                                               UINT_32 u4BufLen;
+#if CFG_SUPPORT_WAPI
+                                               rStatus = kalIoctl(prGlueInfo,
+                                                                  wlanoidSetWapiAssocInfo,
+                                                                  prExtraBuf,
+                                                                  u4ExtraSize,
+                                                                  FALSE,
+                                                                  FALSE, TRUE, FALSE, &u4BufLen);
+
+                                               if (rStatus != WLAN_STATUS_SUCCESS) {
+                                                       /* printk(KERN_INFO "[wapi] set wapi assoc info error:%lx\n", rStatus); */
+#endif
+#if CFG_SUPPORT_WPS2
+                                                       PUINT_8 prDesiredIE = NULL;
+                                                       if (wextSrchDesiredWPSIE(prExtraBuf,
+                                                                                u4ExtraSize,
+                                                                                0xDD,
+                                                                                (PUINT_8 *) &
+                                                                                prDesiredIE)) {
+                                                               rStatus =
+                                                                   kalIoctl(prGlueInfo,
+                                                                            wlanoidSetWSCAssocInfo,
+                                                                            prDesiredIE,
+                                                                            IE_SIZE(prDesiredIE),
+                                                                            FALSE, FALSE, TRUE,
+                                                                            FALSE, &u4BufLen);
+                                                               if (rStatus != WLAN_STATUS_SUCCESS) {
+                                                                       /* printk(KERN_INFO "[WSC] set WSC assoc info error:%lx\n", rStatus); */
+                                                               }
+                                                       }
+#endif
+#if CFG_SUPPORT_WAPI
+                                               }
+#endif
+                                       }
+                                       kalMemFree(prExtraBuf, VIR_MEM_TYPE, u4ExtraSize);
+                                       prExtraBuf = NULL;
+                               }
+                       }
+               }
+               break;
+
+       case SIOCGIWGENIE:      /* 0x8B31, get gen ie, unused */
+               break;
+
+#endif
+
+       case SIOCSIWAUTH:       /* 0x8B32, set auth mode params */
+               ret = wext_set_auth(prDev, NULL, &iwr->u.param, NULL);
+               break;
+
+               /* case SIOCGIWAUTH: 0x8B33, unused? */
+       case SIOCSIWENCODEEXT:  /* 0x8B34, set extended encoding token & mode */
+               if (iwr->u.encoding.pointer) {
+                       u4ExtraSize = iwr->u.encoding.length;
+                       prExtraBuf = kalMemAlloc(u4ExtraSize, VIR_MEM_TYPE);
+                       if (!prExtraBuf) {
+                               ret = -ENOMEM;
+                               break;
+                       }
+
+                       if (copy_from_user(prExtraBuf,
+                                          iwr->u.encoding.pointer, iwr->u.encoding.length)) {
+                               ret = -EFAULT;
+                       }
+               } else if (iwr->u.encoding.length != 0) {
+                       ret = -EINVAL;
+                       break;
+               }
+
+               if (ret == 0) {
+                       ret = wext_set_encode_ext(prDev, NULL, &iwr->u.encoding, prExtraBuf);
+               }
+
+               if (prExtraBuf) {
+                       kalMemFree(prExtraBuf, VIR_MEM_TYPE, u4ExtraSize);
+                       prExtraBuf = NULL;
+               }
+               break;
+
+               /* case SIOCGIWENCODEEXT: 0x8B35, unused? */
+
+       case SIOCSIWPMKSA:      /* 0x8B36, pmksa cache operation */
+#if 1
+               if (iwr->u.data.pointer) {
+                       /* Fixed length structure */
+                       if (iwr->u.data.length != sizeof(struct iw_pmksa)) {
+                               ret = -EINVAL;
+                               break;
+                       }
+
+                       u4ExtraSize = sizeof(struct iw_pmksa);
+                       prExtraBuf = kalMemAlloc(u4ExtraSize, VIR_MEM_TYPE);
+                       if (!prExtraBuf) {
+                               ret = -ENOMEM;
+                               break;
+                       }
+
+                       if (copy_from_user(prExtraBuf,
+                                          iwr->u.data.pointer, sizeof(struct iw_pmksa))) {
+                               ret = -EFAULT;
+                       } else {
+                               switch (((struct iw_pmksa *)prExtraBuf)->cmd) {
+                               case IW_PMKSA_ADD:
+                                       /*
+                                          printk(KERN_INFO "IW_PMKSA_ADD [" MACSTR "]\n",
+                                          MAC2STR(((struct iw_pmksa *)pExtraBuf)->bssid.sa_data));
+                                        */
+                                       {
+                                               P_GLUE_INFO_T prGlueInfo =
+                                                   *((P_GLUE_INFO_T *) netdev_priv(prDev));
+                                               WLAN_STATUS rStatus;
+                                               UINT_32 u4BufLen;
+                                               P_PARAM_PMKID_T prPmkid;
+
+                                               prPmkid =
+                                                   (P_PARAM_PMKID_T) kalMemAlloc(8 +
+                                                                                 sizeof
+                                                                                 (PARAM_BSSID_INFO_T),
+                                                                                 VIR_MEM_TYPE);
+                                               if (!prPmkid) {
+                                                       DBGLOG(INIT, INFO,
+                                                              ("Can not alloc memory for IW_PMKSA_ADD\n"));
+                                                       ret = -ENOMEM;
+                                                       break;
+                                               }
+
+                                               prPmkid->u4Length = 8 + sizeof(PARAM_BSSID_INFO_T);
+                                               prPmkid->u4BSSIDInfoCount = 1;
+                                               kalMemCopy(prPmkid->arBSSIDInfo->arBSSID,
+                                                          ((struct iw_pmksa *)prExtraBuf)->bssid.
+                                                          sa_data, 6);
+                                               kalMemCopy(prPmkid->arBSSIDInfo->arPMKID,
+                                                          ((struct iw_pmksa *)prExtraBuf)->pmkid,
+                                                          IW_PMKID_LEN);
+
+                                               rStatus = kalIoctl(prGlueInfo,
+                                                                  wlanoidSetPmkid,
+                                                                  prPmkid,
+                                                                  sizeof(PARAM_PMKID_T),
+                                                                  FALSE,
+                                                                  FALSE, TRUE, FALSE, &u4BufLen);
+
+                                               if (rStatus != WLAN_STATUS_SUCCESS) {
+                                                       DBGLOG(INIT, INFO,
+                                                              ("add pmkid error:%lx\n", rStatus));
+                                               }
+                                               kalMemFree(prPmkid, VIR_MEM_TYPE,
+                                                          8 + sizeof(PARAM_BSSID_INFO_T));
+                                       }
+                                       break;
+                               case IW_PMKSA_REMOVE:
+                                       /*
+                                          printk(KERN_INFO "IW_PMKSA_REMOVE [" MACSTR "]\n",
+                                          MAC2STR(((struct iw_pmksa *)buf)->bssid.sa_data));
+                                        */
+                                       break;
+                               case IW_PMKSA_FLUSH:
+                                       /*
+                                          printk(KERN_INFO "IW_PMKSA_FLUSH\n");
+                                        */
+                                       {
+                                               P_GLUE_INFO_T prGlueInfo =
+                                                   *((P_GLUE_INFO_T *) netdev_priv(prDev));
+                                               WLAN_STATUS rStatus;
+                                               UINT_32 u4BufLen;
+                                               P_PARAM_PMKID_T prPmkid;
+
+                                               prPmkid =
+                                                   (P_PARAM_PMKID_T) kalMemAlloc(8, VIR_MEM_TYPE);
+                                               if (!prPmkid) {
+                                                       DBGLOG(INIT, INFO,
+                                                              ("Can not alloc memory for IW_PMKSA_FLUSH\n"));
+                                                       ret = -ENOMEM;
+                                                       break;
+                                               }
+
+                                               prPmkid->u4Length = 8;
+                                               prPmkid->u4BSSIDInfoCount = 0;
+
+                                               rStatus = kalIoctl(prGlueInfo,
+                                                                  wlanoidSetPmkid,
+                                                                  prPmkid,
+                                                                  sizeof(PARAM_PMKID_T),
+                                                                  FALSE,
+                                                                  FALSE, TRUE, FALSE, &u4BufLen);
+
+                                               if (rStatus != WLAN_STATUS_SUCCESS) {
+                                                       DBGLOG(INIT, INFO,
+                                                              ("flush pmkid error:%lx\n",
+                                                               rStatus));
+                                               }
+                                               kalMemFree(prPmkid, VIR_MEM_TYPE, 8);
+                                       }
+                                       break;
+                               default:
+                                       DBGLOG(INIT, INFO, ("UNKNOWN iw_pmksa command:%d\n",
+                                                           ((struct iw_pmksa *)prExtraBuf)->cmd));
+                                       ret = -EFAULT;
+                                       break;
+                               }
+                       }
+
+                       if (prExtraBuf) {
+                               kalMemFree(prExtraBuf, VIR_MEM_TYPE, u4ExtraSize);
+                               prExtraBuf = NULL;
+                       }
+               } else if (iwr->u.data.length != 0) {
+                       ret = -EINVAL;
+                       break;
+               }
+#endif
+               break;
+
+#endif
+
+       default:
+               /* printk(KERN_NOTICE "unsupported IOCTL: 0x%x\n", i4Cmd); */
+               ret = -EOPNOTSUPP;
+               break;
+       }
+
+       /* printk("%ld CMD:0x%x ret:%d\n", jiffies_to_msecs(jiffies), i4Cmd, ret); */
+
+       return ret;
+}                              /* wext_support_ioctl */
+
+
+
+/*----------------------------------------------------------------------------*/
+/*!
+* \brief To send an event (RAW socket pacekt) to user process actively.
+*
+* \param[in] prGlueInfo Glue layer info.
+* \param[in] u4cmd Whcih event command we want to indicate to user process.
+* \param[in] pData Data buffer to be indicated.
+* \param[in] dataLen Available data size in pData.
+*
+* \return (none)
+*
+* \note Event is indicated to upper layer if cmd is supported and data is valid.
+*       Using of kernel symbol wireless_send_event(), which is defined in
+*      <net/iw_handler.h> after WE-14 (2.4.20).
+*/
+/*----------------------------------------------------------------------------*/
+void
+wext_indicate_wext_event(IN P_GLUE_INFO_T prGlueInfo,
+                        IN unsigned int u4Cmd,
+                        IN unsigned char *pucData, IN unsigned int u4dataLen)
+{
+       union iwreq_data wrqu;
+       unsigned char *pucExtraInfo = NULL;
+#if WIRELESS_EXT >= 15
+       unsigned char *pucDesiredIE = NULL;
+       unsigned char aucExtraInfoBuf[200];
+#endif
+#if WIRELESS_EXT < 18
+       int i;
+#endif
+
+       memset(&wrqu, 0, sizeof(wrqu));
+
+       switch (u4Cmd) {
+       case SIOCGIWTXPOW:
+               memcpy(&wrqu.power, pucData, u4dataLen);
+               break;
+       case SIOCGIWSCAN:
+               complete_all(&prGlueInfo->rScanComp);
+               break;
+
+       case SIOCGIWAP:
+               if (pucData) {
+                       memcpy(&wrqu.ap_addr.sa_data, pucData, ETH_ALEN);
+               } else {
+                       memset(&wrqu.ap_addr.sa_data, 0, ETH_ALEN);
+               }
+               break;
+
+       case IWEVASSOCREQIE:
+#if WIRELESS_EXT < 15
+               /* under WE-15, no suitable Event can be used */
+               goto skip_indicate_event;
+#else
+               /* do supplicant a favor, parse to the start of WPA/RSN IE */
+               if (wextSrchDesiredWPAIE(pucData, u4dataLen, 0x30, &pucDesiredIE)) {
+                       /* RSN IE found */
+               }
+#if 0
+               else if (wextSrchDesiredWPSIE(pucData, u4dataLen, 0xDD, &pucDesiredIE)) {
+                       /* WPS IE found */
+               }
+#endif
+               else if (wextSrchDesiredWPAIE(pucData, u4dataLen, 0xDD, &pucDesiredIE)) {
+                       /* WPA IE found */
+               }
+#if CFG_SUPPORT_WAPI           /* Android+ */
+               else if (wextSrchDesiredWAPIIE(pucData, u4dataLen, &pucDesiredIE)) {
+                       /* printk("wextSrchDesiredWAPIIE!!\n"); */
+                       /* WAPI IE found */
+               }
+#endif
+               else {
+                       /* no WPA/RSN IE found, skip this event */
+                       goto skip_indicate_event;
+               }
+
+#if WIRELESS_EXT < 18
+               /* under WE-18, only IWEVCUSTOM can be used */
+               u4Cmd = IWEVCUSTOM;
+               pucExtraInfo = aucExtraInfoBuf;
+               pucExtraInfo += sprintf(pucExtraInfo, "ASSOCINFO(ReqIEs=");
+               /* printk(KERN_DEBUG "assoc info buffer size needed:%d\n", infoElemLen * 2 + 17); */
+               /* translate binary string to hex string, requirement of IWEVCUSTOM */
+               for (i = 0; i < pucDesiredIE[1] + 2; ++i) {
+                       pucExtraInfo += sprintf(pucExtraInfo, "%02x", pucDesiredIE[i]);
+               }
+               pucExtraInfo = aucExtraInfoBuf;
+               wrqu.data.length = 17 + (pucDesiredIE[1] + 2) * 2;
+#else
+               /* IWEVASSOCREQIE, indicate binary string */
+               pucExtraInfo = pucDesiredIE;
+               wrqu.data.length = pucDesiredIE[1] + 2;
+#endif
+#endif                         /* WIRELESS_EXT < 15 */
+               break;
+
+       case IWEVMICHAELMICFAILURE:
+#if WIRELESS_EXT < 15
+               /* under WE-15, no suitable Event can be used */
+               goto skip_indicate_event;
+#else
+               if (pucData) {
+                       P_PARAM_AUTH_REQUEST_T pAuthReq = (P_PARAM_AUTH_REQUEST_T) pucData;
+                       /* under WE-18, only IWEVCUSTOM can be used */
+                       u4Cmd = IWEVCUSTOM;
+                       pucExtraInfo = aucExtraInfoBuf;
+                       pucExtraInfo += sprintf(pucExtraInfo, "MLME-MICHAELMICFAILURE.indication ");
+                       pucExtraInfo += sprintf(pucExtraInfo,
+                                               "%s",
+                                               (pAuthReq->u4Flags ==
+                                                PARAM_AUTH_REQUEST_GROUP_ERROR) ? "groupcast " :
+                                               "unicast ");
+
+                       wrqu.data.length = pucExtraInfo - aucExtraInfoBuf;
+                       pucExtraInfo = aucExtraInfoBuf;
+               }
+#endif                         /* WIRELESS_EXT < 15 */
+               break;
+
+       case IWEVPMKIDCAND:
+               if (prGlueInfo->rWpaInfo.u4WpaVersion == IW_AUTH_WPA_VERSION_WPA2 &&
+                   prGlueInfo->rWpaInfo.u4KeyMgmt == IW_AUTH_KEY_MGMT_802_1X) {
+
+                       /* only used in WPA2 */
+#if WIRELESS_EXT >= 18
+                       P_PARAM_PMKID_CANDIDATE_T prPmkidCand = (P_PARAM_PMKID_CANDIDATE_T) pucData;
+
+                       struct iw_pmkid_cand rPmkidCand;
+                       pucExtraInfo = aucExtraInfoBuf;
+
+                       rPmkidCand.flags = prPmkidCand->u4Flags;
+                       rPmkidCand.index = 0;
+                       kalMemCopy(rPmkidCand.bssid.sa_data, prPmkidCand->arBSSID, 6);
+
+                       kalMemCopy(pucExtraInfo, (PUINT_8) &rPmkidCand,
+                                  sizeof(struct iw_pmkid_cand));
+                       wrqu.data.length = sizeof(struct iw_pmkid_cand);
+
+                       /* pmkid canadidate list is supported after WE-18 */
+                       /* indicate struct iw_pmkid_cand */
+#else
+                       /* printk(KERN_INFO "IWEVPMKIDCAND event skipped, WE < 18\n"); */
+                       goto skip_indicate_event;
+#endif
+               } else {
+                       /* printk(KERN_INFO "IWEVPMKIDCAND event skipped, NOT WPA2\n"); */
+                       goto skip_indicate_event;
+               }
+               break;
+
+       case IWEVCUSTOM:
+               u4Cmd = IWEVCUSTOM;
+               pucExtraInfo = aucExtraInfoBuf;
+               kalMemCopy(pucExtraInfo, pucData, sizeof(PTA_IPC_T));
+               wrqu.data.length = sizeof(PTA_IPC_T);
+               break;
+
+       default:
+               /* printk(KERN_INFO "Unsupported wext event:%x\n", cmd); */
+               goto skip_indicate_event;
+       }
+
+       /* Send event to user space */
+       wireless_send_event(prGlueInfo->prDevHandler, u4Cmd, &wrqu, pucExtraInfo);
+
+ skip_indicate_event:
+       return;
+}                              /* wext_indicate_wext_event */
+
+
+/*----------------------------------------------------------------------------*/
+/*!
+* \brief A method of struct net_device, to get the network interface statistical
+*        information.
+*
+* Whenever an application needs to get statistics for the interface, this method
+* is called. This happens, for example, when ifconfig or netstat -i is run.
+*
+* \param[in] pDev Pointer to struct net_device.
+*
+* \return net_device_stats buffer pointer.
+*
+*/
+/*----------------------------------------------------------------------------*/
+struct iw_statistics *wext_get_wireless_stats(struct net_device *prDev)
+{
+
+       WLAN_STATUS rStatus = WLAN_STATUS_FAILURE;
+       P_GLUE_INFO_T prGlueInfo = NULL;
+       struct iw_statistics *pStats = NULL;
+       INT_32 i4Rssi;
+       UINT_32 bufLen = 0;
+
+
+       prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev));
+       ASSERT(prGlueInfo);
+       if (!prGlueInfo) {
+               goto stat_out;
+       }
+
+       pStats = (struct iw_statistics *)(&(prGlueInfo->rIwStats));
+
+       if (!prDev || !netif_carrier_ok(prDev)) {
+               /* network not connected */
+               goto stat_out;
+       }
+
+       rStatus = kalIoctl(prGlueInfo,
+                          wlanoidQueryRssi,
+                          &i4Rssi, sizeof(i4Rssi), TRUE, TRUE, TRUE, FALSE, &bufLen);
+
+ stat_out:
+       return pStats;
+}                              /* wlan_get_wireless_stats */
+
+/*----------------------------------------------------------------------------*/
+/*!
+* \brief To report the private supported IOCTLs table to user space.
+*
+* \param[in] prNetDev Net device requested.
+* \param[out] prIfReq Pointer to ifreq structure, content is copied back to
+*                  user space buffer in gl_iwpriv_table.
+*
+* \retval 0 For success.
+* \retval -E2BIG For user's buffer size is too small.
+* \retval -EFAULT For fail.
+*
+*/
+/*----------------------------------------------------------------------------*/
+int wext_get_priv(IN struct net_device *prNetDev, IN struct ifreq *prIfReq)
+{
+       /* prIfReq is verified in the caller function wlanDoIOCTL() */
+       struct iwreq *prIwReq = (struct iwreq *)prIfReq;
+       struct iw_point *prData = (struct iw_point *)&prIwReq->u.data;
+       UINT_16 u2BufferSize = 0;
+
+       u2BufferSize = prData->length;
+
+       /* update our private table size */
+       prData->length = (__u16) sizeof(rIwPrivTable) / sizeof(struct iw_priv_args);
+
+       if (u2BufferSize < prData->length) {
+               return -E2BIG;
+       }
+
+       if (prData->length) {
+               if (copy_to_user(prData->pointer, rIwPrivTable, sizeof(rIwPrivTable))) {
+                       return -EFAULT;
+               }
+       }
+
+       return 0;
+}                              /* wext_get_priv */
+
+#endif                         /* WIRELESS_EXT */