All of lore.kernel.org
 help / color / mirror / Atom feed
From: Larry Finger <Larry.Finger@lwfinger.net>
To: netdev@vger.kernel.org, John Linville <linville@tuxdriver.com>
Subject: [RFC ] [3 of 4] IEEE802.11 Regulatory/Geographical Support for drivers - Patches for ieee80211
Date: Sat, 03 Jun 2006 17:45:54 -0500	[thread overview]
Message-ID: <44821122.5080909@lwfinger.net> (raw)

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);

                 reply	other threads:[~2006-06-03 22:45 UTC|newest]

Thread overview: [no followups] expand[flat|nested]  mbox.gz  Atom feed

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=44821122.5080909@lwfinger.net \
    --to=larry.finger@lwfinger.net \
    --cc=linville@tuxdriver.com \
    --cc=netdev@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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.