• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Linux Wireless Extensions support
3  *
4  * Copyright (C) 1999-2010, Broadcom Corporation
5  *
6  *      Unless you and Broadcom execute a separate written software license
7  * agreement governing use of this software, this software is licensed to you
8  * under the terms of the GNU General Public License version 2 (the "GPL"),
9  * available at http://www.broadcom.com/licenses/GPLv2.php, with the
10  * following added to such license:
11  *
12  *      As a special exception, the copyright holders of this software give you
13  * permission to link this software with independent modules, and to copy and
14  * distribute the resulting executable under terms of your choice, provided that
15  * you also meet, for each linked independent module, the terms and conditions of
16  * the license of that module.  An independent module is a module which is not
17  * derived from this software.  The special exception does not apply to any
18  * modifications of the software.
19  *
20  *      Notwithstanding the above, under no circumstances may you combine this
21  * software in any way with any other Broadcom software provided under a license
22  * other than the GPL, without Broadcom's express prior written consent.
23  *
24  * $Id: wl_iw.c,v 1.51.4.9.2.6.4.142.4.13 2010/09/15 03:34:56 Exp $
25  */
26 
27 
28 #include <typedefs.h>
29 #include <linuxver.h>
30 #include <osl.h>
31 
32 #include <bcmutils.h>
33 #include <bcmendian.h>
34 #include <proto/ethernet.h>
35 
36 #include <linux/if_arp.h>
37 #include <asm/uaccess.h>
38 
39 #include <dngl_stats.h>
40 #include <dhd.h>
41 #include <dhdioctl.h>
42 
43 typedef void wlc_info_t;
44 typedef void wl_info_t;
45 typedef const struct si_pub  si_t;
46 #include <wlioctl.h>
47 
48 #include <proto/ethernet.h>
49 #include <dngl_stats.h>
50 #include <dhd.h>
51 #define WL_ERROR(x) printf x
52 #define WL_TRACE(x)
53 #define WL_ASSOC(x)
54 #define WL_INFORM(x)
55 #define WL_WSEC(x)
56 #define WL_SCAN(x)
57 
58 #include <wl_iw.h>
59 
60 
61 
62 #ifndef IW_ENCODE_ALG_SM4
63 #define IW_ENCODE_ALG_SM4 0x20
64 #endif
65 
66 #ifndef IW_AUTH_WAPI_ENABLED
67 #define IW_AUTH_WAPI_ENABLED 0x20
68 #endif
69 
70 #ifndef IW_AUTH_WAPI_VERSION_1
71 #define IW_AUTH_WAPI_VERSION_1	0x00000008
72 #endif
73 
74 #ifndef IW_AUTH_CIPHER_SMS4
75 #define IW_AUTH_CIPHER_SMS4	0x00000020
76 #endif
77 
78 #ifndef IW_AUTH_KEY_MGMT_WAPI_PSK
79 #define IW_AUTH_KEY_MGMT_WAPI_PSK 4
80 #endif
81 
82 #ifndef IW_AUTH_KEY_MGMT_WAPI_CERT
83 #define IW_AUTH_KEY_MGMT_WAPI_CERT 8
84 #endif
85 
86 
87 #define IW_WSEC_ENABLED(wsec)	((wsec) & (WEP_ENABLED | TKIP_ENABLED | AES_ENABLED | SMS4_ENABLED))
88 
89 #include <linux/rtnetlink.h>
90 #include <linux/mutex.h>
91 
92 #define WL_IW_USE_ISCAN  1
93 #define ENABLE_ACTIVE_PASSIVE_SCAN_SUPPRESS  1
94 
95 #if defined(SOFTAP)
96 #define WL_SOFTAP(x) printk x
97 static struct net_device *priv_dev;
98 static bool ap_cfg_running = FALSE;
99 static bool ap_fw_loaded = FALSE;
100 struct net_device *ap_net_dev = NULL;
101 struct semaphore  ap_eth_sema;
102 static int wl_iw_set_ap_security(struct net_device *dev, struct ap_profile *ap);
103 static int wl_iw_softap_deassoc_stations(struct net_device *dev);
104 #endif
105 
106 #define WL_IW_IOCTL_CALL(func_call) \
107 	do {				\
108 		func_call;		\
109 	} while (0)
110 
111 static int		g_onoff = G_WLAN_SET_ON;
112 wl_iw_extra_params_t	 g_wl_iw_params;
113 static struct mutex	wl_start_lock;
114 static struct mutex	wl_cache_lock;
115 
116 extern bool wl_iw_conn_status_str(uint32 event_type, uint32 status,
117 	uint32 reason, char* stringBuf, uint buflen);
118 #include <bcmsdbus.h>
119 extern void dhd_customer_gpio_wlan_ctrl(int onoff);
120 extern uint dhd_dev_reset(struct net_device *dev, uint8 flag);
121 extern void dhd_dev_init_ioctl(struct net_device *dev);
122 int dev_iw_write_cfg1_bss_var(struct net_device *dev, int val);
123 
124 uint wl_msg_level = WL_ERROR_VAL;
125 
126 #define MAX_WLIW_IOCTL_LEN 1024
127 
128 
129 #if defined(IL_BIGENDIAN)
130 #include <bcmendian.h>
131 #define htod32(i) (bcmswap32(i))
132 #define htod16(i) (bcmswap16(i))
133 #define dtoh32(i) (bcmswap32(i))
134 #define dtoh16(i) (bcmswap16(i))
135 #define htodchanspec(i) htod16(i)
136 #define dtohchanspec(i) dtoh16(i)
137 #else
138 #define htod32(i) i
139 #define htod16(i) i
140 #define dtoh32(i) i
141 #define dtoh16(i) i
142 #define htodchanspec(i) i
143 #define dtohchanspec(i) i
144 #endif
145 
146 #ifdef CONFIG_WIRELESS_EXT
147 
148 extern struct iw_statistics *dhd_get_wireless_stats(struct net_device *dev);
149 extern int dhd_wait_pend8021x(struct net_device *dev);
150 #endif
151 
152 #if WIRELESS_EXT < 19
153 #define IW_IOCTL_IDX(cmd)	((cmd) - SIOCIWFIRST)
154 #define IW_EVENT_IDX(cmd)	((cmd) - IWEVFIRST)
155 #endif
156 
157 static void *g_scan = NULL;
158 static volatile uint g_scan_specified_ssid;
159 static wlc_ssid_t g_specific_ssid;
160 
161 static wlc_ssid_t g_ssid;
162 
163 static wl_iw_ss_cache_ctrl_t g_ss_cache_ctrl;
164 static volatile uint g_first_broadcast_scan;
165 static volatile uint g_first_counter_scans;
166 #define MAX_ALLOWED_BLOCK_SCAN_FROM_FIRST_SCAN 3
167 
168 
169 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0))
170 #define DAEMONIZE(a) daemonize(a); \
171 	allow_signal(SIGKILL); \
172 	allow_signal(SIGTERM);
173 #else
174 #define RAISE_RX_SOFTIRQ() \
175 	cpu_raise_softirq(smp_processor_id(), NET_RX_SOFTIRQ)
176 #define DAEMONIZE(a) daemonize(); \
177 	do { if (a) \
178 		strncpy(current->comm, a, MIN(sizeof(current->comm), (strlen(a) + 1))); \
179 	} while (0);
180 #endif
181 
182 #if defined(WL_IW_USE_ISCAN)
183 #if !defined(CSCAN)
184 static void wl_iw_free_ss_cache(void);
185 static int   wl_iw_run_ss_cache_timer(int kick_off);
186 #endif
187 int  wl_iw_iscan_set_scan_broadcast_prep(struct net_device *dev, uint flag);
188 static int dev_wlc_bufvar_set(struct net_device *dev, char *name, char *buf, int len);
189 #define ISCAN_STATE_IDLE   0
190 #define ISCAN_STATE_SCANING 1
191 
192 #define WLC_IW_ISCAN_MAXLEN   2048
193 typedef struct iscan_buf {
194 	struct iscan_buf * next;
195 	char   iscan_buf[WLC_IW_ISCAN_MAXLEN];
196 } iscan_buf_t;
197 
198 typedef struct iscan_info {
199 	struct net_device *dev;
200 	struct timer_list timer;
201 	uint32 timer_ms;
202 	uint32 timer_on;
203 	int    iscan_state;
204 	iscan_buf_t * list_hdr;
205 	iscan_buf_t * list_cur;
206 
207 
208 	long sysioc_pid;
209 	struct semaphore sysioc_sem;
210 	struct completion sysioc_exited;
211 
212 	uint32 scan_flag;
213 #if defined CSCAN
214 	char ioctlbuf[WLC_IOCTL_MEDLEN];
215 #else
216 	char ioctlbuf[WLC_IOCTL_SMLEN];
217 #endif
218 	wl_iscan_params_t *iscan_ex_params_p;
219 	int iscan_ex_param_size;
220 } iscan_info_t;
221 #define COEX_DHCP 1
222 static void wl_iw_bt_flag_set(struct net_device *dev, bool set);
223 static void wl_iw_bt_release(void);
224 
225 typedef enum bt_coex_status {
226 	BT_DHCP_IDLE = 0,
227 	BT_DHCP_START,
228 	BT_DHCP_OPPORTUNITY_WINDOW,
229 	BT_DHCP_FLAG_FORCE_TIMEOUT
230 } coex_status_t;
231 #define BT_DHCP_OPPORTUNITY_WINDOW_TIEM	2500
232 #define BT_DHCP_FLAG_FORCE_TIME				5500
233 
234 typedef struct bt_info {
235 	struct net_device *dev;
236 	struct timer_list timer;
237 	uint32 timer_ms;
238 	uint32 timer_on;
239 	int	bt_state;
240 
241 
242 	long bt_pid;
243 	struct semaphore bt_sem;
244 	struct completion bt_exited;
245 } bt_info_t;
246 
247 bt_info_t *g_bt = NULL;
248 static void wl_iw_bt_timerfunc(ulong data);
249 iscan_info_t *g_iscan = NULL;
250 static void wl_iw_timerfunc(ulong data);
251 static void wl_iw_set_event_mask(struct net_device *dev);
252 static int
253 wl_iw_iscan(iscan_info_t *iscan, wlc_ssid_t *ssid, uint16 action);
254 #endif
255 static int
256 wl_iw_set_scan(
257 	struct net_device *dev,
258 	struct iw_request_info *info,
259 	union iwreq_data *wrqu,
260 	char *extra
261 );
262 
263 #ifndef CSCAN
264 static int
265 wl_iw_get_scan(
266 	struct net_device *dev,
267 	struct iw_request_info *info,
268 	struct iw_point *dwrq,
269 	char *extra
270 );
271 
272 static uint
273 wl_iw_get_scan_prep(
274 	wl_scan_results_t *list,
275 	struct iw_request_info *info,
276 	char *extra,
277 	short max_size
278 );
279 #endif
280 
swap_key_from_BE(wl_wsec_key_t * key)281 static void swap_key_from_BE(
282 	        wl_wsec_key_t *key
283 )
284 {
285 	key->index = htod32(key->index);
286 	key->len = htod32(key->len);
287 	key->algo = htod32(key->algo);
288 	key->flags = htod32(key->flags);
289 	key->rxiv.hi = htod32(key->rxiv.hi);
290 	key->rxiv.lo = htod16(key->rxiv.lo);
291 	key->iv_initialized = htod32(key->iv_initialized);
292 }
293 
swap_key_to_BE(wl_wsec_key_t * key)294 static void swap_key_to_BE(
295 	        wl_wsec_key_t *key
296 )
297 {
298 	key->index = dtoh32(key->index);
299 	key->len = dtoh32(key->len);
300 	key->algo = dtoh32(key->algo);
301 	key->flags = dtoh32(key->flags);
302 	key->rxiv.hi = dtoh32(key->rxiv.hi);
303 	key->rxiv.lo = dtoh16(key->rxiv.lo);
304 	key->iv_initialized = dtoh32(key->iv_initialized);
305 }
306 
307 static int
dev_wlc_ioctl(struct net_device * dev,int cmd,void * arg,int len)308 dev_wlc_ioctl(
309 	struct net_device *dev,
310 	int cmd,
311 	void *arg,
312 	int len
313 )
314 {
315 	struct ifreq ifr;
316 	wl_ioctl_t ioc;
317 	mm_segment_t fs;
318 	int ret = -EINVAL;
319 
320 	if (!dev) {
321 		WL_ERROR(("%s: dev is null\n", __FUNCTION__));
322 		return ret;
323 	}
324 
325 	net_os_wake_lock(dev);
326 
327 	WL_INFORM(("\n%s, PID:%x: send Local IOCTL -> dhd: cmd:0x%x, buf:%p, len:%d ,\n",
328 		__FUNCTION__, current->pid, cmd, arg, len));
329 
330 	if (g_onoff == G_WLAN_SET_ON) {
331 		memset(&ioc, 0, sizeof(ioc));
332 		ioc.cmd = cmd;
333 		ioc.buf = arg;
334 		ioc.len = len;
335 
336 		strcpy(ifr.ifr_name, dev->name);
337 		ifr.ifr_data = (caddr_t) &ioc;
338 
339 		ret = dev_open(dev);
340 		if (ret) {
341 			WL_ERROR(("%s: Error dev_open: %d\n", __func__, ret));
342 			net_os_wake_unlock(dev);
343 			return ret;
344 		}
345 
346 		fs = get_fs();
347 		set_fs(get_ds());
348 #if (LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 31))
349 		ret = dev->do_ioctl(dev, &ifr, SIOCDEVPRIVATE);
350 #else
351 		ret = dev->netdev_ops->ndo_do_ioctl(dev, &ifr, SIOCDEVPRIVATE);
352 #endif
353 		set_fs(fs);
354 	}
355 	else {
356 		WL_TRACE(("%s: call after driver stop : ignored\n", __FUNCTION__));
357 	}
358 
359 	net_os_wake_unlock(dev);
360 
361 	return ret;
362 }
363 
364 
365 static int
dev_wlc_intvar_get_reg(struct net_device * dev,char * name,uint reg,int * retval)366 dev_wlc_intvar_get_reg(
367 	struct net_device *dev,
368 	char *name,
369 	uint  reg,
370 	int *retval)
371 {
372 	union {
373 		char buf[WLC_IOCTL_SMLEN];
374 		int val;
375 	} var;
376 	int error;
377 
378 	uint len;
379 	len = bcm_mkiovar(name, (char *)(&reg), sizeof(reg), (char *)(&var), sizeof(var.buf));
380 	ASSERT(len);
381 	error = dev_wlc_ioctl(dev, WLC_GET_VAR, (void *)&var, len);
382 
383 	*retval = dtoh32(var.val);
384 	return (error);
385 }
386 
387 
388 static int
dev_wlc_intvar_set_reg(struct net_device * dev,char * name,char * addr,char * val)389 dev_wlc_intvar_set_reg(
390 	struct net_device *dev,
391 	char *name,
392 	char *addr,
393 	char * val)
394 {
395 	char reg_addr[8];
396 
397 	memset(reg_addr, 0, sizeof(reg_addr));
398 	memcpy((char *)&reg_addr[0], (char *)addr, 4);
399 	memcpy((char *)&reg_addr[4], (char *)val, 4);
400 
401 	return (dev_wlc_bufvar_set(dev, name,  (char *)&reg_addr[0], sizeof(reg_addr)));
402 }
403 
404 
405 static int
dev_wlc_intvar_set(struct net_device * dev,char * name,int val)406 dev_wlc_intvar_set(
407 	struct net_device *dev,
408 	char *name,
409 	int val)
410 {
411 	char buf[WLC_IOCTL_SMLEN];
412 	uint len;
413 
414 	val = htod32(val);
415 	len = bcm_mkiovar(name, (char *)(&val), sizeof(val), buf, sizeof(buf));
416 	ASSERT(len);
417 
418 	return (dev_wlc_ioctl(dev, WLC_SET_VAR, buf, len));
419 }
420 
421 #if defined(WL_IW_USE_ISCAN)
422 static int
dev_iw_iovar_setbuf(struct net_device * dev,char * iovar,void * param,int paramlen,void * bufptr,int buflen)423 dev_iw_iovar_setbuf(
424 	struct net_device *dev,
425 	char *iovar,
426 	void *param,
427 	int paramlen,
428 	void *bufptr,
429 	int buflen)
430 {
431 	int iolen;
432 
433 	iolen = bcm_mkiovar(iovar, param, paramlen, bufptr, buflen);
434 	ASSERT(iolen);
435 
436 	if (iolen == 0)
437 		return 0;
438 
439 	return (dev_wlc_ioctl(dev, WLC_SET_VAR, bufptr, iolen));
440 }
441 
442 static int
dev_iw_iovar_getbuf(struct net_device * dev,char * iovar,void * param,int paramlen,void * bufptr,int buflen)443 dev_iw_iovar_getbuf(
444 	struct net_device *dev,
445 	char *iovar,
446 	void *param,
447 	int paramlen,
448 	void *bufptr,
449 	int buflen)
450 {
451 	int iolen;
452 
453 	iolen = bcm_mkiovar(iovar, param, paramlen, bufptr, buflen);
454 	ASSERT(iolen);
455 
456 	return (dev_wlc_ioctl(dev, WLC_GET_VAR, bufptr, buflen));
457 }
458 #endif
459 
460 
461 #if WIRELESS_EXT > 17
462 static int
dev_wlc_bufvar_set(struct net_device * dev,char * name,char * buf,int len)463 dev_wlc_bufvar_set(
464 	struct net_device *dev,
465 	char *name,
466 	char *buf, int len)
467 {
468 	static char ioctlbuf[MAX_WLIW_IOCTL_LEN];
469 	uint buflen;
470 
471 	buflen = bcm_mkiovar(name, buf, len, ioctlbuf, sizeof(ioctlbuf));
472 	ASSERT(buflen);
473 
474 	return (dev_wlc_ioctl(dev, WLC_SET_VAR, ioctlbuf, buflen));
475 }
476 #endif
477 
478 
479 static int
dev_wlc_bufvar_get(struct net_device * dev,char * name,char * buf,int buflen)480 dev_wlc_bufvar_get(
481 	struct net_device *dev,
482 	char *name,
483 	char *buf, int buflen)
484 {
485 	static char ioctlbuf[MAX_WLIW_IOCTL_LEN];
486 	int error;
487 	uint len;
488 
489 	len = bcm_mkiovar(name, NULL, 0, ioctlbuf, sizeof(ioctlbuf));
490 	ASSERT(len);
491 	error = dev_wlc_ioctl(dev, WLC_GET_VAR, (void *)ioctlbuf, MAX_WLIW_IOCTL_LEN);
492 	if (!error)
493 		bcopy(ioctlbuf, buf, buflen);
494 
495 	return (error);
496 }
497 
498 
499 
500 static int
dev_wlc_intvar_get(struct net_device * dev,char * name,int * retval)501 dev_wlc_intvar_get(
502 	struct net_device *dev,
503 	char *name,
504 	int *retval)
505 {
506 	union {
507 		char buf[WLC_IOCTL_SMLEN];
508 		int val;
509 	} var;
510 	int error;
511 
512 	uint len;
513 	uint data_null;
514 
515 	len = bcm_mkiovar(name, (char *)(&data_null), 0, (char *)(&var), sizeof(var.buf));
516 	ASSERT(len);
517 	error = dev_wlc_ioctl(dev, WLC_GET_VAR, (void *)&var, len);
518 
519 	*retval = dtoh32(var.val);
520 
521 	return (error);
522 }
523 
524 
525 #if WIRELESS_EXT > 12
526 static int
wl_iw_set_active_scan(struct net_device * dev,struct iw_request_info * info,union iwreq_data * wrqu,char * extra)527 wl_iw_set_active_scan(
528 	struct net_device *dev,
529 	struct iw_request_info *info,
530 	union iwreq_data *wrqu,
531 	char *extra
532 )
533 {
534 	int as = 0;
535 	int error = 0;
536 	char *p = extra;
537 
538 #if defined(WL_IW_USE_ISCAN)
539 	if (g_iscan->iscan_state == ISCAN_STATE_IDLE)
540 #endif
541 		error = dev_wlc_ioctl(dev, WLC_SET_PASSIVE_SCAN, &as, sizeof(as));
542 #if defined(WL_IW_USE_ISCAN)
543 	else
544 		g_iscan->scan_flag = as;
545 #endif
546 	p += snprintf(p, MAX_WX_STRING, "OK");
547 
548 	wrqu->data.length = p - extra + 1;
549 	return error;
550 }
551 
552 static int
wl_iw_set_passive_scan(struct net_device * dev,struct iw_request_info * info,union iwreq_data * wrqu,char * extra)553 wl_iw_set_passive_scan(
554 	struct net_device *dev,
555 	struct iw_request_info *info,
556 	union iwreq_data *wrqu,
557 	char *extra
558 )
559 {
560 	int ps = 1;
561 	int error = 0;
562 	char *p = extra;
563 
564 #if defined(WL_IW_USE_ISCAN)
565 	if (g_iscan->iscan_state == ISCAN_STATE_IDLE) {
566 #endif
567 
568 
569 		if (g_scan_specified_ssid == 0) {
570 			error = dev_wlc_ioctl(dev, WLC_SET_PASSIVE_SCAN, &ps, sizeof(ps));
571 		}
572 #if defined(WL_IW_USE_ISCAN)
573 	}
574 	else
575 		g_iscan->scan_flag = ps;
576 #endif
577 
578 	p += snprintf(p, MAX_WX_STRING, "OK");
579 
580 	wrqu->data.length = p - extra + 1;
581 	return error;
582 }
583 
584 static int
wl_iw_get_macaddr(struct net_device * dev,struct iw_request_info * info,union iwreq_data * wrqu,char * extra)585 wl_iw_get_macaddr(
586 	struct net_device *dev,
587 	struct iw_request_info *info,
588 	union iwreq_data *wrqu,
589 	char *extra
590 )
591 {
592 	int error;
593 	char buf[128];
594 	struct ether_addr *id;
595 	char *p = extra;
596 
597 
598 	strcpy(buf, "cur_etheraddr");
599 	error = dev_wlc_ioctl(dev, WLC_GET_VAR, buf, sizeof(buf));
600 	id = (struct ether_addr *) buf;
601 	p += snprintf(p, MAX_WX_STRING, "Macaddr = %02X:%02X:%02X:%02X:%02X:%02X\n",
602 		id->octet[0], id->octet[1], id->octet[2],
603 		id->octet[3], id->octet[4], id->octet[5]);
604 	wrqu->data.length = p - extra + 1;
605 
606 	return error;
607 }
608 
609 
610 static int
wl_iw_set_country(struct net_device * dev,struct iw_request_info * info,union iwreq_data * wrqu,char * extra)611 wl_iw_set_country(
612 	struct net_device *dev,
613 	struct iw_request_info *info,
614 	union iwreq_data *wrqu,
615 	char *extra
616 )
617 {
618 	char country_code[WLC_CNTRY_BUF_SZ];
619 	int error = 0;
620 	char *p = extra;
621 	int country_offset;
622 	int country_code_size;
623 
624 	WL_TRACE(("%s\n", __FUNCTION__));
625 	memset(country_code, 0, sizeof(country_code));
626 
627 	country_offset = strcspn(extra, " ");
628 	country_code_size = strlen(extra) - country_offset;
629 
630 
631 	if (country_offset != 0) {
632 		strncpy(country_code, extra + country_offset + 1,
633 			MIN(country_code_size, sizeof(country_code)));
634 
635 
636 		if ((error = dev_wlc_ioctl(dev, WLC_SET_COUNTRY,
637 			&country_code, sizeof(country_code))) >= 0) {
638 			p += snprintf(p, MAX_WX_STRING, "OK");
639 			WL_TRACE(("%s: set country %s OK\n", __FUNCTION__, country_code));
640 			goto exit;
641 		}
642 	}
643 
644 	WL_ERROR(("%s: set country %s failed code %d\n", __FUNCTION__, country_code, error));
645 	p += snprintf(p, MAX_WX_STRING, "FAIL");
646 
647 exit:
648 	wrqu->data.length = p - extra + 1;
649 	return error;
650 }
651 
652 #ifdef CUSTOMER_HW2
653 static int
wl_iw_set_power_mode(struct net_device * dev,struct iw_request_info * info,union iwreq_data * wrqu,char * extra)654 wl_iw_set_power_mode(
655 	struct net_device *dev,
656 	struct iw_request_info *info,
657 	union iwreq_data *wrqu,
658 	char *extra
659 )
660 {
661 	int error = 0;
662 	char *p = extra;
663 	static int pm = PM_FAST;
664 	int pm_local = PM_OFF;
665 	char powermode_val = 0;
666 
667 	strncpy((char *)&powermode_val, extra + strlen("POWERMODE") + 1, 1);
668 
669 	if (strnicmp((char *)&powermode_val, "1", strlen("1")) == 0) {
670 
671 		WL_TRACE(("%s: DHCP session starts\n", __FUNCTION__));
672 
673 		dev_wlc_ioctl(dev, WLC_GET_PM, &pm, sizeof(pm));
674 		dev_wlc_ioctl(dev, WLC_SET_PM, &pm_local, sizeof(pm_local));
675 
676 		/* Disable packet filtering if necessary */
677 		net_os_set_packet_filter(dev, 0);
678 
679 	} else if (strnicmp((char *)&powermode_val, "0", strlen("0")) == 0) {
680 
681 		WL_TRACE(("%s: DHCP session done\n", __FUNCTION__));
682 
683 		dev_wlc_ioctl(dev, WLC_SET_PM, &pm, sizeof(pm));
684 
685 		/* Enable packet filtering if was turned off */
686 		net_os_set_packet_filter(dev, 1);
687 
688 	} else {
689 		WL_ERROR(("Unkwown yet power setting, ignored\n"));
690 	}
691 
692 	p += snprintf(p, MAX_WX_STRING, "OK");
693 
694 	wrqu->data.length = p - extra + 1;
695 
696 	return error;
697 }
698 #endif
699 
700 static int
wl_iw_get_power_mode(struct net_device * dev,struct iw_request_info * info,union iwreq_data * wrqu,char * extra)701 wl_iw_get_power_mode(
702 	struct net_device *dev,
703 	struct iw_request_info *info,
704 	union iwreq_data *wrqu,
705 	char *extra
706 )
707 {
708 	int error;
709 	char *p = extra;
710 	int pm_local = PM_FAST;
711 
712 	error = dev_wlc_ioctl(dev, WLC_GET_PM, &pm_local, sizeof(pm_local));
713 	if (!error) {
714 		WL_TRACE(("%s: Powermode = %d\n", __func__, pm_local));
715 		if (pm_local == PM_OFF)
716 			pm_local = 1; /* Active */
717 		else
718 			pm_local = 0; /* Auto */
719 		p += snprintf(p, MAX_WX_STRING, "powermode = %d", pm_local);
720 	}
721 	else {
722 		WL_TRACE(("%s: Error = %d\n", __func__, error));
723 		p += snprintf(p, MAX_WX_STRING, "FAIL");
724 	}
725 	wrqu->data.length = p - extra + 1;
726 	return error;
727 }
728 
729 static int
wl_iw_set_btcoex_dhcp(struct net_device * dev,struct iw_request_info * info,union iwreq_data * wrqu,char * extra)730 wl_iw_set_btcoex_dhcp(
731 	struct net_device *dev,
732 	struct iw_request_info *info,
733 	union iwreq_data *wrqu,
734 	char *extra
735 )
736 {
737 	int error = 0;
738 	char *p = extra;
739 #ifndef CUSTOMER_HW2
740 	static int  pm = PM_FAST;
741 	int  pm_local = PM_OFF;
742 #endif
743 	char powermode_val = 0;
744 	char buf_reg66va_dhcp_on[8] = { 66, 00, 00, 00, 0x10, 0x27, 0x00, 0x00 };
745 	char buf_reg41va_dhcp_on[8] = { 41, 00, 00, 00, 0x33, 0x00, 0x00, 0x00 };
746 	char buf_reg68va_dhcp_on[8] = { 68, 00, 00, 00, 0x90, 0x01, 0x00, 0x00 };
747 
748 	uint32 regaddr;
749 	static uint32 saved_reg66;
750 	static uint32 saved_reg41;
751 	static uint32 saved_reg68;
752 	static bool saved_status = FALSE;
753 
754 	char buf_flag7_default[8] =   { 7, 00, 00, 00, 0x0, 0x00, 0x00, 0x00};
755 #ifndef CUSTOMER_HW2
756 	uint32 temp1, temp2;
757 #endif
758 
759 #ifdef CUSTOMER_HW2
760 	strncpy((char *)&powermode_val, extra + strlen("BTCOEXMODE") + 1, 1);
761 #else
762 	strncpy((char *)&powermode_val, extra + strlen("POWERMODE") + 1, 1);
763 #endif
764 
765 	if (strnicmp((char *)&powermode_val, "1", strlen("1")) == 0) {
766 
767 		WL_TRACE(("%s: DHCP session starts\n", __FUNCTION__));
768 
769 		if ((saved_status == FALSE) &&
770 #ifndef CUSTOMER_HW2
771 			(!dev_wlc_ioctl(dev, WLC_GET_PM, &pm, sizeof(pm))) &&
772 #endif
773 			(!dev_wlc_intvar_get_reg(dev, "btc_params", 66,  &saved_reg66)) &&
774 			(!dev_wlc_intvar_get_reg(dev, "btc_params", 41,  &saved_reg41)) &&
775 			(!dev_wlc_intvar_get_reg(dev, "btc_params", 68,  &saved_reg68)))   {
776 				saved_status = TRUE;
777 				WL_TRACE(("Saved 0x%x 0x%x 0x%x\n", \
778 					saved_reg66, saved_reg41, saved_reg68));
779 
780 #ifndef CUSTOMER_HW2
781 				dev_wlc_ioctl(dev, WLC_SET_PM, &pm_local, sizeof(pm_local));
782 #endif
783 
784 		dev_wlc_bufvar_set(dev, "btc_params", \
785 				   (char *)&buf_reg66va_dhcp_on[0], sizeof(buf_reg66va_dhcp_on));
786 		dev_wlc_bufvar_set(dev, "btc_params", \
787 				   (char *)&buf_reg41va_dhcp_on[0], sizeof(buf_reg41va_dhcp_on));
788 		dev_wlc_bufvar_set(dev, "btc_params", \
789 				   (char *)&buf_reg68va_dhcp_on[0], sizeof(buf_reg68va_dhcp_on));
790 #ifndef CUSTOMER_HW2
791 				if ((!dev_wlc_intvar_get_reg(dev, "btc_params", 12, &temp1)) &&
792 					(!dev_wlc_intvar_get_reg(dev, "btc_params", 13, &temp2)))
793 				{
794 					if ((temp1 != 0) && (temp2 != 0)) {
795 #endif
796 						g_bt->bt_state = BT_DHCP_START;
797 						g_bt->timer_on = 1;
798 						mod_timer(&g_bt->timer, g_bt->timer.expires);
799 						WL_TRACE(("%s enable BT DHCP Timer\n", \
800 							__FUNCTION__));
801 #ifndef CUSTOMER_HW2
802 					}
803 				}
804 #endif
805 		}
806 		else if (saved_status == TRUE) {
807 			WL_ERROR(("%s was called w/o DHCP OFF. Continue\n", __FUNCTION__));
808 		}
809 	}
810 #ifdef CUSTOMER_HW2
811 	else if (strnicmp((char *)&powermode_val, "2", strlen("2")) == 0) {
812 #else
813 	else if (strnicmp((char *)&powermode_val, "0", strlen("0")) == 0) {
814 #endif
815 		WL_TRACE(("%s: DHCP session done\n", __FUNCTION__));
816 
817 #ifndef CUSTOMER_HW2
818 		dev_wlc_ioctl(dev, WLC_SET_PM, &pm, sizeof(pm));
819 #endif
820 
821 		WL_TRACE(("%s disable BT DHCP Timer\n", __FUNCTION__));
822 		if (g_bt->timer_on) {
823 			g_bt->timer_on = 0;
824 			del_timer_sync(&g_bt->timer);
825 		}
826 
827 		dev_wlc_bufvar_set(dev, "btc_flags", \
828 				(char *)&buf_flag7_default[0], sizeof(buf_flag7_default));
829 
830 		if (saved_status) {
831 			regaddr = 66;
832 			dev_wlc_intvar_set_reg(dev, "btc_params", \
833 				(char *)&regaddr, (char *)&saved_reg66);
834 			regaddr = 41;
835 			dev_wlc_intvar_set_reg(dev, "btc_params", \
836 				(char *)&regaddr, (char *)&saved_reg41);
837 			regaddr = 68;
838 			dev_wlc_intvar_set_reg(dev, "btc_params", \
839 				(char *)&regaddr, (char *)&saved_reg68);
840 		}
841 		saved_status = FALSE;
842 	}
843 	else {
844 		WL_ERROR(("Unkwown yet power setting, ignored\n"));
845 	}
846 
847 	p += snprintf(p, MAX_WX_STRING, "OK");
848 
849 	wrqu->data.length = p - extra + 1;
850 
851 	return error;
852 }
853 
854 static int
855 wl_iw_set_suspend(
856 	struct net_device *dev,
857 	struct iw_request_info *info,
858 	union iwreq_data *wrqu,
859 	char *extra
860 )
861 {
862 	int suspend_flag;
863 	int ret_now;
864 	int ret = 0;
865 
866 	suspend_flag = *(extra + strlen(SETSUSPEND_CMD) + 1) - '0';
867 
868 	if (suspend_flag != 0)
869 		suspend_flag = 1;
870 
871 	ret_now = net_os_set_suspend_disable(dev, suspend_flag);
872 
873 	if (ret_now != suspend_flag) {
874 		if (!(ret = net_os_set_suspend(dev, ret_now)))
875 			WL_ERROR(("%s: Suspend Flag %d -> %d\n", \
876 					__FUNCTION__, ret_now, suspend_flag));
877 		else
878 			WL_ERROR(("%s: failed %d\n", __FUNCTION__, ret));
879 	}
880 
881 	return ret;
882 }
883 
884 int
885 wl_format_ssid(char* ssid_buf, uint8* ssid, int ssid_len)
886 {
887 	int i, c;
888 	char *p = ssid_buf;
889 
890 	if (ssid_len > 32) ssid_len = 32;
891 
892 	for (i = 0; i < ssid_len; i++) {
893 		c = (int)ssid[i];
894 		if (c == '\\') {
895 			*p++ = '\\';
896 			*p++ = '\\';
897 		} else if (isprint((uchar)c)) {
898 			*p++ = (char)c;
899 		} else {
900 			p += sprintf(p, "\\x%02X", c);
901 		}
902 	}
903 	*p = '\0';
904 
905 	return p - ssid_buf;
906 }
907 
908 static int
909 wl_iw_get_link_speed(
910 	struct net_device *dev,
911 	struct iw_request_info *info,
912 	union iwreq_data *wrqu,
913 	char *extra
914 )
915 {
916 	int error = 0;
917 	char *p = extra;
918 	static int link_speed;
919 
920 	net_os_wake_lock(dev);
921 	if (g_onoff == G_WLAN_SET_ON) {
922 		error = dev_wlc_ioctl(dev, WLC_GET_RATE, &link_speed, sizeof(link_speed));
923 		link_speed *= 500000;
924 	}
925 
926 	p += snprintf(p, MAX_WX_STRING, "LinkSpeed %d", link_speed/1000000);
927 
928 	wrqu->data.length = p - extra + 1;
929 
930 	net_os_wake_unlock(dev);
931 	return error;
932 }
933 
934 
935 static int
936 wl_iw_get_dtim_skip(
937 	struct net_device *dev,
938 	struct iw_request_info *info,
939 	union iwreq_data *wrqu,
940 	char *extra
941 )
942 {
943 	int error = -1;
944 	char *p = extra;
945 	char iovbuf[32];
946 
947 	net_os_wake_lock(dev);
948 	if (g_onoff == G_WLAN_SET_ON) {
949 
950 			memset(iovbuf, 0, sizeof(iovbuf));
951 			strcpy(iovbuf, "bcn_li_dtim");
952 
953 			if ((error = dev_wlc_ioctl(dev, WLC_GET_VAR,
954 				&iovbuf, sizeof(iovbuf))) >= 0) {
955 
956 				p += snprintf(p, MAX_WX_STRING, "Dtim_skip %d", iovbuf[0]);
957 				WL_TRACE(("%s: get dtim_skip = %d\n", __FUNCTION__, iovbuf[0]));
958 				wrqu->data.length = p - extra + 1;
959 			}
960 			else
961 				WL_ERROR(("%s: get dtim_skip failed code %d\n", \
962 					__FUNCTION__, error));
963 	}
964 	net_os_wake_unlock(dev);
965 	return error;
966 }
967 
968 
969 static int
970 wl_iw_set_dtim_skip(
971 	struct net_device *dev,
972 	struct iw_request_info *info,
973 	union iwreq_data *wrqu,
974 	char *extra
975 )
976 {
977 	int error = -1;
978 	char *p = extra;
979 	int bcn_li_dtim;
980 	char iovbuf[32];
981 
982 	net_os_wake_lock(dev);
983 	if (g_onoff == G_WLAN_SET_ON) {
984 
985 		bcn_li_dtim = htod32((uint)*(extra + strlen(DTIM_SKIP_SET_CMD) + 1) - '0');
986 
987 		if ((bcn_li_dtim >= 0) || ((bcn_li_dtim <= 5))) {
988 
989 			memset(iovbuf, 0, sizeof(iovbuf));
990 			bcm_mkiovar("bcn_li_dtim", (char *)&bcn_li_dtim,
991 				4, iovbuf, sizeof(iovbuf));
992 
993 			if ((error = dev_wlc_ioctl(dev, WLC_SET_VAR,
994 				&iovbuf, sizeof(iovbuf))) >= 0) {
995 				p += snprintf(p, MAX_WX_STRING, "OK");
996 
997 				net_os_set_dtim_skip(dev, bcn_li_dtim);
998 
999 				WL_TRACE(("%s: set dtim_skip %d OK\n", __FUNCTION__, \
1000 					bcn_li_dtim));
1001 				goto exit;
1002 			}
1003 			else  WL_ERROR(("%s: set dtim_skip %d failed code %d\n", \
1004 				__FUNCTION__, bcn_li_dtim, error));
1005 		}
1006 		else  WL_ERROR(("%s Incorrect dtim_skip setting %d, ignored\n", \
1007 			__FUNCTION__, bcn_li_dtim));
1008 	}
1009 
1010 	p += snprintf(p, MAX_WX_STRING, "FAIL");
1011 
1012 exit:
1013 	wrqu->data.length = p - extra + 1;
1014 	net_os_wake_unlock(dev);
1015 	return error;
1016 }
1017 
1018 
1019 static int
1020 wl_iw_get_band(
1021 	struct net_device *dev,
1022 	struct iw_request_info *info,
1023 	union iwreq_data *wrqu,
1024 	char *extra
1025 )
1026 {
1027 	int error = -1;
1028 	char *p = extra;
1029 	static int band;
1030 
1031 	net_os_wake_lock(dev);
1032 
1033 	if (g_onoff == G_WLAN_SET_ON) {
1034 		error = dev_wlc_ioctl(dev, WLC_GET_BAND, &band, sizeof(band));
1035 
1036 		p += snprintf(p, MAX_WX_STRING, "Band %d", band);
1037 
1038 		wrqu->data.length = p - extra + 1;
1039 	}
1040 
1041 	net_os_wake_unlock(dev);
1042 	return error;
1043 }
1044 
1045 
1046 static int
1047 wl_iw_set_band(
1048 	struct net_device *dev,
1049 	struct iw_request_info *info,
1050 	union iwreq_data *wrqu,
1051 	char *extra
1052 )
1053 {
1054 	int error = -1;
1055 	char *p = extra;
1056 	uint band;
1057 
1058 	net_os_wake_lock(dev);
1059 
1060 	if (g_onoff == G_WLAN_SET_ON) {
1061 
1062 		band = htod32((uint)*(extra + strlen(BAND_SET_CMD) + 1) - '0');
1063 
1064 		if ((band == WLC_BAND_AUTO) || (band == WLC_BAND_5G) || (band == WLC_BAND_2G)) {
1065 
1066 
1067 			if ((error = dev_wlc_ioctl(dev, WLC_SET_BAND,
1068 				&band, sizeof(band))) >= 0) {
1069 				p += snprintf(p, MAX_WX_STRING, "OK");
1070 				WL_TRACE(("%s: set band %d OK\n", __FUNCTION__, band));
1071 				goto exit;
1072 			}
1073 			else WL_ERROR(("%s: set band %d failed code %d\n", __FUNCTION__, \
1074 					band, error));
1075 		}
1076 		else WL_ERROR(("%s Incorrect band setting %d, ignored\n", __FUNCTION__, band));
1077 	}
1078 
1079 	p += snprintf(p, MAX_WX_STRING, "FAIL");
1080 
1081 exit:
1082 	wrqu->data.length = p - extra + 1;
1083 	net_os_wake_unlock(dev);
1084 	return error;
1085 }
1086 
1087 #ifdef PNO_SUPPORT
1088 
1089 static int
1090 wl_iw_set_pno_reset(
1091 	struct net_device *dev,
1092 	struct iw_request_info *info,
1093 	union iwreq_data *wrqu,
1094 	char *extra
1095 )
1096 {
1097 	int error = -1;
1098 	char *p = extra;
1099 
1100 	net_os_wake_lock(dev);
1101 	if ((g_onoff == G_WLAN_SET_ON) && (dev != NULL)) {
1102 
1103 		if ((error = dhd_dev_pno_reset(dev)) >= 0) {
1104 				p += snprintf(p, MAX_WX_STRING, "OK");
1105 				WL_TRACE(("%s: set OK\n", __FUNCTION__));
1106 				goto exit;
1107 		}
1108 		else  WL_ERROR(("%s: failed code %d\n", __FUNCTION__, error));
1109 	}
1110 
1111 	p += snprintf(p, MAX_WX_STRING, "FAIL");
1112 
1113 exit:
1114 	wrqu->data.length = p - extra + 1;
1115 	net_os_wake_unlock(dev);
1116 	return error;
1117 }
1118 
1119 
1120 
1121 static int
1122 wl_iw_set_pno_enable(
1123 	struct net_device *dev,
1124 	struct iw_request_info *info,
1125 	union iwreq_data *wrqu,
1126 	char *extra
1127 )
1128 {
1129 	int error = -1;
1130 	char *p = extra;
1131 	int pfn_enabled;
1132 
1133 	net_os_wake_lock(dev);
1134 	pfn_enabled = htod32((uint)*(extra + strlen(PNOENABLE_SET_CMD) + 1) - '0');
1135 
1136 	if ((g_onoff == G_WLAN_SET_ON) && (dev != NULL)) {
1137 
1138 		if ((error = dhd_dev_pno_enable(dev, pfn_enabled)) >= 0) {
1139 				p += snprintf(p, MAX_WX_STRING, "OK");
1140 				WL_TRACE(("%s: set OK\n", __FUNCTION__));
1141 				goto exit;
1142 		}
1143 		else  WL_ERROR(("%s: failed code %d\n", __FUNCTION__, error));
1144 	}
1145 
1146 	p += snprintf(p, MAX_WX_STRING, "FAIL");
1147 
1148 exit:
1149 	wrqu->data.length = p - extra + 1;
1150 	net_os_wake_unlock(dev);
1151 	return error;
1152 }
1153 
1154 
1155 
1156 static int
1157 wl_iw_set_pno_set(
1158 	struct net_device *dev,
1159 	struct iw_request_info *info,
1160 	union iwreq_data *wrqu,
1161 	char *extra
1162 )
1163 {
1164 	int res = -1;
1165 	wlc_ssid_t ssids_local[MAX_PFN_LIST_COUNT];
1166 	int nssid = 0;
1167 	cmd_tlv_t *cmd_tlv_temp;
1168 	char type;
1169 	char *str_ptr;
1170 	int tlv_size_left;
1171 	int pno_time;
1172 
1173 #ifdef PNO_SET_DEBUG
1174 	int i;
1175 	char pno_in_example[] = {'P', 'N', 'O', 'S', 'E', 'T', 'U', 'P', ' ', \
1176 							'S', 0x01, 0x01, 0x00,
1177 							'S',
1178 							0x04,
1179 							'B', 'R', 'C', 'M',
1180 							'S',
1181 							0x04,
1182 							'G', 'O', 'O', 'G',
1183 							'T',
1184 							0x00,
1185 							0x0A
1186 							};
1187 #endif
1188 
1189 	net_os_wake_lock(dev);
1190 	WL_ERROR(("\n### %s: info->cmd:%x, info->flags:%x, u.data=0x%p, u.len=%d\n",
1191 		__FUNCTION__, info->cmd, info->flags,
1192 		wrqu->data.pointer, wrqu->data.length));
1193 
1194 	if (g_onoff == G_WLAN_SET_OFF) {
1195 		WL_TRACE(("%s: driver is not up yet after START\n", __FUNCTION__));
1196 		goto exit_proc;
1197 	}
1198 
1199 	if (wrqu->data.length < (strlen(PNOSETUP_SET_CMD) + sizeof(cmd_tlv_t))) {
1200 		WL_ERROR(("%s aggument=%d  less %d\n", __FUNCTION__, \
1201 			wrqu->data.length, strlen(PNOSETUP_SET_CMD) + sizeof(cmd_tlv_t)));
1202 		goto exit_proc;
1203 	}
1204 
1205 #ifdef PNO_SET_DEBUG
1206 	if (!(extra = kmalloc(sizeof(pno_in_example) +100, GFP_KERNEL))) {
1207 		res = -ENOMEM;
1208 		goto exit_proc;
1209 	}
1210 	memcpy(extra, pno_in_example, sizeof(pno_in_example));
1211 	wrqu->data.length = sizeof(pno_in_example);
1212 	for (i = 0; i < wrqu->data.length; i++)
1213 		printf("%02X ", extra[i]);
1214 	printf("\n");
1215 #endif
1216 
1217 	str_ptr = extra;
1218 #ifdef PNO_SET_DEBUG
1219 	str_ptr +=  strlen("PNOSETUP ");
1220 	tlv_size_left = wrqu->data.length - strlen("PNOSETUP ");
1221 #else
1222 	str_ptr +=  strlen(PNOSETUP_SET_CMD);
1223 	tlv_size_left = wrqu->data.length - strlen(PNOSETUP_SET_CMD);
1224 #endif
1225 
1226 	cmd_tlv_temp = (cmd_tlv_t *)str_ptr;
1227 	memset(ssids_local, 0, sizeof(ssids_local));
1228 
1229 	if ((cmd_tlv_temp->prefix == PNO_TLV_PREFIX) && \
1230 		(cmd_tlv_temp->version == PNO_TLV_VERSION) && \
1231 		(cmd_tlv_temp->subver == PNO_TLV_SUBVERSION))
1232 	{
1233 		str_ptr += sizeof(cmd_tlv_t);
1234 		tlv_size_left  -= sizeof(cmd_tlv_t);
1235 
1236 		if ((nssid = wl_iw_parse_ssid_list_tlv(&str_ptr, ssids_local, \
1237 				MAX_PFN_LIST_COUNT, &tlv_size_left)) <= 0) {
1238 			WL_ERROR(("SSID is not presented or corrupted ret=%d\n", nssid));
1239 			goto exit_proc;
1240 		}
1241 		else {
1242 			while (tlv_size_left > 0)
1243 			{
1244 				type = str_ptr[0];
1245 				switch (type) {
1246 					case PNO_TLV_TYPE_TIME:
1247 
1248 					if ((res = wl_iw_parse_data_tlv(&str_ptr, \
1249 						&pno_time, \
1250 						sizeof(pno_time), \
1251 						type, sizeof(short), &tlv_size_left)) == -1) {
1252 							WL_ERROR(("%s return %d\n", \
1253 							__FUNCTION__, res));
1254 							goto exit_proc;
1255 					}
1256 					break;
1257 
1258 					default:
1259 						WL_ERROR(("%s get unkwown type %X\n", \
1260 							__FUNCTION__, type));
1261 						goto exit_proc;
1262 					break;
1263 				}
1264 			}
1265 		}
1266 	}
1267 	else {
1268 		WL_ERROR(("%s get wrong TLV command\n", __FUNCTION__));
1269 		goto exit_proc;
1270 	}
1271 
1272 	res = dhd_dev_pno_set(dev, ssids_local, nssid, pno_time);
1273 
1274 exit_proc:
1275 	net_os_wake_unlock(dev);
1276 	return res;
1277 }
1278 #endif
1279 
1280 static int
1281 wl_iw_get_rssi(
1282 	struct net_device *dev,
1283 	struct iw_request_info *info,
1284 	union iwreq_data *wrqu,
1285 	char *extra
1286 )
1287 {
1288 	static int rssi = 0;
1289 	static wlc_ssid_t ssid = {0};
1290 	int error = 0;
1291 	char *p = extra;
1292 	static char ssidbuf[SSID_FMT_BUF_LEN];
1293 	scb_val_t scb_val;
1294 
1295 	net_os_wake_lock(dev);
1296 
1297 	bzero(&scb_val, sizeof(scb_val_t));
1298 
1299 	if (g_onoff == G_WLAN_SET_ON) {
1300 		error = dev_wlc_ioctl(dev, WLC_GET_RSSI, &scb_val, sizeof(scb_val_t));
1301 		if (error) {
1302 			WL_ERROR(("%s: Fails %d\n", __FUNCTION__, error));
1303 			net_os_wake_unlock(dev);
1304 			return error;
1305 		}
1306 		rssi = dtoh32(scb_val.val);
1307 
1308 		error = dev_wlc_ioctl(dev, WLC_GET_SSID, &ssid, sizeof(ssid));
1309 		if (!error) {
1310 			ssid.SSID_len = dtoh32(ssid.SSID_len);
1311 			wl_format_ssid(ssidbuf, ssid.SSID, dtoh32(ssid.SSID_len));
1312 		}
1313 	}
1314 
1315 	p += snprintf(p, MAX_WX_STRING, "%s rssi %d ", ssidbuf, rssi);
1316 	wrqu->data.length = p - extra + 1;
1317 
1318 	net_os_wake_unlock(dev);
1319 	return error;
1320 }
1321 
1322 int
1323 wl_iw_send_priv_event(
1324 	struct net_device *dev,
1325 	char *flag
1326 )
1327 {
1328 	union iwreq_data wrqu;
1329 	char extra[IW_CUSTOM_MAX + 1];
1330 	int cmd;
1331 
1332 	cmd = IWEVCUSTOM;
1333 	memset(&wrqu, 0, sizeof(wrqu));
1334 	if (strlen(flag) > sizeof(extra))
1335 		return -1;
1336 
1337 	strcpy(extra, flag);
1338 	wrqu.data.length = strlen(extra);
1339 	wireless_send_event(dev, cmd, &wrqu, extra);
1340 	net_os_wake_lock_timeout_enable(dev);
1341 	WL_TRACE(("Send IWEVCUSTOM Event as %s\n", extra));
1342 
1343 	return 0;
1344 }
1345 
1346 
1347 int
1348 wl_control_wl_start(struct net_device *dev)
1349 {
1350 	int ret = 0;
1351 
1352 	WL_TRACE(("Enter %s \n", __FUNCTION__));
1353 
1354 	if (!dev) {
1355 		WL_ERROR(("%s: dev is null\n", __FUNCTION__));
1356 		return -1;
1357 	}
1358 
1359 	mutex_lock(&wl_start_lock);
1360 
1361 	if (g_onoff == G_WLAN_SET_OFF) {
1362 		dhd_customer_gpio_wlan_ctrl(WLAN_RESET_ON);
1363 
1364 #if defined(BCMLXSDMMC)
1365 		sdioh_start(NULL, 0);
1366 #endif
1367 
1368 		dhd_dev_reset(dev, 0);
1369 
1370 #if defined(BCMLXSDMMC)
1371 		sdioh_start(NULL, 1);
1372 #endif
1373 
1374 		dhd_dev_init_ioctl(dev);
1375 
1376 		g_onoff = G_WLAN_SET_ON;
1377 	}
1378 	WL_TRACE(("Exited %s \n", __FUNCTION__));
1379 
1380 	mutex_unlock(&wl_start_lock);
1381 	return ret;
1382 }
1383 
1384 
1385 static int
1386 wl_iw_control_wl_off(
1387 	struct net_device *dev,
1388 	struct iw_request_info *info
1389 )
1390 {
1391 	int ret = 0;
1392 	WL_TRACE(("Enter %s\n", __FUNCTION__));
1393 
1394 	if (!dev) {
1395 		WL_ERROR(("%s: dev is null\n", __FUNCTION__));
1396 		return -1;
1397 	}
1398 
1399 	mutex_lock(&wl_start_lock);
1400 
1401 #ifdef SOFTAP
1402 	ap_cfg_running = FALSE;
1403 #endif
1404 
1405 	if (g_onoff == G_WLAN_SET_ON) {
1406 		g_onoff = G_WLAN_SET_OFF;
1407 #if defined(WL_IW_USE_ISCAN)
1408 		g_iscan->iscan_state = ISCAN_STATE_IDLE;
1409 #endif
1410 
1411 		dhd_dev_reset(dev, 1);
1412 
1413 #if defined(WL_IW_USE_ISCAN)
1414 #if !defined(CSCAN)
1415 		wl_iw_free_ss_cache();
1416 		wl_iw_run_ss_cache_timer(0);
1417 
1418 		g_ss_cache_ctrl.m_link_down = 1;
1419 #endif
1420 		memset(g_scan, 0, G_SCAN_RESULTS);
1421 		g_scan_specified_ssid = 0;
1422 
1423 		g_first_broadcast_scan = BROADCAST_SCAN_FIRST_IDLE;
1424 		g_first_counter_scans = 0;
1425 #endif
1426 
1427 #if defined(BCMLXSDMMC)
1428 		sdioh_stop(NULL);
1429 #endif
1430 
1431 		net_os_set_dtim_skip(dev, 0);
1432 
1433 		dhd_customer_gpio_wlan_ctrl(WLAN_RESET_OFF);
1434 
1435 		wl_iw_send_priv_event(dev, "STOP");
1436 	}
1437 
1438 	mutex_unlock(&wl_start_lock);
1439 
1440 	WL_TRACE(("Exited %s\n", __FUNCTION__));
1441 
1442 	return ret;
1443 }
1444 
1445 static int
1446 wl_iw_control_wl_on(
1447 	struct net_device *dev,
1448 	struct iw_request_info *info
1449 )
1450 {
1451 	int ret = 0;
1452 
1453 	WL_TRACE(("Enter %s \n", __FUNCTION__));
1454 
1455 	ret = wl_control_wl_start(dev);
1456 
1457 	wl_iw_send_priv_event(dev, "START");
1458 
1459 #ifdef SOFTAP
1460 	if (!ap_fw_loaded) {
1461 		wl_iw_iscan_set_scan_broadcast_prep(dev, 0);
1462 	}
1463 #else
1464 	wl_iw_iscan_set_scan_broadcast_prep(dev, 0);
1465 #endif
1466 
1467 	WL_TRACE(("Exited %s \n", __FUNCTION__));
1468 
1469 	return ret;
1470 }
1471 
1472 #ifdef SOFTAP
1473 static struct ap_profile my_ap;
1474 static int set_ap_cfg(struct net_device *dev, struct ap_profile *ap);
1475 static int get_assoc_sta_list(struct net_device *dev, char *buf, int len);
1476 static int set_ap_mac_list(struct net_device *dev, char *buf);
1477 
1478 #define PTYPE_STRING	0
1479 #define PTYPE_INTDEC	1
1480 #define PTYPE_INTHEX	2
1481 #define PTYPE_STR_HEX	3
1482 int get_parmeter_from_string(
1483 	char **str_ptr, const char *token, int param_type, void  *dst, int param_max_len);
1484 
1485 #endif
1486 
1487 int hex2num(char c)
1488 {
1489 	if (c >= '0' && c <= '9')
1490 		return c - '0';
1491 	if (c >= 'a' && c <= 'f')
1492 		return c - 'a' + 10;
1493 	if (c >= 'A' && c <= 'F')
1494 		return c - 'A' + 10;
1495 	return -1;
1496 }
1497 
1498 int hex2byte(const char *hex)
1499 {
1500 	int a, b;
1501 	a = hex2num(*hex++);
1502 	if (a < 0)
1503 		return -1;
1504 	b = hex2num(*hex++);
1505 	if (b < 0)
1506 		return -1;
1507 	return (a << 4) | b;
1508 }
1509 
1510 
1511 
1512 int hstr_2_buf(const char *txt, u8 *buf, int len)
1513 {
1514 	int i;
1515 
1516 	for (i = 0; i < len; i++) {
1517 		int a, b;
1518 
1519 		a = hex2num(*txt++);
1520 		if (a < 0)
1521 			return -1;
1522 		b = hex2num(*txt++);
1523 		if (b < 0)
1524 			return -1;
1525 		*buf++ = (a << 4) | b;
1526 	}
1527 
1528 	return 0;
1529 }
1530 
1531 #ifdef SOFTAP
1532 int init_ap_profile_from_string(char *param_str, struct ap_profile *ap_cfg)
1533 {
1534 	char *str_ptr = param_str;
1535 	char sub_cmd[16];
1536 	int ret = 0;
1537 
1538 	memset(sub_cmd, 0, sizeof(sub_cmd));
1539 	memset(ap_cfg, 0, sizeof(struct ap_profile));
1540 
1541 	if (get_parmeter_from_string(&str_ptr, "ASCII_CMD=",
1542 		PTYPE_STRING, sub_cmd, SSID_LEN) != 0) {
1543 		return -1;
1544 	}
1545 	if (strncmp(sub_cmd, "AP_CFG", 6)) {
1546 		WL_ERROR(("ERROR: sub_cmd:%s != 'AP_CFG'!\n", sub_cmd));
1547 		return -1;
1548 	}
1549 
1550 	ret = get_parmeter_from_string(&str_ptr, "SSID=", PTYPE_STRING, ap_cfg->ssid, SSID_LEN);
1551 
1552 	ret |= get_parmeter_from_string(&str_ptr, "SEC=", PTYPE_STRING,  ap_cfg->sec, SEC_LEN);
1553 
1554 	ret |= get_parmeter_from_string(&str_ptr, "KEY=", PTYPE_STRING,  ap_cfg->key, KEY_LEN);
1555 
1556 	ret |= get_parmeter_from_string(&str_ptr, "CHANNEL=", PTYPE_INTDEC, &ap_cfg->channel, 5);
1557 
1558 	ret |= get_parmeter_from_string(&str_ptr, "PREAMBLE=", PTYPE_INTDEC, &ap_cfg->preamble, 5);
1559 
1560 	ret |= get_parmeter_from_string(&str_ptr, "MAX_SCB=", PTYPE_INTDEC,  &ap_cfg->max_scb, 5);
1561 
1562 	return ret;
1563 }
1564 #endif
1565 
1566 
1567 #ifdef SOFTAP
1568 static int iwpriv_set_ap_config(struct net_device *dev,
1569 		struct iw_request_info *info,
1570 		union iwreq_data *wrqu,
1571 		char *ext)
1572 {
1573 	int res = 0;
1574 	char  *extra = NULL;
1575 	struct ap_profile *ap_cfg = &my_ap;
1576 
1577 	WL_TRACE(("> Got IWPRIV SET_AP IOCTL: info->cmd:%x, info->flags:%x, u.data:%p, u.len:%d\n",
1578 		info->cmd, info->flags,
1579 		wrqu->data.pointer, wrqu->data.length));
1580 
1581 	if (wrqu->data.length != 0) {
1582 
1583 		char *str_ptr;
1584 
1585 		if (!(extra = kmalloc(wrqu->data.length+1, GFP_KERNEL)))
1586 			return -ENOMEM;
1587 
1588 		if (copy_from_user(extra, wrqu->data.pointer, wrqu->data.length)) {
1589 			kfree(extra);
1590 			return -EFAULT;
1591 		}
1592 
1593 		extra[wrqu->data.length] = 0;
1594 		WL_SOFTAP((" Got str param in iw_point:\n %s\n", extra));
1595 
1596 		memset(ap_cfg, 0, sizeof(struct ap_profile));
1597 
1598 		str_ptr = extra;
1599 
1600 		if ((res = init_ap_profile_from_string(extra, ap_cfg)) < 0) {
1601 			WL_ERROR(("%s failed to parse %d\n", __FUNCTION__, res));
1602 			kfree(extra);
1603 			return -1;
1604 		}
1605 
1606 	} else {
1607 		WL_ERROR(("IWPRIV argument len = 0 \n"));
1608 		return -1;
1609 	}
1610 
1611 	if ((res = set_ap_cfg(dev, ap_cfg)) < 0)
1612 		WL_ERROR(("%s failed to set_ap_cfg %d\n", __FUNCTION__, res));
1613 
1614 	kfree(extra);
1615 
1616 	return res;
1617 }
1618 #endif
1619 
1620 
1621 #ifdef SOFTAP
1622 static int iwpriv_get_assoc_list(struct net_device *dev,
1623 		struct iw_request_info *info,
1624 		union iwreq_data *p_iwrq,
1625 		char *extra)
1626 {
1627 	int i, ret = 0;
1628 	char mac_buf[256];
1629 	struct maclist *sta_maclist = (struct maclist *)mac_buf;
1630 
1631 	char mac_lst[256];
1632 	char *p_mac_str;
1633 
1634 	WL_TRACE(("\n %s: IWPRIV IOCTL: cmd:%hx, flags:%hx, extra:%p, iwp.len:%d, \
1635 		iwp.len:%p, iwp.flags:%x  \n", __FUNCTION__, info->cmd, info->flags, \
1636 		extra, p_iwrq->data.length, p_iwrq->data.pointer, p_iwrq->data.flags));
1637 
1638 	WL_SOFTAP(("extra:%s\n", extra));
1639 	print_buf((u8 *)p_iwrq, 16, 0);
1640 
1641 	memset(sta_maclist, 0, sizeof(mac_buf));
1642 
1643 	sta_maclist->count = 8;
1644 
1645 	WL_TRACE((" net device:%s, buf_sz:%d\n", dev->name, sizeof(mac_buf)));
1646 	get_assoc_sta_list(dev, mac_buf, 256);
1647 	WL_TRACE((" got %d stations\n", sta_maclist->count));
1648 
1649 	memset(mac_lst, 0, sizeof(mac_lst));
1650 	p_mac_str = mac_lst;
1651 
1652 	for (i = 0; i < 8; i++) {
1653 		struct ether_addr *id = &sta_maclist->ea[i];
1654 
1655 		WL_SOFTAP(("dhd_drv>> sta_mac[%d] :", i));
1656 		print_buf((unsigned char *)&sta_maclist->ea[i], 6, 0);
1657 
1658 		p_mac_str += snprintf(p_mac_str, MAX_WX_STRING,
1659 			"Mac[%d]=%02X:%02X:%02X:%02X:%02X:%02X\n", i,
1660 			id->octet[0], id->octet[1], id->octet[2],
1661 			id->octet[3], id->octet[4], id->octet[5]);
1662 
1663 	}
1664 
1665 	p_iwrq->data.length = strlen(mac_lst);
1666 
1667 	WL_TRACE(("u.pointer:%p\n", p_iwrq->data.pointer));
1668 	WL_TRACE(("resulting str:\n%s \n len:%d\n\n", mac_lst, p_iwrq->data.length));
1669 
1670 	if (p_iwrq->data.length) {
1671 		if (copy_to_user(p_iwrq->data.pointer, mac_lst, p_iwrq->data.length)) {
1672 			WL_ERROR(("%s: Can't copy to user\n", __FUNCTION__));
1673 			return -EFAULT;
1674 		}
1675 	}
1676 
1677 	WL_TRACE(("Exited %s \n", __FUNCTION__));
1678 	return ret;
1679 }
1680 #endif
1681 
1682 
1683 #ifdef SOFTAP
1684 static int iwpriv_set_mac_filters(struct net_device *dev,
1685 		struct iw_request_info *info,
1686 		union iwreq_data *wrqu,
1687 		char *ext)
1688 {
1689 
1690 	int i, ret = -1;
1691 	char *extra = NULL;
1692 	u8  macfilt[8][6];
1693 	int mac_cnt = 0;
1694 	char sub_cmd[16];
1695 
1696 	WL_TRACE((">>> Got IWPRIV SET_MAC_FILTER IOCTL:  info->cmd:%x, \
1697 			info->flags:%x, u.data:%p, u.len:%d\n",
1698 			info->cmd, info->flags,
1699 			wrqu->data.pointer, wrqu->data.length));
1700 
1701 	if (wrqu->data.length != 0) {
1702 
1703 		char *str_ptr;
1704 
1705 		if (!(extra = kmalloc(wrqu->data.length+1, GFP_KERNEL)))
1706 			return -ENOMEM;
1707 
1708 		if (copy_from_user(extra, wrqu->data.pointer, wrqu->data.length)) {
1709 			kfree(extra);
1710 			return -EFAULT;
1711 		}
1712 
1713 		extra[wrqu->data.length] = 0;
1714 		WL_SOFTAP((" Got parameter string in iw_point:\n %s \n", extra));
1715 
1716 		memset(macfilt, 0, sizeof(macfilt));
1717 		memset(sub_cmd, 0, sizeof(sub_cmd));
1718 
1719 		str_ptr = extra;
1720 
1721 		if (get_parmeter_from_string(&str_ptr, "ASCII_CMD=", PTYPE_STRING, sub_cmd, 15) != 0) {
1722 			goto exit_proc;
1723 		}
1724 
1725 #define MAC_FILT_MAX 8
1726 
1727 		if (strncmp(sub_cmd, "MAC_FLT_W", strlen("MAC_FLT_W"))) {
1728 			WL_ERROR(("ERROR: sub_cmd:%s != 'MAC_FLT_W'!\n", sub_cmd));
1729 			goto exit_proc;
1730 		}
1731 
1732 		if (get_parmeter_from_string(&str_ptr, "MAC_CNT=",
1733 			PTYPE_INTDEC, &mac_cnt, 4) != 0) {
1734 			WL_ERROR(("ERROR: MAC_CNT param is missing \n"));
1735 			goto exit_proc;
1736 		}
1737 
1738 		if (mac_cnt > MAC_FILT_MAX) {
1739 			WL_ERROR(("ERROR: number of MAC filters > MAX\n"));
1740 			goto exit_proc;
1741 		}
1742 
1743 		for (i = 0; i < mac_cnt; i++) {
1744 			if (get_parmeter_from_string(&str_ptr, "MAC=",
1745 				PTYPE_STR_HEX, macfilt[i], 12) != 0) {
1746 				WL_ERROR(("ERROR: MAC_filter[%d] is missing !\n", i));
1747 				goto exit_proc;
1748 			}
1749 		}
1750 
1751 		for (i = 0; i < mac_cnt; i++) {
1752 			WL_SOFTAP(("mac_filt[%d]:", i));
1753 			print_buf(macfilt[i], 6, 0);
1754 		}
1755 
1756 		wrqu->data.pointer = NULL;
1757 		wrqu->data.length = 0;
1758 		ret = 0;
1759 
1760 	} else {
1761 		WL_ERROR(("IWPRIV argument len is 0\n"));
1762 		return -1;
1763 	}
1764 
1765 	exit_proc:
1766 	kfree(extra);
1767 	return ret;
1768 }
1769 #endif
1770 
1771 #endif
1772 
1773 #if WIRELESS_EXT < 13
1774 struct iw_request_info
1775 {
1776 	__u16		cmd;
1777 	__u16		flags;
1778 };
1779 
1780 typedef int (*iw_handler)(struct net_device *dev,
1781 		struct iw_request_info *info,
1782 		void *wrqu,
1783 		char *extra);
1784 #endif
1785 
1786 static int
1787 wl_iw_config_commit(
1788 	struct net_device *dev,
1789 	struct iw_request_info *info,
1790 	void *zwrq,
1791 	char *extra
1792 )
1793 {
1794 	wlc_ssid_t ssid;
1795 	int error;
1796 	struct sockaddr bssid;
1797 
1798 	WL_TRACE(("%s: SIOCSIWCOMMIT\n", dev->name));
1799 
1800 	if ((error = dev_wlc_ioctl(dev, WLC_GET_SSID, &ssid, sizeof(ssid))))
1801 		return error;
1802 
1803 	ssid.SSID_len = dtoh32(ssid.SSID_len);
1804 
1805 	if (!ssid.SSID_len)
1806 		return 0;
1807 
1808 	bzero(&bssid, sizeof(struct sockaddr));
1809 	if ((error = dev_wlc_ioctl(dev, WLC_REASSOC, &bssid, ETHER_ADDR_LEN))) {
1810 		WL_ERROR(("%s: WLC_REASSOC to %s failed \n", __FUNCTION__, ssid.SSID));
1811 		return error;
1812 	}
1813 
1814 	return 0;
1815 }
1816 
1817 static int
1818 wl_iw_get_name(
1819 	struct net_device *dev,
1820 	struct iw_request_info *info,
1821 	char *cwrq,
1822 	char *extra
1823 )
1824 {
1825 	WL_TRACE(("%s: SIOCGIWNAME\n", dev->name));
1826 
1827 	strcpy(cwrq, "IEEE 802.11-DS");
1828 
1829 	return 0;
1830 }
1831 
1832 static int
1833 wl_iw_set_freq(
1834 	struct net_device *dev,
1835 	struct iw_request_info *info,
1836 	struct iw_freq *fwrq,
1837 	char *extra
1838 )
1839 {
1840 	int error, chan;
1841 	uint sf = 0;
1842 
1843 	WL_TRACE(("%s %s: SIOCSIWFREQ\n", __FUNCTION__, dev->name));
1844 
1845 #if defined(SOFTAP)
1846 	if (ap_cfg_running) {
1847 		WL_TRACE(("%s:>> not executed, 'SOFT_AP is active' \n", __FUNCTION__));
1848 		return 0;
1849 	}
1850 #endif
1851 
1852 
1853 	if (fwrq->e == 0 && fwrq->m < MAXCHANNEL) {
1854 		chan = fwrq->m;
1855 	}
1856 
1857 
1858 	else {
1859 
1860 		if (fwrq->e >= 6) {
1861 			fwrq->e -= 6;
1862 			while (fwrq->e--)
1863 				fwrq->m *= 10;
1864 		} else if (fwrq->e < 6) {
1865 			while (fwrq->e++ < 6)
1866 				fwrq->m /= 10;
1867 		}
1868 
1869 	if (fwrq->m > 4000 && fwrq->m < 5000)
1870 		sf = WF_CHAN_FACTOR_4_G;
1871 
1872 		chan = wf_mhz2channel(fwrq->m, sf);
1873 	}
1874 	chan = htod32(chan);
1875 	if ((error = dev_wlc_ioctl(dev, WLC_SET_CHANNEL, &chan, sizeof(chan))))
1876 		return error;
1877 
1878 	g_wl_iw_params.target_channel = chan;
1879 
1880 	return -EINPROGRESS;
1881 }
1882 
1883 static int
1884 wl_iw_get_freq(
1885 	struct net_device *dev,
1886 	struct iw_request_info *info,
1887 	struct iw_freq *fwrq,
1888 	char *extra
1889 )
1890 {
1891 	channel_info_t ci;
1892 	int error;
1893 
1894 	WL_TRACE(("%s: SIOCGIWFREQ\n", dev->name));
1895 
1896 	if ((error = dev_wlc_ioctl(dev, WLC_GET_CHANNEL, &ci, sizeof(ci))))
1897 		return error;
1898 
1899 	fwrq->m = dtoh32(ci.hw_channel);
1900 	fwrq->e = dtoh32(0);
1901 	return 0;
1902 }
1903 
1904 static int
1905 wl_iw_set_mode(
1906 	struct net_device *dev,
1907 	struct iw_request_info *info,
1908 	__u32 *uwrq,
1909 	char *extra
1910 )
1911 {
1912 	int infra = 0, ap = 0, error = 0;
1913 
1914 	WL_TRACE(("%s: SIOCSIWMODE\n", dev->name));
1915 
1916 	switch (*uwrq) {
1917 	case IW_MODE_MASTER:
1918 		infra = ap = 1;
1919 		break;
1920 	case IW_MODE_ADHOC:
1921 	case IW_MODE_AUTO:
1922 		break;
1923 	case IW_MODE_INFRA:
1924 		infra = 1;
1925 		break;
1926 	default:
1927 		return -EINVAL;
1928 	}
1929 	infra = htod32(infra);
1930 	ap = htod32(ap);
1931 
1932 	if ((error = dev_wlc_ioctl(dev, WLC_SET_INFRA, &infra, sizeof(infra))) ||
1933 	    (error = dev_wlc_ioctl(dev, WLC_SET_AP, &ap, sizeof(ap))))
1934 		return error;
1935 
1936 
1937 	return -EINPROGRESS;
1938 }
1939 
1940 static int
1941 wl_iw_get_mode(
1942 	struct net_device *dev,
1943 	struct iw_request_info *info,
1944 	__u32 *uwrq,
1945 	char *extra
1946 )
1947 {
1948 	int error, infra = 0, ap = 0;
1949 
1950 	WL_TRACE(("%s: SIOCGIWMODE\n", dev->name));
1951 
1952 	if ((error = dev_wlc_ioctl(dev, WLC_GET_INFRA, &infra, sizeof(infra))) ||
1953 	    (error = dev_wlc_ioctl(dev, WLC_GET_AP, &ap, sizeof(ap))))
1954 		return error;
1955 
1956 	infra = dtoh32(infra);
1957 	ap = dtoh32(ap);
1958 	*uwrq = infra ? ap ? IW_MODE_MASTER : IW_MODE_INFRA : IW_MODE_ADHOC;
1959 
1960 	return 0;
1961 }
1962 
1963 static int
1964 wl_iw_get_range(
1965 	struct net_device *dev,
1966 	struct iw_request_info *info,
1967 	struct iw_point *dwrq,
1968 	char *extra
1969 )
1970 {
1971 	struct iw_range *range = (struct iw_range *) extra;
1972 	wl_uint32_list_t *list;
1973 	wl_rateset_t rateset;
1974 	int8 *channels;
1975 	int error, i, k;
1976 	uint sf, ch;
1977 
1978 	int phytype;
1979 	int bw_cap = 0, sgi_tx = 0, nmode = 0;
1980 	channel_info_t ci;
1981 	uint8 nrate_list2copy = 0;
1982 	uint16 nrate_list[4][8] = { {13, 26, 39, 52, 78, 104, 117, 130},
1983 		{14, 29, 43, 58, 87, 116, 130, 144},
1984 		{27, 54, 81, 108, 162, 216, 243, 270},
1985 		{30, 60, 90, 120, 180, 240, 270, 300}};
1986 
1987 	WL_TRACE(("%s: SIOCGIWRANGE\n", dev->name));
1988 
1989 	if (!extra)
1990 		return -EINVAL;
1991 
1992 	channels = kmalloc((MAXCHANNEL+1)*4, GFP_KERNEL);
1993 	if (!channels) {
1994 		WL_ERROR(("Could not alloc channels\n"));
1995 		return -ENOMEM;
1996 	}
1997 	list = (wl_uint32_list_t *)channels;
1998 
1999 	dwrq->length = sizeof(struct iw_range);
2000 	memset(range, 0, sizeof(range));
2001 
2002 	range->min_nwid = range->max_nwid = 0;
2003 
2004 	list->count = htod32(MAXCHANNEL);
2005 	if ((error = dev_wlc_ioctl(dev, WLC_GET_VALID_CHANNELS, channels, (MAXCHANNEL+1)*4))) {
2006 		kfree(channels);
2007 		return error;
2008 	}
2009 	for (i = 0; i < dtoh32(list->count) && i < IW_MAX_FREQUENCIES; i++) {
2010 		range->freq[i].i = dtoh32(list->element[i]);
2011 
2012 		ch = dtoh32(list->element[i]);
2013 		if (ch <= CH_MAX_2G_CHANNEL)
2014 			sf = WF_CHAN_FACTOR_2_4_G;
2015 		else
2016 			sf = WF_CHAN_FACTOR_5_G;
2017 
2018 		range->freq[i].m = wf_channel2mhz(ch, sf);
2019 		range->freq[i].e = 6;
2020 	}
2021 	range->num_frequency = range->num_channels = i;
2022 
2023 	range->max_qual.qual = 5;
2024 
2025 	range->max_qual.level = 0x100 - 200;
2026 
2027 	range->max_qual.noise = 0x100 - 200;
2028 
2029 	range->sensitivity = 65535;
2030 
2031 #if WIRELESS_EXT > 11
2032 
2033 	range->avg_qual.qual = 3;
2034 
2035 	range->avg_qual.level = 0x100 + WL_IW_RSSI_GOOD;
2036 
2037 	range->avg_qual.noise = 0x100 - 75;
2038 #endif
2039 
2040 	if ((error = dev_wlc_ioctl(dev, WLC_GET_CURR_RATESET, &rateset, sizeof(rateset)))) {
2041 		kfree(channels);
2042 		return error;
2043 	}
2044 	rateset.count = dtoh32(rateset.count);
2045 	range->num_bitrates = rateset.count;
2046 	for (i = 0; i < rateset.count && i < IW_MAX_BITRATES; i++)
2047 		range->bitrate[i] = (rateset.rates[i]& 0x7f) * 500000;
2048 	dev_wlc_intvar_get(dev, "nmode", &nmode);
2049 	dev_wlc_ioctl(dev, WLC_GET_PHYTYPE, &phytype, sizeof(phytype));
2050 
2051 	if (nmode == 1 && phytype == WLC_PHY_TYPE_SSN) {
2052 		dev_wlc_intvar_get(dev, "mimo_bw_cap", &bw_cap);
2053 		dev_wlc_intvar_get(dev, "sgi_tx", &sgi_tx);
2054 		dev_wlc_ioctl(dev, WLC_GET_CHANNEL, &ci, sizeof(channel_info_t));
2055 		ci.hw_channel = dtoh32(ci.hw_channel);
2056 
2057 		if (bw_cap == 0 ||
2058 			(bw_cap == 2 && ci.hw_channel <= 14)) {
2059 			if (sgi_tx == 0)
2060 				nrate_list2copy = 0;
2061 			else
2062 				nrate_list2copy = 1;
2063 		}
2064 		if (bw_cap == 1 ||
2065 			(bw_cap == 2 && ci.hw_channel >= 36)) {
2066 			if (sgi_tx == 0)
2067 				nrate_list2copy = 2;
2068 			else
2069 				nrate_list2copy = 3;
2070 		}
2071 		range->num_bitrates += 8;
2072 		for (k = 0; i < range->num_bitrates; k++, i++) {
2073 
2074 			range->bitrate[i] = (nrate_list[nrate_list2copy][k]) * 500000;
2075 		}
2076 	}
2077 
2078 	if ((error = dev_wlc_ioctl(dev, WLC_GET_PHYTYPE, &i, sizeof(i)))) {
2079 		kfree(channels);
2080 		return error;
2081 	}
2082 	i = dtoh32(i);
2083 	if (i == WLC_PHY_TYPE_A)
2084 		range->throughput = 24000000;
2085 	else
2086 		range->throughput = 1500000;
2087 
2088 	range->min_rts = 0;
2089 	range->max_rts = 2347;
2090 	range->min_frag = 256;
2091 	range->max_frag = 2346;
2092 
2093 	range->max_encoding_tokens = DOT11_MAX_DEFAULT_KEYS;
2094 	range->num_encoding_sizes = 4;
2095 	range->encoding_size[0] = WEP1_KEY_SIZE;
2096 	range->encoding_size[1] = WEP128_KEY_SIZE;
2097 #if WIRELESS_EXT > 17
2098 	range->encoding_size[2] = TKIP_KEY_SIZE;
2099 #else
2100 	range->encoding_size[2] = 0;
2101 #endif
2102 	range->encoding_size[3] = AES_KEY_SIZE;
2103 
2104 	range->min_pmp = 0;
2105 	range->max_pmp = 0;
2106 	range->min_pmt = 0;
2107 	range->max_pmt = 0;
2108 	range->pmp_flags = 0;
2109 	range->pm_capa = 0;
2110 
2111 	range->num_txpower = 2;
2112 	range->txpower[0] = 1;
2113 	range->txpower[1] = 255;
2114 	range->txpower_capa = IW_TXPOW_MWATT;
2115 
2116 #if WIRELESS_EXT > 10
2117 	range->we_version_compiled = WIRELESS_EXT;
2118 	range->we_version_source = 19;
2119 
2120 	range->retry_capa = IW_RETRY_LIMIT;
2121 	range->retry_flags = IW_RETRY_LIMIT;
2122 	range->r_time_flags = 0;
2123 
2124 	range->min_retry = 1;
2125 	range->max_retry = 255;
2126 
2127 	range->min_r_time = 0;
2128 	range->max_r_time = 0;
2129 #endif
2130 
2131 #if WIRELESS_EXT > 17
2132 	range->enc_capa = IW_ENC_CAPA_WPA;
2133 	range->enc_capa |= IW_ENC_CAPA_CIPHER_TKIP;
2134 	range->enc_capa |= IW_ENC_CAPA_CIPHER_CCMP;
2135 #ifdef BCMWPA2
2136 	range->enc_capa |= IW_ENC_CAPA_WPA2;
2137 #endif
2138 
2139 	IW_EVENT_CAPA_SET_KERNEL(range->event_capa);
2140 
2141 	IW_EVENT_CAPA_SET(range->event_capa, SIOCGIWAP);
2142 	IW_EVENT_CAPA_SET(range->event_capa, SIOCGIWSCAN);
2143 	IW_EVENT_CAPA_SET(range->event_capa, IWEVTXDROP);
2144 	IW_EVENT_CAPA_SET(range->event_capa, IWEVMICHAELMICFAILURE);
2145 #ifdef BCMWPA2
2146 	IW_EVENT_CAPA_SET(range->event_capa, IWEVPMKIDCAND);
2147 #endif
2148 #endif
2149 
2150 	kfree(channels);
2151 
2152 	return 0;
2153 }
2154 
2155 static int
2156 rssi_to_qual(int rssi)
2157 {
2158 	if (rssi <= WL_IW_RSSI_NO_SIGNAL)
2159 		return 0;
2160 	else if (rssi <= WL_IW_RSSI_VERY_LOW)
2161 		return 1;
2162 	else if (rssi <= WL_IW_RSSI_LOW)
2163 		return 2;
2164 	else if (rssi <= WL_IW_RSSI_GOOD)
2165 		return 3;
2166 	else if (rssi <= WL_IW_RSSI_VERY_GOOD)
2167 		return 4;
2168 	else
2169 		return 5;
2170 }
2171 
2172 static int
2173 wl_iw_set_spy(
2174 	struct net_device *dev,
2175 	struct iw_request_info *info,
2176 	struct iw_point *dwrq,
2177 	char *extra
2178 )
2179 {
2180 	wl_iw_t *iw = *(wl_iw_t **)netdev_priv(dev);
2181 	struct sockaddr *addr = (struct sockaddr *) extra;
2182 	int i;
2183 
2184 	WL_TRACE(("%s: SIOCSIWSPY\n", dev->name));
2185 
2186 	if (!extra)
2187 		return -EINVAL;
2188 
2189 	iw->spy_num = MIN(ARRAYSIZE(iw->spy_addr), dwrq->length);
2190 	for (i = 0; i < iw->spy_num; i++)
2191 		memcpy(&iw->spy_addr[i], addr[i].sa_data, ETHER_ADDR_LEN);
2192 	memset(iw->spy_qual, 0, sizeof(iw->spy_qual));
2193 
2194 	return 0;
2195 }
2196 
2197 static int
2198 wl_iw_get_spy(
2199 	struct net_device *dev,
2200 	struct iw_request_info *info,
2201 	struct iw_point *dwrq,
2202 	char *extra
2203 )
2204 {
2205 	wl_iw_t *iw = *(wl_iw_t **)netdev_priv(dev);
2206 	struct sockaddr *addr = (struct sockaddr *) extra;
2207 	struct iw_quality *qual = (struct iw_quality *) &addr[iw->spy_num];
2208 	int i;
2209 
2210 	WL_TRACE(("%s: SIOCGIWSPY\n", dev->name));
2211 
2212 	if (!extra)
2213 		return -EINVAL;
2214 
2215 	dwrq->length = iw->spy_num;
2216 	for (i = 0; i < iw->spy_num; i++) {
2217 		memcpy(addr[i].sa_data, &iw->spy_addr[i], ETHER_ADDR_LEN);
2218 		addr[i].sa_family = AF_UNIX;
2219 		memcpy(&qual[i], &iw->spy_qual[i], sizeof(struct iw_quality));
2220 		iw->spy_qual[i].updated = 0;
2221 	}
2222 
2223 	return 0;
2224 }
2225 
2226 
2227 static int
2228 wl_iw_ch_to_chanspec(int ch, wl_join_params_t *join_params, int *join_params_size)
2229 {
2230 	chanspec_t chanspec = 0;
2231 
2232 	if (ch != 0) {
2233 
2234 		join_params->params.chanspec_num = 1;
2235 		join_params->params.chanspec_list[0] = ch;
2236 
2237 		if (join_params->params.chanspec_list[0])
2238 			chanspec |= WL_CHANSPEC_BAND_2G;
2239 		else
2240 			chanspec |= WL_CHANSPEC_BAND_5G;
2241 
2242 		chanspec |= WL_CHANSPEC_BW_20;
2243 		chanspec |= WL_CHANSPEC_CTL_SB_NONE;
2244 
2245 		*join_params_size += WL_ASSOC_PARAMS_FIXED_SIZE +
2246 			join_params->params.chanspec_num * sizeof(chanspec_t);
2247 
2248 		join_params->params.chanspec_list[0]  &= WL_CHANSPEC_CHAN_MASK;
2249 		join_params->params.chanspec_list[0] |= chanspec;
2250 		join_params->params.chanspec_list[0] =
2251 		        htodchanspec(join_params->params.chanspec_list[0]);
2252 
2253 		join_params->params.chanspec_num = htod32(join_params->params.chanspec_num);
2254 
2255 		WL_TRACE(("%s  join_params->params.chanspec_list[0]= %X\n", \
2256 			__FUNCTION__, join_params->params.chanspec_list[0]));
2257 	}
2258 	return 1;
2259 }
2260 
2261 static int
2262 wl_iw_set_wap(
2263 	struct net_device *dev,
2264 	struct iw_request_info *info,
2265 	struct sockaddr *awrq,
2266 	char *extra
2267 )
2268 {
2269 	int error = -EINVAL;
2270 	wl_join_params_t join_params;
2271 	int join_params_size;
2272 
2273 	WL_TRACE(("%s: SIOCSIWAP\n", dev->name));
2274 
2275 	if (awrq->sa_family != ARPHRD_ETHER) {
2276 		WL_ERROR(("Invalid Header...sa_family\n"));
2277 		return -EINVAL;
2278 	}
2279 
2280 
2281 	if (ETHER_ISBCAST(awrq->sa_data) || ETHER_ISNULLADDR(awrq->sa_data)) {
2282 		scb_val_t scbval;
2283 
2284 		bzero(&scbval, sizeof(scb_val_t));
2285 
2286 		(void) dev_wlc_ioctl(dev, WLC_DISASSOC, &scbval, sizeof(scb_val_t));
2287 		return 0;
2288 	}
2289 
2290 
2291 
2292 	memset(&join_params, 0, sizeof(join_params));
2293 	join_params_size = sizeof(join_params.ssid);
2294 
2295 	memcpy(join_params.ssid.SSID, g_ssid.SSID, g_ssid.SSID_len);
2296 	join_params.ssid.SSID_len = htod32(g_ssid.SSID_len);
2297 	memcpy(&join_params.params.bssid, awrq->sa_data, ETHER_ADDR_LEN);
2298 
2299 	WL_TRACE(("%s  target_channel=%d\n", __FUNCTION__, g_wl_iw_params.target_channel));
2300 	wl_iw_ch_to_chanspec(g_wl_iw_params.target_channel, &join_params, &join_params_size);
2301 
2302 	if ((error = dev_wlc_ioctl(dev, WLC_SET_SSID, &join_params, join_params_size))) {
2303 		WL_ERROR(("%s Invalid ioctl data=%d\n", __FUNCTION__, error));
2304 		return error;
2305 	}
2306 
2307 	if (g_ssid.SSID_len) {
2308 		WL_TRACE(("%s: join SSID=%s BSSID="MACSTR" ch=%d\n", __FUNCTION__,  \
2309 			g_ssid.SSID, MAC2STR((u8 *)awrq->sa_data), \
2310 			g_wl_iw_params.target_channel));
2311 	}
2312 
2313 
2314 	memset(&g_ssid, 0, sizeof(g_ssid));
2315 	return 0;
2316 }
2317 
2318 static int
2319 wl_iw_get_wap(
2320 	struct net_device *dev,
2321 	struct iw_request_info *info,
2322 	struct sockaddr *awrq,
2323 	char *extra
2324 )
2325 {
2326 	WL_TRACE(("%s: SIOCGIWAP\n", dev->name));
2327 
2328 	awrq->sa_family = ARPHRD_ETHER;
2329 	memset(awrq->sa_data, 0, ETHER_ADDR_LEN);
2330 
2331 
2332 	(void) dev_wlc_ioctl(dev, WLC_GET_BSSID, awrq->sa_data, ETHER_ADDR_LEN);
2333 
2334 	return 0;
2335 }
2336 
2337 #if WIRELESS_EXT > 17
2338 static int
2339 wl_iw_mlme(
2340 	struct net_device *dev,
2341 	struct iw_request_info *info,
2342 	struct sockaddr *awrq,
2343 	char *extra
2344 )
2345 {
2346 	struct iw_mlme *mlme;
2347 	scb_val_t scbval;
2348 	int error  = -EINVAL;
2349 
2350 	WL_TRACE(("%s: SIOCSIWMLME DISASSOC/DEAUTH\n", dev->name));
2351 
2352 	mlme = (struct iw_mlme *)extra;
2353 	if (mlme == NULL) {
2354 		WL_ERROR(("Invalid ioctl data.\n"));
2355 		return error;
2356 	}
2357 
2358 	scbval.val = mlme->reason_code;
2359 	bcopy(&mlme->addr.sa_data, &scbval.ea, ETHER_ADDR_LEN);
2360 
2361 	if (mlme->cmd == IW_MLME_DISASSOC) {
2362 		scbval.val = htod32(scbval.val);
2363 		error = dev_wlc_ioctl(dev, WLC_DISASSOC, &scbval, sizeof(scb_val_t));
2364 	}
2365 	else if (mlme->cmd == IW_MLME_DEAUTH) {
2366 		scbval.val = htod32(scbval.val);
2367 		error = dev_wlc_ioctl(dev, WLC_SCB_DEAUTHENTICATE_FOR_REASON, &scbval,
2368 			sizeof(scb_val_t));
2369 	}
2370 	else {
2371 		WL_ERROR(("Invalid ioctl data.\n"));
2372 		return error;
2373 	}
2374 
2375 	return error;
2376 }
2377 #endif
2378 
2379 #ifndef WL_IW_USE_ISCAN
2380 static int
2381 wl_iw_get_aplist(
2382 	struct net_device *dev,
2383 	struct iw_request_info *info,
2384 	struct iw_point *dwrq,
2385 	char *extra
2386 )
2387 {
2388 	wl_scan_results_t *list;
2389 	struct sockaddr *addr = (struct sockaddr *) extra;
2390 	struct iw_quality qual[IW_MAX_AP];
2391 	wl_bss_info_t *bi = NULL;
2392 	int error, i;
2393 	uint buflen = dwrq->length;
2394 
2395 	WL_TRACE(("%s: SIOCGIWAPLIST\n", dev->name));
2396 
2397 	if (!extra)
2398 		return -EINVAL;
2399 
2400 	list = kmalloc(buflen, GFP_KERNEL);
2401 	if (!list)
2402 		return -ENOMEM;
2403 	memset(list, 0, buflen);
2404 	list->buflen = htod32(buflen);
2405 	if ((error = dev_wlc_ioctl(dev, WLC_SCAN_RESULTS, list, buflen))) {
2406 		WL_ERROR(("%d: Scan results error %d\n", __LINE__, error));
2407 		kfree(list);
2408 		return error;
2409 	}
2410 	list->buflen = dtoh32(list->buflen);
2411 	list->version = dtoh32(list->version);
2412 	list->count = dtoh32(list->count);
2413 	if (list->version != WL_BSS_INFO_VERSION) {
2414 		WL_ERROR(("%s : list->version %d != WL_BSS_INFO_VERSION\n", \
2415 			 __FUNCTION__, list->version));
2416 		kfree(list);
2417 		return -EINVAL;
2418 	}
2419 
2420 	for (i = 0, dwrq->length = 0; i < list->count && dwrq->length < IW_MAX_AP; i++) {
2421 		bi = bi ? (wl_bss_info_t *)((uintptr)bi + dtoh32(bi->length)) : list->bss_info;
2422 		ASSERT(((uintptr)bi + dtoh32(bi->length)) <= ((uintptr)list +
2423 			buflen));
2424 
2425 
2426 		if (!(dtoh16(bi->capability) & DOT11_CAP_ESS))
2427 			continue;
2428 
2429 
2430 		memcpy(addr[dwrq->length].sa_data, &bi->BSSID, ETHER_ADDR_LEN);
2431 		addr[dwrq->length].sa_family = ARPHRD_ETHER;
2432 		qual[dwrq->length].qual = rssi_to_qual(dtoh16(bi->RSSI));
2433 		qual[dwrq->length].level = 0x100 + dtoh16(bi->RSSI);
2434 		qual[dwrq->length].noise = 0x100 + bi->phy_noise;
2435 
2436 
2437 #if WIRELESS_EXT > 18
2438 		qual[dwrq->length].updated = IW_QUAL_ALL_UPDATED | IW_QUAL_DBM;
2439 #else
2440 		qual[dwrq->length].updated = 7;
2441 #endif
2442 
2443 		dwrq->length++;
2444 	}
2445 
2446 	kfree(list);
2447 
2448 	if (dwrq->length) {
2449 		memcpy(&addr[dwrq->length], qual, sizeof(struct iw_quality) * dwrq->length);
2450 
2451 		dwrq->flags = 1;
2452 	}
2453 	return 0;
2454 }
2455 #endif
2456 
2457 #ifdef WL_IW_USE_ISCAN
2458 static int
2459 wl_iw_iscan_get_aplist(
2460 	struct net_device *dev,
2461 	struct iw_request_info *info,
2462 	struct iw_point *dwrq,
2463 	char *extra
2464 )
2465 {
2466 	wl_scan_results_t *list;
2467 	iscan_buf_t * buf;
2468 	iscan_info_t *iscan = g_iscan;
2469 
2470 	struct sockaddr *addr = (struct sockaddr *) extra;
2471 	struct iw_quality qual[IW_MAX_AP];
2472 	wl_bss_info_t *bi = NULL;
2473 	int i;
2474 
2475 	WL_TRACE(("%s: SIOCGIWAPLIST\n", dev->name));
2476 
2477 	if (!extra)
2478 		return -EINVAL;
2479 
2480 	if ((!iscan) || (iscan->sysioc_pid < 0)) {
2481 		WL_ERROR(("%s error\n", __FUNCTION__));
2482 		return 0;
2483 	}
2484 
2485 	buf = iscan->list_hdr;
2486 
2487 	while (buf) {
2488 		list = &((wl_iscan_results_t*)buf->iscan_buf)->results;
2489 		if (list->version != WL_BSS_INFO_VERSION) {
2490 			WL_ERROR(("%s : list->version %d != WL_BSS_INFO_VERSION\n", \
2491 				__FUNCTION__, list->version));
2492 			return -EINVAL;
2493 		}
2494 
2495 		bi = NULL;
2496 		for (i = 0, dwrq->length = 0; i < list->count && dwrq->length < IW_MAX_AP; i++) {
2497 			bi = bi ? (wl_bss_info_t *)((uintptr)bi + dtoh32(bi->length))
2498 			          : list->bss_info;
2499 			ASSERT(((uintptr)bi + dtoh32(bi->length)) <= ((uintptr)list +
2500 				WLC_IW_ISCAN_MAXLEN));
2501 
2502 
2503 			if (!(dtoh16(bi->capability) & DOT11_CAP_ESS))
2504 				continue;
2505 
2506 
2507 			memcpy(addr[dwrq->length].sa_data, &bi->BSSID, ETHER_ADDR_LEN);
2508 			addr[dwrq->length].sa_family = ARPHRD_ETHER;
2509 			qual[dwrq->length].qual = rssi_to_qual(dtoh16(bi->RSSI));
2510 			qual[dwrq->length].level = 0x100 + dtoh16(bi->RSSI);
2511 			qual[dwrq->length].noise = 0x100 + bi->phy_noise;
2512 
2513 
2514 #if WIRELESS_EXT > 18
2515 			qual[dwrq->length].updated = IW_QUAL_ALL_UPDATED | IW_QUAL_DBM;
2516 #else
2517 			qual[dwrq->length].updated = 7;
2518 #endif
2519 
2520 			dwrq->length++;
2521 		}
2522 		buf = buf->next;
2523 	}
2524 	if (dwrq->length) {
2525 		memcpy(&addr[dwrq->length], qual, sizeof(struct iw_quality) * dwrq->length);
2526 
2527 		dwrq->flags = 1;
2528 	}
2529 	return 0;
2530 }
2531 
2532 static int
2533 wl_iw_iscan_prep(wl_scan_params_t *params, wlc_ssid_t *ssid)
2534 {
2535 	int err = 0;
2536 
2537 	memcpy(&params->bssid, &ether_bcast, ETHER_ADDR_LEN);
2538 	params->bss_type = DOT11_BSSTYPE_ANY;
2539 	params->scan_type = 0;
2540 	params->nprobes = -1;
2541 	params->active_time = -1;
2542 	params->passive_time = -1;
2543 	params->home_time = -1;
2544 	params->channel_num = 0;
2545 
2546 	params->nprobes = htod32(params->nprobes);
2547 	params->active_time = htod32(params->active_time);
2548 	params->passive_time = htod32(params->passive_time);
2549 	params->home_time = htod32(params->home_time);
2550 	if (ssid && ssid->SSID_len)
2551 		memcpy(&params->ssid, ssid, sizeof(wlc_ssid_t));
2552 
2553 	return err;
2554 }
2555 
2556 static int
2557 wl_iw_iscan(iscan_info_t *iscan, wlc_ssid_t *ssid, uint16 action)
2558 {
2559 	int err = 0;
2560 
2561 	iscan->iscan_ex_params_p->version = htod32(ISCAN_REQ_VERSION);
2562 	iscan->iscan_ex_params_p->action = htod16(action);
2563 	iscan->iscan_ex_params_p->scan_duration = htod16(0);
2564 
2565 	WL_SCAN(("%s : nprobes=%d\n", __FUNCTION__, iscan->iscan_ex_params_p->params.nprobes));
2566 	WL_SCAN(("active_time=%d\n", iscan->iscan_ex_params_p->params.active_time));
2567 	WL_SCAN(("passive_time=%d\n", iscan->iscan_ex_params_p->params.passive_time));
2568 	WL_SCAN(("home_time=%d\n", iscan->iscan_ex_params_p->params.home_time));
2569 	WL_SCAN(("scan_type=%d\n", iscan->iscan_ex_params_p->params.scan_type));
2570 	WL_SCAN(("bss_type=%d\n", iscan->iscan_ex_params_p->params.bss_type));
2571 
2572 
2573 	if ((err = dev_iw_iovar_setbuf(iscan->dev, "iscan", iscan->iscan_ex_params_p, \
2574 		iscan->iscan_ex_param_size, iscan->ioctlbuf, sizeof(iscan->ioctlbuf)))) {
2575 			WL_ERROR(("Set ISCAN for %s failed with %d\n", __FUNCTION__, err));
2576 			err = -1;
2577 	}
2578 
2579 	return err;
2580 }
2581 
2582 static void
2583 wl_iw_timerfunc(ulong data)
2584 {
2585 	iscan_info_t *iscan = (iscan_info_t *)data;
2586 	if (iscan) {
2587 		iscan->timer_on = 0;
2588 		if (iscan->iscan_state != ISCAN_STATE_IDLE) {
2589 			WL_SCAN(("timer trigger\n"));
2590 			up(&iscan->sysioc_sem);
2591 		}
2592 	}
2593 }
2594 static void wl_iw_set_event_mask(struct net_device *dev)
2595 {
2596 	char eventmask[WL_EVENTING_MASK_LEN];
2597 	char iovbuf[WL_EVENTING_MASK_LEN + 12];
2598 
2599 	dev_iw_iovar_getbuf(dev, "event_msgs", "", 0, iovbuf, sizeof(iovbuf));
2600 	bcopy(iovbuf, eventmask, WL_EVENTING_MASK_LEN);
2601 	setbit(eventmask, WLC_E_SCAN_COMPLETE);
2602 	dev_iw_iovar_setbuf(dev, "event_msgs", eventmask, WL_EVENTING_MASK_LEN,
2603 		iovbuf, sizeof(iovbuf));
2604 }
2605 
2606 static uint32
2607 wl_iw_iscan_get(iscan_info_t *iscan)
2608 {
2609 	iscan_buf_t * buf;
2610 	iscan_buf_t * ptr;
2611 	wl_iscan_results_t * list_buf;
2612 	wl_iscan_results_t list;
2613 	wl_scan_results_t *results;
2614 	uint32 status;
2615 	int res;
2616 
2617 	mutex_lock(&wl_cache_lock);
2618 	if (iscan->list_cur) {
2619 		buf = iscan->list_cur;
2620 		iscan->list_cur = buf->next;
2621 	}
2622 	else {
2623 		buf = kmalloc(sizeof(iscan_buf_t), GFP_KERNEL);
2624 		if (!buf) {
2625 			WL_ERROR(("%s can't alloc iscan_buf_t : going to abort currect iscan\n", \
2626 						__FUNCTION__));
2627 			mutex_unlock(&wl_cache_lock);
2628 			return WL_SCAN_RESULTS_NO_MEM;
2629 		}
2630 		buf->next = NULL;
2631 		if (!iscan->list_hdr)
2632 			iscan->list_hdr = buf;
2633 		else {
2634 			ptr = iscan->list_hdr;
2635 			while (ptr->next) {
2636 				ptr = ptr->next;
2637 			}
2638 			ptr->next = buf;
2639 		}
2640 	}
2641 	memset(buf->iscan_buf, 0, WLC_IW_ISCAN_MAXLEN);
2642 	list_buf = (wl_iscan_results_t*)buf->iscan_buf;
2643 	results = &list_buf->results;
2644 	results->buflen = WL_ISCAN_RESULTS_FIXED_SIZE;
2645 	results->version = 0;
2646 	results->count = 0;
2647 
2648 	memset(&list, 0, sizeof(list));
2649 	list.results.buflen = htod32(WLC_IW_ISCAN_MAXLEN);
2650 	res = dev_iw_iovar_getbuf(
2651 		iscan->dev,
2652 		"iscanresults",
2653 		&list,
2654 		WL_ISCAN_RESULTS_FIXED_SIZE,
2655 		buf->iscan_buf,
2656 		WLC_IW_ISCAN_MAXLEN);
2657 	if (res == 0) {
2658 		results->buflen = dtoh32(results->buflen);
2659 		results->version = dtoh32(results->version);
2660 		results->count = dtoh32(results->count);
2661 		WL_SCAN(("results->count = %d\n", results->count));
2662 
2663 		WL_SCAN(("results->buflen = %d\n", results->buflen));
2664 		status = dtoh32(list_buf->status);
2665 	} else {
2666 		WL_ERROR(("%s returns error %d\n", __FUNCTION__, res));
2667 		status = WL_SCAN_RESULTS_NO_MEM;
2668 	}
2669 	mutex_unlock(&wl_cache_lock);
2670 	return status;
2671 }
2672 
2673 static void wl_iw_force_specific_scan(iscan_info_t *iscan)
2674 {
2675 	WL_TRACE(("%s force Specific SCAN for %s\n", __FUNCTION__, g_specific_ssid.SSID));
2676 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27))
2677 	rtnl_lock();
2678 #endif
2679 	(void) dev_wlc_ioctl(iscan->dev, WLC_SCAN, &g_specific_ssid, sizeof(g_specific_ssid));
2680 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27))
2681 	rtnl_unlock();
2682 #endif
2683 }
2684 
2685 static void wl_iw_send_scan_complete(iscan_info_t *iscan)
2686 {
2687 #ifndef SANDGATE2G
2688 	union iwreq_data wrqu;
2689 
2690 	memset(&wrqu, 0, sizeof(wrqu));
2691 
2692 	wireless_send_event(iscan->dev, SIOCGIWSCAN, &wrqu, NULL);
2693 	if (g_first_broadcast_scan == BROADCAST_SCAN_FIRST_STARTED)
2694 		g_first_broadcast_scan = BROADCAST_SCAN_FIRST_RESULT_READY;
2695 	WL_TRACE(("Send Event ISCAN complete\n"));
2696 #endif
2697 }
2698 
2699 static int
2700 _iscan_sysioc_thread(void *data)
2701 {
2702 	uint32 status;
2703 	iscan_info_t *iscan = (iscan_info_t *)data;
2704 	static bool iscan_pass_abort = FALSE;
2705 
2706 	DAEMONIZE("iscan_sysioc");
2707 
2708 	status = WL_SCAN_RESULTS_PARTIAL;
2709 	while (down_interruptible(&iscan->sysioc_sem) == 0) {
2710 
2711 		net_os_wake_lock(iscan->dev);
2712 
2713 #if defined(SOFTAP)
2714 		if (ap_cfg_running) {
2715 			WL_SCAN(("%s skipping SCAN ops in AP mode !!!\n", __FUNCTION__));
2716 			net_os_wake_unlock(iscan->dev);
2717 			continue;
2718 		}
2719 #endif
2720 
2721 		if (iscan->timer_on) {
2722 			iscan->timer_on = 0;
2723 			del_timer_sync(&iscan->timer);
2724 		}
2725 
2726 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27))
2727 		rtnl_lock();
2728 #endif
2729 		status = wl_iw_iscan_get(iscan);
2730 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27))
2731 		rtnl_unlock();
2732 #endif
2733 
2734 		if (g_scan_specified_ssid && (iscan_pass_abort == TRUE)) {
2735 			WL_SCAN(("%s Get results from specific scan status=%d\n", __FUNCTION__, status));
2736 			wl_iw_send_scan_complete(iscan);
2737 			iscan_pass_abort = FALSE;
2738 			status  = -1;
2739 		}
2740 
2741 		switch (status) {
2742 			case WL_SCAN_RESULTS_PARTIAL:
2743 				WL_SCAN(("iscanresults incomplete\n"));
2744 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27))
2745 				rtnl_lock();
2746 #endif
2747 
2748 				wl_iw_iscan(iscan, NULL, WL_SCAN_ACTION_CONTINUE);
2749 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27))
2750 				rtnl_unlock();
2751 #endif
2752 
2753 				mod_timer(&iscan->timer, jiffies + iscan->timer_ms*HZ/1000);
2754 				iscan->timer_on = 1;
2755 				break;
2756 			case WL_SCAN_RESULTS_SUCCESS:
2757 				WL_SCAN(("iscanresults complete\n"));
2758 				iscan->iscan_state = ISCAN_STATE_IDLE;
2759 				wl_iw_send_scan_complete(iscan);
2760 				break;
2761 			case WL_SCAN_RESULTS_PENDING:
2762 				WL_SCAN(("iscanresults pending\n"));
2763 
2764 				mod_timer(&iscan->timer, jiffies + iscan->timer_ms*HZ/1000);
2765 				iscan->timer_on = 1;
2766 				break;
2767 			case WL_SCAN_RESULTS_ABORTED:
2768 				WL_SCAN(("iscanresults aborted\n"));
2769 				iscan->iscan_state = ISCAN_STATE_IDLE;
2770 				if (g_scan_specified_ssid == 0)
2771 					wl_iw_send_scan_complete(iscan);
2772 				else {
2773 					iscan_pass_abort = TRUE;
2774 					wl_iw_force_specific_scan(iscan);
2775 				}
2776 				break;
2777 			case WL_SCAN_RESULTS_NO_MEM:
2778 				WL_SCAN(("iscanresults can't alloc memory: skip\n"));
2779 				iscan->iscan_state = ISCAN_STATE_IDLE;
2780 				break;
2781 			default:
2782 				WL_SCAN(("iscanresults returned unknown status %d\n", status));
2783 				break;
2784 		}
2785 
2786 		net_os_wake_unlock(iscan->dev);
2787 	}
2788 
2789 	if (iscan->timer_on) {
2790 		iscan->timer_on = 0;
2791 		del_timer_sync(&iscan->timer);
2792 	}
2793 
2794 	complete_and_exit(&iscan->sysioc_exited, 0);
2795 }
2796 #endif
2797 
2798 #if !defined(CSCAN)
2799 
2800 static void
2801 wl_iw_set_ss_cache_timer_flag(void)
2802 {
2803 	g_ss_cache_ctrl.m_timer_expired = 1;
2804 	WL_TRACE(("%s called\n", __FUNCTION__));
2805 }
2806 
2807 static int
2808 wl_iw_init_ss_cache_ctrl(void)
2809 {
2810 	WL_TRACE(("%s :\n", __FUNCTION__));
2811 	g_ss_cache_ctrl.m_prev_scan_mode = 0;
2812 	g_ss_cache_ctrl.m_cons_br_scan_cnt = 0;
2813 	g_ss_cache_ctrl.m_cache_head = NULL;
2814 	g_ss_cache_ctrl.m_link_down = 0;
2815 	g_ss_cache_ctrl.m_timer_expired = 0;
2816 	memset(g_ss_cache_ctrl.m_active_bssid, 0, ETHER_ADDR_LEN);
2817 
2818 	g_ss_cache_ctrl.m_timer = kmalloc(sizeof(struct timer_list), GFP_KERNEL);
2819 	if (!g_ss_cache_ctrl.m_timer) {
2820 		return -ENOMEM;
2821 	}
2822 	g_ss_cache_ctrl.m_timer->function = (void *)wl_iw_set_ss_cache_timer_flag;
2823 	init_timer(g_ss_cache_ctrl.m_timer);
2824 
2825 	return 0;
2826 }
2827 
2828 
2829 
2830 static void
2831 wl_iw_free_ss_cache(void)
2832 {
2833 	wl_iw_ss_cache_t *node, *cur;
2834 	wl_iw_ss_cache_t **spec_scan_head;
2835 
2836 	WL_TRACE(("%s called\n", __FUNCTION__));
2837 
2838 	mutex_lock(&wl_cache_lock);
2839 	spec_scan_head = &g_ss_cache_ctrl.m_cache_head;
2840 	node = *spec_scan_head;
2841 
2842 	for (;node;) {
2843 		WL_TRACE(("%s : SSID - %s\n", __FUNCTION__, node->bss_info->SSID));
2844 		cur = node;
2845 		node = cur->next;
2846 		kfree(cur);
2847 	}
2848 	*spec_scan_head = NULL;
2849 	mutex_unlock(&wl_cache_lock);
2850 }
2851 
2852 
2853 
2854 static int
2855 wl_iw_run_ss_cache_timer(int kick_off)
2856 {
2857 	struct timer_list **timer;
2858 
2859 	timer = &g_ss_cache_ctrl.m_timer;
2860 
2861 	if (*timer) {
2862 		if (kick_off) {
2863 			(*timer)->expires = jiffies + 30000 * HZ / 1000;
2864 			add_timer(*timer);
2865 			WL_TRACE(("%s : timer starts \n", __FUNCTION__));
2866 		} else {
2867 			del_timer_sync(*timer);
2868 			WL_TRACE(("%s : timer stops \n", __FUNCTION__));
2869 		}
2870 	}
2871 
2872 	return 0;
2873 }
2874 
2875 
2876 void
2877 wl_iw_release_ss_cache_ctrl(void)
2878 {
2879 	WL_TRACE(("%s :\n", __FUNCTION__));
2880 	wl_iw_free_ss_cache();
2881 	wl_iw_run_ss_cache_timer(0);
2882 	if (g_ss_cache_ctrl.m_timer) {
2883 		kfree(g_ss_cache_ctrl.m_timer);
2884 	}
2885 }
2886 
2887 
2888 
2889 static void
2890 wl_iw_reset_ss_cache(void)
2891 {
2892 	wl_iw_ss_cache_t *node, *prev, *cur;
2893 	wl_iw_ss_cache_t **spec_scan_head;
2894 
2895 	mutex_lock(&wl_cache_lock);
2896 	spec_scan_head = &g_ss_cache_ctrl.m_cache_head;
2897 	node = *spec_scan_head;
2898 	prev = node;
2899 
2900 	for (;node;) {
2901 		WL_TRACE(("%s : node SSID %s \n", __FUNCTION__, node->bss_info->SSID));
2902 		if (!node->dirty) {
2903 			cur = node;
2904 			if (cur == *spec_scan_head) {
2905 				*spec_scan_head = cur->next;
2906 				prev = *spec_scan_head;
2907 			}
2908 			else {
2909 				prev->next = cur->next;
2910 			}
2911 			node = cur->next;
2912 
2913 			WL_TRACE(("%s : Del node : SSID %s\n", __FUNCTION__, cur->bss_info->SSID));
2914 			kfree(cur);
2915 			continue;
2916 		}
2917 
2918 		node->dirty = 0;
2919 		prev = node;
2920 		node = node->next;
2921 	}
2922 	mutex_unlock(&wl_cache_lock);
2923 }
2924 
2925 
2926 static int
2927 wl_iw_add_bss_to_ss_cache(wl_scan_results_t *ss_list)
2928 {
2929 
2930 	wl_iw_ss_cache_t *node, *prev, *leaf;
2931 	wl_iw_ss_cache_t **spec_scan_head;
2932 	wl_bss_info_t *bi = NULL;
2933 	int i;
2934 
2935 	if (!ss_list->count) {
2936 		return 0;
2937 	}
2938 
2939 	mutex_lock(&wl_cache_lock);
2940 	spec_scan_head = &g_ss_cache_ctrl.m_cache_head;
2941 
2942 	for (i = 0; i < ss_list->count; i++) {
2943 
2944 		node = *spec_scan_head;
2945 		prev = node;
2946 
2947 		bi = bi ? (wl_bss_info_t *)((uintptr)bi + dtoh32(bi->length)) : ss_list->bss_info;
2948 
2949 		WL_TRACE(("%s : find %d with specific SSID %s\n", __FUNCTION__, i, bi->SSID));
2950 		for (;node;) {
2951 			if (!memcmp(&node->bss_info->BSSID, &bi->BSSID, ETHER_ADDR_LEN)) {
2952 
2953 				WL_TRACE(("dirty marked : SSID %s\n", bi->SSID));
2954 				node->dirty = 1;
2955 				break;
2956 			}
2957 			prev = node;
2958 			node = node->next;
2959 		}
2960 
2961 		if (node) {
2962 			continue;
2963 		}
2964 		leaf = kmalloc(bi->length + WLC_IW_SS_CACHE_CTRL_FIELD_MAXLEN, GFP_KERNEL);
2965 		if (!leaf) {
2966 			WL_ERROR(("Memory alloc failure %d\n", \
2967 				bi->length + WLC_IW_SS_CACHE_CTRL_FIELD_MAXLEN));
2968 			mutex_unlock(&wl_cache_lock);
2969 			return -ENOMEM;
2970 		}
2971 
2972 		memcpy(leaf->bss_info, bi, bi->length);
2973 		leaf->next = NULL;
2974 		leaf->dirty = 1;
2975 		leaf->count = 1;
2976 		leaf->version = ss_list->version;
2977 
2978 		if (!prev) {
2979 			*spec_scan_head = leaf;
2980 		}
2981 		else {
2982 			prev->next = leaf;
2983 		}
2984 	}
2985 	mutex_unlock(&wl_cache_lock);
2986 	return 0;
2987 }
2988 
2989 
2990 static int
2991 wl_iw_merge_scan_cache(struct iw_request_info *info, char *extra, uint buflen_from_user,
2992 __u16 *merged_len)
2993 {
2994 	wl_iw_ss_cache_t *node;
2995 	wl_scan_results_t *list_merge;
2996 
2997 	mutex_lock(&wl_cache_lock);
2998 	node = g_ss_cache_ctrl.m_cache_head;
2999 	for (;node;) {
3000 		list_merge = (wl_scan_results_t *)node;
3001 		WL_TRACE(("%s: Cached Specific APs list=%d\n", __FUNCTION__, list_merge->count));
3002 		if (buflen_from_user - *merged_len > 0) {
3003 			*merged_len += (__u16) wl_iw_get_scan_prep(list_merge, info,
3004 				extra + *merged_len, buflen_from_user - *merged_len);
3005 		}
3006 		else {
3007 			WL_TRACE(("%s: exit with break\n", __FUNCTION__));
3008 			break;
3009 		}
3010 		node = node->next;
3011 	}
3012 	mutex_unlock(&wl_cache_lock);
3013 	return 0;
3014 }
3015 
3016 
3017 static int
3018 wl_iw_delete_bss_from_ss_cache(void *addr)
3019 {
3020 
3021 	wl_iw_ss_cache_t *node, *prev;
3022 	wl_iw_ss_cache_t **spec_scan_head;
3023 
3024 	mutex_lock(&wl_cache_lock);
3025 	spec_scan_head = &g_ss_cache_ctrl.m_cache_head;
3026 	node = *spec_scan_head;
3027 	prev = node;
3028 	for (;node;) {
3029 		if (!memcmp(&node->bss_info->BSSID, addr, ETHER_ADDR_LEN)) {
3030 			if (node == *spec_scan_head) {
3031 				*spec_scan_head = node->next;
3032 			}
3033 			else {
3034 				prev->next = node->next;
3035 			}
3036 
3037 			WL_TRACE(("%s : Del node : %s\n", __FUNCTION__, node->bss_info->SSID));
3038 			kfree(node);
3039 			break;
3040 		}
3041 
3042 		prev = node;
3043 		node = node->next;
3044 	}
3045 
3046 	memset(addr, 0, ETHER_ADDR_LEN);
3047 	mutex_unlock(&wl_cache_lock);
3048 	return 0;
3049 }
3050 
3051 #endif
3052 
3053 
3054 static int
3055 wl_iw_set_scan(
3056 	struct net_device *dev,
3057 	struct iw_request_info *info,
3058 	union iwreq_data *wrqu,
3059 	char *extra
3060 )
3061 {
3062 	int error;
3063 	WL_TRACE(("%s dev:%s: SIOCSIWSCAN : SCAN\n", __FUNCTION__, dev->name));
3064 
3065 #if defined(CSCAN)
3066 	WL_ERROR(("%s: Scan from SIOCGIWSCAN not supported\n", __FUNCTION__));
3067 	return -EINVAL;
3068 #endif
3069 
3070 #if defined(SOFTAP)
3071 	if (ap_cfg_running) {
3072 		WL_TRACE(("\n>%s: Not executed, reason -'SOFTAP is active'\n", __FUNCTION__));
3073 		return 0;
3074 	}
3075 #endif
3076 
3077 	if (g_onoff == G_WLAN_SET_OFF)
3078 		return 0;
3079 
3080 	memset(&g_specific_ssid, 0, sizeof(g_specific_ssid));
3081 #ifndef WL_IW_USE_ISCAN
3082 	g_scan_specified_ssid = 0;
3083 #endif
3084 
3085 #if WIRELESS_EXT > 17
3086 
3087 	if (wrqu->data.length == sizeof(struct iw_scan_req)) {
3088 		if (wrqu->data.flags & IW_SCAN_THIS_ESSID) {
3089 			struct iw_scan_req *req = (struct iw_scan_req *)extra;
3090 			if (g_first_broadcast_scan != BROADCAST_SCAN_FIRST_RESULT_CONSUMED) {
3091 				WL_TRACE(("%s Ignoring SC %s first BC is not done = %d\n", \
3092 						__FUNCTION__, req->essid, \
3093 						g_first_broadcast_scan));
3094 				return -EBUSY;
3095 			}
3096 			if (g_scan_specified_ssid) {
3097 				WL_TRACE(("%s Specific SCAN is not done ignore scan for = %s \n", \
3098 					__FUNCTION__, req->essid));
3099 				return -EBUSY;
3100 			}
3101 			else {
3102 				g_specific_ssid.SSID_len = MIN(sizeof(g_specific_ssid.SSID), \
3103 										req->essid_len);
3104 				memcpy(g_specific_ssid.SSID, req->essid, g_specific_ssid.SSID_len);
3105 				g_specific_ssid.SSID_len = htod32(g_specific_ssid.SSID_len);
3106 				g_scan_specified_ssid = 1;
3107 				WL_TRACE(("### Specific scan ssid=%s len=%d\n", \
3108 						g_specific_ssid.SSID, g_specific_ssid.SSID_len));
3109 			}
3110 		}
3111 	}
3112 #endif
3113 
3114 	if ((error = dev_wlc_ioctl(dev, WLC_SCAN, &g_specific_ssid, sizeof(g_specific_ssid)))) {
3115 		WL_TRACE(("#### Set SCAN for %s failed with %d\n", g_specific_ssid.SSID, error));
3116 		g_scan_specified_ssid = 0;
3117 		return -EBUSY;
3118 	}
3119 
3120 	return 0;
3121 }
3122 
3123 #ifdef WL_IW_USE_ISCAN
3124 int
3125 wl_iw_iscan_set_scan_broadcast_prep(struct net_device *dev, uint flag)
3126 {
3127 	wlc_ssid_t ssid;
3128 	iscan_info_t *iscan = g_iscan;
3129 
3130 	if (g_first_broadcast_scan == BROADCAST_SCAN_FIRST_IDLE) {
3131 		g_first_broadcast_scan = BROADCAST_SCAN_FIRST_STARTED;
3132 		WL_TRACE(("%s: First Brodcast scan was forced\n", __FUNCTION__));
3133 	}
3134 	else if (g_first_broadcast_scan == BROADCAST_SCAN_FIRST_STARTED) {
3135 		WL_TRACE(("%s: ignore ISCAN request first BS is not done yet\n", __FUNCTION__));
3136 		return 0;
3137 	}
3138 
3139 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27))
3140 	if (flag)
3141 		rtnl_lock();
3142 #endif
3143 
3144 	dev_wlc_ioctl(dev, WLC_SET_PASSIVE_SCAN, &iscan->scan_flag, sizeof(iscan->scan_flag));
3145 	wl_iw_set_event_mask(dev);
3146 
3147 	WL_TRACE(("+++: Set Broadcast ISCAN\n"));
3148 
3149 	memset(&ssid, 0, sizeof(ssid));
3150 
3151 	iscan->list_cur = iscan->list_hdr;
3152 	iscan->iscan_state = ISCAN_STATE_SCANING;
3153 
3154 	memset(&iscan->iscan_ex_params_p->params, 0, iscan->iscan_ex_param_size);
3155 	wl_iw_iscan_prep(&iscan->iscan_ex_params_p->params, &ssid);
3156 	wl_iw_iscan(iscan, &ssid, WL_SCAN_ACTION_START);
3157 
3158 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27))
3159 	if (flag)
3160 		rtnl_unlock();
3161 #endif
3162 
3163 	mod_timer(&iscan->timer, jiffies + iscan->timer_ms*HZ/1000);
3164 
3165 	iscan->timer_on = 1;
3166 
3167 	return 0;
3168 }
3169 
3170 static int
3171 wl_iw_iscan_set_scan(
3172 	struct net_device *dev,
3173 	struct iw_request_info *info,
3174 	union iwreq_data *wrqu,
3175 	char *extra
3176 )
3177 {
3178 	wlc_ssid_t ssid;
3179 	iscan_info_t *iscan = g_iscan;
3180 	int ret = 0;
3181 
3182 	WL_TRACE(("%s: SIOCSIWSCAN : ISCAN\n", dev->name));
3183 
3184 #if defined(CSCAN)
3185 	WL_ERROR(("%s: Scan from SIOCGIWSCAN not supported\n", __FUNCTION__));
3186 	return -EINVAL;
3187 #endif
3188 
3189 	net_os_wake_lock(dev);
3190 
3191 #if defined(SOFTAP)
3192 	if (ap_cfg_running) {
3193 		WL_TRACE(("\n>%s: Not executed, reason -'SOFTAP is active'\n", __FUNCTION__));
3194 		goto set_scan_end;
3195 	}
3196 #endif
3197 
3198 	if (g_onoff == G_WLAN_SET_OFF) {
3199 		WL_TRACE(("%s: driver is not up yet after START\n", __FUNCTION__));
3200 		goto set_scan_end;
3201 	}
3202 
3203 #ifdef PNO_SUPPORT
3204 	if  (dhd_dev_get_pno_status(dev)) {
3205 		WL_ERROR(("%s: Scan called when PNO is active\n", __FUNCTION__));
3206 	}
3207 #endif
3208 
3209 	if ((!iscan) || (iscan->sysioc_pid < 0)) {
3210 		WL_ERROR(("%s error\n", __FUNCTION__));
3211 		goto set_scan_end;
3212 	}
3213 
3214 	if (g_scan_specified_ssid) {
3215 		WL_TRACE(("%s Specific SCAN already running ignoring BC scan\n", \
3216 				__FUNCTION__));
3217 		ret = EBUSY;
3218 		goto set_scan_end;
3219 	}
3220 
3221 	memset(&ssid, 0, sizeof(ssid));
3222 
3223 #if WIRELESS_EXT > 17
3224 
3225 	if (wrqu->data.length == sizeof(struct iw_scan_req)) {
3226 		if (wrqu->data.flags & IW_SCAN_THIS_ESSID) {
3227 			int as = 0;
3228 			struct iw_scan_req *req = (struct iw_scan_req *)extra;
3229 			ssid.SSID_len = MIN(sizeof(ssid.SSID), req->essid_len);
3230 			memcpy(ssid.SSID, req->essid, ssid.SSID_len);
3231 			ssid.SSID_len = htod32(ssid.SSID_len);
3232 			dev_wlc_ioctl(dev, WLC_SET_PASSIVE_SCAN, &as, sizeof(as));
3233 			wl_iw_set_event_mask(dev);
3234 			ret = wl_iw_set_scan(dev, info, wrqu, extra);
3235 			goto set_scan_end;
3236 		}
3237 		else {
3238 			g_scan_specified_ssid = 0;
3239 
3240 			if (iscan->iscan_state == ISCAN_STATE_SCANING) {
3241 				WL_TRACE(("%s ISCAN already in progress \n", __FUNCTION__));
3242 				goto set_scan_end;
3243 			}
3244 		}
3245 	}
3246 #endif
3247 
3248 #if !defined(CSCAN)
3249 	if (g_first_broadcast_scan < BROADCAST_SCAN_FIRST_RESULT_CONSUMED) {
3250 		if (++g_first_counter_scans == MAX_ALLOWED_BLOCK_SCAN_FROM_FIRST_SCAN) {
3251 
3252 			WL_ERROR(("%s Clean up First scan flag which is %d\n", \
3253 				 __FUNCTION__, g_first_broadcast_scan));
3254 			g_first_broadcast_scan = BROADCAST_SCAN_FIRST_RESULT_CONSUMED;
3255 		}
3256 		else {
3257 			WL_ERROR(("%s Ignoring Broadcast Scan:First Scan is not done yet %d\n", \
3258 					__FUNCTION__, g_first_counter_scans));
3259 			ret = -EBUSY;
3260 			goto set_scan_end;
3261 		}
3262 	}
3263 #endif
3264 
3265 	wl_iw_iscan_set_scan_broadcast_prep(dev, 0);
3266 
3267 set_scan_end:
3268 	net_os_wake_unlock(dev);
3269 	return ret;
3270 }
3271 #endif
3272 
3273 #if WIRELESS_EXT > 17
3274 static bool
3275 ie_is_wpa_ie(uint8 **wpaie, uint8 **tlvs, int *tlvs_len)
3276 {
3277 	uint8 *ie = *wpaie;
3278 
3279 	if ((ie[1] >= 6) &&
3280 		!bcmp((const void *)&ie[2], (const void *)(WPA_OUI "\x01"), 4)) {
3281 		return TRUE;
3282 	}
3283 
3284 	ie += ie[1] + 2;
3285 
3286 	*tlvs_len -= (int)(ie - *tlvs);
3287 
3288 	*tlvs = ie;
3289 	return FALSE;
3290 }
3291 
3292 static bool
3293 ie_is_wps_ie(uint8 **wpsie, uint8 **tlvs, int *tlvs_len)
3294 {
3295 	uint8 *ie = *wpsie;
3296 
3297 	if ((ie[1] >= 4) &&
3298 		!bcmp((const void *)&ie[2], (const void *)(WPA_OUI "\x04"), 4)) {
3299 		return TRUE;
3300 	}
3301 
3302 	ie += ie[1] + 2;
3303 
3304 	*tlvs_len -= (int)(ie - *tlvs);
3305 
3306 	*tlvs = ie;
3307 	return FALSE;
3308 }
3309 #endif
3310 
3311 static inline int _wpa_snprintf_hex(char *buf, size_t buf_size, const u8 *data,
3312 	size_t len, int uppercase)
3313 {
3314 	size_t i;
3315 	char *pos = buf, *end = buf + buf_size;
3316 	int ret;
3317 	if (buf_size == 0)
3318 		return 0;
3319 	for (i = 0; i < len; i++) {
3320 		ret = snprintf(pos, end - pos, uppercase ? "%02X" : "%02x",
3321 			data[i]);
3322 		if (ret < 0 || ret >= end - pos) {
3323 			end[-1] = '\0';
3324 			return pos - buf;
3325 		}
3326 		pos += ret;
3327 	}
3328 	end[-1] = '\0';
3329 	return pos - buf;
3330 }
3331 
3332 
3333 int wpa_snprintf_hex(char *buf, size_t buf_size, const u8 *data, size_t len)
3334 {
3335 	return _wpa_snprintf_hex(buf, buf_size, data, len, 0);
3336 }
3337 
3338 static int
3339 wl_iw_handle_scanresults_ies(char **event_p, char *end,
3340 	struct iw_request_info *info, wl_bss_info_t *bi)
3341 {
3342 #if WIRELESS_EXT > 17
3343 	struct iw_event	iwe;
3344 	char *event;
3345 	char *buf;
3346 	int custom_event_len;
3347 
3348 	event = *event_p;
3349 	if (bi->ie_length) {
3350 
3351 		bcm_tlv_t *ie;
3352 		uint8 *ptr = ((uint8 *)bi) + sizeof(wl_bss_info_t);
3353 		int ptr_len = bi->ie_length;
3354 
3355 #ifdef BCMWPA2
3356 		if ((ie = bcm_parse_tlvs(ptr, ptr_len, DOT11_MNG_RSN_ID))) {
3357 			iwe.cmd = IWEVGENIE;
3358 			iwe.u.data.length = ie->len + 2;
3359 			event = IWE_STREAM_ADD_POINT(info, event, end, &iwe, (char *)ie);
3360 		}
3361 		ptr = ((uint8 *)bi) + sizeof(wl_bss_info_t);
3362 #endif
3363 
3364 		while ((ie = bcm_parse_tlvs(ptr, ptr_len, DOT11_MNG_WPA_ID))) {
3365 
3366 			if (ie_is_wps_ie(((uint8 **)&ie), &ptr, &ptr_len)) {
3367 				iwe.cmd = IWEVGENIE;
3368 				iwe.u.data.length = ie->len + 2;
3369 				event = IWE_STREAM_ADD_POINT(info, event, end, &iwe, (char *)ie);
3370 				break;
3371 			}
3372 		}
3373 
3374 		ptr = ((uint8 *)bi) + sizeof(wl_bss_info_t);
3375 		ptr_len = bi->ie_length;
3376 		while ((ie = bcm_parse_tlvs(ptr, ptr_len, DOT11_MNG_WPA_ID))) {
3377 			if (ie_is_wpa_ie(((uint8 **)&ie), &ptr, &ptr_len)) {
3378 				iwe.cmd = IWEVGENIE;
3379 				iwe.u.data.length = ie->len + 2;
3380 				event = IWE_STREAM_ADD_POINT(info, event, end, &iwe, (char *)ie);
3381 				break;
3382 			}
3383 		}
3384 
3385 		ptr = ((uint8 *)bi) + sizeof(wl_bss_info_t);
3386 		ptr_len = bi->ie_length;
3387 
3388 		while ((ie = bcm_parse_tlvs(ptr, ptr_len, DOT11_MNG_WAPI_ID))) {
3389 			WL_TRACE(("%s: found a WAPI IE...\n", __FUNCTION__));
3390 #ifdef WAPI_IE_USE_GENIE
3391 			iwe.cmd = IWEVGENIE;
3392 			iwe.u.data.length = ie->len + 2;
3393 			event = IWE_STREAM_ADD_POINT(info, event, end, &iwe, (char *)ie);
3394 #else
3395 			iwe.cmd = IWEVCUSTOM;
3396 			custom_event_len = strlen("wapi_ie=") + 2*(ie->len + 2);
3397 			iwe.u.data.length = custom_event_len;
3398 
3399 			buf = kmalloc(custom_event_len+1, GFP_KERNEL);
3400 			if (buf == NULL)
3401 			{
3402 				WL_ERROR(("malloc(%d) returned NULL...\n", custom_event_len));
3403 				break;
3404 			}
3405 
3406 			memcpy(buf, "wapi_ie=", 8);
3407 			wpa_snprintf_hex(buf + 8, 2+1, &(ie->id), 1);
3408 			wpa_snprintf_hex(buf + 10, 2+1, &(ie->len), 1);
3409 			wpa_snprintf_hex(buf + 12, 2*ie->len+1, ie->data, ie->len);
3410 			event = IWE_STREAM_ADD_POINT(info, event, end, &iwe, buf);
3411 #endif
3412 			break;
3413 		}
3414 	*event_p = event;
3415 	}
3416 #endif
3417 
3418 	return 0;
3419 }
3420 
3421 #ifndef CSCAN
3422 static uint
3423 wl_iw_get_scan_prep(
3424 	wl_scan_results_t *list,
3425 	struct iw_request_info *info,
3426 	char *extra,
3427 	short max_size)
3428 {
3429 	int  i, j;
3430 	struct iw_event  iwe;
3431 	wl_bss_info_t *bi = NULL;
3432 	char *event = extra, *end = extra + max_size - WE_ADD_EVENT_FIX, *value;
3433 	int	ret = 0;
3434 
3435 	ASSERT(list);
3436 
3437 	for (i = 0; i < list->count && i < IW_MAX_AP; i++)
3438 	{
3439 		if (list->version != WL_BSS_INFO_VERSION) {
3440 			WL_ERROR(("%s : list->version %d != WL_BSS_INFO_VERSION\n", \
3441 				__FUNCTION__, list->version));
3442 			return ret;
3443 		 }
3444 
3445 		bi = bi ? (wl_bss_info_t *)((uintptr)bi + dtoh32(bi->length)) : list->bss_info;
3446 
3447 		WL_TRACE(("%s : %s\n", __FUNCTION__, bi->SSID));
3448 
3449 		iwe.cmd = SIOCGIWAP;
3450 		iwe.u.ap_addr.sa_family = ARPHRD_ETHER;
3451 		memcpy(iwe.u.ap_addr.sa_data, &bi->BSSID, ETHER_ADDR_LEN);
3452 		event = IWE_STREAM_ADD_EVENT(info, event, end, &iwe, IW_EV_ADDR_LEN);
3453 
3454 		iwe.u.data.length = dtoh32(bi->SSID_len);
3455 		iwe.cmd = SIOCGIWESSID;
3456 		iwe.u.data.flags = 1;
3457 		event = IWE_STREAM_ADD_POINT(info, event, end, &iwe, bi->SSID);
3458 
3459 
3460 		if (dtoh16(bi->capability) & (DOT11_CAP_ESS | DOT11_CAP_IBSS)) {
3461 			iwe.cmd = SIOCGIWMODE;
3462 			if (dtoh16(bi->capability) & DOT11_CAP_ESS)
3463 				iwe.u.mode = IW_MODE_INFRA;
3464 			else
3465 				iwe.u.mode = IW_MODE_ADHOC;
3466 			event = IWE_STREAM_ADD_EVENT(info, event, end, &iwe, IW_EV_UINT_LEN);
3467 		}
3468 
3469 
3470 		iwe.cmd = SIOCGIWFREQ;
3471 		iwe.u.freq.m = wf_channel2mhz(CHSPEC_CHANNEL(bi->chanspec),
3472 			CHSPEC_CHANNEL(bi->chanspec) <= CH_MAX_2G_CHANNEL ?
3473 			WF_CHAN_FACTOR_2_4_G : WF_CHAN_FACTOR_5_G);
3474 		iwe.u.freq.e = 6;
3475 		event = IWE_STREAM_ADD_EVENT(info, event, end, &iwe, IW_EV_FREQ_LEN);
3476 
3477 
3478 		iwe.cmd = IWEVQUAL;
3479 		iwe.u.qual.qual = rssi_to_qual(dtoh16(bi->RSSI));
3480 		iwe.u.qual.level = 0x100 + dtoh16(bi->RSSI);
3481 		iwe.u.qual.noise = 0x100 + bi->phy_noise;
3482 		event = IWE_STREAM_ADD_EVENT(info, event, end, &iwe, IW_EV_QUAL_LEN);
3483 
3484 		wl_iw_handle_scanresults_ies(&event, end, info, bi);
3485 
3486 		iwe.cmd = SIOCGIWENCODE;
3487 		if (dtoh16(bi->capability) & DOT11_CAP_PRIVACY)
3488 			iwe.u.data.flags = IW_ENCODE_ENABLED | IW_ENCODE_NOKEY;
3489 		else
3490 			iwe.u.data.flags = IW_ENCODE_DISABLED;
3491 		iwe.u.data.length = 0;
3492 		event = IWE_STREAM_ADD_POINT(info, event, end, &iwe, (char *)event);
3493 
3494 
3495 		if (bi->rateset.count) {
3496 			if (((event -extra) + IW_EV_LCP_LEN) <= (uintptr)end) {
3497 				value = event + IW_EV_LCP_LEN;
3498 				iwe.cmd = SIOCGIWRATE;
3499 
3500 				iwe.u.bitrate.fixed = iwe.u.bitrate.disabled = 0;
3501 				for (j = 0; j < bi->rateset.count && j < IW_MAX_BITRATES; j++) {
3502 					iwe.u.bitrate.value = (bi->rateset.rates[j] & 0x7f) * 500000;
3503 					value = IWE_STREAM_ADD_VALUE(info, event, value, end, &iwe,
3504 						IW_EV_PARAM_LEN);
3505 				}
3506 				event = value;
3507 			}
3508 		}
3509 	}
3510 
3511 	if ((ret = (event - extra)) < 0) {
3512 		WL_ERROR(("==> Wrong size\n"));
3513 		ret = 0;
3514 	}
3515 	WL_TRACE(("%s: size=%d bytes prepared \n", __FUNCTION__, (unsigned int)(event - extra)));
3516 	return (uint)ret;
3517 }
3518 
3519 static int
3520 wl_iw_get_scan(
3521 	struct net_device *dev,
3522 	struct iw_request_info *info,
3523 	struct iw_point *dwrq,
3524 	char *extra
3525 )
3526 {
3527 	channel_info_t ci;
3528 	wl_scan_results_t *list_merge;
3529 	wl_scan_results_t *list = (wl_scan_results_t *) g_scan;
3530 	int error;
3531 	uint buflen_from_user = dwrq->length;
3532 	uint len =  G_SCAN_RESULTS;
3533 	__u16 len_ret = 0;
3534 #if !defined(CSCAN)
3535 	__u16 merged_len = 0;
3536 #endif
3537 #if defined(WL_IW_USE_ISCAN)
3538 	iscan_info_t *iscan = g_iscan;
3539 	iscan_buf_t * p_buf;
3540 #if  !defined(CSCAN)
3541 	uint32 counter = 0;
3542 #endif
3543 #endif
3544 	WL_TRACE(("%s: buflen_from_user %d: \n", dev->name, buflen_from_user));
3545 
3546 	if (!extra) {
3547 		WL_TRACE(("%s: wl_iw_get_scan return -EINVAL\n", dev->name));
3548 		return -EINVAL;
3549 	}
3550 
3551 
3552 	if ((error = dev_wlc_ioctl(dev, WLC_GET_CHANNEL, &ci, sizeof(ci))))
3553 		return error;
3554 	ci.scan_channel = dtoh32(ci.scan_channel);
3555 	if (ci.scan_channel)
3556 		return -EAGAIN;
3557 
3558 #if !defined(CSCAN)
3559 	if (g_ss_cache_ctrl.m_timer_expired) {
3560 		wl_iw_free_ss_cache();
3561 		g_ss_cache_ctrl.m_timer_expired ^= 1;
3562 	}
3563 	if ((!g_scan_specified_ssid && g_ss_cache_ctrl.m_prev_scan_mode) ||
3564 		g_ss_cache_ctrl.m_cons_br_scan_cnt > 4) {
3565 		g_ss_cache_ctrl.m_cons_br_scan_cnt = 0;
3566 
3567 		wl_iw_reset_ss_cache();
3568 	}
3569 	g_ss_cache_ctrl.m_prev_scan_mode = g_scan_specified_ssid;
3570 	if (g_scan_specified_ssid) {
3571 		g_ss_cache_ctrl.m_cons_br_scan_cnt = 0;
3572 	}
3573 	else {
3574 		g_ss_cache_ctrl.m_cons_br_scan_cnt++;
3575 	}
3576 #endif
3577 
3578 	if (g_scan_specified_ssid) {
3579 
3580 		list = kmalloc(len, GFP_KERNEL);
3581 		if (!list) {
3582 			WL_TRACE(("%s: wl_iw_get_scan return -ENOMEM\n", dev->name));
3583 			g_scan_specified_ssid = 0;
3584 			return -ENOMEM;
3585 		}
3586 	}
3587 
3588 	memset(list, 0, len);
3589 	list->buflen = htod32(len);
3590 	if ((error = dev_wlc_ioctl(dev, WLC_SCAN_RESULTS, list, len))) {
3591 		WL_ERROR(("%s: %s : Scan_results ERROR %d\n", dev->name, __FUNCTION__, error));
3592 		dwrq->length = len;
3593 		if (g_scan_specified_ssid) {
3594 			g_scan_specified_ssid = 0;
3595 			kfree(list);
3596 		}
3597 		return 0;
3598 	}
3599 	list->buflen = dtoh32(list->buflen);
3600 	list->version = dtoh32(list->version);
3601 	list->count = dtoh32(list->count);
3602 
3603 	if (list->version != WL_BSS_INFO_VERSION) {
3604 		WL_ERROR(("%s : list->version %d != WL_BSS_INFO_VERSION\n",
3605 				__FUNCTION__, list->version));
3606 		if (g_scan_specified_ssid) {
3607 			g_scan_specified_ssid = 0;
3608 			kfree(list);
3609 		}
3610 		return -EINVAL;
3611 	}
3612 
3613 #if !defined(CSCAN)
3614 	if (g_scan_specified_ssid) {
3615 
3616 		wl_iw_add_bss_to_ss_cache(list);
3617 		kfree(list);
3618 	}
3619 
3620 	mutex_lock(&wl_cache_lock);
3621 #if defined(WL_IW_USE_ISCAN)
3622 	if (g_scan_specified_ssid)
3623 		WL_TRACE(("%s: Specified scan APs from scan=%d\n", __FUNCTION__, list->count));
3624 	p_buf = iscan->list_hdr;
3625 
3626 	while (p_buf != iscan->list_cur) {
3627 		list_merge = &((wl_iscan_results_t*)p_buf->iscan_buf)->results;
3628 		WL_TRACE(("%s: Bcast APs list=%d\n", __FUNCTION__, list_merge->count));
3629 		counter += list_merge->count;
3630 		if (list_merge->count > 0)
3631 			len_ret += (__u16) wl_iw_get_scan_prep(list_merge, info,
3632 				extra+len_ret, buflen_from_user -len_ret);
3633 		p_buf = p_buf->next;
3634 	}
3635 	WL_TRACE(("%s merged with total Bcast APs=%d\n", __FUNCTION__, counter));
3636 #else
3637 	list_merge = (wl_scan_results_t *) g_scan;
3638 	len_ret = (__u16) wl_iw_get_scan_prep(list_merge, info, extra, buflen_from_user);
3639 #endif
3640 	mutex_unlock(&wl_cache_lock);
3641 	if (g_ss_cache_ctrl.m_link_down) {
3642 		wl_iw_delete_bss_from_ss_cache(g_ss_cache_ctrl.m_active_bssid);
3643 	}
3644 
3645 	wl_iw_merge_scan_cache(info, extra+len_ret, buflen_from_user-len_ret, &merged_len);
3646 	len_ret += merged_len;
3647 	wl_iw_run_ss_cache_timer(0);
3648 	wl_iw_run_ss_cache_timer(1);
3649 #else
3650 
3651 	if (g_scan_specified_ssid) {
3652 		WL_TRACE(("%s: Specified scan APs in the list =%d\n", __FUNCTION__, list->count));
3653 		len_ret = (__u16) wl_iw_get_scan_prep(list, info, extra, buflen_from_user);
3654 		kfree(list);
3655 
3656 #if defined(WL_IW_USE_ISCAN)
3657 		p_buf = iscan->list_hdr;
3658 
3659 		while (p_buf != iscan->list_cur) {
3660 			list_merge = &((wl_iscan_results_t*)p_buf->iscan_buf)->results;
3661 			WL_TRACE(("%s: Bcast APs list=%d\n", __FUNCTION__, list_merge->count));
3662 			if (list_merge->count > 0)
3663 				len_ret += (__u16) wl_iw_get_scan_prep(list_merge, info,
3664 				    extra+len_ret, buflen_from_user -len_ret);
3665 			p_buf = p_buf->next;
3666 		}
3667 #else
3668 		list_merge = (wl_scan_results_t *) g_scan;
3669 		WL_TRACE(("%s: Bcast APs list=%d\n", __FUNCTION__, list_merge->count));
3670 		if (list_merge->count > 0)
3671 			len_ret += (__u16) wl_iw_get_scan_prep(list_merge, info, extra+len_ret,
3672 				buflen_from_user -len_ret);
3673 #endif
3674 	}
3675 	else {
3676 		list = (wl_scan_results_t *) g_scan;
3677 		len_ret = (__u16) wl_iw_get_scan_prep(list, info, extra, buflen_from_user);
3678 	}
3679 #endif
3680 
3681 #if defined(WL_IW_USE_ISCAN)
3682 
3683 	g_scan_specified_ssid = 0;
3684 #endif
3685 
3686 	if ((len_ret + WE_ADD_EVENT_FIX) < buflen_from_user)
3687 		len = len_ret;
3688 
3689 	dwrq->length = len;
3690 	dwrq->flags = 0;
3691 
3692 	WL_TRACE(("%s return to WE %d bytes APs=%d\n", __FUNCTION__, dwrq->length, list->count));
3693 	return 0;
3694 }
3695 #endif
3696 
3697 #if defined(WL_IW_USE_ISCAN)
3698 static int
3699 wl_iw_iscan_get_scan(
3700 	struct net_device *dev,
3701 	struct iw_request_info *info,
3702 	struct iw_point *dwrq,
3703 	char *extra
3704 )
3705 {
3706 	wl_scan_results_t *list;
3707 	struct iw_event	iwe;
3708 	wl_bss_info_t *bi = NULL;
3709 	int ii, j;
3710 	int apcnt;
3711 	char *event = extra, *end = extra + dwrq->length, *value;
3712 	iscan_info_t *iscan = g_iscan;
3713 	iscan_buf_t * p_buf;
3714 	uint32  counter = 0;
3715 	uint8   channel;
3716 #if !defined(CSCAN)
3717 	__u16 merged_len = 0;
3718 	uint buflen_from_user = dwrq->length;
3719 #endif
3720 
3721 	WL_TRACE(("%s %s buflen_from_user %d:\n", dev->name, __FUNCTION__, dwrq->length));
3722 
3723 #if defined(SOFTAP)
3724 	if (ap_cfg_running) {
3725 		WL_TRACE(("%s: Not executed, reason -'SOFTAP is active'\n", __FUNCTION__));
3726 		return -EINVAL;
3727 	}
3728 #endif
3729 
3730 	if (!extra) {
3731 		WL_TRACE(("%s: INVALID SIOCGIWSCAN GET bad parameter\n", dev->name));
3732 		return -EINVAL;
3733 	}
3734 
3735 	if (g_first_broadcast_scan < BROADCAST_SCAN_FIRST_RESULT_READY) {
3736 		WL_TRACE(("%s %s: first ISCAN results are NOT ready yet \n", \
3737 			 dev->name, __FUNCTION__));
3738 		return -EAGAIN;
3739 	}
3740 
3741 	if ((!iscan) || (iscan->sysioc_pid < 0)) {
3742 		WL_ERROR(("%ssysioc_pid\n", __FUNCTION__));
3743 		return -EAGAIN;
3744 	}
3745 
3746 #if !defined(CSCAN)
3747 	if (g_ss_cache_ctrl.m_timer_expired) {
3748 		wl_iw_free_ss_cache();
3749 		g_ss_cache_ctrl.m_timer_expired ^= 1;
3750 	}
3751 	if (g_scan_specified_ssid) {
3752 		return wl_iw_get_scan(dev, info, dwrq, extra);
3753 	}
3754 	else {
3755 		if (g_ss_cache_ctrl.m_link_down) {
3756 			wl_iw_delete_bss_from_ss_cache(g_ss_cache_ctrl.m_active_bssid);
3757 		}
3758 		if (g_ss_cache_ctrl.m_prev_scan_mode || g_ss_cache_ctrl.m_cons_br_scan_cnt > 4) {
3759 			g_ss_cache_ctrl.m_cons_br_scan_cnt = 0;
3760 
3761 			wl_iw_reset_ss_cache();
3762 		}
3763 		g_ss_cache_ctrl.m_prev_scan_mode = g_scan_specified_ssid;
3764 		g_ss_cache_ctrl.m_cons_br_scan_cnt++;
3765 	}
3766 #endif
3767 
3768 	WL_TRACE(("%s: SIOCGIWSCAN GET broadcast results\n", dev->name));
3769 	apcnt = 0;
3770 	p_buf = iscan->list_hdr;
3771 
3772 	while (p_buf != iscan->list_cur) {
3773 	    list = &((wl_iscan_results_t*)p_buf->iscan_buf)->results;
3774 
3775 	    counter += list->count;
3776 
3777 	    if (list->version != WL_BSS_INFO_VERSION) {
3778 		WL_ERROR(("%s : list->version %d != WL_BSS_INFO_VERSION\n",
3779 			 __FUNCTION__, list->version));
3780 		return -EINVAL;
3781 	    }
3782 
3783 	    bi = NULL;
3784 	    for (ii = 0; ii < list->count && apcnt < IW_MAX_AP; apcnt++, ii++) {
3785 		bi = bi ? (wl_bss_info_t *)((uintptr)bi + dtoh32(bi->length)) : list->bss_info;
3786 		ASSERT(((uintptr)bi + dtoh32(bi->length)) <= ((uintptr)list +
3787 			WLC_IW_ISCAN_MAXLEN));
3788 
3789 
3790 		if (event + ETHER_ADDR_LEN + bi->SSID_len + IW_EV_UINT_LEN + IW_EV_FREQ_LEN +
3791 			IW_EV_QUAL_LEN >= end)
3792 			return -E2BIG;
3793 
3794 		iwe.cmd = SIOCGIWAP;
3795 		iwe.u.ap_addr.sa_family = ARPHRD_ETHER;
3796 		memcpy(iwe.u.ap_addr.sa_data, &bi->BSSID, ETHER_ADDR_LEN);
3797 		event = IWE_STREAM_ADD_EVENT(info, event, end, &iwe, IW_EV_ADDR_LEN);
3798 
3799 
3800 		iwe.u.data.length = dtoh32(bi->SSID_len);
3801 		iwe.cmd = SIOCGIWESSID;
3802 		iwe.u.data.flags = 1;
3803 		event = IWE_STREAM_ADD_POINT(info, event, end, &iwe, bi->SSID);
3804 
3805 
3806 		if (dtoh16(bi->capability) & (DOT11_CAP_ESS | DOT11_CAP_IBSS)) {
3807 			iwe.cmd = SIOCGIWMODE;
3808 			if (dtoh16(bi->capability) & DOT11_CAP_ESS)
3809 				iwe.u.mode = IW_MODE_INFRA;
3810 			else
3811 				iwe.u.mode = IW_MODE_ADHOC;
3812 			event = IWE_STREAM_ADD_EVENT(info, event, end, &iwe, IW_EV_UINT_LEN);
3813 		}
3814 
3815 
3816 		iwe.cmd = SIOCGIWFREQ;
3817 		channel = (bi->ctl_ch == 0) ? CHSPEC_CHANNEL(bi->chanspec) : bi->ctl_ch;
3818 		iwe.u.freq.m = wf_channel2mhz(channel,
3819 			channel <= CH_MAX_2G_CHANNEL ?
3820 			WF_CHAN_FACTOR_2_4_G : WF_CHAN_FACTOR_5_G);
3821 		iwe.u.freq.e = 6;
3822 		event = IWE_STREAM_ADD_EVENT(info, event, end, &iwe, IW_EV_FREQ_LEN);
3823 
3824 
3825 		iwe.cmd = IWEVQUAL;
3826 		iwe.u.qual.qual = rssi_to_qual(dtoh16(bi->RSSI));
3827 		iwe.u.qual.level = 0x100 + dtoh16(bi->RSSI);
3828 		iwe.u.qual.noise = 0x100 + bi->phy_noise;
3829 		event = IWE_STREAM_ADD_EVENT(info, event, end, &iwe, IW_EV_QUAL_LEN);
3830 
3831 
3832 		wl_iw_handle_scanresults_ies(&event, end, info, bi);
3833 
3834 
3835 		iwe.cmd = SIOCGIWENCODE;
3836 		if (dtoh16(bi->capability) & DOT11_CAP_PRIVACY)
3837 			iwe.u.data.flags = IW_ENCODE_ENABLED | IW_ENCODE_NOKEY;
3838 		else
3839 			iwe.u.data.flags = IW_ENCODE_DISABLED;
3840 		iwe.u.data.length = 0;
3841 		event = IWE_STREAM_ADD_POINT(info, event, end, &iwe, (char *)event);
3842 
3843 
3844 		if (bi->rateset.count) {
3845 			if (event + IW_MAX_BITRATES*IW_EV_PARAM_LEN >= end)
3846 				return -E2BIG;
3847 
3848 			value = event + IW_EV_LCP_LEN;
3849 			iwe.cmd = SIOCGIWRATE;
3850 
3851 			iwe.u.bitrate.fixed = iwe.u.bitrate.disabled = 0;
3852 			for (j = 0; j < bi->rateset.count && j < IW_MAX_BITRATES; j++) {
3853 				iwe.u.bitrate.value = (bi->rateset.rates[j] & 0x7f) * 500000;
3854 				value = IWE_STREAM_ADD_VALUE(info, event, value, end, &iwe,
3855 					IW_EV_PARAM_LEN);
3856 			}
3857 			event = value;
3858 		}
3859 	    }
3860 	    p_buf = p_buf->next;
3861 	}
3862 
3863 	dwrq->length = event - extra;
3864 	dwrq->flags = 0;
3865 
3866 #if !defined(CSCAN)
3867 	wl_iw_merge_scan_cache(info, event, buflen_from_user - dwrq->length, &merged_len);
3868 	dwrq->length += merged_len;
3869 	wl_iw_run_ss_cache_timer(0);
3870 	wl_iw_run_ss_cache_timer(1);
3871 #endif /* CSCAN */
3872 	g_first_broadcast_scan = BROADCAST_SCAN_FIRST_RESULT_CONSUMED;
3873 
3874 	WL_TRACE(("%s return to WE %d bytes APs=%d\n", __FUNCTION__, dwrq->length, counter));
3875 
3876 	return 0;
3877 }
3878 #endif
3879 
3880 static int
3881 wl_iw_set_essid(
3882 	struct net_device *dev,
3883 	struct iw_request_info *info,
3884 	struct iw_point *dwrq,
3885 	char *extra
3886 )
3887 {
3888 	int error;
3889 	wl_join_params_t join_params;
3890 	int join_params_size;
3891 
3892 	WL_TRACE(("%s: SIOCSIWESSID\n", dev->name));
3893 
3894 
3895 	memset(&g_ssid, 0, sizeof(g_ssid));
3896 
3897 	CHECK_EXTRA_FOR_NULL(extra);
3898 
3899 	if (dwrq->length && extra) {
3900 #if WIRELESS_EXT > 20
3901 		g_ssid.SSID_len = MIN(sizeof(g_ssid.SSID), dwrq->length);
3902 #else
3903 		g_ssid.SSID_len = MIN(sizeof(g_ssid.SSID), dwrq->length-1);
3904 #endif
3905 		memcpy(g_ssid.SSID, extra, g_ssid.SSID_len);
3906 	} else {
3907 
3908 		g_ssid.SSID_len = 0;
3909 	}
3910 	g_ssid.SSID_len = htod32(g_ssid.SSID_len);
3911 
3912 	memset(&join_params, 0, sizeof(join_params));
3913 	join_params_size = sizeof(join_params.ssid);
3914 
3915 	memcpy(&join_params.ssid.SSID, g_ssid.SSID, g_ssid.SSID_len);
3916 	join_params.ssid.SSID_len = htod32(g_ssid.SSID_len);
3917 	memcpy(&join_params.params.bssid, &ether_bcast, ETHER_ADDR_LEN);
3918 
3919 	wl_iw_ch_to_chanspec(g_wl_iw_params.target_channel, &join_params, &join_params_size);
3920 
3921 	if ((error = dev_wlc_ioctl(dev, WLC_SET_SSID, &join_params, join_params_size))) {
3922 		WL_ERROR(("Invalid ioctl data=%d\n", error));
3923 		return error;
3924 	}
3925 
3926 	if (g_ssid.SSID_len) {
3927 		WL_TRACE(("%s: join SSID=%s ch=%d\n", __FUNCTION__, \
3928 			g_ssid.SSID,  g_wl_iw_params.target_channel));
3929 	}
3930 	return 0;
3931 }
3932 
3933 static int
3934 wl_iw_get_essid(
3935 	struct net_device *dev,
3936 	struct iw_request_info *info,
3937 	struct iw_point *dwrq,
3938 	char *extra
3939 )
3940 {
3941 	wlc_ssid_t ssid;
3942 	int error;
3943 
3944 	WL_TRACE(("%s: SIOCGIWESSID\n", dev->name));
3945 
3946 	if (!extra)
3947 		return -EINVAL;
3948 
3949 	if ((error = dev_wlc_ioctl(dev, WLC_GET_SSID, &ssid, sizeof(ssid)))) {
3950 		WL_ERROR(("Error getting the SSID\n"));
3951 		return error;
3952 	}
3953 
3954 	ssid.SSID_len = dtoh32(ssid.SSID_len);
3955 
3956 	memcpy(extra, ssid.SSID, ssid.SSID_len);
3957 
3958 	dwrq->length = ssid.SSID_len;
3959 
3960 	dwrq->flags = 1;
3961 
3962 	return 0;
3963 }
3964 
3965 static int
3966 wl_iw_set_nick(
3967 	struct net_device *dev,
3968 	struct iw_request_info *info,
3969 	struct iw_point *dwrq,
3970 	char *extra
3971 )
3972 {
3973 	wl_iw_t *iw = *(wl_iw_t **)netdev_priv(dev);
3974 
3975 	WL_TRACE(("%s: SIOCSIWNICKN\n", dev->name));
3976 
3977 	if (!extra)
3978 		return -EINVAL;
3979 
3980 	if (dwrq->length > sizeof(iw->nickname))
3981 		return -E2BIG;
3982 
3983 	memcpy(iw->nickname, extra, dwrq->length);
3984 	iw->nickname[dwrq->length - 1] = '\0';
3985 
3986 	return 0;
3987 }
3988 
3989 static int
3990 wl_iw_get_nick(
3991 	struct net_device *dev,
3992 	struct iw_request_info *info,
3993 	struct iw_point *dwrq,
3994 	char *extra
3995 )
3996 {
3997 	wl_iw_t *iw = *(wl_iw_t **)netdev_priv(dev);
3998 
3999 	WL_TRACE(("%s: SIOCGIWNICKN\n", dev->name));
4000 
4001 	if (!extra)
4002 		return -EINVAL;
4003 
4004 	strcpy(extra, iw->nickname);
4005 	dwrq->length = strlen(extra) + 1;
4006 
4007 	return 0;
4008 }
4009 
4010 static int wl_iw_set_rate(
4011 	struct net_device *dev,
4012 	struct iw_request_info *info,
4013 	struct iw_param *vwrq,
4014 	char *extra
4015 )
4016 {
4017 	wl_rateset_t rateset;
4018 	int error, rate, i, error_bg, error_a;
4019 
4020 	WL_TRACE(("%s: SIOCSIWRATE\n", dev->name));
4021 
4022 
4023 	if ((error = dev_wlc_ioctl(dev, WLC_GET_CURR_RATESET, &rateset, sizeof(rateset))))
4024 		return error;
4025 
4026 	rateset.count = dtoh32(rateset.count);
4027 
4028 	if (vwrq->value < 0) {
4029 
4030 		rate = rateset.rates[rateset.count - 1] & 0x7f;
4031 	} else if (vwrq->value < rateset.count) {
4032 
4033 		rate = rateset.rates[vwrq->value] & 0x7f;
4034 	} else {
4035 
4036 		rate = vwrq->value / 500000;
4037 	}
4038 
4039 	if (vwrq->fixed) {
4040 
4041 		error_bg = dev_wlc_intvar_set(dev, "bg_rate", rate);
4042 		error_a = dev_wlc_intvar_set(dev, "a_rate", rate);
4043 
4044 		if (error_bg && error_a)
4045 			return (error_bg | error_a);
4046 	} else {
4047 
4048 
4049 		error_bg = dev_wlc_intvar_set(dev, "bg_rate", 0);
4050 
4051 		error_a = dev_wlc_intvar_set(dev, "a_rate", 0);
4052 
4053 		if (error_bg && error_a)
4054 			return (error_bg | error_a);
4055 
4056 
4057 		for (i = 0; i < rateset.count; i++)
4058 			if ((rateset.rates[i] & 0x7f) > rate)
4059 				break;
4060 		rateset.count = htod32(i);
4061 
4062 
4063 		if ((error = dev_wlc_ioctl(dev, WLC_SET_RATESET, &rateset, sizeof(rateset))))
4064 			return error;
4065 	}
4066 
4067 	return 0;
4068 }
4069 
4070 static int wl_iw_get_rate(
4071 	struct net_device *dev,
4072 	struct iw_request_info *info,
4073 	struct iw_param *vwrq,
4074 	char *extra
4075 )
4076 {
4077 	int error, rate;
4078 
4079 	WL_TRACE(("%s: SIOCGIWRATE\n", dev->name));
4080 
4081 
4082 	if ((error = dev_wlc_ioctl(dev, WLC_GET_RATE, &rate, sizeof(rate))))
4083 		return error;
4084 	rate = dtoh32(rate);
4085 	vwrq->value = rate * 500000;
4086 
4087 	return 0;
4088 }
4089 
4090 static int
4091 wl_iw_set_rts(
4092 	struct net_device *dev,
4093 	struct iw_request_info *info,
4094 	struct iw_param *vwrq,
4095 	char *extra
4096 )
4097 {
4098 	int error, rts;
4099 
4100 	WL_TRACE(("%s: SIOCSIWRTS\n", dev->name));
4101 
4102 	if (vwrq->disabled)
4103 		rts = DOT11_DEFAULT_RTS_LEN;
4104 	else if (vwrq->value < 0 || vwrq->value > DOT11_DEFAULT_RTS_LEN)
4105 		return -EINVAL;
4106 	else
4107 		rts = vwrq->value;
4108 
4109 	if ((error = dev_wlc_intvar_set(dev, "rtsthresh", rts)))
4110 		return error;
4111 
4112 	return 0;
4113 }
4114 
4115 static int
4116 wl_iw_get_rts(
4117 	struct net_device *dev,
4118 	struct iw_request_info *info,
4119 	struct iw_param *vwrq,
4120 	char *extra
4121 )
4122 {
4123 	int error, rts;
4124 
4125 	WL_TRACE(("%s: SIOCGIWRTS\n", dev->name));
4126 
4127 	if ((error = dev_wlc_intvar_get(dev, "rtsthresh", &rts)))
4128 		return error;
4129 
4130 	vwrq->value = rts;
4131 	vwrq->disabled = (rts >= DOT11_DEFAULT_RTS_LEN);
4132 	vwrq->fixed = 1;
4133 
4134 	return 0;
4135 }
4136 
4137 static int
4138 wl_iw_set_frag(
4139 	struct net_device *dev,
4140 	struct iw_request_info *info,
4141 	struct iw_param *vwrq,
4142 	char *extra
4143 )
4144 {
4145 	int error, frag;
4146 
4147 	WL_TRACE(("%s: SIOCSIWFRAG\n", dev->name));
4148 
4149 	if (vwrq->disabled)
4150 		frag = DOT11_DEFAULT_FRAG_LEN;
4151 	else if (vwrq->value < 0 || vwrq->value > DOT11_DEFAULT_FRAG_LEN)
4152 		return -EINVAL;
4153 	else
4154 		frag = vwrq->value;
4155 
4156 	if ((error = dev_wlc_intvar_set(dev, "fragthresh", frag)))
4157 		return error;
4158 
4159 	return 0;
4160 }
4161 
4162 static int
4163 wl_iw_get_frag(
4164 	struct net_device *dev,
4165 	struct iw_request_info *info,
4166 	struct iw_param *vwrq,
4167 	char *extra
4168 )
4169 {
4170 	int error, fragthreshold;
4171 
4172 	WL_TRACE(("%s: SIOCGIWFRAG\n", dev->name));
4173 
4174 	if ((error = dev_wlc_intvar_get(dev, "fragthresh", &fragthreshold)))
4175 		return error;
4176 
4177 	vwrq->value = fragthreshold;
4178 	vwrq->disabled = (fragthreshold >= DOT11_DEFAULT_FRAG_LEN);
4179 	vwrq->fixed = 1;
4180 
4181 	return 0;
4182 }
4183 
4184 static int
4185 wl_iw_set_txpow(
4186 	struct net_device *dev,
4187 	struct iw_request_info *info,
4188 	struct iw_param *vwrq,
4189 	char *extra
4190 )
4191 {
4192 	int error, disable;
4193 	uint16 txpwrmw;
4194 	WL_TRACE(("%s: SIOCSIWTXPOW\n", dev->name));
4195 
4196 
4197 	disable = vwrq->disabled ? WL_RADIO_SW_DISABLE : 0;
4198 	disable += WL_RADIO_SW_DISABLE << 16;
4199 
4200 	disable = htod32(disable);
4201 	if ((error = dev_wlc_ioctl(dev, WLC_SET_RADIO, &disable, sizeof(disable))))
4202 		return error;
4203 
4204 
4205 	if (disable & WL_RADIO_SW_DISABLE)
4206 		return 0;
4207 
4208 
4209 	if (!(vwrq->flags & IW_TXPOW_MWATT))
4210 		return -EINVAL;
4211 
4212 
4213 	if (vwrq->value < 0)
4214 		return 0;
4215 
4216 	if (vwrq->value > 0xffff) txpwrmw = 0xffff;
4217 	else txpwrmw = (uint16)vwrq->value;
4218 
4219 
4220 	error = dev_wlc_intvar_set(dev, "qtxpower", (int)(bcm_mw_to_qdbm(txpwrmw)));
4221 	return error;
4222 }
4223 
4224 static int
4225 wl_iw_get_txpow(
4226 	struct net_device *dev,
4227 	struct iw_request_info *info,
4228 	struct iw_param *vwrq,
4229 	char *extra
4230 )
4231 {
4232 	int error, disable, txpwrdbm;
4233 	uint8 result;
4234 
4235 	WL_TRACE(("%s: SIOCGIWTXPOW\n", dev->name));
4236 
4237 	if ((error = dev_wlc_ioctl(dev, WLC_GET_RADIO, &disable, sizeof(disable))) ||
4238 	    (error = dev_wlc_intvar_get(dev, "qtxpower", &txpwrdbm)))
4239 		return error;
4240 
4241 	disable = dtoh32(disable);
4242 	result = (uint8)(txpwrdbm & ~WL_TXPWR_OVERRIDE);
4243 	vwrq->value = (int32)bcm_qdbm_to_mw(result);
4244 	vwrq->fixed = 0;
4245 	vwrq->disabled = (disable & (WL_RADIO_SW_DISABLE | WL_RADIO_HW_DISABLE)) ? 1 : 0;
4246 	vwrq->flags = IW_TXPOW_MWATT;
4247 
4248 	return 0;
4249 }
4250 
4251 #if WIRELESS_EXT > 10
4252 static int
4253 wl_iw_set_retry(
4254 	struct net_device *dev,
4255 	struct iw_request_info *info,
4256 	struct iw_param *vwrq,
4257 	char *extra
4258 )
4259 {
4260 	int error, lrl, srl;
4261 
4262 	WL_TRACE(("%s: SIOCSIWRETRY\n", dev->name));
4263 
4264 
4265 	if (vwrq->disabled || (vwrq->flags & IW_RETRY_LIFETIME))
4266 		return -EINVAL;
4267 
4268 
4269 	if (vwrq->flags & IW_RETRY_LIMIT) {
4270 
4271 
4272 #if WIRELESS_EXT > 20
4273 	if ((vwrq->flags & IW_RETRY_LONG) ||(vwrq->flags & IW_RETRY_MAX) ||
4274 		!((vwrq->flags & IW_RETRY_SHORT) || (vwrq->flags & IW_RETRY_MIN))) {
4275 #else
4276 	if ((vwrq->flags & IW_RETRY_MAX) || !(vwrq->flags & IW_RETRY_MIN)) {
4277 #endif
4278 			lrl = htod32(vwrq->value);
4279 			if ((error = dev_wlc_ioctl(dev, WLC_SET_LRL, &lrl, sizeof(lrl))))
4280 				return error;
4281 		}
4282 
4283 
4284 #if WIRELESS_EXT > 20
4285 	if ((vwrq->flags & IW_RETRY_SHORT) ||(vwrq->flags & IW_RETRY_MIN) ||
4286 		!((vwrq->flags & IW_RETRY_LONG) || (vwrq->flags & IW_RETRY_MAX))) {
4287 #else
4288 		if ((vwrq->flags & IW_RETRY_MIN) || !(vwrq->flags & IW_RETRY_MAX)) {
4289 #endif
4290 			srl = htod32(vwrq->value);
4291 			if ((error = dev_wlc_ioctl(dev, WLC_SET_SRL, &srl, sizeof(srl))))
4292 				return error;
4293 		}
4294 	}
4295 	return 0;
4296 }
4297 
4298 static int
4299 wl_iw_get_retry(
4300 	struct net_device *dev,
4301 	struct iw_request_info *info,
4302 	struct iw_param *vwrq,
4303 	char *extra
4304 )
4305 {
4306 	int error, lrl, srl;
4307 
4308 	WL_TRACE(("%s: SIOCGIWRETRY\n", dev->name));
4309 
4310 	vwrq->disabled = 0;
4311 
4312 
4313 	if ((vwrq->flags & IW_RETRY_TYPE) == IW_RETRY_LIFETIME)
4314 		return -EINVAL;
4315 
4316 
4317 	if ((error = dev_wlc_ioctl(dev, WLC_GET_LRL, &lrl, sizeof(lrl))) ||
4318 	    (error = dev_wlc_ioctl(dev, WLC_GET_SRL, &srl, sizeof(srl))))
4319 		return error;
4320 
4321 	lrl = dtoh32(lrl);
4322 	srl = dtoh32(srl);
4323 
4324 
4325 	if (vwrq->flags & IW_RETRY_MAX) {
4326 		vwrq->flags = IW_RETRY_LIMIT | IW_RETRY_MAX;
4327 		vwrq->value = lrl;
4328 	} else {
4329 		vwrq->flags = IW_RETRY_LIMIT;
4330 		vwrq->value = srl;
4331 		if (srl != lrl)
4332 			vwrq->flags |= IW_RETRY_MIN;
4333 	}
4334 
4335 	return 0;
4336 }
4337 #endif
4338 
4339 static int
4340 wl_iw_set_encode(
4341 	struct net_device *dev,
4342 	struct iw_request_info *info,
4343 	struct iw_point *dwrq,
4344 	char *extra
4345 )
4346 {
4347 	wl_wsec_key_t key;
4348 	int error, val, wsec;
4349 
4350 	WL_TRACE(("%s: SIOCSIWENCODE\n", dev->name));
4351 
4352 	memset(&key, 0, sizeof(key));
4353 
4354 	if ((dwrq->flags & IW_ENCODE_INDEX) == 0) {
4355 
4356 		for (key.index = 0; key.index < DOT11_MAX_DEFAULT_KEYS; key.index++) {
4357 			val = htod32(key.index);
4358 			if ((error = dev_wlc_ioctl(dev, WLC_GET_KEY_PRIMARY, &val, sizeof(val))))
4359 				return error;
4360 			val = dtoh32(val);
4361 			if (val)
4362 				break;
4363 		}
4364 
4365 		if (key.index == DOT11_MAX_DEFAULT_KEYS)
4366 			key.index = 0;
4367 	} else {
4368 		key.index = (dwrq->flags & IW_ENCODE_INDEX) - 1;
4369 		if (key.index >= DOT11_MAX_DEFAULT_KEYS)
4370 			return -EINVAL;
4371 	}
4372 
4373 
4374 	if (!extra || !dwrq->length || (dwrq->flags & IW_ENCODE_NOKEY)) {
4375 
4376 		val = htod32(key.index);
4377 		if ((error = dev_wlc_ioctl(dev, WLC_SET_KEY_PRIMARY, &val, sizeof(val))))
4378 			return error;
4379 	} else {
4380 		key.len = dwrq->length;
4381 
4382 		if (dwrq->length > sizeof(key.data))
4383 			return -EINVAL;
4384 
4385 		memcpy(key.data, extra, dwrq->length);
4386 
4387 		key.flags = WL_PRIMARY_KEY;
4388 		switch (key.len) {
4389 		case WEP1_KEY_SIZE:
4390 			key.algo = CRYPTO_ALGO_WEP1;
4391 			break;
4392 		case WEP128_KEY_SIZE:
4393 			key.algo = CRYPTO_ALGO_WEP128;
4394 			break;
4395 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 14)
4396 		case TKIP_KEY_SIZE:
4397 			key.algo = CRYPTO_ALGO_TKIP;
4398 			break;
4399 #endif
4400 		case AES_KEY_SIZE:
4401 			key.algo = CRYPTO_ALGO_AES_CCM;
4402 			break;
4403 		default:
4404 			return -EINVAL;
4405 		}
4406 
4407 
4408 		swap_key_from_BE(&key);
4409 		if ((error = dev_wlc_ioctl(dev, WLC_SET_KEY, &key, sizeof(key))))
4410 			return error;
4411 	}
4412 
4413 
4414 	val = (dwrq->flags & IW_ENCODE_DISABLED) ? 0 : WEP_ENABLED;
4415 
4416 	if ((error = dev_wlc_intvar_get(dev, "wsec", &wsec)))
4417 		return error;
4418 
4419 	wsec  &= ~(WEP_ENABLED);
4420 	wsec |= val;
4421 
4422 	if ((error = dev_wlc_intvar_set(dev, "wsec", wsec)))
4423 		return error;
4424 
4425 
4426 	val = (dwrq->flags & IW_ENCODE_RESTRICTED) ? 1 : 0;
4427 	val = htod32(val);
4428 	if ((error = dev_wlc_ioctl(dev, WLC_SET_AUTH, &val, sizeof(val))))
4429 		return error;
4430 
4431 	return 0;
4432 }
4433 
4434 static int
4435 wl_iw_get_encode(
4436 	struct net_device *dev,
4437 	struct iw_request_info *info,
4438 	struct iw_point *dwrq,
4439 	char *extra
4440 )
4441 {
4442 	wl_wsec_key_t key;
4443 	int error, val, wsec, auth;
4444 
4445 	WL_TRACE(("%s: SIOCGIWENCODE\n", dev->name));
4446 
4447 
4448 	bzero(&key, sizeof(wl_wsec_key_t));
4449 
4450 	if ((dwrq->flags & IW_ENCODE_INDEX) == 0) {
4451 
4452 		for (key.index = 0; key.index < DOT11_MAX_DEFAULT_KEYS; key.index++) {
4453 			val = key.index;
4454 			if ((error = dev_wlc_ioctl(dev, WLC_GET_KEY_PRIMARY, &val, sizeof(val))))
4455 				return error;
4456 			val = dtoh32(val);
4457 			if (val)
4458 				break;
4459 		}
4460 	} else
4461 		key.index = (dwrq->flags & IW_ENCODE_INDEX) - 1;
4462 
4463 	if (key.index >= DOT11_MAX_DEFAULT_KEYS)
4464 		key.index = 0;
4465 
4466 
4467 
4468 	if ((error = dev_wlc_ioctl(dev, WLC_GET_WSEC, &wsec, sizeof(wsec))) ||
4469 	    (error = dev_wlc_ioctl(dev, WLC_GET_AUTH, &auth, sizeof(auth))))
4470 		return error;
4471 
4472 	swap_key_to_BE(&key);
4473 
4474 	wsec = dtoh32(wsec);
4475 	auth = dtoh32(auth);
4476 
4477 	dwrq->length = MIN(DOT11_MAX_KEY_SIZE, key.len);
4478 
4479 
4480 	dwrq->flags = key.index + 1;
4481 	if (!(wsec & (WEP_ENABLED | TKIP_ENABLED | AES_ENABLED))) {
4482 
4483 		dwrq->flags |= IW_ENCODE_DISABLED;
4484 	}
4485 	if (auth) {
4486 
4487 		dwrq->flags |= IW_ENCODE_RESTRICTED;
4488 	}
4489 
4490 
4491 	if (dwrq->length && extra)
4492 		memcpy(extra, key.data, dwrq->length);
4493 
4494 	return 0;
4495 }
4496 
4497 static int
4498 wl_iw_set_power(
4499 	struct net_device *dev,
4500 	struct iw_request_info *info,
4501 	struct iw_param *vwrq,
4502 	char *extra
4503 )
4504 {
4505 	int error, pm;
4506 
4507 	WL_TRACE(("%s: SIOCSIWPOWER\n", dev->name));
4508 
4509 	pm = vwrq->disabled ? PM_OFF : PM_MAX;
4510 
4511 	pm = htod32(pm);
4512 	if ((error = dev_wlc_ioctl(dev, WLC_SET_PM, &pm, sizeof(pm))))
4513 		return error;
4514 
4515 	return 0;
4516 }
4517 
4518 static int
4519 wl_iw_get_power(
4520 	struct net_device *dev,
4521 	struct iw_request_info *info,
4522 	struct iw_param *vwrq,
4523 	char *extra
4524 )
4525 {
4526 	int error, pm;
4527 
4528 	WL_TRACE(("%s: SIOCGIWPOWER\n", dev->name));
4529 
4530 	if ((error = dev_wlc_ioctl(dev, WLC_GET_PM, &pm, sizeof(pm))))
4531 		return error;
4532 
4533 	pm = dtoh32(pm);
4534 	vwrq->disabled = pm ? 0 : 1;
4535 	vwrq->flags = IW_POWER_ALL_R;
4536 
4537 	return 0;
4538 }
4539 
4540 #if WIRELESS_EXT > 17
4541 static int
4542 wl_iw_set_wpaie(
4543 	struct net_device *dev,
4544 	struct iw_request_info *info,
4545 	struct iw_point *iwp,
4546 	char *extra
4547 )
4548 {
4549 	uchar buf[WLC_IOCTL_SMLEN] = {0};
4550 	uchar *p = buf;
4551 	int wapi_ie_size;
4552 
4553 	WL_TRACE(("%s: SIOCSIWGENIE\n", dev->name));
4554 
4555 	CHECK_EXTRA_FOR_NULL(extra);
4556 
4557 	if (extra[0] == DOT11_MNG_WAPI_ID)
4558 	{
4559 		wapi_ie_size = iwp->length;
4560 		memcpy(p, extra, iwp->length);
4561 		dev_wlc_bufvar_set(dev, "wapiie", buf, wapi_ie_size);
4562 	}
4563 	else
4564 		dev_wlc_bufvar_set(dev, "wpaie", extra, iwp->length);
4565 
4566 	return 0;
4567 }
4568 
4569 static int
4570 wl_iw_get_wpaie(
4571 	struct net_device *dev,
4572 	struct iw_request_info *info,
4573 	struct iw_point *iwp,
4574 	char *extra
4575 )
4576 {
4577 	WL_TRACE(("%s: SIOCGIWGENIE\n", dev->name));
4578 	iwp->length = 64;
4579 	dev_wlc_bufvar_get(dev, "wpaie", extra, iwp->length);
4580 	return 0;
4581 }
4582 
4583 static int
4584 wl_iw_set_encodeext(
4585 	struct net_device *dev,
4586 	struct iw_request_info *info,
4587 	struct iw_point *dwrq,
4588 	char *extra
4589 )
4590 {
4591 	wl_wsec_key_t key;
4592 	int error;
4593 	struct iw_encode_ext *iwe;
4594 
4595 	WL_TRACE(("%s: SIOCSIWENCODEEXT\n", dev->name));
4596 
4597 	CHECK_EXTRA_FOR_NULL(extra);
4598 
4599 	memset(&key, 0, sizeof(key));
4600 	iwe = (struct iw_encode_ext *)extra;
4601 
4602 
4603 	if (dwrq->flags & IW_ENCODE_DISABLED) {
4604 
4605 	}
4606 
4607 
4608 	key.index = 0;
4609 	if (dwrq->flags & IW_ENCODE_INDEX)
4610 		key.index = (dwrq->flags & IW_ENCODE_INDEX) - 1;
4611 
4612 	key.len = iwe->key_len;
4613 
4614 
4615 	if (!ETHER_ISMULTI(iwe->addr.sa_data))
4616 		bcopy((void *)&iwe->addr.sa_data, (char *)&key.ea, ETHER_ADDR_LEN);
4617 
4618 
4619 	if (key.len == 0) {
4620 		if (iwe->ext_flags & IW_ENCODE_EXT_SET_TX_KEY) {
4621 			WL_WSEC(("Changing the the primary Key to %d\n", key.index));
4622 
4623 			key.index = htod32(key.index);
4624 			error = dev_wlc_ioctl(dev, WLC_SET_KEY_PRIMARY,
4625 				&key.index, sizeof(key.index));
4626 			if (error)
4627 				return error;
4628 		}
4629 
4630 		else {
4631 			swap_key_from_BE(&key);
4632 			dev_wlc_ioctl(dev, WLC_SET_KEY, &key, sizeof(key));
4633 		}
4634 	}
4635 	else {
4636 		if (iwe->key_len > sizeof(key.data))
4637 			return -EINVAL;
4638 
4639 		WL_WSEC(("Setting the key index %d\n", key.index));
4640 		if (iwe->ext_flags & IW_ENCODE_EXT_SET_TX_KEY) {
4641 			WL_WSEC(("key is a Primary Key\n"));
4642 			key.flags = WL_PRIMARY_KEY;
4643 		}
4644 
4645 		bcopy((void *)iwe->key, key.data, iwe->key_len);
4646 
4647 		if (iwe->alg == IW_ENCODE_ALG_TKIP) {
4648 			uint8 keybuf[8];
4649 			bcopy(&key.data[24], keybuf, sizeof(keybuf));
4650 			bcopy(&key.data[16], &key.data[24], sizeof(keybuf));
4651 			bcopy(keybuf, &key.data[16], sizeof(keybuf));
4652 		}
4653 
4654 
4655 		if (iwe->ext_flags & IW_ENCODE_EXT_RX_SEQ_VALID) {
4656 			uchar *ivptr;
4657 			ivptr = (uchar *)iwe->rx_seq;
4658 			key.rxiv.hi = (ivptr[5] << 24) | (ivptr[4] << 16) |
4659 				(ivptr[3] << 8) | ivptr[2];
4660 			key.rxiv.lo = (ivptr[1] << 8) | ivptr[0];
4661 			key.iv_initialized = TRUE;
4662 		}
4663 
4664 		switch (iwe->alg) {
4665 			case IW_ENCODE_ALG_NONE:
4666 				key.algo = CRYPTO_ALGO_OFF;
4667 				break;
4668 			case IW_ENCODE_ALG_WEP:
4669 				if (iwe->key_len == WEP1_KEY_SIZE)
4670 					key.algo = CRYPTO_ALGO_WEP1;
4671 				else
4672 					key.algo = CRYPTO_ALGO_WEP128;
4673 				break;
4674 			case IW_ENCODE_ALG_TKIP:
4675 				key.algo = CRYPTO_ALGO_TKIP;
4676 				break;
4677 			case IW_ENCODE_ALG_CCMP:
4678 				key.algo = CRYPTO_ALGO_AES_CCM;
4679 				break;
4680 			case IW_ENCODE_ALG_SM4:
4681 				key.algo = CRYPTO_ALGO_SMS4;
4682 				if (iwe->ext_flags & IW_ENCODE_EXT_GROUP_KEY) {
4683 					key.flags &= ~WL_PRIMARY_KEY;
4684 				}
4685 				break;
4686 			default:
4687 				break;
4688 		}
4689 		swap_key_from_BE(&key);
4690 
4691 		dhd_wait_pend8021x(dev);
4692 
4693 		error = dev_wlc_ioctl(dev, WLC_SET_KEY, &key, sizeof(key));
4694 		if (error)
4695 			return error;
4696 	}
4697 	return 0;
4698 }
4699 
4700 #if WIRELESS_EXT > 17
4701 #ifdef BCMWPA2
4702 struct {
4703 	pmkid_list_t pmkids;
4704 	pmkid_t foo[MAXPMKID-1];
4705 } pmkid_list;
4706 
4707 static int
4708 wl_iw_set_pmksa(
4709 	struct net_device *dev,
4710 	struct iw_request_info *info,
4711 	struct iw_param *vwrq,
4712 	char *extra
4713 )
4714 {
4715 	struct iw_pmksa *iwpmksa;
4716 	uint i;
4717 	int ret = 0;
4718 	char eabuf[ETHER_ADDR_STR_LEN];
4719 
4720 	WL_WSEC(("%s: SIOCSIWPMKSA\n", dev->name));
4721 	CHECK_EXTRA_FOR_NULL(extra);
4722 
4723 	iwpmksa = (struct iw_pmksa *)extra;
4724 	bzero((char *)eabuf, ETHER_ADDR_STR_LEN);
4725 
4726 	if (iwpmksa->cmd == IW_PMKSA_FLUSH) {
4727 		WL_WSEC(("wl_iw_set_pmksa - IW_PMKSA_FLUSH\n"));
4728 		bzero((char *)&pmkid_list, sizeof(pmkid_list));
4729 	}
4730 
4731 	else if (iwpmksa->cmd == IW_PMKSA_REMOVE) {
4732 		{
4733 			pmkid_list_t pmkid, *pmkidptr;
4734 			uint j;
4735 			pmkidptr = &pmkid;
4736 
4737 			bcopy(&iwpmksa->bssid.sa_data[0], &pmkidptr->pmkid[0].BSSID, ETHER_ADDR_LEN);
4738 			bcopy(&iwpmksa->pmkid[0], &pmkidptr->pmkid[0].PMKID, WPA2_PMKID_LEN);
4739 
4740 			WL_WSEC(("wl_iw_set_pmksa,IW_PMKSA_REMOVE - PMKID: %s = ",
4741 				bcm_ether_ntoa(&pmkidptr->pmkid[0].BSSID,
4742 				eabuf)));
4743 			for (j = 0; j < WPA2_PMKID_LEN; j++)
4744 				WL_WSEC(("%02x ", pmkidptr->pmkid[0].PMKID[j]));
4745 			WL_WSEC(("\n"));
4746 		}
4747 
4748 		for (i = 0; i < pmkid_list.pmkids.npmkid; i++)
4749 			if (!bcmp(&iwpmksa->bssid.sa_data[0], &pmkid_list.pmkids.pmkid[i].BSSID,
4750 				ETHER_ADDR_LEN))
4751 				break;
4752 
4753 		if ((pmkid_list.pmkids.npmkid > 0) && (i < pmkid_list.pmkids.npmkid)) {
4754 			bzero(&pmkid_list.pmkids.pmkid[i], sizeof(pmkid_t));
4755 			for (; i < (pmkid_list.pmkids.npmkid - 1); i++) {
4756 				bcopy(&pmkid_list.pmkids.pmkid[i+1].BSSID,
4757 					&pmkid_list.pmkids.pmkid[i].BSSID,
4758 					ETHER_ADDR_LEN);
4759 				bcopy(&pmkid_list.pmkids.pmkid[i+1].PMKID,
4760 					&pmkid_list.pmkids.pmkid[i].PMKID,
4761 					WPA2_PMKID_LEN);
4762 			}
4763 			pmkid_list.pmkids.npmkid--;
4764 		}
4765 		else
4766 			ret = -EINVAL;
4767 	}
4768 
4769 	else if (iwpmksa->cmd == IW_PMKSA_ADD) {
4770 		for (i = 0; i < pmkid_list.pmkids.npmkid; i++)
4771 			if (!bcmp(&iwpmksa->bssid.sa_data[0], &pmkid_list.pmkids.pmkid[i].BSSID,
4772 				ETHER_ADDR_LEN))
4773 				break;
4774 		if (i < MAXPMKID) {
4775 			bcopy(&iwpmksa->bssid.sa_data[0],
4776 				&pmkid_list.pmkids.pmkid[i].BSSID,
4777 				ETHER_ADDR_LEN);
4778 			bcopy(&iwpmksa->pmkid[0], &pmkid_list.pmkids.pmkid[i].PMKID,
4779 				WPA2_PMKID_LEN);
4780 			if (i == pmkid_list.pmkids.npmkid)
4781 				pmkid_list.pmkids.npmkid++;
4782 		}
4783 		else
4784 			ret = -EINVAL;
4785 
4786 		{
4787 			uint j;
4788 			uint k;
4789 			k = pmkid_list.pmkids.npmkid;
4790 			WL_WSEC(("wl_iw_set_pmksa,IW_PMKSA_ADD - PMKID: %s = ",
4791 				bcm_ether_ntoa(&pmkid_list.pmkids.pmkid[k].BSSID,
4792 				eabuf)));
4793 			for (j = 0; j < WPA2_PMKID_LEN; j++)
4794 				WL_WSEC(("%02x ", pmkid_list.pmkids.pmkid[k].PMKID[j]));
4795 			WL_WSEC(("\n"));
4796 		}
4797 	}
4798 	WL_WSEC(("PRINTING pmkid LIST - No of elements %d, ret = %d\n", pmkid_list.pmkids.npmkid, ret));
4799 	for (i = 0; i < pmkid_list.pmkids.npmkid; i++) {
4800 		uint j;
4801 		WL_WSEC(("PMKID[%d]: %s = ", i,
4802 			bcm_ether_ntoa(&pmkid_list.pmkids.pmkid[i].BSSID,
4803 			eabuf)));
4804 		for (j = 0; j < WPA2_PMKID_LEN; j++)
4805 			WL_WSEC(("%02x ", pmkid_list.pmkids.pmkid[i].PMKID[j]));
4806 		WL_WSEC(("\n"));
4807 	}
4808 	WL_WSEC(("\n"));
4809 
4810 	if (!ret)
4811 		ret = dev_wlc_bufvar_set(dev, "pmkid_info", (char *)&pmkid_list, sizeof(pmkid_list));
4812 	return ret;
4813 }
4814 #endif
4815 #endif
4816 
4817 static int
4818 wl_iw_get_encodeext(
4819 	struct net_device *dev,
4820 	struct iw_request_info *info,
4821 	struct iw_param *vwrq,
4822 	char *extra
4823 )
4824 {
4825 	WL_TRACE(("%s: SIOCGIWENCODEEXT\n", dev->name));
4826 	return 0;
4827 }
4828 
4829 static int
4830 wl_iw_set_wpaauth(
4831 	struct net_device *dev,
4832 	struct iw_request_info *info,
4833 	struct iw_param *vwrq,
4834 	char *extra
4835 )
4836 {
4837 	int error = 0;
4838 	int paramid;
4839 	int paramval;
4840 	int val = 0;
4841 	wl_iw_t *iw = *(wl_iw_t **)netdev_priv(dev);
4842 
4843 	WL_TRACE(("%s: SIOCSIWAUTH\n", dev->name));
4844 
4845 #if defined(SOFTAP)
4846 	if (ap_cfg_running) {
4847 		WL_TRACE(("%s: Not executed, reason -'SOFTAP is active'\n", __FUNCTION__));
4848 		return 0;
4849 	}
4850 #endif
4851 
4852 	paramid = vwrq->flags & IW_AUTH_INDEX;
4853 	paramval = vwrq->value;
4854 
4855 	WL_TRACE(("%s: SIOCSIWAUTH, paramid = 0x%0x, paramval = 0x%0x\n",
4856 		dev->name, paramid, paramval));
4857 
4858 	switch (paramid) {
4859 	case IW_AUTH_WPA_VERSION:
4860 
4861 		if (paramval & IW_AUTH_WPA_VERSION_DISABLED)
4862 			val = WPA_AUTH_DISABLED;
4863 		else if (paramval & (IW_AUTH_WPA_VERSION_WPA))
4864 			val = WPA_AUTH_PSK | WPA_AUTH_UNSPECIFIED;
4865 #ifdef BCMWPA2
4866 		else if (paramval & IW_AUTH_WPA_VERSION_WPA2)
4867 			val = WPA2_AUTH_PSK | WPA2_AUTH_UNSPECIFIED;
4868 #endif
4869 		else if (paramval & IW_AUTH_WAPI_VERSION_1)
4870 			val = WPA_AUTH_WAPI;
4871 		WL_INFORM(("%s: %d: setting wpa_auth to 0x%0x\n", __FUNCTION__, __LINE__, val));
4872 		if ((error = dev_wlc_intvar_set(dev, "wpa_auth", val)))
4873 			return error;
4874 		break;
4875 	case IW_AUTH_CIPHER_PAIRWISE:
4876 	case IW_AUTH_CIPHER_GROUP:
4877 
4878 
4879 		if (paramval & (IW_AUTH_CIPHER_WEP40 | IW_AUTH_CIPHER_WEP104))
4880 			val = 	WEP_ENABLED;
4881 		if (paramval & IW_AUTH_CIPHER_TKIP)
4882 			val = TKIP_ENABLED;
4883 		if (paramval & IW_AUTH_CIPHER_CCMP)
4884 			val = AES_ENABLED;
4885 		if (paramval & IW_AUTH_CIPHER_SMS4)
4886 			val = SMS4_ENABLED;
4887 
4888 		if (paramid == IW_AUTH_CIPHER_PAIRWISE) {
4889 			iw->pwsec = val;
4890 			val |= iw->gwsec;
4891 		}
4892 		else {
4893 			iw->gwsec = val;
4894 			val |= iw->pwsec;
4895 		}
4896 
4897 		if (iw->privacy_invoked && !val) {
4898 			WL_WSEC(("%s: %s: 'Privacy invoked' TRUE but clearing wsec, assuming "
4899 				"we're a WPS enrollee\n", dev->name, __FUNCTION__));
4900 			if ((error = dev_wlc_intvar_set(dev, "is_WPS_enrollee", TRUE))) {
4901 				WL_WSEC(("Failed to set iovar is_WPS_enrollee\n"));
4902 				return error;
4903 			}
4904 		} else if (val) {
4905 			if ((error = dev_wlc_intvar_set(dev, "is_WPS_enrollee", FALSE))) {
4906 				WL_WSEC(("Failed to clear iovar is_WPS_enrollee\n"));
4907 				return error;
4908 			}
4909 		}
4910 
4911 		if ((error = dev_wlc_intvar_set(dev, "wsec", val)))
4912 			return error;
4913 
4914 		break;
4915 
4916 	case IW_AUTH_KEY_MGMT:
4917 		if ((error = dev_wlc_intvar_get(dev, "wpa_auth", &val)))
4918 			return error;
4919 
4920 		if (val & (WPA_AUTH_PSK | WPA_AUTH_UNSPECIFIED)) {
4921 			if (paramval & IW_AUTH_KEY_MGMT_PSK)
4922 				val = WPA_AUTH_PSK;
4923 			else
4924 				val = WPA_AUTH_UNSPECIFIED;
4925 		}
4926 #ifdef BCMWPA2
4927 		else if (val & (WPA2_AUTH_PSK | WPA2_AUTH_UNSPECIFIED)) {
4928 			if (paramval & IW_AUTH_KEY_MGMT_PSK)
4929 				val = WPA2_AUTH_PSK;
4930 			else
4931 				val = WPA2_AUTH_UNSPECIFIED;
4932 		}
4933 #endif
4934 		if (paramval & (IW_AUTH_KEY_MGMT_WAPI_PSK | IW_AUTH_KEY_MGMT_WAPI_CERT))
4935 			val = WPA_AUTH_WAPI;
4936 		WL_INFORM(("%s: %d: setting wpa_auth to %d\n", __FUNCTION__, __LINE__, val));
4937 		if ((error = dev_wlc_intvar_set(dev, "wpa_auth", val)))
4938 			return error;
4939 
4940 		break;
4941 	case IW_AUTH_TKIP_COUNTERMEASURES:
4942 		dev_wlc_bufvar_set(dev, "tkip_countermeasures", (char *)&paramval, 1);
4943 		break;
4944 
4945 	case IW_AUTH_80211_AUTH_ALG:
4946 
4947 		WL_INFORM(("Setting the D11auth %d\n", paramval));
4948 		if (paramval == IW_AUTH_ALG_OPEN_SYSTEM)
4949 			val = 0;
4950 		else if (paramval == IW_AUTH_ALG_SHARED_KEY)
4951 			val = 1;
4952 		else if (paramval == (IW_AUTH_ALG_OPEN_SYSTEM | IW_AUTH_ALG_SHARED_KEY))
4953 			val = 2;
4954 		else
4955 			error = 1;
4956 		if (!error && (error = dev_wlc_intvar_set(dev, "auth", val)))
4957 			return error;
4958 		break;
4959 
4960 	case IW_AUTH_WPA_ENABLED:
4961 		if (paramval == 0) {
4962 			iw->pwsec = 0;
4963 			iw->gwsec = 0;
4964 			if ((error = dev_wlc_intvar_get(dev, "wsec", &val)))
4965 				return error;
4966 			if (val & (TKIP_ENABLED | AES_ENABLED)) {
4967 				val &= ~(TKIP_ENABLED | AES_ENABLED);
4968 				dev_wlc_intvar_set(dev, "wsec", val);
4969 			}
4970 			val = 0;
4971 		WL_INFORM(("%s: %d: setting wpa_auth to %d\n", __FUNCTION__, __LINE__, val));
4972 			dev_wlc_intvar_set(dev, "wpa_auth", 0);
4973 			return error;
4974 		}
4975 
4976 
4977 		break;
4978 
4979 	case IW_AUTH_DROP_UNENCRYPTED:
4980 		dev_wlc_bufvar_set(dev, "wsec_restrict", (char *)&paramval, 1);
4981 		break;
4982 
4983 	case IW_AUTH_RX_UNENCRYPTED_EAPOL:
4984 		dev_wlc_bufvar_set(dev, "rx_unencrypted_eapol", (char *)&paramval, 1);
4985 		break;
4986 
4987 #if WIRELESS_EXT > 17
4988 	case IW_AUTH_ROAMING_CONTROL:
4989 		WL_INFORM(("%s: IW_AUTH_ROAMING_CONTROL\n", __FUNCTION__));
4990 
4991 		break;
4992 	case IW_AUTH_PRIVACY_INVOKED: {
4993 		int wsec;
4994 
4995 		if (paramval == 0) {
4996 			iw->privacy_invoked = FALSE;
4997 			if ((error = dev_wlc_intvar_set(dev, "is_WPS_enrollee", FALSE))) {
4998 				WL_WSEC(("Failed to clear iovar is_WPS_enrollee\n"));
4999 				return error;
5000 			}
5001 		} else {
5002 			iw->privacy_invoked = TRUE;
5003 			if ((error = dev_wlc_intvar_get(dev, "wsec", &wsec)))
5004 				return error;
5005 
5006 			if (!(IW_WSEC_ENABLED(wsec))) {
5007 
5008 				if ((error = dev_wlc_intvar_set(dev, "is_WPS_enrollee", TRUE))) {
5009 					WL_WSEC(("Failed to set iovar is_WPS_enrollee\n"));
5010 					return error;
5011 				}
5012 			} else {
5013 				if ((error = dev_wlc_intvar_set(dev, "is_WPS_enrollee", FALSE))) {
5014 					WL_WSEC(("Failed to clear iovar is_WPS_enrollee\n"));
5015 					return error;
5016 				}
5017 			}
5018 		}
5019 		break;
5020 	}
5021 #endif
5022 	case IW_AUTH_WAPI_ENABLED:
5023 		if ((error = dev_wlc_intvar_get(dev, "wsec", &val)))
5024 			return error;
5025 		if (paramval) {
5026 			val |= SMS4_ENABLED;
5027 			if ((error = dev_wlc_intvar_set(dev, "wsec", val))) {
5028 				WL_ERROR(("%s: setting wsec to 0x%0x returned error %d\n",
5029 					__FUNCTION__, val, error));
5030 				return error;
5031 			}
5032 			if ((error = dev_wlc_intvar_set(dev, "wpa_auth", WPA_AUTH_WAPI))) {
5033 				WL_ERROR(("%s: setting wpa_auth(WPA_AUTH_WAPI) returned %d\n",
5034 					__FUNCTION__, error));
5035 				return error;
5036 			}
5037 		}
5038 
5039 		break;
5040 	default:
5041 		break;
5042 	}
5043 	return 0;
5044 }
5045 #ifdef BCMWPA2
5046 #define VAL_PSK(_val) (((_val) & WPA_AUTH_PSK) || ((_val) & WPA2_AUTH_PSK))
5047 #else
5048 #define VAL_PSK(_val) (((_val) & WPA_AUTH_PSK))
5049 #endif
5050 
5051 static int
5052 wl_iw_get_wpaauth(
5053 	struct net_device *dev,
5054 	struct iw_request_info *info,
5055 	struct iw_param *vwrq,
5056 	char *extra
5057 )
5058 {
5059 	int error;
5060 	int paramid;
5061 	int paramval = 0;
5062 	int val;
5063 	wl_iw_t *iw = *(wl_iw_t **)netdev_priv(dev);
5064 
5065 	WL_TRACE(("%s: SIOCGIWAUTH\n", dev->name));
5066 
5067 	paramid = vwrq->flags & IW_AUTH_INDEX;
5068 
5069 	switch (paramid) {
5070 	case IW_AUTH_WPA_VERSION:
5071 
5072 		if ((error = dev_wlc_intvar_get(dev, "wpa_auth", &val)))
5073 			return error;
5074 		if (val & (WPA_AUTH_NONE | WPA_AUTH_DISABLED))
5075 			paramval = IW_AUTH_WPA_VERSION_DISABLED;
5076 		else if (val & (WPA_AUTH_PSK | WPA_AUTH_UNSPECIFIED))
5077 			paramval = IW_AUTH_WPA_VERSION_WPA;
5078 #ifdef BCMWPA2
5079 		else if (val & (WPA2_AUTH_PSK | WPA2_AUTH_UNSPECIFIED))
5080 			paramval = IW_AUTH_WPA_VERSION_WPA2;
5081 #endif
5082 		break;
5083 	case IW_AUTH_CIPHER_PAIRWISE:
5084 	case IW_AUTH_CIPHER_GROUP:
5085 		if (paramid == IW_AUTH_CIPHER_PAIRWISE)
5086 			val = iw->pwsec;
5087 		else
5088 			val = iw->gwsec;
5089 
5090 		paramval = 0;
5091 		if (val) {
5092 			if (val & WEP_ENABLED)
5093 				paramval |= (IW_AUTH_CIPHER_WEP40 | IW_AUTH_CIPHER_WEP104);
5094 			if (val & TKIP_ENABLED)
5095 				paramval |= (IW_AUTH_CIPHER_TKIP);
5096 			if (val & AES_ENABLED)
5097 				paramval |= (IW_AUTH_CIPHER_CCMP);
5098 		}
5099 		else
5100 			paramval = IW_AUTH_CIPHER_NONE;
5101 		break;
5102 	case IW_AUTH_KEY_MGMT:
5103 
5104 		if ((error = dev_wlc_intvar_get(dev, "wpa_auth", &val)))
5105 			return error;
5106 		if (VAL_PSK(val))
5107 			paramval = IW_AUTH_KEY_MGMT_PSK;
5108 		else
5109 			paramval = IW_AUTH_KEY_MGMT_802_1X;
5110 
5111 		break;
5112 	case IW_AUTH_TKIP_COUNTERMEASURES:
5113 		dev_wlc_bufvar_get(dev, "tkip_countermeasures", (char *)&paramval, 1);
5114 		break;
5115 
5116 	case IW_AUTH_DROP_UNENCRYPTED:
5117 		dev_wlc_bufvar_get(dev, "wsec_restrict", (char *)&paramval, 1);
5118 		break;
5119 
5120 	case IW_AUTH_RX_UNENCRYPTED_EAPOL:
5121 		dev_wlc_bufvar_get(dev, "rx_unencrypted_eapol", (char *)&paramval, 1);
5122 		break;
5123 
5124 	case IW_AUTH_80211_AUTH_ALG:
5125 
5126 		if ((error = dev_wlc_intvar_get(dev, "auth", &val)))
5127 			return error;
5128 		if (!val)
5129 			paramval = IW_AUTH_ALG_OPEN_SYSTEM;
5130 		else
5131 			paramval = IW_AUTH_ALG_SHARED_KEY;
5132 		break;
5133 	case IW_AUTH_WPA_ENABLED:
5134 		if ((error = dev_wlc_intvar_get(dev, "wpa_auth", &val)))
5135 			return error;
5136 		if (val)
5137 			paramval = TRUE;
5138 		else
5139 			paramval = FALSE;
5140 		break;
5141 #if WIRELESS_EXT > 17
5142 	case IW_AUTH_ROAMING_CONTROL:
5143 		WL_ERROR(("%s: IW_AUTH_ROAMING_CONTROL\n", __FUNCTION__));
5144 
5145 		break;
5146 	case IW_AUTH_PRIVACY_INVOKED:
5147 		paramval = iw->privacy_invoked;
5148 		break;
5149 #endif
5150 	}
5151 	vwrq->value = paramval;
5152 	return 0;
5153 }
5154 #endif
5155 
5156 
5157 #ifdef SOFTAP
5158 
5159 static int ap_macmode = MACLIST_MODE_DISABLED;
5160 static struct mflist ap_black_list;
5161 static int
5162 wl_iw_parse_wep(char *keystr, wl_wsec_key_t *key)
5163 {
5164 	char hex[] = "XX";
5165 	unsigned char *data = key->data;
5166 
5167 	switch (strlen(keystr)) {
5168 	case 5:
5169 	case 13:
5170 	case 16:
5171 		key->len = strlen(keystr);
5172 		memcpy(data, keystr, key->len + 1);
5173 		break;
5174 	case 12:
5175 	case 28:
5176 	case 34:
5177 	case 66:
5178 		if (!strnicmp(keystr, "0x", 2))
5179 			keystr += 2;
5180 		else
5181 			return -1;
5182 	case 10:
5183 	case 26:
5184 	case 32:
5185 	case 64:
5186 		key->len = strlen(keystr) / 2;
5187 		while (*keystr) {
5188 			strncpy(hex, keystr, 2);
5189 			*data++ = (char) bcm_strtoul(hex, NULL, 16);
5190 			keystr += 2;
5191 		}
5192 		break;
5193 	default:
5194 		return -1;
5195 	}
5196 
5197 	switch (key->len) {
5198 	case 5:
5199 		key->algo = CRYPTO_ALGO_WEP1;
5200 		break;
5201 	case 13:
5202 		key->algo = CRYPTO_ALGO_WEP128;
5203 		break;
5204 	case 16:
5205 		key->algo = CRYPTO_ALGO_AES_CCM;
5206 		break;
5207 	case 32:
5208 		key->algo = CRYPTO_ALGO_TKIP;
5209 		break;
5210 	default:
5211 		return -1;
5212 	}
5213 
5214 	key->flags |= WL_PRIMARY_KEY;
5215 
5216 	return 0;
5217 }
5218 
5219 #ifdef EXT_WPA_CRYPTO
5220 #define SHA1HashSize 20
5221 extern void pbkdf2_sha1(const char *passphrase, const char *ssid, size_t ssid_len,
5222 				int iterations, u8 *buf, size_t buflen);
5223 
5224 #else
5225 
5226 #define SHA1HashSize 20
5227 int pbkdf2_sha1(const char *passphrase, const char *ssid, size_t ssid_len,
5228 				int iterations, u8 *buf, size_t buflen)
5229 {
5230 	WL_ERROR(("WARNING: %s is not implemented !!!\n", __FUNCTION__));
5231 	return -1;
5232 }
5233 
5234 #endif
5235 
5236 
5237 int dev_iw_write_cfg1_bss_var(struct net_device *dev, int val)
5238 {
5239 	struct {
5240 		int cfg;
5241 		int val;
5242 	} bss_setbuf;
5243 
5244 	int bss_set_res;
5245 	char smbuf[WLC_IOCTL_SMLEN];
5246 	memset(smbuf, 0, sizeof(smbuf));
5247 
5248 	bss_setbuf.cfg = 1;
5249 	bss_setbuf.val = val;
5250 
5251 	bss_set_res = dev_iw_iovar_setbuf(dev, "bss",
5252 		&bss_setbuf, sizeof(bss_setbuf), smbuf, sizeof(smbuf));
5253 	WL_TRACE(("%s: bss_set_result:%d set with %d\n", __FUNCTION__, bss_set_res, val));
5254 
5255 	return bss_set_res;
5256 }
5257 
5258 
5259 int dev_iw_read_cfg1_bss_var(struct net_device *dev, int *val)
5260 {
5261 	int bsscfg_idx = 1;
5262 	int bss_set_res;
5263 	char smbuf[WLC_IOCTL_SMLEN];
5264 	memset(smbuf, 0, sizeof(smbuf));
5265 
5266 	bss_set_res = dev_iw_iovar_getbuf(dev, "bss", \
5267 		 &bsscfg_idx, sizeof(bsscfg_idx), smbuf, sizeof(smbuf));
5268 	*val = *(int*)smbuf;
5269 	*val = dtoh32(*val);
5270 	WL_TRACE(("%s: status=%d bss_get_result=%d\n", __FUNCTION__, bss_set_res, *val));
5271 	return bss_set_res;
5272 }
5273 
5274 
5275 #ifndef AP_ONLY
5276 static int wl_bssiovar_mkbuf(
5277 			const char *iovar,
5278 			int bssidx,
5279 			void *param,
5280 			int paramlen,
5281 			void *bufptr,
5282 			int buflen,
5283 			int *perr)
5284 {
5285 	const char *prefix = "bsscfg:";
5286 	int8 *p;
5287 	uint prefixlen;
5288 	uint namelen;
5289 	uint iolen;
5290 
5291 	prefixlen = strlen(prefix);
5292 	namelen = strlen(iovar) + 1;
5293 	iolen = prefixlen + namelen + sizeof(int) + paramlen;
5294 
5295 	if (buflen < 0 || iolen > (uint)buflen) {
5296 		*perr = BCME_BUFTOOSHORT;
5297 		return 0;
5298 	}
5299 
5300 	p = (int8 *)bufptr;
5301 
5302 	memcpy(p, prefix, prefixlen);
5303 	p += prefixlen;
5304 
5305 	memcpy(p, iovar, namelen);
5306 	p += namelen;
5307 
5308 	bssidx = htod32(bssidx);
5309 	memcpy(p, &bssidx, sizeof(int32));
5310 	p += sizeof(int32);
5311 
5312 	if (paramlen)
5313 		memcpy(p, param, paramlen);
5314 
5315 	*perr = 0;
5316 	return iolen;
5317 }
5318 #endif
5319 
5320 
5321 int get_user_params(char *user_params, struct iw_point *dwrq)
5322 {
5323 	int ret = 0;
5324 
5325 	if (copy_from_user(user_params, dwrq->pointer, dwrq->length)) {
5326 		WL_ERROR(("\n%s: no user params: uptr:%p, ulen:%d\n",
5327 			__FUNCTION__, dwrq->pointer, dwrq->length));
5328 		return -EFAULT;
5329 	}
5330 
5331 	WL_TRACE(("\n%s: iwpriv user params:%s\n", __FUNCTION__, user_params));
5332 
5333 	return ret;
5334 }
5335 
5336 
5337 #define strtoul(nptr, endptr, base) bcm_strtoul((nptr), (endptr), (base))
5338 
5339 #if defined(CSCAN)
5340 
5341 static int
5342 wl_iw_combined_scan_set(struct net_device *dev, wlc_ssid_t* ssids_local, int nssid, int nchan)
5343 {
5344 	int params_size = WL_SCAN_PARAMS_FIXED_SIZE + WL_NUMCHANNELS * sizeof(uint16);
5345 	int err = 0;
5346 	char *p;
5347 	int i;
5348 	iscan_info_t *iscan = g_iscan;
5349 
5350 	WL_TRACE(("%s nssid=%d nchan=%d\n", __FUNCTION__, nssid, nchan));
5351 
5352 	if ((!dev) && (!g_iscan) && (!iscan->iscan_ex_params_p)) {
5353 		WL_ERROR(("%s error exit\n", __FUNCTION__));
5354 		err = -1;
5355 		goto exit;
5356 	}
5357 
5358 #ifdef PNO_SUPPORT
5359 	if  (dhd_dev_get_pno_status(dev)) {
5360 		WL_ERROR(("%s: Scan called when PNO is active\n", __FUNCTION__));
5361 	}
5362 #endif
5363 
5364 	params_size += WL_SCAN_PARAMS_SSID_MAX * sizeof(wlc_ssid_t);
5365 
5366 	if (nssid > 0) {
5367 		i = OFFSETOF(wl_scan_params_t, channel_list) + nchan * sizeof(uint16);
5368 		i = ROUNDUP(i, sizeof(uint32));
5369 		if (i + nssid * sizeof(wlc_ssid_t) > params_size) {
5370 			printf("additional ssids exceed params_size\n");
5371 			err = -1;
5372 			goto exit;
5373 		}
5374 
5375 		p = ((char*)&iscan->iscan_ex_params_p->params) + i;
5376 		memcpy(p, ssids_local, nssid * sizeof(wlc_ssid_t));
5377 		p += nssid * sizeof(wlc_ssid_t);
5378 	} else {
5379 		p = (char*)iscan->iscan_ex_params_p->params.channel_list + nchan * sizeof(uint16);
5380 	}
5381 
5382 
5383 	iscan->iscan_ex_params_p->params.channel_num = \
5384 		htod32((nssid << WL_SCAN_PARAMS_NSSID_SHIFT) | \
5385 					(nchan & WL_SCAN_PARAMS_COUNT_MASK));
5386 
5387 	nssid = \
5388 	(uint)((iscan->iscan_ex_params_p->params.channel_num >> WL_SCAN_PARAMS_NSSID_SHIFT) & \
5389 		               WL_SCAN_PARAMS_COUNT_MASK);
5390 
5391 
5392 	params_size = (int) (p - (char*)iscan->iscan_ex_params_p + nssid * sizeof(wlc_ssid_t));
5393 	iscan->iscan_ex_param_size = params_size;
5394 
5395 	iscan->list_cur = iscan->list_hdr;
5396 	iscan->iscan_state = ISCAN_STATE_SCANING;
5397 	wl_iw_set_event_mask(dev);
5398 	mod_timer(&iscan->timer, jiffies + iscan->timer_ms*HZ/1000);
5399 
5400 	iscan->timer_on = 1;
5401 
5402 #ifdef SCAN_DUMP
5403 	{
5404 		int i;
5405 		WL_SCAN(("\n### List of SSIDs to scan ###\n"));
5406 		for (i = 0; i < nssid; i++) {
5407 			if (!ssids_local[i].SSID_len)
5408 				WL_SCAN(("%d: Broadcast scan\n", i));
5409 			else
5410 			WL_SCAN(("%d: scan  for  %s size =%d\n", i, \
5411 				ssids_local[i].SSID, ssids_local[i].SSID_len));
5412 		}
5413 		WL_SCAN(("### List of channels to scan ###\n"));
5414 		for (i = 0; i < nchan; i++)
5415 		{
5416 			WL_SCAN(("%d ", iscan->iscan_ex_params_p->params.channel_list[i]));
5417 		}
5418 		WL_SCAN(("\nnprobes=%d\n", iscan->iscan_ex_params_p->params.nprobes));
5419 		WL_SCAN(("active_time=%d\n", iscan->iscan_ex_params_p->params.active_time));
5420 		WL_SCAN(("passive_time=%d\n", iscan->iscan_ex_params_p->params.passive_time));
5421 		WL_SCAN(("home_time=%d\n", iscan->iscan_ex_params_p->params.home_time));
5422 		WL_SCAN(("scan_type=%d\n", iscan->iscan_ex_params_p->params.scan_type));
5423 		WL_SCAN(("\n###################\n"));
5424 	}
5425 #endif
5426 
5427 	if (params_size > WLC_IOCTL_MEDLEN) {
5428 			WL_ERROR(("Set ISCAN for %s due to params_size=%d  \n", \
5429 				__FUNCTION__, params_size));
5430 			err = -1;
5431 	}
5432 
5433 	if ((err = dev_iw_iovar_setbuf(dev, "iscan", iscan->iscan_ex_params_p, \
5434 			iscan->iscan_ex_param_size, \
5435 			iscan->ioctlbuf, sizeof(iscan->ioctlbuf)))) {
5436 			WL_ERROR(("Set ISCAN for %s failed with %d\n", __FUNCTION__, err));
5437 			err = -1;
5438 	}
5439 
5440 exit:
5441 
5442 	return err;
5443 }
5444 
5445 
5446 static int iwpriv_set_cscan(struct net_device *dev, struct iw_request_info *info, \
5447 				union iwreq_data *wrqu, char *ext)
5448 {
5449 	int res = 0;
5450 	char  *extra = NULL;
5451 	iscan_info_t *iscan = g_iscan;
5452 	wlc_ssid_t ssids_local[WL_SCAN_PARAMS_SSID_MAX];
5453 	int nssid = 0;
5454 	int nchan = 0;
5455 
5456 	WL_TRACE(("\%s: info->cmd:%x, info->flags:%x, u.data=0x%p, u.len=%d\n",
5457 		__FUNCTION__, info->cmd, info->flags,
5458 		wrqu->data.pointer, wrqu->data.length));
5459 
5460 	if (g_onoff == G_WLAN_SET_OFF) {
5461 		WL_TRACE(("%s: driver is not up yet after START\n", __FUNCTION__));
5462 		return -1;
5463 	}
5464 
5465 	if (wrqu->data.length != 0) {
5466 
5467 		char *str_ptr;
5468 
5469 		if (!iscan->iscan_ex_params_p) {
5470 			return -EFAULT;
5471 		}
5472 
5473 		if (!(extra = kmalloc(wrqu->data.length+1, GFP_KERNEL)))
5474 			return -ENOMEM;
5475 
5476 		if (copy_from_user(extra, wrqu->data.pointer, wrqu->data.length)) {
5477 			kfree(extra);
5478 			return -EFAULT;
5479 		}
5480 
5481 		extra[wrqu->data.length] = 0;
5482 		WL_ERROR(("Got str param in iw_point:\n %s\n", extra));
5483 
5484 		str_ptr = extra;
5485 
5486 		if (strncmp(str_ptr, GET_SSID, strlen(GET_SSID))) {
5487 			WL_ERROR(("%s Error: extracting SSID='' string\n", __FUNCTION__));
5488 			goto exit_proc;
5489 		}
5490 		str_ptr += strlen(GET_SSID);
5491 		nssid = wl_iw_parse_ssid_list(&str_ptr, ssids_local, nssid, \
5492 						WL_SCAN_PARAMS_SSID_MAX);
5493 		if (nssid == -1) {
5494 			WL_ERROR(("%s wrong ssid list", __FUNCTION__));
5495 			return -1;
5496 		}
5497 
5498 		memset(iscan->iscan_ex_params_p, 0, iscan->iscan_ex_param_size);
5499 		ASSERT(iscan->iscan_ex_param_size < WLC_IOCTL_MAXLEN);
5500 
5501 
5502 		wl_iw_iscan_prep(&iscan->iscan_ex_params_p->params, NULL);
5503 		iscan->iscan_ex_params_p->version = htod32(ISCAN_REQ_VERSION);
5504 		iscan->iscan_ex_params_p->action = htod16(WL_SCAN_ACTION_START);
5505 		iscan->iscan_ex_params_p->scan_duration = htod16(0);
5506 
5507 
5508 		if ((nchan = wl_iw_parse_channel_list(&str_ptr, \
5509 					&iscan->iscan_ex_params_p->params.channel_list[0], \
5510 					WL_NUMCHANNELS)) == -1) {
5511 			WL_ERROR(("%s missing channel list\n", __FUNCTION__));
5512 			return -1;
5513 		}
5514 
5515 
5516 		get_parmeter_from_string(&str_ptr, \
5517 				GET_NPROBE, PTYPE_INTDEC, \
5518 				&iscan->iscan_ex_params_p->params.nprobes, 2);
5519 
5520 		get_parmeter_from_string(&str_ptr, GET_ACTIVE_ASSOC_DWELL, PTYPE_INTDEC, \
5521 						&iscan->iscan_ex_params_p->params.active_time, 4);
5522 
5523 		get_parmeter_from_string(&str_ptr, GET_PASSIVE_ASSOC_DWELL, PTYPE_INTDEC, \
5524 						&iscan->iscan_ex_params_p->params.passive_time, 4);
5525 
5526 		get_parmeter_from_string(&str_ptr, GET_HOME_DWELL, PTYPE_INTDEC, \
5527 					&iscan->iscan_ex_params_p->params.home_time, 4);
5528 
5529 		get_parmeter_from_string(&str_ptr, GET_SCAN_TYPE, PTYPE_INTDEC, \
5530 					&iscan->iscan_ex_params_p->params.scan_type, 1);
5531 
5532 		res = wl_iw_combined_scan_set(dev, ssids_local, nssid, nchan);
5533 
5534 	} else {
5535 		  WL_ERROR(("IWPRIV argument len = 0 \n"));
5536 		  return -1;
5537 	}
5538 
5539 exit_proc:
5540 
5541 	kfree(extra);
5542 
5543 	return res;
5544 }
5545 
5546 
5547 static int
5548 wl_iw_set_cscan(
5549 	struct net_device *dev,
5550 	struct iw_request_info *info,
5551 	union iwreq_data *wrqu,
5552 	char *extra
5553 )
5554 {
5555 	int res = -1;
5556 	iscan_info_t *iscan = g_iscan;
5557 	wlc_ssid_t ssids_local[WL_SCAN_PARAMS_SSID_MAX];
5558 	int nssid = 0;
5559 	int nchan = 0;
5560 	cscan_tlv_t *cscan_tlv_temp;
5561 	char type;
5562 	char *str_ptr;
5563 	int tlv_size_left;
5564 #ifdef TLV_DEBUG
5565 	int i;
5566 	char tlv_in_example[] = {			'C', 'S', 'C', 'A', 'N', ' ', \
5567 							0x53, 0x01, 0x00, 0x00,
5568 							'S',
5569 							0x00,
5570 							'S',
5571 							0x04,
5572 							'B', 'R', 'C', 'M',
5573 							'C',
5574 							0x06,
5575 							'P',
5576 							0x94,
5577 							0x11,
5578 							'T',
5579 							0x01
5580 							};
5581 #endif
5582 
5583 	WL_TRACE(("\n### %s: info->cmd:%x, info->flags:%x, u.data=0x%p, u.len=%d\n",
5584 		__FUNCTION__, info->cmd, info->flags,
5585 		wrqu->data.pointer, wrqu->data.length));
5586 
5587 	net_os_wake_lock(dev);
5588 
5589 	if (g_onoff == G_WLAN_SET_OFF) {
5590 		WL_TRACE(("%s: driver is not up yet after START\n", __FUNCTION__));
5591 		goto exit_proc;
5592 	}
5593 
5594 
5595 	if (wrqu->data.length < (strlen(CSCAN_COMMAND) + sizeof(cscan_tlv_t))) {
5596 		WL_ERROR(("%s aggument=%d  less %d\n", __FUNCTION__, \
5597 			wrqu->data.length, strlen(CSCAN_COMMAND) + sizeof(cscan_tlv_t)));
5598 		goto exit_proc;
5599 	}
5600 
5601 #ifdef TLV_DEBUG
5602 	memcpy(extra, tlv_in_example, sizeof(tlv_in_example));
5603 	wrqu->data.length = sizeof(tlv_in_example);
5604 	for (i = 0; i < wrqu->data.length; i++)
5605 		printf("%02X ", extra[i]);
5606 	printf("\n");
5607 #endif
5608 
5609 	str_ptr = extra;
5610 	str_ptr +=  strlen(CSCAN_COMMAND);
5611 	tlv_size_left = wrqu->data.length - strlen(CSCAN_COMMAND);
5612 
5613 	cscan_tlv_temp = (cscan_tlv_t *)str_ptr;
5614 	memset(ssids_local, 0, sizeof(ssids_local));
5615 
5616 	if ((cscan_tlv_temp->prefix == CSCAN_TLV_PREFIX) && \
5617 		(cscan_tlv_temp->version == CSCAN_TLV_VERSION) && \
5618 		(cscan_tlv_temp->subver == CSCAN_TLV_SUBVERSION))
5619 	{
5620 		str_ptr += sizeof(cscan_tlv_t);
5621 		tlv_size_left  -= sizeof(cscan_tlv_t);
5622 
5623 
5624 		if ((nssid = wl_iw_parse_ssid_list_tlv(&str_ptr, ssids_local, \
5625 				WL_SCAN_PARAMS_SSID_MAX, &tlv_size_left)) <= 0) {
5626 			WL_ERROR(("SSID is not presented or corrupted ret=%d\n", nssid));
5627 			goto exit_proc;
5628 		}
5629 		else {
5630 
5631 			memset(iscan->iscan_ex_params_p, 0, iscan->iscan_ex_param_size);
5632 
5633 
5634 			wl_iw_iscan_prep(&iscan->iscan_ex_params_p->params, NULL);
5635 			iscan->iscan_ex_params_p->version = htod32(ISCAN_REQ_VERSION);
5636 			iscan->iscan_ex_params_p->action = htod16(WL_SCAN_ACTION_START);
5637 			iscan->iscan_ex_params_p->scan_duration = htod16(0);
5638 
5639 
5640 			while (tlv_size_left > 0)
5641 			{
5642 			type = str_ptr[0];
5643 			switch (type) {
5644 				case CSCAN_TLV_TYPE_CHANNEL_IE:
5645 
5646 					if ((nchan = wl_iw_parse_channel_list_tlv(&str_ptr, \
5647 					&iscan->iscan_ex_params_p->params.channel_list[0], \
5648 					WL_NUMCHANNELS, &tlv_size_left)) == -1) {
5649 					WL_ERROR(("%s missing channel list\n", \
5650 						 __FUNCTION__));
5651 						goto exit_proc;
5652 					}
5653 				break;
5654 				case CSCAN_TLV_TYPE_NPROBE_IE:
5655 					if ((res = wl_iw_parse_data_tlv(&str_ptr, \
5656 						&iscan->iscan_ex_params_p->params.nprobes, \
5657 						sizeof(iscan->iscan_ex_params_p->params.nprobes), \
5658 						type, sizeof(char), &tlv_size_left)) == -1) {
5659 						WL_ERROR(("%s return %d\n", \
5660 							__FUNCTION__, res));
5661 							goto exit_proc;
5662 					}
5663 				break;
5664 				case CSCAN_TLV_TYPE_ACTIVE_IE:
5665 					if ((res = wl_iw_parse_data_tlv(&str_ptr, \
5666 					&iscan->iscan_ex_params_p->params.active_time, \
5667 					sizeof(iscan->iscan_ex_params_p->params.active_time), \
5668 					type, sizeof(short), &tlv_size_left)) == -1) {
5669 						WL_ERROR(("%s return %d\n", \
5670 						__FUNCTION__, res));
5671 						goto exit_proc;
5672 					}
5673 				break;
5674 				case CSCAN_TLV_TYPE_PASSIVE_IE:
5675 					if ((res = wl_iw_parse_data_tlv(&str_ptr, \
5676 					&iscan->iscan_ex_params_p->params.passive_time, \
5677 					sizeof(iscan->iscan_ex_params_p->params.passive_time), \
5678 					type, sizeof(short), &tlv_size_left)) == -1) {
5679 						WL_ERROR(("%s return %d\n", \
5680 						__FUNCTION__, res));
5681 						goto exit_proc;
5682 					}
5683 				break;
5684 				case CSCAN_TLV_TYPE_HOME_IE:
5685 					if ((res = wl_iw_parse_data_tlv(&str_ptr, \
5686 					&iscan->iscan_ex_params_p->params.home_time, \
5687 					sizeof(iscan->iscan_ex_params_p->params.home_time), \
5688 					type, sizeof(short), &tlv_size_left)) == -1) {
5689 						WL_ERROR(("%s return %d\n", \
5690 						__FUNCTION__, res));
5691 						goto exit_proc;
5692 					}
5693 				break;
5694 				case CSCAN_TLV_TYPE_STYPE_IE:
5695 					if ((res = wl_iw_parse_data_tlv(&str_ptr, \
5696 					&iscan->iscan_ex_params_p->params.scan_type, \
5697 					sizeof(iscan->iscan_ex_params_p->params.scan_type), \
5698 					type, sizeof(char), &tlv_size_left)) == -1) {
5699 					WL_ERROR(("%s return %d\n", \
5700 						__FUNCTION__, res));
5701 						goto exit_proc;
5702 					}
5703 				break;
5704 
5705 				default :
5706 					WL_ERROR(("%s get unkwown type %X\n", \
5707 						__FUNCTION__, type));
5708 					goto exit_proc;
5709 				break;
5710 				}
5711 			}
5712 			}
5713 		}
5714 		else {
5715 			WL_ERROR(("%s get wrong TLV command\n", __FUNCTION__));
5716 			goto exit_proc;
5717 		}
5718 
5719 		if (g_first_broadcast_scan < BROADCAST_SCAN_FIRST_RESULT_CONSUMED) {
5720 			if (++g_first_counter_scans == MAX_ALLOWED_BLOCK_SCAN_FROM_FIRST_SCAN) {
5721 
5722 				WL_ERROR(("%s Clean up First scan flag which is %d\n", \
5723 						 __FUNCTION__, g_first_broadcast_scan));
5724 				g_first_broadcast_scan = BROADCAST_SCAN_FIRST_RESULT_CONSUMED;
5725 			}
5726 			else {
5727 				WL_ERROR(("%s Ignoring CSCAN : First Scan is not done yet %d\n", \
5728 						__FUNCTION__, g_first_counter_scans));
5729 				res = -EBUSY;
5730 				goto exit_proc;
5731 			}
5732 		}
5733 
5734 		res = wl_iw_combined_scan_set(dev, ssids_local, nssid, nchan);
5735 
5736 exit_proc:
5737 	net_os_wake_unlock(dev);
5738 	return res;
5739 }
5740 
5741 #endif
5742 
5743 #ifdef SOFTAP
5744 #ifndef AP_ONLY
5745 
5746 static int thr_wait_for_2nd_eth_dev(void *data)
5747 {
5748 	int ret = 0;
5749 
5750 	DAEMONIZE("wl0_eth_wthread");
5751 
5752 	WL_TRACE(("\n>%s threda started:, PID:%x\n", __FUNCTION__, current->pid));
5753 
5754 	if (down_timeout(&ap_eth_sema,  msecs_to_jiffies(5000)) != 0) {
5755 		WL_ERROR(("\n%s: sap_eth_sema timeout \n", __FUNCTION__));
5756 		ret = -1;
5757 		goto fail;
5758 	}
5759 
5760 	if (!ap_net_dev) {
5761 		WL_ERROR((" ap_net_dev is null !!!"));
5762 		ret = -1;
5763 		goto fail;
5764 	}
5765 
5766 	WL_TRACE(("\n>%s: Thread:'softap ethdev IF:%s is detected !!!'\n\n",
5767 		__FUNCTION__, ap_net_dev->name));
5768 
5769 	ap_cfg_running = TRUE;
5770 
5771 	bcm_mdelay(500);
5772 
5773 	wl_iw_send_priv_event(priv_dev, "AP_SET_CFG_OK");
5774 
5775 fail:
5776 	WL_TRACE(("\n>%s, thread completed\n", __FUNCTION__));
5777 
5778 	return ret;
5779 }
5780 #endif
5781 #ifndef AP_ONLY
5782 static int last_auto_channel = 6;
5783 #endif
5784 static int get_softap_auto_channel(struct net_device *dev, struct ap_profile *ap)
5785 {
5786 	int chosen = 0;
5787 	wl_uint32_list_t request;
5788 	int rescan = 0;
5789 	int retry = 0;
5790 	int updown = 0;
5791 	int ret = 0;
5792 	wlc_ssid_t null_ssid;
5793 	int res = 0;
5794 #ifndef AP_ONLY
5795 	int iolen = 0;
5796 	int mkvar_err = 0;
5797 	int bsscfg_index = 1;
5798 	char buf[WLC_IOCTL_SMLEN];
5799 #endif
5800 	WL_SOFTAP(("Enter %s\n", __FUNCTION__));
5801 
5802 #ifndef AP_ONLY
5803 	if (ap_cfg_running) {
5804 		ap->channel = last_auto_channel;
5805 		return res;
5806 	}
5807 #endif
5808 	memset(&null_ssid, 0, sizeof(wlc_ssid_t));
5809 	res |= dev_wlc_ioctl(dev, WLC_UP, &updown, sizeof(updown));
5810 #ifdef AP_ONLY
5811 	res |= dev_wlc_ioctl(dev, WLC_SET_SSID, &null_ssid, sizeof(null_ssid));
5812 #else
5813 	iolen = wl_bssiovar_mkbuf("ssid", bsscfg_index, (char *)(&null_ssid), \
5814 		null_ssid.SSID_len+4, buf, sizeof(buf), &mkvar_err);
5815 	ASSERT(iolen);
5816 	res |= dev_wlc_ioctl(dev, WLC_SET_VAR, buf, iolen);
5817 #endif
5818 	auto_channel_retry:
5819 			request.count = htod32(0);
5820 			ret = dev_wlc_ioctl(dev, WLC_START_CHANNEL_SEL, &request, sizeof(request));
5821 			if (ret < 0) {
5822 				WL_ERROR(("can't start auto channel scan\n"));
5823 				goto fail;
5824 			}
5825 
5826 	get_channel_retry:
5827 			bcm_mdelay(500);
5828 
5829 			ret = dev_wlc_ioctl(dev, WLC_GET_CHANNEL_SEL, &chosen, sizeof(chosen));
5830 			if (ret < 0 || dtoh32(chosen) == 0) {
5831 				if (retry++ < 3)
5832 					goto get_channel_retry;
5833 				else {
5834 					WL_ERROR(("can't get auto channel sel, err = %d, \
5835 						chosen = %d\n", ret, chosen));
5836 					goto fail;
5837 				}
5838 			}
5839 			if ((chosen == 1) && (!rescan++))
5840 				goto auto_channel_retry;
5841 			WL_SOFTAP(("Set auto channel = %d\n", chosen));
5842 			ap->channel = chosen;
5843 			if ((res = dev_wlc_ioctl(dev, WLC_DOWN, &updown, sizeof(updown))) < 0) {
5844 				WL_ERROR(("%s fail to set up err =%d\n", __FUNCTION__, res));
5845 				goto fail;
5846 			}
5847 #ifndef AP_ONLY
5848 	if (!res)
5849 		last_auto_channel = ap->channel;
5850 #endif
5851 
5852 fail :
5853 	return res;
5854 }
5855 
5856 
5857 static int set_ap_cfg(struct net_device *dev, struct ap_profile *ap)
5858 {
5859 	int updown = 0;
5860 	int channel = 0;
5861 
5862 	wlc_ssid_t ap_ssid;
5863 	int max_assoc = 8;
5864 
5865 	int res = 0;
5866 	int apsta_var = 0;
5867 #ifndef AP_ONLY
5868 	int mpc = 0;
5869 	int iolen = 0;
5870 	int mkvar_err = 0;
5871 	int bsscfg_index = 1;
5872 	char buf[WLC_IOCTL_SMLEN];
5873 #endif
5874 
5875 	if (!dev) {
5876 		WL_ERROR(("%s: dev is null\n", __FUNCTION__));
5877 		return -1;
5878 	}
5879 
5880 	net_os_wake_lock(dev);
5881 
5882 	WL_SOFTAP(("wl_iw: set ap profile:\n"));
5883 	WL_SOFTAP(("	ssid = '%s'\n", ap->ssid));
5884 	WL_SOFTAP(("	security = '%s'\n", ap->sec));
5885 	if (ap->key[0] != '\0')
5886 		WL_SOFTAP(("	key = '%s'\n", ap->key));
5887 	WL_SOFTAP(("	channel = %d\n", ap->channel));
5888 	WL_SOFTAP(("	max scb = %d\n", ap->max_scb));
5889 
5890 #ifdef AP_ONLY
5891 	if (ap_cfg_running) {
5892 		wl_iw_softap_deassoc_stations(dev);
5893 		ap_cfg_running = FALSE;
5894 	}
5895 #endif
5896 
5897 	if (ap_cfg_running == FALSE) {
5898 
5899 #ifndef AP_ONLY
5900 
5901 		sema_init(&ap_eth_sema, 0);
5902 
5903 		mpc = 0;
5904 		if ((res = dev_wlc_intvar_set(dev, "mpc", mpc))) {
5905 			WL_ERROR(("%s fail to set mpc\n", __FUNCTION__));
5906 			goto fail;
5907 		}
5908 #endif
5909 
5910 		updown = 0;
5911 		if ((res = dev_wlc_ioctl(dev, WLC_DOWN, &updown, sizeof(updown)))) {
5912 			WL_ERROR(("%s fail to set updown\n", __FUNCTION__));
5913 			goto fail;
5914 		}
5915 
5916 #ifdef AP_ONLY
5917 		apsta_var = 0;
5918 		if ((res = dev_wlc_ioctl(dev, WLC_SET_AP, &apsta_var, sizeof(apsta_var)))) {
5919 			WL_ERROR(("%s fail to set apsta_var 0\n", __FUNCTION__));
5920 			goto fail;
5921 		}
5922 		apsta_var = 1;
5923 		if ((res = dev_wlc_ioctl(dev, WLC_SET_AP, &apsta_var, sizeof(apsta_var)))) {
5924 			WL_ERROR(("%s fail to set apsta_var 1\n", __FUNCTION__));
5925 			goto fail;
5926 		}
5927 		res = dev_wlc_ioctl(dev, WLC_GET_AP, &apsta_var, sizeof(apsta_var));
5928 #else
5929 		apsta_var = 1;
5930 		iolen = wl_bssiovar_mkbuf("apsta",
5931 			bsscfg_index,  &apsta_var, sizeof(apsta_var)+4,
5932 			buf, sizeof(buf), &mkvar_err);
5933 		ASSERT(iolen);
5934 		if ((res = dev_wlc_ioctl(dev, WLC_SET_VAR, buf, iolen)) < 0) {
5935 			WL_ERROR(("%s fail to set apsta \n", __FUNCTION__));
5936 			goto fail;
5937 		}
5938 		WL_TRACE(("\n>in %s: apsta set result: %d \n", __FUNCTION__, res));
5939 #endif
5940 
5941 		updown = 1;
5942 		if ((res = dev_wlc_ioctl(dev, WLC_UP, &updown, sizeof(updown))) < 0) {
5943 			WL_ERROR(("%s fail to set apsta \n", __FUNCTION__));
5944 			goto fail;
5945 		}
5946 
5947 	} else {
5948 
5949 		if (!ap_net_dev) {
5950 			WL_ERROR(("%s: ap_net_dev is null\n", __FUNCTION__));
5951 			goto fail;
5952 		}
5953 
5954 		res = wl_iw_softap_deassoc_stations(ap_net_dev);
5955 
5956 
5957 		if ((res = dev_iw_write_cfg1_bss_var(dev, 0)) < 0) {
5958 			WL_ERROR(("%s fail to set bss down\n", __FUNCTION__));
5959 			goto fail;
5960 		}
5961 	}
5962 
5963 
5964 	if ((ap->channel == 0) && (get_softap_auto_channel(dev, ap) < 0)) {
5965 		ap->channel = 1;
5966 		WL_ERROR(("%s auto channel failed, pick up channel=%d\n", \
5967 			__FUNCTION__, ap->channel));
5968 	}
5969 
5970 	channel = ap->channel;
5971 	if ((res = dev_wlc_ioctl(dev, WLC_SET_CHANNEL, &channel, sizeof(channel)))) {
5972 			WL_ERROR(("%s fail to set channel\n", __FUNCTION__));
5973 			goto fail;
5974 	}
5975 
5976 	if (ap_cfg_running == FALSE) {
5977 		updown = 0;
5978 		if ((res = dev_wlc_ioctl(dev, WLC_UP, &updown, sizeof(updown)))) {
5979 			WL_ERROR(("%s fail to set up\n", __FUNCTION__));
5980 			goto fail;
5981 		}
5982 	}
5983 
5984 	max_assoc = ap->max_scb;
5985 	if ((res = dev_wlc_intvar_set(dev, "maxassoc", max_assoc))) {
5986 			WL_ERROR(("%s fail to set maxassoc\n", __FUNCTION__));
5987 			goto fail;
5988 	}
5989 
5990 	ap_ssid.SSID_len = strlen(ap->ssid);
5991 	strncpy(ap_ssid.SSID, ap->ssid, ap_ssid.SSID_len);
5992 
5993 #ifdef AP_ONLY
5994 	if ((res = wl_iw_set_ap_security(dev, &my_ap)) != 0) {
5995 		WL_ERROR(("ERROR:%d in:%s, wl_iw_set_ap_security is skipped\n", \
5996 		res, __FUNCTION__));
5997 		goto fail;
5998 	}
5999 	wl_iw_send_priv_event(dev, "ASCII_CMD=AP_BSS_START");
6000 	ap_cfg_running = TRUE;
6001 #else
6002 	iolen = wl_bssiovar_mkbuf("ssid", bsscfg_index, (char *)(&ap_ssid),
6003 		ap_ssid.SSID_len+4, buf, sizeof(buf), &mkvar_err);
6004 	ASSERT(iolen);
6005 	if ((res = dev_wlc_ioctl(dev, WLC_SET_VAR, buf, iolen)) != 0) {
6006 		WL_ERROR(("ERROR:%d in:%s, Security & BSS reconfiguration is skipped\n", \
6007 		res, __FUNCTION__));
6008 		goto fail;
6009 	}
6010 	if (ap_cfg_running == FALSE) {
6011 		kernel_thread(thr_wait_for_2nd_eth_dev, 0, 0);
6012 	} else {
6013 		if (ap_net_dev == NULL) {
6014 			WL_ERROR(("%s ERROR: ap_net_dev is NULL !!!\n", __FUNCTION__));
6015 			goto fail;
6016 		}
6017 
6018 		WL_ERROR(("%s: %s Configure security & restart AP bss \n", \
6019 			 __FUNCTION__, ap_net_dev->name));
6020 
6021 		if ((res = wl_iw_set_ap_security(ap_net_dev, &my_ap)) < 0) {
6022 			WL_ERROR(("%s fail to set security : %d\n", __FUNCTION__, res));
6023 			goto fail;
6024 		}
6025 
6026 		if ((res = dev_iw_write_cfg1_bss_var(dev, 1)) < 0) {
6027 			WL_ERROR(("%s fail to set bss up\n", __FUNCTION__));
6028 			goto fail;
6029 		}
6030 	}
6031 #endif
6032 fail:
6033 	WL_SOFTAP(("%s exit with %d\n", __FUNCTION__, res));
6034 
6035 	net_os_wake_unlock(dev);
6036 
6037 	return res;
6038 }
6039 
6040 
6041 static int wl_iw_set_ap_security(struct net_device *dev, struct ap_profile *ap)
6042 {
6043 	int wsec = 0;
6044 	int wpa_auth = 0;
6045 	int res = 0;
6046 	int i;
6047 	char *ptr;
6048 #ifdef AP_ONLY
6049 	int mpc = 0;
6050 	wlc_ssid_t ap_ssid;
6051 #endif
6052 	wl_wsec_key_t key;
6053 
6054 	WL_SOFTAP(("\nsetting SOFTAP security mode:\n"));
6055 	WL_SOFTAP(("wl_iw: set ap profile:\n"));
6056 	WL_SOFTAP(("	ssid = '%s'\n", ap->ssid));
6057 	WL_SOFTAP(("	security = '%s'\n", ap->sec));
6058 	if (ap->key[0] != '\0')
6059 		WL_SOFTAP(("	key = '%s'\n", ap->key));
6060 	WL_SOFTAP(("	channel = %d\n", ap->channel));
6061 	WL_SOFTAP(("	max scb = %d\n", ap->max_scb));
6062 
6063 	if (strnicmp(ap->sec, "open", strlen("open")) == 0) {
6064 		wsec = 0;
6065 		res = dev_wlc_intvar_set(dev, "wsec", wsec);
6066 		wpa_auth = WPA_AUTH_DISABLED;
6067 		res |= dev_wlc_intvar_set(dev, "wpa_auth", wpa_auth);
6068 
6069 		WL_SOFTAP(("=====================\n"));
6070 		WL_SOFTAP((" wsec & wpa_auth set 'OPEN', result:&d %d\n", res));
6071 		WL_SOFTAP(("=====================\n"));
6072 
6073 	} else if (strnicmp(ap->sec, "wep", strlen("wep")) == 0) {
6074 
6075 		memset(&key, 0, sizeof(key));
6076 
6077 		wsec = WEP_ENABLED;
6078 		res = dev_wlc_intvar_set(dev, "wsec", wsec);
6079 
6080 		key.index = 0;
6081 		if (wl_iw_parse_wep(ap->key, &key)) {
6082 			WL_SOFTAP(("wep key parse err!\n"));
6083 			return -1;
6084 		}
6085 
6086 		key.index = htod32(key.index);
6087 		key.len = htod32(key.len);
6088 		key.algo = htod32(key.algo);
6089 		key.flags = htod32(key.flags);
6090 
6091 		res |= dev_wlc_ioctl(dev, WLC_SET_KEY, &key, sizeof(key));
6092 
6093 		wpa_auth = WPA_AUTH_DISABLED;
6094 		res |= dev_wlc_intvar_set(dev, "wpa_auth", wpa_auth);
6095 
6096 		WL_SOFTAP(("=====================\n"));
6097 		WL_SOFTAP((" wsec & auth set 'WEP', result:&d %d\n", res));
6098 		WL_SOFTAP(("=====================\n"));
6099 
6100 	} else if (strnicmp(ap->sec, "wpa2-psk", strlen("wpa2-psk")) == 0) {
6101 		wsec_pmk_t psk;
6102 		size_t key_len;
6103 
6104 		wsec = AES_ENABLED;
6105 		dev_wlc_intvar_set(dev, "wsec", wsec);
6106 
6107 		key_len = strlen(ap->key);
6108 		if (key_len < WSEC_MIN_PSK_LEN || key_len > WSEC_MAX_PSK_LEN) {
6109 			WL_SOFTAP(("passphrase must be between %d and %d characters long\n",
6110 			WSEC_MIN_PSK_LEN, WSEC_MAX_PSK_LEN));
6111 			return -1;
6112 		}
6113 
6114 		if (key_len < WSEC_MAX_PSK_LEN) {
6115 			unsigned char output[2*SHA1HashSize];
6116 			char key_str_buf[WSEC_MAX_PSK_LEN+1];
6117 
6118 			memset(output, 0, sizeof(output));
6119 			pbkdf2_sha1(ap->key, ap->ssid, strlen(ap->ssid), 4096, output, 32);
6120 
6121 			ptr = key_str_buf;
6122 			for (i = 0; i < (WSEC_MAX_PSK_LEN/8); i++) {
6123 				sprintf(ptr, "%02x%02x%02x%02x", (uint)output[i*4], \
6124 					 (uint)output[i*4+1], (uint)output[i*4+2], \
6125 					 (uint)output[i*4+3]);
6126 				ptr += 8;
6127 			}
6128 			WL_SOFTAP(("%s: passphase = %s\n", __FUNCTION__, key_str_buf));
6129 
6130 			psk.key_len = htod16((ushort)WSEC_MAX_PSK_LEN);
6131 			memcpy(psk.key, key_str_buf, psk.key_len);
6132 		} else {
6133 			psk.key_len = htod16((ushort) key_len);
6134 			memcpy(psk.key, ap->key, key_len);
6135 		}
6136 		psk.flags = htod16(WSEC_PASSPHRASE);
6137 		dev_wlc_ioctl(dev, WLC_SET_WSEC_PMK, &psk, sizeof(psk));
6138 
6139 		wpa_auth = WPA2_AUTH_PSK;
6140 		dev_wlc_intvar_set(dev, "wpa_auth", wpa_auth);
6141 
6142 	} else if (strnicmp(ap->sec, "wpa-psk", strlen("wpa-psk")) == 0) {
6143 
6144 		wsec_pmk_t psk;
6145 		size_t key_len;
6146 
6147 		wsec = TKIP_ENABLED;
6148 		res = dev_wlc_intvar_set(dev, "wsec", wsec);
6149 
6150 		key_len = strlen(ap->key);
6151 		if (key_len < WSEC_MIN_PSK_LEN || key_len > WSEC_MAX_PSK_LEN) {
6152 			WL_SOFTAP(("passphrase must be between %d and %d characters long\n",
6153 			WSEC_MIN_PSK_LEN, WSEC_MAX_PSK_LEN));
6154 			return -1;
6155 		}
6156 
6157 		if (key_len < WSEC_MAX_PSK_LEN) {
6158 			unsigned char output[2*SHA1HashSize];
6159 			char key_str_buf[WSEC_MAX_PSK_LEN+1];
6160 
6161 			WL_SOFTAP(("%s: do passhash...\n", __FUNCTION__));
6162 
6163 			pbkdf2_sha1(ap->key, ap->ssid, strlen(ap->ssid), 4096, output, 32);
6164 
6165 			ptr = key_str_buf;
6166 			for (i = 0; i < (WSEC_MAX_PSK_LEN/8); i++) {
6167 				WL_SOFTAP(("[%02d]: %08x\n", i, *((unsigned int *)&output[i*4])));
6168 
6169 				sprintf(ptr, "%02x%02x%02x%02x", (uint)output[i*4],
6170 					(uint)output[i*4+1], (uint)output[i*4+2],
6171 					(uint)output[i*4+3]);
6172 				ptr += 8;
6173 			}
6174 			WL_SOFTAP(("%s: passphase = %s\n", __FUNCTION__, key_str_buf));
6175 
6176 			psk.key_len = htod16((ushort)WSEC_MAX_PSK_LEN);
6177 			memcpy(psk.key, key_str_buf, psk.key_len);
6178 		} else {
6179 			psk.key_len = htod16((ushort) key_len);
6180 			memcpy(psk.key, ap->key, key_len);
6181 		}
6182 
6183 		psk.flags = htod16(WSEC_PASSPHRASE);
6184 		res |= dev_wlc_ioctl(dev, WLC_SET_WSEC_PMK, &psk, sizeof(psk));
6185 
6186 		wpa_auth = WPA_AUTH_PSK;
6187 		res |= dev_wlc_intvar_set(dev, "wpa_auth", wpa_auth);
6188 
6189 		WL_SOFTAP((" wsec & auth set 'wpa-psk' (TKIP), result:&d %d\n", res));
6190 	}
6191 
6192 #ifdef AP_ONLY
6193 		ap_ssid.SSID_len = strlen(ap->ssid);
6194 		strncpy(ap_ssid.SSID, ap->ssid, ap_ssid.SSID_len);
6195 		res |= dev_wlc_ioctl(dev, WLC_SET_SSID, &ap_ssid, sizeof(ap_ssid));
6196 		mpc = 0;
6197 		res |= dev_wlc_intvar_set(dev, "mpc", mpc);
6198 		if (strnicmp(ap->sec, "wep", strlen("wep")) == 0) {
6199 			res |= dev_wlc_ioctl(dev, WLC_SET_KEY, &key, sizeof(key));
6200 		}
6201 #endif
6202 	return res;
6203 }
6204 
6205 
6206 
6207 int get_parmeter_from_string(
6208 			char **str_ptr, const char *token,
6209 			int param_type, void  *dst, int param_max_len)
6210 {
6211 	char int_str[7] = "0";
6212 	int parm_str_len;
6213 	char  *param_str_begin;
6214 	char  *param_str_end;
6215 	char  *orig_str = *str_ptr;
6216 
6217 	if ((*str_ptr) && !strncmp(*str_ptr, token, strlen(token))) {
6218 
6219 		strsep(str_ptr, "=,");
6220 		param_str_begin = *str_ptr;
6221 		strsep(str_ptr, "=,");
6222 
6223 		if (*str_ptr == NULL) {
6224 			parm_str_len = strlen(param_str_begin);
6225 		} else {
6226 			param_str_end = *str_ptr-1;
6227 			parm_str_len = param_str_end - param_str_begin;
6228 		}
6229 
6230 		WL_TRACE((" 'token:%s', len:%d, ", token, parm_str_len));
6231 
6232 		if (parm_str_len > param_max_len) {
6233 			WL_TRACE((" WARNING: extracted param len:%d is > MAX:%d\n",
6234 				parm_str_len, param_max_len));
6235 
6236 			parm_str_len = param_max_len;
6237 		}
6238 
6239 		switch (param_type) {
6240 
6241 		case PTYPE_INTDEC: {
6242 			int *pdst_int = dst;
6243 			char *eptr;
6244 
6245 			if (parm_str_len > sizeof(int_str))
6246 				 parm_str_len = sizeof(int_str);
6247 
6248 			memcpy(int_str, param_str_begin, parm_str_len);
6249 
6250 			*pdst_int = simple_strtoul(int_str, &eptr, 10);
6251 
6252 			WL_TRACE((" written as integer:%d\n",  *pdst_int));
6253 			}
6254 			break;
6255 		case PTYPE_STR_HEX: {
6256 			u8 *buf = dst;
6257 
6258 			param_max_len = param_max_len >> 1;
6259 			hstr_2_buf(param_str_begin, buf, param_max_len);
6260 			print_buf(buf, param_max_len, 0);
6261 			}
6262 			break;
6263 		default:
6264 			memcpy(dst, param_str_begin, parm_str_len);
6265 			*((char *)dst + parm_str_len) = 0;
6266 			WL_TRACE((" written as a string:%s\n", (char *)dst));
6267 			break;
6268 		}
6269 
6270 		return 0;
6271 	} else {
6272 		WL_ERROR(("\n %s: ERROR: can't find token:%s in str:%s \n",
6273 			__FUNCTION__, token, orig_str));
6274 
6275 		return -1;
6276 	}
6277 }
6278 
6279 
6280 static int wl_iw_softap_deassoc_stations(struct net_device *dev)
6281 {
6282 	int i;
6283 	int res = 0;
6284 	char mac_buf[128] = {0};
6285 	struct maclist *assoc_maclist = (struct maclist *)mac_buf;
6286 
6287 	memset(assoc_maclist, 0, sizeof(mac_buf));
6288 	assoc_maclist->count = 8;
6289 
6290 	res = dev_wlc_ioctl(dev, WLC_GET_ASSOCLIST, assoc_maclist, 128);
6291 	if (res != 0) {
6292 		WL_SOFTAP((" Error:%d in :%s, Couldn't get ASSOC List\n", res, __FUNCTION__));
6293 		return res;
6294 	}
6295 
6296 	if (assoc_maclist->count) {
6297 		for (i = 0; i < assoc_maclist->count; i++) {
6298 			scb_val_t scbval;
6299 
6300 			scbval.val = htod32(1);
6301 			bcopy(&assoc_maclist->ea[i], &scbval.ea, ETHER_ADDR_LEN);
6302 
6303 			WL_SOFTAP(("deauth STA:%d \n", i));
6304 			res |= dev_wlc_ioctl(dev, WLC_SCB_DEAUTHENTICATE_FOR_REASON,
6305 					&scbval, sizeof(scb_val_t));
6306 		}
6307 	} else {
6308 		WL_SOFTAP((" STA ASSOC list is empty\n"));
6309 	}
6310 
6311 	if (res != 0)
6312 		WL_SOFTAP((" Error:%d in :%s\n", res, __FUNCTION__));
6313 	else if (assoc_maclist->count) {
6314 
6315 		bcm_mdelay(200);
6316 	}
6317 	return res;
6318 }
6319 
6320 
6321 static int iwpriv_softap_stop(struct net_device *dev,
6322 	struct iw_request_info *info,
6323 	union iwreq_data *wrqu,
6324 	char *ext)
6325 {
6326 	int res = 0;
6327 
6328 	WL_SOFTAP(("got iwpriv AP_BSS_STOP\n"));
6329 
6330 	if ((!dev) && (!ap_net_dev)) {
6331 		WL_ERROR(("%s: dev is null\n", __FUNCTION__));
6332 		return res;
6333 	}
6334 
6335 	net_os_wake_lock(dev);
6336 
6337 	if ((ap_cfg_running == TRUE)) {
6338 #ifdef AP_ONLY
6339 		 wl_iw_softap_deassoc_stations(dev);
6340 #else
6341 		 wl_iw_softap_deassoc_stations(ap_net_dev);
6342 
6343 		if ((res = dev_iw_write_cfg1_bss_var(dev, 2)) < 0)
6344 			WL_ERROR(("%s failed to del BSS err = %d", __FUNCTION__, res));
6345 #endif
6346 
6347 		bcm_mdelay(100);
6348 
6349 		wrqu->data.length = 0;
6350 		ap_cfg_running = FALSE;
6351 	}
6352 	else
6353 		WL_ERROR(("%s: was called when SoftAP is OFF : move on\n", __FUNCTION__));
6354 
6355 	WL_SOFTAP(("%s Done with %d\n", __FUNCTION__, res));
6356 
6357 	net_os_wake_unlock(dev);
6358 
6359 	return res;
6360 }
6361 
6362 
6363 static int iwpriv_fw_reload(struct net_device *dev,
6364 		struct iw_request_info *info,
6365 		union iwreq_data *wrqu,
6366 		char *ext)
6367 {
6368 	int ret = -1;
6369 	char extra[256];
6370 	char *fwstr = fw_path;
6371 
6372 	WL_SOFTAP(("current firmware_path[]=%s\n", fwstr));
6373 
6374 	WL_TRACE((">Got FW_RELOAD cmd:"
6375 				"info->cmd:%x, info->flags:%x, u.data:%p, u.len:%d, \
6376 				fw_path:%p, len:%d \n",
6377 				info->cmd, info->flags,
6378 				wrqu->data.pointer, wrqu->data.length, fwstr, strlen(fwstr)));
6379 
6380 	if ((wrqu->data.length > 4) && (wrqu->data.length < sizeof(extra))) {
6381 
6382 		char *str_ptr;
6383 
6384 		if (copy_from_user(extra, wrqu->data.pointer, wrqu->data.length)) {
6385 			ret = -EFAULT;
6386 			goto exit_proc;
6387 		}
6388 
6389 		extra[wrqu->data.length] = 8;
6390 		str_ptr = extra;
6391 
6392 		if (get_parmeter_from_string(&str_ptr, "FW_PATH=", PTYPE_STRING, fwstr, 255) != 0) {
6393 			WL_ERROR(("Error: extracting FW_PATH='' string\n"));
6394 			goto exit_proc;
6395 		}
6396 
6397 		if (strstr(fwstr, "apsta") != NULL) {
6398 			WL_SOFTAP(("GOT APSTA FIRMWARE\n"));
6399 			ap_fw_loaded = TRUE;
6400 		} else {
6401 			WL_SOFTAP(("GOT STA FIRMWARE\n"));
6402 			ap_fw_loaded = FALSE;
6403 		}
6404 
6405 		WL_SOFTAP(("SET firmware_path[]=%s , str_p:%p\n", fwstr, fwstr));
6406 		ret = 0;
6407 	} else {
6408 		WL_ERROR(("Error: ivalid param len:%d\n", wrqu->data.length));
6409 	}
6410 
6411 exit_proc:
6412 	return ret;
6413 }
6414 #endif
6415 
6416 #ifdef SOFTAP
6417 static int iwpriv_wpasupp_loop_tst(struct net_device *dev,
6418 		struct iw_request_info *info,
6419 		union iwreq_data *wrqu,
6420 		char *ext)
6421 {
6422 	int res = 0;
6423 	char  *params = NULL;
6424 
6425 	WL_TRACE((">Got IWPRIV  wp_supp loopback cmd test:"
6426 				"info->cmd:%x, info->flags:%x, u.data:%p, u.len:%d\n",
6427 				info->cmd, info->flags,
6428 				wrqu->data.pointer, wrqu->data.length));
6429 
6430 	if (wrqu->data.length != 0) {
6431 
6432 		if (!(params = kmalloc(wrqu->data.length+1, GFP_KERNEL)))
6433 			return -ENOMEM;
6434 
6435 		if (copy_from_user(params, wrqu->data.pointer, wrqu->data.length)) {
6436 			kfree(params);
6437 			return -EFAULT;
6438 		}
6439 
6440 		params[wrqu->data.length] = 0;
6441 		WL_SOFTAP(("\n>> copied from user:\n %s\n", params));
6442 	} else {
6443 		WL_ERROR(("ERROR param length is 0\n"));
6444 		return -EFAULT;
6445 	}
6446 
6447 	res = wl_iw_send_priv_event(dev, params);
6448 	kfree(params);
6449 
6450 	return res;
6451 }
6452 #endif
6453 
6454 
6455 static int
6456 iwpriv_en_ap_bss(
6457 		struct net_device *dev,
6458 		struct iw_request_info *info,
6459 		void *wrqu,
6460 		char *extra)
6461 {
6462 	int res = 0;
6463 
6464 	if (!dev) {
6465 		WL_ERROR(("%s: dev is null\n", __FUNCTION__));
6466 		return -1;
6467 	}
6468 
6469 	net_os_wake_lock(dev);
6470 
6471 	WL_TRACE(("%s: rcvd IWPRIV IOCTL:  for dev:%s\n", __FUNCTION__, dev->name));
6472 
6473 #ifndef AP_ONLY
6474 	if ((res = wl_iw_set_ap_security(dev, &my_ap)) != 0) {
6475 		WL_ERROR((" %s ERROR setting SOFTAP security in :%d\n", __FUNCTION__, res));
6476 	}
6477 	else {
6478 		if ((res = dev_iw_write_cfg1_bss_var(dev, 1)) < 0)
6479 			WL_ERROR(("%s fail to set bss up err=%d\n", __FUNCTION__, res));
6480 		else
6481 			bcm_mdelay(100);
6482 	}
6483 
6484 #endif
6485 	WL_SOFTAP(("%s done with res %d \n", __FUNCTION__, res));
6486 
6487 	net_os_wake_unlock(dev);
6488 
6489 	return res;
6490 }
6491 
6492 static int
6493 get_assoc_sta_list(struct net_device *dev, char *buf, int len)
6494 {
6495 	WL_TRACE(("calling dev_wlc_ioctl(dev:%p, cmd:%d, buf:%p, len:%d)\n",
6496 		dev, WLC_GET_ASSOCLIST, buf, len));
6497 
6498 	dev_wlc_ioctl(dev, WLC_GET_ASSOCLIST, buf, len);
6499 
6500 	return 0;
6501 }
6502 
6503 
6504 static int
6505 set_ap_mac_list(struct net_device *dev, char *buf)
6506 {
6507 	struct mac_list_set *mac_list_set = (struct mac_list_set *)buf;
6508 	struct maclist *white_maclist = (struct maclist *)&mac_list_set->white_list;
6509 	struct maclist *black_maclist = (struct maclist *)&mac_list_set->black_list;
6510 	int mac_mode = mac_list_set->mode;
6511 	int length;
6512 	int i;
6513 
6514 	ap_macmode = mac_mode;
6515 	if (mac_mode == MACLIST_MODE_DISABLED) {
6516 
6517 		bzero(&ap_black_list, sizeof(struct mflist));
6518 
6519 		dev_wlc_ioctl(dev, WLC_SET_MACMODE, &mac_mode, sizeof(mac_mode));
6520 	} else {
6521 		scb_val_t scbval;
6522 		char mac_buf[256] = {0};
6523 		struct maclist *assoc_maclist = (struct maclist *) mac_buf;
6524 
6525 		mac_mode = MACLIST_MODE_ALLOW;
6526 
6527 		dev_wlc_ioctl(dev, WLC_SET_MACMODE, &mac_mode, sizeof(mac_mode));
6528 
6529 		length = sizeof(white_maclist->count)+white_maclist->count*ETHER_ADDR_LEN;
6530 		dev_wlc_ioctl(dev, WLC_SET_MACLIST, white_maclist, length);
6531 		WL_SOFTAP(("White List, length %d:\n", length));
6532 		for (i = 0; i < white_maclist->count; i++)
6533 			WL_SOFTAP(("mac %d: %02X:%02X:%02X:%02X:%02X:%02X\n",
6534 				i, white_maclist->ea[i].octet[0], white_maclist->ea[i].octet[1],
6535 				white_maclist->ea[i].octet[2],
6536 				white_maclist->ea[i].octet[3], white_maclist->ea[i].octet[4],
6537 				white_maclist->ea[i].octet[5]));
6538 
6539 		bcopy(black_maclist, &ap_black_list, sizeof(ap_black_list));
6540 
6541 		WL_SOFTAP(("Black List, size %d:\n", sizeof(ap_black_list)));
6542 		for (i = 0; i < ap_black_list.count; i++)
6543 			WL_SOFTAP(("mac %d: %02X:%02X:%02X:%02X:%02X:%02X\n",
6544 				i, ap_black_list.ea[i].octet[0], ap_black_list.ea[i].octet[1],
6545 				ap_black_list.ea[i].octet[2],
6546 				ap_black_list.ea[i].octet[3],
6547 				ap_black_list.ea[i].octet[4], ap_black_list.ea[i].octet[5]));
6548 
6549 		dev_wlc_ioctl(dev, WLC_GET_ASSOCLIST, assoc_maclist, 256);
6550 		if (assoc_maclist->count) {
6551 			int j;
6552 			for (i = 0; i < assoc_maclist->count; i++) {
6553 				for (j = 0; j < white_maclist->count; j++) {
6554 					if (!bcmp(&assoc_maclist->ea[i], &white_maclist->ea[j],
6555 						ETHER_ADDR_LEN)) {
6556 						WL_SOFTAP(("match allow, let it be\n"));
6557 						break;
6558 					}
6559 				}
6560 				if (j == white_maclist->count) {
6561 						WL_SOFTAP(("match black, deauth it\n"));
6562 						scbval.val = htod32(1);
6563 						bcopy(&assoc_maclist->ea[i], &scbval.ea,
6564 							ETHER_ADDR_LEN);
6565 						dev_wlc_ioctl(dev,
6566 							WLC_SCB_DEAUTHENTICATE_FOR_REASON, &scbval,
6567 							sizeof(scb_val_t));
6568 				}
6569 			}
6570 		}
6571 	}
6572 	return 0;
6573 }
6574 #endif
6575 
6576 
6577 #ifdef SOFTAP
6578 int set_macfilt_from_string(struct mflist *pmflist, char **param_str)
6579 {
6580 	return 0;
6581 }
6582 #endif
6583 
6584 
6585 #ifdef SOFTAP
6586 #define PARAM_OFFSET PROFILE_OFFSET
6587 
6588 int wl_iw_process_private_ascii_cmd(
6589 			struct net_device *dev,
6590 			struct iw_request_info *info,
6591 			union iwreq_data *dwrq,
6592 			char *cmd_str)
6593 {
6594 	int ret = 0;
6595 	char *sub_cmd = cmd_str + PROFILE_OFFSET + strlen("ASCII_CMD=");
6596 
6597 	WL_SOFTAP(("\n %s: ASCII_CMD: offs_0:%s, offset_32:\n'%s'\n",
6598 		__FUNCTION__, cmd_str, cmd_str + PROFILE_OFFSET));
6599 
6600 	if (strnicmp(sub_cmd, "AP_CFG", strlen("AP_CFG")) == 0) {
6601 
6602 		WL_SOFTAP((" AP_CFG \n"));
6603 
6604 
6605 		if (init_ap_profile_from_string(cmd_str+PROFILE_OFFSET, &my_ap) != 0) {
6606 			WL_ERROR(("ERROR: SoftAP CFG prams !\n"));
6607 			ret = -1;
6608 		} else {
6609 			ret = set_ap_cfg(dev, &my_ap);
6610 		}
6611 
6612 	} else if (strnicmp(sub_cmd, "AP_BSS_START", strlen("AP_BSS_START")) == 0) {
6613 
6614 		WL_SOFTAP(("\n SOFTAP - ENABLE BSS \n"));
6615 
6616 		WL_SOFTAP(("\n!!! got 'WL_AP_EN_BSS' from WPA supplicant, dev:%s\n", dev->name));
6617 
6618 #ifndef AP_ONLY
6619 		if (ap_net_dev == NULL) {
6620 			printf("\n ERROR: SOFTAP net_dev* is NULL !!!\n");
6621 		} else {
6622 			if ((ret = iwpriv_en_ap_bss(ap_net_dev, info, dwrq, cmd_str)) < 0)
6623 				WL_ERROR(("%s line %d fail to set bss up\n", \
6624 					__FUNCTION__, __LINE__));
6625 		}
6626 #else
6627 		if ((ret = iwpriv_en_ap_bss(dev, info, dwrq, cmd_str)) < 0)
6628 				WL_ERROR(("%s line %d fail to set bss up\n", \
6629 					__FUNCTION__, __LINE__));
6630 #endif
6631 	} else if (strnicmp(sub_cmd, "ASSOC_LST", strlen("ASSOC_LST")) == 0) {
6632 		/* no code yet */
6633 	} else if (strnicmp(sub_cmd, "AP_BSS_STOP", strlen("AP_BSS_STOP")) == 0) {
6634 		WL_SOFTAP((" \n temp DOWN SOFTAP\n"));
6635 #ifndef AP_ONLY
6636 		if ((ret = dev_iw_write_cfg1_bss_var(dev, 0)) < 0) {
6637 				WL_ERROR(("%s line %d fail to set bss down\n", \
6638 					__FUNCTION__, __LINE__));
6639 		}
6640 #endif
6641 	}
6642 
6643 	return ret;
6644 }
6645 #endif
6646 
6647 static int wl_iw_set_priv(
6648 	struct net_device *dev,
6649 	struct iw_request_info *info,
6650 	struct iw_point *dwrq,
6651 	char *ext
6652 )
6653 {
6654 	int ret = 0;
6655 	char * extra;
6656 
6657 	if (!(extra = kmalloc(dwrq->length, GFP_KERNEL)))
6658 	    return -ENOMEM;
6659 
6660 	if (copy_from_user(extra, dwrq->pointer, dwrq->length)) {
6661 	    kfree(extra);
6662 	    return -EFAULT;
6663 	}
6664 
6665 	WL_TRACE(("%s: SIOCSIWPRIV request %s, info->cmd:%x, info->flags:%d\n dwrq->length:%d",
6666 		dev->name, extra, info->cmd, info->flags, dwrq->length));
6667 
6668 	net_os_wake_lock(dev);
6669 
6670 	if (dwrq->length && extra) {
6671 		if (strnicmp(extra, "START", strlen("START")) == 0) {
6672 			wl_iw_control_wl_on(dev, info);
6673 			WL_TRACE(("%s, Received regular START command\n", __FUNCTION__));
6674 		}
6675 
6676 		if (g_onoff == G_WLAN_SET_OFF) {
6677 			WL_TRACE(("%s, missing START, Fail\n", __FUNCTION__));
6678 			kfree(extra);
6679 			net_os_wake_unlock(dev);
6680 			return -EFAULT;
6681 		}
6682 
6683 		if (strnicmp(extra, "SCAN-ACTIVE", strlen("SCAN-ACTIVE")) == 0) {
6684 #ifdef ENABLE_ACTIVE_PASSIVE_SCAN_SUPPRESS
6685 			WL_TRACE(("%s: active scan setting suppressed\n", dev->name));
6686 #else
6687 			ret = wl_iw_set_active_scan(dev, info, (union iwreq_data *)dwrq, extra);
6688 #endif
6689 		} else if (strnicmp(extra, "SCAN-PASSIVE", strlen("SCAN-PASSIVE")) == 0)
6690 #ifdef ENABLE_ACTIVE_PASSIVE_SCAN_SUPPRESS
6691 			WL_TRACE(("%s: passive scan setting suppressed\n", dev->name));
6692 #else
6693 			ret = wl_iw_set_passive_scan(dev, info, (union iwreq_data *)dwrq, extra);
6694 #endif
6695 		else if (strnicmp(extra, "RSSI", strlen("RSSI")) == 0)
6696 			ret = wl_iw_get_rssi(dev, info, (union iwreq_data *)dwrq, extra);
6697 		else if (strnicmp(extra, "LINKSPEED", strlen("LINKSPEED")) == 0)
6698 			ret = wl_iw_get_link_speed(dev, info, (union iwreq_data *)dwrq, extra);
6699 		else if (strnicmp(extra, "MACADDR", strlen("MACADDR")) == 0)
6700 			ret = wl_iw_get_macaddr(dev, info, (union iwreq_data *)dwrq, extra);
6701 		else if (strnicmp(extra, "COUNTRY", strlen("COUNTRY")) == 0)
6702 			ret = wl_iw_set_country(dev, info, (union iwreq_data *)dwrq, extra);
6703 		else if (strnicmp(extra, "STOP", strlen("STOP")) == 0)
6704 			ret = wl_iw_control_wl_off(dev, info);
6705 	    else if (strnicmp(extra, BAND_GET_CMD, strlen(BAND_GET_CMD)) == 0)
6706 			ret = wl_iw_get_band(dev, info, (union iwreq_data *)dwrq, extra);
6707 	    else if (strnicmp(extra, BAND_SET_CMD, strlen(BAND_SET_CMD)) == 0)
6708 			ret = wl_iw_set_band(dev, info, (union iwreq_data *)dwrq, extra);
6709 	    else if (strnicmp(extra, DTIM_SKIP_GET_CMD, strlen(DTIM_SKIP_GET_CMD)) == 0)
6710 			ret = wl_iw_get_dtim_skip(dev, info, (union iwreq_data *)dwrq, extra);
6711 	    else if (strnicmp(extra, DTIM_SKIP_SET_CMD, strlen(DTIM_SKIP_SET_CMD)) == 0)
6712 			ret = wl_iw_set_dtim_skip(dev, info, (union iwreq_data *)dwrq, extra);
6713 	    else if (strnicmp(extra, SETSUSPEND_CMD, strlen(SETSUSPEND_CMD)) == 0)
6714 			ret = wl_iw_set_suspend(dev, info, (union iwreq_data *)dwrq, extra);
6715 #if defined(PNO_SUPPORT)
6716 	    else if (strnicmp(extra, PNOSSIDCLR_SET_CMD, strlen(PNOSSIDCLR_SET_CMD)) == 0)
6717 			ret = wl_iw_set_pno_reset(dev, info, (union iwreq_data *)dwrq, extra);
6718 	    else if (strnicmp(extra, PNOSETUP_SET_CMD, strlen(PNOSETUP_SET_CMD)) == 0)
6719 			ret = wl_iw_set_pno_set(dev, info, (union iwreq_data *)dwrq, extra);
6720 	    else if (strnicmp(extra, PNOENABLE_SET_CMD, strlen(PNOENABLE_SET_CMD)) == 0)
6721 			ret = wl_iw_set_pno_enable(dev, info, (union iwreq_data *)dwrq, extra);
6722 #endif
6723 #if defined(CSCAN)
6724 	    else if (strnicmp(extra, CSCAN_COMMAND, strlen(CSCAN_COMMAND)) == 0)
6725 			ret = wl_iw_set_cscan(dev, info, (union iwreq_data *)dwrq, extra);
6726 #endif
6727 #ifdef CUSTOMER_HW2
6728 		else if (strnicmp(extra, "POWERMODE", strlen("POWERMODE")) == 0)
6729 			ret = wl_iw_set_power_mode(dev, info, (union iwreq_data *)dwrq, extra);
6730 		else if (strnicmp(extra, "BTCOEXMODE", strlen("BTCOEXMODE")) == 0)
6731 			ret = wl_iw_set_btcoex_dhcp(dev, info, (union iwreq_data *)dwrq, extra);
6732 #else
6733 		else if (strnicmp(extra, "POWERMODE", strlen("POWERMODE")) == 0)
6734 			ret = wl_iw_set_btcoex_dhcp(dev, info, (union iwreq_data *)dwrq, extra);
6735 #endif
6736 		else if (strnicmp(extra, "GETPOWER", strlen("GETPOWER")) == 0)
6737 			ret = wl_iw_get_power_mode(dev, info, (union iwreq_data *)dwrq, extra);
6738 #ifdef SOFTAP
6739 		else if (strnicmp(extra, "ASCII_CMD", strlen("ASCII_CMD")) == 0) {
6740 			wl_iw_process_private_ascii_cmd(dev, info, (union iwreq_data *)dwrq, extra);
6741 		} else if (strnicmp(extra, "AP_MAC_LIST_SET", strlen("AP_MAC_LIST_SET")) == 0) {
6742 			WL_SOFTAP(("penguin, set AP_MAC_LIST_SET\n"));
6743 			set_ap_mac_list(dev, (extra + PROFILE_OFFSET));
6744 		}
6745 #endif
6746 		else {
6747 			WL_TRACE(("Unknown PRIVATE command: %s: ignored\n", extra));
6748 			snprintf(extra, MAX_WX_STRING, "OK");
6749 			dwrq->length = strlen("OK") + 1;
6750 		}
6751 	}
6752 
6753 	net_os_wake_unlock(dev);
6754 
6755 	if (extra) {
6756 		if (copy_to_user(dwrq->pointer, extra, dwrq->length)) {
6757 			kfree(extra);
6758 			return -EFAULT;
6759 		}
6760 
6761 		kfree(extra);
6762 	}
6763 
6764 	return ret;
6765 }
6766 
6767 static const iw_handler wl_iw_handler[] =
6768 {
6769 	(iw_handler) wl_iw_config_commit,
6770 	(iw_handler) wl_iw_get_name,
6771 	(iw_handler) NULL,
6772 	(iw_handler) NULL,
6773 	(iw_handler) wl_iw_set_freq,
6774 	(iw_handler) wl_iw_get_freq,
6775 	(iw_handler) wl_iw_set_mode,
6776 	(iw_handler) wl_iw_get_mode,
6777 	(iw_handler) NULL,
6778 	(iw_handler) NULL,
6779 	(iw_handler) NULL,
6780 	(iw_handler) wl_iw_get_range,
6781 	(iw_handler) wl_iw_set_priv,
6782 	(iw_handler) NULL,
6783 	(iw_handler) NULL,
6784 	(iw_handler) NULL,
6785 	(iw_handler) wl_iw_set_spy,
6786 	(iw_handler) wl_iw_get_spy,
6787 	(iw_handler) NULL,
6788 	(iw_handler) NULL,
6789 	(iw_handler) wl_iw_set_wap,
6790 	(iw_handler) wl_iw_get_wap,
6791 #if WIRELESS_EXT > 17
6792 	(iw_handler) wl_iw_mlme,
6793 #else
6794 	(iw_handler) NULL,
6795 #endif
6796 #if defined(WL_IW_USE_ISCAN)
6797 	(iw_handler) wl_iw_iscan_get_aplist,
6798 #else
6799 	(iw_handler) wl_iw_get_aplist,
6800 #endif
6801 #if WIRELESS_EXT > 13
6802 #if defined(WL_IW_USE_ISCAN)
6803 	(iw_handler) wl_iw_iscan_set_scan,
6804 	(iw_handler) wl_iw_iscan_get_scan,
6805 #else
6806 	(iw_handler) wl_iw_set_scan,
6807 	(iw_handler) wl_iw_get_scan,
6808 #endif
6809 #else
6810 	(iw_handler) NULL,
6811 	(iw_handler) NULL,
6812 #endif
6813 	(iw_handler) wl_iw_set_essid,
6814 	(iw_handler) wl_iw_get_essid,
6815 	(iw_handler) wl_iw_set_nick,
6816 	(iw_handler) wl_iw_get_nick,
6817 	(iw_handler) NULL,
6818 	(iw_handler) NULL,
6819 	(iw_handler) wl_iw_set_rate,
6820 	(iw_handler) wl_iw_get_rate,
6821 	(iw_handler) wl_iw_set_rts,
6822 	(iw_handler) wl_iw_get_rts,
6823 	(iw_handler) wl_iw_set_frag,
6824 	(iw_handler) wl_iw_get_frag,
6825 	(iw_handler) wl_iw_set_txpow,
6826 	(iw_handler) wl_iw_get_txpow,
6827 #if WIRELESS_EXT > 10
6828 	(iw_handler) wl_iw_set_retry,
6829 	(iw_handler) wl_iw_get_retry,
6830 #endif
6831 	(iw_handler) wl_iw_set_encode,
6832 	(iw_handler) wl_iw_get_encode,
6833 	(iw_handler) wl_iw_set_power,
6834 	(iw_handler) wl_iw_get_power,
6835 #if WIRELESS_EXT > 17
6836 	(iw_handler) NULL,
6837 	(iw_handler) NULL,
6838 	(iw_handler) wl_iw_set_wpaie,
6839 	(iw_handler) wl_iw_get_wpaie,
6840 	(iw_handler) wl_iw_set_wpaauth,
6841 	(iw_handler) wl_iw_get_wpaauth,
6842 	(iw_handler) wl_iw_set_encodeext,
6843 	(iw_handler) wl_iw_get_encodeext,
6844 #ifdef BCMWPA2
6845 	(iw_handler) wl_iw_set_pmksa,
6846 #endif
6847 #endif
6848 };
6849 
6850 #if WIRELESS_EXT > 12
6851 static const iw_handler wl_iw_priv_handler[] = {
6852 	NULL,
6853 	(iw_handler)wl_iw_set_active_scan,
6854 	NULL,
6855 	(iw_handler)wl_iw_get_rssi,
6856 	NULL,
6857 	(iw_handler)wl_iw_set_passive_scan,
6858 	NULL,
6859 	(iw_handler)wl_iw_get_link_speed,
6860 	NULL,
6861 	(iw_handler)wl_iw_get_macaddr,
6862 	NULL,
6863 	(iw_handler)wl_iw_control_wl_off,
6864 	NULL,
6865 	(iw_handler)wl_iw_control_wl_on,
6866 #ifdef SOFTAP
6867 	NULL,
6868 	(iw_handler)iwpriv_set_ap_config,
6869 
6870 	NULL,
6871 	(iw_handler)iwpriv_get_assoc_list,
6872 
6873 	NULL,
6874 	(iw_handler)iwpriv_set_mac_filters,
6875 
6876 	NULL,
6877 	(iw_handler)iwpriv_en_ap_bss,
6878 
6879 	NULL,
6880 	(iw_handler)iwpriv_wpasupp_loop_tst,
6881 
6882 	NULL,
6883 	(iw_handler)iwpriv_softap_stop,
6884 
6885 	NULL,
6886 	(iw_handler)iwpriv_fw_reload,
6887 #endif
6888 #if defined(CSCAN)
6889 
6890 	NULL,
6891 	(iw_handler)iwpriv_set_cscan
6892 #endif
6893 };
6894 
6895 static const struct iw_priv_args wl_iw_priv_args[] = {
6896 	{
6897 		WL_IW_SET_ACTIVE_SCAN,
6898 		0,
6899 		IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | MAX_WX_STRING,
6900 		"SCAN-ACTIVE"
6901 	},
6902 	{
6903 		WL_IW_GET_RSSI,
6904 		0,
6905 		IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | MAX_WX_STRING,
6906 		"RSSI"
6907 	},
6908 	{
6909 		WL_IW_SET_PASSIVE_SCAN,
6910 		0,
6911 		IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | MAX_WX_STRING,
6912 		"SCAN-PASSIVE"
6913 	},
6914 	{
6915 		WL_IW_GET_LINK_SPEED,
6916 		0,
6917 		IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | MAX_WX_STRING,
6918 		"LINKSPEED"
6919 	},
6920 	{
6921 		WL_IW_GET_CURR_MACADDR,
6922 		0,
6923 		IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | MAX_WX_STRING,
6924 		"Macaddr"
6925 	},
6926 	{
6927 		WL_IW_SET_STOP,
6928 		0,
6929 		IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | MAX_WX_STRING,
6930 		"STOP"
6931 	},
6932 	{
6933 		WL_IW_SET_START,
6934 		0,
6935 		IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | MAX_WX_STRING,
6936 		"START"
6937 	},
6938 
6939 #ifdef SOFTAP
6940 	{
6941 		WL_SET_AP_CFG,
6942 		IW_PRIV_TYPE_CHAR |  256,
6943 		0,
6944 		"AP_SET_CFG"
6945 	},
6946 
6947 	{
6948 		WL_AP_STA_LIST,
6949 		0,
6950 		IW_PRIV_TYPE_CHAR | 0,
6951 		"AP_GET_STA_LIST"
6952 	},
6953 
6954 	{
6955 		WL_AP_MAC_FLTR,
6956 		IW_PRIV_TYPE_CHAR | 256,
6957 		IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | 0,
6958 		"AP_SET_MAC_FLTR"
6959 	},
6960 
6961 	{
6962 		WL_AP_BSS_START,
6963 		0,
6964 		IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | MAX_WX_STRING,
6965 		"AP_BSS_START"
6966 	},
6967 
6968 	{
6969 		AP_LPB_CMD,
6970 		IW_PRIV_TYPE_CHAR | 256,
6971 		IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | 0,
6972 		"AP_LPB_CMD"
6973 	},
6974 
6975 	{
6976 		WL_AP_STOP,
6977 		IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | 0,
6978 		IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | 0,
6979 		"AP_BSS_STOP"
6980 	},
6981 
6982 	{
6983 		WL_FW_RELOAD,
6984 		IW_PRIV_TYPE_CHAR | 256,
6985 		IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | 0,
6986 		"WL_FW_RELOAD"
6987 	},
6988 #endif
6989 #if defined(CSCAN)
6990 	{
6991 		WL_COMBO_SCAN,
6992 		IW_PRIV_TYPE_CHAR | 1024,
6993 		0,
6994 		"CSCAN"
6995 	},
6996 #endif
6997 };
6998 
6999 const struct iw_handler_def wl_iw_handler_def =
7000 {
7001 	.num_standard = ARRAYSIZE(wl_iw_handler),
7002 	.standard = (iw_handler *) wl_iw_handler,
7003 	.num_private = ARRAYSIZE(wl_iw_priv_handler),
7004 	.num_private_args = ARRAY_SIZE(wl_iw_priv_args),
7005 	.private = (iw_handler *)wl_iw_priv_handler,
7006 	.private_args = (void *) wl_iw_priv_args,
7007 
7008 #if WIRELESS_EXT >= 19
7009 	get_wireless_stats: dhd_get_wireless_stats,
7010 #endif
7011 };
7012 #endif
7013 
7014 
7015 int wl_iw_ioctl(
7016 	struct net_device *dev,
7017 	struct ifreq *rq,
7018 	int cmd
7019 )
7020 {
7021 	struct iwreq *wrq = (struct iwreq *) rq;
7022 	struct iw_request_info info;
7023 	iw_handler handler;
7024 	char *extra = NULL;
7025 	int token_size = 1, max_tokens = 0, ret = 0;
7026 
7027 	net_os_wake_lock(dev);
7028 
7029 	WL_TRACE(("%s: cmd:%x alled via dhd->do_ioctl()entry point\n", __FUNCTION__, cmd));
7030 	if (cmd < SIOCIWFIRST ||
7031 		IW_IOCTL_IDX(cmd) >= ARRAYSIZE(wl_iw_handler) ||
7032 		!(handler = wl_iw_handler[IW_IOCTL_IDX(cmd)])) {
7033 			WL_ERROR(("%s: error in cmd=%x : not supported\n", __FUNCTION__, cmd));
7034 			net_os_wake_unlock(dev);
7035 			return -EOPNOTSUPP;
7036 	}
7037 
7038 	switch (cmd) {
7039 
7040 	case SIOCSIWESSID:
7041 	case SIOCGIWESSID:
7042 	case SIOCSIWNICKN:
7043 	case SIOCGIWNICKN:
7044 		max_tokens = IW_ESSID_MAX_SIZE + 1;
7045 		break;
7046 
7047 	case SIOCSIWENCODE:
7048 	case SIOCGIWENCODE:
7049 #if WIRELESS_EXT > 17
7050 	case SIOCSIWENCODEEXT:
7051 	case SIOCGIWENCODEEXT:
7052 #endif
7053 		max_tokens = wrq->u.data.length;
7054 		break;
7055 
7056 	case SIOCGIWRANGE:
7057 		max_tokens = sizeof(struct iw_range) + 500;
7058 		break;
7059 
7060 	case SIOCGIWAPLIST:
7061 		token_size = sizeof(struct sockaddr) + sizeof(struct iw_quality);
7062 		max_tokens = IW_MAX_AP;
7063 		break;
7064 
7065 #if WIRELESS_EXT > 13
7066 	case SIOCGIWSCAN:
7067 #if defined(WL_IW_USE_ISCAN)
7068 	if (g_iscan)
7069 		max_tokens = wrq->u.data.length;
7070 	else
7071 #endif
7072 		max_tokens = IW_SCAN_MAX_DATA;
7073 		break;
7074 #endif
7075 
7076 	case SIOCSIWSPY:
7077 		token_size = sizeof(struct sockaddr);
7078 		max_tokens = IW_MAX_SPY;
7079 		break;
7080 
7081 	case SIOCGIWSPY:
7082 		token_size = sizeof(struct sockaddr) + sizeof(struct iw_quality);
7083 		max_tokens = IW_MAX_SPY;
7084 		break;
7085 
7086 #if WIRELESS_EXT > 17
7087 	case SIOCSIWPMKSA:
7088 	case SIOCSIWGENIE:
7089 #endif
7090 	case SIOCSIWPRIV:
7091 		max_tokens = wrq->u.data.length;
7092 		break;
7093 	}
7094 
7095 	if (max_tokens && wrq->u.data.pointer) {
7096 		if (wrq->u.data.length > max_tokens) {
7097 			WL_ERROR(("%s: error in cmd=%x wrq->u.data.length=%d  > max_tokens=%d\n", \
7098 				__FUNCTION__, cmd, wrq->u.data.length, max_tokens));
7099 			ret = -E2BIG;
7100 			goto wl_iw_ioctl_done;
7101 		}
7102 		if (!(extra = kmalloc(max_tokens * token_size, GFP_KERNEL))) {
7103 			ret = -ENOMEM;
7104 			goto wl_iw_ioctl_done;
7105 		}
7106 
7107 		if (copy_from_user(extra, wrq->u.data.pointer, wrq->u.data.length * token_size)) {
7108 			kfree(extra);
7109 			ret = -EFAULT;
7110 			goto wl_iw_ioctl_done;
7111 		}
7112 	}
7113 
7114 	info.cmd = cmd;
7115 	info.flags = 0;
7116 
7117 	ret = handler(dev, &info, &wrq->u, extra);
7118 
7119 	if (extra) {
7120 		if (copy_to_user(wrq->u.data.pointer, extra, wrq->u.data.length * token_size)) {
7121 			kfree(extra);
7122 			ret = -EFAULT;
7123 			goto wl_iw_ioctl_done;
7124 		}
7125 
7126 		kfree(extra);
7127 	}
7128 
7129 wl_iw_ioctl_done:
7130 
7131 	net_os_wake_unlock(dev);
7132 
7133 	return ret;
7134 }
7135 
7136 
7137 bool
7138 wl_iw_conn_status_str(uint32 event_type, uint32 status, uint32 reason,
7139 	char* stringBuf, uint buflen)
7140 {
7141 	typedef struct conn_fail_event_map_t {
7142 		uint32 inEvent;
7143 		uint32 inStatus;
7144 		uint32 inReason;
7145 		const char* outName;
7146 		const char* outCause;
7147 	} conn_fail_event_map_t;
7148 
7149 
7150 #	define WL_IW_DONT_CARE	9999
7151 	const conn_fail_event_map_t event_map [] = {
7152 
7153 
7154 		{WLC_E_SET_SSID,     WLC_E_STATUS_SUCCESS,   WL_IW_DONT_CARE,
7155 		"Conn", "Success"},
7156 		{WLC_E_SET_SSID,     WLC_E_STATUS_NO_NETWORKS, WL_IW_DONT_CARE,
7157 		"Conn", "NoNetworks"},
7158 		{WLC_E_SET_SSID,     WLC_E_STATUS_FAIL,      WL_IW_DONT_CARE,
7159 		"Conn", "ConfigMismatch"},
7160 		{WLC_E_PRUNE,        WL_IW_DONT_CARE,        WLC_E_PRUNE_ENCR_MISMATCH,
7161 		"Conn", "EncrypMismatch"},
7162 		{WLC_E_PRUNE,        WL_IW_DONT_CARE,        WLC_E_RSN_MISMATCH,
7163 		"Conn", "RsnMismatch"},
7164 		{WLC_E_AUTH,         WLC_E_STATUS_TIMEOUT,   WL_IW_DONT_CARE,
7165 		"Conn", "AuthTimeout"},
7166 		{WLC_E_AUTH,         WLC_E_STATUS_FAIL,      WL_IW_DONT_CARE,
7167 		"Conn", "AuthFail"},
7168 		{WLC_E_AUTH,         WLC_E_STATUS_NO_ACK,    WL_IW_DONT_CARE,
7169 		"Conn", "AuthNoAck"},
7170 		{WLC_E_REASSOC,      WLC_E_STATUS_FAIL,      WL_IW_DONT_CARE,
7171 		"Conn", "ReassocFail"},
7172 		{WLC_E_REASSOC,      WLC_E_STATUS_TIMEOUT,   WL_IW_DONT_CARE,
7173 		"Conn", "ReassocTimeout"},
7174 		{WLC_E_REASSOC,      WLC_E_STATUS_ABORT,     WL_IW_DONT_CARE,
7175 		"Conn", "ReassocAbort"},
7176 		{WLC_E_PSK_SUP,      WLC_SUP_KEYED,          WL_IW_DONT_CARE,
7177 		"Sup", "ConnSuccess"},
7178 		{WLC_E_PSK_SUP,      WL_IW_DONT_CARE,        WL_IW_DONT_CARE,
7179 		"Sup", "WpaHandshakeFail"},
7180 		{WLC_E_DEAUTH_IND,   WL_IW_DONT_CARE,        WL_IW_DONT_CARE,
7181 		"Conn", "Deauth"},
7182 		{WLC_E_DISASSOC_IND, WL_IW_DONT_CARE,        WL_IW_DONT_CARE,
7183 		"Conn", "DisassocInd"},
7184 		{WLC_E_DISASSOC,     WL_IW_DONT_CARE,        WL_IW_DONT_CARE,
7185 		"Conn", "Disassoc"}
7186 	};
7187 
7188 	const char* name = "";
7189 	const char* cause = NULL;
7190 	int i;
7191 
7192 
7193 	for (i = 0;  i < sizeof(event_map)/sizeof(event_map[0]);  i++) {
7194 		const conn_fail_event_map_t* row = &event_map[i];
7195 		if (row->inEvent == event_type &&
7196 		    (row->inStatus == status || row->inStatus == WL_IW_DONT_CARE) &&
7197 		    (row->inReason == reason || row->inReason == WL_IW_DONT_CARE)) {
7198 			name = row->outName;
7199 			cause = row->outCause;
7200 			break;
7201 		}
7202 	}
7203 
7204 
7205 	if (cause) {
7206 		memset(stringBuf, 0, buflen);
7207 		snprintf(stringBuf, buflen, "%s %s %02d %02d",
7208 			name, cause, status, reason);
7209 		WL_INFORM(("Connection status: %s\n", stringBuf));
7210 		return TRUE;
7211 	} else {
7212 		return FALSE;
7213 	}
7214 }
7215 
7216 #if WIRELESS_EXT > 14
7217 
7218 static bool
7219 wl_iw_check_conn_fail(wl_event_msg_t *e, char* stringBuf, uint buflen)
7220 {
7221 	uint32 event = ntoh32(e->event_type);
7222 	uint32 status =  ntoh32(e->status);
7223 	uint32 reason =  ntoh32(e->reason);
7224 
7225 	if (wl_iw_conn_status_str(event, status, reason, stringBuf, buflen)) {
7226 		return TRUE;
7227 	}
7228 	else
7229 		return FALSE;
7230 }
7231 #endif
7232 
7233 #ifndef IW_CUSTOM_MAX
7234 #define IW_CUSTOM_MAX 256
7235 #endif
7236 
7237 void
7238 wl_iw_event(struct net_device *dev, wl_event_msg_t *e, void* data)
7239 {
7240 #if WIRELESS_EXT > 13
7241 	union iwreq_data wrqu;
7242 	char extra[IW_CUSTOM_MAX + 1];
7243 	int cmd = 0;
7244 	uint32 event_type = ntoh32(e->event_type);
7245 	uint16 flags =  ntoh16(e->flags);
7246 	uint32 datalen = ntoh32(e->datalen);
7247 	uint32 status =  ntoh32(e->status);
7248 	uint32 toto;
7249 	static uint32 roam_no_success = 0;
7250 	static bool roam_no_success_send = FALSE;
7251 
7252 	memset(&wrqu, 0, sizeof(wrqu));
7253 	memset(extra, 0, sizeof(extra));
7254 
7255 	if (!dev) {
7256 		WL_ERROR(("%s: dev is null\n", __FUNCTION__));
7257 		return;
7258 	}
7259 
7260 	net_os_wake_lock(dev);
7261 
7262 	WL_TRACE(("%s: dev=%s event=%d \n", __FUNCTION__, dev->name, event_type));
7263 
7264 	switch (event_type) {
7265 #if defined(SOFTAP)
7266 	case WLC_E_PRUNE:
7267 		if (ap_cfg_running) {
7268 			char *macaddr = (char *)&e->addr;
7269 			WL_SOFTAP(("PRUNE received, %02X:%02X:%02X:%02X:%02X:%02X!\n",
7270 				macaddr[0], macaddr[1], macaddr[2], macaddr[3], \
7271 				macaddr[4], macaddr[5]));
7272 
7273 			if (ap_macmode) {
7274 				int i;
7275 				for (i = 0; i < ap_black_list.count; i++) {
7276 					if (!bcmp(macaddr, &ap_black_list.ea[i], \
7277 						sizeof(struct ether_addr))) {
7278 						WL_SOFTAP(("mac in black list, ignore it\n"));
7279 						break;
7280 					}
7281 				}
7282 
7283 				if (i == ap_black_list.count) {
7284 					char mac_buf[32] = {0};
7285 					sprintf(mac_buf, "STA_BLOCK %02X:%02X:%02X:%02X:%02X:%02X",
7286 						macaddr[0], macaddr[1], macaddr[2],
7287 						macaddr[3], macaddr[4], macaddr[5]);
7288 					wl_iw_send_priv_event(priv_dev, mac_buf);
7289 				}
7290 			}
7291 		}
7292 		break;
7293 #endif
7294 	case WLC_E_TXFAIL:
7295 		cmd = IWEVTXDROP;
7296 		memcpy(wrqu.addr.sa_data, &e->addr, ETHER_ADDR_LEN);
7297 		wrqu.addr.sa_family = ARPHRD_ETHER;
7298 		break;
7299 #if WIRELESS_EXT > 14
7300 	case WLC_E_JOIN:
7301 	case WLC_E_ASSOC_IND:
7302 	case WLC_E_REASSOC_IND:
7303 #if defined(SOFTAP)
7304 		WL_SOFTAP(("STA connect received %d\n", event_type));
7305 		if (ap_cfg_running) {
7306 			wl_iw_send_priv_event(priv_dev, "STA_JOIN");
7307 			goto wl_iw_event_end;
7308 		}
7309 #endif
7310 		memcpy(wrqu.addr.sa_data, &e->addr, ETHER_ADDR_LEN);
7311 		wrqu.addr.sa_family = ARPHRD_ETHER;
7312 		cmd = IWEVREGISTERED;
7313 		break;
7314 	case WLC_E_ROAM:
7315 		if (status != WLC_E_STATUS_SUCCESS) {
7316 			roam_no_success++;
7317 			if ((roam_no_success == 3) && (roam_no_success_send == FALSE)) {
7318 
7319 				roam_no_success_send = TRUE;
7320 				bzero(wrqu.addr.sa_data, ETHER_ADDR_LEN);
7321 				bzero(&extra, ETHER_ADDR_LEN);
7322 				cmd = SIOCGIWAP;
7323 				WL_ERROR(("%s  ROAMING did not succeeded , send Link Down\n", \
7324 					__FUNCTION__));
7325 			} else {
7326 				WL_TRACE(("##### ROAMING did not succeeded %d\n", roam_no_success));
7327 				goto wl_iw_event_end;
7328 			}
7329 		} else {
7330 			memcpy(wrqu.addr.sa_data, &e->addr.octet, ETHER_ADDR_LEN);
7331 			wrqu.addr.sa_family = ARPHRD_ETHER;
7332 			cmd = SIOCGIWAP;
7333 		}
7334 		break;
7335 	case WLC_E_DEAUTH_IND:
7336 	case WLC_E_DISASSOC_IND:
7337 #if defined(SOFTAP)
7338 		WL_SOFTAP(("STA disconnect received %d\n", event_type));
7339 		if (ap_cfg_running) {
7340 			wl_iw_send_priv_event(priv_dev, "STA_LEAVE");
7341 			goto wl_iw_event_end;
7342 		}
7343 #endif
7344 		cmd = SIOCGIWAP;
7345 		bzero(wrqu.addr.sa_data, ETHER_ADDR_LEN);
7346 		wrqu.addr.sa_family = ARPHRD_ETHER;
7347 		bzero(&extra, ETHER_ADDR_LEN);
7348 		break;
7349 	case WLC_E_LINK:
7350 	case WLC_E_NDIS_LINK:
7351 		cmd = SIOCGIWAP;
7352 		if (!(flags & WLC_EVENT_MSG_LINK)) {
7353 #ifdef SOFTAP
7354 #ifdef AP_ONLY
7355 		if (ap_cfg_running) {
7356 #else
7357 		if (ap_cfg_running && !strncmp(dev->name, "wl0.1", 5)) {
7358 #endif
7359 				WL_SOFTAP(("AP DOWN %d\n", event_type));
7360 				wl_iw_send_priv_event(priv_dev, "AP_DOWN");
7361 			} else {
7362 				WL_TRACE(("STA_Link Down\n"));
7363 				g_ss_cache_ctrl.m_link_down = 1;
7364 			}
7365 #else
7366 			g_ss_cache_ctrl.m_link_down = 1;
7367 #endif
7368 			WL_TRACE(("Link Down\n"));
7369 
7370 			bzero(wrqu.addr.sa_data, ETHER_ADDR_LEN);
7371 			bzero(&extra, ETHER_ADDR_LEN);
7372 		}
7373 		else {
7374 			memcpy(wrqu.addr.sa_data, &e->addr, ETHER_ADDR_LEN);
7375 			g_ss_cache_ctrl.m_link_down = 0;
7376 
7377 			memcpy(g_ss_cache_ctrl.m_active_bssid, &e->addr, ETHER_ADDR_LEN);
7378 
7379 #ifdef SOFTAP
7380 #ifdef AP_ONLY
7381 			if (ap_cfg_running) {
7382 #else
7383 			if (ap_cfg_running && !strncmp(dev->name, "wl0.1", 5)) {
7384 #endif
7385 				WL_SOFTAP(("AP UP %d\n", event_type));
7386 				wl_iw_send_priv_event(priv_dev, "AP_UP");
7387 			} else {
7388 				WL_TRACE(("STA_LINK_UP\n"));
7389 				roam_no_success_send = FALSE;
7390 				roam_no_success = 0;
7391 			}
7392 #endif
7393 			WL_TRACE(("Link UP\n"));
7394 
7395 		}
7396 		net_os_wake_lock_timeout_enable(dev);
7397 		wrqu.addr.sa_family = ARPHRD_ETHER;
7398 		break;
7399 	case WLC_E_ACTION_FRAME:
7400 		cmd = IWEVCUSTOM;
7401 		if (datalen + 1 <= sizeof(extra)) {
7402 			wrqu.data.length = datalen + 1;
7403 			extra[0] = WLC_E_ACTION_FRAME;
7404 			memcpy(&extra[1], data, datalen);
7405 			WL_TRACE(("WLC_E_ACTION_FRAME len %d \n", wrqu.data.length));
7406 		}
7407 		break;
7408 
7409 	case WLC_E_ACTION_FRAME_COMPLETE:
7410 		cmd = IWEVCUSTOM;
7411 		memcpy(&toto, data, 4);
7412 		if (sizeof(status) + 1 <= sizeof(extra)) {
7413 			wrqu.data.length = sizeof(status) + 1;
7414 			extra[0] = WLC_E_ACTION_FRAME_COMPLETE;
7415 			memcpy(&extra[1], &status, sizeof(status));
7416 			printf("wl_iw_event status %d PacketId %d \n", status, toto);
7417 			printf("WLC_E_ACTION_FRAME_COMPLETE len %d \n", wrqu.data.length);
7418 		}
7419 		break;
7420 #endif
7421 #if WIRELESS_EXT > 17
7422 	case WLC_E_MIC_ERROR: {
7423 		struct	iw_michaelmicfailure  *micerrevt = (struct  iw_michaelmicfailure  *)&extra;
7424 		cmd = IWEVMICHAELMICFAILURE;
7425 		wrqu.data.length = sizeof(struct iw_michaelmicfailure);
7426 		if (flags & WLC_EVENT_MSG_GROUP)
7427 			micerrevt->flags |= IW_MICFAILURE_GROUP;
7428 		else
7429 			micerrevt->flags |= IW_MICFAILURE_PAIRWISE;
7430 		memcpy(micerrevt->src_addr.sa_data, &e->addr, ETHER_ADDR_LEN);
7431 		micerrevt->src_addr.sa_family = ARPHRD_ETHER;
7432 
7433 		break;
7434 	}
7435 #ifdef BCMWPA2
7436 	case WLC_E_PMKID_CACHE: {
7437 		if (data)
7438 		{
7439 			struct iw_pmkid_cand *iwpmkidcand = (struct iw_pmkid_cand *)&extra;
7440 			pmkid_cand_list_t *pmkcandlist;
7441 			pmkid_cand_t	*pmkidcand;
7442 			int count;
7443 
7444 			cmd = IWEVPMKIDCAND;
7445 			pmkcandlist = data;
7446 			count = ntoh32_ua((uint8 *)&pmkcandlist->npmkid_cand);
7447 			ASSERT(count >= 0);
7448 			wrqu.data.length = sizeof(struct iw_pmkid_cand);
7449 			pmkidcand = pmkcandlist->pmkid_cand;
7450 			while (count) {
7451 				bzero(iwpmkidcand, sizeof(struct iw_pmkid_cand));
7452 				if (pmkidcand->preauth)
7453 					iwpmkidcand->flags |= IW_PMKID_CAND_PREAUTH;
7454 				bcopy(&pmkidcand->BSSID, &iwpmkidcand->bssid.sa_data,
7455 					ETHER_ADDR_LEN);
7456 #ifndef SANDGATE2G
7457 				wireless_send_event(dev, cmd, &wrqu, extra);
7458 #endif
7459 				pmkidcand++;
7460 				count--;
7461 			}
7462 		}
7463 		goto wl_iw_event_end;
7464 	}
7465 #endif
7466 #endif
7467 
7468 	case WLC_E_SCAN_COMPLETE:
7469 #if defined(WL_IW_USE_ISCAN)
7470 		if ((g_iscan) && (g_iscan->sysioc_pid >= 0) &&
7471 			(g_iscan->iscan_state != ISCAN_STATE_IDLE))
7472 		{
7473 			up(&g_iscan->sysioc_sem);
7474 		} else {
7475 			cmd = SIOCGIWSCAN;
7476 			wrqu.data.length = strlen(extra);
7477 			WL_TRACE(("Event WLC_E_SCAN_COMPLETE from specific scan %d\n", \
7478 				g_iscan->iscan_state));
7479 		}
7480 #else
7481 		cmd = SIOCGIWSCAN;
7482 		wrqu.data.length = strlen(extra);
7483 		WL_TRACE(("Event WLC_E_SCAN_COMPLETE\n"));
7484 #endif
7485 		break;
7486 
7487 	case WLC_E_PFN_NET_FOUND:
7488 	{
7489 		wlc_ssid_t	* ssid;
7490 		ssid = (wlc_ssid_t *)data;
7491 		WL_TRACE(("%s Event WLC_E_PFN_NET_FOUND, send %s up : find %s len=%d\n", \
7492 			__FUNCTION__, PNO_EVENT_UP, ssid->SSID, ssid->SSID_len));
7493 		net_os_wake_lock_timeout_enable(dev);
7494 		cmd = IWEVCUSTOM;
7495 		memset(&wrqu, 0, sizeof(wrqu));
7496 		strcpy(extra, PNO_EVENT_UP);
7497 		wrqu.data.length = strlen(extra);
7498 	}
7499 	break;
7500 
7501 	default:
7502 
7503 		WL_TRACE(("Unknown Event %d: ignoring\n", event_type));
7504 		break;
7505 	}
7506 #ifndef SANDGATE2G
7507 	if (cmd) {
7508 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 31))
7509 		if (cmd == SIOCGIWSCAN)
7510 			wireless_send_event(dev, cmd, &wrqu, NULL);
7511 		else
7512 #endif
7513 		wireless_send_event(dev, cmd, &wrqu, extra);
7514 	}
7515 #endif
7516 
7517 #if WIRELESS_EXT > 14
7518 
7519 	memset(extra, 0, sizeof(extra));
7520 	if (wl_iw_check_conn_fail(e, extra, sizeof(extra))) {
7521 		cmd = IWEVCUSTOM;
7522 		wrqu.data.length = strlen(extra);
7523 #ifndef SANDGATE2G
7524 		wireless_send_event(dev, cmd, &wrqu, extra);
7525 #endif
7526 	}
7527 #endif
7528 wl_iw_event_end:
7529 	net_os_wake_unlock(dev);
7530 #endif
7531 }
7532 
7533 int wl_iw_get_wireless_stats(struct net_device *dev, struct iw_statistics *wstats)
7534 {
7535 	int res = 0;
7536 	wl_cnt_t cnt;
7537 	int phy_noise;
7538 	int rssi;
7539 	scb_val_t scb_val;
7540 
7541 	phy_noise = 0;
7542 	if ((res = dev_wlc_ioctl(dev, WLC_GET_PHY_NOISE, &phy_noise, sizeof(phy_noise))))
7543 		goto done;
7544 
7545 	phy_noise = dtoh32(phy_noise);
7546 	WL_TRACE(("wl_iw_get_wireless_stats phy noise=%d\n", phy_noise));
7547 
7548 	bzero(&scb_val, sizeof(scb_val_t));
7549 	if ((res = dev_wlc_ioctl(dev, WLC_GET_RSSI, &scb_val, sizeof(scb_val_t))))
7550 		goto done;
7551 
7552 	rssi = dtoh32(scb_val.val);
7553 	WL_TRACE(("wl_iw_get_wireless_stats rssi=%d\n", rssi));
7554 	if (rssi <= WL_IW_RSSI_NO_SIGNAL)
7555 		wstats->qual.qual = 0;
7556 	else if (rssi <= WL_IW_RSSI_VERY_LOW)
7557 		wstats->qual.qual = 1;
7558 	else if (rssi <= WL_IW_RSSI_LOW)
7559 		wstats->qual.qual = 2;
7560 	else if (rssi <= WL_IW_RSSI_GOOD)
7561 		wstats->qual.qual = 3;
7562 	else if (rssi <= WL_IW_RSSI_VERY_GOOD)
7563 		wstats->qual.qual = 4;
7564 	else
7565 		wstats->qual.qual = 5;
7566 
7567 
7568 	wstats->qual.level = 0x100 + rssi;
7569 	wstats->qual.noise = 0x100 + phy_noise;
7570 #if WIRELESS_EXT > 18
7571 	wstats->qual.updated |= (IW_QUAL_ALL_UPDATED | IW_QUAL_DBM);
7572 #else
7573 	wstats->qual.updated |= 7;
7574 #endif
7575 
7576 #if WIRELESS_EXT > 11
7577 	WL_TRACE(("wl_iw_get_wireless_stats counters=%d\n", (int)sizeof(wl_cnt_t)));
7578 
7579 	memset(&cnt, 0, sizeof(wl_cnt_t));
7580 	res = dev_wlc_bufvar_get(dev, "counters", (char *)&cnt, sizeof(wl_cnt_t));
7581 	if (res)
7582 	{
7583 		WL_ERROR(("wl_iw_get_wireless_stats counters failed error=%d\n", res));
7584 		goto done;
7585 	}
7586 
7587 	cnt.version = dtoh16(cnt.version);
7588 	if (cnt.version != WL_CNT_T_VERSION) {
7589 		WL_TRACE(("\tIncorrect version of counters struct: expected %d; got %d\n",
7590 			WL_CNT_T_VERSION, cnt.version));
7591 		goto done;
7592 	}
7593 
7594 	wstats->discard.nwid = 0;
7595 	wstats->discard.code = dtoh32(cnt.rxundec);
7596 	wstats->discard.fragment = dtoh32(cnt.rxfragerr);
7597 	wstats->discard.retries = dtoh32(cnt.txfail);
7598 	wstats->discard.misc = dtoh32(cnt.rxrunt) + dtoh32(cnt.rxgiant);
7599 	wstats->miss.beacon = 0;
7600 
7601 	WL_TRACE(("wl_iw_get_wireless_stats counters txframe=%d txbyte=%d\n",
7602 		dtoh32(cnt.txframe), dtoh32(cnt.txbyte)));
7603 	WL_TRACE(("wl_iw_get_wireless_stats counters rxfrmtoolong=%d\n", dtoh32(cnt.rxfrmtoolong)));
7604 	WL_TRACE(("wl_iw_get_wireless_stats counters rxbadplcp=%d\n", dtoh32(cnt.rxbadplcp)));
7605 	WL_TRACE(("wl_iw_get_wireless_stats counters rxundec=%d\n", dtoh32(cnt.rxundec)));
7606 	WL_TRACE(("wl_iw_get_wireless_stats counters rxfragerr=%d\n", dtoh32(cnt.rxfragerr)));
7607 	WL_TRACE(("wl_iw_get_wireless_stats counters txfail=%d\n", dtoh32(cnt.txfail)));
7608 	WL_TRACE(("wl_iw_get_wireless_stats counters rxrunt=%d\n", dtoh32(cnt.rxrunt)));
7609 	WL_TRACE(("wl_iw_get_wireless_stats counters rxgiant=%d\n", dtoh32(cnt.rxgiant)));
7610 
7611 #endif
7612 
7613 done:
7614 	return res;
7615 }
7616 static void
7617 wl_iw_bt_flag_set(
7618 	struct net_device *dev,
7619 	bool set)
7620 {
7621 	char buf_flag7_dhcp_on[8] = { 7, 00, 00, 00, 0x1, 0x0, 0x00, 0x00 };
7622 	char buf_flag7_default[8]   = { 7, 00, 00, 00, 0x0, 0x00, 0x00, 0x00};
7623 
7624 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27))
7625 	rtnl_lock();
7626 #endif
7627 
7628 	if (set == TRUE) {
7629 		dev_wlc_bufvar_set(dev, "btc_flags",
7630 					(char *)&buf_flag7_dhcp_on[0], sizeof(buf_flag7_dhcp_on));
7631 	}
7632 	else  {
7633 		dev_wlc_bufvar_set(dev, "btc_flags",
7634 					(char *)&buf_flag7_default[0], sizeof(buf_flag7_default));
7635 	}
7636 
7637 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27))
7638 	rtnl_unlock();
7639 #endif
7640 }
7641 
7642 static void
7643 wl_iw_bt_timerfunc(ulong data)
7644 {
7645 	bt_info_t  *bt_local = (bt_info_t *)data;
7646 	bt_local->timer_on = 0;
7647 	WL_TRACE(("%s\n", __FUNCTION__));
7648 
7649 	up(&bt_local->bt_sem);
7650 }
7651 
7652 static int
7653 _bt_dhcp_sysioc_thread(void *data)
7654 {
7655 	DAEMONIZE("dhcp_sysioc");
7656 
7657 	while (down_interruptible(&g_bt->bt_sem) == 0) {
7658 
7659 		net_os_wake_lock(g_bt->dev);
7660 
7661 		if (g_bt->timer_on) {
7662 			g_bt->timer_on = 0;
7663 			del_timer_sync(&g_bt->timer);
7664 		}
7665 
7666 		switch (g_bt->bt_state) {
7667 			case BT_DHCP_START:
7668 				g_bt->bt_state = BT_DHCP_OPPORTUNITY_WINDOW;
7669 				mod_timer(&g_bt->timer, jiffies + BT_DHCP_OPPORTUNITY_WINDOW_TIEM*HZ/1000);
7670 				g_bt->timer_on = 1;
7671 				break;
7672 
7673 			case BT_DHCP_OPPORTUNITY_WINDOW:
7674 				WL_TRACE(("%s waiting for %d msec expired, force bt flag\n", \
7675 						__FUNCTION__, BT_DHCP_OPPORTUNITY_WINDOW_TIEM));
7676 				if (g_bt->dev) wl_iw_bt_flag_set(g_bt->dev, TRUE);
7677 				g_bt->bt_state = BT_DHCP_FLAG_FORCE_TIMEOUT;
7678 				mod_timer(&g_bt->timer, jiffies + BT_DHCP_FLAG_FORCE_TIME*HZ/1000);
7679 				g_bt->timer_on = 1;
7680 				break;
7681 
7682 			case BT_DHCP_FLAG_FORCE_TIMEOUT:
7683 				WL_TRACE(("%s waiting for %d msec expired remove bt flag\n", \
7684 						__FUNCTION__, BT_DHCP_FLAG_FORCE_TIME));
7685 
7686 				if (g_bt->dev)  wl_iw_bt_flag_set(g_bt->dev, FALSE);
7687 				g_bt->bt_state = BT_DHCP_IDLE;
7688 				g_bt->timer_on = 0;
7689 				break;
7690 
7691 			default:
7692 				WL_ERROR(("%s error g_status=%d !!!\n", __FUNCTION__, \
7693 				          g_bt->bt_state));
7694 				if (g_bt->dev) wl_iw_bt_flag_set(g_bt->dev, FALSE);
7695 				g_bt->bt_state = BT_DHCP_IDLE;
7696 				g_bt->timer_on = 0;
7697 				break;
7698 		}
7699 
7700 		net_os_wake_unlock(g_bt->dev);
7701 	}
7702 
7703 	if (g_bt->timer_on) {
7704 		g_bt->timer_on = 0;
7705 		del_timer_sync(&g_bt->timer);
7706 	}
7707 
7708 	complete_and_exit(&g_bt->bt_exited, 0);
7709 }
7710 
7711 static void
7712 wl_iw_bt_release(void)
7713 {
7714 	bt_info_t *bt_local = g_bt;
7715 
7716 	if (!bt_local) {
7717 		return;
7718 	}
7719 
7720 	if (bt_local->bt_pid >= 0) {
7721 		KILL_PROC(bt_local->bt_pid, SIGTERM);
7722 		wait_for_completion(&bt_local->bt_exited);
7723 	}
7724 	kfree(bt_local);
7725 	g_bt = NULL;
7726 }
7727 
7728 static int
7729 wl_iw_bt_init(struct net_device *dev)
7730 {
7731 	bt_info_t *bt_dhcp = NULL;
7732 
7733 	bt_dhcp = kmalloc(sizeof(bt_info_t), GFP_KERNEL);
7734 	if (!bt_dhcp)
7735 		return -ENOMEM;
7736 
7737 	memset(bt_dhcp, 0, sizeof(bt_info_t));
7738 	bt_dhcp->bt_pid = -1;
7739 	g_bt = bt_dhcp;
7740 	bt_dhcp->dev = dev;
7741 	bt_dhcp->bt_state = BT_DHCP_IDLE;
7742 
7743 
7744 	bt_dhcp->timer_ms    = 10;
7745 	init_timer(&bt_dhcp->timer);
7746 	bt_dhcp->timer.data = (ulong)bt_dhcp;
7747 	bt_dhcp->timer.function = wl_iw_bt_timerfunc;
7748 
7749 	sema_init(&bt_dhcp->bt_sem, 0);
7750 	init_completion(&bt_dhcp->bt_exited);
7751 	bt_dhcp->bt_pid = kernel_thread(_bt_dhcp_sysioc_thread, bt_dhcp, 0);
7752 	if (bt_dhcp->bt_pid < 0) {
7753 		WL_ERROR(("Failed in %s\n", __FUNCTION__));
7754 		return -ENOMEM;
7755 	}
7756 
7757 	return 0;
7758 }
7759 
7760 int wl_iw_attach(struct net_device *dev, void * dhdp)
7761 {
7762 	int params_size;
7763 	wl_iw_t *iw;
7764 #if defined(WL_IW_USE_ISCAN)
7765 	iscan_info_t *iscan = NULL;
7766 #endif
7767 
7768 	mutex_init(&wl_cache_lock);
7769 	mutex_init(&wl_start_lock);
7770 
7771 #if defined(WL_IW_USE_ISCAN)
7772 	if (!dev)
7773 		return 0;
7774 
7775 	memset(&g_wl_iw_params, 0, sizeof(wl_iw_extra_params_t));
7776 
7777 #ifdef CSCAN
7778 	params_size = (WL_SCAN_PARAMS_FIXED_SIZE + OFFSETOF(wl_iscan_params_t, params)) +
7779 	    (WL_NUMCHANNELS * sizeof(uint16)) + WL_SCAN_PARAMS_SSID_MAX * sizeof(wlc_ssid_t);
7780 #else
7781 	params_size = (WL_SCAN_PARAMS_FIXED_SIZE + OFFSETOF(wl_iscan_params_t, params));
7782 #endif
7783 	iscan = kmalloc(sizeof(iscan_info_t), GFP_KERNEL);
7784 	if (!iscan)
7785 		return -ENOMEM;
7786 	memset(iscan, 0, sizeof(iscan_info_t));
7787 
7788 	iscan->iscan_ex_params_p = (wl_iscan_params_t*)kmalloc(params_size, GFP_KERNEL);
7789 	if (!iscan->iscan_ex_params_p)
7790 		return -ENOMEM;
7791 	iscan->iscan_ex_param_size = params_size;
7792 	iscan->sysioc_pid = -1;
7793 
7794 	g_iscan = iscan;
7795 	iscan->dev = dev;
7796 	iscan->iscan_state = ISCAN_STATE_IDLE;
7797 	g_first_broadcast_scan = BROADCAST_SCAN_FIRST_IDLE;
7798 	g_first_counter_scans = 0;
7799 	g_iscan->scan_flag = 0;
7800 
7801 	iscan->timer_ms    = 8000;
7802 	init_timer(&iscan->timer);
7803 	iscan->timer.data = (ulong)iscan;
7804 	iscan->timer.function = wl_iw_timerfunc;
7805 
7806 	sema_init(&iscan->sysioc_sem, 0);
7807 	init_completion(&iscan->sysioc_exited);
7808 	iscan->sysioc_pid = kernel_thread(_iscan_sysioc_thread, iscan, 0);
7809 	if (iscan->sysioc_pid < 0)
7810 		return -ENOMEM;
7811 #endif
7812 
7813 	iw = *(wl_iw_t **)netdev_priv(dev);
7814 	iw->pub = (dhd_pub_t *)dhdp;
7815 #ifdef SOFTAP
7816 	priv_dev = dev;
7817 #endif
7818 	g_scan = NULL;
7819 
7820 	g_scan = (void *)kmalloc(G_SCAN_RESULTS, GFP_KERNEL);
7821 	if (!g_scan)
7822 		return -ENOMEM;
7823 
7824 	memset(g_scan, 0, G_SCAN_RESULTS);
7825 	g_scan_specified_ssid = 0;
7826 
7827 #if !defined(CSCAN)
7828 	wl_iw_init_ss_cache_ctrl();
7829 #endif
7830 
7831 	wl_iw_bt_init(dev);
7832 
7833 	return 0;
7834 }
7835 
7836 void wl_iw_detach(void)
7837 {
7838 #if defined(WL_IW_USE_ISCAN)
7839 	iscan_buf_t  *buf;
7840 	iscan_info_t *iscan = g_iscan;
7841 
7842 	if (!iscan)
7843 		return;
7844 	if (iscan->sysioc_pid >= 0) {
7845 		KILL_PROC(iscan->sysioc_pid, SIGTERM);
7846 		wait_for_completion(&iscan->sysioc_exited);
7847 	}
7848 	mutex_lock(&wl_cache_lock);
7849 	while (iscan->list_hdr) {
7850 		buf = iscan->list_hdr->next;
7851 		kfree(iscan->list_hdr);
7852 		iscan->list_hdr = buf;
7853 	}
7854 	kfree(iscan->iscan_ex_params_p);
7855 	kfree(iscan);
7856 	g_iscan = NULL;
7857 	mutex_unlock(&wl_cache_lock);
7858 #endif
7859 
7860 	if (g_scan)
7861 		kfree(g_scan);
7862 
7863 	g_scan = NULL;
7864 #if !defined(CSCAN)
7865 	wl_iw_release_ss_cache_ctrl();
7866 #endif
7867 	wl_iw_bt_release();
7868 #ifdef SOFTAP
7869 	if (ap_cfg_running) {
7870 		WL_TRACE(("\n%s AP is going down\n", __FUNCTION__));
7871 		wl_iw_send_priv_event(priv_dev, "AP_DOWN");
7872 	}
7873 #endif
7874 
7875 }
7876