All of lore.kernel.org
 help / color / mirror / Atom feed
From: "Luis R. Rodriguez" <mcgrof@gmail.com>
To: John Linville <linville@tuxdriver.com>
Cc: linux-wireless@vger.kernel.org,
	Michael Wu <flamingice@sourmilk.net>,
	Johannes Berg <johannes@sipsolutions.net>,
	Daniel Drake <dsd@gentoo.org>,
	Larry Finger <Larry.Finger@lwfinger.net>
Subject: [PATCH 4/5] Wireless: Add regdomain support to cfg80211
Date: Fri, 21 Sep 2007 17:07:01 -0400	[thread overview]
Message-ID: <20070921210701.GH31768@pogo> (raw)
In-Reply-To: <20070921204606.GD31768@pogo>

[-- Attachment #1: Type: text/plain, Size: 10216 bytes --]

This patch makes cfg80211 provide an interface for defining
a central regulatory domain all cfg80211 wireless drivers
should adhere to.

Now when cfg80211 starts up and you will see this:

ieee80211_regdomains: regulatory domain WORLD created
Regulatory Domain:      WORLD   Regulatory Domain ID:   0x03
        IEEE 802.11g    2GHz    ISM subband
        max_ir_ptmp:    20 dBm  max_eirp_ptmp:  20 dBm
        max_ir_ptp:     0 dBm   max_eirp_ptp:   0 dBm
        max_antenna_gain:       6 dBi
        Environment capability: Indoor & Outdoor
                Channel Freq (MHz)
                5       2432
                6       2437
                7       2442

Signed-off-by: Luis R. Rodriguez <mcgrof@gmail.com>
---
 include/net/cfg80211.h |   72 ++++++++++++++++++++++++++
 net/wireless/Kconfig   |    1 +
 net/wireless/core.c    |  133 ++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 206 insertions(+), 0 deletions(-)

diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index 1459d12..34fd74b 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -5,11 +5,13 @@
 #include <linux/skbuff.h>
 #include <linux/nl80211.h>
 #include <net/genetlink.h>
+#include <net/ieee80211_regdomains.h>
 
 /*
  * 802.11 configuration in-kernel interface
  *
  * Copyright 2006 Johannes Berg <johannes@sipsolutions.net>
+ * Copyright 2007 Luis R. Rodriguez <mcgrof@winlab.rutgers.edu>
  */
 
 /**
@@ -117,6 +119,73 @@ extern int ieee80211_radiotap_iterator_next(
 struct wiphy;
 
 /**
+ * enum regdom_set_by - the different ways by which the central regulatory
+ *   domain can be set
+ *
+ * @REG_SET_BY_INIT: indicates regdomain was set by regdomain_init()
+ * @REG_SET_BY_DRIVER: indicates regdomain was set by a driver 
+ * 	through cfg80211_set_regdomain(). This type of settings is ignored if
+ * 	the regdomain was already set by userspace (%REG_SET_BY_USER). If
+ * 	userspace never set the regdomain and two drivers are found trying to
+ * 	set the regdomain to two different regdomains then the world regulatory
+ * 	domain will be set by cfg80211_set_regdomain().
+ * @REG_SET_BY_USER: indicates regdomain was set by userspace.
+ * @REG_SET_BY_80211D: indicates an 802.11d frame was received with a valid
+ * 	country information element to which the wireless stack is going to
+ * 	adhere to.
+ * @REG_SET_BY_CONFLICT: indicates a conflict was found and regdomain was 
+ * 	therefore set to the world regulatory domain by 
+ * 	cfg80211_set_regdomain().
+ */
+enum regdom_set_by {
+	REG_SET_BY_INIT = 1,
+	REG_SET_BY_DRIVER,
+	REG_SET_BY_USER,
+	REG_SET_BY_80211D,
+	REG_SET_BY_CONFLICT
+};
+
+/**
+ * struct cfg80211_regdomain_settings - central regulatory domain settings
+ *
+ * @regdomain: central regulatory domain, an &ieee80211_regdomain
+ *
+ * @country: country to which this regulatory domain corresponds in the 
+ * 	last setting. This must be a valid ISO3166-1 country or one of the 
+ * 	accepted exceptions, such as 00 for the world regulatory domain or 
+ * 	UK for the United Kingdom.
+ *
+ * @set_by: tells us who set last the regualtory domain. This can be any of 
+ * 	%regdom_set_by
+ *
+ * @wiphy: wiphy of driver who last set the regdomain, if set by 
+ * 	driver. This used to determine conflicts of driver regulatory domains 
+ * 	settings if more than one wirless card is present and to simply keep
+ * 	record if a driver set the regulatory domain which driver set it.
+ *
+ * This structure defines the cfg80211 central wireless regulatory domain
+ * structure which all cfg80211 drivers should adhere to. It is initialized to
+ * the world regulatory domain by cfg80211 by default (%REG_SET_BY_INIT). If a
+ * wireless driver present has a built-in regulatory domain set either in the
+ * EEPROM or firmware it can inform cfg80211 about this and change the 
+ * regulatory domain as such (%REG_SET_BY_DRIVER). If a second wireless card
+ * is present and if there is a conflict between regulatory domains then the
+ * world regulatory domain is set (%REG_SET_BY_CONFLICT). The regulatory domain
+ * can also be changed by receiving an 802.11d frame with a valid country code
+ * (%REG_SET_BY_80211D). Finally, If the regulatory domain was set by userspace
+ * (%REG_SET_BY_USER) then driver specific setting of regulatory domains 
+ * (%REG_SET_BY_DRIVER) and 802.11d frames for changing the regulatory domain
+ * (%REG_SET_BY_80211D) will be ignored.
+ */
+struct cfg80211_regdomain_settings {
+	struct ieee80211_regdomain *regdomain;
+	enum regdom_set_by set_by;
+	struct wiphy *wiphy;
+	char country[ISOCOUNTRYSIZ2];
+};
+
+
+/**
  * struct cfg80211_ops - backend description for wireless configuration
  *
  * This struct is registered by fullmac card drivers and/or wireless stacks
@@ -183,6 +252,9 @@ struct cfg80211_ops {
 			   struct key_params *params);
 };
 
+extern int cfg80211_set_regdomain(char *country, u32,
+				enum regdom_set_by set_by,
+				struct wiphy *wiphy_reg_set);
 
 /* helper functions specific to nl80211 */
 extern void *nl80211hdr_put(struct sk_buff *skb, u32 pid,
diff --git a/net/wireless/Kconfig b/net/wireless/Kconfig
index c60ee87..0505347 100644
--- a/net/wireless/Kconfig
+++ b/net/wireless/Kconfig
@@ -1,5 +1,6 @@
 config CFG80211
         tristate "Improved wireless configuration API"
+	select IEEE80211_REGDOMAINS
 
 config NL80211
 	bool "nl80211 new netlink interface support"
diff --git a/net/wireless/core.c b/net/wireless/core.c
index 2f3f7b6..c2f773b 100644
--- a/net/wireless/core.c
+++ b/net/wireless/core.c
@@ -2,6 +2,7 @@
  * This is the linux wireless configuration interface.
  *
  * Copyright 2006, 2007		Johannes Berg <johannes@sipsolutions.net>
+ * Copyright 2007		Luis R. Rodriguez <mcgrof@winlab.rutgers.edu>
  */
 
 #include <linux/if.h>
@@ -34,6 +35,14 @@ LIST_HEAD(cfg80211_drv_list);
 DEFINE_MUTEX(cfg80211_drv_mutex);
 static int wiphy_counter;
 
+/* All cfg80211 drivers adhere to this */
+struct cfg80211_regdomain_settings cfg80211_regdomain;
+EXPORT_SYMBOL(cfg80211_regdomain);
+/* Since the regulatory domain may be set by different events we protect its
+ * structure */
+DEFINE_MUTEX(cfg80211_regdomain_mutex);
+EXPORT_SYMBOL(cfg80211_regdomain_mutex);
+
 /* for debugfs */
 static struct dentry *ieee80211_debugfs_dir;
 
@@ -335,12 +344,135 @@ static struct notifier_block cfg80211_netdev_notifier = {
 	.notifier_call = cfg80211_netdev_notifier_call,
 };
 
+int cfg80211_set_regdomain(char *country, u32 regdomain_id,
+	enum regdom_set_by set_by, 
+	struct wiphy *wiphy_reg_set)
+{
+	struct ieee80211_regdomain *old_reg, *new_reg;
+	int r = 0;
+	enum regdom_set_by old_set_by;
+	int needs_freeing = 0;
+
+	mutex_lock(&cfg80211_regdomain_mutex);
+	old_reg = cfg80211_regdomain.regdomain;
+	old_set_by = cfg80211_regdomain.set_by;
+
+	switch (cfg80211_regdomain.set_by) {
+	case 0:
+		switch (set_by) {
+		case REG_SET_BY_INIT:
+			/* XXX: Test this first */
+			cfg80211_regdomain.set_by = REG_SET_BY_INIT;
+			break;
+		default:
+			/* Should not happen unless later we support clearing 
+			 * of set_by before calling this routine */
+			r = -EOPNOTSUPP;
+			goto unlock_and_exit;
+		}
+		break;
+	case REG_SET_BY_INIT:
+		switch (set_by) {
+		case REG_SET_BY_INIT:
+			/* Should never happen */
+			r = -EOPNOTSUPP;
+			goto unlock_and_exit;
+		case REG_SET_BY_DRIVER:
+			if (wiphy_reg_set == NULL) {
+				r =-EINVAL;
+				goto unlock_and_exit;
+			}
+			/* XXX: This is not handled yet */
+			r = -EOPNOTSUPP; /* Not handled yet */
+			goto unlock_and_exit;
+		case REG_SET_BY_USER:
+			printk("Userspace changed regulatory domain\n");
+			/* XXX don't free until we know for sure we set
+			 * a new regdomain, then free it and arrange pointers */
+			needs_freeing = 1;
+			cfg80211_regdomain.set_by = REG_SET_BY_USER;
+			break;
+		default:
+			BUG();
+		}
+		break;
+	case REG_SET_BY_USER:
+		switch (set_by) {
+		case REG_SET_BY_USER:
+			printk("Userspace changed regulatory domain\n");
+			needs_freeing = 1;
+			cfg80211_regdomain.set_by = REG_SET_BY_USER;
+			break;
+		default:
+			r = -EOPNOTSUPP; /* Not handled yet */
+			goto unlock_and_exit;
+		}
+		break;
+	default:
+		r = -EOPNOTSUPP; /* Not handled yet */
+		goto unlock_and_exit;
+		break;
+	}
+
+	/* This does all the work */
+	r = regdomain_build(regdomain_id, &new_reg);
+	if(r) {
+		cfg80211_regdomain.set_by =  old_set_by;
+		goto unlock_and_exit;
+	}
+
+	if (needs_freeing) {
+		free_regdomain(old_reg);
+		cfg80211_regdomain.regdomain = NULL;
+	}
+
+	strcpy(cfg80211_regdomain.country, country);
+	cfg80211_regdomain.country[ISOCOUNTRYSIZ2] = '\0';
+	/* Lastly, update pointer */
+	cfg80211_regdomain.regdomain = new_reg;
+	mutex_unlock(&cfg80211_regdomain_mutex);
+	print_regdomain(cfg80211_regdomain.regdomain);
+
+	return 0;
+
+unlock_and_exit:
+	mutex_unlock(&cfg80211_regdomain_mutex);
+	return r;
+}
+EXPORT_SYMBOL(cfg80211_set_regdomain);
+
+static int regdomain_init(void)
+{
+	int r;
+	char country[ISOCOUNTRYSIZ2] = DEFAULT_REG_ISO3166_1;
+	u32 regdomain_id = 0; /* Initialize just to shut up GCC */
+
+	country[ISOCOUNTRYSIZ2] = '\0';
+
+	memset(&cfg80211_regdomain, 0, 
+		sizeof(struct cfg80211_regdomain_settings));
+
+	r = iso3166_to_reg(country, &regdomain_id);
+	if (r)
+		return r;
+	r = cfg80211_set_regdomain(country, regdomain_id, 
+		REG_SET_BY_INIT, NULL);
+	if (r)
+		return r;
+
+	return 0;
+}
+
 static int cfg80211_init(void)
 {
 	int err = wiphy_sysfs_init();
 	if (err)
 		goto out_fail_sysfs;
 
+	err = regdomain_init();
+	if (err)
+		goto out_fail_sysfs;
+
 	err = register_netdevice_notifier(&cfg80211_netdev_notifier);
 	if (err)
 		goto out_fail_notifier;
@@ -367,6 +499,7 @@ static void cfg80211_exit(void)
 	debugfs_remove(ieee80211_debugfs_dir);
 	nl80211_exit();
 	unregister_netdevice_notifier(&cfg80211_netdev_notifier);
+	free_regdomain(cfg80211_regdomain.regdomain);
 	wiphy_sysfs_exit();
 }
 module_exit(cfg80211_exit);
-- 
1.5.2.4


[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 189 bytes --]

  parent reply	other threads:[~2007-09-21 21:05 UTC|newest]

Thread overview: 23+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2007-09-21 20:46 [PATCH 0/5] Add central regulatory domain agent - Patchset I Luis R. Rodriguez
2007-09-21 20:46 ` Dan Williams
2007-09-21 20:47 ` Dan Williams
2007-09-21 21:00 ` [PATCH 1/5] Move standard wireless defintions out of mac80211 Luis R. Rodriguez
2007-09-21 21:17   ` Johannes Berg
2007-09-21 21:33     ` Luis R. Rodriguez
2007-09-24  9:49       ` Joerg Mayer
2007-09-24 17:49         ` Luis R. Rodriguez
2007-09-26 15:01           ` Dan Williams
2007-09-26 15:48             ` Luis R. Rodriguez
2007-09-21 21:04 ` [PATCH 3/5] Wireless: add IEEE-802.11 regualtory domain module Luis R. Rodriguez
2007-09-21 21:30   ` Johannes Berg
2007-09-21 21:52     ` Luis R. Rodriguez
2007-09-21 21:58       ` Johannes Berg
2007-09-21 22:57         ` Luis R. Rodriguez
2007-09-21 21:07 ` Luis R. Rodriguez [this message]
2007-09-21 21:08 ` [PATCH 5/5] Wireless: add wireless configfs module Luis R. Rodriguez
2007-09-21 21:17 ` [PATCH 5/5] Wireless: add wireless configfs module - v2 Luis R. Rodriguez
2007-09-21 21:39 ` [PATCH 0/5] Add central regulatory domain agent - Patchset I Dan Williams
2007-09-21 21:49   ` Johannes Berg
2007-09-21 22:00     ` Luis R. Rodriguez
2007-09-22  0:14       ` Luis R. Rodriguez
2007-09-22  0:23         ` Luis R. Rodriguez

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=20070921210701.GH31768@pogo \
    --to=mcgrof@gmail.com \
    --cc=Larry.Finger@lwfinger.net \
    --cc=dsd@gentoo.org \
    --cc=flamingice@sourmilk.net \
    --cc=johannes@sipsolutions.net \
    --cc=linux-wireless@vger.kernel.org \
    --cc=linville@tuxdriver.com \
    /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.