Update BCM4329 Wifi drivers to the glacier version

file:f94c24f94487e25880df3dcee74dcd9a495a7d82 -> file:29f464ef9b9b0336be22d239920fb2bcf88086fe
--- a/arch/arm/mach-msm/board-bravo-wifi.c
+++ b/arch/arm/mach-msm/board-bravo-wifi.c
@@ -87,6 +87,7 @@ static struct wifi_platform_data bravo_w
.set_carddetect = bravo_wifi_set_carddetect,
.mem_prealloc = bravo_wifi_mem_prealloc,
.dot11n_enable = 1,
+ .cscan_enable = 0,
};
static struct platform_device bravo_wifi_device = {
file:4e513444348acc73960a9a5a1a529e8608a6c32c -> file:9b997a94505538545dd2bf8c5a3afe03d5258e51
--- a/arch/arm/mach-msm/board-incrediblec-wifi.c
+++ b/arch/arm/mach-msm/board-incrediblec-wifi.c
@@ -102,6 +102,7 @@ static struct wifi_platform_data incredi
.set_carddetect = incrediblec_wifi_set_carddetect,
.mem_prealloc = incrediblec_wifi_mem_prealloc,
.dot11n_enable = 1,
+ .cscan_enable = 0,
};
static struct platform_device incrediblec_wifi_device = {
file:a41bb43181cca21d84ea18534033ea4d3b17f6ef -> file:d2554a6c35be8f875acebff1f40da9fabc10c6cb
--- a/arch/arm/mach-msm/board-supersonic-wifi.c
+++ b/arch/arm/mach-msm/board-supersonic-wifi.c
@@ -99,6 +99,7 @@ static struct wifi_platform_data superso
.set_carddetect = supersonic_wifi_set_carddetect,
.mem_prealloc = supersonic_wifi_mem_prealloc,
.dot11n_enable = 1,
+ .cscan_enable = 0,
};
static struct platform_device supersonic_wifi_device = {
file:35b7a93e50aa51e21e8e62b10878cdd8183e5932 -> file:87db44ead73e11e7348a917d81a27130b758d25f
--- a/drivers/net/wireless/bcm4329_204/Makefile
+++ b/drivers/net/wireless/bcm4329_204/Makefile
@@ -5,7 +5,8 @@ DHDCFLAGS = -DLINUX -DBCMDRIVER -DBCMDON
-DSHOW_EVENTS -DBCMSDIO -DDHD_GPL -DBCMLXSDMMC -DBCMPLATFORM_BUS \
-Wall -Wstrict-prototypes -Werror -DOOB_INTR_ONLY -DCUSTOMER_HW2 \
-DDHD_USE_STATIC_BUF -DMMC_SDIO_ABORT -DWLAN_PFN -DWLAN_PROTECT \
- -DBCMWAPI_WPI \
+ -DBCMWAPI_WPI -DWLAN_LOW_RSSI_IND -DCSCAN -DSOFTAP_PROTECT \
+ -DMMC_RECOVER \
-Idrivers/net/wireless/bcm4329_204 -Idrivers/net/wireless/bcm4329_204/include
DHDOFILES = dhd_linux.o linux_osl.o bcmutils.o dhd_common.o dhd_custom_gpio.o \
file:166bf3e23a18cc6446317866d298db3462bc6e16 -> file:97f233eb909280b77beaa15a82c662bbccff399a
--- a/drivers/net/wireless/bcm4329_204/bcmsdh_linux.c
+++ b/drivers/net/wireless/bcm4329_204/bcmsdh_linux.c
@@ -2,13 +2,13 @@
* SDIO access interface for drivers - linux specific (pci only)
*
* 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
@@ -16,7 +16,7 @@
* 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.
@@ -600,7 +600,7 @@ int bcmsdh_register_oob_intr(void * dhdp
return -ENODEV;
set_irq_wake(sdhcinfo->oob_irq, 1);
-
+ myprintf("irq: %d\n", sdhcinfo->oob_irq);
return 0;
}
file:5c7b3a073d6440954806b091562207e1dc17096c -> file:305ae545f69191c1b6bfbe0aeb1c93d925fa20a1
--- a/drivers/net/wireless/bcm4329_204/dhd.h
+++ b/drivers/net/wireless/bcm4329_204/dhd.h
@@ -413,6 +413,7 @@ enum dhdhtc_pwr_ctrl{
DHDHTC_POWER_CTRL_BROWSER_LOAD_PAGE,
DHDHTC_POWER_CTRL_USER_CONFIG,
DHDHTC_POWER_CTRL_WIFI_PHONE,
+ DHDHTC_POWER_CTRL_FOTA_DOWNLOADING,
DHDHTC_POWER_CTRL_MAX_NUM,
};
extern int dhdhtc_update_wifi_power_mode(int is_screen_off);
@@ -420,5 +421,8 @@ extern int dhdhtc_set_power_control(int
extern unsigned int dhdhtc_get_cur_pwr_ctrl(void);
extern int dhdhtc_update_dtim_listen_interval(int is_screen_off);
+#ifdef MMC_RECOVER
+void dhdsdio_set_mmc_recover(int set);
+#endif
#endif /* _dhd_h_ */
file:2412e886e97031bc3a995c5d43dec1afc03bb581 -> file:54229be0af026675e0712bd8348275ee0c470335
--- a/drivers/net/wireless/bcm4329_204/dhd_cdc.c
+++ b/drivers/net/wireless/bcm4329_204/dhd_cdc.c
@@ -609,6 +609,7 @@ static int dhd_set_pfn(dhd_pub_t *dhd, i
wl_pfn_t pfn_element;
int i;
int config_network = 0;
+ int iov_len = 0;
/* Disable pfn */
bcm_mkiovar("pfn", (char *)&pfn_enabled, 4, iovbuf, sizeof(iovbuf));
dhdcdc_set_ioctl(dhd, 0, WLC_SET_VAR, iovbuf, sizeof(iovbuf));
@@ -617,8 +618,9 @@ static int dhd_set_pfn(dhd_pub_t *dhd, i
return 0;
/* clear pfn */
- bcm_mkiovar("pfnclear", NULL, 0, iovbuf, sizeof(iovbuf));
- dhdcdc_set_ioctl(dhd, 0, WLC_SET_VAR, iovbuf, sizeof(iovbuf));
+ iov_len = bcm_mkiovar("pfnclear", NULL, 0, iovbuf, sizeof(iovbuf));
+ if (iov_len)
+ dhdcdc_set_ioctl(dhd, 0, WLC_SET_VAR, iovbuf, iov_len);
/* set pfn parameters */
pfn_param.version = htod32(PFN_VERSION);
@@ -704,6 +706,10 @@ int dhd_set_suspend(int value, dhd_pub_t
/* set pfn */
dhd_set_pfn(dhd, 1);
#endif
+
+#ifdef MMC_RECOVER
+ dhdsdio_set_mmc_recover(1);
+#endif
/* indicate wl_iw screen off */
wl_iw_set_screen_off(1);
@@ -731,6 +737,9 @@ int dhd_set_suspend(int value, dhd_pub_t
#ifdef WLAN_PFN
dhd_set_pfn(dhd, 0);
#endif
+#ifdef MMC_RECOVER
+ dhdsdio_set_mmc_recover(0);
+#endif
/* indicate wl_iw screen on */
wl_iw_set_screen_off(0);
}
@@ -854,6 +863,9 @@ int dhd_set_pktfilter(int add, int id, i
return 0;
}
+#define WLC_HT_WEP_RESTRICT 0x01 /* restrict HT with TKIP */
+#define WLC_HT_TKIP_RESTRICT 0x02 /* restrict HT with WEP */
+
int
dhd_preinit_ioctls(dhd_pub_t *dhd)
{
@@ -893,6 +905,7 @@ dhd_preinit_ioctls(dhd_pub_t *dhd)
uint filter_mode = 1;
wl_keep_alive_pkt_t keep_alive_pkt;
wl_keep_alive_pkt_t *keep_alive_pktp;
+ int ht_wsec_restrict = WLC_HT_TKIP_RESTRICT | WLC_HT_WEP_RESTRICT;
pdhd = dhd;
@@ -981,6 +994,9 @@ dhd_preinit_ioctls(dhd_pub_t *dhd)
#ifdef WLAN_PFN
setbit(eventmask, WLC_E_PFN_NET_FOUND);
#endif
+#ifdef WLAN_LOW_RSSI_IND
+ setbit(eventmask, WLC_E_RSSI_LOW);
+#endif
bcm_mkiovar("event_msgs", eventmask, WL_EVENTING_MASK_LEN, iovbuf, sizeof(iovbuf));
dhdcdc_set_ioctl(dhd, 0, WLC_SET_VAR, iovbuf, sizeof(iovbuf));
@@ -1114,6 +1130,10 @@ dhd_preinit_ioctls(dhd_pub_t *dhd)
dhdcdc_set_ioctl(dhd, 0, WLC_SET_VAR, buf, buf_len);
+ /* set HT restrict */
+ bcm_mkiovar("ht_wsec_restrict", (char *)&ht_wsec_restrict, 4, iovbuf, sizeof(iovbuf));
+ dhdcdc_set_ioctl(dhd, 0, WLC_SET_VAR, iovbuf, sizeof(iovbuf));
+
dhd_os_proto_unblock(dhd);
return 0;
}
file:8424bd01a19661157a62ea0ec0a2f01fb4078342 -> file:6330dd3125485e5de3ecc704d3c0a1ec452797bc
--- a/drivers/net/wireless/bcm4329_204/dhd_common.c
+++ b/drivers/net/wireless/bcm4329_204/dhd_common.c
@@ -49,6 +49,10 @@ extern void htc_linux_periodic_wakeup_st
int dhd_msg_level;
+#if defined(CSCAN)
+#include <wl_iw.h>
+#endif
+
char fw_path[MOD_PARAM_PATHLEN];
char nv_path[MOD_PARAM_PATHLEN];
@@ -57,6 +61,12 @@ uint32 dhd_conn_event;
uint32 dhd_conn_status;
uint32 dhd_conn_reason;
+#define htod32(i) i
+#define htod16(i) i
+#define dtoh32(i) i
+#define dtoh16(i) i
+#define strtoul(nptr, endptr, base) bcm_strtoul((nptr), (endptr), (base))
+
#ifdef DHD_DEBUG
const char dhd_version[] = "Dongle Host Driver, version " EPI_VERSION_STR "\nCompiled on "
__DATE__ " at " __TIME__;
@@ -926,3 +936,254 @@ wl_event_to_host_order(wl_event_msg_t *e
evt->datalen = ntoh32(evt->datalen);
evt->version = ntoh16(evt->version);
}
+
+/* Androd 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));
+ printk (KERN_INFO"[WLAN] BROADCAST SCAN\n");
+ }
+ else if (str[0] <= DOT11_MAX_SSID_LEN) {
+ printk (KERN_INFO"[WLAN] Specific SSID scan\n");
+ /* 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) {
+ printk(KERN_INFO"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
+
file:44da2c7c1244ec903a3821a143f30d30133ca0e6 -> file:ab4382205cb92d1a052ce5bb450bef220e117801
--- a/drivers/net/wireless/bcm4329_204/dhd_linux.c
+++ b/drivers/net/wireless/bcm4329_204/dhd_linux.c
@@ -99,6 +99,14 @@ int wifi_get_dot11n_enable(void)
return 0;
}
+int wifi_get_cscan_enable(void)
+{
+ if (wifi_control_data && wifi_control_data->cscan_enable) {
+ return wifi_control_data->cscan_enable;
+ }
+ return 0;
+}
+
int wifi_set_carddetect(int on)
{
myprintf("%s = %d\n", __FUNCTION__, on);
@@ -853,6 +861,8 @@ _dhd_sysioc_thread(void *data)
}
dhd_os_wake_unlock(&dhd->pub);
}
+
+ myprintf("%s exit\n", __func__);
complete_and_exit(&dhd->sysioc_exited, 0);
}
@@ -865,6 +875,14 @@ dhd_set_mac_address(struct net_device *d
struct sockaddr *sa = (struct sockaddr *)addr;
int ifidx;
+ myprintf("enter %s\n", __func__);
+
+ /* BRCM: anthony, add for debug, reject if down */
+ if ( !dhd->pub.up || (dhd->pub.busstate == DHD_BUS_DOWN)) {
+ printk("%s: dhd is down. skip it.\n", __func__);
+ return -ENODEV;
+ }
+
ifidx = dhd_net2idx(dhd, dev);
if (ifidx == DHD_BAD_IF)
return -1;
@@ -883,6 +901,15 @@ dhd_set_multicast_list(struct net_device
dhd_info_t *dhd = *(dhd_info_t **)netdev_priv(dev);
int ifidx;
+
+ myprintf("enter %s\n", __func__);
+
+ /* BRCM: anthoy, add for debug, reject if down */
+ if ( !dhd->pub.up || (dhd->pub.busstate == DHD_BUS_DOWN) ) {
+ printk("%s: dhd is down. skip it.\n", __func__);
+ return;
+ }
+
ifidx = dhd_net2idx(dhd, dev);
if (ifidx == DHD_BAD_IF)
return;
@@ -1208,7 +1235,7 @@ dhd_watchdog_thread(void *data)
else
break;
}
-
+ myprintf("%s exit\n", __func__);
complete_and_exit(&dhd->watchdog_exited, 0);
}
@@ -1277,7 +1304,7 @@ dhd_dpc_thread(void *data)
else
break;
}
-
+ myprintf("%s exit\n", __func__);
complete_and_exit(&dhd->dpc_exited, 0);
}
@@ -1525,6 +1552,13 @@ dhd_ioctl_entry(struct net_device *net,
int ifidx;
bool is_set_key_cmd;
+
+ /* BRCM: anthoy, add for debug, reject if down */
+ if ( !dhd->pub.up || (dhd->pub.busstate == DHD_BUS_DOWN)){
+ myprintf("%s: dhd is down. skip it.\n", __func__);
+ return -ENODEV;
+ }
+
ifidx = dhd_net2idx(dhd, net);
DHD_TRACE(("%s: ifidx %d, cmd 0x%04x\n", __FUNCTION__, ifidx, cmd));
@@ -2418,6 +2452,11 @@ dhd_os_wd_timer(void *bus, uint wdtick)
dhd_info_t *dhd = (dhd_info_t *)pub->info;
static uint save_dhd_watchdog_ms = 0;
+ /* BRCM: anthony: stop timer, if bus down. */
+ if (pub->busstate == DHD_BUS_DOWN) {
+ return;
+ }
+
/* Totally stop the timer */
if (!wdtick && dhd->wd_timer_valid == TRUE) {
del_timer_sync(&dhd->timer);
file:fa223c063b14344026d0da41181186e2a4b4237d -> file:34d38a1440863e3f089ec6cac24347d36e2c84dd
--- a/drivers/net/wireless/bcm4329_204/dhd_sdio.c
+++ b/drivers/net/wireless/bcm4329_204/dhd_sdio.c
@@ -2,13 +2,13 @@
* DHD Bus Module for SDIO
*
* 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
@@ -16,7 +16,7 @@
* 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.
@@ -2445,6 +2445,8 @@ dhd_bus_stop(struct dhd_bus *bus, bool e
if (enforce_mutex)
dhd_os_sdlock(bus->dhd);
+ myprintf("%s enter\n", __func__);
+
BUS_WAKE(bus);
/* Enable clock for device interrupts */
@@ -3798,6 +3800,21 @@ dhdsdio_hostmail(dhd_bus_t *bus)
return intstatus;
}
+#ifdef MMC_RECOVER
+static uint8 prev_tx_seq = 0;
+static uint8 prev_tx_max = 0;
+static int max_equal_count = 0;
+static int start_mmc_recover = 0;
+void dhdsdio_set_mmc_recover(int set)
+{
+ // myprintf("set mmc recover %d\n", set);
+ if (set)
+ start_mmc_recover = 1;
+ else
+ start_mmc_recover = 0;
+}
+#endif
+
static int dhdsdio_regfail = 0;
bool
dhdsdio_dpc(dhd_bus_t *bus)
@@ -3957,6 +3974,28 @@ clkwait:
bcmsdh_intr_enable(sdh);
}
+#ifdef MMC_RECOVER
+ if (start_mmc_recover) {
+ if ((bus->tx_max == bus->tx_seq)&&(bus->tx_max == prev_tx_max)&&(bus->tx_seq == prev_tx_seq)) {
+ max_equal_count++;
+ //myprintf("bad case, count %d\n", max_equal_count);
+ //myprintf("framecnt = %d\n", framecnt);
+ } else {
+ max_equal_count = 0;
+ }
+
+ prev_tx_max = bus->tx_max;
+ prev_tx_seq = bus->tx_seq;
+
+ if (max_equal_count >= 5) {
+ bus->tx_seq = (bus->tx_seq + 1) % SDPCM_SEQUENCE_WRAP;
+ //bus->tx_max = bus->tx_seq + 2;
+ max_equal_count = 0;
+ //myprintf("reset count\n");
+ }
+ }
+#endif
+
if (DATAOK(bus) && bus->ctrl_frame_stat) {
int ret, i;
@@ -4102,7 +4141,7 @@ dhdsdio_isr(void *arg)
#else
bus->dpc_sched = TRUE;
dhd_sched_dpc(bus->dhd);
-#endif
+#endif
}
@@ -5012,9 +5051,11 @@ dhdsdio_release(dhd_bus_t *bus, osl_t *o
if (bus->dhd) {
- dhdsdio_release_dongle(bus, osh);
-
+ /* BRCM: anthony: move dhd_detach before dhdsdio_release_dongle
+ * to avoid unnecessary commands running.
+ */
dhd_detach(bus->dhd);
+ dhdsdio_release_dongle(bus, osh);
bus->dhd = NULL;
}
@@ -5064,11 +5105,11 @@ dhdsdio_release_dongle(dhd_bus_t *bus, o
return;
if (bus->sih) {
- dhdsdio_clkctl(bus, CLK_AVAIL, FALSE);
#if !defined(BCMLXSDMMC)
+ dhdsdio_clkctl(bus, CLK_AVAIL, FALSE);
si_watchdog(bus->sih, 4);
-#endif /* !defined(BCMLXSDMMC) */
dhdsdio_clkctl(bus, CLK_NONE, FALSE);
+#endif /* !defined(BCMLXSDMMC) */
si_detach(bus->sih);
if (bus->vars && bus->varsz)
MFREE(osh, bus->vars, bus->varsz);
@@ -5564,7 +5605,7 @@ dhd_bus_devreset(dhd_pub_t *dhdp, uint8
#if !defined(IGNORE_ETH0_DOWN)
/* Restore flow control */
dhd_txflowcontrol(bus->dhd, 0, OFF);
-#endif
+#endif
DHD_TRACE(("%s: WLAN ON DONE\n", __FUNCTION__));
} else
file:c7bb3376edbc2e65c2e6b0cc5721be5269ae7f3a -> file:e52e55a9776b692fa4d93d6e6fa82a12eef5253b
--- a/drivers/net/wireless/bcm4329_204/include/proto/bcmevent.h
+++ b/drivers/net/wireless/bcm4329_204/include/proto/bcmevent.h
@@ -2,13 +2,13 @@
* Broadcom Event protocol definitions
*
* Copyright (C) 1999-2009, 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
@@ -16,7 +16,7 @@
* 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.
@@ -41,26 +41,26 @@
#include <packed_section_start.h>
-#define BCM_EVENT_MSG_VERSION 1
-#define BCM_MSG_IFNAME_MAX 16
+#define BCM_EVENT_MSG_VERSION 1
+#define BCM_MSG_IFNAME_MAX 16
-#define WLC_EVENT_MSG_LINK 0x01
-#define WLC_EVENT_MSG_FLUSHTXQ 0x02
-#define WLC_EVENT_MSG_GROUP 0x04
+#define WLC_EVENT_MSG_LINK 0x01
+#define WLC_EVENT_MSG_FLUSHTXQ 0x02
+#define WLC_EVENT_MSG_GROUP 0x04
typedef BWL_PRE_PACKED_STRUCT struct
{
uint16 version;
- uint16 flags;
- uint32 event_type;
- uint32 status;
- uint32 reason;
- uint32 auth_type;
- uint32 datalen;
- struct ether_addr addr;
- char ifname[BCM_MSG_IFNAME_MAX];
+ uint16 flags;
+ uint32 event_type;
+ uint32 status;
+ uint32 reason;
+ uint32 auth_type;
+ uint32 datalen;
+ struct ether_addr addr;
+ char ifname[BCM_MSG_IFNAME_MAX];
} BWL_POST_PACKED_STRUCT wl_event_msg_t;
@@ -68,145 +68,146 @@ typedef BWL_PRE_PACKED_STRUCT struct bcm
struct ether_header eth;
bcmeth_hdr_t bcm_hdr;
wl_event_msg_t event;
-
+
} BWL_POST_PACKED_STRUCT bcm_event_t;
#define BCM_MSG_LEN (sizeof(bcm_event_t) - sizeof(bcmeth_hdr_t) - sizeof(struct ether_header))
-#define WLC_E_SET_SSID 0
-#define WLC_E_JOIN 1
-#define WLC_E_START 2
-#define WLC_E_AUTH 3
-#define WLC_E_AUTH_IND 4
-#define WLC_E_DEAUTH 5
-#define WLC_E_DEAUTH_IND 6
-#define WLC_E_ASSOC 7
-#define WLC_E_ASSOC_IND 8
-#define WLC_E_REASSOC 9
-#define WLC_E_REASSOC_IND 10
-#define WLC_E_DISASSOC 11
-#define WLC_E_DISASSOC_IND 12
-#define WLC_E_QUIET_START 13
-#define WLC_E_QUIET_END 14
-#define WLC_E_BEACON_RX 15
-#define WLC_E_LINK 16
-#define WLC_E_MIC_ERROR 17
-#define WLC_E_NDIS_LINK 18
-#define WLC_E_ROAM 19
-#define WLC_E_TXFAIL 20
-#define WLC_E_PMKID_CACHE 21
-#define WLC_E_RETROGRADE_TSF 22
-#define WLC_E_PRUNE 23
-#define WLC_E_AUTOAUTH 24
-#define WLC_E_EAPOL_MSG 25
-#define WLC_E_SCAN_COMPLETE 26
-#define WLC_E_ADDTS_IND 27
-#define WLC_E_DELTS_IND 28
-#define WLC_E_BCNSENT_IND 29
-#define WLC_E_BCNRX_MSG 30
-#define WLC_E_BCNLOST_MSG 31
-#define WLC_E_ROAM_PREP 32
-#define WLC_E_PFN_NET_FOUND 33
-#define WLC_E_PFN_NET_LOST 34
+#define WLC_E_SET_SSID 0
+#define WLC_E_JOIN 1
+#define WLC_E_START 2
+#define WLC_E_AUTH 3
+#define WLC_E_AUTH_IND 4
+#define WLC_E_DEAUTH 5
+#define WLC_E_DEAUTH_IND 6
+#define WLC_E_ASSOC 7
+#define WLC_E_ASSOC_IND 8
+#define WLC_E_REASSOC 9
+#define WLC_E_REASSOC_IND 10
+#define WLC_E_DISASSOC 11
+#define WLC_E_DISASSOC_IND 12
+#define WLC_E_QUIET_START 13
+#define WLC_E_QUIET_END 14
+#define WLC_E_BEACON_RX 15
+#define WLC_E_LINK 16
+#define WLC_E_MIC_ERROR 17
+#define WLC_E_NDIS_LINK 18
+#define WLC_E_ROAM 19
+#define WLC_E_TXFAIL 20
+#define WLC_E_PMKID_CACHE 21
+#define WLC_E_RETROGRADE_TSF 22
+#define WLC_E_PRUNE 23
+#define WLC_E_AUTOAUTH 24
+#define WLC_E_EAPOL_MSG 25
+#define WLC_E_SCAN_COMPLETE 26
+#define WLC_E_ADDTS_IND 27
+#define WLC_E_DELTS_IND 28
+#define WLC_E_BCNSENT_IND 29
+#define WLC_E_BCNRX_MSG 30
+#define WLC_E_BCNLOST_MSG 31
+#define WLC_E_ROAM_PREP 32
+#define WLC_E_PFN_NET_FOUND 33
+#define WLC_E_PFN_NET_LOST 34
#define WLC_E_RESET_COMPLETE 35
#define WLC_E_JOIN_START 36
#define WLC_E_ROAM_START 37
#define WLC_E_ASSOC_START 38
#define WLC_E_IBSS_ASSOC 39
#define WLC_E_RADIO 40
-#define WLC_E_PSM_WATCHDOG 41
-#define WLC_E_PROBREQ_MSG 44
+#define WLC_E_PSM_WATCHDOG 41
+#define WLC_E_PROBREQ_MSG 44
#define WLC_E_SCAN_CONFIRM_IND 45
-#define WLC_E_PSK_SUP 46
+#define WLC_E_PSK_SUP 46
#define WLC_E_COUNTRY_CODE_CHANGED 47
-#define WLC_E_EXCEEDED_MEDIUM_TIME 48
-#define WLC_E_ICV_ERROR 49
-#define WLC_E_UNICAST_DECODE_ERROR 50
-#define WLC_E_MULTICAST_DECODE_ERROR 51
+#define WLC_E_EXCEEDED_MEDIUM_TIME 48
+#define WLC_E_ICV_ERROR 49
+#define WLC_E_UNICAST_DECODE_ERROR 50
+#define WLC_E_MULTICAST_DECODE_ERROR 51
#define WLC_E_TRACE 52
-#define WLC_E_IF 54
+#define WLC_E_IF 54
#define WLC_E_ASSOCREQ_IE 55 /* penguin, Send up assoc ie */
-#define WLC_E_RSSI 56
-#define WLC_E_PFN_SCAN_COMPLETE 57
-#define WLC_E_ACTION_FRAME 58
-#define WLC_E_ACTION_FRAME_COMPLETE 59
-
-#define WLC_E_ESCAN_RESULT 69
-#define WLC_E_WAKE_EVENT 70
-#define WLC_E_LAST 71
-
-
-
-
-#define WLC_E_STATUS_SUCCESS 0
-#define WLC_E_STATUS_FAIL 1
-#define WLC_E_STATUS_TIMEOUT 2
-#define WLC_E_STATUS_NO_NETWORKS 3
-#define WLC_E_STATUS_ABORT 4
-#define WLC_E_STATUS_NO_ACK 5
-#define WLC_E_STATUS_UNSOLICITED 6
-#define WLC_E_STATUS_ATTEMPT 7
-#define WLC_E_STATUS_PARTIAL 8
-#define WLC_E_STATUS_NEWSCAN 9
-#define WLC_E_STATUS_NEWASSOC 10
-#define WLC_E_STATUS_11HQUIET 11
-#define WLC_E_STATUS_SUPPRESS 12
-#define WLC_E_STATUS_NOCHANS 13
-#define WLC_E_STATUS_CCXFASTRM 14
-#define WLC_E_STATUS_CS_ABORT 15
-
-
-#define WLC_E_REASON_INITIAL_ASSOC 0
-#define WLC_E_REASON_LOW_RSSI 1
-#define WLC_E_REASON_DEAUTH 2
-#define WLC_E_REASON_DISASSOC 3
-#define WLC_E_REASON_BCNS_LOST 4
-#define WLC_E_REASON_FAST_ROAM_FAILED 5
-#define WLC_E_REASON_DIRECTED_ROAM 6
-#define WLC_E_REASON_TSPEC_REJECTED 7
-#define WLC_E_REASON_BETTER_AP 8
-
-
-#define WLC_E_PRUNE_ENCR_MISMATCH 1
-#define WLC_E_PRUNE_BCAST_BSSID 2
-#define WLC_E_PRUNE_MAC_DENY 3
-#define WLC_E_PRUNE_MAC_NA 4
-#define WLC_E_PRUNE_REG_PASSV 5
-#define WLC_E_PRUNE_SPCT_MGMT 6
-#define WLC_E_PRUNE_RADAR 7
-#define WLC_E_RSN_MISMATCH 8
-#define WLC_E_PRUNE_NO_COMMON_RATES 9
-#define WLC_E_PRUNE_BASIC_RATES 10
-#define WLC_E_PRUNE_CIPHER_NA 12
-#define WLC_E_PRUNE_KNOWN_STA 13
-#define WLC_E_PRUNE_WDS_PEER 15
-#define WLC_E_PRUNE_QBSS_LOAD 16
-#define WLC_E_PRUNE_HOME_AP 17
-
-
-#define WLC_E_SUP_OTHER 0
-#define WLC_E_SUP_DECRYPT_KEY_DATA 1
-#define WLC_E_SUP_BAD_UCAST_WEP128 2
-#define WLC_E_SUP_BAD_UCAST_WEP40 3
-#define WLC_E_SUP_UNSUP_KEY_LEN 4
-#define WLC_E_SUP_PW_KEY_CIPHER 5
-#define WLC_E_SUP_MSG3_TOO_MANY_IE 6
-#define WLC_E_SUP_MSG3_IE_MISMATCH 7
-#define WLC_E_SUP_NO_INSTALL_FLAG 8
-#define WLC_E_SUP_MSG3_NO_GTK 9
-#define WLC_E_SUP_GRP_KEY_CIPHER 10
-#define WLC_E_SUP_GRP_MSG1_NO_GTK 11
-#define WLC_E_SUP_GTK_DECRYPT_FAIL 12
-#define WLC_E_SUP_SEND_FAIL 13
-#define WLC_E_SUP_DEAUTH 14
-#define WLC_E_SUP_WPA_PSK_TMO 15
+#define WLC_E_RSSI 56
+#define WLC_E_PFN_SCAN_COMPLETE 57
+#define WLC_E_ACTION_FRAME 58
+#define WLC_E_ACTION_FRAME_COMPLETE 59
+#define WLC_E_RSSI_LOW 60 /* penguin, Send up rssi low event */
+
+#define WLC_E_ESCAN_RESULT 69
+#define WLC_E_WAKE_EVENT 70
+#define WLC_E_LAST 71
+
+
+
+
+#define WLC_E_STATUS_SUCCESS 0
+#define WLC_E_STATUS_FAIL 1
+#define WLC_E_STATUS_TIMEOUT 2
+#define WLC_E_STATUS_NO_NETWORKS 3
+#define WLC_E_STATUS_ABORT 4
+#define WLC_E_STATUS_NO_ACK 5
+#define WLC_E_STATUS_UNSOLICITED 6
+#define WLC_E_STATUS_ATTEMPT 7
+#define WLC_E_STATUS_PARTIAL 8
+#define WLC_E_STATUS_NEWSCAN 9
+#define WLC_E_STATUS_NEWASSOC 10
+#define WLC_E_STATUS_11HQUIET 11
+#define WLC_E_STATUS_SUPPRESS 12
+#define WLC_E_STATUS_NOCHANS 13
+#define WLC_E_STATUS_CCXFASTRM 14
+#define WLC_E_STATUS_CS_ABORT 15
+
+
+#define WLC_E_REASON_INITIAL_ASSOC 0
+#define WLC_E_REASON_LOW_RSSI 1
+#define WLC_E_REASON_DEAUTH 2
+#define WLC_E_REASON_DISASSOC 3
+#define WLC_E_REASON_BCNS_LOST 4
+#define WLC_E_REASON_FAST_ROAM_FAILED 5
+#define WLC_E_REASON_DIRECTED_ROAM 6
+#define WLC_E_REASON_TSPEC_REJECTED 7
+#define WLC_E_REASON_BETTER_AP 8
+
+
+#define WLC_E_PRUNE_ENCR_MISMATCH 1
+#define WLC_E_PRUNE_BCAST_BSSID 2
+#define WLC_E_PRUNE_MAC_DENY 3
+#define WLC_E_PRUNE_MAC_NA 4
+#define WLC_E_PRUNE_REG_PASSV 5
+#define WLC_E_PRUNE_SPCT_MGMT 6
+#define WLC_E_PRUNE_RADAR 7
+#define WLC_E_RSN_MISMATCH 8
+#define WLC_E_PRUNE_NO_COMMON_RATES 9
+#define WLC_E_PRUNE_BASIC_RATES 10
+#define WLC_E_PRUNE_CIPHER_NA 12
+#define WLC_E_PRUNE_KNOWN_STA 13
+#define WLC_E_PRUNE_WDS_PEER 15
+#define WLC_E_PRUNE_QBSS_LOAD 16
+#define WLC_E_PRUNE_HOME_AP 17
+
+
+#define WLC_E_SUP_OTHER 0
+#define WLC_E_SUP_DECRYPT_KEY_DATA 1
+#define WLC_E_SUP_BAD_UCAST_WEP128 2
+#define WLC_E_SUP_BAD_UCAST_WEP40 3
+#define WLC_E_SUP_UNSUP_KEY_LEN 4
+#define WLC_E_SUP_PW_KEY_CIPHER 5
+#define WLC_E_SUP_MSG3_TOO_MANY_IE 6
+#define WLC_E_SUP_MSG3_IE_MISMATCH 7
+#define WLC_E_SUP_NO_INSTALL_FLAG 8
+#define WLC_E_SUP_MSG3_NO_GTK 9
+#define WLC_E_SUP_GRP_KEY_CIPHER 10
+#define WLC_E_SUP_GRP_MSG1_NO_GTK 11
+#define WLC_E_SUP_GTK_DECRYPT_FAIL 12
+#define WLC_E_SUP_SEND_FAIL 13
+#define WLC_E_SUP_DEAUTH 14
+#define WLC_E_SUP_WPA_PSK_TMO 15
-#define WLC_E_IF_ADD 1
-#define WLC_E_IF_DEL 2
+#define WLC_E_IF_ADD 1
+#define WLC_E_IF_DEL 2
#include <packed_section_end.h>
-#endif
+#endif
file:511889a8a78eaf546aa71e1cf881947f589085af -> file:b0c3128b989a344f06e42608a7d98921209c3f53
--- a/drivers/net/wireless/bcm4329_204/wl_iw.c
+++ b/drivers/net/wireless/bcm4329_204/wl_iw.c
@@ -52,10 +52,11 @@ typedef const struct si_pub si_t;
#include <dngl_stats.h>
#include <dhd.h>
#define WL_ERROR(x) myprintf x
-#define WL_TRACE(x)
+#define WL_TRACE(x) //myprintf x
#define WL_ASSOC(x)
#define WL_INFORM(x)
#define WL_WSEC(x)
+#define WL_SCAN(x) //myprintf x
#include <wl_iw.h>
@@ -100,6 +101,21 @@ static bool ap_cfg_running = FALSE;
static bool ap_fw_loaded = FALSE;
static int ap_mode = 0;
#endif
+
+#ifdef SOFTAP_PROTECT
+#define AP_PROTECT_TIME 5000
+#define AP_MAX_FAIL_COUNT 2
+typedef struct ap_info {
+ struct timer_list timer;
+ uint32 timer_on;
+ long ap_pid;
+ struct semaphore ap_sem;
+ struct completion ap_exited;
+} ap_info_t;
+ap_info_t *g_ap_protect = NULL;
+static void wl_iw_ap_restart(void);
+#endif
+
static struct net_device *priv_dev;
#ifdef WLAN_AUTO_RSSI
@@ -122,7 +138,7 @@ extern bool wl_iw_conn_status_str(uint32
extern void dhd_customer_gpio_wlan_ctrl(int onoff);
extern uint dhd_dev_reset(struct net_device *dev, uint8 flag);
extern void dhd_dev_init_ioctl(struct net_device *dev);
-
+extern int wifi_get_cscan_enable(void);
uint wl_msg_level = WL_ERROR_VAL;
#define MAX_WLIW_IOCTL_LEN 1024
@@ -225,12 +241,15 @@ typedef struct iscan_info {
uint32 scan_flag;
- char ioctlbuf[WLC_IOCTL_SMLEN];
+ char ioctlbuf[WLC_IOCTL_MEDLEN];
+ wl_iscan_params_t *iscan_ex_params_p;
+ int iscan_ex_param_size;
} iscan_info_t;
static void wl_iw_bt_flag_set(struct net_device *dev, bool set);
static void wl_iw_bt_release(void);
static int wl_iw_fixed_scan(struct net_device *dev);
+static int wl_iw_combined_scan_set(struct net_device *dev, wlc_ssid_t* ssids_local, int nssid, int nchan);
typedef enum bt_coex_status {
BT_DHCP_IDLE = 0,
@@ -450,6 +469,10 @@ dev_wlc_ioctl(
#ifdef WLAN_PROTECT
void wl_iw_set_busdown(int busdown)
{
+#ifdef CONFIG_BCM4329_SOFTAP
+ if (ap_mode) /* handle by ap recover */
+ return;
+#endif
wl_iw_busdown = busdown;
}
#endif
@@ -785,7 +808,13 @@ wl_iw_del_pfn(
return 0;
}
- strncpy(ssid, extra + ssid_offset+1,
+ if (ssid_size > 32) {
+ WL_ERROR(("%s: ssid too long: %s\n", __FUNCTION__,
+ (char *)extra + ssid_offset + 1));
+ return 0;
+ }
+
+ strncpy(ssid, extra + ssid_offset + 1,
MIN(ssid_size, sizeof(ssid)));
WL_ERROR(("%s: remove ssid: %s\n", __FUNCTION__, ssid));
@@ -798,6 +827,57 @@ wl_iw_del_pfn(
}
#endif
+#ifdef WLAN_LOW_RSSI_IND
+static int
+wl_iw_low_rssi_set(
+ struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu,
+ char *extra
+)
+{
+ char *p = extra;
+ int low_rssi_trigger;
+ int low_rssi_duration;
+ int trigger_offset;
+ int duration_offset;
+ char tran_buf[16] = {0};
+ char *pp;
+ int err = 0;
+ WL_TRACE(("%s\n", __FUNCTION__));
+
+ trigger_offset = strcspn(extra, " ");
+ duration_offset = strcspn(extra+trigger_offset + 1, " ");
+
+ // myprintf("%s: %s, t_off: %d, dur: %d\n", __func__, extra, trigger_offset, duration_offset);
+
+ pp = extra+trigger_offset+1;
+
+ memcpy(tran_buf, pp, duration_offset);
+ low_rssi_trigger = bcm_strtoul(tran_buf, NULL, 10);
+
+ err |= dev_wlc_intvar_set(dev, "low_rssi_trigger", low_rssi_trigger);
+
+ memset(tran_buf, 0, 16);
+ pp = extra+trigger_offset+duration_offset+2;
+ memcpy(tran_buf, pp, strlen(extra) - (trigger_offset+duration_offset+1));
+ low_rssi_duration = bcm_strtoul(tran_buf, NULL, 10);
+ err |= dev_wlc_intvar_set(dev, "low_rssi_duration", low_rssi_duration);
+
+ myprintf("set low rssi trigger %d, duration %d\n",low_rssi_trigger, low_rssi_duration);
+
+ if (err) {
+ WL_ERROR(("set low rssi ind fail!\n"));
+ p += snprintf(p, MAX_WX_STRING, "FAIL");
+ } else
+ p += snprintf(p, MAX_WX_STRING, "OK");
+ wrqu->data.length = p - extra + 1;
+
+
+ return 0;
+}
+#endif
+
static int
wl_iw_set_country(
struct net_device *dev,
@@ -911,7 +991,7 @@ static int btcoex_dhcp_timer_start(struc
char buf_reg41va_dhcp_on[8] = { 41, 00, 00, 00, 0x33, 0x00, 0x00, 0x00 };
char buf_reg68va_dhcp_on[8] = { 68, 00, 00, 00, 0x90, 0x01, 0x00, 0x00 };
char buf_reg12va_sco_time[4] = { 12, 0, 0, 0};
- int sco_lasttime;
+ int sco_lasttime = 0;
int ret;
bcm_mkiovar("btc_params", (char*)&buf_reg12va_sco_time[0], sizeof(buf_reg12va_sco_time), ioctlbuf, sizeof(ioctlbuf));
@@ -1030,6 +1110,15 @@ wl_iw_set_power_mode(
dhdhtc_set_power_control(1, DHDHTC_POWER_CTRL_USER_CONFIG);
dhdhtc_update_wifi_power_mode(screen_off);
break;
+ /* for fota download */
+ case 30:
+ dhdhtc_set_power_control(0, DHDHTC_POWER_CTRL_FOTA_DOWNLOADING);
+ dhdhtc_update_wifi_power_mode(screen_off);
+ break;
+ case 31:
+ dhdhtc_set_power_control(1, DHDHTC_POWER_CTRL_FOTA_DOWNLOADING);
+ dhdhtc_update_wifi_power_mode(screen_off);
+ break;
case 99: /* For debug. power active or not while usb plugin */
dhdcdc_power_active_while_plugin = !dhdcdc_power_active_while_plugin;
dhdhtc_update_wifi_power_mode(screen_off);
@@ -1540,11 +1629,13 @@ _wl_control_sysioc_thread_wl_off(void *d
dhd_dev_reset(wl_ctl->dev, 1);
#if defined(WL_IW_USE_ISCAN)
+ if(!wifi_get_cscan_enable())
+ {
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;
+ }
g_scan_specified_ssid = 0;
g_first_broadcast_scan = BROADCAST_SCAN_FIRST_IDLE;
@@ -1661,8 +1752,11 @@ wl_iw_control_wl_off(
dhd_dev_reset(dev, 1);
#if defined(WL_IW_USE_ISCAN)
+ if(!wifi_get_cscan_enable())
+ {
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;
@@ -2805,26 +2899,25 @@ wl_iw_iscan(iscan_info_t *iscan, wlc_ssi
return -EINVAL;
}
- if (ssid && ssid->SSID_len) {
- params_size += sizeof(wlc_ssid_t);
+ if (ssid && ssid->SSID_len) {
+ params_size += sizeof(wlc_ssid_t);
}
- params = (wl_iscan_params_t*)kmalloc(params_size, GFP_KERNEL);
+ 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);
+ if(!wifi_get_cscan_enable()){
+ err = wl_iw_iscan_prep(&params->params, ssid);
- err = wl_iw_iscan_prep(&params->params, ssid);
-
- if (!err) {
- params->version = htod32(ISCAN_REQ_VERSION);
- params->action = htod16(action);
- params->scan_duration = htod16(0);
-
+ if (!err) {
+ params->version = htod32(ISCAN_REQ_VERSION);
+ params->action = htod16(action);
+ params->scan_duration = htod16(0);
iscan_retry:
- err = dev_iw_iovar_setbuf(iscan->dev, "iscan", params, params_size,
+ err = dev_iw_iovar_setbuf(iscan->dev, "iscan", params, params_size,
iscan->ioctlbuf, WLC_IOCTL_SMLEN);
if (err&&(retry < 2)) {
retry++;
@@ -2835,10 +2928,38 @@ iscan_retry:
if (err)
WL_ERROR(("iscan fail!\n"));
- }
+ }
+ }
+ else{
+ 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);
+
+ 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));
+ WL_SCAN(("channel_num=%d\n", iscan->iscan_ex_params_p->params.channel_num&WL_SCAN_PARAMS_COUNT_MASK));
- kfree(params);
- return err;
+
+
+cscan_retry:
+ err = dev_iw_iovar_setbuf(iscan->dev, "iscan", iscan->iscan_ex_params_p, \
+ iscan->iscan_ex_param_size, iscan->ioctlbuf, sizeof(iscan->ioctlbuf));
+ if (err&&(retry < 2)) {
+ retry++;
+ WL_ERROR(("iscan retry!\n"));
+ bcm_mdelay(500);
+ goto cscan_retry;
+ }
+
+ if (err)
+ WL_ERROR(("iscan fail!\n"));
+ }
+ kfree(params);
+ return err;
}
static void
@@ -2865,6 +2986,19 @@ static void wl_iw_set_event_mask(struct
iovbuf, sizeof(iovbuf));
}
+static void wl_iw_set_event_mask_deauth(struct net_device *dev)
+{
+ char eventmask[WL_EVENTING_MASK_LEN];
+ char iovbuf[WL_EVENTING_MASK_LEN + 12];
+
+ WL_SOFTAP(("set deauth event!\n"));
+ dev_iw_iovar_getbuf(dev, "event_msgs", "", 0, iovbuf, sizeof(iovbuf));
+ bcopy(iovbuf, eventmask, WL_EVENTING_MASK_LEN);
+ setbit(eventmask, WLC_E_DEAUTH);
+ dev_iw_iovar_setbuf(dev, "event_msgs", eventmask, WL_EVENTING_MASK_LEN,
+ iovbuf, sizeof(iovbuf));
+}
+
static uint32
wl_iw_iscan_get(iscan_info_t *iscan)
{
@@ -2874,6 +3008,7 @@ wl_iw_iscan_get(iscan_info_t *iscan)
wl_iscan_results_t list;
wl_scan_results_t *results;
uint32 status;
+ int res = 0;
mutex_lock(&wl_cache_lock);
if (iscan->list_cur) {
@@ -2908,20 +3043,28 @@ wl_iw_iscan_get(iscan_info_t *iscan)
memset(&list, 0, sizeof(list));
list.results.buflen = htod32(WLC_IW_ISCAN_MAXLEN);
- (void) dev_iw_iovar_getbuf(
+ res = dev_iw_iovar_getbuf(
iscan->dev,
"iscanresults",
&list,
WL_ISCAN_RESULTS_FIXED_SIZE,
buf->iscan_buf,
WLC_IW_ISCAN_MAXLEN);
- results->buflen = dtoh32(results->buflen);
- results->version = dtoh32(results->version);
- results->count = dtoh32(results->count);
- WL_TRACE(("results->count = %d\n", results->count));
+ if (res == 0) {
+ results->buflen = dtoh32(results->buflen);
+ results->version = dtoh32(results->version);
+ results->count = dtoh32(results->count);
+ WL_TRACE(("results->count = %d\n", results->count));
+
+ WL_TRACE(("results->buflen = %d\n", results->buflen));
+ status = dtoh32(list_buf->status);
+ }
+ else {
+ WL_ERROR(("%s returns error %d\n", __FUNCTION__, res));
+
+ status = WL_SCAN_RESULTS_NO_MEM;
+ }
- WL_TRACE(("results->buflen = %d\n", results->buflen));
- status = dtoh32(list_buf->status);
mutex_unlock(&wl_cache_lock);
return status;
}
@@ -2949,6 +3092,7 @@ static void wl_iw_send_scan_complete(isc
if (g_first_broadcast_scan == BROADCAST_SCAN_FIRST_STARTED)
g_first_broadcast_scan = BROADCAST_SCAN_FIRST_RESULT_READY;
WL_TRACE(("Send Event ISCAN complete\n"));
+ printk (KERN_INFO"[WLAN] Send Event ISCAN complete\n");
#endif
}
@@ -3022,14 +3166,21 @@ _iscan_sysioc_thread(void *data)
iscan->timer_on = 1;
break;
case WL_SCAN_RESULTS_ABORTED:
- WL_TRACE(("iscanresults aborted\n"));
+ WL_ERROR(("iscanresults aborted\n"));
iscan->iscan_state = ISCAN_STATE_IDLE;
+#if 0
if (g_scan_specified_ssid == 0)
wl_iw_send_scan_complete(iscan);
else {
iscan_pass_abort = TRUE;
wl_iw_force_specific_scan(iscan);
}
+#else
+ /* scan again
+ */
+ iscan_pass_abort = TRUE;
+ wl_iw_force_specific_scan(iscan);
+#endif
break;
case WL_SCAN_RESULTS_NO_MEM:
WL_TRACE(("iscanresults can't alloc memory: skip\n"));
@@ -3221,6 +3372,8 @@ wl_iw_add_bss_to_ss_cache(wl_scan_result
leaf = kmalloc(WLC_IW_SS_CACHE_MAXLEN, GFP_KERNEL);
if (!leaf) {
mutex_unlock(&wl_cache_lock);
+ WL_ERROR(("Memory alloc failure %d\n", \
+ bi->length + WLC_IW_SS_CACHE_CTRL_FIELD_MAXLEN));
return -ENOMEM;
}
@@ -3322,6 +3475,11 @@ wl_iw_set_scan(
int ret, retry = 0;
WL_TRACE(("%s dev:%s: SIOCSIWSCAN : SCAN\n", __FUNCTION__, dev->name));
+ if(wifi_get_cscan_enable()){
+ WL_ERROR(("%s: Scan from SIOCGIWSCAN not supported (Using CSCAN)\n", __FUNCTION__));
+ return -EINVAL;
+ }
+
#if defined(CONFIG_BCM4329_SOFTAP)
if (ap_cfg_running) {
WL_TRACE(("\n>%s: Not executed, reason -'SOFTAP is active'\n", __FUNCTION__));
@@ -3384,6 +3542,154 @@ specific_retry:
return 0;
}
+int
+wl_iw_CSCAN_first(struct net_device *dev)
+{
+ int res = -1;
+ iscan_info_t *iscan = g_iscan;
+ int nssid = 0;
+ int nchan = 0,datalength;
+ cscan_tlv_t *cscan_tlv_temp;
+ wlc_ssid_t ssids_local[WL_SCAN_PARAMS_SSID_MAX];
+ char type;
+ char *str_ptr;
+ int tlv_size_left;
+ char *temp;
+ char tlv_in_firstscan[] = { 'C', 'S', 'C', 'A', 'N', ' ', \
+ 0x53, 0x01, 0x00, 0x00,
+ 'S',0x00,
+ 'C',0x01,'C',0x02,'C',0x03,'C',0x04,'C',0x05,'C',0x06,'C',0x07,'C',0x08,'C',0x09,
+ 'C',0x10,'C',0x11
+ };
+ datalength = sizeof(tlv_in_firstscan);
+
+ if (!(temp = kmalloc(datalength, GFP_KERNEL)))
+ return -ENOMEM;
+
+ if (g_onoff == G_WLAN_SET_OFF) {
+ WL_TRACE(("%s: driver is not up yet after START\n", __FUNCTION__));
+ return -1;
+ }
+
+ memcpy(temp, tlv_in_firstscan, sizeof(tlv_in_firstscan));
+
+ str_ptr = temp;
+ str_ptr += strlen(CSCAN_COMMAND);
+ tlv_size_left = datalength - 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;
+}
+
#ifdef WL_IW_USE_ISCAN
int
wl_iw_iscan_set_scan_broadcast_prep(struct net_device *dev, uint flag)
@@ -3415,13 +3721,18 @@ wl_iw_iscan_set_scan_broadcast_prep(stru
if (flag)
rtnl_lock();
#endif
-
+ if(!wifi_get_cscan_enable()){
dev_wlc_ioctl(dev, WLC_SET_PASSIVE_SCAN, &iscan->scan_flag, sizeof(iscan->scan_flag));
wl_iw_set_event_mask(dev);
WL_TRACE(("+++: Set Broadcast ISCAN\n"));
ret = wl_iw_iscan(iscan, &ssid, WL_SCAN_ACTION_START);
+ }else
+ {
+ printk(KERN_INFO"Try to do scan first (CSCAN) !");
+ ret=wl_iw_CSCAN_first(dev);
+ }
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27))
if (flag)
@@ -3449,6 +3760,11 @@ wl_iw_iscan_set_scan(
WL_TRACE(("%s: SIOCSIWSCAN : ISCAN\n", dev->name));
+ if(wifi_get_cscan_enable()){
+ WL_ERROR(("%s: Scan from SIOCGIWSCAN not supported (Due to Using CSCAN)\n", __FUNCTION__));
+ return -EINVAL;
+ }
+
if (dev_wlc_ioctl_off) {
WL_ERROR(("%s: wl driver going down!\n", __FUNCTION__));
return -EINVAL;
@@ -3498,11 +3814,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(!wifi_get_cscan_enable()){
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;
}
+ }
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);
@@ -3824,8 +4142,13 @@ wl_iw_get_scan(
if ((error = dev_wlc_ioctl(dev, WLC_GET_CHANNEL, &ci, sizeof(ci))))
return error;
ci.scan_channel = dtoh32(ci.scan_channel);
- if (ci.scan_channel)
+ if (ci.scan_channel) {
+ if(!wifi_get_cscan_enable()){
+ WL_ERROR(("%s: scan is running. channel: %d\n", __func__, ci.scan_channel));
+ wl_iw_fixed_scan(dev);
+ }
return -EAGAIN;
+ }
if (g_ss_cache_ctrl.m_timer_expired) {
wl_iw_free_ss_cache();
@@ -3879,12 +4202,12 @@ wl_iw_get_scan(
wl_iw_fixed_scan(dev);
return -EINVAL;
}
+ if(!wifi_get_cscan_enable()){
+ if (g_scan_specified_ssid) {
- if (g_scan_specified_ssid) {
-
- wl_iw_add_bss_to_ss_cache(list);
- kfree(list);
- }
+ wl_iw_add_bss_to_ss_cache(list);
+ kfree(list);
+ }
mutex_lock(&wl_cache_lock);
#if defined(WL_IW_USE_ISCAN)
@@ -3915,9 +4238,38 @@ 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);
+ }
+ }
+#if defined(WL_IW_USE_ISCAN)
g_scan_specified_ssid = 0;
#endif
@@ -4030,6 +4382,7 @@ wl_iw_iscan_get_scan(
uint32 counter = 0;
__u16 merged_len = 0;
uint buflen_from_user = dwrq->length;
+ uint8 channel;
WL_TRACE(("%s %s buflen_from_user %d:\n", dev->name, __FUNCTION__, dwrq->length));
@@ -4049,18 +4402,18 @@ wl_iw_iscan_get_scan(
WL_ERROR(("%s: wl driver going down!\n", __FUNCTION__));
return -EINVAL;
}
-
+ if(!wifi_get_cscan_enable()){
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__));
+ WL_ERROR(("%s %s: first ISCAN results are NOT ready yet \n", \
+ dev->name, __func__));
return -EAGAIN;
}
-
+ }
if ((!iscan) || (iscan->sysioc_pid < 0)) {
WL_TRACE(("%ssysioc_pid\n", __FUNCTION__));
return wl_iw_get_scan(dev, info, dwrq, extra);
}
-
+ if(!wifi_get_cscan_enable()){
if (g_ss_cache_ctrl.m_timer_expired) {
wl_iw_free_ss_cache();
g_ss_cache_ctrl.m_timer_expired ^= 1;
@@ -4080,7 +4433,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++;
}
-
+ }
WL_TRACE(("%s: SIOCGIWSCAN GET broadcast results\n", dev->name));
apcnt = 0;
p_buf = iscan->list_hdr;
@@ -4131,6 +4484,7 @@ wl_iw_iscan_get_scan(
iwe.cmd = SIOCGIWFREQ;
+ if(!wifi_get_cscan_enable()){
#ifdef CUSTOMER_HW2
if (dtoh32(bi->version) != 107 && bi->n_cap)
{
@@ -4142,6 +4496,13 @@ wl_iw_iscan_get_scan(
iwe.u.freq.m = wf_channel2mhz(CHSPEC_CHANNEL(bi->chanspec),
CHSPEC_CHANNEL(bi->chanspec) <= CH_MAX_2G_CHANNEL ?
WF_CHAN_FACTOR_2_4_G : WF_CHAN_FACTOR_5_G);
+ }else
+ {
+ channel = (bi->ctl_ch == 0) ? CHSPEC_CHANNEL(bi->chanspec) : bi->ctl_ch;
+ iwe.u.freq.m = wf_channel2mhz(channel,
+ channel <= CH_MAX_2G_CHANNEL ?
+ WF_CHAN_FACTOR_2_4_G : WF_CHAN_FACTOR_5_G);
+ }
iwe.u.freq.e = 6;
event = IWE_STREAM_ADD_EVENT(info, event, end, &iwe, IW_EV_FREQ_LEN);
@@ -4186,15 +4547,15 @@ wl_iw_iscan_get_scan(
dwrq->length = event - extra;
dwrq->flags = 0;
-
- 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;
-
- WL_TRACE(("%s return to WE %d bytes APs=%d\n", __FUNCTION__, dwrq->length, counter));
+ if(!wifi_get_cscan_enable()){
+ 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;
+ }
+ myprintf("[WLAN] %s return to WE %d bytes APs=%d\n", __func__, dwrq->length, counter);
if (!dwrq->length)
return -EAGAIN;
@@ -5620,6 +5981,405 @@ int get_user_params(char *user_params, s
return ret;
}
+#if defined(CSCAN)
+
+
+
+static int
+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) {
+ i = OFFSETOF(wl_scan_params_t, channel_list) + nchan * sizeof(uint16);
+ i = ROUNDUP(i, sizeof(uint32));
+ if (i + nssid * sizeof(wlc_ssid_t) > params_size) {
+ printk(KERN_INFO"additional ssids exceed params_size\n");
+ err = -1;
+ goto exit;
+ }
+
+ 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*)iscan->iscan_ex_params_p->params.channel_list + nchan * sizeof(uint16);
+ }
+
+
+ iscan->iscan_ex_params_p->params.channel_num = \
+ htod32((nssid << WL_SCAN_PARAMS_NSSID_SHIFT) | \
+ (nchan & WL_SCAN_PARAMS_COUNT_MASK));
+
+ 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 0
+#ifdef SCAN_DUMP
+ {
+ 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"));
+ }
+#endif
+
+ if (params_size > WLC_IOCTL_MEDLEN) {
+ printk (KERN_INFO"[WLAN] error1\n");
+ 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)))) {
+ printk (KERN_INFO"[WLAN] error2\n");
+ WL_TRACE(("Set ISCAN for %s failed with %d\n", __FUNCTION__, err));
+ err = -1;
+ }
+
+exit:
+
+ return err;
+}
+
+
+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;
+ iscan_info_t *iscan = g_iscan;
+ wlc_ssid_t ssids_local[WL_SCAN_PARAMS_SSID_MAX];
+ int nssid = 0;
+ int nchan = 0;
+
+
+ WL_TRACE(("\%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 != 0) {
+
+ char *str_ptr;
+
+ if (!iscan->iscan_ex_params_p) {
+ return -EFAULT;
+ }
+
+ if (!(extra = kmalloc(wrqu->data.length+1, GFP_KERNEL)))
+ return -ENOMEM;
+
+ if (copy_from_user(extra, wrqu->data.pointer, wrqu->data.length)) {
+ kfree(extra);
+ return -EFAULT;
+ }
+
+ extra[wrqu->data.length] = 0;
+ WL_ERROR(("Got str param in iw_point:\n %s\n", extra));
+
+ str_ptr = extra;
+
+
+ if (strncmp(str_ptr, GET_SSID, strlen(GET_SSID))) {
+ WL_ERROR(("%s Error: extracting SSID='' string\n", __FUNCTION__));
+ goto exit_proc;
+ }
+ str_ptr += strlen(GET_SSID);
+ nssid = wl_iw_parse_ssid_list(&str_ptr, ssids_local, nssid, \
+ WL_SCAN_PARAMS_SSID_MAX);
+
+ if (nssid == -1) {
+ WL_ERROR(("%s wrong ssid list", __FUNCTION__));
+ return -1;
+ }
+
+ 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(&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, \
+ &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, \
+ &iscan->iscan_ex_params_p->params.nprobes, 2);
+
+ 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, \
+ &iscan->iscan_ex_params_p->params.passive_time, 4);
+
+ 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);
+
+ } else {
+
+ WL_ERROR(("IWPRIV argument len = 0 \n"));
+ return -1;
+ }
+
+exit_proc:
+
+ kfree(extra);
+
+ return res;
+}
+
+
+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,
+ //0x00,
+ //'P',
+ 'A',
+ 0x94,
+ 0x11,
+ 'T',
+ //0x01
+ 0x00
+ };
+#endif
+ WL_SCAN(("\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++)
+ printk(KERN_INFO"%02X ", extra[i]);
+ printk(KERN_INFO"--\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;
+ }
+
+ //if (g_first_broadcast_scan < BROADCAST_SCAN_FIRST_RESULT_CONSUMED) {
+ // WL_ERROR(("%s First ISCAN in progress : ignoring\n", __FUNCTION__));
+ // return -EBUSY;
+ //}
+
+
+ res = wl_iw_combined_scan_set(dev, ssids_local, nssid, nchan);
+
+exit_proc:
+
+ return res;
+}
+
+#endif
+
#ifdef CONFIG_BCM4329_SOFTAP
@@ -5877,6 +6637,8 @@ get_channel_retry:
ap_mode = 1;
}
#endif
+ wl_iw_set_event_mask_deauth(dev);
+
return res;
}
@@ -6194,7 +6956,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;
@@ -6306,6 +7068,12 @@ static int iwpriv_softap_stop(struct net
res = wl_iw_softap_deassoc_stations(dev);
ap_mode = 0;
wl_iw_send_priv_event(priv_dev, "AP_DOWN");
+#ifdef SOFTAP_PROTECT
+ if (g_ap_protect&&g_ap_protect->timer_on) {
+ g_ap_protect->timer_on = 0;
+ del_timer_sync(&g_ap_protect->timer);
+ }
+#endif
#else
res = wl_iw_softap_deassoc_stations(ap_net_dev);
@@ -6760,6 +7528,10 @@ 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);
+#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);
@@ -6804,6 +7576,12 @@ static int wl_iw_set_priv(
set_ap_mac_list(dev, (extra + PROFILE_OFFSET));
}
#endif
+#ifdef WLAN_LOW_RSSI_IND
+ else if (strnicmp(extra, "LOW_RSSI_IND_SET", strlen("LOW_RSSI_IND_SET")) == 0) {
+ WL_TRACE(("set LOW_RSSI_IND_SET\n"));
+ wl_iw_low_rssi_set(dev, info, (union iwreq_data *)dwrq, extra);
+ }
+#endif
/* for packet filter rule
*/
else if (strnicmp(extra, "RXFILTER-ADD", strlen("RXFILTER-ADD")) == 0 ||
@@ -6952,7 +7730,10 @@ static const iw_handler wl_iw_priv_handl
NULL,
(iw_handler)iwpriv_fw_reload,
-
+#if defined(CSCAN)
+ NULL,
+ (iw_handler)iwpriv_set_cscan,
+#endif
NULL,
(iw_handler)iwpriv_settxpower
@@ -7060,6 +7841,14 @@ static const struct iw_priv_args wl_iw_p
"AP_TX_POWER"
},
#endif
+#if defined(CSCAN)
+ {
+ WL_COMBO_SCAN,
+ IW_PRIV_TYPE_CHAR | 1024,
+ 0,
+ "CSCAN"
+ },
+#endif
};
const struct iw_handler_def wl_iw_handler_def =
@@ -7373,6 +8162,7 @@ wl_iw_event(struct net_device *dev, wl_e
case WLC_E_DEAUTH_IND:
case WLC_E_DISASSOC_IND:
#if defined(CONFIG_BCM4329_SOFTAP)
+ case WLC_E_DEAUTH:
WL_SOFTAP(("STA disconnect received %d\n", event_type));
if (ap_mode) {
//wl_iw_send_priv_event(priv_dev, "STA_LEAVE");
@@ -7386,11 +8176,15 @@ wl_iw_event(struct net_device *dev, wl_e
wl_iw_send_priv_event(priv_dev, mac_buf);
return;
}
+ if (event_type != WLC_E_DEAUTH) {
#endif
cmd = SIOCGIWAP;
bzero(wrqu.addr.sa_data, ETHER_ADDR_LEN);
wrqu.addr.sa_family = ARPHRD_ETHER;
bzero(&extra, ETHER_ADDR_LEN);
+#if defined(CONFIG_BCM4329_SOFTAP)
+ }
+#endif
break;
case WLC_E_LINK:
case WLC_E_NDIS_LINK:
@@ -7404,6 +8198,12 @@ wl_iw_event(struct net_device *dev, wl_e
#endif
WL_SOFTAP(("AP DOWN %d\n", event_type));
wl_iw_send_priv_event(priv_dev, "AP_DOWN");
+#ifdef SOFTAP_PROTECT
+ if (g_ap_protect&&g_ap_protect->timer_on) {
+ g_ap_protect->timer_on = 0;
+ del_timer_sync(&g_ap_protect->timer);
+ }
+#endif
} else {
WL_TRACE(("STA_Link Down\n"));
if (g_ss_cache_ctrl.last_rssi == 0)
@@ -7434,6 +8234,13 @@ wl_iw_event(struct net_device *dev, wl_e
#endif
WL_SOFTAP(("AP UP %d\n", event_type));
wl_iw_send_priv_event(priv_dev, "AP_UP");
+#ifdef SOFTAP_PROTECT
+ if (g_ap_protect->timer_on == 0) {
+ g_ap_protect->timer_on = 1;
+ mod_timer(&g_ap_protect->timer, jiffies + AP_PROTECT_TIME*HZ/1000);
+ WL_SOFTAP(("%s Start AP Timer\n", __FUNCTION__));
+ }
+#endif
} else
#endif
{
@@ -7548,6 +8355,14 @@ wl_iw_event(struct net_device *dev, wl_e
break;
}
#endif
+#ifdef WLAN_LOW_RSSI_IND
+ case WLC_E_RSSI_LOW:
+ {
+ myprintf("Recevied RSSI LOW event!\n");
+ wl_iw_send_priv_event(priv_dev, "LOW_RSSI");
+ break;
+ }
+#endif
case WLC_E_SCAN_COMPLETE:
#if defined(WL_IW_USE_ISCAN)
if ((g_iscan) && (g_iscan->sysioc_pid >= 0) &&
@@ -7833,8 +8648,139 @@ wl_iw_bt_init(struct net_device *dev)
return 0;
}
+#ifdef SOFTAP_PROTECT
+static void
+wl_iw_ap_timerfunc(ulong data)
+{
+ ap_info_t *ap_local = (ap_info_t *)data;
+ ap_local->timer_on = 0;
+ WL_TRACE(("%s\n", __FUNCTION__));
+
+ up(&ap_local->ap_sem);
+}
+
+static int ap_fail_count = 0;
+static int
+_ap_protect_sysioc_thread(void *data)
+{
+ int isup;
+ int ret = 0;
+ DAEMONIZE("ap_sysioc");
+
+ while (down_interruptible(&g_ap_protect->ap_sem) == 0) {
+
+ net_os_wake_lock(priv_dev);
+
+ if (g_ap_protect->timer_on) {
+ g_ap_protect->timer_on = 0;
+ del_timer_sync(&g_ap_protect->timer);
+ }
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27))
+ rtnl_lock();
+#endif
+ if ((ret = dev_wlc_ioctl(priv_dev, WLC_GET_UP, &isup, sizeof(isup))) != 0)
+ ap_fail_count++;
+ else
+ ap_fail_count = 0;
+
+ if (ap_fail_count == AP_MAX_FAIL_COUNT) {
+ wl_iw_restart(priv_dev);
+ wl_iw_ap_restart();
+ }
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27))
+ rtnl_unlock();
+#endif
+ mod_timer(&g_ap_protect->timer, jiffies + AP_PROTECT_TIME*HZ/1000);
+ g_ap_protect->timer_on = 1;
+
+ net_os_wake_unlock(priv_dev);
+ }
+
+ if (g_ap_protect->timer_on) {
+ g_ap_protect->timer_on = 0;
+ del_timer_sync(&g_ap_protect->timer);
+ }
+
+ complete_and_exit(&g_ap_protect->ap_exited, 0);
+}
+
+static int
+wl_iw_ap_init(void)
+{
+ ap_info_t *ap_protect = NULL;
+
+ ap_protect = kmalloc(sizeof(ap_info_t), GFP_KERNEL);
+ if (!ap_protect)
+ return -ENOMEM;
+
+ memset(ap_protect, 0, sizeof(ap_info_t));
+ ap_protect->ap_pid = -1;
+ g_ap_protect = ap_protect;
+
+
+ init_timer(&ap_protect->timer);
+ ap_protect->timer.data = (ulong)ap_protect;
+ ap_protect->timer.function = wl_iw_ap_timerfunc;
+ ap_protect->timer_on = 0;
+
+ sema_init(&ap_protect->ap_sem, 0);
+ init_completion(&ap_protect->ap_exited);
+ ap_protect->ap_pid = kernel_thread(_ap_protect_sysioc_thread, ap_protect, 0);
+ if (ap_protect->ap_pid < 0) {
+ WL_ERROR(("Failed in %s\n", __FUNCTION__));
+ return -ENOMEM;
+ }
+
+ return 0;
+}
+
+
+static void
+wl_iw_ap_release(void)
+{
+ ap_info_t *ap_local = g_ap_protect;
+
+ if (!ap_local) {
+ return;
+ }
+
+ if (ap_local->ap_pid >= 0) {
+ KILL_PROC(ap_local->ap_pid, SIGTERM);
+ wait_for_completion(&ap_local->ap_exited);
+ }
+ kfree(ap_local);
+ g_ap_protect = NULL;
+}
+
+
+static void wl_iw_ap_restart(void)
+{
+ WL_SOFTAP(("Enter %s...\n", __FUNCTION__));
+
+ ap_mode = 0;
+ ap_cfg_running = FALSE;
+ ap_net_dev = NULL;
+
+ set_ap_cfg(priv_dev, &my_ap);
+
+ WL_SOFTAP(("SOFTAP - ENABLE BSS \n"));
+
+#ifndef AP_ONLY
+ if (ap_net_dev == NULL) {
+ printk("ERROR: SOFTAP net_dev* is NULL !!!\n");
+ } else {
+ iwpriv_en_ap_bss(ap_net_dev, NULL, NULL, NULL);
+ }
+#endif
+}
+
+#endif
+
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;
@@ -7847,10 +8793,24 @@ int wl_iw_attach(struct net_device *dev,
if (!dev)
return 0;
+
+ if(wifi_get_cscan_enable()){
+ 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));
+ }
+
iscan = kmalloc(sizeof(iscan_info_t), GFP_KERNEL);
if (!iscan)
return -ENOMEM;
memset(iscan, 0, sizeof(iscan_info_t));
+ if(wifi_get_cscan_enable()){
+ 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;
@@ -7882,10 +8842,14 @@ int wl_iw_attach(struct net_device *dev,
memset(g_scan, 0, G_SCAN_RESULTS);
g_scan_specified_ssid = 0;
- wl_iw_init_ss_cache_ctrl();
+ if(!wifi_get_cscan_enable()){
+ wl_iw_init_ss_cache_ctrl();
+ }
wl_iw_bt_init(dev);
-
+#ifdef SOFTAP_PROTECT
+ wl_iw_ap_init();
+#endif
// perf_lock_init(&wl_wificall_perf_lock, PERF_LOCK_HIGHEST, "wifi-call");
mutex_init(&wl_wificall_mutex);
@@ -7911,6 +8875,9 @@ void wl_iw_detach(void)
kfree(iscan->list_hdr);
iscan->list_hdr = buf;
}
+ if(wifi_get_cscan_enable())
+ kfree(iscan->iscan_ex_params_p);
+
kfree(iscan);
g_iscan = NULL;
mutex_unlock(&wl_cache_lock);
@@ -7920,8 +8887,13 @@ void wl_iw_detach(void)
kfree(g_scan);
g_scan = NULL;
+ if(!wifi_get_cscan_enable()){
wl_iw_release_ss_cache_ctrl();
+ }
wl_iw_bt_release();
+#ifdef SOFTAP_PROTECT
+ wl_iw_ap_release();
+#endif
#ifdef CONFIG_BCM4329_SOFTAP
if (ap_mode) {
WL_TRACE(("\n%s AP is going down\n", __FUNCTION__));
file:1b1075ade40a70251a79e7c32e57d4803d133649 -> file:aca012d515b9c25cdaa567b0e1440f828d2b22ae
--- a/drivers/net/wireless/bcm4329_204/wl_iw.h
+++ b/drivers/net/wireless/bcm4329_204/wl_iw.h
@@ -34,6 +34,17 @@
#include <proto/ethernet.h>
#include <wlioctl.h>
+#define WL_SCAN_PARAMS_SSID_MAX 10
+#define GET_SSID "SSID="
+#define GET_CHANNEL "CH="
+#define GET_NPROBE "NPROBE="
+#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 "BANDGET"
+#define BAND_SET_CMD "BANDSET"
#define WL_IW_RSSI_MINVAL -200
#define WL_IW_RSSI_NO_SIGNAL -91
@@ -61,12 +72,9 @@
#define AP_LPB_CMD (SIOCIWFIRSTPRIV+23)
#define WL_AP_STOP (SIOCIWFIRSTPRIV+25)
#define WL_FW_RELOAD (SIOCIWFIRSTPRIV+27)
-#if 0
-#define WL_AP_SPARE2 (SIOCIWFIRSTPRIV+29)
-#else
-#define WL_SET_AP_TXPWR (SIOCIWFIRSTPRIV+29)
-#endif
-#define WL_AP_SPARE3 (SIOCIWFIRSTPRIV+31)
+#define WL_COMBO_SCAN (SIOCIWFIRSTPRIV+29)
+//#define WL_AP_SPARE2 (SIOCIWFIRSTPRIV+29)
+#define WL_SET_AP_TXPWR (SIOCIWFIRSTPRIV+31)
#define G_SCAN_RESULTS (8*1024)
#define WE_ADD_EVENT_FIX 0x80
#define G_WLAN_SET_ON 0
@@ -196,4 +204,40 @@ extern int net_os_wake_lock_timeout_enab
iwe_stream_add_point(stream, ends, iwe, extra)
#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
file:08c29fc5e6800cff81002e879ec4061051f41caa -> file:1e7202b22ec0752ebedb755b18b6a4727008fc0b
--- a/include/linux/wifi_tiwlan.h
+++ b/include/linux/wifi_tiwlan.h
@@ -29,6 +29,7 @@ struct wifi_platform_data {
int (*set_carddetect)(int val);
void *(*mem_prealloc)(int section, unsigned long size);
int dot11n_enable;
+ int cscan_enable;
};
#endif