While refactorring orinoco I found I was encapsulating the static
channel frequency table. A quick poll of drivers showed that a number of
the older driver have their own version of the table, and use it in the
same way. So rather than keep this to orinoco I added the function to
the ieee80211 header.
To be complete I've added conversion routines for all the
bands/modulations in IEEE 802.11-2007
Does this seem reasonable? Should they go somewhere else?
Thanks,
Dave.
---
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 them in the older fullmac drivers. This eliminates a number of
const static buffers mapping channels to frequencies.
This duplicates some of the functionality exported by the cfg80211
specific net/wireless.h
Signed-off-by: David Kilroy <[email protected]>
---
drivers/net/wireless/airo.c | 26 +++-----
drivers/net/wireless/atmel.c | 13 +---
drivers/net/wireless/orinoco/orinoco.c | 34 ++++------
drivers/net/wireless/rndis_wlan.c | 15 ++---
drivers/net/wireless/wl3501_cs.c | 11 +--
drivers/net/wireless/zd1201.c | 7 +-
include/linux/ieee80211.h | 112 ++++++++++++++++++++++++++++++++
7 files changed, 151 insertions(+), 67 deletions(-)
diff --git a/drivers/net/wireless/airo.c b/drivers/net/wireless/airo.c
index 45f8384..967b43a 100644
--- a/drivers/net/wireless/airo.c
+++ b/drivers/net/wireless/airo.c
@@ -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)
#define MAX_KEY_SIZE 13 // 128 (?) bits
#define MIN_KEY_SIZE 5 // 40 bits RC4 - WEP
@@ -5739,12 +5735,10 @@ static int airo_set_freq(struct net_device *dev,
(fwrq->m >= (int) 2.412e8) &&
(fwrq->m <= (int) 2.487e8)) {
int f = fwrq->m / 100000;
- int c = 0;
- while((c < 14) && (f != frequency_list[c]))
- c++;
+
/* Hack to fall through... */
fwrq->e = 0;
- fwrq->m = c + 1;
+ fwrq->m = ieee80211_freq_to_dsss_chan(f);
}
/* Setting by channel number */
if((fwrq->m > 1000) || (fwrq->e > 0))
@@ -5788,8 +5782,8 @@ static int airo_get_freq(struct net_device *dev,
ch = le16_to_cpu(status_rid.channel);
if((ch > 0) && (ch < 15)) {
- fwrq->m = frequency_list[ch - 1] * 100000;
- fwrq->e = 1;
+ fwrq->m = ieee80211_dsss_chan_to_freq(ch);
+ fwrq->e = 6;
} else {
fwrq->m = ch;
fwrq->e = 0;
@@ -6805,8 +6799,8 @@ static int airo_get_range(struct net_device *dev,
k = 0;
for(i = 0; i < 14; i++) {
range->freq[k].i = i + 1; /* List index */
- range->freq[k].m = frequency_list[i] * 100000;
- range->freq[k++].e = 1; /* Values in table in MHz -> * 10^5 * 10 */
+ range->freq[k].m = ieee80211_dsss_chan_to_freq(i + 1);
+ range->freq[k++].e = 6; /* Values in MHz -> * 10^6 */
}
range->num_frequency = k;
@@ -7199,11 +7193,9 @@ static inline char *airo_translate_scan(struct net_device *dev,
/* Add frequency */
iwe.cmd = SIOCGIWFREQ;
iwe.u.freq.m = le16_to_cpu(bss->dsChannel);
- /* iwe.u.freq.m containt the channel (starting 1), our
- * 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.m contains the channel (starting 1) */
+ iwe.u.freq.m = ieee80211_dsss_chan_to_freq(iwe.u.freq.m);
+ iwe.u.freq.e = 6;
current_ev = iwe_stream_add_event(info, current_ev, end_buf,
&iwe, IW_EV_FREQ_LEN);
diff --git a/drivers/net/wireless/atmel.c b/drivers/net/wireless/atmel.c
index f551ec0..05fa951 100644
--- a/drivers/net/wireless/atmel.c
+++ b/drivers/net/wireless/atmel.c
@@ -2207,9 +2207,6 @@ static int atmel_get_frag(struct net_device *dev,
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,
struct iw_request_info *info,
struct iw_freq *fwrq,
@@ -2223,12 +2220,10 @@ static int atmel_set_freq(struct net_device *dev,
(fwrq->m >= (int) 241200000) &&
(fwrq->m <= (int) 248700000)) {
int f = fwrq->m / 100000;
- int c = 0;
- while ((c < 14) && (f != frequency_list[c]))
- c++;
+
/* Hack to fall through... */
fwrq->e = 0;
- fwrq->m = c + 1;
+ fwrq->m = ieee80211_freq_to_dsss_chan(f);
}
/* Setting by channel number */
if ((fwrq->m > 1000) || (fwrq->e > 0))
@@ -2387,8 +2382,8 @@ static int atmel_get_range(struct net_device *dev,
if (range->num_channels != 0) {
for (k = 0, i = channel_table[j].min; i <= channel_table[j].max; i++) {
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 */
+ range->freq[k].m = ieee80211_dsss_chan_to_freq(i);
+ range->freq[k++].e = 6; /* Values in MHz -> * 10^6 */
}
range->num_frequency = k;
}
diff --git a/drivers/net/wireless/orinoco/orinoco.c b/drivers/net/wireless/orinoco/orinoco.c
index b33e13f..51b9812 100644
--- a/drivers/net/wireless/orinoco/orinoco.c
+++ b/drivers/net/wireless/orinoco/orinoco.c
@@ -178,12 +178,7 @@ static const struct ethtool_ops orinoco_ethtool_ops;
/* Data tables */
/********************************************************************/
-/* The frequency of each channel in MHz */
-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)
+#define NUM_CHANNELS 14
/* This tables gives the actual meanings of the bitrate IDs returned
* by the firmware. */
@@ -3724,7 +3719,7 @@ static int orinoco_hw_get_essid(struct orinoco_private *priv, int *active,
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;
@@ -3753,7 +3748,7 @@ static long orinoco_hw_get_freq(struct orinoco_private *priv)
goto out;
}
- freq = channel_frequency[channel-1] * 100000;
+ freq = ieee80211_dsss_chan_to_freq(channel);
out:
orinoco_unlock(priv, &flags);
@@ -3980,8 +3975,8 @@ static int orinoco_ioctl_getiwrange(struct net_device *dev,
for (i = 0; i < NUM_CHANNELS; i++) {
if (priv->channel_mask & (1 << i)) {
range->freq[k].i = i + 1;
- range->freq[k].m = channel_frequency[i] * 100000;
- range->freq[k].e = 1;
+ range->freq[k].m = ieee80211_dsss_chan_to_freq(i + 1);
+ range->freq[k].e = 6;
k++;
}
@@ -4329,15 +4324,14 @@ static int orinoco_ioctl_setfreq(struct net_device *dev,
chan = frq->m;
} else {
/* Setting by frequency - search the table */
- int mult = 1;
+ int denom = 1;
int i;
+ /* Calculate denominator to rescale to MHz */
for (i = 0; i < (6 - frq->e); i++)
- mult *= 10;
+ denom *= 10;
- for (i = 0; i < NUM_CHANNELS; i++)
- if (frq->m == (channel_frequency[i] * mult))
- chan = i+1;
+ chan = ieee80211_freq_to_dsss_chan(frq->m / denom);
}
if ( (chan < 1) || (chan > NUM_CHANNELS) ||
@@ -4375,7 +4369,7 @@ static int orinoco_ioctl_getfreq(struct net_device *dev,
}
frq->m = tmp;
- frq->e = 1;
+ frq->e = 6;
return 0;
}
@@ -5595,8 +5589,8 @@ static inline char *orinoco_translate_scan(struct net_device *dev,
current_ev = iwe_stream_add_event(info, current_ev, end_buf,
&iwe, IW_EV_FREQ_LEN);
- iwe.u.freq.m = channel_frequency[channel-1] * 100000;
- iwe.u.freq.e = 1;
+ iwe.u.freq.m = ieee80211_dsss_chan_to_freq(channel);
+ iwe.u.freq.e = 6;
current_ev = iwe_stream_add_event(info, current_ev, end_buf,
&iwe, IW_EV_FREQ_LEN);
}
@@ -5746,8 +5740,8 @@ static inline char *orinoco_translate_ext_scan(struct net_device *dev,
current_ev = iwe_stream_add_event(info, current_ev, end_buf,
&iwe, IW_EV_FREQ_LEN);
- iwe.u.freq.m = channel_frequency[channel-1] * 100000;
- iwe.u.freq.e = 1;
+ iwe.u.freq.m = ieee80211_dsss_chan_to_freq(channel);
+ iwe.u.freq.e = 6;
current_ev = iwe_stream_add_event(info, current_ev, end_buf,
&iwe, IW_EV_FREQ_LEN);
}
diff --git a/drivers/net/wireless/rndis_wlan.c b/drivers/net/wireless/rndis_wlan.c
index ed5785a..7b0f0f5 100644
--- a/drivers/net/wireless/rndis_wlan.c
+++ b/drivers/net/wireless/rndis_wlan.c
@@ -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 bcm4320_power_output[4] = { 25, 50, 75, 100 };
@@ -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)
{
if (freq->m < 1000 && freq->e == 0) {
- if (freq->m >= 1 && freq->m <= ARRAY_SIZE(freq_chan))
- *dsconfig = freq_chan[freq->m - 1] * 1000;
+ if (freq->m >= 1 && freq->m <= 14)
+ *dsconfig = ieee80211_dsss_chan_to_freq(freq->m) * 1000;
else
return -1;
} else {
@@ -1178,12 +1175,12 @@ static int rndis_iw_get_range(struct net_device *dev,
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].m = freq_chan[i] * 100000;
- range->freq[i].e = 1;
+ range->freq[i].m = ieee80211_dsss_chan_to_freq(i + 1);
+ range->freq[i].e = 6;
}
range->num_frequency = i;
diff --git a/drivers/net/wireless/wl3501_cs.c b/drivers/net/wireless/wl3501_cs.c
index 68789c6..7c17c40 100644
--- a/drivers/net/wireless/wl3501_cs.c
+++ b/drivers/net/wireless/wl3501_cs.c
@@ -44,6 +44,7 @@
#include <linux/slab.h>
#include <linux/string.h>
#include <linux/wireless.h>
+#include <linux/ieee80211.h>
#include <net/iw_handler.h>
@@ -111,12 +112,6 @@ static void wl3501_release(struct pcmcia_device *link);
*/
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 {
int reg_domain;
int min, max, deflt;
@@ -1512,8 +1507,8 @@ static int wl3501_get_freq(struct net_device *dev, struct iw_request_info *info,
{
struct wl3501_card *this = netdev_priv(dev);
- wrqu->freq.m = wl3501_chan2freq[this->chan - 1] * 100000;
- wrqu->freq.e = 1;
+ wrqu->freq.m = ieee80211_dsss_chan_to_freq(this->chan);
+ wrqu->freq.e = 6;
return 0;
}
diff --git a/drivers/net/wireless/zd1201.c b/drivers/net/wireless/zd1201.c
index 45a5747..59e00eb 100644
--- a/drivers/net/wireless/zd1201.c
+++ b/drivers/net/wireless/zd1201.c
@@ -921,10 +921,9 @@ static int zd1201_set_freq(struct net_device *dev,
if (freq->e == 0)
channel = freq->m;
else {
- if (freq->m >= 2482)
- channel = 14;
- if (freq->m >= 2407)
- channel = (freq->m-2407)/5;
+ channel = ieee80211_freq_to_dsss_chan(freq->m);
+ if (channel < 0)
+ channel = 0;
}
err = zd1201_setconfig16(zd, ZD1201_RID_CNFOWNCHANNEL, channel);
diff --git a/include/linux/ieee80211.h b/include/linux/ieee80211.h
index c4e6ca1..c530e89 100644
--- a/include/linux/ieee80211.h
+++ b/include/linux/ieee80211.h
@@ -1185,4 +1185,116 @@ static inline u8 *ieee80211_get_DA(struct ieee80211_hdr *hdr)
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 frequency
+ * @channel: the DSSS channel
+ *
+ * Convert IEEE802.11 DSSS channel to 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 channels frequency
+ *
+ * Convert frequency (MHz) to IEEE802.11 DSSS channel
+ * Ref IEEE 802.11-2007 section 15.6
+ */
+static inline int ieee80211_freq_to_dsss_chan(int freq)
+{
+ if ((freq > 2407) && (freq < 2477))
+ return (freq - 2407) / 5;
+ else if (freq == 2484)
+ 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 frequency
+ * @s_freq: starting frequency == (dotChannelStartingFactor/2) MHz
+ * @channel: the OFDM channel
+ *
+ * Convert IEEE802.11 OFDM channel to 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 channels frequency
+ *
+ * Convert frequency (MHz) to IEEE802.11 OFDM channel
+ * Ref IEEE 802.11-2007 section 17.3.8.3.2
+ */
+static inline int ieee80211_freq_to_ofdm_chan(int s_freq, int freq)
+{
+ if ((freq > s_freq) && (freq <= (s_freq + 1200)) &&
+ (s_freq >= 4000))
+ return (freq - s_freq) / 5;
+ else
+ return -1;
+}
+
#endif /* LINUX_IEEE80211_H */
--
1.5.6.4
On Sat, 2008-12-20 at 18:31 +0000, David Kilroy wrote:
> While refactorring orinoco I found I was encapsulating the static
> channel frequency table. A quick poll of drivers showed that a number of
> the older driver have their own version of the table, and use it in the
> same way. So rather than keep this to orinoco I added the function to
> the ieee80211 header.
>
> To be complete I've added conversion routines for all the
> bands/modulations in IEEE 802.11-2007
>
> Does this seem reasonable? Should they go somewhere else?
Seems fine, though maybe lib80211 would be appropriate? I'd hate using
lib80211 in cfg80211 though since that pulls in all crypto bits that we
don't need there. OTOH, the code really isn't big, so I wouldn't worry
about inlining them.
johannes
Johannes Berg wrote:
> On Sat, 2008-12-20 at 18:31 +0000, David Kilroy wrote:
>> While refactorring orinoco I found I was encapsulating the static
>> channel frequency table. A quick poll of drivers showed that a number of
>> the older driver have their own version of the table, and use it in the
>> same way. So rather than keep this to orinoco I added the function to
>> the ieee80211 header.
>>
>> To be complete I've added conversion routines for all the
>> bands/modulations in IEEE 802.11-2007
>>
>> Does this seem reasonable? Should they go somewhere else?
>
> Seems fine, though maybe lib80211 would be appropriate? I'd hate using
> lib80211 in cfg80211 though since that pulls in all crypto bits that we
> don't need there. OTOH, the code really isn't big, so I wouldn't worry
> about inlining them.
I didn't quite get what you meant by that last statement - did you mean
that the inlining is OK, or that you'd prefer them not inlined?
If you meant the former (and there aren't any strong opinions about
lib80211), I'll just submit as is.
Regards,
Dave.
On Mon, 22 Dec 2008 10:28:54 +0000, Dave <[email protected]> wrote:
> I didn't quite get what you meant by that last statement - did you mean
> that the inlining is OK, or that you'd prefer them not inlined?
>
> If you meant the former (and there aren't any strong opinions about
> lib80211), I'll just submit as is.
Sorry, I meant it's fine, go ahead.
johannes