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