support different wifi bt chip auto compatible
[firefly-linux-kernel-4.4.55.git] / drivers / net / wireless / rockchip_wlan / combo_mt66xx / mt6628 / wlan / os / linux / gl_wext.c
1 /*
2 ** $Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/os/linux/gl_wext.c#3 $
3 */
4
5 /*! \file gl_wext.c
6     \brief  ioctl() (mostly Linux Wireless Extensions) routines for STA driver.
7 */
8
9
10
11 /*
12 ** $Log: gl_wext.c $
13  *
14  * 06 13 2012 yuche.tsai
15  * NULL
16  * Update maintrunk driver.
17  * Add support for driver compose assoc request frame.
18  *
19  * 01 16 2012 wh.su
20  * [WCXRP00001170] [MT6620 Wi-Fi][Driver] Adding the related code for set/get band ioctl
21  * Adding the template code for set / get band IOCTL (with ICS supplicant_6)..
22  *
23  * 01 05 2012 wh.su
24  * [WCXRP00001153] [MT6620 Wi-Fi][Driver] Adding the get_ch_list and set_tx_power proto type function
25  * Adding the related ioctl / wlan oid function to set the Tx power cfg.
26  *
27  * 01 02 2012 wh.su
28  * [WCXRP00001153] [MT6620 Wi-Fi][Driver] Adding the get_ch_list and set_tx_power proto type function
29  * Adding the proto type function for set_int set_tx_power and get int get_ch_list.
30  *
31  * 11 10 2011 cp.wu
32  * [WCXRP00001098] [MT6620 Wi-Fi][Driver] Replace printk by DBG LOG macros in linux porting layer
33  * 1. eliminaite direct calls to printk in porting layer.
34  * 2. replaced by DBGLOG, which would be XLOG on ALPS platforms.
35  *
36  * 10 12 2011 wh.su
37  * [WCXRP00001036] [MT6620 Wi-Fi][Driver][FW] Adding the 802.11w code for MFP
38  * adding the 802.11w related function and define .
39  *
40  * 09 23 2011 tsaiyuan.hsu
41  * [WCXRP00000979] [MT6620 Wi-Fi][DRV]] stop attempting to connect to config AP after D3 state
42  * avoid entering D3 state after deep sleep.
43  *
44  * 07 28 2011 chinghwa.yu
45  * [WCXRP00000063] Update BCM CoEx design and settings
46  * Add BWCS cmd and event.
47  *
48  * 07 27 2011 wh.su
49  * [WCXRP00000877] [MT6620 Wi-Fi][Driver] Remove the netif_carry_ok check for avoid the wpa_supplicant fail to query the ap address
50  * Remove the netif check while query bssid and ssid
51  *
52  * 07 26 2011 chinglan.wang
53  * NULL
54  * [MT6620][WiFi Driver] Do not include the WSC IE in the association info packet when not do the wps connection..
55  *
56  * 07 18 2011 chinghwa.yu
57  * [WCXRP00000063] Update BCM CoEx design and settings[WCXRP00000612] [MT6620 Wi-Fi] [FW] CSD update SWRDD algorithm
58  * Add CMD/Event for RDD and BWCS.
59  *
60  * 05 17 2011 eddie.chen
61  * [WCXRP00000603] [MT6620 Wi-Fi][DRV] Fix Klocwork warning
62  * Initilize the vairlabes.
63  *
64  * 05 11 2011 jeffrey.chang
65  * [WCXRP00000718] [MT6620 Wi-Fi] modify the behavior of setting tx power
66  * modify set_tx_pow ioctl
67  *
68  * 03 29 2011 terry.wu
69  * [WCXRP00000610] [MT 6620 Wi-Fi][Driver] Fix klocwork waring
70  * [MT6620 Wi-Fi][Driver] Fix klocwork warning. Add Null pointer check on wext_get_essid. Limit the upper bound of essid storage array.
71  *
72  * 03 21 2011 cp.wu
73  * [WCXRP00000540] [MT5931][Driver] Add eHPI8/eHPI16 support to Linux Glue Layer
74  * improve portability for awareness of early version of linux kernel and wireless extension.
75  *
76  * 03 17 2011 chinglan.wang
77  * [WCXRP00000570] [MT6620 Wi-Fi][Driver] Add Wi-Fi Protected Setup v2.0 feature
78  * .
79  *
80  * 03 07 2011 terry.wu
81  * [WCXRP00000521] [MT6620 Wi-Fi][Driver] Remove non-standard debug message
82  * Toggle non-standard debug messages to comments.
83  *
84  * 02 21 2011 wh.su
85  * [WCXRP00000483] [MT6620 Wi-Fi][Driver] Check the kalIoctl return value before doing the memory copy at linux get essid
86  * fixed the potential error to do a larget memory copy while wlanoid get essid not actually running.
87  *
88  * 02 08 2011 george.huang
89  * [WCXRP00000422] [MT6620 Wi-Fi][Driver] support query power mode OID handler
90  * Support querying power mode OID.
91  *
92  * 01 29 2011 wh.su
93  * [WCXRP00000408] [MT6620 Wi-Fi][Driver] Not doing memory alloc while ioctl set ie with length 0
94  * not doing mem alloc. while set ie length already 0
95  *
96  * 01 20 2011 eddie.chen
97  * [WCXRP00000374] [MT6620 Wi-Fi][DRV] SW debug control
98  * Remove debug text.
99  *
100  * 01 20 2011 eddie.chen
101  * [WCXRP00000374] [MT6620 Wi-Fi][DRV] SW debug control
102  * Adjust OID order.
103  *
104  * 01 20 2011 eddie.chen
105  * [WCXRP00000374] [MT6620 Wi-Fi][DRV] SW debug control
106  * Add Oid for sw control debug command
107  *
108  * 01 11 2011 chinglan.wang
109  * NULL
110  * Modify to reslove the CR :[ALPS00028994] Use WEP security to connect Marvell 11N AP.  Connection establish successfully.
111  * Use the WPS function to connect AP, the privacy bit always is set to 1. .
112  *
113  * 01 07 2011 cm.chang
114  * [WCXRP00000336] [MT6620 Wi-Fi][Driver] Add test mode commands in normal phone operation
115  * Add a new compiling option to control if MCR read/write is permitted
116  *
117  * 01 04 2011 cp.wu
118  * [WCXRP00000338] [MT6620 Wi-Fi][Driver] Separate kalMemAlloc into kmalloc and vmalloc implementations to ease physically continous memory demands
119  * separate kalMemAlloc() into virtually-continous and physically-continous types
120  * to ease slab system pressure
121  *
122  * 01 04 2011 cp.wu
123  * [WCXRP00000338] [MT6620 Wi-Fi][Driver] Separate kalMemAlloc into kmalloc and vmalloc implementations to ease physically continous memory demands
124  * separate kalMemAlloc() into virtually-continous and physically-continous type to ease slab system pressure
125  *
126  * 12 31 2010 cm.chang
127  * [WCXRP00000336] [MT6620 Wi-Fi][Driver] Add test mode commands in normal phone operation
128  * Add some iwpriv commands to support test mode operation
129  *
130  * 12 15 2010 george.huang
131  * [WCXRP00000152] [MT6620 Wi-Fi] AP mode power saving function
132  * Support set PS profile and set WMM-PS related iwpriv.
133  *
134  * 12 15 2010 george.huang
135  * [WCXRP00000152] [MT6620 Wi-Fi] AP mode power saving function
136  * Allow change PS profile function (throught wext_set_power()).
137  *
138  * 12 14 2010 jeffrey.chang
139  * [WCXRP00000262] [MT6620 Wi-Fi][Driver] modify the scan request ioctl to handle hidden SSID
140  * handle hidden SSID
141  *
142  * 12 13 2010 chinglan.wang
143  * NULL
144  * Add WPS 1.0 feature flag to enable the WPS 1.0 function.
145  *
146  * 12 07 2010 cm.chang
147  * [WCXRP00000238] MT6620 Wi-Fi][Driver][FW] Support regulation domain setting from NVRAM and supplicant
148  * Fix compiling error
149  *
150  * 12 07 2010 cm.chang
151  * [WCXRP00000238] MT6620 Wi-Fi][Driver][FW] Support regulation domain setting from NVRAM and supplicant
152  * 1. Country code is from NVRAM or supplicant
153  * 2. Change band definition in CMD/EVENT.
154  *
155  * 11 30 2010 cp.wu
156  * [WCXRP00000213] [MT6620 Wi-Fi][Driver] Implement scanning with specified SSID for wpa_supplicant with ap_scan=1
157  * .
158  *
159  * 11 08 2010 wh.su
160  * [WCXRP00000171] [MT6620 Wi-Fi][Driver] Add message check code same behavior as mt5921
161  * add the message check code from mt5921.
162  *
163  * 10 19 2010 jeffrey.chang
164  * [WCXRP00000121] [MT6620 Wi-Fi][Driver] Temporarily disable set power mode ioctl which may cause 6620 to enter power saving
165  * Temporarily disable set power mode ioctl which may cause MT6620 to enter power saving
166  *
167  * 10 18 2010 jeffrey.chang
168  * [WCXRP00000116] [MT6620 Wi-Fi][Driver] Refine the set_scan ioctl to resolve the Android UI hanging issue
169  * refine the scan ioctl to prevent hanging of Android UI
170  *
171  * 10 01 2010 wh.su
172  * [WCXRP00000067] [MT6620 Wi-Fi][Driver] Support the android+ WAPI function
173  * add the scan result with wapi ie.
174  *
175  * 09 30 2010 wh.su
176  * [WCXRP00000072] [MT6620 Wi-Fi][Driver] Fix TKIP Counter Measure EAPoL callback register issue
177  * fixed the wapi ie assigned issue.
178  *
179  * 09 27 2010 wh.su
180  * NULL
181  * [WCXRP00000067][MT6620 Wi-Fi][Driver] Support the android+ WAPI function.
182  *
183  * 09 21 2010 kevin.huang
184  * [WCXRP00000052] [MT6620 Wi-Fi][Driver] Eliminate Linux Compile Warning
185  * Eliminate Linux Compile Warning
186  *
187  * 09 09 2010 cp.wu
188  * NULL
189  * add WPS/WPA/RSN IE for Wi-Fi Direct scanning result.
190  *
191  * 09 06 2010 cp.wu
192  * NULL
193  * Androi/Linux: return current operating channel information
194  *
195  * 09 01 2010 wh.su
196  * NULL
197  * adding the wapi support for integration test.
198  *
199  * 08 02 2010 jeffrey.chang
200  * NULL
201  * enable remove key ioctl
202  *
203  * 08 02 2010 jeffrey.chang
204  * NULL
205  * 1) modify tx service thread to avoid busy looping
206  * 2) add spin lock declartion for linux build
207  *
208  * 07 28 2010 jeffrey.chang
209  * NULL
210  * 1) enable encyption ioctls
211  * 2) temporarily disable remove keys ioctl to prevent  TX1 busy
212  *
213  * 07 28 2010 jeffrey.chang
214  * NULL
215  * 1) remove unused spinlocks
216  * 2) enable encyption ioctls
217  * 3) fix scan ioctl which may cause supplicant to hang
218  *
219  * 07 19 2010 jeffrey.chang
220  *
221  * add kal api for scanning done
222  *
223  * 07 19 2010 jeffrey.chang
224  *
225  * for linux driver migration
226  *
227  * 07 19 2010 jeffrey.chang
228  *
229  * Linux port modification
230  *
231  * 07 08 2010 cp.wu
232  *
233  * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository.
234  *
235  * 06 06 2010 kevin.huang
236  * [WPD00003832][MT6620 5931] Create driver base
237  * [MT6620 5931] Create driver base
238  *
239  * 05 28 2010 jeffrey.chang
240  * [WPD00003826]Initial import for Linux port
241  * remove unused macro and debug messages
242  *
243  * 05 14 2010 jeffrey.chang
244  * [WPD00003826]Initial import for Linux port
245  * Add dissassoication support for wpa supplicant
246  *
247  * 04 22 2010 jeffrey.chang
248  * [WPD00003826]Initial import for Linux port
249  *
250  * 1) modify rx path code for supporting Wi-Fi direct
251  * 2) modify config.h since Linux dont need to consider retaining packet
252  *
253  * 04 21 2010 jeffrey.chang
254  * [WPD00003826]Initial import for Linux port
255  * add for private ioctl support
256  *
257  * 04 19 2010 jeffrey.chang
258  * [WPD00003826]Initial import for Linux port
259  * Add ioctl of power management
260  *
261  * 04 19 2010 jeffrey.chang
262  * [WPD00003826]Initial import for Linux port
263  * remove debug message
264  *
265  * 04 14 2010 jeffrey.chang
266  * [WPD00003826]Initial import for Linux port
267  * 1) prGlueInfo->pvInformationBuffer and prGlueInfo->u4InformationBufferLength are no longer used
268  *  * 2) fix ioctl
269  *
270  * 04 12 2010 jeffrey.chang
271  * [WPD00003826]Initial import for Linux port
272  * remove debug messages for pre-release
273  *
274  * 04 07 2010 cp.wu
275  * [WPD00001943]Create WiFi test driver framework on WinXP
276  * rWlanInfo should be placed at adapter rather than glue due to most operations
277  *  *  *  *  *  *  *  * are done in adapter layer.
278  *
279  * 04 02 2010 jeffrey.chang
280  * [WPD00003826]Initial import for Linux port
281  * fix ioctl type
282  *
283  * 04 01 2010 jeffrey.chang
284  * [WPD00003826]Initial import for Linux port
285  * enable pmksa cache operation
286  *
287  * 03 31 2010 jeffrey.chang
288  * [WPD00003826]Initial import for Linux port
289  * fix ioctl which may cause cmdinfo memory leak
290  *
291  * 03 31 2010 wh.su
292  * [WPD00003816][MT6620 Wi-Fi] Adding the security support
293  * modify the wapi related code for new driver's design.
294  *
295  * 03 30 2010 jeffrey.chang
296  * [WPD00003826]Initial import for Linux port
297  * emulate NDIS Pending OID facility
298  *
299  * 03 24 2010 jeffrey.chang
300  * [WPD00003826]Initial import for Linux port
301  * initial import for Linux port
302 **  \main\maintrunk.MT5921\38 2009-10-08 10:33:22 GMT mtk01090
303 **  Avoid accessing private data of net_device directly. Replace with netdev_priv(). Add more checking for input parameters and pointers.
304 **  \main\maintrunk.MT5921\37 2009-09-29 16:49:48 GMT mtk01090
305 **  Remove unused variables
306 **  \main\maintrunk.MT5921\36 2009-09-28 20:19:11 GMT mtk01090
307 **  Add private ioctl to carry OID structures. Restructure public/private ioctl interfaces to Linux kernel.
308 **  \main\maintrunk.MT5921\35 2009-09-03 11:42:30 GMT mtk01088
309 **  adding the wapi ioctl support
310 **  \main\maintrunk.MT5921\34 2009-08-18 22:56:50 GMT mtk01090
311 **  Add Linux SDIO (with mmc core) support.
312 **  Add Linux 2.6.21, 2.6.25, 2.6.26.
313 **  Fix compile warning in Linux.
314 **  \main\maintrunk.MT5921\33 2009-05-14 22:43:47 GMT mtk01089
315 **  fix compiling warning
316 **  \main\maintrunk.MT5921\32 2009-05-07 22:26:18 GMT mtk01089
317 **  Add mandatory and private IO control for Linux BWCS
318 **  \main\maintrunk.MT5921\31 2009-02-07 15:11:14 GMT mtk01088
319 **  fixed the compiling error
320 **  \main\maintrunk.MT5921\30 2009-02-07 14:46:51 GMT mtk01088
321 **  add the privacy setting from linux supplicant ap selection
322 **  \main\maintrunk.MT5921\29 2008-11-19 15:18:50 GMT mtk01088
323 **  fixed the compling error
324 **  \main\maintrunk.MT5921\28 2008-11-19 11:56:18 GMT mtk01088
325 **  rename some variable with pre-fix to avoid the misunderstanding
326 **  \main\maintrunk.MT5921\27 2008-08-29 16:59:43 GMT mtk01088
327 **  fixed compiling error
328 **  \main\maintrunk.MT5921\26 2008-08-29 14:55:53 GMT mtk01088
329 **  adjust the code for meet the coding style, and add assert check
330 **  \main\maintrunk.MT5921\25 2008-06-02 11:15:19 GMT mtk01461
331 **  Update after wlanoidSetPowerMode changed
332 **  \main\maintrunk.MT5921\24 2008-05-30 15:13:12 GMT mtk01084
333 **  rename wlanoid
334 **  \main\maintrunk.MT5921\23 2008-03-28 10:40:28 GMT mtk01461
335 **  Add set desired rate in Linux STD IOCTL
336 **  \main\maintrunk.MT5921\22 2008-03-18 10:31:24 GMT mtk01088
337 **  add pmkid ioctl and indicate
338 **  \main\maintrunk.MT5921\21 2008-03-11 15:21:24 GMT mtk01461
339 **  \main\maintrunk.MT5921\20 2008-03-11 14:50:55 GMT mtk01461
340 **  Refine WPS related priv ioctl for unified interface
341 **
342 **  \main\maintrunk.MT5921\19 2008-03-06 16:30:41 GMT mtk01088
343 **  move the configuration code from set essid function,
344 **  remove the non-used code
345 **  \main\maintrunk.MT5921\18 2008-02-21 15:47:09 GMT mtk01461
346 **  Fix CR[489]
347 **  \main\maintrunk.MT5921\17 2008-02-12 23:38:31 GMT mtk01461
348 **  Add Set Frequency & Channel oid support for Linux
349 **  \main\maintrunk.MT5921\16 2008-01-24 12:07:34 GMT mtk01461
350 **  \main\maintrunk.MT5921\15 2008-01-24 12:00:10 GMT mtk01461
351 **  Modify the wext_essid for set up correct information for IBSS, and fix the wrong input ptr for prAdapter
352 **  \main\maintrunk.MT5921\14 2007-12-06 09:30:12 GMT mtk01425
353 **  1. Branch Test
354 **  \main\maintrunk.MT5921\13 2007-12-04 18:07:59 GMT mtk01461
355 **  fix typo
356 **  \main\maintrunk.MT5921\12 2007-11-30 17:10:21 GMT mtk01425
357 **  1. Fix compiling erros
358 **
359 **  \main\maintrunk.MT5921\11 2007-11-27 10:43:22 GMT mtk01425
360 **  1. Add WMM-PS setting
361 **  \main\maintrunk.MT5921\10 2007-11-06 20:33:32 GMT mtk01088
362 **  fixed the compiler error
363 **  \main\maintrunk.MT5921\9 2007-11-06 19:33:15 GMT mtk01088
364 **  add WPS code
365 **  \main\maintrunk.MT5921\8 2007-10-30 12:00:44 GMT MTK01425
366 **  1. Update wlanQueryInformation
367 */
368
369 /*******************************************************************************
370 *                         C O M P I L E R   F L A G S
371 ********************************************************************************
372 */
373
374 /*******************************************************************************
375 *                    E X T E R N A L   R E F E R E N C E S
376 ********************************************************************************
377 */
378
379 #include "gl_os.h"
380
381 #include "config.h"
382 #include "wlan_oid.h"
383
384 #include "gl_wext.h"
385 #include "gl_wext_priv.h"
386
387 #include "precomp.h"
388
389 #if CFG_SUPPORT_WAPI
390 #include "gl_sec.h"
391 #endif
392
393 /* compatibility to wireless extensions */
394 #ifdef WIRELESS_EXT
395
396 /*******************************************************************************
397 *                              C O N S T A N T S
398 ********************************************************************************
399 */
400 const long channel_freq[] = {
401         2412, 2417, 2422, 2427, 2432, 2437, 2442,
402         2447, 2452, 2457, 2462, 2467, 2472, 2484
403 };
404
405 #define     MAP_CHANNEL_ID_TO_KHZ(ch, khz)  {               \
406                 switch (ch)                                 \
407                 {                                           \
408                     case 1:     khz = 2412000;   break;     \
409                     case 2:     khz = 2417000;   break;     \
410                     case 3:     khz = 2422000;   break;     \
411                     case 4:     khz = 2427000;   break;     \
412                     case 5:     khz = 2432000;   break;     \
413                     case 6:     khz = 2437000;   break;     \
414                     case 7:     khz = 2442000;   break;     \
415                     case 8:     khz = 2447000;   break;     \
416                     case 9:     khz = 2452000;   break;     \
417                     case 10:    khz = 2457000;   break;     \
418                     case 11:    khz = 2462000;   break;     \
419                     case 12:    khz = 2467000;   break;     \
420                     case 13:    khz = 2472000;   break;     \
421                     case 14:    khz = 2484000;   break;     \
422                     case 36:  /* UNII */  khz = 5180000;   break;     \
423                     case 40:  /* UNII */  khz = 5200000;   break;     \
424                     case 44:  /* UNII */  khz = 5220000;   break;     \
425                     case 48:  /* UNII */  khz = 5240000;   break;     \
426                     case 52:  /* UNII */  khz = 5260000;   break;     \
427                     case 56:  /* UNII */  khz = 5280000;   break;     \
428                     case 60:  /* UNII */  khz = 5300000;   break;     \
429                     case 64:  /* UNII */  khz = 5320000;   break;     \
430                     case 149: /* UNII */  khz = 5745000;   break;     \
431                     case 153: /* UNII */  khz = 5765000;   break;     \
432                     case 157: /* UNII */  khz = 5785000;   break;     \
433                     case 161: /* UNII */  khz = 5805000;   break;     \
434                     case 165: /* UNII */  khz = 5825000;   break;     \
435                     case 100: /* HiperLAN2 */  khz = 5500000;   break;     \
436                     case 104: /* HiperLAN2 */  khz = 5520000;   break;     \
437                     case 108: /* HiperLAN2 */  khz = 5540000;   break;     \
438                     case 112: /* HiperLAN2 */  khz = 5560000;   break;     \
439                     case 116: /* HiperLAN2 */  khz = 5580000;   break;     \
440                     case 120: /* HiperLAN2 */  khz = 5600000;   break;     \
441                     case 124: /* HiperLAN2 */  khz = 5620000;   break;     \
442                     case 128: /* HiperLAN2 */  khz = 5640000;   break;     \
443                     case 132: /* HiperLAN2 */  khz = 5660000;   break;     \
444                     case 136: /* HiperLAN2 */  khz = 5680000;   break;     \
445                     case 140: /* HiperLAN2 */  khz = 5700000;   break;     \
446                     case 34:  /* Japan MMAC */   khz = 5170000;   break;   \
447                     case 38:  /* Japan MMAC */   khz = 5190000;   break;   \
448                     case 42:  /* Japan MMAC */   khz = 5210000;   break;   \
449                     case 46:  /* Japan MMAC */   khz = 5230000;   break;   \
450                     case 184: /* Japan */   khz = 4920000;   break;   \
451                     case 188: /* Japan */   khz = 4940000;   break;   \
452                     case 192: /* Japan */   khz = 4960000;   break;   \
453                     case 196: /* Japan */   khz = 4980000;   break;   \
454                     case 208: /* Japan, means J08 */   khz = 5040000;   break;   \
455                     case 212: /* Japan, means J12 */   khz = 5060000;   break;   \
456                     case 216: /* Japan, means J16 */   khz = 5080000;   break;   \
457                     default:    khz = 2412000;   break;     \
458                 }                                           \
459             }
460
461
462 #define NUM_CHANNELS (sizeof(channel_freq) / sizeof(channel_freq[0]))
463
464 #define MAX_SSID_LEN    32
465
466
467 /*******************************************************************************
468 *                             D A T A   T Y P E S
469 ********************************************************************************
470 */
471
472 /*******************************************************************************
473 *                            P U B L I C   D A T A
474 ********************************************************************************
475 */
476 /* NOTE: name in iwpriv_args only have 16 bytes */
477 static const struct iw_priv_args rIwPrivTable[] = {
478     {IOCTL_SET_INT,             IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0,   ""},
479     {IOCTL_GET_INT,             0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,   ""},
480     {IOCTL_SET_INT,             IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 3, 0,   ""},
481     {IOCTL_GET_INT,             0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 3,   ""},
482     {IOCTL_SET_INT,             IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 2, 0,   ""},
483
484     {IOCTL_GET_INT,             IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 2, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,   ""},
485     {IOCTL_GET_INT,             IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,   ""},
486
487     {IOCTL_SET_INTS,            IW_PRIV_TYPE_INT | 4, 0,                        ""},
488     {IOCTL_GET_INT,             0, IW_PRIV_TYPE_INT | 50,                       ""},
489     {IOCTL_GET_INT,             0, IW_PRIV_TYPE_CHAR | 16,                      ""},
490
491     /* added for set_oid and get_oid */
492     {IOCTL_SET_STRUCT,          256,                                    0, ""},
493     {IOCTL_GET_STRUCT,          0,                                      256, ""},
494
495     /* sub-ioctl definitions */
496 #if 0
497     {PRIV_CMD_REG_DOMAIN,       IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0,   "set_reg_domain" },
498     {PRIV_CMD_REG_DOMAIN,       0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,   "get_reg_domain" },
499 #endif
500
501 #if CFG_TCP_IP_CHKSUM_OFFLOAD
502     {PRIV_CMD_CSUM_OFFLOAD,     IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0,   "set_tcp_csum" },
503 #endif /* CFG_TCP_IP_CHKSUM_OFFLOAD */
504
505     {PRIV_CMD_POWER_MODE,       IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0,   "set_power_mode" },
506     {PRIV_CMD_POWER_MODE,       0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,   "get_power_mode" },
507
508     {PRIV_CMD_WMM_PS,           IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 3, 0,   "set_wmm_ps" },
509
510     {PRIV_CMD_TEST_MODE,        IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0,   "set_test_mode" },
511     {PRIV_CMD_TEST_CMD,         IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 2, 0,   "set_test_cmd" },
512     {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" },
513 #if CFG_SUPPORT_PRIV_MCR_RW
514     {PRIV_CMD_ACCESS_MCR,       IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 2, 0,   "set_mcr" },
515     {PRIV_CMD_ACCESS_MCR,       IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,   "get_mcr" },
516 #endif
517     {PRIV_CMD_SW_CTRL,          IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 2, 0,   "set_sw_ctrl" },
518     {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" },
519
520 #if CFG_SUPPORT_BCM && CFG_SUPPORT_BCM_BWCS
521     {PRIV_CUSTOM_BWCS_CMD,              IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "set_bwcs"},
522     /* GET STRUCT sub-ioctls commands */
523     {PRIV_CUSTOM_BWCS_CMD,              IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "get_bwcs"},
524 #endif
525
526     /* SET STRUCT sub-ioctls commands */
527     {PRIV_CMD_OID,              256, 0, "set_oid"},
528     /* GET STRUCT sub-ioctls commands */
529     {PRIV_CMD_OID,              0, 256, "get_oid"},
530
531     {PRIV_CMD_BAND_CONFIG,      IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0,   "set_band" },
532     {PRIV_CMD_BAND_CONFIG,      0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,   "get_band" },
533
534     {PRIV_CMD_SET_TX_POWER,     IW_PRIV_TYPE_INT | 4, 0,                        "set_txpower" },
535     {PRIV_CMD_GET_CH_LIST,      0, IW_PRIV_TYPE_INT | 50,                       "get_ch_list" },
536     {PRIV_CMD_DUMP_MEM,         IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 2, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,   "get_mem" },
537
538 #if CFG_ENABLE_WIFI_DIRECT
539     {PRIV_CMD_P2P_MODE,         IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 2, 0,   "set_p2p_mode" },
540 #endif
541     {PRIV_CMD_GET_BUILD_DATE_CODE,      0, IW_PRIV_TYPE_CHAR | 16,              "get_date_code" },
542 };
543
544 static const iw_handler rIwPrivHandler[] = {
545     [IOCTL_SET_INT - SIOCIWFIRSTPRIV] = priv_set_int,
546     [IOCTL_GET_INT - SIOCIWFIRSTPRIV] = priv_get_int,
547     [IOCTL_SET_ADDRESS - SIOCIWFIRSTPRIV] = NULL,
548     [IOCTL_GET_ADDRESS - SIOCIWFIRSTPRIV] = NULL,
549     [IOCTL_SET_STR - SIOCIWFIRSTPRIV] = NULL,
550     [IOCTL_GET_STR - SIOCIWFIRSTPRIV] = NULL,
551     [IOCTL_SET_KEY - SIOCIWFIRSTPRIV] = NULL,
552     [IOCTL_GET_KEY - SIOCIWFIRSTPRIV] = NULL,
553     [IOCTL_SET_STRUCT - SIOCIWFIRSTPRIV] = priv_set_struct,
554     [IOCTL_GET_STRUCT - SIOCIWFIRSTPRIV] = priv_get_struct,
555     [IOCTL_SET_STRUCT_FOR_EM - SIOCIWFIRSTPRIV] = priv_set_struct,
556     [IOCTL_SET_INTS - SIOCIWFIRSTPRIV] = priv_set_ints,
557     [IOCTL_GET_INTS - SIOCIWFIRSTPRIV] = priv_get_ints,
558 };
559
560 const struct iw_handler_def wext_handler_def = {
561     .num_standard   = 0,
562     .num_private = (__u16)sizeof(rIwPrivHandler)/sizeof(iw_handler),
563     .num_private_args = (__u16)sizeof(rIwPrivTable)/sizeof(struct iw_priv_args),
564     .standard   = (iw_handler *) NULL,
565     .private = rIwPrivHandler,
566     .private_args = rIwPrivTable,
567     .get_wireless_stats = wext_get_wireless_stats,
568 };
569
570 /*******************************************************************************
571 *                           P R I V A T E   D A T A
572 ********************************************************************************
573 */
574
575 /*******************************************************************************
576 *                                 M A C R O S
577 ********************************************************************************
578 */
579
580 /*******************************************************************************
581 *                  F U N C T I O N   D E C L A R A T I O N S
582 ********************************************************************************
583 */
584
585 /*******************************************************************************
586 *                              F U N C T I O N S
587 ********************************************************************************
588 */
589
590 /*----------------------------------------------------------------------------*/
591 /*!
592 * \brief Find the desired WPA/RSN Information Element according to desiredElemID.
593 *
594 * \param[in] pucIEStart IE starting address.
595 * \param[in] i4TotalIeLen Total length of all the IE.
596 * \param[in] ucDesiredElemId Desired element ID.
597 * \param[out] ppucDesiredIE Pointer to the desired IE.
598 *
599 * \retval TRUE Find the desired IE.
600 * \retval FALSE Desired IE not found.
601 *
602 * \note
603 */
604 /*----------------------------------------------------------------------------*/
605 BOOLEAN
606 wextSrchDesiredWPAIE (
607     IN  PUINT_8         pucIEStart,
608     IN  INT_32          i4TotalIeLen,
609     IN  UINT_8          ucDesiredElemId,
610     OUT PUINT_8         *ppucDesiredIE
611     )
612 {
613     INT_32 i4InfoElemLen;
614
615     ASSERT(pucIEStart);
616     ASSERT(ppucDesiredIE);
617
618     while (i4TotalIeLen >= 2) {
619         i4InfoElemLen = (INT_32) pucIEStart[1] + 2;
620
621         if (pucIEStart[0] == ucDesiredElemId && i4InfoElemLen <= i4TotalIeLen) {
622             if (ucDesiredElemId != 0xDD) {
623                 /* Non 0xDD, OK! */
624                 *ppucDesiredIE = &pucIEStart[0];
625                 return TRUE;
626             }
627             else {
628                 /* EID == 0xDD, check WPA IE */
629                 if (pucIEStart[1] >= 4) {
630                     if (memcmp(&pucIEStart[2], "\x00\x50\xf2\x01", 4) == 0) {
631                         *ppucDesiredIE = &pucIEStart[0];
632                         return TRUE;
633                     }
634                 } /* check WPA IE length */
635             } /* check EID == 0xDD */
636         } /* check desired EID */
637
638         /* Select next information element. */
639         i4TotalIeLen -= i4InfoElemLen;
640         pucIEStart += i4InfoElemLen;
641     }
642
643     return FALSE;
644 } /* parseSearchDesiredWPAIE */
645
646
647 #if CFG_SUPPORT_WAPI
648 /*----------------------------------------------------------------------------*/
649 /*!
650 * \brief Find the desired WAPI Information Element .
651 *
652 * \param[in] pucIEStart IE starting address.
653 * \param[in] i4TotalIeLen Total length of all the IE.
654 * \param[out] ppucDesiredIE Pointer to the desired IE.
655 *
656 * \retval TRUE Find the desired IE.
657 * \retval FALSE Desired IE not found.
658 *
659 * \note
660 */
661 /*----------------------------------------------------------------------------*/
662 BOOLEAN
663 wextSrchDesiredWAPIIE (
664     IN  PUINT_8         pucIEStart,
665     IN  INT_32          i4TotalIeLen,
666     OUT PUINT_8         *ppucDesiredIE
667     )
668 {
669     INT_32 i4InfoElemLen;
670
671     ASSERT(pucIEStart);
672     ASSERT(ppucDesiredIE);
673
674     while (i4TotalIeLen >= 2) {
675         i4InfoElemLen = (INT_32) pucIEStart[1] + 2;
676
677         if (pucIEStart[0] == ELEM_ID_WAPI && i4InfoElemLen <= i4TotalIeLen) {
678             *ppucDesiredIE = &pucIEStart[0];
679             return TRUE;
680         } /* check desired EID */
681
682         /* Select next information element. */
683         i4TotalIeLen -= i4InfoElemLen;
684         pucIEStart += i4InfoElemLen;
685     }
686
687     return FALSE;
688 } /* wextSrchDesiredWAPIIE */
689 #endif
690
691
692 #if CFG_SUPPORT_WPS
693 /*----------------------------------------------------------------------------*/
694 /*!
695 * \brief Find the desired WPS Information Element according to desiredElemID.
696 *
697 * \param[in] pucIEStart IE starting address.
698 * \param[in] i4TotalIeLen Total length of all the IE.
699 * \param[in] ucDesiredElemId Desired element ID.
700 * \param[out] ppucDesiredIE Pointer to the desired IE.
701 *
702 * \retval TRUE Find the desired IE.
703 * \retval FALSE Desired IE not found.
704 *
705 * \note
706 */
707 /*----------------------------------------------------------------------------*/
708 BOOLEAN
709 wextSrchDesiredWPSIE (
710     IN PUINT_8 pucIEStart,
711     IN INT_32 i4TotalIeLen,
712     IN UINT_8 ucDesiredElemId,
713     OUT PUINT_8 *ppucDesiredIE)
714 {
715     INT_32 i4InfoElemLen;
716
717     ASSERT(pucIEStart);
718     ASSERT(ppucDesiredIE);
719
720     while (i4TotalIeLen >= 2) {
721         i4InfoElemLen = (INT_32) pucIEStart[1] + 2;
722
723         if (pucIEStart[0] == ucDesiredElemId && i4InfoElemLen <= i4TotalIeLen) {
724             if (ucDesiredElemId != 0xDD) {
725                 /* Non 0xDD, OK! */
726                 *ppucDesiredIE = &pucIEStart[0];
727                 return TRUE;
728             }
729             else {
730                 /* EID == 0xDD, check WPS IE */
731                 if (pucIEStart[1] >= 4) {
732                     if (memcmp(&pucIEStart[2], "\x00\x50\xf2\x04", 4) == 0) {
733                         *ppucDesiredIE = &pucIEStart[0];
734                         return TRUE;
735                     }
736                 } /* check WPS IE length */
737             } /* check EID == 0xDD */
738         } /* check desired EID */
739
740         /* Select next information element. */
741         i4TotalIeLen -= i4InfoElemLen;
742         pucIEStart += i4InfoElemLen;
743     }
744
745     return FALSE;
746 } /* parseSearchDesiredWPSIE */
747 #endif
748
749
750 /*----------------------------------------------------------------------------*/
751 /*!
752 * \brief Get the name of the protocol used on the air.
753 *
754 * \param[in]  prDev Net device requested.
755 * \param[in]  prIwrInfo NULL.
756 * \param[out] pcName Buffer to store protocol name string
757 * \param[in]  pcExtra NULL.
758 *
759 * \retval 0 For success.
760 *
761 * \note If netif_carrier_ok, protocol name is returned;
762 *       otherwise, "disconnected" is returned.
763 */
764 /*----------------------------------------------------------------------------*/
765 static int
766 wext_get_name (
767     IN struct net_device *prNetDev,
768     IN struct iw_request_info *prIwrInfo,
769     OUT char *pcName,
770     IN char *pcExtra
771     )
772 {
773     ENUM_PARAM_NETWORK_TYPE_T  eNetWorkType;
774
775     P_GLUE_INFO_T prGlueInfo = NULL;
776     WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS;
777     UINT_32 u4BufLen = 0;
778
779     ASSERT(prNetDev);
780     ASSERT(pcName);
781     if (FALSE == GLUE_CHK_PR2(prNetDev, pcName)) {
782         return -EINVAL;
783     }
784     prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev));
785
786     if (netif_carrier_ok(prNetDev)) {
787
788         rStatus = kalIoctl(prGlueInfo,
789             wlanoidQueryNetworkTypeInUse,
790             &eNetWorkType,
791             sizeof(eNetWorkType),
792             TRUE,
793             FALSE,
794             FALSE,
795             FALSE,
796             &u4BufLen);
797
798         switch(eNetWorkType) {
799         case PARAM_NETWORK_TYPE_DS:
800             strcpy(pcName, "IEEE 802.11b");
801             break;
802         case PARAM_NETWORK_TYPE_OFDM24:
803             strcpy(pcName, "IEEE 802.11bgn");
804             break;
805         case PARAM_NETWORK_TYPE_AUTOMODE:
806         case PARAM_NETWORK_TYPE_OFDM5:
807             strcpy(pcName, "IEEE 802.11abgn");
808             break;
809         case PARAM_NETWORK_TYPE_FH:
810         default:
811             strcpy(pcName, "IEEE 802.11");
812             break;
813         }
814     }
815     else {
816         strcpy(pcName, "Disconnected");
817     }
818
819     return 0;
820 } /* wext_get_name */
821
822 /*----------------------------------------------------------------------------*/
823 /*!
824 * \brief To set the operating channel in the wireless device.
825 *
826 * \param[in] prDev Net device requested.
827 * \param[in] prIwrInfo NULL
828 * \param[in] prFreq Buffer to store frequency information
829 * \param[in] pcExtra NULL
830 *
831 * \retval 0 For success.
832 * \retval -EOPNOTSUPP If infrastructure mode is not NET NET_TYPE_IBSS.
833 * \retval -EINVAL Invalid channel frequency.
834 *
835 * \note If infrastructure mode is IBSS, new channel frequency is set to device.
836 *      The range of channel number depends on different regulatory domain.
837 */
838 /*----------------------------------------------------------------------------*/
839 static int
840 wext_set_freq (
841     IN struct net_device *prNetDev,
842     IN struct iw_request_info *prIwReqInfo,
843     IN struct iw_freq *prIwFreq,
844     IN char *pcExtra
845     )
846 {
847
848 #if 0
849     UINT_32 u4ChnlFreq; /* Store channel or frequency information */
850
851     P_GLUE_INFO_T prGlueInfo = NULL;
852     WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS;
853     UINT_32 u4BufLen = 0;
854
855     ASSERT(prNetDev);
856     ASSERT(prIwFreq);
857     if (FALSE == GLUE_CHK_PR2(prNetDev, prIwFreq)) {
858         return -EINVAL;
859     }
860     prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev));
861
862     /*
863     printk("set m:%d, e:%d, i:%d, flags:%d\n",
864         prIwFreq->m, prIwFreq->e, prIwFreq->i, prIwFreq->flags);
865     */
866
867     /* If setting by frequency, convert to a channel */
868     if ((prIwFreq->e == 1) &&
869         (prIwFreq->m >= (int) 2.412e8) &&
870         (prIwFreq->m <= (int) 2.484e8)) {
871
872         /* Change to KHz format */
873         u4ChnlFreq = (UINT_32)(prIwFreq->m / (KILO / 10));
874
875         rStatus = kalIoctl(prGlueInfo,
876                            wlanoidSetFrequency,
877                            &u4ChnlFreq,
878                            sizeof(u4ChnlFreq),
879                            FALSE,
880                            FALSE,
881                            FALSE,
882                            &u4BufLen);
883
884         if (WLAN_STATUS_SUCCESS != rStatus) {
885             return -EINVAL;
886         }
887     }
888     /* Setting by channel number */
889     else if ((prIwFreq->m > KILO) || (prIwFreq->e > 0)) {
890         return -EOPNOTSUPP;
891     }
892     else {
893         /* Change to channel number format */
894         u4ChnlFreq = (UINT_32)prIwFreq->m;
895
896         rStatus = kalIoctl(prGlueInfo,
897                            wlanoidSetChannel,
898                            &u4ChnlFreq,
899                            sizeof(u4ChnlFreq),
900                            FALSE,
901                            FALSE,
902                            FALSE,
903                            &u4BufLen);
904
905
906
907
908         if (WLAN_STATUS_SUCCESS != rStatus) {
909             return -EINVAL;
910         }
911     }
912
913 #endif
914
915     return 0;
916
917 } /* wext_set_freq */
918
919
920 /*----------------------------------------------------------------------------*/
921 /*!
922 * \brief To get the operating channel in the wireless device.
923 *
924 * \param[in] prDev Net device requested.
925 * \param[in] prIwrInfo NULL.
926 * \param[out] prFreq Buffer to store frequency information.
927 * \param[in] pcExtra NULL.
928 *
929 * \retval 0 If netif_carrier_ok.
930 * \retval -ENOTCONN Otherwise
931 *
932 * \note If netif_carrier_ok, channel frequency information is stored in pFreq.
933 */
934 /*----------------------------------------------------------------------------*/
935 static int
936 wext_get_freq (
937     IN struct net_device *prNetDev,
938     IN struct iw_request_info *prIwrInfo,
939     OUT struct iw_freq *prIwFreq,
940     IN char *pcExtra
941     )
942 {
943     UINT_32 u4Channel = 0;
944
945
946     P_GLUE_INFO_T prGlueInfo = NULL;
947     WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS;
948     UINT_32 u4BufLen = 0;
949
950     ASSERT(prNetDev);
951     ASSERT(prIwFreq);
952     if (FALSE == GLUE_CHK_PR2(prNetDev, prIwFreq)) {
953         return -EINVAL;
954     }
955     prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev));
956
957     /* GeorgeKuo: TODO skip checking in IBSS mode */
958     if (!netif_carrier_ok(prNetDev)) {
959         return -ENOTCONN;
960     }
961
962     rStatus = kalIoctl(prGlueInfo,
963          wlanoidQueryFrequency,
964          &u4Channel,
965          sizeof(u4Channel),
966          TRUE,
967          FALSE,
968          FALSE,
969          FALSE,
970          &u4BufLen);
971
972     prIwFreq->m = (int) u4Channel; /* freq in KHz */
973     prIwFreq->e = 3;
974
975     return 0;
976
977 } /* wext_get_freq */
978
979
980 /*----------------------------------------------------------------------------*/
981 /*!
982 * \brief To set operating mode.
983 *
984 * \param[in] prDev Net device requested.
985 * \param[in] prIwrInfo NULL.
986 * \param[in] pu4Mode Pointer to new operation mode.
987 * \param[in] pcExtra NULL.
988 *
989 * \retval 0 For success.
990 * \retval -EOPNOTSUPP If new mode is not supported.
991 *
992 * \note Device will run in new operation mode if it is valid.
993 */
994 /*----------------------------------------------------------------------------*/
995 static int
996 wext_set_mode (
997     IN struct net_device *prNetDev,
998     IN struct iw_request_info *prIwReqInfo,
999     IN unsigned int *pu4Mode,
1000     IN char *pcExtra
1001     )
1002 {
1003     ENUM_PARAM_OP_MODE_T eOpMode;
1004
1005     P_GLUE_INFO_T prGlueInfo = NULL;
1006     WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS;
1007     UINT_32 u4BufLen = 0;
1008
1009     ASSERT(prNetDev);
1010     ASSERT(pu4Mode);
1011     if (FALSE == GLUE_CHK_PR2(prNetDev, pu4Mode)) {
1012         return -EINVAL;
1013     }
1014     prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev));
1015
1016     switch (*pu4Mode) {
1017     case IW_MODE_AUTO:
1018         eOpMode = NET_TYPE_AUTO_SWITCH;
1019         break;
1020
1021     case IW_MODE_ADHOC:
1022         eOpMode = NET_TYPE_IBSS;
1023         break;
1024
1025     case IW_MODE_INFRA:
1026         eOpMode = NET_TYPE_INFRA;
1027         break;
1028
1029     default:
1030         DBGLOG(INIT, INFO, ("%s(): Set UNSUPPORTED Mode = %d.\n", __FUNCTION__, *pu4Mode));
1031         return -EOPNOTSUPP;
1032     }
1033
1034     //printk("%s(): Set Mode = %d\n", __FUNCTION__, *pu4Mode);
1035
1036     rStatus = kalIoctl(prGlueInfo,
1037         wlanoidSetInfrastructureMode,
1038         &eOpMode,
1039         sizeof(eOpMode),
1040         FALSE,
1041         FALSE,
1042         TRUE,
1043         FALSE,
1044         &u4BufLen);
1045
1046
1047     /* after set operation mode, key table are cleared */
1048
1049     /* reset wpa info */
1050     prGlueInfo->rWpaInfo.u4WpaVersion = IW_AUTH_WPA_VERSION_DISABLED;
1051     prGlueInfo->rWpaInfo.u4KeyMgmt = 0;
1052     prGlueInfo->rWpaInfo.u4CipherGroup = IW_AUTH_CIPHER_NONE;
1053     prGlueInfo->rWpaInfo.u4CipherPairwise = IW_AUTH_CIPHER_NONE;
1054     prGlueInfo->rWpaInfo.u4AuthAlg = IW_AUTH_ALG_OPEN_SYSTEM;
1055 #if CFG_SUPPORT_802_11W
1056     prGlueInfo->rWpaInfo.u4Mfp = IW_AUTH_MFP_DISABLED;
1057 #endif
1058
1059     return 0;
1060 } /* wext_set_mode */
1061
1062 /*----------------------------------------------------------------------------*/
1063 /*!
1064 * \brief To get operating mode.
1065 *
1066 * \param[in] prNetDev Net device requested.
1067 * \param[in] prIwReqInfo NULL.
1068 * \param[out] pu4Mode Buffer to store operating mode information.
1069 * \param[in] pcExtra NULL.
1070 *
1071 * \retval 0 If data is valid.
1072 * \retval -EINVAL Otherwise.
1073 *
1074 * \note If netif_carrier_ok, operating mode information is stored in pu4Mode.
1075 */
1076 /*----------------------------------------------------------------------------*/
1077 static int
1078 wext_get_mode (
1079     IN struct net_device *prNetDev,
1080     IN struct iw_request_info *prIwReqInfo,
1081     OUT unsigned int *pu4Mode,
1082     IN char *pcExtra
1083     )
1084 {
1085     ENUM_PARAM_OP_MODE_T eOpMode;
1086
1087     P_GLUE_INFO_T prGlueInfo = NULL;
1088     WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS;
1089     UINT_32 u4BufLen = 0;
1090
1091     ASSERT(prNetDev);
1092     ASSERT(pu4Mode);
1093     if (FALSE == GLUE_CHK_PR2(prNetDev, pu4Mode)) {
1094         return -EINVAL;
1095     }
1096     prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev));
1097
1098     rStatus = kalIoctl(prGlueInfo,
1099          wlanoidQueryInfrastructureMode,
1100          &eOpMode,
1101          sizeof(eOpMode),
1102          TRUE,
1103          FALSE,
1104          FALSE,
1105          FALSE,
1106          &u4BufLen);
1107
1108
1109
1110     switch (eOpMode){
1111     case NET_TYPE_IBSS:
1112         *pu4Mode = IW_MODE_ADHOC;
1113         break;
1114
1115     case NET_TYPE_INFRA:
1116         *pu4Mode = IW_MODE_INFRA;
1117         break;
1118
1119     case NET_TYPE_AUTO_SWITCH:
1120         *pu4Mode = IW_MODE_AUTO;
1121         break;
1122
1123     default:
1124         DBGLOG(INIT, INFO, ("%s(): Get UNKNOWN Mode.\n", __FUNCTION__));
1125         return -EINVAL;
1126     }
1127
1128     return 0;
1129 } /* wext_get_mode */
1130
1131 /*----------------------------------------------------------------------------*/
1132 /*!
1133 * \brief To get the valid range for each configurable STA setting value.
1134 *
1135 * \param[in] prDev Net device requested.
1136 * \param[in] prIwrInfo NULL.
1137 * \param[in] prData Pointer to iw_point structure, not used.
1138 * \param[out] pcExtra Pointer to buffer which is allocated by caller of this
1139 *                     function, wext_support_ioctl() or ioctl_standard_call() in
1140 *                     wireless.c.
1141 *
1142 * \retval 0 If data is valid.
1143 *
1144 * \note The extra buffer (pcExtra) is filled with information from driver.
1145 */
1146 /*----------------------------------------------------------------------------*/
1147 static int
1148 wext_get_range (
1149     IN struct net_device *prNetDev,
1150     IN struct iw_request_info *prIwrInfo,
1151     IN struct iw_point *prData,
1152     OUT char *pcExtra
1153     )
1154 {
1155     struct iw_range *prRange = NULL;
1156     PARAM_RATES_EX aucSuppRate = {0}; /* data buffers */
1157     int i = 0;
1158
1159     P_GLUE_INFO_T prGlueInfo = NULL;
1160     WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS;
1161     UINT_32 u4BufLen = 0;
1162
1163     ASSERT(prNetDev);
1164     ASSERT(pcExtra);
1165     if (FALSE == GLUE_CHK_PR2(prNetDev, pcExtra)) {
1166         return -EINVAL;
1167     }
1168     prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev));
1169
1170     prRange = (struct iw_range *) pcExtra;
1171
1172     memset(prRange, 0, sizeof(*prRange));
1173     prRange->throughput = 20000000;  /* 20Mbps */
1174     prRange->min_nwid = 0;   /* not used */
1175     prRange->max_nwid = 0;   /* not used */
1176
1177     /* scan_capa not implemented */
1178
1179     /* event_capa[6]: kernel + driver capabilities */
1180     prRange->event_capa[0] = (IW_EVENT_CAPA_K_0
1181         | IW_EVENT_CAPA_MASK(SIOCGIWAP)
1182         | IW_EVENT_CAPA_MASK(SIOCGIWSCAN)
1183         /* can't display meaningful string in iwlist
1184         | IW_EVENT_CAPA_MASK(SIOCGIWTXPOW)
1185         | IW_EVENT_CAPA_MASK(IWEVMICHAELMICFAILURE)
1186         | IW_EVENT_CAPA_MASK(IWEVASSOCREQIE)
1187         | IW_EVENT_CAPA_MASK(IWEVPMKIDCAND)
1188         */
1189         );
1190     prRange->event_capa[1] = IW_EVENT_CAPA_K_1;
1191
1192     /* report 2.4G channel and frequency only */
1193     prRange->num_channels = (__u16) NUM_CHANNELS;
1194     prRange->num_frequency = (__u8) NUM_CHANNELS;
1195     for (i = 0; i < NUM_CHANNELS; i++) {
1196         /* iwlib takes this number as channel number */
1197         prRange->freq[i].i = i + 1;
1198         prRange->freq[i].m = channel_freq[i];
1199         prRange->freq[i].e = 6;  /* Values in table in MHz */
1200     }
1201
1202     rStatus = kalIoctl(
1203          prGlueInfo,
1204          wlanoidQuerySupportedRates,
1205          &aucSuppRate,
1206          sizeof(aucSuppRate),
1207          TRUE,
1208          FALSE,
1209          FALSE,
1210          FALSE,
1211          &u4BufLen);
1212
1213
1214
1215     for (i = 0; i < IW_MAX_BITRATES && i < PARAM_MAX_LEN_RATES_EX ; i++) {
1216         if (aucSuppRate[i] == 0) {
1217             break;
1218     }
1219         prRange->bitrate[i] = (aucSuppRate[i] & 0x7F) * 500000; /* 0.5Mbps */
1220     }
1221     prRange->num_bitrates = i;
1222
1223     prRange->min_rts = 0;
1224     prRange->max_rts = 2347;
1225     prRange->min_frag = 256;
1226     prRange->max_frag = 2346;
1227
1228     prRange->min_pmp = 0;    /* power management by driver */
1229     prRange->max_pmp = 0;    /* power management by driver */
1230     prRange->min_pmt = 0;    /* power management by driver */
1231     prRange->max_pmt = 0;    /* power management by driver */
1232     prRange->pmp_flags = IW_POWER_RELATIVE;    /* pm default flag */
1233     prRange->pmt_flags = IW_POWER_ON;    /* pm timeout flag */
1234     prRange->pm_capa = IW_POWER_ON;  /* power management by driver */
1235
1236     prRange->encoding_size[0] = 5;   /* wep40 */
1237     prRange->encoding_size[1] = 16;   /* tkip */
1238     prRange->encoding_size[2] = 16;   /* ckip */
1239     prRange->encoding_size[3] = 16;   /* ccmp */
1240     prRange->encoding_size[4] = 13;  /* wep104 */
1241     prRange->encoding_size[5] = 16;  /* wep128 */
1242     prRange->num_encoding_sizes = 6;
1243     prRange->max_encoding_tokens = 6;    /* token? */
1244
1245 #if WIRELESS_EXT < 17
1246     prRange->txpower_capa = 0x0002; /* IW_TXPOW_RELATIVE */
1247 #else
1248     prRange->txpower_capa = IW_TXPOW_RELATIVE;
1249 #endif
1250     prRange->num_txpower = 5;
1251     prRange->txpower[0] = 0; /* minimum */
1252     prRange->txpower[1] = 25; /* 25% */
1253     prRange->txpower[2] = 50;    /* 50% */
1254     prRange->txpower[3] = 100;    /* 100% */
1255
1256     prRange->we_version_compiled = WIRELESS_EXT;
1257     prRange->we_version_source = WIRELESS_EXT;
1258
1259     prRange->retry_capa = IW_RETRY_LIMIT;
1260     prRange->retry_flags = IW_RETRY_LIMIT;
1261     prRange->min_retry = 7;
1262     prRange->max_retry = 7;
1263     prRange->r_time_flags = IW_RETRY_ON;
1264     prRange->min_r_time = 0;
1265     prRange->max_r_time = 0;
1266
1267     /* signal strength and link quality */
1268     /* Just define range here, reporting value moved to wext_get_stats() */
1269     prRange->sensitivity = -83;  /* fixed value */
1270     prRange->max_qual.qual = 100;  /* max 100% */
1271     prRange->max_qual.level = (__u8)(0x100 - 0); /* max 0 dbm */
1272     prRange->max_qual.noise = (__u8)(0x100 - 0); /* max 0 dbm */
1273
1274     /* enc_capa */
1275 #if WIRELESS_EXT > 17
1276     prRange->enc_capa = IW_ENC_CAPA_WPA |
1277         IW_ENC_CAPA_WPA2 |
1278         IW_ENC_CAPA_CIPHER_TKIP |
1279         IW_ENC_CAPA_CIPHER_CCMP;
1280 #endif
1281
1282     /* min_pms; Minimal PM saving */
1283     /* max_pms; Maximal PM saving */
1284     /* pms_flags; How to decode max/min PM saving */
1285
1286     /* modul_capa; IW_MODUL_* bit field */
1287     /* bitrate_capa; Types of bitrates supported */
1288
1289     return 0;
1290 } /* wext_get_range */
1291
1292
1293 /*----------------------------------------------------------------------------*/
1294 /*!
1295 * \brief To set BSSID of AP to connect.
1296 *
1297 * \param[in] prDev Net device requested.
1298 * \param[in] prIwrInfo NULL.
1299 * \param[in] prAddr Pointer to struct sockaddr structure containing AP's BSSID.
1300 * \param[in] pcExtra NULL.
1301 *
1302 * \retval 0 For success.
1303 *
1304 * \note Desired AP's BSSID is set to driver.
1305 */
1306 /*----------------------------------------------------------------------------*/
1307 static int
1308 wext_set_ap (
1309     IN struct net_device *prDev,
1310     IN struct iw_request_info *prIwrInfo,
1311     IN struct sockaddr *prAddr,
1312     IN char *pcExtra
1313     )
1314 {
1315     return 0;
1316 } /* wext_set_ap */
1317
1318
1319 /*----------------------------------------------------------------------------*/
1320 /*!
1321 * \brief To get AP MAC address.
1322 *
1323 * \param[in] prDev Net device requested.
1324 * \param[in] prIwrInfo NULL.
1325 * \param[out] prAddr Pointer to struct sockaddr structure storing AP's BSSID.
1326 * \param[in] pcExtra NULL.
1327 *
1328 * \retval 0 If netif_carrier_ok.
1329 * \retval -ENOTCONN Otherwise.
1330 *
1331 * \note If netif_carrier_ok, AP's mac address is stored in pAddr->sa_data.
1332 */
1333 /*----------------------------------------------------------------------------*/
1334 static int
1335 wext_get_ap (
1336     IN struct net_device *prNetDev,
1337     IN struct iw_request_info *prIwrInfo,
1338     OUT struct sockaddr *prAddr,
1339     IN char *pcExtra
1340     )
1341 {
1342     P_GLUE_INFO_T prGlueInfo = NULL;
1343     WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS;
1344     UINT_32 u4BufLen = 0;
1345
1346     ASSERT(prNetDev);
1347     ASSERT(prAddr);
1348     if (FALSE == GLUE_CHK_PR2(prNetDev, prAddr)) {
1349         return -EINVAL;
1350     }
1351     prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev));
1352
1353     //if (!netif_carrier_ok(prNetDev)) {
1354     //    return -ENOTCONN;
1355     //}
1356
1357     if(prGlueInfo->eParamMediaStateIndicated == PARAM_MEDIA_STATE_DISCONNECTED){
1358         memset(prAddr, 0, 6);
1359         return 0;
1360     }
1361
1362     rStatus = kalIoctl(prGlueInfo,
1363         wlanoidQueryBssid,
1364         prAddr->sa_data,
1365         ETH_ALEN,
1366         TRUE,
1367         FALSE,
1368         FALSE,
1369         FALSE,
1370         &u4BufLen);
1371
1372     return 0;
1373 } /* wext_get_ap */
1374
1375 /*----------------------------------------------------------------------------*/
1376 /*!
1377 * \brief To set mlme operation request.
1378 *
1379 * \param[in] prDev Net device requested.
1380 * \param[in] prIwrInfo NULL.
1381 * \param[in] prData Pointer of iw_point header.
1382 * \param[in] pcExtra Pointer to iw_mlme structure mlme request information.
1383 *
1384 * \retval 0 For success.
1385 * \retval -EOPNOTSUPP unsupported IW_MLME_ command.
1386 * \retval -EINVAL Set MLME Fail, different bssid.
1387 *
1388 * \note Driver will start mlme operation if valid.
1389 */
1390 /*----------------------------------------------------------------------------*/
1391 static int
1392 wext_set_mlme (
1393     IN struct net_device *prNetDev,
1394     IN struct iw_request_info *prIwrInfo,
1395     IN struct iw_point *prData,
1396     IN char *pcExtra
1397     )
1398 {
1399     struct iw_mlme *prMlme = NULL;
1400
1401
1402     P_GLUE_INFO_T prGlueInfo = NULL;
1403     WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS;
1404     UINT_32 u4BufLen = 0;
1405
1406     ASSERT(prNetDev);
1407     ASSERT(pcExtra);
1408     if (FALSE == GLUE_CHK_PR2(prNetDev, pcExtra)) {
1409         return -EINVAL;
1410     }
1411     prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev));
1412
1413     prMlme = (struct iw_mlme *)pcExtra;
1414     if (prMlme->cmd == IW_MLME_DEAUTH || prMlme->cmd == IW_MLME_DISASSOC) {
1415         if (!netif_carrier_ok(prNetDev)) {
1416             DBGLOG(INIT, INFO, ("[wifi] Set MLME Deauth/Disassoc, but netif_carrier_off\n"));
1417             return 0;
1418         }
1419
1420         rStatus = kalIoctl(prGlueInfo,
1421             wlanoidSetDisassociate,
1422             NULL,
1423             0,
1424             FALSE,
1425             FALSE,
1426             TRUE,
1427             FALSE,
1428             &u4BufLen);
1429         return 0;
1430     }
1431     else {
1432         DBGLOG(INIT, INFO, ("[wifi] unsupported IW_MLME_ command :%d\n", prMlme->cmd));
1433         return -EOPNOTSUPP;
1434     }
1435 } /* wext_set_mlme */
1436
1437 /*----------------------------------------------------------------------------*/
1438 /*!
1439 * \brief To issue scan request.
1440 *
1441 * \param[in] prDev Net device requested.
1442 * \param[in] prIwrInfo NULL.
1443 * \param[in] prData NULL.
1444 * \param[in] pcExtra NULL.
1445 *
1446 * \retval 0 For success.
1447 * \retval -EFAULT Tx power is off.
1448 *
1449 * \note Device will start scanning.
1450 */
1451 /*----------------------------------------------------------------------------*/
1452 static int
1453 wext_set_scan (
1454     IN struct net_device *prNetDev,
1455     IN struct iw_request_info *prIwrInfo,
1456     IN union iwreq_data *prData,
1457     IN char *pcExtra
1458     )
1459 {
1460     P_GLUE_INFO_T prGlueInfo = NULL;
1461     WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS;
1462     UINT_32 u4BufLen = 0;
1463     int essid_len = 0;
1464
1465     ASSERT(prNetDev);
1466     if (FALSE == GLUE_CHK_DEV(prNetDev)) {
1467         return -EINVAL;
1468     }
1469     prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev));
1470
1471 #if WIRELESS_EXT > 17
1472     /* retrieve SSID */
1473     if(prData) {
1474         essid_len = ((struct iw_scan_req *)(((struct iw_point*)prData)->pointer))->essid_len;
1475     }
1476 #endif
1477
1478     init_completion(&prGlueInfo->rScanComp);
1479
1480     // TODO:  parse flags and issue different scan requests?
1481
1482     rStatus = kalIoctl(prGlueInfo,
1483         wlanoidSetBssidListScan,
1484         pcExtra,
1485         essid_len,
1486         FALSE,
1487         FALSE,
1488         FALSE,
1489         FALSE,
1490         &u4BufLen);
1491
1492     //wait_for_completion_interruptible_timeout(&prGlueInfo->rScanComp, 2 * KAL_HZ);
1493     //kalIndicateStatusAndComplete(prGlueInfo, WLAN_STATUS_SCAN_COMPLETE, NULL, 0);
1494
1495
1496     return 0;
1497 } /* wext_set_scan */
1498
1499
1500 /*----------------------------------------------------------------------------*/
1501 /*!
1502 * \brief To write the ie to buffer
1503 *
1504 */
1505 /*----------------------------------------------------------------------------*/
1506 static inline int snprintf_hex(char *buf, size_t buf_size, const u8 *data,
1507                     size_t len)
1508 {
1509     size_t i;
1510     char *pos = buf, *end = buf + buf_size;
1511     int ret;
1512
1513     if (buf_size == 0)
1514         return 0;
1515
1516     for (i = 0; i < len; i++) {
1517         ret = snprintf(pos, end - pos, "%02x",
1518                   data[i]);
1519         if (ret < 0 || ret >= end - pos) {
1520             end[-1] = '\0';
1521             return pos - buf;
1522         }
1523         pos += ret;
1524     }
1525     end[-1] = '\0';
1526     return pos - buf;
1527 }
1528
1529
1530 /*----------------------------------------------------------------------------*/
1531 /*!
1532 * \brief To get scan results, transform results from driver's format to WE's.
1533 *
1534 * \param[in] prDev Net device requested.
1535 * \param[in] prIwrInfo NULL.
1536 * \param[out] prData Pointer to iw_point structure, pData->length is the size of
1537 *               pcExtra buffer before used, and is updated after filling scan
1538 *               results.
1539 * \param[out] pcExtra Pointer to buffer which is allocated by caller of this
1540 *                     function, wext_support_ioctl() or ioctl_standard_call() in
1541 *                     wireless.c.
1542 *
1543 * \retval 0 For success.
1544 * \retval -ENOMEM If dynamic memory allocation fail.
1545 * \retval -E2BIG Invalid length.
1546 *
1547 * \note Scan results is filled into pcExtra buffer, data size is updated in
1548 *       pData->length.
1549 */
1550 /*----------------------------------------------------------------------------*/
1551 static int
1552 wext_get_scan (
1553     IN struct net_device *prNetDev,
1554     IN struct iw_request_info *prIwrInfo,
1555     IN OUT struct iw_point *prData,
1556     IN char *pcExtra
1557     )
1558 {
1559     UINT_32 i = 0;
1560     UINT_32 j = 0;
1561     P_PARAM_BSSID_LIST_EX_T prList = NULL;
1562     P_PARAM_BSSID_EX_T prBss = NULL;
1563     P_PARAM_VARIABLE_IE_T prDesiredIE = NULL;
1564     struct iw_event iwEvent;    /* local iw_event buffer */
1565
1566     /* write pointer of extra buffer */
1567     char *pcCur = NULL;
1568     /* pointer to the end of  last full entry in extra buffer */
1569     char *pcValidEntryEnd = NULL;
1570     char *pcEnd = NULL; /* end of extra buffer */
1571
1572     UINT_32 u4AllocBufLen = 0;
1573
1574     /* arrange rate information */
1575     UINT_32 u4HighestRate = 0;
1576     char aucRatesBuf[64];
1577     UINT_32 u4BufIndex;
1578
1579     /* return value */
1580     int ret = 0;
1581
1582     P_GLUE_INFO_T prGlueInfo = NULL;
1583     WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS;
1584     UINT_32 u4BufLen = 0;
1585
1586     ASSERT(prNetDev);
1587     ASSERT(prData);
1588     ASSERT(pcExtra);
1589     if (FALSE == GLUE_CHK_PR3(prNetDev, prData, pcExtra)) {
1590         return -EINVAL;
1591     }
1592     prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev));
1593
1594     /* Initialize local variables */
1595     pcCur = pcExtra;
1596     pcValidEntryEnd = pcExtra;
1597     pcEnd = pcExtra + prData->length; /* end of extra buffer */
1598
1599     /* Allocate another query buffer with the same size of extra buffer */
1600     u4AllocBufLen = prData->length;
1601     prList = kalMemAlloc(u4AllocBufLen, VIR_MEM_TYPE);
1602     if (prList == NULL) {
1603         DBGLOG(INIT, INFO, ("[wifi] no memory for scan list:%d\n", prData->length));
1604         ret = -ENOMEM;
1605         goto error;
1606     }
1607     prList->u4NumberOfItems = 0;
1608
1609     /* wait scan done */
1610     //printk ("wait for scan results\n");
1611     //wait_for_completion_interruptible_timeout(&prGlueInfo->rScanComp, 4 * KAL_HZ);
1612
1613     rStatus = kalIoctl(prGlueInfo,
1614         wlanoidQueryBssidList,
1615         prList,
1616         u4AllocBufLen,
1617         TRUE,
1618         FALSE,
1619         FALSE,
1620         FALSE,
1621         &u4BufLen);
1622
1623     if (rStatus == WLAN_STATUS_INVALID_LENGTH) {
1624         /* Buffer length is not large enough. */
1625         //printk(KERN_INFO "[wifi] buf:%d result:%ld\n", pData->length, u4BufLen);
1626
1627 #if WIRELESS_EXT >= 17
1628         /* This feature is supported in WE-17 or above, limited by iwlist.
1629         ** Return -E2BIG and iwlist will request again with a larger buffer.
1630         */
1631         ret = -E2BIG;
1632         /* Update length to give application a hint on result length */
1633         prData->length = (__u16)u4BufLen;
1634         goto error;
1635 #else
1636         /* Realloc a larger query buffer here, but don't write too much to extra
1637         ** buffer when filling it later.
1638         */
1639         kalMemFree(prList, VIR_MEM_TYPE, u4AllocBufLen);
1640
1641         u4AllocBufLen = u4BufLen;
1642         prList = kalMemAlloc(u4AllocBufLen, VIR_MEM_TYPE);
1643         if (prList == NULL) {
1644             DBGLOG(INIT, INFO, ("[wifi] no memory for larger scan list :%ld\n", u4BufLen));
1645             ret = -ENOMEM;
1646             goto error;
1647         }
1648         prList->NumberOfItems = 0;
1649
1650         rStatus = kalIoctl(prGlueInfo,
1651             wlanoidQueryBssidList,
1652             prList,
1653             u4AllocBufLen,
1654             TRUE,
1655             FALSE,
1656             FALSE,
1657             FALSE,
1658             &u4BufLen);
1659
1660         if (rStatus == WLAN_STATUS_INVALID_LENGTH) {
1661             DBGLOG(INIT, INFO, ("[wifi] larger buf:%d result:%ld\n", u4AllocBufLen, u4BufLen));
1662             ret = -E2BIG;
1663             prData->length = (__u16)u4BufLen;
1664             goto error;
1665         }
1666 #endif /* WIRELESS_EXT >= 17 */
1667
1668     }
1669
1670
1671     if (prList->u4NumberOfItems > CFG_MAX_NUM_BSS_LIST) {
1672         DBGLOG(INIT, INFO, ("[wifi] strange scan result count:%ld\n",
1673             prList->u4NumberOfItems));
1674         goto error;
1675     }
1676
1677     /* Copy required data from pList to pcExtra */
1678     prBss = &prList->arBssid[0];    /* set to the first entry */
1679     for (i = 0; i < prList->u4NumberOfItems; ++i) {
1680         /* BSSID */
1681         iwEvent.cmd = SIOCGIWAP;
1682         iwEvent.len = IW_EV_ADDR_LEN;
1683         if ((pcCur + iwEvent.len) > pcEnd)
1684             break;
1685         iwEvent.u.ap_addr.sa_family = ARPHRD_ETHER;
1686         memcpy(iwEvent.u.ap_addr.sa_data, prBss->arMacAddress, ETH_ALEN);
1687         memcpy(pcCur, &iwEvent, IW_EV_ADDR_LEN);
1688         pcCur += IW_EV_ADDR_LEN;
1689
1690         /* SSID */
1691         iwEvent.cmd = SIOCGIWESSID;
1692         /* Modification to user space pointer(essid.pointer) is not needed. */
1693         iwEvent.u.essid.length = (__u16)prBss->rSsid.u4SsidLen;
1694         iwEvent.len = IW_EV_POINT_LEN + iwEvent.u.essid.length;
1695
1696         if ((pcCur + iwEvent.len) > pcEnd)
1697             break;
1698         iwEvent.u.essid.flags = 1;
1699         iwEvent.u.essid.pointer = NULL;
1700
1701 #if WIRELESS_EXT <= 18
1702         memcpy(pcCur, &iwEvent, iwEvent.len);
1703 #else
1704         memcpy(pcCur, &iwEvent, IW_EV_LCP_LEN);
1705         memcpy(pcCur + IW_EV_LCP_LEN,
1706             &iwEvent.u.data.length,
1707             sizeof(struct  iw_point) - IW_EV_POINT_OFF);
1708 #endif
1709         memcpy(pcCur + IW_EV_POINT_LEN, prBss->rSsid.aucSsid, iwEvent.u.essid.length);
1710         pcCur += iwEvent.len;
1711         /* Frequency */
1712         iwEvent.cmd = SIOCGIWFREQ;
1713         iwEvent.len = IW_EV_FREQ_LEN;
1714         if ((pcCur + iwEvent.len) > pcEnd)
1715             break;
1716         iwEvent.u.freq.m = prBss->rConfiguration.u4DSConfig;
1717         iwEvent.u.freq.e = 3;   /* (in KHz) */
1718         iwEvent.u.freq.i = 0;
1719         memcpy(pcCur, &iwEvent, IW_EV_FREQ_LEN);
1720         pcCur += IW_EV_FREQ_LEN;
1721
1722         /* Operation Mode */
1723         iwEvent.cmd = SIOCGIWMODE;
1724         iwEvent.len = IW_EV_UINT_LEN;
1725         if ((pcCur + iwEvent.len) > pcEnd)
1726             break;
1727         if (prBss->eOpMode == NET_TYPE_IBSS) {
1728             iwEvent.u.mode = IW_MODE_ADHOC;
1729         }
1730         else if (prBss->eOpMode == NET_TYPE_INFRA) {
1731             iwEvent.u.mode = IW_MODE_INFRA;
1732         }
1733         else {
1734             iwEvent.u.mode = IW_MODE_AUTO;
1735         }
1736         memcpy(pcCur, &iwEvent, IW_EV_UINT_LEN);
1737         pcCur += IW_EV_UINT_LEN;
1738
1739         /* Quality */
1740         iwEvent.cmd = IWEVQUAL;
1741         iwEvent.len = IW_EV_QUAL_LEN;
1742         if ((pcCur + iwEvent.len) > pcEnd)
1743             break;
1744         iwEvent.u.qual.qual = 0; /* Quality not available now */
1745         /* -100 < Rssi < -10, normalized by adding 0x100 */
1746         iwEvent.u.qual.level = 0x100 + prBss->rRssi;
1747         iwEvent.u.qual.noise = 0; /* Noise not available now */
1748         iwEvent.u.qual.updated = IW_QUAL_QUAL_INVALID | IW_QUAL_LEVEL_UPDATED \
1749             | IW_QUAL_NOISE_INVALID;
1750         memcpy(pcCur, &iwEvent, IW_EV_QUAL_LEN);
1751         pcCur += IW_EV_QUAL_LEN;
1752
1753         /* Security Mode*/
1754         iwEvent.cmd = SIOCGIWENCODE;
1755         iwEvent.len = IW_EV_POINT_LEN;
1756         if ((pcCur + iwEvent.len) > pcEnd)
1757             break;
1758         iwEvent.u.data.pointer = NULL;
1759         iwEvent.u.data.flags = 0;
1760         iwEvent.u.data.length = 0;
1761         if(!prBss->u4Privacy) {
1762             iwEvent.u.data.flags |=  IW_ENCODE_DISABLED;
1763         }
1764 #if WIRELESS_EXT <= 18
1765         memcpy(pcCur, &iwEvent, IW_EV_POINT_LEN);
1766 #else
1767         memcpy(pcCur, &iwEvent, IW_EV_LCP_LEN);
1768         memcpy(pcCur + IW_EV_LCP_LEN,
1769             &iwEvent.u.data.length,
1770             sizeof(struct  iw_point) - IW_EV_POINT_OFF);
1771 #endif
1772         pcCur += IW_EV_POINT_LEN;
1773
1774         /* rearrange rate information */
1775         u4BufIndex = sprintf(aucRatesBuf, "Rates (Mb/s):");
1776         u4HighestRate = 0;
1777         for (j = 0; j < PARAM_MAX_LEN_RATES_EX; ++j) {
1778             UINT_8 curRate = prBss->rSupportedRates[j] & 0x7F;
1779             if (curRate == 0) {
1780                 break;
1781             }
1782
1783             if (curRate > u4HighestRate) {
1784                 u4HighestRate = curRate;
1785             }
1786
1787             if (curRate == RATE_5_5M) {
1788                 u4BufIndex += sprintf(aucRatesBuf + u4BufIndex, " 5.5");
1789             }
1790             else {
1791                 u4BufIndex += sprintf(aucRatesBuf + u4BufIndex, " %d", curRate / 2);
1792             }
1793     #if DBG
1794             if (u4BufIndex > sizeof(aucRatesBuf)) {
1795                 //printk("rate info too long\n");
1796                 break;
1797             }
1798     #endif
1799         }
1800         /* Report Highest Rates */
1801         iwEvent.cmd = SIOCGIWRATE;
1802         iwEvent.len = IW_EV_PARAM_LEN;
1803         if ((pcCur + iwEvent.len) > pcEnd)
1804             break;
1805         iwEvent.u.bitrate.value = u4HighestRate * 500000;
1806         iwEvent.u.bitrate.fixed = 0;
1807         iwEvent.u.bitrate.disabled = 0;
1808         iwEvent.u.bitrate.flags = 0;
1809         memcpy(pcCur, &iwEvent, iwEvent.len);
1810         pcCur += iwEvent.len;
1811
1812     #if WIRELESS_EXT >= 15  /* IWEVCUSTOM is available in WE-15 or above */
1813         /* Report Residual Rates */
1814         iwEvent.cmd = IWEVCUSTOM;
1815         iwEvent.u.data.length = u4BufIndex;
1816         iwEvent.len = IW_EV_POINT_LEN + iwEvent.u.data.length;
1817         if ((pcCur + iwEvent.len) > pcEnd)
1818             break;
1819         iwEvent.u.data.flags = 0;
1820      #if WIRELESS_EXT <= 18
1821         memcpy(pcCur, &iwEvent, IW_EV_POINT_LEN);
1822      #else
1823         memcpy(pcCur, &iwEvent, IW_EV_LCP_LEN);
1824         memcpy(pcCur + IW_EV_LCP_LEN,
1825             &iwEvent.u.data.length,
1826             sizeof(struct  iw_point) - IW_EV_POINT_OFF);
1827      #endif
1828         memcpy(pcCur + IW_EV_POINT_LEN, aucRatesBuf, u4BufIndex);
1829         pcCur += iwEvent.len;
1830     #endif /* WIRELESS_EXT >= 15 */
1831
1832
1833     if (wextSrchDesiredWPAIE(&prBss->aucIEs[sizeof(PARAM_FIXED_IEs)],
1834              prBss->u4IELength - sizeof(PARAM_FIXED_IEs),
1835              0xDD,
1836              (PUINT_8 *)&prDesiredIE)) {
1837             iwEvent.cmd = IWEVGENIE;
1838             iwEvent.u.data.flags = 1;
1839             iwEvent.u.data.length = 2 + (__u16)prDesiredIE->ucLength;
1840             iwEvent.len = IW_EV_POINT_LEN + iwEvent.u.data.length;
1841             if ((pcCur + iwEvent.len) > pcEnd)
1842                 break;
1843 #if WIRELESS_EXT <= 18
1844             memcpy(pcCur, &iwEvent, IW_EV_POINT_LEN);
1845 #else
1846             memcpy(pcCur, &iwEvent, IW_EV_LCP_LEN);
1847             memcpy(pcCur + IW_EV_LCP_LEN,
1848                    &iwEvent.u.data.length,
1849                    sizeof(struct  iw_point) - IW_EV_POINT_OFF);
1850 #endif
1851             memcpy(pcCur + IW_EV_POINT_LEN, prDesiredIE, 2 + prDesiredIE->ucLength);
1852             pcCur += iwEvent.len;
1853     }
1854
1855 #if CFG_SUPPORT_WPS  /* search WPS IE (0xDD, 221, OUI: 0x0050f204 ) */
1856     if (wextSrchDesiredWPSIE(&prBss->aucIEs[sizeof(PARAM_FIXED_IEs)],
1857               prBss->u4IELength - sizeof(PARAM_FIXED_IEs),
1858               0xDD,
1859               (PUINT_8 *)&prDesiredIE)) {
1860                 iwEvent.cmd = IWEVGENIE;
1861                 iwEvent.u.data.flags = 1;
1862                 iwEvent.u.data.length = 2 + (__u16)prDesiredIE->ucLength;
1863                 iwEvent.len = IW_EV_POINT_LEN + iwEvent.u.data.length;
1864             if ((pcCur + iwEvent.len) > pcEnd)
1865                 break;
1866 #if WIRELESS_EXT <= 18
1867             memcpy(pcCur, &iwEvent, IW_EV_POINT_LEN);
1868 #else
1869             memcpy(pcCur, &iwEvent, IW_EV_LCP_LEN);
1870             memcpy(pcCur + IW_EV_LCP_LEN,
1871                 &iwEvent.u.data.length,
1872                 sizeof(struct  iw_point) - IW_EV_POINT_OFF);
1873 #endif
1874                 memcpy(pcCur + IW_EV_POINT_LEN, prDesiredIE, 2 + prDesiredIE->ucLength);
1875                 pcCur += iwEvent.len;
1876             }
1877 #endif
1878
1879
1880         /* Search RSN IE (0x30, 48). pBss->IEs starts from timestamp. */
1881         /* pBss->IEs starts from timestamp */
1882         if (wextSrchDesiredWPAIE(&prBss->aucIEs[sizeof(PARAM_FIXED_IEs)],
1883                 prBss->u4IELength -sizeof(PARAM_FIXED_IEs),
1884                 0x30,
1885                 (PUINT_8 *)&prDesiredIE)) {
1886
1887                 iwEvent.cmd = IWEVGENIE;
1888                 iwEvent.u.data.flags = 1;
1889                 iwEvent.u.data.length = 2 + (__u16)prDesiredIE->ucLength;
1890                 iwEvent.len = IW_EV_POINT_LEN + iwEvent.u.data.length;
1891             if ((pcCur + iwEvent.len) > pcEnd)
1892                 break;
1893 #if WIRELESS_EXT <= 18
1894             memcpy(pcCur, &iwEvent, IW_EV_POINT_LEN);
1895 #else
1896             memcpy(pcCur, &iwEvent, IW_EV_LCP_LEN);
1897             memcpy(pcCur + IW_EV_LCP_LEN,
1898                 &iwEvent.u.data.length,
1899                 sizeof(struct  iw_point) - IW_EV_POINT_OFF);
1900 #endif
1901             memcpy(pcCur + IW_EV_POINT_LEN, prDesiredIE, 2 + prDesiredIE->ucLength);
1902             pcCur += iwEvent.len;
1903         }
1904
1905 #if CFG_SUPPORT_WAPI /* Android+ */
1906         if (wextSrchDesiredWAPIIE(&prBss->aucIEs[sizeof(PARAM_FIXED_IEs)],
1907                 prBss->u4IELength -sizeof(PARAM_FIXED_IEs),
1908                 (PUINT_8 *)&prDesiredIE)) {
1909
1910 #if 0
1911                 iwEvent.cmd = IWEVGENIE;
1912                 iwEvent.u.data.flags = 1;
1913                 iwEvent.u.data.length = 2 + (__u16)prDesiredIE->ucLength;
1914                 iwEvent.len = IW_EV_POINT_LEN + iwEvent.u.data.length;
1915             if ((pcCur + iwEvent.len) > pcEnd)
1916                 break;
1917 #if WIRELESS_EXT <= 18
1918             memcpy(pcCur, &iwEvent, IW_EV_POINT_LEN);
1919 #else
1920             memcpy(pcCur, &iwEvent, IW_EV_LCP_LEN);
1921             memcpy(pcCur + IW_EV_LCP_LEN,
1922                 &iwEvent.u.data.length,
1923                 sizeof(struct  iw_point) - IW_EV_POINT_OFF);
1924 #endif
1925             memcpy(pcCur + IW_EV_POINT_LEN, prDesiredIE, 2 + prDesiredIE->ucLength);
1926             pcCur += iwEvent.len;
1927 #else
1928            iwEvent.cmd = IWEVCUSTOM;
1929            iwEvent.u.data.length = (2 + prDesiredIE->ucLength) * 2 + 8 /* wapi_ie= */;
1930            iwEvent.len = IW_EV_POINT_LEN + iwEvent.u.data.length;
1931            if ((pcCur + iwEvent.len) > pcEnd)
1932                break;
1933            iwEvent.u.data.flags = 1;
1934
1935            memcpy(pcCur, &iwEvent, IW_EV_LCP_LEN);
1936            memcpy(pcCur + IW_EV_LCP_LEN,
1937                       &iwEvent.u.data.length,
1938                       sizeof(struct  iw_point) - IW_EV_POINT_OFF);
1939
1940            pcCur += (IW_EV_POINT_LEN);
1941
1942            pcCur += sprintf(pcCur, "wapi_ie=");
1943
1944            snprintf_hex(pcCur, pcEnd - pcCur, (UINT_8 *)prDesiredIE, prDesiredIE->ucLength + 2);
1945
1946            pcCur += (2 + prDesiredIE->ucLength) * 2 /* iwEvent.len */;
1947 #endif
1948         }
1949 #endif
1950         /* Complete an entry. Update end of valid entry */
1951         pcValidEntryEnd = pcCur;
1952         /* Extract next bss */
1953         prBss = (P_PARAM_BSSID_EX_T)((char *)prBss + prBss->u4Length);
1954     }
1955
1956     /* Update valid data length for caller function and upper layer
1957      * applications.
1958      */
1959     prData->length = (pcValidEntryEnd - pcExtra);
1960     //printk(KERN_INFO "[wifi] buf:%d result:%ld\n", pData->length, u4BufLen);
1961
1962     //kalIndicateStatusAndComplete(prGlueInfo, WLAN_STATUS_SCAN_COMPLETE, NULL, 0);
1963
1964 error:
1965     /* free local query buffer */
1966     if (prList) {
1967         kalMemFree(prList, VIR_MEM_TYPE, u4AllocBufLen);
1968     }
1969
1970     return ret;
1971 } /* wext_get_scan */
1972
1973 /*----------------------------------------------------------------------------*/
1974 /*!
1975 * \brief To set desired network name ESSID.
1976 *
1977 * \param[in] prDev Net device requested.
1978 * \param[in] prIwrInfo NULL.
1979 * \param[in] prEssid Pointer of iw_point header.
1980 * \param[in] pcExtra Pointer to buffer srtoring essid string.
1981 *
1982 * \retval 0 If netif_carrier_ok.
1983 * \retval -E2BIG Essid string length is too big.
1984 * \retval -EINVAL pcExtra is null pointer.
1985 * \retval -EFAULT Driver fail to set new essid.
1986 *
1987 * \note If string lengh is ok, device will try connecting to the new network.
1988 */
1989 /*----------------------------------------------------------------------------*/
1990 static int
1991 wext_set_essid (
1992     IN struct net_device *prNetDev,
1993     IN struct iw_request_info *prIwrInfo,
1994     IN struct iw_point *prEssid,
1995     IN char *pcExtra
1996     )
1997 {
1998     PARAM_SSID_T rNewSsid;
1999     UINT_32 cipher;
2000     ENUM_PARAM_ENCRYPTION_STATUS_T eEncStatus;
2001     ENUM_PARAM_AUTH_MODE_T eAuthMode;
2002
2003     P_GLUE_INFO_T prGlueInfo = NULL;
2004     WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS;
2005     UINT_32 u4BufLen = 0;
2006
2007     ASSERT(prNetDev);
2008     ASSERT(prEssid);
2009     ASSERT(pcExtra);
2010     if (FALSE == GLUE_CHK_PR3(prNetDev, prEssid, pcExtra)) {
2011         return -EINVAL;
2012     }
2013     prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev));
2014
2015     if (prEssid->length > IW_ESSID_MAX_SIZE) {
2016         return -E2BIG;
2017     }
2018
2019
2020     /* set auth mode */
2021     if (prGlueInfo->rWpaInfo.u4WpaVersion == IW_AUTH_WPA_VERSION_DISABLED) {
2022         eAuthMode = (prGlueInfo->rWpaInfo.u4AuthAlg == IW_AUTH_ALG_OPEN_SYSTEM) ?
2023             AUTH_MODE_OPEN : AUTH_MODE_AUTO_SWITCH;
2024         //printk(KERN_INFO "IW_AUTH_WPA_VERSION_DISABLED->Param_AuthMode%s\n",
2025         //    (eAuthMode == AUTH_MODE_OPEN) ? "Open" : "Shared");
2026     }
2027     else {
2028         /* set auth mode */
2029         switch(prGlueInfo->rWpaInfo.u4KeyMgmt) {
2030             case IW_AUTH_KEY_MGMT_802_1X:
2031                 eAuthMode =
2032                     (prGlueInfo->rWpaInfo.u4WpaVersion == IW_AUTH_WPA_VERSION_WPA) ?
2033                     AUTH_MODE_WPA : AUTH_MODE_WPA2;
2034                 //printk("IW_AUTH_KEY_MGMT_802_1X->AUTH_MODE_WPA%s\n",
2035                 //    (eAuthMode == AUTH_MODE_WPA) ? "" : "2");
2036                 break;
2037             case IW_AUTH_KEY_MGMT_PSK:
2038                 eAuthMode =
2039                     (prGlueInfo->rWpaInfo.u4WpaVersion == IW_AUTH_WPA_VERSION_WPA) ?
2040                     AUTH_MODE_WPA_PSK: AUTH_MODE_WPA2_PSK;
2041                 //printk("IW_AUTH_KEY_MGMT_PSK->AUTH_MODE_WPA%sPSK\n",
2042                 //    (eAuthMode == AUTH_MODE_WPA_PSK) ? "" : "2");
2043                 break;
2044 #if CFG_SUPPORT_WAPI /* Android+ */
2045             case IW_AUTH_KEY_MGMT_WAPI_PSK:
2046                 break;
2047             case IW_AUTH_KEY_MGMT_WAPI_CERT:
2048                 break;
2049 #endif
2050
2051 //#if defined (IW_AUTH_KEY_MGMT_WPA_NONE)
2052 //            case IW_AUTH_KEY_MGMT_WPA_NONE:
2053 //                eAuthMode = AUTH_MODE_WPA_NONE;
2054 //                //printk("IW_AUTH_KEY_MGMT_WPA_NONE->AUTH_MODE_WPA_NONE\n");
2055 //                break;
2056 //#endif
2057 #if CFG_SUPPORT_802_11W
2058             case IW_AUTH_KEY_MGMT_802_1X_SHA256:
2059                 eAuthMode = AUTH_MODE_WPA2;
2060                 break;
2061             case IW_AUTH_KEY_MGMT_PSK_SHA256:
2062                 eAuthMode = AUTH_MODE_WPA2_PSK;
2063                 break;
2064 #endif
2065             default:
2066                 //printk(KERN_INFO DRV_NAME"strange IW_AUTH_KEY_MGMT : %ld set auto switch\n",
2067                 //    prGlueInfo->rWpaInfo.u4KeyMgmt);
2068                 eAuthMode = AUTH_MODE_AUTO_SWITCH;
2069                 break;
2070         }
2071     }
2072
2073
2074     rStatus = kalIoctl(prGlueInfo,
2075             wlanoidSetAuthMode,
2076             &eAuthMode,
2077             sizeof(eAuthMode),
2078             FALSE,
2079             FALSE,
2080             FALSE,
2081             FALSE,
2082             &u4BufLen);
2083
2084     /* set encryption status */
2085     cipher = prGlueInfo->rWpaInfo.u4CipherGroup |
2086         prGlueInfo->rWpaInfo.u4CipherPairwise;
2087     if (cipher & IW_AUTH_CIPHER_CCMP) {
2088         //printk("IW_AUTH_CIPHER_CCMP->ENUM_ENCRYPTION3_ENABLED\n");
2089         eEncStatus = ENUM_ENCRYPTION3_ENABLED;
2090     }
2091     else if (cipher & IW_AUTH_CIPHER_TKIP) {
2092         //printk("IW_AUTH_CIPHER_TKIP->ENUM_ENCRYPTION2_ENABLED\n");
2093         eEncStatus = ENUM_ENCRYPTION2_ENABLED;
2094     }
2095     else if (cipher & (IW_AUTH_CIPHER_WEP104 | IW_AUTH_CIPHER_WEP40)) {
2096         //printk("IW_AUTH_CIPHER_WEPx->ENUM_ENCRYPTION1_ENABLED\n");
2097         eEncStatus = ENUM_ENCRYPTION1_ENABLED;
2098     }
2099     else if (cipher & IW_AUTH_CIPHER_NONE){
2100         //printk("IW_AUTH_CIPHER_NONE->ENUM_ENCRYPTION_DISABLED\n");
2101         if (prGlueInfo->rWpaInfo.fgPrivacyInvoke)
2102             eEncStatus = ENUM_ENCRYPTION1_ENABLED;
2103         else
2104             eEncStatus = ENUM_ENCRYPTION_DISABLED;
2105     }
2106     else {
2107         //printk("unknown IW_AUTH_CIPHER->Param_EncryptionDisabled\n");
2108         eEncStatus = ENUM_ENCRYPTION_DISABLED;
2109     }
2110
2111     rStatus = kalIoctl(prGlueInfo,
2112             wlanoidSetEncryptionStatus,
2113             &eEncStatus,
2114             sizeof(eEncStatus),
2115             FALSE,
2116             FALSE,
2117             FALSE,
2118             FALSE,
2119             &u4BufLen);
2120
2121 #if WIRELESS_EXT < 21
2122     /* GeorgeKuo: a length error bug exists in (WE < 21) cases, kernel before
2123      ** 2.6.19. Cut the trailing '\0'.
2124      */
2125     rNewSsid.u4SsidLen = (prEssid->length) ? prEssid->length - 1 : 0;
2126 #else
2127     rNewSsid.u4SsidLen = prEssid->length;
2128 #endif
2129     kalMemCopy(rNewSsid.aucSsid, pcExtra, rNewSsid.u4SsidLen);
2130
2131     /*
2132     rNewSsid.aucSsid[rNewSsid.u4SsidLen] = '\0';
2133     printk("set ssid(%lu): %s\n", rNewSsid.u4SsidLen, rNewSsid.aucSsid);
2134        */
2135
2136     if (kalIoctl(prGlueInfo,
2137                 wlanoidSetSsid,
2138                 (PVOID) &rNewSsid,
2139                 sizeof(PARAM_SSID_T),
2140                 FALSE,
2141                 FALSE,
2142                 TRUE,
2143                 FALSE,
2144                 &u4BufLen) != WLAN_STATUS_SUCCESS) {
2145         //printk(KERN_WARNING "Fail to set ssid\n");
2146         return -EFAULT;
2147     }
2148
2149
2150     return 0;
2151 } /* wext_set_essid */
2152
2153 /*----------------------------------------------------------------------------*/
2154 /*!
2155 * \brief To get current network name ESSID.
2156 *
2157 * \param[in] prDev Net device requested.
2158 * \param[in] prIwrInfo NULL.
2159 * \param[in] prEssid Pointer to iw_point structure containing essid information.
2160 * \param[out] pcExtra Pointer to buffer srtoring essid string.
2161 *
2162 * \retval 0 If netif_carrier_ok.
2163 * \retval -ENOTCONN Otherwise.
2164 *
2165 * \note If netif_carrier_ok, network essid is stored in pcExtra.
2166 */
2167 /*----------------------------------------------------------------------------*/
2168 //static PARAM_SSID_T ssid;
2169 static int
2170 wext_get_essid (
2171     IN struct net_device *prNetDev,
2172     IN struct iw_request_info *prIwrInfo,
2173     IN struct iw_point *prEssid,
2174     OUT char *pcExtra
2175     )
2176 {
2177     //PARAM_SSID_T ssid;
2178
2179     P_PARAM_SSID_T prSsid;
2180     P_GLUE_INFO_T prGlueInfo = NULL;
2181     WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS;
2182     UINT_32 u4BufLen = 0;
2183
2184     ASSERT(prNetDev);
2185     ASSERT(prEssid);
2186     ASSERT(pcExtra);
2187
2188     if (FALSE == GLUE_CHK_PR3(prNetDev, prEssid, pcExtra)) {
2189         return -EINVAL;
2190     }
2191     prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev));
2192
2193     //if (!netif_carrier_ok(prNetDev)) {
2194     //    return -ENOTCONN;
2195     //}
2196
2197     prSsid = kalMemAlloc(sizeof(PARAM_SSID_T), VIR_MEM_TYPE);
2198
2199     if(!prSsid) {
2200         return -ENOMEM;
2201     }
2202
2203     rStatus = kalIoctl(prGlueInfo,
2204         wlanoidQuerySsid,
2205         prSsid,
2206         sizeof(PARAM_SSID_T),
2207         TRUE,
2208         FALSE,
2209         FALSE,
2210         FALSE,
2211         &u4BufLen);
2212
2213     if ((rStatus == WLAN_STATUS_SUCCESS) && (prSsid->u4SsidLen <= MAX_SSID_LEN)) {
2214         kalMemCopy(pcExtra, prSsid->aucSsid, prSsid->u4SsidLen);
2215         prEssid->length = prSsid->u4SsidLen;
2216         prEssid->flags = 1;
2217     }
2218
2219     kalMemFree(prSsid, VIR_MEM_TYPE, sizeof(PARAM_SSID_T));
2220
2221     return 0;
2222 } /* wext_get_essid */
2223
2224
2225 #if 0
2226
2227 /*----------------------------------------------------------------------------*/
2228 /*!
2229 * \brief To set tx desired bit rate. Three cases here
2230 *        iwconfig wlan0 auto -> Set to origianl supported rate set.
2231 *        iwconfig wlan0 18M -> Imply "fixed" case, set to 18Mbps as desired rate.
2232 *        iwconfig wlan0 18M auto -> Set to auto rate lower and equal to 18Mbps
2233 *
2234 * \param[in] prNetDev       Pointer to the net_device handler.
2235 * \param[in] prIwReqInfo    Pointer to the Request Info.
2236 * \param[in] prRate         Pointer to the Rate Parameter.
2237 * \param[in] pcExtra        Pointer to the extra buffer.
2238 *
2239 * \retval 0         Update desired rate.
2240 * \retval -EINVAL   Wrong parameter
2241 */
2242 /*----------------------------------------------------------------------------*/
2243 int
2244 wext_set_rate (
2245     IN struct net_device *prNetDev,
2246     IN struct iw_request_info *prIwReqInfo,
2247     IN struct iw_param *prRate,
2248     IN char *pcExtra
2249     )
2250 {
2251     PARAM_RATES_EX aucSuppRate = {0};
2252     PARAM_RATES_EX aucNewRate = {0};
2253     UINT_32 u4NewRateLen = 0;
2254     UINT_32 i;
2255
2256     P_GLUE_INFO_T prGlueInfo = NULL;
2257     WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS;
2258     UINT_32 u4BufLen = 0;
2259
2260     ASSERT(prNetDev);
2261     ASSERT(prRate);
2262     if (FALSE == GLUE_CHK_PR2(prNetDev, prRate)) {
2263         return -EINVAL;
2264     }
2265     prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev));
2266
2267     /*
2268     printk("value = %d, fixed = %d, disable = %d, flags = %d\n",
2269         prRate->value, prRate->fixed, prRate->disabled, prRate->flags);
2270     */
2271
2272     rStatus = wlanQueryInformation(
2273         prGlueInfo->prAdapter,
2274         wlanoidQuerySupportedRates,
2275         &aucSuppRate,
2276         sizeof(aucSuppRate),
2277         &u4BufLen);
2278
2279     /* Case: AUTO */
2280     if (prRate->value < 0)  {
2281         if (prRate->fixed == 0) {
2282             /* iwconfig wlan0 rate auto */
2283
2284             /* set full supported rate to device */
2285             /* printk("wlanoidQuerySupportedRates():u4BufLen = %ld\n", u4BufLen); */
2286             rStatus = wlanSetInformation(
2287                 prGlueInfo->prAdapter,
2288                 wlanoidSetDesiredRates,
2289                 &aucSuppRate,
2290                 sizeof(aucSuppRate),
2291                 &u4BufLen);
2292             return 0;
2293         }
2294         else {
2295             /* iwconfig wlan0 rate fixed */
2296
2297             /* fix rate to what? DO NOTHING */
2298             return -EINVAL;
2299         }
2300     }
2301
2302
2303     aucNewRate[0] = prRate->value / 500000; /* In unit of 500k */
2304
2305     for (i = 0; i < PARAM_MAX_LEN_RATES_EX; i++) {
2306         /* check the given value is supported */
2307         if (aucSuppRate[i] == 0) {
2308             break;
2309         }
2310
2311         if (aucNewRate[0] == aucSuppRate[i]) {
2312             u4NewRateLen = 1;
2313             break;
2314         }
2315     }
2316
2317     if (u4NewRateLen == 0) {
2318         /* the given value is not supported */
2319         /* return error or use given rate as upper bound? */
2320         return -EINVAL;
2321     }
2322
2323     if (prRate->fixed == 0) {
2324         /* add all rates lower than desired rate */
2325         for (i = 0; i < PARAM_MAX_LEN_RATES_EX; ++i) {
2326             if (aucSuppRate[i] == 0) {
2327                 break;
2328             }
2329
2330             if (aucSuppRate[i] < aucNewRate[0]) {
2331                 aucNewRate[u4NewRateLen++] = aucSuppRate[i];
2332             }
2333         }
2334     }
2335
2336     rStatus = wlanSetInformation(
2337         prGlueInfo->prAdapter,
2338         wlanoidSetDesiredRates,
2339         &aucNewRate,
2340         sizeof(aucNewRate),
2341         &u4BufLen);
2342     return 0;
2343 } /* wext_set_rate */
2344
2345 #endif
2346
2347 /*----------------------------------------------------------------------------*/
2348 /*!
2349 * \brief To get current tx bit rate.
2350 *
2351 * \param[in] prDev Net device requested.
2352 * \param[in] prIwrInfo NULL.
2353 * \param[out] prRate Pointer to iw_param structure to store current tx rate.
2354 * \param[in] pcExtra NULL.
2355 *
2356 * \retval 0 If netif_carrier_ok.
2357 * \retval -ENOTCONN Otherwise.
2358 *
2359 * \note If netif_carrier_ok, current tx rate is stored in pRate.
2360 */
2361 /*----------------------------------------------------------------------------*/
2362 static int
2363 wext_get_rate (
2364     IN struct net_device *prNetDev,
2365     IN struct iw_request_info *prIwrInfo,
2366     OUT struct iw_param *prRate,
2367     IN char *pcExtra
2368     )
2369 {
2370     P_GLUE_INFO_T prGlueInfo = NULL;
2371     WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS;
2372     UINT_32 u4BufLen = 0;
2373     UINT_32 u4Rate = 0;
2374
2375     ASSERT(prNetDev);
2376     ASSERT(prRate);
2377     if (FALSE == GLUE_CHK_PR2(prNetDev, prRate)) {
2378         return -EINVAL;
2379     }
2380     prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev));
2381
2382     if (!netif_carrier_ok(prNetDev)) {
2383         return -ENOTCONN;
2384     }
2385
2386
2387     rStatus = kalIoctl(prGlueInfo,
2388         wlanoidQueryLinkSpeed,
2389         &u4Rate,
2390         sizeof(u4Rate),
2391         TRUE,
2392         FALSE,
2393         FALSE,
2394         FALSE,
2395         &u4BufLen);
2396
2397     if (rStatus != WLAN_STATUS_SUCCESS) {
2398         return -EFAULT;
2399     }
2400
2401     prRate->value = u4Rate * 100;   /* u4Rate is in unit of 100bps */
2402     prRate->fixed = 0;
2403
2404     return 0;
2405 } /* wext_get_rate */
2406
2407
2408 /*----------------------------------------------------------------------------*/
2409 /*!
2410 * \brief To set RTS/CTS theshold.
2411 *
2412 * \param[in] prDev Net device requested.
2413 * \param[in] prIwrInfo NULL.
2414 * \param[in] prRts Pointer to iw_param structure containing rts threshold.
2415 * \param[in] pcExtra NULL.
2416 *
2417 * \retval 0 For success.
2418 * \retval -EINVAL Given value is out of range.
2419 *
2420 * \note If given value is valid, device will follow the new setting.
2421 */
2422 /*----------------------------------------------------------------------------*/
2423 static int
2424 wext_set_rts (
2425     IN struct net_device *prNetDev,
2426     IN struct iw_request_info *prIwrInfo,
2427     IN struct iw_param *prRts,
2428     IN char *pcExtra
2429     )
2430 {
2431     PARAM_RTS_THRESHOLD u4RtsThresh;
2432
2433     P_GLUE_INFO_T prGlueInfo = NULL;
2434     WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS;
2435     UINT_32 u4BufLen = 0;
2436
2437     ASSERT(prNetDev);
2438     ASSERT(prRts);
2439     if (FALSE == GLUE_CHK_PR2(prNetDev, prRts)) {
2440         return -EINVAL;
2441     }
2442     prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev));
2443
2444     if (prRts->disabled == 1) {
2445         u4RtsThresh = 2347;
2446     }
2447     else if (prRts->value < 0 || prRts->value > 2347) {
2448         return -EINVAL;
2449     }
2450     else {
2451         u4RtsThresh = (PARAM_RTS_THRESHOLD)prRts->value;
2452     }
2453
2454     rStatus = kalIoctl(prGlueInfo,
2455         wlanoidSetRtsThreshold,
2456         &u4RtsThresh,
2457         sizeof(u4RtsThresh),
2458         FALSE,
2459         FALSE,
2460         FALSE,
2461         FALSE,
2462         &u4BufLen);
2463
2464
2465
2466     prRts->value = (typeof(prRts->value ))u4RtsThresh;
2467     prRts->disabled = (prRts->value > 2347) ? 1 : 0;
2468     prRts->fixed = 1;
2469
2470     return 0;
2471 } /* wext_set_rts */
2472
2473 /*----------------------------------------------------------------------------*/
2474 /*!
2475 * \brief To get RTS/CTS theshold.
2476 *
2477 * \param[in] prDev Net device requested.
2478 * \param[in] prIwrInfo NULL.
2479 * \param[out] prRts Pointer to iw_param structure containing rts threshold.
2480 * \param[in] pcExtra NULL.
2481 *
2482 * \retval 0 Success.
2483 *
2484 * \note RTS threshold is stored in pRts.
2485 */
2486 /*----------------------------------------------------------------------------*/
2487 static int
2488 wext_get_rts (
2489     IN struct net_device *prNetDev,
2490     IN struct iw_request_info *prIwrInfo,
2491     OUT struct iw_param *prRts,
2492     IN char *pcExtra
2493     )
2494 {
2495     PARAM_RTS_THRESHOLD u4RtsThresh;
2496
2497     P_GLUE_INFO_T prGlueInfo = NULL;
2498     WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS;
2499     UINT_32 u4BufLen = 0;
2500
2501     ASSERT(prNetDev);
2502     ASSERT(prRts);
2503     if (FALSE == GLUE_CHK_PR2(prNetDev, prRts)) {
2504         return -EINVAL;
2505     }
2506     prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev));
2507
2508     rStatus = kalIoctl(prGlueInfo,
2509         wlanoidQueryRtsThreshold,
2510         &u4RtsThresh,
2511         sizeof(u4RtsThresh),
2512         TRUE,
2513         FALSE,
2514         FALSE,
2515         FALSE,
2516         &u4BufLen);
2517
2518
2519
2520     prRts->value = (typeof(prRts->value ))u4RtsThresh;
2521     prRts->disabled = (prRts->value > 2347 || prRts->value < 0) ? 1 : 0;
2522     prRts->fixed = 1;
2523
2524     return 0;
2525 } /* wext_get_rts */
2526
2527 /*----------------------------------------------------------------------------*/
2528 /*!
2529 * \brief To get fragmentation threshold.
2530 *
2531 * \param[in] prDev Net device requested.
2532 * \param[in] prIwrInfo NULL.
2533 * \param[out] prFrag Pointer to iw_param structure containing frag threshold.
2534 * \param[in] pcExtra NULL.
2535 *
2536 * \retval 0 Success.
2537 *
2538 * \note RTS threshold is stored in pFrag. Fragmentation is disabled.
2539 */
2540 /*----------------------------------------------------------------------------*/
2541 static int
2542 wext_get_frag (
2543     IN struct net_device *prNetDev,
2544     IN struct iw_request_info *prIwrInfo,
2545     OUT struct iw_param *prFrag,
2546     IN char *pcExtra
2547     )
2548 {
2549     ASSERT(prFrag);
2550
2551     prFrag->value = 2346;
2552     prFrag->fixed = 1;
2553     prFrag->disabled = 1;
2554     return 0;
2555 } /* wext_get_frag */
2556
2557 #if 1
2558 /*----------------------------------------------------------------------------*/
2559 /*!
2560 * \brief To set TX power, or enable/disable the radio.
2561 *
2562 * \param[in] prDev Net device requested.
2563 * \param[in] prIwrInfo NULL.
2564 * \param[in] prTxPow Pointer to iw_param structure containing tx power setting.
2565 * \param[in] pcExtra NULL.
2566 *
2567 * \retval 0 Success.
2568 *
2569 * \note Tx power is stored in pTxPow. iwconfig wlan0 txpow on/off are used
2570 *       to enable/disable the radio.
2571 */
2572 /*----------------------------------------------------------------------------*/
2573
2574 static int
2575 wext_set_txpow (
2576     IN struct net_device *prNetDev,
2577     IN struct iw_request_info *prIwrInfo,
2578     IN struct iw_param *prTxPow,
2579     IN char *pcExtra
2580     )
2581 {
2582     int ret = 0;
2583     //PARAM_DEVICE_POWER_STATE ePowerState;
2584     ENUM_ACPI_STATE_T ePowerState;
2585
2586     P_GLUE_INFO_T prGlueInfo = NULL;
2587     WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS;
2588     UINT_32 u4BufLen = 0;
2589
2590     ASSERT(prNetDev);
2591     ASSERT(prTxPow);
2592     if (FALSE == GLUE_CHK_PR2(prNetDev, prTxPow)) {
2593         return -EINVAL;
2594     }
2595     prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev));
2596
2597     if(prTxPow->disabled){
2598         /* <1> disconnect */
2599         rStatus = kalIoctl(prGlueInfo,
2600                 wlanoidSetDisassociate,
2601                 NULL,
2602                 0,
2603                 FALSE,
2604                 FALSE,
2605                 TRUE,
2606                 FALSE,
2607                 &u4BufLen);
2608         if (rStatus != WLAN_STATUS_SUCCESS) {
2609             DBGLOG(INIT, INFO, ("######set disassoc failed\n"));
2610         } else {
2611             DBGLOG(INIT, INFO, ("######set assoc ok\n"));
2612         }
2613
2614         /* <2> mark to power state flag*/
2615         ePowerState = ACPI_STATE_D0;
2616         DBGLOG(INIT, INFO, ("set to acpi d3(0)\n"));
2617         wlanSetAcpiState(prGlueInfo->prAdapter, ePowerState);
2618
2619     }
2620     else {
2621         ePowerState = ACPI_STATE_D0;
2622         DBGLOG(INIT, INFO, ("set to acpi d0\n"));
2623         wlanSetAcpiState(prGlueInfo->prAdapter, ePowerState);
2624     }
2625
2626     prGlueInfo->ePowerState = ePowerState;
2627
2628     return ret;
2629 } /* wext_set_txpow */
2630
2631
2632 #endif
2633
2634 /*----------------------------------------------------------------------------*/
2635 /*!
2636 * \brief To get TX power.
2637 *
2638 * \param[in] prDev Net device requested.
2639 * \param[in] prIwrInfo NULL.
2640 * \param[out] prTxPow Pointer to iw_param structure containing tx power setting.
2641 * \param[in] pcExtra NULL.
2642 *
2643 * \retval 0 Success.
2644 *
2645 * \note Tx power is stored in pTxPow.
2646 */
2647 /*----------------------------------------------------------------------------*/
2648 static int
2649 wext_get_txpow (
2650     IN struct net_device *prNetDev,
2651     IN struct iw_request_info *prIwrInfo,
2652     OUT struct iw_param *prTxPow,
2653     IN char *pcExtra
2654     )
2655 {
2656     //PARAM_DEVICE_POWER_STATE ePowerState;
2657
2658     P_GLUE_INFO_T prGlueInfo = NULL;
2659
2660     ASSERT(prNetDev);
2661     ASSERT(prTxPow);
2662     if (FALSE == GLUE_CHK_PR2(prNetDev, prTxPow)) {
2663         return -EINVAL;
2664     }
2665     prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev));
2666
2667     /* GeorgeKuo: wlanoidQueryAcpiDevicePowerState() reports capability, not
2668      * current state. Use GLUE_INFO_T to store state.
2669     */
2670     //ePowerState = prGlueInfo->ePowerState;
2671
2672     /* TxPow parameters: Fixed at relative 100% */
2673 #if WIRELESS_EXT < 17
2674     prTxPow->flags = 0x0002; /* IW_TXPOW_RELATIVE */
2675 #else
2676     prTxPow->flags = IW_TXPOW_RELATIVE;
2677 #endif
2678     prTxPow->value = 100;
2679     prTxPow->fixed = 1;
2680     //prTxPow->disabled = (ePowerState != ParamDeviceStateD3) ? FALSE : TRUE;
2681     prTxPow->disabled = TRUE;
2682
2683     return 0;
2684 } /* wext_get_txpow */
2685
2686
2687 /*----------------------------------------------------------------------------*/
2688 /*!
2689 * \brief To get encryption cipher and key.
2690 *
2691 * \param[in] prDev Net device requested.
2692 * \param[in] prIwrInfo NULL.
2693 * \param[out] prEnc Pointer to iw_point structure containing securiry information.
2694 * \param[in] pcExtra Buffer to store key content.
2695 *
2696 * \retval 0 Success.
2697 *
2698 * \note Securiry information is stored in pEnc except key content.
2699 */
2700 /*----------------------------------------------------------------------------*/
2701 static int
2702 wext_get_encode (
2703     IN struct net_device *prNetDev,
2704     IN struct iw_request_info *prIwrInfo,
2705     OUT struct iw_point *prEnc,
2706     IN char *pcExtra
2707     )
2708 {
2709 #if 1
2710     //ENUM_ENCRYPTION_STATUS_T eEncMode;
2711     ENUM_PARAM_ENCRYPTION_STATUS_T eEncMode;
2712
2713     P_GLUE_INFO_T prGlueInfo = NULL;
2714     WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS;
2715     UINT_32 u4BufLen = 0;
2716
2717     ASSERT(prNetDev);
2718     ASSERT(prEnc);
2719     if (FALSE == GLUE_CHK_PR2(prNetDev, prEnc)) {
2720         return -EINVAL;
2721     }
2722     prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev));
2723
2724
2725     rStatus = kalIoctl(prGlueInfo,
2726         wlanoidQueryEncryptionStatus,
2727         &eEncMode,
2728         sizeof(eEncMode),
2729         TRUE,
2730         FALSE,
2731         FALSE,
2732         FALSE,
2733         &u4BufLen);
2734
2735
2736
2737     switch(eEncMode) {
2738     case ENUM_WEP_DISABLED:
2739         prEnc->flags = IW_ENCODE_DISABLED;
2740         break;
2741     case ENUM_WEP_ENABLED:
2742         prEnc->flags = IW_ENCODE_ENABLED;
2743         break;
2744     case ENUM_WEP_KEY_ABSENT:
2745         prEnc->flags = IW_ENCODE_ENABLED | IW_ENCODE_NOKEY;
2746         break;
2747     default:
2748         prEnc->flags = IW_ENCODE_ENABLED;
2749         break;
2750     }
2751
2752     /* Cipher, Key Content, Key ID can't be queried */
2753     prEnc->flags |= IW_ENCODE_NOKEY;
2754 #endif
2755     return 0;
2756 } /* wext_get_encode */
2757
2758
2759
2760 /*----------------------------------------------------------------------------*/
2761 /*!
2762 * \brief To set encryption cipher and key.
2763 *
2764 * \param[in] prDev Net device requested.
2765 * \param[in] prIwrInfo NULL.
2766 * \param[in] prEnc Pointer to iw_point structure containing securiry information.
2767 * \param[in] pcExtra Pointer to key string buffer.
2768 *
2769 * \retval 0 Success.
2770 * \retval -EINVAL Key ID error for WEP.
2771 * \retval -EFAULT Setting parameters to driver fail.
2772 * \retval -EOPNOTSUPP Key size not supported.
2773 *
2774 * \note Securiry information is stored in pEnc.
2775 */
2776 /*----------------------------------------------------------------------------*/
2777 static UINT_8 wepBuf[48];
2778
2779 static int
2780 wext_set_encode (
2781     IN struct net_device *prNetDev,
2782     IN struct iw_request_info *prIwrInfo,
2783     IN struct iw_point *prEnc,
2784     IN char *pcExtra
2785     )
2786 {
2787 #if 1
2788     ENUM_PARAM_ENCRYPTION_STATUS_T eEncStatus;
2789     ENUM_PARAM_AUTH_MODE_T eAuthMode;
2790     //UINT_8 wepBuf[48];
2791     P_PARAM_WEP_T prWepKey = (P_PARAM_WEP_T) wepBuf;
2792
2793     P_GLUE_INFO_T prGlueInfo = NULL;
2794     WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS;
2795     UINT_32 u4BufLen = 0;
2796
2797     ASSERT(prNetDev);
2798     ASSERT(prEnc);
2799     ASSERT(pcExtra);
2800     if (FALSE == GLUE_CHK_PR3(prNetDev, prEnc, pcExtra)) {
2801         return -EINVAL;
2802     }
2803     prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev));
2804
2805     /* reset to default mode */
2806     prGlueInfo->rWpaInfo.u4WpaVersion = IW_AUTH_WPA_VERSION_DISABLED;
2807     prGlueInfo->rWpaInfo.u4KeyMgmt = 0;
2808     prGlueInfo->rWpaInfo.u4CipherPairwise = IW_AUTH_CIPHER_NONE;
2809     prGlueInfo->rWpaInfo.u4CipherGroup = IW_AUTH_CIPHER_NONE;
2810     prGlueInfo->rWpaInfo.u4AuthAlg = IW_AUTH_ALG_OPEN_SYSTEM;
2811 #if CFG_SUPPORT_802_11W
2812     prGlueInfo->rWpaInfo.u4Mfp = IW_AUTH_MFP_DISABLED;
2813 #endif
2814
2815     /* iwconfig wlan0 key off */
2816     if ( (prEnc->flags & IW_ENCODE_MODE) == IW_ENCODE_DISABLED ) {
2817         eAuthMode = AUTH_MODE_OPEN;
2818
2819         rStatus = kalIoctl(prGlueInfo,
2820             wlanoidSetAuthMode,
2821             &eAuthMode,
2822             sizeof(eAuthMode),
2823             FALSE,
2824             FALSE,
2825             FALSE,
2826             FALSE,
2827             &u4BufLen);
2828
2829         eEncStatus = ENUM_ENCRYPTION_DISABLED;
2830
2831         rStatus = kalIoctl(prGlueInfo,
2832             wlanoidSetEncryptionStatus,
2833             &eEncStatus,
2834             sizeof(eEncStatus),
2835             FALSE,
2836             FALSE,
2837             FALSE,
2838             FALSE,
2839             &u4BufLen);
2840
2841         return 0;
2842     }
2843
2844     /* iwconfig wlan0 key 0123456789 */
2845     /* iwconfig wlan0 key s:abcde */
2846     /* iwconfig wlan0 key 0123456789 [1] */
2847     /* iwconfig wlan0 key 01234567890123456789012345 [1] */
2848     /* check key size for WEP */
2849     if (prEnc->length == 5 || prEnc->length == 13 || prEnc->length == 16) {
2850         /* prepare PARAM_WEP key structure */
2851         prWepKey->u4KeyIndex = (prEnc->flags & IW_ENCODE_INDEX) ?
2852             (prEnc->flags & IW_ENCODE_INDEX) -1 : 0;
2853         if (prWepKey->u4KeyIndex > 3) {
2854             /* key id is out of range */
2855             return -EINVAL;
2856         }
2857         prWepKey->u4KeyIndex |= 0x80000000;
2858         prWepKey->u4Length = 12 + prEnc->length;
2859         prWepKey->u4KeyLength = prEnc->length;
2860         kalMemCopy(prWepKey->aucKeyMaterial, pcExtra, prEnc->length);
2861
2862
2863         rStatus = kalIoctl(prGlueInfo,
2864                      wlanoidSetAddWep,
2865                      prWepKey,
2866                      prWepKey->u4Length,
2867                      FALSE,
2868                      FALSE,
2869                      TRUE,
2870                      FALSE,
2871                      &u4BufLen);
2872
2873         if (rStatus != WLAN_STATUS_SUCCESS) {
2874             DBGLOG(INIT, INFO, ("wlanoidSetAddWep fail 0x%lx\n", rStatus));
2875             return -EFAULT;
2876         }
2877
2878         /* change to auto switch */
2879         prGlueInfo->rWpaInfo.u4AuthAlg = IW_AUTH_ALG_SHARED_KEY |
2880             IW_AUTH_ALG_OPEN_SYSTEM;
2881         eAuthMode = AUTH_MODE_AUTO_SWITCH;
2882
2883         rStatus = kalIoctl(prGlueInfo,
2884                      wlanoidSetAuthMode,
2885                      &eAuthMode,
2886                      sizeof(eAuthMode),
2887                      FALSE,
2888                      FALSE,
2889                      FALSE,
2890                      FALSE,
2891                      &u4BufLen);
2892
2893         if (rStatus != WLAN_STATUS_SUCCESS) {
2894             //printk(KERN_INFO DRV_NAME"wlanoidSetAuthMode fail 0x%lx\n", rStatus);
2895             return -EFAULT;
2896         }
2897
2898         prGlueInfo->rWpaInfo.u4CipherPairwise =
2899             IW_AUTH_CIPHER_WEP104 | IW_AUTH_CIPHER_WEP40;
2900         prGlueInfo->rWpaInfo.u4CipherGroup =
2901             IW_AUTH_CIPHER_WEP104 | IW_AUTH_CIPHER_WEP40;
2902
2903         eEncStatus = ENUM_WEP_ENABLED;
2904
2905
2906         rStatus = kalIoctl(prGlueInfo,
2907                      wlanoidSetEncryptionStatus,
2908                      &eEncStatus,
2909                      sizeof(ENUM_PARAM_ENCRYPTION_STATUS_T),
2910                      FALSE,
2911                      FALSE,
2912                      FALSE,
2913                      FALSE,
2914                      &u4BufLen);
2915
2916         if (rStatus != WLAN_STATUS_SUCCESS) {
2917             //printk(KERN_INFO DRV_NAME"wlanoidSetEncryptionStatus fail 0x%lx\n", rStatus);
2918             return -EFAULT;
2919         }
2920
2921         return 0;
2922     }
2923 #endif
2924     return -EOPNOTSUPP;
2925 } /* wext_set_encode */
2926
2927
2928 /*----------------------------------------------------------------------------*/
2929 /*!
2930 * \brief To set power management.
2931 *
2932 * \param[in] prDev Net device requested.
2933 * \param[in] prIwrInfo NULL.
2934 * \param[in] prPower Pointer to iw_param structure containing tx power setting.
2935 * \param[in] pcExtra NULL.
2936 *
2937 * \retval 0 Success.
2938 *
2939 * \note New Power Management Mode is set to driver.
2940 */
2941 /*----------------------------------------------------------------------------*/
2942 static int
2943 wext_set_power (
2944     IN struct net_device *prNetDev,
2945     IN struct iw_request_info *prIwrInfo,
2946     IN struct iw_param *prPower,
2947     IN char *pcExtra
2948     )
2949 {
2950 #if 1
2951     PARAM_POWER_MODE ePowerMode;
2952     INT_32 i4PowerValue;
2953
2954     P_GLUE_INFO_T prGlueInfo = NULL;
2955     WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS;
2956     UINT_32 u4BufLen = 0;
2957
2958     ASSERT(prNetDev);
2959     ASSERT(prPower);
2960     if (FALSE == GLUE_CHK_PR2(prNetDev, prPower)) {
2961         return -EINVAL;
2962     }
2963     prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev));
2964
2965     //printk(KERN_INFO "wext_set_power value(%d) disabled(%d) flag(0x%x)\n",
2966     //  prPower->value, prPower->disabled, prPower->flags);
2967
2968     if(prPower->disabled){
2969         ePowerMode = Param_PowerModeCAM;
2970     }
2971     else {
2972         i4PowerValue = prPower->value;
2973 #if WIRELESS_EXT < 21
2974         i4PowerValue /= 1000000;
2975 #endif
2976         if (i4PowerValue == 0) {
2977             ePowerMode = Param_PowerModeCAM;
2978         } else if (i4PowerValue == 1) {
2979             ePowerMode = Param_PowerModeMAX_PSP;
2980         } else if (i4PowerValue == 2) {
2981             ePowerMode = Param_PowerModeFast_PSP;
2982         }
2983         else {
2984             DBGLOG(INIT, INFO, ("%s(): unsupported power management mode value = %d.\n",
2985                 __FUNCTION__,
2986                 prPower->value));
2987
2988             return -EINVAL;
2989     }
2990     }
2991
2992
2993     rStatus = kalIoctl(prGlueInfo,
2994         wlanoidSet802dot11PowerSaveProfile,
2995         &ePowerMode,
2996         sizeof(ePowerMode),
2997         FALSE,
2998         FALSE,
2999         TRUE,
3000         FALSE,
3001         &u4BufLen);
3002
3003     if (rStatus != WLAN_STATUS_SUCCESS) {
3004         //printk(KERN_INFO DRV_NAME"wlanoidSet802dot11PowerSaveProfile fail 0x%lx\n", rStatus);
3005         return -EFAULT;
3006     }
3007
3008 #endif
3009     return 0;
3010 } /* wext_set_power */
3011
3012
3013 /*----------------------------------------------------------------------------*/
3014 /*!
3015 * \brief To get power management.
3016 *
3017 * \param[in] prDev Net device requested.
3018 * \param[in] prIwrInfo NULL.
3019 * \param[out] prPower Pointer to iw_param structure containing tx power setting.
3020 * \param[in] pcExtra NULL.
3021 *
3022 * \retval 0 Success.
3023 *
3024 * \note Power management mode is stored in pTxPow->value.
3025 */
3026 /*----------------------------------------------------------------------------*/
3027 static int
3028 wext_get_power (
3029     IN struct net_device *prNetDev,
3030     IN struct iw_request_info *prIwrInfo,
3031     OUT struct iw_param *prPower,
3032     IN char *pcExtra
3033     )
3034 {
3035
3036     P_GLUE_INFO_T prGlueInfo = NULL;
3037     WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS;
3038     UINT_32 u4BufLen = 0;
3039     PARAM_POWER_MODE ePowerMode = Param_PowerModeCAM;
3040
3041     ASSERT(prNetDev);
3042     ASSERT(prPower);
3043     if (FALSE == GLUE_CHK_PR2(prNetDev, prPower)) {
3044         return -EINVAL;
3045     }
3046     prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev));
3047
3048 #if 0
3049 #if defined(_HIF_SDIO)
3050     rStatus = sdio_io_ctrl(prGlueInfo,
3051         wlanoidQuery802dot11PowerSaveProfile,
3052         &ePowerMode,
3053         sizeof(ePowerMode),
3054         TRUE,
3055         TRUE,
3056         &u4BufLen);
3057 #else
3058     rStatus = wlanQueryInformation(prGlueInfo->prAdapter,
3059         wlanoidQuery802dot11PowerSaveProfile,
3060         &ePowerMode,
3061         sizeof(ePowerMode),
3062         &u4BufLen);
3063 #endif
3064 #else
3065     rStatus = wlanQueryInformation(prGlueInfo->prAdapter,
3066         wlanoidQuery802dot11PowerSaveProfile,
3067         &ePowerMode,
3068         sizeof(ePowerMode),
3069         &u4BufLen);
3070 #endif
3071
3072     if (rStatus != WLAN_STATUS_SUCCESS) {
3073         return -EFAULT;
3074     }
3075
3076     prPower->value = 0;
3077     prPower->disabled = 1;
3078
3079     if (Param_PowerModeCAM == ePowerMode) {
3080         prPower->value = 0;
3081         prPower->disabled = 1;
3082     }
3083     else if (Param_PowerModeMAX_PSP == ePowerMode ) {
3084         prPower->value = 1;
3085         prPower->disabled = 0;
3086     }
3087     else if (Param_PowerModeFast_PSP == ePowerMode ) {
3088         prPower->value = 2;
3089         prPower->disabled = 0;
3090     }
3091
3092     prPower->flags = IW_POWER_PERIOD | IW_POWER_RELATIVE;
3093 #if WIRELESS_EXT < 21
3094     prPower->value *= 1000000;
3095 #endif
3096
3097     //printk(KERN_INFO "wext_get_power value(%d) disabled(%d) flag(0x%x)\n",
3098     //    prPower->value, prPower->disabled, prPower->flags);
3099
3100     return 0;
3101 } /* wext_get_power */
3102
3103 /*----------------------------------------------------------------------------*/
3104 /*!
3105 * \brief To set authentication parameters.
3106 *
3107 * \param[in] prDev Net device requested.
3108 * \param[in] prIwrInfo NULL.
3109 * \param[in] rpAuth Pointer to iw_param structure containing authentication information.
3110 * \param[in] pcExtra Pointer to key string buffer.
3111 *
3112 * \retval 0 Success.
3113 * \retval -EINVAL Key ID error for WEP.
3114 * \retval -EFAULT Setting parameters to driver fail.
3115 * \retval -EOPNOTSUPP Key size not supported.
3116 *
3117 * \note Securiry information is stored in pEnc.
3118 */
3119 /*----------------------------------------------------------------------------*/
3120 static int
3121 wext_set_auth (
3122     IN struct net_device *prNetDev,
3123     IN struct iw_request_info *prIwrInfo,
3124     IN struct iw_param *prAuth,
3125     IN char *pcExtra
3126     )
3127 {
3128     P_GLUE_INFO_T prGlueInfo = NULL;
3129
3130     ASSERT(prNetDev);
3131     ASSERT(prAuth);
3132     if (FALSE == GLUE_CHK_PR2(prNetDev, prAuth)) {
3133         return -EINVAL;
3134     }
3135     prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev));
3136
3137     /* Save information to glue info and process later when ssid is set. */
3138     switch(prAuth->flags & IW_AUTH_INDEX) {
3139         case IW_AUTH_WPA_VERSION:
3140 #if CFG_SUPPORT_WAPI
3141             if (wlanQueryWapiMode(prGlueInfo->prAdapter)){
3142                 prGlueInfo->rWpaInfo.u4WpaVersion = IW_AUTH_WPA_VERSION_DISABLED;
3143                 prGlueInfo->rWpaInfo.u4AuthAlg = IW_AUTH_ALG_OPEN_SYSTEM;
3144             }
3145             else {
3146                 prGlueInfo->rWpaInfo.u4WpaVersion = prAuth->value;
3147             }
3148 #else
3149             prGlueInfo->rWpaInfo.u4WpaVersion = prAuth->value;
3150 #endif
3151             break;
3152
3153         case IW_AUTH_CIPHER_PAIRWISE:
3154             prGlueInfo->rWpaInfo.u4CipherPairwise = prAuth->value;
3155             break;
3156
3157         case IW_AUTH_CIPHER_GROUP:
3158             prGlueInfo->rWpaInfo.u4CipherGroup = prAuth->value;
3159             break;
3160
3161         case IW_AUTH_KEY_MGMT:
3162             prGlueInfo->rWpaInfo.u4KeyMgmt = prAuth->value;
3163 #if CFG_SUPPORT_WAPI
3164             if (prGlueInfo->rWpaInfo.u4KeyMgmt == IW_AUTH_KEY_MGMT_WAPI_PSK ||
3165                 prGlueInfo->rWpaInfo.u4KeyMgmt == IW_AUTH_KEY_MGMT_WAPI_CERT)  {
3166                     UINT_32 u4BufLen;
3167                     WLAN_STATUS rStatus;
3168
3169                     rStatus = kalIoctl(prGlueInfo,
3170                             wlanoidSetWapiMode,
3171                             &prAuth->value,
3172                             sizeof(UINT_32),
3173                             FALSE,
3174                             FALSE,
3175                             TRUE,
3176                             FALSE,
3177                             &u4BufLen);
3178                 DBGLOG(INIT, INFO, ("IW_AUTH_WAPI_ENABLED :%d\n", prAuth->value));
3179             }
3180 #endif
3181             if (prGlueInfo->rWpaInfo.u4KeyMgmt == IW_AUTH_KEY_MGMT_WPS)
3182                 prGlueInfo->fgWpsActive = TRUE;
3183             else
3184                 prGlueInfo->fgWpsActive = FALSE;
3185             break;
3186
3187         case IW_AUTH_80211_AUTH_ALG:
3188             prGlueInfo->rWpaInfo.u4AuthAlg = prAuth->value;
3189             break;
3190
3191         case IW_AUTH_PRIVACY_INVOKED:
3192             prGlueInfo->rWpaInfo.fgPrivacyInvoke = prAuth->value;
3193             break;
3194 #if CFG_SUPPORT_802_11W
3195         case IW_AUTH_MFP:
3196             //printk("wext_set_auth IW_AUTH_MFP=%d\n", prAuth->value);
3197             prGlueInfo->rWpaInfo.u4Mfp = prAuth->value;
3198             break;
3199 #endif
3200 #if CFG_SUPPORT_WAPI
3201         case IW_AUTH_WAPI_ENABLED:
3202             {
3203                 UINT_32 u4BufLen;
3204                 WLAN_STATUS rStatus;
3205
3206                 rStatus = kalIoctl(prGlueInfo,
3207                         wlanoidSetWapiMode,
3208                         &prAuth->value,
3209                         sizeof(UINT_32),
3210                         FALSE,
3211                         FALSE,
3212                         TRUE,
3213                         FALSE,
3214                         &u4BufLen);
3215             }
3216             DBGLOG(INIT, INFO, ("IW_AUTH_WAPI_ENABLED :%d\n", prAuth->value));
3217             break;
3218 #endif
3219         default:
3220             /*
3221             printk(KERN_INFO "[wifi] unsupported IW_AUTH_INDEX :%d\n", prAuth->flags);
3222             */
3223             break;
3224     }
3225     return 0;
3226 } /* wext_set_auth */
3227
3228
3229 /*----------------------------------------------------------------------------*/
3230 /*!
3231 * \brief To set encryption cipher and key.
3232 *
3233 * \param[in] prDev Net device requested.
3234 * \param[in] prIwrInfo NULL.
3235 * \param[in] prEnc Pointer to iw_point structure containing securiry information.
3236 * \param[in] pcExtra Pointer to key string buffer.
3237 *
3238 * \retval 0 Success.
3239 * \retval -EINVAL Key ID error for WEP.
3240 * \retval -EFAULT Setting parameters to driver fail.
3241 * \retval -EOPNOTSUPP Key size not supported.
3242 *
3243 * \note Securiry information is stored in pEnc.
3244 */
3245 /*----------------------------------------------------------------------------*/
3246 #if CFG_SUPPORT_WAPI
3247     UINT_8 keyStructBuf[320];   /* add/remove key shared buffer */
3248 #else
3249     UINT_8 keyStructBuf[100];   /* add/remove key shared buffer */
3250 #endif
3251
3252 static int
3253 wext_set_encode_ext (
3254     IN struct net_device *prNetDev,
3255     IN struct iw_request_info *prIwrInfo,
3256     IN struct iw_point *prEnc,
3257     IN char *pcExtra
3258     )
3259 {
3260     P_PARAM_REMOVE_KEY_T prRemoveKey = (P_PARAM_REMOVE_KEY_T) keyStructBuf;
3261     P_PARAM_KEY_T prKey = (P_PARAM_KEY_T) keyStructBuf;
3262
3263
3264     P_PARAM_WEP_T prWepKey = (P_PARAM_WEP_T) wepBuf;
3265
3266     struct iw_encode_ext *prIWEncExt = (struct iw_encode_ext *) pcExtra;
3267
3268     ENUM_PARAM_ENCRYPTION_STATUS_T eEncStatus;
3269     ENUM_PARAM_AUTH_MODE_T eAuthMode;
3270     //ENUM_PARAM_OP_MODE_T eOpMode = NET_TYPE_AUTO_SWITCH;
3271
3272 #if CFG_SUPPORT_WAPI
3273     P_PARAM_WPI_KEY_T prWpiKey = (P_PARAM_WPI_KEY_T) keyStructBuf;
3274 #endif
3275
3276     P_GLUE_INFO_T prGlueInfo = NULL;
3277     WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS;
3278     UINT_32 u4BufLen = 0;
3279
3280     ASSERT(prNetDev);
3281     ASSERT(prEnc);
3282     if (FALSE == GLUE_CHK_PR3(prNetDev, prEnc, pcExtra)) {
3283         return -EINVAL;
3284     }
3285     prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev));
3286
3287     memset(keyStructBuf, 0, sizeof(keyStructBuf));
3288
3289 #if CFG_SUPPORT_WAPI
3290     if (prIWEncExt->alg == IW_ENCODE_ALG_SMS4) {
3291         if (prEnc->flags & IW_ENCODE_DISABLED) {
3292             //printk(KERN_INFO "[wapi] IW_ENCODE_DISABLED\n");
3293             return 0;
3294         }
3295         /* KeyID */
3296         prWpiKey->ucKeyID = (prEnc->flags & IW_ENCODE_INDEX);
3297         prWpiKey->ucKeyID --;
3298         if (prWpiKey->ucKeyID > 1) {
3299             /* key id is out of range */
3300             //printk(KERN_INFO "[wapi] add key error: key_id invalid %d\n", prWpiKey->ucKeyID);
3301             return -EINVAL;
3302         }
3303
3304         if (prIWEncExt->key_len != 32) {
3305             /* key length not valid */
3306             //printk(KERN_INFO "[wapi] add key error: key_len invalid %d\n", prIWEncExt->key_len);
3307             return -EINVAL;
3308         }
3309
3310         //printk(KERN_INFO "[wapi] %d ext_flags %d\n", prEnc->flags, prIWEncExt->ext_flags);
3311
3312         if (prIWEncExt->ext_flags & IW_ENCODE_EXT_GROUP_KEY) {
3313             prWpiKey->eKeyType = ENUM_WPI_GROUP_KEY;
3314             prWpiKey->eDirection = ENUM_WPI_RX;
3315         }
3316         else if (prIWEncExt->ext_flags & IW_ENCODE_EXT_SET_TX_KEY) {
3317             prWpiKey->eKeyType = ENUM_WPI_PAIRWISE_KEY;
3318             prWpiKey->eDirection = ENUM_WPI_RX_TX;
3319         }
3320
3321         /* PN */
3322         memcpy(prWpiKey->aucPN, prIWEncExt->tx_seq, IW_ENCODE_SEQ_MAX_SIZE * 2);
3323
3324         /* BSSID */
3325         memcpy(prWpiKey->aucAddrIndex, prIWEncExt->addr.sa_data, 6);
3326
3327         memcpy(prWpiKey->aucWPIEK, prIWEncExt->key, 16);
3328         prWpiKey->u4LenWPIEK = 16;
3329
3330         memcpy(prWpiKey->aucWPICK, &prIWEncExt->key[16], 16);
3331         prWpiKey->u4LenWPICK = 16;
3332
3333         rStatus = kalIoctl(prGlueInfo,
3334                      wlanoidSetWapiKey,
3335                      prWpiKey,
3336                      sizeof(PARAM_WPI_KEY_T),
3337                      FALSE,
3338                      FALSE,
3339                      TRUE,
3340                      FALSE,
3341                      &u4BufLen);
3342
3343         if (rStatus != WLAN_STATUS_SUCCESS) {
3344             //printk(KERN_INFO "[wapi] add key error:%lx\n", rStatus);
3345         }
3346
3347     }
3348     else
3349 #endif
3350     {
3351
3352     if ( (prEnc->flags & IW_ENCODE_MODE) == IW_ENCODE_DISABLED) {
3353         prRemoveKey->u4Length = sizeof(*prRemoveKey);
3354         memcpy(prRemoveKey->arBSSID, prIWEncExt->addr.sa_data, 6);
3355         /*
3356         printk("IW_ENCODE_DISABLED: ID:%d, Addr:[" MACSTR "]\n",
3357             prRemoveKey->KeyIndex, MAC2STR(prRemoveKey->BSSID));
3358         */
3359
3360         rStatus = kalIoctl(prGlueInfo,
3361                      wlanoidSetRemoveKey,
3362                      prRemoveKey,
3363                      prRemoveKey->u4Length,
3364                      FALSE,
3365                      FALSE,
3366                      TRUE,
3367                      FALSE,
3368                      &u4BufLen);
3369
3370
3371         if (rStatus != WLAN_STATUS_SUCCESS) {
3372             DBGLOG(INIT, INFO, ("remove key error:%lx\n", rStatus));
3373         }
3374         return 0;
3375     }
3376
3377     //return 0;
3378     //printk ("alg %x\n", prIWEncExt->alg);
3379
3380     switch (prIWEncExt->alg) {
3381         case IW_ENCODE_ALG_NONE:
3382             break;
3383         case IW_ENCODE_ALG_WEP:
3384             /* iwconfig wlan0 key 0123456789 */
3385             /* iwconfig wlan0 key s:abcde */
3386             /* iwconfig wlan0 key 0123456789 [1] */
3387             /* iwconfig wlan0 key 01234567890123456789012345 [1] */
3388             /* check key size for WEP */
3389             if (prIWEncExt->key_len == 5 || prIWEncExt->key_len == 13 || prIWEncExt->key_len == 16) {
3390                 /* prepare PARAM_WEP key structure */
3391                 prWepKey->u4KeyIndex = (prEnc->flags & IW_ENCODE_INDEX) ?
3392                     (prEnc->flags & IW_ENCODE_INDEX) -1 : 0;
3393                 if (prWepKey->u4KeyIndex > 3) {
3394                     /* key id is out of range */
3395                     return -EINVAL;
3396                 }
3397                 prWepKey->u4KeyIndex |= 0x80000000;
3398                 prWepKey->u4Length = 12 + prIWEncExt->key_len;
3399                 prWepKey->u4KeyLength = prIWEncExt->key_len;
3400                 //kalMemCopy(prWepKey->aucKeyMaterial, pcExtra, prIWEncExt->key_len);
3401                 kalMemCopy(prWepKey->aucKeyMaterial, prIWEncExt->key, prIWEncExt->key_len);
3402
3403
3404                 rStatus = kalIoctl(prGlueInfo,
3405                         wlanoidSetAddWep,
3406                         prWepKey,
3407                         prWepKey->u4Length,
3408                         FALSE,
3409                         FALSE,
3410                         TRUE,
3411                         FALSE,
3412                         &u4BufLen);
3413
3414                 if (rStatus != WLAN_STATUS_SUCCESS) {
3415                     DBGLOG(INIT, INFO, ("wlanoidSetAddWep fail 0x%lx\n", rStatus));
3416                     return -EFAULT;
3417                 }
3418
3419                 /* change to auto switch */
3420                 prGlueInfo->rWpaInfo.u4AuthAlg = IW_AUTH_ALG_SHARED_KEY |
3421                     IW_AUTH_ALG_OPEN_SYSTEM;
3422                 eAuthMode = AUTH_MODE_AUTO_SWITCH;
3423
3424                 rStatus = kalIoctl(prGlueInfo,
3425                         wlanoidSetAuthMode,
3426                         &eAuthMode,
3427                         sizeof(eAuthMode),
3428                         FALSE,
3429                         FALSE,
3430                         FALSE,
3431                         FALSE,
3432                         &u4BufLen);
3433
3434                 if (rStatus != WLAN_STATUS_SUCCESS) {
3435                     DBGLOG(INIT, INFO, ("wlanoidSetAuthMode fail 0x%lx\n", rStatus));
3436                     return -EFAULT;
3437                 }
3438
3439                 prGlueInfo->rWpaInfo.u4CipherPairwise =
3440                     IW_AUTH_CIPHER_WEP104 | IW_AUTH_CIPHER_WEP40;
3441                 prGlueInfo->rWpaInfo.u4CipherGroup =
3442                     IW_AUTH_CIPHER_WEP104 | IW_AUTH_CIPHER_WEP40;
3443
3444                 eEncStatus = ENUM_WEP_ENABLED;
3445
3446
3447                 rStatus = kalIoctl(prGlueInfo,
3448                         wlanoidSetEncryptionStatus,
3449                         &eEncStatus,
3450                         sizeof(ENUM_PARAM_ENCRYPTION_STATUS_T),
3451                         FALSE,
3452                         FALSE,
3453                         FALSE,
3454                         FALSE,
3455                         &u4BufLen);
3456
3457                 if (rStatus != WLAN_STATUS_SUCCESS) {
3458                     DBGLOG(INIT, INFO, ("wlanoidSetEncryptionStatus fail 0x%lx\n", rStatus));
3459                     return -EFAULT;
3460                 }
3461
3462             } else {
3463                 DBGLOG(INIT, INFO, ("key length %x\n", prIWEncExt->key_len));
3464                 DBGLOG(INIT, INFO, ("key error\n"));
3465             }
3466
3467             break;
3468         case IW_ENCODE_ALG_TKIP:
3469         case IW_ENCODE_ALG_CCMP:
3470 #if CFG_SUPPORT_802_11W
3471         case IW_ENCODE_ALG_AES_CMAC:
3472 #endif
3473             {
3474
3475                 /* KeyID */
3476                 prKey->u4KeyIndex = (prEnc->flags & IW_ENCODE_INDEX) ?
3477                     (prEnc->flags & IW_ENCODE_INDEX) -1: 0;
3478 #if CFG_SUPPORT_802_11W
3479                 if (prKey->u4KeyIndex > 5)
3480 #else
3481                 if (prKey->u4KeyIndex > 3)
3482 #endif
3483                 {
3484                     DBGLOG(INIT, INFO, ("key index error:0x%lx\n", prKey->u4KeyIndex));
3485                     /* key id is out of range */
3486                     return -EINVAL;
3487                 }
3488
3489                 /* bit(31) and bit(30) are shared by pKey and pRemoveKey */
3490                 /* Tx Key Bit(31)*/
3491                 if (prIWEncExt->ext_flags & IW_ENCODE_EXT_SET_TX_KEY) {
3492                     prKey->u4KeyIndex |= 0x1UL << 31;
3493                 }
3494
3495                 /* Pairwise Key Bit(30) */
3496                 if (prIWEncExt->ext_flags & IW_ENCODE_EXT_GROUP_KEY) {
3497                     /* group key */
3498                 }
3499                 else {
3500                     /* pairwise key */
3501                     prKey->u4KeyIndex |= 0x1UL << 30;
3502                 }
3503
3504             }
3505             /* Rx SC Bit(29) */
3506             if (prIWEncExt->ext_flags & IW_ENCODE_EXT_RX_SEQ_VALID) {
3507                 prKey->u4KeyIndex |= 0x1UL << 29;
3508                 memcpy(&prKey->rKeyRSC, prIWEncExt->rx_seq, IW_ENCODE_SEQ_MAX_SIZE);
3509             }
3510
3511             /* BSSID */
3512             memcpy(prKey->arBSSID, prIWEncExt->addr.sa_data, 6);
3513
3514             /* switch tx/rx MIC key for sta */
3515             if (prIWEncExt->alg == IW_ENCODE_ALG_TKIP && prIWEncExt->key_len == 32) {
3516                 memcpy(prKey->aucKeyMaterial, prIWEncExt->key, 16);
3517                 memcpy(((PUINT_8)prKey->aucKeyMaterial) + 16, prIWEncExt->key + 24, 8);
3518                 memcpy((prKey->aucKeyMaterial) + 24, prIWEncExt->key + 16, 8);
3519             }
3520             else {
3521                 memcpy(prKey->aucKeyMaterial, prIWEncExt->key, prIWEncExt->key_len);
3522             }
3523
3524             prKey->u4KeyLength = prIWEncExt->key_len;
3525             prKey->u4Length = ((UINT_32)&(((P_PARAM_KEY_T)0)->aucKeyMaterial)) + prKey->u4KeyLength;
3526
3527
3528             rStatus = kalIoctl(prGlueInfo,
3529                     wlanoidSetAddKey,
3530                     prKey,
3531                     prKey->u4Length,
3532                     FALSE,
3533                     FALSE,
3534                     TRUE,
3535                     FALSE,
3536                     &u4BufLen);
3537
3538             if (rStatus != WLAN_STATUS_SUCCESS) {
3539                 DBGLOG(INIT, INFO, ("add key error:%lx\n", rStatus));
3540                 return -EFAULT;
3541             }
3542             break;
3543         }
3544     }
3545
3546     return 0;
3547 } /* wext_set_encode_ext */
3548
3549
3550 /*----------------------------------------------------------------------------*/
3551 /*!
3552 * \brief Set country code
3553 *
3554 * \param[in] prDev Net device requested.
3555 * \param[in] prIwrInfo NULL.
3556 * \param[in] pu4Mode Pointer to new operation mode.
3557 * \param[in] pcExtra NULL.
3558 *
3559 * \retval 0 For success.
3560 * \retval -EOPNOTSUPP If new mode is not supported.
3561 *
3562 * \note Device will run in new operation mode if it is valid.
3563 */
3564 /*----------------------------------------------------------------------------*/
3565 static int
3566 wext_set_country (
3567     IN struct net_device *prNetDev,
3568     IN struct iwreq      *iwr
3569     )
3570 {
3571     P_GLUE_INFO_T   prGlueInfo;
3572     WLAN_STATUS     rStatus;
3573     UINT_32         u4BufLen;
3574     UINT_8          aucCountry[2];
3575
3576     ASSERT(prNetDev);
3577
3578     /* iwr->u.data.pointer should be like "COUNTRY US", "COUNTRY EU"
3579      * and "COUNTRY JP"
3580      */
3581     if (FALSE == GLUE_CHK_PR2(prNetDev, iwr) ||
3582         !iwr->u.data.pointer || iwr->u.data.length < 10) {
3583         return -EINVAL;
3584     }
3585     prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev));
3586
3587     aucCountry[0] = *((PUINT_8)iwr->u.data.pointer + 8);
3588     aucCountry[1] = *((PUINT_8)iwr->u.data.pointer + 9);
3589
3590     rStatus = kalIoctl(prGlueInfo,
3591         wlanoidSetCountryCode,
3592         &aucCountry[0],
3593         2,
3594         FALSE,
3595         FALSE,
3596         TRUE,
3597         FALSE,
3598         &u4BufLen);
3599
3600     return 0;
3601 }
3602
3603 /*----------------------------------------------------------------------------*/
3604 /*!
3605 * \brief ioctl() (Linux Wireless Extensions) routines
3606 *
3607 * \param[in] prDev Net device requested.
3608 * \param[in] ifr The ifreq structure for seeting the wireless extension.
3609 * \param[in] i4Cmd The wireless extension ioctl command.
3610 *
3611 * \retval zero On success.
3612 * \retval -EOPNOTSUPP If the cmd is not supported.
3613 * \retval -EFAULT If copy_to_user goes wrong.
3614 * \retval -EINVAL If any value's out of range.
3615 *
3616 * \note
3617 */
3618 /*----------------------------------------------------------------------------*/
3619 int
3620 wext_support_ioctl (
3621     IN struct net_device *prDev,
3622     IN struct ifreq *prIfReq,
3623     IN int i4Cmd
3624     )
3625 {
3626     /* prIfReq is verified in the caller function wlanDoIOCTL() */
3627     struct iwreq *iwr = (struct iwreq*)prIfReq;
3628     struct iw_request_info rIwReqInfo;
3629     int ret = 0;
3630     char *prExtraBuf = NULL;
3631     UINT_32 u4ExtraSize = 0;
3632
3633     /* prDev is verified in the caller function wlanDoIOCTL() */
3634
3635     //printk("%d CMD:0x%x\n", jiffies_to_msecs(jiffies), i4Cmd);
3636
3637     /* Prepare the call */
3638     rIwReqInfo.cmd = (__u16)i4Cmd;
3639     rIwReqInfo.flags = 0;
3640
3641     switch (i4Cmd) {
3642     case SIOCGIWNAME:   /* 0x8B01, get wireless protocol name */
3643         ret = wext_get_name(prDev, &rIwReqInfo, (char *)&iwr->u.name, NULL);
3644         break;
3645
3646     /* case SIOCSIWNWID: 0x8B02, deprecated */
3647     /* case SIOCGIWNWID: 0x8B03, deprecated */
3648
3649     case SIOCSIWFREQ:   /* 0x8B04, set channel */
3650         ret = wext_set_freq(prDev, NULL, &iwr->u.freq, NULL);
3651         break;
3652
3653     case SIOCGIWFREQ:   /* 0x8B05, get channel */
3654         ret = wext_get_freq(prDev, NULL, &iwr->u.freq, NULL);
3655         break;
3656
3657     case SIOCSIWMODE:   /* 0x8B06, set operation mode */
3658         ret = wext_set_mode(prDev, NULL, &iwr->u.mode, NULL);
3659         //ret = 0;
3660         break;
3661
3662     case SIOCGIWMODE:   /* 0x8B07, get operation mode */
3663         ret = wext_get_mode(prDev, NULL, &iwr->u.mode, NULL);
3664         break;
3665
3666     /* case SIOCSIWSENS: 0x8B08, unsupported */
3667     /* case SIOCGIWSENS: 0x8B09, unsupported */
3668
3669     /* case SIOCSIWRANGE: 0x8B0A, unused */
3670     case SIOCGIWRANGE: /* 0x8B0B, get range of parameters */
3671         if (iwr->u.data.pointer != NULL) {
3672             /* Buffer size shoule be large enough */
3673             if (iwr->u.data.length < sizeof(struct iw_range)) {
3674                 ret = -E2BIG;
3675                 break;
3676             }
3677
3678             prExtraBuf = kalMemAlloc(sizeof(struct iw_range), VIR_MEM_TYPE);
3679             if (!prExtraBuf) {
3680                 ret = - ENOMEM;
3681                 break;
3682             }
3683
3684             /* reset all fields */
3685             memset(prExtraBuf, 0, sizeof(struct iw_range));
3686                 iwr->u.data.length = sizeof(struct iw_range);
3687
3688             ret = wext_get_range(prDev, NULL, &iwr->u.data, prExtraBuf);
3689             /* Push up to the caller */
3690             if (copy_to_user(iwr->u.data.pointer,
3691                     prExtraBuf,
3692                     iwr->u.data.length)) {
3693                     ret = -EFAULT;
3694                 }
3695
3696             kalMemFree(prExtraBuf, VIR_MEM_TYPE, sizeof(struct iw_range));
3697             prExtraBuf = NULL;
3698         }
3699         else {
3700             ret = -EINVAL;
3701         }
3702         break;
3703
3704     case SIOCSIWPRIV: /* 0x8B0C, Country */
3705         ret = wext_set_country(prDev, iwr);
3706         break;
3707
3708     /* case SIOCGIWPRIV: 0x8B0D, handled in wlan_do_ioctl() */
3709     /* caes SIOCSIWSTATS: 0x8B0E, unused */
3710     /* case SIOCGIWSTATS:
3711             get statistics, intercepted by wireless_process_ioctl() in wireless.c,
3712             redirected to dev_iwstats(), dev->get_wireless_stats().
3713     */
3714     /* case SIOCSIWSPY: 0x8B10, unsupported */
3715     /* case SIOCGIWSPY: 0x8B11, unsupported*/
3716     /* case SIOCSIWTHRSPY: 0x8B12, unsupported */
3717     /* case SIOCGIWTHRSPY: 0x8B13, unsupported*/
3718
3719     case SIOCSIWAP: /* 0x8B14, set access point MAC addresses (BSSID) */
3720         if (iwr->u.ap_addr.sa_data[0] == 0 &&
3721             iwr->u.ap_addr.sa_data[1] == 0 &&
3722             iwr->u.ap_addr.sa_data[2] == 0 &&
3723             iwr->u.ap_addr.sa_data[3] == 0 &&
3724             iwr->u.ap_addr.sa_data[4] == 0 &&
3725             iwr->u.ap_addr.sa_data[5] == 0) {
3726             /* WPA Supplicant will set 000000000000 in
3727             ** wpa_driver_wext_deinit(), do nothing here or disassoc again?
3728             */
3729             ret = 0;
3730             break;
3731         }
3732         else {
3733             ret = wext_set_ap(prDev, NULL, &iwr->u.ap_addr, NULL);
3734         }
3735         break;
3736
3737     case SIOCGIWAP: /* 0x8B15, get access point MAC addresses (BSSID) */
3738         ret = wext_get_ap(prDev, NULL, &iwr->u.ap_addr, NULL);
3739         break;
3740
3741     case SIOCSIWMLME: /* 0x8B16, request MLME operation */
3742         /* Fixed length structure */
3743         if (iwr->u.data.length != sizeof(struct iw_mlme)) {
3744             DBGLOG(INIT, INFO, ("MLME buffer strange:%d\n", iwr->u.data.length));
3745             ret = -EINVAL;
3746             break;
3747         }
3748
3749         if (!iwr->u.data.pointer) {
3750             ret = -EINVAL;
3751             break;
3752         }
3753
3754         prExtraBuf = kalMemAlloc(sizeof(struct iw_mlme), VIR_MEM_TYPE);
3755         if (!prExtraBuf) {
3756             ret = - ENOMEM;
3757                 break;
3758         }
3759
3760         if (copy_from_user(prExtraBuf, iwr->u.data.pointer, sizeof(struct iw_mlme))) {
3761             ret = -EFAULT;
3762         }
3763         else {
3764             ret = wext_set_mlme(prDev, NULL, &(iwr->u.data), prExtraBuf);
3765         }
3766
3767         kalMemFree(prExtraBuf, VIR_MEM_TYPE, sizeof(struct iw_mlme));
3768         prExtraBuf = NULL;
3769         break;
3770
3771     /* case SIOCGIWAPLIST: 0x8B17, deprecated */
3772     case SIOCSIWSCAN: /* 0x8B18, scan request */
3773         if (iwr->u.data.pointer == NULL) {
3774             ret = wext_set_scan(prDev, NULL, NULL, NULL);
3775         }
3776 #if WIRELESS_EXT > 17
3777                 else if (iwr->u.data.length == sizeof(struct iw_scan_req)) {
3778             prExtraBuf = kalMemAlloc(MAX_SSID_LEN, VIR_MEM_TYPE);
3779             if (!prExtraBuf) {
3780                 ret = -ENOMEM;
3781                 break;
3782             }
3783             if (copy_from_user(prExtraBuf, ((struct iw_scan_req *) (iwr->u.data.pointer))->essid,
3784                 ((struct iw_scan_req *) (iwr->u.data.pointer))->essid_len)) {
3785                 ret = -EFAULT;
3786             } else {
3787                 ret = wext_set_scan(prDev, NULL, (union iwreq_data *)  &(iwr->u.data), prExtraBuf);
3788             }
3789
3790             kalMemFree(prExtraBuf, VIR_MEM_TYPE, MAX_SSID_LEN);
3791             prExtraBuf = NULL;
3792         }
3793 #endif
3794                 else {
3795             ret = -EINVAL;
3796         }
3797         break;
3798 #if 1
3799     case SIOCGIWSCAN: /* 0x8B19, get scan results */
3800         if (!iwr->u.data.pointer|| !iwr->u.essid.pointer) {
3801             ret = -EINVAL;
3802             break;
3803         }
3804
3805         u4ExtraSize = iwr->u.data.length;
3806         /* allocate the same size of kernel buffer to store scan results. */
3807         prExtraBuf = kalMemAlloc(u4ExtraSize, VIR_MEM_TYPE);
3808             if (!prExtraBuf) {
3809                 ret = - ENOMEM;
3810                 break;
3811             }
3812
3813         /* iwr->u.data.length may be updated by wext_get_scan() */
3814             ret = wext_get_scan(prDev, NULL, &iwr->u.data, prExtraBuf);
3815             if (ret != 0) {
3816                 if (ret == -E2BIG) {
3817                     DBGLOG(INIT, INFO, ("[wifi] wext_get_scan -E2BIG\n"));
3818                 }
3819             }
3820             else {
3821             /* check updated length is valid */
3822                 ASSERT(iwr->u.data.length <= u4ExtraSize);
3823                 if (iwr->u.data.length > u4ExtraSize) {
3824                     DBGLOG(INIT, INFO, ("Updated result length is larger than allocated (%d > %ld)\n",
3825                         iwr->u.data.length, u4ExtraSize));
3826                     iwr->u.data.length = u4ExtraSize;
3827                 }
3828
3829                 if (copy_to_user(iwr->u.data.pointer,
3830                         prExtraBuf,
3831                     iwr->u.data.length)) {
3832                     ret = -EFAULT;
3833                 }
3834             }
3835
3836         kalMemFree(prExtraBuf, VIR_MEM_TYPE, u4ExtraSize);
3837         prExtraBuf = NULL;
3838
3839         break;
3840
3841 #endif
3842
3843 #if 1
3844     case SIOCSIWESSID: /* 0x8B1A, set SSID (network name) */
3845         if (iwr->u.essid.length > IW_ESSID_MAX_SIZE) {
3846             ret = -E2BIG;
3847             break;
3848         }
3849         if (!iwr->u.essid.pointer) {
3850             ret = -EINVAL;
3851             break;
3852         }
3853
3854         prExtraBuf = kalMemAlloc(IW_ESSID_MAX_SIZE + 4, VIR_MEM_TYPE);
3855         if (!prExtraBuf) {
3856             ret = - ENOMEM;
3857             break;
3858         }
3859
3860         if (copy_from_user(prExtraBuf,
3861                 iwr->u.essid.pointer,
3862                 iwr->u.essid.length)) {
3863                 ret = -EFAULT;
3864         }
3865         else {
3866         /* Add trailing '\0' for printk */
3867         //prExtraBuf[iwr->u.essid.length] = 0;
3868         //printk(KERN_INFO "wext_set_essid: %s (%d)\n", prExtraBuf, iwr->u.essid.length);
3869             ret = wext_set_essid(prDev, NULL, &iwr->u.essid, prExtraBuf);
3870             //printk ("set essid %d\n", ret);
3871         }
3872
3873         kalMemFree(prExtraBuf, VIR_MEM_TYPE, IW_ESSID_MAX_SIZE + 4);
3874         prExtraBuf = NULL;
3875         break;
3876
3877 #endif
3878
3879     case SIOCGIWESSID: /* 0x8B1B, get SSID */
3880         if (!iwr->u.essid.pointer) {
3881             ret = -EINVAL;
3882             break;
3883         }
3884
3885         if (iwr->u.essid.length < IW_ESSID_MAX_SIZE) {
3886         DBGLOG(INIT, INFO, ("[wifi] iwr->u.essid.length:%d too small\n",
3887                 iwr->u.essid.length));
3888             ret = -E2BIG;   /* let caller try larger buffer */
3889             break;
3890         }
3891
3892         prExtraBuf = kalMemAlloc(IW_ESSID_MAX_SIZE, VIR_MEM_TYPE);
3893         if (!prExtraBuf) {
3894             ret = -ENOMEM;
3895             break;
3896         }
3897
3898         /* iwr->u.essid.length is updated by wext_get_essid() */
3899
3900         ret = wext_get_essid(prDev, NULL, &iwr->u.essid, prExtraBuf);
3901         if (ret == 0) {
3902             if (copy_to_user(iwr->u.essid.pointer, prExtraBuf, iwr->u.essid.length)) {
3903                 ret = -EFAULT;
3904             }
3905         }
3906
3907         kalMemFree(prExtraBuf, VIR_MEM_TYPE, IW_ESSID_MAX_SIZE);
3908         prExtraBuf = NULL;
3909
3910         break;
3911
3912     /* case SIOCSIWNICKN: 0x8B1C, not supported */
3913     /* case SIOCGIWNICKN: 0x8B1D, not supported */
3914
3915     case SIOCSIWRATE: /* 0x8B20, set default bit rate (bps) */
3916         //ret = wext_set_rate(prDev, &rIwReqInfo, &iwr->u.bitrate, NULL);
3917         break;
3918
3919     case SIOCGIWRATE: /* 0x8B21, get current bit rate (bps) */
3920         ret = wext_get_rate(prDev, NULL, &iwr->u.bitrate, NULL);
3921         break;
3922
3923     case SIOCSIWRTS: /* 0x8B22, set rts/cts threshold */
3924         ret = wext_set_rts(prDev, NULL, &iwr->u.rts, NULL);
3925         break;
3926
3927     case SIOCGIWRTS: /* 0x8B23, get rts/cts threshold */
3928         ret = wext_get_rts(prDev, NULL, &iwr->u.rts, NULL);
3929         break;
3930
3931     /* case SIOCSIWFRAG: 0x8B24, unsupported */
3932     case SIOCGIWFRAG: /* 0x8B25, get frag threshold */
3933         ret = wext_get_frag(prDev, NULL, &iwr->u.frag, NULL);
3934         break;
3935
3936     case SIOCSIWTXPOW: /* 0x8B26, set relative tx power (in %) */
3937         ret = wext_set_txpow(prDev, NULL, &iwr->u.txpower, NULL);
3938         break;
3939
3940     case SIOCGIWTXPOW: /* 0x8B27, get relative tx power (in %) */
3941         ret = wext_get_txpow(prDev, NULL, &iwr->u.txpower, NULL);
3942         break;
3943
3944     /* case SIOCSIWRETRY: 0x8B28, unsupported */
3945     /* case SIOCGIWRETRY: 0x8B29, unsupported */
3946
3947 #if 1
3948     case SIOCSIWENCODE: /* 0x8B2A, set encoding token & mode */
3949         /* Only DISABLED case has NULL pointer and length == 0 */
3950         if (iwr->u.encoding.pointer) {
3951             if (iwr->u.encoding.length > 16) {
3952                 ret = -E2BIG;
3953                 break;
3954             }
3955
3956             u4ExtraSize = iwr->u.encoding.length;
3957             prExtraBuf = kalMemAlloc(u4ExtraSize, VIR_MEM_TYPE);
3958         if (!prExtraBuf) {
3959             ret = -ENOMEM;
3960             break;
3961         }
3962
3963         if (copy_from_user(prExtraBuf,
3964                 iwr->u.encoding.pointer,
3965                 iwr->u.encoding.length)) {
3966                 ret = -EFAULT;
3967             }
3968         }
3969         else if (iwr->u.encoding.length != 0) {
3970             ret = -EINVAL;
3971             break;
3972         }
3973
3974         if (ret == 0) {
3975             ret = wext_set_encode(prDev, NULL, &iwr->u.encoding, prExtraBuf);
3976         }
3977
3978         if (prExtraBuf) {
3979             kalMemFree(prExtraBuf, VIR_MEM_TYPE, u4ExtraSize);
3980             prExtraBuf = NULL;
3981         }
3982         break;
3983
3984     case SIOCGIWENCODE: /* 0x8B2B, get encoding token & mode */
3985         /* check pointer */
3986         ret = wext_get_encode(prDev, NULL, &iwr->u.encoding, NULL);
3987         break;
3988
3989     case SIOCSIWPOWER: /* 0x8B2C, set power management */
3990         ret = wext_set_power(prDev, NULL, &iwr->u.power, NULL);
3991         break;
3992
3993     case SIOCGIWPOWER: /* 0x8B2D, get power management */
3994         ret = wext_get_power(prDev, NULL, &iwr->u.power, NULL);
3995         break;
3996
3997 #if WIRELESS_EXT > 17
3998     case SIOCSIWGENIE: /* 0x8B30, set gen ie */
3999         if (iwr->u.data.pointer) {
4000             P_GLUE_INFO_T prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev));
4001             if (1 /* wlanQueryWapiMode(prGlueInfo->prAdapter) */) {
4002                 /* Fixed length structure */
4003 #if CFG_SUPPORT_WAPI
4004                 if (iwr->u.data.length > 42 /* The max wapi ie buffer */) {
4005                     ret = -EINVAL;
4006                     break;
4007                 }
4008 #endif
4009                 u4ExtraSize = iwr->u.data.length;
4010                 if (u4ExtraSize) {
4011                     prExtraBuf = kalMemAlloc(u4ExtraSize, VIR_MEM_TYPE);
4012                     if (!prExtraBuf) {
4013                         ret = -ENOMEM;
4014                         break;
4015                     }
4016                     if (copy_from_user(prExtraBuf,
4017                         iwr->u.data.pointer,
4018                         iwr->u.data.length)) {
4019                         ret = -EFAULT;
4020                     }
4021                     else {
4022                         WLAN_STATUS    rStatus;
4023                         UINT_32        u4BufLen;
4024 #if CFG_SUPPORT_WAPI
4025                         rStatus = kalIoctl(prGlueInfo,
4026                             wlanoidSetWapiAssocInfo,
4027                             prExtraBuf,
4028                             u4ExtraSize,
4029                             FALSE,
4030                             FALSE,
4031                             TRUE,
4032                             FALSE,
4033                             &u4BufLen);
4034
4035                         if (rStatus != WLAN_STATUS_SUCCESS) {
4036                             //printk(KERN_INFO "[wapi] set wapi assoc info error:%lx\n", rStatus);
4037 #endif
4038 #if CFG_SUPPORT_WPS2
4039                             PUINT_8 prDesiredIE = NULL;
4040                                                         if (wextSrchDesiredWPSIE(prExtraBuf,
4041                                                                                   u4ExtraSize,
4042                                                                                   0xDD,
4043                                                                                   (PUINT_8 *)&prDesiredIE)) {
4044                                 rStatus = kalIoctl(prGlueInfo,
4045                                     wlanoidSetWSCAssocInfo,
4046                                     prDesiredIE,
4047                                     IE_SIZE(prDesiredIE),
4048                                     FALSE,
4049                                     FALSE,
4050                                     TRUE,
4051                                     FALSE,
4052                                     &u4BufLen);
4053                                 if (rStatus != WLAN_STATUS_SUCCESS) {
4054                                                                     //printk(KERN_INFO "[WSC] set WSC assoc info error:%lx\n", rStatus);
4055                                 }
4056                                                         }
4057 #endif
4058 #if CFG_SUPPORT_WAPI
4059                         }
4060 #endif
4061                     }
4062                     kalMemFree(prExtraBuf, VIR_MEM_TYPE, u4ExtraSize);
4063                     prExtraBuf = NULL;
4064                 }
4065             }
4066         }
4067         break;
4068
4069     case SIOCGIWGENIE: /* 0x8B31, get gen ie, unused */
4070         break;
4071
4072 #endif
4073
4074     case SIOCSIWAUTH: /* 0x8B32, set auth mode params */
4075         ret = wext_set_auth(prDev, NULL, &iwr->u.param, NULL);
4076         break;
4077
4078     /* case SIOCGIWAUTH: 0x8B33, unused? */
4079     case SIOCSIWENCODEEXT: /* 0x8B34, set extended encoding token & mode */
4080         if (iwr->u.encoding.pointer) {
4081             u4ExtraSize = iwr->u.encoding.length;
4082             prExtraBuf = kalMemAlloc(u4ExtraSize, VIR_MEM_TYPE);
4083             if (!prExtraBuf) {
4084                 ret = -ENOMEM;
4085                 break;
4086             }
4087
4088             if (copy_from_user(prExtraBuf,
4089                     iwr->u.encoding.pointer,
4090                     iwr->u.encoding.length)) {
4091                 ret = -EFAULT;
4092             }
4093         }
4094         else if (iwr->u.encoding.length != 0) {
4095             ret = -EINVAL;
4096             break;
4097         }
4098
4099         if (ret == 0) {
4100             ret = wext_set_encode_ext(prDev, NULL, &iwr->u.encoding, prExtraBuf);
4101         }
4102
4103         if (prExtraBuf) {
4104             kalMemFree(prExtraBuf, VIR_MEM_TYPE, u4ExtraSize);
4105             prExtraBuf = NULL;
4106         }
4107         break;
4108
4109     /* case SIOCGIWENCODEEXT: 0x8B35, unused? */
4110
4111     case SIOCSIWPMKSA: /* 0x8B36, pmksa cache operation */
4112         #if 1
4113         if (iwr->u.data.pointer) {
4114             /* Fixed length structure */
4115             if (iwr->u.data.length != sizeof(struct iw_pmksa)) {
4116                 ret = -EINVAL;
4117                 break;
4118             }
4119
4120             u4ExtraSize = sizeof(struct iw_pmksa);
4121             prExtraBuf = kalMemAlloc(u4ExtraSize, VIR_MEM_TYPE);
4122             if (!prExtraBuf) {
4123                 ret = -ENOMEM;
4124                 break;
4125             }
4126
4127             if (copy_from_user(prExtraBuf,
4128                   iwr->u.data.pointer,
4129                   sizeof(struct iw_pmksa))) {
4130                 ret = -EFAULT;
4131             }
4132             else {
4133                 switch(((struct iw_pmksa *)prExtraBuf)->cmd) {
4134                 case IW_PMKSA_ADD:
4135                     /*
4136                     printk(KERN_INFO "IW_PMKSA_ADD [" MACSTR "]\n",
4137                         MAC2STR(((struct iw_pmksa *)pExtraBuf)->bssid.sa_data));
4138                     */
4139                     {
4140                     P_GLUE_INFO_T prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev));
4141                     WLAN_STATUS    rStatus;
4142                     UINT_32        u4BufLen;
4143                     P_PARAM_PMKID_T  prPmkid;
4144
4145                     prPmkid =(P_PARAM_PMKID_T)kalMemAlloc(8 + sizeof(PARAM_BSSID_INFO_T), VIR_MEM_TYPE);
4146                     if (!prPmkid) {
4147                         DBGLOG(INIT, INFO, ("Can not alloc memory for IW_PMKSA_ADD\n"));
4148                         ret = -ENOMEM;
4149                         break;
4150                     }
4151
4152                     prPmkid->u4Length = 8 + sizeof(PARAM_BSSID_INFO_T);
4153                     prPmkid->u4BSSIDInfoCount = 1;
4154                     kalMemCopy(prPmkid->arBSSIDInfo->arBSSID,
4155                         ((struct iw_pmksa *)prExtraBuf)->bssid.sa_data,
4156                         6);
4157                     kalMemCopy(prPmkid->arBSSIDInfo->arPMKID,
4158                         ((struct iw_pmksa *)prExtraBuf)->pmkid,
4159                         IW_PMKID_LEN);
4160
4161                     rStatus = kalIoctl(prGlueInfo,
4162                                  wlanoidSetPmkid,
4163                                  prPmkid,
4164                                  sizeof(PARAM_PMKID_T),
4165                                  FALSE,
4166                                  FALSE,
4167                                  TRUE,
4168                                  FALSE,
4169                                  &u4BufLen);
4170
4171                     if (rStatus != WLAN_STATUS_SUCCESS) {
4172                         DBGLOG(INIT, INFO, ("add pmkid error:%lx\n", rStatus));
4173                     }
4174                     kalMemFree(prPmkid, VIR_MEM_TYPE, 8 + sizeof(PARAM_BSSID_INFO_T));
4175                     }
4176                     break;
4177                 case IW_PMKSA_REMOVE:
4178                     /*
4179                     printk(KERN_INFO "IW_PMKSA_REMOVE [" MACSTR "]\n",
4180                         MAC2STR(((struct iw_pmksa *)buf)->bssid.sa_data));
4181                     */
4182                     break;
4183                 case IW_PMKSA_FLUSH:
4184                     /*
4185                     printk(KERN_INFO "IW_PMKSA_FLUSH\n");
4186                     */
4187                     {
4188                     P_GLUE_INFO_T prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev));
4189                     WLAN_STATUS    rStatus;
4190                     UINT_32        u4BufLen;
4191                     P_PARAM_PMKID_T  prPmkid;
4192
4193                     prPmkid =(P_PARAM_PMKID_T)kalMemAlloc(8, VIR_MEM_TYPE);
4194                     if (!prPmkid) {
4195                         DBGLOG(INIT, INFO, ("Can not alloc memory for IW_PMKSA_FLUSH\n"));
4196                         ret = -ENOMEM;
4197                         break;
4198                     }
4199
4200                     prPmkid->u4Length = 8;
4201                     prPmkid->u4BSSIDInfoCount = 0;
4202
4203                     rStatus = kalIoctl(prGlueInfo,
4204                                  wlanoidSetPmkid,
4205                                  prPmkid,
4206                                  sizeof(PARAM_PMKID_T),
4207                                  FALSE,
4208                                  FALSE,
4209                                  TRUE,
4210                                  FALSE,
4211                                  &u4BufLen);
4212
4213                     if (rStatus != WLAN_STATUS_SUCCESS) {
4214                         DBGLOG(INIT, INFO, ("flush pmkid error:%lx\n", rStatus));
4215                     }
4216                     kalMemFree(prPmkid, VIR_MEM_TYPE, 8);
4217                     }
4218                     break;
4219                 default:
4220                     DBGLOG(INIT, INFO, ("UNKNOWN iw_pmksa command:%d\n",
4221                         ((struct iw_pmksa *)prExtraBuf)->cmd));
4222                     ret = -EFAULT;
4223                     break;
4224                 }
4225             }
4226
4227             if (prExtraBuf) {
4228                 kalMemFree(prExtraBuf, VIR_MEM_TYPE, u4ExtraSize);
4229                 prExtraBuf = NULL;
4230             }
4231         }
4232         else if (iwr->u.data.length != 0) {
4233             ret = -EINVAL;
4234             break;
4235         }
4236         #endif
4237         break;
4238
4239 #endif
4240
4241     default:
4242     /* printk(KERN_NOTICE "unsupported IOCTL: 0x%x\n", i4Cmd); */
4243         ret = -EOPNOTSUPP;
4244         break;
4245     }
4246
4247     //printk("%ld CMD:0x%x ret:%d\n", jiffies_to_msecs(jiffies), i4Cmd, ret);
4248
4249     return ret;
4250 } /* wext_support_ioctl */
4251
4252
4253
4254 /*----------------------------------------------------------------------------*/
4255 /*!
4256 * \brief To send an event (RAW socket pacekt) to user process actively.
4257 *
4258 * \param[in] prGlueInfo Glue layer info.
4259 * \param[in] u4cmd Whcih event command we want to indicate to user process.
4260 * \param[in] pData Data buffer to be indicated.
4261 * \param[in] dataLen Available data size in pData.
4262 *
4263 * \return (none)
4264 *
4265 * \note Event is indicated to upper layer if cmd is supported and data is valid.
4266 *       Using of kernel symbol wireless_send_event(), which is defined in
4267 *      <net/iw_handler.h> after WE-14 (2.4.20).
4268 */
4269 /*----------------------------------------------------------------------------*/
4270 void
4271 wext_indicate_wext_event (
4272     IN P_GLUE_INFO_T prGlueInfo,
4273     IN unsigned int u4Cmd,
4274     IN unsigned char *pucData,
4275     IN unsigned int u4dataLen
4276     )
4277 {
4278     union iwreq_data wrqu;
4279     unsigned char *pucExtraInfo = NULL;
4280 #if WIRELESS_EXT >= 15
4281     unsigned char *pucDesiredIE = NULL;
4282     unsigned char aucExtraInfoBuf[200];
4283 #endif
4284 #if WIRELESS_EXT < 18
4285         int i;
4286 #endif
4287
4288     memset(&wrqu, 0, sizeof(wrqu));
4289
4290     switch (u4Cmd) {
4291     case SIOCGIWTXPOW:
4292         memcpy(&wrqu.power, pucData, u4dataLen);
4293         break;
4294     case SIOCGIWSCAN:
4295         complete_all(&prGlueInfo->rScanComp);
4296         break;
4297
4298     case SIOCGIWAP:
4299         if (pucData) {
4300             memcpy(&wrqu.ap_addr.sa_data, pucData, ETH_ALEN);
4301         }
4302         else {
4303             memset(&wrqu.ap_addr.sa_data, 0, ETH_ALEN);
4304         }
4305         break;
4306
4307     case IWEVASSOCREQIE:
4308 #if WIRELESS_EXT < 15
4309         /* under WE-15, no suitable Event can be used */
4310         goto skip_indicate_event;
4311 #else
4312         /* do supplicant a favor, parse to the start of WPA/RSN IE */
4313         if (wextSrchDesiredWPAIE(pucData, u4dataLen, 0x30, &pucDesiredIE)) {
4314             /* RSN IE found */
4315         }
4316 #if 0
4317         else if (wextSrchDesiredWPSIE(pucData, u4dataLen, 0xDD, &pucDesiredIE)) {
4318             /* WPS IE found */
4319         }
4320 #endif
4321         else if (wextSrchDesiredWPAIE(pucData, u4dataLen, 0xDD, &pucDesiredIE)) {
4322             /* WPA IE found */
4323         }
4324 #if CFG_SUPPORT_WAPI /* Android+ */
4325         else if (wextSrchDesiredWAPIIE(pucData, u4dataLen, &pucDesiredIE)) {
4326             //printk("wextSrchDesiredWAPIIE!!\n");
4327             /* WAPI IE found */
4328         }
4329 #endif
4330         else {
4331             /* no WPA/RSN IE found, skip this event */
4332             goto skip_indicate_event;
4333         }
4334
4335     #if WIRELESS_EXT < 18
4336         /* under WE-18, only IWEVCUSTOM can be used */
4337         u4Cmd = IWEVCUSTOM;
4338         pucExtraInfo = aucExtraInfoBuf;
4339         pucExtraInfo += sprintf(pucExtraInfo, "ASSOCINFO(ReqIEs=");
4340         /* printk(KERN_DEBUG "assoc info buffer size needed:%d\n", infoElemLen * 2 + 17); */
4341         /* translate binary string to hex string, requirement of IWEVCUSTOM */
4342         for (i = 0; i < pucDesiredIE[1] + 2 ; ++i) {
4343             pucExtraInfo += sprintf(pucExtraInfo, "%02x", pucDesiredIE[i]);
4344         }
4345         pucExtraInfo = aucExtraInfoBuf;
4346         wrqu.data.length = 17 + (pucDesiredIE[1] + 2) * 2;
4347     #else
4348          /* IWEVASSOCREQIE, indicate binary string */
4349         pucExtraInfo = pucDesiredIE;
4350         wrqu.data.length = pucDesiredIE[1] + 2;
4351     #endif
4352 #endif  /* WIRELESS_EXT < 15 */
4353         break;
4354
4355     case IWEVMICHAELMICFAILURE:
4356 #if WIRELESS_EXT < 15
4357         /* under WE-15, no suitable Event can be used */
4358         goto skip_indicate_event;
4359 #else
4360         if (pucData) {
4361             P_PARAM_AUTH_REQUEST_T pAuthReq = (P_PARAM_AUTH_REQUEST_T)pucData;
4362             /* under WE-18, only IWEVCUSTOM can be used */
4363             u4Cmd = IWEVCUSTOM;
4364             pucExtraInfo = aucExtraInfoBuf;
4365             pucExtraInfo += sprintf(pucExtraInfo,
4366                     "MLME-MICHAELMICFAILURE.indication ");
4367             pucExtraInfo += sprintf(pucExtraInfo,
4368                                 "%s",
4369                                 (pAuthReq->u4Flags == PARAM_AUTH_REQUEST_GROUP_ERROR) ?
4370                                 "groupcast " : "unicast ");
4371
4372             wrqu.data.length = pucExtraInfo - aucExtraInfoBuf;
4373             pucExtraInfo = aucExtraInfoBuf;
4374         }
4375 #endif /* WIRELESS_EXT < 15 */
4376         break;
4377
4378     case IWEVPMKIDCAND:
4379         if (prGlueInfo->rWpaInfo.u4WpaVersion == IW_AUTH_WPA_VERSION_WPA2 &&
4380             prGlueInfo->rWpaInfo.u4KeyMgmt == IW_AUTH_KEY_MGMT_802_1X) {
4381
4382             /* only used in WPA2 */
4383 #if WIRELESS_EXT >= 18
4384             P_PARAM_PMKID_CANDIDATE_T prPmkidCand = (P_PARAM_PMKID_CANDIDATE_T)pucData;
4385
4386             struct  iw_pmkid_cand rPmkidCand;
4387             pucExtraInfo = aucExtraInfoBuf;
4388
4389             rPmkidCand.flags = prPmkidCand->u4Flags;
4390             rPmkidCand.index = 0;
4391             kalMemCopy(rPmkidCand.bssid.sa_data, prPmkidCand->arBSSID, 6);
4392
4393             kalMemCopy(pucExtraInfo, (PUINT_8)&rPmkidCand, sizeof(struct iw_pmkid_cand));
4394             wrqu.data.length = sizeof(struct iw_pmkid_cand);
4395
4396             /* pmkid canadidate list is supported after WE-18 */
4397             /* indicate struct iw_pmkid_cand */
4398 #else
4399             /* printk(KERN_INFO "IWEVPMKIDCAND event skipped, WE < 18\n"); */
4400             goto skip_indicate_event;
4401 #endif
4402         }
4403         else {
4404             /* printk(KERN_INFO "IWEVPMKIDCAND event skipped, NOT WPA2\n"); */
4405             goto skip_indicate_event;
4406         }
4407         break;
4408
4409     case IWEVCUSTOM:
4410         u4Cmd = IWEVCUSTOM;
4411         pucExtraInfo = aucExtraInfoBuf;
4412         kalMemCopy(pucExtraInfo, pucData, sizeof(PTA_IPC_T));
4413         wrqu.data.length = sizeof(PTA_IPC_T);
4414         break;
4415
4416         default:
4417             /* printk(KERN_INFO "Unsupported wext event:%x\n", cmd); */
4418             goto skip_indicate_event;
4419     }
4420
4421     /* Send event to user space */
4422     wireless_send_event(prGlueInfo->prDevHandler, u4Cmd, &wrqu, pucExtraInfo);
4423
4424 skip_indicate_event:
4425     return;
4426 } /* wext_indicate_wext_event */
4427
4428
4429 /*----------------------------------------------------------------------------*/
4430 /*!
4431 * \brief A method of struct net_device, to get the network interface statistical
4432 *        information.
4433 *
4434 * Whenever an application needs to get statistics for the interface, this method
4435 * is called. This happens, for example, when ifconfig or netstat -i is run.
4436 *
4437 * \param[in] pDev Pointer to struct net_device.
4438 *
4439 * \return net_device_stats buffer pointer.
4440 *
4441 */
4442 /*----------------------------------------------------------------------------*/
4443 struct iw_statistics *
4444 wext_get_wireless_stats (
4445     struct net_device *prDev
4446     )
4447 {
4448
4449     WLAN_STATUS rStatus = WLAN_STATUS_FAILURE;
4450     P_GLUE_INFO_T prGlueInfo = NULL;
4451     struct iw_statistics *pStats = NULL;
4452     INT_32 i4Rssi;
4453     UINT_32 bufLen = 0;
4454
4455
4456     prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev));
4457      ASSERT(prGlueInfo);
4458     if (!prGlueInfo) {
4459         goto stat_out;
4460     }
4461
4462     pStats = (struct iw_statistics *) (&(prGlueInfo->rIwStats));
4463
4464     if (!prDev || !netif_carrier_ok(prDev)) {
4465         /* network not connected */
4466         goto stat_out;
4467     }
4468
4469     rStatus = kalIoctl(prGlueInfo,
4470         wlanoidQueryRssi,
4471         &i4Rssi,
4472         sizeof(i4Rssi),
4473         TRUE,
4474         TRUE,
4475         TRUE,
4476         FALSE,
4477         &bufLen);
4478
4479 stat_out:
4480     return pStats;
4481 } /* wlan_get_wireless_stats */
4482
4483 /*----------------------------------------------------------------------------*/
4484 /*!
4485 * \brief To report the private supported IOCTLs table to user space.
4486 *
4487 * \param[in] prNetDev Net device requested.
4488 * \param[out] prIfReq Pointer to ifreq structure, content is copied back to
4489 *                  user space buffer in gl_iwpriv_table.
4490 *
4491 * \retval 0 For success.
4492 * \retval -E2BIG For user's buffer size is too small.
4493 * \retval -EFAULT For fail.
4494 *
4495 */
4496 /*----------------------------------------------------------------------------*/
4497 int
4498 wext_get_priv (
4499     IN struct net_device *prNetDev,
4500     IN struct ifreq *prIfReq
4501     )
4502 {
4503     /* prIfReq is verified in the caller function wlanDoIOCTL() */
4504     struct iwreq *prIwReq = (struct iwreq *)prIfReq;
4505     struct iw_point *prData= (struct iw_point *)&prIwReq->u.data;
4506     UINT_16 u2BufferSize = 0;
4507
4508     u2BufferSize = prData->length;
4509
4510     /* update our private table size */
4511     prData->length = (__u16)sizeof(rIwPrivTable)/sizeof(struct iw_priv_args);
4512
4513     if (u2BufferSize < prData->length) {
4514         return -E2BIG;
4515     }
4516
4517     if (prData->length) {
4518         if (copy_to_user(prData->pointer, rIwPrivTable, sizeof(rIwPrivTable))) {
4519             return -EFAULT;
4520         }
4521     }
4522
4523     return 0;
4524 } /* wext_get_priv */
4525
4526 #endif /* WIRELESS_EXT */
4527
4528
4529