Return-path: Received: from mail-ew0-f46.google.com ([209.85.215.46]:64124 "EHLO mail-ew0-f46.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753079Ab1GZPnu (ORCPT ); Tue, 26 Jul 2011 11:43:50 -0400 Received: by ewy4 with SMTP id 4so521894ewy.19 for ; Tue, 26 Jul 2011 08:43:49 -0700 (PDT) Subject: Re: [RFC v4 3/4] mac80211: Add HT helper functions From: Alexander Simon To: linux-wireless@vger.kernel.org In-Reply-To: <1311694819.2974.3.camel@alex-2> References: <1311694819.2974.3.camel@alex-2> Content-Type: text/plain; charset="UTF-8" Date: Tue, 26 Jul 2011 17:43:46 +0200 Message-ID: <1311695026.2974.6.camel@alex-2> (sfid-20110726_174353_941670_340A9305) Mime-Version: 1.0 Sender: linux-wireless-owner@vger.kernel.org List-ID: these can also be used from existing code. Signed-off-by: Alexander Simon --- net/mac80211/ieee80211_i.h | 8 +++ net/mac80211/util.c | 116 +++++++++++++++++++++++++++++++++++++------ net/mac80211/work.c | 29 +----------- 3 files changed, 108 insertions(+), 45 deletions(-) diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index 400c09b..bfb820c 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h @@ -1401,6 +1401,12 @@ void ieee80211_recalc_smps(struct ieee80211_local *local); size_t ieee80211_ie_split(const u8 *ies, size_t ielen, const u8 *ids, int n_ids, size_t offset); size_t ieee80211_ie_split_vendor(const u8 *ies, size_t ielen, size_t offset); +u8 *ieee80211_ie_build_ht_cap(u8 *pos, struct ieee80211_supported_band *sband, + u16 cap); +u8 *ieee80211_ie_build_ht_info(u8 *pos, + struct ieee80211_sta_ht_cap *ht_cap, + struct ieee80211_channel *channel, + enum nl80211_channel_type channel_type); /* internal work items */ void ieee80211_work_init(struct ieee80211_local *local); @@ -1429,6 +1435,8 @@ ieee80211_get_channel_mode(struct ieee80211_local *local, bool ieee80211_set_channel_type(struct ieee80211_local *local, struct ieee80211_sub_if_data *sdata, enum nl80211_channel_type chantype); +enum nl80211_channel_type ieee80211_ht_info_to_channel_type( + struct ieee80211_ht_info *ht_info); #ifdef CONFIG_MAC80211_NOINLINE #define debug_noinline noinline diff --git a/net/mac80211/util.c b/net/mac80211/util.c index ddeb1b9..b62fc4e 100644 --- a/net/mac80211/util.c +++ b/net/mac80211/util.c @@ -983,23 +983,8 @@ int ieee80211_build_preq_ies(struct ieee80211_local *local, u8 *buffer, offset = noffset; } - if (sband->ht_cap.ht_supported) { - u16 cap = sband->ht_cap.cap; - __le16 tmp; - - *pos++ = WLAN_EID_HT_CAPABILITY; - *pos++ = sizeof(struct ieee80211_ht_cap); - memset(pos, 0, sizeof(struct ieee80211_ht_cap)); - tmp = cpu_to_le16(cap); - memcpy(pos, &tmp, sizeof(u16)); - pos += sizeof(u16); - *pos++ = sband->ht_cap.ampdu_factor | - (sband->ht_cap.ampdu_density << - IEEE80211_HT_AMPDU_PARM_DENSITY_SHIFT); - memcpy(pos, &sband->ht_cap.mcs, sizeof(sband->ht_cap.mcs)); - pos += sizeof(sband->ht_cap.mcs); - pos += 2 + 4 + 1; /* ext info, BF cap, antsel */ - } + if (sband->ht_cap.ht_supported) + pos = ieee80211_ie_build_ht_cap(pos, sband, sband->ht_cap.cap); /* * If adding more here, adjust code in main.c @@ -1522,3 +1507,100 @@ void ieee80211_disable_rssi_reports(struct ieee80211_vif *vif) _ieee80211_enable_rssi_reports(sdata, 0, 0); } EXPORT_SYMBOL(ieee80211_disable_rssi_reports); + +u8 *ieee80211_ie_build_ht_cap(u8 *pos, struct ieee80211_supported_band *sband, + u16 cap) +{ + __le16 tmp; + + *pos++ = WLAN_EID_HT_CAPABILITY; + *pos++ = sizeof(struct ieee80211_ht_cap); + memset(pos, 0, sizeof(struct ieee80211_ht_cap)); + + /* capability flags */ + tmp = cpu_to_le16(cap); + memcpy(pos, &tmp, sizeof(u16)); + pos += sizeof(u16); + + /* AMPDU parameters */ + *pos++ = sband->ht_cap.ampdu_factor | + (sband->ht_cap.ampdu_density << + IEEE80211_HT_AMPDU_PARM_DENSITY_SHIFT); + + /* MCS set */ + memcpy(pos, &sband->ht_cap.mcs, sizeof(sband->ht_cap.mcs)); + pos += sizeof(sband->ht_cap.mcs); + + /* extended capabilities */ + pos += sizeof(__le16); + + /* BF capabilities */ + pos += sizeof(__le32); + + /* antenna selection */ + pos += sizeof(u8); + + return pos; +} + +u8 *ieee80211_ie_build_ht_info(u8 *pos, + struct ieee80211_sta_ht_cap *ht_cap, + struct ieee80211_channel *channel, + enum nl80211_channel_type channel_type) +{ + struct ieee80211_ht_info *ht_info; + /* Build HT Information */ + *pos++ = WLAN_EID_HT_INFORMATION; + *pos++ = sizeof(struct ieee80211_ht_info); + ht_info = (struct ieee80211_ht_info *)pos; + ht_info->control_chan = + ieee80211_frequency_to_channel(channel->center_freq); + switch (channel_type) { + case NL80211_CHAN_HT40MINUS: + ht_info->ht_param = IEEE80211_HT_PARAM_CHA_SEC_BELOW; + break; + case NL80211_CHAN_HT40PLUS: + ht_info->ht_param = IEEE80211_HT_PARAM_CHA_SEC_ABOVE; + break; + case NL80211_CHAN_HT20: + default: + ht_info->ht_param = IEEE80211_HT_PARAM_CHA_SEC_NONE; + break; + } + if (ht_cap->cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40) + ht_info->ht_param |= IEEE80211_HT_PARAM_CHAN_WIDTH_ANY; + ht_info->operation_mode = 0x0000; + ht_info->stbc_param = 0x0000; + + /* It seems that Basic MCS set and Supported MCS set + are identical for the first 10 bytes */ + memset(&ht_info->basic_set, 0, 16); + memcpy(&ht_info->basic_set, &ht_cap->mcs, 10); + + return pos + sizeof(struct ieee80211_ht_info); +} + +enum nl80211_channel_type ieee80211_ht_info_to_channel_type( + struct ieee80211_ht_info *ht_info) +{ + enum nl80211_channel_type channel_type; + + if (!ht_info) + return NL80211_CHAN_NO_HT; + + switch (ht_info->ht_param & IEEE80211_HT_PARAM_CHA_SEC_OFFSET) { + case IEEE80211_HT_PARAM_CHA_SEC_NONE: + channel_type = NL80211_CHAN_HT20; + break; + case IEEE80211_HT_PARAM_CHA_SEC_ABOVE: + channel_type = NL80211_CHAN_HT40PLUS; + break; + case IEEE80211_HT_PARAM_CHA_SEC_BELOW: + channel_type = NL80211_CHAN_HT40MINUS; + break; + default: + channel_type = NL80211_CHAN_NO_HT; + } + + return channel_type; +} diff --git a/net/mac80211/work.c b/net/mac80211/work.c index 380b9a7..8d9251c 100644 --- a/net/mac80211/work.c +++ b/net/mac80211/work.c @@ -103,7 +103,6 @@ static void ieee80211_add_ht_ie(struct sk_buff *skb, const u8 *ht_info_ie, u8 *pos; u32 flags = channel->flags; u16 cap = sband->ht_cap.cap; - __le16 tmp; if (!sband->ht_cap.ht_supported) return; @@ -154,34 +153,8 @@ static void ieee80211_add_ht_ie(struct sk_buff *skb, const u8 *ht_info_ie, } /* reserve and fill IE */ - pos = skb_put(skb, sizeof(struct ieee80211_ht_cap) + 2); - *pos++ = WLAN_EID_HT_CAPABILITY; - *pos++ = sizeof(struct ieee80211_ht_cap); - memset(pos, 0, sizeof(struct ieee80211_ht_cap)); - - /* capability flags */ - tmp = cpu_to_le16(cap); - memcpy(pos, &tmp, sizeof(u16)); - pos += sizeof(u16); - - /* AMPDU parameters */ - *pos++ = sband->ht_cap.ampdu_factor | - (sband->ht_cap.ampdu_density << - IEEE80211_HT_AMPDU_PARM_DENSITY_SHIFT); - - /* MCS set */ - memcpy(pos, &sband->ht_cap.mcs, sizeof(sband->ht_cap.mcs)); - pos += sizeof(sband->ht_cap.mcs); - - /* extended capabilities */ - pos += sizeof(__le16); - - /* BF capabilities */ - pos += sizeof(__le32); - - /* antenna selection */ - pos += sizeof(u8); + ieee80211_ie_build_ht_cap(pos, sband, cap); } static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata, -- 1.7.3.4