mac80211: Add HT helper functions

Some refactoring for IBSS HT.

Move HT info and capability IEs building code into separate functions.

Add function to get the channel type from an HT info IE.

Signed-off-by: Alexander Simon <an.alexsimon@googlemail.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
This commit is contained in:
Alexander Simon 2011-10-26 14:47:26 -07:00 committed by John W. Linville
parent 3b69a9c5f2
commit 42e7aa7711
3 changed files with 108 additions and 45 deletions

View File

@ -1333,6 +1333,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);
@ -1361,6 +1367,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

View File

@ -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);

View File

@ -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,