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, ®domain_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 --]
next prev 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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox