* [RFC ] [3 of 4] IEEE802.11 Regulatory/Geographical Support for drivers - Patches for ieee80211
@ 2006-06-03 22:45 Larry Finger
0 siblings, 0 replies; only message in thread
From: Larry Finger @ 2006-06-03 22:45 UTC (permalink / raw)
To: netdev, John Linville
This message contains the patch to add routine ieee80211_init_geo to the kernel, and a new flag
definition for the IEEE80211 codes. Note: I know that my mailer has messed up the white space by
converting all the tabs to spaces. The original files are OK. Larry
=====================================================================================
diff --git a/include/net/ieee80211.h b/include/net/ieee80211.h
index d5926bf..8a5dc0f 100644
--- a/include/net/ieee80211.h
+++ b/include/net/ieee80211.h
@@ -965,6 +965,7 @@ #define IEEE80211_52GHZ_CHANNELS (IEEE80
enum {
IEEE80211_CH_PASSIVE_ONLY = (1 << 0),
+ IEEE80211_CH_80211H_RULES = (1 << 1),
IEEE80211_CH_B_ONLY = (1 << 2),
IEEE80211_CH_NO_IBSS = (1 << 3),
IEEE80211_CH_UNIFORM_SPREADING = (1 << 4),
@@ -973,10 +974,10 @@ enum {
};
struct ieee80211_channel {
- u32 freq;
+ u32 freq; /* in MHz */
u8 channel;
u8 flags;
- u8 max_power;
+ u8 max_power; /* in dBm */
};
struct ieee80211_geo {
@@ -1260,6 +1261,9 @@ extern const struct ieee80211_geo *ieee8
extern int ieee80211_set_geo(struct ieee80211_device *ieee,
const struct ieee80211_geo *geo);
+extern int ieee80211_init_geo(struct ieee80211_device *ieee,
+ char * country, u8 outdoor);
+
extern int ieee80211_is_valid_channel(struct ieee80211_device *ieee,
u8 channel);
extern int ieee80211_channel_to_index(struct ieee80211_device *ieee,
diff --git a/net/ieee80211/ieee80211_geo.c b/net/ieee80211/ieee80211_geo.c
index 192243a..2e4806b 100644
--- a/net/ieee80211/ieee80211_geo.c
+++ b/net/ieee80211/ieee80211_geo.c
@@ -41,6 +41,7 @@ #include <linux/types.h>
#include <linux/wireless.h>
#include <linux/etherdevice.h>
#include <asm/uaccess.h>
+#include <linux/delay.h>
#include <net/ieee80211.h>
@@ -133,6 +134,136 @@ int ieee80211_set_geo(struct ieee80211_d
return 0;
}
+static char ieee80211_country[10];
+static uint ieee80211_outdoor;
+static struct proc_dir_entry *ieee80211_geo_proc;
+static uint ieee80211_data_back;
+struct ieee80211_geo *geo;
+static uint bytes_xfer;
+
+static int show_geo_country(char *page, char **start, off_t offset,
+ int count, int *eof, void *data)
+{
+ return snprintf(page, count, "%s %d\n", ieee80211_country, ieee80211_outdoor);
+}
+
+static int store_geo_data(struct file *file, const char __user * buffer,
+ unsigned long count, void *data)
+{
+ unsigned long len = min((unsigned long)sizeof(struct ieee80211_geo) , count);
+ int i;
+
+ if (copy_from_user((geo + bytes_xfer), buffer, len)) {
+ IEEE80211_ERROR( "Error return from copy_from_user.\n");
+ return -EFAULT;
+ }
+ bytes_xfer += len;
+ if (bytes_xfer == sizeof(struct ieee80211_geo)) {
+ IEEE80211_DEBUG_INFO( "All data has been received.\n");
+ if (!geo->bg_channels && !geo->a_channels) { /* if no channels specified - error */
+ IEEE80211_DEBUG_INFO( "No bg or a/h channels specified.\n");
+ return count;
+ }
+ if (geo->bg_channels > IEEE80211_24GHZ_CHANNELS) { /* too many bg channels */
+ IEEE80211_DEBUG_INFO( "Too many bg channels specified.\n");
+ return count;
+ }
+ if (geo->a_channels > IEEE80211_52GHZ_CHANNELS) { /* too many a channels */
+ IEEE80211_DEBUG_INFO( "Too many a/h channels specified.\n");
+ return count;
+ }
+ for (i=0; i<geo->a_channels; i++) {
+ if (geo->a[i].channel < IEEE80211_52GHZ_MIN_CHANNEL ||
+ geo->a[i].channel > IEEE80211_52GHZ_MAX_CHANNEL)
+ return count; /* here if channel out of range */
+ }
+ for (i=0; i<geo->bg_channels; i++) {
+ if (geo->bg[i].channel < IEEE80211_24GHZ_MIN_CHANNEL ||
+ geo->bg[i].channel > IEEE80211_24GHZ_MAX_CHANNEL)
+ return count; /* here if channel out of range */
+ }
+ IEEE80211_DEBUG_INFO( "Data passed sanity checks.\n"); /* data seems to be correct */
+ ieee80211_data_back = 0;
+ }
+ return count;
+}
+
+int ieee80211_init_geo(struct ieee80211_device *ieee,
+ char *country, u8 outdoor)
+{
+ int ret;
+ struct proc_dir_entry *e1, *e2;
+
+ static const struct ieee80211_geo ieee80211_geos[] = {
+ { /* Default parameters to be returned if daemon not running or other error */
+ "---",
+ .a_channels = 0,
+ .bg_channels = 11,
+ .bg = {{.freq = 2412, .channel = 1, .max_power = 20},
+ {.freq = 2417, .channel = 2, .max_power = 20},
+ {.freq = 2422, .channel = 3, .max_power = 20},
+ {.freq = 2427, .channel = 4, .max_power = 20},
+ {.freq = 2432, .channel = 5, .max_power = 20},
+ {.freq = 2437, .channel = 6, .max_power = 20},
+ {.freq = 2442, .channel = 7, .max_power = 20},
+ {.freq = 2447, .channel = 8, .max_power = 20},
+ {.freq = 2452, .channel = 9, .max_power = 20},
+ {.freq = 2457, .channel = 10, .max_power = 20},
+ {.freq = 2462, .channel = 11, .max_power = 20}
+ },
+ },
+ };
+
+ IEEE80211_DEBUG_INFO( "Country Code: %s, Outdoor: %d\n", country, outdoor);
+ memcpy(ieee80211_country, country, strlen(country));
+ ieee80211_outdoor = outdoor;
+ ieee80211_geo_proc = proc_mkdir("ieee80211_geo", proc_net);
+ (void)ieee80211_set_geo( ieee, ieee80211_geos); /* load default data in case of error */
+ if (ieee80211_geo_proc == NULL) {
+ IEEE80211_ERROR( "Unable to create ieee80211_geo"
+ " proc directory - default geo data loaded\n");
+ return -EIO;
+ }
+ geo = kzalloc(sizeof(struct ieee80211_geo), GFP_KERNEL);
+ if (!geo) {
+ ret = -ENOMEM;
+ goto cleanup;
+ }
+ e1 = create_proc_entry("geo_country", S_IFREG | S_IRUSR | S_IWUSR,
+ ieee80211_geo_proc);
+ e1->read_proc = show_geo_country;
+ e2 = create_proc_entry("geo_data", S_IWUSR | S_IWGRP | S_IWOTH,
+ ieee80211_geo_proc);
+ ieee80211_data_back = 1;
+ bytes_xfer = 0;
+ e2->write_proc = store_geo_data;
+
+ if (!e1 || !e2 ) {
+ IEEE80211_ERROR( "Unable to create files in ieee80211_geo"
+ " - default data loaded.\n");
+ ret = -EIO;
+ goto free_geo;
+ }
+ for (ret=0; ret<1000; ret++) {
+ if (!ieee80211_data_back)
+ break;
+ udelay(1000);
+ }
+ if (ret == 1000) {
+ ret = -EIO;
+ IEEE80211_DEBUG_INFO( "ieee80211_geo daemon not running - default data loaded.\n");
+ goto free_geo; /* daemon not running */
+ }
+ ret = ieee80211_set_geo( ieee, geo);
+free_geo:
+ kfree(geo);
+cleanup:
+ remove_proc_entry("geo_country", ieee80211_geo_proc);
+ remove_proc_entry("geo_data", ieee80211_geo_proc);
+ remove_proc_entry("ieee80211_geo", proc_net);
+ return ret;
+}
+
const struct ieee80211_geo *ieee80211_get_geo(struct ieee80211_device *ieee)
{
return &ieee->geo;
@@ -177,4 +308,5 @@ EXPORT_SYMBOL(ieee80211_is_valid_channel
EXPORT_SYMBOL(ieee80211_freq_to_channel);
EXPORT_SYMBOL(ieee80211_channel_to_index);
EXPORT_SYMBOL(ieee80211_set_geo);
+EXPORT_SYMBOL(ieee80211_init_geo);
EXPORT_SYMBOL(ieee80211_get_geo);
^ permalink raw reply related [flat|nested] only message in thread
only message in thread, other threads:[~2006-06-03 22:45 UTC | newest]
Thread overview: (only message) (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2006-06-03 22:45 [RFC ] [3 of 4] IEEE802.11 Regulatory/Geographical Support for drivers - Patches for ieee80211 Larry Finger
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.