2 * Linux Wireless Extensions support
4 * Copyright (C) 1999-2011, 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.132.2.18 2011-02-05 01:44:47 $
34 #include <bcmendian.h>
35 #include <proto/ethernet.h>
37 #include <linux/if_arp.h>
38 #include <asm/uaccess.h>
40 #include <dngl_stats.h>
44 typedef void wlc_info_t;
45 typedef void wl_info_t;
46 typedef const struct si_pub si_t;
49 #include <proto/ethernet.h>
50 #include <dngl_stats.h>
52 #define WL_ERROR(x) printf x
61 #define WL_PNO(x) printf x
67 #define JF2MS ((((jiffies / HZ) * 1000) + ((jiffies % HZ) * 1000) / HZ))
70 #define WL_TRACE_COEX(x) printf("TS:%lu ", JF2MS); \
73 #define WL_TRACE_COEX(x)
77 #define WL_TRACE_SCAN(x) printf("TS:%lu ", JF2MS); \
80 #define WL_TRACE_SCAN(x)
89 #define IW_WSEC_ENABLED(wsec) ((wsec) & (WEP_ENABLED | TKIP_ENABLED | AES_ENABLED))
91 #include <linux/rtnetlink.h>
93 #define WL_IW_USE_ISCAN 1
94 #define ENABLE_ACTIVE_PASSIVE_SCAN_SUPPRESS 1
97 bool g_set_essid_before_scan = TRUE;
100 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)) && 1
101 struct mutex g_wl_ss_scan_lock;
106 static struct net_device *priv_dev;
107 extern bool ap_cfg_running;
108 extern bool ap_fw_loaded;
109 struct net_device *ap_net_dev = NULL;
110 tsk_ctl_t ap_eth_ctl;
111 static int wl_iw_set_ap_security(struct net_device *dev, struct ap_profile *ap);
112 static int wl_iw_softap_deassoc_stations(struct net_device *dev, u8 *mac);
116 #define WL_IW_IOCTL_CALL(func_call) \
121 #define RETURN_IF_EXTRA_NULL(extra) \
123 WL_ERROR(("%s: error : extra is null pointer\n", __FUNCTION__)); \
127 static int g_onoff = G_WLAN_SET_ON;
128 wl_iw_extra_params_t g_wl_iw_params;
131 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)) && 1
133 static struct mutex wl_cache_lock;
134 static struct mutex wl_softap_lock;
136 #define DHD_OS_MUTEX_INIT(a) mutex_init(a)
137 #define DHD_OS_MUTEX_LOCK(a) mutex_lock(a)
138 #define DHD_OS_MUTEX_UNLOCK(a) mutex_unlock(a)
142 #define DHD_OS_MUTEX_INIT(a)
143 #define DHD_OS_MUTEX_LOCK(a)
144 #define DHD_OS_MUTEX_UNLOCK(a)
148 #include <bcmsdbus.h>
149 extern void dhd_customer_gpio_wlan_ctrl(int onoff);
150 extern uint dhd_dev_reset(struct net_device *dev, uint8 flag);
151 extern void dhd_dev_init_ioctl(struct net_device *dev);
153 uint wl_msg_level = WL_ERROR_VAL;
155 #define MAX_WLIW_IOCTL_LEN 1024
162 #define htodchanspec(i) i
163 #define dtohchanspec(i) i
165 extern struct iw_statistics *dhd_get_wireless_stats(struct net_device *dev);
166 extern int dhd_wait_pend8021x(struct net_device *dev);
168 #if WIRELESS_EXT < 19
169 #define IW_IOCTL_IDX(cmd) ((cmd) - SIOCIWFIRST)
170 #define IW_EVENT_IDX(cmd) ((cmd) - IWEVFIRST)
173 static void *g_scan = NULL;
174 static volatile uint g_scan_specified_ssid;
175 static wlc_ssid_t g_specific_ssid;
177 static wlc_ssid_t g_ssid;
180 static char *g_wps_probe_req_ie;
181 static int g_wps_probe_req_ie_len;
184 bool btcoex_is_sco_active(struct net_device *dev);
185 static wl_iw_ss_cache_ctrl_t g_ss_cache_ctrl;
186 #if defined(CONFIG_FIRST_SCAN)
187 static volatile uint g_first_broadcast_scan;
188 static volatile uint g_first_counter_scans;
189 #define MAX_ALLOWED_BLOCK_SCAN_FROM_FIRST_SCAN 3
192 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0))
193 #define DAEMONIZE(a) daemonize(a); \
194 allow_signal(SIGKILL); \
195 allow_signal(SIGTERM);
197 #define RAISE_RX_SOFTIRQ() \
198 cpu_raise_softirq(smp_processor_id(), NET_RX_SOFTIRQ)
199 #define DAEMONIZE(a) daemonize(); \
201 strncpy(current->comm, a, MIN(sizeof(current->comm), (strlen(a) + 1))); \
205 #if defined(WL_IW_USE_ISCAN)
207 static void wl_iw_free_ss_cache(void);
208 static int wl_iw_run_ss_cache_timer(int kick_off);
210 #if defined(CONFIG_FIRST_SCAN)
211 int wl_iw_iscan_set_scan_broadcast_prep(struct net_device *dev, uint flag);
213 static int dev_wlc_bufvar_set(struct net_device *dev, char *name, char *buf, int len);
214 #define ISCAN_STATE_IDLE 0
215 #define ISCAN_STATE_SCANING 1
218 #define WLC_IW_ISCAN_MAXLEN 2048
219 typedef struct iscan_buf {
220 struct iscan_buf * next;
221 char iscan_buf[WLC_IW_ISCAN_MAXLEN];
224 typedef struct iscan_info {
225 struct net_device *dev;
226 struct timer_list timer;
230 iscan_buf_t * list_hdr;
231 iscan_buf_t * list_cur;
238 char ioctlbuf[WLC_IOCTL_MEDLEN];
240 char ioctlbuf[WLC_IOCTL_SMLEN];
243 wl_iscan_params_t *iscan_ex_params_p;
244 int iscan_ex_param_size;
252 #define BT_DHCP_eSCO_FIX
253 #define BT_DHCP_USE_FLAGS
254 #define BT_DHCP_OPPORTUNITY_WINDOW_TIME 2500
255 #define BT_DHCP_FLAG_FORCE_TIME 5500
259 static int wl_iw_set_btcoex_dhcp(
260 struct net_device *dev,
261 struct iw_request_info *info,
262 union iwreq_data *wrqu,
266 static void wl_iw_bt_flag_set(struct net_device *dev, bool set);
267 static void wl_iw_bt_release(void);
269 typedef enum bt_coex_status {
272 BT_DHCP_OPPORTUNITY_WINDOW,
273 BT_DHCP_FLAG_FORCE_TIMEOUT
277 typedef struct bt_info {
278 struct net_device *dev;
279 struct timer_list timer;
282 uint32 ts_dhcp_start;
292 bt_info_t *g_bt = NULL;
293 static void wl_iw_bt_timerfunc(ulong data);
295 iscan_info_t *g_iscan = NULL;
296 void dhd_print_buf(void *pbuf, int len, int bytes_per_line);
297 static void wl_iw_timerfunc(ulong data);
298 static void wl_iw_set_event_mask(struct net_device *dev);
300 wl_iw_iscan(iscan_info_t *iscan, wlc_ssid_t *ssid, uint16 action);
305 struct net_device *dev,
306 struct iw_request_info *info,
307 union iwreq_data *wrqu,
314 struct net_device *dev,
315 struct iw_request_info *info,
316 struct iw_point *dwrq,
322 wl_scan_results_t *list,
323 struct iw_request_info *info,
334 key->index = htod32(key->index);
335 key->len = htod32(key->len);
336 key->algo = htod32(key->algo);
337 key->flags = htod32(key->flags);
338 key->rxiv.hi = htod32(key->rxiv.hi);
339 key->rxiv.lo = htod16(key->rxiv.lo);
340 key->iv_initialized = htod32(key->iv_initialized);
348 key->index = dtoh32(key->index);
349 key->len = dtoh32(key->len);
350 key->algo = dtoh32(key->algo);
351 key->flags = dtoh32(key->flags);
352 key->rxiv.hi = dtoh32(key->rxiv.hi);
353 key->rxiv.lo = dtoh16(key->rxiv.lo);
354 key->iv_initialized = dtoh32(key->iv_initialized);
359 struct net_device *dev,
371 WL_ERROR(("%s: dev is null\n", __FUNCTION__));
375 net_os_wake_lock(dev);
377 WL_INFORM(("%s, PID:%x: send Local IOCTL -> dhd: cmd:0x%x, buf:%p, len:%d ,\n",
378 __FUNCTION__, current->pid, cmd, arg, len));
380 if (g_onoff == G_WLAN_SET_ON) {
381 memset(&ioc, 0, sizeof(ioc));
386 strcpy(ifr.ifr_name, dev->name);
387 ifr.ifr_data = (caddr_t) &ioc;
392 WL_ERROR(("%s: Error dev_open: %d\n", __func__, ret));
393 net_os_wake_unlock(dev);
399 #if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 31)
400 ret = dev->do_ioctl(dev, &ifr, SIOCDEVPRIVATE);
402 ret = dev->netdev_ops->ndo_do_ioctl(dev, &ifr, SIOCDEVPRIVATE);
407 WL_TRACE(("%s: call after driver stop : ignored\n", __FUNCTION__));
410 net_os_wake_unlock(dev);
417 dev_wlc_intvar_get_reg(
418 struct net_device *dev,
424 char buf[WLC_IOCTL_SMLEN];
430 len = bcm_mkiovar(name, (char *)(®), sizeof(reg), (char *)(&var), sizeof(var.buf));
432 error = dev_wlc_ioctl(dev, WLC_GET_VAR, (void *)&var, len);
434 *retval = dtoh32(var.val);
440 dev_wlc_intvar_set_reg(
441 struct net_device *dev,
448 memset(reg_addr, 0, sizeof(reg_addr));
449 memcpy((char *)®_addr[0], (char *)addr, 4);
450 memcpy((char *)®_addr[4], (char *)val, 4);
452 return (dev_wlc_bufvar_set(dev, name, (char *)®_addr[0], sizeof(reg_addr)));
460 struct net_device *dev,
464 char buf[WLC_IOCTL_SMLEN];
468 len = bcm_mkiovar(name, (char *)(&val), sizeof(val), buf, sizeof(buf));
471 return (dev_wlc_ioctl(dev, WLC_SET_VAR, buf, len));
474 #if defined(WL_IW_USE_ISCAN)
477 struct net_device *dev,
486 iolen = bcm_mkiovar(iovar, param, paramlen, bufptr, buflen);
492 return (dev_wlc_ioctl(dev, WLC_SET_VAR, bufptr, iolen));
497 struct net_device *dev,
506 iolen = bcm_mkiovar(iovar, param, paramlen, bufptr, buflen);
509 return (dev_wlc_ioctl(dev, WLC_GET_VAR, bufptr, buflen));
514 #if WIRELESS_EXT > 17
517 struct net_device *dev,
521 #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 31)
522 char ioctlbuf[MAX_WLIW_IOCTL_LEN];
524 static char ioctlbuf[MAX_WLIW_IOCTL_LEN];
528 buflen = bcm_mkiovar(name, buf, len, ioctlbuf, sizeof(ioctlbuf));
531 return (dev_wlc_ioctl(dev, WLC_SET_VAR, ioctlbuf, buflen));
538 struct net_device *dev,
540 char *buf, int buflen)
542 #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 31)
543 char ioctlbuf[MAX_WLIW_IOCTL_LEN];
545 static char ioctlbuf[MAX_WLIW_IOCTL_LEN];
550 len = bcm_mkiovar(name, NULL, 0, ioctlbuf, sizeof(ioctlbuf));
552 error = dev_wlc_ioctl(dev, WLC_GET_VAR, (void *)ioctlbuf, MAX_WLIW_IOCTL_LEN);
554 bcopy(ioctlbuf, buf, buflen);
563 struct net_device *dev,
568 char buf[WLC_IOCTL_SMLEN];
576 len = bcm_mkiovar(name, (char *)(&data_null), 0, (char *)(&var), sizeof(var.buf));
578 error = dev_wlc_ioctl(dev, WLC_GET_VAR, (void *)&var, len);
580 *retval = dtoh32(var.val);
586 #if WIRELESS_EXT > 12
588 wl_iw_set_active_scan(
589 struct net_device *dev,
590 struct iw_request_info *info,
591 union iwreq_data *wrqu,
599 #if defined(WL_IW_USE_ISCAN)
600 if (g_iscan->iscan_state == ISCAN_STATE_IDLE)
602 error = dev_wlc_ioctl(dev, WLC_SET_PASSIVE_SCAN, &as, sizeof(as));
603 #if defined(WL_IW_USE_ISCAN)
605 g_iscan->scan_flag = as;
607 p += snprintf(p, MAX_WX_STRING, "OK");
609 wrqu->data.length = p - extra + 1;
614 wl_iw_set_passive_scan(
615 struct net_device *dev,
616 struct iw_request_info *info,
617 union iwreq_data *wrqu,
625 #if defined(WL_IW_USE_ISCAN)
626 if (g_iscan->iscan_state == ISCAN_STATE_IDLE) {
630 if (g_scan_specified_ssid == 0) {
631 error = dev_wlc_ioctl(dev, WLC_SET_PASSIVE_SCAN, &ps, sizeof(ps));
633 #if defined(WL_IW_USE_ISCAN)
636 g_iscan->scan_flag = ps;
639 p += snprintf(p, MAX_WX_STRING, "OK");
641 wrqu->data.length = p - extra + 1;
648 struct net_device *dev,
649 struct iw_request_info *info,
650 union iwreq_data *wrqu,
658 txpower = bcm_atoi(extra + strlen(TXPOWER_SET_CMD) + 1);
659 if ((txpower >= 0) && (txpower <= 127))
661 txpower |= WL_TXPWR_OVERRIDE;
662 txpower = htod32(txpower);
664 error = dev_wlc_intvar_set(dev, "qtxpower", txpower);
665 p += snprintf(p, MAX_WX_STRING, "OK");
666 WL_TRACE(("%s: set TXpower 0x%X is OK\n", __FUNCTION__, txpower));
668 WL_ERROR(("%s: set tx power failed\n", __FUNCTION__));
669 p += snprintf(p, MAX_WX_STRING, "FAIL");
672 wrqu->data.length = p - extra + 1;
678 struct net_device *dev,
679 struct iw_request_info *info,
680 union iwreq_data *wrqu,
686 struct ether_addr *id;
690 strcpy(buf, "cur_etheraddr");
691 error = dev_wlc_ioctl(dev, WLC_GET_VAR, buf, sizeof(buf));
692 id = (struct ether_addr *) buf;
693 p += snprintf(p, MAX_WX_STRING, "Macaddr = %02X:%02X:%02X:%02X:%02X:%02X\n",
694 id->octet[0], id->octet[1], id->octet[2],
695 id->octet[3], id->octet[4], id->octet[5]);
696 wrqu->data.length = p - extra + 1;
705 struct net_device *dev,
706 struct iw_request_info *info,
707 union iwreq_data *wrqu,
711 char country_code[WLC_CNTRY_BUF_SZ];
715 int country_code_size;
716 wl_country_t cspec = {{0}, 0, {0}};
717 char smbuf[WLC_IOCTL_SMLEN];
721 memset(country_code, 0, sizeof(country_code));
722 memset(smbuf, 0, sizeof(smbuf));
725 country_offset = strcspn(extra, " ");
726 country_code_size = strlen(extra) - country_offset;
729 if (country_offset != 0) {
730 strncpy(country_code, extra + country_offset +1,
731 MIN(country_code_size, sizeof(country_code)));
734 bzero(&scbval, sizeof(scb_val_t));
735 if ((error = dev_wlc_ioctl(dev, WLC_DISASSOC, &scbval, sizeof(scb_val_t)))) {
736 WL_ERROR(("%s: set country failed due to Disassoc error\n", __FUNCTION__));
740 memcpy(cspec.country_abbrev, country_code, WLC_CNTRY_BUF_SZ);
741 memcpy(cspec.ccode, country_code, WLC_CNTRY_BUF_SZ);
743 get_customized_country_code((char *)&cspec.country_abbrev, &cspec);
746 if ((error = dev_iw_iovar_setbuf(dev, "country", &cspec,
747 sizeof(cspec), smbuf, sizeof(smbuf))) >= 0) {
748 p += snprintf(p, MAX_WX_STRING, "OK");
749 WL_ERROR(("%s: set country for %s as %s rev %d is OK\n",
750 __FUNCTION__, country_code, cspec.ccode, cspec.rev));
751 dhd_bus_country_set(dev, &cspec);
756 WL_ERROR(("%s: set country for %s as %s rev %d failed\n",
757 __FUNCTION__, country_code, cspec.ccode, cspec.rev));
760 p += snprintf(p, MAX_WX_STRING, "FAIL");
763 wrqu->data.length = p - extra + 1;
768 wl_iw_set_power_mode(
769 struct net_device *dev,
770 struct iw_request_info *info,
771 union iwreq_data *wrqu,
777 static int pm = PM_FAST;
778 int pm_local = PM_OFF;
779 char powermode_val = 0;
781 WL_TRACE_COEX(("%s: DHCP session cmd:%s\n", __FUNCTION__, extra));
783 strncpy((char *)&powermode_val, extra + strlen("POWERMODE") +1, 1);
785 if (strnicmp((char *)&powermode_val, "1", strlen("1")) == 0) {
787 WL_TRACE(("%s: DHCP session starts\n", __FUNCTION__));
789 dev_wlc_ioctl(dev, WLC_GET_PM, &pm, sizeof(pm));
790 dev_wlc_ioctl(dev, WLC_SET_PM, &pm_local, sizeof(pm_local));
793 net_os_set_packet_filter(dev, 0);
796 g_bt->ts_dhcp_start = JF2MS;
797 g_bt->dhcp_done = FALSE;
798 WL_TRACE_COEX(("%s: DHCP start, pm:%d changed to pm:%d\n",
799 __FUNCTION__, pm, pm_local));
802 } else if (strnicmp((char *)&powermode_val, "0", strlen("0")) == 0) {
805 dev_wlc_ioctl(dev, WLC_SET_PM, &pm, sizeof(pm));
808 net_os_set_packet_filter(dev, 1);
811 g_bt->dhcp_done = TRUE;
812 g_bt->ts_dhcp_ok = JF2MS;
813 WL_TRACE_COEX(("%s: DHCP done for:%d ms, restored pm:%d\n",
814 __FUNCTION__, (g_bt->ts_dhcp_ok - g_bt->ts_dhcp_start), pm));
818 WL_ERROR(("%s Unkwown yet power setting, ignored\n",
822 p += snprintf(p, MAX_WX_STRING, "OK");
824 wrqu->data.length = p - extra + 1;
830 bool btcoex_is_sco_active(struct net_device *dev)
838 for (i = 0; i < 12; i++) {
840 ioc_res = dev_wlc_intvar_get_reg(dev, "btc_params", 27, ¶m27);
842 WL_TRACE_COEX(("%s, sample[%d], btc params: 27:%x\n",
843 __FUNCTION__, i, param27));
846 WL_ERROR(("%s ioc read btc params error\n", __FUNCTION__));
850 if ((param27 & 0x6) == 2) {
854 if (sco_id_cnt > 2) {
855 WL_TRACE_COEX(("%s, sco/esco detected, pkt id_cnt:%d samples:%d\n",
856 __FUNCTION__, sco_id_cnt, i));
867 #if defined(BT_DHCP_eSCO_FIX)
869 static int set_btc_esco_params(struct net_device *dev, bool trump_sco)
871 static bool saved_status = FALSE;
873 char buf_reg50va_dhcp_on[8] = { 50, 00, 00, 00, 0x22, 0x80, 0x00, 0x00 };
874 char buf_reg51va_dhcp_on[8] = { 51, 00, 00, 00, 0x00, 0x00, 0x00, 0x00 };
875 char buf_reg64va_dhcp_on[8] = { 64, 00, 00, 00, 0x00, 0x00, 0x00, 0x00 };
876 char buf_reg65va_dhcp_on[8] = { 65, 00, 00, 00, 0x00, 0x00, 0x00, 0x00 };
877 char buf_reg71va_dhcp_on[8] = { 71, 00, 00, 00, 0x00, 0x00, 0x00, 0x00 };
880 static uint32 saved_reg50;
881 static uint32 saved_reg51;
882 static uint32 saved_reg64;
883 static uint32 saved_reg65;
884 static uint32 saved_reg71;
889 WL_TRACE_COEX(("Do new SCO/eSCO coex algo {save & override} \n"));
892 if ((!dev_wlc_intvar_get_reg(dev, "btc_params", 50, &saved_reg50)) &&
893 (!dev_wlc_intvar_get_reg(dev, "btc_params", 51, &saved_reg51)) &&
894 (!dev_wlc_intvar_get_reg(dev, "btc_params", 64, &saved_reg64)) &&
895 (!dev_wlc_intvar_get_reg(dev, "btc_params", 65, &saved_reg65)) &&
896 (!dev_wlc_intvar_get_reg(dev, "btc_params", 71, &saved_reg71))) {
899 WL_TRACE_COEX(("%s saved bt_params[50,51,64,65,71]:"
900 " 0x%x 0x%x 0x%x 0x%x 0x%x\n",
901 __FUNCTION__, saved_reg50, saved_reg51,
902 saved_reg64, saved_reg65, saved_reg71));
905 WL_ERROR((":%s: save btc_params failed\n",
907 saved_status = FALSE;
911 WL_TRACE_COEX(("override with [50,51,64,65,71]:"
912 " 0x%x 0x%x 0x%x 0x%x 0x%x\n",
913 *(u32 *)(buf_reg50va_dhcp_on+4),
914 *(u32 *)(buf_reg51va_dhcp_on+4),
915 *(u32 *)(buf_reg64va_dhcp_on+4),
916 *(u32 *)(buf_reg65va_dhcp_on+4),
917 *(u32 *)(buf_reg71va_dhcp_on+4)));
919 dev_wlc_bufvar_set(dev, "btc_params", (char *)&buf_reg50va_dhcp_on[0], 8);
920 dev_wlc_bufvar_set(dev, "btc_params", (char *)&buf_reg51va_dhcp_on[0], 8);
921 dev_wlc_bufvar_set(dev, "btc_params", (char *)&buf_reg64va_dhcp_on[0], 8);
922 dev_wlc_bufvar_set(dev, "btc_params", (char *)&buf_reg65va_dhcp_on[0], 8);
923 dev_wlc_bufvar_set(dev, "btc_params", (char *)&buf_reg71va_dhcp_on[0], 8);
927 } else if (saved_status) {
929 WL_TRACE_COEX(("Do new SCO/eSCO coex algo {save & override} \n"));
932 dev_wlc_intvar_set_reg(dev, "btc_params",
933 (char *)®addr, (char *)&saved_reg50);
935 dev_wlc_intvar_set_reg(dev, "btc_params",
936 (char *)®addr, (char *)&saved_reg51);
938 dev_wlc_intvar_set_reg(dev, "btc_params",
939 (char *)®addr, (char *)&saved_reg64);
941 dev_wlc_intvar_set_reg(dev, "btc_params",
942 (char *)®addr, (char *)&saved_reg65);
944 dev_wlc_intvar_set_reg(dev, "btc_params",
945 (char *)®addr, (char *)&saved_reg71);
947 WL_TRACE_COEX(("restore bt_params[50,51,64,65,71]: 0x%x 0x%x 0x%x 0x%x 0x%x\n",
948 saved_reg50, saved_reg51, saved_reg64,
949 saved_reg65, saved_reg71));
951 saved_status = FALSE;
953 WL_ERROR((":%s att to restore not saved BTCOEX params\n",
963 wl_iw_get_power_mode(
964 struct net_device *dev,
965 struct iw_request_info *info,
966 union iwreq_data *wrqu,
974 error = dev_wlc_ioctl(dev, WLC_GET_PM, &pm_local, sizeof(pm_local));
976 WL_TRACE(("%s: Powermode = %d\n", __func__, pm_local));
977 if (pm_local == PM_OFF)
981 p += snprintf(p, MAX_WX_STRING, "powermode = %d", pm_local);
984 WL_TRACE(("%s: Error = %d\n", __func__, error));
985 p += snprintf(p, MAX_WX_STRING, "FAIL");
987 wrqu->data.length = p - extra + 1;
992 wl_iw_set_btcoex_dhcp(
993 struct net_device *dev,
994 struct iw_request_info *info,
995 union iwreq_data *wrqu,
1001 char powermode_val = 0;
1002 char buf_reg66va_dhcp_on[8] = { 66, 00, 00, 00, 0x10, 0x27, 0x00, 0x00 };
1003 char buf_reg41va_dhcp_on[8] = { 41, 00, 00, 00, 0x33, 0x00, 0x00, 0x00 };
1004 char buf_reg68va_dhcp_on[8] = { 68, 00, 00, 00, 0x90, 0x01, 0x00, 0x00 };
1007 static uint32 saved_reg66;
1008 static uint32 saved_reg41;
1009 static uint32 saved_reg68;
1010 static bool saved_status = FALSE;
1013 char buf_flag7_default[8] = { 7, 00, 00, 00, 0x0, 0x00, 0x00, 0x00};
1017 strncpy((char *)&powermode_val, extra + strlen("BTCOEXMODE") +1, 1);
1019 if (strnicmp((char *)&powermode_val, "1", strlen("1")) == 0) {
1021 WL_TRACE(("%s: DHCP session starts\n", __FUNCTION__));
1024 if ((saved_status == FALSE) &&
1025 (!dev_wlc_intvar_get_reg(dev, "btc_params", 66, &saved_reg66)) &&
1026 (!dev_wlc_intvar_get_reg(dev, "btc_params", 41, &saved_reg41)) &&
1027 (!dev_wlc_intvar_get_reg(dev, "btc_params", 68, &saved_reg68))) {
1028 saved_status = TRUE;
1029 WL_TRACE(("Saved 0x%x 0x%x 0x%x\n",
1030 saved_reg66, saved_reg41, saved_reg68));
1037 if (btcoex_is_sco_active(dev)) {
1039 dev_wlc_bufvar_set(dev, "btc_params",
1040 (char *)&buf_reg66va_dhcp_on[0],
1041 sizeof(buf_reg66va_dhcp_on));
1043 dev_wlc_bufvar_set(dev, "btc_params",
1044 (char *)&buf_reg41va_dhcp_on[0],
1045 sizeof(buf_reg41va_dhcp_on));
1047 dev_wlc_bufvar_set(dev, "btc_params",
1048 (char *)&buf_reg68va_dhcp_on[0],
1049 sizeof(buf_reg68va_dhcp_on));
1050 saved_status = TRUE;
1052 g_bt->bt_state = BT_DHCP_START;
1054 mod_timer(&g_bt->timer, g_bt->timer.expires);
1055 WL_TRACE_COEX(("%s enable BT DHCP Timer\n",
1060 else if (saved_status == TRUE) {
1061 WL_ERROR(("%s was called w/o DHCP OFF. Continue\n", __FUNCTION__));
1064 else if (strnicmp((char *)&powermode_val, "2", strlen("2")) == 0) {
1071 WL_TRACE(("%s disable BT DHCP Timer\n", __FUNCTION__));
1072 if (g_bt->timer_on) {
1074 del_timer_sync(&g_bt->timer);
1076 if (g_bt->bt_state != BT_DHCP_IDLE) {
1078 WL_TRACE_COEX(("%s bt->bt_state:%d\n",
1079 __FUNCTION__, g_bt->bt_state));
1081 up(&g_bt->tsk_ctl.sema);
1086 if (saved_status == TRUE)
1087 dev_wlc_bufvar_set(dev, "btc_flags",
1088 (char *)&buf_flag7_default[0], sizeof(buf_flag7_default));
1092 if (saved_status == TRUE) {
1094 dev_wlc_intvar_set_reg(dev, "btc_params",
1095 (char *)®addr, (char *)&saved_reg66);
1097 dev_wlc_intvar_set_reg(dev, "btc_params",
1098 (char *)®addr, (char *)&saved_reg41);
1100 dev_wlc_intvar_set_reg(dev, "btc_params",
1101 (char *)®addr, (char *)&saved_reg68);
1103 WL_TRACE_COEX(("restore regs {66,41,68} <- 0x%x 0x%x 0x%x\n",
1104 saved_reg66, saved_reg41, saved_reg68));
1106 saved_status = FALSE;
1110 WL_ERROR(("%s Unkwown yet power setting, ignored\n",
1114 p += snprintf(p, MAX_WX_STRING, "OK");
1116 wrqu->data.length = p - extra + 1;
1122 wl_iw_set_suspend_opt(
1123 struct net_device *dev,
1124 struct iw_request_info *info,
1125 union iwreq_data *wrqu,
1133 suspend_flag = *(extra + strlen(SETSUSPENDOPT_CMD) + 1) - '0';
1135 if (suspend_flag != 0)
1138 ret_now = net_os_set_suspend_disable(dev, suspend_flag);
1140 if (ret_now != suspend_flag) {
1141 if (!(ret = net_os_set_suspend(dev, ret_now, 1)))
1142 WL_ERROR(("%s: Suspend Flag %d -> %d\n",
1143 __FUNCTION__, ret_now, suspend_flag));
1145 WL_ERROR(("%s: failed %d\n", __FUNCTION__, ret));
1152 wl_iw_set_suspend_mode(
1153 struct net_device *dev,
1154 struct iw_request_info *info,
1155 union iwreq_data *wrqu,
1161 #if !defined(CONFIG_HAS_EARLYSUSPEND) || !defined(DHD_USE_EARLYSUSPEND)
1164 suspend_flag = *(extra + strlen(SETSUSPENDMODE_CMD) + 1) - '0';
1166 if (suspend_flag != 0)
1169 if (!(ret = net_os_set_suspend(dev, suspend_flag, 0)))
1170 WL_ERROR(("%s: Suspend Mode %d\n",__FUNCTION__,suspend_flag));
1172 WL_ERROR(("%s: failed %d\n", __FUNCTION__, ret));
1178 wl_format_ssid(char* ssid_buf, uint8* ssid, int ssid_len)
1183 if (ssid_len > 32) ssid_len = 32;
1185 for (i = 0; i < ssid_len; i++) {
1190 } else if (isprint((uchar)c)) {
1193 p += sprintf(p, "\\x%02X", c);
1198 return p - ssid_buf;
1202 wl_iw_get_link_speed(
1203 struct net_device *dev,
1204 struct iw_request_info *info,
1205 union iwreq_data *wrqu,
1211 static int link_speed;
1214 net_os_wake_lock(dev);
1215 if (g_onoff == G_WLAN_SET_ON) {
1216 error = dev_wlc_ioctl(dev, WLC_GET_RATE, &link_speed, sizeof(link_speed));
1217 link_speed *= 500000;
1220 p += snprintf(p, MAX_WX_STRING, "LinkSpeed %d", link_speed/1000000);
1222 wrqu->data.length = p - extra + 1;
1224 net_os_wake_unlock(dev);
1230 wl_iw_get_dtim_skip(
1231 struct net_device *dev,
1232 struct iw_request_info *info,
1233 union iwreq_data *wrqu,
1241 net_os_wake_lock(dev);
1242 if (g_onoff == G_WLAN_SET_ON) {
1244 memset(iovbuf, 0, sizeof(iovbuf));
1245 strcpy(iovbuf, "bcn_li_dtim");
1247 if ((error = dev_wlc_ioctl(dev, WLC_GET_VAR,
1248 &iovbuf, sizeof(iovbuf))) >= 0) {
1250 p += snprintf(p, MAX_WX_STRING, "Dtim_skip %d", iovbuf[0]);
1251 WL_TRACE(("%s: get dtim_skip = %d\n", __FUNCTION__, iovbuf[0]));
1252 wrqu->data.length = p - extra + 1;
1255 WL_ERROR(("%s: get dtim_skip failed code %d\n",
1256 __FUNCTION__, error));
1258 net_os_wake_unlock(dev);
1264 wl_iw_set_dtim_skip(
1265 struct net_device *dev,
1266 struct iw_request_info *info,
1267 union iwreq_data *wrqu,
1276 net_os_wake_lock(dev);
1277 if (g_onoff == G_WLAN_SET_ON) {
1279 bcn_li_dtim = htod32((uint)*(extra + strlen(DTIM_SKIP_SET_CMD) + 1) - '0');
1281 if ((bcn_li_dtim >= 0) || ((bcn_li_dtim <= 5))) {
1283 memset(iovbuf, 0, sizeof(iovbuf));
1284 bcm_mkiovar("bcn_li_dtim", (char *)&bcn_li_dtim,
1285 4, iovbuf, sizeof(iovbuf));
1287 if ((error = dev_wlc_ioctl(dev, WLC_SET_VAR,
1288 &iovbuf, sizeof(iovbuf))) >= 0) {
1289 p += snprintf(p, MAX_WX_STRING, "OK");
1292 net_os_set_dtim_skip(dev, bcn_li_dtim);
1294 WL_TRACE(("%s: set dtim_skip %d OK\n", __FUNCTION__,
1298 else WL_ERROR(("%s: set dtim_skip %d failed code %d\n",
1299 __FUNCTION__, bcn_li_dtim, error));
1301 else WL_ERROR(("%s Incorrect dtim_skip setting %d, ignored\n",
1302 __FUNCTION__, bcn_li_dtim));
1305 p += snprintf(p, MAX_WX_STRING, "FAIL");
1308 wrqu->data.length = p - extra + 1;
1309 net_os_wake_unlock(dev);
1316 struct net_device *dev,
1317 struct iw_request_info *info,
1318 union iwreq_data *wrqu,
1326 net_os_wake_lock(dev);
1328 if (g_onoff == G_WLAN_SET_ON) {
1329 error = dev_wlc_ioctl(dev, WLC_GET_BAND, &band, sizeof(band));
1331 p += snprintf(p, MAX_WX_STRING, "Band %d", band);
1333 wrqu->data.length = p - extra + 1;
1336 net_os_wake_unlock(dev);
1343 struct net_device *dev,
1344 struct iw_request_info *info,
1345 union iwreq_data *wrqu,
1353 net_os_wake_lock(dev);
1355 if (g_onoff == G_WLAN_SET_ON) {
1357 band = htod32((uint)*(extra + strlen(BAND_SET_CMD) + 1) - '0');
1359 if ((band == WLC_BAND_AUTO) || (band == WLC_BAND_5G) || (band == WLC_BAND_2G)) {
1361 if ((error = dev_wlc_ioctl(dev, WLC_SET_BAND,
1362 &band, sizeof(band))) >= 0) {
1363 p += snprintf(p, MAX_WX_STRING, "OK");
1364 WL_TRACE(("%s: set band %d OK\n", __FUNCTION__, band));
1367 WL_ERROR(("%s: set band %d failed code %d\n", __FUNCTION__,
1371 WL_ERROR(("%s Incorrect band setting %d, ignored\n", __FUNCTION__, band));
1375 p += snprintf(p, MAX_WX_STRING, "FAIL");
1378 wrqu->data.length = p - extra + 1;
1379 net_os_wake_unlock(dev);
1386 wl_iw_set_pno_reset(
1387 struct net_device *dev,
1388 struct iw_request_info *info,
1389 union iwreq_data *wrqu,
1396 net_os_wake_lock(dev);
1397 if ((g_onoff == G_WLAN_SET_ON) && (dev != NULL)) {
1399 if ((error = dhd_dev_pno_reset(dev)) >= 0) {
1400 p += snprintf(p, MAX_WX_STRING, "OK");
1401 WL_TRACE(("%s: set OK\n", __FUNCTION__));
1404 else WL_ERROR(("%s: failed code %d\n", __FUNCTION__, error));
1407 p += snprintf(p, MAX_WX_STRING, "FAIL");
1410 wrqu->data.length = p - extra + 1;
1411 net_os_wake_unlock(dev);
1418 wl_iw_set_pno_enable(
1419 struct net_device *dev,
1420 struct iw_request_info *info,
1421 union iwreq_data *wrqu,
1429 net_os_wake_lock(dev);
1430 pfn_enabled = htod32((uint)*(extra + strlen(PNOENABLE_SET_CMD) + 1) - '0');
1432 if ((g_onoff == G_WLAN_SET_ON) && (dev != NULL)) {
1434 if ((error = dhd_dev_pno_enable(dev, pfn_enabled)) >= 0) {
1435 p += snprintf(p, MAX_WX_STRING, "OK");
1436 WL_TRACE(("%s: set OK\n", __FUNCTION__));
1439 else WL_ERROR(("%s: failed code %d\n", __FUNCTION__, error));
1442 p += snprintf(p, MAX_WX_STRING, "FAIL");
1445 wrqu->data.length = p - extra + 1;
1446 net_os_wake_unlock(dev);
1454 struct net_device *dev,
1455 struct iw_request_info *info,
1456 union iwreq_data *wrqu,
1461 wlc_ssid_t ssids_local[MAX_PFN_LIST_COUNT];
1463 cmd_tlv_t *cmd_tlv_temp;
1468 int pno_freq_expo_max;
1469 #ifdef PNO_SET_DEBUG
1471 char pno_in_example[] = {
1472 'P', 'N', 'O', 'S', 'E', 'T', 'U', 'P', ' ',
1490 net_os_wake_lock(dev);
1491 WL_ERROR(("\n### %s: info->cmd:%x, info->flags:%x, u.data=0x%p, u.len=%d\n",
1492 __FUNCTION__, info->cmd, info->flags,
1493 wrqu->data.pointer, wrqu->data.length));
1495 if (g_onoff == G_WLAN_SET_OFF) {
1496 WL_TRACE(("%s: driver is not up yet after START\n", __FUNCTION__));
1500 if (wrqu->data.length < (strlen(PNOSETUP_SET_CMD) + sizeof(cmd_tlv_t))) {
1501 WL_ERROR(("%s argument=%d less %d\n", __FUNCTION__,
1502 wrqu->data.length, (int)(strlen(PNOSETUP_SET_CMD) + sizeof(cmd_tlv_t))));
1506 #ifdef PNO_SET_DEBUG
1507 if (!(extra = kmalloc(sizeof(pno_in_example) +100, GFP_KERNEL))) {
1511 memcpy(extra, pno_in_example, sizeof(pno_in_example));
1512 wrqu->data.length = sizeof(pno_in_example);
1513 for (i = 0; i < wrqu->data.length; i++)
1514 printf("%02X ", extra[i]);
1519 #ifdef PNO_SET_DEBUG
1520 str_ptr += strlen("PNOSETUP ");
1521 tlv_size_left = wrqu->data.length - strlen("PNOSETUP ");
1523 str_ptr += strlen(PNOSETUP_SET_CMD);
1524 tlv_size_left = wrqu->data.length - strlen(PNOSETUP_SET_CMD);
1527 cmd_tlv_temp = (cmd_tlv_t *)str_ptr;
1528 memset(ssids_local, 0, sizeof(ssids_local));
1529 pno_repeat = pno_freq_expo_max = 0;
1531 if ((cmd_tlv_temp->prefix == PNO_TLV_PREFIX) &&
1532 (cmd_tlv_temp->version == PNO_TLV_VERSION) &&
1533 (cmd_tlv_temp->subver == PNO_TLV_SUBVERSION))
1535 str_ptr += sizeof(cmd_tlv_t);
1536 tlv_size_left -= sizeof(cmd_tlv_t);
1539 if ((nssid = wl_iw_parse_ssid_list_tlv(&str_ptr, ssids_local,
1541 &tlv_size_left)) <= 0) {
1542 WL_ERROR(("SSID is not presented or corrupted ret=%d\n", nssid));
1546 if ((str_ptr[0] != PNO_TLV_TYPE_TIME) || (tlv_size_left <= 1)) {
1547 WL_ERROR(("%s scan duration corrupted field size %d\n",
1548 __FUNCTION__, tlv_size_left));
1552 pno_time = simple_strtoul(str_ptr, &str_ptr, 16);
1553 WL_PNO(("%s: pno_time=%d\n", __FUNCTION__, pno_time));
1556 if (str_ptr[0] != 0) {
1557 if ((str_ptr[0] != PNO_TLV_FREQ_REPEAT)) {
1558 WL_ERROR(("%s pno repeat : corrupted field\n",
1563 pno_repeat = simple_strtoul(str_ptr, &str_ptr, 16);
1564 WL_PNO(("%s :got pno_repeat=%d\n", __FUNCTION__, pno_repeat));
1565 if (str_ptr[0] != PNO_TLV_FREQ_EXPO_MAX) {
1566 WL_ERROR(("%s FREQ_EXPO_MAX corrupted field size\n",
1571 pno_freq_expo_max = simple_strtoul(str_ptr, &str_ptr, 16);
1572 WL_PNO(("%s: pno_freq_expo_max=%d\n",
1573 __FUNCTION__, pno_freq_expo_max));
1578 WL_ERROR(("%s get wrong TLV command\n", __FUNCTION__));
1583 res = dhd_dev_pno_set(dev, ssids_local, nssid, pno_time, pno_repeat, pno_freq_expo_max);
1586 net_os_wake_unlock(dev);
1591 wl_iw_set_pno_setadd(
1592 struct net_device *dev,
1593 struct iw_request_info *info,
1594 union iwreq_data *wrqu,
1602 net_os_wake_lock(dev);
1603 WL_ERROR(("\n### %s: info->cmd:%x, info->flags:%x, u.data=0x%p, u.len=%d\n",
1604 __FUNCTION__, info->cmd, info->flags,
1605 wrqu->data.pointer, wrqu->data.length));
1607 if (g_onoff == G_WLAN_SET_OFF) {
1608 WL_TRACE(("%s: driver is not up yet after START\n", __FUNCTION__));
1612 if (wrqu->data.length <= strlen(PNOSETADD_SET_CMD) + sizeof(cmd_tlv_t)) {
1613 WL_ERROR(("%s argument=%d less than %d\n", __FUNCTION__,
1614 wrqu->data.length, (int)(strlen(PNOSETADD_SET_CMD) + sizeof(cmd_tlv_t))));
1619 bcopy(PNOSETUP_SET_CMD, extra, strlen(PNOSETUP_SET_CMD));
1621 tmp_ptr = extra + strlen(PNOSETUP_SET_CMD);
1622 size = wrqu->data.length - strlen(PNOSETUP_SET_CMD);
1625 while (*tmp_ptr && tmp_size > 0) {
1626 if ((*tmp_ptr == 'S') && (size - tmp_size) >= sizeof(cmd_tlv_t)) {
1627 *(tmp_ptr + 1) = ((*(tmp_ptr + 1) - '0') << 4) + (*(tmp_ptr + 2) - '0');
1628 memmove(tmp_ptr + 2, tmp_ptr + 3, tmp_size - 3);
1629 tmp_size -= 2 + *(tmp_ptr + 1);
1630 tmp_ptr += 2 + *(tmp_ptr + 1);
1638 wrqu->data.length = strlen(PNOSETUP_SET_CMD) + size;
1639 ret = wl_iw_set_pno_set(dev, info, wrqu, extra);
1642 net_os_wake_unlock(dev);
1650 struct net_device *dev,
1651 struct iw_request_info *info,
1652 union iwreq_data *wrqu,
1656 static int rssi = 0;
1657 static wlc_ssid_t ssid = {0};
1660 static char ssidbuf[SSID_FMT_BUF_LEN];
1663 net_os_wake_lock(dev);
1665 bzero(&scb_val, sizeof(scb_val_t));
1667 if (g_onoff == G_WLAN_SET_ON) {
1668 error = dev_wlc_ioctl(dev, WLC_GET_RSSI, &scb_val, sizeof(scb_val_t));
1670 WL_ERROR(("%s: Fails %d\n", __FUNCTION__, error));
1671 net_os_wake_unlock(dev);
1674 rssi = dtoh32(scb_val.val);
1676 error = dev_wlc_ioctl(dev, WLC_GET_SSID, &ssid, sizeof(ssid));
1678 ssid.SSID_len = dtoh32(ssid.SSID_len);
1679 wl_format_ssid(ssidbuf, ssid.SSID, dtoh32(ssid.SSID_len));
1683 p += snprintf(p, MAX_WX_STRING, "%s rssi %d ", ssidbuf, rssi);
1684 wrqu->data.length = p - extra + 1;
1686 net_os_wake_unlock(dev);
1691 wl_iw_send_priv_event(
1692 struct net_device *dev,
1696 union iwreq_data wrqu;
1697 char extra[IW_CUSTOM_MAX + 1];
1701 memset(&wrqu, 0, sizeof(wrqu));
1702 if (strlen(flag) > sizeof(extra))
1705 strcpy(extra, flag);
1706 wrqu.data.length = strlen(extra);
1707 wireless_send_event(dev, cmd, &wrqu, extra);
1708 net_os_wake_lock_ctrl_timeout_enable(dev, DHD_EVENT_TIMEOUT_MS);
1709 WL_TRACE(("Send IWEVCUSTOM Event as %s\n", extra));
1716 wl_control_wl_start(struct net_device *dev)
1721 WL_TRACE(("Enter %s \n", __FUNCTION__));
1724 WL_ERROR(("%s: dev is null\n", __FUNCTION__));
1728 iw = *(wl_iw_t **)netdev_priv(dev);
1731 WL_ERROR(("%s: wl is null\n", __FUNCTION__));
1735 dhd_net_if_lock(dev);
1737 if (g_onoff == G_WLAN_SET_OFF) {
1738 dhd_customer_gpio_wlan_ctrl(WLAN_RESET_ON);
1740 #if defined(BCMLXSDMMC)
1741 sdioh_start(NULL, 0);
1744 ret = dhd_dev_reset(dev, 0);
1746 #if defined(BCMLXSDMMC)
1747 sdioh_start(NULL, 1);
1750 dhd_dev_init_ioctl(dev);
1752 g_onoff = G_WLAN_SET_ON;
1754 WL_TRACE(("Exited %s\n", __FUNCTION__));
1756 dhd_net_if_unlock(dev);
1762 wl_iw_control_wl_off(
1763 struct net_device *dev,
1764 struct iw_request_info *info
1770 WL_TRACE(("Enter %s\n", __FUNCTION__));
1773 WL_ERROR(("%s: dev is null\n", __FUNCTION__));
1777 iw = *(wl_iw_t **)netdev_priv(dev);
1780 WL_ERROR(("%s: wl is null\n", __FUNCTION__));
1784 dhd_net_if_lock(dev);
1787 ap_cfg_running = FALSE;
1790 if (g_onoff == G_WLAN_SET_ON) {
1791 g_onoff = G_WLAN_SET_OFF;
1793 #if defined(WL_IW_USE_ISCAN)
1794 g_iscan->iscan_state = ISCAN_STATE_IDLE;
1797 ret = dhd_dev_reset(dev, 1);
1799 #if defined(WL_IW_USE_ISCAN)
1802 wl_iw_free_ss_cache();
1803 wl_iw_run_ss_cache_timer(0);
1805 g_ss_cache_ctrl.m_link_down = 1;
1807 memset(g_scan, 0, G_SCAN_RESULTS);
1808 g_scan_specified_ssid = 0;
1809 #if defined(CONFIG_FIRST_SCAN)
1811 g_first_broadcast_scan = BROADCAST_SCAN_FIRST_IDLE;
1812 g_first_counter_scans = 0;
1816 #if defined(BCMLXSDMMC)
1820 dhd_customer_gpio_wlan_ctrl(WLAN_RESET_OFF);
1822 wl_iw_send_priv_event(dev, "STOP");
1825 dhd_net_if_unlock(dev);
1827 WL_TRACE(("Exited %s\n", __FUNCTION__));
1833 wl_iw_control_wl_on(
1834 struct net_device *dev,
1835 struct iw_request_info *info
1840 WL_TRACE(("Enter %s \n", __FUNCTION__));
1842 ret = wl_control_wl_start(dev);
1844 wl_iw_send_priv_event(dev, "START");
1847 if (!ap_fw_loaded) {
1848 wl_iw_iscan_set_scan_broadcast_prep(dev, 0);
1851 wl_iw_iscan_set_scan_broadcast_prep(dev, 0);
1854 WL_TRACE(("Exited %s\n", __FUNCTION__));
1860 static struct ap_profile my_ap;
1861 static int set_ap_cfg(struct net_device *dev, struct ap_profile *ap);
1862 static int get_assoc_sta_list(struct net_device *dev, char *buf, int len);
1863 static int set_ap_mac_list(struct net_device *dev, void *buf);
1865 #define PTYPE_STRING 0
1866 #define PTYPE_INTDEC 1
1867 #define PTYPE_INTHEX 2
1868 #define PTYPE_STR_HEX 3
1870 static int get_parameter_from_string(
1871 char **str_ptr, const char *token, int param_type, void *dst, int param_max_len);
1876 if (c >= '0' && c <= '9')
1878 if (c >= 'a' && c <= 'f')
1879 return c - 'a' + 10;
1880 if (c >= 'A' && c <= 'F')
1881 return c - 'A' + 10;
1888 hstr_2_buf(const char *txt, u8 *buf, int len)
1892 for (i = 0; i < len; i++) {
1895 a = hex2num(*txt++);
1898 b = hex2num(*txt++);
1901 *buf++ = (a << 4) | b;
1910 init_ap_profile_from_string(char *param_str, struct ap_profile *ap_cfg)
1912 char *str_ptr = param_str;
1916 memset(sub_cmd, 0, sizeof(sub_cmd));
1917 memset(ap_cfg, 0, sizeof(struct ap_profile));
1920 if (get_parameter_from_string(&str_ptr, "ASCII_CMD=",
1921 PTYPE_STRING, sub_cmd, SSID_LEN) != 0) {
1924 if (strncmp(sub_cmd, "AP_CFG", 6)) {
1925 WL_ERROR(("ERROR: sub_cmd:%s != 'AP_CFG'!\n", sub_cmd));
1931 ret = get_parameter_from_string(&str_ptr, "SSID=", PTYPE_STRING, ap_cfg->ssid, SSID_LEN);
1933 ret |= get_parameter_from_string(&str_ptr, "SEC=", PTYPE_STRING, ap_cfg->sec, SEC_LEN);
1935 ret |= get_parameter_from_string(&str_ptr, "KEY=", PTYPE_STRING, ap_cfg->key, KEY_LEN);
1937 ret |= get_parameter_from_string(&str_ptr, "CHANNEL=", PTYPE_INTDEC, &ap_cfg->channel, 5);
1940 get_parameter_from_string(&str_ptr, "PREAMBLE=", PTYPE_INTDEC, &ap_cfg->preamble, 5);
1943 get_parameter_from_string(&str_ptr, "MAX_SCB=", PTYPE_INTDEC, &ap_cfg->max_scb, 5);
1946 get_parameter_from_string(&str_ptr, "HIDDEN=",
1947 PTYPE_INTDEC, &ap_cfg->closednet, 5);
1950 get_parameter_from_string(&str_ptr, "COUNTRY=",
1951 PTYPE_STRING, &ap_cfg->country_code, 3);
1961 iwpriv_set_ap_config(struct net_device *dev,
1962 struct iw_request_info *info,
1963 union iwreq_data *wrqu,
1968 struct ap_profile *ap_cfg = &my_ap;
1970 WL_TRACE(("> Got IWPRIV SET_AP IOCTL: info->cmd:%x, info->flags:%x, u.data:%p, u.len:%d\n",
1971 info->cmd, info->flags,
1972 wrqu->data.pointer, wrqu->data.length));
1974 if (!ap_fw_loaded) {
1975 WL_ERROR(("Can't execute %s(), SOFTAP fw is not Loaded\n",
1980 if (wrqu->data.length != 0) {
1984 if (!(extra = kmalloc(wrqu->data.length+1, GFP_KERNEL)))
1987 if (copy_from_user(extra, wrqu->data.pointer, wrqu->data.length)) {
1992 extra[wrqu->data.length] = 0;
1993 WL_SOFTAP((" Got str param in iw_point:\n %s\n", extra));
1995 memset(ap_cfg, 0, sizeof(struct ap_profile));
2001 if ((res = init_ap_profile_from_string(extra, ap_cfg)) < 0) {
2002 WL_ERROR(("%s failed to parse %d\n", __FUNCTION__, res));
2009 WL_ERROR(("IWPRIV argument len = 0 \n"));
2013 if ((res = set_ap_cfg(dev, ap_cfg)) < 0)
2014 WL_ERROR(("%s failed to set_ap_cfg %d\n", __FUNCTION__, res));
2025 static int iwpriv_get_assoc_list(struct net_device *dev,
2026 struct iw_request_info *info,
2027 union iwreq_data *p_iwrq,
2032 struct maclist *sta_maclist = (struct maclist *)mac_buf;
2036 char *p_mac_str_end;
2039 if ((!dev) || (!extra)) {
2045 iw = *(wl_iw_t **)netdev_priv(dev);
2047 net_os_wake_lock(dev);
2048 DHD_OS_MUTEX_LOCK(&wl_softap_lock);
2050 WL_TRACE(("\n %s: IWPRIV IOCTL: cmd:%hx, flags:%hx, extra:%p, iwp.len:%d,"
2051 "iwp.len:%p, iwp.flags:%x \n", __FUNCTION__, info->cmd, info->flags,
2052 extra, p_iwrq->data.length, p_iwrq->data.pointer, p_iwrq->data.flags));
2055 memset(sta_maclist, 0, sizeof(mac_buf));
2057 sta_maclist->count = 8;
2059 WL_SOFTAP(("%s: net device:%s, buf_sz:%d\n",
2060 __FUNCTION__, dev->name, sizeof(mac_buf)));
2062 if ((ret = get_assoc_sta_list(dev, mac_buf, sizeof(mac_buf))) < 0) {
2063 WL_ERROR(("%s: sta list ioctl error:%d\n",
2064 __FUNCTION__, ret));
2068 WL_SOFTAP(("%s: got %d stations\n", __FUNCTION__,
2069 sta_maclist->count));
2073 memset(mac_lst, 0, sizeof(mac_lst));
2074 p_mac_str = mac_lst;
2075 p_mac_str_end = &mac_lst[sizeof(mac_lst)-1];
2077 for (i = 0; i < 8; i++) {
2078 struct ether_addr * id = &sta_maclist->ea[i];
2079 if (!ETHER_ISNULLADDR(id->octet)) {
2082 bzero(&scb_val, sizeof(scb_val_t));
2085 if ((p_mac_str_end - p_mac_str) <= 36) {
2086 WL_ERROR(("%s: mac list buf is < 36 for item[%i] item\n",
2091 p_mac_str += snprintf(p_mac_str, MAX_WX_STRING,
2092 "\nMac[%d]=%02X:%02X:%02X:%02X:%02X:%02X,", i,
2093 id->octet[0], id->octet[1], id->octet[2],
2094 id->octet[3], id->octet[4], id->octet[5]);
2097 bcopy(id->octet, &scb_val.ea, 6);
2098 ret = dev_wlc_ioctl(dev, WLC_GET_RSSI, &scb_val, sizeof(scb_val_t));
2100 snprintf(p_mac_str, MAX_WX_STRING, "RSSI:ERR");
2101 WL_ERROR(("%s: RSSI ioctl error:%d\n",
2102 __FUNCTION__, ret));
2106 rssi = dtoh32(scb_val.val);
2107 p_mac_str += snprintf(p_mac_str, MAX_WX_STRING,
2112 p_iwrq->data.length = strlen(mac_lst)+1;
2114 WL_SOFTAP(("%s: data to user:\n%s\n usr_ptr:%p\n", __FUNCTION__,
2115 mac_lst, p_iwrq->data.pointer));
2117 if (p_iwrq->data.length) {
2118 bcopy(mac_lst, extra, p_iwrq->data.length);
2123 DHD_OS_MUTEX_UNLOCK(&wl_softap_lock);
2124 net_os_wake_unlock(dev);
2126 WL_SOFTAP(("%s: Exited\n", __FUNCTION__));
2134 #define MAC_FILT_MAX 8
2135 static int iwpriv_set_mac_filters(struct net_device *dev,
2136 struct iw_request_info *info,
2137 union iwreq_data *wrqu,
2141 char * extra = NULL;
2144 struct ether_addr *p_ea;
2145 struct mac_list_set mflist_set;
2147 WL_SOFTAP((">>> Got IWPRIV SET_MAC_FILTER IOCTL: info->cmd:%x,"
2148 "info->flags:%x, u.data:%p, u.len:%d\n",
2149 info->cmd, info->flags,
2150 wrqu->data.pointer, wrqu->data.length));
2152 if (wrqu->data.length != 0) {
2156 if (!(extra = kmalloc(wrqu->data.length+1, GFP_KERNEL)))
2159 if (copy_from_user(extra, wrqu->data.pointer, wrqu->data.length)) {
2164 extra[wrqu->data.length] = 0;
2165 WL_SOFTAP((" Got parameter string in iw_point:\n %s \n", extra));
2167 memset(&mflist_set, 0, sizeof(mflist_set));
2174 if (get_parameter_from_string(&str_ptr, "MAC_MODE=",
2175 PTYPE_INTDEC, &mac_mode, 4) != 0) {
2176 WL_ERROR(("ERROR: 'MAC_MODE=' token is missing\n"));
2180 p_ea = &mflist_set.mac_list.ea[0];
2182 if (get_parameter_from_string(&str_ptr, "MAC_CNT=",
2183 PTYPE_INTDEC, &mac_cnt, 4) != 0) {
2184 WL_ERROR(("ERROR: 'MAC_CNT=' token param is missing \n"));
2188 if (mac_cnt > MAC_FILT_MAX) {
2189 WL_ERROR(("ERROR: number of MAC filters > MAX\n"));
2193 for (i=0; i< mac_cnt; i++)
2194 if (get_parameter_from_string(&str_ptr, "MAC=",
2195 PTYPE_STR_HEX, &p_ea[i], 12) != 0) {
2196 WL_ERROR(("ERROR: MAC_filter[%d] is missing !\n", i));
2200 WL_SOFTAP(("MAC_MODE=:%d, MAC_CNT=%d, MACs:..\n", mac_mode, mac_cnt));
2201 for (i = 0; i < mac_cnt; i++) {
2202 WL_SOFTAP(("mac_filt[%d]:", i));
2203 dhd_print_buf(&p_ea[i], 6, 0);
2207 mflist_set.mode = mac_mode;
2208 mflist_set.mac_list.count = mac_cnt;
2209 set_ap_mac_list(dev, &mflist_set);
2212 wrqu->data.pointer = NULL;
2213 wrqu->data.length = 0;
2218 WL_ERROR(("IWPRIV argument len is 0\n"));
2231 static int iwpriv_set_ap_sta_disassoc(struct net_device *dev,
2232 struct iw_request_info *info,
2233 union iwreq_data *wrqu,
2237 char sta_mac[6] = {0, 0, 0, 0, 0, 0};
2239 char *str_ptr = cmd_buf;
2241 WL_SOFTAP((">>%s called\n args: info->cmd:%x,"
2242 " info->flags:%x, u.data.p:%p, u.data.len:%d\n",
2243 __FUNCTION__, info->cmd, info->flags,
2244 wrqu->data.pointer, wrqu->data.length));
2246 if (wrqu->data.length != 0) {
2248 if (copy_from_user(cmd_buf, wrqu->data.pointer, wrqu->data.length)) {
2252 if (get_parameter_from_string(&str_ptr,
2253 "MAC=", PTYPE_STR_HEX, sta_mac, 12) == 0) {
2254 res = wl_iw_softap_deassoc_stations(dev, sta_mac);
2256 WL_ERROR(("ERROR: STA_MAC= token not found\n"));
2266 #if WIRELESS_EXT < 13
2267 struct iw_request_info
2273 typedef int (*iw_handler)(struct net_device *dev,
2274 struct iw_request_info *info,
2280 wl_iw_config_commit(
2281 struct net_device *dev,
2282 struct iw_request_info *info,
2289 struct sockaddr bssid;
2291 WL_TRACE(("%s: SIOCSIWCOMMIT\n", dev->name));
2293 if ((error = dev_wlc_ioctl(dev, WLC_GET_SSID, &ssid, sizeof(ssid))))
2296 ssid.SSID_len = dtoh32(ssid.SSID_len);
2301 bzero(&bssid, sizeof(struct sockaddr));
2302 if ((error = dev_wlc_ioctl(dev, WLC_REASSOC, &bssid, ETHER_ADDR_LEN))) {
2303 WL_ERROR(("%s: WLC_REASSOC to %s failed \n", __FUNCTION__, ssid.SSID));
2312 struct net_device *dev,
2313 struct iw_request_info *info,
2318 WL_TRACE(("%s: SIOCGIWNAME\n", dev->name));
2320 strcpy(cwrq, "IEEE 802.11-DS");
2327 struct net_device *dev,
2328 struct iw_request_info *info,
2329 struct iw_freq *fwrq,
2336 WL_TRACE(("%s %s: SIOCSIWFREQ\n", __FUNCTION__, dev->name));
2339 if (ap_cfg_running) {
2340 WL_TRACE(("%s:>> not executed, 'SOFT_AP is active' \n", __FUNCTION__));
2346 if (fwrq->e == 0 && fwrq->m < MAXCHANNEL) {
2356 } else if (fwrq->e < 6) {
2357 while (fwrq->e++ < 6)
2361 if (fwrq->m > 4000 && fwrq->m < 5000)
2362 sf = WF_CHAN_FACTOR_4_G;
2364 chan = wf_mhz2channel(fwrq->m, sf);
2367 chan = htod32(chan);
2369 if ((error = dev_wlc_ioctl(dev, WLC_SET_CHANNEL, &chan, sizeof(chan))))
2372 g_wl_iw_params.target_channel = chan;
2375 return -EINPROGRESS;
2380 struct net_device *dev,
2381 struct iw_request_info *info,
2382 struct iw_freq *fwrq,
2389 WL_TRACE(("%s: SIOCGIWFREQ\n", dev->name));
2391 if ((error = dev_wlc_ioctl(dev, WLC_GET_CHANNEL, &ci, sizeof(ci))))
2395 fwrq->m = dtoh32(ci.hw_channel);
2396 fwrq->e = dtoh32(0);
2402 struct net_device *dev,
2403 struct iw_request_info *info,
2408 int infra = 0, ap = 0, error = 0;
2410 WL_TRACE(("%s: SIOCSIWMODE\n", dev->name));
2413 case IW_MODE_MASTER:
2425 infra = htod32(infra);
2428 if ((error = dev_wlc_ioctl(dev, WLC_SET_INFRA, &infra, sizeof(infra))) ||
2429 (error = dev_wlc_ioctl(dev, WLC_SET_AP, &ap, sizeof(ap))))
2433 return -EINPROGRESS;
2438 struct net_device *dev,
2439 struct iw_request_info *info,
2444 int error, infra = 0, ap = 0;
2446 WL_TRACE(("%s: SIOCGIWMODE\n", dev->name));
2448 if ((error = dev_wlc_ioctl(dev, WLC_GET_INFRA, &infra, sizeof(infra))) ||
2449 (error = dev_wlc_ioctl(dev, WLC_GET_AP, &ap, sizeof(ap))))
2452 infra = dtoh32(infra);
2454 *uwrq = infra ? ap ? IW_MODE_MASTER : IW_MODE_INFRA : IW_MODE_ADHOC;
2461 struct net_device *dev,
2462 struct iw_request_info *info,
2463 struct iw_point *dwrq,
2467 struct iw_range *range = (struct iw_range *) extra;
2468 wl_uint32_list_t *list;
2469 wl_rateset_t rateset;
2475 int bw_cap = 0, sgi_tx = 0, nmode = 0;
2477 uint8 nrate_list2copy = 0;
2478 uint16 nrate_list[4][8] = { {13, 26, 39, 52, 78, 104, 117, 130},
2479 {14, 29, 43, 58, 87, 116, 130, 144},
2480 {27, 54, 81, 108, 162, 216, 243, 270},
2481 {30, 60, 90, 120, 180, 240, 270, 300}};
2483 WL_TRACE(("%s: SIOCGIWRANGE\n", dev->name));
2488 channels = kmalloc((MAXCHANNEL+1)*4, GFP_KERNEL);
2490 WL_ERROR(("Could not alloc channels\n"));
2493 list = (wl_uint32_list_t *)channels;
2495 dwrq->length = sizeof(struct iw_range);
2496 memset(range, 0, sizeof(*range));
2499 range->min_nwid = range->max_nwid = 0;
2502 list->count = htod32(MAXCHANNEL);
2503 if ((error = dev_wlc_ioctl(dev, WLC_GET_VALID_CHANNELS, channels, (MAXCHANNEL+1)*4))) {
2507 for (i = 0; i < dtoh32(list->count) && i < IW_MAX_FREQUENCIES; i++) {
2508 range->freq[i].i = dtoh32(list->element[i]);
2510 ch = dtoh32(list->element[i]);
2511 if (ch <= CH_MAX_2G_CHANNEL)
2512 sf = WF_CHAN_FACTOR_2_4_G;
2514 sf = WF_CHAN_FACTOR_5_G;
2516 range->freq[i].m = wf_channel2mhz(ch, sf);
2517 range->freq[i].e = 6;
2519 range->num_frequency = range->num_channels = i;
2522 range->max_qual.qual = 5;
2524 range->max_qual.level = 0x100 - 200;
2526 range->max_qual.noise = 0x100 - 200;
2528 range->sensitivity = 65535;
2530 #if WIRELESS_EXT > 11
2532 range->avg_qual.qual = 3;
2534 range->avg_qual.level = 0x100 + WL_IW_RSSI_GOOD;
2536 range->avg_qual.noise = 0x100 - 75;
2540 if ((error = dev_wlc_ioctl(dev, WLC_GET_CURR_RATESET, &rateset, sizeof(rateset)))) {
2544 rateset.count = dtoh32(rateset.count);
2545 range->num_bitrates = rateset.count;
2546 for (i = 0; i < rateset.count && i < IW_MAX_BITRATES; i++)
2547 range->bitrate[i] = (rateset.rates[i]& 0x7f) * 500000;
2548 dev_wlc_intvar_get(dev, "nmode", &nmode);
2549 dev_wlc_ioctl(dev, WLC_GET_PHYTYPE, &phytype, sizeof(phytype));
2551 if (nmode == 1 && phytype == WLC_PHY_TYPE_SSN) {
2552 dev_wlc_intvar_get(dev, "mimo_bw_cap", &bw_cap);
2553 dev_wlc_intvar_get(dev, "sgi_tx", &sgi_tx);
2554 dev_wlc_ioctl(dev, WLC_GET_CHANNEL, &ci, sizeof(channel_info_t));
2555 ci.hw_channel = dtoh32(ci.hw_channel);
2558 (bw_cap == 2 && ci.hw_channel <= 14)) {
2560 nrate_list2copy = 0;
2562 nrate_list2copy = 1;
2565 (bw_cap == 2 && ci.hw_channel >= 36)) {
2567 nrate_list2copy = 2;
2569 nrate_list2copy = 3;
2571 range->num_bitrates += 8;
2572 for (k = 0; i < range->num_bitrates; k++, i++) {
2574 range->bitrate[i] = (nrate_list[nrate_list2copy][k]) * 500000;
2579 if ((error = dev_wlc_ioctl(dev, WLC_GET_PHYTYPE, &i, sizeof(i)))) {
2584 if (i == WLC_PHY_TYPE_A)
2585 range->throughput = 24000000;
2587 range->throughput = 1500000;
2591 range->max_rts = 2347;
2592 range->min_frag = 256;
2593 range->max_frag = 2346;
2595 range->max_encoding_tokens = DOT11_MAX_DEFAULT_KEYS;
2596 range->num_encoding_sizes = 4;
2597 range->encoding_size[0] = WEP1_KEY_SIZE;
2598 range->encoding_size[1] = WEP128_KEY_SIZE;
2599 #if WIRELESS_EXT > 17
2600 range->encoding_size[2] = TKIP_KEY_SIZE;
2602 range->encoding_size[2] = 0;
2604 range->encoding_size[3] = AES_KEY_SIZE;
2611 range->pmp_flags = 0;
2615 range->num_txpower = 2;
2616 range->txpower[0] = 1;
2617 range->txpower[1] = 255;
2618 range->txpower_capa = IW_TXPOW_MWATT;
2620 #if WIRELESS_EXT > 10
2621 range->we_version_compiled = WIRELESS_EXT;
2622 range->we_version_source = 19;
2625 range->retry_capa = IW_RETRY_LIMIT;
2626 range->retry_flags = IW_RETRY_LIMIT;
2627 range->r_time_flags = 0;
2629 range->min_retry = 1;
2630 range->max_retry = 255;
2632 range->min_r_time = 0;
2633 range->max_r_time = 0;
2636 #if WIRELESS_EXT > 17
2637 range->enc_capa = IW_ENC_CAPA_WPA;
2638 range->enc_capa |= IW_ENC_CAPA_CIPHER_TKIP;
2639 range->enc_capa |= IW_ENC_CAPA_CIPHER_CCMP;
2640 range->enc_capa |= IW_ENC_CAPA_WPA2;
2643 IW_EVENT_CAPA_SET_KERNEL(range->event_capa);
2645 IW_EVENT_CAPA_SET(range->event_capa, SIOCGIWAP);
2646 IW_EVENT_CAPA_SET(range->event_capa, SIOCGIWSCAN);
2647 IW_EVENT_CAPA_SET(range->event_capa, IWEVTXDROP);
2648 IW_EVENT_CAPA_SET(range->event_capa, IWEVMICHAELMICFAILURE);
2649 IW_EVENT_CAPA_SET(range->event_capa, IWEVASSOCREQIE);
2650 IW_EVENT_CAPA_SET(range->event_capa, IWEVASSOCRESPIE);
2651 IW_EVENT_CAPA_SET(range->event_capa, IWEVPMKIDCAND);
2660 rssi_to_qual(int rssi)
2662 if (rssi <= WL_IW_RSSI_NO_SIGNAL)
2664 else if (rssi <= WL_IW_RSSI_VERY_LOW)
2666 else if (rssi <= WL_IW_RSSI_LOW)
2668 else if (rssi <= WL_IW_RSSI_GOOD)
2670 else if (rssi <= WL_IW_RSSI_VERY_GOOD)
2678 struct net_device *dev,
2679 struct iw_request_info *info,
2680 struct iw_point *dwrq,
2684 wl_iw_t *iw = NETDEV_PRIV(dev);
2685 struct sockaddr *addr = (struct sockaddr *) extra;
2688 WL_TRACE(("%s: SIOCSIWSPY\n", dev->name));
2693 iw->spy_num = MIN(ARRAYSIZE(iw->spy_addr), dwrq->length);
2694 for (i = 0; i < iw->spy_num; i++)
2695 memcpy(&iw->spy_addr[i], addr[i].sa_data, ETHER_ADDR_LEN);
2696 memset(iw->spy_qual, 0, sizeof(iw->spy_qual));
2703 struct net_device *dev,
2704 struct iw_request_info *info,
2705 struct iw_point *dwrq,
2709 wl_iw_t *iw = NETDEV_PRIV(dev);
2710 struct sockaddr *addr = (struct sockaddr *) extra;
2711 struct iw_quality *qual = (struct iw_quality *) &addr[iw->spy_num];
2714 WL_TRACE(("%s: SIOCGIWSPY\n", dev->name));
2719 dwrq->length = iw->spy_num;
2720 for (i = 0; i < iw->spy_num; i++) {
2721 memcpy(addr[i].sa_data, &iw->spy_addr[i], ETHER_ADDR_LEN);
2722 addr[i].sa_family = AF_UNIX;
2723 memcpy(&qual[i], &iw->spy_qual[i], sizeof(struct iw_quality));
2724 iw->spy_qual[i].updated = 0;
2732 wl_iw_ch_to_chanspec(int ch, wl_join_params_t *join_params, int *join_params_size)
2734 chanspec_t chanspec = 0;
2738 join_params->params.chanspec_num = 1;
2739 join_params->params.chanspec_list[0] = ch;
2741 if (join_params->params.chanspec_list[0])
2742 chanspec |= WL_CHANSPEC_BAND_2G;
2744 chanspec |= WL_CHANSPEC_BAND_5G;
2746 chanspec |= WL_CHANSPEC_BW_20;
2747 chanspec |= WL_CHANSPEC_CTL_SB_NONE;
2750 *join_params_size += WL_ASSOC_PARAMS_FIXED_SIZE +
2751 join_params->params.chanspec_num * sizeof(chanspec_t);
2754 join_params->params.chanspec_list[0] &= WL_CHANSPEC_CHAN_MASK;
2755 join_params->params.chanspec_list[0] |= chanspec;
2756 join_params->params.chanspec_list[0] =
2757 htodchanspec(join_params->params.chanspec_list[0]);
2759 join_params->params.chanspec_num = htod32(join_params->params.chanspec_num);
2761 WL_TRACE(("%s join_params->params.chanspec_list[0]= %X\n",
2762 __FUNCTION__, join_params->params.chanspec_list[0]));
2769 struct net_device *dev,
2770 struct iw_request_info *info,
2771 struct sockaddr *awrq,
2775 int error = -EINVAL;
2776 wl_join_params_t join_params;
2777 int join_params_size;
2779 WL_TRACE(("%s: SIOCSIWAP\n", dev->name));
2781 if (awrq->sa_family != ARPHRD_ETHER) {
2782 WL_ERROR(("Invalid Header...sa_family\n"));
2787 if (ETHER_ISBCAST(awrq->sa_data) || ETHER_ISNULLADDR(awrq->sa_data)) {
2790 bzero(&scbval, sizeof(scb_val_t));
2792 (void) dev_wlc_ioctl(dev, WLC_DISASSOC, &scbval, sizeof(scb_val_t));
2798 memset(&join_params, 0, sizeof(join_params));
2799 join_params_size = sizeof(join_params.ssid);
2801 memcpy(join_params.ssid.SSID, g_ssid.SSID, g_ssid.SSID_len);
2802 join_params.ssid.SSID_len = htod32(g_ssid.SSID_len);
2803 memcpy(&join_params.params.bssid, awrq->sa_data, ETHER_ADDR_LEN);
2807 WL_TRACE(("%s target_channel=%d\n", __FUNCTION__, g_wl_iw_params.target_channel));
2808 wl_iw_ch_to_chanspec(g_wl_iw_params.target_channel, &join_params, &join_params_size);
2810 if ((error = dev_wlc_ioctl(dev, WLC_SET_SSID, &join_params, join_params_size))) {
2811 WL_ERROR(("%s Invalid ioctl data=%d\n", __FUNCTION__, error));
2815 if (g_ssid.SSID_len) {
2816 WL_TRACE(("%s: join SSID=%s BSSID="MACSTR" ch=%d\n", __FUNCTION__,
2817 g_ssid.SSID, MAC2STR((u8 *)awrq->sa_data),
2818 g_wl_iw_params.target_channel));
2822 memset(&g_ssid, 0, sizeof(g_ssid));
2828 struct net_device *dev,
2829 struct iw_request_info *info,
2830 struct sockaddr *awrq,
2834 WL_TRACE(("%s: SIOCGIWAP\n", dev->name));
2836 awrq->sa_family = ARPHRD_ETHER;
2837 memset(awrq->sa_data, 0, ETHER_ADDR_LEN);
2840 (void) dev_wlc_ioctl(dev, WLC_GET_BSSID, awrq->sa_data, ETHER_ADDR_LEN);
2845 #if WIRELESS_EXT > 17
2848 struct net_device *dev,
2849 struct iw_request_info *info,
2850 struct sockaddr *awrq,
2854 struct iw_mlme *mlme;
2856 int error = -EINVAL;
2858 WL_TRACE(("%s: SIOCSIWMLME DISASSOC/DEAUTH\n", dev->name));
2860 mlme = (struct iw_mlme *)extra;
2862 WL_ERROR(("Invalid ioctl data.\n"));
2866 scbval.val = mlme->reason_code;
2867 bcopy(&mlme->addr.sa_data, &scbval.ea, ETHER_ADDR_LEN);
2869 if (mlme->cmd == IW_MLME_DISASSOC) {
2870 scbval.val = htod32(scbval.val);
2871 error = dev_wlc_ioctl(dev, WLC_DISASSOC, &scbval, sizeof(scb_val_t));
2873 else if (mlme->cmd == IW_MLME_DEAUTH) {
2874 scbval.val = htod32(scbval.val);
2875 error = dev_wlc_ioctl(dev, WLC_SCB_DEAUTHENTICATE_FOR_REASON, &scbval,
2879 WL_ERROR(("Invalid ioctl data.\n"));
2887 #ifndef WL_IW_USE_ISCAN
2890 struct net_device *dev,
2891 struct iw_request_info *info,
2892 struct iw_point *dwrq,
2896 wl_scan_results_t *list;
2897 struct sockaddr *addr = (struct sockaddr *) extra;
2898 struct iw_quality qual[IW_MAX_AP];
2899 wl_bss_info_t *bi = NULL;
2901 uint buflen = dwrq->length;
2903 WL_TRACE(("%s: SIOCGIWAPLIST\n", dev->name));
2909 list = kmalloc(buflen, GFP_KERNEL);
2912 memset(list, 0, buflen);
2913 list->buflen = htod32(buflen);
2914 if ((error = dev_wlc_ioctl(dev, WLC_SCAN_RESULTS, list, buflen))) {
2915 WL_ERROR(("%d: Scan results error %d\n", __LINE__, error));
2919 list->buflen = dtoh32(list->buflen);
2920 list->version = dtoh32(list->version);
2921 list->count = dtoh32(list->count);
2922 if (list->version != WL_BSS_INFO_VERSION) {
2923 WL_ERROR(("%s : list->version %d != WL_BSS_INFO_VERSION\n",
2924 __FUNCTION__, list->version));
2929 for (i = 0, dwrq->length = 0; i < list->count && dwrq->length < IW_MAX_AP; i++) {
2930 bi = bi ? (wl_bss_info_t *)((uintptr)bi + dtoh32(bi->length)) : list->bss_info;
2931 ASSERT(((uintptr)bi + dtoh32(bi->length)) <= ((uintptr)list +
2935 if (!(dtoh16(bi->capability) & DOT11_CAP_ESS))
2939 memcpy(addr[dwrq->length].sa_data, &bi->BSSID, ETHER_ADDR_LEN);
2940 addr[dwrq->length].sa_family = ARPHRD_ETHER;
2941 qual[dwrq->length].qual = rssi_to_qual(dtoh16(bi->RSSI));
2942 qual[dwrq->length].level = 0x100 + dtoh16(bi->RSSI);
2943 qual[dwrq->length].noise = 0x100 + bi->phy_noise;
2946 #if WIRELESS_EXT > 18
2947 qual[dwrq->length].updated = IW_QUAL_ALL_UPDATED | IW_QUAL_DBM;
2949 qual[dwrq->length].updated = 7;
2958 memcpy(&addr[dwrq->length], qual, sizeof(struct iw_quality) * dwrq->length);
2967 #ifdef WL_IW_USE_ISCAN
2969 wl_iw_iscan_get_aplist(
2970 struct net_device *dev,
2971 struct iw_request_info *info,
2972 struct iw_point *dwrq,
2976 wl_scan_results_t *list;
2978 iscan_info_t *iscan = g_iscan;
2980 struct sockaddr *addr = (struct sockaddr *) extra;
2981 struct iw_quality qual[IW_MAX_AP];
2982 wl_bss_info_t *bi = NULL;
2985 WL_TRACE(("%s: SIOCGIWAPLIST\n", dev->name));
2990 if ((!iscan) || (iscan->tsk_ctl.thr_pid < 0)) {
2991 WL_ERROR(("%s error\n", __FUNCTION__));
2995 buf = iscan->list_hdr;
2998 list = &((wl_iscan_results_t*)buf->iscan_buf)->results;
2999 if (list->version != WL_BSS_INFO_VERSION) {
3000 WL_ERROR(("%s : list->version %d != WL_BSS_INFO_VERSION\n",
3001 __FUNCTION__, list->version));
3006 for (i = 0, dwrq->length = 0; i < list->count && dwrq->length < IW_MAX_AP; i++) {
3007 bi = bi ? (wl_bss_info_t *)((uintptr)bi + dtoh32(bi->length))
3009 ASSERT(((uintptr)bi + dtoh32(bi->length)) <= ((uintptr)list +
3010 WLC_IW_ISCAN_MAXLEN));
3013 if (!(dtoh16(bi->capability) & DOT11_CAP_ESS))
3017 memcpy(addr[dwrq->length].sa_data, &bi->BSSID, ETHER_ADDR_LEN);
3018 addr[dwrq->length].sa_family = ARPHRD_ETHER;
3019 qual[dwrq->length].qual = rssi_to_qual(dtoh16(bi->RSSI));
3020 qual[dwrq->length].level = 0x100 + dtoh16(bi->RSSI);
3021 qual[dwrq->length].noise = 0x100 + bi->phy_noise;
3024 #if WIRELESS_EXT > 18
3025 qual[dwrq->length].updated = IW_QUAL_ALL_UPDATED | IW_QUAL_DBM;
3027 qual[dwrq->length].updated = 7;
3035 memcpy(&addr[dwrq->length], qual, sizeof(struct iw_quality) * dwrq->length);
3044 wl_iw_iscan_prep(wl_scan_params_t *params, wlc_ssid_t *ssid)
3048 memcpy(¶ms->bssid, ðer_bcast, ETHER_ADDR_LEN);
3049 params->bss_type = DOT11_BSSTYPE_ANY;
3050 params->scan_type = 0;
3051 params->nprobes = -1;
3052 params->active_time = -1;
3053 params->passive_time = -1;
3054 params->home_time = -1;
3055 params->channel_num = 0;
3057 #if defined(CONFIG_FIRST_SCAN)
3059 if (g_first_broadcast_scan == BROADCAST_SCAN_FIRST_STARTED)
3060 params->passive_time = 30;
3062 params->nprobes = htod32(params->nprobes);
3063 params->active_time = htod32(params->active_time);
3064 params->passive_time = htod32(params->passive_time);
3065 params->home_time = htod32(params->home_time);
3066 if (ssid && ssid->SSID_len)
3067 memcpy(¶ms->ssid, ssid, sizeof(wlc_ssid_t));
3073 wl_iw_iscan(iscan_info_t *iscan, wlc_ssid_t *ssid, uint16 action)
3077 iscan->iscan_ex_params_p->version = htod32(ISCAN_REQ_VERSION);
3078 iscan->iscan_ex_params_p->action = htod16(action);
3079 iscan->iscan_ex_params_p->scan_duration = htod16(0);
3081 WL_SCAN(("%s : nprobes=%d\n", __FUNCTION__, iscan->iscan_ex_params_p->params.nprobes));
3082 WL_SCAN(("active_time=%d\n", iscan->iscan_ex_params_p->params.active_time));
3083 WL_SCAN(("passive_time=%d\n", iscan->iscan_ex_params_p->params.passive_time));
3084 WL_SCAN(("home_time=%d\n", iscan->iscan_ex_params_p->params.home_time));
3085 WL_SCAN(("scan_type=%d\n", iscan->iscan_ex_params_p->params.scan_type));
3086 WL_SCAN(("bss_type=%d\n", iscan->iscan_ex_params_p->params.bss_type));
3088 if ((dev_iw_iovar_setbuf(iscan->dev, "iscan", iscan->iscan_ex_params_p,
3089 iscan->iscan_ex_param_size, iscan->ioctlbuf, sizeof(iscan->ioctlbuf)))) {
3090 WL_ERROR(("Set ISCAN for %s failed with %d\n", __FUNCTION__, err));
3098 wl_iw_timerfunc(ulong data)
3100 iscan_info_t *iscan = (iscan_info_t *)data;
3102 iscan->timer_on = 0;
3103 if (iscan->iscan_state != ISCAN_STATE_IDLE) {
3104 WL_TRACE(("timer trigger\n"));
3105 up(&iscan->tsk_ctl.sema);
3111 wl_iw_set_event_mask(struct net_device *dev)
3113 char eventmask[WL_EVENTING_MASK_LEN];
3114 char iovbuf[WL_EVENTING_MASK_LEN + 12];
3116 dev_iw_iovar_getbuf(dev, "event_msgs", "", 0, iovbuf, sizeof(iovbuf));
3117 bcopy(iovbuf, eventmask, WL_EVENTING_MASK_LEN);
3118 setbit(eventmask, WLC_E_SCAN_COMPLETE);
3119 dev_iw_iovar_setbuf(dev, "event_msgs", eventmask, WL_EVENTING_MASK_LEN,
3120 iovbuf, sizeof(iovbuf));
3124 wl_iw_iscan_get(iscan_info_t *iscan)
3128 wl_iscan_results_t * list_buf;
3129 wl_iscan_results_t list;
3130 wl_scan_results_t *results;
3134 DHD_OS_MUTEX_LOCK(&wl_cache_lock);
3135 if (iscan->list_cur) {
3136 buf = iscan->list_cur;
3137 iscan->list_cur = buf->next;
3140 buf = kmalloc(sizeof(iscan_buf_t), GFP_KERNEL);
3142 WL_ERROR(("%s can't alloc iscan_buf_t : going to abort currect iscan\n",
3144 DHD_OS_MUTEX_UNLOCK(&wl_cache_lock);
3145 return WL_SCAN_RESULTS_NO_MEM;
3148 if (!iscan->list_hdr)
3149 iscan->list_hdr = buf;
3151 ptr = iscan->list_hdr;
3158 memset(buf->iscan_buf, 0, WLC_IW_ISCAN_MAXLEN);
3159 list_buf = (wl_iscan_results_t*)buf->iscan_buf;
3160 results = &list_buf->results;
3161 results->buflen = WL_ISCAN_RESULTS_FIXED_SIZE;
3162 results->version = 0;
3165 memset(&list, 0, sizeof(list));
3166 list.results.buflen = htod32(WLC_IW_ISCAN_MAXLEN);
3167 res = dev_iw_iovar_getbuf(
3171 WL_ISCAN_RESULTS_FIXED_SIZE,
3173 WLC_IW_ISCAN_MAXLEN);
3175 results->buflen = dtoh32(results->buflen);
3176 results->version = dtoh32(results->version);
3177 results->count = dtoh32(results->count);
3178 WL_TRACE(("results->count = %d\n", results->count));
3179 WL_TRACE(("results->buflen = %d\n", results->buflen));
3180 status = dtoh32(list_buf->status);
3182 WL_ERROR(("%s returns error %d\n", __FUNCTION__, res));
3184 status = WL_SCAN_RESULTS_NO_MEM;
3186 DHD_OS_MUTEX_UNLOCK(&wl_cache_lock);
3191 wl_iw_force_specific_scan(iscan_info_t *iscan)
3193 WL_TRACE(("%s force Specific SCAN for %s\n", __FUNCTION__, g_specific_ssid.SSID));
3194 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27))
3198 (void) dev_wlc_ioctl(iscan->dev, WLC_SCAN, &g_specific_ssid, sizeof(g_specific_ssid));
3200 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27))
3206 wl_iw_send_scan_complete(iscan_info_t *iscan)
3208 union iwreq_data wrqu;
3210 memset(&wrqu, 0, sizeof(wrqu));
3213 wireless_send_event(iscan->dev, SIOCGIWSCAN, &wrqu, NULL);
3214 #if defined(CONFIG_FIRST_SCAN)
3215 if (g_first_broadcast_scan == BROADCAST_SCAN_FIRST_STARTED)
3216 g_first_broadcast_scan = BROADCAST_SCAN_FIRST_RESULT_READY;
3218 WL_TRACE(("Send Event ISCAN complete\n"));
3222 _iscan_sysioc_thread(void *data)
3226 tsk_ctl_t *tsk_ctl = (tsk_ctl_t *)data;
3227 iscan_info_t *iscan = (iscan_info_t *) tsk_ctl->parent;
3230 static bool iscan_pass_abort = FALSE;
3232 DAEMONIZE("iscan_sysioc");
3234 status = WL_SCAN_RESULTS_PARTIAL;
3237 complete(&tsk_ctl->completed);
3239 while (down_interruptible(&tsk_ctl->sema) == 0) {
3241 SMP_RD_BARRIER_DEPENDS();
3242 if (tsk_ctl->terminated) {
3247 if (ap_cfg_running) {
3248 WL_TRACE(("%s skipping SCAN ops in AP mode !!!\n", __FUNCTION__));
3249 net_os_wake_unlock(iscan->dev);
3254 if (iscan->timer_on) {
3256 iscan->timer_on = 0;
3257 del_timer_sync(&iscan->timer);
3260 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27))
3263 status = wl_iw_iscan_get(iscan);
3264 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27))
3268 if (g_scan_specified_ssid && (iscan_pass_abort == TRUE)) {
3269 WL_TRACE(("%s Get results from specific scan status=%d\n", __FUNCTION__, status));
3270 wl_iw_send_scan_complete(iscan);
3271 iscan_pass_abort = FALSE;
3276 case WL_SCAN_RESULTS_PARTIAL:
3277 WL_TRACE(("iscanresults incomplete\n"));
3278 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27))
3282 wl_iw_iscan(iscan, NULL, WL_SCAN_ACTION_CONTINUE);
3283 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27))
3287 mod_timer(&iscan->timer, jiffies + iscan->timer_ms*HZ/1000);
3288 iscan->timer_on = 1;
3290 case WL_SCAN_RESULTS_SUCCESS:
3291 WL_TRACE(("iscanresults complete\n"));
3292 iscan->iscan_state = ISCAN_STATE_IDLE;
3293 wl_iw_send_scan_complete(iscan);
3295 case WL_SCAN_RESULTS_PENDING:
3296 WL_TRACE(("iscanresults pending\n"));
3298 mod_timer(&iscan->timer, jiffies + iscan->timer_ms*HZ/1000);
3299 iscan->timer_on = 1;
3301 case WL_SCAN_RESULTS_ABORTED:
3302 WL_TRACE(("iscanresults aborted\n"));
3303 iscan->iscan_state = ISCAN_STATE_IDLE;
3304 if (g_scan_specified_ssid == 0)
3305 wl_iw_send_scan_complete(iscan);
3307 iscan_pass_abort = TRUE;
3308 wl_iw_force_specific_scan(iscan);
3311 case WL_SCAN_RESULTS_NO_MEM:
3312 WL_TRACE(("iscanresults can't alloc memory: skip\n"));
3313 iscan->iscan_state = ISCAN_STATE_IDLE;
3316 WL_TRACE(("iscanresults returned unknown status %d\n", status));
3320 net_os_wake_unlock(iscan->dev);
3323 if (iscan->timer_on) {
3324 iscan->timer_on = 0;
3325 del_timer_sync(&iscan->timer);
3327 complete_and_exit(&tsk_ctl->completed, 0);
3334 wl_iw_set_ss_cache_timer_flag(void)
3336 g_ss_cache_ctrl.m_timer_expired = 1;
3337 WL_TRACE(("%s called\n", __FUNCTION__));
3342 wl_iw_init_ss_cache_ctrl(void)
3344 WL_TRACE(("%s :\n", __FUNCTION__));
3345 g_ss_cache_ctrl.m_prev_scan_mode = 0;
3346 g_ss_cache_ctrl.m_cons_br_scan_cnt = 0;
3347 g_ss_cache_ctrl.m_cache_head = NULL;
3348 g_ss_cache_ctrl.m_link_down = 0;
3349 g_ss_cache_ctrl.m_timer_expired = 0;
3350 memset(g_ss_cache_ctrl.m_active_bssid, 0, ETHER_ADDR_LEN);
3352 g_ss_cache_ctrl.m_timer = kmalloc(sizeof(struct timer_list), GFP_KERNEL);
3353 if (!g_ss_cache_ctrl.m_timer) {
3356 g_ss_cache_ctrl.m_timer->function = (void *)wl_iw_set_ss_cache_timer_flag;
3357 init_timer(g_ss_cache_ctrl.m_timer);
3365 wl_iw_free_ss_cache(void)
3367 wl_iw_ss_cache_t *node, *cur;
3368 wl_iw_ss_cache_t **spec_scan_head;
3370 WL_TRACE(("%s called\n", __FUNCTION__));
3372 DHD_OS_MUTEX_LOCK(&wl_cache_lock);
3373 spec_scan_head = &g_ss_cache_ctrl.m_cache_head;
3374 node = *spec_scan_head;
3377 WL_TRACE(("%s : SSID - %s\n", __FUNCTION__, node->bss_info->SSID));
3382 *spec_scan_head = NULL;
3383 DHD_OS_MUTEX_UNLOCK(&wl_cache_lock);
3389 wl_iw_run_ss_cache_timer(int kick_off)
3391 struct timer_list **timer;
3393 timer = &g_ss_cache_ctrl.m_timer;
3397 #ifdef CONFIG_PRESCANNED
3398 (*timer)->expires = jiffies + 70000 * HZ / 1000;
3400 (*timer)->expires = jiffies + 30000 * HZ / 1000;
3403 WL_TRACE(("%s : timer starts \n", __FUNCTION__));
3405 del_timer_sync(*timer);
3406 WL_TRACE(("%s : timer stops \n", __FUNCTION__));
3415 wl_iw_release_ss_cache_ctrl(void)
3417 WL_TRACE(("%s :\n", __FUNCTION__));
3418 wl_iw_free_ss_cache();
3419 wl_iw_run_ss_cache_timer(0);
3420 if (g_ss_cache_ctrl.m_timer) {
3421 kfree(g_ss_cache_ctrl.m_timer);
3428 wl_iw_reset_ss_cache(void)
3430 wl_iw_ss_cache_t *node, *prev, *cur;
3431 wl_iw_ss_cache_t **spec_scan_head;
3433 DHD_OS_MUTEX_LOCK(&wl_cache_lock);
3434 spec_scan_head = &g_ss_cache_ctrl.m_cache_head;
3435 node = *spec_scan_head;
3439 WL_TRACE(("%s : node SSID %s \n", __FUNCTION__, node->bss_info->SSID));
3442 if (cur == *spec_scan_head) {
3443 *spec_scan_head = cur->next;
3444 prev = *spec_scan_head;
3447 prev->next = cur->next;
3451 WL_TRACE(("%s : Del node : SSID %s\n", __FUNCTION__, cur->bss_info->SSID));
3460 DHD_OS_MUTEX_UNLOCK(&wl_cache_lock);
3465 wl_iw_add_bss_to_ss_cache(wl_scan_results_t *ss_list)
3468 wl_iw_ss_cache_t *node, *prev, *leaf;
3469 wl_iw_ss_cache_t **spec_scan_head;
3470 wl_bss_info_t *bi = NULL;
3474 if (!ss_list->count) {
3478 DHD_OS_MUTEX_LOCK(&wl_cache_lock);
3479 spec_scan_head = &g_ss_cache_ctrl.m_cache_head;
3481 for (i = 0; i < ss_list->count; i++) {
3483 node = *spec_scan_head;
3486 bi = bi ? (wl_bss_info_t *)((uintptr)bi + dtoh32(bi->length)) : ss_list->bss_info;
3488 WL_TRACE(("%s : find %d with specific SSID %s\n", __FUNCTION__, i, bi->SSID));
3490 if (!memcmp(&node->bss_info->BSSID, &bi->BSSID, ETHER_ADDR_LEN)) {
3492 WL_TRACE(("dirty marked : SSID %s\n", bi->SSID));
3504 leaf = kmalloc(bi->length + WLC_IW_SS_CACHE_CTRL_FIELD_MAXLEN, GFP_KERNEL);
3506 WL_ERROR(("Memory alloc failure %d\n",
3507 bi->length + WLC_IW_SS_CACHE_CTRL_FIELD_MAXLEN));
3508 DHD_OS_MUTEX_UNLOCK(&wl_cache_lock);
3512 memcpy(leaf->bss_info, bi, bi->length);
3516 leaf->version = ss_list->version;
3519 *spec_scan_head = leaf;
3525 DHD_OS_MUTEX_UNLOCK(&wl_cache_lock);
3531 wl_iw_merge_scan_cache(struct iw_request_info *info, char *extra, uint buflen_from_user,
3534 wl_iw_ss_cache_t *node;
3535 wl_scan_results_t *list_merge;
3537 DHD_OS_MUTEX_LOCK(&wl_cache_lock);
3538 node = g_ss_cache_ctrl.m_cache_head;
3540 list_merge = (wl_scan_results_t *)&node->buflen;
3541 WL_TRACE(("%s: Cached Specific APs list=%d\n", __FUNCTION__, list_merge->count));
3542 if (buflen_from_user - *merged_len > 0) {
3543 *merged_len += (__u16) wl_iw_get_scan_prep(list_merge, info,
3544 extra + *merged_len, buflen_from_user - *merged_len);
3547 WL_TRACE(("%s: exit with break\n", __FUNCTION__));
3552 DHD_OS_MUTEX_UNLOCK(&wl_cache_lock);
3558 wl_iw_delete_bss_from_ss_cache(void *addr)
3561 wl_iw_ss_cache_t *node, *prev;
3562 wl_iw_ss_cache_t **spec_scan_head;
3564 DHD_OS_MUTEX_LOCK(&wl_cache_lock);
3565 spec_scan_head = &g_ss_cache_ctrl.m_cache_head;
3566 node = *spec_scan_head;
3569 if (!memcmp(&node->bss_info->BSSID, addr, ETHER_ADDR_LEN)) {
3570 if (node == *spec_scan_head) {
3571 *spec_scan_head = node->next;
3574 prev->next = node->next;
3577 WL_TRACE(("%s : Del node : %s\n", __FUNCTION__, node->bss_info->SSID));
3586 memset(addr, 0, ETHER_ADDR_LEN);
3587 DHD_OS_MUTEX_UNLOCK(&wl_cache_lock);
3595 struct net_device *dev,
3596 struct iw_request_info *info,
3597 union iwreq_data *wrqu,
3602 WL_TRACE(("\n:%s dev:%s: SIOCSIWSCAN : SCAN\n", __FUNCTION__, dev->name));
3604 #ifdef OEM_CHROMIUMOS
3605 g_set_essid_before_scan = FALSE;
3609 WL_ERROR(("%s: Scan from SIOCGIWSCAN not supported\n", __FUNCTION__));
3615 if (ap_cfg_running) {
3616 WL_TRACE(("\n>%s: Not executed, reason -'SOFTAP is active'\n", __FUNCTION__));
3622 if (g_onoff == G_WLAN_SET_OFF)
3626 memset(&g_specific_ssid, 0, sizeof(g_specific_ssid));
3627 #ifndef WL_IW_USE_ISCAN
3629 g_scan_specified_ssid = 0;
3632 #if WIRELESS_EXT > 17
3634 if (wrqu->data.length == sizeof(struct iw_scan_req)) {
3635 if (wrqu->data.flags & IW_SCAN_THIS_ESSID) {
3636 struct iw_scan_req *req = (struct iw_scan_req *)extra;
3637 #if defined(CONFIG_FIRST_SCAN)
3638 if (g_first_broadcast_scan != BROADCAST_SCAN_FIRST_RESULT_CONSUMED) {
3640 WL_TRACE(("%s Ignoring SC %s first BC is not done = %d\n",
3641 __FUNCTION__, req->essid,
3642 g_first_broadcast_scan));
3646 if (g_scan_specified_ssid) {
3647 WL_TRACE(("%s Specific SCAN is not done ignore scan for = %s \n",
3648 __FUNCTION__, req->essid));
3653 g_specific_ssid.SSID_len = MIN(sizeof(g_specific_ssid.SSID),
3655 memcpy(g_specific_ssid.SSID, req->essid, g_specific_ssid.SSID_len);
3656 g_specific_ssid.SSID_len = htod32(g_specific_ssid.SSID_len);
3657 g_scan_specified_ssid = 1;
3658 WL_TRACE(("### Specific scan ssid=%s len=%d\n",
3659 g_specific_ssid.SSID, g_specific_ssid.SSID_len));
3665 if ((error = dev_wlc_ioctl(dev, WLC_SCAN, &g_specific_ssid, sizeof(g_specific_ssid)))) {
3666 WL_TRACE(("#### Set SCAN for %s failed with %d\n", g_specific_ssid.SSID, error));
3668 g_scan_specified_ssid = 0;
3675 #ifdef WL_IW_USE_ISCAN
3677 wl_iw_iscan_set_scan_broadcast_prep(struct net_device *dev, uint flag)
3680 iscan_info_t *iscan = g_iscan;
3682 #if defined(CONFIG_FIRST_SCAN)
3684 if (g_first_broadcast_scan == BROADCAST_SCAN_FIRST_IDLE) {
3685 g_first_broadcast_scan = BROADCAST_SCAN_FIRST_STARTED;
3686 WL_TRACE(("%s: First Brodcast scan was forced\n", __FUNCTION__));
3688 else if (g_first_broadcast_scan == BROADCAST_SCAN_FIRST_STARTED) {
3689 WL_TRACE(("%s: ignore ISCAN request first BS is not done yet\n", __FUNCTION__));
3694 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27))
3699 dev_wlc_ioctl(dev, WLC_SET_PASSIVE_SCAN, &iscan->scan_flag, sizeof(iscan->scan_flag));
3700 wl_iw_set_event_mask(dev);
3702 WL_TRACE(("+++: Set Broadcast ISCAN\n"));
3704 memset(&ssid, 0, sizeof(ssid));
3706 iscan->list_cur = iscan->list_hdr;
3707 iscan->iscan_state = ISCAN_STATE_SCANING;
3709 memset(&iscan->iscan_ex_params_p->params, 0, iscan->iscan_ex_param_size);
3710 wl_iw_iscan_prep(&iscan->iscan_ex_params_p->params, &ssid);
3711 wl_iw_iscan(iscan, &ssid, WL_SCAN_ACTION_START);
3713 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27))
3718 mod_timer(&iscan->timer, jiffies + iscan->timer_ms*HZ/1000);
3720 iscan->timer_on = 1;
3726 wl_iw_iscan_set_scan(
3727 struct net_device *dev,
3728 struct iw_request_info *info,
3729 union iwreq_data *wrqu,
3734 iscan_info_t *iscan = g_iscan;
3737 WL_TRACE_SCAN(("%s: SIOCSIWSCAN : ISCAN\n", dev->name));
3740 WL_ERROR(("%s: Scan from SIOCGIWSCAN not supported\n", __FUNCTION__));
3744 net_os_wake_lock(dev);
3748 if (ap_cfg_running) {
3749 WL_TRACE(("\n>%s: Not executed, reason -'SOFTAP is active'\n", __FUNCTION__));
3754 if (g_onoff == G_WLAN_SET_OFF) {
3755 WL_TRACE(("%s: driver is not up yet after START\n", __FUNCTION__));
3761 if (dhd_dev_get_pno_status(dev)) {
3762 WL_ERROR(("%s: Scan called when PNO is active\n", __FUNCTION__));
3767 if ((!iscan) || (iscan->tsk_ctl.thr_pid < 0)) {
3768 WL_ERROR(("%s error \n", __FUNCTION__));
3772 if (g_scan_specified_ssid) {
3773 WL_TRACE(("%s Specific SCAN already running ignoring BC scan\n",
3780 memset(&ssid, 0, sizeof(ssid));
3782 #if WIRELESS_EXT > 17
3784 if (wrqu->data.length == sizeof(struct iw_scan_req)) {
3785 if (wrqu->data.flags & IW_SCAN_THIS_ESSID) {
3787 struct iw_scan_req *req = (struct iw_scan_req *)extra;
3789 ssid.SSID_len = MIN(sizeof(ssid.SSID), req->essid_len);
3790 memcpy(ssid.SSID, req->essid, ssid.SSID_len);
3791 ssid.SSID_len = htod32(ssid.SSID_len);
3792 dev_wlc_ioctl(dev, WLC_SET_PASSIVE_SCAN, &as, sizeof(as));
3793 wl_iw_set_event_mask(dev);
3794 ret = wl_iw_set_scan(dev, info, wrqu, extra);
3798 g_scan_specified_ssid = 0;
3800 if (iscan->iscan_state == ISCAN_STATE_SCANING) {
3801 WL_TRACE(("%s ISCAN already in progress \n", __FUNCTION__));
3808 #if defined(CONFIG_FIRST_SCAN) && !defined(CSCAN)
3809 if (g_first_broadcast_scan < BROADCAST_SCAN_FIRST_RESULT_CONSUMED) {
3810 if (++g_first_counter_scans == MAX_ALLOWED_BLOCK_SCAN_FROM_FIRST_SCAN) {
3812 WL_ERROR(("%s Clean up First scan flag which is %d\n",
3813 __FUNCTION__, g_first_broadcast_scan));
3814 g_first_broadcast_scan = BROADCAST_SCAN_FIRST_RESULT_CONSUMED;
3817 WL_ERROR(("%s Ignoring Broadcast Scan:First Scan is not done yet %d\n",
3818 __FUNCTION__, g_first_counter_scans));
3825 wl_iw_iscan_set_scan_broadcast_prep(dev, 0);
3828 net_os_wake_unlock(dev);
3833 #if WIRELESS_EXT > 17
3835 ie_is_wpa_ie(uint8 **wpaie, uint8 **tlvs, int *tlvs_len)
3843 !bcmp((const void *)&ie[2], (const void *)(WPA_OUI "\x01"), 4)) {
3850 *tlvs_len -= (int)(ie - *tlvs);
3857 ie_is_wps_ie(uint8 **wpsie, uint8 **tlvs, int *tlvs_len)
3865 !bcmp((const void *)&ie[2], (const void *)(WPA_OUI "\x04"), 4)) {
3872 *tlvs_len -= (int)(ie - *tlvs);
3881 wl_iw_handle_scanresults_ies(char **event_p, char *end,
3882 struct iw_request_info *info, wl_bss_info_t *bi)
3884 #if WIRELESS_EXT > 17
3885 struct iw_event iwe;
3889 if (bi->ie_length) {
3892 uint8 *ptr = ((uint8 *)bi) + sizeof(wl_bss_info_t);
3893 int ptr_len = bi->ie_length;
3895 if ((ie = bcm_parse_tlvs(ptr, ptr_len, DOT11_MNG_RSN_ID))) {
3896 iwe.cmd = IWEVGENIE;
3897 iwe.u.data.length = ie->len + 2;
3898 event = IWE_STREAM_ADD_POINT(info, event, end, &iwe, (char *)ie);
3900 ptr = ((uint8 *)bi) + sizeof(wl_bss_info_t);
3902 while ((ie = bcm_parse_tlvs(ptr, ptr_len, DOT11_MNG_WPA_ID))) {
3904 if (ie_is_wps_ie(((uint8 **)&ie), &ptr, &ptr_len)) {
3905 iwe.cmd = IWEVGENIE;
3906 iwe.u.data.length = ie->len + 2;
3907 event = IWE_STREAM_ADD_POINT(info, event, end, &iwe, (char *)ie);
3912 ptr = ((uint8 *)bi) + sizeof(wl_bss_info_t);
3913 ptr_len = bi->ie_length;
3914 while ((ie = bcm_parse_tlvs(ptr, ptr_len, DOT11_MNG_WPA_ID))) {
3915 if (ie_is_wpa_ie(((uint8 **)&ie), &ptr, &ptr_len)) {
3916 iwe.cmd = IWEVGENIE;
3917 iwe.u.data.length = ie->len + 2;
3918 event = IWE_STREAM_ADD_POINT(info, event, end, &iwe, (char *)ie);
3932 wl_iw_get_scan_prep(
3933 wl_scan_results_t *list,
3934 struct iw_request_info *info,
3939 struct iw_event iwe;
3940 wl_bss_info_t *bi = NULL;
3941 char *event = extra, *end = extra + max_size - WE_ADD_EVENT_FIX, *value;
3945 WL_ERROR(("%s: Null list pointer", __FUNCTION__));
3951 for (i = 0; i < list->count && i < IW_MAX_AP; i++) {
3952 if (list->version != WL_BSS_INFO_VERSION) {
3953 WL_ERROR(("%s : list->version %d != WL_BSS_INFO_VERSION\n",
3954 __FUNCTION__, list->version));
3958 bi = bi ? (wl_bss_info_t *)((uintptr)bi + dtoh32(bi->length)) : list->bss_info;
3960 WL_TRACE(("%s : %s\n", __FUNCTION__, bi->SSID));
3963 iwe.cmd = SIOCGIWAP;
3964 iwe.u.ap_addr.sa_family = ARPHRD_ETHER;
3965 memcpy(iwe.u.ap_addr.sa_data, &bi->BSSID, ETHER_ADDR_LEN);
3966 event = IWE_STREAM_ADD_EVENT(info, event, end, &iwe, IW_EV_ADDR_LEN);
3968 iwe.u.data.length = dtoh32(bi->SSID_len);
3969 iwe.cmd = SIOCGIWESSID;
3970 iwe.u.data.flags = 1;
3971 event = IWE_STREAM_ADD_POINT(info, event, end, &iwe, bi->SSID);
3974 if (dtoh16(bi->capability) & (DOT11_CAP_ESS | DOT11_CAP_IBSS)) {
3975 iwe.cmd = SIOCGIWMODE;
3976 if (dtoh16(bi->capability) & DOT11_CAP_ESS)
3977 iwe.u.mode = IW_MODE_INFRA;
3979 iwe.u.mode = IW_MODE_ADHOC;
3980 event = IWE_STREAM_ADD_EVENT(info, event, end, &iwe, IW_EV_UINT_LEN);
3984 iwe.cmd = SIOCGIWFREQ;
3985 iwe.u.freq.m = wf_channel2mhz(CHSPEC_CHANNEL(bi->chanspec),
3986 CHSPEC_CHANNEL(bi->chanspec) <= CH_MAX_2G_CHANNEL ?
3987 WF_CHAN_FACTOR_2_4_G : WF_CHAN_FACTOR_5_G);
3989 event = IWE_STREAM_ADD_EVENT(info, event, end, &iwe, IW_EV_FREQ_LEN);
3993 iwe.u.qual.qual = rssi_to_qual(dtoh16(bi->RSSI));
3994 iwe.u.qual.level = 0x100 + dtoh16(bi->RSSI);
3995 iwe.u.qual.noise = 0x100 + bi->phy_noise;
3996 event = IWE_STREAM_ADD_EVENT(info, event, end, &iwe, IW_EV_QUAL_LEN);
3999 wl_iw_handle_scanresults_ies(&event, end, info, bi);
4002 iwe.cmd = SIOCGIWENCODE;
4003 if (dtoh16(bi->capability) & DOT11_CAP_PRIVACY)
4004 iwe.u.data.flags = IW_ENCODE_ENABLED | IW_ENCODE_NOKEY;
4006 iwe.u.data.flags = IW_ENCODE_DISABLED;
4007 iwe.u.data.length = 0;
4008 event = IWE_STREAM_ADD_POINT(info, event, end, &iwe, (char *)event);
4011 if (bi->rateset.count) {
4012 if (((event -extra) + IW_EV_LCP_LEN) <= (uintptr)end) {
4013 value = event + IW_EV_LCP_LEN;
4014 iwe.cmd = SIOCGIWRATE;
4016 iwe.u.bitrate.fixed = iwe.u.bitrate.disabled = 0;
4017 for (j = 0; j < bi->rateset.count && j < IW_MAX_BITRATES; j++) {
4018 iwe.u.bitrate.value =
4019 (bi->rateset.rates[j] & 0x7f) * 500000;
4020 value = IWE_STREAM_ADD_VALUE(info, event, value, end, &iwe,
4028 if ((ret = (event - extra)) < 0) {
4029 WL_ERROR(("==> Wrong size\n"));
4033 WL_TRACE(("%s: size=%d bytes prepared \n", __FUNCTION__, (unsigned int)(event - extra)));
4039 struct net_device *dev,
4040 struct iw_request_info *info,
4041 struct iw_point *dwrq,
4046 wl_scan_results_t *list_merge;
4047 wl_scan_results_t *list = (wl_scan_results_t *) g_scan;
4049 uint buflen_from_user = dwrq->length;
4050 uint len = G_SCAN_RESULTS;
4053 __u16 merged_len = 0;
4055 #if defined(WL_IW_USE_ISCAN)
4056 iscan_info_t *iscan = g_iscan;
4057 iscan_buf_t * p_buf;
4063 WL_TRACE(("%s: buflen_from_user %d: \n", dev->name, buflen_from_user));
4066 WL_TRACE(("%s: wl_iw_get_scan return -EINVAL\n", dev->name));
4071 if ((error = dev_wlc_ioctl(dev, WLC_GET_CHANNEL, &ci, sizeof(ci))))
4073 ci.scan_channel = dtoh32(ci.scan_channel);
4074 if (ci.scan_channel)
4078 if (g_ss_cache_ctrl.m_timer_expired) {
4079 wl_iw_free_ss_cache();
4080 g_ss_cache_ctrl.m_timer_expired ^= 1;
4082 if ((!g_scan_specified_ssid && g_ss_cache_ctrl.m_prev_scan_mode) ||
4083 g_ss_cache_ctrl.m_cons_br_scan_cnt > 4) {
4084 g_ss_cache_ctrl.m_cons_br_scan_cnt = 0;
4086 wl_iw_reset_ss_cache();
4088 g_ss_cache_ctrl.m_prev_scan_mode = g_scan_specified_ssid;
4089 if (g_scan_specified_ssid) {
4090 g_ss_cache_ctrl.m_cons_br_scan_cnt = 0;
4093 g_ss_cache_ctrl.m_cons_br_scan_cnt++;
4099 if (g_scan_specified_ssid) {
4101 list = kmalloc(len, GFP_KERNEL);
4103 WL_TRACE(("%s: wl_iw_get_scan return -ENOMEM\n", dev->name));
4104 g_scan_specified_ssid = 0;
4109 memset(list, 0, len);
4110 list->buflen = htod32(len);
4111 if ((error = dev_wlc_ioctl(dev, WLC_SCAN_RESULTS, list, len))) {
4112 WL_ERROR(("%s: %s : Scan_results ERROR %d\n", dev->name, __FUNCTION__, error));
4114 if (g_scan_specified_ssid) {
4115 g_scan_specified_ssid = 0;
4120 list->buflen = dtoh32(list->buflen);
4121 list->version = dtoh32(list->version);
4122 list->count = dtoh32(list->count);
4125 if (list->version != WL_BSS_INFO_VERSION) {
4126 WL_ERROR(("%s : list->version %d != WL_BSS_INFO_VERSION\n",
4127 __FUNCTION__, list->version));
4128 if (g_scan_specified_ssid) {
4129 g_scan_specified_ssid = 0;
4136 if (g_scan_specified_ssid) {
4138 wl_iw_add_bss_to_ss_cache(list);
4144 DHD_OS_MUTEX_LOCK(&wl_cache_lock);
4145 #if defined(WL_IW_USE_ISCAN)
4146 if (g_scan_specified_ssid)
4147 WL_TRACE(("%s: Specified scan APs from scan=%d\n", __FUNCTION__, list->count));
4148 p_buf = iscan->list_hdr;
4150 while (p_buf != iscan->list_cur) {
4151 list_merge = &((wl_iscan_results_t*)p_buf->iscan_buf)->results;
4152 WL_TRACE(("%s: Bcast APs list=%d\n", __FUNCTION__, list_merge->count));
4153 counter += list_merge->count;
4154 if (list_merge->count > 0)
4155 len_ret += (__u16) wl_iw_get_scan_prep(list_merge, info,
4156 extra+len_ret, buflen_from_user -len_ret);
4157 p_buf = p_buf->next;
4159 WL_TRACE(("%s merged with total Bcast APs=%d\n", __FUNCTION__, counter));
4161 list_merge = (wl_scan_results_t *) g_scan;
4162 len_ret = (__u16) wl_iw_get_scan_prep(list_merge, info, extra, buflen_from_user);
4164 DHD_OS_MUTEX_UNLOCK(&wl_cache_lock);
4165 if (g_ss_cache_ctrl.m_link_down) {
4167 wl_iw_delete_bss_from_ss_cache(g_ss_cache_ctrl.m_active_bssid);
4170 wl_iw_merge_scan_cache(info, extra+len_ret, buflen_from_user-len_ret, &merged_len);
4171 len_ret += merged_len;
4172 wl_iw_run_ss_cache_timer(0);
4173 wl_iw_run_ss_cache_timer(1);
4177 if (g_scan_specified_ssid) {
4178 WL_TRACE(("%s: Specified scan APs in the list =%d\n", __FUNCTION__, list->count));
4179 len_ret = (__u16) wl_iw_get_scan_prep(list, info, extra, buflen_from_user);
4182 #if defined(WL_IW_USE_ISCAN)
4183 p_buf = iscan->list_hdr;
4185 while (p_buf != iscan->list_cur) {
4186 list_merge = &((wl_iscan_results_t*)p_buf->iscan_buf)->results;
4187 WL_TRACE(("%s: Bcast APs list=%d\n", __FUNCTION__, list_merge->count));
4188 if (list_merge->count > 0)
4189 len_ret += (__u16) wl_iw_get_scan_prep(list_merge, info,
4190 extra+len_ret, buflen_from_user -len_ret);
4191 p_buf = p_buf->next;
4194 list_merge = (wl_scan_results_t *) g_scan;
4195 WL_TRACE(("%s: Bcast APs list=%d\n", __FUNCTION__, list_merge->count));
4196 if (list_merge->count > 0)
4197 len_ret += (__u16) wl_iw_get_scan_prep(list_merge, info, extra+len_ret,
4198 buflen_from_user -len_ret);
4202 list = (wl_scan_results_t *) g_scan;
4203 len_ret = (__u16) wl_iw_get_scan_prep(list, info, extra, buflen_from_user);
4207 #if defined(WL_IW_USE_ISCAN)
4209 g_scan_specified_ssid = 0;
4212 if ((len_ret + WE_ADD_EVENT_FIX) < buflen_from_user)
4218 WL_TRACE(("%s return to WE %d bytes APs=%d\n", __FUNCTION__, dwrq->length, list->count));
4223 #if defined(WL_IW_USE_ISCAN)
4225 wl_iw_iscan_get_scan(
4226 struct net_device *dev,
4227 struct iw_request_info *info,
4228 struct iw_point *dwrq,
4232 wl_scan_results_t *list;
4233 struct iw_event iwe;
4234 wl_bss_info_t *bi = NULL;
4237 char *event = extra, *end = extra + dwrq->length, *value;
4238 iscan_info_t *iscan = g_iscan;
4239 iscan_buf_t * p_buf;
4243 __u16 merged_len = 0;
4244 uint buflen_from_user = dwrq->length;
4247 WL_TRACE(("%s %s buflen_from_user %d:\n", dev->name, __FUNCTION__, dwrq->length));
4250 if (ap_cfg_running) {
4251 WL_TRACE(("%s: Not executed, reason -'SOFTAP is active'\n", __FUNCTION__));
4257 WL_TRACE(("%s: INVALID SIOCGIWSCAN GET bad parameter\n", dev->name));
4261 #if defined(CONFIG_FIRST_SCAN)
4262 if (g_first_broadcast_scan < BROADCAST_SCAN_FIRST_RESULT_READY) {
4263 WL_TRACE(("%s %s: first ISCAN results are NOT ready yet \n",
4264 dev->name, __FUNCTION__));
4269 if ((!iscan) || (iscan->tsk_ctl.thr_pid < 0)) {
4270 WL_ERROR(("%ssysioc_pid\n", __FUNCTION__));
4277 if (g_ss_cache_ctrl.m_timer_expired) {
4278 wl_iw_free_ss_cache();
4279 g_ss_cache_ctrl.m_timer_expired ^= 1;
4281 if (g_scan_specified_ssid) {
4282 return wl_iw_get_scan(dev, info, dwrq, extra);
4285 if (g_ss_cache_ctrl.m_link_down) {
4287 wl_iw_delete_bss_from_ss_cache(g_ss_cache_ctrl.m_active_bssid);
4289 if (g_ss_cache_ctrl.m_prev_scan_mode || g_ss_cache_ctrl.m_cons_br_scan_cnt > 4) {
4290 g_ss_cache_ctrl.m_cons_br_scan_cnt = 0;
4292 wl_iw_reset_ss_cache();
4294 g_ss_cache_ctrl.m_prev_scan_mode = g_scan_specified_ssid;
4295 g_ss_cache_ctrl.m_cons_br_scan_cnt++;
4299 WL_TRACE(("%s: SIOCGIWSCAN GET broadcast results\n", dev->name));
4301 p_buf = iscan->list_hdr;
4303 while (p_buf != iscan->list_cur) {
4304 list = &((wl_iscan_results_t*)p_buf->iscan_buf)->results;
4306 counter += list->count;
4308 if (list->version != WL_BSS_INFO_VERSION) {
4309 WL_ERROR(("%s : list->version %d != WL_BSS_INFO_VERSION\n",
4310 __FUNCTION__, list->version));
4315 for (ii = 0; ii < list->count && apcnt < IW_MAX_AP; apcnt++, ii++) {
4317 (wl_bss_info_t *)((uintptr)bi + dtoh32(bi->length)) :
4319 ASSERT(((uintptr)bi + dtoh32(bi->length)) <= ((uintptr)list +
4320 WLC_IW_ISCAN_MAXLEN));
4323 if (event + ETHER_ADDR_LEN + bi->SSID_len +
4324 IW_EV_UINT_LEN + IW_EV_FREQ_LEN + IW_EV_QUAL_LEN >= end)
4327 iwe.cmd = SIOCGIWAP;
4328 iwe.u.ap_addr.sa_family = ARPHRD_ETHER;
4329 memcpy(iwe.u.ap_addr.sa_data, &bi->BSSID, ETHER_ADDR_LEN);
4330 event = IWE_STREAM_ADD_EVENT(info, event, end, &iwe, IW_EV_ADDR_LEN);
4333 iwe.u.data.length = dtoh32(bi->SSID_len);
4334 iwe.cmd = SIOCGIWESSID;
4335 iwe.u.data.flags = 1;
4336 event = IWE_STREAM_ADD_POINT(info, event, end, &iwe, bi->SSID);
4339 if (dtoh16(bi->capability) & (DOT11_CAP_ESS | DOT11_CAP_IBSS)) {
4340 iwe.cmd = SIOCGIWMODE;
4341 if (dtoh16(bi->capability) & DOT11_CAP_ESS)
4342 iwe.u.mode = IW_MODE_INFRA;
4344 iwe.u.mode = IW_MODE_ADHOC;
4345 event = IWE_STREAM_ADD_EVENT(info, event, end,
4346 &iwe, IW_EV_UINT_LEN);
4350 iwe.cmd = SIOCGIWFREQ;
4351 channel = (bi->ctl_ch == 0) ? CHSPEC_CHANNEL(bi->chanspec) : bi->ctl_ch;
4352 iwe.u.freq.m = wf_channel2mhz(channel,
4353 channel <= CH_MAX_2G_CHANNEL ?
4354 WF_CHAN_FACTOR_2_4_G : WF_CHAN_FACTOR_5_G);
4356 event = IWE_STREAM_ADD_EVENT(info, event, end, &iwe, IW_EV_FREQ_LEN);
4360 iwe.u.qual.qual = rssi_to_qual(dtoh16(bi->RSSI));
4361 iwe.u.qual.level = 0x100 + dtoh16(bi->RSSI);
4362 iwe.u.qual.noise = 0x100 + bi->phy_noise;
4363 event = IWE_STREAM_ADD_EVENT(info, event, end, &iwe, IW_EV_QUAL_LEN);
4366 wl_iw_handle_scanresults_ies(&event, end, info, bi);
4369 iwe.cmd = SIOCGIWENCODE;
4370 if (dtoh16(bi->capability) & DOT11_CAP_PRIVACY)
4371 iwe.u.data.flags = IW_ENCODE_ENABLED | IW_ENCODE_NOKEY;
4373 iwe.u.data.flags = IW_ENCODE_DISABLED;
4374 iwe.u.data.length = 0;
4375 event = IWE_STREAM_ADD_POINT(info, event, end, &iwe, (char *)event);
4378 if (bi->rateset.count) {
4379 if (event + IW_MAX_BITRATES*IW_EV_PARAM_LEN >= end)
4382 value = event + IW_EV_LCP_LEN;
4383 iwe.cmd = SIOCGIWRATE;
4385 iwe.u.bitrate.fixed = iwe.u.bitrate.disabled = 0;
4386 for (j = 0; j < bi->rateset.count && j < IW_MAX_BITRATES; j++) {
4387 iwe.u.bitrate.value =
4388 (bi->rateset.rates[j] & 0x7f) * 500000;
4389 value = IWE_STREAM_ADD_VALUE(info, event, value, end, &iwe,
4395 p_buf = p_buf->next;
4398 dwrq->length = event - extra;
4403 wl_iw_merge_scan_cache(info, event, buflen_from_user - dwrq->length, &merged_len);
4404 dwrq->length += merged_len;
4405 wl_iw_run_ss_cache_timer(0);
4406 wl_iw_run_ss_cache_timer(1);
4409 #if defined(CONFIG_FIRST_SCAN)
4410 g_first_broadcast_scan = BROADCAST_SCAN_FIRST_RESULT_CONSUMED;
4413 WL_TRACE(("%s return to WE %d bytes APs=%d\n", __FUNCTION__, dwrq->length, counter));
4419 #define WL_JOIN_PARAMS_MAX 1600
4420 #ifdef CONFIG_PRESCANNED
4422 check_prescan(wl_join_params_t *join_params, int *join_params_size)
4426 wl_iw_ss_cache_t *node = NULL;
4427 wl_bss_info_t *bi = NULL;
4428 iscan_info_t *iscan = g_iscan;
4430 wl_scan_results_t *list;
4433 buf = iscan->list_hdr;
4436 list = &((wl_iscan_results_t*)buf->iscan_buf)->results;
4438 for (indx = 0; indx < list->count; indx++) {
4439 bi = bi ? (wl_bss_info_t *)((uintptr)bi + dtoh32(bi->length))
4441 if (!(dtoh16(bi->capability) & DOT11_CAP_ESS))
4443 if ((dtoh32(bi->SSID_len) != join_params->ssid.SSID_len) ||
4444 memcmp(bi->SSID, join_params->ssid.SSID,
4445 join_params->ssid.SSID_len))
4447 memcpy(&join_params->params.chanspec_list[cnt],
4448 &bi->chanspec, sizeof(chanspec_t));
4449 WL_ERROR(("iscan : chanspec :%d, count %d \n", bi->chanspec, cnt));
4456 MUTEX_LOCK_WL_SCAN_SET();
4457 node = g_ss_cache_ctrl.m_cache_head;
4459 if (!memcmp(&node->bss_info->SSID, join_params->ssid.SSID,
4460 join_params->ssid.SSID_len)) {
4461 memcpy(&join_params->params.chanspec_list[cnt],
4462 &node->bss_info->chanspec, sizeof(chanspec_t));
4463 WL_ERROR(("cache_scan : chanspec :%d, count %d \n",
4464 (int)node->bss_info->chanspec, cnt));
4469 MUTEX_UNLOCK_WL_SCAN_SET();
4476 destbuf = (char *)&join_params->params.chanspec_list[cnt];
4477 *join_params_size = destbuf - (char*)join_params;
4478 join_params->ssid.SSID_len = htod32(g_ssid.SSID_len);
4479 memcpy(&(join_params->params.bssid), ðer_bcast, ETHER_ADDR_LEN);
4480 join_params->params.chanspec_num = htod32(cnt);
4482 if ((*join_params_size) > WL_JOIN_PARAMS_MAX) {
4483 WL_ERROR(("can't fit bssids for all %d APs found\n", cnt));
4488 WL_ERROR(("Passing %d channel/bssid pairs.\n", cnt));
4495 struct net_device *dev,
4496 struct iw_request_info *info,
4497 struct iw_point *dwrq,
4502 wl_join_params_t *join_params;
4503 int join_params_size;
4505 WL_TRACE(("%s: SIOCSIWESSID\n", dev->name));
4507 RETURN_IF_EXTRA_NULL(extra);
4509 #ifdef OEM_CHROMIUMOS
4510 if (g_set_essid_before_scan)
4513 if (!(join_params = kmalloc(WL_JOIN_PARAMS_MAX, GFP_KERNEL))) {
4514 WL_ERROR(("allocation failed for join_params size is %d\n", WL_JOIN_PARAMS_MAX));
4518 memset(join_params, 0, WL_JOIN_PARAMS_MAX);
4521 memset(&g_ssid, 0, sizeof(g_ssid));
4523 if (dwrq->length && extra) {
4524 #if WIRELESS_EXT > 20
4525 g_ssid.SSID_len = MIN(sizeof(g_ssid.SSID), dwrq->length);
4527 g_ssid.SSID_len = MIN(sizeof(g_ssid.SSID), dwrq->length-1);
4529 memcpy(g_ssid.SSID, extra, g_ssid.SSID_len);
4531 #ifdef CONFIG_PRESCANNED
4532 memcpy(join_params->ssid.SSID, g_ssid.SSID, g_ssid.SSID_len);
4533 join_params->ssid.SSID_len = g_ssid.SSID_len;
4535 if (check_prescan(join_params, &join_params_size)) {
4536 if ((error = dev_wlc_ioctl(dev, WLC_SET_SSID,
4537 join_params, join_params_size))) {
4538 WL_ERROR(("Invalid ioctl data=%d\n", error));
4545 WL_ERROR(("No matched found\n Trying to join to specific channel\n"));
4550 g_ssid.SSID_len = 0;
4552 g_ssid.SSID_len = htod32(g_ssid.SSID_len);
4555 memset(join_params, 0, sizeof(*join_params));
4556 join_params_size = sizeof(join_params->ssid);
4558 memcpy(join_params->ssid.SSID, g_ssid.SSID, g_ssid.SSID_len);
4559 join_params->ssid.SSID_len = htod32(g_ssid.SSID_len);
4560 memcpy(&(join_params->params.bssid), ðer_bcast, ETHER_ADDR_LEN);
4564 wl_iw_ch_to_chanspec(g_wl_iw_params.target_channel, join_params, &join_params_size);
4566 if ((error = dev_wlc_ioctl(dev, WLC_SET_SSID, join_params, join_params_size))) {
4567 WL_ERROR(("Invalid ioctl data=%d\n", error));
4571 if (g_ssid.SSID_len) {
4572 WL_ERROR(("%s: join SSID=%s ch=%d\n", __FUNCTION__,
4573 g_ssid.SSID, g_wl_iw_params.target_channel));
4581 struct net_device *dev,
4582 struct iw_request_info *info,
4583 struct iw_point *dwrq,
4590 WL_TRACE(("%s: SIOCGIWESSID\n", dev->name));
4595 if ((error = dev_wlc_ioctl(dev, WLC_GET_SSID, &ssid, sizeof(ssid)))) {
4596 WL_ERROR(("Error getting the SSID\n"));
4600 ssid.SSID_len = dtoh32(ssid.SSID_len);
4603 memcpy(extra, ssid.SSID, ssid.SSID_len);
4605 dwrq->length = ssid.SSID_len;
4614 struct net_device *dev,
4615 struct iw_request_info *info,
4616 struct iw_point *dwrq,
4620 wl_iw_t *iw = NETDEV_PRIV(dev);
4622 WL_TRACE(("%s: SIOCSIWNICKN\n", dev->name));
4628 if (dwrq->length > sizeof(iw->nickname))
4631 memcpy(iw->nickname, extra, dwrq->length);
4632 iw->nickname[dwrq->length - 1] = '\0';
4639 struct net_device *dev,
4640 struct iw_request_info *info,
4641 struct iw_point *dwrq,
4645 wl_iw_t *iw = NETDEV_PRIV(dev);
4647 WL_TRACE(("%s: SIOCGIWNICKN\n", dev->name));
4652 strcpy(extra, iw->nickname);
4653 dwrq->length = strlen(extra) + 1;
4660 struct net_device *dev,
4661 struct iw_request_info *info,
4662 struct iw_param *vwrq,
4666 wl_rateset_t rateset;
4667 int error, rate, i, error_bg, error_a;
4669 WL_TRACE(("%s: SIOCSIWRATE\n", dev->name));
4672 if ((error = dev_wlc_ioctl(dev, WLC_GET_CURR_RATESET, &rateset, sizeof(rateset))))
4675 rateset.count = dtoh32(rateset.count);
4677 if (vwrq->value < 0) {
4679 rate = rateset.rates[rateset.count - 1] & 0x7f;
4680 } else if (vwrq->value < rateset.count) {
4682 rate = rateset.rates[vwrq->value] & 0x7f;
4685 rate = vwrq->value / 500000;
4690 error_bg = dev_wlc_intvar_set(dev, "bg_rate", rate);
4691 error_a = dev_wlc_intvar_set(dev, "a_rate", rate);
4693 if (error_bg && error_a)
4694 return (error_bg | error_a);
4698 error_bg = dev_wlc_intvar_set(dev, "bg_rate", 0);
4700 error_a = dev_wlc_intvar_set(dev, "a_rate", 0);
4702 if (error_bg && error_a)
4703 return (error_bg | error_a);
4706 for (i = 0; i < rateset.count; i++)
4707 if ((rateset.rates[i] & 0x7f) > rate)
4709 rateset.count = htod32(i);
4712 if ((error = dev_wlc_ioctl(dev, WLC_SET_RATESET, &rateset, sizeof(rateset))))
4721 struct net_device *dev,
4722 struct iw_request_info *info,
4723 struct iw_param *vwrq,
4729 WL_TRACE(("%s: SIOCGIWRATE\n", dev->name));
4732 if ((error = dev_wlc_ioctl(dev, WLC_GET_RATE, &rate, sizeof(rate))))
4734 rate = dtoh32(rate);
4735 vwrq->value = rate * 500000;
4742 struct net_device *dev,
4743 struct iw_request_info *info,
4744 struct iw_param *vwrq,
4750 WL_TRACE(("%s: SIOCSIWRTS\n", dev->name));
4753 rts = DOT11_DEFAULT_RTS_LEN;
4754 else if (vwrq->value < 0 || vwrq->value > DOT11_DEFAULT_RTS_LEN)
4759 if ((error = dev_wlc_intvar_set(dev, "rtsthresh", rts)))
4767 struct net_device *dev,
4768 struct iw_request_info *info,
4769 struct iw_param *vwrq,
4775 WL_TRACE(("%s: SIOCGIWRTS\n", dev->name));
4777 if ((error = dev_wlc_intvar_get(dev, "rtsthresh", &rts)))
4781 vwrq->disabled = (rts >= DOT11_DEFAULT_RTS_LEN);
4789 struct net_device *dev,
4790 struct iw_request_info *info,
4791 struct iw_param *vwrq,
4797 WL_TRACE(("%s: SIOCSIWFRAG\n", dev->name));
4800 frag = DOT11_DEFAULT_FRAG_LEN;
4801 else if (vwrq->value < 0 || vwrq->value > DOT11_DEFAULT_FRAG_LEN)
4806 if ((error = dev_wlc_intvar_set(dev, "fragthresh", frag)))
4814 struct net_device *dev,
4815 struct iw_request_info *info,
4816 struct iw_param *vwrq,
4820 int error, fragthreshold;
4822 WL_TRACE(("%s: SIOCGIWFRAG\n", dev->name));
4824 if ((error = dev_wlc_intvar_get(dev, "fragthresh", &fragthreshold)))
4827 vwrq->value = fragthreshold;
4828 vwrq->disabled = (fragthreshold >= DOT11_DEFAULT_FRAG_LEN);
4836 struct net_device *dev,
4837 struct iw_request_info *info,
4838 struct iw_param *vwrq,
4844 WL_TRACE(("%s: SIOCSIWTXPOW\n", dev->name));
4847 disable = vwrq->disabled ? WL_RADIO_SW_DISABLE : 0;
4848 disable += WL_RADIO_SW_DISABLE << 16;
4850 disable = htod32(disable);
4851 if ((error = dev_wlc_ioctl(dev, WLC_SET_RADIO, &disable, sizeof(disable))))
4855 if (disable & WL_RADIO_SW_DISABLE)
4859 if (!(vwrq->flags & IW_TXPOW_MWATT))
4863 if (vwrq->value < 0)
4866 if (vwrq->value > 0xffff) txpwrmw = 0xffff;
4867 else txpwrmw = (uint16)vwrq->value;
4870 error = dev_wlc_intvar_set(dev, "qtxpower", (int)(bcm_mw_to_qdbm(txpwrmw)));
4876 struct net_device *dev,
4877 struct iw_request_info *info,
4878 struct iw_param *vwrq,
4882 int error, disable, txpwrdbm;
4885 WL_TRACE(("%s: SIOCGIWTXPOW\n", dev->name));
4887 if ((error = dev_wlc_ioctl(dev, WLC_GET_RADIO, &disable, sizeof(disable))) ||
4888 (error = dev_wlc_intvar_get(dev, "qtxpower", &txpwrdbm)))
4891 disable = dtoh32(disable);
4892 result = (uint8)(txpwrdbm & ~WL_TXPWR_OVERRIDE);
4893 vwrq->value = (int32)bcm_qdbm_to_mw(result);
4895 vwrq->disabled = (disable & (WL_RADIO_SW_DISABLE | WL_RADIO_HW_DISABLE)) ? 1 : 0;
4896 vwrq->flags = IW_TXPOW_MWATT;
4901 #if WIRELESS_EXT > 10
4904 struct net_device *dev,
4905 struct iw_request_info *info,
4906 struct iw_param *vwrq,
4910 int error, lrl, srl;
4912 WL_TRACE(("%s: SIOCSIWRETRY\n", dev->name));
4915 if (vwrq->disabled || (vwrq->flags & IW_RETRY_LIFETIME))
4919 if (vwrq->flags & IW_RETRY_LIMIT) {
4922 #if WIRELESS_EXT > 20
4923 if ((vwrq->flags & IW_RETRY_LONG) ||(vwrq->flags & IW_RETRY_MAX) ||
4924 !((vwrq->flags & IW_RETRY_SHORT) || (vwrq->flags & IW_RETRY_MIN))) {
4926 if ((vwrq->flags & IW_RETRY_MAX) || !(vwrq->flags & IW_RETRY_MIN)) {
4928 lrl = htod32(vwrq->value);
4929 if ((error = dev_wlc_ioctl(dev, WLC_SET_LRL, &lrl, sizeof(lrl))))
4934 #if WIRELESS_EXT > 20
4935 if ((vwrq->flags & IW_RETRY_SHORT) ||(vwrq->flags & IW_RETRY_MIN) ||
4936 !((vwrq->flags & IW_RETRY_LONG) || (vwrq->flags & IW_RETRY_MAX))) {
4938 if ((vwrq->flags & IW_RETRY_MIN) || !(vwrq->flags & IW_RETRY_MAX)) {
4940 srl = htod32(vwrq->value);
4941 if ((error = dev_wlc_ioctl(dev, WLC_SET_SRL, &srl, sizeof(srl))))
4950 struct net_device *dev,
4951 struct iw_request_info *info,
4952 struct iw_param *vwrq,
4956 int error, lrl, srl;
4958 WL_TRACE(("%s: SIOCGIWRETRY\n", dev->name));
4963 if ((vwrq->flags & IW_RETRY_TYPE) == IW_RETRY_LIFETIME)
4967 if ((error = dev_wlc_ioctl(dev, WLC_GET_LRL, &lrl, sizeof(lrl))) ||
4968 (error = dev_wlc_ioctl(dev, WLC_GET_SRL, &srl, sizeof(srl))))
4975 if (vwrq->flags & IW_RETRY_MAX) {
4976 vwrq->flags = IW_RETRY_LIMIT | IW_RETRY_MAX;
4979 vwrq->flags = IW_RETRY_LIMIT;
4982 vwrq->flags |= IW_RETRY_MIN;
4991 struct net_device *dev,
4992 struct iw_request_info *info,
4993 struct iw_point *dwrq,
4998 int error, val, wsec;
5000 WL_TRACE(("%s: SIOCSIWENCODE index %d, len %d, flags %04x (%s%s%s%s%s)\n",
5001 dev->name, dwrq->flags & IW_ENCODE_INDEX, dwrq->length, dwrq->flags,
5002 dwrq->flags & IW_ENCODE_NOKEY ? "NOKEY" : "",
5003 dwrq->flags & IW_ENCODE_DISABLED ? " DISABLED" : "",
5004 dwrq->flags & IW_ENCODE_RESTRICTED ? " RESTRICTED" : "",
5005 dwrq->flags & IW_ENCODE_OPEN ? " OPEN" : "",
5006 dwrq->flags & IW_ENCODE_TEMP ? " TEMP" : ""));
5008 memset(&key, 0, sizeof(key));
5010 if ((dwrq->flags & IW_ENCODE_INDEX) == 0) {
5012 for (key.index = 0; key.index < DOT11_MAX_DEFAULT_KEYS; key.index++) {
5013 val = htod32(key.index);
5014 if ((error = dev_wlc_ioctl(dev, WLC_GET_KEY_PRIMARY, &val, sizeof(val))))
5021 if (key.index == DOT11_MAX_DEFAULT_KEYS)
5024 key.index = (dwrq->flags & IW_ENCODE_INDEX) - 1;
5025 if (key.index >= DOT11_MAX_DEFAULT_KEYS)
5030 if (!extra || !dwrq->length || (dwrq->flags & IW_ENCODE_NOKEY)) {
5032 val = htod32(key.index);
5033 if ((error = dev_wlc_ioctl(dev, WLC_SET_KEY_PRIMARY, &val, sizeof(val))))
5036 key.len = dwrq->length;
5038 if (dwrq->length > sizeof(key.data))
5041 memcpy(key.data, extra, dwrq->length);
5043 key.flags = WL_PRIMARY_KEY;
5046 key.algo = CRYPTO_ALGO_WEP1;
5048 case WEP128_KEY_SIZE:
5049 key.algo = CRYPTO_ALGO_WEP128;
5051 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 14)
5053 key.algo = CRYPTO_ALGO_TKIP;
5057 key.algo = CRYPTO_ALGO_AES_CCM;
5064 swap_key_from_BE(&key);
5065 if ((error = dev_wlc_ioctl(dev, WLC_SET_KEY, &key, sizeof(key))))
5070 val = (dwrq->flags & IW_ENCODE_DISABLED) ? 0 : WEP_ENABLED;
5072 if ((error = dev_wlc_intvar_get(dev, "wsec", &wsec)))
5075 wsec &= ~(WEP_ENABLED);
5078 if ((error = dev_wlc_intvar_set(dev, "wsec", wsec)))
5082 val = (dwrq->flags & IW_ENCODE_RESTRICTED) ? 1 : 0;
5084 if ((error = dev_wlc_ioctl(dev, WLC_SET_AUTH, &val, sizeof(val))))
5092 struct net_device *dev,
5093 struct iw_request_info *info,
5094 struct iw_point *dwrq,
5099 int error, val, wsec, auth;
5101 WL_TRACE(("%s: SIOCGIWENCODE\n", dev->name));
5104 bzero(&key, sizeof(wl_wsec_key_t));
5106 if ((dwrq->flags & IW_ENCODE_INDEX) == 0) {
5108 for (key.index = 0; key.index < DOT11_MAX_DEFAULT_KEYS; key.index++) {
5110 if ((error = dev_wlc_ioctl(dev, WLC_GET_KEY_PRIMARY, &val, sizeof(val))))
5117 key.index = (dwrq->flags & IW_ENCODE_INDEX) - 1;
5119 if (key.index >= DOT11_MAX_DEFAULT_KEYS)
5124 if ((error = dev_wlc_ioctl(dev, WLC_GET_WSEC, &wsec, sizeof(wsec))) ||
5125 (error = dev_wlc_ioctl(dev, WLC_GET_AUTH, &auth, sizeof(auth))))
5128 swap_key_to_BE(&key);
5130 wsec = dtoh32(wsec);
5131 auth = dtoh32(auth);
5133 dwrq->length = MIN(DOT11_MAX_KEY_SIZE, key.len);
5136 dwrq->flags = key.index + 1;
5137 if (!(wsec & (WEP_ENABLED | TKIP_ENABLED | AES_ENABLED))) {
5139 dwrq->flags |= IW_ENCODE_DISABLED;
5143 dwrq->flags |= IW_ENCODE_RESTRICTED;
5147 if (dwrq->length && extra)
5148 memcpy(extra, key.data, dwrq->length);
5155 struct net_device *dev,
5156 struct iw_request_info *info,
5157 struct iw_param *vwrq,
5163 WL_TRACE(("%s: SIOCSIWPOWER\n", dev->name));
5165 pm = vwrq->disabled ? PM_OFF : PM_MAX;
5168 if ((error = dev_wlc_ioctl(dev, WLC_SET_PM, &pm, sizeof(pm))))
5176 struct net_device *dev,
5177 struct iw_request_info *info,
5178 struct iw_param *vwrq,
5184 WL_TRACE(("%s: SIOCGIWPOWER\n", dev->name));
5186 if ((error = dev_wlc_ioctl(dev, WLC_GET_PM, &pm, sizeof(pm))))
5190 vwrq->disabled = pm ? 0 : 1;
5191 vwrq->flags = IW_POWER_ALL_R;
5196 #if WIRELESS_EXT > 17
5199 struct net_device *dev,
5200 struct iw_request_info *info,
5201 struct iw_point *iwp,
5206 WL_TRACE(("%s: SIOCSIWGENIE\n", dev->name));
5208 RETURN_IF_EXTRA_NULL(extra);
5214 for (i = 0; i < iwp->length; i++)
5215 WL_TRACE(("%02X ", extra[i]));
5220 dev_wlc_bufvar_set(dev, "wpaie", extra, iwp->length);
5227 struct net_device *dev,
5228 struct iw_request_info *info,
5229 struct iw_point *iwp,
5233 WL_TRACE(("%s: SIOCGIWGENIE\n", dev->name));
5235 dev_wlc_bufvar_get(dev, "wpaie", extra, iwp->length);
5240 wl_iw_set_encodeext(
5241 struct net_device *dev,
5242 struct iw_request_info *info,
5243 struct iw_point *dwrq,
5249 struct iw_encode_ext *iwe;
5251 WL_TRACE(("%s: SIOCSIWENCODEEXT\n", dev->name));
5253 RETURN_IF_EXTRA_NULL(extra);
5255 memset(&key, 0, sizeof(key));
5256 iwe = (struct iw_encode_ext *)extra;
5259 if (dwrq->flags & IW_ENCODE_DISABLED) {
5265 if (dwrq->flags & IW_ENCODE_INDEX)
5266 key.index = (dwrq->flags & IW_ENCODE_INDEX) - 1;
5268 key.len = iwe->key_len;
5271 if (!ETHER_ISMULTI(iwe->addr.sa_data))
5272 bcopy((void *)&iwe->addr.sa_data, (char *)&key.ea, ETHER_ADDR_LEN);
5276 if (iwe->ext_flags & IW_ENCODE_EXT_SET_TX_KEY) {
5277 WL_WSEC(("Changing the the primary Key to %d\n", key.index));
5279 key.index = htod32(key.index);
5280 error = dev_wlc_ioctl(dev, WLC_SET_KEY_PRIMARY,
5281 &key.index, sizeof(key.index));
5287 swap_key_from_BE(&key);
5288 dev_wlc_ioctl(dev, WLC_SET_KEY, &key, sizeof(key));
5292 if (iwe->key_len > sizeof(key.data))
5295 WL_WSEC(("Setting the key index %d\n", key.index));
5296 if (iwe->ext_flags & IW_ENCODE_EXT_SET_TX_KEY) {
5297 WL_WSEC(("key is a Primary Key\n"));
5298 key.flags = WL_PRIMARY_KEY;
5301 bcopy((void *)iwe->key, key.data, iwe->key_len);
5303 if (iwe->alg == IW_ENCODE_ALG_TKIP) {
5305 bcopy(&key.data[24], keybuf, sizeof(keybuf));
5306 bcopy(&key.data[16], &key.data[24], sizeof(keybuf));
5307 bcopy(keybuf, &key.data[16], sizeof(keybuf));
5311 if (iwe->ext_flags & IW_ENCODE_EXT_RX_SEQ_VALID) {
5313 ivptr = (uchar *)iwe->rx_seq;
5314 key.rxiv.hi = (ivptr[5] << 24) | (ivptr[4] << 16) |
5315 (ivptr[3] << 8) | ivptr[2];
5316 key.rxiv.lo = (ivptr[1] << 8) | ivptr[0];
5317 key.iv_initialized = TRUE;
5321 case IW_ENCODE_ALG_NONE:
5322 key.algo = CRYPTO_ALGO_OFF;
5324 case IW_ENCODE_ALG_WEP:
5325 if (iwe->key_len == WEP1_KEY_SIZE)
5326 key.algo = CRYPTO_ALGO_WEP1;
5328 key.algo = CRYPTO_ALGO_WEP128;
5330 case IW_ENCODE_ALG_TKIP:
5331 key.algo = CRYPTO_ALGO_TKIP;
5333 case IW_ENCODE_ALG_CCMP:
5334 key.algo = CRYPTO_ALGO_AES_CCM;
5339 swap_key_from_BE(&key);
5341 dhd_wait_pend8021x(dev);
5343 error = dev_wlc_ioctl(dev, WLC_SET_KEY, &key, sizeof(key));
5350 #if WIRELESS_EXT > 17
5352 pmkid_list_t pmkids;
5353 pmkid_t foo[MAXPMKID-1];
5358 struct net_device *dev,
5359 struct iw_request_info *info,
5360 struct iw_param *vwrq,
5364 struct iw_pmksa *iwpmksa;
5367 char eabuf[ETHER_ADDR_STR_LEN];
5368 pmkid_t * pmkid_array = pmkid_list.pmkids.pmkid;
5370 WL_WSEC(("%s: SIOCSIWPMKSA\n", dev->name));
5372 RETURN_IF_EXTRA_NULL(extra);
5374 iwpmksa = (struct iw_pmksa *)extra;
5375 bzero((char *)eabuf, ETHER_ADDR_STR_LEN);
5377 if (iwpmksa->cmd == IW_PMKSA_FLUSH) {
5378 WL_WSEC(("wl_iw_set_pmksa - IW_PMKSA_FLUSH\n"));
5379 bzero((char *)&pmkid_list, sizeof(pmkid_list));
5382 else if (iwpmksa->cmd == IW_PMKSA_REMOVE) {
5384 pmkid_list_t pmkid, *pmkidptr;
5388 bcopy(&iwpmksa->bssid.sa_data[0], &pmkidptr->pmkid[0].BSSID,
5390 bcopy(&iwpmksa->pmkid[0], &pmkidptr->pmkid[0].PMKID, WPA2_PMKID_LEN);
5392 WL_WSEC(("wl_iw_set_pmksa,IW_PMKSA_REMOVE - PMKID: %s = ",
5393 bcm_ether_ntoa(&pmkidptr->pmkid[0].BSSID,
5395 for (j = 0; j < WPA2_PMKID_LEN; j++)
5396 WL_WSEC(("%02x ", pmkidptr->pmkid[0].PMKID[j]));
5400 for (i = 0; i < pmkid_list.pmkids.npmkid; i++)
5401 if (!bcmp(&iwpmksa->bssid.sa_data[0], &pmkid_array[i].BSSID,
5405 if ((pmkid_list.pmkids.npmkid > 0) && (i < pmkid_list.pmkids.npmkid)) {
5406 bzero(&pmkid_array[i], sizeof(pmkid_t));
5407 for (; i < (pmkid_list.pmkids.npmkid - 1); i++) {
5408 bcopy(&pmkid_array[i+1].BSSID,
5409 &pmkid_array[i].BSSID,
5411 bcopy(&pmkid_array[i+1].PMKID,
5412 &pmkid_array[i].PMKID,
5415 pmkid_list.pmkids.npmkid--;
5421 else if (iwpmksa->cmd == IW_PMKSA_ADD) {
5422 for (i = 0; i < pmkid_list.pmkids.npmkid; i++)
5423 if (!bcmp(&iwpmksa->bssid.sa_data[0], &pmkid_array[i].BSSID,
5427 bcopy(&iwpmksa->bssid.sa_data[0],
5428 &pmkid_array[i].BSSID,
5430 bcopy(&iwpmksa->pmkid[0], &pmkid_array[i].PMKID,
5432 if (i == pmkid_list.pmkids.npmkid)
5433 pmkid_list.pmkids.npmkid++;
5441 k = pmkid_list.pmkids.npmkid;
5442 WL_WSEC(("wl_iw_set_pmksa,IW_PMKSA_ADD - PMKID: %s = ",
5443 bcm_ether_ntoa(&pmkid_array[k].BSSID,
5445 for (j = 0; j < WPA2_PMKID_LEN; j++)
5446 WL_WSEC(("%02x ", pmkid_array[k].PMKID[j]));
5450 WL_WSEC(("PRINTING pmkid LIST - No of elements %d", pmkid_list.pmkids.npmkid));
5451 for (i = 0; i < pmkid_list.pmkids.npmkid; i++) {
5453 WL_WSEC(("\nPMKID[%d]: %s = ", i,
5454 bcm_ether_ntoa(&pmkid_array[i].BSSID,
5456 for (j = 0; j < WPA2_PMKID_LEN; j++)
5457 WL_WSEC(("%02x ", pmkid_array[i].PMKID[j]));
5462 ret = dev_wlc_bufvar_set(dev, "pmkid_info", (char *)&pmkid_list,
5463 sizeof(pmkid_list));
5469 wl_iw_get_encodeext(
5470 struct net_device *dev,
5471 struct iw_request_info *info,
5472 struct iw_param *vwrq,
5476 WL_TRACE(("%s: SIOCGIWENCODEEXT\n", dev->name));
5482 wl_iw_create_wpaauth_wsec(struct net_device *dev)
5484 wl_iw_t *iw = NETDEV_PRIV(dev);
5488 if (iw->pcipher & (IW_AUTH_CIPHER_WEP40 | IW_AUTH_CIPHER_WEP104))
5490 else if (iw->pcipher & IW_AUTH_CIPHER_TKIP)
5491 wsec = TKIP_ENABLED;
5492 else if (iw->pcipher & IW_AUTH_CIPHER_CCMP)
5498 if (iw->gcipher & (IW_AUTH_CIPHER_WEP40 | IW_AUTH_CIPHER_WEP104))
5499 wsec |= WEP_ENABLED;
5500 else if (iw->gcipher & IW_AUTH_CIPHER_TKIP)
5501 wsec |= TKIP_ENABLED;
5502 else if (iw->gcipher & IW_AUTH_CIPHER_CCMP)
5503 wsec |= AES_ENABLED;
5506 if (wsec == 0 && iw->privacy_invoked)
5509 WL_INFORM(("%s: returning wsec of %d\n", __FUNCTION__, wsec));
5516 struct net_device *dev,
5517 struct iw_request_info *info,
5518 struct iw_param *vwrq,
5526 wl_iw_t *iw = NETDEV_PRIV(dev);
5528 paramid = vwrq->flags & IW_AUTH_INDEX;
5529 paramval = vwrq->value;
5531 WL_TRACE(("%s: SIOCSIWAUTH, %s(%d), paramval = 0x%0x\n",
5533 paramid == IW_AUTH_WPA_VERSION ? "IW_AUTH_WPA_VERSION" :
5534 paramid == IW_AUTH_CIPHER_PAIRWISE ? "IW_AUTH_CIPHER_PAIRWISE" :
5535 paramid == IW_AUTH_CIPHER_GROUP ? "IW_AUTH_CIPHER_GROUP" :
5536 paramid == IW_AUTH_KEY_MGMT ? "IW_AUTH_KEY_MGMT" :
5537 paramid == IW_AUTH_TKIP_COUNTERMEASURES ? "IW_AUTH_TKIP_COUNTERMEASURES" :
5538 paramid == IW_AUTH_DROP_UNENCRYPTED ? "IW_AUTH_DROP_UNENCRYPTED" :
5539 paramid == IW_AUTH_80211_AUTH_ALG ? "IW_AUTH_80211_AUTH_ALG" :
5540 paramid == IW_AUTH_WPA_ENABLED ? "IW_AUTH_WPA_ENABLED" :
5541 paramid == IW_AUTH_RX_UNENCRYPTED_EAPOL ? "IW_AUTH_RX_UNENCRYPTED_EAPOL" :
5542 paramid == IW_AUTH_ROAMING_CONTROL ? "IW_AUTH_ROAMING_CONTROL" :
5543 paramid == IW_AUTH_PRIVACY_INVOKED ? "IW_AUTH_PRIVACY_INVOKED" :
5545 paramid, paramval));
5548 if (ap_cfg_running) {
5549 WL_TRACE(("%s: Not executed, reason -'SOFTAP is active'\n", __FUNCTION__));
5555 case IW_AUTH_WPA_VERSION:
5557 if (paramval & IW_AUTH_WPA_VERSION_DISABLED)
5558 val = WPA_AUTH_DISABLED;
5559 else if (paramval & (IW_AUTH_WPA_VERSION_WPA))
5560 val = WPA_AUTH_PSK | WPA_AUTH_UNSPECIFIED;
5561 else if (paramval & IW_AUTH_WPA_VERSION_WPA2)
5562 val = WPA2_AUTH_PSK | WPA2_AUTH_UNSPECIFIED;
5563 WL_ERROR(("%s: %d: setting wpa_auth to 0x%0x\n", __FUNCTION__, __LINE__, val));
5564 if ((error = dev_wlc_intvar_set(dev, "wpa_auth", val)))
5568 case IW_AUTH_CIPHER_PAIRWISE:
5569 iw->pcipher = paramval;
5570 val = wl_iw_create_wpaauth_wsec(dev);
5571 if ((error = dev_wlc_intvar_set(dev, "wsec", val)))
5575 case IW_AUTH_CIPHER_GROUP:
5576 iw->gcipher = paramval;
5577 val = wl_iw_create_wpaauth_wsec(dev);
5578 if ((error = dev_wlc_intvar_set(dev, "wsec", val)))
5582 case IW_AUTH_KEY_MGMT:
5583 if ((error = dev_wlc_intvar_get(dev, "wpa_auth", &val)))
5586 if (val & (WPA_AUTH_PSK | WPA_AUTH_UNSPECIFIED)) {
5587 if (paramval & IW_AUTH_KEY_MGMT_PSK)
5590 val = WPA_AUTH_UNSPECIFIED;
5591 if (paramval & 0x04)
5592 val |= WPA2_AUTH_FT;
5594 else if (val & (WPA2_AUTH_PSK | WPA2_AUTH_UNSPECIFIED)) {
5595 if (paramval & IW_AUTH_KEY_MGMT_PSK)
5596 val = WPA2_AUTH_PSK;
5598 val = WPA2_AUTH_UNSPECIFIED;
5599 if (paramval & 0x04)
5600 val |= WPA2_AUTH_FT;
5603 else if (paramval & IW_AUTH_KEY_MGMT_PSK) {
5604 if (iw->wpaversion == IW_AUTH_WPA_VERSION_WPA)
5606 else if (iw->wpaversion == IW_AUTH_WPA_VERSION_WPA2)
5607 val = WPA2_AUTH_PSK;
5609 val = WPA_AUTH_DISABLED;
5610 } else if (paramval & IW_AUTH_KEY_MGMT_802_1X) {
5611 if (iw->wpaversion == IW_AUTH_WPA_VERSION_WPA)
5612 val = WPA_AUTH_UNSPECIFIED;
5613 else if (iw->wpaversion == IW_AUTH_WPA_VERSION_WPA2)
5614 val = WPA2_AUTH_UNSPECIFIED;
5616 val = WPA_AUTH_DISABLED;
5619 val = WPA_AUTH_DISABLED;
5621 WL_INFORM(("%s: %d: setting wpa_auth to %d\n", __FUNCTION__, __LINE__, val));
5622 if ((error = dev_wlc_intvar_set(dev, "wpa_auth", val)))
5626 case IW_AUTH_TKIP_COUNTERMEASURES:
5627 dev_wlc_bufvar_set(dev, "tkip_countermeasures", (char *)¶mval, 1);
5630 case IW_AUTH_80211_AUTH_ALG:
5632 WL_INFORM(("Setting the D11auth %d\n", paramval));
5633 if (paramval == IW_AUTH_ALG_OPEN_SYSTEM)
5635 else if (paramval == IW_AUTH_ALG_SHARED_KEY)
5637 else if (paramval == (IW_AUTH_ALG_OPEN_SYSTEM | IW_AUTH_ALG_SHARED_KEY))
5641 if (!error && (error = dev_wlc_intvar_set(dev, "auth", val)))
5645 case IW_AUTH_WPA_ENABLED:
5646 if (paramval == 0) {
5647 iw->privacy_invoked = 0;
5650 val = wl_iw_create_wpaauth_wsec(dev);
5651 if ((error = dev_wlc_intvar_set(dev, "wsec", val)))
5653 WL_INFORM(("%s: %d: setting wpa_auth to %d, wsec to %d\n",
5654 __FUNCTION__, __LINE__, paramval, val));
5655 dev_wlc_intvar_set(dev, "wpa_auth", paramval);
5662 case IW_AUTH_DROP_UNENCRYPTED:
5663 if ((error = dev_wlc_intvar_set(dev, "wsec_restrict", paramval)))
5667 case IW_AUTH_RX_UNENCRYPTED_EAPOL:
5668 dev_wlc_bufvar_set(dev, "rx_unencrypted_eapol", (char *)¶mval, 1);
5671 #if WIRELESS_EXT > 17
5672 case IW_AUTH_ROAMING_CONTROL:
5673 WL_INFORM(("%s: IW_AUTH_ROAMING_CONTROL\n", __FUNCTION__));
5677 case IW_AUTH_PRIVACY_INVOKED:
5678 iw->privacy_invoked = paramval;
5679 val = wl_iw_create_wpaauth_wsec(dev);
5680 if ((error = dev_wlc_intvar_set(dev, "wsec", val)))
5690 #define VAL_PSK(_val) (((_val) & WPA_AUTH_PSK) || ((_val) & WPA2_AUTH_PSK))
5694 struct net_device *dev,
5695 struct iw_request_info *info,
5696 struct iw_param *vwrq,
5704 wl_iw_t *iw = NETDEV_PRIV(dev);
5706 WL_TRACE(("%s: SIOCGIWAUTH\n", dev->name));
5708 paramid = vwrq->flags & IW_AUTH_INDEX;
5711 case IW_AUTH_WPA_VERSION:
5712 paramval = iw->wpaversion;
5715 case IW_AUTH_CIPHER_PAIRWISE:
5716 paramval = iw->pcipher;
5719 case IW_AUTH_CIPHER_GROUP:
5720 paramval = iw->gcipher;
5723 case IW_AUTH_KEY_MGMT:
5725 if ((error = dev_wlc_intvar_get(dev, "wpa_auth", &val)))
5728 paramval = IW_AUTH_KEY_MGMT_PSK;
5730 paramval = IW_AUTH_KEY_MGMT_802_1X;
5734 case IW_AUTH_TKIP_COUNTERMEASURES:
5735 dev_wlc_bufvar_get(dev, "tkip_countermeasures", (char *)¶mval, 1);
5738 case IW_AUTH_DROP_UNENCRYPTED:
5739 dev_wlc_intvar_get(dev, "wsec_restrict", ¶mval);
5742 case IW_AUTH_RX_UNENCRYPTED_EAPOL:
5743 dev_wlc_bufvar_get(dev, "rx_unencrypted_eapol", (char *)¶mval, 1);
5746 case IW_AUTH_80211_AUTH_ALG:
5748 if ((error = dev_wlc_intvar_get(dev, "auth", &val)))
5751 paramval = IW_AUTH_ALG_OPEN_SYSTEM;
5753 paramval = IW_AUTH_ALG_SHARED_KEY;
5755 case IW_AUTH_WPA_ENABLED:
5756 if ((error = dev_wlc_intvar_get(dev, "wpa_auth", &val)))
5763 #if WIRELESS_EXT > 17
5764 case IW_AUTH_ROAMING_CONTROL:
5765 WL_ERROR(("%s: IW_AUTH_ROAMING_CONTROL\n", __FUNCTION__));
5768 case IW_AUTH_PRIVACY_INVOKED:
5769 paramval = iw->privacy_invoked;
5774 vwrq->value = paramval;
5782 static int ap_macmode = MACLIST_MODE_DISABLED;
5783 static struct mflist ap_black_list;
5786 wl_iw_parse_wep(char *keystr, wl_wsec_key_t *key)
5789 unsigned char *data = key->data;
5791 switch (strlen(keystr)) {
5795 key->len = strlen(keystr);
5796 memcpy(data, keystr, key->len + 1);
5803 if (!strnicmp(keystr, "0x", 2))
5812 key->len = strlen(keystr) / 2;
5814 strncpy(hex, keystr, 2);
5815 *data++ = (char) bcm_strtoul(hex, NULL, 16);
5825 key->algo = CRYPTO_ALGO_WEP1;
5828 key->algo = CRYPTO_ALGO_WEP128;
5832 key->algo = CRYPTO_ALGO_AES_CCM;
5835 key->algo = CRYPTO_ALGO_TKIP;
5842 key->flags |= WL_PRIMARY_KEY;
5847 #ifdef EXT_WPA_CRYPTO
5848 #define SHA1HashSize 20
5849 extern void pbkdf2_sha1(const char *passphrase, const char *ssid, size_t ssid_len,
5850 int iterations, u8 *buf, size_t buflen);
5854 #define SHA1HashSize 20
5856 pbkdf2_sha1(const char *passphrase, const char *ssid, size_t ssid_len,
5857 int iterations, u8 *buf, size_t buflen)
5859 WL_ERROR(("WARNING: %s is not implemented !!!\n", __FUNCTION__));
5867 dev_iw_write_cfg1_bss_var(struct net_device *dev, int val)
5875 char smbuf[WLC_IOCTL_SMLEN];
5876 memset(smbuf, 0, sizeof(smbuf));
5879 bss_setbuf.val = val;
5881 bss_set_res = dev_iw_iovar_setbuf(dev, "bss",
5882 &bss_setbuf, sizeof(bss_setbuf), smbuf, sizeof(smbuf));
5883 WL_TRACE(("%s: bss_set_result:%d set with %d\n", __FUNCTION__, bss_set_res, val));
5901 const char *prefix = "bsscfg:";
5907 prefixlen = strlen(prefix);
5908 namelen = strlen(iovar) + 1;
5909 iolen = prefixlen + namelen + sizeof(int) + paramlen;
5912 if (buflen < 0 || iolen > (uint)buflen) {
5913 *perr = BCME_BUFTOOSHORT;
5920 memcpy(p, prefix, prefixlen);
5924 memcpy(p, iovar, namelen);
5928 bssidx = htod32(bssidx);
5929 memcpy(p, &bssidx, sizeof(int32));
5934 memcpy(p, param, paramlen);
5944 #define strtoul(nptr, endptr, base) bcm_strtoul((nptr), (endptr), (base))
5952 wl_iw_combined_scan_set(struct net_device *dev, wlc_ssid_t* ssids_local, int nssid, int nchan)
5954 int params_size = WL_SCAN_PARAMS_FIXED_SIZE + WL_NUMCHANNELS * sizeof(uint16);
5958 iscan_info_t *iscan = g_iscan;
5960 WL_TRACE(("%s nssid=%d nchan=%d\n", __FUNCTION__, nssid, nchan));
5962 if ((!dev) && (!g_iscan) && (!iscan->iscan_ex_params_p)) {
5963 WL_ERROR(("%s error exit\n", __FUNCTION__));
5970 if (dhd_dev_get_pno_status(dev)) {
5971 WL_ERROR(("%s: Scan called when PNO is active\n", __FUNCTION__));
5975 params_size += WL_SCAN_PARAMS_SSID_MAX * sizeof(wlc_ssid_t);
5979 i = OFFSETOF(wl_scan_params_t, channel_list) + nchan * sizeof(uint16);
5980 i = ROUNDUP(i, sizeof(uint32));
5981 if (i + nssid * sizeof(wlc_ssid_t) > params_size) {
5982 printf("additional ssids exceed params_size\n");
5987 p = ((char*)&iscan->iscan_ex_params_p->params) + i;
5988 memcpy(p, ssids_local, nssid * sizeof(wlc_ssid_t));
5989 p += nssid * sizeof(wlc_ssid_t);
5991 p = (char*)iscan->iscan_ex_params_p->params.channel_list + nchan * sizeof(uint16);
5995 iscan->iscan_ex_params_p->params.channel_num =
5996 htod32((nssid << WL_SCAN_PARAMS_NSSID_SHIFT) |
5997 (nchan & WL_SCAN_PARAMS_COUNT_MASK));
6000 ((iscan->iscan_ex_params_p->params.channel_num >> WL_SCAN_PARAMS_NSSID_SHIFT) &
6001 WL_SCAN_PARAMS_COUNT_MASK);
6004 params_size = (int) (p - (char*)iscan->iscan_ex_params_p + nssid * sizeof(wlc_ssid_t));
6005 iscan->iscan_ex_param_size = params_size;
6007 iscan->list_cur = iscan->list_hdr;
6008 iscan->iscan_state = ISCAN_STATE_SCANING;
6009 wl_iw_set_event_mask(dev);
6010 mod_timer(&iscan->timer, jiffies + iscan->timer_ms*HZ/1000);
6012 iscan->timer_on = 1;
6017 WL_SCAN(("\n### List of SSIDs to scan ###\n"));
6018 for (i = 0; i < nssid; i++) {
6019 if (!ssids_local[i].SSID_len)
6020 WL_SCAN(("%d: Broadcast scan\n", i));
6022 WL_SCAN(("%d: scan for %s size =%d\n", i,
6023 ssids_local[i].SSID, ssids_local[i].SSID_len));
6025 WL_SCAN(("### List of channels to scan ###\n"));
6026 for (i = 0; i < nchan; i++)
6028 WL_SCAN(("%d ", iscan->iscan_ex_params_p->params.channel_list[i]));
6030 WL_SCAN(("\nnprobes=%d\n", iscan->iscan_ex_params_p->params.nprobes));
6031 WL_SCAN(("active_time=%d\n", iscan->iscan_ex_params_p->params.active_time));
6032 WL_SCAN(("passive_time=%d\n", iscan->iscan_ex_params_p->params.passive_time));
6033 WL_SCAN(("home_time=%d\n", iscan->iscan_ex_params_p->params.home_time));
6034 WL_SCAN(("scan_type=%d\n", iscan->iscan_ex_params_p->params.scan_type));
6035 WL_SCAN(("\n###################\n"));
6039 if (params_size > WLC_IOCTL_MEDLEN) {
6040 WL_ERROR(("Set ISCAN for %s due to params_size=%d \n",
6041 __FUNCTION__, params_size));
6045 if ((err = dev_iw_iovar_setbuf(dev, "iscan", iscan->iscan_ex_params_p,
6046 iscan->iscan_ex_param_size,
6047 iscan->ioctlbuf, sizeof(iscan->ioctlbuf)))) {
6048 WL_TRACE(("Set ISCAN for %s failed with %d\n", __FUNCTION__, err));
6058 iwpriv_set_cscan(struct net_device *dev, struct iw_request_info *info,
6059 union iwreq_data *wrqu, char *ext)
6063 iscan_info_t *iscan = g_iscan;
6064 wlc_ssid_t ssids_local[WL_SCAN_PARAMS_SSID_MAX];
6069 WL_TRACE(("%s: info->cmd:%x, info->flags:%x, u.data=0x%p, u.len=%d\n",
6070 __FUNCTION__, info->cmd, info->flags,
6071 wrqu->data.pointer, wrqu->data.length));
6073 if (g_onoff == G_WLAN_SET_OFF) {
6074 WL_TRACE(("%s: driver is not up yet after START\n", __FUNCTION__));
6078 if (wrqu->data.length == 0) {
6079 WL_ERROR(("IWPRIV argument len = 0\n"));
6083 if (!iscan->iscan_ex_params_p) {
6087 if (!(extra = kmalloc(wrqu->data.length+1, GFP_KERNEL)))
6090 if (copy_from_user(extra, wrqu->data.pointer, wrqu->data.length)) {
6095 extra[wrqu->data.length] = 0;
6096 WL_ERROR(("Got str param in iw_point:\n %s\n", extra));
6101 if (strncmp(str_ptr, GET_SSID, strlen(GET_SSID))) {
6102 WL_ERROR(("%s Error: extracting SSID='' string\n", __FUNCTION__));
6107 str_ptr += strlen(GET_SSID);
6108 nssid = wl_iw_parse_ssid_list(&str_ptr, ssids_local, nssid,
6109 WL_SCAN_PARAMS_SSID_MAX);
6111 WL_ERROR(("%s wrong ssid list", __FUNCTION__));
6116 memset(iscan->iscan_ex_params_p, 0, iscan->iscan_ex_param_size);
6117 ASSERT(iscan->iscan_ex_param_size < WLC_IOCTL_MAXLEN);
6120 wl_iw_iscan_prep(&iscan->iscan_ex_params_p->params, NULL);
6121 iscan->iscan_ex_params_p->version = htod32(ISCAN_REQ_VERSION);
6122 iscan->iscan_ex_params_p->action = htod16(WL_SCAN_ACTION_START);
6123 iscan->iscan_ex_params_p->scan_duration = htod16(0);
6126 if ((nchan = wl_iw_parse_channel_list(&str_ptr,
6127 &iscan->iscan_ex_params_p->params.channel_list[0],
6128 WL_NUMCHANNELS)) == -1) {
6129 WL_ERROR(("%s missing channel list\n", __FUNCTION__));
6135 get_parameter_from_string(&str_ptr,
6136 GET_NPROBE, PTYPE_INTDEC,
6137 &iscan->iscan_ex_params_p->params.nprobes, 2);
6139 get_parameter_from_string(&str_ptr, GET_ACTIVE_ASSOC_DWELL, PTYPE_INTDEC,
6140 &iscan->iscan_ex_params_p->params.active_time, 4);
6142 get_parameter_from_string(&str_ptr, GET_PASSIVE_ASSOC_DWELL, PTYPE_INTDEC,
6143 &iscan->iscan_ex_params_p->params.passive_time, 4);
6145 get_parameter_from_string(&str_ptr, GET_HOME_DWELL, PTYPE_INTDEC,
6146 &iscan->iscan_ex_params_p->params.home_time, 4);
6148 get_parameter_from_string(&str_ptr, GET_SCAN_TYPE, PTYPE_INTDEC,
6149 &iscan->iscan_ex_params_p->params.scan_type, 1);
6152 res = wl_iw_combined_scan_set(dev, ssids_local, nssid, nchan);
6163 struct net_device *dev,
6164 struct iw_request_info *info,
6165 union iwreq_data *wrqu,
6170 iscan_info_t *iscan = g_iscan;
6171 wlc_ssid_t ssids_local[WL_SCAN_PARAMS_SSID_MAX];
6174 cscan_tlv_t *cscan_tlv_temp;
6180 char tlv_in_example[] = {
6181 'C', 'S', 'C', 'A', 'N', ' ',
6182 0x53, 0x01, 0x00, 0x00,
6198 WL_TRACE(("\n### %s: info->cmd:%x, info->flags:%x, u.data=0x%p, u.len=%d\n",
6199 __FUNCTION__, info->cmd, info->flags,
6200 wrqu->data.pointer, wrqu->data.length));
6202 net_os_wake_lock(dev);
6204 if (g_onoff == G_WLAN_SET_OFF) {
6205 WL_TRACE(("%s: driver is not up yet after START\n", __FUNCTION__));
6209 if (wrqu->data.length < (strlen(CSCAN_COMMAND) + sizeof(cscan_tlv_t))) {
6210 WL_ERROR(("%s argument=%d less %d\n", __FUNCTION__,
6211 wrqu->data.length, (int)(strlen(CSCAN_COMMAND) + sizeof(cscan_tlv_t))));
6216 memcpy(extra, tlv_in_example, sizeof(tlv_in_example));
6217 wrqu->data.length = sizeof(tlv_in_example);
6218 for (i = 0; i < wrqu->data.length; i++)
6219 printf("%02X ", extra[i]);
6224 str_ptr += strlen(CSCAN_COMMAND);
6225 tlv_size_left = wrqu->data.length - strlen(CSCAN_COMMAND);
6227 cscan_tlv_temp = (cscan_tlv_t *)str_ptr;
6228 memset(ssids_local, 0, sizeof(ssids_local));
6230 if ((cscan_tlv_temp->prefix == CSCAN_TLV_PREFIX) &&
6231 (cscan_tlv_temp->version == CSCAN_TLV_VERSION) &&
6232 (cscan_tlv_temp->subver == CSCAN_TLV_SUBVERSION))
6234 str_ptr += sizeof(cscan_tlv_t);
6235 tlv_size_left -= sizeof(cscan_tlv_t);
6238 if ((nssid = wl_iw_parse_ssid_list_tlv(&str_ptr, ssids_local,
6239 WL_SCAN_PARAMS_SSID_MAX, &tlv_size_left)) <= 0) {
6240 WL_ERROR(("SSID is not presented or corrupted ret=%d\n", nssid));
6245 memset(iscan->iscan_ex_params_p, 0, iscan->iscan_ex_param_size);
6248 wl_iw_iscan_prep(&iscan->iscan_ex_params_p->params, NULL);
6249 iscan->iscan_ex_params_p->version = htod32(ISCAN_REQ_VERSION);
6250 iscan->iscan_ex_params_p->action = htod16(WL_SCAN_ACTION_START);
6251 iscan->iscan_ex_params_p->scan_duration = htod16(0);
6254 while (tlv_size_left > 0)
6258 case CSCAN_TLV_TYPE_CHANNEL_IE:
6260 if ((nchan = wl_iw_parse_channel_list_tlv(&str_ptr,
6261 &iscan->iscan_ex_params_p->params.channel_list[0],
6262 WL_NUMCHANNELS, &tlv_size_left)) == -1) {
6263 WL_ERROR(("%s missing channel list\n",
6268 case CSCAN_TLV_TYPE_NPROBE_IE:
6269 if ((res = wl_iw_parse_data_tlv(&str_ptr,
6270 &iscan->iscan_ex_params_p->params.nprobes,
6271 sizeof(iscan->iscan_ex_params_p->params.nprobes),
6272 type, sizeof(char), &tlv_size_left)) == -1) {
6273 WL_ERROR(("%s return %d\n",
6274 __FUNCTION__, res));
6278 case CSCAN_TLV_TYPE_ACTIVE_IE:
6279 if ((res = wl_iw_parse_data_tlv(&str_ptr,
6280 &iscan->iscan_ex_params_p->params.active_time,
6281 sizeof(iscan->iscan_ex_params_p->params.active_time),
6282 type, sizeof(short), &tlv_size_left)) == -1) {
6283 WL_ERROR(("%s return %d\n",
6284 __FUNCTION__, res));
6288 case CSCAN_TLV_TYPE_PASSIVE_IE:
6289 if ((res = wl_iw_parse_data_tlv(&str_ptr,
6290 &iscan->iscan_ex_params_p->params.passive_time,
6291 sizeof(iscan->iscan_ex_params_p->params.passive_time),
6292 type, sizeof(short), &tlv_size_left)) == -1) {
6293 WL_ERROR(("%s return %d\n",
6294 __FUNCTION__, res));
6298 case CSCAN_TLV_TYPE_HOME_IE:
6299 if ((res = wl_iw_parse_data_tlv(&str_ptr,
6300 &iscan->iscan_ex_params_p->params.home_time,
6301 sizeof(iscan->iscan_ex_params_p->params.home_time),
6302 type, sizeof(short), &tlv_size_left)) == -1) {
6303 WL_ERROR(("%s return %d\n",
6304 __FUNCTION__, res));
6308 case CSCAN_TLV_TYPE_STYPE_IE:
6309 if ((res = wl_iw_parse_data_tlv(&str_ptr,
6310 &iscan->iscan_ex_params_p->params.scan_type,
6311 sizeof(iscan->iscan_ex_params_p->params.scan_type),
6312 type, sizeof(char), &tlv_size_left)) == -1) {
6313 WL_ERROR(("%s return %d\n",
6314 __FUNCTION__, res));
6320 WL_ERROR(("%s get unkwown type %X\n",
6321 __FUNCTION__, type));
6329 WL_ERROR(("%s get wrong TLV command\n", __FUNCTION__));
6333 #if defined(CONFIG_FIRST_SCAN)
6334 if (g_first_broadcast_scan < BROADCAST_SCAN_FIRST_RESULT_CONSUMED) {
6335 if (++g_first_counter_scans == MAX_ALLOWED_BLOCK_SCAN_FROM_FIRST_SCAN) {
6337 WL_ERROR(("%s Clean up First scan flag which is %d\n",
6338 __FUNCTION__, g_first_broadcast_scan));
6339 g_first_broadcast_scan = BROADCAST_SCAN_FIRST_RESULT_CONSUMED;
6342 WL_ERROR(("%s Ignoring CSCAN : First Scan is not done yet %d\n",
6343 __FUNCTION__, g_first_counter_scans));
6350 res = wl_iw_combined_scan_set(dev, ssids_local, nssid, nchan);
6353 net_os_wake_unlock(dev);
6361 wl_iw_del_wps_probe_req_ie(
6362 struct net_device *dev,
6363 struct iw_request_info *info,
6364 union iwreq_data *wrqu,
6369 vndr_ie_setbuf_t *ie_delbuf;
6371 if (g_wps_probe_req_ie) {
6372 ie_delbuf = (vndr_ie_setbuf_t *)(g_wps_probe_req_ie + strlen("vndr_ie "));
6373 strncpy(ie_delbuf->cmd, "del", 3);
6374 ie_delbuf->cmd[3] = '\0';
6376 ret = dev_wlc_ioctl(dev, WLC_SET_VAR, g_wps_probe_req_ie, g_wps_probe_req_ie_len);
6378 WL_ERROR(("ioctl failed %d \n", ret));
6381 kfree(g_wps_probe_req_ie);
6382 g_wps_probe_req_ie = NULL;
6383 g_wps_probe_req_ie_len = 0;
6390 wl_iw_add_wps_probe_req_ie(
6391 struct net_device *dev,
6392 struct iw_request_info *info,
6393 union iwreq_data *wrqu,
6397 char *str_ptr = NULL;
6398 char *bufptr = NULL;
6399 uint buflen, datalen, iecount, pktflag, iolen, total_len;
6401 vndr_ie_setbuf_t *ie_setbuf = NULL;
6403 if (!g_wps_probe_req_ie) {
6406 str_ptr += WPS_PROBE_REQ_IE_CMD_LENGTH;
6407 datalen = wrqu->data.length - WPS_PROBE_REQ_IE_CMD_LENGTH;
6411 buflen = sizeof(vndr_ie_setbuf_t) + datalen - sizeof(vndr_ie_t);
6412 ie_setbuf = (vndr_ie_setbuf_t *)kmalloc(buflen, GFP_KERNEL);
6414 WL_ERROR(("memory alloc failure ie_setbuf\n"));
6418 memset(ie_setbuf, 0x00, buflen);
6421 strncpy(ie_setbuf->cmd, "add", VNDR_IE_CMD_LEN - 1);
6422 ie_setbuf->cmd[VNDR_IE_CMD_LEN - 1] = '\0';
6425 iecount = htod32(1);
6426 memcpy((void *)&ie_setbuf->vndr_ie_buffer.iecount, &iecount, sizeof(int));
6430 memcpy((void *)&ie_setbuf->vndr_ie_buffer.vndr_ie_list[0].pktflag,
6431 &pktflag, sizeof(uint32));
6433 memcpy((void *)&ie_setbuf->vndr_ie_buffer.vndr_ie_list[0].vndr_ie_data,
6436 total_len = strlen("vndr_ie ") + buflen;
6437 bufptr = (char *)kmalloc(total_len, GFP_KERNEL);
6439 WL_ERROR(("memory alloc failure bufptr\n"));
6443 iolen = bcm_mkiovar("vndr_ie", (char *)ie_setbuf, buflen, bufptr, total_len);
6445 WL_ERROR(("Buffer length is illegal\n"));
6449 ret = dev_wlc_ioctl(dev, WLC_SET_VAR, bufptr, iolen);
6451 WL_ERROR(("ioctl failed\n"));
6455 g_wps_probe_req_ie = (char *)kmalloc(iolen, GFP_KERNEL);
6456 if (!g_wps_probe_req_ie) {
6457 WL_ERROR(("memory alloc failure g_wps_probe_req_ie\n"));
6461 memcpy(g_wps_probe_req_ie, bufptr, iolen);
6462 g_wps_probe_req_ie_len = iolen;
6485 thr_wait_for_2nd_eth_dev(void *data)
6489 unsigned long flags = 0;
6491 tsk_ctl_t *tsk_ctl = (tsk_ctl_t *)data;
6492 struct net_device *dev = (struct net_device *)tsk_ctl->parent;
6493 iw = *(wl_iw_t **)netdev_priv(dev);
6495 DAEMONIZE("wl0_eth_wthread");
6498 WL_SOFTAP(("\n>%s threda started:, PID:%x\n", __FUNCTION__, current->pid));
6500 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27))
6502 WL_ERROR(("%s: dev is null\n", __FUNCTION__));
6503 tsk_ctl->thr_pid = -1;
6504 complete(&tsk_ctl->completed);
6507 DHD_OS_WAKE_LOCK(iw->pub);
6508 complete(&tsk_ctl->completed);
6509 if (down_timeout(&tsk_ctl->sema, msecs_to_jiffies(1000)) != 0) {
6511 if (down_interruptible(&tsk_ctl->sema) != 0) {
6513 WL_ERROR(("\n%s: sap_eth_sema timeout \n", __FUNCTION__));
6518 SMP_RD_BARRIER_DEPENDS();
6519 if (tsk_ctl->terminated) {
6524 flags = dhd_os_spin_lock(iw->pub);
6526 WL_ERROR((" ap_net_dev is null !!!"));
6528 dhd_os_spin_unlock(iw->pub, flags);
6532 WL_SOFTAP(("\n>%s: Thread:'softap ethdev IF:%s is detected!'\n\n",
6533 __FUNCTION__, ap_net_dev->name));
6535 ap_cfg_running = TRUE;
6537 dhd_os_spin_unlock(iw->pub, flags);
6541 wl_iw_send_priv_event(priv_dev, "AP_SET_CFG_OK");
6545 DHD_OS_WAKE_UNLOCK(iw->pub);
6547 WL_SOFTAP(("\n>%s, thread completed\n", __FUNCTION__));
6549 complete_and_exit(&tsk_ctl->completed, 0);
6554 static int last_auto_channel = 6;
6558 get_softap_auto_channel(struct net_device *dev, struct ap_profile *ap)
6561 wl_uint32_list_t request;
6565 wlc_ssid_t null_ssid;
6570 int bsscfg_index = 1;
6571 char buf[WLC_IOCTL_SMLEN];
6573 WL_SOFTAP(("Enter %s\n", __FUNCTION__));
6576 if (ap_cfg_running) {
6577 ap->channel = last_auto_channel;
6582 memset(&null_ssid, 0, sizeof(wlc_ssid_t));
6583 res |= dev_wlc_ioctl(dev, WLC_UP, &updown, sizeof(updown));
6586 res |= dev_wlc_ioctl(dev, WLC_SET_SSID, &null_ssid, sizeof(null_ssid));
6589 iolen = wl_bssiovar_mkbuf("ssid", bsscfg_index, (char *)(&null_ssid),
6590 null_ssid.SSID_len+4, buf, sizeof(buf), &mkvar_err);
6592 res |= dev_wlc_ioctl(dev, WLC_SET_VAR, buf, iolen);
6596 request.count = htod32(0);
6597 ret = dev_wlc_ioctl(dev, WLC_START_CHANNEL_SEL, &request, sizeof(request));
6599 WL_ERROR(("can't start auto channel scan\n"));
6606 ret = dev_wlc_ioctl(dev, WLC_GET_CHANNEL_SEL, &chosen, sizeof(chosen));
6607 if (ret < 0 || dtoh32(chosen) == 0) {
6609 goto get_channel_retry;
6612 WL_ERROR(("can't get auto channel sel, err = %d, "
6613 "chosen = 0x%04X\n", ret, (uint16)chosen));
6616 ap->channel = (uint16)last_auto_channel;
6617 WL_ERROR(("auto channel sel timed out. we get channel %d\n",
6624 ap->channel = (uint16)chosen & 0x00FF;
6625 WL_SOFTAP(("%s: Got auto channel = %d, attempt:%d\n",
6626 __FUNCTION__, ap->channel, retry));
6629 if ((res = dev_wlc_ioctl(dev, WLC_DOWN, &updown, sizeof(updown))) < 0) {
6630 WL_ERROR(("%s fail to set up err =%d\n", __FUNCTION__, res));
6636 last_auto_channel = ap->channel;
6641 WL_TRACE(("%s: return value %d\n", __FUNCTION__, ret));
6649 set_ap_cfg(struct net_device *dev, struct ap_profile *ap)
6663 int bsscfg_index = 1;
6664 char buf[WLC_IOCTL_SMLEN];
6668 WL_ERROR(("%s: dev is null\n", __FUNCTION__));
6672 net_os_wake_lock(dev);
6673 DHD_OS_MUTEX_LOCK(&wl_softap_lock);
6675 WL_SOFTAP(("wl_iw: set ap profile:\n"));
6676 WL_SOFTAP((" ssid = '%s'\n", ap->ssid));
6677 WL_SOFTAP((" security = '%s'\n", ap->sec));
6678 if (ap->key[0] != '\0')
6679 WL_SOFTAP((" key = '%s'\n", ap->key));
6680 WL_SOFTAP((" channel = %d\n", ap->channel));
6681 WL_SOFTAP((" max scb = %d\n", ap->max_scb));
6684 if (ap_cfg_running) {
6685 wl_iw_softap_deassoc_stations(dev, NULL);
6686 ap_cfg_running = FALSE;
6691 if (ap_cfg_running == FALSE) {
6696 sema_init(&ap_eth_ctl.sema, 0);
6699 if ((res = dev_wlc_intvar_set(dev, "mpc", mpc))) {
6700 WL_ERROR(("%s fail to set mpc\n", __FUNCTION__));
6706 if ((res = dev_wlc_ioctl(dev, WLC_DOWN, &updown, sizeof(updown)))) {
6707 WL_ERROR(("%s fail to set updown\n", __FUNCTION__));
6714 if ((res = dev_wlc_ioctl(dev, WLC_SET_AP, &apsta_var, sizeof(apsta_var)))) {
6715 WL_ERROR(("%s fail to set apsta_var 0\n", __FUNCTION__));
6719 if ((res = dev_wlc_ioctl(dev, WLC_SET_AP, &apsta_var, sizeof(apsta_var)))) {
6720 WL_ERROR(("%s fail to set apsta_var 1\n", __FUNCTION__));
6723 res = dev_wlc_ioctl(dev, WLC_GET_AP, &apsta_var, sizeof(apsta_var));
6727 iolen = wl_bssiovar_mkbuf("apsta",
6728 bsscfg_index, &apsta_var, sizeof(apsta_var)+4,
6729 buf, sizeof(buf), &mkvar_err);
6731 if ((res = dev_wlc_ioctl(dev, WLC_SET_VAR, buf, iolen)) < 0) {
6732 WL_ERROR(("%s fail to set apsta \n", __FUNCTION__));
6735 WL_TRACE(("\n>in %s: apsta set result: %d \n", __FUNCTION__, res));
6739 if ((res = dev_wlc_intvar_set(dev, "mpc", mpc))) {
6740 WL_ERROR(("%s fail to set mpc\n", __FUNCTION__));
6748 if ((res = dev_wlc_ioctl(dev, WLC_UP, &updown, sizeof(updown))) < 0) {
6749 WL_ERROR(("%s fail to set apsta \n", __FUNCTION__));
6756 WL_ERROR(("%s: ap_net_dev is null\n", __FUNCTION__));
6760 res = wl_iw_softap_deassoc_stations(ap_net_dev, NULL);
6763 if ((res = dev_iw_write_cfg1_bss_var(dev, 0)) < 0) {
6764 WL_ERROR(("%s fail to set bss down\n", __FUNCTION__));
6770 if (strlen(ap->country_code)) {
6771 WL_ERROR(("%s: Igonored: Country MUST be specified"
6772 "COUNTRY command with \n", __FUNCTION__));
6774 WL_SOFTAP(("%s: Country code is not specified,"
6775 " will use Radio's default\n",
6779 iolen = wl_bssiovar_mkbuf("closednet",
6780 bsscfg_index, &ap->closednet, sizeof(ap->closednet)+4,
6781 buf, sizeof(buf), &mkvar_err);
6783 if ((res = dev_wlc_ioctl(dev, WLC_SET_VAR, buf, iolen)) < 0) {
6784 WL_ERROR(("%s failed to set 'closednet'for apsta \n", __FUNCTION__));
6789 if ((ap->channel == 0) && (get_softap_auto_channel(dev, ap) < 0)) {
6791 WL_ERROR(("%s auto channel failed, use channel=%d\n",
6792 __FUNCTION__, ap->channel));
6795 channel = ap->channel;
6796 if ((res = dev_wlc_ioctl(dev, WLC_SET_CHANNEL, &channel, sizeof(channel)))) {
6797 WL_ERROR(("%s fail to set channel\n", __FUNCTION__));
6801 if (ap_cfg_running == FALSE) {
6803 if ((res = dev_wlc_ioctl(dev, WLC_UP, &updown, sizeof(updown)))) {
6804 WL_ERROR(("%s fail to set up\n", __FUNCTION__));
6809 max_assoc = ap->max_scb;
6810 if ((res = dev_wlc_intvar_set(dev, "maxassoc", max_assoc))) {
6811 WL_ERROR(("%s fail to set maxassoc\n", __FUNCTION__));
6815 ap_ssid.SSID_len = strlen(ap->ssid);
6816 strncpy(ap_ssid.SSID, ap->ssid, ap_ssid.SSID_len);
6820 if ((res = wl_iw_set_ap_security(dev, &my_ap)) != 0) {
6821 WL_ERROR(("ERROR:%d in:%s, wl_iw_set_ap_security is skipped\n",
6822 res, __FUNCTION__));
6825 wl_iw_send_priv_event(dev, "ASCII_CMD=AP_BSS_START");
6826 ap_cfg_running = TRUE;
6829 iolen = wl_bssiovar_mkbuf("ssid", bsscfg_index, (char *)(&ap_ssid),
6830 ap_ssid.SSID_len+4, buf, sizeof(buf), &mkvar_err);
6832 if ((res = dev_wlc_ioctl(dev, WLC_SET_VAR, buf, iolen)) != 0) {
6833 WL_ERROR(("ERROR:%d in:%s, Security & BSS reconfiguration is skipped\n",
6834 res, __FUNCTION__));
6837 if (ap_cfg_running == FALSE) {
6839 PROC_START(thr_wait_for_2nd_eth_dev, dev, &ap_eth_ctl, 0);
6841 ap_eth_ctl.thr_pid = -1;
6843 if (ap_net_dev == NULL) {
6844 WL_ERROR(("%s ERROR: ap_net_dev is NULL !!!\n", __FUNCTION__));
6848 WL_ERROR(("%s: %s Configure security & restart AP bss \n",
6849 __FUNCTION__, ap_net_dev->name));
6852 if ((res = wl_iw_set_ap_security(ap_net_dev, &my_ap)) < 0) {
6853 WL_ERROR(("%s fail to set security : %d\n", __FUNCTION__, res));
6858 if ((res = dev_iw_write_cfg1_bss_var(dev, 1)) < 0) {
6859 WL_ERROR(("%s fail to set bss up\n", __FUNCTION__));
6865 WL_SOFTAP(("%s exit with %d\n", __FUNCTION__, res));
6867 DHD_OS_MUTEX_UNLOCK(&wl_softap_lock);
6868 net_os_wake_unlock(dev);
6877 wl_iw_set_ap_security(struct net_device *dev, struct ap_profile *ap)
6890 WL_SOFTAP(("\nsetting SOFTAP security mode:\n"));
6891 WL_SOFTAP(("wl_iw: set ap profile:\n"));
6892 WL_SOFTAP((" ssid = '%s'\n", ap->ssid));
6893 WL_SOFTAP((" security = '%s'\n", ap->sec));
6894 if (ap->key[0] != '\0')
6895 WL_SOFTAP((" key = '%s'\n", ap->key));
6896 WL_SOFTAP((" channel = %d\n", ap->channel));
6897 WL_SOFTAP((" max scb = %d\n", ap->max_scb));
6900 if (strnicmp(ap->sec, "open", strlen("open")) == 0) {
6904 res = dev_wlc_intvar_set(dev, "wsec", wsec);
6905 wpa_auth = WPA_AUTH_DISABLED;
6906 res |= dev_wlc_intvar_set(dev, "wpa_auth", wpa_auth);
6908 WL_SOFTAP(("=====================\n"));
6909 WL_SOFTAP((" wsec & wpa_auth set 'OPEN', result:&d %d\n", res));
6910 WL_SOFTAP(("=====================\n"));
6912 } else if (strnicmp(ap->sec, "wep", strlen("wep")) == 0) {
6915 memset(&key, 0, sizeof(key));
6918 res = dev_wlc_intvar_set(dev, "wsec", wsec);
6921 if (wl_iw_parse_wep(ap->key, &key)) {
6922 WL_SOFTAP(("wep key parse err!\n"));
6926 key.index = htod32(key.index);
6927 key.len = htod32(key.len);
6928 key.algo = htod32(key.algo);
6929 key.flags = htod32(key.flags);
6931 res |= dev_wlc_ioctl(dev, WLC_SET_KEY, &key, sizeof(key));
6933 wpa_auth = WPA_AUTH_DISABLED;
6934 res |= dev_wlc_intvar_set(dev, "wpa_auth", wpa_auth);
6936 WL_SOFTAP(("=====================\n"));
6937 WL_SOFTAP((" wsec & auth set 'WEP', result:&d %d\n", res));
6938 WL_SOFTAP(("=====================\n"));
6940 } else if (strnicmp(ap->sec, "wpa2-psk", strlen("wpa2-psk")) == 0) {
6948 dev_wlc_intvar_set(dev, "wsec", wsec);
6950 key_len = strlen(ap->key);
6951 if (key_len < WSEC_MIN_PSK_LEN || key_len > WSEC_MAX_PSK_LEN) {
6952 WL_SOFTAP(("passphrase must be between %d and %d characters long\n",
6953 WSEC_MIN_PSK_LEN, WSEC_MAX_PSK_LEN));
6958 if (key_len < WSEC_MAX_PSK_LEN) {
6959 unsigned char output[2*SHA1HashSize];
6960 char key_str_buf[WSEC_MAX_PSK_LEN+1];
6963 memset(output, 0, sizeof(output));
6964 pbkdf2_sha1(ap->key, ap->ssid, strlen(ap->ssid), 4096, output, 32);
6967 for (i = 0; i < (WSEC_MAX_PSK_LEN/8); i++) {
6969 sprintf(ptr, "%02x%02x%02x%02x", (uint)output[i*4],
6970 (uint)output[i*4+1], (uint)output[i*4+2],
6971 (uint)output[i*4+3]);
6974 WL_SOFTAP(("%s: passphase = %s\n", __FUNCTION__, key_str_buf));
6976 psk.key_len = htod16((ushort)WSEC_MAX_PSK_LEN);
6977 memcpy(psk.key, key_str_buf, psk.key_len);
6979 psk.key_len = htod16((ushort) key_len);
6980 memcpy(psk.key, ap->key, key_len);
6982 psk.flags = htod16(WSEC_PASSPHRASE);
6983 dev_wlc_ioctl(dev, WLC_SET_WSEC_PMK, &psk, sizeof(psk));
6985 wpa_auth = WPA2_AUTH_PSK;
6986 dev_wlc_intvar_set(dev, "wpa_auth", wpa_auth);
6988 } else if (strnicmp(ap->sec, "wpa-psk", strlen("wpa-psk")) == 0) {
6994 wsec = TKIP_ENABLED;
6995 res = dev_wlc_intvar_set(dev, "wsec", wsec);
6997 key_len = strlen(ap->key);
6998 if (key_len < WSEC_MIN_PSK_LEN || key_len > WSEC_MAX_PSK_LEN) {
6999 WL_SOFTAP(("passphrase must be between %d and %d characters long\n",
7000 WSEC_MIN_PSK_LEN, WSEC_MAX_PSK_LEN));
7005 if (key_len < WSEC_MAX_PSK_LEN) {
7006 unsigned char output[2*SHA1HashSize];
7007 char key_str_buf[WSEC_MAX_PSK_LEN+1];
7008 bzero(output, 2*SHA1HashSize);
7010 WL_SOFTAP(("%s: do passhash...\n", __FUNCTION__));
7012 pbkdf2_sha1(ap->key, ap->ssid, strlen(ap->ssid), 4096, output, 32);
7015 for (i = 0; i < (WSEC_MAX_PSK_LEN/8); i++) {
7016 WL_SOFTAP(("[%02d]: %08x\n", i, *((unsigned int*)&output[i*4])));
7018 sprintf(ptr, "%02x%02x%02x%02x", (uint)output[i*4],
7019 (uint)output[i*4+1], (uint)output[i*4+2],
7020 (uint)output[i*4+3]);
7023 printk("%s: passphase = %s\n", __FUNCTION__, key_str_buf);
7025 psk.key_len = htod16((ushort)WSEC_MAX_PSK_LEN);
7026 memcpy(psk.key, key_str_buf, psk.key_len);
7028 psk.key_len = htod16((ushort) key_len);
7029 memcpy(psk.key, ap->key, key_len);
7032 psk.flags = htod16(WSEC_PASSPHRASE);
7033 res |= dev_wlc_ioctl(dev, WLC_SET_WSEC_PMK, &psk, sizeof(psk));
7035 wpa_auth = WPA_AUTH_PSK;
7036 res |= dev_wlc_intvar_set(dev, "wpa_auth", wpa_auth);
7038 WL_SOFTAP((" wsec & auth set 'wpa-psk' (TKIP), result:&d %d\n", res));
7042 ap_ssid.SSID_len = strlen(ap->ssid);
7043 strncpy(ap_ssid.SSID, ap->ssid, ap_ssid.SSID_len);
7044 res |= dev_wlc_ioctl(dev, WLC_SET_SSID, &ap_ssid, sizeof(ap_ssid));
7046 res |= dev_wlc_intvar_set(dev, "mpc", mpc);
7047 if (strnicmp(ap->sec, "wep", strlen("wep")) == 0) {
7048 res |= dev_wlc_ioctl(dev, WLC_SET_KEY, &key, sizeof(key));
7057 get_parameter_from_string(
7058 char **str_ptr, const char *token,
7059 int param_type, void *dst, int param_max_len)
7061 char int_str[7] = "0";
7063 char *param_str_begin;
7064 char *param_str_end;
7065 char *orig_str = *str_ptr;
7067 if ((*str_ptr) && !strncmp(*str_ptr, token, strlen(token))) {
7069 strsep(str_ptr, "=,");
7070 param_str_begin = *str_ptr;
7071 strsep(str_ptr, "=,");
7073 if (*str_ptr == NULL) {
7075 parm_str_len = strlen(param_str_begin);
7077 param_str_end = *str_ptr-1;
7078 parm_str_len = param_str_end - param_str_begin;
7081 WL_TRACE((" 'token:%s', len:%d, ", token, parm_str_len));
7083 if (parm_str_len > param_max_len) {
7084 WL_ERROR((" WARNING: extracted param len:%d is > MAX:%d\n",
7085 parm_str_len, param_max_len));
7087 parm_str_len = param_max_len;
7090 switch (param_type) {
7092 case PTYPE_INTDEC: {
7094 int *pdst_int = dst;
7097 if (parm_str_len > sizeof(int_str))
7098 parm_str_len = sizeof(int_str);
7100 memcpy(int_str, param_str_begin, parm_str_len);
7102 *pdst_int = simple_strtoul(int_str, &eptr, 10);
7104 WL_TRACE((" written as integer:%d\n", *pdst_int));
7107 case PTYPE_STR_HEX: {
7110 param_max_len = param_max_len >> 1;
7111 hstr_2_buf(param_str_begin, buf, param_max_len);
7112 dhd_print_buf(buf, param_max_len, 0);
7117 memcpy(dst, param_str_begin, parm_str_len);
7118 *((char *)dst + parm_str_len) = 0;
7119 WL_ERROR((" written as a string:%s\n", (char *)dst));
7126 WL_ERROR(("\n %s: ERROR: can't find token:%s in str:%s \n",
7127 __FUNCTION__, token, orig_str));
7133 static int wl_iw_softap_deassoc_stations(struct net_device *dev, u8 *mac)
7137 char mac_buf[128] = {0};
7138 char z_mac[6] = {0, 0, 0, 0, 0, 0};
7140 struct maclist *assoc_maclist = (struct maclist *) mac_buf;
7141 bool deauth_all = FALSE;
7151 memset(assoc_maclist, 0, sizeof(mac_buf));
7152 assoc_maclist->count = 8;
7154 res = dev_wlc_ioctl(dev, WLC_GET_ASSOCLIST, assoc_maclist, 128);
7156 WL_SOFTAP(("%s: Error:%d Couldn't get ASSOC List\n", __FUNCTION__, res));
7160 if (assoc_maclist->count)
7161 for (i = 0; i < assoc_maclist->count; i++) {
7163 scbval.val = htod32(1);
7165 bcopy(&assoc_maclist->ea[i], &scbval.ea, ETHER_ADDR_LEN);
7167 if (deauth_all || (memcmp(&scbval.ea, sta_mac, ETHER_ADDR_LEN) == 0)) {
7169 WL_SOFTAP(("%s, deauth STA:%d \n", __FUNCTION__, i));
7170 res |= dev_wlc_ioctl(dev, WLC_SCB_DEAUTHENTICATE_FOR_REASON,
7171 &scbval, sizeof(scb_val_t));
7173 } else WL_SOFTAP(("%s: No Stations \n", __FUNCTION__));
7176 WL_ERROR(("%s: Error:%d\n", __FUNCTION__, res));
7177 } else if (assoc_maclist->count) {
7187 iwpriv_softap_stop(struct net_device *dev,
7188 struct iw_request_info *info,
7189 union iwreq_data *wrqu,
7194 WL_SOFTAP(("got iwpriv AP_BSS_STOP \n"));
7196 if ((!dev) && (!ap_net_dev)) {
7197 WL_ERROR(("%s: dev is null\n", __FUNCTION__));
7201 net_os_wake_lock(dev);
7202 DHD_OS_MUTEX_LOCK(&wl_softap_lock);
7204 if ((ap_cfg_running == TRUE)) {
7206 wl_iw_softap_deassoc_stations(dev, NULL);
7208 wl_iw_softap_deassoc_stations(ap_net_dev, NULL);
7209 if ((res = dev_iw_write_cfg1_bss_var(dev, 2)) < 0)
7210 WL_ERROR(("%s failed to del BSS err = %d", __FUNCTION__, res));
7216 wrqu->data.length = 0;
7217 ap_cfg_running = FALSE;
7219 WL_ERROR(("%s: was called when SoftAP is OFF : move on\n", __FUNCTION__));
7221 WL_SOFTAP(("%s Done with %d\n", __FUNCTION__, res));
7222 DHD_OS_MUTEX_UNLOCK(&wl_softap_lock);
7223 net_os_wake_unlock(dev);
7231 iwpriv_fw_reload(struct net_device *dev,
7232 struct iw_request_info *info,
7233 union iwreq_data *wrqu,
7238 char *fwstr = fw_path ;
7240 WL_SOFTAP(("current firmware_path[]=%s\n", fwstr));
7242 WL_TRACE((">Got FW_RELOAD cmd:"
7243 "info->cmd:%x, info->flags:%x, u.data:%p, u.len:%d, "
7244 "fw_path:%p, len:%d \n",
7245 info->cmd, info->flags,
7246 wrqu->data.pointer, wrqu->data.length, fwstr, strlen(fwstr)));
7248 if ((wrqu->data.length > 4) && (wrqu->data.length < sizeof(extra))) {
7251 if (copy_from_user(extra, wrqu->data.pointer, wrqu->data.length)) {
7257 extra[wrqu->data.length] = 8;
7260 if (get_parameter_from_string(&str_ptr,
7261 "FW_PATH=", PTYPE_STRING, fwstr, 255) != 0) {
7262 WL_ERROR(("Error: extracting FW_PATH='' string\n"));
7266 if (strstr(fwstr, "apsta") != NULL) {
7267 WL_SOFTAP(("GOT APSTA FIRMWARE\n"));
7268 ap_fw_loaded = TRUE;
7270 WL_SOFTAP(("GOT STA FIRMWARE\n"));
7271 ap_fw_loaded = FALSE;
7274 WL_SOFTAP(("SET firmware_path[]=%s , str_p:%p\n", fwstr, fwstr));
7277 WL_ERROR(("Error: ivalid param len:%d\n", wrqu->data.length));
7287 iwpriv_wpasupp_loop_tst(struct net_device *dev,
7288 struct iw_request_info *info,
7289 union iwreq_data *wrqu,
7293 char *params = NULL;
7295 WL_TRACE((">Got IWPRIV wp_supp loopback cmd test:"
7296 "info->cmd:%x, info->flags:%x, u.data:%p, u.len:%d\n",
7297 info->cmd, info->flags,
7298 wrqu->data.pointer, wrqu->data.length));
7300 if (wrqu->data.length != 0) {
7302 if (!(params = kmalloc(wrqu->data.length+1, GFP_KERNEL)))
7306 if (copy_from_user(params, wrqu->data.pointer, wrqu->data.length)) {
7311 params[wrqu->data.length] = 0;
7312 WL_SOFTAP(("\n>> copied from user:\n %s\n", params));
7314 WL_ERROR(("ERROR param length is 0\n"));
7319 res = wl_iw_send_priv_event(dev, params);
7329 struct net_device *dev,
7330 struct iw_request_info *info,
7337 WL_ERROR(("%s: dev is null\n", __FUNCTION__));
7341 net_os_wake_lock(dev);
7342 DHD_OS_MUTEX_LOCK(&wl_softap_lock);
7344 WL_TRACE(("%s: rcvd IWPRIV IOCTL: for dev:%s\n", __FUNCTION__, dev->name));
7348 if ((res = wl_iw_set_ap_security(dev, &my_ap)) != 0) {
7349 WL_ERROR((" %s ERROR setting SOFTAP security in :%d\n", __FUNCTION__, res));
7353 if ((res = dev_iw_write_cfg1_bss_var(dev, 1)) < 0)
7354 WL_ERROR(("%s fail to set bss up err=%d\n", __FUNCTION__, res));
7361 WL_SOFTAP(("%s done with res %d \n", __FUNCTION__, res));
7363 DHD_OS_MUTEX_UNLOCK(&wl_softap_lock);
7364 net_os_wake_unlock(dev);
7370 get_assoc_sta_list(struct net_device *dev, char *buf, int len)
7373 WL_TRACE(("%s: dev_wlc_ioctl(dev:%p, cmd:%d, buf:%p, len:%d)\n",
7374 __FUNCTION__, dev, WLC_GET_ASSOCLIST, buf, len));
7376 return dev_wlc_ioctl(dev, WLC_GET_ASSOCLIST, buf, len);
7381 void check_error(int res, const char *msg, const char *func, int line)
7384 WL_ERROR(("%s, %d function:%s, line:%d\n", msg, res, func, line));
7388 set_ap_mac_list(struct net_device *dev, void *buf)
7390 struct mac_list_set *mac_list_set = (struct mac_list_set *)buf;
7391 struct maclist *maclist = (struct maclist *)&mac_list_set->mac_list;
7394 int mac_mode = mac_list_set->mode;
7396 ap_macmode = mac_list_set->mode;
7399 bzero(&ap_black_list, sizeof(struct mflist));
7401 if (mac_mode == MACLIST_MODE_DISABLED) {
7403 ioc_res = dev_wlc_ioctl(dev, WLC_SET_MACMODE, &mac_mode, sizeof(mac_mode));
7404 check_error(ioc_res, "ioctl ERROR:", __FUNCTION__, __LINE__);
7405 WL_SOFTAP(("%s: MAC filtering disabled\n", __FUNCTION__));
7409 char mac_buf[256] = {0};
7410 struct maclist *assoc_maclist = (struct maclist *) mac_buf;
7413 bcopy(maclist, &ap_black_list, sizeof(ap_black_list));
7416 ioc_res = dev_wlc_ioctl(dev, WLC_SET_MACMODE, &mac_mode, sizeof(mac_mode));
7417 check_error(ioc_res, "ioctl ERROR:", __FUNCTION__, __LINE__);
7420 length = sizeof(maclist->count) + maclist->count*ETHER_ADDR_LEN;
7421 dev_wlc_ioctl(dev, WLC_SET_MACLIST, maclist, length);
7423 WL_SOFTAP(("%s: applied MAC List, mode:%d, length %d:\n",
7424 __FUNCTION__, mac_mode, length));
7426 for (i = 0; i < maclist->count; i++)
7427 WL_SOFTAP(("mac %d: %02X:%02X:%02X:%02X:%02X:%02X\n",
7428 i, maclist->ea[i].octet[0], maclist->ea[i].octet[1],
7429 maclist->ea[i].octet[2],
7430 maclist->ea[i].octet[3], maclist->ea[i].octet[4],
7431 maclist->ea[i].octet[5]));
7434 assoc_maclist->count = 8;
7435 ioc_res = dev_wlc_ioctl(dev, WLC_GET_ASSOCLIST, assoc_maclist, 256);
7436 check_error(ioc_res, "ioctl ERROR:", __FUNCTION__, __LINE__);
7437 WL_SOFTAP((" Cur assoc clients:%d\n", assoc_maclist->count));
7440 if (assoc_maclist->count)
7441 for (i = 0; i < assoc_maclist->count; i++) {
7443 bool assoc_mac_matched = FALSE;
7445 WL_SOFTAP(("\n Cheking assoc STA: "));
7446 dhd_print_buf(&assoc_maclist->ea[i], 6, 7);
7447 WL_SOFTAP(("with the b/w list:"));
7449 for (j = 0; j < maclist->count; j++)
7450 if (!bcmp(&assoc_maclist->ea[i], &maclist->ea[j],
7453 assoc_mac_matched = TRUE;
7458 if (((mac_mode == MACLIST_MODE_ALLOW) && !assoc_mac_matched) ||
7459 ((mac_mode == MACLIST_MODE_DENY) && assoc_mac_matched)) {
7461 WL_SOFTAP(("b-match or w-mismatch,"
7462 " do deauth/disassoc \n"));
7463 scbval.val = htod32(1);
7464 bcopy(&assoc_maclist->ea[i], &scbval.ea,
7466 ioc_res = dev_wlc_ioctl(dev,
7467 WLC_SCB_DEAUTHENTICATE_FOR_REASON,
7468 &scbval, sizeof(scb_val_t));
7469 check_error(ioc_res,
7471 __FUNCTION__, __LINE__);
7474 WL_SOFTAP((" no b/w list hits, let it be\n"));
7477 WL_SOFTAP(("No ASSOC CLIENTS\n"));
7482 WL_SOFTAP(("%s iocres:%d\n", __FUNCTION__, ioc_res));
7490 #define PARAM_OFFSET PROFILE_OFFSET
7493 wl_iw_process_private_ascii_cmd(
7494 struct net_device *dev,
7495 struct iw_request_info *info,
7496 union iwreq_data *dwrq,
7500 char *sub_cmd = cmd_str + PROFILE_OFFSET + strlen("ASCII_CMD=");
7502 WL_SOFTAP(("\n %s: ASCII_CMD: offs_0:%s, offset_32:\n'%s'\n",
7503 __FUNCTION__, cmd_str, cmd_str + PROFILE_OFFSET));
7505 if (strnicmp(sub_cmd, "AP_CFG", strlen("AP_CFG")) == 0) {
7507 WL_SOFTAP((" AP_CFG \n"));
7510 if (init_ap_profile_from_string(cmd_str+PROFILE_OFFSET, &my_ap) != 0) {
7511 WL_ERROR(("ERROR: SoftAP CFG prams !\n"));
7514 ret = set_ap_cfg(dev, &my_ap);
7517 } else if (strnicmp(sub_cmd, "AP_BSS_START", strlen("AP_BSS_START")) == 0) {
7519 WL_SOFTAP(("\n SOFTAP - ENABLE BSS \n"));
7522 WL_SOFTAP(("\n!!! got 'WL_AP_EN_BSS' from WPA supplicant, dev:%s\n", dev->name));
7525 if (ap_net_dev == NULL) {
7526 printf("\n ERROR: SOFTAP net_dev* is NULL !!!\n");
7529 if ((ret = iwpriv_en_ap_bss(ap_net_dev, info, dwrq, cmd_str)) < 0)
7530 WL_ERROR(("%s line %d fail to set bss up\n",
7531 __FUNCTION__, __LINE__));
7534 if ((ret = iwpriv_en_ap_bss(dev, info, dwrq, cmd_str)) < 0)
7535 WL_ERROR(("%s line %d fail to set bss up\n",
7536 __FUNCTION__, __LINE__));
7538 } else if (strnicmp(sub_cmd, "ASSOC_LST", strlen("ASSOC_LST")) == 0) {
7542 } else if (strnicmp(sub_cmd, "AP_BSS_STOP", strlen("AP_BSS_STOP")) == 0) {
7544 WL_SOFTAP((" \n temp DOWN SOFTAP\n"));
7546 if ((ret = dev_iw_write_cfg1_bss_var(dev, 0)) < 0) {
7547 WL_ERROR(("%s line %d fail to set bss down\n",
7548 __FUNCTION__, __LINE__));
7561 struct net_device *dev,
7562 struct iw_request_info *info,
7563 struct iw_point *dwrq,
7570 if (!(extra = kmalloc(dwrq->length, GFP_KERNEL)))
7573 if (copy_from_user(extra, dwrq->pointer, dwrq->length)) {
7578 WL_TRACE(("%s: SIOCSIWPRIV request %s, info->cmd:%x, info->flags:%d\n dwrq->length:%d\n",
7579 dev->name, extra, info->cmd, info->flags, dwrq->length));
7583 net_os_wake_lock(dev);
7585 if (dwrq->length && extra) {
7586 if (strnicmp(extra, "START", strlen("START")) == 0) {
7587 wl_iw_control_wl_on(dev, info);
7588 WL_TRACE(("%s, Received regular START command\n", __FUNCTION__));
7591 if (g_onoff == G_WLAN_SET_OFF) {
7592 WL_TRACE(("%s, missing START, Fail\n", __FUNCTION__));
7594 net_os_wake_unlock(dev);
7598 if (strnicmp(extra, "SCAN-ACTIVE", strlen("SCAN-ACTIVE")) == 0) {
7599 #ifdef ENABLE_ACTIVE_PASSIVE_SCAN_SUPPRESS
7600 WL_TRACE(("%s: active scan setting suppressed\n", dev->name));
7602 ret = wl_iw_set_active_scan(dev, info, (union iwreq_data *)dwrq, extra);
7605 else if (strnicmp(extra, "SCAN-PASSIVE", strlen("SCAN-PASSIVE")) == 0)
7606 #ifdef ENABLE_ACTIVE_PASSIVE_SCAN_SUPPRESS
7607 WL_TRACE(("%s: passive scan setting suppressed\n", dev->name));
7609 ret = wl_iw_set_passive_scan(dev, info, (union iwreq_data *)dwrq, extra);
7611 else if (strnicmp(extra, "RSSI", strlen("RSSI")) == 0)
7612 ret = wl_iw_get_rssi(dev, info, (union iwreq_data *)dwrq, extra);
7613 else if (strnicmp(extra, "LINKSPEED", strlen("LINKSPEED")) == 0)
7614 ret = wl_iw_get_link_speed(dev, info, (union iwreq_data *)dwrq, extra);
7615 else if (strnicmp(extra, "MACADDR", strlen("MACADDR")) == 0)
7616 ret = wl_iw_get_macaddr(dev, info, (union iwreq_data *)dwrq, extra);
7617 else if (strnicmp(extra, "COUNTRY", strlen("COUNTRY")) == 0)
7618 ret = wl_iw_set_country(dev, info, (union iwreq_data *)dwrq, extra);
7619 else if (strnicmp(extra, "STOP", strlen("STOP")) == 0)
7620 ret = wl_iw_control_wl_off(dev, info);
7621 else if (strnicmp(extra, BAND_GET_CMD, strlen(BAND_GET_CMD)) == 0)
7622 ret = wl_iw_get_band(dev, info, (union iwreq_data *)dwrq, extra);
7623 else if (strnicmp(extra, BAND_SET_CMD, strlen(BAND_SET_CMD)) == 0)
7624 ret = wl_iw_set_band(dev, info, (union iwreq_data *)dwrq, extra);
7625 else if (strnicmp(extra, DTIM_SKIP_GET_CMD, strlen(DTIM_SKIP_GET_CMD)) == 0)
7626 ret = wl_iw_get_dtim_skip(dev, info, (union iwreq_data *)dwrq, extra);
7627 else if (strnicmp(extra, DTIM_SKIP_SET_CMD, strlen(DTIM_SKIP_SET_CMD)) == 0)
7628 ret = wl_iw_set_dtim_skip(dev, info, (union iwreq_data *)dwrq, extra);
7629 else if (strnicmp(extra, SETSUSPENDOPT_CMD, strlen(SETSUSPENDOPT_CMD)) == 0)
7630 ret = wl_iw_set_suspend_opt(dev, info, (union iwreq_data *)dwrq, extra);
7631 else if (strnicmp(extra, SETSUSPENDMODE_CMD, strlen(SETSUSPENDMODE_CMD)) == 0)
7632 ret = wl_iw_set_suspend_mode(dev, info, (union iwreq_data *)dwrq, extra);
7633 else if (strnicmp(extra, TXPOWER_SET_CMD, strlen(TXPOWER_SET_CMD)) == 0)
7634 ret = wl_iw_set_txpower(dev, info, (union iwreq_data *)dwrq, extra);
7635 #if defined(PNO_SUPPORT)
7636 else if (strnicmp(extra, PNOSSIDCLR_SET_CMD, strlen(PNOSSIDCLR_SET_CMD)) == 0)
7637 ret = wl_iw_set_pno_reset(dev, info, (union iwreq_data *)dwrq, extra);
7638 else if (strnicmp(extra, PNOSETUP_SET_CMD, strlen(PNOSETUP_SET_CMD)) == 0)
7639 ret = wl_iw_set_pno_set(dev, info, (union iwreq_data *)dwrq, extra);
7640 else if (strnicmp(extra, PNOSETADD_SET_CMD, strlen(PNOSETADD_SET_CMD)) == 0)
7641 ret = wl_iw_set_pno_setadd(dev, info, (union iwreq_data *)dwrq, extra);
7642 else if (strnicmp(extra, PNOENABLE_SET_CMD, strlen(PNOENABLE_SET_CMD)) == 0)
7643 ret = wl_iw_set_pno_enable(dev, info, (union iwreq_data *)dwrq, extra);
7647 else if (strnicmp(extra, CSCAN_COMMAND, strlen(CSCAN_COMMAND)) == 0)
7648 ret = wl_iw_set_cscan(dev, info, (union iwreq_data *)dwrq, extra);
7651 else if (strnicmp(extra, WPS_ADD_PROBE_REQ_IE_CMD,
7652 strlen(WPS_ADD_PROBE_REQ_IE_CMD)) == 0)
7653 ret = wl_iw_add_wps_probe_req_ie(dev, info,
7654 (union iwreq_data *)dwrq, extra);
7655 else if (strnicmp(extra, WPS_DEL_PROBE_REQ_IE_CMD,
7656 strlen(WPS_DEL_PROBE_REQ_IE_CMD)) == 0)
7657 ret = wl_iw_del_wps_probe_req_ie(dev, info,
7658 (union iwreq_data *)dwrq, extra);
7660 else if (strnicmp(extra, "POWERMODE", strlen("POWERMODE")) == 0)
7661 ret = wl_iw_set_power_mode(dev, info, (union iwreq_data *)dwrq, extra);
7662 else if (strnicmp(extra, "BTCOEXMODE", strlen("BTCOEXMODE")) == 0)
7663 ret = wl_iw_set_btcoex_dhcp(dev, info, (union iwreq_data *)dwrq, extra);
7664 else if (strnicmp(extra, "GETPOWER", strlen("GETPOWER")) == 0)
7665 ret = wl_iw_get_power_mode(dev, info, (union iwreq_data *)dwrq, extra);
7667 else if (strnicmp(extra, "ASCII_CMD", strlen("ASCII_CMD")) == 0) {
7668 wl_iw_process_private_ascii_cmd(dev, info, (union iwreq_data *)dwrq, extra);
7670 else if (strnicmp(extra, "AP_MAC_LIST_SET", strlen("AP_MAC_LIST_SET")) == 0) {
7671 WL_SOFTAP(("penguin, set AP_MAC_LIST_SET\n"));
7672 set_ap_mac_list(dev, (extra + PROFILE_OFFSET));
7676 WL_ERROR(("Unknown PRIVATE command %s - ignored\n", extra));
7677 snprintf(extra, MAX_WX_STRING, "OK");
7678 dwrq->length = strlen("OK") + 1;
7682 net_os_wake_unlock(dev);
7685 if (copy_to_user(dwrq->pointer, extra, dwrq->length)) {
7696 static const iw_handler wl_iw_handler[] =
7698 (iw_handler) wl_iw_config_commit,
7699 (iw_handler) wl_iw_get_name,
7702 (iw_handler) wl_iw_set_freq,
7703 (iw_handler) wl_iw_get_freq,
7704 (iw_handler) wl_iw_set_mode,
7705 (iw_handler) wl_iw_get_mode,
7709 (iw_handler) wl_iw_get_range,
7710 (iw_handler) wl_iw_set_priv,
7714 (iw_handler) wl_iw_set_spy,
7715 (iw_handler) wl_iw_get_spy,
7718 (iw_handler) wl_iw_set_wap,
7719 (iw_handler) wl_iw_get_wap,
7720 #if WIRELESS_EXT > 17
7721 (iw_handler) wl_iw_mlme,
7725 #if defined(WL_IW_USE_ISCAN)
7726 (iw_handler) wl_iw_iscan_get_aplist,
7728 (iw_handler) wl_iw_get_aplist,
7730 #if WIRELESS_EXT > 13
7731 #if defined(WL_IW_USE_ISCAN)
7732 (iw_handler) wl_iw_iscan_set_scan,
7733 (iw_handler) wl_iw_iscan_get_scan,
7735 (iw_handler) wl_iw_set_scan,
7736 (iw_handler) wl_iw_get_scan,
7742 (iw_handler) wl_iw_set_essid,
7743 (iw_handler) wl_iw_get_essid,
7744 (iw_handler) wl_iw_set_nick,
7745 (iw_handler) wl_iw_get_nick,
7748 (iw_handler) wl_iw_set_rate,
7749 (iw_handler) wl_iw_get_rate,
7750 (iw_handler) wl_iw_set_rts,
7751 (iw_handler) wl_iw_get_rts,
7752 (iw_handler) wl_iw_set_frag,
7753 (iw_handler) wl_iw_get_frag,
7754 (iw_handler) wl_iw_set_txpow,
7755 (iw_handler) wl_iw_get_txpow,
7756 #if WIRELESS_EXT > 10
7757 (iw_handler) wl_iw_set_retry,
7758 (iw_handler) wl_iw_get_retry,
7760 (iw_handler) wl_iw_set_encode,
7761 (iw_handler) wl_iw_get_encode,
7762 (iw_handler) wl_iw_set_power,
7763 (iw_handler) wl_iw_get_power,
7764 #if WIRELESS_EXT > 17
7767 (iw_handler) wl_iw_set_wpaie,
7768 (iw_handler) wl_iw_get_wpaie,
7769 (iw_handler) wl_iw_set_wpaauth,
7770 (iw_handler) wl_iw_get_wpaauth,
7771 (iw_handler) wl_iw_set_encodeext,
7772 (iw_handler) wl_iw_get_encodeext,
7773 (iw_handler) wl_iw_set_pmksa,
7777 #if WIRELESS_EXT > 12
7778 static const iw_handler wl_iw_priv_handler[] = {
7780 (iw_handler)wl_iw_set_active_scan,
7782 (iw_handler)wl_iw_get_rssi,
7784 (iw_handler)wl_iw_set_passive_scan,
7786 (iw_handler)wl_iw_get_link_speed,
7788 (iw_handler)wl_iw_get_macaddr,
7790 (iw_handler)wl_iw_control_wl_off,
7792 (iw_handler)wl_iw_control_wl_on,
7797 (iw_handler)iwpriv_set_ap_config,
7802 (iw_handler)iwpriv_get_assoc_list,
7806 (iw_handler)iwpriv_set_mac_filters,
7810 (iw_handler)iwpriv_en_ap_bss,
7814 (iw_handler)iwpriv_wpasupp_loop_tst,
7817 (iw_handler)iwpriv_softap_stop,
7820 (iw_handler)iwpriv_fw_reload,
7822 (iw_handler)iwpriv_set_ap_sta_disassoc,
7827 (iw_handler)iwpriv_set_cscan
7831 static const struct iw_priv_args wl_iw_priv_args[] =
7834 WL_IW_SET_ACTIVE_SCAN,
7836 IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | MAX_WX_STRING,
7842 IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | MAX_WX_STRING,
7846 WL_IW_SET_PASSIVE_SCAN,
7848 IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | MAX_WX_STRING,
7852 WL_IW_GET_LINK_SPEED,
7854 IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | MAX_WX_STRING,
7858 WL_IW_GET_CURR_MACADDR,
7860 IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | MAX_WX_STRING,
7866 IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | MAX_WX_STRING,
7872 IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | MAX_WX_STRING,
7881 IW_PRIV_TYPE_CHAR | 256,
7888 IW_PRIV_TYPE_CHAR | 0,
7889 IW_PRIV_TYPE_CHAR | 1024,
7895 IW_PRIV_TYPE_CHAR | 256,
7896 IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | 0,
7903 IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | MAX_WX_STRING,
7909 IW_PRIV_TYPE_CHAR | 256,
7910 IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | 0,
7916 IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | 0,
7917 IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | 0,
7922 IW_PRIV_TYPE_CHAR | 256,
7923 IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | 0,
7930 IW_PRIV_TYPE_CHAR | 1024,
7937 const struct iw_handler_def wl_iw_handler_def =
7939 .num_standard = ARRAYSIZE(wl_iw_handler),
7940 .standard = (iw_handler *) wl_iw_handler,
7941 .num_private = ARRAYSIZE(wl_iw_priv_handler),
7942 .num_private_args = ARRAY_SIZE(wl_iw_priv_args),
7943 .private = (iw_handler *)wl_iw_priv_handler,
7944 .private_args = (void *) wl_iw_priv_args,
7946 #if WIRELESS_EXT >= 19
7947 get_wireless_stats: dhd_get_wireless_stats,
7956 struct net_device *dev,
7961 struct iwreq *wrq = (struct iwreq *) rq;
7962 struct iw_request_info info;
7965 size_t token_size = 1;
7966 int max_tokens = 0, ret = 0;
7968 net_os_wake_lock(dev);
7970 WL_TRACE(("\n%s, cmd:%x called via dhd->do_ioctl()entry point\n", __FUNCTION__, cmd));
7971 if (cmd < SIOCIWFIRST ||
7972 IW_IOCTL_IDX(cmd) >= ARRAYSIZE(wl_iw_handler) ||
7973 !(handler = wl_iw_handler[IW_IOCTL_IDX(cmd)])) {
7974 WL_ERROR(("%s: error in cmd=%x : not supported\n", __FUNCTION__, cmd));
7975 net_os_wake_unlock(dev);
7985 max_tokens = IW_ESSID_MAX_SIZE + 1;
7990 #if WIRELESS_EXT > 17
7991 case SIOCSIWENCODEEXT:
7992 case SIOCGIWENCODEEXT:
7994 max_tokens = wrq->u.data.length;
7999 max_tokens = sizeof(struct iw_range) + 500;
8003 token_size = sizeof(struct sockaddr) + sizeof(struct iw_quality);
8004 max_tokens = IW_MAX_AP;
8007 #if WIRELESS_EXT > 13
8009 #if defined(WL_IW_USE_ISCAN)
8011 max_tokens = wrq->u.data.length;
8014 max_tokens = IW_SCAN_MAX_DATA;
8019 token_size = sizeof(struct sockaddr);
8020 max_tokens = IW_MAX_SPY;
8024 token_size = sizeof(struct sockaddr) + sizeof(struct iw_quality);
8025 max_tokens = IW_MAX_SPY;
8028 #if WIRELESS_EXT > 17
8033 max_tokens = wrq->u.data.length;
8037 if (max_tokens && wrq->u.data.pointer) {
8038 if (wrq->u.data.length > max_tokens) {
8039 WL_ERROR(("%s: error in cmd=%x wrq->u.data.length=%d > max_tokens=%d\n",
8040 __FUNCTION__, cmd, wrq->u.data.length, max_tokens));
8042 goto wl_iw_ioctl_done;
8044 if (!(extra = kmalloc(max_tokens * token_size, GFP_KERNEL))) {
8046 goto wl_iw_ioctl_done;
8049 if (copy_from_user(extra, wrq->u.data.pointer, wrq->u.data.length * token_size)) {
8052 goto wl_iw_ioctl_done;
8059 ret = handler(dev, &info, &wrq->u, extra);
8062 if (copy_to_user(wrq->u.data.pointer, extra, wrq->u.data.length * token_size)) {
8065 goto wl_iw_ioctl_done;
8073 net_os_wake_unlock(dev);
8080 wl_iw_conn_status_str(uint32 event_type, uint32 status, uint32 reason,
8081 char* stringBuf, uint buflen)
8083 typedef struct conn_fail_event_map_t {
8087 const char* outName;
8088 const char* outCause;
8089 } conn_fail_event_map_t;
8092 #define WL_IW_DONT_CARE 9999
8093 const conn_fail_event_map_t event_map [] = {
8096 {WLC_E_SET_SSID, WLC_E_STATUS_SUCCESS, WL_IW_DONT_CARE,
8098 {WLC_E_SET_SSID, WLC_E_STATUS_NO_NETWORKS, WL_IW_DONT_CARE,
8099 "Conn", "NoNetworks"},
8100 {WLC_E_SET_SSID, WLC_E_STATUS_FAIL, WL_IW_DONT_CARE,
8101 "Conn", "ConfigMismatch"},
8102 {WLC_E_PRUNE, WL_IW_DONT_CARE, WLC_E_PRUNE_ENCR_MISMATCH,
8103 "Conn", "EncrypMismatch"},
8104 {WLC_E_PRUNE, WL_IW_DONT_CARE, WLC_E_RSN_MISMATCH,
8105 "Conn", "RsnMismatch"},
8106 {WLC_E_AUTH, WLC_E_STATUS_TIMEOUT, WL_IW_DONT_CARE,
8107 "Conn", "AuthTimeout"},
8108 {WLC_E_AUTH, WLC_E_STATUS_FAIL, WL_IW_DONT_CARE,
8109 "Conn", "AuthFail"},
8110 {WLC_E_AUTH, WLC_E_STATUS_NO_ACK, WL_IW_DONT_CARE,
8111 "Conn", "AuthNoAck"},
8112 {WLC_E_REASSOC, WLC_E_STATUS_FAIL, WL_IW_DONT_CARE,
8113 "Conn", "ReassocFail"},
8114 {WLC_E_REASSOC, WLC_E_STATUS_TIMEOUT, WL_IW_DONT_CARE,
8115 "Conn", "ReassocTimeout"},
8116 {WLC_E_REASSOC, WLC_E_STATUS_ABORT, WL_IW_DONT_CARE,
8117 "Conn", "ReassocAbort"},
8118 {WLC_E_PSK_SUP, WLC_SUP_KEYED, WL_IW_DONT_CARE,
8119 "Sup", "ConnSuccess"},
8120 {WLC_E_PSK_SUP, WL_IW_DONT_CARE, WL_IW_DONT_CARE,
8121 "Sup", "WpaHandshakeFail"},
8122 {WLC_E_DEAUTH_IND, WL_IW_DONT_CARE, WL_IW_DONT_CARE,
8124 {WLC_E_DISASSOC_IND, WL_IW_DONT_CARE, WL_IW_DONT_CARE,
8125 "Conn", "DisassocInd"},
8126 {WLC_E_DISASSOC, WL_IW_DONT_CARE, WL_IW_DONT_CARE,
8130 const char* name = "";
8131 const char* cause = NULL;
8135 for (i = 0; i < sizeof(event_map)/sizeof(event_map[0]); i++) {
8136 const conn_fail_event_map_t* row = &event_map[i];
8137 if (row->inEvent == event_type &&
8138 (row->inStatus == status || row->inStatus == WL_IW_DONT_CARE) &&
8139 (row->inReason == reason || row->inReason == WL_IW_DONT_CARE)) {
8140 name = row->outName;
8141 cause = row->outCause;
8148 memset(stringBuf, 0, buflen);
8149 snprintf(stringBuf, buflen, "%s %s %02d %02d",
8150 name, cause, status, reason);
8151 WL_INFORM(("Connection status: %s\n", stringBuf));
8158 #if WIRELESS_EXT > 14
8161 wl_iw_check_conn_fail(wl_event_msg_t *e, char* stringBuf, uint buflen)
8163 uint32 event = ntoh32(e->event_type);
8164 uint32 status = ntoh32(e->status);
8165 uint32 reason = ntoh32(e->reason);
8167 if (wl_iw_conn_status_str(event, status, reason, stringBuf, buflen)) {
8175 #ifndef IW_CUSTOM_MAX
8176 #define IW_CUSTOM_MAX 256
8180 wl_iw_event(struct net_device *dev, wl_event_msg_t *e, void* data)
8182 #if WIRELESS_EXT > 13
8183 union iwreq_data wrqu;
8184 char extra[IW_CUSTOM_MAX + 1];
8186 uint32 event_type = ntoh32(e->event_type);
8187 uint16 flags = ntoh16(e->flags);
8188 uint32 datalen = ntoh32(e->datalen);
8189 uint32 status = ntoh32(e->status);
8191 memset(&wrqu, 0, sizeof(wrqu));
8192 memset(extra, 0, sizeof(extra));
8195 WL_ERROR(("%s: dev is null\n", __FUNCTION__));
8199 net_os_wake_lock(dev);
8201 WL_TRACE(("%s: dev=%s event=%d \n", __FUNCTION__, dev->name, event_type));
8204 switch (event_type) {
8207 if (ap_cfg_running) {
8208 char *macaddr = (char *)&e->addr;
8209 WL_SOFTAP(("PRUNE received, %02X:%02X:%02X:%02X:%02X:%02X!\n",
8210 macaddr[0], macaddr[1], macaddr[2], macaddr[3],
8211 macaddr[4], macaddr[5]));
8217 for (i = 0; i < ap_black_list.count; i++) {
8218 if (!bcmp(macaddr, &ap_black_list.ea[i],
8219 sizeof(struct ether_addr))) {
8220 WL_SOFTAP(("mac in black list, ignore it\n"));
8225 if (i == ap_black_list.count) {
8227 char mac_buf[32] = {0};
8228 sprintf(mac_buf, "STA_BLOCK %02X:%02X:%02X:%02X:%02X:%02X",
8229 macaddr[0], macaddr[1], macaddr[2],
8230 macaddr[3], macaddr[4], macaddr[5]);
8231 wl_iw_send_priv_event(priv_dev, mac_buf);
8239 memcpy(wrqu.addr.sa_data, &e->addr, ETHER_ADDR_LEN);
8240 wrqu.addr.sa_family = ARPHRD_ETHER;
8242 #if WIRELESS_EXT > 14
8244 case WLC_E_ASSOC_IND:
8245 case WLC_E_REASSOC_IND:
8247 WL_SOFTAP(("STA connect received %d\n", event_type));
8248 if (ap_cfg_running) {
8249 wl_iw_send_priv_event(priv_dev, "STA_JOIN");
8250 goto wl_iw_event_end;
8253 memcpy(wrqu.addr.sa_data, &e->addr, ETHER_ADDR_LEN);
8254 wrqu.addr.sa_family = ARPHRD_ETHER;
8255 cmd = IWEVREGISTERED;
8258 if (status == WLC_E_STATUS_SUCCESS) {
8259 WL_ASSOC((" WLC_E_ROAM : success \n"));
8260 goto wl_iw_event_end;
8264 case WLC_E_DEAUTH_IND:
8265 case WLC_E_DISASSOC_IND:
8267 WL_SOFTAP(("STA disconnect received %d\n", event_type));
8268 if (ap_cfg_running) {
8269 wl_iw_send_priv_event(priv_dev, "STA_LEAVE");
8270 goto wl_iw_event_end;
8274 bzero(wrqu.addr.sa_data, ETHER_ADDR_LEN);
8275 wrqu.addr.sa_family = ARPHRD_ETHER;
8276 bzero(&extra, ETHER_ADDR_LEN);
8279 case WLC_E_NDIS_LINK:
8281 if (!(flags & WLC_EVENT_MSG_LINK)) {
8286 if (ap_cfg_running) {
8288 if (ap_cfg_running && !strncmp(dev->name, "wl0.1", 5)) {
8291 WL_SOFTAP(("AP DOWN %d\n", event_type));
8292 wl_iw_send_priv_event(priv_dev, "AP_DOWN");
8294 WL_TRACE(("STA_Link Down\n"));
8295 g_ss_cache_ctrl.m_link_down = 1;
8298 g_ss_cache_ctrl.m_link_down = 1;
8300 WL_TRACE(("Link Down\n"));
8302 bzero(wrqu.addr.sa_data, ETHER_ADDR_LEN);
8303 bzero(&extra, ETHER_ADDR_LEN);
8307 memcpy(wrqu.addr.sa_data, &e->addr, ETHER_ADDR_LEN);
8308 g_ss_cache_ctrl.m_link_down = 0;
8310 memcpy(g_ss_cache_ctrl.m_active_bssid, &e->addr, ETHER_ADDR_LEN);
8314 if (ap_cfg_running) {
8316 if (ap_cfg_running && !strncmp(dev->name, "wl0.1", 5)) {
8319 WL_SOFTAP(("AP UP %d\n", event_type));
8320 wl_iw_send_priv_event(priv_dev, "AP_UP");
8322 WL_TRACE(("STA_LINK_UP\n"));
8326 WL_TRACE(("Link UP\n"));
8329 wrqu.addr.sa_family = ARPHRD_ETHER;
8331 case WLC_E_ACTION_FRAME:
8333 if (datalen + 1 <= sizeof(extra)) {
8334 wrqu.data.length = datalen + 1;
8335 extra[0] = WLC_E_ACTION_FRAME;
8336 memcpy(&extra[1], data, datalen);
8337 WL_TRACE(("WLC_E_ACTION_FRAME len %d \n", wrqu.data.length));
8341 case WLC_E_ACTION_FRAME_COMPLETE:
8343 memcpy(&toto, data, 4);
8344 if (sizeof(status) + 1 <= sizeof(extra)) {
8345 wrqu.data.length = sizeof(status) + 1;
8346 extra[0] = WLC_E_ACTION_FRAME_COMPLETE;
8347 memcpy(&extra[1], &status, sizeof(status));
8348 printf("wl_iw_event status %d PacketId %d \n", status, toto);
8349 printf("WLC_E_ACTION_FRAME_COMPLETE len %d \n", wrqu.data.length);
8353 #if WIRELESS_EXT > 17
8354 case WLC_E_MIC_ERROR: {
8355 struct iw_michaelmicfailure *micerrevt = (struct iw_michaelmicfailure *)&extra;
8356 cmd = IWEVMICHAELMICFAILURE;
8357 wrqu.data.length = sizeof(struct iw_michaelmicfailure);
8358 if (flags & WLC_EVENT_MSG_GROUP)
8359 micerrevt->flags |= IW_MICFAILURE_GROUP;
8361 micerrevt->flags |= IW_MICFAILURE_PAIRWISE;
8362 memcpy(micerrevt->src_addr.sa_data, &e->addr, ETHER_ADDR_LEN);
8363 micerrevt->src_addr.sa_family = ARPHRD_ETHER;
8368 case WLC_E_ASSOC_REQ_IE:
8369 cmd = IWEVASSOCREQIE;
8370 wrqu.data.length = datalen;
8371 if (datalen < sizeof(extra))
8372 memcpy(extra, data, datalen);
8375 case WLC_E_ASSOC_RESP_IE:
8376 cmd = IWEVASSOCRESPIE;
8377 wrqu.data.length = datalen;
8378 if (datalen < sizeof(extra))
8379 memcpy(extra, data, datalen);
8382 case WLC_E_PMKID_CACHE: {
8385 struct iw_pmkid_cand *iwpmkidcand = (struct iw_pmkid_cand *)&extra;
8386 pmkid_cand_list_t *pmkcandlist;
8387 pmkid_cand_t *pmkidcand;
8390 cmd = IWEVPMKIDCAND;
8392 count = ntoh32_ua((uint8 *)&pmkcandlist->npmkid_cand);
8394 wrqu.data.length = sizeof(struct iw_pmkid_cand);
8395 pmkidcand = pmkcandlist->pmkid_cand;
8397 bzero(iwpmkidcand, sizeof(struct iw_pmkid_cand));
8398 if (pmkidcand->preauth)
8399 iwpmkidcand->flags |= IW_PMKID_CAND_PREAUTH;
8400 bcopy(&pmkidcand->BSSID, &iwpmkidcand->bssid.sa_data,
8402 wireless_send_event(dev, cmd, &wrqu, extra);
8407 goto wl_iw_event_end;
8411 case WLC_E_SCAN_COMPLETE:
8412 #if defined(WL_IW_USE_ISCAN)
8414 WL_ERROR(("Event WLC_E_SCAN_COMPLETE on g_iscan NULL!"));
8415 goto wl_iw_event_end;
8418 if ((g_iscan) && (g_iscan->tsk_ctl.thr_pid >= 0) &&
8419 (g_iscan->iscan_state != ISCAN_STATE_IDLE))
8421 up(&g_iscan->tsk_ctl.sema);
8424 wrqu.data.length = strlen(extra);
8425 WL_TRACE(("Event WLC_E_SCAN_COMPLETE from specific scan %d\n",
8426 g_iscan->iscan_state));
8430 wrqu.data.length = strlen(extra);
8431 WL_TRACE(("Event WLC_E_SCAN_COMPLETE\n"));
8436 case WLC_E_PFN_NET_FOUND:
8438 wl_pfn_net_info_t *netinfo;
8439 netinfo = (wl_pfn_net_info_t *)(data + sizeof(wl_pfn_scanresults_t) -
8440 sizeof(wl_pfn_net_info_t));
8441 WL_ERROR(("%s Event WLC_E_PFN_NET_FOUND, send %s up : find %s len=%d\n",
8442 __FUNCTION__, PNO_EVENT_UP, netinfo->pfnsubnet.SSID,
8443 netinfo->pfnsubnet.SSID_len));
8445 memset(&wrqu, 0, sizeof(wrqu));
8446 strcpy(extra, PNO_EVENT_UP);
8447 wrqu.data.length = strlen(extra);
8453 WL_TRACE(("Unknown Event %d: ignoring\n", event_type));
8457 if (cmd == SIOCGIWSCAN)
8458 wireless_send_event(dev, cmd, &wrqu, NULL);
8460 wireless_send_event(dev, cmd, &wrqu, extra);
8463 #if WIRELESS_EXT > 14
8465 memset(extra, 0, sizeof(extra));
8466 if (wl_iw_check_conn_fail(e, extra, sizeof(extra))) {
8468 wrqu.data.length = strlen(extra);
8469 wireless_send_event(dev, cmd, &wrqu, extra);
8473 goto wl_iw_event_end;
8476 net_os_wake_unlock(dev);
8481 wl_iw_get_wireless_stats(struct net_device *dev, struct iw_statistics *wstats)
8490 if ((res = dev_wlc_ioctl(dev, WLC_GET_PHY_NOISE, &phy_noise, sizeof(phy_noise))))
8493 phy_noise = dtoh32(phy_noise);
8494 WL_TRACE(("wl_iw_get_wireless_stats phy noise=%d\n", phy_noise));
8496 bzero(&scb_val, sizeof(scb_val_t));
8497 if ((res = dev_wlc_ioctl(dev, WLC_GET_RSSI, &scb_val, sizeof(scb_val_t))))
8500 rssi = dtoh32(scb_val.val);
8501 WL_TRACE(("wl_iw_get_wireless_stats rssi=%d\n", rssi));
8502 if (rssi <= WL_IW_RSSI_NO_SIGNAL)
8503 wstats->qual.qual = 0;
8504 else if (rssi <= WL_IW_RSSI_VERY_LOW)
8505 wstats->qual.qual = 1;
8506 else if (rssi <= WL_IW_RSSI_LOW)
8507 wstats->qual.qual = 2;
8508 else if (rssi <= WL_IW_RSSI_GOOD)
8509 wstats->qual.qual = 3;
8510 else if (rssi <= WL_IW_RSSI_VERY_GOOD)
8511 wstats->qual.qual = 4;
8513 wstats->qual.qual = 5;
8516 wstats->qual.level = 0x100 + rssi;
8517 wstats->qual.noise = 0x100 + phy_noise;
8518 #if WIRELESS_EXT > 18
8519 wstats->qual.updated |= (IW_QUAL_ALL_UPDATED | IW_QUAL_DBM);
8521 wstats->qual.updated |= 7;
8524 #if WIRELESS_EXT > 11
8525 WL_TRACE(("wl_iw_get_wireless_stats counters=%d\n", (int)sizeof(wl_cnt_t)));
8527 memset(&cnt, 0, sizeof(wl_cnt_t));
8528 res = dev_wlc_bufvar_get(dev, "counters", (char *)&cnt, sizeof(wl_cnt_t));
8531 WL_ERROR(("wl_iw_get_wireless_stats counters failed error=%d\n", res));
8535 cnt.version = dtoh16(cnt.version);
8536 if (cnt.version != WL_CNT_T_VERSION) {
8537 WL_TRACE(("\tIncorrect version of counters struct: expected %d; got %d\n",
8538 WL_CNT_T_VERSION, cnt.version));
8542 wstats->discard.nwid = 0;
8543 wstats->discard.code = dtoh32(cnt.rxundec);
8544 wstats->discard.fragment = dtoh32(cnt.rxfragerr);
8545 wstats->discard.retries = dtoh32(cnt.txfail);
8546 wstats->discard.misc = dtoh32(cnt.rxrunt) + dtoh32(cnt.rxgiant);
8547 wstats->miss.beacon = 0;
8549 WL_TRACE(("wl_iw_get_wireless_stats counters txframe=%d txbyte=%d\n",
8550 dtoh32(cnt.txframe), dtoh32(cnt.txbyte)));
8551 WL_TRACE(("wl_iw_get_wireless_stats counters rxfrmtoolong=%d\n", dtoh32(cnt.rxfrmtoolong)));
8552 WL_TRACE(("wl_iw_get_wireless_stats counters rxbadplcp=%d\n", dtoh32(cnt.rxbadplcp)));
8553 WL_TRACE(("wl_iw_get_wireless_stats counters rxundec=%d\n", dtoh32(cnt.rxundec)));
8554 WL_TRACE(("wl_iw_get_wireless_stats counters rxfragerr=%d\n", dtoh32(cnt.rxfragerr)));
8555 WL_TRACE(("wl_iw_get_wireless_stats counters txfail=%d\n", dtoh32(cnt.txfail)));
8556 WL_TRACE(("wl_iw_get_wireless_stats counters rxrunt=%d\n", dtoh32(cnt.rxrunt)));
8557 WL_TRACE(("wl_iw_get_wireless_stats counters rxgiant=%d\n", dtoh32(cnt.rxgiant)));
8564 #if defined(COEX_DHCP)
8567 struct net_device *dev,
8570 #if defined(BT_DHCP_USE_FLAGS)
8571 char buf_flag7_dhcp_on[8] = { 7, 00, 00, 00, 0x1, 0x0, 0x00, 0x00 };
8572 char buf_flag7_default[8] = { 7, 00, 00, 00, 0x0, 0x00, 0x00, 0x00};
8575 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27))
8580 #if defined(BT_DHCP_eSCO_FIX)
8582 set_btc_esco_params(dev, set);
8586 #if defined(BT_DHCP_USE_FLAGS)
8587 WL_TRACE_COEX(("WI-FI priority boost via bt flags, set:%d\n", set));
8590 dev_wlc_bufvar_set(dev, "btc_flags",
8591 (char *)&buf_flag7_dhcp_on[0], sizeof(buf_flag7_dhcp_on));
8595 dev_wlc_bufvar_set(dev, "btc_flags",
8596 (char *)&buf_flag7_default[0], sizeof(buf_flag7_default));
8600 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27))
8606 wl_iw_bt_timerfunc(ulong data)
8608 bt_info_t *bt_local = (bt_info_t *)data;
8609 bt_local->timer_on = 0;
8610 WL_TRACE(("%s\n", __FUNCTION__));
8612 up(&bt_local->tsk_ctl.sema);
8616 _bt_dhcp_sysioc_thread(void *data)
8618 tsk_ctl_t *tsk_ctl = (tsk_ctl_t *)data;
8620 DAEMONIZE("dhcp_sysioc");
8622 complete(&tsk_ctl->completed);
8624 while (down_interruptible(&tsk_ctl->sema) == 0) {
8626 SMP_RD_BARRIER_DEPENDS();
8627 if (tsk_ctl->terminated) {
8631 if (g_bt->timer_on) {
8633 del_timer_sync(&g_bt->timer);
8636 switch (g_bt->bt_state) {
8639 WL_TRACE_COEX(("%s bt_dhcp stm: started \n", __FUNCTION__));
8640 g_bt->bt_state = BT_DHCP_OPPORTUNITY_WINDOW;
8641 mod_timer(&g_bt->timer,
8642 jiffies + BT_DHCP_OPPORTUNITY_WINDOW_TIME*HZ/1000);
8646 case BT_DHCP_OPPORTUNITY_WINDOW:
8647 if (g_bt->dhcp_done) {
8648 WL_TRACE_COEX(("%s DHCP Done before T1 expiration\n",
8654 WL_TRACE_COEX(("%s DHCP T1:%d expired\n",
8655 __FUNCTION__, BT_DHCP_OPPORTUNITY_WINDOW_TIME));
8657 if (g_bt->dev) wl_iw_bt_flag_set(g_bt->dev, TRUE);
8658 g_bt->bt_state = BT_DHCP_FLAG_FORCE_TIMEOUT;
8659 mod_timer(&g_bt->timer, jiffies + BT_DHCP_FLAG_FORCE_TIME*HZ/1000);
8663 case BT_DHCP_FLAG_FORCE_TIMEOUT:
8664 if (g_bt->dhcp_done) {
8665 WL_TRACE_COEX(("%s DHCP Done before T2 expiration\n",
8669 WL_TRACE_COEX(("%s DHCP wait interval T2:%d msec expired\n",
8670 __FUNCTION__, BT_DHCP_FLAG_FORCE_TIME));
8674 if (g_bt->dev) wl_iw_bt_flag_set(g_bt->dev, FALSE);
8676 g_bt->bt_state = BT_DHCP_IDLE;
8681 WL_ERROR(("%s error g_status=%d !!!\n", __FUNCTION__,
8683 if (g_bt->dev) wl_iw_bt_flag_set(g_bt->dev, FALSE);
8684 g_bt->bt_state = BT_DHCP_IDLE;
8689 net_os_wake_unlock(g_bt->dev);
8692 if (g_bt->timer_on) {
8694 del_timer_sync(&g_bt->timer);
8696 complete_and_exit(&tsk_ctl->completed, 0);
8700 wl_iw_bt_release(void)
8702 bt_info_t *bt_local = g_bt;
8708 if (bt_local->tsk_ctl.thr_pid >= 0) {
8709 PROC_STOP(&bt_local->tsk_ctl);
8716 wl_iw_bt_init(struct net_device *dev)
8718 bt_info_t *bt_dhcp = NULL;
8720 bt_dhcp = kmalloc(sizeof(bt_info_t), GFP_KERNEL);
8724 memset(bt_dhcp, 0, sizeof(bt_info_t));
8728 bt_dhcp->bt_state = BT_DHCP_IDLE;
8731 bt_dhcp->timer_ms = 10;
8732 init_timer(&bt_dhcp->timer);
8733 bt_dhcp->timer.data = (ulong)bt_dhcp;
8734 bt_dhcp->timer.function = wl_iw_bt_timerfunc;
8735 bt_dhcp->ts_dhcp_start = 0;
8736 bt_dhcp->ts_dhcp_ok = 0;
8738 PROC_START(_bt_dhcp_sysioc_thread, bt_dhcp, &bt_dhcp->tsk_ctl, 0);
8739 if (bt_dhcp->tsk_ctl.thr_pid < 0) {
8740 WL_ERROR(("Failed in %s\n", __FUNCTION__));
8749 wl_iw_attach(struct net_device *dev, void * dhdp)
8751 #if defined(WL_IW_USE_ISCAN)
8752 int params_size = 0;
8755 #if defined(WL_IW_USE_ISCAN)
8756 iscan_info_t *iscan = NULL;
8759 DHD_OS_MUTEX_INIT(&wl_cache_lock);
8760 DHD_OS_MUTEX_INIT(&wl_softap_lock);
8762 #if defined(WL_IW_USE_ISCAN)
8767 memset(&g_wl_iw_params, 0, sizeof(wl_iw_extra_params_t));
8771 params_size = (WL_SCAN_PARAMS_FIXED_SIZE + OFFSETOF(wl_iscan_params_t, params)) +
8772 (WL_NUMCHANNELS * sizeof(uint16)) + WL_SCAN_PARAMS_SSID_MAX * sizeof(wlc_ssid_t);
8774 params_size = (WL_SCAN_PARAMS_FIXED_SIZE + OFFSETOF(wl_iscan_params_t, params));
8776 iscan = kmalloc(sizeof(iscan_info_t), GFP_KERNEL);
8779 memset(iscan, 0, sizeof(iscan_info_t));
8782 iscan->iscan_ex_params_p = (wl_iscan_params_t*)kmalloc(params_size, GFP_KERNEL);
8783 if (!iscan->iscan_ex_params_p) {
8787 iscan->iscan_ex_param_size = params_size;
8792 iscan->iscan_state = ISCAN_STATE_IDLE;
8794 #if defined(CONFIG_FIRST_SCAN)
8795 g_first_broadcast_scan = BROADCAST_SCAN_FIRST_IDLE;
8796 g_first_counter_scans = 0;
8797 g_iscan->scan_flag = 0;
8801 g_wps_probe_req_ie = NULL;
8802 g_wps_probe_req_ie_len = 0;
8805 iscan->timer_ms = 8000;
8806 init_timer(&iscan->timer);
8807 iscan->timer.data = (ulong)iscan;
8808 iscan->timer.function = wl_iw_timerfunc;
8810 PROC_START(_iscan_sysioc_thread, iscan, &iscan->tsk_ctl, 0);
8811 if (iscan->tsk_ctl.thr_pid < 0)
8815 iw = *(wl_iw_t **)netdev_priv(dev);
8816 iw->pub = (dhd_pub_t *)dhdp;
8823 g_scan = (void *)kmalloc(G_SCAN_RESULTS, GFP_KERNEL);
8827 memset(g_scan, 0, G_SCAN_RESULTS);
8828 g_scan_specified_ssid = 0;
8832 wl_iw_init_ss_cache_ctrl();
8846 #if defined(WL_IW_USE_ISCAN)
8848 iscan_info_t *iscan = g_iscan;
8852 if (iscan->tsk_ctl.thr_pid >= 0) {
8853 PROC_STOP(&iscan->tsk_ctl);
8855 DHD_OS_MUTEX_LOCK(&wl_cache_lock);
8856 while (iscan->list_hdr) {
8857 buf = iscan->list_hdr->next;
8858 kfree(iscan->list_hdr);
8859 iscan->list_hdr = buf;
8861 kfree(iscan->iscan_ex_params_p);
8864 DHD_OS_MUTEX_UNLOCK(&wl_cache_lock);
8873 if (g_wps_probe_req_ie) {
8874 kfree(g_wps_probe_req_ie);
8875 g_wps_probe_req_ie = NULL;
8876 g_wps_probe_req_ie_len = 0;
8880 wl_iw_release_ss_cache_ctrl();
8887 if (ap_cfg_running) {
8888 WL_TRACE(("\n%s AP is going down\n", __FUNCTION__));
8890 wl_iw_send_priv_event(priv_dev, "AP_DOWN");