net: wireless: bcm4329: Update to 4.218.245 (combo scan)
authorHoward Harte <hharte@broadcom.com>
Fri, 30 Jul 2010 00:43:06 +0000 (17:43 -0700)
committerColin Cross <ccross@android.com>
Thu, 30 Sep 2010 00:49:42 +0000 (17:49 -0700)
Signed-off-by: Dmitry Shmidt <dimitrysh@google.com>
drivers/net/wireless/bcm4329/Makefile
drivers/net/wireless/bcm4329/dhd_cdc.c
drivers/net/wireless/bcm4329/dhd_common.c
drivers/net/wireless/bcm4329/dhd_linux.c
drivers/net/wireless/bcm4329/dhd_sdio.c
drivers/net/wireless/bcm4329/include/bcmsdpcm.h
drivers/net/wireless/bcm4329/include/epivers.h
drivers/net/wireless/bcm4329/include/hndrte_cons.h
drivers/net/wireless/bcm4329/wl_iw.c
drivers/net/wireless/bcm4329/wl_iw.h

index 43f891a8ea3dd7a64bce5f0ee4e39c945eae944e..15926e4a08d31baef32452a044e7881d77c0fe2a 100644 (file)
@@ -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 \
index c95ca9b3471f44e7ba7817cd402934211fe2deef..070e95ef773e9ad25a212200140a423494a0dbdb 100644 (file)
@@ -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);
index 74b0a79091b21905dd3d95c5411b1a52c244d0cb..8faffcb23fc2958f35987270d2616343b3522b4e 100644 (file)
@@ -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 <typedefs.h>
 #include <osl.h>
@@ -50,6 +50,10 @@ int wifi_get_mac_addr(unsigned char *buf);
 
 int dhd_msg_level;
 
+#if defined(CSCAN)
+#include <wl_iw.h>
+#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 
index 00f545045cdcdefa33d9c0bbc0b711f25ca65d26..cce87ba890d50ba4506027b84277f210b6be2005 100644 (file)
@@ -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);
 }
index e5a05a7d5cec37ba37af2c115e79bb36b80ae307..0cf6508b527b66a9307f8b983fb52ac0059fe72a 100644 (file)
@@ -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 <typedefs.h>
@@ -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);
                        }
                }
index b63b1d39a51fc646a890465bda0157f16a99570b..77aca4500ad8f3f1ea05de463616352652fc9b04 100644 (file)
@@ -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;
index 1453361cb75741161e1c719f6a3b30b2640e5648..114c735fb381915b618372c7121b74daef4eb32c 100644 (file)
 
 #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 
index dccafdb55d1f504ed711fac26a8fb3f02fd0fbbd..a42417478a16b44e055d3e1bf840770f09b58c60 100644 (file)
@@ -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
  * 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 <typedefs.h>
 
-#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 */
index 03385bb5f56bb6c23a6066fd5272b504644ee6f4..2fac2e800efb0dfd014e9f8ffce852ebb08d93a6 100644 (file)
@@ -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 <wl_iw.h>
 
 
+
 #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(&params->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, &params->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, &params->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, &params->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, &params->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) {
index 7b7b16b33b1868e355322d8e414d4afd52fcdbf9..d49ce240b78cdc51a9fe417825a4a0495f2133d5 100644 (file)
@@ -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 $
  */
 
 
 #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