summaryrefslogtreecommitdiffstats
path: root/bcm4329/src/wl/sys/wl_iw.c
diff options
context:
space:
mode:
Diffstat (limited to 'bcm4329/src/wl/sys/wl_iw.c')
-rw-r--r--bcm4329/src/wl/sys/wl_iw.c1047
1 files changed, 930 insertions, 117 deletions
diff --git a/bcm4329/src/wl/sys/wl_iw.c b/bcm4329/src/wl/sys/wl_iw.c
index de32e94..0307ae0 100644
--- a/bcm4329/src/wl/sys/wl_iw.c
+++ b/bcm4329/src/wl/sys/wl_iw.c
@@ -21,7 +21,7 @@
* software in any way with any other Broadcom software provided under a license
* other than the GPL, without Broadcom's express prior written consent.
*
- * $Id: wl_iw.c,v 1.51.4.9.2.6.4.104 2010/04/21 23:21:00 Exp $
+ * $Id: wl_iw.c,v 1.51.4.9.2.6.4.124 2010/07/27 20:46:02 Exp $
*/
@@ -53,11 +53,38 @@ typedef const struct si_pub si_t;
#define WL_ASSOC(x)
#define WL_INFORM(x)
#define WL_WSEC(x)
+#define WL_SCAN(x)
#include <wl_iw.h>
-#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>
#include <linux/mutex.h>
@@ -150,8 +177,10 @@ static volatile uint g_first_broadcast_scan;
#endif
#if defined(WL_IW_USE_ISCAN)
+#if !defined(CSCAN)
static void wl_iw_free_ss_cache(void);
static int wl_iw_run_ss_cache_timer(int kick_off);
+#endif
int wl_iw_iscan_set_scan_broadcast_prep(struct net_device *dev, uint flag);
static int dev_wlc_bufvar_set(struct net_device *dev, char *name, char *buf, int len);
#define ISCAN_STATE_IDLE 0
@@ -178,8 +207,13 @@ typedef struct iscan_info {
struct completion sysioc_exited;
uint32 scan_flag;
-
+#if defined CSCAN
+ char ioctlbuf[WLC_IOCTL_MEDLEN];
+#else
char ioctlbuf[WLC_IOCTL_SMLEN];
+#endif
+ wl_iscan_params_t *iscan_ex_params_p;
+ int iscan_ex_param_size;
} iscan_info_t;
#define COEX_DHCP 1
static void wl_iw_bt_flag_set(struct net_device *dev, bool set);
@@ -283,7 +317,9 @@ dev_wlc_ioctl(
return ret;
}
- WL_TRACE(("%s, PID:%x: send Local IOCTL -> dhd: cmd:0x%x, buf:%p, len:%d ,\n",
+ net_os_wake_lock(dev);
+
+ WL_INFORM(("\n%s, PID:%x: send Local IOCTL -> dhd: cmd:0x%x, buf:%p, len:%d ,\n",
__FUNCTION__, current->pid, cmd, arg, len));
if (g_onoff == G_WLAN_SET_ON) {
@@ -298,6 +334,7 @@ dev_wlc_ioctl(
ret = dev_open(dev);
if (ret) {
WL_ERROR(("%s: Error dev_open: %d\n", __func__, ret));
+ net_os_wake_unlock(dev);
return ret;
}
@@ -311,8 +348,11 @@ dev_wlc_ioctl(
set_fs(fs);
}
else {
- WL_TRACE(("%s: call after driver stop\n", __FUNCTION__));
+ WL_TRACE(("%s: call after driver stop : ignored\n", __FUNCTION__));
}
+
+ net_os_wake_unlock(dev);
+
return ret;
}
@@ -388,6 +428,9 @@ dev_iw_iovar_setbuf(
iolen = bcm_mkiovar(iovar, param, paramlen, bufptr, buflen);
ASSERT(iolen);
+ if (iolen == 0)
+ return 0;
+
return (dev_wlc_ioctl(dev, WLC_SET_VAR, bufptr, iolen));
}
@@ -632,7 +675,7 @@ wl_iw_set_power_mode(
dev_wlc_ioctl(dev, WLC_SET_PM, &pm, sizeof(pm));
}
else {
- WL_TRACE(("Unkwown yet power setting, ignored\n"));
+ WL_ERROR(("Unkwown yet power setting, ignored\n"));
}
p += snprintf(p, MAX_WX_STRING, "OK");
@@ -644,6 +687,35 @@ wl_iw_set_power_mode(
#endif
static int
+wl_iw_get_power_mode(
+ struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu,
+ char *extra
+)
+{
+ int error;
+ char *p = extra;
+ int pm_local = PM_FAST;
+
+ error = dev_wlc_ioctl(dev, WLC_GET_PM, &pm_local, sizeof(pm_local));
+ if (!error) {
+ WL_TRACE(("%s: Powermode = %d\n", __func__, pm_local));
+ if (pm_local == PM_OFF)
+ pm_local = 1; /* Active */
+ else
+ pm_local = 0; /* Auto */
+ p += snprintf(p, MAX_WX_STRING, "powermode = %d", pm_local);
+ }
+ else {
+ WL_TRACE(("%s: Error = %d\n", __func__, error));
+ p += snprintf(p, MAX_WX_STRING, "FAIL");
+ }
+ wrqu->data.length = p - extra + 1;
+ return error;
+}
+
+static int
wl_iw_set_btcoex_dhcp(
struct net_device *dev,
struct iw_request_info *info,
@@ -768,6 +840,20 @@ wl_iw_set_btcoex_dhcp(
return error;
}
+static int
+wl_iw_set_suspend(
+ struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu,
+ char *extra
+)
+{
+ int suspend_flag;
+
+ suspend_flag = *(extra + strlen("SETSUSPEND") + 1) - '0';
+ return net_os_set_suspend_disable(dev, suspend_flag);
+}
+
int
wl_format_ssid(char* ssid_buf, uint8* ssid, int ssid_len)
{
@@ -817,6 +903,69 @@ wl_iw_get_link_speed(
return error;
}
+
+static int
+wl_iw_get_band(
+ struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu,
+ char *extra
+)
+{
+ int error = -1;
+ char *p = extra;
+ static int band;
+
+ if (g_onoff == G_WLAN_SET_ON) {
+ error = dev_wlc_ioctl(dev, WLC_GET_BAND, &band, sizeof(band));
+
+ p += snprintf(p, MAX_WX_STRING, "Band %d", band);
+
+ wrqu->data.length = p - extra + 1;
+ }
+ return error;
+}
+
+
+static int
+wl_iw_set_band(
+ struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu,
+ char *extra
+)
+{
+ int error = -1;
+ char *p = extra;
+ uint band;
+
+ if (g_onoff == G_WLAN_SET_ON) {
+
+ band = *(extra + strlen(BAND_SET_CMD) + 1) - '0';
+
+ if ((band == WLC_BAND_AUTO) || (band == WLC_BAND_5G) || (band == WLC_BAND_2G)) {
+
+
+ if ((error = dev_wlc_ioctl(dev, WLC_SET_BAND,
+ &band, sizeof(band))) >= 0) {
+ p += snprintf(p, MAX_WX_STRING, "OK");
+ WL_TRACE(("%s: set band %d OK\n", __FUNCTION__, band));
+ goto exit;
+ }
+ else WL_ERROR(("%s: set band %d failed code %d\n", __FUNCTION__, \
+ band, error));
+ }
+ else WL_ERROR(("%s Incorrect band setting, ignored\n", __FUNCTION__));
+ }
+
+ p += snprintf(p, MAX_WX_STRING, "FAIL");
+
+exit:
+ wrqu->data.length = p - extra + 1;
+ return error;
+}
+
+
static int
wl_iw_get_rssi(
struct net_device *dev,
@@ -855,7 +1004,7 @@ wl_iw_get_rssi(
return error;
}
-static int
+int
wl_iw_send_priv_event(
struct net_device *dev,
char *flag
@@ -873,6 +1022,7 @@ wl_iw_send_priv_event(
strcpy(extra, flag);
wrqu.data.length = strlen(extra);
wireless_send_event(dev, cmd, &wrqu, extra);
+ net_os_wake_lock_timeout_enable(dev);
WL_TRACE(("Send IWEVCUSTOM Event as %s\n", extra));
return 0;
@@ -946,11 +1096,13 @@ wl_iw_control_wl_off(
dhd_dev_reset(dev, 1);
#if defined(WL_IW_USE_ISCAN)
+#if !defined(CSCAN)
wl_iw_free_ss_cache();
wl_iw_run_ss_cache_timer(0);
- memset(g_scan, 0, G_SCAN_RESULTS);
g_ss_cache_ctrl.m_link_down = 1;
+#endif
+ memset(g_scan, 0, G_SCAN_RESULTS);
g_scan_specified_ssid = 0;
g_first_broadcast_scan = BROADCAST_SCAN_FIRST_IDLE;
@@ -963,8 +1115,6 @@ wl_iw_control_wl_off(
dhd_customer_gpio_wlan_ctrl(WLAN_RESET_OFF);
wl_iw_send_priv_event(dev, "STOP");
-
- net_os_wake_lock_timeout_enable(dev);
}
mutex_unlock(&wl_start_lock);
@@ -988,6 +1138,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);
@@ -995,8 +1146,7 @@ wl_iw_control_wl_on(
#else
wl_iw_iscan_set_scan_broadcast_prep(dev, 0);
#endif
-
- net_os_wake_lock_timeout_enable(dev);
+#endif
WL_TRACE(("Exited %s \n", __FUNCTION__));
@@ -1153,28 +1303,6 @@ static int iwpriv_set_ap_config(struct net_device *dev,
#ifdef SOFTAP
-void print_buf(void *pbuf, int len, int bytes_per_line)
-{
- int i, j = 0;
- unsigned char *buf = pbuf;
-
- if (bytes_per_line == 0) {
- bytes_per_line = len;
- }
-
- for (i = 0; i < len; i++) {
- WL_SOFTAP(("%2.2x", *buf++));
- j++;
- if (j == bytes_per_line) {
- WL_SOFTAP(("\n"));
- j = 0;
- } else {
- WL_SOFTAP((":"));
- }
- }
- WL_SOFTAP(("\n"));
-}
-
static int iwpriv_get_assoc_list(struct net_device *dev,
struct iw_request_info *info,
union iwreq_data *p_iwrq,
@@ -1525,9 +1653,9 @@ wl_iw_get_range(
)
{
struct iw_range *range = (struct iw_range *) extra;
- int channels[MAXCHANNEL+1];
- wl_uint32_list_t *list = (wl_uint32_list_t *) channels;
+ wl_uint32_list_t *list;
wl_rateset_t rateset;
+ int8 *channels;
int error, i, k;
uint sf, ch;
@@ -1545,14 +1673,23 @@ wl_iw_get_range(
if (!extra)
return -EINVAL;
+ channels = kmalloc((MAXCHANNEL+1)*4, GFP_KERNEL);
+ if (!channels) {
+ WL_ERROR(("Could not alloc channels\n"));
+ return -ENOMEM;
+ }
+ list = (wl_uint32_list_t *)channels;
+
dwrq->length = sizeof(struct iw_range);
memset(range, 0, sizeof(range));
range->min_nwid = range->max_nwid = 0;
list->count = htod32(MAXCHANNEL);
- if ((error = dev_wlc_ioctl(dev, WLC_GET_VALID_CHANNELS, channels, sizeof(channels))))
+ 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]);
@@ -1584,8 +1721,10 @@ wl_iw_get_range(
range->avg_qual.noise = 0x100 - 75;
#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++)
@@ -1620,8 +1759,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;
@@ -1690,6 +1831,8 @@ wl_iw_get_range(
#endif
#endif
+ kfree(channels);
+
return 0;
}
@@ -2048,35 +2191,23 @@ wl_iw_iscan_prep(wl_scan_params_t *params, wlc_ssid_t *ssid)
static int
wl_iw_iscan(iscan_info_t *iscan, wlc_ssid_t *ssid, uint16 action)
{
- int params_size = (WL_SCAN_PARAMS_FIXED_SIZE + OFFSETOF(wl_iscan_params_t, params));
- wl_iscan_params_t *params;
int err = 0;
- WL_TRACE(("%s: start\n", __func__));
-
- if (ssid && ssid->SSID_len) {
- params_size += sizeof(wlc_ssid_t);
- }
- params = (wl_iscan_params_t*)kmalloc(params_size, GFP_KERNEL);
- if (params == NULL) {
- return -ENOMEM;
- }
- memset(params, 0, params_size);
- ASSERT(params_size < WLC_IOCTL_SMLEN);
-
- err = wl_iw_iscan_prep(&params->params, ssid);
+ iscan->iscan_ex_params_p->version = htod32(ISCAN_REQ_VERSION);
+ iscan->iscan_ex_params_p->action = htod16(action);
+ iscan->iscan_ex_params_p->scan_duration = htod16(0);
- if (!err) {
- params->version = htod32(ISCAN_REQ_VERSION);
- params->action = htod16(action);
- params->scan_duration = htod16(0);
+ WL_SCAN(("%s : nprobes=%d\n", __FUNCTION__, iscan->iscan_ex_params_p->params.nprobes));
+ WL_SCAN(("active_time=%d\n", iscan->iscan_ex_params_p->params.active_time));
+ WL_SCAN(("passive_time=%d\n", iscan->iscan_ex_params_p->params.passive_time));
+ WL_SCAN(("home_time=%d\n", iscan->iscan_ex_params_p->params.home_time));
+ WL_SCAN(("scan_type=%d\n", iscan->iscan_ex_params_p->params.scan_type));
+ WL_SCAN(("bss_type=%d\n", iscan->iscan_ex_params_p->params.bss_type));
-
- (void) dev_iw_iovar_setbuf(iscan->dev, "iscan", params, params_size,
- iscan->ioctlbuf, WLC_IOCTL_SMLEN);
- }
+
+ (void) dev_iw_iovar_setbuf(iscan->dev, "iscan", iscan->iscan_ex_params_p, \
+ iscan->iscan_ex_param_size, iscan->ioctlbuf, sizeof(iscan->ioctlbuf));
- kfree(params);
return err;
}
@@ -2087,7 +2218,7 @@ wl_iw_timerfunc(ulong data)
if (iscan) {
iscan->timer_on = 0;
if (iscan->iscan_state != ISCAN_STATE_IDLE) {
- WL_TRACE(("timer trigger\n"));
+ WL_SCAN(("timer trigger\n"));
up(&iscan->sysioc_sem);
}
}
@@ -2157,9 +2288,9 @@ wl_iw_iscan_get(iscan_info_t *iscan)
results->buflen = dtoh32(results->buflen);
results->version = dtoh32(results->version);
results->count = dtoh32(results->count);
- WL_TRACE(("results->count = %d\n", results->count));
+ WL_SCAN(("results->count = %d\n", results->count));
- WL_TRACE(("results->buflen = %d\n", results->buflen));
+ WL_SCAN(("results->buflen = %d\n", results->buflen));
status = dtoh32(list_buf->status);
mutex_unlock(&wl_cache_lock);
return status;
@@ -2185,8 +2316,10 @@ static void wl_iw_send_scan_complete(iscan_info_t *iscan)
memset(&wrqu, 0, sizeof(wrqu));
wireless_send_event(iscan->dev, SIOCGIWSCAN, &wrqu, NULL);
+#if !defined(CSCAN)
if (g_first_broadcast_scan == BROADCAST_SCAN_FIRST_STARTED)
g_first_broadcast_scan = BROADCAST_SCAN_FIRST_RESULT_READY;
+#endif
WL_TRACE(("Send Event ISCAN complete\n"));
#endif
}
@@ -2203,13 +2336,15 @@ _iscan_sysioc_thread(void *data)
status = WL_SCAN_RESULTS_PARTIAL;
while (down_interruptible(&iscan->sysioc_sem) == 0) {
+ net_os_wake_lock(iscan->dev);
+
#if defined(SOFTAP)
if (ap_cfg_running) {
- WL_TRACE(("%s skipping SCAN ops in AP mode !!!\n", __FUNCTION__));
+ WL_SCAN(("%s skipping SCAN ops in AP mode !!!\n", __FUNCTION__));
+ net_os_wake_unlock(iscan->dev);
continue;
}
#endif
- net_os_wake_lock(iscan->dev);
if (iscan->timer_on) {
iscan->timer_on = 0;
@@ -2225,7 +2360,7 @@ _iscan_sysioc_thread(void *data)
#endif
if (g_scan_specified_ssid && (iscan_pass_abort == TRUE)) {
- WL_TRACE(("%s Get results from specific scan status=%d\n", __FUNCTION__, status));
+ WL_SCAN(("%s Get results from specific scan status=%d\n", __FUNCTION__, status));
wl_iw_send_scan_complete(iscan);
iscan_pass_abort = FALSE;
status = -1;
@@ -2233,7 +2368,7 @@ _iscan_sysioc_thread(void *data)
switch (status) {
case WL_SCAN_RESULTS_PARTIAL:
- WL_TRACE(("iscanresults incomplete\n"));
+ WL_SCAN(("iscanresults incomplete\n"));
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27))
rtnl_lock();
#endif
@@ -2247,18 +2382,18 @@ _iscan_sysioc_thread(void *data)
iscan->timer_on = 1;
break;
case WL_SCAN_RESULTS_SUCCESS:
- WL_TRACE(("iscanresults complete\n"));
+ WL_SCAN(("iscanresults complete\n"));
iscan->iscan_state = ISCAN_STATE_IDLE;
wl_iw_send_scan_complete(iscan);
break;
case WL_SCAN_RESULTS_PENDING:
- WL_TRACE(("iscanresults pending\n"));
+ WL_SCAN(("iscanresults pending\n"));
mod_timer(&iscan->timer, jiffies + iscan->timer_ms*HZ/1000);
iscan->timer_on = 1;
break;
case WL_SCAN_RESULTS_ABORTED:
- WL_TRACE(("iscanresults aborted\n"));
+ WL_SCAN(("iscanresults aborted\n"));
iscan->iscan_state = ISCAN_STATE_IDLE;
if (g_scan_specified_ssid == 0)
wl_iw_send_scan_complete(iscan);
@@ -2268,11 +2403,11 @@ _iscan_sysioc_thread(void *data)
}
break;
case WL_SCAN_RESULTS_NO_MEM:
- WL_TRACE(("iscanresults can't alloc memory: skip\n"));
+ WL_SCAN(("iscanresults can't alloc memory: skip\n"));
iscan->iscan_state = ISCAN_STATE_IDLE;
break;
default:
- WL_TRACE(("iscanresults returned unknown status %d\n", status));
+ WL_SCAN(("iscanresults returned unknown status %d\n", status));
break;
}
@@ -2288,6 +2423,7 @@ _iscan_sysioc_thread(void *data)
}
#endif
+#if !defined(CSCAN)
static void
wl_iw_set_ss_cache_timer_flag(void)
@@ -2453,18 +2589,12 @@ wl_iw_add_bss_to_ss_cache(wl_scan_results_t *ss_list)
if (node) {
continue;
}
- leaf = kmalloc(WLC_IW_SS_CACHE_MAXLEN, GFP_KERNEL);
+ leaf = kmalloc(bi->length + WLC_IW_SS_CACHE_CTRL_FIELD_MAXLEN, GFP_KERNEL);
if (!leaf) {
mutex_unlock(&wl_cache_lock);
return -ENOMEM;
}
- if (bi->length > WLC_IW_BSS_INFO_MAXLEN) {
- WL_TRACE(("bss info length is too long : %d\n", bi->length));
- kfree(leaf);
- continue;
- }
-
memcpy(leaf->bss_info, bi, bi->length);
leaf->next = NULL;
leaf->dirty = 1;
@@ -2544,6 +2674,7 @@ wl_iw_delete_bss_from_ss_cache(void *addr)
return 0;
}
+#endif
static int
@@ -2557,6 +2688,11 @@ wl_iw_set_scan(
int error;
WL_TRACE(("%s dev:%s: SIOCSIWSCAN : SCAN\n", __FUNCTION__, dev->name));
+#if defined(CSCAN)
+ WL_ERROR(("%s: Scan from SIOCGIWSCAN not supported\n", __FUNCTION__));
+ return -EINVAL;
+#endif
+
#if defined(SOFTAP)
if (ap_cfg_running) {
WL_TRACE(("\n>%s: Not executed, reason -'SOFTAP is active'\n", __FUNCTION__));
@@ -2617,6 +2753,7 @@ wl_iw_iscan_set_scan_broadcast_prep(struct net_device *dev, uint flag)
wlc_ssid_t ssid;
iscan_info_t *iscan = g_iscan;
+#if !defined(CSCAN)
if (g_first_broadcast_scan == BROADCAST_SCAN_FIRST_IDLE) {
g_first_broadcast_scan = BROADCAST_SCAN_FIRST_STARTED;
WL_TRACE(("%s: First Brodcast scan was forced\n", __FUNCTION__));
@@ -2625,11 +2762,7 @@ wl_iw_iscan_set_scan_broadcast_prep(struct net_device *dev, uint flag)
WL_TRACE(("%s: ignore ISCAN request first BS is not done yet\n", __FUNCTION__));
return 0;
}
-
- memset(&ssid, 0, sizeof(ssid));
-
- iscan->list_cur = iscan->list_hdr;
- iscan->iscan_state = ISCAN_STATE_SCANING;
+#endif
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27))
if (flag)
@@ -2640,7 +2773,14 @@ wl_iw_iscan_set_scan_broadcast_prep(struct net_device *dev, uint flag)
wl_iw_set_event_mask(dev);
WL_TRACE(("+++: Set Broadcast ISCAN\n"));
+
+ memset(&ssid, 0, sizeof(ssid));
+ iscan->list_cur = iscan->list_hdr;
+ iscan->iscan_state = ISCAN_STATE_SCANING;
+
+ memset(&iscan->iscan_ex_params_p->params, 0, iscan->iscan_ex_param_size);
+ wl_iw_iscan_prep(&iscan->iscan_ex_params_p->params, &ssid);
wl_iw_iscan(iscan, &ssid, WL_SCAN_ACTION_START);
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27))
@@ -2667,6 +2807,11 @@ wl_iw_iscan_set_scan(
WL_TRACE(("%s: SIOCSIWSCAN : ISCAN\n", dev->name));
+#if defined(CSCAN)
+ WL_ERROR(("%s: Scan from SIOCGIWSCAN not supported\n", __FUNCTION__));
+ return -EINVAL;
+#endif
+
#if defined(SOFTAP)
if (ap_cfg_running) {
WL_TRACE(("\n>%s: Not executed, reason -'SOFTAP is active'\n", __FUNCTION__));
@@ -2699,11 +2844,13 @@ wl_iw_iscan_set_scan(
if (wrqu->data.flags & IW_SCAN_THIS_ESSID) {
int as = 0;
struct iw_scan_req *req = (struct iw_scan_req *)extra;
+#if !defined(CSCAN)
if (g_first_broadcast_scan < BROADCAST_SCAN_FIRST_RESULT_CONSUMED) {
WL_TRACE(("%s First ISCAN in progress : ignoring SC = %s\n", \
__FUNCTION__, req->essid));
return -EBUSY;
}
+#endif
ssid.SSID_len = MIN(sizeof(ssid.SSID), req->essid_len);
memcpy(ssid.SSID, req->essid, ssid.SSID_len);
ssid.SSID_len = htod32(ssid.SSID_len);
@@ -2766,6 +2913,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,
@@ -2774,6 +2947,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) {
@@ -2812,6 +2987,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
@@ -2931,12 +3135,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));
if (!extra) {
@@ -2951,6 +3159,7 @@ wl_iw_get_scan(
if (ci.scan_channel)
return -EAGAIN;
+#if !defined(CSCAN)
if (g_ss_cache_ctrl.m_timer_expired) {
wl_iw_free_ss_cache();
g_ss_cache_ctrl.m_timer_expired ^= 1;
@@ -2968,6 +3177,7 @@ wl_iw_get_scan(
else {
g_ss_cache_ctrl.m_cons_br_scan_cnt++;
}
+#endif
if (g_scan_specified_ssid) {
@@ -3003,6 +3213,7 @@ wl_iw_get_scan(
return -EINVAL;
}
+#if !defined(CSCAN)
if (g_scan_specified_ssid) {
wl_iw_add_bss_to_ss_cache(list);
@@ -3038,6 +3249,37 @@ wl_iw_get_scan(
len_ret += merged_len;
wl_iw_run_ss_cache_timer(0);
wl_iw_run_ss_cache_timer(1);
+#else
+
+ if (g_scan_specified_ssid) {
+ WL_TRACE(("%s: Specified scan APs in the list =%d\n", __FUNCTION__, list->count));
+ len_ret = (__u16) wl_iw_get_scan_prep(list, info, extra, buflen_from_user);
+ kfree(list);
+
+#if defined(WL_IW_USE_ISCAN)
+ p_buf = iscan->list_hdr;
+
+ while (p_buf != iscan->list_cur) {
+ list_merge = &((wl_iscan_results_t*)p_buf->iscan_buf)->results;
+ WL_TRACE(("%s: Bcast APs list=%d\n", __FUNCTION__, list_merge->count));
+ if (list_merge->count > 0)
+ len_ret += (__u16) wl_iw_get_scan_prep(list_merge, info,
+ extra+len_ret, buflen_from_user -len_ret);
+ p_buf = p_buf->next;
+ }
+#else
+ list_merge = (wl_scan_results_t *) g_scan;
+ WL_TRACE(("%s: Bcast APs list=%d\n", __FUNCTION__, list_merge->count));
+ if (list_merge->count > 0)
+ len_ret += (__u16) wl_iw_get_scan_prep(list_merge, info, extra+len_ret,
+ buflen_from_user -len_ret);
+#endif
+ }
+ else {
+ list = (wl_scan_results_t *) g_scan;
+ len_ret = (__u16) wl_iw_get_scan_prep(list, info, extra, buflen_from_user);
+ }
+#endif
#if defined(WL_IW_USE_ISCAN)
@@ -3072,8 +3314,10 @@ wl_iw_iscan_get_scan(
iscan_info_t *iscan = g_iscan;
iscan_buf_t * p_buf;
uint32 counter = 0;
+#if !defined(CSCAN)
__u16 merged_len = 0;
uint buflen_from_user = dwrq->length;
+#endif
WL_TRACE(("%s %s buflen_from_user %d:\n", dev->name, __FUNCTION__, dwrq->length));
@@ -3089,17 +3333,20 @@ wl_iw_iscan_get_scan(
return -EINVAL;
}
+#if !defined(CSCAN)
if (g_first_broadcast_scan < BROADCAST_SCAN_FIRST_RESULT_READY) {
WL_TRACE(("%s %s: first ISCAN results are NOT ready yet \n", \
dev->name, __FUNCTION__));
return -EAGAIN;
}
+#endif
if ((!iscan) || (iscan->sysioc_pid < 0)) {
WL_TRACE(("%ssysioc_pid\n", __FUNCTION__));
return wl_iw_get_scan(dev, info, dwrq, extra);
}
+#if !defined(CSCAN)
if (g_ss_cache_ctrl.m_timer_expired) {
wl_iw_free_ss_cache();
g_ss_cache_ctrl.m_timer_expired ^= 1;
@@ -3119,6 +3366,7 @@ wl_iw_iscan_get_scan(
g_ss_cache_ctrl.m_prev_scan_mode = g_scan_specified_ssid;
g_ss_cache_ctrl.m_cons_br_scan_cnt++;
}
+#endif
WL_TRACE(("%s: SIOCGIWSCAN GET broadcast results\n", dev->name));
apcnt = 0;
@@ -3217,12 +3465,14 @@ wl_iw_iscan_get_scan(
dwrq->length = event - extra;
dwrq->flags = 0;
+#if !defined(CSCAN)
wl_iw_merge_scan_cache(info, event, buflen_from_user - dwrq->length, &merged_len);
dwrq->length += merged_len;
wl_iw_run_ss_cache_timer(0);
wl_iw_run_ss_cache_timer(1);
g_first_broadcast_scan = BROADCAST_SCAN_FIRST_RESULT_CONSUMED;
+#endif
WL_TRACE(("%s return to WE %d bytes APs=%d\n", __FUNCTION__, dwrq->length, counter));
@@ -3889,11 +4139,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;
@@ -4010,6 +4270,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;
}
@@ -4193,6 +4459,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;
@@ -4207,6 +4475,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;
@@ -4254,9 +4524,12 @@ 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;
+
break;
case IW_AUTH_TKIP_COUNTERMEASURES:
dev_wlc_bufvar_set(dev, "tkip_countermeasures", (char *)&paramval, 1);
@@ -4339,6 +4612,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;
}
@@ -4574,6 +4865,7 @@ int dev_iw_read_cfg1_bss_var(struct net_device *dev, int *val)
}
+#ifndef AP_ONLY
static int wl_bssiovar_mkbuf(
const char *iovar,
int bssidx,
@@ -4616,6 +4908,7 @@ static int wl_bssiovar_mkbuf(
*perr = 0;
return iolen;
}
+#endif
int get_user_params(char *user_params, struct iw_point *dwrq)
@@ -4634,7 +4927,391 @@ 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, wlc_ssid_t* ssids_local, int nssid, int nchan)
+{
+ int params_size = WL_SCAN_PARAMS_FIXED_SIZE + WL_NUMCHANNELS * sizeof(uint16);
+ int err = 0;
+ char *p;
+ int i;
+ iscan_info_t *iscan = g_iscan;
+
+ WL_TRACE(("%s nssid=%d nchan=%d\n", __FUNCTION__, nssid, nchan));
+
+ if ((!dev) && (!g_iscan) && (!iscan->iscan_ex_params_p)) {
+ WL_ERROR(("%s error exit\n", __FUNCTION__));
+ err = -1;
+ }
+
+ params_size += WL_SCAN_PARAMS_SSID_MAX * sizeof(wlc_ssid_t);
+
+ if (nssid > 0) {
+ i = OFFSETOF(wl_scan_params_t, channel_list) + nchan * sizeof(uint16);
+ i = ROUNDUP(i, sizeof(uint32));
+ if (i + nssid * sizeof(wlc_ssid_t) > params_size) {
+ printf("additional ssids exceed params_size\n");
+ err = -1;
+ goto exit;
+ }
+
+ p = ((char*)&iscan->iscan_ex_params_p->params) + i;
+ memcpy(p, ssids_local, nssid * sizeof(wlc_ssid_t));
+ p += nssid * sizeof(wlc_ssid_t);
+ } else {
+ p = (char*)iscan->iscan_ex_params_p->params.channel_list + nchan * sizeof(uint16);
+ }
+
+
+ iscan->iscan_ex_params_p->params.channel_num = \
+ htod32((nssid << WL_SCAN_PARAMS_NSSID_SHIFT) | \
+ (nchan & WL_SCAN_PARAMS_COUNT_MASK));
+
+ nssid = \
+ (uint)((iscan->iscan_ex_params_p->params.channel_num >> WL_SCAN_PARAMS_NSSID_SHIFT) & \
+ WL_SCAN_PARAMS_COUNT_MASK);
+
+
+ params_size = (int) (p - (char*)iscan->iscan_ex_params_p + nssid * sizeof(wlc_ssid_t));
+ iscan->iscan_ex_param_size = params_size;
+
+ iscan->list_cur = iscan->list_hdr;
+ iscan->iscan_state = ISCAN_STATE_SCANING;
+ wl_iw_set_event_mask(dev);
+ mod_timer(&iscan->timer, jiffies + iscan->timer_ms*HZ/1000);
+
+ iscan->timer_on = 1;
+
+#ifdef SCAN_DUMP
+ {
+ int i;
+ WL_SCAN(("\n### List of SSIDs to scan ###\n"));
+ for (i = 0; i < nssid; i++) {
+ if (!ssids_local[i].SSID_len)
+ WL_SCAN(("%d: Broadcast scan\n", i));
+ else
+ WL_SCAN(("%d: scan for %s size =%d\n", i, \
+ ssids_local[i].SSID, ssids_local[i].SSID_len));
+ }
+ WL_SCAN(("### List of channels to scan ###\n"));
+ for (i = 0; i < nchan; i++)
+ {
+ WL_SCAN(("%d ", iscan->iscan_ex_params_p->params.channel_list[i]));
+ }
+ WL_SCAN(("\nnprobes=%d\n", iscan->iscan_ex_params_p->params.nprobes));
+ WL_SCAN(("active_time=%d\n", iscan->iscan_ex_params_p->params.active_time));
+ WL_SCAN(("passive_time=%d\n", iscan->iscan_ex_params_p->params.passive_time));
+ WL_SCAN(("home_time=%d\n", iscan->iscan_ex_params_p->params.home_time));
+ WL_SCAN(("scan_type=%d\n", iscan->iscan_ex_params_p->params.scan_type));
+ WL_SCAN(("\n###################\n"));
+ }
+#endif
+
+ if (params_size > WLC_IOCTL_MEDLEN) {
+ WL_ERROR(("Set ISCAN for %s due to params_size=%d \n", \
+ __FUNCTION__, params_size));
+ err = -1;
+ }
+
+ if ((err = dev_iw_iovar_setbuf(dev, "iscan", iscan->iscan_ex_params_p, \
+ iscan->iscan_ex_param_size, \
+ iscan->ioctlbuf, sizeof(iscan->ioctlbuf)))) {
+ WL_TRACE(("Set ISCAN for %s failed with %d\n", __FUNCTION__, err));
+ err = -1;
+ }
+
+exit:
+
+ return err;
+}
+
+
+static int iwpriv_set_cscan(struct net_device *dev, struct iw_request_info *info, \
+ union iwreq_data *wrqu, char *ext)
+{
+ int res = 0;
+ char *extra = NULL;
+ iscan_info_t *iscan = g_iscan;
+ wlc_ssid_t ssids_local[WL_SCAN_PARAMS_SSID_MAX];
+ int nssid = 0;
+ int nchan = 0;
+
+ WL_TRACE(("\%s: info->cmd:%x, info->flags:%x, u.data=0x%p, u.len=%d\n",
+ __FUNCTION__, info->cmd, info->flags,
+ wrqu->data.pointer, wrqu->data.length));
+
+ if (g_onoff == G_WLAN_SET_OFF) {
+ WL_TRACE(("%s: driver is not up yet after START\n", __FUNCTION__));
+ return -1;
+ }
+
+ if (wrqu->data.length != 0) {
+
+ char *str_ptr;
+
+ if (!iscan->iscan_ex_params_p) {
+ return -EFAULT;
+ }
+
+ if (!(extra = kmalloc(wrqu->data.length+1, GFP_KERNEL)))
+ return -ENOMEM;
+
+ if (copy_from_user(extra, wrqu->data.pointer, wrqu->data.length)) {
+ kfree(extra);
+ return -EFAULT;
+ }
+
+ extra[wrqu->data.length] = 0;
+ WL_ERROR(("Got str param in iw_point:\n %s\n", extra));
+
+ str_ptr = extra;
+
+ if (strncmp(str_ptr, GET_SSID, strlen(GET_SSID))) {
+ WL_ERROR(("%s Error: extracting SSID='' string\n", __FUNCTION__));
+ goto exit_proc;
+ }
+ str_ptr += strlen(GET_SSID);
+ nssid = wl_iw_parse_ssid_list(&str_ptr, ssids_local, nssid, \
+ WL_SCAN_PARAMS_SSID_MAX);
+ if (nssid == -1) {
+ WL_ERROR(("%s wrong ssid list", __FUNCTION__));
+ return -1;
+ }
+
+ memset(iscan->iscan_ex_params_p, 0, iscan->iscan_ex_param_size);
+ ASSERT(iscan->iscan_ex_param_size < WLC_IOCTL_MAXLEN);
+
+
+ wl_iw_iscan_prep(&iscan->iscan_ex_params_p->params, NULL);
+ iscan->iscan_ex_params_p->version = htod32(ISCAN_REQ_VERSION);
+ iscan->iscan_ex_params_p->action = htod16(WL_SCAN_ACTION_START);
+ iscan->iscan_ex_params_p->scan_duration = htod16(0);
+
+
+ if ((nchan = wl_iw_parse_channel_list(&str_ptr, \
+ &iscan->iscan_ex_params_p->params.channel_list[0], \
+ WL_NUMCHANNELS)) == -1) {
+ WL_ERROR(("%s missing channel list\n", __FUNCTION__));
+ return -1;
+ }
+
+
+ get_parmeter_from_string(&str_ptr, \
+ GET_NPROBE, PTYPE_INTDEC, \
+ &iscan->iscan_ex_params_p->params.nprobes, 2);
+
+ get_parmeter_from_string(&str_ptr, GET_ACTIVE_ASSOC_DWELL, PTYPE_INTDEC, \
+ &iscan->iscan_ex_params_p->params.active_time, 4);
+
+ get_parmeter_from_string(&str_ptr, GET_PASSIVE_ASSOC_DWELL, PTYPE_INTDEC, \
+ &iscan->iscan_ex_params_p->params.passive_time, 4);
+
+ get_parmeter_from_string(&str_ptr, GET_HOME_DWELL, PTYPE_INTDEC, \
+ &iscan->iscan_ex_params_p->params.home_time, 4);
+
+ get_parmeter_from_string(&str_ptr, GET_SCAN_TYPE, PTYPE_INTDEC, \
+ &iscan->iscan_ex_params_p->params.scan_type, 1);
+
+
+ res = wl_iw_combined_scan_set(dev, ssids_local, nssid, nchan);
+
+ } else {
+ WL_ERROR(("IWPRIV argument len = 0 \n"));
+ return -1;
+ }
+
+exit_proc:
+
+ kfree(extra);
+
+ return res;
+}
+
+
+static int
+wl_iw_set_cscan(
+ struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu,
+ char *extra
+)
+{
+ int res = -1;
+ iscan_info_t *iscan = g_iscan;
+ wlc_ssid_t ssids_local[WL_SCAN_PARAMS_SSID_MAX];
+ int nssid = 0;
+ int nchan = 0;
+ cscan_tlv_t *cscan_tlv_temp;
+ char type;
+ char *str_ptr;
+ int tlv_size_left;
+#ifdef TLV_DEBUG
+ int i;
+ char tlv_in_example[] = { 'C', 'S', 'C', 'A', 'N', ' ', \
+ 0x53, 0x01, 0x00, 0x00,
+ 'S',
+ 0x00,
+ 'S',
+ 0x04,
+ 'B', 'R', 'C', 'M',
+ 'C',
+ 0x06,
+ 'P',
+ 0x94,
+ 0x11,
+ 'T',
+ 0x01
+ };
+#endif
+
+ WL_TRACE(("\n### %s: info->cmd:%x, info->flags:%x, u.data=0x%p, u.len=%d\n",
+ __FUNCTION__, info->cmd, info->flags,
+ wrqu->data.pointer, wrqu->data.length));
+
+ if (g_onoff == G_WLAN_SET_OFF) {
+ WL_TRACE(("%s: driver is not up yet after START\n", __FUNCTION__));
+ return -1;
+ }
+
+
+ if (wrqu->data.length < (strlen(CSCAN_COMMAND) + sizeof(cscan_tlv_t))) {
+ WL_ERROR(("%s aggument=%d less %d\n", __FUNCTION__, \
+ wrqu->data.length, strlen(CSCAN_COMMAND) + sizeof(cscan_tlv_t)));
+ return -1;
+ }
+
+#ifdef TLV_DEBUG
+ memcpy(extra, tlv_in_example, sizeof(tlv_in_example));
+ wrqu->data.length = sizeof(tlv_in_example);
+ for (i = 0; i < wrqu->data.length; i++)
+ printf("%02X ", extra[i]);
+ printf("\n");
+#endif
+
+ str_ptr = extra;
+ str_ptr += strlen(CSCAN_COMMAND);
+ tlv_size_left = wrqu->data.length - strlen(CSCAN_COMMAND);
+
+ cscan_tlv_temp = (cscan_tlv_t *)str_ptr;
+ memset(ssids_local, 0, sizeof(ssids_local));
+
+ if ((cscan_tlv_temp->prefix == CSCAN_TLV_PREFIX) && \
+ (cscan_tlv_temp->version == CSCAN_TLV_VERSION) && \
+ (cscan_tlv_temp->subver == CSCAN_TLV_SUBVERSION))
+ {
+ str_ptr += sizeof(cscan_tlv_t);
+ tlv_size_left -= sizeof(cscan_tlv_t);
+
+
+ if ((nssid = wl_iw_parse_ssid_list_tlv(&str_ptr, ssids_local, \
+ WL_SCAN_PARAMS_SSID_MAX, &tlv_size_left)) <= 0) {
+ WL_ERROR(("SSID is not presented or corrupted ret=%d\n", nssid));
+ goto exit_proc;
+ }
+ else {
+
+ memset(iscan->iscan_ex_params_p, 0, iscan->iscan_ex_param_size);
+
+
+ wl_iw_iscan_prep(&iscan->iscan_ex_params_p->params, NULL);
+ iscan->iscan_ex_params_p->version = htod32(ISCAN_REQ_VERSION);
+ iscan->iscan_ex_params_p->action = htod16(WL_SCAN_ACTION_START);
+ iscan->iscan_ex_params_p->scan_duration = htod16(0);
+
+
+ while (tlv_size_left > 0)
+ {
+ type = str_ptr[0];
+ switch (type) {
+ case CSCAN_TLV_TYPE_CHANNEL_IE:
+
+ if ((nchan = wl_iw_parse_channel_list_tlv(&str_ptr, \
+ &iscan->iscan_ex_params_p->params.channel_list[0], \
+ WL_NUMCHANNELS, &tlv_size_left)) == -1) {
+ WL_ERROR(("%s missing channel list\n", \
+ __FUNCTION__));
+ goto exit_proc;
+ }
+ break;
+ case CSCAN_TLV_TYPE_NPROBE_IE:
+ if ((res = wl_iw_parse_data_tlv(&str_ptr, \
+ &iscan->iscan_ex_params_p->params.nprobes, \
+ sizeof(iscan->iscan_ex_params_p->params.nprobes), \
+ type, sizeof(char), &tlv_size_left)) == -1) {
+ WL_ERROR(("%s return %d\n", \
+ __FUNCTION__, res));
+ goto exit_proc;
+ }
+ break;
+ case CSCAN_TLV_TYPE_ACTIVE_IE:
+ if ((res = wl_iw_parse_data_tlv(&str_ptr, \
+ &iscan->iscan_ex_params_p->params.active_time, \
+ sizeof(iscan->iscan_ex_params_p->params.active_time), \
+ type, sizeof(short), &tlv_size_left)) == -1) {
+ WL_ERROR(("%s return %d\n", \
+ __FUNCTION__, res));
+ goto exit_proc;
+ }
+ break;
+ case CSCAN_TLV_TYPE_PASSIVE_IE:
+ if ((res = wl_iw_parse_data_tlv(&str_ptr, \
+ &iscan->iscan_ex_params_p->params.passive_time, \
+ sizeof(iscan->iscan_ex_params_p->params.passive_time), \
+ type, sizeof(short), &tlv_size_left)) == -1) {
+ WL_ERROR(("%s return %d\n", \
+ __FUNCTION__, res));
+ goto exit_proc;
+ }
+ break;
+ case CSCAN_TLV_TYPE_HOME_IE:
+ if ((res = wl_iw_parse_data_tlv(&str_ptr, \
+ &iscan->iscan_ex_params_p->params.home_time, \
+ sizeof(iscan->iscan_ex_params_p->params.home_time), \
+ type, sizeof(short), &tlv_size_left)) == -1) {
+ WL_ERROR(("%s return %d\n", \
+ __FUNCTION__, res));
+ goto exit_proc;
+ }
+ break;
+ case CSCAN_TLV_TYPE_STYPE_IE:
+ if ((res = wl_iw_parse_data_tlv(&str_ptr, \
+ &iscan->iscan_ex_params_p->params.scan_type, \
+ sizeof(iscan->iscan_ex_params_p->params.scan_type), \
+ type, sizeof(char), &tlv_size_left)) == -1) {
+ WL_ERROR(("%s return %d\n", \
+ __FUNCTION__, res));
+ goto exit_proc;
+ }
+ break;
+
+ default :
+ WL_ERROR(("%s get unkwown type %X\n", \
+ __FUNCTION__, type));
+ goto exit_proc;
+ break;
+ }
+ }
+ }
+ }
+ else {
+ WL_ERROR(("%s get wrong TLV command\n", __FUNCTION__));
+ goto exit_proc;
+ }
+
+
+ res = wl_iw_combined_scan_set(dev, ssids_local, nssid, nchan);
+
+exit_proc:
+ return res;
+}
+
+#endif
+
#ifdef SOFTAP
+#ifndef AP_ONLY
static int thr_wait_for_2nd_eth_dev(void *data)
{
@@ -4670,7 +5347,10 @@ fail:
return ret;
}
-
+#endif
+#ifndef AP_ONLY
+static int last_auto_channel = 6;
+#endif
static int get_softap_auto_channel(struct net_device *dev, struct ap_profile *ap)
{
int chosen = 0;
@@ -4681,12 +5361,30 @@ static int get_softap_auto_channel(struct net_device *dev, struct ap_profile *ap
int ret = 0;
wlc_ssid_t null_ssid;
int res = 0;
-
+#ifndef AP_ONLY
+ int iolen = 0;
+ int mkvar_err = 0;
+ int bsscfg_index = 1;
+ char buf[WLC_IOCTL_SMLEN];
+#endif
WL_SOFTAP(("Enter %s\n", __FUNCTION__));
+
+#ifndef AP_ONLY
+ if (ap_cfg_running) {
+ ap->channel = last_auto_channel;
+ return res;
+ }
+#endif
memset(&null_ssid, 0, sizeof(wlc_ssid_t));
res |= dev_wlc_ioctl(dev, WLC_UP, &updown, sizeof(updown));
+#ifdef AP_ONLY
res |= dev_wlc_ioctl(dev, WLC_SET_SSID, &null_ssid, sizeof(null_ssid));
-
+#else
+ iolen = wl_bssiovar_mkbuf("ssid", bsscfg_index, (char *)(&null_ssid), \
+ null_ssid.SSID_len+4, buf, sizeof(buf), &mkvar_err);
+ ASSERT(iolen);
+ res |= dev_wlc_ioctl(dev, WLC_SET_VAR, buf, iolen);
+#endif
auto_channel_retry:
request.count = htod32(0);
ret = dev_wlc_ioctl(dev, WLC_START_CHANNEL_SEL, &request, sizeof(request));
@@ -4716,6 +5414,11 @@ static int get_softap_auto_channel(struct net_device *dev, struct ap_profile *ap
WL_ERROR(("%s fail to set up err =%d\n", __FUNCTION__, res));
goto fail;
}
+#ifndef AP_ONLY
+ if (!res)
+ last_auto_channel = ap->channel;
+#endif
+
fail :
return res;
}
@@ -4728,21 +5431,23 @@ static int set_ap_cfg(struct net_device *dev, struct ap_profile *ap)
wlc_ssid_t ap_ssid;
int max_assoc = 8;
- int mpc = 0;
int res = 0;
int apsta_var = 0;
+#ifndef AP_ONLY
+ int mpc = 0;
int iolen = 0;
int mkvar_err = 0;
int bsscfg_index = 1;
char buf[WLC_IOCTL_SMLEN];
+#endif
if (!dev) {
WL_ERROR(("%s: dev is null\n", __FUNCTION__));
return -1;
}
- net_os_wake_lock(dev);
+ net_os_wake_lock(dev);
WL_SOFTAP(("wl_iw: set ap profile:\n"));
WL_SOFTAP((" ssid = '%s'\n", ap->ssid));
@@ -4752,8 +5457,16 @@ static int set_ap_cfg(struct net_device *dev, struct ap_profile *ap)
WL_SOFTAP((" channel = %d\n", ap->channel));
WL_SOFTAP((" max scb = %d\n", ap->max_scb));
+#ifdef AP_ONLY
+ if (ap_cfg_running) {
+ wl_iw_softap_deassoc_stations(dev);
+ ap_cfg_running = FALSE;
+ }
+#endif
+
if (ap_cfg_running == FALSE) {
+#ifndef AP_ONLY
sema_init(&ap_eth_sema, 0);
mpc = 0;
@@ -4761,6 +5474,7 @@ static int set_ap_cfg(struct net_device *dev, struct ap_profile *ap)
WL_ERROR(("%s fail to set mpc\n", __FUNCTION__));
goto fail;
}
+#endif
updown = 0;
if ((res = dev_wlc_ioctl(dev, WLC_DOWN, &updown, sizeof(updown)))) {
@@ -4845,6 +5559,15 @@ static int set_ap_cfg(struct net_device *dev, struct ap_profile *ap)
ap_ssid.SSID_len = strlen(ap->ssid);
strncpy(ap_ssid.SSID, ap->ssid, ap_ssid.SSID_len);
+#ifdef AP_ONLY
+ if ((res = wl_iw_set_ap_security(dev, &my_ap)) != 0) {
+ WL_ERROR(("ERROR:%d in:%s, wl_iw_set_ap_security is skipped\n", \
+ res, __FUNCTION__));
+ goto fail;
+ }
+ wl_iw_send_priv_event(dev, "ASCII_CMD=AP_BSS_START");
+ ap_cfg_running = TRUE;
+#else
iolen = wl_bssiovar_mkbuf("ssid", bsscfg_index, (char *)(&ap_ssid),
ap_ssid.SSID_len+4, buf, sizeof(buf), &mkvar_err);
ASSERT(iolen);
@@ -4874,12 +5597,13 @@ static int set_ap_cfg(struct net_device *dev, struct ap_profile *ap)
goto fail;
}
}
+#endif
fail:
WL_SOFTAP(("%s exit with %d\n", __FUNCTION__, res));
- net_os_wake_unlock(dev);
+ net_os_wake_unlock(dev);
- return res;
+ return res;
}
@@ -4890,6 +5614,11 @@ static int wl_iw_set_ap_security(struct net_device *dev, struct ap_profile *ap)
int res = 0;
int i;
char *ptr;
+#ifdef AP_ONLY
+ int mpc = 0;
+ wlc_ssid_t ap_ssid;
+#endif
+ wl_wsec_key_t key;
WL_SOFTAP(("\nsetting SOFTAP security mode:\n"));
WL_SOFTAP(("wl_iw: set ap profile:\n"));
@@ -4912,7 +5641,6 @@ static int wl_iw_set_ap_security(struct net_device *dev, struct ap_profile *ap)
} else if (strnicmp(ap->sec, "wep", strlen("wep")) == 0) {
- wl_wsec_key_t key;
memset(&key, 0, sizeof(key));
wsec = WEP_ENABLED;
@@ -5030,6 +5758,16 @@ static int wl_iw_set_ap_security(struct net_device *dev, struct ap_profile *ap)
WL_SOFTAP((" wsec & auth set 'wpa-psk' (TKIP), result:&d %d\n", res));
}
+#ifdef AP_ONLY
+ ap_ssid.SSID_len = strlen(ap->ssid);
+ strncpy(ap_ssid.SSID, ap->ssid, ap_ssid.SSID_len);
+ res |= dev_wlc_ioctl(dev, WLC_SET_SSID, &ap_ssid, sizeof(ap_ssid));
+ mpc = 0;
+ res |= dev_wlc_intvar_set(dev, "mpc", mpc);
+ if (strnicmp(ap->sec, "wep", strlen("wep")) == 0) {
+ res |= dev_wlc_ioctl(dev, WLC_SET_KEY, &key, sizeof(key));
+ }
+#endif
return res;
}
@@ -5045,7 +5783,7 @@ int get_parmeter_from_string(
char *param_str_end;
char *orig_str = *str_ptr;
- if (!strncmp(*str_ptr, token, strlen(token))) {
+ if ((*str_ptr) && !strncmp(*str_ptr, token, strlen(token))) {
strsep(str_ptr, "=,");
param_str_begin = *str_ptr;
@@ -5163,13 +5901,17 @@ static int iwpriv_softap_stop(struct net_device *dev,
return res;
}
- net_os_wake_lock(dev);
+ net_os_wake_lock(dev);
if ((ap_cfg_running == TRUE)) {
- wl_iw_softap_deassoc_stations(ap_net_dev);
+#ifdef AP_ONLY
+ wl_iw_softap_deassoc_stations(dev);
+#else
+ wl_iw_softap_deassoc_stations(ap_net_dev);
if ((res = dev_iw_write_cfg1_bss_var(dev, 2)) < 0)
WL_ERROR(("%s failed to del BSS err = %d", __FUNCTION__, res));
+#endif
bcm_mdelay(100);
@@ -5181,9 +5923,9 @@ static int iwpriv_softap_stop(struct net_device *dev,
WL_SOFTAP(("%s Done with %d\n", __FUNCTION__, res));
- net_os_wake_unlock(dev);
+ net_os_wake_unlock(dev);
- return res;
+ return res;
}
@@ -5293,10 +6035,11 @@ iwpriv_en_ap_bss(
return -1;
}
- net_os_wake_lock(dev);
+ net_os_wake_lock(dev);
WL_TRACE(("%s: rcvd IWPRIV IOCTL: for dev:%s\n", __FUNCTION__, dev->name));
+#ifndef AP_ONLY
if ((res = wl_iw_set_ap_security(dev, &my_ap)) != 0) {
WL_ERROR((" %s ERROR setting SOFTAP security in :%d\n", __FUNCTION__, res));
}
@@ -5307,9 +6050,10 @@ iwpriv_en_ap_bss(
bcm_mdelay(100);
}
+#endif
WL_SOFTAP(("%s done with res %d \n", __FUNCTION__, res));
- net_os_wake_unlock(dev);
+ net_os_wake_unlock(dev);
return res;
}
@@ -5440,6 +6184,7 @@ int wl_iw_process_private_ascii_cmd(
WL_SOFTAP(("\n!!! got 'WL_AP_EN_BSS' from WPA supplicant, dev:%s\n", dev->name));
+#ifndef AP_ONLY
if (ap_net_dev == NULL) {
printf("\n ERROR: SOFTAP net_dev* is NULL !!!\n");
} else {
@@ -5447,15 +6192,21 @@ int wl_iw_process_private_ascii_cmd(
WL_ERROR(("%s line %d fail to set bss up\n", \
__FUNCTION__, __LINE__));
}
-
+#else
+ if ((ret = iwpriv_en_ap_bss(dev, info, dwrq, cmd_str)) < 0)
+ WL_ERROR(("%s line %d fail to set bss up\n", \
+ __FUNCTION__, __LINE__));
+#endif
} else if (strnicmp(sub_cmd, "ASSOC_LST", strlen("ASSOC_LST")) == 0) {
/* no code yet */
} else if (strnicmp(sub_cmd, "AP_BSS_STOP", strlen("AP_BSS_STOP")) == 0) {
WL_SOFTAP((" \n temp DOWN SOFTAP\n"));
+#ifndef AP_ONLY
if ((ret = dev_iw_write_cfg1_bss_var(dev, 0)) < 0) {
WL_ERROR(("%s line %d fail to set bss down\n", \
__FUNCTION__, __LINE__));
}
+#endif
}
return ret;
@@ -5520,6 +6271,14 @@ static int wl_iw_set_priv(
ret = wl_iw_set_country(dev, info, (union iwreq_data *)dwrq, extra);
else if (strnicmp(extra, "STOP", strlen("STOP")) == 0)
ret = wl_iw_control_wl_off(dev, info);
+ else if (strnicmp(extra, BAND_GET_CMD, strlen(BAND_GET_CMD)) == 0)
+ ret = wl_iw_get_band(dev, info, (union iwreq_data *)dwrq, extra);
+ else if (strnicmp(extra, BAND_SET_CMD, strlen(BAND_SET_CMD)) == 0)
+ ret = wl_iw_set_band(dev, info, (union iwreq_data *)dwrq, extra);
+#if defined(CSCAN)
+ else if (strnicmp(extra, CSCAN_COMMAND, strlen(CSCAN_COMMAND)) == 0)
+ ret = wl_iw_set_cscan(dev, info, (union iwreq_data *)dwrq, extra);
+#endif
#ifdef CUSTOMER_HW2
else if (strnicmp(extra, "POWERMODE", strlen("POWERMODE")) == 0)
ret = wl_iw_set_power_mode(dev, info, (union iwreq_data *)dwrq, extra);
@@ -5529,6 +6288,10 @@ static int wl_iw_set_priv(
else if (strnicmp(extra, "POWERMODE", strlen("POWERMODE")) == 0)
ret = wl_iw_set_btcoex_dhcp(dev, info, (union iwreq_data *)dwrq, extra);
#endif
+ else if (strnicmp(extra, "GETPOWER", strlen("GETPOWER")) == 0)
+ ret = wl_iw_get_power_mode(dev, info, (union iwreq_data *)dwrq, extra);
+ else if (strnicmp(extra, "SETSUSPEND", strlen("SETSUSPEND")) == 0)
+ ret = wl_iw_set_suspend(dev, info, (union iwreq_data *)dwrq, extra);
#ifdef SOFTAP
else if (strnicmp(extra, "ASCII_CMD", strlen("ASCII_CMD")) == 0) {
wl_iw_process_private_ascii_cmd(dev, info, (union iwreq_data *)dwrq, extra);
@@ -5677,8 +6440,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[] = {
@@ -5775,6 +6543,14 @@ static const struct iw_priv_args wl_iw_priv_args[] = {
"WL_FW_RELOAD"
},
#endif
+#if defined(CSCAN)
+ {
+ WL_COMBO_SCAN,
+ IW_PRIV_TYPE_CHAR | 1024,
+ 0,
+ "CSCAN"
+ },
+#endif
};
const struct iw_handler_def wl_iw_handler_def =
@@ -5805,11 +6581,14 @@ int wl_iw_ioctl(
char *extra = NULL;
int token_size = 1, max_tokens = 0, ret = 0;
+ net_os_wake_lock(dev);
+
WL_TRACE(("%s: cmd:%x alled via dhd->do_ioctl()entry point\n", __FUNCTION__, cmd));
if (cmd < SIOCIWFIRST ||
IW_IOCTL_IDX(cmd) >= ARRAYSIZE(wl_iw_handler) ||
!(handler = wl_iw_handler[IW_IOCTL_IDX(cmd)])) {
WL_ERROR(("%s: error in cmd=%x : not supported\n", __FUNCTION__, cmd));
+ net_os_wake_unlock(dev);
return -EOPNOTSUPP;
}
@@ -5874,14 +6653,18 @@ int wl_iw_ioctl(
if (wrq->u.data.length > max_tokens) {
WL_ERROR(("%s: error in cmd=%x wrq->u.data.length=%d > max_tokens=%d\n", \
__FUNCTION__, cmd, wrq->u.data.length, max_tokens));
- return -E2BIG;
+ ret = -E2BIG;
+ goto wl_iw_ioctl_done;
+ }
+ if (!(extra = kmalloc(max_tokens * token_size, GFP_KERNEL))) {
+ ret = -ENOMEM;
+ goto wl_iw_ioctl_done;
}
- if (!(extra = kmalloc(max_tokens * token_size, GFP_KERNEL)))
- return -ENOMEM;
if (copy_from_user(extra, wrq->u.data.pointer, wrq->u.data.length * token_size)) {
kfree(extra);
- return -EFAULT;
+ ret = -EFAULT;
+ goto wl_iw_ioctl_done;
}
}
@@ -5893,12 +6676,17 @@ int wl_iw_ioctl(
if (extra) {
if (copy_to_user(wrq->u.data.pointer, extra, wrq->u.data.length * token_size)) {
kfree(extra);
- return -EFAULT;
+ ret = -EFAULT;
+ goto wl_iw_ioctl_done;
}
kfree(extra);
}
+wl_iw_ioctl_done:
+
+ net_os_wake_unlock(dev);
+
return ret;
}
@@ -6024,7 +6812,7 @@ wl_iw_event(struct net_device *dev, wl_event_msg_t *e, void* data)
return;
}
- net_os_wake_lock(dev);
+ net_os_wake_lock(dev);
WL_TRACE(("%s: dev=%s event=%d \n", __FUNCTION__, dev->name, event_type));
@@ -6097,7 +6885,11 @@ wl_iw_event(struct net_device *dev, wl_event_msg_t *e, void* data)
cmd = SIOCGIWAP;
if (!(flags & WLC_EVENT_MSG_LINK)) {
#ifdef SOFTAP
+#ifdef AP_ONLY
+ if (ap_cfg_running) {
+#else
if (ap_cfg_running && !strncmp(dev->name, "wl0.1", 5)) {
+#endif
WL_SOFTAP(("AP DOWN %d\n", event_type));
wl_iw_send_priv_event(priv_dev, "AP_DOWN");
} else {
@@ -6111,7 +6903,6 @@ wl_iw_event(struct net_device *dev, wl_event_msg_t *e, void* data)
bzero(wrqu.addr.sa_data, ETHER_ADDR_LEN);
bzero(&extra, ETHER_ADDR_LEN);
- net_os_wake_lock_timeout_enable(dev);
}
else {
memcpy(wrqu.addr.sa_data, &e->addr, ETHER_ADDR_LEN);
@@ -6120,7 +6911,11 @@ wl_iw_event(struct net_device *dev, wl_event_msg_t *e, void* data)
memcpy(g_ss_cache_ctrl.m_active_bssid, &e->addr, ETHER_ADDR_LEN);
#ifdef SOFTAP
+#ifdef AP_ONLY
+ if (ap_cfg_running) {
+#else
if (ap_cfg_running && !strncmp(dev->name, "wl0.1", 5)) {
+#endif
WL_SOFTAP(("AP UP %d\n", event_type));
wl_iw_send_priv_event(priv_dev, "AP_UP");
} else {
@@ -6130,6 +6925,7 @@ wl_iw_event(struct net_device *dev, wl_event_msg_t *e, void* data)
WL_TRACE(("Link UP\n"));
}
+ net_os_wake_lock_timeout_enable(dev);
wrqu.addr.sa_family = ARPHRD_ETHER;
break;
case WLC_E_ACTION_FRAME:
@@ -6210,13 +7006,14 @@ wl_iw_event(struct net_device *dev, wl_event_msg_t *e, void* data)
} else {
cmd = SIOCGIWSCAN;
wrqu.data.length = strlen(extra);
- WL_TRACE(("Event WLC_E_SCAN_COMPLETE from specific scan\n"));
+ WL_TRACE(("Event WLC_E_SCAN_COMPLETE from specific scan %d\n", \
+ g_iscan->iscan_state));
}
#else
cmd = SIOCGIWSCAN;
wrqu.data.length = strlen(extra);
WL_TRACE(("Event WLC_E_SCAN_COMPLETE\n"));
-#endif
+#endif
break;
default:
@@ -6247,8 +7044,8 @@ wl_iw_event(struct net_device *dev, wl_event_msg_t *e, void* data)
}
#endif
wl_iw_event_end:
- net_os_wake_unlock(dev);
-#endif
+ net_os_wake_unlock(dev);
+#endif
}
int wl_iw_get_wireless_stats(struct net_device *dev, struct iw_statistics *wstats)
@@ -6416,7 +7213,7 @@ _bt_dhcp_sysioc_thread(void *data)
g_bt->bt_state = BT_DHCP_IDLE;
g_bt->timer_on = 0;
break;
- }
+ }
net_os_wake_unlock(g_bt->dev);
}
@@ -6480,6 +7277,7 @@ wl_iw_bt_init(struct net_device *dev)
int wl_iw_attach(struct net_device *dev, void * dhdp)
{
+ int params_size;
wl_iw_t *iw;
#if defined(WL_IW_USE_ISCAN)
iscan_info_t *iscan = NULL;
@@ -6492,10 +7290,21 @@ int wl_iw_attach(struct net_device *dev, void * dhdp)
if (!dev)
return 0;
+#ifdef CSCAN
+ params_size = (WL_SCAN_PARAMS_FIXED_SIZE + OFFSETOF(wl_iscan_params_t, params)) +
+ (WL_NUMCHANNELS * sizeof(uint16)) + WL_SCAN_PARAMS_SSID_MAX * sizeof(wlc_ssid_t);
+#else
+ params_size = (WL_SCAN_PARAMS_FIXED_SIZE + OFFSETOF(wl_iscan_params_t, params));
+#endif
iscan = kmalloc(sizeof(iscan_info_t), GFP_KERNEL);
if (!iscan)
return -ENOMEM;
memset(iscan, 0, sizeof(iscan_info_t));
+
+ iscan->iscan_ex_params_p = (wl_iscan_params_t*)kmalloc(params_size, GFP_KERNEL);
+ if (!iscan->iscan_ex_params_p)
+ return -ENOMEM;
+ iscan->iscan_ex_param_size = params_size;
iscan->sysioc_pid = -1;
g_iscan = iscan;
@@ -6530,11 +7339,12 @@ int wl_iw_attach(struct net_device *dev, void * dhdp)
memset(g_scan, 0, G_SCAN_RESULTS);
g_scan_specified_ssid = 0;
+#if !defined(CSCAN)
wl_iw_init_ss_cache_ctrl();
+#endif
wl_iw_bt_init(dev);
-
return 0;
}
@@ -6556,6 +7366,7 @@ void wl_iw_detach(void)
kfree(iscan->list_hdr);
iscan->list_hdr = buf;
}
+ kfree(iscan->iscan_ex_params_p);
kfree(iscan);
g_iscan = NULL;
mutex_unlock(&wl_cache_lock);
@@ -6565,7 +7376,9 @@ void wl_iw_detach(void)
kfree(g_scan);
g_scan = NULL;
+#if !defined(CSCAN)
wl_iw_release_ss_cache_ctrl();
+#endif
wl_iw_bt_release();
#ifdef SOFTAP
if (ap_cfg_running) {