Building the HT IE when we join an IBSS. I think this patch is rather simple to understand. It takes the configured channel_type and all other else from the interface capabilities (like AMPDU, SGIs). Beamforming is disabled. This was adopted from ieee80211_build_preq_ies in util.c. Yeah and you could ease the last changeset. diff -Nrup compat-wireless-2011-01-17.1//net/mac80211/ibss.c compat-wireless-2011-01-17.2//net/mac80211/ibss.c --- compat-wireless-2011-01-17.1//net/mac80211/ibss.c 2011-01-20 10:01:56.000000000 +0100 +++ compat-wireless-2011-01-17.2//net/mac80211/ibss.c 2011-01-20 10:02:16.000000000 +0100 @@ -174,6 +174,64 @@ static void __ieee80211_sta_join_ibss(st memcpy(skb_put(skb, ifibss->ie_len), ifibss->ie, ifibss->ie_len); + if (channel_type != NL80211_CHAN_NO_HT && sband->ht_cap.ht_supported) { + u16 cap = sband->ht_cap.cap; + struct ieee80211_ht_cap *ht_cap; + struct ieee80211_ht_info *ht_info; + + /* Build HT Capabilities */ + if (ieee80211_disable_40mhz_24ghz && + sband->band == IEEE80211_BAND_2GHZ) { + cap &= ~IEEE80211_HT_CAP_SUP_WIDTH_20_40; + cap &= ~IEEE80211_HT_CAP_SGI_40; + } + + pos = skb_put(skb, 2 + sizeof(struct ieee80211_ht_cap)); + *pos++ = WLAN_EID_HT_CAPABILITY; + *pos++ = sizeof(struct ieee80211_ht_cap); + ht_cap = (struct ieee80211_ht_cap *)pos; + + ht_cap->cap_info = cpu_to_le16(cap); + ht_cap->ampdu_params_info = sband->ht_cap.ampdu_factor | + (sband->ht_cap.ampdu_density << + IEEE80211_HT_AMPDU_PARM_DENSITY_SHIFT); + memcpy(&ht_cap->mcs, &sband->ht_cap.mcs, sizeof(sband->ht_cap.mcs)); + ht_cap->extended_ht_cap_info = 0x0000; + ht_cap->tx_BF_cap_info = 0x00000000; + ht_cap->antenna_selection_info = 0x00; + + /* Build HT Information */ + pos = skb_put(skb, 2 + sizeof(struct ieee80211_ht_info)); + *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(chan->center_freq); + ht_info->ht_param = 0x00; + switch (local->_oper_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 (sband->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, &sband->ht_cap.mcs, 10); + } + if (local->hw.queues >= 4) { pos = skb_put(skb, 9); *pos++ = WLAN_EID_VENDOR_SPECIFIC; @@ -223,6 +281,7 @@ static void ieee80211_sta_join_ibss(stru int i, j; u16 beacon_int = cbss->beacon_interval; enum nl80211_channel_type channel_type = NL80211_CHAN_NO_HT; + const u8 *ht_info_ie; lockdep_assert_held(&sdata->u.ibss.mtx); @@ -923,11 +982,16 @@ int ieee80211_ibss_join(struct ieee80211 struct sk_buff *skb; skb = dev_alloc_skb(sdata->local->hw.extra_tx_headroom + - 36 /* bitrates */ + - 34 /* SSID */ + - 3 /* DS params */ + - 4 /* IBSS params */ + - params->ie_len); + sizeof(struct ieee80211_hdr_3addr) + + 12 /* struct ieee80211_mgmt.u.beacon */ + + 2 + IEEE80211_MAX_SSID_LEN /* max SSID */ + + 2 + 8 /* max Supported Rates */ + + 3 /* max DS params */ + + 4 /* IBSS params */ + + 2 + (IEEE80211_MAX_SUPP_RATES - 8) /* max Ext Rates */ + + 2 + sizeof(struct ieee80211_ht_cap) + + 2 + sizeof(struct ieee80211_ht_info) + + params->ie_len); if (!skb) return -ENOMEM; -- To unsubscribe from this list: send the line "unsubscribe linux-wireless" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html