summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHoward M. Harte <hharte@broadcom.com>2010-07-27 16:40:06 -0700
committerHoward M. Harte <hharte@broadcom.com>2010-07-27 16:40:06 -0700
commitdd0ed55b6892078730078b3b971d2768954891c4 (patch)
tree836ebf982573ebc6f607a8b564665ce575a70869
parent5a838529e6197475cbe8f5a4557fbd31f90586a6 (diff)
downloadbroadcom-dd0ed55b6892078730078b3b971d2768954891c4.tar.gz
Update driver to RC243.
Change-Id: Ie5a9b6f902fefea100b4d288397fd08db0a6e850
-rw-r--r--bcm4329/src/dhd/linux/Makefile5
-rw-r--r--bcm4329/src/dhd/sys/dhd.h45
-rw-r--r--bcm4329/src/dhd/sys/dhd_bus.h6
-rw-r--r--bcm4329/src/dhd/sys/dhd_cdc.c15
-rw-r--r--bcm4329/src/dhd/sys/dhd_common.c697
-rw-r--r--bcm4329/src/dhd/sys/dhd_custom_gpio.c25
-rw-r--r--bcm4329/src/dhd/sys/dhd_dbg.h7
-rw-r--r--bcm4329/src/dhd/sys/dhd_linux.c62
-rw-r--r--bcm4329/src/dhd/sys/dhd_proto.h6
-rw-r--r--bcm4329/src/dhd/sys/dhd_sdio.c311
-rw-r--r--bcm4329/src/include/bcmdefs.h1
-rw-r--r--bcm4329/src/include/bcmdevs.h2
-rw-r--r--bcm4329/src/include/bcmsdpcm.h5
-rw-r--r--bcm4329/src/include/bcmutils.h2
-rw-r--r--bcm4329/src/include/dhdioctl.h3
-rw-r--r--bcm4329/src/include/epivers.h12
-rw-r--r--bcm4329/src/include/linux_osl.h7
-rw-r--r--bcm4329/src/include/linuxver.h6
-rw-r--r--bcm4329/src/include/proto/802.11.h3
-rw-r--r--bcm4329/src/include/proto/ethernet.h1
-rw-r--r--bcm4329/src/include/sbchipc.h1
-rw-r--r--bcm4329/src/include/siutils.h2
-rw-r--r--bcm4329/src/include/wlioctl.h5
-rw-r--r--bcm4329/src/shared/bcmutils.c2
-rw-r--r--bcm4329/src/shared/linux_osl.c8
-rw-r--r--bcm4329/src/shared/siutils.c2
-rw-r--r--bcm4329/src/wl/sys/wl_cfg80211.c467
-rw-r--r--bcm4329/src/wl/sys/wl_cfg80211.h25
-rw-r--r--bcm4329/src/wl/sys/wl_iw.c719
-rw-r--r--bcm4329/src/wl/sys/wl_iw.h55
30 files changed, 2249 insertions, 258 deletions
diff --git a/bcm4329/src/dhd/linux/Makefile b/bcm4329/src/dhd/linux/Makefile
index 94f1712..e25b395 100644
--- a/bcm4329/src/dhd/linux/Makefile
+++ b/bcm4329/src/dhd/linux/Makefile
@@ -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: Makefile,v 1.55.2.6.2.10.6.39 2010/04/20 02:30:25 Exp $
+# $Id: Makefile,v 1.55.2.6.2.10.6.40 2010/04/29 23:29:33 Exp $
#
# Try a couple of places for LINUXDIR if not specified
@@ -228,8 +228,7 @@ DFLAGS += -DSOFTAP
CFILES += sha1.c md5.c
endif
ifneq ($(findstring -nexus-,-$(TARGET)-),)
-DFLAGS += -DEMBEDDED_PLATFORM
-DFLAGS += -DOEM_ANDROID
+DFLAGS += -DOEM_ANDROID -DEMBEDDED_PLATFORM -DARP_OFFLOAD_SUPPORT -DPKT_FILTER_SUPPORT
DFLAGS += -DBCMDBG
DFLAGS += -DDHD_USE_STATIC_BUF
DFLAGS += -DCUSTOMER_HW2
diff --git a/bcm4329/src/dhd/sys/dhd.h b/bcm4329/src/dhd/sys/dhd.h
index 08e0fb8..1c5f8dd 100644
--- a/bcm4329/src/dhd/sys/dhd.h
+++ b/bcm4329/src/dhd/sys/dhd.h
@@ -24,7 +24,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.h,v 1.32.4.7.2.4.14.35.4.2 2010/05/18 03:54:02 Exp $
+ * $Id: dhd.h,v 1.32.4.7.2.4.14.44 2010/06/03 21:27:48 Exp $
*/
/****************
@@ -35,6 +35,9 @@
#define _dhd_h_
#if defined(LINUX)
+#if defined(CHROMIUMOS_COMPAT_WIRELESS)
+#include <linux/sched.h>
+#endif
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/slab.h>
@@ -180,10 +183,10 @@ typedef struct dhd_pub {
#define DHD_SPINWAIT_SLEEP_INIT(a) DECLARE_WAIT_QUEUE_HEAD(a);
#define SPINWAIT_SLEEP(a, exp, us) do { \
- uint countdown = (us) + 9; \
- while ((exp) && (countdown >= 10)) { \
+ uint countdown = (us) + 9999; \
+ while ((exp) && (countdown >= 10000)) { \
wait_event_timeout(a, FALSE, HZ/100); \
- countdown -= 10; \
+ countdown -= 10000; \
} \
} while (0)
@@ -249,6 +252,31 @@ inline static void MUTEX_UNLOCK_SOFTAP_SET(dhd_pub_t * dhdp)
#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) */
}
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)) && 1
+extern struct mutex g_wl_ss_scan_lock; /* lock/unlock for Scan/Cache settings */
+#endif
+
+inline static void MUTEX_LOCK_WL_SCAN_SET_INIT(void)
+{
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)) && 1
+ mutex_init(&g_wl_ss_scan_lock);
+#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) */
+}
+
+inline static void MUTEX_LOCK_WL_SCAN_SET(void)
+{
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)) && 1
+ mutex_lock(&g_wl_ss_scan_lock);
+#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) */
+}
+
+inline static void MUTEX_UNLOCK_WL_SCAN_SET(void)
+{
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)) && 1
+ mutex_unlock(&g_wl_ss_scan_lock);
+#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) */
+}
+
inline static void WAKE_LOCK_INIT(dhd_pub_t * dhdp, int index, char * y)
{
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) && defined(CONFIG_HAS_WAKELOCK)
@@ -350,9 +378,13 @@ extern void dhd_os_sdlock_rxq(dhd_pub_t * pub);
extern void dhd_os_sdunlock_rxq(dhd_pub_t * pub);
extern void dhd_os_sdlock_sndup_rxq(dhd_pub_t * pub);
extern void dhd_customer_gpio_wlan_ctrl(int onoff);
+extern int dhd_custom_get_mac_address(unsigned char *buf);
extern void dhd_os_sdunlock_sndup_rxq(dhd_pub_t * pub);
extern void dhd_os_sdlock_eventq(dhd_pub_t * pub);
extern void dhd_os_sdunlock_eventq(dhd_pub_t * pub);
+#ifdef DHD_DEBUG
+extern int write_to_file(dhd_pub_t *dhd, uint8 *buf, int size);
+#endif /* DHD_DEBUG */
#if defined(OOB_INTR_ONLY)
extern int dhd_customer_oob_irq_map(unsigned long *irq_flags_ptr);
#endif /* defined(OOB_INTR_ONLY) */
@@ -420,7 +452,7 @@ extern uint dhd_watchdog_ms;
#if defined(DHD_DEBUG)
/* Console output poll interval */
extern uint dhd_console_ms;
-#endif
+#endif /* defined(DHD_DEBUG) */
/* Use interrupts */
extern uint dhd_intr;
@@ -437,6 +469,9 @@ extern uint dhd_arp_enable;
/* Pkt filte enable control */
extern uint dhd_pkt_filter_enable;
+/* Pkt filter init setup */
+extern uint dhd_pkt_filter_init;
+
/* Pkt filter mode control */
extern uint dhd_master_mode;
diff --git a/bcm4329/src/dhd/sys/dhd_bus.h b/bcm4329/src/dhd/sys/dhd_bus.h
index 7156543..9e29fb9 100644
--- a/bcm4329/src/dhd/sys/dhd_bus.h
+++ b/bcm4329/src/dhd/sys/dhd_bus.h
@@ -24,7 +24,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_bus.h,v 1.4.6.3.2.3.6.5 2009/06/02 21:56:30 Exp $
+ * $Id: dhd_bus.h,v 1.4.6.3.2.3.6.6 2010/05/17 18:18:13 Exp $
*/
#ifndef _dhd_bus_h_
@@ -60,6 +60,10 @@ extern int dhd_bus_rxctl(struct dhd_bus *bus, uchar *msg, uint msglen);
/* Watchdog timer function */
extern bool dhd_bus_watchdog(dhd_pub_t *dhd);
+#ifdef DHD_DEBUG
+/* Device console input function */
+extern int dhd_bus_console_in(dhd_pub_t *dhd, uchar *msg, uint msglen);
+#endif
/* Deferred processing for the bus, return TRUE requests reschedule */
extern bool dhd_bus_dpc(struct dhd_bus *bus);
diff --git a/bcm4329/src/dhd/sys/dhd_cdc.c b/bcm4329/src/dhd/sys/dhd_cdc.c
index 8829ef4..e98af39 100644
--- a/bcm4329/src/dhd/sys/dhd_cdc.c
+++ b/bcm4329/src/dhd/sys/dhd_cdc.c
@@ -21,7 +21,7 @@
* software in any way with any other Broadcom software provided under a license
* other than the GPL, without Broadcom's express prior written consent.
*
- * $Id: dhd_cdc.c,v 1.22.4.2.4.7.2.36 2010/04/14 12:09:11 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
@@ -40,6 +40,9 @@
#include <dhd_proto.h>
#include <dhd_bus.h>
#include <dhd_dbg.h>
+#ifdef CUSTOMER_HW2
+int wifi_get_mac_addr(unsigned char *buf);
+#endif
extern int dhd_preinit_ioctls(dhd_pub_t *dhd);
@@ -207,7 +210,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);
@@ -521,10 +524,13 @@ dhd_prot_init(dhd_pub_t *dhd)
strcpy(buf, "cur_etheraddr");
ret = dhdcdc_query_ioctl(dhd, 0, WLC_GET_VAR, buf, sizeof(buf));
if (ret < 0) {
- goto fail;
+ dhd_os_proto_unblock(dhd);
+ return ret;
}
memcpy(dhd->mac.octet, buf, ETHER_ADDR_LEN);
+ dhd_os_proto_unblock(dhd);
+
#ifdef EMBEDDED_PLATFORM
ret = dhd_preinit_ioctls(dhd);
#endif /* EMBEDDED_PLATFORM */
@@ -532,9 +538,6 @@ dhd_prot_init(dhd_pub_t *dhd)
/* Always assumes wl for now */
dhd->iswl = TRUE;
-fail:
- dhd_os_proto_unblock(dhd);
-
return ret;
}
diff --git a/bcm4329/src/dhd/sys/dhd_common.c b/bcm4329/src/dhd/sys/dhd_common.c
index 37ea7e9..15a91fb 100644
--- a/bcm4329/src/dhd/sys/dhd_common.c
+++ b/bcm4329/src/dhd/sys/dhd_common.c
@@ -21,7 +21,7 @@
* software in any way with any other Broadcom software provided under a license
* other than the GPL, without Broadcom's express prior written consent.
*
- * $Id: dhd_common.c,v 1.5.6.8.2.6.6.46 2010/04/21 09:54:43 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>
@@ -43,6 +43,10 @@
int dhd_msg_level;
+#if defined(CSCAN)
+#include <wl_iw.h>
+#endif
+
char fw_path[MOD_PARAM_PATHLEN];
char nv_path[MOD_PARAM_PATHLEN];
@@ -55,7 +59,12 @@ uint32 dhd_conn_reason;
#define htod16(i) i
#define dtoh32(i) i
#define dtoh16(i) i
+
extern int dhdcdc_set_ioctl(dhd_pub_t *dhd, int ifidx, uint cmd, void *buf, uint len);
+extern void dhd_ind_scan_confirm(void *h, bool status);
+extern int dhd_wl_ioctl(dhd_pub_t *dhd, uint cmd, char *buf, uint buflen);
+void dhd_iscan_lock(void);
+void dhd_iscan_unlock(void);
/* Packet alignment for most efficient SDIO (can change based on platform) */
#ifndef DHD_SDALIGN
@@ -65,7 +74,6 @@ extern int dhdcdc_set_ioctl(dhd_pub_t *dhd, int ifidx, uint cmd, void *buf, uint
#error DHD_SDALIGN is not a power of 2!
#endif
-
#ifdef DHD_DEBUG
const char dhd_version[] = "Dongle Host Driver, version " EPI_VERSION_STR "\nCompiled on "
__DATE__ " at " __TIME__;
@@ -75,7 +83,6 @@ const char dhd_version[] = "Dongle Host Driver, version " EPI_VERSION_STR;
void dhd_set_timer(void *bus, uint wdtick);
-
/* IOVar table */
enum {
IOV_VERSION = 1,
@@ -84,6 +91,10 @@ enum {
IOV_BCMERROR,
IOV_WDTICK,
IOV_DUMP,
+#ifdef DHD_DEBUG
+ IOV_CONS,
+ IOV_DCONSOLE_POLL,
+#endif
IOV_CLEARCOUNTS,
IOV_LOGDUMP,
IOV_LOGCAL,
@@ -102,6 +113,10 @@ const bcm_iovar_t dhd_iovars[] = {
{"bcmerror", IOV_BCMERROR, 0, IOVT_INT8, 0 },
{"wdtick", IOV_WDTICK, 0, IOVT_UINT32, 0 },
{"dump", IOV_DUMP, 0, IOVT_BUFFER, DHD_IOCTL_MAXLEN },
+#ifdef DHD_DEBUG
+ {"dconpoll", IOV_DCONSOLE_POLL, 0, IOVT_UINT32, 0 },
+ {"cons", IOV_CONS, 0, IOVT_BUFFER, 0 },
+#endif
{"clearcounts", IOV_CLEARCOUNTS, 0, IOVT_VOID, 0 },
{"gpioob", IOV_GPIOOB, 0, IOVT_UINT32, 0 },
{"ioctl_timeout", IOV_IOCTLTIMEOUT, 0, IOVT_UINT32, 0 },
@@ -242,6 +257,21 @@ dhd_doiovar(dhd_pub_t *dhd_pub, const bcm_iovar_t *vi, uint32 actionid, const ch
bcmerror = dhd_dump(dhd_pub, arg, len);
break;
+#ifdef DHD_DEBUG
+ case IOV_GVAL(IOV_DCONSOLE_POLL):
+ int_val = (int32)dhd_console_ms;
+ bcopy(&int_val, arg, val_size);
+ break;
+
+ case IOV_SVAL(IOV_DCONSOLE_POLL):
+ dhd_console_ms = (uint)int_val;
+ break;
+
+ case IOV_SVAL(IOV_CONS):
+ if (len > 0)
+ bcmerror = dhd_bus_console_in(dhd_pub, arg, len - 1);
+ break;
+#endif
case IOV_SVAL(IOV_CLEARCOUNTS):
dhd_pub->tx_packets = dhd_pub->rx_packets = 0;
@@ -1212,6 +1242,29 @@ dhd_preinit_ioctls(dhd_pub_t *dhd)
uint bcn_timeout = 3;
int scan_assoc_time = 40;
int scan_unassoc_time = 80;
+#ifdef GET_CUSTOM_MAC_ENABLE
+ int ret = 0;
+ struct ether_addr ea_addr;
+#endif /* GET_CUSTOM_MAC_ENABLE */
+
+ dhd_os_proto_block(dhd);
+
+#ifdef GET_CUSTOM_MAC_ENABLE
+ /* Read MAC address from external customer place
+ ** NOTE that default mac address has to be present in otp or nvram file to bring up
+ ** firmware but unique per board mac address maybe provided by customer code
+ */
+ ret = dhd_custom_get_mac_address(ea_addr.octet);
+ if (!ret) {
+ bcm_mkiovar("cur_etheraddr", (void *)&ea_addr, ETHER_ADDR_LEN, buf, sizeof(buf));
+ ret = dhdcdc_set_ioctl(dhd, 0, WLC_SET_VAR, buf, sizeof(buf));
+ if (ret < 0) {
+ DHD_ERROR(("%s: can't set MAC address , error=%d\n", __FUNCTION__, ret));
+ }
+ else
+ memcpy(dhd->mac.octet, (void *)&ea_addr, ETHER_ADDR_LEN);
+ }
+#endif /* GET_CUSTOM_MAC_ENABLE */
/* Set Country code */
if (dhd->country_code[0] != 0) {
@@ -1277,11 +1330,647 @@ dhd_preinit_ioctls(dhd_pub_t *dhd)
for (i = 0; i < dhd->pktfilter_count; i++) {
dhd_pktfilter_offload_set(dhd, dhd->pktfilter[i]);
dhd_pktfilter_offload_enable(dhd, dhd->pktfilter[i],
- 1, dhd_master_mode);
+ dhd_pkt_filter_init, dhd_master_mode);
}
}
}
#endif /* PKT_FILTER_SUPPORT */
+ dhd_os_proto_unblock(dhd);
+
return 0;
}
+
+#ifdef SIMPLE_ISCAN
+
+uint iscan_thread_id;
+iscan_buf_t * iscan_chain = 0;
+
+iscan_buf_t *
+dhd_iscan_allocate_buf(dhd_pub_t *dhd, iscan_buf_t **iscanbuf)
+{
+ iscan_buf_t *iscanbuf_alloc = 0;
+ iscan_buf_t *iscanbuf_head;
+
+ dhd_iscan_lock();
+
+ iscanbuf_alloc = (iscan_buf_t*)MALLOC(dhd->osh, sizeof(iscan_buf_t));
+ if (iscanbuf_alloc == NULL)
+ goto fail;
+
+ iscanbuf_alloc->next = NULL;
+ iscanbuf_head = *iscanbuf;
+
+ DHD_ISCAN(("%s: addr of allocated node = 0x%X, addr of iscanbuf_head \
+ = 0x%X dhd = 0x%X\n", __FUNCTION__, iscanbuf_alloc,
+ iscanbuf_head, dhd));
+
+ if (iscanbuf_head == NULL) {
+ *iscanbuf = iscanbuf_alloc;
+ DHD_ISCAN(("%s: Head is allocated\n", __FUNCTION__));
+ goto fail;
+ }
+
+ while (iscanbuf_head->next)
+ iscanbuf_head = iscanbuf_head->next;
+
+ iscanbuf_head->next = iscanbuf_alloc;
+
+fail:
+ dhd_iscan_unlock();
+ return iscanbuf_alloc;
+}
+
+void
+dhd_iscan_free_buf(void *dhdp, iscan_buf_t *iscan_delete)
+{
+ iscan_buf_t *iscanbuf_free = 0;
+ iscan_buf_t *iscanbuf_prv = 0;
+ iscan_buf_t *iscanbuf_cur = iscan_chain;
+ dhd_pub_t *dhd = dhd_bus_pub(dhdp);
+
+ dhd_iscan_lock();
+ /* If iscan_delete is null then delete the entire
+ * chain or else delete specific one provided
+ */
+ if (!iscan_delete) {
+ while (iscanbuf_cur) {
+ iscanbuf_free = iscanbuf_cur;
+ iscanbuf_cur = iscanbuf_cur->next;
+ iscanbuf_free->next = 0;
+ MFREE(dhd->osh, iscanbuf_free, sizeof(iscan_buf_t));
+ }
+ iscan_chain = 0;
+ } else {
+ while (iscanbuf_cur) {
+ if (iscanbuf_cur == iscan_delete)
+ break;
+ iscanbuf_prv = iscanbuf_cur;
+ iscanbuf_cur = iscanbuf_cur->next;
+ }
+ if (iscanbuf_prv)
+ iscanbuf_prv->next = iscan_delete->next;
+
+ iscan_delete->next = 0;
+ MFREE(dhd->osh, iscan_delete, sizeof(iscan_buf_t));
+
+ if (!iscanbuf_prv)
+ iscan_chain = 0;
+ }
+ dhd_iscan_unlock();
+}
+
+iscan_buf_t *
+dhd_iscan_result_buf(void)
+{
+ return iscan_chain;
+}
+
+
+
+/*
+* print scan cache
+* print partial iscan_skip list differently
+*/
+int
+dhd_iscan_print_cache(iscan_buf_t *iscan_skip)
+{
+ int i = 0, l = 0;
+ iscan_buf_t *iscan_cur;
+ wl_iscan_results_t *list;
+ wl_scan_results_t *results;
+ wl_bss_info_t UNALIGNED *bi;
+
+ dhd_iscan_lock();
+
+ iscan_cur = dhd_iscan_result_buf();
+
+ while (iscan_cur) {
+ list = (wl_iscan_results_t *)iscan_cur->iscan_buf;
+ if (!list)
+ break;
+
+ results = (wl_scan_results_t *)&list->results;
+ if (!results)
+ break;
+
+ if (results->version != WL_BSS_INFO_VERSION) {
+ DHD_ISCAN(("%s: results->version %d != WL_BSS_INFO_VERSION\n",
+ __FUNCTION__, results->version));
+ goto done;
+ }
+
+ bi = results->bss_info;
+ for (i = 0; i < results->count; i++) {
+ if (!bi)
+ break;
+
+ DHD_ISCAN(("%s[%2.2d:%2.2d] %X:%X:%X:%X:%X:%X\n",
+ iscan_cur != iscan_skip?"BSS":"bss", l, i,
+ bi->BSSID.octet[0], bi->BSSID.octet[1], bi->BSSID.octet[2],
+ bi->BSSID.octet[3], bi->BSSID.octet[4], bi->BSSID.octet[5]));
+
+ bi = (wl_bss_info_t *)((uintptr)bi + dtoh32(bi->length));
+ }
+ iscan_cur = iscan_cur->next;
+ l++;
+ }
+
+done:
+ dhd_iscan_unlock();
+ return 0;
+}
+
+/*
+* delete disappeared AP from specific scan cache but skip partial list in iscan_skip
+*/
+int
+dhd_iscan_delete_bss(void *dhdp, void *addr, iscan_buf_t *iscan_skip)
+{
+ int i = 0, j = 0, l = 0;
+ iscan_buf_t *iscan_cur;
+ wl_iscan_results_t *list;
+ wl_scan_results_t *results;
+ wl_bss_info_t UNALIGNED *bi, *bi_new, *bi_next;
+
+ uchar *s_addr = addr;
+
+ dhd_iscan_lock();
+ DHD_ISCAN(("%s: BSS to remove %X:%X:%X:%X:%X:%X\n",
+ __FUNCTION__, s_addr[0], s_addr[1], s_addr[2],
+ s_addr[3], s_addr[4], s_addr[5]));
+
+ iscan_cur = dhd_iscan_result_buf();
+
+ while (iscan_cur) {
+ if (iscan_cur != iscan_skip) {
+ list = (wl_iscan_results_t *)iscan_cur->iscan_buf;
+ if (!list)
+ break;
+
+ results = (wl_scan_results_t *)&list->results;
+ if (!results)
+ break;
+
+ if (results->version != WL_BSS_INFO_VERSION) {
+ DHD_ERROR(("%s: results->version %d != WL_BSS_INFO_VERSION\n",
+ __FUNCTION__, results->version));
+ goto done;
+ }
+
+ bi = results->bss_info;
+ for (i = 0; i < results->count; i++) {
+ if (!bi)
+ break;
+
+ if (!memcmp(bi->BSSID.octet, addr, ETHER_ADDR_LEN)) {
+ DHD_ISCAN(("%s: Del BSS[%2.2d:%2.2d] %X:%X:%X:%X:%X:%X\n", \
+ __FUNCTION__, l, i, bi->BSSID.octet[0], \
+ bi->BSSID.octet[1], bi->BSSID.octet[2], \
+ bi->BSSID.octet[3], bi->BSSID.octet[4], \
+ bi->BSSID.octet[5]));
+
+ bi_new = bi;
+ bi = (wl_bss_info_t *)((uintptr)bi + dtoh32(bi->length));
+/*
+ if(bi && bi_new) {
+ bcopy(bi, bi_new, results->buflen -
+ dtoh32(bi_new->length));
+ results->buflen -= dtoh32(bi_new->length);
+ }
+*/
+ results->buflen -= dtoh32(bi_new->length);
+ results->count--;
+
+ for (j = i; j < results->count; j++) {
+ if (bi && bi_new) {
+ DHD_ISCAN(("%s: Moved up BSS[%2.2d:%2.2d] \
+ %X:%X:%X:%X:%X:%X\n",
+ __FUNCTION__, l, j, bi->BSSID.octet[0],
+ bi->BSSID.octet[1], bi->BSSID.octet[2],
+ bi->BSSID.octet[3], bi->BSSID.octet[4],
+ bi->BSSID.octet[5]));
+
+ bi_next = (wl_bss_info_t *)((uintptr)bi +
+ dtoh32(bi->length));
+ bcopy(bi, bi_new, dtoh32(bi->length));
+ bi_new = (wl_bss_info_t *)((uintptr)bi_new +
+ dtoh32(bi_new->length));
+ bi = bi_next;
+ }
+ }
+
+ if (results->count == 0) {
+ /* Prune now empty partial scan list */
+ dhd_iscan_free_buf(dhdp, iscan_cur);
+ goto done;
+ }
+ break;
+ }
+ bi = (wl_bss_info_t *)((uintptr)bi + dtoh32(bi->length));
+ }
+ }
+ iscan_cur = iscan_cur->next;
+ l++;
+ }
+
+done:
+ dhd_iscan_unlock();
+ return 0;
+}
+
+int
+dhd_iscan_remove_duplicates(void * dhdp, iscan_buf_t *iscan_cur)
+{
+ int i = 0;
+ wl_iscan_results_t *list;
+ wl_scan_results_t *results;
+ wl_bss_info_t UNALIGNED *bi, *bi_new, *bi_next;
+
+ dhd_iscan_lock();
+
+ DHD_ISCAN(("%s: Scan cache before delete\n",
+ __FUNCTION__));
+ dhd_iscan_print_cache(iscan_cur);
+
+ if (!iscan_cur)
+ goto done;
+
+ list = (wl_iscan_results_t *)iscan_cur->iscan_buf;
+ if (!list)
+ goto done;
+
+ results = (wl_scan_results_t *)&list->results;
+ if (!results)
+ goto done;
+
+ if (results->version != WL_BSS_INFO_VERSION) {
+ DHD_ERROR(("%s: results->version %d != WL_BSS_INFO_VERSION\n",
+ __FUNCTION__, results->version));
+ goto done;
+ }
+
+ bi = results->bss_info;
+ for (i = 0; i < results->count; i++) {
+ if (!bi)
+ break;
+
+ DHD_ISCAN(("%s: Find dups for BSS[%2.2d] %X:%X:%X:%X:%X:%X\n",
+ __FUNCTION__, i, bi->BSSID.octet[0], bi->BSSID.octet[1], bi->BSSID.octet[2],
+ bi->BSSID.octet[3], bi->BSSID.octet[4], bi->BSSID.octet[5]));
+
+ dhd_iscan_delete_bss(dhdp, bi->BSSID.octet, iscan_cur);
+
+ bi = (wl_bss_info_t *)((uintptr)bi + dtoh32(bi->length));
+ }
+
+done:
+ DHD_ISCAN(("%s: Scan cache after delete\n", __FUNCTION__));
+ dhd_iscan_print_cache(iscan_cur);
+ dhd_iscan_unlock();
+ return 0;
+}
+
+void
+dhd_iscan_ind_scan_confirm(void *dhdp, bool status)
+{
+
+ dhd_ind_scan_confirm(dhdp, status);
+}
+
+int
+dhd_iscan_request(void * dhdp, uint16 action)
+{
+ int rc;
+ wl_iscan_params_t params;
+ dhd_pub_t *dhd = dhd_bus_pub(dhdp);
+ char buf[WLC_IOCTL_SMLEN];
+
+
+ memset(&params, 0, sizeof(wl_iscan_params_t));
+ memcpy(&params.params.bssid, &ether_bcast, ETHER_ADDR_LEN);
+
+ params.params.bss_type = DOT11_BSSTYPE_ANY;
+ params.params.scan_type = DOT11_SCANTYPE_ACTIVE;
+
+ params.params.nprobes = htod32(-1);
+ params.params.active_time = htod32(-1);
+ params.params.passive_time = htod32(-1);
+ params.params.home_time = htod32(-1);
+ params.params.channel_num = htod32(0);
+
+ params.version = htod32(ISCAN_REQ_VERSION);
+ params.action = htod16(action);
+ params.scan_duration = htod16(0);
+
+ bcm_mkiovar("iscan", (char *)&params, sizeof(wl_iscan_params_t), buf, WLC_IOCTL_SMLEN);
+ rc = dhd_wl_ioctl(dhdp, WLC_SET_VAR, buf, WLC_IOCTL_SMLEN);
+
+ return rc;
+}
+
+static int
+dhd_iscan_get_partial_result(void *dhdp, uint *scan_count)
+{
+ wl_iscan_results_t *list_buf;
+ wl_iscan_results_t list;
+ wl_scan_results_t *results;
+ iscan_buf_t *iscan_cur;
+ int status = -1;
+ dhd_pub_t *dhd = dhd_bus_pub(dhdp);
+ int rc;
+
+
+ iscan_cur = dhd_iscan_allocate_buf(dhd, &iscan_chain);
+ if (!iscan_cur) {
+ DHD_ERROR(("%s: Failed to allocate node\n", __FUNCTION__));
+ dhd_iscan_free_buf(dhdp, 0);
+ dhd_iscan_request(dhdp, WL_SCAN_ACTION_ABORT);
+ goto fail;
+ }
+
+ dhd_iscan_lock();
+
+ memset(iscan_cur->iscan_buf, 0, WLC_IW_ISCAN_MAXLEN);
+ list_buf = (wl_iscan_results_t*)iscan_cur->iscan_buf;
+ results = &list_buf->results;
+ results->buflen = WL_ISCAN_RESULTS_FIXED_SIZE;
+ results->version = 0;
+ results->count = 0;
+
+ memset(&list, 0, sizeof(list));
+ list.results.buflen = htod32(WLC_IW_ISCAN_MAXLEN);
+ bcm_mkiovar("iscanresults", (char *)&list, WL_ISCAN_RESULTS_FIXED_SIZE,
+ iscan_cur->iscan_buf, WLC_IW_ISCAN_MAXLEN);
+ rc = dhd_wl_ioctl(dhdp, WLC_GET_VAR, iscan_cur->iscan_buf, WLC_IW_ISCAN_MAXLEN);
+
+ results->buflen = dtoh32(results->buflen);
+ results->version = dtoh32(results->version);
+ *scan_count = results->count = dtoh32(results->count);
+ status = dtoh32(list_buf->status);
+
+ dhd_iscan_unlock();
+
+ if (!(*scan_count))
+ dhd_iscan_free_buf(dhdp, iscan_cur);
+ else
+ dhd_iscan_remove_duplicates(dhdp, iscan_cur);
+
+
+fail:
+ return status;
+}
+
+#endif
+
+/* Android ComboSCAN support */
+#if defined(CSCAN)
+
+/*
+ * data parsing from ComboScan tlv list
+*/
+int
+wl_iw_parse_data_tlv(char** list_str, void *dst, int dst_size, const char token, \
+ int input_size, int *bytes_left)
+{
+ char* str = *list_str;
+ uint16 short_temp;
+ uint32 int_temp;
+
+ if ((list_str == NULL) || (*list_str == NULL) ||(bytes_left == NULL) || (*bytes_left < 0)) {
+ DHD_ERROR(("%s error paramters\n", __FUNCTION__));
+ return -1;
+ }
+
+ /* Clean all dest bytes */
+ memset(dst, 0, dst_size);
+ while (*bytes_left > 0) {
+
+ if (str[0] != token) {
+ DHD_TRACE(("%s NOT Type=%d get=%d left_parse=%d \n", __FUNCTION__, \
+ token, str[0], *bytes_left));
+ return -1;
+ }
+
+ *bytes_left -= 1;
+ str += 1;
+
+ if (input_size == 1) {
+ memcpy(dst, str, input_size);
+ }
+ else if (input_size == 2) {
+ memcpy(dst, (char *)htod16(memcpy(&short_temp, str, input_size)), \
+ input_size);
+ }
+ else if (input_size == 4) {
+ memcpy(dst, (char *)htod32(memcpy(&int_temp, str, input_size)), \
+ input_size);
+ }
+
+ *bytes_left -= input_size;
+ str += input_size;
+ *list_str = str;
+ return 1;
+ }
+ return 1;
+}
+
+/*
+ * channel list parsing from cscan tlv list
+*/
+int
+wl_iw_parse_channel_list_tlv(char** list_str, uint16* channel_list, \
+ int channel_num, int *bytes_left)
+{
+ char* str = *list_str;
+ int idx = 0;
+
+ if ((list_str == NULL) || (*list_str == NULL) ||(bytes_left == NULL) || (*bytes_left < 0)) {
+ DHD_ERROR(("%s error paramters\n", __FUNCTION__));
+ return -1;
+ }
+
+ while (*bytes_left > 0) {
+
+ if (str[0] != CSCAN_TLV_TYPE_CHANNEL_IE) {
+ *list_str = str;
+ DHD_TRACE(("End channel=%d left_parse=%d %d\n", idx, *bytes_left, str[0]));
+ return idx;
+ }
+ /* Get proper CSCAN_TLV_TYPE_CHANNEL_IE */
+ *bytes_left -= 1;
+ str += 1;
+
+ if (str[0] == 0) {
+ /* All channels */
+ channel_list[idx] = 0x0;
+ }
+ else {
+ channel_list[idx] = (uint16)str[0];
+ DHD_TRACE(("%s channel=%d \n", __FUNCTION__, channel_list[idx]));
+ }
+ *bytes_left -= 1;
+ str += 1;
+
+ if (idx++ > 255) {
+ DHD_ERROR(("%s Too many channels \n", __FUNCTION__));
+ return -1;
+ }
+ }
+
+ *list_str = str;
+ return idx;
+}
+
+/*
+ * SSIDs list parsing from cscan tlv list
+ */
+int
+wl_iw_parse_ssid_list_tlv(char** list_str, wlc_ssid_t* ssid, int max, int *bytes_left)
+{
+ char* str = *list_str;
+ int idx = 0;
+
+ if ((list_str == NULL) || (*list_str == NULL) || (*bytes_left < 0)) {
+ DHD_ERROR(("%s error paramters\n", __FUNCTION__));
+ return -1;
+ }
+
+ while (*bytes_left > 0) {
+
+ if (str[0] != CSCAN_TLV_TYPE_SSID_IE) {
+ *list_str = str;
+ DHD_TRACE(("nssid=%d left_parse=%d %d\n", idx, *bytes_left, str[0]));
+ return idx;
+ }
+
+ /* Get proper CSCAN_TLV_TYPE_SSID_IE */
+ *bytes_left -= 1;
+ str += 1;
+
+ if (str[0] == 0) {
+ /* Broadcast SSID */
+ ssid[idx].SSID_len = 0;
+ memset((char*)ssid[idx].SSID, 0x0, DOT11_MAX_SSID_LEN);
+ *bytes_left -= 1;
+ str += 1;
+
+ DHD_TRACE(("BROADCAST SCAN left=%d\n", *bytes_left));
+ }
+ else if (str[0] <= DOT11_MAX_SSID_LEN) {
+ /* Get proper SSID size */
+ ssid[idx].SSID_len = str[0];
+ *bytes_left -= 1;
+ str += 1;
+
+ /* Get SSID */
+ if (ssid[idx].SSID_len > *bytes_left) {
+ DHD_ERROR(("%s out of memory range len=%d but left=%d\n", \
+ __FUNCTION__, ssid[idx].SSID_len, *bytes_left));
+ return -1;
+ }
+
+ memcpy((char*)ssid[idx].SSID, str, ssid[idx].SSID_len);
+
+ *bytes_left -= ssid[idx].SSID_len;
+ str += ssid[idx].SSID_len;
+
+ DHD_TRACE(("%s :size=%d left=%d\n", (char*)ssid[idx].SSID, \
+ ssid[idx].SSID_len, *bytes_left));
+ }
+ else {
+ DHD_ERROR(("### SSID size more that %d\n", str[0]));
+ return -1;
+ }
+
+ if (idx++ > max) {
+ DHD_ERROR(("%s number of SSIDs more that %d\n", __FUNCTION__, idx));
+ return -1;
+ }
+ }
+
+ *list_str = str;
+ return idx;
+}
+
+/* Parse a comma-separated list from list_str into ssid array, starting
+ * at index idx. Max specifies size of the ssid array. Parses ssids
+ * and returns updated idx; if idx >= max not all fit, the excess have
+ * not been copied. Returns -1 on empty string, or on ssid too long.
+ */
+int
+wl_iw_parse_ssid_list(char** list_str, wlc_ssid_t* ssid, int idx, int max)
+{
+ char* str, *ptr;
+
+ if ((list_str == NULL) || (*list_str == NULL))
+ return -1;
+
+ for (str = *list_str; str != NULL; str = ptr) {
+
+ /* check for next TAG */
+ if (!strncmp(str, GET_CHANNEL, strlen(GET_CHANNEL))) {
+ *list_str = str + strlen(GET_CHANNEL);
+ return idx;
+ }
+
+ if ((ptr = strchr(str, ',')) != NULL) {
+ *ptr++ = '\0';
+ }
+
+ if (strlen(str) > DOT11_MAX_SSID_LEN) {
+ DHD_ERROR(("ssid <%s> exceeds %d\n", str, DOT11_MAX_SSID_LEN));
+ return -1;
+ }
+
+ if (strlen(str) == 0)
+ ssid[idx].SSID_len = 0;
+
+ if (idx < max) {
+ strcpy((char*)ssid[idx].SSID, str);
+ ssid[idx].SSID_len = strlen(str);
+ }
+ idx++;
+ }
+ return idx;
+}
+
+/*
+ * Parse channel list from iwpriv CSCAN
+ */
+int
+wl_iw_parse_channel_list(char** list_str, uint16* channel_list, int channel_num)
+{
+ int num;
+ int val;
+ char* str;
+ char* endptr = NULL;
+
+ if ((list_str == NULL)||(*list_str == NULL))
+ return -1;
+
+ str = *list_str;
+ num = 0;
+ while (strncmp(str, GET_NPROBE, strlen(GET_NPROBE))) {
+ val = (int)strtoul(str, &endptr, 0);
+ if (endptr == str) {
+ printf("could not parse channel number starting at"
+ " substring \"%s\" in list:\n%s\n",
+ str, *list_str);
+ return -1;
+ }
+ str = endptr + strspn(endptr, " ,");
+
+ if (num == channel_num) {
+ DHD_ERROR(("too many channels (more than %d) in channel list:\n%s\n",
+ channel_num, *list_str));
+ return -1;
+ }
+
+ channel_list[num++] = (uint16)val;
+ }
+ *list_str = str;
+ return num;
+}
+
+#endif
diff --git a/bcm4329/src/dhd/sys/dhd_custom_gpio.c b/bcm4329/src/dhd/sys/dhd_custom_gpio.c
index cb67ae2..7a98762 100644
--- a/bcm4329/src/dhd/sys/dhd_custom_gpio.c
+++ b/bcm4329/src/dhd/sys/dhd_custom_gpio.c
@@ -20,7 +20,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_custom_gpio.c,v 1.1.4.6 2010/02/19 22:56:49 Exp $
+* $Id: dhd_custom_gpio.c,v 1.1.4.7 2010/06/03 21:27:48 Exp $
*/
@@ -148,3 +148,26 @@ dhd_customer_gpio_wlan_ctrl(int onoff)
break;
}
}
+
+#ifdef GET_CUSTOM_MAC_ENABLE
+/* Function to get custom MAC address */
+int
+dhd_custom_get_mac_address(unsigned char *buf)
+{
+ WL_TRACE(("%s Enter\n", __FUNCTION__));
+ if (!buf)
+ return -EINVAL;
+
+ /* Customer access to MAC address stored outside of DHD driver */
+
+#ifdef EXAMPLE_GET_MAC
+ /* EXAMPLE code */
+ {
+ struct ether_addr ea_example = {{0x00, 0x11, 0x22, 0x33, 0x44, 0xFF}};
+ bcopy((char *)&ea_example, buf, sizeof(struct ether_addr));
+ }
+#endif /* EXAMPLE_GET_MAC */
+
+ return 0;
+}
+#endif /* GET_CUSTOM_MAC_ENABLE */
diff --git a/bcm4329/src/dhd/sys/dhd_dbg.h b/bcm4329/src/dhd/sys/dhd_dbg.h
index a4f180c..9f09ce7 100644
--- a/bcm4329/src/dhd/sys/dhd_dbg.h
+++ b/bcm4329/src/dhd/sys/dhd_dbg.h
@@ -21,7 +21,7 @@
* software in any way with any other Broadcom software provided under a license
* other than the GPL, without Broadcom's express prior written consent.
*
- * $Id: dhd_dbg.h,v 1.5.6.2.4.2.14.9 2010/04/20 05:27:52 Exp $
+ * $Id: dhd_dbg.h,v 1.5.6.2.4.2.14.10 2010/05/21 21:49:38 Exp $
*/
#ifndef _dhd_dbg_
@@ -42,6 +42,7 @@
#define DHD_GLOM(args) do {if (dhd_msg_level & DHD_GLOM_VAL) printf args;} while (0)
#define DHD_EVENT(args) do {if (dhd_msg_level & DHD_EVENT_VAL) printf args;} while (0)
#define DHD_BTA(args) do {if (dhd_msg_level & DHD_BTA_VAL) printf args;} while (0)
+#define DHD_ISCAN(args) do {if (dhd_msg_level & DHD_ISCAN_VAL) printf args;} while (0)
#define DHD_ERROR_ON() (dhd_msg_level & DHD_ERROR_VAL)
#define DHD_TRACE_ON() (dhd_msg_level & DHD_TRACE_VAL)
@@ -55,6 +56,7 @@
#define DHD_GLOM_ON() (dhd_msg_level & DHD_GLOM_VAL)
#define DHD_EVENT_ON() (dhd_msg_level & DHD_EVENT_VAL)
#define DHD_BTA_ON() (dhd_msg_level & DHD_BTA_VAL)
+#define DHD_ISCAN_ON() (dhd_msg_level & DHD_ISCAN_VAL)
#else /* (defined BCMDBG) || (defined DHD_DEBUG) */
@@ -70,6 +72,7 @@
#define DHD_GLOM(args)
#define DHD_EVENT(args)
#define DHD_BTA(args)
+#define DHD_ISCAN(args)
#define DHD_ERROR_ON() 0
#define DHD_TRACE_ON() 0
@@ -83,7 +86,7 @@
#define DHD_GLOM_ON() 0
#define DHD_EVENT_ON() 0
#define DHD_BTA_ON() 0
-
+#define DHD_ISCAN_ON() 0
#endif
#define DHD_LOG(args)
diff --git a/bcm4329/src/dhd/sys/dhd_linux.c b/bcm4329/src/dhd/sys/dhd_linux.c
index 1b3f611..f1ddba4 100644
--- a/bcm4329/src/dhd/sys/dhd_linux.c
+++ b/bcm4329/src/dhd/sys/dhd_linux.c
@@ -22,7 +22,7 @@
* software in any way with any other Broadcom software provided under a license
* other than the GPL, without Broadcom's express prior written consent.
*
- * $Id: dhd_linux.c,v 1.65.4.9.2.12.2.79.2.2 2010/05/18 01:39:35 Exp $
+ * $Id: dhd_linux.c,v 1.65.4.9.2.12.2.87 2010/06/23 00:14:28 Exp $
*/
#ifdef CONFIG_WIFI_CONTROL_FUNC
@@ -298,20 +298,24 @@ module_param(dhd_watchdog_ms, uint, 0);
/* Console poll interval */
uint dhd_console_ms = 0;
module_param(dhd_console_ms, uint, 0);
-#endif
+#endif /* DHD_DEBUG */
-/* ARP offload agent mode */
-uint dhd_arp_mode = 0;
+/* ARP offload agent mode : Enable ARP Host Auto-Reply and ARP Peer Auto-Reply */
+uint dhd_arp_mode = 0xb;
module_param(dhd_arp_mode, uint, 0);
/* ARP offload enable */
-uint dhd_arp_enable = FALSE;
+uint dhd_arp_enable = TRUE;
module_param(dhd_arp_enable, uint, 0);
-/* Pkt filte enable control */
-uint dhd_pkt_filter_enable = FALSE;
+/* Global Pkt filter enable control */
+uint dhd_pkt_filter_enable = TRUE;
module_param(dhd_pkt_filter_enable, uint, 0);
+/* Pkt filter init setup */
+uint dhd_pkt_filter_init = 0;
+module_param(dhd_pkt_filter_init, uint, 0);
+
/* Pkt filter mode control */
uint dhd_master_mode = TRUE;
module_param(dhd_master_mode, uint, 1);
@@ -484,6 +488,8 @@ int dhd_set_suspend(int value, dhd_pub_t *dhd)
if (dhd && dhd->up) {
dhd_os_proto_block(dhd);
if (value) {
+
+ /* Kernel suspended */
dhdcdc_set_ioctl(dhd, 0, WLC_SET_PM,
(char *)&power_mode, sizeof(power_mode));
@@ -506,6 +512,8 @@ int dhd_set_suspend(int value, dhd_pub_t *dhd)
dhdcdc_set_ioctl(dhd, 0, WLC_SET_VAR, iovbuf, sizeof(iovbuf));
#endif /* CUSTOMER_HW2 */
} else {
+
+ /* Kernel resumed */
power_mode = PM_FAST;
dhdcdc_set_ioctl(dhd, 0, WLC_SET_PM, (char *)&power_mode,
sizeof(power_mode));
@@ -2247,7 +2255,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 */
@@ -2551,6 +2559,7 @@ dhd_os_wd_timer(void *bus, uint wdtick)
/* don't start the wd until fw is loaded */
if (pub->busstate == DHD_BUS_DOWN)
return;
+
/* Totally stop the timer */
if (!wdtick && dhd->wd_timer_valid == TRUE) {
del_timer(&dhd->timer);
@@ -2835,3 +2844,40 @@ dhd_wait_pend8021x(struct net_device *dev)
}
return pend;
}
+
+#ifdef DHD_DEBUG
+int
+write_to_file(dhd_pub_t *dhd, uint8 *buf, int size)
+{
+ int ret = 0;
+ struct file *fp;
+ mm_segment_t old_fs;
+ loff_t pos = 0;
+
+ /* change to KERNEL_DS address limit */
+ old_fs = get_fs();
+ set_fs(KERNEL_DS);
+
+ /* open file to write */
+ fp = filp_open("/tmp/mem_dump", O_WRONLY|O_CREAT, 0640);
+ if (!fp) {
+ printf("%s: open file error\n", __FUNCTION__);
+ ret = -1;
+ goto exit;
+ }
+
+ /* Write buf to file */
+ fp->f_op->write(fp, buf, size, &pos);
+
+exit:
+ /* free buf before return */
+ MFREE(dhd->osh, buf, size);
+ /* close file before return */
+ if (fp)
+ filp_close(fp, current->files);
+ /* restore previous address limit */
+ set_fs(old_fs);
+
+ return ret;
+}
+#endif /* DHD_DEBUG */
diff --git a/bcm4329/src/dhd/sys/dhd_proto.h b/bcm4329/src/dhd/sys/dhd_proto.h
index 79584d6..382785a 100644
--- a/bcm4329/src/dhd/sys/dhd_proto.h
+++ b/bcm4329/src/dhd/sys/dhd_proto.h
@@ -24,7 +24,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_proto.h,v 1.2.82.1.4.1.16.6 2009/06/17 01:01:55 Exp $
+ * $Id: dhd_proto.h,v 1.2.82.1.4.1.16.7 2010/05/10 12:54:59 Exp $
*/
#ifndef _dhd_proto_h_
@@ -37,6 +37,10 @@
#define IOCTL_RESP_TIMEOUT 2000 /* In milli second */
#endif
+#ifndef IOCTL_CHIP_ACTIVE_TIMEOUT
+#define IOCTL_CHIP_ACTIVE_TIMEOUT 10 /* In milli second */
+#endif
+
/*
* Exported from the dhd protocol module (dhd_cdc, dhd_rndis)
*/
diff --git a/bcm4329/src/dhd/sys/dhd_sdio.c b/bcm4329/src/dhd/sys/dhd_sdio.c
index aa938de..127260a 100644
--- a/bcm4329/src/dhd/sys/dhd_sdio.c
+++ b/bcm4329/src/dhd/sys/dhd_sdio.c
@@ -21,7 +21,7 @@
* software in any way with any other Broadcom software provided under a license
* other than the GPL, without Broadcom's express prior written consent.
*
- * $Id: dhd_sdio.c,v 1.157.2.27.2.33.2.109.2.2 2010/05/18 01:13:11 Exp $
+ * $Id: dhd_sdio.c,v 1.157.2.27.2.33.2.126 2010/06/15 23:38:39 Exp $
*/
#include <typedefs.h>
@@ -551,6 +551,7 @@ dhdsdio_htclk(dhd_bus_t *bus, bool on, bool pendok)
bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_DEVICE_CTL, devctl, &err);
DHD_INFO(("CLKCTL: set PENDING\n"));
bus->clkstate = CLK_PENDING;
+
return BCME_OK;
} else if (bus->clkstate == CLK_PENDING) {
/* Cancel CA-only interrupt filter */
@@ -956,7 +957,6 @@ dhdsdio_txpkt(dhd_bus_t *bus, void *pkt, uint chan, bool free_pkt)
(((pad + SDPCM_HDRLEN) << SDPCM_DOFFSET_SHIFT) & SDPCM_DOFFSET_MASK);
htol32_ua_store(swheader, frame + SDPCM_FRAMETAG_LEN);
htol32_ua_store(0, frame + SDPCM_FRAMETAG_LEN + sizeof(swheader));
- bus->tx_seq = (bus->tx_seq + 1) % SDPCM_SEQUENCE_WRAP;
#ifdef DHD_DEBUG
tx_packets[PKTPRIO(pkt)]++;
@@ -1022,6 +1022,9 @@ dhdsdio_txpkt(dhd_bus_t *bus, void *pkt, uint chan, bool free_pkt)
}
}
+ if (ret == 0) {
+ bus->tx_seq = (bus->tx_seq + 1) % SDPCM_SEQUENCE_WRAP;
+ }
} while ((ret < 0) && retrydata && retries++ < TXRETRIES);
done:
@@ -1073,7 +1076,7 @@ dhd_bus_txdata(struct dhd_bus *bus, void *pkt)
/* Check for existing queue, current flow-control, pending event, or pending clock */
if (dhd_deferred_tx || bus->fcstate || pktq_len(&bus->txq) || bus->dpc_sched ||
(!DATAOK(bus)) || (bus->flowcontrol & NBITVAL(prec)) ||
- (bus->clkstate == CLK_PENDING)) {
+ (bus->clkstate != CLK_AVAIL)) {
DHD_TRACE(("%s: deferring pktq len %d\n", __FUNCTION__,
pktq_len(&bus->txq)));
bus->fcqueued++;
@@ -1109,6 +1112,7 @@ dhd_bus_txdata(struct dhd_bus *bus, void *pkt)
/* Otherwise, send it now */
BUS_WAKE(bus);
+ /* Make sure back plane ht clk is on, no pending allowed */
dhdsdio_clkctl(bus, CLK_AVAIL, TRUE);
#ifndef SDTEST
@@ -1263,6 +1267,8 @@ dhd_bus_txctl(struct dhd_bus *bus, uchar *msg, uint msglen)
htol32_ua_store(0, frame + SDPCM_FRAMETAG_LEN + sizeof(swheader));
if (!DATAOK(bus)) {
+ DHD_INFO(("%s: No bus credit bus->tx_max %d, bus->tx_seq %d\n",
+ __FUNCTION__, bus->tx_max, bus->tx_seq));
bus->ctrl_frame_stat = TRUE;
/* Send from dpc */
bus->ctrl_frame_buf = frame;
@@ -1270,15 +1276,16 @@ dhd_bus_txctl(struct dhd_bus *bus, uchar *msg, uint msglen)
dhd_wait_for_event(bus->dhd, &bus->ctrl_frame_stat);
- if (bus->ctrl_frame_stat == FALSE)
+ if (bus->ctrl_frame_stat == FALSE) {
+ DHD_INFO(("%s: ctrl_frame_stat == FALSE\n", __FUNCTION__));
ret = 0;
- else
+ } else {
+ DHD_INFO(("%s: ctrl_frame_stat == TRUE\n", __FUNCTION__));
ret = -1;
+ }
}
if (ret == -1) {
- bus->tx_seq = (bus->tx_seq + 1) % SDPCM_SEQUENCE_WRAP;
-
#ifdef DHD_DEBUG
if (DHD_BYTES_ON() && DHD_CTL_ON()) {
prhex("Tx Frame", frame, len);
@@ -1288,8 +1295,10 @@ dhd_bus_txctl(struct dhd_bus *bus, uchar *msg, uint msglen)
#endif
do {
+ bus->ctrl_frame_stat = FALSE;
ret = dhd_bcmsdh_send_buf(bus, bcmsdh_cur_sbwad(sdh), SDIO_FUNC_2, F2SYNC,
frame, len, NULL, NULL, NULL);
+
ASSERT(ret != BCME_PENDING);
if (ret < 0) {
@@ -1316,6 +1325,9 @@ dhd_bus_txctl(struct dhd_bus *bus, uchar *msg, uint msglen)
}
}
+ if (ret == 0) {
+ bus->tx_seq = (bus->tx_seq + 1) % SDPCM_SEQUENCE_WRAP;
+ }
} while ((ret < 0) && retries++ < TXRETRIES);
}
@@ -1727,78 +1739,6 @@ dhdsdio_readshared(dhd_bus_t *bus, sdpcm_shared_t *sh)
return BCME_OK;
}
-#define CONSOLE_LINE_MAX 192
-
-static int
-dhdsdio_readconsole(dhd_bus_t *bus)
-{
- dhd_console_t *c = &bus->console;
- uint8 line[CONSOLE_LINE_MAX], ch;
- uint32 n, idx, addr;
- int rv;
-
- /* Don't do anything until FWREADY updates console address */
- if (bus->console_addr == 0)
- return 0;
-
- /* Read console log struct */
- addr = bus->console_addr + OFFSETOF(hndrte_cons_t, log);
- if ((rv = dhdsdio_membytes(bus, FALSE, addr, (uint8 *)&c->log, sizeof(c->log))) < 0)
- return rv;
-
- /* Allocate console buffer (one time only) */
- if (c->buf == NULL) {
- c->bufsize = ltoh32(c->log.buf_size);
- if ((c->buf = MALLOC(bus->dhd->osh, c->bufsize)) == NULL)
- return BCME_NOMEM;
- }
-
- idx = ltoh32(c->log.idx);
-
- /* Protect against corrupt value */
- if (idx > c->bufsize)
- return BCME_ERROR;
-
- /* Skip reading the console buffer if the index pointer has not moved */
- if (idx == c->last)
- return BCME_OK;
-
- /* Read the console buffer */
- addr = ltoh32(c->log.buf);
- if ((rv = dhdsdio_membytes(bus, FALSE, addr, c->buf, c->bufsize)) < 0)
- return rv;
-
- while (c->last != idx) {
- for (n = 0; n < CONSOLE_LINE_MAX - 2; n++) {
- if (c->last == idx) {
- /* This would output a partial line. Instead, back up
- * the buffer pointer and output this line next time around.
- */
- if (c->last >= n)
- c->last -= n;
- else
- c->last = c->bufsize - n;
- goto break2;
- }
- ch = c->buf[c->last];
- c->last = (c->last + 1) % c->bufsize;
- if (ch == '\n')
- break;
- line[n] = ch;
- }
-
- if (n > 0) {
- if (line[n - 1] == '\r')
- n--;
- line[n] = 0;
- printf("CONSOLE: %s\n", line);
- }
- }
-break2:
-
- return BCME_OK;
-}
-
static int
dhdsdio_checkdied(dhd_bus_t *bus, uint8 *data, uint size)
{
@@ -1891,7 +1831,7 @@ dhdsdio_checkdied(dhd_bus_t *bus, uint8 *data, uint size)
goto done;
bcm_bprintf(&strbuf,
- "Dongle trap type 0x%x @ pc 0x%x, cpsr 0x%x, spsr 0x%x, sp 0x%x,"
+ "Dongle trap type 0x%x @ epc 0x%x, cpsr 0x%x, spsr 0x%x, sp 0x%x,"
"lp 0x%x, rpc 0x%x Trap offset 0x%x, "
"r0 0x%x, r1 0x%x, r2 0x%x, r3 0x%x, r4 0x%x, r5 0x%x, r6 0x%x, r7 0x%x\n",
tr.type, tr.epc, tr.cpsr, tr.spsr, tr.r13, tr.r14, tr.pc,
@@ -1904,10 +1844,12 @@ dhdsdio_checkdied(dhd_bus_t *bus, uint8 *data, uint size)
DHD_ERROR(("%s: %s\n", __FUNCTION__, strbuf.origbuf));
}
+#ifdef DHD_DEBUG
if (sdpcm_shared.flags & SDPCM_SHARED_TRAP) {
- /* Mem dump to a file on device */
- dhdsdio_mem_dump(bus);
+ /* Mem dump to a file on device */
+ dhdsdio_mem_dump(bus);
}
+#endif /* DHD_DEBUG */
done:
if (mbuffer)
@@ -1922,9 +1864,125 @@ static int
dhdsdio_mem_dump(dhd_bus_t *bus)
{
int ret = 0;
- return ret;
+ int size; /* Full mem size */
+ int start = 0; /* Start address */
+ int read_size = 0; /* Read size of each iteration */
+ uint8 *buf = NULL, *databuf = NULL;
+
+ /* Get full mem size */
+ size = bus->ramsize;
+ buf = MALLOC(bus->dhd->osh, size);
+ if (!buf) {
+ printf("%s: Out of memory (%d bytes)\n", __FUNCTION__, size);
+ return -1;
+ }
+
+ /* Read mem content */
+ printf("Dump dongle memory");
+ databuf = buf;
+ while (size)
+ {
+ read_size = MIN(MEMBLOCK, size);
+ if ((ret = dhdsdio_membytes(bus, FALSE, start, databuf, read_size)))
+ {
+ printf("%s: Error membytes %d\n", __FUNCTION__, ret);
+ if (buf) {
+ MFREE(bus->dhd->osh, buf, size);
+ }
+ return -1;
+ }
+ printf(".");
+
+ /* Decrement size and increment start address */
+ size -= read_size;
+ start += read_size;
+ databuf += read_size;
+ }
+ printf("Done\n");
+
+ /* free buf before return !!! */
+ if (write_to_file(bus->dhd, buf, bus->ramsize))
+ {
+ printf("%s: Error writing to files\n", __FUNCTION__);
+ return -1;
+ }
+
+ /* buf free handled in write_to_file, not here */
+ return 0;
}
-#endif
+
+#define CONSOLE_LINE_MAX 192
+
+static int
+dhdsdio_readconsole(dhd_bus_t *bus)
+{
+ dhd_console_t *c = &bus->console;
+ uint8 line[CONSOLE_LINE_MAX], ch;
+ uint32 n, idx, addr;
+ int rv;
+
+ /* Don't do anything until FWREADY updates console address */
+ if (bus->console_addr == 0)
+ return 0;
+
+ /* Read console log struct */
+ addr = bus->console_addr + OFFSETOF(hndrte_cons_t, log);
+ if ((rv = dhdsdio_membytes(bus, FALSE, addr, (uint8 *)&c->log, sizeof(c->log))) < 0)
+ return rv;
+
+ /* Allocate console buffer (one time only) */
+ if (c->buf == NULL) {
+ c->bufsize = ltoh32(c->log.buf_size);
+ if ((c->buf = MALLOC(bus->dhd->osh, c->bufsize)) == NULL)
+ return BCME_NOMEM;
+ }
+
+ idx = ltoh32(c->log.idx);
+
+ /* Protect against corrupt value */
+ if (idx > c->bufsize)
+ return BCME_ERROR;
+
+ /* Skip reading the console buffer if the index pointer has not moved */
+ if (idx == c->last)
+ return BCME_OK;
+
+ /* Read the console buffer */
+ addr = ltoh32(c->log.buf);
+ if ((rv = dhdsdio_membytes(bus, FALSE, addr, c->buf, c->bufsize)) < 0)
+ return rv;
+
+ while (c->last != idx) {
+ for (n = 0; n < CONSOLE_LINE_MAX - 2; n++) {
+ if (c->last == idx) {
+ /* This would output a partial line. Instead, back up
+ * the buffer pointer and output this line next time around.
+ */
+ if (c->last >= n)
+ c->last -= n;
+ else
+ c->last = c->bufsize - n;
+ goto break2;
+ }
+ ch = c->buf[c->last];
+ c->last = (c->last + 1) % c->bufsize;
+ if (ch == '\n')
+ break;
+ line[n] = ch;
+ }
+
+ if (n > 0) {
+ if (line[n - 1] == '\r')
+ n--;
+ line[n] = 0;
+ printf("CONSOLE: %s\n", line);
+ }
+ }
+break2:
+
+ return BCME_OK;
+}
+#endif /* DHD_DEBUG */
int
dhdsdio_downloadvars(dhd_bus_t *bus, void *arg, int len)
@@ -4173,7 +4231,7 @@ clkwait:
bcmsdh_intr_enable(sdh);
}
- if (DATAOK(bus) && bus->ctrl_frame_stat) {
+ if (DATAOK(bus) && bus->ctrl_frame_stat && (bus->clkstate == CLK_AVAIL)) {
int ret, i;
ret = dhd_bcmsdh_send_buf(bus, bcmsdh_cur_sbwad(sdh), SDIO_FUNC_2, F2SYNC,
@@ -4205,13 +4263,16 @@ clkwait:
}
}
+ if (ret == 0) {
+ bus->tx_seq = (bus->tx_seq + 1) % SDPCM_SEQUENCE_WRAP;
+ }
+
printf("Return_dpc value is : %d\n", ret);
- bus->tx_seq = (bus->tx_seq + 1) % SDPCM_SEQUENCE_WRAP;
bus->ctrl_frame_stat = FALSE;
dhd_wait_event_wakeup(bus->dhd);
}
/* Send queued frames (limit 1 if rx may still be pending) */
- else if ((bus->clkstate != CLK_PENDING) && !bus->fcstate &&
+ else if ((bus->clkstate == CLK_AVAIL) && !bus->fcstate &&
pktq_mlen(&bus->txq, ~bus->flowcontrol) && txlimit && DATAOK(bus)) {
framecnt = rxdone ? txlimit : MIN(txlimit, dhd_txminmax);
framecnt = dhdsdio_sendfromq(bus, framecnt);
@@ -4226,7 +4287,9 @@ clkwait:
bus->dhd->busstate = DHD_BUS_DOWN;
bus->intstatus = 0;
} else if (bus->clkstate == CLK_PENDING) {
- /* Awaiting I_CHIPACTIVE; don't resched */
+ DHD_INFO(("%s: rescheduled due to CLK_PENDING awaiting \
+ I_CHIPACTIVE interrupt", __FUNCTION__));
+ resched = TRUE;
} else if (bus->intstatus || bus->ipend ||
(!bus->fcstate && pktq_mlen(&bus->txq, ~bus->flowcontrol) && DATAOK(bus)) ||
PKT_AVAILABLE()) { /* Read multiple frames */
@@ -4250,7 +4313,6 @@ clkwait:
bool
dhd_bus_dpc(struct dhd_bus *bus)
{
-#ifdef SDIO_ISR_THREAD
bool resched;
/* Call the DPC directly. */
@@ -4258,9 +4320,6 @@ dhd_bus_dpc(struct dhd_bus *bus)
resched = dhdsdio_dpc(bus);
return resched;
-#else
- return dhdsdio_dpc(bus);
-#endif /* SDIO_ISR_THREAD */
}
void
@@ -4269,6 +4328,8 @@ dhdsdio_isr(void *arg)
dhd_bus_t *bus = (dhd_bus_t*)arg;
bcmsdh_info_t *sdh;
+ DHD_TRACE(("%s: Enter\n", __FUNCTION__));
+
if (!bus) {
DHD_ERROR(("%s : bus is null pointer , exit \n", __FUNCTION__));
return;
@@ -4279,9 +4340,6 @@ dhdsdio_isr(void *arg)
DHD_ERROR(("%s : bus is down. we have nothing to do\n", __FUNCTION__));
return;
}
-
- DHD_TRACE(("%s: Enter\n", __FUNCTION__));
-
/* Count the interrupt call */
bus->intrcount++;
bus->ipend = TRUE;
@@ -4637,6 +4695,7 @@ 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);
}
@@ -4648,6 +4707,68 @@ dhd_bus_watchdog(dhd_pub_t *dhdp)
return bus->ipend;
}
+#ifdef DHD_DEBUG
+extern int
+dhd_bus_console_in(dhd_pub_t *dhdp, uchar *msg, uint msglen)
+{
+ dhd_bus_t *bus = dhdp->bus;
+ uint32 addr, val;
+ int rv;
+ void *pkt;
+
+ /* Address could be zero if CONSOLE := 0 in dongle Makefile */
+ if (bus->console_addr == 0)
+ return BCME_UNSUPPORTED;
+
+ /* Exclusive bus access */
+ dhd_os_sdlock(bus->dhd);
+
+ /* Don't allow input if dongle is in reset */
+ if (bus->dhd->dongle_reset) {
+ dhd_os_sdunlock(bus->dhd);
+ return BCME_NOTREADY;
+ }
+
+ /* Request clock to allow SDIO accesses */
+ BUS_WAKE(bus);
+ /* No pend allowed since txpkt is called later, ht clk has to be on */
+ dhdsdio_clkctl(bus, CLK_AVAIL, FALSE);
+
+ /* Zero cbuf_index */
+ addr = bus->console_addr + OFFSETOF(hndrte_cons_t, cbuf_idx);
+ val = htol32(0);
+ if ((rv = dhdsdio_membytes(bus, TRUE, addr, (uint8 *)&val, sizeof(val))) < 0)
+ goto done;
+
+ /* Write message into cbuf */
+ addr = bus->console_addr + OFFSETOF(hndrte_cons_t, cbuf);
+ if ((rv = dhdsdio_membytes(bus, TRUE, addr, (uint8 *)msg, msglen)) < 0)
+ goto done;
+
+ /* Write length into vcons_in */
+ addr = bus->console_addr + OFFSETOF(hndrte_cons_t, vcons_in);
+ val = htol32(msglen);
+ if ((rv = dhdsdio_membytes(bus, TRUE, addr, (uint8 *)&val, sizeof(val))) < 0)
+ goto done;
+
+ /* Bump dongle by sending an empty event pkt.
+ * sdpcm_sendup (RX) checks for virtual console input.
+ */
+ if (((pkt = PKTGET(bus->dhd->osh, 4 + SDPCM_RESERVE, TRUE)) != NULL) &&
+ bus->clkstate == CLK_AVAIL)
+ dhdsdio_txpkt(bus, pkt, SDPCM_EVENT_CHANNEL, TRUE);
+
+done:
+ if ((bus->idletime == DHD_IDLE_IMMEDIATE) && !bus->dpc_sched) {
+ bus->activity = FALSE;
+ dhdsdio_clkctl(bus, CLK_NONE, TRUE);
+ }
+
+ dhd_os_sdunlock(bus->dhd);
+
+ return rv;
+}
+#endif /* DHD_DEBUG */
#ifdef DHD_DEBUG
static void
diff --git a/bcm4329/src/include/bcmdefs.h b/bcm4329/src/include/bcmdefs.h
index f4e9946..e3c6876 100644
--- a/bcm4329/src/include/bcmdefs.h
+++ b/bcm4329/src/include/bcmdefs.h
@@ -29,6 +29,7 @@
#define STATIC static
+
#define SI_BUS 0
#define PCI_BUS 1
#define PCMCIA_BUS 2
diff --git a/bcm4329/src/include/bcmdevs.h b/bcm4329/src/include/bcmdevs.h
index cad7d31..14853f1 100644
--- a/bcm4329/src/include/bcmdevs.h
+++ b/bcm4329/src/include/bcmdevs.h
@@ -21,7 +21,7 @@
* software in any way with any other Broadcom software provided under a license
* other than the GPL, without Broadcom's express prior written consent.
*
- * $Id: bcmdevs.h,v 13.172.4.5.4.10.2.33 2010/04/05 06:52:57 Exp $
+ * $Id: bcmdevs.h,v 13.172.4.5.4.10.2.36 2010/05/25 08:33:44 Exp $
*/
diff --git a/bcm4329/src/include/bcmsdpcm.h b/bcm4329/src/include/bcmsdpcm.h
index 450c9c3..77aca45 100644
--- a/bcm4329/src/include/bcmsdpcm.h
+++ b/bcm4329/src/include/bcmsdpcm.h
@@ -22,7 +22,7 @@
* software in any way with any other Broadcom software provided under a license
* other than the GPL, without Broadcom's express prior written consent.
*
- * $Id: bcmsdpcm.h,v 1.1.2.3 2009/04/09 18:52:06 Exp $
+ * $Id: bcmsdpcm.h,v 1.1.2.4 2010/07/02 01:15:46 Exp $
*/
#ifndef _bcmsdpcm_h_
@@ -241,7 +241,7 @@ typedef volatile struct {
* Shared structure between dongle and the host
* The structure contains pointers to trap or assert information shared with the host
*/
-#define SDPCM_SHARED_VERSION 0x0001
+#define SDPCM_SHARED_VERSION 0x0002
#define SDPCM_SHARED_VERSION_MASK 0x00FF
#define SDPCM_SHARED_ASSERT_BUILT 0x0100
#define SDPCM_SHARED_ASSERT 0x0200
@@ -255,6 +255,7 @@ typedef struct {
uint32 assert_line;
uint32 console_addr; /* Address of hndrte_cons_t */
uint32 msgtrace_addr;
+ uint8 tag[32];
} sdpcm_shared_t;
extern sdpcm_shared_t sdpcm_shared;
diff --git a/bcm4329/src/include/bcmutils.h b/bcm4329/src/include/bcmutils.h
index 7010838..f85ed35 100644
--- a/bcm4329/src/include/bcmutils.h
+++ b/bcm4329/src/include/bcmutils.h
@@ -20,7 +20,7 @@
* 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: bcmutils.h,v 13.184.4.6.2.1.18.24 2009/12/10 20:19:19 Exp $
+ * $Id: bcmutils.h,v 13.184.4.6.2.1.18.25 2010/04/26 06:05:24 Exp $
*/
diff --git a/bcm4329/src/include/dhdioctl.h b/bcm4329/src/include/dhdioctl.h
index 706b4a8..980a143 100644
--- a/bcm4329/src/include/dhdioctl.h
+++ b/bcm4329/src/include/dhdioctl.h
@@ -25,7 +25,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: dhdioctl.h,v 13.7.8.1.4.1.16.4 2009/09/05 16:50:35 Exp $
+ * $Id: dhdioctl.h,v 13.7.8.1.4.1.16.5 2010/05/21 21:49:38 Exp $
*/
#ifndef _dhdioctl_h_
@@ -79,6 +79,7 @@ typedef struct dhd_ioctl {
#define DHD_GLOM_VAL 0x0400
#define DHD_EVENT_VAL 0x0800
#define DHD_BTA_VAL 0x1000
+#define DHD_ISCAN_VAL 0x2000
#ifdef SDTEST
/* For pktgen iovar */
diff --git a/bcm4329/src/include/epivers.h b/bcm4329/src/include/epivers.h
index a76ea3f..42704f0 100644
--- a/bcm4329/src/include/epivers.h
+++ b/bcm4329/src/include/epivers.h
@@ -31,18 +31,18 @@
#define EPI_MINOR_VERSION 218
-#define EPI_RC_NUMBER 223
+#define EPI_RC_NUMBER 243
-#define EPI_INCREMENTAL_NUMBER 1
+#define EPI_INCREMENTAL_NUMBER 0
#define EPI_BUILD_NUMBER 0
-#define EPI_VERSION 4, 218, 223, 1
+#define EPI_VERSION 4, 218, 243, 0
-#define EPI_VERSION_NUM 0x04dadf01
+#define EPI_VERSION_NUM 0x04daf300
-#define EPI_VERSION_STR "4.218.223.1"
-#define EPI_ROUTER_VERSION_STR "4.219.223.1"
+#define EPI_VERSION_STR "4.218.243.0"
+#define EPI_ROUTER_VERSION_STR "4.219.243.0"
#endif
diff --git a/bcm4329/src/include/linux_osl.h b/bcm4329/src/include/linux_osl.h
index 6c9597d..b059c2a 100644
--- a/bcm4329/src/include/linux_osl.h
+++ b/bcm4329/src/include/linux_osl.h
@@ -21,7 +21,7 @@
* software in any way with any other Broadcom software provided under a license
* other than the GPL, without Broadcom's express prior written consent.
*
- * $Id: linux_osl.h,v 13.131.30.7 2010/03/29 19:03:11 Exp $
+ * $Id: linux_osl.h,v 13.131.30.8 2010/04/26 05:42:18 Exp $
*/
@@ -319,9 +319,4 @@ extern int osl_error(int bcmerror);
#define OSL_SYSUPTIME() ((uint32)jiffies * (1000 / HZ))
-
-#define FILE void
-#define F_OPEN(fp, mode) NULL
-#define F_WRITE(buf, w_size, len, fp) do { } while (0)
-#define F_CLOSE(fp) do { } while (0)
#endif
diff --git a/bcm4329/src/include/linuxver.h b/bcm4329/src/include/linuxver.h
index c329ec2..6ee5c58 100644
--- a/bcm4329/src/include/linuxver.h
+++ b/bcm4329/src/include/linuxver.h
@@ -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: linuxver.h,v 13.38.8.1.8.5 2010/02/04 13:47:16 Exp $
+ * $Id: linuxver.h,v 13.38.8.1.8.6 2010/04/29 05:00:46 Exp $
*/
@@ -33,8 +33,12 @@
#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 0))
#include <linux/config.h>
#else
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 33))
+#include <generated/autoconf.h>
+#else
#include <linux/autoconf.h>
#endif
+#endif
#include <linux/module.h>
#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 3, 0))
diff --git a/bcm4329/src/include/proto/802.11.h b/bcm4329/src/include/proto/802.11.h
index 3ef7de2..fd26317 100644
--- a/bcm4329/src/include/proto/802.11.h
+++ b/bcm4329/src/include/proto/802.11.h
@@ -976,6 +976,7 @@ BWL_PRE_PACKED_STRUCT struct dot11_management_notification {
#define DOT11_MNG_EXT_CSA_ID 60
#define DOT11_MNG_HT_ADD 61
#define DOT11_MNG_EXT_CHANNEL_OFFSET 62
+#define DOT11_MNG_WAPI_ID 68
#define DOT11_MNG_HT_BSS_COEXINFO_ID 72
#define DOT11_MNG_HT_BSS_CHANNEL_REPORT_ID 73
#define DOT11_MNG_HT_OBSS_ID 74
@@ -1422,6 +1423,8 @@ typedef struct vndr_ie vndr_ie_t;
#define AES_KEY_SIZE 16
#define AES_MIC_SIZE 8
+#define SMS4_KEY_LEN 16
+#define SMS4_WPI_CBC_MAC_LEN 16
#include <packed_section_end.h>
diff --git a/bcm4329/src/include/proto/ethernet.h b/bcm4329/src/include/proto/ethernet.h
index c2fc4bf..9ad2ea0 100644
--- a/bcm4329/src/include/proto/ethernet.h
+++ b/bcm4329/src/include/proto/ethernet.h
@@ -67,6 +67,7 @@
#define ETHER_TYPE_8021Q 0x8100
#define ETHER_TYPE_BRCM 0x886c
#define ETHER_TYPE_802_1X 0x888e
+#define ETHER_TYPE_WAI 0x88b4
#ifdef BCMWPA2
#define ETHER_TYPE_802_1X_PREAUTH 0x88c7
#endif
diff --git a/bcm4329/src/include/sbchipc.h b/bcm4329/src/include/sbchipc.h
index 39e5c8d..05b3fd8 100644
--- a/bcm4329/src/include/sbchipc.h
+++ b/bcm4329/src/include/sbchipc.h
@@ -1001,6 +1001,7 @@ typedef volatile struct {
#define CST4315_CBUCK_MODE_BURST 0x00000400
#define CST4315_CBUCK_MODE_LPBURST 0x00000c00
+
#define PMU_MAX_TRANSITION_DLY 15000
diff --git a/bcm4329/src/include/siutils.h b/bcm4329/src/include/siutils.h
index c3e1b29..cb9f140 100644
--- a/bcm4329/src/include/siutils.h
+++ b/bcm4329/src/include/siutils.h
@@ -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: siutils.h,v 13.197.4.2.4.3.8.15 2010/04/19 05:21:30 Exp $
+ * $Id: siutils.h,v 13.197.4.2.4.3.8.16 2010/06/23 21:36:05 Exp $
*/
diff --git a/bcm4329/src/include/wlioctl.h b/bcm4329/src/include/wlioctl.h
index 6324156..d346945 100644
--- a/bcm4329/src/include/wlioctl.h
+++ b/bcm4329/src/include/wlioctl.h
@@ -24,7 +24,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: wlioctl.h,v 1.601.4.15.2.14.2.60 2010/04/12 05:33:02 Exp $
+ * $Id: wlioctl.h,v 1.601.4.15.2.14.2.61 2010/05/04 20:26:25 Exp $
*/
@@ -288,6 +288,7 @@ typedef enum sup_auth_status {
#define CRYPTO_ALGO_AES_OCB_MSDU 5
#define CRYPTO_ALGO_AES_OCB_MPDU 6
#define CRYPTO_ALGO_NALG 7
+#define CRYPTO_ALGO_SMS4 11
#define WSEC_GEN_MIC_ERROR 0x0001
#define WSEC_GEN_REPLAY 0x0002
@@ -338,6 +339,7 @@ typedef struct {
#define AES_ENABLED 0x0004
#define WSEC_SWFLAG 0x0008
#define SES_OW_ENABLED 0x0040
+#define SMS4_ENABLED 0x0100
#define WPA_AUTH_DISABLED 0x0000
@@ -349,6 +351,7 @@ typedef struct {
#define WPA2_AUTH_PSK 0x0080
#define BRCM_AUTH_PSK 0x0100
#define BRCM_AUTH_DPT 0x0200
+#define WPA_AUTH_WAPI 0x0400
#define WPA_AUTH_PFN_ANY 0xffffffff
diff --git a/bcm4329/src/shared/bcmutils.c b/bcm4329/src/shared/bcmutils.c
index c553d8e..43c04ee 100644
--- a/bcm4329/src/shared/bcmutils.c
+++ b/bcm4329/src/shared/bcmutils.c
@@ -20,7 +20,7 @@
* 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: bcmutils.c,v 1.210.4.5.2.4.6.17 2009/11/17 02:20:12 Exp $
+ * $Id: bcmutils.c,v 1.210.4.5.2.4.6.19 2010/04/26 06:05:25 Exp $
*/
#include <typedefs.h>
diff --git a/bcm4329/src/shared/linux_osl.c b/bcm4329/src/shared/linux_osl.c
index c2f5682..242af39 100644
--- a/bcm4329/src/shared/linux_osl.c
+++ b/bcm4329/src/shared/linux_osl.c
@@ -21,12 +21,14 @@
* 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: linux_osl.c,v 1.125.12.3.8.6 2009/12/09 01:29:03 Exp $
+ * $Id: linux_osl.c,v 1.125.12.3.8.7 2010/05/04 21:10:04 Exp $
*/
#define LINUX_OSL
-
+#if defined(CHROMIUMOS_COMPAT_WIRELESS)
+#include <linux/sched.h>
+#endif
#include <typedefs.h>
#include <bcmendian.h>
#include <linuxver.h>
@@ -509,7 +511,7 @@ osl_mfree(osl_t *osh, void *addr, uint size)
#ifdef DHD_USE_STATIC_BUF
if (bcm_static_buf)
{
- if ((addr > (void *)bcm_static_buf) && ((unsigned char *)addr \
+ if ((addr > (void *)bcm_static_buf) && ((unsigned char *)addr
<= ((unsigned char *)bcm_static_buf + STATIC_BUF_TOTAL_LEN)))
{
int buf_idx = 0;
diff --git a/bcm4329/src/shared/siutils.c b/bcm4329/src/shared/siutils.c
index 4ec0501..1814db0 100644
--- a/bcm4329/src/shared/siutils.c
+++ b/bcm4329/src/shared/siutils.c
@@ -22,7 +22,7 @@
* software in any way with any other Broadcom software provided under a license
* other than the GPL, without Broadcom's express prior written consent.
*
- * $Id: siutils.c,v 1.662.4.4.4.16.4.27 2010/04/19 05:21:23 Exp $
+ * $Id: siutils.c,v 1.662.4.4.4.16.4.28 2010/06/23 21:37:54 Exp $
*/
#include <typedefs.h>
diff --git a/bcm4329/src/wl/sys/wl_cfg80211.c b/bcm4329/src/wl/sys/wl_cfg80211.c
index 45a2907..81491cb 100644
--- a/bcm4329/src/wl/sys/wl_cfg80211.c
+++ b/bcm4329/src/wl/sys/wl_cfg80211.c
@@ -21,7 +21,7 @@
* software in any way with any other Broadcom software provided under a license
* other than the GPL, without Broadcom's express prior written consent.
*
- * $Id: wl_cfg80211.c,v 1.1.2.23 2010/04/19 17:10:31 Exp $
+ * $Id: wl_cfg80211.c,v 1.1.2.28 2010/05/04 21:43:38 Exp $
*/
#include <typedefs.h>
@@ -51,6 +51,7 @@
#include <linux/wireless.h>
#include <linux/ieee80211.h>
#include <net/cfg80211.h>
+
#include <net/rtnetlink.h>
#include <linux/mmc/sdio_func.h>
#include <linux/firmware.h>
@@ -65,8 +66,8 @@ uint32 wl_dbg_level = WL_DBG_ERR | WL_DBG_INFO | WL_DBG_DBG;
uint32 wl_dbg_level = WL_DBG_ERR | WL_DBG_INFO;
#endif
-#define WL_4329_FW_FILE "brcm/4329/fw_4329.bin"
-#define WL_4329_NVRAM_FILE "brcm/4329/nvram_4329.txt"
+#define WL_4329_FW_FILE "brcm/fw_4329.bin"
+#define WL_4329_NVRAM_FILE "brcm/nvram_4329.txt"
/*
** cfg80211_ops api/callback list
@@ -107,8 +108,14 @@ static int32 wl_cfg80211_config_default_mgmt_key(struct wiphy *wiphy,
struct net_device *dev, uint8 key_idx);
static int32 wl_cfg80211_resume(struct wiphy *wiphy);
static int32 wl_cfg80211_suspend(struct wiphy *wiphy);
-
-
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 33)) || \
+ defined(CHROMIUMOS_COMPAT_WIRELESS)
+static int32 wl_cfg80211_set_pmksa(struct wiphy *wiphy, struct net_device *dev,
+ struct cfg80211_pmksa *pmksa);
+static int32 wl_cfg80211_del_pmksa(struct wiphy *wiphy, struct net_device *dev,
+ struct cfg80211_pmksa *pmksa);
+static int32 wl_cfg80211_flush_pmksa(struct wiphy *wiphy, struct net_device *dev);
+#endif
/*
** event & event Q handlers for cfg80211 interfaces
*/
@@ -122,19 +129,21 @@ static void wl_unlock_eq(struct wl_priv *wl);
static void wl_init_eq_lock(struct wl_priv *wl);
static void wl_init_eloop_handler(struct wl_event_loop *el);
static struct wl_event_q *wl_deq_event(struct wl_priv *wl);
-static int32 wl_enq_event(struct wl_priv *wl, uint32 type, wl_event_msg_t *msg, void *data);
+static int32 wl_enq_event(struct wl_priv *wl, uint32 type, const wl_event_msg_t *msg, void *data);
static void wl_put_event(struct wl_event_q *e);
static void wl_wakeup_event(struct wl_priv *wl);
static int32 wl_notify_connect_status(struct wl_priv *wl, struct net_device *ndev,
- wl_event_msg_t *e, void* data);
+ const wl_event_msg_t *e, void* data);
static int32 wl_notify_roaming_status(struct wl_priv *wl, struct net_device *ndev,
- wl_event_msg_t *e, void* data);
+ const wl_event_msg_t *e, void* data);
static int32 wl_notify_scan_status(struct wl_priv *wl, struct net_device *ndev,
- wl_event_msg_t *e, void* data);
+ const wl_event_msg_t *e, void* data);
static int32 wl_bss_connect_done(struct wl_priv *wl, struct net_device *ndev,
- wl_event_msg_t *e, void* data);
+ const wl_event_msg_t *e, void* data);
static int32 wl_bss_roaming_done(struct wl_priv *wl, struct net_device *ndev,
- wl_event_msg_t *e, void* data);
+ const wl_event_msg_t *e, void* data);
+static int32 wl_notify_mic_status(struct wl_priv *wl, struct net_device *ndev,
+ const wl_event_msg_t *e, void* data);
/*
** register/deregister sdio function
@@ -146,6 +155,7 @@ static void wl_clear_sdio_func(void);
** ioctl utilites
*/
static int32 wl_dev_bufvar_get(struct net_device *dev, int8 *name, int8 *buf, int32 buf_len);
+static __used int32 wl_dev_bufvar_set(struct net_device *dev, int8 *name, int8 *buf, int32 len);
static int32 wl_dev_intvar_set(struct net_device *dev, int8 *name, int32 val);
static int32 wl_dev_intvar_get(struct net_device *dev, int8 *name, int32 *retval);
static int32 wl_dev_ioctl(struct net_device *dev, uint32 cmd, void *arg, uint32 len);
@@ -161,7 +171,7 @@ static int32 wl_set_retry(struct net_device *dev, uint32 retry, bool l);
/*
** wl profile utilities
*/
-static int32 wl_update_prof(struct wl_priv *wl, wl_event_msg_t *e, void *data, int32 item);
+static int32 wl_update_prof(struct wl_priv *wl, const wl_event_msg_t *e, void *data, int32 item);
static void * wl_read_prof(struct wl_priv *wl, int32 item);
static void wl_init_prof(struct wl_profile *prof);
@@ -230,8 +240,8 @@ static bool wl_is_ibssstarter(struct wl_priv *wl);
/*
** dongle up/down , default configuration utilities
*/
-static bool wl_is_linkdown(struct wl_priv *wl, wl_event_msg_t *e);
-static bool wl_is_linkup(struct wl_priv *wl, wl_event_msg_t *e);
+static bool wl_is_linkdown(struct wl_priv *wl, const wl_event_msg_t *e);
+static bool wl_is_linkup(struct wl_priv *wl, const wl_event_msg_t *e);
static void wl_link_up(struct wl_priv *wl);
static void wl_link_down(struct wl_priv *wl);
static int32 wl_dongle_mode(struct net_device *ndev, int32 iftype);
@@ -289,6 +299,18 @@ static int32 wl_iscan_aborted(struct wl_priv *wl);
*/
static void wl_init_fw(struct wl_fw_ctrl *fw);
+/*
+* find most significant bit set
+*/
+static __used uint32 wl_find_msb(uint16 bit16);
+
+/*
+* update pmklist to dongle
+*/
+static __used int32 wl_update_pmklist(struct net_device *dev, struct wl_pmk_list *pmk_list,
+ int32 err);
+
+
#define WL_PRIV_GET() \
({ \
struct wl_iface *ci; \
@@ -634,7 +656,7 @@ wl_dev_iovar_setbuf(struct net_device *dev, int8 *iovar, void *param,
int32 iolen;
iolen = bcm_mkiovar(iovar, param, paramlen, bufptr, buflen);
- ASSERT(iolen);
+ BUG_ON(unlikely(!iolen));
return wl_dev_ioctl(dev, WLC_SET_VAR, bufptr, iolen);
}
@@ -646,7 +668,7 @@ wl_dev_iovar_getbuf(struct net_device *dev, int8 *iovar, void *param,
int32 iolen;
iolen = bcm_mkiovar(iovar, param, paramlen, bufptr, buflen);
- ASSERT(iolen);
+ BUG_ON(unlikely(!iolen));
return wl_dev_ioctl(dev, WLC_GET_VAR, bufptr, buflen);
}
@@ -667,7 +689,7 @@ wl_run_iscan(struct wl_iscan_ctrl *iscan, struct wlc_ssid *ssid, uint16 action)
if (unlikely(!params))
return -ENOMEM;
memset(params, 0, params_size);
- ASSERT(params_size < WLC_IOCTL_SMLEN);
+ BUG_ON(unlikely(params_size >= WLC_IOCTL_SMLEN));
wl_iscan_prep(&params->params, ssid);
@@ -861,7 +883,7 @@ wl_dev_intvar_set(struct net_device *dev, int8 *name, int32 val)
val = htod32(val);
len = bcm_mkiovar(name, (char *)(&val), sizeof(val), buf, sizeof(buf));
- ASSERT(len);
+ BUG_ON(unlikely(!len));
if (unlikely((err = wl_dev_ioctl(dev, WLC_SET_VAR, buf, len)))) {
WL_ERR(("error (%d)\n", err));
@@ -882,7 +904,7 @@ wl_dev_intvar_get(struct net_device *dev, int8 *name, int32 *retval)
int32 err = 0;
len = bcm_mkiovar(name, (char *)(&data_null), 0, (char *)(&var), sizeof(var.buf));
- ASSERT(len);
+ BUG_ON(unlikely(!len));
if (unlikely((err = wl_dev_ioctl(dev, WLC_GET_VAR, &var, len)))) {
WL_ERR(("error (%d)\n", err));
}
@@ -1090,10 +1112,8 @@ wl_set_wpa_version(struct net_device *dev, struct cfg80211_connect_params *sme)
#endif
if (sme->crypto.wpa_versions & NL80211_WPA_VERSION_1)
val = WPA_AUTH_PSK | WPA_AUTH_UNSPECIFIED;
-#ifdef BCMWPA2
else if (sme->crypto.wpa_versions & NL80211_WPA_VERSION_2)
val = WPA2_AUTH_PSK | WPA2_AUTH_UNSPECIFIED;
-#endif
else
val = WPA_AUTH_DISABLED;
WL_DBG(("setting wpa_auth to 0x%0x\n", val));
@@ -1254,9 +1274,7 @@ wl_set_key_mgmt(struct net_device *dev, struct cfg80211_connect_params *sme)
sme->crypto.cipher_group));
return -EINVAL;
}
- }
-#ifdef BCMWPA2
- else if (val & (WPA2_AUTH_PSK | WPA2_AUTH_UNSPECIFIED)) {
+ } else if (val & (WPA2_AUTH_PSK | WPA2_AUTH_UNSPECIFIED)) {
switch (sme->crypto.akm_suites[0]) {
case WLAN_AKM_SUITE_8021X:
val = WPA2_AUTH_UNSPECIFIED;
@@ -1270,7 +1288,7 @@ wl_set_key_mgmt(struct net_device *dev, struct cfg80211_connect_params *sme)
return -EINVAL;
}
}
-#endif
+
WL_DBG(("setting wpa_auth to %d\n", val));
if (unlikely((err = wl_dev_intvar_set(dev, "wpa_auth", val)))) {
WL_ERR(("could not set wpa_auth (%d)\n", err));
@@ -1530,6 +1548,7 @@ static int32
wl_cfg80211_config_default_key(struct wiphy *wiphy, struct net_device *dev, uint8 key_idx)
{
uint32 index;
+ int32 wsec;
int32 err = 0;
#ifdef WL_CFG80211_BACKTRACE
@@ -1538,11 +1557,19 @@ wl_cfg80211_config_default_key(struct wiphy *wiphy, struct net_device *dev, uint
WL_DBG(("key index (%d)\n", key_idx));
CHECK_SYS_UP();
- /* Just select a new current key */
- index = (uint32)key_idx;
- index = htod32(index);
- if (unlikely((err = wl_dev_ioctl(dev, WLC_SET_KEY_PRIMARY, &index, sizeof(index))))) {
- WL_ERR(("error (%d)\n", err));
+ if (unlikely(err = wl_dev_ioctl(dev, WLC_GET_WSEC, &wsec, sizeof(wsec)))) {
+ WL_ERR(("WLC_GET_WSEC error (%d)\n", err));
+ return err;
+ }
+ wsec = dtoh32(wsec);
+ if (wsec & WEP_ENABLED) {
+ /* Just select a new current key */
+ index = (uint32)key_idx;
+ index = htod32(index);
+ if (unlikely((err = wl_dev_ioctl(dev, WLC_SET_KEY_PRIMARY,
+ &index, sizeof(index))))) {
+ WL_ERR(("error (%d)\n", err));
+ }
}
#ifdef WL_CFG80211_BACKTRACE
WL_DBG(("Out\n"));
@@ -1791,6 +1818,9 @@ wl_cfg80211_get_key(struct wiphy *wiphy, struct net_device *dev,
{
struct key_params params;
struct wl_wsec_key key;
+ struct wl_priv *wl = wiphy_to_wl(wiphy);
+ struct wl_security *sec;
+ int32 wsec;
int32 err = 0;
#ifdef WL_CFG80211_BACKTRACE
@@ -1801,34 +1831,37 @@ wl_cfg80211_get_key(struct wiphy *wiphy, struct net_device *dev,
memset(&key, 0, sizeof(key));
key.index = key_idx;
- if (unlikely((err = wl_dev_ioctl(dev, WLC_GET_KEY, &key, sizeof(key))))) {
- WL_ERR(("WLC_GET_KEY error (%d)\n", err));
- return err;
- }
swap_key_to_BE(&key);
memset(&params, 0, sizeof(params));
params.key_len = (uint8)MIN(DOT11_MAX_KEY_SIZE, key.len);
memcpy(params.key, key.data, params.key_len);
- switch (key.algo) {
- case CRYPTO_ALGO_WEP1:
- params.cipher = WLAN_CIPHER_SUITE_WEP40;
- WL_DBG(("WLAN_CIPHER_SUITE_WEP40\n"));
- break;
- case CRYPTO_ALGO_WEP128:
- params.cipher = WLAN_CIPHER_SUITE_WEP104;
- WL_DBG(("WLAN_CIPHER_SUITE_WEP104\n"));
+ if (unlikely(err = wl_dev_ioctl(dev, WLC_GET_WSEC, &wsec, sizeof(wsec)))) {
+ WL_ERR(("WLC_GET_WSEC error (%d)\n", err));
+ return err;
+ }
+ wsec = dtoh32(wsec);
+ switch (wsec) {
+ case WEP_ENABLED:
+ sec = wl_read_prof(wl, WL_PROF_SEC);
+ if (sec->cipher_pairwise & WLAN_CIPHER_SUITE_WEP40) {
+ params.cipher = WLAN_CIPHER_SUITE_WEP40;
+ WL_DBG(("WLAN_CIPHER_SUITE_WEP40\n"));
+ } else if (sec->cipher_pairwise & WLAN_CIPHER_SUITE_WEP104) {
+ params.cipher = WLAN_CIPHER_SUITE_WEP104;
+ WL_DBG(("WLAN_CIPHER_SUITE_WEP104\n"));
+ }
break;
- case CRYPTO_ALGO_TKIP:
+ case TKIP_ENABLED:
params.cipher = WLAN_CIPHER_SUITE_TKIP;
WL_DBG(("WLAN_CIPHER_SUITE_TKIP\n"));
break;
- case CRYPTO_ALGO_AES_CCM:
+ case AES_ENABLED:
params.cipher = WLAN_CIPHER_SUITE_AES_CMAC;
WL_DBG(("WLAN_CIPHER_SUITE_AES_CMAC\n"));
break;
default:
- WL_ERR(("Invalid algo (0x%x)\n", key.algo));
+ WL_ERR(("Invalid algo (0x%x)\n", wsec));
return -EINVAL;
}
@@ -1924,7 +1957,36 @@ wl_cfg80211_set_power_mgmt(struct wiphy *wiphy, struct net_device *dev,
return err;
}
+static __used uint32
+wl_find_msb(uint16 bit16)
+{
+ uint32 ret = 0;
+
+ if (bit16 & 0xff00) {
+ ret += 8;
+ bit16 >>= 8;
+ }
+ if (bit16 & 0xf0) {
+ ret += 4;
+ bit16 >>= 4;
+ }
+
+ if (bit16 & 0xc) {
+ ret += 2;
+ bit16 >>= 2;
+ }
+
+ if (bit16 & 2)
+ ret += bit16 & 2;
+ else if (bit16)
+ ret += bit16;
+
+ return ret;
+}
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 33)) || \
+ defined(CHROMIUMOS_COMPAT_WIRELESS)
static int32
wl_cfg80211_set_bitrate_mask(struct wiphy *wiphy, struct net_device *dev,
const uint8 *addr, const struct cfg80211_bitrate_mask *mask)
@@ -1934,8 +1996,68 @@ wl_cfg80211_set_bitrate_mask(struct wiphy *wiphy, struct net_device *dev,
int32 val;
int32 err_bg;
int32 err_a;
+ uint32 legacy;
int32 err = 0;
- int32 i;
+
+#ifdef WL_CFG80211_BACKTRACE
+ WL_DBG(("In\n"));
+#endif
+ CHECK_SYS_UP();
+ /* addr param is always NULL. ignore it */
+ /* Get current rateset */
+ if (unlikely((err = wl_dev_ioctl(dev, WLC_GET_CURR_RATESET, &rateset,
+ sizeof(rateset))))) {
+ WL_ERR(("could not get current rateset (%d)\n", err));
+ return err;
+ }
+
+ rateset.count = dtoh32(rateset.count);
+
+ if (!(legacy = wl_find_msb(mask->control[IEEE80211_BAND_2GHZ].legacy)))
+ legacy = wl_find_msb(mask->control[IEEE80211_BAND_5GHZ].legacy);
+
+ val = wl_g_rates[legacy-1].bitrate * 100000;
+
+ if (val < rateset.count) {
+ /* Select rate by rateset index */
+ rate = rateset.rates[val] & 0x7f;
+ } else {
+ /* Specified rate in bps */
+ rate = val / 500000;
+ }
+
+ WL_DBG(("rate %d mbps\n", (rate/2)));
+
+ /*
+ *
+ * Set rate override,
+ * Since the is a/b/g-blind, both a/bg_rate are enforced.
+ */
+ err_bg = wl_dev_intvar_set(dev, "bg_rate", rate);
+ err_a = wl_dev_intvar_set(dev, "a_rate", rate);
+ if (unlikely(err_bg && err_a)) {
+ WL_ERR(("could not set fixed rate (%d) (%d)\n", err_bg, err_a));
+ return (err_bg | err_a);
+ }
+
+#ifdef WL_CFG80211_BACKTRACE
+ WL_DBG(("Out\n"));
+#endif
+
+ return err;
+}
+#else
+static int32
+wl_cfg80211_set_bitrate_mask(struct wiphy *wiphy, struct net_device *dev,
+ const uint8 *addr, const struct cfg80211_bitrate_mask *mask)
+{
+ struct wl_rateset rateset;
+ int32 rate;
+ int32 val;
+ int32 err_bg;
+ int32 err_a;
+ int32 err = 0;
+ int i;
#ifdef WL_CFG80211_BACKTRACE
WL_DBG(("In\n"));
@@ -2010,6 +2132,7 @@ wl_cfg80211_set_bitrate_mask(struct wiphy *wiphy, struct net_device *dev,
return err;
}
+#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 33)) */
static int32
wl_cfg80211_resume(struct wiphy *wiphy)
@@ -2055,6 +2178,148 @@ wl_cfg80211_suspend(struct wiphy *wiphy)
return err;
}
+static __used int32
+wl_update_pmklist(struct net_device *dev, struct wl_pmk_list *pmk_list, int32 err)
+{
+ int8 eabuf[ETHER_ADDR_STR_LEN];
+ int i, j;
+
+ memset(eabuf, 0, ETHER_ADDR_STR_LEN);
+
+ WL_DBG(("No of elements %d\n", pmk_list->pmkids.npmkid));
+ for (i = 0; i < pmk_list->pmkids.npmkid; i++) {
+ WL_DBG(("PMKID[%d]: %s =\n", i,
+ bcm_ether_ntoa(&pmk_list->pmkids.pmkid[i].BSSID,
+ eabuf)));
+ for (j = 0; j < WPA2_PMKID_LEN; j++) {
+ WL_DBG(("%02x\n", pmk_list->pmkids.pmkid[i].PMKID[j]));
+ }
+ }
+ if (likely(!err)) {
+ err = wl_dev_bufvar_set(dev, "pmkid_info", (char *)pmk_list,
+ sizeof(*pmk_list));
+ }
+
+ return err;
+}
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 33)) || \
+ defined(CHROMIUMOS_COMPAT_WIRELESS)
+static int32
+wl_cfg80211_set_pmksa(struct wiphy *wiphy, struct net_device *dev,
+ struct cfg80211_pmksa *pmksa)
+{
+ struct wl_priv *wl = wiphy_to_wl(wiphy);
+ int8 eabuf[ETHER_ADDR_STR_LEN];
+ int32 err = 0;
+ int i;
+#ifdef WL_CFG80211_BACKTRACE
+ WL_DBG(("In\n"));
+#endif
+
+ CHECK_SYS_UP();
+ memset(eabuf, 0, ETHER_ADDR_STR_LEN);
+ for (i = 0; i < wl->pmk_list->pmkids.npmkid; i++)
+ if (!memcmp(pmksa->bssid, &wl->pmk_list->pmkids.pmkid[i].BSSID,
+ ETHER_ADDR_LEN))
+ break;
+ if (i < WL_NUM_PMKIDS_MAX) {
+ memcpy(&wl->pmk_list->pmkids.pmkid[i].BSSID, pmksa->bssid, ETHER_ADDR_LEN);
+ memcpy(&wl->pmk_list->pmkids.pmkid[i].PMKID, pmksa->pmkid, WPA2_PMKID_LEN);
+ if (i == wl->pmk_list->pmkids.npmkid)
+ wl->pmk_list->pmkids.npmkid++;
+ } else {
+ err = -EINVAL;
+ }
+ WL_DBG(("set_pmksa,IW_PMKSA_ADD - PMKID: %s =\n",
+ bcm_ether_ntoa(&wl->pmk_list->pmkids.pmkid[wl->pmk_list->pmkids.npmkid].BSSID,
+ eabuf)));
+ for (i = 0; i < WPA2_PMKID_LEN; i++) {
+ WL_DBG(("%02x\n",
+ wl->pmk_list->pmkids.pmkid[wl->pmk_list->pmkids.npmkid].PMKID[i]));
+ }
+
+ err = wl_update_pmklist(dev, wl->pmk_list, err);
+
+#ifdef WL_CFG80211_BACKTRACE
+ WL_DBG(("Out\n"));
+#endif
+
+ return err;
+}
+
+static int32
+wl_cfg80211_del_pmksa(struct wiphy *wiphy, struct net_device *dev,
+ struct cfg80211_pmksa *pmksa)
+{
+ struct wl_priv *wl = wiphy_to_wl(wiphy);
+ int8 eabuf[ETHER_ADDR_STR_LEN];
+ struct _pmkid_list pmkid;
+ int32 err = 0;
+ int i;
+
+#ifdef WL_CFG80211_BACKTRACE
+ WL_DBG(("In\n"));
+#endif
+
+ CHECK_SYS_UP();
+ memset(eabuf, 0, ETHER_ADDR_STR_LEN);
+ memcpy(&pmkid.pmkid[0].BSSID, pmksa->bssid, ETHER_ADDR_LEN);
+ memcpy(&pmkid.pmkid[0].PMKID, pmksa->pmkid, WPA2_PMKID_LEN);
+
+ WL_DBG(("del_pmksa,IW_PMKSA_REMOVE - PMKID: %s =\n",
+ bcm_ether_ntoa(&pmkid.pmkid[0].BSSID, eabuf)));
+ for (i = 0; i < WPA2_PMKID_LEN; i++) {
+ WL_DBG(("%02x\n", pmkid.pmkid[0].PMKID[i]));
+ }
+
+ for (i = 0; i < wl->pmk_list->pmkids.npmkid; i++)
+ if (!memcmp(pmksa->bssid, &wl->pmk_list->pmkids.pmkid[i].BSSID, ETHER_ADDR_LEN))
+ break;
+
+ if ((wl->pmk_list->pmkids.npmkid > 0) && (i < wl->pmk_list->pmkids.npmkid)) {
+ memset(&wl->pmk_list->pmkids.pmkid[i], 0, sizeof(pmkid_t));
+ for (; i < (wl->pmk_list->pmkids.npmkid - 1); i++) {
+ memcpy(&wl->pmk_list->pmkids.pmkid[i].BSSID,
+ &wl->pmk_list->pmkids.pmkid[i+1].BSSID, ETHER_ADDR_LEN);
+ memcpy(&wl->pmk_list->pmkids.pmkid[i].PMKID,
+ &wl->pmk_list->pmkids.pmkid[i+1].PMKID, WPA2_PMKID_LEN);
+ }
+ wl->pmk_list->pmkids.npmkid--;
+ }
+ else {
+ err = -EINVAL;
+ }
+
+ err = wl_update_pmklist(dev, wl->pmk_list, err);
+
+#ifdef WL_CFG80211_BACKTRACE
+ WL_DBG(("Out\n"));
+#endif
+ return err;
+
+}
+
+static int32
+wl_cfg80211_flush_pmksa(struct wiphy *wiphy, struct net_device *dev)
+{
+ struct wl_priv *wl = wiphy_to_wl(wiphy);
+ int32 err = 0;
+
+#ifdef WL_CFG80211_BACKTRACE
+ WL_DBG(("In\n"));
+#endif
+ CHECK_SYS_UP();
+ memset(wl->pmk_list, 0, sizeof(*wl->pmk_list));
+ err = wl_update_pmklist(dev, wl->pmk_list, err);
+#ifdef WL_CFG80211_BACKTRACE
+ WL_DBG(("Out\n"));
+#endif
+ return err;
+
+}
+#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 33)) */
+
static struct cfg80211_ops wl_cfg80211_ops = {
.change_virtual_intf = wl_cfg80211_change_iface,
.scan = wl_cfg80211_scan,
@@ -2075,6 +2340,12 @@ static struct cfg80211_ops wl_cfg80211_ops = {
.disconnect = wl_cfg80211_disconnect,
.suspend = wl_cfg80211_suspend,
.resume = wl_cfg80211_resume,
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 33)) || \
+ defined(CHROMIUMOS_COMPAT_WIRELESS)
+ .set_pmksa = wl_cfg80211_set_pmksa,
+ .del_pmksa = wl_cfg80211_del_pmksa,
+ .flush_pmksa = wl_cfg80211_flush_pmksa
+#endif
};
static int32
@@ -2122,7 +2393,8 @@ wl_alloc_wdev(int32 sizeof_iface, struct device *dev)
}
set_wiphy_dev(wdev->wiphy, dev);
wdev->wiphy->max_scan_ssids = WL_NUM_SCAN_MAX;
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 33))
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 33)) || \
+ defined(CHROMIUMOS_COMPAT_WIRELESS)
wdev->wiphy->max_num_pmkids = WL_NUM_PMKIDS_MAX;
#endif
wdev->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION)| BIT(NL80211_IFTYPE_ADHOC);
@@ -2136,10 +2408,22 @@ wl_alloc_wdev(int32 sizeof_iface, struct device *dev)
wdev->wiphy->cipher_suites = __wl_cipher_suites;
wdev->wiphy->n_cipher_suites = ARRAY_SIZE(__wl_cipher_suites);
#ifndef WL_POWERSAVE_DISABLED
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 33)) || \
+ defined(CHROMIUMOS_COMPAT_WIRELESS)
+ wdev->wiphy->flags |= WIPHY_FLAG_PS_ON_BY_DEFAULT; /* enable power
+ * save mode by default
+ */
+#else
wdev->wiphy->ps_default = TRUE; /* enable power save mode by default */
+#endif
+#else
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 33)) || \
+ defined(CHROMIUMOS_COMPAT_WIRELESS)
+ wdev->wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT;
#else
wdev->wiphy->ps_default = FALSE;
#endif
+#endif /* !WL_POWERSAVE_DISABLED */
if (unlikely(((err = wiphy_register(wdev->wiphy)) < 0))) {
WL_ERR(("Couldn not register wiphy device (%d)\n", err));
goto wiphy_register_out;
@@ -2185,8 +2469,8 @@ wl_inform_bss(struct wl_priv *wl)
{
struct wl_scan_results *bss_list;
struct wl_bss_info *bi = NULL; /* must be initialized */
- int32 i;
int32 err = 0;
+ int i;
bss_list = wl->bss_list;
@@ -2268,7 +2552,7 @@ wl_inform_single_bss(struct wl_priv *wl, struct wl_bss_info *bi)
}
static bool
-wl_is_linkup(struct wl_priv *wl, wl_event_msg_t *e)
+wl_is_linkup(struct wl_priv *wl, const wl_event_msg_t *e)
{
uint32 event = ntoh32(e->event_type);
uint16 flags = ntoh16(e->flags);
@@ -2290,7 +2574,7 @@ wl_is_linkup(struct wl_priv *wl, wl_event_msg_t *e)
}
static bool
-wl_is_linkdown(struct wl_priv *wl, wl_event_msg_t *e)
+wl_is_linkdown(struct wl_priv *wl, const wl_event_msg_t *e)
{
uint32 event = ntoh32(e->event_type);
uint16 flags = ntoh16(e->flags);
@@ -2307,7 +2591,8 @@ wl_is_linkdown(struct wl_priv *wl, wl_event_msg_t *e)
}
static int32
-wl_notify_connect_status(struct wl_priv *wl, struct net_device *ndev, wl_event_msg_t *e, void* data)
+wl_notify_connect_status(struct wl_priv *wl, struct net_device *ndev,
+ const wl_event_msg_t *e, void* data)
{
bool act;
int32 err = 0;
@@ -2341,7 +2626,8 @@ wl_notify_connect_status(struct wl_priv *wl, struct net_device *ndev, wl_event_m
}
static int32
-wl_notify_roaming_status(struct wl_priv *wl, struct net_device *ndev, wl_event_msg_t *e, void* data)
+wl_notify_roaming_status(struct wl_priv *wl, struct net_device *ndev,
+ const wl_event_msg_t *e, void* data)
{
bool act;
int32 err = 0;
@@ -2359,18 +2645,27 @@ wl_notify_roaming_status(struct wl_priv *wl, struct net_device *ndev, wl_event_m
return err;
}
+static __used int32
+wl_dev_bufvar_set(struct net_device *dev, int8 *name, int8 *buf, int32 len)
+{
+ struct wl_priv *wl = ndev_to_wl(dev);
+ uint32 buflen;
+
+ buflen = bcm_mkiovar(name, buf, len, wl->ioctl_buf, WL_IOCTL_LEN_MAX);
+ BUG_ON(unlikely(!buflen));
+
+ return (wl_dev_ioctl(dev, WLC_SET_VAR, wl->ioctl_buf, buflen));
+}
+
static int32
-wl_dev_bufvar_get(
- struct net_device *dev,
- int8 *name,
- int8 *buf, int32 buf_len)
+wl_dev_bufvar_get(struct net_device *dev, int8 *name, int8 *buf, int32 buf_len)
{
struct wl_priv *wl = ndev_to_wl(dev);
uint32 len;
int32 err = 0;
len = bcm_mkiovar(name, NULL, 0, wl->ioctl_buf, WL_IOCTL_LEN_MAX);
- ASSERT(len);
+ BUG_ON(unlikely(!len));
if (unlikely((err = wl_dev_ioctl(dev, WLC_GET_VAR, (void *)wl->ioctl_buf,
WL_IOCTL_LEN_MAX)))) {
WL_ERR(("error (%d)\n", err));
@@ -2479,7 +2774,8 @@ update_bss_info_out:
}
static int32
-wl_bss_roaming_done(struct wl_priv *wl, struct net_device *ndev, wl_event_msg_t *e, void* data)
+wl_bss_roaming_done(struct wl_priv *wl, struct net_device *ndev,
+ const wl_event_msg_t *e, void* data)
{
struct wl_connect_info *conn_info = wl_to_conn(wl);
int32 err = 0;
@@ -2506,7 +2802,8 @@ wl_bss_roaming_done(struct wl_priv *wl, struct net_device *ndev, wl_event_msg_t
}
static int32
-wl_bss_connect_done(struct wl_priv *wl, struct net_device *ndev, wl_event_msg_t *e, void* data)
+wl_bss_connect_done(struct wl_priv *wl, struct net_device *ndev,
+ const wl_event_msg_t *e, void* data)
{
struct wl_connect_info *conn_info = wl_to_conn(wl);
int32 err = 0;
@@ -2542,7 +2839,34 @@ wl_bss_connect_done(struct wl_priv *wl, struct net_device *ndev, wl_event_msg_t
}
static int32
-wl_notify_scan_status(struct wl_priv *wl, struct net_device *ndev, wl_event_msg_t *e, void* data)
+wl_notify_mic_status(struct wl_priv *wl, struct net_device *ndev,
+ const wl_event_msg_t *e, void* data)
+{
+ uint16 flags = ntoh16(e->flags);
+ enum nl80211_key_type key_type;
+
+#ifdef WL_CFG80211_BACKTRACE
+ WL_DBG(("In\n"));
+#endif
+
+ rtnl_lock();
+ if (flags & WLC_EVENT_MSG_GROUP)
+ key_type = NL80211_KEYTYPE_GROUP;
+ else
+ key_type = NL80211_KEYTYPE_PAIRWISE;
+
+ cfg80211_michael_mic_failure(ndev, (uint8 *)&e->addr, key_type, -1, NULL, GFP_KERNEL);
+ rtnl_unlock();
+
+#ifdef WL_CFG80211_BACKTRACE
+ WL_DBG(("Out\n"));
+#endif
+ return 0;
+}
+
+static int32
+wl_notify_scan_status(struct wl_priv *wl, struct net_device *ndev,
+ const wl_event_msg_t *e, void* data)
{
struct channel_info channel_inform;
struct wl_scan_results *bss_list;
@@ -2631,6 +2955,7 @@ wl_init_eloop_handler(struct wl_event_loop *el)
el->handler[WLC_E_ASSOC_IND] = wl_notify_connect_status;
el->handler[WLC_E_REASSOC_IND] = wl_notify_connect_status;
el->handler[WLC_E_ROAM] = wl_notify_roaming_status;
+ el->handler[WLC_E_MIC_ERROR] = wl_notify_mic_status;
}
static int32
@@ -2681,6 +3006,11 @@ wl_init_priv_mem(struct wl_priv *wl)
WL_ERR(("fw object alloc failed\n"));
goto init_priv_mem_out;
}
+ wl->pmk_list = (void *)kzalloc(sizeof(*wl->pmk_list), GFP_KERNEL);
+ if (unlikely(!wl->pmk_list)) {
+ WL_ERR(("pmk list alloc failed\n"));
+ goto init_priv_mem_out;
+ }
return 0;
@@ -2729,6 +3059,10 @@ wl_deinit_priv_mem(struct wl_priv *wl)
kfree(wl->fw);
wl->fw = NULL;
}
+ if (wl->pmk_list) {
+ kfree(wl->pmk_list);
+ wl->pmk_list = NULL;
+ }
}
@@ -3048,7 +3382,12 @@ wl_init_priv(struct wl_priv *wl)
WL_DBG(("In\n"));
#endif
wl->scan_request = NULL;
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 33)) || \
+ defined(CHROMIUMOS_COMPAT_WIRELESS)
+ wl->pwr_save = !!(wiphy->flags & WIPHY_FLAG_PS_ON_BY_DEFAULT);
+#else
wl->pwr_save = wiphy->ps_default;
+#endif
#ifndef WL_ISCAN_DISABLED
wl->iscan_on = TRUE; /* iscan on & off switch. we enable iscan per default */
#else
@@ -3213,7 +3552,7 @@ wl_event_handler(void *data)
}
void
-wl_cfg80211_event(struct net_device *ndev, wl_event_msg_t *e, void* data)
+wl_cfg80211_event(struct net_device *ndev, const wl_event_msg_t *e, void* data)
{
uint32 event_type = ntoh32(e->event_type);
struct wl_priv *wl = ndev_to_wl(ndev);
@@ -3271,7 +3610,7 @@ wl_deq_event(struct wl_priv *wl)
*/
static int32
-wl_enq_event(struct wl_priv *wl, uint32 event, wl_event_msg_t *msg, void *data)
+wl_enq_event(struct wl_priv *wl, uint32 event, const wl_event_msg_t *msg, void *data)
{
struct wl_event_q *e;
int32 err = 0;
@@ -3544,7 +3883,7 @@ static int32
wl_pattern_atoh(int8 *src, int8 *dst)
{
#define strtoul(nptr, endptr, base) bcm_strtoul((nptr), (endptr), (base))
- int32 i;
+ int i;
if (strncmp(src, "0x", 2) != 0 &&
strncmp(src, "0X", 2) != 0) {
WL_ERR(("Mask invalid format. Needs to start with 0x\n"));
@@ -3847,7 +4186,7 @@ wl_read_prof(struct wl_priv *wl, int32 item)
}
static int32
-wl_update_prof(struct wl_priv *wl, wl_event_msg_t *e, void *data, int32 item)
+wl_update_prof(struct wl_priv *wl, const wl_event_msg_t *e, void *data, int32 item)
{
int32 err = 0;
struct wlc_ssid *ssid;
diff --git a/bcm4329/src/wl/sys/wl_cfg80211.h b/bcm4329/src/wl/sys/wl_cfg80211.h
index 79c7cf9..2722699 100644
--- a/bcm4329/src/wl/sys/wl_cfg80211.h
+++ b/bcm4329/src/wl/sys/wl_cfg80211.h
@@ -21,7 +21,7 @@
* software in any way with any other Broadcom software provided under a license
* other than the GPL, without Broadcom's express prior written consent.
*
- * $Id: wl_cfg80211.h,v 1.1.2.17 2010/04/13 04:45:43 Exp $
+ * $Id: wl_cfg80211.h,v 1.1.2.19 2010/05/04 21:21:00 Exp $
*/
#ifndef _wl_cfg80211_h_
@@ -96,11 +96,14 @@ struct wl_ibss;
#define WL_SCAN_RETRY_MAX 3 /* used for ibss scan */
#define WL_NUM_SCAN_MAX 1
-#define WL_NUM_PMKIDS_MAX 4 /* will be used for 2.6.33 kernel or later */
+#define WL_NUM_PMKIDS_MAX MAXPMKID /* will be used for 2.6.33 kernel
+ * or later
+ */
#define WL_SCAN_BUF_MAX (1024 * 8)
#define WL_TLV_INFO_MAX 1024
#define WL_BSS_INFO_MAX 2048
-#define WL_ASSOC_INFO_MAX 512 /* needs to grab assoc info from dongle to
+#define WL_ASSOC_INFO_MAX 512 /*
+ * needs to grab assoc info from dongle to
* report it to cfg80211 through "connect"
* event
*/
@@ -169,7 +172,7 @@ struct wl_conf {
/* cfg80211 main event loop */
struct wl_event_loop {
int32 (*handler[WLC_E_LAST])(struct wl_priv *wl, struct net_device *ndev,
- wl_event_msg_t *e, void *data);
+ const wl_event_msg_t *e, void *data);
};
/* representing interface of cfg80211 plane */
@@ -282,6 +285,12 @@ struct wl_assoc_ielen {
uint32 resp_len;
};
+/* wpa2 pmk list */
+struct wl_pmk_list {
+ pmkid_list_t pmkids;
+ pmkid_t foo[MAXPMKID-1];
+};
+
/* dongle private data of cfg80211 interface */
struct wl_priv {
@@ -300,12 +309,13 @@ struct wl_priv {
struct ether_addr bssid; /* bssid of currently engaged network */
struct semaphore event_sync; /* for synchronization of main event thread */
struct completion event_exit;
- int32 event_pid; /* pid of main event handler thread */
- ulong status; /* current dongle status */
struct wl_profile *profile; /* holding dongle profile */
struct wl_iscan_ctrl *iscan; /* iscan controller */
struct wl_connect_info conn_info; /* association information container */
struct wl_fw_ctrl *fw; /* control firwmare / nvram paramter downloading */
+ struct wl_pmk_list *pmk_list; /* wpa2 pmk list */
+ int32 event_pid; /* pid of main event handler thread */
+ ulong status; /* current dongle status */
void * pub;
uint32 channel; /* current channel */
bool iscan_on; /* iscan on/off switch */
@@ -316,6 +326,7 @@ struct wl_priv {
bool pwr_save; /* indicate whether dongle to support power save mode */
bool dongle_up; /* indicate whether dongle up or not */
bool roam_on; /* on/off switch for dongle self-roaming */
+ bool scan_tried; /* indicates if first scan attempted */
uint8 *ioctl_buf; /* ioctl buffer */
uint8 *extra_buf; /* maily to grab assoc information */
uint8 ci[0] __attribute__((__aligned__(NETDEV_ALIGN)));
@@ -347,7 +358,7 @@ inline static struct wl_bss_info * next_bss(struct wl_scan_results *list,
extern int32 wl_cfg80211_attach(struct net_device *ndev, void *data);
extern void wl_cfg80211_detach(void);
/* event handler from dongle */
-extern void wl_cfg80211_event(struct net_device *ndev, wl_event_msg_t *e, void* data);
+extern void wl_cfg80211_event(struct net_device *ndev, const wl_event_msg_t *e, void* data);
extern void wl_cfg80211_sdio_func(void *func); /* set sdio function info */
extern int32 wl_cfg80211_up(void); /* dongle up */
extern int32 wl_cfg80211_down(void); /* dongle down */
diff --git a/bcm4329/src/wl/sys/wl_iw.c b/bcm4329/src/wl/sys/wl_iw.c
index ad138bf..ec52705 100644
--- a/bcm4329/src/wl/sys/wl_iw.c
+++ b/bcm4329/src/wl/sys/wl_iw.c
@@ -21,9 +21,10 @@
* 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.104.2.1 2010/05/18 00:12:00 Exp $
+ * $Id: wl_iw.c,v 1.51.4.9.2.6.4.116 2010/07/08 00:51:57 Exp $
*/
+#include <wlioctl.h>
#include <typedefs.h>
#include <linuxver.h>
@@ -58,7 +59,32 @@ typedef const struct si_pub si_t;
-#define IW_WSEC_ENABLED(wsec) ((wsec) & (WEP_ENABLED | TKIP_ENABLED | AES_ENABLED))
+#ifndef IW_ENCODE_ALG_SM4
+#define IW_ENCODE_ALG_SM4 0x20
+#endif
+
+#ifndef IW_AUTH_WAPI_ENABLED
+#define IW_AUTH_WAPI_ENABLED 0x20
+#endif
+
+#ifndef IW_AUTH_WAPI_VERSION_1
+#define IW_AUTH_WAPI_VERSION_1 0x00000008
+#endif
+
+#ifndef IW_AUTH_CIPHER_SMS4
+#define IW_AUTH_CIPHER_SMS4 0x00000020
+#endif
+
+#ifndef IW_AUTH_KEY_MGMT_WAPI_PSK
+#define IW_AUTH_KEY_MGMT_WAPI_PSK 4
+#endif
+
+#ifndef IW_AUTH_KEY_MGMT_WAPI_CERT
+#define IW_AUTH_KEY_MGMT_WAPI_CERT 8
+#endif
+
+
+#define IW_WSEC_ENABLED(wsec) ((wsec) & (WEP_ENABLED | TKIP_ENABLED | AES_ENABLED | SMS4_ENABLED))
#include <linux/rtnetlink.h>
@@ -66,6 +92,10 @@ typedef const struct si_pub si_t;
#define ENABLE_ACTIVE_PASSIVE_SCAN_SUPPRESS 1
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)) && 1
+ struct mutex g_wl_ss_scan_lock;
+#endif
+
#if defined(SOFTAP)
#define WL_SOFTAP(x) printk x
static struct net_device *priv_dev;
@@ -135,6 +165,8 @@ static wl_iw_ss_cache_ctrl_t g_ss_cache_ctrl;
static volatile uint g_first_broadcast_scan;
+
+
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0))
#define DAEMONIZE(a) daemonize(a); \
allow_signal(SIGKILL); \
@@ -149,8 +181,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
@@ -178,8 +212,12 @@ 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
+
} iscan_info_t;
#define COEX_DHCP 1
static void wl_iw_bt_flag_set(struct net_device *dev, bool set);
@@ -283,7 +321,7 @@ dev_wlc_ioctl(
return ret;
}
- WL_TRACE(("\n%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));
memset(&ioc, 0, sizeof(ioc));
ioc.cmd = cmd;
@@ -382,6 +420,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));
}
@@ -561,6 +602,7 @@ wl_iw_get_macaddr(
}
+
static int
wl_iw_set_country(
struct net_device *dev,
@@ -964,16 +1006,18 @@ 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;
-#endif
+#endif
#if defined(BCMLXSDMMC)
sdioh_stop(NULL);
@@ -1006,6 +1050,7 @@ 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);
@@ -1013,6 +1058,7 @@ wl_iw_control_wl_on(
#else
wl_iw_iscan_set_scan_broadcast_prep(dev, 0);
#endif
+#endif
WL_TRACE(("Exited %s \n", __FUNCTION__));
@@ -1568,8 +1614,10 @@ wl_iw_get_range(
list->count = htod32(MAXCHANNEL);
- if ((error = dev_wlc_ioctl(dev, WLC_GET_VALID_CHANNELS, channels, (MAXCHANNEL+1)*4)))
+ if ((error = dev_wlc_ioctl(dev, WLC_GET_VALID_CHANNELS, channels, (MAXCHANNEL+1)*4))) {
+ kfree(channels);
return error;
+ }
for (i = 0; i < dtoh32(list->count) && i < IW_MAX_FREQUENCIES; i++) {
range->freq[i].i = dtoh32(list->element[i]);
@@ -1603,8 +1651,10 @@ wl_iw_get_range(
#endif
- if ((error = dev_wlc_ioctl(dev, WLC_GET_CURR_RATESET, &rateset, sizeof(rateset))))
+ if ((error = dev_wlc_ioctl(dev, WLC_GET_CURR_RATESET, &rateset, sizeof(rateset)))) {
+ kfree(channels);
return error;
+ }
rateset.count = dtoh32(rateset.count);
range->num_bitrates = rateset.count;
for (i = 0; i < rateset.count && i < IW_MAX_BITRATES; i++)
@@ -1640,8 +1690,10 @@ wl_iw_get_range(
}
- if ((error = dev_wlc_ioctl(dev, WLC_GET_PHYTYPE, &i, sizeof(i))))
+ if ((error = dev_wlc_ioctl(dev, WLC_GET_PHYTYPE, &i, sizeof(i)))) {
+ kfree(channels);
return error;
+ }
i = dtoh32(i);
if (i == WLC_PHY_TYPE_A)
range->throughput = 24000000;
@@ -1715,6 +1767,8 @@ wl_iw_get_range(
#endif
#endif
+ kfree(channels);
+
return 0;
}
@@ -2088,7 +2142,7 @@ wl_iw_iscan(iscan_info_t *iscan, wlc_ssid_t *ssid, uint16 action)
return -ENOMEM;
}
memset(params, 0, params_size);
- ASSERT(params_size < WLC_IOCTL_SMLEN);
+ ASSERT(params_size < sizeof(iscan->ioctlbuf));
err = wl_iw_iscan_prep(&params->params, ssid);
@@ -2099,7 +2153,7 @@ wl_iw_iscan(iscan_info_t *iscan, wlc_ssid_t *ssid, uint16 action)
(void) dev_iw_iovar_setbuf(iscan->dev, "iscan", params, params_size,
- iscan->ioctlbuf, WLC_IOCTL_SMLEN);
+ iscan->ioctlbuf, sizeof(iscan->ioctlbuf));
}
kfree(params);
@@ -2141,6 +2195,7 @@ wl_iw_iscan_get(iscan_info_t *iscan)
uint32 status;
+ MUTEX_LOCK_WL_SCAN_SET();
if (iscan->list_cur) {
buf = iscan->list_cur;
iscan->list_cur = buf->next;
@@ -2150,6 +2205,7 @@ wl_iw_iscan_get(iscan_info_t *iscan)
if (!buf) {
WL_ERROR(("%s can't alloc iscan_buf_t : going to abort currect iscan\n", \
__FUNCTION__));
+ MUTEX_UNLOCK_WL_SCAN_SET();
return WL_SCAN_RESULTS_NO_MEM;
}
buf->next = NULL;
@@ -2186,6 +2242,7 @@ wl_iw_iscan_get(iscan_info_t *iscan)
WL_TRACE(("results->buflen = %d\n", results->buflen));
status = dtoh32(list_buf->status);
+ MUTEX_UNLOCK_WL_SCAN_SET();
return status;
}
@@ -2211,8 +2268,10 @@ static void wl_iw_send_scan_complete(iscan_info_t *iscan)
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
}
@@ -2307,6 +2366,7 @@ _iscan_sysioc_thread(void *data)
}
#endif
+#if !defined(CSCAN)
static void
wl_iw_set_ss_cache_timer_flag(void)
@@ -2346,6 +2406,7 @@ wl_iw_free_ss_cache(void)
WL_TRACE(("%s called\n", __FUNCTION__));
+ MUTEX_LOCK_WL_SCAN_SET();
spec_scan_head = &g_ss_cache_ctrl.m_cache_head;
node = *spec_scan_head;
@@ -2356,6 +2417,7 @@ wl_iw_free_ss_cache(void)
kfree(cur);
}
*spec_scan_head = NULL;
+ MUTEX_UNLOCK_WL_SCAN_SET();
}
@@ -2401,6 +2463,7 @@ wl_iw_reset_ss_cache(void)
wl_iw_ss_cache_t *node, *prev, *cur;
wl_iw_ss_cache_t **spec_scan_head;
+ MUTEX_LOCK_WL_SCAN_SET();
spec_scan_head = &g_ss_cache_ctrl.m_cache_head;
node = *spec_scan_head;
prev = node;
@@ -2427,7 +2490,7 @@ wl_iw_reset_ss_cache(void)
prev = node;
node = node->next;
}
-
+ MUTEX_UNLOCK_WL_SCAN_SET();
}
@@ -2440,13 +2503,13 @@ wl_iw_add_bss_to_ss_cache(wl_scan_results_t *ss_list)
wl_bss_info_t *bi = NULL;
int i;
- spec_scan_head = &g_ss_cache_ctrl.m_cache_head;
if (!ss_list->count) {
return 0;
}
-
+ MUTEX_LOCK_WL_SCAN_SET();
+ spec_scan_head = &g_ss_cache_ctrl.m_cache_head;
for (i = 0; i < ss_list->count; i++) {
node = *spec_scan_head;
@@ -2469,17 +2532,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_SCAN_SET();
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;
@@ -2493,6 +2551,7 @@ wl_iw_add_bss_to_ss_cache(wl_scan_results_t *ss_list)
prev->next = leaf;
}
}
+ MUTEX_UNLOCK_WL_SCAN_SET();
return 0;
}
@@ -2505,6 +2564,7 @@ __u16 *merged_len)
wl_iw_ss_cache_t *node;
wl_scan_results_t *list_merge;
+ MUTEX_LOCK_WL_SCAN_SET();
node = g_ss_cache_ctrl.m_cache_head;
for (;node;) {
list_merge = (wl_scan_results_t *)node;
@@ -2519,6 +2579,7 @@ __u16 *merged_len)
}
node = node->next;
}
+ MUTEX_UNLOCK_WL_SCAN_SET();
return 0;
}
@@ -2530,6 +2591,7 @@ wl_iw_delete_bss_from_ss_cache(void *addr)
wl_iw_ss_cache_t *node, *prev;
wl_iw_ss_cache_t **spec_scan_head;
+ MUTEX_LOCK_WL_SCAN_SET();
spec_scan_head = &g_ss_cache_ctrl.m_cache_head;
node = *spec_scan_head;
prev = node;
@@ -2552,10 +2614,12 @@ wl_iw_delete_bss_from_ss_cache(void *addr)
}
memset(addr, 0, ETHER_ADDR_LEN);
+ MUTEX_UNLOCK_WL_SCAN_SET();
return 0;
}
+#endif
static int
@@ -2570,6 +2634,11 @@ wl_iw_set_scan(
WL_TRACE(("\n:%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) {
@@ -2637,6 +2706,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;
@@ -2646,6 +2716,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;
}
+#endif
memset(&ssid, 0, sizeof(ssid));
@@ -2689,6 +2760,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) {
@@ -2724,12 +2800,14 @@ 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);
@@ -2800,6 +2878,32 @@ ie_is_wps_ie(uint8 **wpsie, uint8 **tlvs, int *tlvs_len)
}
#endif
+static inline int _wpa_snprintf_hex(char *buf, size_t buf_size, const u8 *data,
+ size_t len, int uppercase)
+{
+ size_t i;
+ char *pos = buf, *end = buf + buf_size;
+ int ret;
+ if (buf_size == 0)
+ return 0;
+ for (i = 0; i < len; i++) {
+ ret = snprintf(pos, end - pos, uppercase ? "%02X" : "%02x",
+ data[i]);
+ if (ret < 0 || ret >= end - pos) {
+ end[-1] = '\0';
+ return pos - buf;
+ }
+ pos += ret;
+ }
+ end[-1] = '\0';
+ return pos - buf;
+}
+
+
+int wpa_snprintf_hex(char *buf, size_t buf_size, const u8 *data, size_t len)
+{
+ return _wpa_snprintf_hex(buf, buf_size, data, len, 0);
+}
static int
wl_iw_handle_scanresults_ies(char **event_p, char *end,
@@ -2808,6 +2912,8 @@ wl_iw_handle_scanresults_ies(char **event_p, char *end,
#if WIRELESS_EXT > 17
struct iw_event iwe;
char *event;
+ char *buf;
+ int custom_event_len;
event = *event_p;
if (bi->ie_length) {
@@ -2846,6 +2952,35 @@ wl_iw_handle_scanresults_ies(char **event_p, char *end,
}
}
+ ptr = ((uint8 *)bi) + sizeof(wl_bss_info_t);
+ ptr_len = bi->ie_length;
+
+ while ((ie = bcm_parse_tlvs(ptr, ptr_len, DOT11_MNG_WAPI_ID))) {
+ WL_TRACE(("%s: found a WAPI IE...\n", __FUNCTION__));
+#ifdef WAPI_IE_USE_GENIE
+ iwe.cmd = IWEVGENIE;
+ iwe.u.data.length = ie->len + 2;
+ event = IWE_STREAM_ADD_POINT(info, event, end, &iwe, (char *)ie);
+#else
+ iwe.cmd = IWEVCUSTOM;
+ custom_event_len = strlen("wapi_ie=") + 2*(ie->len + 2);
+ iwe.u.data.length = custom_event_len;
+
+ buf = kmalloc(custom_event_len+1, GFP_KERNEL);
+ if (buf == NULL)
+ {
+ WL_ERROR(("malloc(%d) returned NULL...\n", custom_event_len));
+ break;
+ }
+
+ memcpy(buf, "wapi_ie=", 8);
+ wpa_snprintf_hex(buf + 8, 2+1, &(ie->id), 1);
+ wpa_snprintf_hex(buf + 10, 2+1, &(ie->len), 1);
+ wpa_snprintf_hex(buf + 12, 2*ie->len+1, ie->data, ie->len);
+ event = IWE_STREAM_ADD_POINT(info, event, end, &iwe, buf);
+#endif
+ break;
+ }
*event_p = event;
}
#endif
@@ -2971,12 +3106,16 @@ 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));
@@ -2992,6 +3131,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;
@@ -3009,6 +3149,7 @@ wl_iw_get_scan(
else {
g_ss_cache_ctrl.m_cons_br_scan_cnt++;
}
+#endif
@@ -3046,12 +3187,16 @@ wl_iw_get_scan(
return -EINVAL;
}
+#if !defined(CSCAN)
if (g_scan_specified_ssid) {
wl_iw_add_bss_to_ss_cache(list);
kfree(list);
}
+#endif
+#if !defined(CSCAN)
+ MUTEX_LOCK_WL_SCAN_SET();
#if defined(WL_IW_USE_ISCAN)
if (g_scan_specified_ssid)
WL_TRACE(("%s: Specified scan APs from scan=%d\n", __FUNCTION__, list->count));
@@ -3071,6 +3216,7 @@ wl_iw_get_scan(
list_merge = (wl_scan_results_t *) g_scan;
len_ret = (__u16) wl_iw_get_scan_prep(list_merge, info, extra, buflen_from_user);
#endif
+ MUTEX_UNLOCK_WL_SCAN_SET();
if (g_ss_cache_ctrl.m_link_down) {
wl_iw_delete_bss_from_ss_cache(g_ss_cache_ctrl.m_active_bssid);
@@ -3080,6 +3226,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);
+ }
+#endif
#if defined(WL_IW_USE_ISCAN)
@@ -3114,8 +3292,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));
@@ -3131,11 +3311,13 @@ 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__));
@@ -3144,6 +3326,7 @@ wl_iw_iscan_get_scan(
+#if !defined(CSCAN)
if (g_ss_cache_ctrl.m_timer_expired) {
wl_iw_free_ss_cache();
g_ss_cache_ctrl.m_timer_expired ^= 1;
@@ -3164,6 +3347,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;
@@ -3262,6 +3446,7 @@ 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;
@@ -3269,6 +3454,7 @@ wl_iw_iscan_get_scan(
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));
@@ -3937,11 +4123,21 @@ wl_iw_set_wpaie(
char *extra
)
{
+ uchar buf[WLC_IOCTL_SMLEN] = {0};
+ uchar *p = buf;
+ int wapi_ie_size;
WL_TRACE(("%s: SIOCSIWGENIE\n", dev->name));
CHECK_EXTRA_FOR_NULL(extra);
+ if (extra[0] == DOT11_MNG_WAPI_ID)
+ {
+ wapi_ie_size = iwp->length;
+ memcpy(p, extra, iwp->length);
+ dev_wlc_bufvar_set(dev, "wapiie", buf, wapi_ie_size);
+ }
+ else
dev_wlc_bufvar_set(dev, "wpaie", extra, iwp->length);
return 0;
@@ -4058,6 +4254,12 @@ wl_iw_set_encodeext(
case IW_ENCODE_ALG_CCMP:
key.algo = CRYPTO_ALGO_AES_CCM;
break;
+ case IW_ENCODE_ALG_SM4:
+ key.algo = CRYPTO_ALGO_SMS4;
+ if (iwe->ext_flags & IW_ENCODE_EXT_GROUP_KEY) {
+ key.flags &= ~WL_PRIMARY_KEY;
+ }
+ break;
default:
break;
}
@@ -4243,6 +4445,8 @@ wl_iw_set_wpaauth(
else if (paramval & IW_AUTH_WPA_VERSION_WPA2)
val = WPA2_AUTH_PSK | WPA2_AUTH_UNSPECIFIED;
#endif
+ else if (paramval & IW_AUTH_WAPI_VERSION_1)
+ val = WPA_AUTH_WAPI;
WL_INFORM(("%s: %d: setting wpa_auth to 0x%0x\n", __FUNCTION__, __LINE__, val));
if ((error = dev_wlc_intvar_set(dev, "wpa_auth", val)))
return error;
@@ -4257,6 +4461,8 @@ wl_iw_set_wpaauth(
val = TKIP_ENABLED;
if (paramval & IW_AUTH_CIPHER_CCMP)
val = AES_ENABLED;
+ if (paramval & IW_AUTH_CIPHER_SMS4)
+ val = SMS4_ENABLED;
if (paramid == IW_AUTH_CIPHER_PAIRWISE) {
iw->pwsec = val;
@@ -4304,6 +4510,8 @@ wl_iw_set_wpaauth(
val = WPA2_AUTH_UNSPECIFIED;
}
#endif
+ if (paramval & (IW_AUTH_KEY_MGMT_WAPI_PSK | IW_AUTH_KEY_MGMT_WAPI_CERT))
+ val = WPA_AUTH_WAPI;
WL_INFORM(("%s: %d: setting wpa_auth to %d\n", __FUNCTION__, __LINE__, val));
if ((error = dev_wlc_intvar_set(dev, "wpa_auth", val)))
return error;
@@ -4391,6 +4599,24 @@ wl_iw_set_wpaauth(
break;
}
#endif
+ case IW_AUTH_WAPI_ENABLED:
+ if ((error = dev_wlc_intvar_get(dev, "wsec", &val)))
+ return error;
+ if (paramval) {
+ val |= SMS4_ENABLED;
+ if ((error = dev_wlc_intvar_set(dev, "wsec", val))) {
+ WL_ERROR(("%s: setting wsec to 0x%0x returned error %d\n",
+ __FUNCTION__, val, error));
+ return error;
+ }
+ if ((error = dev_wlc_intvar_set(dev, "wpa_auth", WPA_AUTH_WAPI))) {
+ WL_ERROR(("%s: setting wpa_auth(WPA_AUTH_WAPI) returned %d\n",
+ __FUNCTION__, error));
+ return error;
+ }
+ }
+
+ break;
default:
break;
}
@@ -4699,6 +4925,406 @@ int get_user_params(char *user_params, struct iw_point *dwrq)
}
+#define strtoul(nptr, endptr, base) bcm_strtoul((nptr), (endptr), (base))
+
+
+#if defined(CSCAN)
+
+
+
+static int
+wl_iw_combined_scan_set(struct net_device *dev, wl_iscan_params_t *iscan_params, \
+ 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_params)) {
+ 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) {
+ printf("additional ssids exceed params_size\n");
+ err = -1;
+ goto exit;
+ }
+
+ p = ((char*)&iscan_params->params) + i;
+ memcpy(p, ssids_local, nssid * sizeof(wlc_ssid_t));
+ p += nssid * sizeof(wlc_ssid_t);
+ } else {
+ p = (char*)iscan_params->params.channel_list + nchan * sizeof(uint16);
+ }
+
+
+ iscan_params->params.channel_num = htod32((nssid << WL_SCAN_PARAMS_NSSID_SHIFT) | \
+ (nchan & WL_SCAN_PARAMS_COUNT_MASK));
+
+
+ params_size = (int) (p - (char*)iscan_params + nssid * sizeof(wlc_ssid_t));
+
+ 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 ", iscan_params->params.channel_list[i]);
+ }
+ printf("\nnprobes=%d\n", iscan_params->params.nprobes);
+ printf("active_time=%d\n", iscan_params->params.active_time);
+ printf("passive_time=%d\n", iscan_params->params.passive_time);
+ printf("home_time=%d\n", iscan_params->params.home_time);
+ printf("\n###################\n");
+#endif
+
+ 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_params, params_size, \
+ iscan->ioctlbuf, sizeof(iscan->ioctlbuf)))) {
+ 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;
+ int params_size = (WL_SCAN_PARAMS_FIXED_SIZE + OFFSETOF(wl_iscan_params_t, params)) +
+ (WL_NUMCHANNELS * sizeof(uint16));
+ wl_iscan_params_t *iscan_params;
+ 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 (!(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;
+ }
+
+
+ params_size += WL_SCAN_PARAMS_SSID_MAX * sizeof(wlc_ssid_t);
+
+ iscan_params = (wl_iscan_params_t*)kmalloc(params_size, GFP_KERNEL);
+ if (iscan_params == NULL) {
+ WL_ERROR(("%s Failed allocate %d bytes \n", __FUNCTION__, params_size));
+ return -ENOMEM;
+ }
+
+ memset(iscan_params, 0, params_size);
+ ASSERT(params_size < WLC_IOCTL_MAXLEN);
+
+
+ iscan_params->version = htod32(ISCAN_REQ_VERSION);
+ iscan_params->action = htod16(WL_SCAN_ACTION_START);
+ iscan_params->scan_duration = htod16(0);
+
+ wl_iw_iscan_prep(&iscan_params->params, NULL);
+
+
+ if ((nchan = wl_iw_parse_channel_list(&str_ptr, \
+ &iscan_params->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_params->params.nprobes, 2);
+
+ get_parmeter_from_string(&str_ptr, GET_ACTIVE_ASSOC_DWELL, PTYPE_INTDEC, \
+ &iscan_params->params.active_time, 3);
+
+ get_parmeter_from_string(&str_ptr, GET_PASSIVE_ASSOC_DWELL, PTYPE_INTDEC, \
+ &iscan_params->params.passive_time, 3);
+
+ get_parmeter_from_string(&str_ptr, GET_HOME_DWELL, PTYPE_INTDEC, \
+ &iscan_params->params.home_time, 3);
+
+
+ res = wl_iw_combined_scan_set(dev, iscan_params, \
+ ssids_local, nssid, nchan);
+
+ kfree(iscan_params);
+ } 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;
+ int params_size = (WL_SCAN_PARAMS_FIXED_SIZE + OFFSETOF(wl_iscan_params_t, params)) + \
+ (WL_NUMCHANNELS * sizeof(uint16));
+ wl_iscan_params_t *iscan_params;
+ 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,
+ 0x01,
+ 0x00,
+ 0x01,
+ 0x04,
+ 'B', 'R', 'C', 'M',
+ 0x02,
+ 0x00
+ };
+#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 {
+
+ params_size += WL_SCAN_PARAMS_SSID_MAX * sizeof(wlc_ssid_t);
+
+ iscan_params = (wl_iscan_params_t*)kmalloc(params_size, GFP_KERNEL);
+ if (iscan_params == NULL) {
+ WL_ERROR(("%s Failed allocate %d bytes \n", \
+ __FUNCTION__, params_size));
+ return -ENOMEM;
+ }
+ memset(iscan_params, 0, params_size);
+ ASSERT(params_size < WLC_IOCTL_MAXLEN);
+
+
+ iscan_params->version = htod32(ISCAN_REQ_VERSION);
+ iscan_params->action = htod16(WL_SCAN_ACTION_START);
+ iscan_params->scan_duration = htod16(0);
+ wl_iw_iscan_prep(&iscan_params->params, NULL);
+
+
+ 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_params->params.channel_list[0], \
+ WL_NUMCHANNELS, &tlv_size_left)) == -1) {
+ WL_ERROR(("%s missing channel list\n", \
+ __FUNCTION__));
+ goto exit_scan;
+ }
+ break;
+ case CSCAN_TLV_TYPE_NPROBE_IE:
+ if ((res = wl_iw_parse_data_tlv(&str_ptr, \
+ &iscan_params->params.nprobes, \
+ sizeof(iscan_params->params.nprobes), \
+ type, sizeof(char), &tlv_size_left)) == -1) {
+ WL_ERROR(("%s return %d\n", \
+ __FUNCTION__, res));
+ goto exit_scan;
+ }
+ break;
+ case CSCAN_TLV_TYPE_ACTIVE_IE:
+ if ((res = wl_iw_parse_data_tlv(&str_ptr, \
+ &iscan_params->params.active_time, \
+ sizeof(iscan_params->params.active_time), \
+ type, sizeof(short), &tlv_size_left)) == -1) {
+ WL_ERROR(("%s return %d\n", \
+ __FUNCTION__, res));
+ goto exit_scan;
+ }
+ break;
+ case CSCAN_TLV_TYPE_PASSIVE_IE:
+ if ((res = wl_iw_parse_data_tlv(&str_ptr, \
+ &iscan_params->params.passive_time, \
+ sizeof(iscan_params->params.passive_time), \
+ type, sizeof(short), &tlv_size_left)) == -1) {
+ WL_ERROR(("%s return %d\n", \
+ __FUNCTION__, res));
+ goto exit_scan;
+ }
+ break;
+ case CSCAN_TLV_TYPE_HOME_IE:
+ if ((res = wl_iw_parse_data_tlv(&str_ptr, \
+ &iscan_params->params.home_time, \
+ sizeof(iscan_params->params.home_time), \
+ type, sizeof(short), &tlv_size_left)) == -1) {
+ WL_ERROR(("%s return %d\n", \
+ __FUNCTION__, res));
+ goto exit_scan;
+ }
+ break;
+ case CSCAN_TLV_TYPE_STYPE_IE:
+ if ((res = wl_iw_parse_data_tlv(&str_ptr, \
+ &iscan_params->params.scan_type, \
+ sizeof(iscan_params->params.scan_type), \
+ type, sizeof(char), &tlv_size_left)) == -1) {
+ WL_ERROR(("%s return %d\n", \
+ __FUNCTION__, res));
+ goto exit_scan;
+ }
+ break;
+
+ default :
+ WL_ERROR(("%s get unkwown type %X\n", \
+ __FUNCTION__, type));
+ goto exit_scan;
+ break;
+ }
+ }
+ }
+ }
+ else {
+ WL_ERROR(("%s get wrong TLV command\n", __FUNCTION__));
+ goto exit_proc;
+ }
+
+
+ res = wl_iw_combined_scan_set(dev, iscan_params, \
+ ssids_local, nssid, nchan);
+
+exit_scan:
+ kfree(iscan_params);
+
+exit_proc:
+
+ return res;
+}
+
+#endif
+
+
+
#ifdef SOFTAP
@@ -4749,11 +5375,18 @@ 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;
+ int iolen = 0;
+ int mkvar_err = 0;
+ int bsscfg_index = 1;
+ char buf[WLC_IOCTL_SMLEN];
WL_SOFTAP(("Enter %s\n", __FUNCTION__));
memset(&null_ssid, 0, sizeof(wlc_ssid_t));
res |= dev_wlc_ioctl(dev, WLC_UP, &updown, sizeof(updown));
- res |= dev_wlc_ioctl(dev, WLC_SET_SSID, &null_ssid, sizeof(null_ssid));
+ 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);
auto_channel_retry:
request.count = htod32(0);
@@ -5143,7 +5776,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;
@@ -5160,7 +5793,7 @@ int get_parmeter_from_string(
WL_TRACE((" 'token:%s', len:%d, ", token, parm_str_len));
if (parm_str_len > param_max_len) {
- WL_TRACE((" WARNING: extracted param len:%d is > MAX:%d\n",
+ WL_ERROR((" WARNING: extracted param len:%d is > MAX:%d\n",
parm_str_len, param_max_len));
parm_str_len = param_max_len;
@@ -5194,7 +5827,7 @@ int get_parmeter_from_string(
memcpy(dst, param_str_begin, parm_str_len);
*((char *)dst + parm_str_len) = 0;
- WL_TRACE((" written as a string:%s\n", (char *)dst));
+ WL_ERROR((" written as a string:%s\n", (char *)dst));
break;
}
@@ -5352,6 +5985,7 @@ exit_proc:
return ret;
}
#ifdef SOFTAP
+
static int iwpriv_wpasupp_loop_tst(struct net_device *dev,
struct iw_request_info *info,
union iwreq_data *wrqu,
@@ -5611,7 +6245,7 @@ static int wl_iw_set_priv(
return -EFAULT;
}
- WL_TRACE(("%s: SIOCSIWPRIV request %s, info->cmd:%x, info->flags:%d\n dwrq->length:%d",
+ WL_TRACE(("%s: SIOCSIWPRIV request %s, info->cmd:%x, info->flags:%d\n dwrq->length:%d\n",
dev->name, extra, info->cmd, info->flags, dwrq->length));
@@ -5656,6 +6290,11 @@ 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);
@@ -5823,8 +6462,13 @@ static const iw_handler wl_iw_priv_handler[] = {
(iw_handler)iwpriv_softap_stop,
NULL,
- (iw_handler)iwpriv_fw_reload
+ (iw_handler)iwpriv_fw_reload,
#endif
+#if defined(CSCAN)
+
+ NULL,
+ (iw_handler)iwpriv_set_cscan
+#endif
};
static const struct iw_priv_args wl_iw_priv_args[] =
@@ -5923,6 +6567,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 =
@@ -6372,7 +7024,8 @@ 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;
@@ -6425,7 +7078,7 @@ int wl_iw_get_wireless_stats(struct net_device *dev, struct iw_statistics *wstat
phy_noise = dtoh32(phy_noise);
WL_TRACE(("wl_iw_get_wireless_stats phy noise=%d\n", phy_noise));
- scb_val.val = 0;
+ bzero(&scb_val, sizeof(scb_val_t));
if ((res = dev_wlc_ioctl(dev, WLC_GET_RSSI, &scb_val, sizeof(scb_val_t))))
goto done;
@@ -6671,6 +7324,7 @@ int wl_iw_attach(struct net_device *dev, void * dhdp)
iw = *(wl_iw_t **)netdev_priv(dev);
iw->pub = (dhd_pub_t *)dhdp;
MUTEX_LOCK_INIT(iw->pub);
+ MUTEX_LOCK_WL_SCAN_SET_INIT();
#ifdef SOFTAP
priv_dev = dev;
MUTEX_LOCK_SOFTAP_SET_INIT(iw->pub);
@@ -6685,8 +7339,10 @@ 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);
@@ -6706,12 +7362,13 @@ void wl_iw_detach(void)
KILL_PROC(iscan->sysioc_pid, SIGTERM);
wait_for_completion(&iscan->sysioc_exited);
}
-
+ MUTEX_LOCK_WL_SCAN_SET();
while (iscan->list_hdr) {
buf = iscan->list_hdr->next;
kfree(iscan->list_hdr);
iscan->list_hdr = buf;
}
+ MUTEX_UNLOCK_WL_SCAN_SET();
kfree(iscan);
g_iscan = NULL;
#endif
@@ -6720,7 +7377,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
diff --git a/bcm4329/src/wl/sys/wl_iw.h b/bcm4329/src/wl/sys/wl_iw.h
index f354d68..0b7ece1 100644
--- a/bcm4329/src/wl/sys/wl_iw.h
+++ b/bcm4329/src/wl/sys/wl_iw.h
@@ -21,7 +21,7 @@
* software in any way with any other Broadcom software provided under a license
* other than the GPL, without Broadcom's express prior written consent.
*
- * $Id: wl_iw.h,v 1.5.34.1.6.16 2010/04/19 21:32:10 Exp $
+ * $Id: wl_iw.h,v 1.5.34.1.6.21 2010/07/08 00:50:58 Exp $
*/
@@ -34,6 +34,14 @@
#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 SOFTAP 1
@@ -63,7 +71,7 @@
#define AP_LPB_CMD (SIOCIWFIRSTPRIV+23)
#define WL_AP_STOP (SIOCIWFIRSTPRIV+25)
#define WL_FW_RELOAD (SIOCIWFIRSTPRIV+27)
-#define WL_AP_SPARE2 (SIOCIWFIRSTPRIV+29)
+#define WL_COMBO_SCAN (SIOCIWFIRSTPRIV+29)
#define WL_AP_SPARE3 (SIOCIWFIRSTPRIV+31)
#define G_SCAN_RESULTS 8*1024
#define WE_ADD_EVENT_FIX 0x80
@@ -98,14 +106,13 @@ int wl_control_wl_start(struct net_device *dev);
#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 {
+ struct wl_iw_ss_cache *next;
uint32 buflen;
uint32 version;
uint32 count;
- wl_bss_info_t bss_info[1];
- char dummy[WLC_IW_BSS_INFO_MAXLEN - sizeof(wl_bss_info_t)];
int dirty;
- struct wl_iw_ss_cache *next;
+ wl_bss_info_t bss_info[1];
} wl_iw_ss_cache_t;
typedef struct wl_iw_ss_cache_ctrl {
@@ -179,4 +186,40 @@ void wl_iw_detach(void);
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 1
+#define CSCAN_TLV_TYPE_CHANNEL_IE 2
+#define CSCAN_TLV_TYPE_NPROBE_IE 3
+#define CSCAN_TLV_TYPE_ACTIVE_IE 4
+#define CSCAN_TLV_TYPE_PASSIVE_IE 5
+#define CSCAN_TLV_TYPE_HOME_IE 6
+#define CSCAN_TLV_TYPE_STYPE_IE 7
+
+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