summaryrefslogtreecommitdiff
path: root/drivers/net/wireless/bcmdhd/wl_iw.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wireless/bcmdhd/wl_iw.c')
-rw-r--r--drivers/net/wireless/bcmdhd/wl_iw.c154
1 files changed, 141 insertions, 13 deletions
diff --git a/drivers/net/wireless/bcmdhd/wl_iw.c b/drivers/net/wireless/bcmdhd/wl_iw.c
index 32f7b57d2d49..8a8f8a59c688 100644
--- a/drivers/net/wireless/bcmdhd/wl_iw.c
+++ b/drivers/net/wireless/bcmdhd/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.132.2.18 2011-02-05 01:44:47 Exp $
+ * $Id: wl_iw.c,v 1.132.2.18 2011-02-05 01:44:47 $
*/
#include <wlioctl.h>
@@ -162,11 +162,8 @@ uint wl_msg_level = WL_ERROR_VAL;
#define htodchanspec(i) i
#define dtohchanspec(i) i
-#ifdef CONFIG_WIRELESS_EXT
-
extern struct iw_statistics *dhd_get_wireless_stats(struct net_device *dev);
extern int dhd_wait_pend8021x(struct net_device *dev);
-#endif
#if WIRELESS_EXT < 19
#define IW_IOCTL_IDX(cmd) ((cmd) - SIOCIWFIRST)
@@ -1122,7 +1119,7 @@ wl_iw_set_btcoex_dhcp(
}
static int
-wl_iw_set_suspend(
+wl_iw_set_suspend_opt(
struct net_device *dev,
struct iw_request_info *info,
union iwreq_data *wrqu,
@@ -1133,16 +1130,15 @@ char *extra
int ret_now;
int ret = 0;
- suspend_flag = *(extra + strlen(SETSUSPEND_CMD) + 1) - '0';
+ suspend_flag = *(extra + strlen(SETSUSPENDOPT_CMD) + 1) - '0';
if (suspend_flag != 0)
suspend_flag = 1;
ret_now = net_os_set_suspend_disable(dev, suspend_flag);
-
if (ret_now != suspend_flag) {
- if (!(ret = net_os_set_suspend(dev, ret_now)))
+ if (!(ret = net_os_set_suspend(dev, ret_now, 1)))
WL_ERROR(("%s: Suspend Flag %d -> %d\n",
__FUNCTION__, ret_now, suspend_flag));
else
@@ -1153,6 +1149,32 @@ char *extra
}
static int
+wl_iw_set_suspend_mode(
+struct net_device *dev,
+struct iw_request_info *info,
+union iwreq_data *wrqu,
+char *extra
+)
+{
+ int ret = 0;
+
+#if !defined(CONFIG_HAS_EARLYSUSPEND) || !defined(DHD_USE_EARLYSUSPEND)
+ int suspend_flag;
+
+ suspend_flag = *(extra + strlen(SETSUSPENDMODE_CMD) + 1) - '0';
+
+ if (suspend_flag != 0)
+ suspend_flag = 1;
+
+ if (!(ret = net_os_set_suspend(dev, suspend_flag, 0)))
+ WL_ERROR(("%s: Suspend Mode %d\n",__FUNCTION__,suspend_flag));
+ else
+ WL_ERROR(("%s: failed %d\n", __FUNCTION__, ret));
+#endif
+ return ret;
+}
+
+static int
wl_format_ssid(char* ssid_buf, uint8* ssid, int ssid_len)
{
int i, c;
@@ -1564,6 +1586,63 @@ exit_proc:
net_os_wake_unlock(dev);
return res;
}
+
+static int
+wl_iw_set_pno_setadd(
+ struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu,
+ char *extra
+)
+{
+ int ret = -1;
+ char *tmp_ptr;
+ int size, tmp_size;
+
+ net_os_wake_lock(dev);
+ WL_ERROR(("\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__));
+ goto exit_proc;
+ }
+
+ if (wrqu->data.length <= strlen(PNOSETADD_SET_CMD) + sizeof(cmd_tlv_t)) {
+ WL_ERROR(("%s argument=%d less than %d\n", __FUNCTION__,
+ wrqu->data.length, (int)(strlen(PNOSETADD_SET_CMD) + sizeof(cmd_tlv_t))));
+ goto exit_proc;
+ }
+
+
+ bcopy(PNOSETUP_SET_CMD, extra, strlen(PNOSETUP_SET_CMD));
+
+ tmp_ptr = extra + strlen(PNOSETUP_SET_CMD);
+ size = wrqu->data.length - strlen(PNOSETUP_SET_CMD);
+ tmp_size = size;
+
+ while (*tmp_ptr && tmp_size > 0) {
+ if ((*tmp_ptr == 'S') && (size - tmp_size) >= sizeof(cmd_tlv_t)) {
+ *(tmp_ptr + 1) = ((*(tmp_ptr + 1) - '0') << 4) + (*(tmp_ptr + 2) - '0');
+ memmove(tmp_ptr + 2, tmp_ptr + 3, tmp_size - 3);
+ tmp_size -= 2 + *(tmp_ptr + 1);
+ tmp_ptr += 2 + *(tmp_ptr + 1);
+ size--;
+ } else {
+ tmp_ptr++;
+ tmp_size--;
+ }
+ }
+
+ wrqu->data.length = strlen(PNOSETUP_SET_CMD) + size;
+ ret = wl_iw_set_pno_set(dev, info, wrqu, extra);
+
+exit_proc:
+ net_os_wake_unlock(dev);
+ return ret;
+
+}
#endif
static int
@@ -1626,7 +1705,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, DHD_EVENT_TIMEOUT_MS);
+ net_os_wake_lock_ctrl_timeout_enable(dev, DHD_EVENT_TIMEOUT_MS);
WL_TRACE(("Send IWEVCUSTOM Event as %s\n", extra));
return 0;
@@ -2567,6 +2646,8 @@ wl_iw_get_range(
IW_EVENT_CAPA_SET(range->event_capa, SIOCGIWSCAN);
IW_EVENT_CAPA_SET(range->event_capa, IWEVTXDROP);
IW_EVENT_CAPA_SET(range->event_capa, IWEVMICHAELMICFAILURE);
+ IW_EVENT_CAPA_SET(range->event_capa, IWEVASSOCREQIE);
+ IW_EVENT_CAPA_SET(range->event_capa, IWEVASSOCRESPIE);
IW_EVENT_CAPA_SET(range->event_capa, IWEVPMKIDCAND);
#endif
@@ -5473,7 +5554,15 @@ wl_iw_set_wpaauth(
switch (paramid) {
case IW_AUTH_WPA_VERSION:
- iw->wpaversion = paramval;
+ if (paramval & IW_AUTH_WPA_VERSION_DISABLED)
+ val = WPA_AUTH_DISABLED;
+ else if (paramval & (IW_AUTH_WPA_VERSION_WPA))
+ val = WPA_AUTH_PSK | WPA_AUTH_UNSPECIFIED;
+ else if (paramval & IW_AUTH_WPA_VERSION_WPA2)
+ val = WPA2_AUTH_PSK | WPA2_AUTH_UNSPECIFIED;
+ WL_ERROR(("%s: %d: setting wpa_auth to 0x%0x\n", __FUNCTION__, __LINE__, val));
+ if ((error = dev_wlc_intvar_set(dev, "wpa_auth", val)))
+ return error;
break;
case IW_AUTH_CIPHER_PAIRWISE:
@@ -5491,7 +5580,27 @@ wl_iw_set_wpaauth(
break;
case IW_AUTH_KEY_MGMT:
- if (paramval & IW_AUTH_KEY_MGMT_PSK) {
+ if ((error = dev_wlc_intvar_get(dev, "wpa_auth", &val)))
+ return error;
+
+ if (val & (WPA_AUTH_PSK | WPA_AUTH_UNSPECIFIED)) {
+ if (paramval & IW_AUTH_KEY_MGMT_PSK)
+ val = WPA_AUTH_PSK;
+ else
+ val = WPA_AUTH_UNSPECIFIED;
+ if (paramval & 0x04)
+ val |= WPA2_AUTH_FT;
+ }
+ else if (val & (WPA2_AUTH_PSK | WPA2_AUTH_UNSPECIFIED)) {
+ if (paramval & IW_AUTH_KEY_MGMT_PSK)
+ val = WPA2_AUTH_PSK;
+ else
+ val = WPA2_AUTH_UNSPECIFIED;
+ if (paramval & 0x04)
+ val |= WPA2_AUTH_FT;
+ }
+
+ else if (paramval & IW_AUTH_KEY_MGMT_PSK) {
if (iw->wpaversion == IW_AUTH_WPA_VERSION_WPA)
val = WPA_AUTH_PSK;
else if (iw->wpaversion == IW_AUTH_WPA_VERSION_WPA2)
@@ -7517,8 +7626,10 @@ wl_iw_set_priv(
ret = wl_iw_get_dtim_skip(dev, info, (union iwreq_data *)dwrq, extra);
else if (strnicmp(extra, DTIM_SKIP_SET_CMD, strlen(DTIM_SKIP_SET_CMD)) == 0)
ret = wl_iw_set_dtim_skip(dev, info, (union iwreq_data *)dwrq, extra);
- else if (strnicmp(extra, SETSUSPEND_CMD, strlen(SETSUSPEND_CMD)) == 0)
- ret = wl_iw_set_suspend(dev, info, (union iwreq_data *)dwrq, extra);
+ else if (strnicmp(extra, SETSUSPENDOPT_CMD, strlen(SETSUSPENDOPT_CMD)) == 0)
+ ret = wl_iw_set_suspend_opt(dev, info, (union iwreq_data *)dwrq, extra);
+ else if (strnicmp(extra, SETSUSPENDMODE_CMD, strlen(SETSUSPENDMODE_CMD)) == 0)
+ ret = wl_iw_set_suspend_mode(dev, info, (union iwreq_data *)dwrq, extra);
else if (strnicmp(extra, TXPOWER_SET_CMD, strlen(TXPOWER_SET_CMD)) == 0)
ret = wl_iw_set_txpower(dev, info, (union iwreq_data *)dwrq, extra);
#if defined(PNO_SUPPORT)
@@ -7526,6 +7637,8 @@ wl_iw_set_priv(
ret = wl_iw_set_pno_reset(dev, info, (union iwreq_data *)dwrq, extra);
else if (strnicmp(extra, PNOSETUP_SET_CMD, strlen(PNOSETUP_SET_CMD)) == 0)
ret = wl_iw_set_pno_set(dev, info, (union iwreq_data *)dwrq, extra);
+ else if (strnicmp(extra, PNOSETADD_SET_CMD, strlen(PNOSETADD_SET_CMD)) == 0)
+ ret = wl_iw_set_pno_setadd(dev, info, (union iwreq_data *)dwrq, extra);
else if (strnicmp(extra, PNOENABLE_SET_CMD, strlen(PNOENABLE_SET_CMD)) == 0)
ret = wl_iw_set_pno_enable(dev, info, (union iwreq_data *)dwrq, extra);
#endif
@@ -8251,6 +8364,21 @@ wl_iw_event(struct net_device *dev, wl_event_msg_t *e, void* data)
break;
}
+
+ case WLC_E_ASSOC_REQ_IE:
+ cmd = IWEVASSOCREQIE;
+ wrqu.data.length = datalen;
+ if (datalen < sizeof(extra))
+ memcpy(extra, data, datalen);
+ break;
+
+ case WLC_E_ASSOC_RESP_IE:
+ cmd = IWEVASSOCRESPIE;
+ wrqu.data.length = datalen;
+ if (datalen < sizeof(extra))
+ memcpy(extra, data, datalen);
+ break;
+
case WLC_E_PMKID_CACHE: {
if (data)
{