aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211/util.c
diff options
context:
space:
mode:
authorAlexander Simon <an.alexsimon@googlemail.com>2011-10-26 17:47:26 -0400
committerJohn W. Linville <linville@tuxdriver.com>2011-11-08 15:54:32 -0500
commit42e7aa771196d8129d9deaee950b3177a443b8cf (patch)
tree0d6e20054a6a1d57bd751b1678de9e6c51774091 /net/mac80211/util.c
parent3b69a9c5f264d62a0cf46ea61ed3da732c1f88c2 (diff)
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>
Diffstat (limited to 'net/mac80211/util.c')
-rw-r--r--net/mac80211/util.c116
1 files changed, 99 insertions, 17 deletions
diff --git a/net/mac80211/util.c b/net/mac80211/util.c
index 7439d26bf5f9..72b3a2ec0d24 100644
--- a/net/mac80211/util.c
+++ b/net/mac80211/util.c
@@ -811,23 +811,8 @@ int ieee80211_build_preq_ies(struct ieee80211_local *local, u8 *buffer,
811 offset = noffset; 811 offset = noffset;
812 } 812 }
813 813
814 if (sband->ht_cap.ht_supported) { 814 if (sband->ht_cap.ht_supported)
815 u16 cap = sband->ht_cap.cap; 815 pos = ieee80211_ie_build_ht_cap(pos, sband, sband->ht_cap.cap);
816 __le16 tmp;
817
818 *pos++ = WLAN_EID_HT_CAPABILITY;
819 *pos++ = sizeof(struct ieee80211_ht_cap);
820 memset(pos, 0, sizeof(struct ieee80211_ht_cap));
821 tmp = cpu_to_le16(cap);
822 memcpy(pos, &tmp, sizeof(u16));
823 pos += sizeof(u16);
824 *pos++ = sband->ht_cap.ampdu_factor |
825 (sband->ht_cap.ampdu_density <<
826 IEEE80211_HT_AMPDU_PARM_DENSITY_SHIFT);
827 memcpy(pos, &sband->ht_cap.mcs, sizeof(sband->ht_cap.mcs));
828 pos += sizeof(sband->ht_cap.mcs);
829 pos += 2 + 4 + 1; /* ext info, BF cap, antsel */
830 }
831 816
832 /* 817 /*
833 * If adding more here, adjust code in main.c 818 * If adding more here, adjust code in main.c
@@ -1362,6 +1347,103 @@ void ieee80211_disable_rssi_reports(struct ieee80211_vif *vif)
1362} 1347}
1363EXPORT_SYMBOL(ieee80211_disable_rssi_reports); 1348EXPORT_SYMBOL(ieee80211_disable_rssi_reports);
1364 1349
1350u8 *ieee80211_ie_build_ht_cap(u8 *pos, struct ieee80211_supported_band *sband,
1351 u16 cap)
1352{
1353 __le16 tmp;
1354
1355 *pos++ = WLAN_EID_HT_CAPABILITY;
1356 *pos++ = sizeof(struct ieee80211_ht_cap);
1357 memset(pos, 0, sizeof(struct ieee80211_ht_cap));
1358
1359 /* capability flags */
1360 tmp = cpu_to_le16(cap);
1361 memcpy(pos, &tmp, sizeof(u16));
1362 pos += sizeof(u16);
1363
1364 /* AMPDU parameters */
1365 *pos++ = sband->ht_cap.ampdu_factor |
1366 (sband->ht_cap.ampdu_density <<
1367 IEEE80211_HT_AMPDU_PARM_DENSITY_SHIFT);
1368
1369 /* MCS set */
1370 memcpy(pos, &sband->ht_cap.mcs, sizeof(sband->ht_cap.mcs));
1371 pos += sizeof(sband->ht_cap.mcs);
1372
1373 /* extended capabilities */
1374 pos += sizeof(__le16);
1375
1376 /* BF capabilities */
1377 pos += sizeof(__le32);
1378
1379 /* antenna selection */
1380 pos += sizeof(u8);
1381
1382 return pos;
1383}
1384
1385u8 *ieee80211_ie_build_ht_info(u8 *pos,
1386 struct ieee80211_sta_ht_cap *ht_cap,
1387 struct ieee80211_channel *channel,
1388 enum nl80211_channel_type channel_type)
1389{
1390 struct ieee80211_ht_info *ht_info;
1391 /* Build HT Information */
1392 *pos++ = WLAN_EID_HT_INFORMATION;
1393 *pos++ = sizeof(struct ieee80211_ht_info);
1394 ht_info = (struct ieee80211_ht_info *)pos;
1395 ht_info->control_chan =
1396 ieee80211_frequency_to_channel(channel->center_freq);
1397 switch (channel_type) {
1398 case NL80211_CHAN_HT40MINUS:
1399 ht_info->ht_param = IEEE80211_HT_PARAM_CHA_SEC_BELOW;
1400 break;
1401 case NL80211_CHAN_HT40PLUS:
1402 ht_info->ht_param = IEEE80211_HT_PARAM_CHA_SEC_ABOVE;
1403 break;
1404 case NL80211_CHAN_HT20:
1405 default:
1406 ht_info->ht_param = IEEE80211_HT_PARAM_CHA_SEC_NONE;
1407 break;
1408 }
1409 if (ht_cap->cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40)
1410 ht_info->ht_param |= IEEE80211_HT_PARAM_CHAN_WIDTH_ANY;
1411 ht_info->operation_mode = 0x0000;
1412 ht_info->stbc_param = 0x0000;
1413
1414 /* It seems that Basic MCS set and Supported MCS set
1415 are identical for the first 10 bytes */
1416 memset(&ht_info->basic_set, 0, 16);
1417 memcpy(&ht_info->basic_set, &ht_cap->mcs, 10);
1418
1419 return pos + sizeof(struct ieee80211_ht_info);
1420}
1421
1422enum nl80211_channel_type
1423ieee80211_ht_info_to_channel_type(struct ieee80211_ht_info *ht_info)
1424{
1425 enum nl80211_channel_type channel_type;
1426
1427 if (!ht_info)
1428 return NL80211_CHAN_NO_HT;
1429
1430 switch (ht_info->ht_param & IEEE80211_HT_PARAM_CHA_SEC_OFFSET) {
1431 case IEEE80211_HT_PARAM_CHA_SEC_NONE:
1432 channel_type = NL80211_CHAN_HT20;
1433 break;
1434 case IEEE80211_HT_PARAM_CHA_SEC_ABOVE:
1435 channel_type = NL80211_CHAN_HT40PLUS;
1436 break;
1437 case IEEE80211_HT_PARAM_CHA_SEC_BELOW:
1438 channel_type = NL80211_CHAN_HT40MINUS;
1439 break;
1440 default:
1441 channel_type = NL80211_CHAN_NO_HT;
1442 }
1443
1444 return channel_type;
1445}
1446
1365int ieee80211_add_srates_ie(struct ieee80211_vif *vif, struct sk_buff *skb) 1447int ieee80211_add_srates_ie(struct ieee80211_vif *vif, struct sk_buff *skb)
1366{ 1448{
1367 struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif); 1449 struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);