diff options
Diffstat (limited to 'drivers/net/wireless/marvell/libertas/cfg.c')
-rw-r--r-- | drivers/net/wireless/marvell/libertas/cfg.c | 76 |
1 files changed, 63 insertions, 13 deletions
diff --git a/drivers/net/wireless/marvell/libertas/cfg.c b/drivers/net/wireless/marvell/libertas/cfg.c index 3e065cbb0af9..b700c213d10c 100644 --- a/drivers/net/wireless/marvell/libertas/cfg.c +++ b/drivers/net/wireless/marvell/libertas/cfg.c @@ -416,10 +416,20 @@ static int lbs_add_cf_param_tlv(u8 *tlv) static int lbs_add_wpa_tlv(u8 *tlv, const u8 *ie, u8 ie_len) { - size_t tlv_len; + struct mrvl_ie_data *wpatlv = (struct mrvl_ie_data *)tlv; + const struct element *wpaie; + + /* Find the first RSN or WPA IE to use */ + wpaie = cfg80211_find_elem(WLAN_EID_RSN, ie, ie_len); + if (!wpaie) + wpaie = cfg80211_find_vendor_elem(WLAN_OUI_MICROSOFT, + WLAN_OUI_TYPE_MICROSOFT_WPA, + ie, ie_len); + if (!wpaie || wpaie->datalen > 128) + return 0; /* - * We need just convert an IE to an TLV. IEs use u8 for the header, + * Convert the found IE to a TLV. IEs use u8 for the header, * u8 type * u8 len * u8[] data @@ -428,14 +438,47 @@ static int lbs_add_wpa_tlv(u8 *tlv, const u8 *ie, u8 ie_len) * __le16 len * u8[] data */ - *tlv++ = *ie++; - *tlv++ = 0; - tlv_len = *tlv++ = *ie++; - *tlv++ = 0; - while (tlv_len--) - *tlv++ = *ie++; - /* the TLV is two bytes larger than the IE */ - return ie_len + 2; + wpatlv->header.type = cpu_to_le16(wpaie->id); + wpatlv->header.len = cpu_to_le16(wpaie->datalen); + memcpy(wpatlv->data, wpaie->data, wpaie->datalen); + + /* Return the total number of bytes added to the TLV buffer */ + return sizeof(struct mrvl_ie_header) + wpaie->datalen; +} + +/* Add WPS enrollee TLV + */ +#define LBS_MAX_WPS_ENROLLEE_TLV_SIZE \ + (sizeof(struct mrvl_ie_header) \ + + 256) + +static int lbs_add_wps_enrollee_tlv(u8 *tlv, const u8 *ie, size_t ie_len) +{ + struct mrvl_ie_data *wpstlv = (struct mrvl_ie_data *)tlv; + const struct element *wpsie; + + /* Look for a WPS IE and add it to the probe request */ + wpsie = cfg80211_find_vendor_elem(WLAN_OUI_MICROSOFT, + WLAN_OUI_TYPE_MICROSOFT_WPS, + ie, ie_len); + if (!wpsie) + return 0; + + /* Convert the WPS IE to a TLV. The IE looks like this: + * u8 type (WLAN_EID_VENDOR_SPECIFIC) + * u8 len + * u8[] data + * but the TLV will look like this instead: + * __le16 type (TLV_TYPE_WPS_ENROLLEE) + * __le16 len + * u8[] data + */ + wpstlv->header.type = cpu_to_le16(TLV_TYPE_WPS_ENROLLEE); + wpstlv->header.len = cpu_to_le16(wpsie->datalen); + memcpy(wpstlv->data, wpsie->data, wpsie->datalen); + + /* Return the total number of bytes added to the TLV buffer */ + return sizeof(struct mrvl_ie_header) + wpsie->datalen; } /* @@ -664,14 +707,15 @@ static int lbs_ret_scan(struct lbs_private *priv, unsigned long dummy, /* - * Our scan command contains a TLV, consting of a SSID TLV, a channel list - * TLV and a rates TLV. Determine the maximum size of them: + * Our scan command contains a TLV, consisting of a SSID TLV, a channel list + * TLV, a rates TLV, and an optional WPS IE. Determine the maximum size of them: */ #define LBS_SCAN_MAX_CMD_SIZE \ (sizeof(struct cmd_ds_802_11_scan) \ + LBS_MAX_SSID_TLV_SIZE \ + LBS_MAX_CHANNEL_LIST_TLV_SIZE \ - + LBS_MAX_RATES_TLV_SIZE) + + LBS_MAX_RATES_TLV_SIZE \ + + LBS_MAX_WPS_ENROLLEE_TLV_SIZE) /* * Assumes priv->scan_req is initialized and valid @@ -720,6 +764,11 @@ static void lbs_scan_worker(struct work_struct *work) /* add rates TLV */ tlv += lbs_add_supported_rates_tlv(tlv); + /* add optional WPS enrollee TLV */ + if (priv->scan_req->ie && priv->scan_req->ie_len) + tlv += lbs_add_wps_enrollee_tlv(tlv, priv->scan_req->ie, + priv->scan_req->ie_len); + if (priv->scan_channel < priv->scan_req->n_channels) { cancel_delayed_work(&priv->scan_work); if (netif_running(priv->dev)) @@ -2106,6 +2155,7 @@ int lbs_cfg_register(struct lbs_private *priv) int ret; wdev->wiphy->max_scan_ssids = 1; + wdev->wiphy->max_scan_ie_len = 256; wdev->wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM; wdev->wiphy->interface_modes = |