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