|
@@ -811,23 +811,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
|
|
@@ -1362,6 +1347,103 @@ void ieee80211_disable_rssi_reports(struct ieee80211_vif *vif)
|
|
|
}
|
|
|
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;
|
|
|
+}
|
|
|
+
|
|
|
int ieee80211_add_srates_ie(struct ieee80211_vif *vif, struct sk_buff *skb)
|
|
|
{
|
|
|
struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);
|