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