blob: e76cc28b034557fc1dfcadbae21a09307f6fee5c [file] [log] [blame]
/*
* Wireless utility functions
*
* Copyright 2007 Johannes Berg <johannes@sipsolutions.net>
*/
#include <net/wireless.h>
#include <asm/bitops.h>
#include "core.h"
struct ieee80211_rate *
ieee80211_get_response_rate(struct ieee80211_supported_band *sband,
u64 basic_rates, int bitrate)
{
struct ieee80211_rate *result = &sband->bitrates[0];
int i;
for (i = 0; i < sband->n_bitrates; i++) {
if (!(basic_rates & BIT(i)))
continue;
if (sband->bitrates[i].bitrate > bitrate)
continue;
result = &sband->bitrates[i];
}
return result;
}
EXPORT_SYMBOL(ieee80211_get_response_rate);
int ieee80211_channel_to_frequency(int chan)
{
if (chan < 14)
return 2407 + chan * 5;
if (chan == 14)
return 2484;
/* FIXME: 802.11j 17.3.8.3.2 */
return (chan + 1000) * 5;
}
EXPORT_SYMBOL(ieee80211_channel_to_frequency);
int ieee80211_frequency_to_channel(int freq)
{
if (freq == 2484)
return 14;
if (freq < 2484)
return (freq - 2407) / 5;
/* FIXME: 802.11j 17.3.8.3.2 */
return freq/5 - 1000;
}
EXPORT_SYMBOL(ieee80211_frequency_to_channel);
struct ieee80211_channel *__ieee80211_get_channel(struct wiphy *wiphy,
int freq)
{
enum ieee80211_band band;
struct ieee80211_supported_band *sband;
int i;
for (band = 0; band < IEEE80211_NUM_BANDS; band++) {
sband = wiphy->bands[band];
if (!sband)
continue;
for (i = 0; i < sband->n_channels; i++) {
if (sband->channels[i].center_freq == freq)
return &sband->channels[i];
}
}
return NULL;
}
EXPORT_SYMBOL(__ieee80211_get_channel);
static void set_mandatory_flags_band(struct ieee80211_supported_band *sband,
enum ieee80211_band band)
{
int i, want;
switch (band) {
case IEEE80211_BAND_5GHZ:
want = 3;
for (i = 0; i < sband->n_bitrates; i++) {
if (sband->bitrates[i].bitrate == 60 ||
sband->bitrates[i].bitrate == 120 ||
sband->bitrates[i].bitrate == 240) {
sband->bitrates[i].flags |=
IEEE80211_RATE_MANDATORY_A;
want--;
}
}
WARN_ON(want);
break;
case IEEE80211_BAND_2GHZ:
want = 7;
for (i = 0; i < sband->n_bitrates; i++) {
if (sband->bitrates[i].bitrate == 10) {
sband->bitrates[i].flags |=
IEEE80211_RATE_MANDATORY_B |
IEEE80211_RATE_MANDATORY_G;
want--;
}
if (sband->bitrates[i].bitrate == 20 ||
sband->bitrates[i].bitrate == 55 ||
sband->bitrates[i].bitrate == 110 ||
sband->bitrates[i].bitrate == 60 ||
sband->bitrates[i].bitrate == 120 ||
sband->bitrates[i].bitrate == 240) {
sband->bitrates[i].flags |=
IEEE80211_RATE_MANDATORY_G;
want--;
}
if (sband->bitrates[i].bitrate != 10 &&
sband->bitrates[i].bitrate != 20 &&
sband->bitrates[i].bitrate != 55 &&
sband->bitrates[i].bitrate != 110)
sband->bitrates[i].flags |=
IEEE80211_RATE_ERP_G;
}
WARN_ON(want != 0 && want != 3 && want != 6);
break;
case IEEE80211_NUM_BANDS:
WARN_ON(1);
break;
}
}
void ieee80211_set_bitrate_flags(struct wiphy *wiphy)
{
enum ieee80211_band band;
for (band = 0; band < IEEE80211_NUM_BANDS; band++)
if (wiphy->bands[band])
set_mandatory_flags_band(wiphy->bands[band], band);
}