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