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 <kilroyd@xxxxxxxxxxxxxx> --- 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 -- To unsubscribe from this list: send the line "unsubscribe linux-wireless" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html