2 * Linux Wireless Extensions support
4 * Copyright (C) 1999-2010, Broadcom Corporation
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:
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.
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.
24 * $Id: wl_iw.c,v 1.51.4.9.2.6.4.142.4.69 2010/12/21 03:00:08 Exp $
33 #include <bcmendian.h>
34 #include <proto/ethernet.h>
36 #include <linux/if_arp.h>
37 #include <asm/uaccess.h>
39 #include <dngl_stats.h>
43 typedef void wlc_info_t;
44 typedef void wl_info_t;
45 typedef const struct si_pub si_t;
48 #include <proto/ethernet.h>
49 #include <dngl_stats.h>
51 #define WL_ERROR(x) printf x
57 #define WL_TRACE_COEX(x)
63 #ifndef IW_ENCODE_ALG_SM4
64 #define IW_ENCODE_ALG_SM4 0x20
67 #ifndef IW_AUTH_WAPI_ENABLED
68 #define IW_AUTH_WAPI_ENABLED 0x20
71 #ifndef IW_AUTH_WAPI_VERSION_1
72 #define IW_AUTH_WAPI_VERSION_1 0x00000008
75 #ifndef IW_AUTH_CIPHER_SMS4
76 #define IW_AUTH_CIPHER_SMS4 0x00000020
79 #ifndef IW_AUTH_KEY_MGMT_WAPI_PSK
80 #define IW_AUTH_KEY_MGMT_WAPI_PSK 4
83 #ifndef IW_AUTH_KEY_MGMT_WAPI_CERT
84 #define IW_AUTH_KEY_MGMT_WAPI_CERT 8
88 #define IW_WSEC_ENABLED(wsec) ((wsec) & (WEP_ENABLED | TKIP_ENABLED | AES_ENABLED | SMS4_ENABLED))
90 #include <linux/rtnetlink.h>
91 #include <linux/mutex.h>
93 #define WL_IW_USE_ISCAN 1
94 #define ENABLE_ACTIVE_PASSIVE_SCAN_SUPPRESS 1
97 #define WL_SOFTAP(x) printk x
98 static struct net_device *priv_dev;
99 static bool ap_cfg_running = FALSE;
100 bool ap_fw_loaded = FALSE;
101 static long ap_cfg_pid = -1;
102 struct net_device *ap_net_dev = NULL;
103 struct semaphore ap_eth_sema;
104 static struct completion ap_cfg_exited;
105 static int wl_iw_set_ap_security(struct net_device *dev, struct ap_profile *ap);
106 static int wl_iw_softap_deassoc_stations(struct net_device *dev, u8 *mac);
109 #define WL_IW_IOCTL_CALL(func_call) \
114 static int g_onoff = G_WLAN_SET_ON;
115 wl_iw_extra_params_t g_wl_iw_params;
116 static struct mutex wl_cache_lock;
118 #ifdef CONFIG_US_NON_DFS_CHANNELS_ONLY
119 static bool use_non_dfs_channels = true;
122 extern bool wl_iw_conn_status_str(uint32 event_type, uint32 status,
123 uint32 reason, char* stringBuf, uint buflen);
124 #include <bcmsdbus.h>
125 extern void dhd_customer_gpio_wlan_ctrl(int onoff);
126 extern uint dhd_dev_reset(struct net_device *dev, uint8 flag);
127 extern void dhd_dev_init_ioctl(struct net_device *dev);
128 int dev_iw_write_cfg1_bss_var(struct net_device *dev, int val);
130 uint wl_msg_level = WL_ERROR_VAL;
132 #define MAX_WLIW_IOCTL_LEN 1024
135 #if defined(IL_BIGENDIAN)
136 #include <bcmendian.h>
137 #define htod32(i) (bcmswap32(i))
138 #define htod16(i) (bcmswap16(i))
139 #define dtoh32(i) (bcmswap32(i))
140 #define dtoh16(i) (bcmswap16(i))
141 #define htodchanspec(i) htod16(i)
142 #define dtohchanspec(i) dtoh16(i)
148 #define htodchanspec(i) i
149 #define dtohchanspec(i) i
152 #ifdef CONFIG_WIRELESS_EXT
154 extern struct iw_statistics *dhd_get_wireless_stats(struct net_device *dev);
155 extern int dhd_wait_pend8021x(struct net_device *dev);
158 #if WIRELESS_EXT < 19
159 #define IW_IOCTL_IDX(cmd) ((cmd) - SIOCIWFIRST)
160 #define IW_EVENT_IDX(cmd) ((cmd) - IWEVFIRST)
163 static void *g_scan = NULL;
164 static volatile uint g_scan_specified_ssid;
165 static wlc_ssid_t g_specific_ssid;
167 static wlc_ssid_t g_ssid;
169 static wl_iw_ss_cache_ctrl_t g_ss_cache_ctrl;
170 #if defined(CONFIG_FIRST_SCAN)
171 static volatile uint g_first_broadcast_scan;
172 static volatile uint g_first_counter_scans;
173 #define MAX_ALLOWED_BLOCK_SCAN_FROM_FIRST_SCAN 3
177 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0))
178 #define DAEMONIZE(a) daemonize(a); \
179 allow_signal(SIGKILL); \
180 allow_signal(SIGTERM);
182 #define RAISE_RX_SOFTIRQ() \
183 cpu_raise_softirq(smp_processor_id(), NET_RX_SOFTIRQ)
184 #define DAEMONIZE(a) daemonize(); \
186 strncpy(current->comm, a, MIN(sizeof(current->comm), (strlen(a) + 1))); \
190 #if defined(WL_IW_USE_ISCAN)
192 static void wl_iw_free_ss_cache(void);
193 static int wl_iw_run_ss_cache_timer(int kick_off);
195 #if defined(CONFIG_FIRST_SCAN)
196 int wl_iw_iscan_set_scan_broadcast_prep(struct net_device *dev, uint flag);
198 static int dev_wlc_bufvar_set(struct net_device *dev, char *name, char *buf, int len);
199 #define ISCAN_STATE_IDLE 0
200 #define ISCAN_STATE_SCANING 1
202 #define WLC_IW_ISCAN_MAXLEN 2048
203 typedef struct iscan_buf {
204 struct iscan_buf * next;
205 char iscan_buf[WLC_IW_ISCAN_MAXLEN];
208 typedef struct iscan_info {
209 struct net_device *dev;
210 struct timer_list timer;
214 iscan_buf_t * list_hdr;
215 iscan_buf_t * list_cur;
219 struct semaphore sysioc_sem;
220 struct completion sysioc_exited;
224 char ioctlbuf[WLC_IOCTL_MEDLEN];
226 char ioctlbuf[WLC_IOCTL_SMLEN];
228 wl_iscan_params_t *iscan_ex_params_p;
229 int iscan_ex_param_size;
233 #define BT_DHCP_eSCO_FIX
234 #define BT_DHCP_USE_FLAGS
235 #define BT_DHCP_OPPORTUNITY_WINDOW_TIME 2500
236 #define BT_DHCP_FLAG_FORCE_TIME 5500
237 static void wl_iw_bt_flag_set(struct net_device *dev, bool set);
238 static void wl_iw_bt_release(void);
240 typedef enum bt_coex_status {
243 BT_DHCP_OPPORTUNITY_WINDOW,
244 BT_DHCP_FLAG_FORCE_TIMEOUT
247 typedef struct bt_info {
248 struct net_device *dev;
249 struct timer_list timer;
256 struct semaphore bt_sem;
257 struct completion bt_exited;
260 bt_info_t *g_bt = NULL;
261 static void wl_iw_bt_timerfunc(ulong data);
262 iscan_info_t *g_iscan = NULL;
263 static void wl_iw_timerfunc(ulong data);
264 static void wl_iw_set_event_mask(struct net_device *dev);
266 wl_iw_iscan(iscan_info_t *iscan, wlc_ssid_t *ssid, uint16 action);
270 struct net_device *dev,
271 struct iw_request_info *info,
272 union iwreq_data *wrqu,
279 struct net_device *dev,
280 struct iw_request_info *info,
281 struct iw_point *dwrq,
287 wl_scan_results_t *list,
288 struct iw_request_info *info,
294 static void swap_key_from_BE(
298 key->index = htod32(key->index);
299 key->len = htod32(key->len);
300 key->algo = htod32(key->algo);
301 key->flags = htod32(key->flags);
302 key->rxiv.hi = htod32(key->rxiv.hi);
303 key->rxiv.lo = htod16(key->rxiv.lo);
304 key->iv_initialized = htod32(key->iv_initialized);
307 static void swap_key_to_BE(
311 key->index = dtoh32(key->index);
312 key->len = dtoh32(key->len);
313 key->algo = dtoh32(key->algo);
314 key->flags = dtoh32(key->flags);
315 key->rxiv.hi = dtoh32(key->rxiv.hi);
316 key->rxiv.lo = dtoh16(key->rxiv.lo);
317 key->iv_initialized = dtoh32(key->iv_initialized);
322 struct net_device *dev,
334 WL_ERROR(("%s: dev is null\n", __FUNCTION__));
338 net_os_wake_lock(dev);
340 WL_INFORM(("\n%s, PID:%x: send Local IOCTL -> dhd: cmd:0x%x, buf:%p, len:%d ,\n",
341 __FUNCTION__, current->pid, cmd, arg, len));
343 if (g_onoff == G_WLAN_SET_ON) {
344 memset(&ioc, 0, sizeof(ioc));
349 strcpy(ifr.ifr_name, dev->name);
350 ifr.ifr_data = (caddr_t) &ioc;
354 WL_ERROR(("%s: Error dev_open: %d\n", __func__, ret));
355 net_os_wake_unlock(dev);
361 #if (LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 31))
362 ret = dev->do_ioctl(dev, &ifr, SIOCDEVPRIVATE);
364 ret = dev->netdev_ops->ndo_do_ioctl(dev, &ifr, SIOCDEVPRIVATE);
369 WL_TRACE(("%s: call after driver stop : ignored\n", __FUNCTION__));
372 net_os_wake_unlock(dev);
379 dev_wlc_intvar_get_reg(
380 struct net_device *dev,
386 char buf[WLC_IOCTL_SMLEN];
392 len = bcm_mkiovar(name, (char *)(®), sizeof(reg), (char *)(&var), sizeof(var.buf));
394 error = dev_wlc_ioctl(dev, WLC_GET_VAR, (void *)&var, len);
396 *retval = dtoh32(var.val);
402 dev_wlc_intvar_set_reg(
403 struct net_device *dev,
410 memset(reg_addr, 0, sizeof(reg_addr));
411 memcpy((char *)®_addr[0], (char *)addr, 4);
412 memcpy((char *)®_addr[4], (char *)val, 4);
414 return (dev_wlc_bufvar_set(dev, name, (char *)®_addr[0], sizeof(reg_addr)));
420 struct net_device *dev,
424 char buf[WLC_IOCTL_SMLEN];
428 len = bcm_mkiovar(name, (char *)(&val), sizeof(val), buf, sizeof(buf));
431 return (dev_wlc_ioctl(dev, WLC_SET_VAR, buf, len));
434 #if defined(WL_IW_USE_ISCAN)
437 struct net_device *dev,
446 iolen = bcm_mkiovar(iovar, param, paramlen, bufptr, buflen);
452 return (dev_wlc_ioctl(dev, WLC_SET_VAR, bufptr, iolen));
457 struct net_device *dev,
466 iolen = bcm_mkiovar(iovar, param, paramlen, bufptr, buflen);
469 return (dev_wlc_ioctl(dev, WLC_GET_VAR, bufptr, buflen));
474 #if WIRELESS_EXT > 17
477 struct net_device *dev,
481 static char ioctlbuf[MAX_WLIW_IOCTL_LEN];
484 buflen = bcm_mkiovar(name, buf, len, ioctlbuf, sizeof(ioctlbuf));
487 return (dev_wlc_ioctl(dev, WLC_SET_VAR, ioctlbuf, buflen));
494 struct net_device *dev,
496 char *buf, int buflen)
498 static char ioctlbuf[MAX_WLIW_IOCTL_LEN];
502 len = bcm_mkiovar(name, NULL, 0, ioctlbuf, sizeof(ioctlbuf));
504 error = dev_wlc_ioctl(dev, WLC_GET_VAR, (void *)ioctlbuf, MAX_WLIW_IOCTL_LEN);
506 bcopy(ioctlbuf, buf, buflen);
515 struct net_device *dev,
520 char buf[WLC_IOCTL_SMLEN];
528 len = bcm_mkiovar(name, (char *)(&data_null), 0, (char *)(&var), sizeof(var.buf));
530 error = dev_wlc_ioctl(dev, WLC_GET_VAR, (void *)&var, len);
532 *retval = dtoh32(var.val);
538 #if WIRELESS_EXT > 12
540 wl_iw_set_active_scan(
541 struct net_device *dev,
542 struct iw_request_info *info,
543 union iwreq_data *wrqu,
551 #if defined(WL_IW_USE_ISCAN)
552 if (g_iscan->iscan_state == ISCAN_STATE_IDLE)
554 error = dev_wlc_ioctl(dev, WLC_SET_PASSIVE_SCAN, &as, sizeof(as));
555 #if defined(WL_IW_USE_ISCAN)
557 g_iscan->scan_flag = as;
559 p += snprintf(p, MAX_WX_STRING, "OK");
561 wrqu->data.length = p - extra + 1;
566 wl_iw_set_passive_scan(
567 struct net_device *dev,
568 struct iw_request_info *info,
569 union iwreq_data *wrqu,
577 #if defined(WL_IW_USE_ISCAN)
578 if (g_iscan->iscan_state == ISCAN_STATE_IDLE) {
582 if (g_scan_specified_ssid == 0) {
583 error = dev_wlc_ioctl(dev, WLC_SET_PASSIVE_SCAN, &ps, sizeof(ps));
585 #if defined(WL_IW_USE_ISCAN)
588 g_iscan->scan_flag = ps;
591 p += snprintf(p, MAX_WX_STRING, "OK");
593 wrqu->data.length = p - extra + 1;
599 struct net_device *dev,
600 struct iw_request_info *info,
601 union iwreq_data *wrqu,
607 struct ether_addr *id;
611 strcpy(buf, "cur_etheraddr");
612 error = dev_wlc_ioctl(dev, WLC_GET_VAR, buf, sizeof(buf));
613 id = (struct ether_addr *) buf;
614 p += snprintf(p, MAX_WX_STRING, "Macaddr = %02X:%02X:%02X:%02X:%02X:%02X\n",
615 id->octet[0], id->octet[1], id->octet[2],
616 id->octet[3], id->octet[4], id->octet[5]);
617 wrqu->data.length = p - extra + 1;
623 wl_iw_set_country_code(struct net_device *dev, char *ccode)
625 char country_code[WLC_CNTRY_BUF_SZ];
628 WL_TRACE(("%s\n", __FUNCTION__));
630 ccode = dhd_bus_country_get(dev);
631 strncpy(country_code, ccode, sizeof(country_code));
632 if (ccode && (country_code[0] != 0)) {
633 #ifdef CONFIG_US_NON_DFS_CHANNELS_ONLY
634 if (use_non_dfs_channels && !strncmp(country_code, "US", 2))
635 strncpy(country_code, "Q2", WLC_CNTRY_BUF_SZ);
636 if (!use_non_dfs_channels && !strncmp(country_code, "Q2", 2))
637 strncpy(country_code, "US", WLC_CNTRY_BUF_SZ);
639 ret = dev_wlc_ioctl(dev, WLC_SET_COUNTRY, &country_code, sizeof(country_code));
641 WL_TRACE(("%s: set country %s OK\n", __FUNCTION__, country_code));
642 dhd_bus_country_set(dev, &country_code[0]);
650 struct net_device *dev,
651 struct iw_request_info *info,
652 union iwreq_data *wrqu,
656 char country_code[WLC_CNTRY_BUF_SZ];
660 int country_code_size;
662 WL_TRACE(("%s\n", __FUNCTION__));
663 memset(country_code, 0, sizeof(country_code));
665 country_offset = strcspn(extra, " ");
666 country_code_size = strlen(extra) - country_offset;
668 if (country_offset != 0) {
669 strncpy(country_code, extra + country_offset + 1,
670 MIN(country_code_size, sizeof(country_code)));
671 error = wl_iw_set_country_code(dev, country_code);
673 p += snprintf(p, MAX_WX_STRING, "OK");
674 WL_TRACE(("%s: set country %s OK\n", __FUNCTION__, country_code));
679 WL_ERROR(("%s: set country %s failed code %d\n", __FUNCTION__, country_code, error));
680 p += snprintf(p, MAX_WX_STRING, "FAIL");
683 wrqu->data.length = p - extra + 1;
689 wl_iw_set_power_mode(
690 struct net_device *dev,
691 struct iw_request_info *info,
692 union iwreq_data *wrqu,
698 static int pm = PM_FAST;
699 int pm_local = PM_OFF;
700 char powermode_val = 0;
702 WL_TRACE_COEX(("%s: DHCP session cmd:%s\n", __FUNCTION__, extra));
704 strncpy((char *)&powermode_val, extra + strlen("POWERMODE") + 1, 1);
706 if (strnicmp((char *)&powermode_val, "1", strlen("1")) == 0) {
708 dev_wlc_ioctl(dev, WLC_GET_PM, &pm, sizeof(pm));
709 dev_wlc_ioctl(dev, WLC_SET_PM, &pm_local, sizeof(pm_local));
711 /* Disable packet filtering if necessary */
712 net_os_set_packet_filter(dev, 0);
714 g_bt->dhcp_done = false;
715 WL_TRACE_COEX(("%s: DHCP start, pm:%d changed to pm:%d\n",
716 __FUNCTION__, pm, pm_local));
718 } else if (strnicmp((char *)&powermode_val, "0", strlen("0")) == 0) {
720 dev_wlc_ioctl(dev, WLC_SET_PM, &pm, sizeof(pm));
722 /* Enable packet filtering if was turned off */
723 net_os_set_packet_filter(dev, 1);
725 g_bt->dhcp_done = true;
728 WL_ERROR(("%s Unkwown yet power setting, ignored\n",
732 p += snprintf(p, MAX_WX_STRING, "OK");
734 wrqu->data.length = p - extra + 1;
741 static bool btcoex_is_sco_active(struct net_device *dev)
747 ioc_res = dev_wlc_intvar_get_reg(dev, "btc_params", 4, &temp);
750 WL_TRACE_COEX(("%s: read btc_params[4] = %x\n", __FUNCTION__, temp));
752 if ((temp > 0xea0) && (temp < 0xed8)) {
753 WL_TRACE_COEX(("%s: BT SCO/eSCO is ACTIVE\n", __FUNCTION__));
756 WL_TRACE_COEX(("%s: BT SCO/eSCO is NOT detected\n", __FUNCTION__));
759 WL_ERROR(("%s ioc read btc params error\n", __FUNCTION__));
764 #if defined(BT_DHCP_eSCO_FIX)
766 static int set_btc_esco_params(struct net_device *dev, bool trump_sco)
768 static bool saved_status = false;
770 char buf_reg50va_dhcp_on[8] = { 50, 00, 00, 00, 0x22, 0x80, 0x00, 0x00 };
771 char buf_reg51va_dhcp_on[8] = { 51, 00, 00, 00, 0x00, 0x00, 0x00, 0x00 };
772 char buf_reg64va_dhcp_on[8] = { 64, 00, 00, 00, 0x00, 0x00, 0x00, 0x00 };
773 char buf_reg65va_dhcp_on[8] = { 65, 00, 00, 00, 0x00, 0x00, 0x00, 0x00 };
774 char buf_reg71va_dhcp_on[8] = { 71, 00, 00, 00, 0x00, 0x00, 0x00, 0x00 };
777 static uint32 saved_reg50;
778 static uint32 saved_reg51;
779 static uint32 saved_reg64;
780 static uint32 saved_reg65;
781 static uint32 saved_reg71;
785 WL_TRACE_COEX(("Do new SCO/eSCO coex algo {save & override} \n"));
787 if ((!dev_wlc_intvar_get_reg(dev, "btc_params", 50, &saved_reg50)) &&
788 (!dev_wlc_intvar_get_reg(dev, "btc_params", 51, &saved_reg51)) &&
789 (!dev_wlc_intvar_get_reg(dev, "btc_params", 64, &saved_reg64)) &&
790 (!dev_wlc_intvar_get_reg(dev, "btc_params", 65, &saved_reg65)) &&
791 (!dev_wlc_intvar_get_reg(dev, "btc_params", 71, &saved_reg71))) {
794 WL_TRACE_COEX(("%s saved bt_params[50,51,64,65,71]:"
795 " 0x%x 0x%x 0x%x 0x%x 0x%x\n",
796 __FUNCTION__, saved_reg50, saved_reg51,
797 saved_reg64, saved_reg65, saved_reg71));
800 WL_ERROR((":%s: save btc_params failed\n",
802 saved_status = false;
806 WL_TRACE_COEX(("override with [50,51,64,65,71]:"
807 " 0x%x 0x%x 0x%x 0x%x 0x%x\n",
808 *(u32 *)(buf_reg50va_dhcp_on+4),
809 *(u32 *)(buf_reg51va_dhcp_on+4),
810 *(u32 *)(buf_reg64va_dhcp_on+4),
811 *(u32 *)(buf_reg65va_dhcp_on+4),
812 *(u32 *)(buf_reg71va_dhcp_on+4)));
814 dev_wlc_bufvar_set(dev, "btc_params", (char *)&buf_reg50va_dhcp_on[0], 8);
815 dev_wlc_bufvar_set(dev, "btc_params", (char *)&buf_reg51va_dhcp_on[0], 8);
816 dev_wlc_bufvar_set(dev, "btc_params", (char *)&buf_reg64va_dhcp_on[0], 8);
817 dev_wlc_bufvar_set(dev, "btc_params", (char *)&buf_reg65va_dhcp_on[0], 8);
818 dev_wlc_bufvar_set(dev, "btc_params", (char *)&buf_reg71va_dhcp_on[0], 8);
822 } else if (saved_status) {
824 WL_TRACE_COEX(("Do new SCO/eSCO coex algo {save & override} \n"));
827 dev_wlc_intvar_set_reg(dev, "btc_params",
828 (char *)®addr, (char *)&saved_reg50);
830 dev_wlc_intvar_set_reg(dev, "btc_params",
831 (char *)®addr, (char *)&saved_reg51);
833 dev_wlc_intvar_set_reg(dev, "btc_params",
834 (char *)®addr, (char *)&saved_reg64);
836 dev_wlc_intvar_set_reg(dev, "btc_params",
837 (char *)®addr, (char *)&saved_reg65);
839 dev_wlc_intvar_set_reg(dev, "btc_params",
840 (char *)®addr, (char *)&saved_reg71);
842 WL_TRACE_COEX(("restore bt_params[50,51,64,65,71]: 0x%x 0x%x 0x%x 0x%x 0x%x\n",
843 saved_reg50, saved_reg51, saved_reg64,
844 saved_reg65, saved_reg71));
846 saved_status = false;
848 WL_ERROR((":%s att to restore not saved BTCOEX params\n",
857 wl_iw_get_power_mode(
858 struct net_device *dev,
859 struct iw_request_info *info,
860 union iwreq_data *wrqu,
866 int pm_local = PM_FAST;
868 error = dev_wlc_ioctl(dev, WLC_GET_PM, &pm_local, sizeof(pm_local));
870 WL_TRACE(("%s: Powermode = %d\n", __func__, pm_local));
871 if (pm_local == PM_OFF)
872 pm_local = 1; /* Active */
874 pm_local = 0; /* Auto */
875 p += snprintf(p, MAX_WX_STRING, "powermode = %d", pm_local);
878 WL_TRACE(("%s: Error = %d\n", __func__, error));
879 p += snprintf(p, MAX_WX_STRING, "FAIL");
881 wrqu->data.length = p - extra + 1;
886 wl_iw_set_btcoex_dhcp(
887 struct net_device *dev,
888 struct iw_request_info *info,
889 union iwreq_data *wrqu,
896 static int pm = PM_FAST;
897 int pm_local = PM_OFF;
899 char powermode_val = 0;
900 char buf_reg66va_dhcp_on[8] = { 66, 00, 00, 00, 0x10, 0x27, 0x00, 0x00 };
901 char buf_reg41va_dhcp_on[8] = { 41, 00, 00, 00, 0x33, 0x00, 0x00, 0x00 };
902 char buf_reg68va_dhcp_on[8] = { 68, 00, 00, 00, 0x90, 0x01, 0x00, 0x00 };
905 static uint32 saved_reg66;
906 static uint32 saved_reg41;
907 static uint32 saved_reg68;
908 static bool saved_status = FALSE;
910 char buf_flag7_default[8] = { 7, 00, 00, 00, 0x0, 0x00, 0x00, 0x00};
913 strncpy((char *)&powermode_val, extra + strlen("BTCOEXMODE") + 1, 1);
915 strncpy((char *)&powermode_val, extra + strlen("POWERMODE") + 1, 1);
918 if (strnicmp((char *)&powermode_val, "1", strlen("1")) == 0) {
920 WL_TRACE_COEX(("%s: DHCP session start, cmd:%s\n", __FUNCTION__, extra));
922 if ((saved_status == FALSE) &&
924 (!dev_wlc_ioctl(dev, WLC_GET_PM, &pm, sizeof(pm))) &&
926 (!dev_wlc_intvar_get_reg(dev, "btc_params", 66, &saved_reg66)) &&
927 (!dev_wlc_intvar_get_reg(dev, "btc_params", 41, &saved_reg41)) &&
928 (!dev_wlc_intvar_get_reg(dev, "btc_params", 68, &saved_reg68))) {
929 WL_TRACE_COEX(("save regs {66,41,68} ->: 0x%x 0x%x 0x%x\n", \
930 saved_reg66, saved_reg41, saved_reg68));
933 dev_wlc_ioctl(dev, WLC_SET_PM, &pm_local, sizeof(pm_local));
936 if (btcoex_is_sco_active(dev)) {
938 dev_wlc_bufvar_set(dev, "btc_params", \
939 (char *)&buf_reg66va_dhcp_on[0], \
940 sizeof(buf_reg66va_dhcp_on));
942 dev_wlc_bufvar_set(dev, "btc_params", \
943 (char *)&buf_reg41va_dhcp_on[0], \
944 sizeof(buf_reg41va_dhcp_on));
946 dev_wlc_bufvar_set(dev, "btc_params", \
947 (char *)&buf_reg68va_dhcp_on[0], \
948 sizeof(buf_reg68va_dhcp_on));
951 g_bt->bt_state = BT_DHCP_START;
953 mod_timer(&g_bt->timer, g_bt->timer.expires);
954 WL_TRACE_COEX(("%s enable BT DHCP Timer\n", \
958 else if (saved_status == TRUE) {
959 WL_ERROR(("%s was called w/o DHCP OFF. Continue\n", __FUNCTION__));
963 else if (strnicmp((char *)&powermode_val, "2", strlen("2")) == 0) {
965 else if (strnicmp((char *)&powermode_val, "0", strlen("0")) == 0) {
969 dev_wlc_ioctl(dev, WLC_SET_PM, &pm, sizeof(pm));
972 WL_TRACE_COEX(("%s disable BT DHCP Timer\n", __FUNCTION__));
973 if (g_bt->timer_on) {
975 del_timer_sync(&g_bt->timer);
977 if (g_bt->bt_state != BT_DHCP_IDLE) {
978 WL_TRACE_COEX(("%s bt->bt_state:%d\n",
979 __FUNCTION__, g_bt->bt_state));
985 if (saved_status == TRUE) {
986 dev_wlc_bufvar_set(dev, "btc_flags", \
987 (char *)&buf_flag7_default[0], sizeof(buf_flag7_default));
990 dev_wlc_intvar_set_reg(dev, "btc_params", \
991 (char *)®addr, (char *)&saved_reg66);
993 dev_wlc_intvar_set_reg(dev, "btc_params", \
994 (char *)®addr, (char *)&saved_reg41);
996 dev_wlc_intvar_set_reg(dev, "btc_params", \
997 (char *)®addr, (char *)&saved_reg68);
999 WL_TRACE_COEX(("restore regs {66,41,68} <- 0x%x 0x%x 0x%x\n", \
1000 saved_reg66, saved_reg41, saved_reg68));
1002 saved_status = FALSE;
1005 WL_ERROR(("%s Unkwown yet power setting, ignored\n",
1009 p += snprintf(p, MAX_WX_STRING, "OK");
1011 wrqu->data.length = p - extra + 1;
1018 struct net_device *dev,
1019 struct iw_request_info *info,
1020 union iwreq_data *wrqu,
1028 suspend_flag = *(extra + strlen(SETSUSPEND_CMD) + 1) - '0';
1030 if (suspend_flag != 0)
1033 ret_now = net_os_set_suspend_disable(dev, suspend_flag);
1035 if (ret_now != suspend_flag) {
1036 if (!(ret = net_os_set_suspend(dev, ret_now)))
1037 WL_ERROR(("%s: Suspend Flag %d -> %d\n", \
1038 __FUNCTION__, ret_now, suspend_flag));
1040 WL_ERROR(("%s: failed %d\n", __FUNCTION__, ret));
1046 #ifdef CONFIG_US_NON_DFS_CHANNELS_ONLY
1048 wl_iw_set_dfs_channels(
1049 struct net_device *dev,
1050 struct iw_request_info *info,
1051 union iwreq_data *wrqu,
1055 use_non_dfs_channels = *(extra + strlen(SETDFSCHANNELS_CMD) + 1) - '0';
1056 use_non_dfs_channels = (use_non_dfs_channels != 0) ? false : true;
1057 wl_iw_set_country_code(dev, NULL);
1063 wl_format_ssid(char* ssid_buf, uint8* ssid, int ssid_len)
1068 if (ssid_len > 32) ssid_len = 32;
1070 for (i = 0; i < ssid_len; i++) {
1075 } else if (isprint((uchar)c)) {
1078 p += sprintf(p, "\\x%02X", c);
1083 return p - ssid_buf;
1087 wl_iw_get_link_speed(
1088 struct net_device *dev,
1089 struct iw_request_info *info,
1090 union iwreq_data *wrqu,
1096 static int link_speed;
1098 net_os_wake_lock(dev);
1099 if (g_onoff == G_WLAN_SET_ON) {
1100 error = dev_wlc_ioctl(dev, WLC_GET_RATE, &link_speed, sizeof(link_speed));
1101 link_speed *= 500000;
1104 p += snprintf(p, MAX_WX_STRING, "LinkSpeed %d", link_speed/1000000);
1106 wrqu->data.length = p - extra + 1;
1108 net_os_wake_unlock(dev);
1114 wl_iw_get_dtim_skip(
1115 struct net_device *dev,
1116 struct iw_request_info *info,
1117 union iwreq_data *wrqu,
1125 net_os_wake_lock(dev);
1126 if (g_onoff == G_WLAN_SET_ON) {
1128 memset(iovbuf, 0, sizeof(iovbuf));
1129 strcpy(iovbuf, "bcn_li_dtim");
1131 if ((error = dev_wlc_ioctl(dev, WLC_GET_VAR,
1132 &iovbuf, sizeof(iovbuf))) >= 0) {
1134 p += snprintf(p, MAX_WX_STRING, "Dtim_skip %d", iovbuf[0]);
1135 WL_TRACE(("%s: get dtim_skip = %d\n", __FUNCTION__, iovbuf[0]));
1136 wrqu->data.length = p - extra + 1;
1139 WL_ERROR(("%s: get dtim_skip failed code %d\n", \
1140 __FUNCTION__, error));
1142 net_os_wake_unlock(dev);
1148 wl_iw_set_dtim_skip(
1149 struct net_device *dev,
1150 struct iw_request_info *info,
1151 union iwreq_data *wrqu,
1160 net_os_wake_lock(dev);
1161 if (g_onoff == G_WLAN_SET_ON) {
1163 bcn_li_dtim = htod32((uint)*(extra + strlen(DTIM_SKIP_SET_CMD) + 1) - '0');
1165 if ((bcn_li_dtim >= 0) || ((bcn_li_dtim <= 5))) {
1167 memset(iovbuf, 0, sizeof(iovbuf));
1168 bcm_mkiovar("bcn_li_dtim", (char *)&bcn_li_dtim,
1169 4, iovbuf, sizeof(iovbuf));
1171 if ((error = dev_wlc_ioctl(dev, WLC_SET_VAR,
1172 &iovbuf, sizeof(iovbuf))) >= 0) {
1173 p += snprintf(p, MAX_WX_STRING, "OK");
1175 net_os_set_dtim_skip(dev, bcn_li_dtim);
1177 WL_TRACE(("%s: set dtim_skip %d OK\n", __FUNCTION__, \
1181 else WL_ERROR(("%s: set dtim_skip %d failed code %d\n", \
1182 __FUNCTION__, bcn_li_dtim, error));
1184 else WL_ERROR(("%s Incorrect dtim_skip setting %d, ignored\n", \
1185 __FUNCTION__, bcn_li_dtim));
1188 p += snprintf(p, MAX_WX_STRING, "FAIL");
1191 wrqu->data.length = p - extra + 1;
1192 net_os_wake_unlock(dev);
1199 struct net_device *dev,
1200 struct iw_request_info *info,
1201 union iwreq_data *wrqu,
1209 net_os_wake_lock(dev);
1211 if (g_onoff == G_WLAN_SET_ON) {
1212 error = dev_wlc_ioctl(dev, WLC_GET_BAND, &band, sizeof(band));
1214 p += snprintf(p, MAX_WX_STRING, "Band %d", band);
1216 wrqu->data.length = p - extra + 1;
1219 net_os_wake_unlock(dev);
1226 struct net_device *dev,
1227 struct iw_request_info *info,
1228 union iwreq_data *wrqu,
1236 net_os_wake_lock(dev);
1238 if (g_onoff == G_WLAN_SET_ON) {
1240 band = htod32((uint)*(extra + strlen(BAND_SET_CMD) + 1) - '0');
1242 if ((band == WLC_BAND_AUTO) || (band == WLC_BAND_5G) || (band == WLC_BAND_2G)) {
1244 if ((error = dev_wlc_ioctl(dev, WLC_SET_BAND,
1245 &band, sizeof(band))) >= 0) {
1246 p += snprintf(p, MAX_WX_STRING, "OK");
1247 WL_TRACE(("%s: set band %d OK\n", __FUNCTION__, band));
1250 else WL_ERROR(("%s: set band %d failed code %d\n", __FUNCTION__, \
1253 else WL_ERROR(("%s Incorrect band setting %d, ignored\n", __FUNCTION__, band));
1256 p += snprintf(p, MAX_WX_STRING, "FAIL");
1259 wrqu->data.length = p - extra + 1;
1260 net_os_wake_unlock(dev);
1267 wl_iw_set_pno_reset(
1268 struct net_device *dev,
1269 struct iw_request_info *info,
1270 union iwreq_data *wrqu,
1277 net_os_wake_lock(dev);
1278 if ((g_onoff == G_WLAN_SET_ON) && (dev != NULL)) {
1280 if ((error = dhd_dev_pno_reset(dev)) >= 0) {
1281 p += snprintf(p, MAX_WX_STRING, "OK");
1282 WL_TRACE(("%s: set OK\n", __FUNCTION__));
1285 else WL_ERROR(("%s: failed code %d\n", __FUNCTION__, error));
1288 p += snprintf(p, MAX_WX_STRING, "FAIL");
1291 wrqu->data.length = p - extra + 1;
1292 net_os_wake_unlock(dev);
1299 wl_iw_set_pno_enable(
1300 struct net_device *dev,
1301 struct iw_request_info *info,
1302 union iwreq_data *wrqu,
1310 net_os_wake_lock(dev);
1311 pfn_enabled = htod32((uint)*(extra + strlen(PNOENABLE_SET_CMD) + 1) - '0');
1313 if ((g_onoff == G_WLAN_SET_ON) && (dev != NULL)) {
1315 if ((error = dhd_dev_pno_enable(dev, pfn_enabled)) >= 0) {
1316 p += snprintf(p, MAX_WX_STRING, "OK");
1317 WL_TRACE(("%s: set OK\n", __FUNCTION__));
1320 else WL_ERROR(("%s: failed code %d\n", __FUNCTION__, error));
1323 p += snprintf(p, MAX_WX_STRING, "FAIL");
1326 wrqu->data.length = p - extra + 1;
1327 net_os_wake_unlock(dev);
1335 struct net_device *dev,
1336 struct iw_request_info *info,
1337 union iwreq_data *wrqu,
1342 wlc_ssid_t ssids_local[MAX_PFN_LIST_COUNT];
1344 cmd_tlv_t *cmd_tlv_temp;
1350 #ifdef PNO_SET_DEBUG
1352 char pno_in_example[] = {'P', 'N', 'O', 'S', 'E', 'T', 'U', 'P', ' ', \
1366 net_os_wake_lock(dev);
1367 WL_ERROR(("\n### %s: info->cmd:%x, info->flags:%x, u.data=0x%p, u.len=%d\n",
1368 __FUNCTION__, info->cmd, info->flags,
1369 wrqu->data.pointer, wrqu->data.length));
1371 if (g_onoff == G_WLAN_SET_OFF) {
1372 WL_TRACE(("%s: driver is not up yet after START\n", __FUNCTION__));
1376 if (wrqu->data.length < (strlen(PNOSETUP_SET_CMD) + sizeof(cmd_tlv_t))) {
1377 WL_ERROR(("%s aggument=%d less %d\n", __FUNCTION__, \
1378 wrqu->data.length, strlen(PNOSETUP_SET_CMD) + sizeof(cmd_tlv_t)));
1382 #ifdef PNO_SET_DEBUG
1383 if (!(extra = kmalloc(sizeof(pno_in_example) +100, GFP_KERNEL))) {
1387 memcpy(extra, pno_in_example, sizeof(pno_in_example));
1388 wrqu->data.length = sizeof(pno_in_example);
1389 for (i = 0; i < wrqu->data.length; i++)
1390 printf("%02X ", extra[i]);
1395 #ifdef PNO_SET_DEBUG
1396 str_ptr += strlen("PNOSETUP ");
1397 tlv_size_left = wrqu->data.length - strlen("PNOSETUP ");
1399 str_ptr += strlen(PNOSETUP_SET_CMD);
1400 tlv_size_left = wrqu->data.length - strlen(PNOSETUP_SET_CMD);
1403 cmd_tlv_temp = (cmd_tlv_t *)str_ptr;
1404 memset(ssids_local, 0, sizeof(ssids_local));
1406 if ((cmd_tlv_temp->prefix == PNO_TLV_PREFIX) && \
1407 (cmd_tlv_temp->version == PNO_TLV_VERSION) && \
1408 (cmd_tlv_temp->subver == PNO_TLV_SUBVERSION))
1410 str_ptr += sizeof(cmd_tlv_t);
1411 tlv_size_left -= sizeof(cmd_tlv_t);
1413 if ((nssid = wl_iw_parse_ssid_list_tlv(&str_ptr, ssids_local, \
1414 MAX_PFN_LIST_COUNT, &tlv_size_left)) <= 0) {
1415 WL_ERROR(("SSID is not presented or corrupted ret=%d\n", nssid));
1419 if ((str_ptr[0] != PNO_TLV_TYPE_TIME) || (tlv_size_left <= 1)) {
1420 WL_ERROR(("%s scan duration corrupted field size %d\n", \
1421 __FUNCTION__, tlv_size_left));
1425 pno_time = simple_strtoul(str_ptr, &str_ptr_end, 16);
1426 WL_ERROR((" got %d bytes left pno_time %d or %#x\n", \
1427 tlv_size_left, pno_time, pno_time));
1431 WL_ERROR(("%s get wrong TLV command\n", __FUNCTION__));
1435 res = dhd_dev_pno_set(dev, ssids_local, nssid, pno_time);
1438 net_os_wake_unlock(dev);
1445 struct net_device *dev,
1446 struct iw_request_info *info,
1447 union iwreq_data *wrqu,
1451 static int rssi = 0;
1452 static wlc_ssid_t ssid = {0};
1455 static char ssidbuf[SSID_FMT_BUF_LEN];
1458 net_os_wake_lock(dev);
1460 bzero(&scb_val, sizeof(scb_val_t));
1462 if (g_onoff == G_WLAN_SET_ON) {
1463 error = dev_wlc_ioctl(dev, WLC_GET_RSSI, &scb_val, sizeof(scb_val_t));
1465 WL_ERROR(("%s: Fails %d\n", __FUNCTION__, error));
1467 rssi = dtoh32(scb_val.val);
1469 error = dev_wlc_ioctl(dev, WLC_GET_SSID, &ssid, sizeof(ssid));
1471 ssid.SSID_len = dtoh32(ssid.SSID_len);
1472 wl_format_ssid(ssidbuf, ssid.SSID, dtoh32(ssid.SSID_len));
1477 WL_ASSOC(("%s ssid_len:%d, rssi:%d\n", __FUNCTION__, ssid.SSID_len, rssi));
1479 if (error || (ssid.SSID_len == 0)) {
1480 p += snprintf(p, MAX_WX_STRING, "FAIL");
1482 p += snprintf(p, MAX_WX_STRING, "%s rssi %d ", ssidbuf, rssi);
1484 wrqu->data.length = p - extra + 1;
1486 net_os_wake_unlock(dev);
1491 wl_iw_send_priv_event(
1492 struct net_device *dev,
1496 union iwreq_data wrqu;
1497 char extra[IW_CUSTOM_MAX + 1];
1501 memset(&wrqu, 0, sizeof(wrqu));
1502 if (strlen(flag) > sizeof(extra))
1505 strcpy(extra, flag);
1506 wrqu.data.length = strlen(extra);
1507 wireless_send_event(dev, cmd, &wrqu, extra);
1508 net_os_wake_lock_timeout_enable(dev);
1509 WL_TRACE(("Send IWEVCUSTOM Event as %s\n", extra));
1516 wl_control_wl_start(struct net_device *dev)
1521 WL_TRACE(("Enter %s \n", __FUNCTION__));
1524 WL_ERROR(("%s: dev is null\n", __FUNCTION__));
1528 iw = *(wl_iw_t **)netdev_priv(dev);
1531 WL_ERROR(("%s: wl is null\n", __FUNCTION__));
1534 dhd_os_start_lock(iw->pub);
1536 if (g_onoff == G_WLAN_SET_OFF) {
1537 dhd_customer_gpio_wlan_ctrl(WLAN_RESET_ON);
1539 #if defined(BCMLXSDMMC)
1540 sdioh_start(NULL, 0);
1543 ret = dhd_dev_reset(dev, 0);
1545 if (ret == BCME_OK) {
1546 #if defined(BCMLXSDMMC)
1547 sdioh_start(NULL, 1);
1549 dhd_dev_init_ioctl(dev);
1550 g_onoff = G_WLAN_SET_ON;
1553 WL_TRACE(("Exited %s \n", __FUNCTION__));
1555 dhd_os_start_unlock(iw->pub);
1561 wl_iw_control_wl_off(
1562 struct net_device *dev,
1563 struct iw_request_info *info
1569 WL_TRACE(("Enter %s\n", __FUNCTION__));
1572 WL_ERROR(("%s: dev is null\n", __FUNCTION__));
1576 iw = *(wl_iw_t **)netdev_priv(dev);
1578 WL_ERROR(("%s: dev is null\n", __FUNCTION__));
1581 dhd_os_start_lock(iw->pub);
1584 ap_cfg_running = FALSE;
1587 if (g_onoff == G_WLAN_SET_ON) {
1588 g_onoff = G_WLAN_SET_OFF;
1589 #if defined(WL_IW_USE_ISCAN)
1590 g_iscan->iscan_state = ISCAN_STATE_IDLE;
1593 dhd_dev_reset(dev, 1);
1595 #if defined(WL_IW_USE_ISCAN)
1597 wl_iw_free_ss_cache();
1598 wl_iw_run_ss_cache_timer(0);
1600 g_ss_cache_ctrl.m_link_down = 1;
1602 memset(g_scan, 0, G_SCAN_RESULTS);
1603 g_scan_specified_ssid = 0;
1604 #if defined(CONFIG_FIRST_SCAN)
1605 g_first_broadcast_scan = BROADCAST_SCAN_FIRST_IDLE;
1606 g_first_counter_scans = 0;
1610 #if defined(BCMLXSDMMC)
1614 net_os_set_dtim_skip(dev, 0);
1616 dhd_customer_gpio_wlan_ctrl(WLAN_RESET_OFF);
1618 wl_iw_send_priv_event(dev, "STOP");
1621 dhd_os_start_unlock(iw->pub);
1623 WL_TRACE(("Exited %s\n", __FUNCTION__));
1629 wl_iw_control_wl_on(
1630 struct net_device *dev,
1631 struct iw_request_info *info
1636 WL_TRACE(("Enter %s \n", __FUNCTION__));
1638 if ((ret = wl_control_wl_start(dev)) != BCME_OK) {
1639 WL_ERROR(("%s failed first attemp\n", __FUNCTION__));
1640 dhd_customer_gpio_wlan_ctrl(WLAN_RESET_OFF);
1641 if ((ret = wl_control_wl_start(dev)) != BCME_OK) {
1642 WL_ERROR(("%s failed second attemp\n", __FUNCTION__));
1643 net_os_send_hang_message(dev);
1648 wl_iw_send_priv_event(dev, "START");
1651 if (!ap_fw_loaded) {
1652 wl_iw_iscan_set_scan_broadcast_prep(dev, 0);
1655 wl_iw_iscan_set_scan_broadcast_prep(dev, 0);
1658 WL_TRACE(("Exited %s \n", __FUNCTION__));
1664 static struct ap_profile my_ap;
1665 static int set_ap_cfg(struct net_device *dev, struct ap_profile *ap);
1666 static int get_assoc_sta_list(struct net_device *dev, char *buf, int len);
1667 static int set_ap_mac_list(struct net_device *dev, void *buf);
1669 #define PTYPE_STRING 0
1670 #define PTYPE_INTDEC 1
1671 #define PTYPE_INTHEX 2
1672 #define PTYPE_STR_HEX 3
1673 int get_parmeter_from_string(
1674 char **str_ptr, const char *token, int param_type, void *dst, int param_max_len);
1680 if (c >= '0' && c <= '9')
1682 if (c >= 'a' && c <= 'f')
1683 return c - 'a' + 10;
1684 if (c >= 'A' && c <= 'F')
1685 return c - 'A' + 10;
1689 int hex2byte(const char *hex)
1692 a = hex2num(*hex++);
1695 b = hex2num(*hex++);
1698 return (a << 4) | b;
1703 int hstr_2_buf(const char *txt, u8 *buf, int len)
1707 for (i = 0; i < len; i++) {
1710 a = hex2num(*txt++);
1713 b = hex2num(*txt++);
1716 *buf++ = (a << 4) | b;
1723 int init_ap_profile_from_string(char *param_str, struct ap_profile *ap_cfg)
1725 char *str_ptr = param_str;
1729 memset(sub_cmd, 0, sizeof(sub_cmd));
1730 memset(ap_cfg, 0, sizeof(struct ap_profile));
1732 if (get_parmeter_from_string(&str_ptr, "ASCII_CMD=",
1733 PTYPE_STRING, sub_cmd, SSID_LEN) != 0) {
1736 if (strncmp(sub_cmd, "AP_CFG", 6)) {
1737 WL_ERROR(("ERROR: sub_cmd:%s != 'AP_CFG'!\n", sub_cmd));
1741 ret = get_parmeter_from_string(&str_ptr, "SSID=", PTYPE_STRING, ap_cfg->ssid, SSID_LEN);
1743 ret |= get_parmeter_from_string(&str_ptr, "SEC=", PTYPE_STRING, ap_cfg->sec, SEC_LEN);
1745 ret |= get_parmeter_from_string(&str_ptr, "KEY=", PTYPE_STRING, ap_cfg->key, KEY_LEN);
1747 ret |= get_parmeter_from_string(&str_ptr, "CHANNEL=", PTYPE_INTDEC, &ap_cfg->channel, 5);
1749 get_parmeter_from_string(&str_ptr, "PREAMBLE=", PTYPE_INTDEC, &ap_cfg->preamble, 5);
1751 get_parmeter_from_string(&str_ptr, "MAX_SCB=", PTYPE_INTDEC, &ap_cfg->max_scb, 5);
1753 get_parmeter_from_string(&str_ptr, "HIDDEN=", PTYPE_INTDEC, &ap_cfg->closednet, 5);
1755 get_parmeter_from_string(&str_ptr, "COUNTRY=", PTYPE_STRING, &ap_cfg->country_code, 3);
1763 static int iwpriv_set_ap_config(struct net_device *dev,
1764 struct iw_request_info *info,
1765 union iwreq_data *wrqu,
1770 struct ap_profile *ap_cfg = &my_ap;
1772 WL_TRACE(("%s: info->cmd:%x, info->flags:%x, u.data:%p, u.len:%d\n",
1774 info->cmd, info->flags,
1775 wrqu->data.pointer, wrqu->data.length));
1777 if (wrqu->data.length != 0) {
1781 if (!(extra = kmalloc(wrqu->data.length+1, GFP_KERNEL)))
1784 if (copy_from_user(extra, wrqu->data.pointer, wrqu->data.length)) {
1789 extra[wrqu->data.length] = 0;
1790 WL_SOFTAP((" Got str param in iw_point:\n %s\n", extra));
1792 memset(ap_cfg, 0, sizeof(struct ap_profile));
1796 if ((res = init_ap_profile_from_string(extra, ap_cfg)) < 0) {
1797 WL_ERROR(("%s failed to parse %d\n", __FUNCTION__, res));
1803 WL_ERROR(("IWPRIV argument len = 0 \n"));
1807 if ((res = set_ap_cfg(dev, ap_cfg)) < 0)
1808 WL_ERROR(("%s failed to set_ap_cfg %d\n", __FUNCTION__, res));
1818 static int iwpriv_get_assoc_list(struct net_device *dev,
1819 struct iw_request_info *info,
1820 union iwreq_data *p_iwrq,
1825 struct maclist *sta_maclist = (struct maclist *)mac_buf;
1829 char *p_mac_str_end;
1831 if ((!dev) || (!extra)) {
1835 net_os_wake_lock(dev);
1837 WL_TRACE(("\n %s: IWPRIV IOCTL: cmd:%hx, flags:%hx, extra:%p, iwp.len:%d, \
1838 iwp.len:%p, iwp.flags:%x \n", __FUNCTION__, info->cmd, info->flags, \
1839 extra, p_iwrq->data.length, p_iwrq->data.pointer, p_iwrq->data.flags));
1841 memset(sta_maclist, 0, sizeof(mac_buf));
1843 sta_maclist->count = 8;
1845 WL_SOFTAP(("%s: net device:%s, buf_sz:%d\n",
1846 __FUNCTION__, dev->name, sizeof(mac_buf)));
1848 if ((ret = get_assoc_sta_list(dev, mac_buf, sizeof(mac_buf))) < 0) {
1849 WL_ERROR(("%s: sta list ioctl error:%d\n",
1850 __FUNCTION__, ret));
1854 WL_SOFTAP(("%s: got %d stations\n", __FUNCTION__,
1855 sta_maclist->count));
1857 memset(mac_lst, 0, sizeof(mac_lst));
1858 p_mac_str = mac_lst;
1859 p_mac_str_end = &mac_lst[sizeof(mac_lst)-1];
1861 for (i = 0; i < 8; i++) {
1862 struct ether_addr *id = &sta_maclist->ea[i];
1863 if (!ETHER_ISNULLADDR(id->octet)) {
1867 bzero(&scb_val, sizeof(scb_val_t));
1869 if ((p_mac_str_end - p_mac_str) <= 36) {
1870 WL_ERROR(("%s: mac list buf is < 36 for item[%i] item\n",
1875 p_mac_str += snprintf(p_mac_str, MAX_WX_STRING,
1876 "\nMac[%d]=%02X:%02X:%02X:%02X:%02X:%02X,", i,
1877 id->octet[0], id->octet[1], id->octet[2],
1878 id->octet[3], id->octet[4], id->octet[5]);
1880 bcopy(id->octet, &scb_val.ea, 6);
1881 ret = dev_wlc_ioctl(dev, WLC_GET_RSSI, &scb_val, sizeof(scb_val_t));
1883 snprintf(p_mac_str, MAX_WX_STRING, "RSSI:ERR");
1884 WL_ERROR(("%s: RSSI ioctl error:%d\n",
1885 __FUNCTION__, ret));
1889 rssi = dtoh32(scb_val.val);
1890 p_mac_str += snprintf(p_mac_str, MAX_WX_STRING,
1895 p_iwrq->data.length = strlen(mac_lst) + 1;
1897 WL_SOFTAP(("%s: data to user:\n%s\n usr_ptr:%p\n", __FUNCTION__,
1898 mac_lst, p_iwrq->data.pointer));
1900 if (p_iwrq->data.length) {
1901 bcopy(mac_lst, extra, p_iwrq->data.length);
1905 net_os_wake_unlock(dev);
1907 WL_TRACE(("Exited %s \n", __FUNCTION__));
1914 #define MAC_FILT_MAX 8
1915 static int iwpriv_set_mac_filters(struct net_device *dev,
1916 struct iw_request_info *info,
1917 union iwreq_data *wrqu,
1921 char * extra = NULL;
1924 struct ether_addr *p_ea;
1925 struct mac_list_set mflist_set;
1927 WL_SOFTAP((">>> Got IWPRIV SET_MAC_FILTER IOCTL: info->cmd:%x, \
1928 info->flags:%x, u.data:%p, u.len:%d\n",
1929 info->cmd, info->flags,
1930 wrqu->data.pointer, wrqu->data.length));
1932 if (wrqu->data.length != 0) {
1936 if (!(extra = kmalloc(wrqu->data.length+1, GFP_KERNEL)))
1939 if (copy_from_user(extra, wrqu->data.pointer, wrqu->data.length)) {
1944 extra[wrqu->data.length] = 0;
1945 WL_SOFTAP((" Got parameter string in iw_point:\n %s \n", extra));
1947 memset(&mflist_set, 0, sizeof(mflist_set));
1951 if (get_parmeter_from_string(&str_ptr, "MAC_MODE=",
1952 PTYPE_INTDEC, &mac_mode, 4) != 0) {
1953 WL_ERROR(("ERROR: 'MAC_MODE=' token is missing\n"));
1957 p_ea = &mflist_set.mac_list.ea[0];
1959 if (get_parmeter_from_string(&str_ptr, "MAC_CNT=",
1960 PTYPE_INTDEC, &mac_cnt, 4) != 0) {
1961 WL_ERROR(("ERROR: 'MAC_CNT=' token param is missing \n"));
1965 if (mac_cnt > MAC_FILT_MAX) {
1966 WL_ERROR(("ERROR: number of MAC filters > MAX\n"));
1970 for (i=0; i < mac_cnt; i++)
1971 if (get_parmeter_from_string(&str_ptr, "MAC=",
1972 PTYPE_STR_HEX, &p_ea[i], 12) != 0) {
1973 WL_ERROR(("ERROR: MAC_filter[%d] is missing !\n", i));
1977 WL_SOFTAP(("MAC_MODE=:%d, MAC_CNT=%d, MACs:..\n", mac_mode, mac_cnt));
1978 for (i = 0; i < mac_cnt; i++) {
1979 WL_SOFTAP(("mac_filt[%d]:", i));
1980 print_buf(&p_ea[i], 6, 0);
1983 mflist_set.mode = mac_mode;
1984 mflist_set.mac_list.count = mac_cnt;
1985 set_ap_mac_list(dev, &mflist_set);
1987 wrqu->data.pointer = NULL;
1988 wrqu->data.length = 0;
1992 WL_ERROR(("IWPRIV argument len is 0\n"));
2004 static int iwpriv_set_ap_sta_disassoc(struct net_device *dev,
2005 struct iw_request_info *info,
2006 union iwreq_data *wrqu,
2010 char sta_mac[6] = {0, 0, 0, 0, 0, 0};
2012 char *str_ptr = cmd_buf;
2014 WL_SOFTAP((">>%s called\n args: info->cmd:%x,"
2015 " info->flags:%x, u.data.p:%p, u.data.len:%d\n",
2016 __FUNCTION__, info->cmd, info->flags,
2017 wrqu->data.pointer, wrqu->data.length));
2019 if (wrqu->data.length != 0) {
2021 if (copy_from_user(cmd_buf, wrqu->data.pointer, wrqu->data.length)) {
2025 if (get_parmeter_from_string(&str_ptr,
2026 "MAC=", PTYPE_STR_HEX, sta_mac, 12) == 0) {
2027 res = wl_iw_softap_deassoc_stations(dev, sta_mac);
2029 WL_ERROR(("ERROR: STA_MAC= token not found\n"));
2040 #if WIRELESS_EXT < 13
2041 struct iw_request_info
2047 typedef int (*iw_handler)(struct net_device *dev,
2048 struct iw_request_info *info,
2054 wl_iw_config_commit(
2055 struct net_device *dev,
2056 struct iw_request_info *info,
2063 struct sockaddr bssid;
2065 WL_TRACE(("%s: SIOCSIWCOMMIT\n", dev->name));
2067 if ((error = dev_wlc_ioctl(dev, WLC_GET_SSID, &ssid, sizeof(ssid))))
2070 ssid.SSID_len = dtoh32(ssid.SSID_len);
2075 bzero(&bssid, sizeof(struct sockaddr));
2076 if ((error = dev_wlc_ioctl(dev, WLC_REASSOC, &bssid, ETHER_ADDR_LEN))) {
2077 WL_ERROR(("%s: WLC_REASSOC to %s failed \n", __FUNCTION__, ssid.SSID));
2086 struct net_device *dev,
2087 struct iw_request_info *info,
2092 WL_TRACE(("%s: SIOCGIWNAME\n", dev->name));
2094 strcpy(cwrq, "IEEE 802.11-DS");
2101 struct net_device *dev,
2102 struct iw_request_info *info,
2103 struct iw_freq *fwrq,
2110 WL_TRACE(("%s %s: SIOCSIWFREQ\n", __FUNCTION__, dev->name));
2113 if (ap_cfg_running) {
2114 WL_TRACE(("%s:>> not executed, 'SOFT_AP is active' \n", __FUNCTION__));
2120 if (fwrq->e == 0 && fwrq->m < MAXCHANNEL) {
2131 } else if (fwrq->e < 6) {
2132 while (fwrq->e++ < 6)
2136 if (fwrq->m > 4000 && fwrq->m < 5000)
2137 sf = WF_CHAN_FACTOR_4_G;
2139 chan = wf_mhz2channel(fwrq->m, sf);
2141 chan = htod32(chan);
2142 if ((error = dev_wlc_ioctl(dev, WLC_SET_CHANNEL, &chan, sizeof(chan))))
2145 g_wl_iw_params.target_channel = chan;
2147 return -EINPROGRESS;
2152 struct net_device *dev,
2153 struct iw_request_info *info,
2154 struct iw_freq *fwrq,
2161 WL_TRACE(("%s: SIOCGIWFREQ\n", dev->name));
2163 if ((error = dev_wlc_ioctl(dev, WLC_GET_CHANNEL, &ci, sizeof(ci))))
2166 fwrq->m = dtoh32(ci.hw_channel);
2167 fwrq->e = dtoh32(0);
2173 struct net_device *dev,
2174 struct iw_request_info *info,
2179 int infra = 0, ap = 0, error = 0;
2181 WL_TRACE(("%s: SIOCSIWMODE\n", dev->name));
2184 case IW_MODE_MASTER:
2196 infra = htod32(infra);
2199 if ((error = dev_wlc_ioctl(dev, WLC_SET_INFRA, &infra, sizeof(infra))) ||
2200 (error = dev_wlc_ioctl(dev, WLC_SET_AP, &ap, sizeof(ap))))
2204 return -EINPROGRESS;
2209 struct net_device *dev,
2210 struct iw_request_info *info,
2215 int error, infra = 0, ap = 0;
2217 WL_TRACE(("%s: SIOCGIWMODE\n", dev->name));
2219 if ((error = dev_wlc_ioctl(dev, WLC_GET_INFRA, &infra, sizeof(infra))) ||
2220 (error = dev_wlc_ioctl(dev, WLC_GET_AP, &ap, sizeof(ap))))
2223 infra = dtoh32(infra);
2225 *uwrq = infra ? ap ? IW_MODE_MASTER : IW_MODE_INFRA : IW_MODE_ADHOC;
2232 struct net_device *dev,
2233 struct iw_request_info *info,
2234 struct iw_point *dwrq,
2238 struct iw_range *range = (struct iw_range *) extra;
2239 wl_uint32_list_t *list;
2240 wl_rateset_t rateset;
2246 int bw_cap = 0, sgi_tx = 0, nmode = 0;
2248 uint8 nrate_list2copy = 0;
2249 uint16 nrate_list[4][8] = { {13, 26, 39, 52, 78, 104, 117, 130},
2250 {14, 29, 43, 58, 87, 116, 130, 144},
2251 {27, 54, 81, 108, 162, 216, 243, 270},
2252 {30, 60, 90, 120, 180, 240, 270, 300}};
2254 WL_TRACE(("%s: SIOCGIWRANGE\n", dev->name));
2259 channels = kmalloc((MAXCHANNEL+1)*4, GFP_KERNEL);
2261 WL_ERROR(("Could not alloc channels\n"));
2264 list = (wl_uint32_list_t *)channels;
2266 dwrq->length = sizeof(struct iw_range);
2267 memset(range, 0, sizeof(range));
2269 range->min_nwid = range->max_nwid = 0;
2271 list->count = htod32(MAXCHANNEL);
2272 if ((error = dev_wlc_ioctl(dev, WLC_GET_VALID_CHANNELS, channels, (MAXCHANNEL+1)*4))) {
2276 for (i = 0; i < dtoh32(list->count) && i < IW_MAX_FREQUENCIES; i++) {
2277 range->freq[i].i = dtoh32(list->element[i]);
2279 ch = dtoh32(list->element[i]);
2280 if (ch <= CH_MAX_2G_CHANNEL)
2281 sf = WF_CHAN_FACTOR_2_4_G;
2283 sf = WF_CHAN_FACTOR_5_G;
2285 range->freq[i].m = wf_channel2mhz(ch, sf);
2286 range->freq[i].e = 6;
2288 range->num_frequency = range->num_channels = i;
2290 range->max_qual.qual = 5;
2292 range->max_qual.level = 0x100 - 200;
2294 range->max_qual.noise = 0x100 - 200;
2296 range->sensitivity = 65535;
2298 #if WIRELESS_EXT > 11
2300 range->avg_qual.qual = 3;
2302 range->avg_qual.level = 0x100 + WL_IW_RSSI_GOOD;
2304 range->avg_qual.noise = 0x100 - 75;
2307 if ((error = dev_wlc_ioctl(dev, WLC_GET_CURR_RATESET, &rateset, sizeof(rateset)))) {
2311 rateset.count = dtoh32(rateset.count);
2312 range->num_bitrates = rateset.count;
2313 for (i = 0; i < rateset.count && i < IW_MAX_BITRATES; i++)
2314 range->bitrate[i] = (rateset.rates[i]& 0x7f) * 500000;
2315 dev_wlc_intvar_get(dev, "nmode", &nmode);
2316 dev_wlc_ioctl(dev, WLC_GET_PHYTYPE, &phytype, sizeof(phytype));
2318 if (nmode == 1 && phytype == WLC_PHY_TYPE_SSN) {
2319 dev_wlc_intvar_get(dev, "mimo_bw_cap", &bw_cap);
2320 dev_wlc_intvar_get(dev, "sgi_tx", &sgi_tx);
2321 dev_wlc_ioctl(dev, WLC_GET_CHANNEL, &ci, sizeof(channel_info_t));
2322 ci.hw_channel = dtoh32(ci.hw_channel);
2325 (bw_cap == 2 && ci.hw_channel <= 14)) {
2327 nrate_list2copy = 0;
2329 nrate_list2copy = 1;
2332 (bw_cap == 2 && ci.hw_channel >= 36)) {
2334 nrate_list2copy = 2;
2336 nrate_list2copy = 3;
2338 range->num_bitrates += 8;
2339 for (k = 0; i < range->num_bitrates; k++, i++) {
2341 range->bitrate[i] = (nrate_list[nrate_list2copy][k]) * 500000;
2345 if ((error = dev_wlc_ioctl(dev, WLC_GET_PHYTYPE, &i, sizeof(i)))) {
2350 if (i == WLC_PHY_TYPE_A)
2351 range->throughput = 24000000;
2353 range->throughput = 1500000;
2356 range->max_rts = 2347;
2357 range->min_frag = 256;
2358 range->max_frag = 2346;
2360 range->max_encoding_tokens = DOT11_MAX_DEFAULT_KEYS;
2361 range->num_encoding_sizes = 4;
2362 range->encoding_size[0] = WEP1_KEY_SIZE;
2363 range->encoding_size[1] = WEP128_KEY_SIZE;
2364 #if WIRELESS_EXT > 17
2365 range->encoding_size[2] = TKIP_KEY_SIZE;
2367 range->encoding_size[2] = 0;
2369 range->encoding_size[3] = AES_KEY_SIZE;
2375 range->pmp_flags = 0;
2378 range->num_txpower = 2;
2379 range->txpower[0] = 1;
2380 range->txpower[1] = 255;
2381 range->txpower_capa = IW_TXPOW_MWATT;
2383 #if WIRELESS_EXT > 10
2384 range->we_version_compiled = WIRELESS_EXT;
2385 range->we_version_source = 19;
2387 range->retry_capa = IW_RETRY_LIMIT;
2388 range->retry_flags = IW_RETRY_LIMIT;
2389 range->r_time_flags = 0;
2391 range->min_retry = 1;
2392 range->max_retry = 255;
2394 range->min_r_time = 0;
2395 range->max_r_time = 0;
2398 #if WIRELESS_EXT > 17
2399 range->enc_capa = IW_ENC_CAPA_WPA;
2400 range->enc_capa |= IW_ENC_CAPA_CIPHER_TKIP;
2401 range->enc_capa |= IW_ENC_CAPA_CIPHER_CCMP;
2403 range->enc_capa |= IW_ENC_CAPA_WPA2;
2406 IW_EVENT_CAPA_SET_KERNEL(range->event_capa);
2408 IW_EVENT_CAPA_SET(range->event_capa, SIOCGIWAP);
2409 IW_EVENT_CAPA_SET(range->event_capa, SIOCGIWSCAN);
2410 IW_EVENT_CAPA_SET(range->event_capa, IWEVTXDROP);
2411 IW_EVENT_CAPA_SET(range->event_capa, IWEVMICHAELMICFAILURE);
2413 IW_EVENT_CAPA_SET(range->event_capa, IWEVPMKIDCAND);
2423 rssi_to_qual(int rssi)
2425 if (rssi <= WL_IW_RSSI_NO_SIGNAL)
2427 else if (rssi <= WL_IW_RSSI_VERY_LOW)
2429 else if (rssi <= WL_IW_RSSI_LOW)
2431 else if (rssi <= WL_IW_RSSI_GOOD)
2433 else if (rssi <= WL_IW_RSSI_VERY_GOOD)
2441 struct net_device *dev,
2442 struct iw_request_info *info,
2443 struct iw_point *dwrq,
2447 wl_iw_t *iw = *(wl_iw_t **)netdev_priv(dev);
2448 struct sockaddr *addr = (struct sockaddr *) extra;
2451 WL_TRACE(("%s: SIOCSIWSPY\n", dev->name));
2456 iw->spy_num = MIN(ARRAYSIZE(iw->spy_addr), dwrq->length);
2457 for (i = 0; i < iw->spy_num; i++)
2458 memcpy(&iw->spy_addr[i], addr[i].sa_data, ETHER_ADDR_LEN);
2459 memset(iw->spy_qual, 0, sizeof(iw->spy_qual));
2466 struct net_device *dev,
2467 struct iw_request_info *info,
2468 struct iw_point *dwrq,
2472 wl_iw_t *iw = *(wl_iw_t **)netdev_priv(dev);
2473 struct sockaddr *addr = (struct sockaddr *) extra;
2474 struct iw_quality *qual = (struct iw_quality *) &addr[iw->spy_num];
2477 WL_TRACE(("%s: SIOCGIWSPY\n", dev->name));
2482 dwrq->length = iw->spy_num;
2483 for (i = 0; i < iw->spy_num; i++) {
2484 memcpy(addr[i].sa_data, &iw->spy_addr[i], ETHER_ADDR_LEN);
2485 addr[i].sa_family = AF_UNIX;
2486 memcpy(&qual[i], &iw->spy_qual[i], sizeof(struct iw_quality));
2487 iw->spy_qual[i].updated = 0;
2495 wl_iw_ch_to_chanspec(int ch, wl_join_params_t *join_params, int *join_params_size)
2497 chanspec_t chanspec = 0;
2501 join_params->params.chanspec_num = 1;
2502 join_params->params.chanspec_list[0] = ch;
2504 if (join_params->params.chanspec_list[0])
2505 chanspec |= WL_CHANSPEC_BAND_2G;
2507 chanspec |= WL_CHANSPEC_BAND_5G;
2509 chanspec |= WL_CHANSPEC_BW_20;
2510 chanspec |= WL_CHANSPEC_CTL_SB_NONE;
2512 *join_params_size += WL_ASSOC_PARAMS_FIXED_SIZE +
2513 join_params->params.chanspec_num * sizeof(chanspec_t);
2515 join_params->params.chanspec_list[0] &= WL_CHANSPEC_CHAN_MASK;
2516 join_params->params.chanspec_list[0] |= chanspec;
2517 join_params->params.chanspec_list[0] =
2518 htodchanspec(join_params->params.chanspec_list[0]);
2520 join_params->params.chanspec_num = htod32(join_params->params.chanspec_num);
2522 WL_TRACE(("%s join_params->params.chanspec_list[0]= %X\n", \
2523 __FUNCTION__, join_params->params.chanspec_list[0]));
2530 struct net_device *dev,
2531 struct iw_request_info *info,
2532 struct sockaddr *awrq,
2536 int error = -EINVAL;
2537 wl_join_params_t join_params;
2538 int join_params_size;
2540 WL_TRACE(("%s: SIOCSIWAP\n", dev->name));
2542 if (awrq->sa_family != ARPHRD_ETHER) {
2543 WL_ERROR(("Invalid Header...sa_family\n"));
2548 if (ETHER_ISBCAST(awrq->sa_data) || ETHER_ISNULLADDR(awrq->sa_data)) {
2551 bzero(&scbval, sizeof(scb_val_t));
2553 (void) dev_wlc_ioctl(dev, WLC_DISASSOC, &scbval, sizeof(scb_val_t));
2559 memset(&join_params, 0, sizeof(join_params));
2560 join_params_size = sizeof(join_params.ssid);
2562 memcpy(join_params.ssid.SSID, g_ssid.SSID, g_ssid.SSID_len);
2563 join_params.ssid.SSID_len = htod32(g_ssid.SSID_len);
2564 memcpy(&join_params.params.bssid, awrq->sa_data, ETHER_ADDR_LEN);
2566 WL_ASSOC(("%s target_channel=%d\n", __FUNCTION__, g_wl_iw_params.target_channel));
2567 wl_iw_ch_to_chanspec(g_wl_iw_params.target_channel, &join_params, &join_params_size);
2569 if ((error = dev_wlc_ioctl(dev, WLC_SET_SSID, &join_params, join_params_size))) {
2570 WL_ERROR(("%s Invalid ioctl data=%d\n", __FUNCTION__, error));
2574 if (g_ssid.SSID_len) {
2575 WL_ASSOC(("%s: join SSID=%s BSSID="MACSTR" ch=%d\n", __FUNCTION__, \
2576 g_ssid.SSID, MAC2STR((u8 *)awrq->sa_data), \
2577 g_wl_iw_params.target_channel));
2581 memset(&g_ssid, 0, sizeof(g_ssid));
2587 struct net_device *dev,
2588 struct iw_request_info *info,
2589 struct sockaddr *awrq,
2593 WL_TRACE(("%s: SIOCGIWAP\n", dev->name));
2595 awrq->sa_family = ARPHRD_ETHER;
2596 memset(awrq->sa_data, 0, ETHER_ADDR_LEN);
2599 (void) dev_wlc_ioctl(dev, WLC_GET_BSSID, awrq->sa_data, ETHER_ADDR_LEN);
2604 #if WIRELESS_EXT > 17
2607 struct net_device *dev,
2608 struct iw_request_info *info,
2609 struct sockaddr *awrq,
2613 struct iw_mlme *mlme;
2615 int error = -EINVAL;
2617 WL_TRACE(("%s: SIOCSIWMLME DISASSOC/DEAUTH\n", dev->name));
2619 mlme = (struct iw_mlme *)extra;
2621 WL_ERROR(("Invalid ioctl data.\n"));
2625 scbval.val = mlme->reason_code;
2626 bcopy(&mlme->addr.sa_data, &scbval.ea, ETHER_ADDR_LEN);
2628 if (mlme->cmd == IW_MLME_DISASSOC) {
2629 scbval.val = htod32(scbval.val);
2630 error = dev_wlc_ioctl(dev, WLC_DISASSOC, &scbval, sizeof(scb_val_t));
2632 else if (mlme->cmd == IW_MLME_DEAUTH) {
2633 scbval.val = htod32(scbval.val);
2634 error = dev_wlc_ioctl(dev, WLC_SCB_DEAUTHENTICATE_FOR_REASON, &scbval,
2638 WL_ERROR(("Invalid ioctl data.\n"));
2646 #ifndef WL_IW_USE_ISCAN
2649 struct net_device *dev,
2650 struct iw_request_info *info,
2651 struct iw_point *dwrq,
2655 wl_scan_results_t *list;
2656 struct sockaddr *addr = (struct sockaddr *) extra;
2657 struct iw_quality qual[IW_MAX_AP];
2658 wl_bss_info_t *bi = NULL;
2660 uint buflen = dwrq->length;
2662 WL_TRACE(("%s: SIOCGIWAPLIST\n", dev->name));
2667 list = kmalloc(buflen, GFP_KERNEL);
2670 memset(list, 0, buflen);
2671 list->buflen = htod32(buflen);
2672 if ((error = dev_wlc_ioctl(dev, WLC_SCAN_RESULTS, list, buflen))) {
2673 WL_ERROR(("%d: Scan results error %d\n", __LINE__, error));
2677 list->buflen = dtoh32(list->buflen);
2678 list->version = dtoh32(list->version);
2679 list->count = dtoh32(list->count);
2680 if (list->version != WL_BSS_INFO_VERSION) {
2681 WL_ERROR(("%s: list->version %d != WL_BSS_INFO_VERSION\n", \
2682 __FUNCTION__, list->version));
2687 for (i = 0, dwrq->length = 0; i < list->count && dwrq->length < IW_MAX_AP; i++) {
2688 bi = bi ? (wl_bss_info_t *)((uintptr)bi + dtoh32(bi->length)) : list->bss_info;
2690 if ((dtoh32(bi->length) > buflen) ||
2691 (((uintptr)bi + dtoh32(bi->length)) > ((uintptr)list + buflen))) {
2692 WL_ERROR(("%s: Scan results out of bounds: %u\n",__FUNCTION__,dtoh32(bi->length)));
2697 if (!(dtoh16(bi->capability) & DOT11_CAP_ESS))
2700 memcpy(addr[dwrq->length].sa_data, &bi->BSSID, ETHER_ADDR_LEN);
2701 addr[dwrq->length].sa_family = ARPHRD_ETHER;
2702 qual[dwrq->length].qual = rssi_to_qual(dtoh16(bi->RSSI));
2703 qual[dwrq->length].level = 0x100 + dtoh16(bi->RSSI);
2704 qual[dwrq->length].noise = 0x100 + bi->phy_noise;
2706 #if WIRELESS_EXT > 18
2707 qual[dwrq->length].updated = IW_QUAL_ALL_UPDATED | IW_QUAL_DBM;
2709 qual[dwrq->length].updated = 7;
2718 memcpy(&addr[dwrq->length], qual, sizeof(struct iw_quality) * dwrq->length);
2726 #ifdef WL_IW_USE_ISCAN
2728 wl_iw_iscan_get_aplist(
2729 struct net_device *dev,
2730 struct iw_request_info *info,
2731 struct iw_point *dwrq,
2735 wl_scan_results_t *list;
2737 iscan_info_t *iscan = g_iscan;
2739 struct sockaddr *addr = (struct sockaddr *) extra;
2740 struct iw_quality qual[IW_MAX_AP];
2741 wl_bss_info_t *bi = NULL;
2744 WL_TRACE(("%s: SIOCGIWAPLIST\n", dev->name));
2749 if ((!iscan) || (iscan->sysioc_pid < 0)) {
2750 WL_ERROR(("%s error\n", __FUNCTION__));
2754 buf = iscan->list_hdr;
2757 list = &((wl_iscan_results_t*)buf->iscan_buf)->results;
2758 if (list->version != WL_BSS_INFO_VERSION) {
2759 WL_ERROR(("%s : list->version %d != WL_BSS_INFO_VERSION\n", \
2760 __FUNCTION__, list->version));
2765 for (i = 0, dwrq->length = 0; i < list->count && dwrq->length < IW_MAX_AP; i++) {
2766 bi = bi ? (wl_bss_info_t *)((uintptr)bi + dtoh32(bi->length))
2769 if ((dtoh32(bi->length) > WLC_IW_ISCAN_MAXLEN) ||
2770 (((uintptr)bi + dtoh32(bi->length)) > ((uintptr)list + WLC_IW_ISCAN_MAXLEN))) {
2771 WL_ERROR(("%s: Scan results out of bounds: %u\n",__FUNCTION__,dtoh32(bi->length)));
2775 if (!(dtoh16(bi->capability) & DOT11_CAP_ESS))
2778 memcpy(addr[dwrq->length].sa_data, &bi->BSSID, ETHER_ADDR_LEN);
2779 addr[dwrq->length].sa_family = ARPHRD_ETHER;
2780 qual[dwrq->length].qual = rssi_to_qual(dtoh16(bi->RSSI));
2781 qual[dwrq->length].level = 0x100 + dtoh16(bi->RSSI);
2782 qual[dwrq->length].noise = 0x100 + bi->phy_noise;
2784 #if WIRELESS_EXT > 18
2785 qual[dwrq->length].updated = IW_QUAL_ALL_UPDATED | IW_QUAL_DBM;
2787 qual[dwrq->length].updated = 7;
2795 memcpy(&addr[dwrq->length], qual, sizeof(struct iw_quality) * dwrq->length);
2803 wl_iw_iscan_prep(wl_scan_params_t *params, wlc_ssid_t *ssid)
2807 memcpy(¶ms->bssid, ðer_bcast, ETHER_ADDR_LEN);
2808 params->bss_type = DOT11_BSSTYPE_ANY;
2809 params->scan_type = 0;
2810 params->nprobes = -1;
2811 params->active_time = -1;
2812 params->passive_time = -1;
2813 params->home_time = -1;
2814 params->channel_num = 0;
2815 #if defined(CONFIG_FIRST_SCAN)
2816 if (g_first_broadcast_scan == BROADCAST_SCAN_FIRST_STARTED)
2817 params->passive_time = 30;
2819 params->nprobes = htod32(params->nprobes);
2820 params->active_time = htod32(params->active_time);
2821 params->passive_time = htod32(params->passive_time);
2822 params->home_time = htod32(params->home_time);
2823 if (ssid && ssid->SSID_len)
2824 memcpy(¶ms->ssid, ssid, sizeof(wlc_ssid_t));
2830 wl_iw_iscan(iscan_info_t *iscan, wlc_ssid_t *ssid, uint16 action)
2834 iscan->iscan_ex_params_p->version = htod32(ISCAN_REQ_VERSION);
2835 iscan->iscan_ex_params_p->action = htod16(action);
2836 iscan->iscan_ex_params_p->scan_duration = htod16(0);
2838 WL_SCAN(("%s : nprobes=%d\n", __FUNCTION__, iscan->iscan_ex_params_p->params.nprobes));
2839 WL_SCAN(("active_time=%d\n", iscan->iscan_ex_params_p->params.active_time));
2840 WL_SCAN(("passive_time=%d\n", iscan->iscan_ex_params_p->params.passive_time));
2841 WL_SCAN(("home_time=%d\n", iscan->iscan_ex_params_p->params.home_time));
2842 WL_SCAN(("scan_type=%d\n", iscan->iscan_ex_params_p->params.scan_type));
2843 WL_SCAN(("bss_type=%d\n", iscan->iscan_ex_params_p->params.bss_type));
2845 if ((err = dev_iw_iovar_setbuf(iscan->dev, "iscan", iscan->iscan_ex_params_p, \
2846 iscan->iscan_ex_param_size, iscan->ioctlbuf, sizeof(iscan->ioctlbuf)))) {
2847 WL_ERROR(("Set ISCAN for %s failed with %d\n", __FUNCTION__, err));
2855 wl_iw_timerfunc(ulong data)
2857 iscan_info_t *iscan = (iscan_info_t *)data;
2859 iscan->timer_on = 0;
2860 if (iscan->iscan_state != ISCAN_STATE_IDLE) {
2861 WL_SCAN(("timer trigger\n"));
2862 up(&iscan->sysioc_sem);
2866 static void wl_iw_set_event_mask(struct net_device *dev)
2868 char eventmask[WL_EVENTING_MASK_LEN];
2869 char iovbuf[WL_EVENTING_MASK_LEN + 12];
2871 dev_iw_iovar_getbuf(dev, "event_msgs", "", 0, iovbuf, sizeof(iovbuf));
2872 bcopy(iovbuf, eventmask, WL_EVENTING_MASK_LEN);
2873 setbit(eventmask, WLC_E_SCAN_COMPLETE);
2874 dev_iw_iovar_setbuf(dev, "event_msgs", eventmask, WL_EVENTING_MASK_LEN,
2875 iovbuf, sizeof(iovbuf));
2879 wl_iw_iscan_get(iscan_info_t *iscan)
2883 wl_iscan_results_t * list_buf;
2884 wl_iscan_results_t list;
2885 wl_scan_results_t *results;
2889 mutex_lock(&wl_cache_lock);
2890 if (iscan->list_cur) {
2891 buf = iscan->list_cur;
2892 iscan->list_cur = buf->next;
2895 buf = kmalloc(sizeof(iscan_buf_t), GFP_KERNEL);
2897 WL_ERROR(("%s can't alloc iscan_buf_t : going to abort currect iscan\n", \
2899 mutex_unlock(&wl_cache_lock);
2900 return WL_SCAN_RESULTS_NO_MEM;
2903 if (!iscan->list_hdr)
2904 iscan->list_hdr = buf;
2906 ptr = iscan->list_hdr;
2913 memset(buf->iscan_buf, 0, WLC_IW_ISCAN_MAXLEN);
2914 list_buf = (wl_iscan_results_t*)buf->iscan_buf;
2915 results = &list_buf->results;
2916 results->buflen = WL_ISCAN_RESULTS_FIXED_SIZE;
2917 results->version = 0;
2920 memset(&list, 0, sizeof(list));
2921 list.results.buflen = htod32(WLC_IW_ISCAN_MAXLEN);
2922 res = dev_iw_iovar_getbuf(
2926 WL_ISCAN_RESULTS_FIXED_SIZE,
2928 WLC_IW_ISCAN_MAXLEN);
2930 results->buflen = dtoh32(results->buflen);
2931 results->version = dtoh32(results->version);
2932 results->count = dtoh32(results->count);
2933 WL_SCAN(("results->count = %d\n", results->count));
2935 WL_SCAN(("results->buflen = %d\n", results->buflen));
2936 status = dtoh32(list_buf->status);
2938 WL_ERROR(("%s returns error %d\n", __FUNCTION__, res));
2939 status = WL_SCAN_RESULTS_NO_MEM;
2941 mutex_unlock(&wl_cache_lock);
2945 static void wl_iw_force_specific_scan(iscan_info_t *iscan)
2947 WL_SCAN(("%s force Specific SCAN for %s\n", __FUNCTION__, g_specific_ssid.SSID));
2948 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27))
2951 (void) dev_wlc_ioctl(iscan->dev, WLC_SCAN, &g_specific_ssid, sizeof(g_specific_ssid));
2952 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27))
2957 static void wl_iw_send_scan_complete(iscan_info_t *iscan)
2960 union iwreq_data wrqu;
2962 memset(&wrqu, 0, sizeof(wrqu));
2964 wireless_send_event(iscan->dev, SIOCGIWSCAN, &wrqu, NULL);
2965 #if defined(CONFIG_FIRST_SCAN)
2966 if (g_first_broadcast_scan == BROADCAST_SCAN_FIRST_STARTED)
2967 g_first_broadcast_scan = BROADCAST_SCAN_FIRST_RESULT_READY;
2969 WL_SCAN(("Send Event ISCAN complete\n"));
2974 _iscan_sysioc_thread(void *data)
2977 iscan_info_t *iscan = (iscan_info_t *)data;
2978 static bool iscan_pass_abort = FALSE;
2980 DAEMONIZE("iscan_sysioc");
2982 status = WL_SCAN_RESULTS_PARTIAL;
2983 while (down_interruptible(&iscan->sysioc_sem) == 0) {
2985 net_os_wake_lock(iscan->dev);
2988 if (ap_cfg_running) {
2989 WL_SCAN(("%s skipping SCAN ops in AP mode !!!\n", __FUNCTION__));
2990 net_os_wake_unlock(iscan->dev);
2995 if (iscan->timer_on) {
2996 iscan->timer_on = 0;
2997 del_timer_sync(&iscan->timer);
3000 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27))
3003 status = wl_iw_iscan_get(iscan);
3004 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27))
3008 if (g_scan_specified_ssid && (iscan_pass_abort == TRUE)) {
3009 WL_SCAN(("%s Get results from specific scan status=%d\n", __FUNCTION__, status));
3010 wl_iw_send_scan_complete(iscan);
3011 iscan_pass_abort = FALSE;
3016 case WL_SCAN_RESULTS_PARTIAL:
3017 WL_SCAN(("iscanresults incomplete\n"));
3018 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27))
3022 wl_iw_iscan(iscan, NULL, WL_SCAN_ACTION_CONTINUE);
3023 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27))
3027 mod_timer(&iscan->timer, jiffies + iscan->timer_ms*HZ/1000);
3028 iscan->timer_on = 1;
3030 case WL_SCAN_RESULTS_SUCCESS:
3031 WL_SCAN(("iscanresults complete\n"));
3032 iscan->iscan_state = ISCAN_STATE_IDLE;
3033 wl_iw_send_scan_complete(iscan);
3035 case WL_SCAN_RESULTS_PENDING:
3036 WL_SCAN(("iscanresults pending\n"));
3038 mod_timer(&iscan->timer, jiffies + iscan->timer_ms*HZ/1000);
3039 iscan->timer_on = 1;
3041 case WL_SCAN_RESULTS_ABORTED:
3042 WL_SCAN(("iscanresults aborted\n"));
3043 iscan->iscan_state = ISCAN_STATE_IDLE;
3044 if (g_scan_specified_ssid == 0)
3045 wl_iw_send_scan_complete(iscan);
3047 iscan_pass_abort = TRUE;
3048 wl_iw_force_specific_scan(iscan);
3051 case WL_SCAN_RESULTS_NO_MEM:
3052 WL_SCAN(("iscanresults can't alloc memory: skip\n"));
3053 iscan->iscan_state = ISCAN_STATE_IDLE;
3056 WL_SCAN(("iscanresults returned unknown status %d\n", status));
3060 net_os_wake_unlock(iscan->dev);
3063 if (iscan->timer_on) {
3064 iscan->timer_on = 0;
3065 del_timer_sync(&iscan->timer);
3068 complete_and_exit(&iscan->sysioc_exited, 0);
3075 wl_iw_set_ss_cache_timer_flag(void)
3077 g_ss_cache_ctrl.m_timer_expired = 1;
3078 WL_TRACE(("%s called\n", __FUNCTION__));
3082 wl_iw_init_ss_cache_ctrl(void)
3084 WL_TRACE(("%s :\n", __FUNCTION__));
3085 g_ss_cache_ctrl.m_prev_scan_mode = 0;
3086 g_ss_cache_ctrl.m_cons_br_scan_cnt = 0;
3087 g_ss_cache_ctrl.m_cache_head = NULL;
3088 g_ss_cache_ctrl.m_link_down = 0;
3089 g_ss_cache_ctrl.m_timer_expired = 0;
3090 memset(g_ss_cache_ctrl.m_active_bssid, 0, ETHER_ADDR_LEN);
3092 g_ss_cache_ctrl.m_timer = kmalloc(sizeof(struct timer_list), GFP_KERNEL);
3093 if (!g_ss_cache_ctrl.m_timer) {
3096 g_ss_cache_ctrl.m_timer->function = (void *)wl_iw_set_ss_cache_timer_flag;
3097 init_timer(g_ss_cache_ctrl.m_timer);
3105 wl_iw_free_ss_cache(void)
3107 wl_iw_ss_cache_t *node, *cur;
3108 wl_iw_ss_cache_t **spec_scan_head;
3110 WL_TRACE(("%s called\n", __FUNCTION__));
3112 mutex_lock(&wl_cache_lock);
3113 spec_scan_head = &g_ss_cache_ctrl.m_cache_head;
3114 node = *spec_scan_head;
3117 WL_TRACE(("%s : SSID - %s\n", __FUNCTION__, node->bss_info->SSID));
3122 *spec_scan_head = NULL;
3123 mutex_unlock(&wl_cache_lock);
3129 wl_iw_run_ss_cache_timer(int kick_off)
3131 struct timer_list **timer;
3133 timer = &g_ss_cache_ctrl.m_timer;
3137 (*timer)->expires = jiffies + 30000 * HZ / 1000;
3139 WL_TRACE(("%s : timer starts \n", __FUNCTION__));
3141 del_timer_sync(*timer);
3142 WL_TRACE(("%s : timer stops \n", __FUNCTION__));
3151 wl_iw_release_ss_cache_ctrl(void)
3153 WL_TRACE(("%s :\n", __FUNCTION__));
3154 wl_iw_free_ss_cache();
3155 wl_iw_run_ss_cache_timer(0);
3156 if (g_ss_cache_ctrl.m_timer) {
3157 kfree(g_ss_cache_ctrl.m_timer);
3164 wl_iw_reset_ss_cache(void)
3166 wl_iw_ss_cache_t *node, *prev, *cur;
3167 wl_iw_ss_cache_t **spec_scan_head;
3169 mutex_lock(&wl_cache_lock);
3170 spec_scan_head = &g_ss_cache_ctrl.m_cache_head;
3171 node = *spec_scan_head;
3175 WL_TRACE(("%s : node SSID %s \n", __FUNCTION__, node->bss_info->SSID));
3178 if (cur == *spec_scan_head) {
3179 *spec_scan_head = cur->next;
3180 prev = *spec_scan_head;
3183 prev->next = cur->next;
3187 WL_TRACE(("%s : Del node : SSID %s\n", __FUNCTION__, cur->bss_info->SSID));
3196 mutex_unlock(&wl_cache_lock);
3201 wl_iw_add_bss_to_ss_cache(wl_scan_results_t *ss_list)
3204 wl_iw_ss_cache_t *node, *prev, *leaf;
3205 wl_iw_ss_cache_t **spec_scan_head;
3206 wl_bss_info_t *bi = NULL;
3209 if (!ss_list->count) {
3213 mutex_lock(&wl_cache_lock);
3214 spec_scan_head = &g_ss_cache_ctrl.m_cache_head;
3216 for (i = 0; i < ss_list->count; i++) {
3218 node = *spec_scan_head;
3221 bi = bi ? (wl_bss_info_t *)((uintptr)bi + dtoh32(bi->length)) : ss_list->bss_info;
3223 WL_TRACE(("%s : find %d with specific SSID %s\n", __FUNCTION__, i, bi->SSID));
3225 if (!memcmp(&node->bss_info->BSSID, &bi->BSSID, ETHER_ADDR_LEN)) {
3227 WL_TRACE(("dirty marked : SSID %s\n", bi->SSID));
3238 leaf = kmalloc(bi->length + WLC_IW_SS_CACHE_CTRL_FIELD_MAXLEN, GFP_KERNEL);
3240 WL_ERROR(("Memory alloc failure %d\n", \
3241 bi->length + WLC_IW_SS_CACHE_CTRL_FIELD_MAXLEN));
3242 mutex_unlock(&wl_cache_lock);
3246 memcpy(leaf->bss_info, bi, bi->length);
3250 leaf->version = ss_list->version;
3253 *spec_scan_head = leaf;
3259 mutex_unlock(&wl_cache_lock);
3265 wl_iw_merge_scan_cache(struct iw_request_info *info, char *extra, uint buflen_from_user,
3268 wl_iw_ss_cache_t *node;
3269 wl_scan_results_t *list_merge;
3271 mutex_lock(&wl_cache_lock);
3272 node = g_ss_cache_ctrl.m_cache_head;
3274 list_merge = (wl_scan_results_t *)&node->buflen;
3275 WL_TRACE(("%s: Cached Specific APs list=%d\n", __FUNCTION__, list_merge->count));
3276 if (buflen_from_user - *merged_len > 0) {
3277 *merged_len += (__u16) wl_iw_get_scan_prep(list_merge, info,
3278 extra + *merged_len, buflen_from_user - *merged_len);
3281 WL_TRACE(("%s: exit with break\n", __FUNCTION__));
3286 mutex_unlock(&wl_cache_lock);
3292 wl_iw_delete_bss_from_ss_cache(void *addr)
3295 wl_iw_ss_cache_t *node, *prev;
3296 wl_iw_ss_cache_t **spec_scan_head;
3298 mutex_lock(&wl_cache_lock);
3299 spec_scan_head = &g_ss_cache_ctrl.m_cache_head;
3300 node = *spec_scan_head;
3303 if (!memcmp(&node->bss_info->BSSID, addr, ETHER_ADDR_LEN)) {
3304 if (node == *spec_scan_head) {
3305 *spec_scan_head = node->next;
3308 prev->next = node->next;
3311 WL_TRACE(("%s : Del node : %s\n", __FUNCTION__, node->bss_info->SSID));
3320 memset(addr, 0, ETHER_ADDR_LEN);
3321 mutex_unlock(&wl_cache_lock);
3330 struct net_device *dev,
3331 struct iw_request_info *info,
3332 union iwreq_data *wrqu,
3337 WL_TRACE(("%s dev:%s: SIOCSIWSCAN : SCAN\n", __FUNCTION__, dev->name));
3340 WL_ERROR(("%s: Scan from SIOCGIWSCAN not supported\n", __FUNCTION__));
3345 if (ap_cfg_running) {
3346 WL_TRACE(("\n>%s: Not executed, reason -'SOFTAP is active'\n", __FUNCTION__));
3351 if (g_onoff == G_WLAN_SET_OFF)
3354 memset(&g_specific_ssid, 0, sizeof(g_specific_ssid));
3355 #ifndef WL_IW_USE_ISCAN
3356 g_scan_specified_ssid = 0;
3359 #if WIRELESS_EXT > 17
3361 if (wrqu->data.length == sizeof(struct iw_scan_req)) {
3362 if (wrqu->data.flags & IW_SCAN_THIS_ESSID) {
3363 struct iw_scan_req *req = (struct iw_scan_req *)extra;
3364 #if defined(CONFIG_FIRST_SCAN)
3365 if (g_first_broadcast_scan != BROADCAST_SCAN_FIRST_RESULT_CONSUMED) {
3366 WL_ERROR(("%s Ignoring SC %s first BC is not done = %d\n", \
3367 __FUNCTION__, req->essid, \
3368 g_first_broadcast_scan));
3372 if (g_scan_specified_ssid) {
3373 WL_SCAN(("%s Specific SCAN is not done ignore scan for = %s \n", \
3374 __FUNCTION__, req->essid));
3378 g_specific_ssid.SSID_len = MIN(sizeof(g_specific_ssid.SSID), \
3380 memcpy(g_specific_ssid.SSID, req->essid, g_specific_ssid.SSID_len);
3381 g_specific_ssid.SSID_len = htod32(g_specific_ssid.SSID_len);
3382 g_scan_specified_ssid = 1;
3383 WL_TRACE(("### Specific scan ssid=%s len=%d\n", \
3384 g_specific_ssid.SSID, g_specific_ssid.SSID_len));
3390 if ((error = dev_wlc_ioctl(dev, WLC_SCAN, &g_specific_ssid, sizeof(g_specific_ssid)))) {
3391 WL_SCAN(("Set SCAN for %s failed with %d\n", g_specific_ssid.SSID, error));
3392 g_scan_specified_ssid = 0;
3399 #ifdef WL_IW_USE_ISCAN
3401 wl_iw_iscan_set_scan_broadcast_prep(struct net_device *dev, uint flag)
3404 iscan_info_t *iscan = g_iscan;
3406 #if defined(CONFIG_FIRST_SCAN)
3407 if (g_first_broadcast_scan == BROADCAST_SCAN_FIRST_IDLE) {
3408 g_first_broadcast_scan = BROADCAST_SCAN_FIRST_STARTED;
3409 WL_SCAN(("%s: First Brodcast scan was forced\n", __FUNCTION__));
3411 else if (g_first_broadcast_scan == BROADCAST_SCAN_FIRST_STARTED) {
3412 WL_SCAN(("%s: ignore ISCAN request first BS is not done yet\n", __FUNCTION__));
3417 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27))
3422 dev_wlc_ioctl(dev, WLC_SET_PASSIVE_SCAN, &iscan->scan_flag, sizeof(iscan->scan_flag));
3423 wl_iw_set_event_mask(dev);
3425 WL_SCAN(("+++: Set Broadcast ISCAN\n"));
3427 memset(&ssid, 0, sizeof(ssid));
3429 iscan->list_cur = iscan->list_hdr;
3430 iscan->iscan_state = ISCAN_STATE_SCANING;
3432 memset(&iscan->iscan_ex_params_p->params, 0, iscan->iscan_ex_param_size);
3433 wl_iw_iscan_prep(&iscan->iscan_ex_params_p->params, &ssid);
3434 wl_iw_iscan(iscan, &ssid, WL_SCAN_ACTION_START);
3436 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27))
3441 mod_timer(&iscan->timer, jiffies + iscan->timer_ms*HZ/1000);
3443 iscan->timer_on = 1;
3449 wl_iw_iscan_set_scan(
3450 struct net_device *dev,
3451 struct iw_request_info *info,
3452 union iwreq_data *wrqu,
3457 iscan_info_t *iscan = g_iscan;
3460 WL_SCAN(("%s: SIOCSIWSCAN : ISCAN\n", dev->name));
3463 WL_ERROR(("%s: Scan from SIOCGIWSCAN not supported\n", __FUNCTION__));
3467 net_os_wake_lock(dev);
3470 if (ap_cfg_running) {
3471 WL_SCAN(("\n>%s: Not executed, reason -'SOFTAP is active'\n", __FUNCTION__));
3476 if (g_onoff == G_WLAN_SET_OFF) {
3477 WL_SCAN(("%s: driver is not up yet after START\n", __FUNCTION__));
3482 if (dhd_dev_get_pno_status(dev)) {
3483 WL_SCAN(("%s: Scan called when PNO is active\n", __FUNCTION__));
3487 if ((!iscan) || (iscan->sysioc_pid < 0)) {
3488 WL_ERROR(("%s error\n", __FUNCTION__));
3492 if (g_scan_specified_ssid) {
3493 WL_SCAN(("%s Specific SCAN already running ignoring BC scan\n", \
3499 memset(&ssid, 0, sizeof(ssid));
3501 #if WIRELESS_EXT > 17
3503 if (wrqu->data.length == sizeof(struct iw_scan_req)) {
3504 if (wrqu->data.flags & IW_SCAN_THIS_ESSID) {
3506 struct iw_scan_req *req = (struct iw_scan_req *)extra;
3507 ssid.SSID_len = MIN(sizeof(ssid.SSID), req->essid_len);
3508 memcpy(ssid.SSID, req->essid, ssid.SSID_len);
3509 ssid.SSID_len = htod32(ssid.SSID_len);
3510 dev_wlc_ioctl(dev, WLC_SET_PASSIVE_SCAN, &as, sizeof(as));
3511 wl_iw_set_event_mask(dev);
3512 ret = wl_iw_set_scan(dev, info, wrqu, extra);
3516 g_scan_specified_ssid = 0;
3518 if (iscan->iscan_state == ISCAN_STATE_SCANING) {
3519 WL_SCAN(("%s ISCAN already in progress \n", __FUNCTION__));
3526 #if defined(CONFIG_FIRST_SCAN) && !defined(CSCAN)
3527 if (g_first_broadcast_scan < BROADCAST_SCAN_FIRST_RESULT_CONSUMED) {
3528 if (++g_first_counter_scans == MAX_ALLOWED_BLOCK_SCAN_FROM_FIRST_SCAN) {
3530 WL_ERROR(("%s Clean up First scan flag which is %d\n", \
3531 __FUNCTION__, g_first_broadcast_scan));
3532 g_first_broadcast_scan = BROADCAST_SCAN_FIRST_RESULT_CONSUMED;
3535 WL_ERROR(("%s Ignoring Broadcast Scan:First Scan is not done yet %d\n", \
3536 __FUNCTION__, g_first_counter_scans));
3543 wl_iw_iscan_set_scan_broadcast_prep(dev, 0);
3546 net_os_wake_unlock(dev);
3551 #if WIRELESS_EXT > 17
3553 ie_is_wpa_ie(uint8 **wpaie, uint8 **tlvs, int *tlvs_len)
3558 !bcmp((const void *)&ie[2], (const void *)(WPA_OUI "\x01"), 4)) {
3564 *tlvs_len -= (int)(ie - *tlvs);
3571 ie_is_wps_ie(uint8 **wpsie, uint8 **tlvs, int *tlvs_len)
3576 !bcmp((const void *)&ie[2], (const void *)(WPA_OUI "\x04"), 4)) {
3582 *tlvs_len -= (int)(ie - *tlvs);
3589 static inline int _wpa_snprintf_hex(char *buf, size_t buf_size, const u8 *data,
3590 size_t len, int uppercase)
3593 char *pos = buf, *end = buf + buf_size;
3597 for (i = 0; i < len; i++) {
3598 ret = snprintf(pos, end - pos, uppercase ? "%02X" : "%02x",
3600 if (ret < 0 || ret >= end - pos) {
3611 int wpa_snprintf_hex(char *buf, size_t buf_size, const u8 *data, size_t len)
3613 return _wpa_snprintf_hex(buf, buf_size, data, len, 0);
3617 wl_iw_handle_scanresults_ies(char **event_p, char *end,
3618 struct iw_request_info *info, wl_bss_info_t *bi)
3620 #if WIRELESS_EXT > 17
3621 struct iw_event iwe;
3624 int custom_event_len;
3627 if (bi->ie_length) {
3630 uint8 *ptr = ((uint8 *)bi) + sizeof(wl_bss_info_t);
3631 int ptr_len = bi->ie_length;
3634 if ((ie = bcm_parse_tlvs(ptr, ptr_len, DOT11_MNG_RSN_ID))) {
3635 iwe.cmd = IWEVGENIE;
3636 iwe.u.data.length = ie->len + 2;
3637 event = IWE_STREAM_ADD_POINT(info, event, end, &iwe, (char *)ie);
3639 ptr = ((uint8 *)bi) + sizeof(wl_bss_info_t);
3642 while ((ie = bcm_parse_tlvs(ptr, ptr_len, DOT11_MNG_WPA_ID))) {
3644 if (ie_is_wps_ie(((uint8 **)&ie), &ptr, &ptr_len)) {
3645 iwe.cmd = IWEVGENIE;
3646 iwe.u.data.length = ie->len + 2;
3647 event = IWE_STREAM_ADD_POINT(info, event, end, &iwe, (char *)ie);
3652 ptr = ((uint8 *)bi) + sizeof(wl_bss_info_t);
3653 ptr_len = bi->ie_length;
3654 while ((ie = bcm_parse_tlvs(ptr, ptr_len, DOT11_MNG_WPA_ID))) {
3655 if (ie_is_wpa_ie(((uint8 **)&ie), &ptr, &ptr_len)) {
3656 iwe.cmd = IWEVGENIE;
3657 iwe.u.data.length = ie->len + 2;
3658 event = IWE_STREAM_ADD_POINT(info, event, end, &iwe, (char *)ie);
3663 ptr = ((uint8 *)bi) + sizeof(wl_bss_info_t);
3664 ptr_len = bi->ie_length;
3666 while ((ie = bcm_parse_tlvs(ptr, ptr_len, DOT11_MNG_WAPI_ID))) {
3667 WL_TRACE(("%s: found a WAPI IE...\n", __FUNCTION__));
3668 #ifdef WAPI_IE_USE_GENIE
3669 iwe.cmd = IWEVGENIE;
3670 iwe.u.data.length = ie->len + 2;
3671 event = IWE_STREAM_ADD_POINT(info, event, end, &iwe, (char *)ie);
3673 iwe.cmd = IWEVCUSTOM;
3674 custom_event_len = strlen("wapi_ie=") + 2*(ie->len + 2);
3675 iwe.u.data.length = custom_event_len;
3677 buf = kmalloc(custom_event_len+1, GFP_KERNEL);
3680 WL_ERROR(("malloc(%d) returned NULL...\n", custom_event_len));
3684 memcpy(buf, "wapi_ie=", 8);
3685 wpa_snprintf_hex(buf + 8, 2+1, &(ie->id), 1);
3686 wpa_snprintf_hex(buf + 10, 2+1, &(ie->len), 1);
3687 wpa_snprintf_hex(buf + 12, 2*ie->len+1, ie->data, ie->len);
3688 event = IWE_STREAM_ADD_POINT(info, event, end, &iwe, buf);
3701 wl_iw_get_scan_prep(
3702 wl_scan_results_t *list,
3703 struct iw_request_info *info,
3708 struct iw_event iwe;
3709 wl_bss_info_t *bi = NULL;
3710 char *event = extra, *end = extra + max_size - WE_ADD_EVENT_FIX, *value;
3715 WL_ERROR(("%s: Null list pointer",__FUNCTION__));
3719 for (i = 0; i < list->count && i < IW_MAX_AP; i++)
3721 if (list->version != WL_BSS_INFO_VERSION) {
3722 WL_ERROR(("%s : list->version %d != WL_BSS_INFO_VERSION\n", \
3723 __FUNCTION__, list->version));
3727 bi = bi ? (wl_bss_info_t *)((uintptr)bi + dtoh32(bi->length)) : list->bss_info;
3729 WL_TRACE(("%s : %s\n", __FUNCTION__, bi->SSID));
3731 iwe.cmd = SIOCGIWAP;
3732 iwe.u.ap_addr.sa_family = ARPHRD_ETHER;
3733 memcpy(iwe.u.ap_addr.sa_data, &bi->BSSID, ETHER_ADDR_LEN);
3734 event = IWE_STREAM_ADD_EVENT(info, event, end, &iwe, IW_EV_ADDR_LEN);
3736 iwe.u.data.length = dtoh32(bi->SSID_len);
3737 iwe.cmd = SIOCGIWESSID;
3738 iwe.u.data.flags = 1;
3739 event = IWE_STREAM_ADD_POINT(info, event, end, &iwe, bi->SSID);
3741 if (dtoh16(bi->capability) & (DOT11_CAP_ESS | DOT11_CAP_IBSS)) {
3742 iwe.cmd = SIOCGIWMODE;
3743 if (dtoh16(bi->capability) & DOT11_CAP_ESS)
3744 iwe.u.mode = IW_MODE_INFRA;
3746 iwe.u.mode = IW_MODE_ADHOC;
3747 event = IWE_STREAM_ADD_EVENT(info, event, end, &iwe, IW_EV_UINT_LEN);
3750 iwe.cmd = SIOCGIWFREQ;
3751 channel = (bi->ctl_ch == 0) ? CHSPEC_CHANNEL(bi->chanspec) : bi->ctl_ch;
3752 iwe.u.freq.m = wf_channel2mhz(channel,
3753 channel <= CH_MAX_2G_CHANNEL ?
3754 WF_CHAN_FACTOR_2_4_G : WF_CHAN_FACTOR_5_G);
3756 event = IWE_STREAM_ADD_EVENT(info, event, end, &iwe, IW_EV_FREQ_LEN);
3759 iwe.u.qual.qual = rssi_to_qual(dtoh16(bi->RSSI));
3760 iwe.u.qual.level = 0x100 + dtoh16(bi->RSSI);
3761 iwe.u.qual.noise = 0x100 + bi->phy_noise;
3762 event = IWE_STREAM_ADD_EVENT(info, event, end, &iwe, IW_EV_QUAL_LEN);
3764 wl_iw_handle_scanresults_ies(&event, end, info, bi);
3766 iwe.cmd = SIOCGIWENCODE;
3767 if (dtoh16(bi->capability) & DOT11_CAP_PRIVACY)
3768 iwe.u.data.flags = IW_ENCODE_ENABLED | IW_ENCODE_NOKEY;
3770 iwe.u.data.flags = IW_ENCODE_DISABLED;
3771 iwe.u.data.length = 0;
3772 event = IWE_STREAM_ADD_POINT(info, event, end, &iwe, (char *)event);
3774 if (bi->rateset.count) {
3775 if (((event -extra) + IW_EV_LCP_LEN) <= (uintptr)end) {
3776 value = event + IW_EV_LCP_LEN;
3777 iwe.cmd = SIOCGIWRATE;
3779 iwe.u.bitrate.fixed = iwe.u.bitrate.disabled = 0;
3780 for (j = 0; j < bi->rateset.count && j < IW_MAX_BITRATES; j++) {
3781 iwe.u.bitrate.value = (bi->rateset.rates[j] & 0x7f) * 500000;
3782 value = IWE_STREAM_ADD_VALUE(info, event, value, end, &iwe,
3790 if ((ret = (event - extra)) < 0) {
3791 WL_ERROR(("==> Wrong size\n"));
3794 WL_TRACE(("%s: size=%d bytes prepared \n", __FUNCTION__, (unsigned int)(event - extra)));
3800 struct net_device *dev,
3801 struct iw_request_info *info,
3802 struct iw_point *dwrq,
3807 wl_scan_results_t *list_merge;
3808 wl_scan_results_t *list = (wl_scan_results_t *) g_scan;
3810 uint buflen_from_user = dwrq->length;
3811 uint len = G_SCAN_RESULTS;
3814 __u16 merged_len = 0;
3816 #if defined(WL_IW_USE_ISCAN)
3817 iscan_info_t *iscan = g_iscan;
3818 iscan_buf_t * p_buf;
3823 WL_TRACE(("%s: buflen_from_user %d: \n", dev->name, buflen_from_user));
3826 WL_TRACE(("%s: wl_iw_get_scan return -EINVAL\n", dev->name));
3830 if ((error = dev_wlc_ioctl(dev, WLC_GET_CHANNEL, &ci, sizeof(ci))))
3832 ci.scan_channel = dtoh32(ci.scan_channel);
3833 if (ci.scan_channel)
3837 if (g_ss_cache_ctrl.m_timer_expired) {
3838 wl_iw_free_ss_cache();
3839 g_ss_cache_ctrl.m_timer_expired ^= 1;
3841 if ((!g_scan_specified_ssid && g_ss_cache_ctrl.m_prev_scan_mode) ||
3842 g_ss_cache_ctrl.m_cons_br_scan_cnt > 4) {
3843 g_ss_cache_ctrl.m_cons_br_scan_cnt = 0;
3845 wl_iw_reset_ss_cache();
3847 g_ss_cache_ctrl.m_prev_scan_mode = g_scan_specified_ssid;
3848 if (g_scan_specified_ssid) {
3849 g_ss_cache_ctrl.m_cons_br_scan_cnt = 0;
3852 g_ss_cache_ctrl.m_cons_br_scan_cnt++;
3856 if (g_scan_specified_ssid) {
3858 list = kmalloc(len, GFP_KERNEL);
3860 WL_TRACE(("%s: wl_iw_get_scan return -ENOMEM\n", dev->name));
3861 g_scan_specified_ssid = 0;
3866 memset(list, 0, len);
3867 list->buflen = htod32(len);
3868 if ((error = dev_wlc_ioctl(dev, WLC_SCAN_RESULTS, list, len))) {
3869 WL_ERROR(("%s: %s : Scan_results ERROR %d\n", dev->name, __FUNCTION__, error));
3871 if (g_scan_specified_ssid) {
3872 g_scan_specified_ssid = 0;
3877 list->buflen = dtoh32(list->buflen);
3878 list->version = dtoh32(list->version);
3879 list->count = dtoh32(list->count);
3881 if (list->version != WL_BSS_INFO_VERSION) {
3882 WL_ERROR(("%s : list->version %d != WL_BSS_INFO_VERSION\n",
3883 __FUNCTION__, list->version));
3884 if (g_scan_specified_ssid) {
3885 g_scan_specified_ssid = 0;
3892 if (g_scan_specified_ssid) {
3894 wl_iw_add_bss_to_ss_cache(list);
3898 mutex_lock(&wl_cache_lock);
3899 #if defined(WL_IW_USE_ISCAN)
3900 if (g_scan_specified_ssid)
3901 WL_TRACE(("%s: Specified scan APs from scan=%d\n", __FUNCTION__, list->count));
3902 p_buf = iscan->list_hdr;
3904 while (p_buf != iscan->list_cur) {
3905 list_merge = &((wl_iscan_results_t*)p_buf->iscan_buf)->results;
3906 WL_TRACE(("%s: Bcast APs list=%d\n", __FUNCTION__, list_merge->count));
3907 counter += list_merge->count;
3908 if (list_merge->count > 0)
3909 len_ret += (__u16) wl_iw_get_scan_prep(list_merge, info,
3910 extra+len_ret, buflen_from_user -len_ret);
3911 p_buf = p_buf->next;
3913 WL_TRACE(("%s merged with total Bcast APs=%d\n", __FUNCTION__, counter));
3915 list_merge = (wl_scan_results_t *) g_scan;
3916 len_ret = (__u16) wl_iw_get_scan_prep(list_merge, info, extra, buflen_from_user);
3918 mutex_unlock(&wl_cache_lock);
3919 if (g_ss_cache_ctrl.m_link_down) {
3920 wl_iw_delete_bss_from_ss_cache(g_ss_cache_ctrl.m_active_bssid);
3923 wl_iw_merge_scan_cache(info, extra+len_ret, buflen_from_user-len_ret, &merged_len);
3924 len_ret += merged_len;
3925 wl_iw_run_ss_cache_timer(0);
3926 wl_iw_run_ss_cache_timer(1);
3929 if (g_scan_specified_ssid) {
3930 WL_TRACE(("%s: Specified scan APs in the list =%d\n", __FUNCTION__, list->count));
3931 len_ret = (__u16) wl_iw_get_scan_prep(list, info, extra, buflen_from_user);
3934 #if defined(WL_IW_USE_ISCAN)
3935 p_buf = iscan->list_hdr;
3937 while (p_buf != iscan->list_cur) {
3938 list_merge = &((wl_iscan_results_t*)p_buf->iscan_buf)->results;
3939 WL_TRACE(("%s: Bcast APs list=%d\n", __FUNCTION__, list_merge->count));
3940 if (list_merge->count > 0)
3941 len_ret += (__u16) wl_iw_get_scan_prep(list_merge, info,
3942 extra+len_ret, buflen_from_user -len_ret);
3943 p_buf = p_buf->next;
3946 list_merge = (wl_scan_results_t *) g_scan;
3947 WL_TRACE(("%s: Bcast APs list=%d\n", __FUNCTION__, list_merge->count));
3948 if (list_merge->count > 0)
3949 len_ret += (__u16) wl_iw_get_scan_prep(list_merge, info, extra+len_ret,
3950 buflen_from_user -len_ret);
3954 list = (wl_scan_results_t *) g_scan;
3955 len_ret = (__u16) wl_iw_get_scan_prep(list, info, extra, buflen_from_user);
3959 #if defined(WL_IW_USE_ISCAN)
3961 g_scan_specified_ssid = 0;
3964 if ((len_ret + WE_ADD_EVENT_FIX) < buflen_from_user)
3970 WL_TRACE(("%s return to WE %d bytes APs=%d\n", __FUNCTION__, dwrq->length, list->count));
3975 #if defined(WL_IW_USE_ISCAN)
3977 wl_iw_iscan_get_scan(
3978 struct net_device *dev,
3979 struct iw_request_info *info,
3980 struct iw_point *dwrq,
3984 wl_scan_results_t *list;
3985 struct iw_event iwe;
3986 wl_bss_info_t *bi = NULL;
3989 char *event = extra, *end = extra + dwrq->length, *value;
3990 iscan_info_t *iscan = g_iscan;
3991 iscan_buf_t * p_buf;
3995 __u16 merged_len = 0;
3996 uint buflen_from_user = dwrq->length;
3999 WL_SCAN(("%s %s buflen_from_user %d:\n", dev->name, __FUNCTION__, dwrq->length));
4002 if (ap_cfg_running) {
4003 WL_TRACE(("%s: Not executed, reason -'SOFTAP is active'\n", __FUNCTION__));
4009 WL_TRACE(("%s: INVALID SIOCGIWSCAN GET bad parameter\n", dev->name));
4013 #if defined(CONFIG_FIRST_SCAN)
4014 if (g_first_broadcast_scan < BROADCAST_SCAN_FIRST_RESULT_READY) {
4015 WL_TRACE(("%s %s: first ISCAN results are NOT ready yet \n", \
4016 dev->name, __FUNCTION__));
4021 if ((!iscan) || (iscan->sysioc_pid < 0)) {
4022 WL_ERROR(("%ssysioc_pid\n", __FUNCTION__));
4027 if (g_ss_cache_ctrl.m_timer_expired) {
4028 wl_iw_free_ss_cache();
4029 g_ss_cache_ctrl.m_timer_expired ^= 1;
4031 if (g_scan_specified_ssid) {
4032 return wl_iw_get_scan(dev, info, dwrq, extra);
4035 if (g_ss_cache_ctrl.m_link_down) {
4036 wl_iw_delete_bss_from_ss_cache(g_ss_cache_ctrl.m_active_bssid);
4038 if (g_ss_cache_ctrl.m_prev_scan_mode || g_ss_cache_ctrl.m_cons_br_scan_cnt > 4) {
4039 g_ss_cache_ctrl.m_cons_br_scan_cnt = 0;
4041 wl_iw_reset_ss_cache();
4043 g_ss_cache_ctrl.m_prev_scan_mode = g_scan_specified_ssid;
4044 g_ss_cache_ctrl.m_cons_br_scan_cnt++;
4048 WL_TRACE(("%s: SIOCGIWSCAN GET broadcast results\n", dev->name));
4050 p_buf = iscan->list_hdr;
4052 while (p_buf != iscan->list_cur) {
4053 list = &((wl_iscan_results_t*)p_buf->iscan_buf)->results;
4055 counter += list->count;
4057 if (list->version != WL_BSS_INFO_VERSION) {
4058 WL_ERROR(("%s : list->version %d != WL_BSS_INFO_VERSION\n",
4059 __FUNCTION__, list->version));
4064 for (ii = 0; ii < list->count && apcnt < IW_MAX_AP; apcnt++, ii++) {
4065 bi = bi ? (wl_bss_info_t *)((uintptr)bi + dtoh32(bi->length)) : list->bss_info;
4067 if ((dtoh32(bi->length) > WLC_IW_ISCAN_MAXLEN) ||
4068 (((uintptr)bi + dtoh32(bi->length)) > ((uintptr)list + WLC_IW_ISCAN_MAXLEN))) {
4069 WL_ERROR(("%s: Scan results out of bounds: %u\n",__FUNCTION__,dtoh32(bi->length)));
4073 if (event + ETHER_ADDR_LEN + bi->SSID_len + IW_EV_UINT_LEN + IW_EV_FREQ_LEN +
4074 IW_EV_QUAL_LEN >= end)
4077 iwe.cmd = SIOCGIWAP;
4078 iwe.u.ap_addr.sa_family = ARPHRD_ETHER;
4079 memcpy(iwe.u.ap_addr.sa_data, &bi->BSSID, ETHER_ADDR_LEN);
4080 event = IWE_STREAM_ADD_EVENT(info, event, end, &iwe, IW_EV_ADDR_LEN);
4082 iwe.u.data.length = dtoh32(bi->SSID_len);
4083 iwe.cmd = SIOCGIWESSID;
4084 iwe.u.data.flags = 1;
4085 event = IWE_STREAM_ADD_POINT(info, event, end, &iwe, bi->SSID);
4087 if (dtoh16(bi->capability) & (DOT11_CAP_ESS | DOT11_CAP_IBSS)) {
4088 iwe.cmd = SIOCGIWMODE;
4089 if (dtoh16(bi->capability) & DOT11_CAP_ESS)
4090 iwe.u.mode = IW_MODE_INFRA;
4092 iwe.u.mode = IW_MODE_ADHOC;
4093 event = IWE_STREAM_ADD_EVENT(info, event, end, &iwe, IW_EV_UINT_LEN);
4096 iwe.cmd = SIOCGIWFREQ;
4097 channel = (bi->ctl_ch == 0) ? CHSPEC_CHANNEL(bi->chanspec) : bi->ctl_ch;
4098 iwe.u.freq.m = wf_channel2mhz(channel,
4099 channel <= CH_MAX_2G_CHANNEL ?
4100 WF_CHAN_FACTOR_2_4_G : WF_CHAN_FACTOR_5_G);
4102 event = IWE_STREAM_ADD_EVENT(info, event, end, &iwe, IW_EV_FREQ_LEN);
4105 iwe.u.qual.qual = rssi_to_qual(dtoh16(bi->RSSI));
4106 iwe.u.qual.level = 0x100 + dtoh16(bi->RSSI);
4107 iwe.u.qual.noise = 0x100 + bi->phy_noise;
4108 event = IWE_STREAM_ADD_EVENT(info, event, end, &iwe, IW_EV_QUAL_LEN);
4110 wl_iw_handle_scanresults_ies(&event, end, info, bi);
4112 iwe.cmd = SIOCGIWENCODE;
4113 if (dtoh16(bi->capability) & DOT11_CAP_PRIVACY)
4114 iwe.u.data.flags = IW_ENCODE_ENABLED | IW_ENCODE_NOKEY;
4116 iwe.u.data.flags = IW_ENCODE_DISABLED;
4117 iwe.u.data.length = 0;
4118 event = IWE_STREAM_ADD_POINT(info, event, end, &iwe, (char *)event);
4120 if (bi->rateset.count) {
4121 if (event + IW_MAX_BITRATES*IW_EV_PARAM_LEN >= end)
4124 value = event + IW_EV_LCP_LEN;
4125 iwe.cmd = SIOCGIWRATE;
4127 iwe.u.bitrate.fixed = iwe.u.bitrate.disabled = 0;
4128 for (j = 0; j < bi->rateset.count && j < IW_MAX_BITRATES; j++) {
4129 iwe.u.bitrate.value = (bi->rateset.rates[j] & 0x7f) * 500000;
4130 value = IWE_STREAM_ADD_VALUE(info, event, value, end, &iwe,
4136 p_buf = p_buf->next;
4139 dwrq->length = event - extra;
4143 wl_iw_merge_scan_cache(info, event, buflen_from_user - dwrq->length, &merged_len);
4144 dwrq->length += merged_len;
4145 wl_iw_run_ss_cache_timer(0);
4146 wl_iw_run_ss_cache_timer(1);
4148 #if defined(CONFIG_FIRST_SCAN)
4149 g_first_broadcast_scan = BROADCAST_SCAN_FIRST_RESULT_CONSUMED;
4152 WL_TRACE(("%s return to WE %d bytes APs=%d\n", __FUNCTION__, dwrq->length, counter));
4160 struct net_device *dev,
4161 struct iw_request_info *info,
4162 struct iw_point *dwrq,
4167 wl_join_params_t join_params;
4168 int join_params_size;
4170 WL_TRACE(("%s: SIOCSIWESSID\n", dev->name));
4173 memset(&g_ssid, 0, sizeof(g_ssid));
4175 CHECK_EXTRA_FOR_NULL(extra);
4177 if (dwrq->length && extra) {
4178 #if WIRELESS_EXT > 20
4179 g_ssid.SSID_len = MIN(sizeof(g_ssid.SSID), dwrq->length);
4181 g_ssid.SSID_len = MIN(sizeof(g_ssid.SSID), dwrq->length-1);
4183 memcpy(g_ssid.SSID, extra, g_ssid.SSID_len);
4186 g_ssid.SSID_len = 0;
4188 g_ssid.SSID_len = htod32(g_ssid.SSID_len);
4190 memset(&join_params, 0, sizeof(join_params));
4191 join_params_size = sizeof(join_params.ssid);
4193 memcpy(&join_params.ssid.SSID, g_ssid.SSID, g_ssid.SSID_len);
4194 join_params.ssid.SSID_len = htod32(g_ssid.SSID_len);
4195 memcpy(&join_params.params.bssid, ðer_bcast, ETHER_ADDR_LEN);
4197 wl_iw_ch_to_chanspec(g_wl_iw_params.target_channel, &join_params, &join_params_size);
4199 if ((error = dev_wlc_ioctl(dev, WLC_SET_SSID, &join_params, join_params_size))) {
4200 WL_ERROR(("Invalid ioctl data=%d\n", error));
4204 if (g_ssid.SSID_len) {
4205 WL_TRACE(("%s: join SSID=%s ch=%d\n", __FUNCTION__, \
4206 g_ssid.SSID, g_wl_iw_params.target_channel));
4213 struct net_device *dev,
4214 struct iw_request_info *info,
4215 struct iw_point *dwrq,
4222 WL_TRACE(("%s: SIOCGIWESSID\n", dev->name));
4227 if ((error = dev_wlc_ioctl(dev, WLC_GET_SSID, &ssid, sizeof(ssid)))) {
4228 WL_ERROR(("Error getting the SSID\n"));
4232 ssid.SSID_len = dtoh32(ssid.SSID_len);
4234 memcpy(extra, ssid.SSID, ssid.SSID_len);
4236 dwrq->length = ssid.SSID_len;
4245 struct net_device *dev,
4246 struct iw_request_info *info,
4247 struct iw_point *dwrq,
4251 wl_iw_t *iw = *(wl_iw_t **)netdev_priv(dev);
4253 WL_TRACE(("%s: SIOCSIWNICKN\n", dev->name));
4258 if (dwrq->length > sizeof(iw->nickname))
4261 memcpy(iw->nickname, extra, dwrq->length);
4262 iw->nickname[dwrq->length - 1] = '\0';
4269 struct net_device *dev,
4270 struct iw_request_info *info,
4271 struct iw_point *dwrq,
4275 wl_iw_t *iw = *(wl_iw_t **)netdev_priv(dev);
4277 WL_TRACE(("%s: SIOCGIWNICKN\n", dev->name));
4282 strcpy(extra, iw->nickname);
4283 dwrq->length = strlen(extra) + 1;
4288 static int wl_iw_set_rate(
4289 struct net_device *dev,
4290 struct iw_request_info *info,
4291 struct iw_param *vwrq,
4295 wl_rateset_t rateset;
4296 int error, rate, i, error_bg, error_a;
4298 WL_TRACE(("%s: SIOCSIWRATE\n", dev->name));
4301 if ((error = dev_wlc_ioctl(dev, WLC_GET_CURR_RATESET, &rateset, sizeof(rateset))))
4304 rateset.count = dtoh32(rateset.count);
4306 if (vwrq->value < 0) {
4308 rate = rateset.rates[rateset.count - 1] & 0x7f;
4309 } else if (vwrq->value < rateset.count) {
4311 rate = rateset.rates[vwrq->value] & 0x7f;
4314 rate = vwrq->value / 500000;
4319 error_bg = dev_wlc_intvar_set(dev, "bg_rate", rate);
4320 error_a = dev_wlc_intvar_set(dev, "a_rate", rate);
4322 if (error_bg && error_a)
4323 return (error_bg | error_a);
4327 error_bg = dev_wlc_intvar_set(dev, "bg_rate", 0);
4329 error_a = dev_wlc_intvar_set(dev, "a_rate", 0);
4331 if (error_bg && error_a)
4332 return (error_bg | error_a);
4335 for (i = 0; i < rateset.count; i++)
4336 if ((rateset.rates[i] & 0x7f) > rate)
4338 rateset.count = htod32(i);
4341 if ((error = dev_wlc_ioctl(dev, WLC_SET_RATESET, &rateset, sizeof(rateset))))
4348 static int wl_iw_get_rate(
4349 struct net_device *dev,
4350 struct iw_request_info *info,
4351 struct iw_param *vwrq,
4357 WL_TRACE(("%s: SIOCGIWRATE\n", dev->name));
4360 if ((error = dev_wlc_ioctl(dev, WLC_GET_RATE, &rate, sizeof(rate))))
4362 rate = dtoh32(rate);
4363 vwrq->value = rate * 500000;
4370 struct net_device *dev,
4371 struct iw_request_info *info,
4372 struct iw_param *vwrq,
4378 WL_TRACE(("%s: SIOCSIWRTS\n", dev->name));
4381 rts = DOT11_DEFAULT_RTS_LEN;
4382 else if (vwrq->value < 0 || vwrq->value > DOT11_DEFAULT_RTS_LEN)
4387 if ((error = dev_wlc_intvar_set(dev, "rtsthresh", rts)))
4395 struct net_device *dev,
4396 struct iw_request_info *info,
4397 struct iw_param *vwrq,
4403 WL_TRACE(("%s: SIOCGIWRTS\n", dev->name));
4405 if ((error = dev_wlc_intvar_get(dev, "rtsthresh", &rts)))
4409 vwrq->disabled = (rts >= DOT11_DEFAULT_RTS_LEN);
4417 struct net_device *dev,
4418 struct iw_request_info *info,
4419 struct iw_param *vwrq,
4425 WL_TRACE(("%s: SIOCSIWFRAG\n", dev->name));
4428 frag = DOT11_DEFAULT_FRAG_LEN;
4429 else if (vwrq->value < 0 || vwrq->value > DOT11_DEFAULT_FRAG_LEN)
4434 if ((error = dev_wlc_intvar_set(dev, "fragthresh", frag)))
4442 struct net_device *dev,
4443 struct iw_request_info *info,
4444 struct iw_param *vwrq,
4448 int error, fragthreshold;
4450 WL_TRACE(("%s: SIOCGIWFRAG\n", dev->name));
4452 if ((error = dev_wlc_intvar_get(dev, "fragthresh", &fragthreshold)))
4455 vwrq->value = fragthreshold;
4456 vwrq->disabled = (fragthreshold >= DOT11_DEFAULT_FRAG_LEN);
4464 struct net_device *dev,
4465 struct iw_request_info *info,
4466 struct iw_param *vwrq,
4472 WL_TRACE(("%s: SIOCSIWTXPOW\n", dev->name));
4475 disable = vwrq->disabled ? WL_RADIO_SW_DISABLE : 0;
4476 disable += WL_RADIO_SW_DISABLE << 16;
4478 disable = htod32(disable);
4479 if ((error = dev_wlc_ioctl(dev, WLC_SET_RADIO, &disable, sizeof(disable))))
4483 if (disable & WL_RADIO_SW_DISABLE)
4487 if (!(vwrq->flags & IW_TXPOW_MWATT))
4491 if (vwrq->value < 0)
4494 if (vwrq->value > 0xffff) txpwrmw = 0xffff;
4495 else txpwrmw = (uint16)vwrq->value;
4498 error = dev_wlc_intvar_set(dev, "qtxpower", (int)(bcm_mw_to_qdbm(txpwrmw)));
4504 struct net_device *dev,
4505 struct iw_request_info *info,
4506 struct iw_param *vwrq,
4510 int error, disable, txpwrdbm;
4513 WL_TRACE(("%s: SIOCGIWTXPOW\n", dev->name));
4515 if ((error = dev_wlc_ioctl(dev, WLC_GET_RADIO, &disable, sizeof(disable))) ||
4516 (error = dev_wlc_intvar_get(dev, "qtxpower", &txpwrdbm)))
4519 disable = dtoh32(disable);
4520 result = (uint8)(txpwrdbm & ~WL_TXPWR_OVERRIDE);
4521 vwrq->value = (int32)bcm_qdbm_to_mw(result);
4523 vwrq->disabled = (disable & (WL_RADIO_SW_DISABLE | WL_RADIO_HW_DISABLE)) ? 1 : 0;
4524 vwrq->flags = IW_TXPOW_MWATT;
4529 #if WIRELESS_EXT > 10
4532 struct net_device *dev,
4533 struct iw_request_info *info,
4534 struct iw_param *vwrq,
4538 int error, lrl, srl;
4540 WL_TRACE(("%s: SIOCSIWRETRY\n", dev->name));
4543 if (vwrq->disabled || (vwrq->flags & IW_RETRY_LIFETIME))
4547 if (vwrq->flags & IW_RETRY_LIMIT) {
4550 #if WIRELESS_EXT > 20
4551 if ((vwrq->flags & IW_RETRY_LONG) ||(vwrq->flags & IW_RETRY_MAX) ||
4552 !((vwrq->flags & IW_RETRY_SHORT) || (vwrq->flags & IW_RETRY_MIN))) {
4554 if ((vwrq->flags & IW_RETRY_MAX) || !(vwrq->flags & IW_RETRY_MIN)) {
4556 lrl = htod32(vwrq->value);
4557 if ((error = dev_wlc_ioctl(dev, WLC_SET_LRL, &lrl, sizeof(lrl))))
4562 #if WIRELESS_EXT > 20
4563 if ((vwrq->flags & IW_RETRY_SHORT) ||(vwrq->flags & IW_RETRY_MIN) ||
4564 !((vwrq->flags & IW_RETRY_LONG) || (vwrq->flags & IW_RETRY_MAX))) {
4566 if ((vwrq->flags & IW_RETRY_MIN) || !(vwrq->flags & IW_RETRY_MAX)) {
4568 srl = htod32(vwrq->value);
4569 if ((error = dev_wlc_ioctl(dev, WLC_SET_SRL, &srl, sizeof(srl))))
4578 struct net_device *dev,
4579 struct iw_request_info *info,
4580 struct iw_param *vwrq,
4584 int error, lrl, srl;
4586 WL_TRACE(("%s: SIOCGIWRETRY\n", dev->name));
4591 if ((vwrq->flags & IW_RETRY_TYPE) == IW_RETRY_LIFETIME)
4595 if ((error = dev_wlc_ioctl(dev, WLC_GET_LRL, &lrl, sizeof(lrl))) ||
4596 (error = dev_wlc_ioctl(dev, WLC_GET_SRL, &srl, sizeof(srl))))
4603 if (vwrq->flags & IW_RETRY_MAX) {
4604 vwrq->flags = IW_RETRY_LIMIT | IW_RETRY_MAX;
4607 vwrq->flags = IW_RETRY_LIMIT;
4610 vwrq->flags |= IW_RETRY_MIN;
4619 struct net_device *dev,
4620 struct iw_request_info *info,
4621 struct iw_point *dwrq,
4626 int error, val, wsec;
4628 WL_TRACE(("%s: SIOCSIWENCODE\n", dev->name));
4630 memset(&key, 0, sizeof(key));
4632 if ((dwrq->flags & IW_ENCODE_INDEX) == 0) {
4634 for (key.index = 0; key.index < DOT11_MAX_DEFAULT_KEYS; key.index++) {
4635 val = htod32(key.index);
4636 if ((error = dev_wlc_ioctl(dev, WLC_GET_KEY_PRIMARY, &val, sizeof(val))))
4643 if (key.index == DOT11_MAX_DEFAULT_KEYS)
4646 key.index = (dwrq->flags & IW_ENCODE_INDEX) - 1;
4647 if (key.index >= DOT11_MAX_DEFAULT_KEYS)
4652 if (!extra || !dwrq->length || (dwrq->flags & IW_ENCODE_NOKEY)) {
4654 val = htod32(key.index);
4655 if ((error = dev_wlc_ioctl(dev, WLC_SET_KEY_PRIMARY, &val, sizeof(val))))
4658 key.len = dwrq->length;
4660 if (dwrq->length > sizeof(key.data))
4663 memcpy(key.data, extra, dwrq->length);
4665 key.flags = WL_PRIMARY_KEY;
4668 key.algo = CRYPTO_ALGO_WEP1;
4670 case WEP128_KEY_SIZE:
4671 key.algo = CRYPTO_ALGO_WEP128;
4673 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 14)
4675 key.algo = CRYPTO_ALGO_TKIP;
4679 key.algo = CRYPTO_ALGO_AES_CCM;
4686 swap_key_from_BE(&key);
4687 if ((error = dev_wlc_ioctl(dev, WLC_SET_KEY, &key, sizeof(key))))
4692 val = (dwrq->flags & IW_ENCODE_DISABLED) ? 0 : WEP_ENABLED;
4694 if ((error = dev_wlc_intvar_get(dev, "wsec", &wsec)))
4697 wsec &= ~(WEP_ENABLED);
4700 if ((error = dev_wlc_intvar_set(dev, "wsec", wsec)))
4704 val = (dwrq->flags & IW_ENCODE_RESTRICTED) ? 1 : 0;
4706 if ((error = dev_wlc_ioctl(dev, WLC_SET_AUTH, &val, sizeof(val))))
4714 struct net_device *dev,
4715 struct iw_request_info *info,
4716 struct iw_point *dwrq,
4721 int error, val, wsec, auth;
4723 WL_TRACE(("%s: SIOCGIWENCODE\n", dev->name));
4726 bzero(&key, sizeof(wl_wsec_key_t));
4728 if ((dwrq->flags & IW_ENCODE_INDEX) == 0) {
4730 for (key.index = 0; key.index < DOT11_MAX_DEFAULT_KEYS; key.index++) {
4732 if ((error = dev_wlc_ioctl(dev, WLC_GET_KEY_PRIMARY, &val, sizeof(val))))
4739 key.index = (dwrq->flags & IW_ENCODE_INDEX) - 1;
4741 if (key.index >= DOT11_MAX_DEFAULT_KEYS)
4746 if ((error = dev_wlc_ioctl(dev, WLC_GET_WSEC, &wsec, sizeof(wsec))) ||
4747 (error = dev_wlc_ioctl(dev, WLC_GET_AUTH, &auth, sizeof(auth))))
4750 swap_key_to_BE(&key);
4752 wsec = dtoh32(wsec);
4753 auth = dtoh32(auth);
4755 dwrq->length = MIN(DOT11_MAX_KEY_SIZE, key.len);
4758 dwrq->flags = key.index + 1;
4759 if (!(wsec & (WEP_ENABLED | TKIP_ENABLED | AES_ENABLED))) {
4761 dwrq->flags |= IW_ENCODE_DISABLED;
4765 dwrq->flags |= IW_ENCODE_RESTRICTED;
4769 if (dwrq->length && extra)
4770 memcpy(extra, key.data, dwrq->length);
4777 struct net_device *dev,
4778 struct iw_request_info *info,
4779 struct iw_param *vwrq,
4785 WL_TRACE(("%s: SIOCSIWPOWER\n", dev->name));
4787 pm = vwrq->disabled ? PM_OFF : PM_MAX;
4790 if ((error = dev_wlc_ioctl(dev, WLC_SET_PM, &pm, sizeof(pm))))
4798 struct net_device *dev,
4799 struct iw_request_info *info,
4800 struct iw_param *vwrq,
4806 WL_TRACE(("%s: SIOCGIWPOWER\n", dev->name));
4808 if ((error = dev_wlc_ioctl(dev, WLC_GET_PM, &pm, sizeof(pm))))
4812 vwrq->disabled = pm ? 0 : 1;
4813 vwrq->flags = IW_POWER_ALL_R;
4818 #if WIRELESS_EXT > 17
4821 struct net_device *dev,
4822 struct iw_request_info *info,
4823 struct iw_point *iwp,
4827 uchar buf[WLC_IOCTL_SMLEN] = {0};
4831 WL_TRACE(("%s: SIOCSIWGENIE\n", dev->name));
4833 CHECK_EXTRA_FOR_NULL(extra);
4835 if (extra[0] == DOT11_MNG_WAPI_ID)
4837 wapi_ie_size = iwp->length;
4838 memcpy(p, extra, iwp->length);
4839 dev_wlc_bufvar_set(dev, "wapiie", buf, wapi_ie_size);
4842 dev_wlc_bufvar_set(dev, "wpaie", extra, iwp->length);
4849 struct net_device *dev,
4850 struct iw_request_info *info,
4851 struct iw_point *iwp,
4855 WL_TRACE(("%s: SIOCGIWGENIE\n", dev->name));
4857 dev_wlc_bufvar_get(dev, "wpaie", extra, iwp->length);
4862 wl_iw_set_encodeext(
4863 struct net_device *dev,
4864 struct iw_request_info *info,
4865 struct iw_point *dwrq,
4871 struct iw_encode_ext *iwe;
4873 WL_WSEC(("%s: SIOCSIWENCODEEXT\n", dev->name));
4875 CHECK_EXTRA_FOR_NULL(extra);
4877 memset(&key, 0, sizeof(key));
4878 iwe = (struct iw_encode_ext *)extra;
4881 if (dwrq->flags & IW_ENCODE_DISABLED) {
4887 if (dwrq->flags & IW_ENCODE_INDEX)
4888 key.index = (dwrq->flags & IW_ENCODE_INDEX) - 1;
4890 key.len = iwe->key_len;
4893 if (!ETHER_ISMULTI(iwe->addr.sa_data))
4894 bcopy((void *)&iwe->addr.sa_data, (char *)&key.ea, ETHER_ADDR_LEN);
4898 if (iwe->ext_flags & IW_ENCODE_EXT_SET_TX_KEY) {
4899 WL_WSEC(("Changing the the primary Key to %d\n", key.index));
4901 key.index = htod32(key.index);
4902 error = dev_wlc_ioctl(dev, WLC_SET_KEY_PRIMARY,
4903 &key.index, sizeof(key.index));
4909 swap_key_from_BE(&key);
4910 dev_wlc_ioctl(dev, WLC_SET_KEY, &key, sizeof(key));
4914 if (iwe->key_len > sizeof(key.data))
4917 WL_WSEC(("Setting the key index %d\n", key.index));
4918 if (iwe->ext_flags & IW_ENCODE_EXT_SET_TX_KEY) {
4919 WL_WSEC(("key is a Primary Key\n"));
4920 key.flags = WL_PRIMARY_KEY;
4923 bcopy((void *)iwe->key, key.data, iwe->key_len);
4925 if (iwe->alg == IW_ENCODE_ALG_TKIP) {
4927 bcopy(&key.data[24], keybuf, sizeof(keybuf));
4928 bcopy(&key.data[16], &key.data[24], sizeof(keybuf));
4929 bcopy(keybuf, &key.data[16], sizeof(keybuf));
4933 if (iwe->ext_flags & IW_ENCODE_EXT_RX_SEQ_VALID) {
4935 ivptr = (uchar *)iwe->rx_seq;
4936 key.rxiv.hi = (ivptr[5] << 24) | (ivptr[4] << 16) |
4937 (ivptr[3] << 8) | ivptr[2];
4938 key.rxiv.lo = (ivptr[1] << 8) | ivptr[0];
4939 key.iv_initialized = TRUE;
4943 case IW_ENCODE_ALG_NONE:
4944 key.algo = CRYPTO_ALGO_OFF;
4946 case IW_ENCODE_ALG_WEP:
4947 if (iwe->key_len == WEP1_KEY_SIZE)
4948 key.algo = CRYPTO_ALGO_WEP1;
4950 key.algo = CRYPTO_ALGO_WEP128;
4952 case IW_ENCODE_ALG_TKIP:
4953 key.algo = CRYPTO_ALGO_TKIP;
4955 case IW_ENCODE_ALG_CCMP:
4956 key.algo = CRYPTO_ALGO_AES_CCM;
4958 case IW_ENCODE_ALG_SM4:
4959 key.algo = CRYPTO_ALGO_SMS4;
4960 if (iwe->ext_flags & IW_ENCODE_EXT_GROUP_KEY) {
4961 key.flags &= ~WL_PRIMARY_KEY;
4967 swap_key_from_BE(&key);
4969 dhd_wait_pend8021x(dev);
4971 error = dev_wlc_ioctl(dev, WLC_SET_KEY, &key, sizeof(key));
4978 #if WIRELESS_EXT > 17
4981 pmkid_list_t pmkids;
4982 pmkid_t foo[MAXPMKID-1];
4987 struct net_device *dev,
4988 struct iw_request_info *info,
4989 struct iw_param *vwrq,
4993 struct iw_pmksa *iwpmksa;
4996 char eabuf[ETHER_ADDR_STR_LEN];
4998 WL_WSEC(("%s: SIOCSIWPMKSA\n", dev->name));
4999 CHECK_EXTRA_FOR_NULL(extra);
5001 iwpmksa = (struct iw_pmksa *)extra;
5002 bzero((char *)eabuf, ETHER_ADDR_STR_LEN);
5004 if (iwpmksa->cmd == IW_PMKSA_FLUSH) {
5005 WL_WSEC(("wl_iw_set_pmksa - IW_PMKSA_FLUSH\n"));
5006 bzero((char *)&pmkid_list, sizeof(pmkid_list));
5009 else if (iwpmksa->cmd == IW_PMKSA_REMOVE) {
5011 pmkid_list_t pmkid, *pmkidptr;
5015 bcopy(&iwpmksa->bssid.sa_data[0], &pmkidptr->pmkid[0].BSSID, ETHER_ADDR_LEN);
5016 bcopy(&iwpmksa->pmkid[0], &pmkidptr->pmkid[0].PMKID, WPA2_PMKID_LEN);
5018 WL_WSEC(("wl_iw_set_pmksa,IW_PMKSA_REMOVE - PMKID: %s = ",
5019 bcm_ether_ntoa(&pmkidptr->pmkid[0].BSSID,
5021 for (j = 0; j < WPA2_PMKID_LEN; j++)
5022 WL_WSEC(("%02x ", pmkidptr->pmkid[0].PMKID[j]));
5026 for (i = 0; i < pmkid_list.pmkids.npmkid; i++)
5027 if (!bcmp(&iwpmksa->bssid.sa_data[0], &pmkid_list.pmkids.pmkid[i].BSSID,
5031 if ((pmkid_list.pmkids.npmkid > 0) && (i < pmkid_list.pmkids.npmkid)) {
5032 bzero(&pmkid_list.pmkids.pmkid[i], sizeof(pmkid_t));
5033 for (; i < (pmkid_list.pmkids.npmkid - 1); i++) {
5034 bcopy(&pmkid_list.pmkids.pmkid[i+1].BSSID,
5035 &pmkid_list.pmkids.pmkid[i].BSSID,
5037 bcopy(&pmkid_list.pmkids.pmkid[i+1].PMKID,
5038 &pmkid_list.pmkids.pmkid[i].PMKID,
5041 pmkid_list.pmkids.npmkid--;
5047 else if (iwpmksa->cmd == IW_PMKSA_ADD) {
5048 for (i = 0; i < pmkid_list.pmkids.npmkid; i++)
5049 if (!bcmp(&iwpmksa->bssid.sa_data[0], &pmkid_list.pmkids.pmkid[i].BSSID,
5053 bcopy(&iwpmksa->bssid.sa_data[0],
5054 &pmkid_list.pmkids.pmkid[i].BSSID,
5056 bcopy(&iwpmksa->pmkid[0], &pmkid_list.pmkids.pmkid[i].PMKID,
5058 if (i == pmkid_list.pmkids.npmkid)
5059 pmkid_list.pmkids.npmkid++;
5067 k = pmkid_list.pmkids.npmkid;
5068 WL_WSEC(("wl_iw_set_pmksa,IW_PMKSA_ADD - PMKID: %s = ",
5069 bcm_ether_ntoa(&pmkid_list.pmkids.pmkid[k].BSSID,
5071 for (j = 0; j < WPA2_PMKID_LEN; j++)
5072 WL_WSEC(("%02x ", pmkid_list.pmkids.pmkid[k].PMKID[j]));
5076 WL_WSEC(("PRINTING pmkid LIST - No of elements %d, ret = %d\n", pmkid_list.pmkids.npmkid, ret));
5077 for (i = 0; i < pmkid_list.pmkids.npmkid; i++) {
5079 WL_WSEC(("PMKID[%d]: %s = ", i,
5080 bcm_ether_ntoa(&pmkid_list.pmkids.pmkid[i].BSSID,
5082 for (j = 0; j < WPA2_PMKID_LEN; j++)
5083 WL_WSEC(("%02x ", pmkid_list.pmkids.pmkid[i].PMKID[j]));
5089 ret = dev_wlc_bufvar_set(dev, "pmkid_info", (char *)&pmkid_list, sizeof(pmkid_list));
5096 wl_iw_get_encodeext(
5097 struct net_device *dev,
5098 struct iw_request_info *info,
5099 struct iw_param *vwrq,
5103 WL_WSEC(("%s: SIOCGIWENCODEEXT\n", dev->name));
5109 struct net_device *dev,
5110 struct iw_request_info *info,
5111 struct iw_param *vwrq,
5119 wl_iw_t *iw = *(wl_iw_t **)netdev_priv(dev);
5121 WL_WSEC(("%s: SIOCSIWAUTH\n", dev->name));
5124 if (ap_cfg_running) {
5125 WL_TRACE(("%s: Not executed, reason -'SOFTAP is active'\n", __FUNCTION__));
5130 paramid = vwrq->flags & IW_AUTH_INDEX;
5131 paramval = vwrq->value;
5133 WL_WSEC(("%s: SIOCSIWAUTH, paramid = 0x%0x, paramval = 0x%0x\n",
5134 dev->name, paramid, paramval));
5137 case IW_AUTH_WPA_VERSION:
5139 if (paramval & IW_AUTH_WPA_VERSION_DISABLED)
5140 val = WPA_AUTH_DISABLED;
5141 else if (paramval & (IW_AUTH_WPA_VERSION_WPA))
5142 val = WPA_AUTH_PSK | WPA_AUTH_UNSPECIFIED;
5144 else if (paramval & IW_AUTH_WPA_VERSION_WPA2)
5145 val = WPA2_AUTH_PSK | WPA2_AUTH_UNSPECIFIED;
5147 else if (paramval & IW_AUTH_WAPI_VERSION_1)
5148 val = WPA_AUTH_WAPI;
5149 WL_WSEC(("%s: %d: setting wpa_auth to 0x%0x\n", __FUNCTION__, __LINE__, val));
5150 if ((error = dev_wlc_intvar_set(dev, "wpa_auth", val)))
5153 case IW_AUTH_CIPHER_PAIRWISE:
5154 case IW_AUTH_CIPHER_GROUP:
5157 if (paramval & (IW_AUTH_CIPHER_WEP40 | IW_AUTH_CIPHER_WEP104))
5159 if (paramval & IW_AUTH_CIPHER_TKIP)
5161 if (paramval & IW_AUTH_CIPHER_CCMP)
5163 if (paramval & IW_AUTH_CIPHER_SMS4)
5166 if (paramid == IW_AUTH_CIPHER_PAIRWISE) {
5175 if (iw->privacy_invoked && !val) {
5176 WL_WSEC(("%s: %s: 'Privacy invoked' TRUE but clearing wsec, assuming "
5177 "we're a WPS enrollee\n", dev->name, __FUNCTION__));
5178 if ((error = dev_wlc_intvar_set(dev, "is_WPS_enrollee", TRUE))) {
5179 WL_ERROR(("Failed to set iovar is_WPS_enrollee\n"));
5183 if ((error = dev_wlc_intvar_set(dev, "is_WPS_enrollee", FALSE))) {
5184 WL_ERROR(("Failed to clear iovar is_WPS_enrollee\n"));
5189 if ((error = dev_wlc_intvar_set(dev, "wsec", val))) {
5190 WL_ERROR(("Failed to set 'wsec'iovar\n"));
5196 case IW_AUTH_KEY_MGMT:
5197 if ((error = dev_wlc_intvar_get(dev, "wpa_auth", &val))) {
5198 WL_ERROR(("Failed to get 'wpa_auth'iovar\n"));
5202 if (val & (WPA_AUTH_PSK | WPA_AUTH_UNSPECIFIED)) {
5203 if (paramval & IW_AUTH_KEY_MGMT_PSK)
5206 val = WPA_AUTH_UNSPECIFIED;
5209 else if (val & (WPA2_AUTH_PSK | WPA2_AUTH_UNSPECIFIED)) {
5210 if (paramval & IW_AUTH_KEY_MGMT_PSK)
5211 val = WPA2_AUTH_PSK;
5213 val = WPA2_AUTH_UNSPECIFIED;
5216 if (paramval & (IW_AUTH_KEY_MGMT_WAPI_PSK | IW_AUTH_KEY_MGMT_WAPI_CERT))
5217 val = WPA_AUTH_WAPI;
5218 WL_WSEC(("%s: %d: setting wpa_auth to %d\n", __FUNCTION__, __LINE__, val));
5219 if ((error = dev_wlc_intvar_set(dev, "wpa_auth", val))) {
5220 WL_ERROR(("Failed to set 'wpa_auth'iovar\n"));
5225 case IW_AUTH_TKIP_COUNTERMEASURES:
5226 if ((error = dev_wlc_bufvar_set(dev, "tkip_countermeasures", \
5227 (char *)¶mval, sizeof(paramval))))
5228 WL_WSEC(("%s: tkip_countermeasures failed %d\n", __FUNCTION__, error));
5231 case IW_AUTH_80211_AUTH_ALG:
5233 WL_WSEC(("Setting the D11auth %d\n", paramval));
5234 if (paramval == IW_AUTH_ALG_OPEN_SYSTEM)
5236 else if (paramval == IW_AUTH_ALG_SHARED_KEY)
5238 else if (paramval == (IW_AUTH_ALG_OPEN_SYSTEM | IW_AUTH_ALG_SHARED_KEY))
5242 if (!error && (error = dev_wlc_intvar_set(dev, "auth", val)))
5246 case IW_AUTH_WPA_ENABLED:
5247 if (paramval == 0) {
5250 if ((error = dev_wlc_intvar_get(dev, "wsec", &val))) {
5251 WL_ERROR(("Failed to get 'wsec'iovar\n"));
5254 if (val & (TKIP_ENABLED | AES_ENABLED)) {
5255 val &= ~(TKIP_ENABLED | AES_ENABLED);
5256 dev_wlc_intvar_set(dev, "wsec", val);
5260 WL_INFORM(("%s: %d: setting wpa_auth to %d\n",
5261 __FUNCTION__, __LINE__, val));
5262 error = dev_wlc_intvar_set(dev, "wpa_auth", 0);
5264 WL_ERROR(("Failed to set 'wpa_auth'iovar\n"));
5271 case IW_AUTH_DROP_UNENCRYPTED:
5272 error = dev_wlc_bufvar_set(dev, "wsec_restrict", \
5273 (char *)¶mval, sizeof(paramval));
5275 WL_ERROR(("%s: wsec_restrict %d\n", __FUNCTION__, error));
5278 case IW_AUTH_RX_UNENCRYPTED_EAPOL:
5279 error = dev_wlc_bufvar_set(dev, "rx_unencrypted_eapol", \
5280 (char *)¶mval, sizeof(paramval));
5282 WL_WSEC(("%s: rx_unencrypted_eapol %d\n", __FUNCTION__, error));
5285 #if WIRELESS_EXT > 17
5286 case IW_AUTH_ROAMING_CONTROL:
5287 WL_INFORM(("%s: IW_AUTH_ROAMING_CONTROL\n", __FUNCTION__));
5290 case IW_AUTH_PRIVACY_INVOKED: {
5293 if (paramval == 0) {
5294 iw->privacy_invoked = FALSE;
5295 if ((error = dev_wlc_intvar_set(dev, "is_WPS_enrollee", FALSE))) {
5296 WL_WSEC(("Failed to clear iovar is_WPS_enrollee\n"));
5300 iw->privacy_invoked = TRUE;
5301 if ((error = dev_wlc_intvar_get(dev, "wsec", &wsec)))
5304 if (!(IW_WSEC_ENABLED(wsec))) {
5306 if ((error = dev_wlc_intvar_set(dev, "is_WPS_enrollee", TRUE))) {
5307 WL_WSEC(("Failed to set iovar is_WPS_enrollee\n"));
5311 if ((error = dev_wlc_intvar_set(dev, "is_WPS_enrollee", FALSE))) {
5312 WL_WSEC(("Failed to clear iovar is_WPS_enrollee\n"));
5320 case IW_AUTH_WAPI_ENABLED:
5321 if ((error = dev_wlc_intvar_get(dev, "wsec", &val)))
5324 val |= SMS4_ENABLED;
5325 if ((error = dev_wlc_intvar_set(dev, "wsec", val))) {
5326 WL_ERROR(("%s: setting wsec to 0x%0x returned error %d\n",
5327 __FUNCTION__, val, error));
5330 if ((error = dev_wlc_intvar_set(dev, "wpa_auth", WPA_AUTH_WAPI))) {
5331 WL_ERROR(("%s: setting wpa_auth(WPA_AUTH_WAPI) returned %d\n",
5332 __FUNCTION__, error));
5344 #define VAL_PSK(_val) (((_val) & WPA_AUTH_PSK) || ((_val) & WPA2_AUTH_PSK))
5346 #define VAL_PSK(_val) (((_val) & WPA_AUTH_PSK))
5351 struct net_device *dev,
5352 struct iw_request_info *info,
5353 struct iw_param *vwrq,
5361 wl_iw_t *iw = *(wl_iw_t **)netdev_priv(dev);
5363 WL_TRACE(("%s: SIOCGIWAUTH\n", dev->name));
5365 paramid = vwrq->flags & IW_AUTH_INDEX;
5368 case IW_AUTH_WPA_VERSION:
5370 if ((error = dev_wlc_intvar_get(dev, "wpa_auth", &val)))
5372 if (val & (WPA_AUTH_NONE | WPA_AUTH_DISABLED))
5373 paramval = IW_AUTH_WPA_VERSION_DISABLED;
5374 else if (val & (WPA_AUTH_PSK | WPA_AUTH_UNSPECIFIED))
5375 paramval = IW_AUTH_WPA_VERSION_WPA;
5377 else if (val & (WPA2_AUTH_PSK | WPA2_AUTH_UNSPECIFIED))
5378 paramval = IW_AUTH_WPA_VERSION_WPA2;
5381 case IW_AUTH_CIPHER_PAIRWISE:
5382 case IW_AUTH_CIPHER_GROUP:
5383 if (paramid == IW_AUTH_CIPHER_PAIRWISE)
5390 if (val & WEP_ENABLED)
5391 paramval |= (IW_AUTH_CIPHER_WEP40 | IW_AUTH_CIPHER_WEP104);
5392 if (val & TKIP_ENABLED)
5393 paramval |= (IW_AUTH_CIPHER_TKIP);
5394 if (val & AES_ENABLED)
5395 paramval |= (IW_AUTH_CIPHER_CCMP);
5398 paramval = IW_AUTH_CIPHER_NONE;
5400 case IW_AUTH_KEY_MGMT:
5402 if ((error = dev_wlc_intvar_get(dev, "wpa_auth", &val)))
5405 paramval = IW_AUTH_KEY_MGMT_PSK;
5407 paramval = IW_AUTH_KEY_MGMT_802_1X;
5410 case IW_AUTH_TKIP_COUNTERMEASURES:
5411 error = dev_wlc_bufvar_get(dev, "tkip_countermeasures", \
5412 (char *)¶mval, sizeof(paramval));
5414 WL_ERROR(("%s get tkip_countermeasures %d\n", __FUNCTION__, error));
5417 case IW_AUTH_DROP_UNENCRYPTED:
5418 error = dev_wlc_bufvar_get(dev, "wsec_restrict", \
5419 (char *)¶mval, sizeof(paramval));
5421 WL_ERROR(("%s get wsec_restrict %d\n", __FUNCTION__, error));
5424 case IW_AUTH_RX_UNENCRYPTED_EAPOL:
5425 error = dev_wlc_bufvar_get(dev, "rx_unencrypted_eapol", \
5426 (char *)¶mval, sizeof(paramval));
5428 WL_ERROR(("%s get rx_unencrypted_eapol %d\n", __FUNCTION__, error));
5431 case IW_AUTH_80211_AUTH_ALG:
5433 if ((error = dev_wlc_intvar_get(dev, "auth", &val)))
5436 paramval = IW_AUTH_ALG_OPEN_SYSTEM;
5438 paramval = IW_AUTH_ALG_SHARED_KEY;
5440 case IW_AUTH_WPA_ENABLED:
5441 if ((error = dev_wlc_intvar_get(dev, "wpa_auth", &val)))
5448 #if WIRELESS_EXT > 17
5449 case IW_AUTH_ROAMING_CONTROL:
5450 WL_ERROR(("%s: IW_AUTH_ROAMING_CONTROL\n", __FUNCTION__));
5453 case IW_AUTH_PRIVACY_INVOKED:
5454 paramval = iw->privacy_invoked;
5458 vwrq->value = paramval;
5466 static int ap_macmode = MACLIST_MODE_DISABLED;
5467 static struct mflist ap_black_list;
5469 wl_iw_parse_wep(char *keystr, wl_wsec_key_t *key)
5472 unsigned char *data = key->data;
5474 switch (strlen(keystr)) {
5478 key->len = strlen(keystr);
5479 memcpy(data, keystr, key->len + 1);
5485 if (!strnicmp(keystr, "0x", 2))
5493 key->len = strlen(keystr) / 2;
5495 strncpy(hex, keystr, 2);
5496 *data++ = (char) bcm_strtoul(hex, NULL, 16);
5506 key->algo = CRYPTO_ALGO_WEP1;
5509 key->algo = CRYPTO_ALGO_WEP128;
5512 key->algo = CRYPTO_ALGO_AES_CCM;
5515 key->algo = CRYPTO_ALGO_TKIP;
5521 key->flags |= WL_PRIMARY_KEY;
5526 #ifdef EXT_WPA_CRYPTO
5527 #define SHA1HashSize 20
5528 extern void pbkdf2_sha1(const char *passphrase, const char *ssid, size_t ssid_len,
5529 int iterations, u8 *buf, size_t buflen);
5533 #define SHA1HashSize 20
5534 int pbkdf2_sha1(const char *passphrase, const char *ssid, size_t ssid_len,
5535 int iterations, u8 *buf, size_t buflen)
5537 WL_ERROR(("WARNING: %s is not implemented !!!\n", __FUNCTION__));
5544 int dev_iw_write_cfg1_bss_var(struct net_device *dev, int val)
5552 char smbuf[WLC_IOCTL_SMLEN];
5553 memset(smbuf, 0, sizeof(smbuf));
5556 bss_setbuf.val = val;
5558 bss_set_res = dev_iw_iovar_setbuf(dev, "bss",
5559 &bss_setbuf, sizeof(bss_setbuf), smbuf, sizeof(smbuf));
5560 WL_TRACE(("%s: bss_set_result:%d set with %d\n", __FUNCTION__, bss_set_res, val));
5566 int dev_iw_read_cfg1_bss_var(struct net_device *dev, int *val)
5570 char smbuf[WLC_IOCTL_SMLEN];
5571 memset(smbuf, 0, sizeof(smbuf));
5573 bss_set_res = dev_iw_iovar_getbuf(dev, "bss", \
5574 &bsscfg_idx, sizeof(bsscfg_idx), smbuf, sizeof(smbuf));
5575 *val = *(int*)smbuf;
5576 *val = dtoh32(*val);
5577 WL_TRACE(("%s: status=%d bss_get_result=%d\n", __FUNCTION__, bss_set_res, *val));
5583 static int wl_bssiovar_mkbuf(
5592 const char *prefix = "bsscfg:";
5598 prefixlen = strlen(prefix);
5599 namelen = strlen(iovar) + 1;
5600 iolen = prefixlen + namelen + sizeof(int) + paramlen;
5602 if (buflen < 0 || iolen > (uint)buflen) {
5603 *perr = BCME_BUFTOOSHORT;
5609 memcpy(p, prefix, prefixlen);
5612 memcpy(p, iovar, namelen);
5615 bssidx = htod32(bssidx);
5616 memcpy(p, &bssidx, sizeof(int32));
5620 memcpy(p, param, paramlen);
5628 int get_user_params(char *user_params, struct iw_point *dwrq)
5632 if (copy_from_user(user_params, dwrq->pointer, dwrq->length)) {
5633 WL_ERROR(("\n%s: no user params: uptr:%p, ulen:%d\n",
5634 __FUNCTION__, dwrq->pointer, dwrq->length));
5638 WL_TRACE(("\n%s: iwpriv user params:%s\n", __FUNCTION__, user_params));
5644 #define strtoul(nptr, endptr, base) bcm_strtoul((nptr), (endptr), (base))
5649 wl_iw_combined_scan_set(struct net_device *dev, wlc_ssid_t* ssids_local, int nssid, int nchan)
5651 int params_size = WL_SCAN_PARAMS_FIXED_SIZE + WL_NUMCHANNELS * sizeof(uint16);
5655 iscan_info_t *iscan = g_iscan;
5657 WL_SCAN(("%s nssid=%d nchan=%d\n", __FUNCTION__, nssid, nchan));
5659 if ((!dev) && (!g_iscan) && (!iscan->iscan_ex_params_p)) {
5660 WL_ERROR(("%s error exit\n", __FUNCTION__));
5666 if (dhd_dev_get_pno_status(dev)) {
5667 WL_ERROR(("%s: Scan called when PNO is active\n", __FUNCTION__));
5671 params_size += WL_SCAN_PARAMS_SSID_MAX * sizeof(wlc_ssid_t);
5674 i = OFFSETOF(wl_scan_params_t, channel_list) + nchan * sizeof(uint16);
5675 i = ROUNDUP(i, sizeof(uint32));
5676 if (i + nssid * sizeof(wlc_ssid_t) > params_size) {
5677 printf("additional ssids exceed params_size\n");
5682 p = ((char*)&iscan->iscan_ex_params_p->params) + i;
5683 memcpy(p, ssids_local, nssid * sizeof(wlc_ssid_t));
5684 p += nssid * sizeof(wlc_ssid_t);
5686 p = (char*)iscan->iscan_ex_params_p->params.channel_list + nchan * sizeof(uint16);
5689 iscan->iscan_ex_params_p->params.channel_num = \
5690 htod32((nssid << WL_SCAN_PARAMS_NSSID_SHIFT) | \
5691 (nchan & WL_SCAN_PARAMS_COUNT_MASK));
5694 (uint)((iscan->iscan_ex_params_p->params.channel_num >> WL_SCAN_PARAMS_NSSID_SHIFT) & \
5695 WL_SCAN_PARAMS_COUNT_MASK);
5697 params_size = (int) (p - (char*)iscan->iscan_ex_params_p + nssid * sizeof(wlc_ssid_t));
5698 iscan->iscan_ex_param_size = params_size;
5700 iscan->list_cur = iscan->list_hdr;
5701 iscan->iscan_state = ISCAN_STATE_SCANING;
5702 wl_iw_set_event_mask(dev);
5703 mod_timer(&iscan->timer, jiffies + iscan->timer_ms*HZ/1000);
5705 iscan->timer_on = 1;
5710 WL_SCAN(("\n### List of SSIDs to scan ###\n"));
5711 for (i = 0; i < nssid; i++) {
5712 if (!ssids_local[i].SSID_len)
5713 WL_SCAN(("%d: Broadcast scan\n", i));
5715 WL_SCAN(("%d: scan for %s size =%d\n", i, \
5716 ssids_local[i].SSID, ssids_local[i].SSID_len));
5718 WL_SCAN(("### List of channels to scan ###\n"));
5719 for (i = 0; i < nchan; i++)
5721 WL_SCAN(("%d ", iscan->iscan_ex_params_p->params.channel_list[i]));
5723 WL_SCAN(("\nnprobes=%d\n", iscan->iscan_ex_params_p->params.nprobes));
5724 WL_SCAN(("active_time=%d\n", iscan->iscan_ex_params_p->params.active_time));
5725 WL_SCAN(("passive_time=%d\n", iscan->iscan_ex_params_p->params.passive_time));
5726 WL_SCAN(("home_time=%d\n", iscan->iscan_ex_params_p->params.home_time));
5727 WL_SCAN(("scan_type=%d\n", iscan->iscan_ex_params_p->params.scan_type));
5728 WL_SCAN(("\n###################\n"));
5732 if (params_size > WLC_IOCTL_MEDLEN) {
5733 WL_ERROR(("Set ISCAN for %s due to params_size=%d \n", \
5734 __FUNCTION__, params_size));
5738 if ((err = dev_iw_iovar_setbuf(dev, "iscan", iscan->iscan_ex_params_p, \
5739 iscan->iscan_ex_param_size, \
5740 iscan->ioctlbuf, sizeof(iscan->ioctlbuf)))) {
5741 WL_ERROR(("Set ISCAN for %s failed with %d\n", __FUNCTION__, err));
5751 static int iwpriv_set_cscan(struct net_device *dev, struct iw_request_info *info, \
5752 union iwreq_data *wrqu, char *ext)
5756 iscan_info_t *iscan = g_iscan;
5757 wlc_ssid_t ssids_local[WL_SCAN_PARAMS_SSID_MAX];
5761 WL_TRACE(("\%s: info->cmd:%x, info->flags:%x, u.data=0x%p, u.len=%d\n",
5762 __FUNCTION__, info->cmd, info->flags,
5763 wrqu->data.pointer, wrqu->data.length));
5765 if (g_onoff == G_WLAN_SET_OFF) {
5766 WL_TRACE(("%s: driver is not up yet after START\n", __FUNCTION__));
5770 if (wrqu->data.length != 0) {
5774 if (!iscan->iscan_ex_params_p) {
5778 if (!(extra = kmalloc(wrqu->data.length+1, GFP_KERNEL)))
5781 if (copy_from_user(extra, wrqu->data.pointer, wrqu->data.length)) {
5786 extra[wrqu->data.length] = 0;
5787 WL_ERROR(("Got str param in iw_point:\n %s\n", extra));
5791 if (strncmp(str_ptr, GET_SSID, strlen(GET_SSID))) {
5792 WL_ERROR(("%s Error: extracting SSID='' string\n", __FUNCTION__));
5795 str_ptr += strlen(GET_SSID);
5796 nssid = wl_iw_parse_ssid_list(&str_ptr, ssids_local, nssid, \
5797 WL_SCAN_PARAMS_SSID_MAX);
5799 WL_ERROR(("%s wrong ssid list", __FUNCTION__));
5803 if (iscan->iscan_ex_param_size > WLC_IOCTL_MAXLEN) {
5804 WL_ERROR(("%s wrong ex_param_size %d", \
5805 __FUNCTION__, iscan->iscan_ex_param_size));
5808 memset(iscan->iscan_ex_params_p, 0, iscan->iscan_ex_param_size);
5811 wl_iw_iscan_prep(&iscan->iscan_ex_params_p->params, NULL);
5812 iscan->iscan_ex_params_p->version = htod32(ISCAN_REQ_VERSION);
5813 iscan->iscan_ex_params_p->action = htod16(WL_SCAN_ACTION_START);
5814 iscan->iscan_ex_params_p->scan_duration = htod16(0);
5817 if ((nchan = wl_iw_parse_channel_list(&str_ptr, \
5818 &iscan->iscan_ex_params_p->params.channel_list[0], \
5819 WL_NUMCHANNELS)) == -1) {
5820 WL_ERROR(("%s missing channel list\n", __FUNCTION__));
5825 get_parmeter_from_string(&str_ptr, \
5826 GET_NPROBE, PTYPE_INTDEC, \
5827 &iscan->iscan_ex_params_p->params.nprobes, 2);
5829 get_parmeter_from_string(&str_ptr, GET_ACTIVE_ASSOC_DWELL, PTYPE_INTDEC, \
5830 &iscan->iscan_ex_params_p->params.active_time, 4);
5832 get_parmeter_from_string(&str_ptr, GET_PASSIVE_ASSOC_DWELL, PTYPE_INTDEC, \
5833 &iscan->iscan_ex_params_p->params.passive_time, 4);
5835 get_parmeter_from_string(&str_ptr, GET_HOME_DWELL, PTYPE_INTDEC, \
5836 &iscan->iscan_ex_params_p->params.home_time, 4);
5838 get_parmeter_from_string(&str_ptr, GET_SCAN_TYPE, PTYPE_INTDEC, \
5839 &iscan->iscan_ex_params_p->params.scan_type, 1);
5841 res = wl_iw_combined_scan_set(dev, ssids_local, nssid, nchan);
5844 WL_ERROR(("IWPRIV argument len = 0 \n"));
5858 struct net_device *dev,
5859 struct iw_request_info *info,
5860 union iwreq_data *wrqu,
5865 iscan_info_t *iscan = g_iscan;
5866 wlc_ssid_t ssids_local[WL_SCAN_PARAMS_SSID_MAX];
5869 cscan_tlv_t *cscan_tlv_temp;
5875 char tlv_in_example[] = { 'C', 'S', 'C', 'A', 'N', ' ', \
5876 0x53, 0x01, 0x00, 0x00,
5892 WL_TRACE(("\n### %s: info->cmd:%x, info->flags:%x, u.data=0x%p, u.len=%d\n",
5893 __FUNCTION__, info->cmd, info->flags,
5894 wrqu->data.pointer, wrqu->data.length));
5896 net_os_wake_lock(dev);
5898 if (g_onoff == G_WLAN_SET_OFF) {
5899 WL_TRACE(("%s: driver is not up yet after START\n", __FUNCTION__));
5904 if (wrqu->data.length < (strlen(CSCAN_COMMAND) + sizeof(cscan_tlv_t))) {
5905 WL_ERROR(("%s aggument=%d less %d\n", __FUNCTION__, \
5906 wrqu->data.length, strlen(CSCAN_COMMAND) + sizeof(cscan_tlv_t)));
5911 memcpy(extra, tlv_in_example, sizeof(tlv_in_example));
5912 wrqu->data.length = sizeof(tlv_in_example);
5913 for (i = 0; i < wrqu->data.length; i++)
5914 printf("%02X ", extra[i]);
5919 str_ptr += strlen(CSCAN_COMMAND);
5920 tlv_size_left = wrqu->data.length - strlen(CSCAN_COMMAND);
5922 cscan_tlv_temp = (cscan_tlv_t *)str_ptr;
5923 memset(ssids_local, 0, sizeof(ssids_local));
5925 if ((cscan_tlv_temp->prefix == CSCAN_TLV_PREFIX) && \
5926 (cscan_tlv_temp->version == CSCAN_TLV_VERSION) && \
5927 (cscan_tlv_temp->subver == CSCAN_TLV_SUBVERSION))
5929 str_ptr += sizeof(cscan_tlv_t);
5930 tlv_size_left -= sizeof(cscan_tlv_t);
5933 if ((nssid = wl_iw_parse_ssid_list_tlv(&str_ptr, ssids_local, \
5934 WL_SCAN_PARAMS_SSID_MAX, &tlv_size_left)) <= 0) {
5935 WL_ERROR(("SSID is not presented or corrupted ret=%d\n", nssid));
5940 memset(iscan->iscan_ex_params_p, 0, iscan->iscan_ex_param_size);
5943 wl_iw_iscan_prep(&iscan->iscan_ex_params_p->params, NULL);
5944 iscan->iscan_ex_params_p->version = htod32(ISCAN_REQ_VERSION);
5945 iscan->iscan_ex_params_p->action = htod16(WL_SCAN_ACTION_START);
5946 iscan->iscan_ex_params_p->scan_duration = htod16(0);
5949 while (tlv_size_left > 0)
5953 case CSCAN_TLV_TYPE_CHANNEL_IE:
5955 if ((nchan = wl_iw_parse_channel_list_tlv(&str_ptr, \
5956 &iscan->iscan_ex_params_p->params.channel_list[0], \
5957 WL_NUMCHANNELS, &tlv_size_left)) == -1) {
5958 WL_ERROR(("%s missing channel list\n", \
5963 case CSCAN_TLV_TYPE_NPROBE_IE:
5964 if ((res = wl_iw_parse_data_tlv(&str_ptr, \
5965 &iscan->iscan_ex_params_p->params.nprobes, \
5966 sizeof(iscan->iscan_ex_params_p->params.nprobes), \
5967 type, sizeof(char), &tlv_size_left)) == -1) {
5968 WL_ERROR(("%s return %d\n", \
5969 __FUNCTION__, res));
5973 case CSCAN_TLV_TYPE_ACTIVE_IE:
5974 if ((res = wl_iw_parse_data_tlv(&str_ptr, \
5975 &iscan->iscan_ex_params_p->params.active_time, \
5976 sizeof(iscan->iscan_ex_params_p->params.active_time), \
5977 type, sizeof(short), &tlv_size_left)) == -1) {
5978 WL_ERROR(("%s return %d\n", \
5979 __FUNCTION__, res));
5983 case CSCAN_TLV_TYPE_PASSIVE_IE:
5984 if ((res = wl_iw_parse_data_tlv(&str_ptr, \
5985 &iscan->iscan_ex_params_p->params.passive_time, \
5986 sizeof(iscan->iscan_ex_params_p->params.passive_time), \
5987 type, sizeof(short), &tlv_size_left)) == -1) {
5988 WL_ERROR(("%s return %d\n", \
5989 __FUNCTION__, res));
5993 case CSCAN_TLV_TYPE_HOME_IE:
5994 if ((res = wl_iw_parse_data_tlv(&str_ptr, \
5995 &iscan->iscan_ex_params_p->params.home_time, \
5996 sizeof(iscan->iscan_ex_params_p->params.home_time), \
5997 type, sizeof(short), &tlv_size_left)) == -1) {
5998 WL_ERROR(("%s return %d\n", \
5999 __FUNCTION__, res));
6003 case CSCAN_TLV_TYPE_STYPE_IE:
6004 if ((res = wl_iw_parse_data_tlv(&str_ptr, \
6005 &iscan->iscan_ex_params_p->params.scan_type, \
6006 sizeof(iscan->iscan_ex_params_p->params.scan_type), \
6007 type, sizeof(char), &tlv_size_left)) == -1) {
6008 WL_ERROR(("%s return %d\n", \
6009 __FUNCTION__, res));
6015 WL_ERROR(("%s get unkwown type %X\n", \
6016 __FUNCTION__, type));
6024 WL_ERROR(("%s get wrong TLV command\n", __FUNCTION__));
6028 #if defined(CONFIG_FIRST_SCAN)
6029 if (g_first_broadcast_scan < BROADCAST_SCAN_FIRST_RESULT_CONSUMED) {
6030 if (++g_first_counter_scans == MAX_ALLOWED_BLOCK_SCAN_FROM_FIRST_SCAN) {
6032 WL_ERROR(("%s Clean up First scan flag which is %d\n", \
6033 __FUNCTION__, g_first_broadcast_scan));
6034 g_first_broadcast_scan = BROADCAST_SCAN_FIRST_RESULT_CONSUMED;
6037 WL_ERROR(("%s Ignoring CSCAN : First Scan is not done yet %d\n", \
6038 __FUNCTION__, g_first_counter_scans));
6045 res = wl_iw_combined_scan_set(dev, ssids_local, nssid, nchan);
6048 net_os_wake_unlock(dev);
6057 static int thr_wait_for_2nd_eth_dev(void *data)
6059 struct net_device *dev = (struct net_device *)data;
6062 unsigned long flags;
6064 net_os_wake_lock(dev);
6066 DAEMONIZE("wl0_eth_wthread");
6068 WL_TRACE(("\n>%s thread started:, PID:%x\n", __FUNCTION__, current->pid));
6069 iw = *(wl_iw_t **)netdev_priv(dev);
6071 WL_ERROR(("%s: dev is null\n", __FUNCTION__));
6076 #ifndef BCMSDIOH_STD
6077 if (down_timeout(&ap_eth_sema, msecs_to_jiffies(5000)) != 0) {
6078 WL_ERROR(("\n%s: sap_eth_sema timeout \n", __FUNCTION__));
6084 flags = dhd_os_spin_lock(iw->pub);
6086 WL_ERROR((" ap_net_dev is null !!!"));
6088 dhd_os_spin_unlock(iw->pub, flags);
6092 WL_TRACE(("\n>%s: Thread:'softap ethdev IF:%s is detected !!!'\n\n",
6093 __FUNCTION__, ap_net_dev->name));
6095 ap_cfg_running = TRUE;
6097 dhd_os_spin_unlock(iw->pub, flags);
6101 wl_iw_send_priv_event(priv_dev, "AP_SET_CFG_OK");
6104 WL_TRACE(("\n>%s, thread completed\n", __FUNCTION__));
6106 net_os_wake_unlock(dev);
6108 complete_and_exit(&ap_cfg_exited, 0);
6113 static int last_auto_channel = 6;
6115 static int get_softap_auto_channel(struct net_device *dev, struct ap_profile *ap)
6118 wl_uint32_list_t request;
6123 wlc_ssid_t null_ssid;
6128 int bsscfg_index = 1;
6129 char buf[WLC_IOCTL_SMLEN];
6131 WL_SOFTAP(("Enter %s\n", __FUNCTION__));
6134 if (ap_cfg_running) {
6135 ap->channel = last_auto_channel;
6139 memset(&null_ssid, 0, sizeof(wlc_ssid_t));
6140 res |= dev_wlc_ioctl(dev, WLC_UP, &updown, sizeof(updown));
6142 res |= dev_wlc_ioctl(dev, WLC_SET_SSID, &null_ssid, sizeof(null_ssid));
6144 iolen = wl_bssiovar_mkbuf("ssid", bsscfg_index, (char *)(&null_ssid), \
6145 null_ssid.SSID_len+4, buf, sizeof(buf), &mkvar_err);
6147 res |= dev_wlc_ioctl(dev, WLC_SET_VAR, buf, iolen);
6150 request.count = htod32(0);
6151 ret = dev_wlc_ioctl(dev, WLC_START_CHANNEL_SEL, &request, sizeof(request));
6153 WL_ERROR(("can't start auto channel scan\n"));
6160 ret = dev_wlc_ioctl(dev, WLC_GET_CHANNEL_SEL, &chosen, sizeof(chosen));
6161 if (ret < 0 || dtoh32(chosen) == 0) {
6163 goto get_channel_retry;
6165 WL_ERROR(("can't get auto channel sel, err = %d, \
6166 chosen = %d\n", ret, chosen));
6170 if ((chosen == 1) && (!rescan++))
6171 goto auto_channel_retry;
6172 WL_SOFTAP(("Set auto channel = %d\n", chosen));
6173 ap->channel = chosen;
6174 if ((res = dev_wlc_ioctl(dev, WLC_DOWN, &updown, sizeof(updown))) < 0) {
6175 WL_ERROR(("%s fail to set up err =%d\n", __FUNCTION__, res));
6180 last_auto_channel = ap->channel;
6188 static int set_ap_cfg(struct net_device *dev, struct ap_profile *ap)
6202 int bsscfg_index = 1;
6203 char buf[WLC_IOCTL_SMLEN];
6207 WL_ERROR(("%s: dev is null\n", __FUNCTION__));
6211 net_os_wake_lock(dev);
6213 WL_SOFTAP(("wl_iw: set ap profile:\n"));
6214 WL_SOFTAP((" ssid = '%s'\n", ap->ssid));
6215 WL_SOFTAP((" security = '%s'\n", ap->sec));
6216 if (ap->key[0] != '\0')
6217 WL_SOFTAP((" key = '%s'\n", ap->key));
6218 WL_SOFTAP((" channel = %d\n", ap->channel));
6219 WL_SOFTAP((" max scb = %d\n", ap->max_scb));
6222 if (ap_cfg_running) {
6223 wl_iw_softap_deassoc_stations(dev, NULL);
6224 ap_cfg_running = FALSE;
6228 if (ap_cfg_running == FALSE) {
6231 sema_init(&ap_eth_sema, 0);
6234 if ((res = dev_wlc_intvar_set(dev, "mpc", mpc))) {
6235 WL_ERROR(("%s fail to set mpc\n", __FUNCTION__));
6241 if ((res = dev_wlc_ioctl(dev, WLC_DOWN, &updown, sizeof(updown)))) {
6242 WL_ERROR(("%s fail to set updown\n", __FUNCTION__));
6248 if ((res = dev_wlc_ioctl(dev, WLC_SET_AP, &apsta_var, sizeof(apsta_var)))) {
6249 WL_ERROR(("%s fail to set apsta_var 0\n", __FUNCTION__));
6253 if ((res = dev_wlc_ioctl(dev, WLC_SET_AP, &apsta_var, sizeof(apsta_var)))) {
6254 WL_ERROR(("%s fail to set apsta_var 1\n", __FUNCTION__));
6257 res = dev_wlc_ioctl(dev, WLC_GET_AP, &apsta_var, sizeof(apsta_var));
6260 iolen = wl_bssiovar_mkbuf("apsta",
6261 bsscfg_index, &apsta_var, sizeof(apsta_var)+4,
6262 buf, sizeof(buf), &mkvar_err);
6267 if ((res = dev_wlc_ioctl(dev, WLC_SET_VAR, buf, iolen)) < 0) {
6268 WL_ERROR(("%s fail to set apsta \n", __FUNCTION__));
6271 WL_TRACE(("\n>in %s: apsta set result: %d \n", __FUNCTION__, res));
6275 if ((res = dev_wlc_ioctl(dev, WLC_UP, &updown, sizeof(updown))) < 0) {
6276 WL_ERROR(("%s fail to set apsta \n", __FUNCTION__));
6283 WL_ERROR(("%s: ap_net_dev is null\n", __FUNCTION__));
6287 res = wl_iw_softap_deassoc_stations(ap_net_dev, NULL);
6290 if ((res = dev_iw_write_cfg1_bss_var(dev, 0)) < 0) {
6291 WL_ERROR(("%s fail to set bss down\n", __FUNCTION__));
6296 if (strlen(ap->country_code)) {
6298 if ((error = dev_wlc_ioctl(dev, WLC_SET_COUNTRY,
6299 ap->country_code, sizeof(ap->country_code))) >= 0) {
6300 WL_SOFTAP(("%s: set country %s OK\n",
6301 __FUNCTION__, ap->country_code));
6302 dhd_bus_country_set(dev, &ap->country_code[0]);
6304 WL_ERROR(("%s: ERROR:%d setting country %s\n",
6305 __FUNCTION__, error, ap->country_code));
6308 WL_SOFTAP(("%s: Country code is not specified,"
6309 " will use Radio's default\n",
6313 iolen = wl_bssiovar_mkbuf("closednet",
6314 bsscfg_index, &ap->closednet, sizeof(ap->closednet)+4,
6315 buf, sizeof(buf), &mkvar_err);
6317 if ((res = dev_wlc_ioctl(dev, WLC_SET_VAR, buf, iolen)) < 0) {
6318 WL_ERROR(("%s failed to set 'closednet'for apsta \n", __FUNCTION__));
6323 if ((ap->channel == 0) && (get_softap_auto_channel(dev, ap) < 0)) {
6325 WL_ERROR(("%s auto channel failed, pick up channel=%d\n", \
6326 __FUNCTION__, ap->channel));
6329 channel = ap->channel;
6330 if ((res = dev_wlc_ioctl(dev, WLC_SET_CHANNEL, &channel, sizeof(channel)))) {
6331 WL_ERROR(("%s fail to set channel\n", __FUNCTION__));
6335 if (ap_cfg_running == FALSE) {
6337 if ((res = dev_wlc_ioctl(dev, WLC_UP, &updown, sizeof(updown)))) {
6338 WL_ERROR(("%s fail to set up\n", __FUNCTION__));
6343 max_assoc = ap->max_scb;
6344 if ((res = dev_wlc_intvar_set(dev, "maxassoc", max_assoc))) {
6345 WL_ERROR(("%s fail to set maxassoc\n", __FUNCTION__));
6349 ap_ssid.SSID_len = strlen(ap->ssid);
6350 strncpy(ap_ssid.SSID, ap->ssid, ap_ssid.SSID_len);
6353 if ((res = wl_iw_set_ap_security(dev, &my_ap)) != 0) {
6354 WL_ERROR(("ERROR:%d in:%s, wl_iw_set_ap_security is skipped\n", \
6355 res, __FUNCTION__));
6358 wl_iw_send_priv_event(dev, "ASCII_CMD=AP_BSS_START");
6359 ap_cfg_running = TRUE;
6361 iolen = wl_bssiovar_mkbuf("ssid", bsscfg_index, (char *)(&ap_ssid),
6362 ap_ssid.SSID_len+4, buf, sizeof(buf), &mkvar_err);
6364 if ((res = dev_wlc_ioctl(dev, WLC_SET_VAR, buf, iolen)) != 0) {
6365 WL_ERROR(("ERROR:%d in:%s, Security & BSS reconfiguration is skipped\n", \
6366 res, __FUNCTION__));
6369 if (ap_cfg_running == FALSE) {
6370 init_completion(&ap_cfg_exited);
6371 ap_cfg_pid = kernel_thread(thr_wait_for_2nd_eth_dev, dev, 0);
6374 if (ap_net_dev == NULL) {
6375 WL_ERROR(("%s ERROR: ap_net_dev is NULL !!!\n", __FUNCTION__));
6379 WL_ERROR(("%s: %s Configure security & restart AP bss \n", \
6380 __FUNCTION__, ap_net_dev->name));
6382 if ((res = wl_iw_set_ap_security(ap_net_dev, &my_ap)) < 0) {
6383 WL_ERROR(("%s fail to set security : %d\n", __FUNCTION__, res));
6387 if ((res = dev_iw_write_cfg1_bss_var(dev, 1)) < 0) {
6388 WL_ERROR(("%s fail to set bss up\n", __FUNCTION__));
6394 WL_SOFTAP(("%s exit with %d\n", __FUNCTION__, res));
6396 net_os_wake_unlock(dev);
6402 static int wl_iw_set_ap_security(struct net_device *dev, struct ap_profile *ap)
6415 WL_SOFTAP(("\nsetting SOFTAP security mode:\n"));
6416 WL_SOFTAP(("wl_iw: set ap profile:\n"));
6417 WL_SOFTAP((" ssid = '%s'\n", ap->ssid));
6418 WL_SOFTAP((" security = '%s'\n", ap->sec));
6419 if (ap->key[0] != '\0') {
6420 WL_SOFTAP((" key = '%s'\n", ap->key));
6422 WL_SOFTAP((" channel = %d\n", ap->channel));
6423 WL_SOFTAP((" max scb = %d\n", ap->max_scb));
6425 if (strnicmp(ap->sec, "open", strlen("open")) == 0) {
6427 res = dev_wlc_intvar_set(dev, "wsec", wsec);
6428 wpa_auth = WPA_AUTH_DISABLED;
6429 res |= dev_wlc_intvar_set(dev, "wpa_auth", wpa_auth);
6431 WL_SOFTAP(("=====================\n"));
6432 WL_SOFTAP((" wsec & wpa_auth set 'OPEN', result:&d %d\n", res));
6433 WL_SOFTAP(("=====================\n"));
6435 } else if (strnicmp(ap->sec, "wep", strlen("wep")) == 0) {
6437 memset(&key, 0, sizeof(key));
6440 res = dev_wlc_intvar_set(dev, "wsec", wsec);
6443 if (wl_iw_parse_wep(ap->key, &key)) {
6444 WL_SOFTAP(("wep key parse err!\n"));
6448 key.index = htod32(key.index);
6449 key.len = htod32(key.len);
6450 key.algo = htod32(key.algo);
6451 key.flags = htod32(key.flags);
6453 res |= dev_wlc_ioctl(dev, WLC_SET_KEY, &key, sizeof(key));
6455 wpa_auth = WPA_AUTH_DISABLED;
6456 res |= dev_wlc_intvar_set(dev, "wpa_auth", wpa_auth);
6458 WL_SOFTAP(("=====================\n"));
6459 WL_SOFTAP((" wsec & auth set 'WEP', result:&d %d\n", res));
6460 WL_SOFTAP(("=====================\n"));
6462 } else if (strnicmp(ap->sec, "wpa2-psk", strlen("wpa2-psk")) == 0) {
6467 dev_wlc_intvar_set(dev, "wsec", wsec);
6469 key_len = strlen(ap->key);
6470 if (key_len < WSEC_MIN_PSK_LEN || key_len > WSEC_MAX_PSK_LEN) {
6471 WL_SOFTAP(("passphrase must be between %d and %d characters long\n",
6472 WSEC_MIN_PSK_LEN, WSEC_MAX_PSK_LEN));
6476 if (key_len < WSEC_MAX_PSK_LEN) {
6477 unsigned char output[2*SHA1HashSize];
6478 char key_str_buf[WSEC_MAX_PSK_LEN+1];
6480 memset(output, 0, sizeof(output));
6481 pbkdf2_sha1(ap->key, ap->ssid, strlen(ap->ssid), 4096, output, 32);
6484 for (i = 0; i < (WSEC_MAX_PSK_LEN/8); i++) {
6485 sprintf(ptr, "%02x%02x%02x%02x", (uint)output[i*4], \
6486 (uint)output[i*4+1], (uint)output[i*4+2], \
6487 (uint)output[i*4+3]);
6490 WL_SOFTAP(("%s: passphase = %s\n", __FUNCTION__, key_str_buf));
6492 psk.key_len = htod16((ushort)WSEC_MAX_PSK_LEN);
6493 memcpy(psk.key, key_str_buf, psk.key_len);
6495 psk.key_len = htod16((ushort) key_len);
6496 memcpy(psk.key, ap->key, key_len);
6498 psk.flags = htod16(WSEC_PASSPHRASE);
6499 dev_wlc_ioctl(dev, WLC_SET_WSEC_PMK, &psk, sizeof(psk));
6501 wpa_auth = WPA2_AUTH_PSK;
6502 dev_wlc_intvar_set(dev, "wpa_auth", wpa_auth);
6504 } else if (strnicmp(ap->sec, "wpa-psk", strlen("wpa-psk")) == 0) {
6509 wsec = TKIP_ENABLED;
6510 res = dev_wlc_intvar_set(dev, "wsec", wsec);
6512 key_len = strlen(ap->key);
6513 if (key_len < WSEC_MIN_PSK_LEN || key_len > WSEC_MAX_PSK_LEN) {
6514 WL_SOFTAP(("passphrase must be between %d and %d characters long\n",
6515 WSEC_MIN_PSK_LEN, WSEC_MAX_PSK_LEN));
6519 if (key_len < WSEC_MAX_PSK_LEN) {
6520 unsigned char output[2*SHA1HashSize];
6521 char key_str_buf[WSEC_MAX_PSK_LEN+1];
6522 bzero(output, 2*SHA1HashSize);
6524 WL_SOFTAP(("%s: do passhash...\n", __FUNCTION__));
6526 pbkdf2_sha1(ap->key, ap->ssid, strlen(ap->ssid), 4096, output, 32);
6529 for (i = 0; i < (WSEC_MAX_PSK_LEN/8); i++) {
6530 WL_SOFTAP(("[%02d]: %08x\n", i, *((unsigned int *)&output[i*4])));
6532 sprintf(ptr, "%02x%02x%02x%02x", (uint)output[i*4],
6533 (uint)output[i*4+1], (uint)output[i*4+2],
6534 (uint)output[i*4+3]);
6537 WL_SOFTAP(("%s: passphase = %s\n", __FUNCTION__, key_str_buf));
6539 psk.key_len = htod16((ushort)WSEC_MAX_PSK_LEN);
6540 memcpy(psk.key, key_str_buf, psk.key_len);
6542 psk.key_len = htod16((ushort) key_len);
6543 memcpy(psk.key, ap->key, key_len);
6546 psk.flags = htod16(WSEC_PASSPHRASE);
6547 res |= dev_wlc_ioctl(dev, WLC_SET_WSEC_PMK, &psk, sizeof(psk));
6549 wpa_auth = WPA_AUTH_PSK;
6550 res |= dev_wlc_intvar_set(dev, "wpa_auth", wpa_auth);
6552 WL_SOFTAP((" wsec & auth set 'wpa-psk' (TKIP), result:&d %d\n", res));
6556 ap_ssid.SSID_len = strlen(ap->ssid);
6557 strncpy(ap_ssid.SSID, ap->ssid, ap_ssid.SSID_len);
6558 res |= dev_wlc_ioctl(dev, WLC_SET_SSID, &ap_ssid, sizeof(ap_ssid));
6560 res |= dev_wlc_intvar_set(dev, "mpc", mpc);
6561 if (strnicmp(ap->sec, "wep", strlen("wep")) == 0) {
6562 res |= dev_wlc_ioctl(dev, WLC_SET_KEY, &key, sizeof(key));
6570 int get_parmeter_from_string(
6571 char **str_ptr, const char *token,
6572 int param_type, void *dst, int param_max_len)
6574 char int_str[7] = "0";
6576 char *param_str_begin;
6577 char *param_str_end;
6579 if ((*str_ptr) && !strncmp(*str_ptr, token, strlen(token))) {
6581 strsep(str_ptr, "=,");
6582 param_str_begin = *str_ptr;
6583 strsep(str_ptr, "=,");
6585 if (*str_ptr == NULL) {
6586 parm_str_len = strlen(param_str_begin);
6588 param_str_end = *str_ptr-1;
6589 parm_str_len = param_str_end - param_str_begin;
6592 WL_TRACE((" 'token:%s', len:%d, ", token, parm_str_len));
6594 if (parm_str_len > param_max_len) {
6595 WL_TRACE((" WARNING: extracted param len:%d is > MAX:%d\n",
6596 parm_str_len, param_max_len));
6598 parm_str_len = param_max_len;
6601 switch (param_type) {
6603 case PTYPE_INTDEC: {
6604 int *pdst_int = dst;
6607 if (parm_str_len > sizeof(int_str))
6608 parm_str_len = sizeof(int_str);
6610 memcpy(int_str, param_str_begin, parm_str_len);
6612 *pdst_int = simple_strtoul(int_str, &eptr, 10);
6614 WL_TRACE((" written as integer:%d\n", *pdst_int));
6617 case PTYPE_STR_HEX: {
6620 param_max_len = param_max_len >> 1;
6621 hstr_2_buf(param_str_begin, buf, param_max_len);
6622 print_buf(buf, param_max_len, 0);
6626 memcpy(dst, param_str_begin, parm_str_len);
6627 *((char *)dst + parm_str_len) = 0;
6628 WL_TRACE((" written as a string:%s\n", (char *)dst));
6634 WL_ERROR(("\n %s: No token:%s in str:%s\n",
6635 __FUNCTION__, token, *str_ptr));
6641 static int wl_iw_softap_deassoc_stations(struct net_device *dev, u8 *mac)
6645 char mac_buf[128] = {0};
6646 char z_mac[6] = {0, 0, 0, 0, 0, 0};
6648 struct maclist *assoc_maclist = (struct maclist *) mac_buf;
6649 bool deauth_all = false;
6658 memset(assoc_maclist, 0, sizeof(mac_buf));
6659 assoc_maclist->count = 8;
6661 res = dev_wlc_ioctl(dev, WLC_GET_ASSOCLIST, assoc_maclist, 128);
6663 WL_SOFTAP(("%s: Error:%d Couldn't get ASSOC List\n", __FUNCTION__, res));
6667 if (assoc_maclist->count) {
6668 for (i = 0; i < assoc_maclist->count; i++) {
6671 scbval.val = htod32(1);
6672 bcopy(&assoc_maclist->ea[i], &scbval.ea, ETHER_ADDR_LEN);
6674 if (deauth_all || (memcmp(&scbval.ea, sta_mac, ETHER_ADDR_LEN) == 0)) {
6675 WL_SOFTAP(("%s, deauth STA:%d \n", __FUNCTION__, i));
6676 res |= dev_wlc_ioctl(dev, WLC_SCB_DEAUTHENTICATE_FOR_REASON,
6677 &scbval, sizeof(scb_val_t));
6681 WL_SOFTAP((" STA ASSOC list is empty\n"));
6685 WL_ERROR(("%s: Error:%d\n", __FUNCTION__, res));
6686 } else if (assoc_maclist->count) {
6693 static int iwpriv_softap_stop(struct net_device *dev,
6694 struct iw_request_info *info,
6695 union iwreq_data *wrqu,
6700 WL_SOFTAP(("got iwpriv AP_BSS_STOP\n"));
6702 if ((!dev) && (!ap_net_dev)) {
6703 WL_ERROR(("%s: dev is null\n", __FUNCTION__));
6707 net_os_wake_lock(dev);
6709 if ((ap_cfg_running == TRUE)) {
6711 wl_iw_softap_deassoc_stations(dev, NULL);
6713 wl_iw_softap_deassoc_stations(ap_net_dev, NULL);
6715 if ((res = dev_iw_write_cfg1_bss_var(dev, 2)) < 0)
6716 WL_ERROR(("%s failed to del BSS err = %d", __FUNCTION__, res));
6721 wrqu->data.length = 0;
6722 ap_cfg_running = FALSE;
6725 WL_ERROR(("%s: was called when SoftAP is OFF : move on\n", __FUNCTION__));
6727 WL_SOFTAP(("%s Done with %d\n", __FUNCTION__, res));
6729 net_os_wake_unlock(dev);
6735 static int iwpriv_fw_reload(struct net_device *dev,
6736 struct iw_request_info *info,
6737 union iwreq_data *wrqu,
6742 char *fwstr = fw_path;
6744 WL_SOFTAP(("current firmware_path[]=%s\n", fwstr));
6746 WL_TRACE((">Got FW_RELOAD cmd:"
6747 "info->cmd:%x, info->flags:%x, u.data:%p, u.len:%d, \
6748 fw_path:%p, len:%d \n",
6749 info->cmd, info->flags,
6750 wrqu->data.pointer, wrqu->data.length, fwstr, strlen(fwstr)));
6752 if ((wrqu->data.length > 4) && (wrqu->data.length < sizeof(extra))) {
6756 if (copy_from_user(extra, wrqu->data.pointer, wrqu->data.length)) {
6761 extra[wrqu->data.length] = 8;
6764 if (get_parmeter_from_string(&str_ptr, "FW_PATH=", PTYPE_STRING, fwstr, 255) != 0) {
6765 WL_ERROR(("Error: extracting FW_PATH='' string\n"));
6769 if (strstr(fwstr, "apsta") != NULL) {
6770 WL_SOFTAP(("GOT APSTA FIRMWARE\n"));
6771 ap_fw_loaded = TRUE;
6773 WL_SOFTAP(("GOT STA FIRMWARE\n"));
6774 ap_fw_loaded = FALSE;
6777 WL_SOFTAP(("SET firmware_path[]=%s , str_p:%p\n", fwstr, fwstr));
6780 WL_ERROR(("Error: ivalid param len:%d\n", wrqu->data.length));
6789 static int iwpriv_wpasupp_loop_tst(struct net_device *dev,
6790 struct iw_request_info *info,
6791 union iwreq_data *wrqu,
6795 char *params = NULL;
6797 WL_TRACE((">Got IWPRIV wp_supp loopback cmd test:"
6798 "info->cmd:%x, info->flags:%x, u.data:%p, u.len:%d\n",
6799 info->cmd, info->flags,
6800 wrqu->data.pointer, wrqu->data.length));
6802 if (wrqu->data.length != 0) {
6804 if (!(params = kmalloc(wrqu->data.length+1, GFP_KERNEL)))
6807 if (copy_from_user(params, wrqu->data.pointer, wrqu->data.length)) {
6812 params[wrqu->data.length] = 0;
6813 WL_SOFTAP(("\n>> copied from user:\n %s\n", params));
6815 WL_ERROR(("ERROR param length is 0\n"));
6819 res = wl_iw_send_priv_event(dev, params);
6829 struct net_device *dev,
6830 struct iw_request_info *info,
6837 WL_ERROR(("%s: dev is null\n", __FUNCTION__));
6841 net_os_wake_lock(dev);
6843 WL_SOFTAP(("%s: rcvd IWPRIV IOCTL: for dev:%s\n", __FUNCTION__, dev->name));
6846 if (ap_cfg_pid >= 0) {
6847 wait_for_completion(&ap_cfg_exited);
6851 if ((res = wl_iw_set_ap_security(dev, &my_ap)) != 0) {
6852 WL_ERROR((" %s ERROR setting SOFTAP security in :%d\n", __FUNCTION__, res));
6855 if ((res = dev_iw_write_cfg1_bss_var(dev, 1)) < 0)
6856 WL_ERROR(("%s fail to set bss up err=%d\n", __FUNCTION__, res));
6862 WL_SOFTAP(("%s done with res %d \n", __FUNCTION__, res));
6864 net_os_wake_unlock(dev);
6870 get_assoc_sta_list(struct net_device *dev, char *buf, int len)
6872 WL_TRACE(("%s: dev_wlc_ioctl(dev:%p, cmd:%d, buf:%p, len:%d)\n",
6873 __FUNCTION__, dev, WLC_GET_ASSOCLIST, buf, len));
6875 return dev_wlc_ioctl(dev, WLC_GET_ASSOCLIST, buf, len);
6880 void check_error(int res, const char *msg, const char *func, int line)
6883 WL_ERROR(("%s, %d function:%s, line:%d\n", msg, res, func, line));
6887 set_ap_mac_list(struct net_device *dev, void *buf)
6889 struct mac_list_set *mac_list_set = (struct mac_list_set *)buf;
6890 struct maclist *maclist = (struct maclist *)&mac_list_set->mac_list;
6893 int mac_mode = mac_list_set->mode;
6895 ap_macmode = mac_list_set->mode;
6897 bzero(&ap_black_list, sizeof(struct mflist));
6899 if (mac_mode == MACLIST_MODE_DISABLED) {
6901 ioc_res = dev_wlc_ioctl(dev, WLC_SET_MACMODE, &mac_mode, sizeof(mac_mode));
6902 check_error(ioc_res, "ioctl ERROR:", __FUNCTION__, __LINE__);
6903 WL_SOFTAP(("%s: MAC filtering disabled\n", __FUNCTION__));
6907 char mac_buf[256] = {0};
6908 struct maclist *assoc_maclist = (struct maclist *) mac_buf;
6910 bcopy(maclist, &ap_black_list, sizeof(ap_black_list));
6912 ioc_res = dev_wlc_ioctl(dev, WLC_SET_MACMODE, &mac_mode, sizeof(mac_mode));
6913 check_error(ioc_res, "ioctl ERROR:", __FUNCTION__, __LINE__);
6915 length = sizeof(maclist->count) + maclist->count*ETHER_ADDR_LEN;
6916 dev_wlc_ioctl(dev, WLC_SET_MACLIST, maclist, length);
6918 WL_SOFTAP(("%s: applied MAC List, mode:%d, length %d:\n",
6919 __FUNCTION__, mac_mode, length));
6920 for (i = 0; i < maclist->count; i++)
6921 WL_SOFTAP(("mac %d: %02X:%02X:%02X:%02X:%02X:%02X\n",
6922 i, maclist->ea[i].octet[0], maclist->ea[i].octet[1], \
6923 maclist->ea[i].octet[2], \
6924 maclist->ea[i].octet[3], maclist->ea[i].octet[4], \
6925 maclist->ea[i].octet[5]));
6927 assoc_maclist->count = 8;
6928 ioc_res = dev_wlc_ioctl(dev, WLC_GET_ASSOCLIST, assoc_maclist, 256);
6929 check_error(ioc_res, "ioctl ERROR:", __FUNCTION__, __LINE__);
6930 WL_SOFTAP((" Cur assoc clients:%d\n", assoc_maclist->count));
6932 if (assoc_maclist->count)
6933 for (i = 0; i < assoc_maclist->count; i++) {
6935 bool assoc_mac_matched = false;
6937 WL_SOFTAP(("\n Cheking assoc STA: "));
6938 print_buf(&assoc_maclist->ea[i], 6, 7);
6939 WL_SOFTAP(("with the b/w list:"));
6941 for (j = 0; j < maclist->count; j++)
6942 if (!bcmp(&assoc_maclist->ea[i], &maclist->ea[j],
6945 assoc_mac_matched = true;
6949 if (((mac_mode == MACLIST_MODE_ALLOW) && !assoc_mac_matched) ||
6950 ((mac_mode == MACLIST_MODE_DENY) && assoc_mac_matched)) {
6952 WL_SOFTAP(("b-match or w-mismatch,"
6953 " do deauth/disassoc \n"));
6954 scbval.val = htod32(1);
6955 bcopy(&assoc_maclist->ea[i], &scbval.ea, \
6957 ioc_res = dev_wlc_ioctl(dev,
6958 WLC_SCB_DEAUTHENTICATE_FOR_REASON,
6959 &scbval, sizeof(scb_val_t));
6960 check_error(ioc_res,
6962 __FUNCTION__, __LINE__);
6965 WL_SOFTAP((" no b/w list hits, let it be\n"));
6968 WL_SOFTAP(("No ASSOC CLIENTS\n"));
6972 WL_SOFTAP(("%s iocres:%d\n", __FUNCTION__, ioc_res));
6979 int set_macfilt_from_string(struct mflist *pmflist, char **param_str)
6987 #define PARAM_OFFSET PROFILE_OFFSET
6989 int wl_iw_process_private_ascii_cmd(
6990 struct net_device *dev,
6991 struct iw_request_info *info,
6992 union iwreq_data *dwrq,
6996 char *sub_cmd = cmd_str + PROFILE_OFFSET + strlen("ASCII_CMD=");
6998 WL_SOFTAP(("\n %s: ASCII_CMD: offs_0:%s, offset_32:\n'%s'\n",
6999 __FUNCTION__, cmd_str, cmd_str + PROFILE_OFFSET));
7001 if (strnicmp(sub_cmd, "AP_CFG", strlen("AP_CFG")) == 0) {
7003 WL_SOFTAP((" AP_CFG \n"));
7006 if (init_ap_profile_from_string(cmd_str+PROFILE_OFFSET, &my_ap) != 0) {
7007 WL_ERROR(("ERROR: SoftAP CFG prams !\n"));
7010 ret = set_ap_cfg(dev, &my_ap);
7013 } else if (strnicmp(sub_cmd, "AP_BSS_START", strlen("AP_BSS_START")) == 0) {
7015 WL_SOFTAP(("\n SOFTAP - ENABLE BSS \n"));
7017 WL_SOFTAP(("\n!!! got 'WL_AP_EN_BSS' from WPA supplicant, dev:%s\n", dev->name));
7020 if (ap_net_dev == NULL) {
7021 printf("\n ERROR: SOFTAP net_dev* is NULL !!!\n");
7023 if ((ret = iwpriv_en_ap_bss(ap_net_dev, info, dwrq, cmd_str)) < 0)
7024 WL_ERROR(("%s line %d fail to set bss up\n", \
7025 __FUNCTION__, __LINE__));
7028 if ((ret = iwpriv_en_ap_bss(dev, info, dwrq, cmd_str)) < 0)
7029 WL_ERROR(("%s line %d fail to set bss up\n", \
7030 __FUNCTION__, __LINE__));
7032 } else if (strnicmp(sub_cmd, "ASSOC_LST", strlen("ASSOC_LST")) == 0) {
7034 } else if (strnicmp(sub_cmd, "AP_BSS_STOP", strlen("AP_BSS_STOP")) == 0) {
7035 WL_SOFTAP((" \n temp DOWN SOFTAP\n"));
7037 if ((ret = dev_iw_write_cfg1_bss_var(dev, 0)) < 0) {
7038 WL_ERROR(("%s line %d fail to set bss down\n", \
7039 __FUNCTION__, __LINE__));
7048 static int wl_iw_set_priv(
7049 struct net_device *dev,
7050 struct iw_request_info *info,
7051 struct iw_point *dwrq,
7058 if (!(extra = kmalloc(dwrq->length, GFP_KERNEL)))
7061 if (copy_from_user(extra, dwrq->pointer, dwrq->length)) {
7066 WL_TRACE(("%s: SIOCSIWPRIV request %s, info->cmd:%x, info->flags:%d\n dwrq->length:%d",
7067 dev->name, extra, info->cmd, info->flags, dwrq->length));
7069 net_os_wake_lock(dev);
7071 if (dwrq->length && extra) {
7072 if (strnicmp(extra, "START", strlen("START")) == 0) {
7073 wl_iw_control_wl_on(dev, info);
7074 WL_TRACE(("%s, Received regular START command\n", __FUNCTION__));
7077 if (g_onoff == G_WLAN_SET_OFF) {
7078 WL_TRACE(("%s, missing START, Fail\n", __FUNCTION__));
7080 net_os_wake_unlock(dev);
7084 if (strnicmp(extra, "SCAN-ACTIVE", strlen("SCAN-ACTIVE")) == 0) {
7085 #ifdef ENABLE_ACTIVE_PASSIVE_SCAN_SUPPRESS
7086 WL_TRACE(("%s: active scan setting suppressed\n", dev->name));
7088 ret = wl_iw_set_active_scan(dev, info, (union iwreq_data *)dwrq, extra);
7090 } else if (strnicmp(extra, "SCAN-PASSIVE", strlen("SCAN-PASSIVE")) == 0)
7091 #ifdef ENABLE_ACTIVE_PASSIVE_SCAN_SUPPRESS
7092 WL_TRACE(("%s: passive scan setting suppressed\n", dev->name));
7094 ret = wl_iw_set_passive_scan(dev, info, (union iwreq_data *)dwrq, extra);
7096 else if (strnicmp(extra, "RSSI", strlen("RSSI")) == 0)
7097 ret = wl_iw_get_rssi(dev, info, (union iwreq_data *)dwrq, extra);
7098 else if (strnicmp(extra, "LINKSPEED", strlen("LINKSPEED")) == 0)
7099 ret = wl_iw_get_link_speed(dev, info, (union iwreq_data *)dwrq, extra);
7100 else if (strnicmp(extra, "MACADDR", strlen("MACADDR")) == 0)
7101 ret = wl_iw_get_macaddr(dev, info, (union iwreq_data *)dwrq, extra);
7102 else if (strnicmp(extra, "COUNTRY", strlen("COUNTRY")) == 0)
7103 ret = wl_iw_set_country(dev, info, (union iwreq_data *)dwrq, extra);
7104 else if (strnicmp(extra, "STOP", strlen("STOP")) == 0)
7105 ret = wl_iw_control_wl_off(dev, info);
7106 else if (strnicmp(extra, BAND_GET_CMD, strlen(BAND_GET_CMD)) == 0)
7107 ret = wl_iw_get_band(dev, info, (union iwreq_data *)dwrq, extra);
7108 else if (strnicmp(extra, BAND_SET_CMD, strlen(BAND_SET_CMD)) == 0)
7109 ret = wl_iw_set_band(dev, info, (union iwreq_data *)dwrq, extra);
7110 else if (strnicmp(extra, DTIM_SKIP_GET_CMD, strlen(DTIM_SKIP_GET_CMD)) == 0)
7111 ret = wl_iw_get_dtim_skip(dev, info, (union iwreq_data *)dwrq, extra);
7112 else if (strnicmp(extra, DTIM_SKIP_SET_CMD, strlen(DTIM_SKIP_SET_CMD)) == 0)
7113 ret = wl_iw_set_dtim_skip(dev, info, (union iwreq_data *)dwrq, extra);
7114 else if (strnicmp(extra, SETSUSPEND_CMD, strlen(SETSUSPEND_CMD)) == 0)
7115 ret = wl_iw_set_suspend(dev, info, (union iwreq_data *)dwrq, extra);
7116 #ifdef CONFIG_US_NON_DFS_CHANNELS_ONLY
7117 else if (strnicmp(extra, SETDFSCHANNELS_CMD, strlen(SETDFSCHANNELS_CMD)) == 0)
7118 ret = wl_iw_set_dfs_channels(dev, info, (union iwreq_data *)dwrq, extra);
7120 #if defined(PNO_SUPPORT)
7121 else if (strnicmp(extra, PNOSSIDCLR_SET_CMD, strlen(PNOSSIDCLR_SET_CMD)) == 0)
7122 ret = wl_iw_set_pno_reset(dev, info, (union iwreq_data *)dwrq, extra);
7123 else if (strnicmp(extra, PNOSETUP_SET_CMD, strlen(PNOSETUP_SET_CMD)) == 0)
7124 ret = wl_iw_set_pno_set(dev, info, (union iwreq_data *)dwrq, extra);
7125 else if (strnicmp(extra, PNOENABLE_SET_CMD, strlen(PNOENABLE_SET_CMD)) == 0)
7126 ret = wl_iw_set_pno_enable(dev, info, (union iwreq_data *)dwrq, extra);
7129 else if (strnicmp(extra, CSCAN_COMMAND, strlen(CSCAN_COMMAND)) == 0)
7130 ret = wl_iw_set_cscan(dev, info, (union iwreq_data *)dwrq, extra);
7133 else if (strnicmp(extra, "POWERMODE", strlen("POWERMODE")) == 0)
7134 ret = wl_iw_set_power_mode(dev, info, (union iwreq_data *)dwrq, extra);
7135 else if (strnicmp(extra, "BTCOEXMODE", strlen("BTCOEXMODE")) == 0)
7136 ret = wl_iw_set_btcoex_dhcp(dev, info, (union iwreq_data *)dwrq, extra);
7138 else if (strnicmp(extra, "POWERMODE", strlen("POWERMODE")) == 0)
7139 ret = wl_iw_set_btcoex_dhcp(dev, info, (union iwreq_data *)dwrq, extra);
7141 else if (strnicmp(extra, "GETPOWER", strlen("GETPOWER")) == 0)
7142 ret = wl_iw_get_power_mode(dev, info, (union iwreq_data *)dwrq, extra);
7144 else if (strnicmp(extra, "ASCII_CMD", strlen("ASCII_CMD")) == 0) {
7145 wl_iw_process_private_ascii_cmd(dev, info, (union iwreq_data *)dwrq, extra);
7146 } else if (strnicmp(extra, "AP_MAC_LIST_SET", strlen("AP_MAC_LIST_SET")) == 0) {
7147 WL_SOFTAP(("penguin, set AP_MAC_LIST_SET\n"));
7148 set_ap_mac_list(dev, (extra + PROFILE_OFFSET));
7152 WL_TRACE(("Unknown PRIVATE command: %s: ignored\n", extra));
7153 snprintf(extra, MAX_WX_STRING, "OK");
7154 dwrq->length = strlen("OK") + 1;
7158 net_os_wake_unlock(dev);
7161 if (copy_to_user(dwrq->pointer, extra, dwrq->length)) {
7172 static const iw_handler wl_iw_handler[] =
7174 (iw_handler) wl_iw_config_commit,
7175 (iw_handler) wl_iw_get_name,
7178 (iw_handler) wl_iw_set_freq,
7179 (iw_handler) wl_iw_get_freq,
7180 (iw_handler) wl_iw_set_mode,
7181 (iw_handler) wl_iw_get_mode,
7185 (iw_handler) wl_iw_get_range,
7186 (iw_handler) wl_iw_set_priv,
7190 (iw_handler) wl_iw_set_spy,
7191 (iw_handler) wl_iw_get_spy,
7194 (iw_handler) wl_iw_set_wap,
7195 (iw_handler) wl_iw_get_wap,
7196 #if WIRELESS_EXT > 17
7197 (iw_handler) wl_iw_mlme,
7201 #if defined(WL_IW_USE_ISCAN)
7202 (iw_handler) wl_iw_iscan_get_aplist,
7204 (iw_handler) wl_iw_get_aplist,
7206 #if WIRELESS_EXT > 13
7207 #if defined(WL_IW_USE_ISCAN)
7208 (iw_handler) wl_iw_iscan_set_scan,
7209 (iw_handler) wl_iw_iscan_get_scan,
7211 (iw_handler) wl_iw_set_scan,
7212 (iw_handler) wl_iw_get_scan,
7218 (iw_handler) wl_iw_set_essid,
7219 (iw_handler) wl_iw_get_essid,
7220 (iw_handler) wl_iw_set_nick,
7221 (iw_handler) wl_iw_get_nick,
7224 (iw_handler) wl_iw_set_rate,
7225 (iw_handler) wl_iw_get_rate,
7226 (iw_handler) wl_iw_set_rts,
7227 (iw_handler) wl_iw_get_rts,
7228 (iw_handler) wl_iw_set_frag,
7229 (iw_handler) wl_iw_get_frag,
7230 (iw_handler) wl_iw_set_txpow,
7231 (iw_handler) wl_iw_get_txpow,
7232 #if WIRELESS_EXT > 10
7233 (iw_handler) wl_iw_set_retry,
7234 (iw_handler) wl_iw_get_retry,
7236 (iw_handler) wl_iw_set_encode,
7237 (iw_handler) wl_iw_get_encode,
7238 (iw_handler) wl_iw_set_power,
7239 (iw_handler) wl_iw_get_power,
7240 #if WIRELESS_EXT > 17
7243 (iw_handler) wl_iw_set_wpaie,
7244 (iw_handler) wl_iw_get_wpaie,
7245 (iw_handler) wl_iw_set_wpaauth,
7246 (iw_handler) wl_iw_get_wpaauth,
7247 (iw_handler) wl_iw_set_encodeext,
7248 (iw_handler) wl_iw_get_encodeext,
7250 (iw_handler) wl_iw_set_pmksa,
7255 #if WIRELESS_EXT > 12
7256 static const iw_handler wl_iw_priv_handler[] = {
7258 (iw_handler)wl_iw_set_active_scan,
7260 (iw_handler)wl_iw_get_rssi,
7262 (iw_handler)wl_iw_set_passive_scan,
7264 (iw_handler)wl_iw_get_link_speed,
7266 (iw_handler)wl_iw_get_macaddr,
7268 (iw_handler)wl_iw_control_wl_off,
7270 (iw_handler)wl_iw_control_wl_on,
7273 (iw_handler)iwpriv_set_ap_config,
7276 (iw_handler)iwpriv_get_assoc_list,
7279 (iw_handler)iwpriv_set_mac_filters,
7282 (iw_handler)iwpriv_en_ap_bss,
7285 (iw_handler)iwpriv_wpasupp_loop_tst,
7288 (iw_handler)iwpriv_softap_stop,
7291 (iw_handler)iwpriv_fw_reload,
7294 (iw_handler)iwpriv_set_ap_sta_disassoc,
7299 (iw_handler)iwpriv_set_cscan
7303 static const struct iw_priv_args wl_iw_priv_args[] = {
7305 WL_IW_SET_ACTIVE_SCAN,
7307 IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | MAX_WX_STRING,
7313 IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | MAX_WX_STRING,
7317 WL_IW_SET_PASSIVE_SCAN,
7319 IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | MAX_WX_STRING,
7323 WL_IW_GET_LINK_SPEED,
7325 IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | MAX_WX_STRING,
7329 WL_IW_GET_CURR_MACADDR,
7331 IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | MAX_WX_STRING,
7337 IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | MAX_WX_STRING,
7343 IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | MAX_WX_STRING,
7350 IW_PRIV_TYPE_CHAR | 256,
7357 IW_PRIV_TYPE_CHAR | 0,
7358 IW_PRIV_TYPE_CHAR | 1024,
7364 IW_PRIV_TYPE_CHAR | 256,
7365 IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | 0,
7372 IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | MAX_WX_STRING,
7378 IW_PRIV_TYPE_CHAR | 256,
7379 IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | 0,
7385 IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | 0,
7386 IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | 0,
7392 IW_PRIV_TYPE_CHAR | 256,
7393 IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | 0,
7399 IW_PRIV_TYPE_CHAR | 256,
7400 IW_PRIV_TYPE_CHAR | 0,
7407 IW_PRIV_TYPE_CHAR | 1024,
7414 const struct iw_handler_def wl_iw_handler_def =
7416 .num_standard = ARRAYSIZE(wl_iw_handler),
7417 .standard = (iw_handler *) wl_iw_handler,
7418 .num_private = ARRAYSIZE(wl_iw_priv_handler),
7419 .num_private_args = ARRAY_SIZE(wl_iw_priv_args),
7420 .private = (iw_handler *)wl_iw_priv_handler,
7421 .private_args = (void *) wl_iw_priv_args,
7423 #if WIRELESS_EXT >= 19
7424 get_wireless_stats: dhd_get_wireless_stats,
7431 struct net_device *dev,
7436 struct iwreq *wrq = (struct iwreq *) rq;
7437 struct iw_request_info info;
7440 int token_size = 1, max_tokens = 0, ret = 0;
7442 net_os_wake_lock(dev);
7444 WL_TRACE(("%s: cmd:%x alled via dhd->do_ioctl()entry point\n", __FUNCTION__, cmd));
7445 if (cmd < SIOCIWFIRST ||
7446 IW_IOCTL_IDX(cmd) >= ARRAYSIZE(wl_iw_handler) ||
7447 !(handler = wl_iw_handler[IW_IOCTL_IDX(cmd)])) {
7448 WL_ERROR(("%s: error in cmd=%x : not supported\n", __FUNCTION__, cmd));
7449 net_os_wake_unlock(dev);
7459 max_tokens = IW_ESSID_MAX_SIZE + 1;
7464 #if WIRELESS_EXT > 17
7465 case SIOCSIWENCODEEXT:
7466 case SIOCGIWENCODEEXT:
7468 max_tokens = wrq->u.data.length;
7472 max_tokens = sizeof(struct iw_range) + 500;
7476 token_size = sizeof(struct sockaddr) + sizeof(struct iw_quality);
7477 max_tokens = IW_MAX_AP;
7480 #if WIRELESS_EXT > 13
7482 #if defined(WL_IW_USE_ISCAN)
7484 max_tokens = wrq->u.data.length;
7487 max_tokens = IW_SCAN_MAX_DATA;
7492 token_size = sizeof(struct sockaddr);
7493 max_tokens = IW_MAX_SPY;
7497 token_size = sizeof(struct sockaddr) + sizeof(struct iw_quality);
7498 max_tokens = IW_MAX_SPY;
7501 #if WIRELESS_EXT > 17
7506 max_tokens = wrq->u.data.length;
7510 if (max_tokens && wrq->u.data.pointer) {
7511 if (wrq->u.data.length > max_tokens) {
7512 WL_ERROR(("%s: error in cmd=%x wrq->u.data.length=%d > max_tokens=%d\n", \
7513 __FUNCTION__, cmd, wrq->u.data.length, max_tokens));
7515 goto wl_iw_ioctl_done;
7517 if (!(extra = kmalloc(max_tokens * token_size, GFP_KERNEL))) {
7519 goto wl_iw_ioctl_done;
7522 if (copy_from_user(extra, wrq->u.data.pointer, wrq->u.data.length * token_size)) {
7525 goto wl_iw_ioctl_done;
7532 ret = handler(dev, &info, &wrq->u, extra);
7535 if (copy_to_user(wrq->u.data.pointer, extra, wrq->u.data.length * token_size)) {
7538 goto wl_iw_ioctl_done;
7546 net_os_wake_unlock(dev);
7553 wl_iw_conn_status_str(uint32 event_type, uint32 status, uint32 reason,
7554 char* stringBuf, uint buflen)
7556 typedef struct conn_fail_event_map_t {
7560 const char* outName;
7561 const char* outCause;
7562 } conn_fail_event_map_t;
7565 # define WL_IW_DONT_CARE 9999
7566 const conn_fail_event_map_t event_map [] = {
7569 {WLC_E_SET_SSID, WLC_E_STATUS_SUCCESS, WL_IW_DONT_CARE,
7571 {WLC_E_SET_SSID, WLC_E_STATUS_NO_NETWORKS, WL_IW_DONT_CARE,
7572 "Conn", "NoNetworks"},
7573 {WLC_E_SET_SSID, WLC_E_STATUS_FAIL, WL_IW_DONT_CARE,
7574 "Conn", "ConfigMismatch"},
7575 {WLC_E_PRUNE, WL_IW_DONT_CARE, WLC_E_PRUNE_ENCR_MISMATCH,
7576 "Conn", "EncrypMismatch"},
7577 {WLC_E_PRUNE, WL_IW_DONT_CARE, WLC_E_RSN_MISMATCH,
7578 "Conn", "RsnMismatch"},
7579 {WLC_E_AUTH, WLC_E_STATUS_TIMEOUT, WL_IW_DONT_CARE,
7580 "Conn", "AuthTimeout"},
7581 {WLC_E_AUTH, WLC_E_STATUS_FAIL, WL_IW_DONT_CARE,
7582 "Conn", "AuthFail"},
7583 {WLC_E_AUTH, WLC_E_STATUS_NO_ACK, WL_IW_DONT_CARE,
7584 "Conn", "AuthNoAck"},
7585 {WLC_E_REASSOC, WLC_E_STATUS_FAIL, WL_IW_DONT_CARE,
7586 "Conn", "ReassocFail"},
7587 {WLC_E_REASSOC, WLC_E_STATUS_TIMEOUT, WL_IW_DONT_CARE,
7588 "Conn", "ReassocTimeout"},
7589 {WLC_E_REASSOC, WLC_E_STATUS_ABORT, WL_IW_DONT_CARE,
7590 "Conn", "ReassocAbort"},
7591 {WLC_E_PSK_SUP, WLC_SUP_KEYED, WL_IW_DONT_CARE,
7592 "Sup", "ConnSuccess"},
7593 {WLC_E_PSK_SUP, WL_IW_DONT_CARE, WL_IW_DONT_CARE,
7594 "Sup", "WpaHandshakeFail"},
7595 {WLC_E_DEAUTH_IND, WL_IW_DONT_CARE, WL_IW_DONT_CARE,
7597 {WLC_E_DISASSOC_IND, WL_IW_DONT_CARE, WL_IW_DONT_CARE,
7598 "Conn", "DisassocInd"},
7599 {WLC_E_DISASSOC, WL_IW_DONT_CARE, WL_IW_DONT_CARE,
7603 const char* name = "";
7604 const char* cause = NULL;
7608 for (i = 0; i < sizeof(event_map)/sizeof(event_map[0]); i++) {
7609 const conn_fail_event_map_t* row = &event_map[i];
7610 if (row->inEvent == event_type &&
7611 (row->inStatus == status || row->inStatus == WL_IW_DONT_CARE) &&
7612 (row->inReason == reason || row->inReason == WL_IW_DONT_CARE)) {
7613 name = row->outName;
7614 cause = row->outCause;
7621 memset(stringBuf, 0, buflen);
7622 snprintf(stringBuf, buflen, "%s %s %02d %02d",
7623 name, cause, status, reason);
7624 WL_INFORM(("Connection status: %s\n", stringBuf));
7631 #if WIRELESS_EXT > 14
7634 wl_iw_check_conn_fail(wl_event_msg_t *e, char* stringBuf, uint buflen)
7636 uint32 event = ntoh32(e->event_type);
7637 uint32 status = ntoh32(e->status);
7638 uint32 reason = ntoh32(e->reason);
7640 if (wl_iw_conn_status_str(event, status, reason, stringBuf, buflen)) {
7648 #ifndef IW_CUSTOM_MAX
7649 #define IW_CUSTOM_MAX 256
7653 wl_iw_event(struct net_device *dev, wl_event_msg_t *e, void* data)
7655 #if WIRELESS_EXT > 13
7656 union iwreq_data wrqu;
7657 char extra[IW_CUSTOM_MAX + 1];
7659 uint32 event_type = ntoh32(e->event_type);
7660 uint16 flags = ntoh16(e->flags);
7661 uint32 datalen = ntoh32(e->datalen);
7662 uint32 status = ntoh32(e->status);
7664 static uint32 roam_no_success = 0;
7665 static bool roam_no_success_send = FALSE;
7667 memset(&wrqu, 0, sizeof(wrqu));
7668 memset(extra, 0, sizeof(extra));
7671 WL_ERROR(("%s: dev is null\n", __FUNCTION__));
7675 net_os_wake_lock(dev);
7677 WL_TRACE(("%s: dev=%s event=%d \n", __FUNCTION__, dev->name, event_type));
7679 switch (event_type) {
7682 WL_ERROR(("%s: Firmware ERROR %d\n", __FUNCTION__, status));
7683 net_os_send_hang_message(dev);
7684 goto wl_iw_event_end;
7688 if (ap_cfg_running) {
7689 char *macaddr = (char *)&e->addr;
7690 WL_SOFTAP(("PRUNE received, %02X:%02X:%02X:%02X:%02X:%02X!\n",
7691 macaddr[0], macaddr[1], macaddr[2], macaddr[3], \
7692 macaddr[4], macaddr[5]));
7696 for (i = 0; i < ap_black_list.count; i++) {
7697 if (!bcmp(macaddr, &ap_black_list.ea[i], \
7698 sizeof(struct ether_addr))) {
7699 WL_SOFTAP(("mac in black list, ignore it\n"));
7704 if (i == ap_black_list.count) {
7705 char mac_buf[32] = {0};
7706 sprintf(mac_buf, "STA_BLOCK %02X:%02X:%02X:%02X:%02X:%02X",
7707 macaddr[0], macaddr[1], macaddr[2],
7708 macaddr[3], macaddr[4], macaddr[5]);
7709 wl_iw_send_priv_event(priv_dev, mac_buf);
7717 memcpy(wrqu.addr.sa_data, &e->addr, ETHER_ADDR_LEN);
7718 wrqu.addr.sa_family = ARPHRD_ETHER;
7720 #if WIRELESS_EXT > 14
7722 case WLC_E_ASSOC_IND:
7723 case WLC_E_REASSOC_IND:
7725 WL_SOFTAP(("STA connect received %d\n", event_type));
7726 if (ap_cfg_running) {
7727 wl_iw_send_priv_event(priv_dev, "STA_JOIN");
7728 goto wl_iw_event_end;
7731 memcpy(wrqu.addr.sa_data, &e->addr, ETHER_ADDR_LEN);
7732 wrqu.addr.sa_family = ARPHRD_ETHER;
7733 cmd = IWEVREGISTERED;
7736 if (status == WLC_E_STATUS_SUCCESS) {
7737 memcpy(wrqu.addr.sa_data, &e->addr.octet, ETHER_ADDR_LEN);
7738 wrqu.addr.sa_family = ARPHRD_ETHER;
7741 else if (status == WLC_E_STATUS_NO_NETWORKS) {
7743 if ((roam_no_success == 5) && (roam_no_success_send == FALSE)) {
7744 roam_no_success_send = TRUE;
7745 bzero(wrqu.addr.sa_data, ETHER_ADDR_LEN);
7746 bzero(&extra, ETHER_ADDR_LEN);
7748 WL_ERROR(("%s ROAMING did not succeeded , send Link Down\n", \
7751 WL_TRACE(("##### ROAMING did not succeeded %d\n", roam_no_success));
7752 goto wl_iw_event_end;
7756 case WLC_E_DEAUTH_IND:
7757 case WLC_E_DISASSOC_IND:
7759 WL_SOFTAP(("STA disconnect received %d\n", event_type));
7760 if (ap_cfg_running) {
7761 wl_iw_send_priv_event(priv_dev, "STA_LEAVE");
7762 goto wl_iw_event_end;
7766 bzero(wrqu.addr.sa_data, ETHER_ADDR_LEN);
7767 wrqu.addr.sa_family = ARPHRD_ETHER;
7768 bzero(&extra, ETHER_ADDR_LEN);
7771 case WLC_E_NDIS_LINK:
7773 if (!(flags & WLC_EVENT_MSG_LINK)) {
7776 if (ap_cfg_running) {
7778 if (ap_cfg_running && !strncmp(dev->name, "wl0.1", 5)) {
7780 WL_SOFTAP(("AP DOWN %d\n", event_type));
7781 wl_iw_send_priv_event(priv_dev, "AP_DOWN");
7783 WL_TRACE(("STA_Link Down\n"));
7784 g_ss_cache_ctrl.m_link_down = 1;
7787 g_ss_cache_ctrl.m_link_down = 1;
7789 WL_TRACE(("Link Down\n"));
7791 bzero(wrqu.addr.sa_data, ETHER_ADDR_LEN);
7792 bzero(&extra, ETHER_ADDR_LEN);
7795 memcpy(wrqu.addr.sa_data, &e->addr, ETHER_ADDR_LEN);
7796 g_ss_cache_ctrl.m_link_down = 0;
7798 memcpy(g_ss_cache_ctrl.m_active_bssid, &e->addr, ETHER_ADDR_LEN);
7802 if (ap_cfg_running) {
7804 if (ap_cfg_running && !strncmp(dev->name, "wl0.1", 5)) {
7806 WL_SOFTAP(("AP UP %d\n", event_type));
7807 wl_iw_send_priv_event(priv_dev, "AP_UP");
7809 WL_TRACE(("STA_LINK_UP\n"));
7810 roam_no_success_send = FALSE;
7811 roam_no_success = 0;
7814 WL_TRACE(("Link UP\n"));
7817 net_os_wake_lock_timeout_enable(dev);
7818 wrqu.addr.sa_family = ARPHRD_ETHER;
7820 case WLC_E_ACTION_FRAME:
7822 if (datalen + 1 <= sizeof(extra)) {
7823 wrqu.data.length = datalen + 1;
7824 extra[0] = WLC_E_ACTION_FRAME;
7825 memcpy(&extra[1], data, datalen);
7826 WL_TRACE(("WLC_E_ACTION_FRAME len %d \n", wrqu.data.length));
7830 case WLC_E_ACTION_FRAME_COMPLETE:
7832 memcpy(&toto, data, 4);
7833 if (sizeof(status) + 1 <= sizeof(extra)) {
7834 wrqu.data.length = sizeof(status) + 1;
7835 extra[0] = WLC_E_ACTION_FRAME_COMPLETE;
7836 memcpy(&extra[1], &status, sizeof(status));
7837 printf("wl_iw_event status %d PacketId %d \n", status, toto);
7838 printf("WLC_E_ACTION_FRAME_COMPLETE len %d \n", wrqu.data.length);
7842 #if WIRELESS_EXT > 17
7843 case WLC_E_MIC_ERROR: {
7844 struct iw_michaelmicfailure *micerrevt = (struct iw_michaelmicfailure *)&extra;
7845 cmd = IWEVMICHAELMICFAILURE;
7846 wrqu.data.length = sizeof(struct iw_michaelmicfailure);
7847 if (flags & WLC_EVENT_MSG_GROUP)
7848 micerrevt->flags |= IW_MICFAILURE_GROUP;
7850 micerrevt->flags |= IW_MICFAILURE_PAIRWISE;
7851 memcpy(micerrevt->src_addr.sa_data, &e->addr, ETHER_ADDR_LEN);
7852 micerrevt->src_addr.sa_family = ARPHRD_ETHER;
7857 case WLC_E_PMKID_CACHE: {
7860 struct iw_pmkid_cand *iwpmkidcand = (struct iw_pmkid_cand *)&extra;
7861 pmkid_cand_list_t *pmkcandlist;
7862 pmkid_cand_t *pmkidcand;
7865 cmd = IWEVPMKIDCAND;
7867 count = ntoh32_ua((uint8 *)&pmkcandlist->npmkid_cand);
7869 wrqu.data.length = sizeof(struct iw_pmkid_cand);
7870 pmkidcand = pmkcandlist->pmkid_cand;
7872 bzero(iwpmkidcand, sizeof(struct iw_pmkid_cand));
7873 if (pmkidcand->preauth)
7874 iwpmkidcand->flags |= IW_PMKID_CAND_PREAUTH;
7875 bcopy(&pmkidcand->BSSID, &iwpmkidcand->bssid.sa_data,
7878 wireless_send_event(dev, cmd, &wrqu, extra);
7884 goto wl_iw_event_end;
7889 case WLC_E_SCAN_COMPLETE:
7890 #if defined(WL_IW_USE_ISCAN)
7891 if ((g_iscan) && (g_iscan->sysioc_pid >= 0) &&
7892 (g_iscan->iscan_state != ISCAN_STATE_IDLE))
7894 up(&g_iscan->sysioc_sem);
7897 wrqu.data.length = strlen(extra);
7898 WL_TRACE(("Event WLC_E_SCAN_COMPLETE from specific scan %d\n", \
7899 g_iscan->iscan_state));
7903 wrqu.data.length = strlen(extra);
7904 WL_TRACE(("Event WLC_E_SCAN_COMPLETE\n"));
7908 case WLC_E_PFN_NET_FOUND:
7911 ssid = (wlc_ssid_t *)data;
7912 WL_TRACE(("%s Event WLC_E_PFN_NET_FOUND, send %s up : find %s len=%d\n", \
7913 __FUNCTION__, PNO_EVENT_UP, ssid->SSID, ssid->SSID_len));
7914 net_os_wake_lock_timeout_enable(dev);
7916 memset(&wrqu, 0, sizeof(wrqu));
7917 strcpy(extra, PNO_EVENT_UP);
7918 wrqu.data.length = strlen(extra);
7924 WL_TRACE(("Unknown Event %d: ignoring\n", event_type));
7929 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 31))
7930 if (cmd == SIOCGIWSCAN)
7931 wireless_send_event(dev, cmd, &wrqu, NULL);
7934 wireless_send_event(dev, cmd, &wrqu, extra);
7938 #if WIRELESS_EXT > 14
7940 memset(extra, 0, sizeof(extra));
7941 if (wl_iw_check_conn_fail(e, extra, sizeof(extra))) {
7943 wrqu.data.length = strlen(extra);
7945 wireless_send_event(dev, cmd, &wrqu, extra);
7950 net_os_wake_unlock(dev);
7954 int wl_iw_get_wireless_stats(struct net_device *dev, struct iw_statistics *wstats)
7963 if ((res = dev_wlc_ioctl(dev, WLC_GET_PHY_NOISE, &phy_noise, sizeof(phy_noise))))
7966 phy_noise = dtoh32(phy_noise);
7967 WL_TRACE(("wl_iw_get_wireless_stats phy noise=%d\n", phy_noise));
7969 bzero(&scb_val, sizeof(scb_val_t));
7970 if ((res = dev_wlc_ioctl(dev, WLC_GET_RSSI, &scb_val, sizeof(scb_val_t))))
7973 rssi = dtoh32(scb_val.val);
7974 WL_TRACE(("wl_iw_get_wireless_stats rssi=%d\n", rssi));
7975 if (rssi <= WL_IW_RSSI_NO_SIGNAL)
7976 wstats->qual.qual = 0;
7977 else if (rssi <= WL_IW_RSSI_VERY_LOW)
7978 wstats->qual.qual = 1;
7979 else if (rssi <= WL_IW_RSSI_LOW)
7980 wstats->qual.qual = 2;
7981 else if (rssi <= WL_IW_RSSI_GOOD)
7982 wstats->qual.qual = 3;
7983 else if (rssi <= WL_IW_RSSI_VERY_GOOD)
7984 wstats->qual.qual = 4;
7986 wstats->qual.qual = 5;
7989 wstats->qual.level = 0x100 + rssi;
7990 wstats->qual.noise = 0x100 + phy_noise;
7991 #if WIRELESS_EXT > 18
7992 wstats->qual.updated |= (IW_QUAL_ALL_UPDATED | IW_QUAL_DBM);
7994 wstats->qual.updated |= 7;
7997 #if WIRELESS_EXT > 11
7998 WL_TRACE(("wl_iw_get_wireless_stats counters=%d\n", (int)sizeof(wl_cnt_t)));
8000 memset(&cnt, 0, sizeof(wl_cnt_t));
8001 res = dev_wlc_bufvar_get(dev, "counters", (char *)&cnt, sizeof(wl_cnt_t));
8004 WL_ERROR(("wl_iw_get_wireless_stats counters failed error=%d\n", res));
8008 cnt.version = dtoh16(cnt.version);
8009 if (cnt.version != WL_CNT_T_VERSION) {
8010 WL_TRACE(("\tIncorrect version of counters struct: expected %d; got %d\n",
8011 WL_CNT_T_VERSION, cnt.version));
8015 wstats->discard.nwid = 0;
8016 wstats->discard.code = dtoh32(cnt.rxundec);
8017 wstats->discard.fragment = dtoh32(cnt.rxfragerr);
8018 wstats->discard.retries = dtoh32(cnt.txfail);
8019 wstats->discard.misc = dtoh32(cnt.rxrunt) + dtoh32(cnt.rxgiant);
8020 wstats->miss.beacon = 0;
8022 WL_TRACE(("wl_iw_get_wireless_stats counters txframe=%d txbyte=%d\n",
8023 dtoh32(cnt.txframe), dtoh32(cnt.txbyte)));
8024 WL_TRACE(("wl_iw_get_wireless_stats counters rxfrmtoolong=%d\n", dtoh32(cnt.rxfrmtoolong)));
8025 WL_TRACE(("wl_iw_get_wireless_stats counters rxbadplcp=%d\n", dtoh32(cnt.rxbadplcp)));
8026 WL_TRACE(("wl_iw_get_wireless_stats counters rxundec=%d\n", dtoh32(cnt.rxundec)));
8027 WL_TRACE(("wl_iw_get_wireless_stats counters rxfragerr=%d\n", dtoh32(cnt.rxfragerr)));
8028 WL_TRACE(("wl_iw_get_wireless_stats counters txfail=%d\n", dtoh32(cnt.txfail)));
8029 WL_TRACE(("wl_iw_get_wireless_stats counters rxrunt=%d\n", dtoh32(cnt.rxrunt)));
8030 WL_TRACE(("wl_iw_get_wireless_stats counters rxgiant=%d\n", dtoh32(cnt.rxgiant)));
8039 struct net_device *dev,
8042 #if defined(BT_DHCP_USE_FLAGS)
8043 char buf_flag7_dhcp_on[8] = { 7, 00, 00, 00, 0x1, 0x0, 0x00, 0x00 };
8044 char buf_flag7_default[8] = { 7, 00, 00, 00, 0x0, 0x00, 0x00, 0x00};
8047 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27))
8051 #if defined(BT_DHCP_eSCO_FIX)
8052 set_btc_esco_params(dev, set);
8055 #if defined(BT_DHCP_USE_FLAGS)
8056 WL_TRACE_COEX(("WI-FI priority boost via bt flags, set:%d\n", set));
8058 dev_wlc_bufvar_set(dev, "btc_flags",
8059 (char *)&buf_flag7_dhcp_on[0], sizeof(buf_flag7_dhcp_on));
8062 dev_wlc_bufvar_set(dev, "btc_flags",
8063 (char *)&buf_flag7_default[0], sizeof(buf_flag7_default));
8067 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27))
8073 wl_iw_bt_timerfunc(ulong data)
8075 bt_info_t *bt_local = (bt_info_t *)data;
8076 bt_local->timer_on = 0;
8077 WL_TRACE(("%s\n", __FUNCTION__));
8079 up(&bt_local->bt_sem);
8083 _bt_dhcp_sysioc_thread(void *data)
8085 DAEMONIZE("dhcp_sysioc");
8087 while (down_interruptible(&g_bt->bt_sem) == 0) {
8089 net_os_wake_lock(g_bt->dev);
8091 if (g_bt->timer_on) {
8093 del_timer_sync(&g_bt->timer);
8096 switch (g_bt->bt_state) {
8098 WL_TRACE_COEX(("%s bt_dhcp stm: started \n", __FUNCTION__));
8099 g_bt->bt_state = BT_DHCP_OPPORTUNITY_WINDOW;
8100 mod_timer(&g_bt->timer, jiffies + BT_DHCP_OPPORTUNITY_WINDOW_TIME*HZ/1000);
8104 case BT_DHCP_OPPORTUNITY_WINDOW:
8105 if (g_bt->dhcp_done) {
8106 WL_TRACE_COEX(("%s DHCP Done before T1 expiration\n", \
8108 g_bt->bt_state = BT_DHCP_IDLE;
8113 WL_TRACE_COEX(("%s DHCP T1:%d expired\n", \
8114 __FUNCTION__, BT_DHCP_OPPORTUNITY_WINDOW_TIME));
8115 if (g_bt->dev) wl_iw_bt_flag_set(g_bt->dev, TRUE);
8116 g_bt->bt_state = BT_DHCP_FLAG_FORCE_TIMEOUT;
8117 mod_timer(&g_bt->timer, jiffies + BT_DHCP_FLAG_FORCE_TIME*HZ/1000);
8121 case BT_DHCP_FLAG_FORCE_TIMEOUT:
8122 if (g_bt->dhcp_done) {
8123 WL_TRACE_COEX(("%s DHCP Done before T2 expiration\n", \
8126 WL_TRACE_COEX(("%s DHCP wait interval T2:%d msec expired\n",
8127 __FUNCTION__, BT_DHCP_FLAG_FORCE_TIME));
8130 if (g_bt->dev) wl_iw_bt_flag_set(g_bt->dev, FALSE);
8131 g_bt->bt_state = BT_DHCP_IDLE;
8136 WL_ERROR(("%s error g_status=%d !!!\n", __FUNCTION__, \
8138 if (g_bt->dev) wl_iw_bt_flag_set(g_bt->dev, FALSE);
8139 g_bt->bt_state = BT_DHCP_IDLE;
8144 net_os_wake_unlock(g_bt->dev);
8147 if (g_bt->timer_on) {
8149 del_timer_sync(&g_bt->timer);
8152 complete_and_exit(&g_bt->bt_exited, 0);
8156 wl_iw_bt_release(void)
8158 bt_info_t *bt_local = g_bt;
8164 if (bt_local->bt_pid >= 0) {
8165 KILL_PROC(bt_local->bt_pid, SIGTERM);
8166 wait_for_completion(&bt_local->bt_exited);
8173 wl_iw_bt_init(struct net_device *dev)
8175 bt_info_t *bt_dhcp = NULL;
8177 bt_dhcp = kmalloc(sizeof(bt_info_t), GFP_KERNEL);
8181 memset(bt_dhcp, 0, sizeof(bt_info_t));
8182 bt_dhcp->bt_pid = -1;
8185 bt_dhcp->bt_state = BT_DHCP_IDLE;
8188 bt_dhcp->timer_ms = 10;
8189 init_timer(&bt_dhcp->timer);
8190 bt_dhcp->timer.data = (ulong)bt_dhcp;
8191 bt_dhcp->timer.function = wl_iw_bt_timerfunc;
8193 sema_init(&bt_dhcp->bt_sem, 0);
8194 init_completion(&bt_dhcp->bt_exited);
8195 bt_dhcp->bt_pid = kernel_thread(_bt_dhcp_sysioc_thread, bt_dhcp, 0);
8196 if (bt_dhcp->bt_pid < 0) {
8197 WL_ERROR(("Failed in %s\n", __FUNCTION__));
8204 int wl_iw_attach(struct net_device *dev, void *dhdp)
8208 #if defined(WL_IW_USE_ISCAN)
8209 iscan_info_t *iscan = NULL;
8212 mutex_init(&wl_cache_lock);
8214 #if defined(WL_IW_USE_ISCAN)
8218 memset(&g_wl_iw_params, 0, sizeof(wl_iw_extra_params_t));
8221 params_size = (WL_SCAN_PARAMS_FIXED_SIZE + OFFSETOF(wl_iscan_params_t, params)) +
8222 (WL_NUMCHANNELS * sizeof(uint16)) + WL_SCAN_PARAMS_SSID_MAX * sizeof(wlc_ssid_t);
8224 params_size = (WL_SCAN_PARAMS_FIXED_SIZE + OFFSETOF(wl_iscan_params_t, params));
8226 iscan = kmalloc(sizeof(iscan_info_t), GFP_KERNEL);
8229 memset(iscan, 0, sizeof(iscan_info_t));
8231 iscan->iscan_ex_params_p = (wl_iscan_params_t*)kmalloc(params_size, GFP_KERNEL);
8232 if (!iscan->iscan_ex_params_p)
8234 iscan->iscan_ex_param_size = params_size;
8235 iscan->sysioc_pid = -1;
8239 iscan->iscan_state = ISCAN_STATE_IDLE;
8240 #if defined(CONFIG_FIRST_SCAN)
8241 g_first_broadcast_scan = BROADCAST_SCAN_FIRST_IDLE;
8242 g_first_counter_scans = 0;
8243 g_iscan->scan_flag = 0;
8246 iscan->timer_ms = 8000;
8247 init_timer(&iscan->timer);
8248 iscan->timer.data = (ulong)iscan;
8249 iscan->timer.function = wl_iw_timerfunc;
8251 sema_init(&iscan->sysioc_sem, 0);
8252 init_completion(&iscan->sysioc_exited);
8253 iscan->sysioc_pid = kernel_thread(_iscan_sysioc_thread, iscan, 0);
8254 if (iscan->sysioc_pid < 0)
8258 iw = *(wl_iw_t **)netdev_priv(dev);
8259 iw->pub = (dhd_pub_t *)dhdp;
8265 g_scan = (void *)kmalloc(G_SCAN_RESULTS, GFP_KERNEL);
8269 memset(g_scan, 0, G_SCAN_RESULTS);
8270 g_scan_specified_ssid = 0;
8273 wl_iw_init_ss_cache_ctrl();
8281 void wl_iw_detach(void)
8283 #if defined(WL_IW_USE_ISCAN)
8285 iscan_info_t *iscan = g_iscan;
8289 if (iscan->sysioc_pid >= 0) {
8290 KILL_PROC(iscan->sysioc_pid, SIGTERM);
8291 wait_for_completion(&iscan->sysioc_exited);
8293 mutex_lock(&wl_cache_lock);
8294 while (iscan->list_hdr) {
8295 buf = iscan->list_hdr->next;
8296 kfree(iscan->list_hdr);
8297 iscan->list_hdr = buf;
8299 kfree(iscan->iscan_ex_params_p);
8302 mutex_unlock(&wl_cache_lock);
8310 wl_iw_release_ss_cache_ctrl();
8314 if (ap_cfg_running) {
8315 WL_TRACE(("\n%s AP is going down\n", __FUNCTION__));
8316 wl_iw_send_priv_event(priv_dev, "AP_DOWN");