mwifiex: add support for WPS2.0

This patches enables setting association request and probe request
IE for station interface. WPS exchange between WPS2.0 AP and mwifiex
STA Enrollee/External Registrar completes successfully.

Tested with wpa_supplicant 1.0 and 2.0 devel.

Signed-off-by: Avinash Patil <patila@marvell.com>
Signed-off-by: Kiran Divekar <dkiran@marvell.com>
Signed-off-by: Bing Zhao <bzhao@marvell.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
This commit is contained in:
Avinash Patil 2012-04-09 20:06:56 -07:00 committed by John W. Linville
parent 5e218b7ab8
commit 13d7ba78b5
7 changed files with 105 additions and 0 deletions

View File

@ -1162,6 +1162,17 @@ mwifiex_cfg80211_scan(struct wiphy *wiphy, struct net_device *dev,
priv->user_scan_cfg->num_ssids = request->n_ssids;
priv->user_scan_cfg->ssid_list = request->ssids;
if (request->ie && request->ie_len) {
for (i = 0; i < MWIFIEX_MAX_VSIE_NUM; i++) {
if (priv->vs_ie[i].mask != MWIFIEX_VSIE_MASK_CLEAR)
continue;
priv->vs_ie[i].mask = MWIFIEX_VSIE_MASK_SCAN;
memcpy(&priv->vs_ie[i].ie, request->ie,
request->ie_len);
break;
}
}
for (i = 0; i < request->n_channels; i++) {
chan = request->channels[i];
priv->user_scan_cfg->chan_list[i].chan_number = chan->hw_value;
@ -1179,6 +1190,15 @@ mwifiex_cfg80211_scan(struct wiphy *wiphy, struct net_device *dev,
if (mwifiex_set_user_scan_ioctl(priv, priv->user_scan_cfg))
return -EFAULT;
if (request->ie && request->ie_len) {
for (i = 0; i < MWIFIEX_MAX_VSIE_NUM; i++) {
if (priv->vs_ie[i].mask == MWIFIEX_VSIE_MASK_SCAN) {
priv->vs_ie[i].mask = MWIFIEX_VSIE_MASK_CLEAR;
memset(&priv->vs_ie[i].ie, 0,
MWIFIEX_MAX_VSIE_LEN);
}
}
}
return 0;
}
@ -1439,6 +1459,7 @@ int mwifiex_register_cfg80211(struct mwifiex_private *priv)
}
wdev->iftype = NL80211_IFTYPE_STATION;
wdev->wiphy->max_scan_ssids = 10;
wdev->wiphy->max_scan_ie_len = MWIFIEX_MAX_VSIE_LEN;
wdev->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) |
BIT(NL80211_IFTYPE_ADHOC);

View File

@ -104,6 +104,7 @@ enum MWIFIEX_802_11_PRIVACY_FILTER {
#define TLV_TYPE_RATE_SCOPE (PROPRIETARY_TLV_BASE_ID + 83)
#define TLV_TYPE_POWER_GROUP (PROPRIETARY_TLV_BASE_ID + 84)
#define TLV_TYPE_WAPI_IE (PROPRIETARY_TLV_BASE_ID + 94)
#define TLV_TYPE_MGMT_IE (PROPRIETARY_TLV_BASE_ID + 105)
#define TLV_TYPE_AUTO_DS_PARAM (PROPRIETARY_TLV_BASE_ID + 113)
#define TLV_TYPE_PS_PARAM (PROPRIETARY_TLV_BASE_ID + 114)

View File

@ -131,6 +131,8 @@ static int mwifiex_init_priv(struct mwifiex_private *priv)
priv->wmm_qosinfo = 0;
priv->curr_bcn_buf = NULL;
priv->curr_bcn_size = 0;
priv->wps_ie = NULL;
priv->wps_ie_len = 0;
priv->scan_block = false;

View File

@ -303,6 +303,7 @@ struct mwifiex_ds_misc_subsc_evt {
#define MWIFIEX_MAX_VSIE_LEN (256)
#define MWIFIEX_MAX_VSIE_NUM (8)
#define MWIFIEX_VSIE_MASK_CLEAR 0x00
#define MWIFIEX_VSIE_MASK_SCAN 0x01
#define MWIFIEX_VSIE_MASK_ASSOC 0x02
#define MWIFIEX_VSIE_MASK_ADHOC 0x04

View File

@ -224,6 +224,48 @@ mwifiex_setup_rates_from_bssdesc(struct mwifiex_private *priv,
return 0;
}
/*
* This function appends a WPS IE. It is called from the network join command
* preparation routine.
*
* If the IE buffer has been setup by the application, this routine appends
* the buffer as a WPS TLV type to the request.
*/
static int
mwifiex_cmd_append_wps_ie(struct mwifiex_private *priv, u8 **buffer)
{
int retLen = 0;
struct mwifiex_ie_types_header ie_header;
if (!buffer || !*buffer)
return 0;
/*
* If there is a wps ie buffer setup, append it to the return
* parameter buffer pointer.
*/
if (priv->wps_ie_len) {
dev_dbg(priv->adapter->dev, "cmd: append wps ie %d to %p\n",
priv->wps_ie_len, *buffer);
/* Wrap the generic IE buffer with a pass through TLV type */
ie_header.type = cpu_to_le16(TLV_TYPE_MGMT_IE);
ie_header.len = cpu_to_le16(priv->wps_ie_len);
memcpy(*buffer, &ie_header, sizeof(ie_header));
*buffer += sizeof(ie_header);
retLen += sizeof(ie_header);
memcpy(*buffer, priv->wps_ie, priv->wps_ie_len);
*buffer += priv->wps_ie_len;
retLen += priv->wps_ie_len;
}
kfree(priv->wps_ie);
priv->wps_ie_len = 0;
return retLen;
}
/*
* This function appends a WAPI IE.
*
@ -480,6 +522,8 @@ int mwifiex_cmd_802_11_associate(struct mwifiex_private *priv,
if (priv->sec_info.wapi_enabled && priv->wapi_ie_len)
mwifiex_cmd_append_wapi_ie(priv, &pos);
if (priv->wps.session_enable && priv->wps_ie_len)
mwifiex_cmd_append_wps_ie(priv, &pos);
mwifiex_cmd_append_generic_ie(priv, &pos);

View File

@ -407,6 +407,8 @@ struct mwifiex_private {
struct host_cmd_ds_802_11_key_material aes_key;
u8 wapi_ie[256];
u8 wapi_ie_len;
u8 *wps_ie;
u8 wps_ie_len;
u8 wmm_required;
u8 wmm_enabled;
u8 wmm_qosinfo;

View File

@ -996,6 +996,39 @@ static int mwifiex_set_wapi_ie(struct mwifiex_private *priv,
return 0;
}
/*
* IOCTL request handler to set/reset WPS IE.
*
* The supplied WPS IE is treated as a opaque buffer. Only the first field
* is checked to internally enable WPS. If buffer length is zero, the existing
* WPS IE is reset.
*/
static int mwifiex_set_wps_ie(struct mwifiex_private *priv,
u8 *ie_data_ptr, u16 ie_len)
{
if (ie_len) {
priv->wps_ie = kzalloc(MWIFIEX_MAX_VSIE_LEN, GFP_KERNEL);
if (!priv->wps_ie)
return -ENOMEM;
if (ie_len > sizeof(priv->wps_ie)) {
dev_dbg(priv->adapter->dev,
"info: failed to copy WPS IE, too big\n");
kfree(priv->wps_ie);
return -1;
}
memcpy(priv->wps_ie, ie_data_ptr, ie_len);
priv->wps_ie_len = ie_len;
dev_dbg(priv->adapter->dev, "cmd: Set wps_ie_len=%d IE=%#x\n",
priv->wps_ie_len, priv->wps_ie[0]);
} else {
kfree(priv->wps_ie);
priv->wps_ie_len = ie_len;
dev_dbg(priv->adapter->dev,
"info: Reset wps_ie_len=%d\n", priv->wps_ie_len);
}
return 0;
}
/*
* IOCTL request handler to set WAPI key.
*
@ -1409,6 +1442,7 @@ mwifiex_set_gen_ie_helper(struct mwifiex_private *priv, u8 *ie_data_ptr,
priv->wps.session_enable = true;
dev_dbg(priv->adapter->dev,
"info: WPS Session Enabled.\n");
ret = mwifiex_set_wps_ie(priv, ie_data_ptr, ie_len);
}
/* Append the passed data to the end of the