From d3bf457b29b12522bef6d563534b568184d373b5 Mon Sep 17 00:00:00 2001 From: Howard Harte Date: Thu, 29 Jul 2010 17:43:06 -0700 Subject: [PATCH] net: wireless: bcm4329: Update to 4.218.245 (combo scan) Signed-off-by: Dmitry Shmidt --- drivers/net/wireless/bcm4329/Makefile | 2 +- drivers/net/wireless/bcm4329/dhd_cdc.c | 4 +- drivers/net/wireless/bcm4329/dhd_common.c | 258 +++++- drivers/net/wireless/bcm4329/dhd_linux.c | 18 +- drivers/net/wireless/bcm4329/dhd_sdio.c | 4 +- .../net/wireless/bcm4329/include/bcmsdpcm.h | 7 +- .../net/wireless/bcm4329/include/epivers.h | 10 +- .../wireless/bcm4329/include/hndrte_cons.h | 23 +- drivers/net/wireless/bcm4329/wl_iw.c | 769 +++++++++++++----- drivers/net/wireless/bcm4329/wl_iw.h | 46 +- 10 files changed, 911 insertions(+), 230 deletions(-) diff --git a/drivers/net/wireless/bcm4329/Makefile b/drivers/net/wireless/bcm4329/Makefile index 43f891a8ea3d..15926e4a08d3 100644 --- a/drivers/net/wireless/bcm4329/Makefile +++ b/drivers/net/wireless/bcm4329/Makefile @@ -6,7 +6,7 @@ DHDCFLAGS = -DLINUX -DBCMDRIVER -DBCMDONGLEHOST -DDHDTHREAD -DBCMWPA2 \ -Wall -Wstrict-prototypes -Werror -DOOB_INTR_ONLY -DCUSTOMER_HW2 \ -DDHD_USE_STATIC_BUF -DMMC_SDIO_ABORT -DDHD_DEBUG_TRAP -DSOFTAP \ -DEMBEDDED_PLATFORM -DARP_OFFLOAD_SUPPORT -DPKT_FILTER_SUPPORT \ - -DGET_CUSTOM_MAC_ENABLE -DSET_RANDOM_MAC_SOFTAP \ + -DGET_CUSTOM_MAC_ENABLE -DSET_RANDOM_MAC_SOFTAP -DCSCAN \ -Idrivers/net/wireless/bcm4329 -Idrivers/net/wireless/bcm4329/include DHDOFILES = dhd_linux.o linux_osl.o bcmutils.o dhd_common.o dhd_custom_gpio.o \ diff --git a/drivers/net/wireless/bcm4329/dhd_cdc.c b/drivers/net/wireless/bcm4329/dhd_cdc.c index c95ca9b3471f..070e95ef773e 100644 --- a/drivers/net/wireless/bcm4329/dhd_cdc.c +++ b/drivers/net/wireless/bcm4329/dhd_cdc.c @@ -21,7 +21,7 @@ * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. * - * $Id: dhd_cdc.c,v 1.22.4.2.4.7.2.39 2010/06/04 19:08:09 Exp $ + * $Id: dhd_cdc.c,v 1.22.4.2.4.7.2.41 2010/06/23 19:58:18 Exp $ * * BDC is like CDC, except it includes a header for data packets to convey * packet priority over the bus, and flags (e.g. to indicate checksum status @@ -211,7 +211,7 @@ dhdcdc_set_ioctl(dhd_pub_t *dhd, int ifidx, uint cmd, void *buf, uint len) msg->len = htol32(len); msg->flags = (++prot->reqid << CDCF_IOC_ID_SHIFT) | CDCF_IOC_SET; CDC_SET_IF_IDX(msg, ifidx); - msg->flags |= htol32(msg->flags); + msg->flags = htol32(msg->flags); if (buf) memcpy(prot->buf, buf, len); diff --git a/drivers/net/wireless/bcm4329/dhd_common.c b/drivers/net/wireless/bcm4329/dhd_common.c index 74b0a79091b2..8faffcb23fc2 100644 --- a/drivers/net/wireless/bcm4329/dhd_common.c +++ b/drivers/net/wireless/bcm4329/dhd_common.c @@ -21,7 +21,7 @@ * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. * - * $Id: dhd_common.c,v 1.5.6.8.2.6.6.62 2010/06/04 19:08:13 Exp $ + * $Id: dhd_common.c,v 1.5.6.8.2.6.6.65 2010/07/07 00:05:07 Exp $ */ #include #include @@ -50,6 +50,10 @@ int wifi_get_mac_addr(unsigned char *buf); int dhd_msg_level; +#if defined(CSCAN) +#include +#endif + char fw_path[MOD_PARAM_PATHLEN]; char nv_path[MOD_PARAM_PATHLEN]; @@ -1751,3 +1755,255 @@ fail: } #endif + +/* Android ComboSCAN support */ +#if defined(CSCAN) + +/* + * data parsing from ComboScan tlv list +*/ +int +wl_iw_parse_data_tlv(char** list_str, void *dst, int dst_size, const char token, \ + int input_size, int *bytes_left) +{ + char* str = *list_str; + uint16 short_temp; + uint32 int_temp; + + if ((list_str == NULL) || (*list_str == NULL) ||(bytes_left == NULL) || (*bytes_left < 0)) { + DHD_ERROR(("%s error paramters\n", __FUNCTION__)); + return -1; + } + + /* Clean all dest bytes */ + memset(dst, 0, dst_size); + while (*bytes_left > 0) { + + if (str[0] != token) { + DHD_TRACE(("%s NOT Type=%d get=%d left_parse=%d \n", __FUNCTION__, \ + token, str[0], *bytes_left)); + return -1; + } + + *bytes_left -= 1; + str += 1; + + if (input_size == 1) { + memcpy(dst, str, input_size); + } + else if (input_size == 2) { + memcpy(dst, (char *)htod16(memcpy(&short_temp, str, input_size)), \ + input_size); + } + else if (input_size == 4) { + memcpy(dst, (char *)htod32(memcpy(&int_temp, str, input_size)), \ + input_size); + } + + *bytes_left -= input_size; + str += input_size; + *list_str = str; + return 1; + } + return 1; +} + +/* + * channel list parsing from cscan tlv list +*/ +int +wl_iw_parse_channel_list_tlv(char** list_str, uint16* channel_list, \ + int channel_num, int *bytes_left) +{ + char* str = *list_str; + int idx = 0; + + if ((list_str == NULL) || (*list_str == NULL) ||(bytes_left == NULL) || (*bytes_left < 0)) { + DHD_ERROR(("%s error paramters\n", __FUNCTION__)); + return -1; + } + + while (*bytes_left > 0) { + + if (str[0] != CSCAN_TLV_TYPE_CHANNEL_IE) { + *list_str = str; + DHD_TRACE(("End channel=%d left_parse=%d %d\n", idx, *bytes_left, str[0])); + return idx; + } + /* Get proper CSCAN_TLV_TYPE_CHANNEL_IE */ + *bytes_left -= 1; + str += 1; + + if (str[0] == 0) { + /* All channels */ + channel_list[idx] = 0x0; + } + else { + channel_list[idx] = (uint16)str[0]; + DHD_TRACE(("%s channel=%d \n", __FUNCTION__, channel_list[idx])); + } + *bytes_left -= 1; + str += 1; + + if (idx++ > 255) { + DHD_ERROR(("%s Too many channels \n", __FUNCTION__)); + return -1; + } + } + + *list_str = str; + return idx; +} + +/* + * SSIDs list parsing from cscan tlv list + */ +int +wl_iw_parse_ssid_list_tlv(char** list_str, wlc_ssid_t* ssid, int max, int *bytes_left) +{ + char* str = *list_str; + int idx = 0; + + if ((list_str == NULL) || (*list_str == NULL) || (*bytes_left < 0)) { + DHD_ERROR(("%s error paramters\n", __FUNCTION__)); + return -1; + } + + while (*bytes_left > 0) { + + if (str[0] != CSCAN_TLV_TYPE_SSID_IE) { + *list_str = str; + DHD_TRACE(("nssid=%d left_parse=%d %d\n", idx, *bytes_left, str[0])); + return idx; + } + + /* Get proper CSCAN_TLV_TYPE_SSID_IE */ + *bytes_left -= 1; + str += 1; + + if (str[0] == 0) { + /* Broadcast SSID */ + ssid[idx].SSID_len = 0; + memset((char*)ssid[idx].SSID, 0x0, DOT11_MAX_SSID_LEN); + *bytes_left -= 1; + str += 1; + + DHD_TRACE(("BROADCAST SCAN left=%d\n", *bytes_left)); + } + else if (str[0] <= DOT11_MAX_SSID_LEN) { + /* Get proper SSID size */ + ssid[idx].SSID_len = str[0]; + *bytes_left -= 1; + str += 1; + + /* Get SSID */ + if (ssid[idx].SSID_len > *bytes_left) { + DHD_ERROR(("%s out of memory range len=%d but left=%d\n", \ + __FUNCTION__, ssid[idx].SSID_len, *bytes_left)); + return -1; + } + + memcpy((char*)ssid[idx].SSID, str, ssid[idx].SSID_len); + + *bytes_left -= ssid[idx].SSID_len; + str += ssid[idx].SSID_len; + + DHD_TRACE(("%s :size=%d left=%d\n", (char*)ssid[idx].SSID, \ + ssid[idx].SSID_len, *bytes_left)); + } + else { + DHD_ERROR(("### SSID size more that %d\n", str[0])); + return -1; + } + + if (idx++ > max) { + DHD_ERROR(("%s number of SSIDs more that %d\n", __FUNCTION__, idx)); + return -1; + } + } + + *list_str = str; + return idx; +} + +/* Parse a comma-separated list from list_str into ssid array, starting + * at index idx. Max specifies size of the ssid array. Parses ssids + * and returns updated idx; if idx >= max not all fit, the excess have + * not been copied. Returns -1 on empty string, or on ssid too long. + */ +int +wl_iw_parse_ssid_list(char** list_str, wlc_ssid_t* ssid, int idx, int max) +{ + char* str, *ptr; + + if ((list_str == NULL) || (*list_str == NULL)) + return -1; + + for (str = *list_str; str != NULL; str = ptr) { + + /* check for next TAG */ + if (!strncmp(str, GET_CHANNEL, strlen(GET_CHANNEL))) { + *list_str = str + strlen(GET_CHANNEL); + return idx; + } + + if ((ptr = strchr(str, ',')) != NULL) { + *ptr++ = '\0'; + } + + if (strlen(str) > DOT11_MAX_SSID_LEN) { + DHD_ERROR(("ssid <%s> exceeds %d\n", str, DOT11_MAX_SSID_LEN)); + return -1; + } + + if (strlen(str) == 0) + ssid[idx].SSID_len = 0; + + if (idx < max) { + strcpy((char*)ssid[idx].SSID, str); + ssid[idx].SSID_len = strlen(str); + } + idx++; + } + return idx; +} + +/* + * Parse channel list from iwpriv CSCAN + */ +int +wl_iw_parse_channel_list(char** list_str, uint16* channel_list, int channel_num) +{ + int num; + int val; + char* str; + char* endptr = NULL; + + if ((list_str == NULL)||(*list_str == NULL)) + return -1; + + str = *list_str; + num = 0; + while (strncmp(str, GET_NPROBE, strlen(GET_NPROBE))) { + val = (int)strtoul(str, &endptr, 0); + if (endptr == str) { + printf("could not parse channel number starting at" + " substring \"%s\" in list:\n%s\n", + str, *list_str); + return -1; + } + str = endptr + strspn(endptr, " ,"); + + if (num == channel_num) { + DHD_ERROR(("too many channels (more than %d) in channel list:\n%s\n", + channel_num, *list_str)); + return -1; + } + + channel_list[num++] = (uint16)val; + } + *list_str = str; + return num; +} + +#endif diff --git a/drivers/net/wireless/bcm4329/dhd_linux.c b/drivers/net/wireless/bcm4329/dhd_linux.c index 00f545045cdc..cce87ba890d5 100644 --- a/drivers/net/wireless/bcm4329/dhd_linux.c +++ b/drivers/net/wireless/bcm4329/dhd_linux.c @@ -22,7 +22,7 @@ * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. * - * $Id: dhd_linux.c,v 1.65.4.9.2.12.2.86 2010/05/18 05:48:53 Exp $ + * $Id: dhd_linux.c,v 1.65.4.9.2.12.2.89 2010/07/21 18:07:11 Exp $ */ #ifdef CONFIG_WIFI_CONTROL_FUNC @@ -2283,14 +2283,14 @@ dhd_net_attach(dhd_pub_t *dhdp, int ifidx) net->ethtool_ops = &dhd_ethtool_ops; #endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 24) */ -#ifdef CONFIG_WIRELESS_EXT +#if defined(CONFIG_WIRELESS_EXT) #if WIRELESS_EXT < 19 net->get_wireless_stats = dhd_get_wireless_stats; #endif /* WIRELESS_EXT < 19 */ #if WIRELESS_EXT > 12 net->wireless_handlers = (struct iw_handler_def *)&wl_iw_handler_def; #endif /* WIRELESS_EXT > 12 */ -#endif /* CONFIG_WIRELESS_EXT */ +#endif /* defined(CONFIG_WIRELESS_EXT) */ dhd->pub.rxsz = net->mtu + net->hard_header_len + dhd->pub.hdrlen; @@ -2305,7 +2305,7 @@ dhd_net_attach(dhd_pub_t *dhdp, int ifidx) dhd->pub.mac.octet[0], dhd->pub.mac.octet[1], dhd->pub.mac.octet[2], dhd->pub.mac.octet[3], dhd->pub.mac.octet[4], dhd->pub.mac.octet[5]); -#ifdef CONFIG_WIRELESS_EXT +#if defined(CONFIG_WIRELESS_EXT) && !defined(CSCAN) #ifdef SOFTAP if (ifidx == 0) /* Don't call for SOFTAP Interface in SOFTAP MODE */ @@ -2317,7 +2317,7 @@ dhd_net_attach(dhd_pub_t *dhdp, int ifidx) #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) up(&dhd_registration_sem); -#endif +#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) */ return 0; fail: @@ -2779,7 +2779,7 @@ dhd_get_wireless_stats(struct net_device *dev) else return NULL; } -#endif +#endif /* defined(CONFIG_WIRELESS_EXT) */ static int dhd_wl_host_event(dhd_info_t *dhd, int *ifidx, void *pktdata, @@ -2795,9 +2795,11 @@ dhd_wl_host_event(dhd_info_t *dhd, int *ifidx, void *pktdata, #if defined(CONFIG_WIRELESS_EXT) ASSERT(dhd->iflist[*ifidx] != NULL); + ASSERT(dhd->iflist[*ifidx]->net != NULL); - wl_iw_event(dhd->iflist[*ifidx]->net, event, *data); -#endif + if (dhd->iflist[*ifidx]->net) + wl_iw_event(dhd->iflist[*ifidx]->net, event, *data); +#endif /* defined(CONFIG_WIRELESS_EXT) */ return (bcmerror); } diff --git a/drivers/net/wireless/bcm4329/dhd_sdio.c b/drivers/net/wireless/bcm4329/dhd_sdio.c index e5a05a7d5cec..0cf6508b527b 100644 --- a/drivers/net/wireless/bcm4329/dhd_sdio.c +++ b/drivers/net/wireless/bcm4329/dhd_sdio.c @@ -21,7 +21,7 @@ * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. * - * $Id: dhd_sdio.c,v 1.157.2.27.2.33.2.125 2010/06/04 02:52:15 Exp $ + * $Id: dhd_sdio.c,v 1.157.2.27.2.33.2.126 2010/06/15 23:38:39 Exp $ */ #include @@ -4694,6 +4694,8 @@ dhd_bus_watchdog(dhd_pub_t *dhdp) bus->idlecount = 0; if (bus->activity) { bus->activity = FALSE; + dhd_os_wd_timer(bus->dhd,dhd_watchdog_ms); + } else { dhdsdio_clkctl(bus, CLK_NONE, FALSE); } } diff --git a/drivers/net/wireless/bcm4329/include/bcmsdpcm.h b/drivers/net/wireless/bcm4329/include/bcmsdpcm.h index b63b1d39a51f..77aca4500ad8 100644 --- a/drivers/net/wireless/bcm4329/include/bcmsdpcm.h +++ b/drivers/net/wireless/bcm4329/include/bcmsdpcm.h @@ -2,7 +2,7 @@ * Broadcom SDIO/PCMCIA * Software-specific definitions shared between device and host side * - * Copyright (C) 1999-2009, Broadcom Corporation + * Copyright (C) 1999-2010, Broadcom Corporation * * Unless you and Broadcom execute a separate written software license * agreement governing use of this software, this software is licensed to you @@ -22,7 +22,7 @@ * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. * - * $Id: bcmsdpcm.h,v 1.1.2.3 2009/04/09 18:52:06 Exp $ + * $Id: bcmsdpcm.h,v 1.1.2.4 2010/07/02 01:15:46 Exp $ */ #ifndef _bcmsdpcm_h_ @@ -241,7 +241,7 @@ typedef volatile struct { * Shared structure between dongle and the host * The structure contains pointers to trap or assert information shared with the host */ -#define SDPCM_SHARED_VERSION 0x0001 +#define SDPCM_SHARED_VERSION 0x0002 #define SDPCM_SHARED_VERSION_MASK 0x00FF #define SDPCM_SHARED_ASSERT_BUILT 0x0100 #define SDPCM_SHARED_ASSERT 0x0200 @@ -255,6 +255,7 @@ typedef struct { uint32 assert_line; uint32 console_addr; /* Address of hndrte_cons_t */ uint32 msgtrace_addr; + uint8 tag[32]; } sdpcm_shared_t; extern sdpcm_shared_t sdpcm_shared; diff --git a/drivers/net/wireless/bcm4329/include/epivers.h b/drivers/net/wireless/bcm4329/include/epivers.h index 1453361cb757..114c735fb381 100644 --- a/drivers/net/wireless/bcm4329/include/epivers.h +++ b/drivers/net/wireless/bcm4329/include/epivers.h @@ -31,18 +31,18 @@ #define EPI_MINOR_VERSION 218 -#define EPI_RC_NUMBER 239 +#define EPI_RC_NUMBER 245 #define EPI_INCREMENTAL_NUMBER 0 #define EPI_BUILD_NUMBER 0 -#define EPI_VERSION 4, 218, 239, 0 +#define EPI_VERSION 4, 218, 245, 0 -#define EPI_VERSION_NUM 0x04daef00 +#define EPI_VERSION_NUM 0x04daf500 -#define EPI_VERSION_STR "4.218.239.0" -#define EPI_ROUTER_VERSION_STR "4.219.239.0" +#define EPI_VERSION_STR "4.218.245.0" +#define EPI_ROUTER_VERSION_STR "4.219.245.0" #endif diff --git a/drivers/net/wireless/bcm4329/include/hndrte_cons.h b/drivers/net/wireless/bcm4329/include/hndrte_cons.h index dccafdb55d1f..a42417478a16 100644 --- a/drivers/net/wireless/bcm4329/include/hndrte_cons.h +++ b/drivers/net/wireless/bcm4329/include/hndrte_cons.h @@ -1,12 +1,14 @@ /* - * Copyright (C) 1999-2010, Broadcom Corporation + * Console support for hndrte. * + * Copyright (C) 1999-2010, Broadcom Corporation + * * Unless you and Broadcom execute a separate written software license * agreement governing use of this software, this software is licensed to you * under the terms of the GNU General Public License version 2 (the "GPL"), * available at http://www.broadcom.com/licenses/GPLv2.php, with the * following added to such license: - * + * * As a special exception, the copyright holders of this software give you * permission to link this software with independent modules, and to copy and * distribute the resulting executable under terms of your choice, provided that @@ -14,32 +16,19 @@ * the license of that module. An independent module is a module which is not * derived from this software. The special exception does not apply to any * modifications of the software. - * + * * Notwithstanding the above, under no circumstances may you combine this * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. * - * $Id: hndrte_cons.h,v 13.1.2.3 2010/02/18 01:09:39 Exp $ + * $Id: hndrte_cons.h,v 13.1.2.4 2010/07/15 19:06:11 Exp $ */ #include -#ifdef RWL_DONGLE -/* For Dongle uart tranport max cmd len is 256 bytes + header length (16 bytes) - * In case of ASD commands we are not sure about how much is the command size - * To be on the safe side, input buf len CBUF_LEN is increased to max (512) bytes. - */ -#define RWL_MAX_DATA_LEN (512 + 8) /* allow some extra bytes for '/n' termination */ -#define CBUF_LEN (RWL_MAX_DATA_LEN + 64) /* allow 64 bytes for header ("rwl...") */ -#else #define CBUF_LEN (128) -#endif -#ifdef WLLMAC -#define LOG_BUF_LEN 2048 -#else /* WLLMAC */ #define LOG_BUF_LEN 1024 -#endif /* WLLMAC */ typedef struct { uint32 buf; /* Can't be pointer on (64-bit) hosts */ diff --git a/drivers/net/wireless/bcm4329/wl_iw.c b/drivers/net/wireless/bcm4329/wl_iw.c index 03385bb5f56b..2fac2e800efb 100644 --- a/drivers/net/wireless/bcm4329/wl_iw.c +++ b/drivers/net/wireless/bcm4329/wl_iw.c @@ -21,7 +21,7 @@ * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. * - * $Id: wl_iw.c,v 1.51.4.9.2.6.4.108 2010/05/18 00:09:41 Exp $ + * $Id: wl_iw.c,v 1.51.4.9.2.6.4.124 2010/07/27 20:46:02 Exp $ */ @@ -53,10 +53,12 @@ typedef const struct si_pub si_t; #define WL_ASSOC(x) #define WL_INFORM(x) #define WL_WSEC(x) +#define WL_SCAN(x) #include + #ifndef IW_ENCODE_ALG_SM4 #define IW_ENCODE_ALG_SM4 0x20 #endif @@ -175,8 +177,10 @@ static volatile uint g_first_broadcast_scan; #endif #if defined(WL_IW_USE_ISCAN) +#if !defined(CSCAN) static void wl_iw_free_ss_cache(void); static int wl_iw_run_ss_cache_timer(int kick_off); +#endif int wl_iw_iscan_set_scan_broadcast_prep(struct net_device *dev, uint flag); static int dev_wlc_bufvar_set(struct net_device *dev, char *name, char *buf, int len); #define ISCAN_STATE_IDLE 0 @@ -203,8 +207,13 @@ typedef struct iscan_info { struct completion sysioc_exited; uint32 scan_flag; - +#if defined CSCAN + char ioctlbuf[WLC_IOCTL_MEDLEN]; +#else char ioctlbuf[WLC_IOCTL_SMLEN]; +#endif + wl_iscan_params_t *iscan_ex_params_p; + int iscan_ex_param_size; } iscan_info_t; #define COEX_DHCP 1 static void wl_iw_bt_flag_set(struct net_device *dev, bool set); @@ -310,7 +319,7 @@ dev_wlc_ioctl( net_os_wake_lock(dev); - WL_TRACE(("%s, PID:%x: send Local IOCTL -> dhd: cmd:0x%x, buf:%p, len:%d ,\n", + WL_INFORM(("\n%s, PID:%x: send Local IOCTL -> dhd: cmd:0x%x, buf:%p, len:%d ,\n", __FUNCTION__, current->pid, cmd, arg, len)); if (g_onoff == G_WLAN_SET_ON) { @@ -339,7 +348,7 @@ dev_wlc_ioctl( set_fs(fs); } else { - WL_TRACE(("%s: call after driver stop\n", __FUNCTION__)); + WL_TRACE(("%s: call after driver stop : ignored\n", __FUNCTION__)); } net_os_wake_unlock(dev); @@ -419,6 +428,9 @@ dev_iw_iovar_setbuf( iolen = bcm_mkiovar(iovar, param, paramlen, bufptr, buflen); ASSERT(iolen); + if (iolen == 0) + return 0; + return (dev_wlc_ioctl(dev, WLC_SET_VAR, bufptr, iolen)); } @@ -663,7 +675,7 @@ wl_iw_set_power_mode( dev_wlc_ioctl(dev, WLC_SET_PM, &pm, sizeof(pm)); } else { - WL_TRACE(("Unkwown yet power setting, ignored\n")); + WL_ERROR(("Unkwown yet power setting, ignored\n")); } p += snprintf(p, MAX_WX_STRING, "OK"); @@ -891,6 +903,69 @@ wl_iw_get_link_speed( return error; } + +static int +wl_iw_get_band( + struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, + char *extra +) +{ + int error = -1; + char *p = extra; + static int band; + + if (g_onoff == G_WLAN_SET_ON) { + error = dev_wlc_ioctl(dev, WLC_GET_BAND, &band, sizeof(band)); + + p += snprintf(p, MAX_WX_STRING, "Band %d", band); + + wrqu->data.length = p - extra + 1; + } + return error; +} + + +static int +wl_iw_set_band( + struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, + char *extra +) +{ + int error = -1; + char *p = extra; + char band; + + if (g_onoff == G_WLAN_SET_ON) { + + band = *(extra + strlen(BAND_SET_CMD) + 1) - '0'; + + if ((band == WLC_BAND_AUTO) || (band == WLC_BAND_5G) || (band == WLC_BAND_2G)) { + + + if ((error = dev_wlc_ioctl(dev, WLC_SET_BAND, + &band, sizeof(band))) >= 0) { + p += snprintf(p, MAX_WX_STRING, "OK"); + WL_TRACE(("%s: set band %d OK\n", __FUNCTION__, band)); + goto exit; + } + else WL_ERROR(("%s: set band %d failed code %d\n", __FUNCTION__, \ + band, error)); + } + else WL_ERROR(("%s Incorrect band setting, ignored\n", __FUNCTION__)); + } + + p += snprintf(p, MAX_WX_STRING, "FAIL"); + +exit: + wrqu->data.length = p - extra + 1; + return error; +} + + static int wl_iw_get_rssi( struct net_device *dev, @@ -1021,11 +1096,13 @@ wl_iw_control_wl_off( dhd_dev_reset(dev, 1); #if defined(WL_IW_USE_ISCAN) +#if !defined(CSCAN) wl_iw_free_ss_cache(); wl_iw_run_ss_cache_timer(0); - memset(g_scan, 0, G_SCAN_RESULTS); g_ss_cache_ctrl.m_link_down = 1; +#endif + memset(g_scan, 0, G_SCAN_RESULTS); g_scan_specified_ssid = 0; g_first_broadcast_scan = BROADCAST_SCAN_FIRST_IDLE; @@ -1061,12 +1138,14 @@ wl_iw_control_wl_on( wl_iw_send_priv_event(dev, "START"); +#if !defined(CSCAN) #ifdef SOFTAP if (!ap_fw_loaded) { wl_iw_iscan_set_scan_broadcast_prep(dev, 0); } #else wl_iw_iscan_set_scan_broadcast_prep(dev, 0); +#endif #endif WL_TRACE(("Exited %s \n", __FUNCTION__)); @@ -2112,35 +2191,23 @@ wl_iw_iscan_prep(wl_scan_params_t *params, wlc_ssid_t *ssid) static int wl_iw_iscan(iscan_info_t *iscan, wlc_ssid_t *ssid, uint16 action) { - int params_size = (WL_SCAN_PARAMS_FIXED_SIZE + OFFSETOF(wl_iscan_params_t, params)); - wl_iscan_params_t *params; int err = 0; - WL_TRACE(("%s: start\n", __func__)); - - if (ssid && ssid->SSID_len) { - params_size += sizeof(wlc_ssid_t); - } - params = (wl_iscan_params_t*)kmalloc(params_size, GFP_KERNEL); - if (params == NULL) { - return -ENOMEM; - } - memset(params, 0, params_size); - ASSERT(params_size < WLC_IOCTL_SMLEN); - - err = wl_iw_iscan_prep(¶ms->params, ssid); + iscan->iscan_ex_params_p->version = htod32(ISCAN_REQ_VERSION); + iscan->iscan_ex_params_p->action = htod16(action); + iscan->iscan_ex_params_p->scan_duration = htod16(0); - if (!err) { - params->version = htod32(ISCAN_REQ_VERSION); - params->action = htod16(action); - params->scan_duration = htod16(0); + WL_SCAN(("%s : nprobes=%d\n", __FUNCTION__, iscan->iscan_ex_params_p->params.nprobes)); + WL_SCAN(("active_time=%d\n", iscan->iscan_ex_params_p->params.active_time)); + WL_SCAN(("passive_time=%d\n", iscan->iscan_ex_params_p->params.passive_time)); + WL_SCAN(("home_time=%d\n", iscan->iscan_ex_params_p->params.home_time)); + WL_SCAN(("scan_type=%d\n", iscan->iscan_ex_params_p->params.scan_type)); + WL_SCAN(("bss_type=%d\n", iscan->iscan_ex_params_p->params.bss_type)); - - (void) dev_iw_iovar_setbuf(iscan->dev, "iscan", params, params_size, - iscan->ioctlbuf, WLC_IOCTL_SMLEN); - } + + (void) dev_iw_iovar_setbuf(iscan->dev, "iscan", iscan->iscan_ex_params_p, \ + iscan->iscan_ex_param_size, iscan->ioctlbuf, sizeof(iscan->ioctlbuf)); - kfree(params); return err; } @@ -2151,7 +2218,7 @@ wl_iw_timerfunc(ulong data) if (iscan) { iscan->timer_on = 0; if (iscan->iscan_state != ISCAN_STATE_IDLE) { - WL_TRACE(("timer trigger\n")); + WL_SCAN(("timer trigger\n")); up(&iscan->sysioc_sem); } } @@ -2221,9 +2288,9 @@ wl_iw_iscan_get(iscan_info_t *iscan) results->buflen = dtoh32(results->buflen); results->version = dtoh32(results->version); results->count = dtoh32(results->count); - WL_TRACE(("results->count = %d\n", results->count)); + WL_SCAN(("results->count = %d\n", results->count)); - WL_TRACE(("results->buflen = %d\n", results->buflen)); + WL_SCAN(("results->buflen = %d\n", results->buflen)); status = dtoh32(list_buf->status); mutex_unlock(&wl_cache_lock); return status; @@ -2249,8 +2316,10 @@ static void wl_iw_send_scan_complete(iscan_info_t *iscan) memset(&wrqu, 0, sizeof(wrqu)); wireless_send_event(iscan->dev, SIOCGIWSCAN, &wrqu, NULL); +#if !defined(CSCAN) if (g_first_broadcast_scan == BROADCAST_SCAN_FIRST_STARTED) g_first_broadcast_scan = BROADCAST_SCAN_FIRST_RESULT_READY; +#endif WL_TRACE(("Send Event ISCAN complete\n")); #endif } @@ -2271,7 +2340,7 @@ _iscan_sysioc_thread(void *data) #if defined(SOFTAP) if (ap_cfg_running) { - WL_TRACE(("%s skipping SCAN ops in AP mode !!!\n", __FUNCTION__)); + WL_SCAN(("%s skipping SCAN ops in AP mode !!!\n", __FUNCTION__)); net_os_wake_unlock(iscan->dev); continue; } @@ -2291,7 +2360,7 @@ _iscan_sysioc_thread(void *data) #endif if (g_scan_specified_ssid && (iscan_pass_abort == TRUE)) { - WL_TRACE(("%s Get results from specific scan status=%d\n", __FUNCTION__, status)); + WL_SCAN(("%s Get results from specific scan status=%d\n", __FUNCTION__, status)); wl_iw_send_scan_complete(iscan); iscan_pass_abort = FALSE; status = -1; @@ -2299,7 +2368,7 @@ _iscan_sysioc_thread(void *data) switch (status) { case WL_SCAN_RESULTS_PARTIAL: - WL_TRACE(("iscanresults incomplete\n")); + WL_SCAN(("iscanresults incomplete\n")); #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) rtnl_lock(); #endif @@ -2313,18 +2382,18 @@ _iscan_sysioc_thread(void *data) iscan->timer_on = 1; break; case WL_SCAN_RESULTS_SUCCESS: - WL_TRACE(("iscanresults complete\n")); + WL_SCAN(("iscanresults complete\n")); iscan->iscan_state = ISCAN_STATE_IDLE; wl_iw_send_scan_complete(iscan); break; case WL_SCAN_RESULTS_PENDING: - WL_TRACE(("iscanresults pending\n")); + WL_SCAN(("iscanresults pending\n")); mod_timer(&iscan->timer, jiffies + iscan->timer_ms*HZ/1000); iscan->timer_on = 1; break; case WL_SCAN_RESULTS_ABORTED: - WL_TRACE(("iscanresults aborted\n")); + WL_SCAN(("iscanresults aborted\n")); iscan->iscan_state = ISCAN_STATE_IDLE; if (g_scan_specified_ssid == 0) wl_iw_send_scan_complete(iscan); @@ -2334,11 +2403,11 @@ _iscan_sysioc_thread(void *data) } break; case WL_SCAN_RESULTS_NO_MEM: - WL_TRACE(("iscanresults can't alloc memory: skip\n")); + WL_SCAN(("iscanresults can't alloc memory: skip\n")); iscan->iscan_state = ISCAN_STATE_IDLE; break; default: - WL_TRACE(("iscanresults returned unknown status %d\n", status)); + WL_SCAN(("iscanresults returned unknown status %d\n", status)); break; } @@ -2354,6 +2423,7 @@ _iscan_sysioc_thread(void *data) } #endif +#if !defined(CSCAN) static void wl_iw_set_ss_cache_timer_flag(void) @@ -2519,18 +2589,12 @@ wl_iw_add_bss_to_ss_cache(wl_scan_results_t *ss_list) if (node) { continue; } - leaf = kmalloc(WLC_IW_SS_CACHE_MAXLEN, GFP_KERNEL); + leaf = kmalloc(bi->length + WLC_IW_SS_CACHE_CTRL_FIELD_MAXLEN, GFP_KERNEL); if (!leaf) { mutex_unlock(&wl_cache_lock); return -ENOMEM; } - if (bi->length > WLC_IW_BSS_INFO_MAXLEN) { - WL_TRACE(("bss info length is too long : %d\n", bi->length)); - kfree(leaf); - continue; - } - memcpy(leaf->bss_info, bi, bi->length); leaf->next = NULL; leaf->dirty = 1; @@ -2610,6 +2674,7 @@ wl_iw_delete_bss_from_ss_cache(void *addr) return 0; } +#endif static int @@ -2623,6 +2688,11 @@ wl_iw_set_scan( int error; WL_TRACE(("%s dev:%s: SIOCSIWSCAN : SCAN\n", __FUNCTION__, dev->name)); +#if defined(CSCAN) + WL_ERROR(("%s: Scan from SIOCGIWSCAN not supported\n", __FUNCTION__)); + return -EINVAL; +#endif + #if defined(SOFTAP) if (ap_cfg_running) { WL_TRACE(("\n>%s: Not executed, reason -'SOFTAP is active'\n", __FUNCTION__)); @@ -2683,6 +2753,7 @@ wl_iw_iscan_set_scan_broadcast_prep(struct net_device *dev, uint flag) wlc_ssid_t ssid; iscan_info_t *iscan = g_iscan; +#if !defined(CSCAN) if (g_first_broadcast_scan == BROADCAST_SCAN_FIRST_IDLE) { g_first_broadcast_scan = BROADCAST_SCAN_FIRST_STARTED; WL_TRACE(("%s: First Brodcast scan was forced\n", __FUNCTION__)); @@ -2691,11 +2762,7 @@ wl_iw_iscan_set_scan_broadcast_prep(struct net_device *dev, uint flag) WL_TRACE(("%s: ignore ISCAN request first BS is not done yet\n", __FUNCTION__)); return 0; } - - memset(&ssid, 0, sizeof(ssid)); - - iscan->list_cur = iscan->list_hdr; - iscan->iscan_state = ISCAN_STATE_SCANING; +#endif #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) if (flag) @@ -2706,7 +2773,14 @@ wl_iw_iscan_set_scan_broadcast_prep(struct net_device *dev, uint flag) wl_iw_set_event_mask(dev); WL_TRACE(("+++: Set Broadcast ISCAN\n")); + + memset(&ssid, 0, sizeof(ssid)); + iscan->list_cur = iscan->list_hdr; + iscan->iscan_state = ISCAN_STATE_SCANING; + + memset(&iscan->iscan_ex_params_p->params, 0, iscan->iscan_ex_param_size); + wl_iw_iscan_prep(&iscan->iscan_ex_params_p->params, &ssid); wl_iw_iscan(iscan, &ssid, WL_SCAN_ACTION_START); #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) @@ -2733,6 +2807,11 @@ wl_iw_iscan_set_scan( WL_TRACE(("%s: SIOCSIWSCAN : ISCAN\n", dev->name)); +#if defined(CSCAN) + WL_ERROR(("%s: Scan from SIOCGIWSCAN not supported\n", __FUNCTION__)); + return -EINVAL; +#endif + #if defined(SOFTAP) if (ap_cfg_running) { WL_TRACE(("\n>%s: Not executed, reason -'SOFTAP is active'\n", __FUNCTION__)); @@ -2765,11 +2844,13 @@ wl_iw_iscan_set_scan( if (wrqu->data.flags & IW_SCAN_THIS_ESSID) { int as = 0; struct iw_scan_req *req = (struct iw_scan_req *)extra; +#if !defined(CSCAN) if (g_first_broadcast_scan < BROADCAST_SCAN_FIRST_RESULT_CONSUMED) { WL_TRACE(("%s First ISCAN in progress : ignoring SC = %s\n", \ __FUNCTION__, req->essid)); return -EBUSY; } +#endif ssid.SSID_len = MIN(sizeof(ssid.SSID), req->essid_len); memcpy(ssid.SSID, req->essid, ssid.SSID_len); ssid.SSID_len = htod32(ssid.SSID_len); @@ -3054,11 +3135,15 @@ wl_iw_get_scan( uint buflen_from_user = dwrq->length; uint len = G_SCAN_RESULTS; __u16 len_ret = 0; +#if !defined(CSCAN) __u16 merged_len = 0; +#endif #if defined(WL_IW_USE_ISCAN) iscan_info_t *iscan = g_iscan; iscan_buf_t * p_buf; +#if !defined(CSCAN) uint32 counter = 0; +#endif #endif WL_TRACE(("%s: buflen_from_user %d: \n", dev->name, buflen_from_user)); @@ -3074,6 +3159,7 @@ wl_iw_get_scan( if (ci.scan_channel) return -EAGAIN; +#if !defined(CSCAN) if (g_ss_cache_ctrl.m_timer_expired) { wl_iw_free_ss_cache(); g_ss_cache_ctrl.m_timer_expired ^= 1; @@ -3091,6 +3177,7 @@ wl_iw_get_scan( else { g_ss_cache_ctrl.m_cons_br_scan_cnt++; } +#endif if (g_scan_specified_ssid) { @@ -3126,6 +3213,7 @@ wl_iw_get_scan( return -EINVAL; } +#if !defined(CSCAN) if (g_scan_specified_ssid) { wl_iw_add_bss_to_ss_cache(list); @@ -3161,6 +3249,37 @@ wl_iw_get_scan( len_ret += merged_len; wl_iw_run_ss_cache_timer(0); wl_iw_run_ss_cache_timer(1); +#else + + if (g_scan_specified_ssid) { + WL_TRACE(("%s: Specified scan APs in the list =%d\n", __FUNCTION__, list->count)); + len_ret = (__u16) wl_iw_get_scan_prep(list, info, extra, buflen_from_user); + kfree(list); + +#if defined(WL_IW_USE_ISCAN) + p_buf = iscan->list_hdr; + + while (p_buf != iscan->list_cur) { + list_merge = &((wl_iscan_results_t*)p_buf->iscan_buf)->results; + WL_TRACE(("%s: Bcast APs list=%d\n", __FUNCTION__, list_merge->count)); + if (list_merge->count > 0) + len_ret += (__u16) wl_iw_get_scan_prep(list_merge, info, + extra+len_ret, buflen_from_user -len_ret); + p_buf = p_buf->next; + } +#else + list_merge = (wl_scan_results_t *) g_scan; + WL_TRACE(("%s: Bcast APs list=%d\n", __FUNCTION__, list_merge->count)); + if (list_merge->count > 0) + len_ret += (__u16) wl_iw_get_scan_prep(list_merge, info, extra+len_ret, + buflen_from_user -len_ret); +#endif + } + else { + list = (wl_scan_results_t *) g_scan; + len_ret = (__u16) wl_iw_get_scan_prep(list, info, extra, buflen_from_user); + } +#endif #if defined(WL_IW_USE_ISCAN) @@ -3195,8 +3314,10 @@ wl_iw_iscan_get_scan( iscan_info_t *iscan = g_iscan; iscan_buf_t * p_buf; uint32 counter = 0; +#if !defined(CSCAN) __u16 merged_len = 0; uint buflen_from_user = dwrq->length; +#endif WL_TRACE(("%s %s buflen_from_user %d:\n", dev->name, __FUNCTION__, dwrq->length)); @@ -3212,17 +3333,20 @@ wl_iw_iscan_get_scan( return -EINVAL; } +#if !defined(CSCAN) if (g_first_broadcast_scan < BROADCAST_SCAN_FIRST_RESULT_READY) { WL_TRACE(("%s %s: first ISCAN results are NOT ready yet \n", \ dev->name, __FUNCTION__)); return -EAGAIN; } +#endif if ((!iscan) || (iscan->sysioc_pid < 0)) { WL_TRACE(("%ssysioc_pid\n", __FUNCTION__)); return wl_iw_get_scan(dev, info, dwrq, extra); } +#if !defined(CSCAN) if (g_ss_cache_ctrl.m_timer_expired) { wl_iw_free_ss_cache(); g_ss_cache_ctrl.m_timer_expired ^= 1; @@ -3242,6 +3366,7 @@ wl_iw_iscan_get_scan( g_ss_cache_ctrl.m_prev_scan_mode = g_scan_specified_ssid; g_ss_cache_ctrl.m_cons_br_scan_cnt++; } +#endif WL_TRACE(("%s: SIOCGIWSCAN GET broadcast results\n", dev->name)); apcnt = 0; @@ -3340,12 +3465,14 @@ wl_iw_iscan_get_scan( dwrq->length = event - extra; dwrq->flags = 0; +#if !defined(CSCAN) wl_iw_merge_scan_cache(info, event, buflen_from_user - dwrq->length, &merged_len); dwrq->length += merged_len; wl_iw_run_ss_cache_timer(0); wl_iw_run_ss_cache_timer(1); g_first_broadcast_scan = BROADCAST_SCAN_FIRST_RESULT_CONSUMED; +#endif WL_TRACE(("%s return to WE %d bytes APs=%d\n", __FUNCTION__, dwrq->length, counter)); @@ -4738,6 +4865,7 @@ int dev_iw_read_cfg1_bss_var(struct net_device *dev, int *val) } +#ifndef AP_ONLY static int wl_bssiovar_mkbuf( const char *iovar, int bssidx, @@ -4780,6 +4908,7 @@ static int wl_bssiovar_mkbuf( *perr = 0; return iolen; } +#endif int get_user_params(char *user_params, struct iw_point *dwrq) @@ -4800,91 +4929,24 @@ int get_user_params(char *user_params, struct iw_point *dwrq) #define strtoul(nptr, endptr, base) bcm_strtoul((nptr), (endptr), (base)) -static int -wl_iw_parse_channel_list(char** list_str, uint16* channel_list, int channel_num) -{ - int num; - int val; - char* str; - char* endptr = NULL; - - if ((list_str == NULL)||(*list_str == NULL)) - return -1; - - str = *list_str; - num = 0; - while (strncmp(str, GET_NPROBE, strlen(GET_NPROBE))) { - val = (int)strtoul(str, &endptr, 0); - if (endptr == str) { - printf("could not parse channel number starting at" - " substring \"%s\" in list:\n%s\n", - str, *list_str); - return -1; - } - str = endptr + strspn(endptr, " ,"); - - if (num == channel_num) { - printf("too many channels (more than %d) in channel list:\n%s\n", - channel_num, *list_str); - return -1; - } - - channel_list[num++] = (uint16)val; - } - *list_str = str; - return num; -} - - - -static int -wl_iw_parse_ssid_list(char** list_str, wlc_ssid_t* ssid, int idx, int max) -{ - char* str, *ptr; - - if ((list_str == NULL) || (*list_str == NULL)) - return -1; - - for (str = *list_str; str != NULL; str = ptr) { - - if (!strncmp(str, GET_CHANNEL, strlen(GET_CHANNEL))) { - *list_str = str + strlen(GET_CHANNEL); - return idx; - } - - if ((ptr = strchr(str, ',')) != NULL) { - *ptr++ = '\0'; - } - - if (strlen(str) > DOT11_MAX_SSID_LEN) { - printf("ssid <%s> exceeds %d\n", str, DOT11_MAX_SSID_LEN); - return -1; - } - - if (strlen(str) == 0) - ssid[idx].SSID_len = 0; - - if (idx < max) { - strcpy((char*)ssid[idx].SSID, str); - ssid[idx].SSID_len = strlen(str); - } - idx++; - } - return idx; -} - +#if defined(CSCAN) static int -wl_iw_combined_scan_set(struct net_device *dev, wl_scan_params_t *params, \ -wlc_ssid_t* ssids_local, int nssid, int nchan) +wl_iw_combined_scan_set(struct net_device *dev, wlc_ssid_t* ssids_local, int nssid, int nchan) { int params_size = WL_SCAN_PARAMS_FIXED_SIZE + WL_NUMCHANNELS * sizeof(uint16); int err = 0; char *p; int i; + iscan_info_t *iscan = g_iscan; WL_TRACE(("%s nssid=%d nchan=%d\n", __FUNCTION__, nssid, nchan)); + if ((!dev) && (!g_iscan) && (!iscan->iscan_ex_params_p)) { + WL_ERROR(("%s error exit\n", __FUNCTION__)); + err = -1; + } + params_size += WL_SCAN_PARAMS_SSID_MAX * sizeof(wlc_ssid_t); if (nssid > 0) { @@ -4896,43 +4958,69 @@ wlc_ssid_t* ssids_local, int nssid, int nchan) goto exit; } - p = (char*)params + i; + p = ((char*)&iscan->iscan_ex_params_p->params) + i; memcpy(p, ssids_local, nssid * sizeof(wlc_ssid_t)); p += nssid * sizeof(wlc_ssid_t); } else { - p = (char*)params->channel_list + nchan * sizeof(uint16); + p = (char*)iscan->iscan_ex_params_p->params.channel_list + nchan * sizeof(uint16); } - params->channel_num = htod32((nssid << WL_SCAN_PARAMS_NSSID_SHIFT) | \ + + iscan->iscan_ex_params_p->params.channel_num = \ + htod32((nssid << WL_SCAN_PARAMS_NSSID_SHIFT) | \ (nchan & WL_SCAN_PARAMS_COUNT_MASK)); - params_size = (int) (p - (char*)params + nssid * sizeof(wlc_ssid_t)); + nssid = \ + (uint)((iscan->iscan_ex_params_p->params.channel_num >> WL_SCAN_PARAMS_NSSID_SHIFT) & \ + WL_SCAN_PARAMS_COUNT_MASK); + + + params_size = (int) (p - (char*)iscan->iscan_ex_params_p + nssid * sizeof(wlc_ssid_t)); + iscan->iscan_ex_param_size = params_size; + + iscan->list_cur = iscan->list_hdr; + iscan->iscan_state = ISCAN_STATE_SCANING; + wl_iw_set_event_mask(dev); + mod_timer(&iscan->timer, jiffies + iscan->timer_ms*HZ/1000); + + iscan->timer_on = 1; -#define SCAN_DUMP 1 #ifdef SCAN_DUMP - printf("\n### List of SSIDs to scan ###\n"); - for (i = 0; i < nssid; i++) { - if (!ssids_local[i].SSID_len) - printf("%d: Broadcast scan\n", i); - else - printf("%d: scan for %s size =%d\n", i, \ - ssids_local[i].SSID, ssids_local[i].SSID_len); - } - printf("### List of channels to scan ###\n"); - for (i = 0; i < nchan; i++) { - printf("%d ", params->channel_list[i]); + int i; + WL_SCAN(("\n### List of SSIDs to scan ###\n")); + for (i = 0; i < nssid; i++) { + if (!ssids_local[i].SSID_len) + WL_SCAN(("%d: Broadcast scan\n", i)); + else + WL_SCAN(("%d: scan for %s size =%d\n", i, \ + ssids_local[i].SSID, ssids_local[i].SSID_len)); + } + WL_SCAN(("### List of channels to scan ###\n")); + for (i = 0; i < nchan; i++) + { + WL_SCAN(("%d ", iscan->iscan_ex_params_p->params.channel_list[i])); + } + WL_SCAN(("\nnprobes=%d\n", iscan->iscan_ex_params_p->params.nprobes)); + WL_SCAN(("active_time=%d\n", iscan->iscan_ex_params_p->params.active_time)); + WL_SCAN(("passive_time=%d\n", iscan->iscan_ex_params_p->params.passive_time)); + WL_SCAN(("home_time=%d\n", iscan->iscan_ex_params_p->params.home_time)); + WL_SCAN(("scan_type=%d\n", iscan->iscan_ex_params_p->params.scan_type)); + WL_SCAN(("\n###################\n")); } - printf("\nnprobes=%d\n", params->nprobes); - printf("active_time=%d\n", params->active_time); - printf("passive_time=%d\n", params->passive_time); - printf("home_time=%d\n", params->home_time); - printf("\n###################\n"); -#endif +#endif - if ((err = dev_wlc_ioctl(dev, WLC_SCAN, params, params_size))) { - WL_TRACE(("Set SCAN for %s failed with %d\n", __FUNCTION__, error)); - err = -1; + if (params_size > WLC_IOCTL_MEDLEN) { + WL_ERROR(("Set ISCAN for %s due to params_size=%d \n", \ + __FUNCTION__, params_size)); + err = -1; + } + + if ((err = dev_iw_iovar_setbuf(dev, "iscan", iscan->iscan_ex_params_p, \ + iscan->iscan_ex_param_size, \ + iscan->ioctlbuf, sizeof(iscan->ioctlbuf)))) { + WL_TRACE(("Set ISCAN for %s failed with %d\n", __FUNCTION__, err)); + err = -1; } exit: @@ -4941,13 +5029,12 @@ exit: } -static int iwpriv_set_scan(struct net_device *dev, struct iw_request_info *info, \ +static int iwpriv_set_cscan(struct net_device *dev, struct iw_request_info *info, \ union iwreq_data *wrqu, char *ext) { int res = 0; char *extra = NULL; - wl_scan_params_t *params; - int params_size = WL_SCAN_PARAMS_FIXED_SIZE + WL_NUMCHANNELS * sizeof(uint16); + iscan_info_t *iscan = g_iscan; wlc_ssid_t ssids_local[WL_SCAN_PARAMS_SSID_MAX]; int nssid = 0; int nchan = 0; @@ -4956,11 +5043,19 @@ static int iwpriv_set_scan(struct net_device *dev, struct iw_request_info *info, __FUNCTION__, info->cmd, info->flags, wrqu->data.pointer, wrqu->data.length)); + if (g_onoff == G_WLAN_SET_OFF) { + WL_TRACE(("%s: driver is not up yet after START\n", __FUNCTION__)); + return -1; + } if (wrqu->data.length != 0) { char *str_ptr; + if (!iscan->iscan_ex_params_p) { + return -EFAULT; + } + if (!(extra = kmalloc(wrqu->data.length+1, GFP_KERNEL))) return -ENOMEM; @@ -4986,38 +5081,43 @@ static int iwpriv_set_scan(struct net_device *dev, struct iw_request_info *info, return -1; } - params_size += WL_SCAN_PARAMS_SSID_MAX * sizeof(wlc_ssid_t); - - params = (wl_scan_params_t*)kmalloc(params_size, GFP_KERNEL); - if (params == NULL) { - WL_ERROR(("%s Failed allocate %d bytes \n", __FUNCTION__, params_size)); - return -ENOMEM; - } - memset(params, 0, params_size); - ASSERT(params_size < WLC_IOCTL_MAXLEN); + memset(iscan->iscan_ex_params_p, 0, iscan->iscan_ex_param_size); + ASSERT(iscan->iscan_ex_param_size < WLC_IOCTL_MAXLEN); - wl_iw_iscan_prep(params, NULL); + + wl_iw_iscan_prep(&iscan->iscan_ex_params_p->params, NULL); + iscan->iscan_ex_params_p->version = htod32(ISCAN_REQ_VERSION); + iscan->iscan_ex_params_p->action = htod16(WL_SCAN_ACTION_START); + iscan->iscan_ex_params_p->scan_duration = htod16(0); - if ((nchan = wl_iw_parse_channel_list(&str_ptr, params->channel_list, \ - WL_NUMCHANNELS)) == -1) { + + if ((nchan = wl_iw_parse_channel_list(&str_ptr, \ + &iscan->iscan_ex_params_p->params.channel_list[0], \ + WL_NUMCHANNELS)) == -1) { WL_ERROR(("%s missing channel list\n", __FUNCTION__)); return -1; } + get_parmeter_from_string(&str_ptr, \ - GET_NPROBE, PTYPE_INTDEC, ¶ms->nprobes, 2); + GET_NPROBE, PTYPE_INTDEC, \ + &iscan->iscan_ex_params_p->params.nprobes, 2); - get_parmeter_from_string(&str_ptr, GET_ACTIVE_ASSOC_DWELL, \ - PTYPE_INTDEC, ¶ms->active_time, 3); + get_parmeter_from_string(&str_ptr, GET_ACTIVE_ASSOC_DWELL, PTYPE_INTDEC, \ + &iscan->iscan_ex_params_p->params.active_time, 4); - get_parmeter_from_string(&str_ptr, GET_PASSIVE_ASSOC_DWELL, \ - PTYPE_INTDEC, ¶ms->passive_time, 3); + get_parmeter_from_string(&str_ptr, GET_PASSIVE_ASSOC_DWELL, PTYPE_INTDEC, \ + &iscan->iscan_ex_params_p->params.passive_time, 4); - get_parmeter_from_string(&str_ptr, \ - GET_HOME_DWELL, PTYPE_INTDEC, ¶ms->home_time, 3); + get_parmeter_from_string(&str_ptr, GET_HOME_DWELL, PTYPE_INTDEC, \ + &iscan->iscan_ex_params_p->params.home_time, 4); + + get_parmeter_from_string(&str_ptr, GET_SCAN_TYPE, PTYPE_INTDEC, \ + &iscan->iscan_ex_params_p->params.scan_type, 1); + + + res = wl_iw_combined_scan_set(dev, ssids_local, nssid, nchan); - res = wl_iw_combined_scan_set(dev, params, \ - ssids_local, nssid, nchan); } else { WL_ERROR(("IWPRIV argument len = 0 \n")); return -1; @@ -5031,7 +5131,187 @@ exit_proc: } +static int +wl_iw_set_cscan( + struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, + char *extra +) +{ + int res = -1; + iscan_info_t *iscan = g_iscan; + wlc_ssid_t ssids_local[WL_SCAN_PARAMS_SSID_MAX]; + int nssid = 0; + int nchan = 0; + cscan_tlv_t *cscan_tlv_temp; + char type; + char *str_ptr; + int tlv_size_left; +#ifdef TLV_DEBUG + int i; + char tlv_in_example[] = { 'C', 'S', 'C', 'A', 'N', ' ', \ + 0x53, 0x01, 0x00, 0x00, + 'S', + 0x00, + 'S', + 0x04, + 'B', 'R', 'C', 'M', + 'C', + 0x06, + 'P', + 0x94, + 0x11, + 'T', + 0x01 + }; +#endif + + WL_TRACE(("\n### %s: info->cmd:%x, info->flags:%x, u.data=0x%p, u.len=%d\n", + __FUNCTION__, info->cmd, info->flags, + wrqu->data.pointer, wrqu->data.length)); + + if (g_onoff == G_WLAN_SET_OFF) { + WL_TRACE(("%s: driver is not up yet after START\n", __FUNCTION__)); + return -1; + } + + + if (wrqu->data.length < (strlen(CSCAN_COMMAND) + sizeof(cscan_tlv_t))) { + WL_ERROR(("%s aggument=%d less %d\n", __FUNCTION__, \ + wrqu->data.length, strlen(CSCAN_COMMAND) + sizeof(cscan_tlv_t))); + return -1; + } + +#ifdef TLV_DEBUG + memcpy(extra, tlv_in_example, sizeof(tlv_in_example)); + wrqu->data.length = sizeof(tlv_in_example); + for (i = 0; i < wrqu->data.length; i++) + printf("%02X ", extra[i]); + printf("\n"); +#endif + + str_ptr = extra; + str_ptr += strlen(CSCAN_COMMAND); + tlv_size_left = wrqu->data.length - strlen(CSCAN_COMMAND); + + cscan_tlv_temp = (cscan_tlv_t *)str_ptr; + memset(ssids_local, 0, sizeof(ssids_local)); + + if ((cscan_tlv_temp->prefix == CSCAN_TLV_PREFIX) && \ + (cscan_tlv_temp->version == CSCAN_TLV_VERSION) && \ + (cscan_tlv_temp->subver == CSCAN_TLV_SUBVERSION)) + { + str_ptr += sizeof(cscan_tlv_t); + tlv_size_left -= sizeof(cscan_tlv_t); + + + if ((nssid = wl_iw_parse_ssid_list_tlv(&str_ptr, ssids_local, \ + WL_SCAN_PARAMS_SSID_MAX, &tlv_size_left)) <= 0) { + WL_ERROR(("SSID is not presented or corrupted ret=%d\n", nssid)); + goto exit_proc; + } + else { + + memset(iscan->iscan_ex_params_p, 0, iscan->iscan_ex_param_size); + + + wl_iw_iscan_prep(&iscan->iscan_ex_params_p->params, NULL); + iscan->iscan_ex_params_p->version = htod32(ISCAN_REQ_VERSION); + iscan->iscan_ex_params_p->action = htod16(WL_SCAN_ACTION_START); + iscan->iscan_ex_params_p->scan_duration = htod16(0); + + + while (tlv_size_left > 0) + { + type = str_ptr[0]; + switch (type) { + case CSCAN_TLV_TYPE_CHANNEL_IE: + + if ((nchan = wl_iw_parse_channel_list_tlv(&str_ptr, \ + &iscan->iscan_ex_params_p->params.channel_list[0], \ + WL_NUMCHANNELS, &tlv_size_left)) == -1) { + WL_ERROR(("%s missing channel list\n", \ + __FUNCTION__)); + goto exit_proc; + } + break; + case CSCAN_TLV_TYPE_NPROBE_IE: + if ((res = wl_iw_parse_data_tlv(&str_ptr, \ + &iscan->iscan_ex_params_p->params.nprobes, \ + sizeof(iscan->iscan_ex_params_p->params.nprobes), \ + type, sizeof(char), &tlv_size_left)) == -1) { + WL_ERROR(("%s return %d\n", \ + __FUNCTION__, res)); + goto exit_proc; + } + break; + case CSCAN_TLV_TYPE_ACTIVE_IE: + if ((res = wl_iw_parse_data_tlv(&str_ptr, \ + &iscan->iscan_ex_params_p->params.active_time, \ + sizeof(iscan->iscan_ex_params_p->params.active_time), \ + type, sizeof(short), &tlv_size_left)) == -1) { + WL_ERROR(("%s return %d\n", \ + __FUNCTION__, res)); + goto exit_proc; + } + break; + case CSCAN_TLV_TYPE_PASSIVE_IE: + if ((res = wl_iw_parse_data_tlv(&str_ptr, \ + &iscan->iscan_ex_params_p->params.passive_time, \ + sizeof(iscan->iscan_ex_params_p->params.passive_time), \ + type, sizeof(short), &tlv_size_left)) == -1) { + WL_ERROR(("%s return %d\n", \ + __FUNCTION__, res)); + goto exit_proc; + } + break; + case CSCAN_TLV_TYPE_HOME_IE: + if ((res = wl_iw_parse_data_tlv(&str_ptr, \ + &iscan->iscan_ex_params_p->params.home_time, \ + sizeof(iscan->iscan_ex_params_p->params.home_time), \ + type, sizeof(short), &tlv_size_left)) == -1) { + WL_ERROR(("%s return %d\n", \ + __FUNCTION__, res)); + goto exit_proc; + } + break; + case CSCAN_TLV_TYPE_STYPE_IE: + if ((res = wl_iw_parse_data_tlv(&str_ptr, \ + &iscan->iscan_ex_params_p->params.scan_type, \ + sizeof(iscan->iscan_ex_params_p->params.scan_type), \ + type, sizeof(char), &tlv_size_left)) == -1) { + WL_ERROR(("%s return %d\n", \ + __FUNCTION__, res)); + goto exit_proc; + } + break; + + default : + WL_ERROR(("%s get unkwown type %X\n", \ + __FUNCTION__, type)); + goto exit_proc; + break; + } + } + } + } + else { + WL_ERROR(("%s get wrong TLV command\n", __FUNCTION__)); + goto exit_proc; + } + + + res = wl_iw_combined_scan_set(dev, ssids_local, nssid, nchan); + +exit_proc: + return res; +} + +#endif + #ifdef SOFTAP +#ifndef AP_ONLY static int thr_wait_for_2nd_eth_dev(void *data) { @@ -5067,7 +5347,10 @@ fail: return ret; } - +#endif +#ifndef AP_ONLY +static int last_auto_channel = 6; +#endif static int get_softap_auto_channel(struct net_device *dev, struct ap_profile *ap) { int chosen = 0; @@ -5078,12 +5361,30 @@ static int get_softap_auto_channel(struct net_device *dev, struct ap_profile *ap int ret = 0; wlc_ssid_t null_ssid; int res = 0; - +#ifndef AP_ONLY + int iolen = 0; + int mkvar_err = 0; + int bsscfg_index = 1; + char buf[WLC_IOCTL_SMLEN]; +#endif WL_SOFTAP(("Enter %s\n", __FUNCTION__)); + +#ifndef AP_ONLY + if (ap_cfg_running) { + ap->channel = last_auto_channel; + return res; + } +#endif memset(&null_ssid, 0, sizeof(wlc_ssid_t)); res |= dev_wlc_ioctl(dev, WLC_UP, &updown, sizeof(updown)); +#ifdef AP_ONLY res |= dev_wlc_ioctl(dev, WLC_SET_SSID, &null_ssid, sizeof(null_ssid)); - +#else + iolen = wl_bssiovar_mkbuf("ssid", bsscfg_index, (char *)(&null_ssid), \ + null_ssid.SSID_len+4, buf, sizeof(buf), &mkvar_err); + ASSERT(iolen); + res |= dev_wlc_ioctl(dev, WLC_SET_VAR, buf, iolen); +#endif auto_channel_retry: request.count = htod32(0); ret = dev_wlc_ioctl(dev, WLC_START_CHANNEL_SEL, &request, sizeof(request)); @@ -5113,6 +5414,11 @@ static int get_softap_auto_channel(struct net_device *dev, struct ap_profile *ap WL_ERROR(("%s fail to set up err =%d\n", __FUNCTION__, res)); goto fail; } +#ifndef AP_ONLY + if (!res) + last_auto_channel = ap->channel; +#endif + fail : return res; } @@ -5125,14 +5431,16 @@ static int set_ap_cfg(struct net_device *dev, struct ap_profile *ap) wlc_ssid_t ap_ssid; int max_assoc = 8; - int mpc = 0; int res = 0; int apsta_var = 0; +#ifndef AP_ONLY + int mpc = 0; int iolen = 0; int mkvar_err = 0; int bsscfg_index = 1; char buf[WLC_IOCTL_SMLEN]; +#endif if (!dev) { WL_ERROR(("%s: dev is null\n", __FUNCTION__)); @@ -5149,8 +5457,16 @@ static int set_ap_cfg(struct net_device *dev, struct ap_profile *ap) WL_SOFTAP((" channel = %d\n", ap->channel)); WL_SOFTAP((" max scb = %d\n", ap->max_scb)); +#ifdef AP_ONLY + if (ap_cfg_running) { + wl_iw_softap_deassoc_stations(dev); + ap_cfg_running = FALSE; + } +#endif + if (ap_cfg_running == FALSE) { +#ifndef AP_ONLY sema_init(&ap_eth_sema, 0); mpc = 0; @@ -5158,6 +5474,7 @@ static int set_ap_cfg(struct net_device *dev, struct ap_profile *ap) WL_ERROR(("%s fail to set mpc\n", __FUNCTION__)); goto fail; } +#endif updown = 0; if ((res = dev_wlc_ioctl(dev, WLC_DOWN, &updown, sizeof(updown)))) { @@ -5242,6 +5559,15 @@ static int set_ap_cfg(struct net_device *dev, struct ap_profile *ap) ap_ssid.SSID_len = strlen(ap->ssid); strncpy(ap_ssid.SSID, ap->ssid, ap_ssid.SSID_len); +#ifdef AP_ONLY + if ((res = wl_iw_set_ap_security(dev, &my_ap)) != 0) { + WL_ERROR(("ERROR:%d in:%s, wl_iw_set_ap_security is skipped\n", \ + res, __FUNCTION__)); + goto fail; + } + wl_iw_send_priv_event(dev, "ASCII_CMD=AP_BSS_START"); + ap_cfg_running = TRUE; +#else iolen = wl_bssiovar_mkbuf("ssid", bsscfg_index, (char *)(&ap_ssid), ap_ssid.SSID_len+4, buf, sizeof(buf), &mkvar_err); ASSERT(iolen); @@ -5271,6 +5597,7 @@ static int set_ap_cfg(struct net_device *dev, struct ap_profile *ap) goto fail; } } +#endif fail: WL_SOFTAP(("%s exit with %d\n", __FUNCTION__, res)); @@ -5287,6 +5614,11 @@ static int wl_iw_set_ap_security(struct net_device *dev, struct ap_profile *ap) int res = 0; int i; char *ptr; +#ifdef AP_ONLY + int mpc = 0; + wlc_ssid_t ap_ssid; +#endif + wl_wsec_key_t key; WL_SOFTAP(("\nsetting SOFTAP security mode:\n")); WL_SOFTAP(("wl_iw: set ap profile:\n")); @@ -5309,7 +5641,6 @@ static int wl_iw_set_ap_security(struct net_device *dev, struct ap_profile *ap) } else if (strnicmp(ap->sec, "wep", strlen("wep")) == 0) { - wl_wsec_key_t key; memset(&key, 0, sizeof(key)); wsec = WEP_ENABLED; @@ -5427,6 +5758,16 @@ static int wl_iw_set_ap_security(struct net_device *dev, struct ap_profile *ap) WL_SOFTAP((" wsec & auth set 'wpa-psk' (TKIP), result:&d %d\n", res)); } +#ifdef AP_ONLY + ap_ssid.SSID_len = strlen(ap->ssid); + strncpy(ap_ssid.SSID, ap->ssid, ap_ssid.SSID_len); + res |= dev_wlc_ioctl(dev, WLC_SET_SSID, &ap_ssid, sizeof(ap_ssid)); + mpc = 0; + res |= dev_wlc_intvar_set(dev, "mpc", mpc); + if (strnicmp(ap->sec, "wep", strlen("wep")) == 0) { + res |= dev_wlc_ioctl(dev, WLC_SET_KEY, &key, sizeof(key)); + } +#endif return res; } @@ -5442,7 +5783,7 @@ int get_parmeter_from_string( char *param_str_end; char *orig_str = *str_ptr; - if (!strncmp(*str_ptr, token, strlen(token))) { + if ((*str_ptr) && !strncmp(*str_ptr, token, strlen(token))) { strsep(str_ptr, "=,"); param_str_begin = *str_ptr; @@ -5563,10 +5904,14 @@ static int iwpriv_softap_stop(struct net_device *dev, net_os_wake_lock(dev); if ((ap_cfg_running == TRUE)) { - wl_iw_softap_deassoc_stations(ap_net_dev); +#ifdef AP_ONLY + wl_iw_softap_deassoc_stations(dev); +#else + wl_iw_softap_deassoc_stations(ap_net_dev); if ((res = dev_iw_write_cfg1_bss_var(dev, 2)) < 0) WL_ERROR(("%s failed to del BSS err = %d", __FUNCTION__, res)); +#endif bcm_mdelay(100); @@ -5694,6 +6039,7 @@ iwpriv_en_ap_bss( WL_TRACE(("%s: rcvd IWPRIV IOCTL: for dev:%s\n", __FUNCTION__, dev->name)); +#ifndef AP_ONLY if ((res = wl_iw_set_ap_security(dev, &my_ap)) != 0) { WL_ERROR((" %s ERROR setting SOFTAP security in :%d\n", __FUNCTION__, res)); } @@ -5704,6 +6050,7 @@ iwpriv_en_ap_bss( bcm_mdelay(100); } +#endif WL_SOFTAP(("%s done with res %d \n", __FUNCTION__, res)); net_os_wake_unlock(dev); @@ -5837,6 +6184,7 @@ int wl_iw_process_private_ascii_cmd( WL_SOFTAP(("\n!!! got 'WL_AP_EN_BSS' from WPA supplicant, dev:%s\n", dev->name)); +#ifndef AP_ONLY if (ap_net_dev == NULL) { printf("\n ERROR: SOFTAP net_dev* is NULL !!!\n"); } else { @@ -5844,15 +6192,21 @@ int wl_iw_process_private_ascii_cmd( WL_ERROR(("%s line %d fail to set bss up\n", \ __FUNCTION__, __LINE__)); } - +#else + if ((ret = iwpriv_en_ap_bss(dev, info, dwrq, cmd_str)) < 0) + WL_ERROR(("%s line %d fail to set bss up\n", \ + __FUNCTION__, __LINE__)); +#endif } else if (strnicmp(sub_cmd, "ASSOC_LST", strlen("ASSOC_LST")) == 0) { /* no code yet */ } else if (strnicmp(sub_cmd, "AP_BSS_STOP", strlen("AP_BSS_STOP")) == 0) { WL_SOFTAP((" \n temp DOWN SOFTAP\n")); +#ifndef AP_ONLY if ((ret = dev_iw_write_cfg1_bss_var(dev, 0)) < 0) { WL_ERROR(("%s line %d fail to set bss down\n", \ __FUNCTION__, __LINE__)); } +#endif } return ret; @@ -5917,6 +6271,14 @@ static int wl_iw_set_priv( ret = wl_iw_set_country(dev, info, (union iwreq_data *)dwrq, extra); else if (strnicmp(extra, "STOP", strlen("STOP")) == 0) ret = wl_iw_control_wl_off(dev, info); + else if (strnicmp(extra, BAND_GET_CMD, strlen(BAND_GET_CMD)) == 0) + ret = wl_iw_get_band(dev, info, (union iwreq_data *)dwrq, extra); + else if (strnicmp(extra, BAND_SET_CMD, strlen(BAND_SET_CMD)) == 0) + ret = wl_iw_set_band(dev, info, (union iwreq_data *)dwrq, extra); +#if defined(CSCAN) + else if (strnicmp(extra, CSCAN_COMMAND, strlen(CSCAN_COMMAND)) == 0) + ret = wl_iw_set_cscan(dev, info, (union iwreq_data *)dwrq, extra); +#endif #ifdef CUSTOMER_HW2 else if (strnicmp(extra, "POWERMODE", strlen("POWERMODE")) == 0) ret = wl_iw_set_power_mode(dev, info, (union iwreq_data *)dwrq, extra); @@ -6080,9 +6442,11 @@ static const iw_handler wl_iw_priv_handler[] = { NULL, (iw_handler)iwpriv_fw_reload, #endif +#if defined(CSCAN) NULL, - (iw_handler)iwpriv_set_scan + (iw_handler)iwpriv_set_cscan +#endif }; static const struct iw_priv_args wl_iw_priv_args[] = { @@ -6179,12 +6543,14 @@ static const struct iw_priv_args wl_iw_priv_args[] = { "WL_FW_RELOAD" }, #endif +#if defined(CSCAN) { WL_COMBO_SCAN, IW_PRIV_TYPE_CHAR | 1024, 0, "CSCAN" }, +#endif }; const struct iw_handler_def wl_iw_handler_def = @@ -6519,7 +6885,11 @@ wl_iw_event(struct net_device *dev, wl_event_msg_t *e, void* data) cmd = SIOCGIWAP; if (!(flags & WLC_EVENT_MSG_LINK)) { #ifdef SOFTAP +#ifdef AP_ONLY + if (ap_cfg_running) { +#else if (ap_cfg_running && !strncmp(dev->name, "wl0.1", 5)) { +#endif WL_SOFTAP(("AP DOWN %d\n", event_type)); wl_iw_send_priv_event(priv_dev, "AP_DOWN"); } else { @@ -6541,7 +6911,11 @@ wl_iw_event(struct net_device *dev, wl_event_msg_t *e, void* data) memcpy(g_ss_cache_ctrl.m_active_bssid, &e->addr, ETHER_ADDR_LEN); #ifdef SOFTAP +#ifdef AP_ONLY + if (ap_cfg_running) { +#else if (ap_cfg_running && !strncmp(dev->name, "wl0.1", 5)) { +#endif WL_SOFTAP(("AP UP %d\n", event_type)); wl_iw_send_priv_event(priv_dev, "AP_UP"); } else { @@ -6632,13 +7006,14 @@ wl_iw_event(struct net_device *dev, wl_event_msg_t *e, void* data) } else { cmd = SIOCGIWSCAN; wrqu.data.length = strlen(extra); - WL_TRACE(("Event WLC_E_SCAN_COMPLETE from specific scan\n")); + WL_TRACE(("Event WLC_E_SCAN_COMPLETE from specific scan %d\n", \ + g_iscan->iscan_state)); } #else cmd = SIOCGIWSCAN; wrqu.data.length = strlen(extra); WL_TRACE(("Event WLC_E_SCAN_COMPLETE\n")); -#endif +#endif break; default: @@ -6902,6 +7277,7 @@ wl_iw_bt_init(struct net_device *dev) int wl_iw_attach(struct net_device *dev, void * dhdp) { + int params_size; wl_iw_t *iw; #if defined(WL_IW_USE_ISCAN) iscan_info_t *iscan = NULL; @@ -6914,10 +7290,21 @@ int wl_iw_attach(struct net_device *dev, void * dhdp) if (!dev) return 0; +#ifdef CSCAN + params_size = (WL_SCAN_PARAMS_FIXED_SIZE + OFFSETOF(wl_iscan_params_t, params)) + + (WL_NUMCHANNELS * sizeof(uint16)) + WL_SCAN_PARAMS_SSID_MAX * sizeof(wlc_ssid_t); +#else + params_size = (WL_SCAN_PARAMS_FIXED_SIZE + OFFSETOF(wl_iscan_params_t, params)); +#endif iscan = kmalloc(sizeof(iscan_info_t), GFP_KERNEL); if (!iscan) return -ENOMEM; memset(iscan, 0, sizeof(iscan_info_t)); + + iscan->iscan_ex_params_p = (wl_iscan_params_t*)kmalloc(params_size, GFP_KERNEL); + if (!iscan->iscan_ex_params_p) + return -ENOMEM; + iscan->iscan_ex_param_size = params_size; iscan->sysioc_pid = -1; g_iscan = iscan; @@ -6952,11 +7339,12 @@ int wl_iw_attach(struct net_device *dev, void * dhdp) memset(g_scan, 0, G_SCAN_RESULTS); g_scan_specified_ssid = 0; +#if !defined(CSCAN) wl_iw_init_ss_cache_ctrl(); +#endif wl_iw_bt_init(dev); - return 0; } @@ -6978,6 +7366,7 @@ void wl_iw_detach(void) kfree(iscan->list_hdr); iscan->list_hdr = buf; } + kfree(iscan->iscan_ex_params_p); kfree(iscan); g_iscan = NULL; mutex_unlock(&wl_cache_lock); @@ -6987,7 +7376,9 @@ void wl_iw_detach(void) kfree(g_scan); g_scan = NULL; +#if !defined(CSCAN) wl_iw_release_ss_cache_ctrl(); +#endif wl_iw_bt_release(); #ifdef SOFTAP if (ap_cfg_running) { diff --git a/drivers/net/wireless/bcm4329/wl_iw.h b/drivers/net/wireless/bcm4329/wl_iw.h index 7b7b16b33b18..d49ce240b78c 100644 --- a/drivers/net/wireless/bcm4329/wl_iw.h +++ b/drivers/net/wireless/bcm4329/wl_iw.h @@ -21,7 +21,7 @@ * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. * - * $Id: wl_iw.h,v 1.5.34.1.6.18 2010/06/03 02:27:14 Exp $ + * $Id: wl_iw.h,v 1.5.34.1.6.24 2010/07/27 20:46:02 Exp $ */ @@ -41,6 +41,10 @@ #define GET_ACTIVE_ASSOC_DWELL "ACTIVE=" #define GET_PASSIVE_ASSOC_DWELL "PASSIVE=" #define GET_HOME_DWELL "HOME=" +#define GET_SCAN_TYPE "TYPE=" + +#define BAND_GET_CMD "GETBAND" +#define BAND_SET_CMD "SETBAND" #define WL_IW_RSSI_MINVAL -200 #define WL_IW_RSSI_NO_SIGNAL -91 @@ -102,7 +106,7 @@ typedef struct wl_iw { #define WLC_IW_BSS_INFO_MAXLEN \ (WLC_IW_SS_CACHE_MAXLEN - WLC_IW_SS_CACHE_CTRL_FIELD_MAXLEN) -typedef struct wl_iw_ss_cache{ +typedef struct wl_iw_ss_cache { uint32 buflen; uint32 version; uint32 count; @@ -191,4 +195,40 @@ extern int net_os_set_suspend_disable(struct net_device *dev, int val); iwe_stream_add_point(stream, ends, iwe, extra) #endif -#endif +#if defined(CSCAN) + +typedef struct cscan_tlv { + char prefix; + char version; + char subver; + char reserved; +} cscan_tlv_t; + +#define CSCAN_COMMAND "CSCAN " +#define CSCAN_TLV_PREFIX 'S' +#define CSCAN_TLV_VERSION 1 +#define CSCAN_TLV_SUBVERSION 0 +#define CSCAN_TLV_TYPE_SSID_IE 'S' +#define CSCAN_TLV_TYPE_CHANNEL_IE 'C' +#define CSCAN_TLV_TYPE_NPROBE_IE 'N' +#define CSCAN_TLV_TYPE_ACTIVE_IE 'A' +#define CSCAN_TLV_TYPE_PASSIVE_IE 'P' +#define CSCAN_TLV_TYPE_HOME_IE 'H' +#define CSCAN_TLV_TYPE_STYPE_IE 'T' + +extern int wl_iw_parse_channel_list_tlv(char** list_str, uint16* channel_list, \ + int channel_num, int *bytes_left); + +extern int wl_iw_parse_data_tlv(char** list_str, void *dst, int dst_size, \ + const char token, int input_size, int *bytes_left); + +extern int wl_iw_parse_ssid_list_tlv(char** list_str, wlc_ssid_t* ssid, \ + int max, int *bytes_left); + +extern int wl_iw_parse_ssid_list(char** list_str, wlc_ssid_t* ssid, int idx, int max); + +extern int wl_iw_parse_channel_list(char** list_str, uint16* channel_list, int channel_num); + +#endif + +#endif -- 2.34.1