About Kernel Documentation Linux Kernel Contact Linux Resources Linux Blog

Documentation / networking / regulatory.txt




Custom Search

Based on kernel version 4.16.1. Page generated on 2018-04-09 11:53 EST.

1	Linux wireless regulatory documentation
2	---------------------------------------
3	
4	This document gives a brief review over how the Linux wireless
5	regulatory infrastructure works.
6	
7	More up to date information can be obtained at the project's web page:
8	
9	http://wireless.kernel.org/en/developers/Regulatory
10	
11	Keeping regulatory domains in userspace
12	---------------------------------------
13	
14	Due to the dynamic nature of regulatory domains we keep them
15	in userspace and provide a framework for userspace to upload
16	to the kernel one regulatory domain to be used as the central
17	core regulatory domain all wireless devices should adhere to.
18	
19	How to get regulatory domains to the kernel
20	-------------------------------------------
21	
22	When the regulatory domain is first set up, the kernel will request a
23	database file (regulatory.db) containing all the regulatory rules. It
24	will then use that database when it needs to look up the rules for a
25	given country.
26	
27	How to get regulatory domains to the kernel (old CRDA solution)
28	---------------------------------------------------------------
29	
30	Userspace gets a regulatory domain in the kernel by having
31	a userspace agent build it and send it via nl80211. Only
32	expected regulatory domains will be respected by the kernel.
33	
34	A currently available userspace agent which can accomplish this
35	is CRDA - central regulatory domain agent. Its documented here:
36	
37	http://wireless.kernel.org/en/developers/Regulatory/CRDA
38	
39	Essentially the kernel will send a udev event when it knows
40	it needs a new regulatory domain. A udev rule can be put in place
41	to trigger crda to send the respective regulatory domain for a
42	specific ISO/IEC 3166 alpha2.
43	
44	Below is an example udev rule which can be used:
45	
46	# Example file, should be put in /etc/udev/rules.d/regulatory.rules
47	KERNEL=="regulatory*", ACTION=="change", SUBSYSTEM=="platform", RUN+="/sbin/crda"
48	
49	The alpha2 is passed as an environment variable under the variable COUNTRY.
50	
51	Who asks for regulatory domains?
52	--------------------------------
53	
54	* Users
55	
56	Users can use iw:
57	
58	http://wireless.kernel.org/en/users/Documentation/iw
59	
60	An example:
61	
62	  # set regulatory domain to "Costa Rica"
63	  iw reg set CR
64	
65	This will request the kernel to set the regulatory domain to
66	the specificied alpha2. The kernel in turn will then ask userspace
67	to provide a regulatory domain for the alpha2 specified by the user
68	by sending a uevent.
69	
70	* Wireless subsystems for Country Information elements
71	
72	The kernel will send a uevent to inform userspace a new
73	regulatory domain is required. More on this to be added
74	as its integration is added.
75	
76	* Drivers
77	
78	If drivers determine they need a specific regulatory domain
79	set they can inform the wireless core using regulatory_hint().
80	They have two options -- they either provide an alpha2 so that
81	crda can provide back a regulatory domain for that country or
82	they can build their own regulatory domain based on internal
83	custom knowledge so the wireless core can respect it.
84	
85	*Most* drivers will rely on the first mechanism of providing a
86	regulatory hint with an alpha2. For these drivers there is an additional
87	check that can be used to ensure compliance based on custom EEPROM
88	regulatory data. This additional check can be used by drivers by
89	registering on its struct wiphy a reg_notifier() callback. This notifier
90	is called when the core's regulatory domain has been changed. The driver
91	can use this to review the changes made and also review who made them
92	(driver, user, country IE) and determine what to allow based on its
93	internal EEPROM data. Devices drivers wishing to be capable of world
94	roaming should use this callback. More on world roaming will be
95	added to this document when its support is enabled.
96	
97	Device drivers who provide their own built regulatory domain
98	do not need a callback as the channels registered by them are
99	the only ones that will be allowed and therefore *additional*
100	channels cannot be enabled.
101	
102	Example code - drivers hinting an alpha2:
103	------------------------------------------
104	
105	This example comes from the zd1211rw device driver. You can start
106	by having a mapping of your device's EEPROM country/regulatory
107	domain value to a specific alpha2 as follows:
108	
109	static struct zd_reg_alpha2_map reg_alpha2_map[] = {
110		{ ZD_REGDOMAIN_FCC, "US" },
111		{ ZD_REGDOMAIN_IC, "CA" },
112		{ ZD_REGDOMAIN_ETSI, "DE" }, /* Generic ETSI, use most restrictive */
113		{ ZD_REGDOMAIN_JAPAN, "JP" },
114		{ ZD_REGDOMAIN_JAPAN_ADD, "JP" },
115		{ ZD_REGDOMAIN_SPAIN, "ES" },
116		{ ZD_REGDOMAIN_FRANCE, "FR" },
117	
118	Then you can define a routine to map your read EEPROM value to an alpha2,
119	as follows:
120	
121	static int zd_reg2alpha2(u8 regdomain, char *alpha2)
122	{
123		unsigned int i;
124		struct zd_reg_alpha2_map *reg_map;
125			for (i = 0; i < ARRAY_SIZE(reg_alpha2_map); i++) {
126				reg_map = &reg_alpha2_map[i];
127				if (regdomain == reg_map->reg) {
128				alpha2[0] = reg_map->alpha2[0];
129				alpha2[1] = reg_map->alpha2[1];
130				return 0;
131			}
132		}
133		return 1;
134	}
135	
136	Lastly, you can then hint to the core of your discovered alpha2, if a match
137	was found. You need to do this after you have registered your wiphy. You
138	are expected to do this during initialization.
139	
140		r = zd_reg2alpha2(mac->regdomain, alpha2);
141		if (!r)
142			regulatory_hint(hw->wiphy, alpha2);
143	
144	Example code - drivers providing a built in regulatory domain:
145	--------------------------------------------------------------
146	
147	[NOTE: This API is not currently available, it can be added when required]
148	
149	If you have regulatory information you can obtain from your
150	driver and you *need* to use this we let you build a regulatory domain
151	structure and pass it to the wireless core. To do this you should
152	kmalloc() a structure big enough to hold your regulatory domain
153	structure and you should then fill it with your data. Finally you simply
154	call regulatory_hint() with the regulatory domain structure in it.
155	
156	Bellow is a simple example, with a regulatory domain cached using the stack.
157	Your implementation may vary (read EEPROM cache instead, for example).
158	
159	Example cache of some regulatory domain
160	
161	struct ieee80211_regdomain mydriver_jp_regdom = {
162		.n_reg_rules = 3,
163		.alpha2 =  "JP",
164		//.alpha2 =  "99", /* If I have no alpha2 to map it to */
165		.reg_rules = {
166			/* IEEE 802.11b/g, channels 1..14 */
167			REG_RULE(2412-10, 2484+10, 40, 6, 20, 0),
168			/* IEEE 802.11a, channels 34..48 */
169			REG_RULE(5170-10, 5240+10, 40, 6, 20,
170				NL80211_RRF_NO_IR),
171			/* IEEE 802.11a, channels 52..64 */
172			REG_RULE(5260-10, 5320+10, 40, 6, 20,
173				NL80211_RRF_NO_IR|
174				NL80211_RRF_DFS),
175		}
176	};
177	
178	Then in some part of your code after your wiphy has been registered:
179	
180		struct ieee80211_regdomain *rd;
181		int size_of_regd;
182		int num_rules = mydriver_jp_regdom.n_reg_rules;
183		unsigned int i;
184	
185		size_of_regd = sizeof(struct ieee80211_regdomain) +
186			(num_rules * sizeof(struct ieee80211_reg_rule));
187	
188		rd = kzalloc(size_of_regd, GFP_KERNEL);
189		if (!rd)
190			return -ENOMEM;
191	
192		memcpy(rd, &mydriver_jp_regdom, sizeof(struct ieee80211_regdomain));
193	
194		for (i=0; i < num_rules; i++)
195			memcpy(&rd->reg_rules[i],
196			       &mydriver_jp_regdom.reg_rules[i],
197			       sizeof(struct ieee80211_reg_rule));
198		regulatory_struct_hint(rd);
199	
200	Statically compiled regulatory database
201	---------------------------------------
202	
203	When a database should be fixed into the kernel, it can be provided as a
204	firmware file at build time that is then linked into the kernel.
Hide Line Numbers
About Kernel Documentation Linux Kernel Contact Linux Resources Linux Blog

Information is copyright its respective author. All material is available from the Linux Kernel Source distributed under a GPL License. This page is provided as a free service by mjmwired.net.