Commit 9ee677c2 authored by David Kilroy's avatar David Kilroy Committed by John W. Linville

wireless: Add channel/frequency conversions to ieee80211.h

Added mappings for FHSS, DSSS and OFDM channels - with macros to point
HR DSSS and ERP to the DSSS mappings. Currently just static inline
functions.

Use the new functions in the older fullmac drivers. This eliminates a
number of const static buffers and removes a couple of range checks that
are now redundant.
Signed-off-by: default avatarDavid Kilroy <kilroyd@googlemail.com>
Acked-by: default avatarArnaldo Carvalho de Melo <acme@redhat.com>
Acked-by: default avatarRichard Farina <sidhayn@gmail.com>
Acked-by: default avatarJeroen Vreeken <pe1rxq@amsat.org>
Signed-off-by: default avatarJohn W. Linville <linville@tuxdriver.com>
parent eaee7cc2
...@@ -1070,10 +1070,6 @@ static WifiCtlHdr wifictlhdr8023 = { ...@@ -1070,10 +1070,6 @@ static WifiCtlHdr wifictlhdr8023 = {
} }
}; };
// Frequency list (map channels to frequencies)
static const long frequency_list[] = { 2412, 2417, 2422, 2427, 2432, 2437, 2442,
2447, 2452, 2457, 2462, 2467, 2472, 2484 };
// A few details needed for WEP (Wireless Equivalent Privacy) // A few details needed for WEP (Wireless Equivalent Privacy)
#define MAX_KEY_SIZE 13 // 128 (?) bits #define MAX_KEY_SIZE 13 // 128 (?) bits
#define MIN_KEY_SIZE 5 // 40 bits RC4 - WEP #define MIN_KEY_SIZE 5 // 40 bits RC4 - WEP
...@@ -5725,16 +5721,12 @@ static int airo_set_freq(struct net_device *dev, ...@@ -5725,16 +5721,12 @@ static int airo_set_freq(struct net_device *dev,
int rc = -EINPROGRESS; /* Call commit handler */ int rc = -EINPROGRESS; /* Call commit handler */
/* If setting by frequency, convert to a channel */ /* If setting by frequency, convert to a channel */
if((fwrq->e == 1) && if(fwrq->e == 1) {
(fwrq->m >= (int) 2.412e8) &&
(fwrq->m <= (int) 2.487e8)) {
int f = fwrq->m / 100000; int f = fwrq->m / 100000;
int c = 0;
while((c < 14) && (f != frequency_list[c]))
c++;
/* Hack to fall through... */ /* Hack to fall through... */
fwrq->e = 0; fwrq->e = 0;
fwrq->m = c + 1; fwrq->m = ieee80211_freq_to_dsss_chan(f);
} }
/* Setting by channel number */ /* Setting by channel number */
if((fwrq->m > 1000) || (fwrq->e > 0)) if((fwrq->m > 1000) || (fwrq->e > 0))
...@@ -5778,7 +5770,7 @@ static int airo_get_freq(struct net_device *dev, ...@@ -5778,7 +5770,7 @@ static int airo_get_freq(struct net_device *dev,
ch = le16_to_cpu(status_rid.channel); ch = le16_to_cpu(status_rid.channel);
if((ch > 0) && (ch < 15)) { if((ch > 0) && (ch < 15)) {
fwrq->m = frequency_list[ch - 1] * 100000; fwrq->m = ieee80211_dsss_chan_to_freq(ch) * 100000;
fwrq->e = 1; fwrq->e = 1;
} else { } else {
fwrq->m = ch; fwrq->m = ch;
...@@ -6795,8 +6787,8 @@ static int airo_get_range(struct net_device *dev, ...@@ -6795,8 +6787,8 @@ static int airo_get_range(struct net_device *dev,
k = 0; k = 0;
for(i = 0; i < 14; i++) { for(i = 0; i < 14; i++) {
range->freq[k].i = i + 1; /* List index */ range->freq[k].i = i + 1; /* List index */
range->freq[k].m = frequency_list[i] * 100000; range->freq[k].m = ieee80211_dsss_chan_to_freq(i + 1) * 100000;
range->freq[k++].e = 1; /* Values in table in MHz -> * 10^5 * 10 */ range->freq[k++].e = 1; /* Values in MHz -> * 10^5 * 10 */
} }
range->num_frequency = k; range->num_frequency = k;
...@@ -7189,10 +7181,7 @@ static inline char *airo_translate_scan(struct net_device *dev, ...@@ -7189,10 +7181,7 @@ static inline char *airo_translate_scan(struct net_device *dev,
/* Add frequency */ /* Add frequency */
iwe.cmd = SIOCGIWFREQ; iwe.cmd = SIOCGIWFREQ;
iwe.u.freq.m = le16_to_cpu(bss->dsChannel); iwe.u.freq.m = le16_to_cpu(bss->dsChannel);
/* iwe.u.freq.m containt the channel (starting 1), our iwe.u.freq.m = ieee80211_dsss_chan_to_freq(iwe.u.freq.m) * 100000;
* frequency_list array start at index 0...
*/
iwe.u.freq.m = frequency_list[iwe.u.freq.m - 1] * 100000;
iwe.u.freq.e = 1; iwe.u.freq.e = 1;
current_ev = iwe_stream_add_event(info, current_ev, end_buf, current_ev = iwe_stream_add_event(info, current_ev, end_buf,
&iwe, IW_EV_FREQ_LEN); &iwe, IW_EV_FREQ_LEN);
......
...@@ -2204,9 +2204,6 @@ static int atmel_get_frag(struct net_device *dev, ...@@ -2204,9 +2204,6 @@ static int atmel_get_frag(struct net_device *dev,
return 0; return 0;
} }
static const long frequency_list[] = { 2412, 2417, 2422, 2427, 2432, 2437, 2442,
2447, 2452, 2457, 2462, 2467, 2472, 2484 };
static int atmel_set_freq(struct net_device *dev, static int atmel_set_freq(struct net_device *dev,
struct iw_request_info *info, struct iw_request_info *info,
struct iw_freq *fwrq, struct iw_freq *fwrq,
...@@ -2216,16 +2213,12 @@ static int atmel_set_freq(struct net_device *dev, ...@@ -2216,16 +2213,12 @@ static int atmel_set_freq(struct net_device *dev,
int rc = -EINPROGRESS; /* Call commit handler */ int rc = -EINPROGRESS; /* Call commit handler */
/* If setting by frequency, convert to a channel */ /* If setting by frequency, convert to a channel */
if ((fwrq->e == 1) && if (fwrq->e == 1) {
(fwrq->m >= (int) 241200000) &&
(fwrq->m <= (int) 248700000)) {
int f = fwrq->m / 100000; int f = fwrq->m / 100000;
int c = 0;
while ((c < 14) && (f != frequency_list[c]))
c++;
/* Hack to fall through... */ /* Hack to fall through... */
fwrq->e = 0; fwrq->e = 0;
fwrq->m = c + 1; fwrq->m = ieee80211_freq_to_dsss_chan(f);
} }
/* Setting by channel number */ /* Setting by channel number */
if ((fwrq->m > 1000) || (fwrq->e > 0)) if ((fwrq->m > 1000) || (fwrq->e > 0))
...@@ -2384,8 +2377,11 @@ static int atmel_get_range(struct net_device *dev, ...@@ -2384,8 +2377,11 @@ static int atmel_get_range(struct net_device *dev,
if (range->num_channels != 0) { if (range->num_channels != 0) {
for (k = 0, i = channel_table[j].min; i <= channel_table[j].max; i++) { for (k = 0, i = channel_table[j].min; i <= channel_table[j].max; i++) {
range->freq[k].i = i; /* List index */ range->freq[k].i = i; /* List index */
range->freq[k].m = frequency_list[i - 1] * 100000;
range->freq[k++].e = 1; /* Values in table in MHz -> * 10^5 * 10 */ /* Values in MHz -> * 10^5 * 10 */
range->freq[k].m = (ieee80211_dsss_chan_to_freq(i) *
100000);
range->freq[k++].e = 1;
} }
range->num_frequency = k; range->num_frequency = k;
} }
......
...@@ -178,12 +178,7 @@ static const struct ethtool_ops orinoco_ethtool_ops; ...@@ -178,12 +178,7 @@ static const struct ethtool_ops orinoco_ethtool_ops;
/* Data tables */ /* Data tables */
/********************************************************************/ /********************************************************************/
/* The frequency of each channel in MHz */ #define NUM_CHANNELS 14
static const long channel_frequency[] = {
2412, 2417, 2422, 2427, 2432, 2437, 2442,
2447, 2452, 2457, 2462, 2467, 2472, 2484
};
#define NUM_CHANNELS ARRAY_SIZE(channel_frequency)
/* This tables gives the actual meanings of the bitrate IDs returned /* This tables gives the actual meanings of the bitrate IDs returned
* by the firmware. */ * by the firmware. */
...@@ -3742,13 +3737,13 @@ static int orinoco_hw_get_essid(struct orinoco_private *priv, int *active, ...@@ -3742,13 +3737,13 @@ static int orinoco_hw_get_essid(struct orinoco_private *priv, int *active,
return err; return err;
} }
static long orinoco_hw_get_freq(struct orinoco_private *priv) static int orinoco_hw_get_freq(struct orinoco_private *priv)
{ {
hermes_t *hw = &priv->hw; hermes_t *hw = &priv->hw;
int err = 0; int err = 0;
u16 channel; u16 channel;
long freq = 0; int freq = 0;
unsigned long flags; unsigned long flags;
if (orinoco_lock(priv, &flags) != 0) if (orinoco_lock(priv, &flags) != 0)
...@@ -3771,7 +3766,7 @@ static long orinoco_hw_get_freq(struct orinoco_private *priv) ...@@ -3771,7 +3766,7 @@ static long orinoco_hw_get_freq(struct orinoco_private *priv)
goto out; goto out;
} }
freq = channel_frequency[channel-1] * 100000; freq = ieee80211_dsss_chan_to_freq(channel);
out: out:
orinoco_unlock(priv, &flags); orinoco_unlock(priv, &flags);
...@@ -3998,7 +3993,8 @@ static int orinoco_ioctl_getiwrange(struct net_device *dev, ...@@ -3998,7 +3993,8 @@ static int orinoco_ioctl_getiwrange(struct net_device *dev,
for (i = 0; i < NUM_CHANNELS; i++) { for (i = 0; i < NUM_CHANNELS; i++) {
if (priv->channel_mask & (1 << i)) { if (priv->channel_mask & (1 << i)) {
range->freq[k].i = i + 1; range->freq[k].i = i + 1;
range->freq[k].m = channel_frequency[i] * 100000; range->freq[k].m = (ieee80211_dsss_chan_to_freq(i + 1) *
100000);
range->freq[k].e = 1; range->freq[k].e = 1;
k++; k++;
} }
...@@ -4346,16 +4342,15 @@ static int orinoco_ioctl_setfreq(struct net_device *dev, ...@@ -4346,16 +4342,15 @@ static int orinoco_ioctl_setfreq(struct net_device *dev,
/* Setting by channel number */ /* Setting by channel number */
chan = frq->m; chan = frq->m;
} else { } else {
/* Setting by frequency - search the table */ /* Setting by frequency */
int mult = 1; int denom = 1;
int i; int i;
/* Calculate denominator to rescale to MHz */
for (i = 0; i < (6 - frq->e); i++) for (i = 0; i < (6 - frq->e); i++)
mult *= 10; denom *= 10;
for (i = 0; i < NUM_CHANNELS; i++) chan = ieee80211_freq_to_dsss_chan(frq->m / denom);
if (frq->m == (channel_frequency[i] * mult))
chan = i+1;
} }
if ( (chan < 1) || (chan > NUM_CHANNELS) || if ( (chan < 1) || (chan > NUM_CHANNELS) ||
...@@ -4392,7 +4387,7 @@ static int orinoco_ioctl_getfreq(struct net_device *dev, ...@@ -4392,7 +4387,7 @@ static int orinoco_ioctl_getfreq(struct net_device *dev,
return tmp; return tmp;
} }
frq->m = tmp; frq->m = tmp * 100000;
frq->e = 1; frq->e = 1;
return 0; return 0;
...@@ -5609,7 +5604,7 @@ static inline char *orinoco_translate_scan(struct net_device *dev, ...@@ -5609,7 +5604,7 @@ static inline char *orinoco_translate_scan(struct net_device *dev,
current_ev = iwe_stream_add_event(info, current_ev, end_buf, current_ev = iwe_stream_add_event(info, current_ev, end_buf,
&iwe, IW_EV_FREQ_LEN); &iwe, IW_EV_FREQ_LEN);
iwe.u.freq.m = channel_frequency[channel-1] * 100000; iwe.u.freq.m = ieee80211_dsss_chan_to_freq(channel) * 100000;
iwe.u.freq.e = 1; iwe.u.freq.e = 1;
current_ev = iwe_stream_add_event(info, current_ev, end_buf, current_ev = iwe_stream_add_event(info, current_ev, end_buf,
&iwe, IW_EV_FREQ_LEN); &iwe, IW_EV_FREQ_LEN);
...@@ -5760,7 +5755,7 @@ static inline char *orinoco_translate_ext_scan(struct net_device *dev, ...@@ -5760,7 +5755,7 @@ static inline char *orinoco_translate_ext_scan(struct net_device *dev,
current_ev = iwe_stream_add_event(info, current_ev, end_buf, current_ev = iwe_stream_add_event(info, current_ev, end_buf,
&iwe, IW_EV_FREQ_LEN); &iwe, IW_EV_FREQ_LEN);
iwe.u.freq.m = channel_frequency[channel-1] * 100000; iwe.u.freq.m = ieee80211_dsss_chan_to_freq(channel) * 100000;
iwe.u.freq.e = 1; iwe.u.freq.e = 1;
current_ev = iwe_stream_add_event(info, current_ev, end_buf, current_ev = iwe_stream_add_event(info, current_ev, end_buf,
&iwe, IW_EV_FREQ_LEN); &iwe, IW_EV_FREQ_LEN);
......
...@@ -369,9 +369,6 @@ struct rndis_wext_private { ...@@ -369,9 +369,6 @@ struct rndis_wext_private {
}; };
static const int freq_chan[] = { 2412, 2417, 2422, 2427, 2432, 2437, 2442,
2447, 2452, 2457, 2462, 2467, 2472, 2484 };
static const int rates_80211g[8] = { 6, 9, 12, 18, 24, 36, 48, 54 }; static const int rates_80211g[8] = { 6, 9, 12, 18, 24, 36, 48, 54 };
static const int bcm4320_power_output[4] = { 25, 50, 75, 100 }; static const int bcm4320_power_output[4] = { 25, 50, 75, 100 };
...@@ -640,8 +637,8 @@ static void dsconfig_to_freq(unsigned int dsconfig, struct iw_freq *freq) ...@@ -640,8 +637,8 @@ static void dsconfig_to_freq(unsigned int dsconfig, struct iw_freq *freq)
static int freq_to_dsconfig(struct iw_freq *freq, unsigned int *dsconfig) static int freq_to_dsconfig(struct iw_freq *freq, unsigned int *dsconfig)
{ {
if (freq->m < 1000 && freq->e == 0) { if (freq->m < 1000 && freq->e == 0) {
if (freq->m >= 1 && freq->m <= ARRAY_SIZE(freq_chan)) if (freq->m >= 1 && freq->m <= 14)
*dsconfig = freq_chan[freq->m - 1] * 1000; *dsconfig = ieee80211_dsss_chan_to_freq(freq->m) * 1000;
else else
return -1; return -1;
} else { } else {
...@@ -1178,11 +1175,11 @@ static int rndis_iw_get_range(struct net_device *dev, ...@@ -1178,11 +1175,11 @@ static int rndis_iw_get_range(struct net_device *dev,
range->throughput = 11 * 1000 * 1000 / 2; range->throughput = 11 * 1000 * 1000 / 2;
} }
range->num_channels = ARRAY_SIZE(freq_chan); range->num_channels = 14;
for (i = 0; i < ARRAY_SIZE(freq_chan) && i < IW_MAX_FREQUENCIES; i++) { for (i = 0; (i < 14) && (i < IW_MAX_FREQUENCIES); i++) {
range->freq[i].i = i + 1; range->freq[i].i = i + 1;
range->freq[i].m = freq_chan[i] * 100000; range->freq[i].m = ieee80211_dsss_chan_to_freq(i + 1) * 100000;
range->freq[i].e = 1; range->freq[i].e = 1;
} }
range->num_frequency = i; range->num_frequency = i;
......
...@@ -44,6 +44,7 @@ ...@@ -44,6 +44,7 @@
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/string.h> #include <linux/string.h>
#include <linux/wireless.h> #include <linux/wireless.h>
#include <linux/ieee80211.h>
#include <net/iw_handler.h> #include <net/iw_handler.h>
...@@ -111,12 +112,6 @@ static void wl3501_release(struct pcmcia_device *link); ...@@ -111,12 +112,6 @@ static void wl3501_release(struct pcmcia_device *link);
*/ */
static dev_info_t wl3501_dev_info = "wl3501_cs"; static dev_info_t wl3501_dev_info = "wl3501_cs";
static int wl3501_chan2freq[] = {
[0] = 2412, [1] = 2417, [2] = 2422, [3] = 2427, [4] = 2432,
[5] = 2437, [6] = 2442, [7] = 2447, [8] = 2452, [9] = 2457,
[10] = 2462, [11] = 2467, [12] = 2472, [13] = 2477,
};
static const struct { static const struct {
int reg_domain; int reg_domain;
int min, max, deflt; int min, max, deflt;
...@@ -1510,7 +1505,7 @@ static int wl3501_get_freq(struct net_device *dev, struct iw_request_info *info, ...@@ -1510,7 +1505,7 @@ static int wl3501_get_freq(struct net_device *dev, struct iw_request_info *info,
{ {
struct wl3501_card *this = netdev_priv(dev); struct wl3501_card *this = netdev_priv(dev);
wrqu->freq.m = wl3501_chan2freq[this->chan - 1] * 100000; wrqu->freq.m = ieee80211_dsss_chan_to_freq(this->chan) * 100000;
wrqu->freq.e = 1; wrqu->freq.e = 1;
return 0; return 0;
} }
......
...@@ -919,10 +919,9 @@ static int zd1201_set_freq(struct net_device *dev, ...@@ -919,10 +919,9 @@ static int zd1201_set_freq(struct net_device *dev,
if (freq->e == 0) if (freq->e == 0)
channel = freq->m; channel = freq->m;
else { else {
if (freq->m >= 2482) channel = ieee80211_freq_to_dsss_chan(freq->m);
channel = 14; if (channel < 0)
if (freq->m >= 2407) channel = 0;
channel = (freq->m-2407)/5;
} }
err = zd1201_setconfig16(zd, ZD1201_RID_CNFOWNCHANNEL, channel); err = zd1201_setconfig16(zd, ZD1201_RID_CNFOWNCHANNEL, channel);
......
...@@ -1185,4 +1185,120 @@ static inline u8 *ieee80211_get_DA(struct ieee80211_hdr *hdr) ...@@ -1185,4 +1185,120 @@ static inline u8 *ieee80211_get_DA(struct ieee80211_hdr *hdr)
return hdr->addr1; return hdr->addr1;
} }
/**
* ieee80211_fhss_chan_to_freq - get channel frequency
* @channel: the FHSS channel
*
* Convert IEEE802.11 FHSS channel to frequency (MHz)
* Ref IEEE 802.11-2007 section 14.6
*/
static inline int ieee80211_fhss_chan_to_freq(int channel)
{
if ((channel > 1) && (channel < 96))
return channel + 2400;
else
return -1;
}
/**
* ieee80211_freq_to_fhss_chan - get channel
* @freq: the channels frequency
*
* Convert frequency (MHz) to IEEE802.11 FHSS channel
* Ref IEEE 802.11-2007 section 14.6
*/
static inline int ieee80211_freq_to_fhss_chan(int freq)
{
if ((freq > 2401) && (freq < 2496))
return freq - 2400;
else
return -1;
}
/**
* ieee80211_dsss_chan_to_freq - get channel center frequency
* @channel: the DSSS channel
*
* Convert IEEE802.11 DSSS channel to the center frequency (MHz).
* Ref IEEE 802.11-2007 section 15.6
*/
static inline int ieee80211_dsss_chan_to_freq(int channel)
{
if ((channel > 0) && (channel < 14))
return 2407 + (channel * 5);
else if (channel == 14)
return 2484;
else
return -1;
}
/**
* ieee80211_freq_to_dsss_chan - get channel
* @freq: the frequency
*
* Convert frequency (MHz) to IEEE802.11 DSSS channel
* Ref IEEE 802.11-2007 section 15.6
*
* This routine selects the channel with the closest center frequency.
*/
static inline int ieee80211_freq_to_dsss_chan(int freq)
{
if ((freq >= 2410) && (freq < 2475))
return (freq - 2405) / 5;
else if ((freq >= 2482) && (freq < 2487))
return 14;
else
return -1;
}
/* Convert IEEE802.11 HR DSSS channel to frequency (MHz) and back
* Ref IEEE 802.11-2007 section 18.4.6.2
*
* The channels and frequencies are the same as those defined for DSSS
*/
#define ieee80211_hr_chan_to_freq(chan) ieee80211_dsss_chan_to_freq(chan)
#define ieee80211_freq_to_hr_chan(freq) ieee80211_freq_to_dsss_chan(freq)
/* Convert IEEE802.11 ERP channel to frequency (MHz) and back
* Ref IEEE 802.11-2007 section 19.4.2
*/
#define ieee80211_erp_chan_to_freq(chan) ieee80211_hr_chan_to_freq(chan)
#define ieee80211_freq_to_erp_chan(freq) ieee80211_freq_to_hr_chan(freq)
/**
* ieee80211_ofdm_chan_to_freq - get channel center frequency
* @s_freq: starting frequency == (dotChannelStartingFactor/2) MHz
* @channel: the OFDM channel
*
* Convert IEEE802.11 OFDM channel to center frequency (MHz)
* Ref IEEE 802.11-2007 section 17.3.8.3.2
*/
static inline int ieee80211_ofdm_chan_to_freq(int s_freq, int channel)
{
if ((channel > 0) && (channel <= 200) &&
(s_freq >= 4000))
return s_freq + (channel * 5);
else
return -1;
}
/**
* ieee80211_freq_to_ofdm_channel - get channel
* @s_freq: starting frequency == (dotChannelStartingFactor/2) MHz
* @freq: the frequency
*
* Convert frequency (MHz) to IEEE802.11 OFDM channel
* Ref IEEE 802.11-2007 section 17.3.8.3.2
*
* This routine selects the channel with the closest center frequency.
*/
static inline int ieee80211_freq_to_ofdm_chan(int s_freq, int freq)
{
if ((freq > (s_freq + 2)) && (freq <= (s_freq + 1202)) &&
(s_freq >= 4000))
return (freq + 2 - s_freq) / 5;
else
return -1;
}
#endif /* LINUX_IEEE80211_H */ #endif /* LINUX_IEEE80211_H */
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment