0001 .. SPDX-License-Identifier: GPL-2.0
0002
0003 =======================================
0004 Linux wireless regulatory documentation
0005 =======================================
0006
0007 This document gives a brief review over how the Linux wireless
0008 regulatory infrastructure works.
0009
0010 More up to date information can be obtained at the project's web page:
0011
0012 https://wireless.wiki.kernel.org/en/developers/Regulatory
0013
0014 Keeping regulatory domains in userspace
0015 ---------------------------------------
0016
0017 Due to the dynamic nature of regulatory domains we keep them
0018 in userspace and provide a framework for userspace to upload
0019 to the kernel one regulatory domain to be used as the central
0020 core regulatory domain all wireless devices should adhere to.
0021
0022 How to get regulatory domains to the kernel
0023 -------------------------------------------
0024
0025 When the regulatory domain is first set up, the kernel will request a
0026 database file (regulatory.db) containing all the regulatory rules. It
0027 will then use that database when it needs to look up the rules for a
0028 given country.
0029
0030 How to get regulatory domains to the kernel (old CRDA solution)
0031 ---------------------------------------------------------------
0032
0033 Userspace gets a regulatory domain in the kernel by having
0034 a userspace agent build it and send it via nl80211. Only
0035 expected regulatory domains will be respected by the kernel.
0036
0037 A currently available userspace agent which can accomplish this
0038 is CRDA - central regulatory domain agent. Its documented here:
0039
0040 https://wireless.wiki.kernel.org/en/developers/Regulatory/CRDA
0041
0042 Essentially the kernel will send a udev event when it knows
0043 it needs a new regulatory domain. A udev rule can be put in place
0044 to trigger crda to send the respective regulatory domain for a
0045 specific ISO/IEC 3166 alpha2.
0046
0047 Below is an example udev rule which can be used:
0048
0049 # Example file, should be put in /etc/udev/rules.d/regulatory.rules
0050 KERNEL=="regulatory*", ACTION=="change", SUBSYSTEM=="platform", RUN+="/sbin/crda"
0051
0052 The alpha2 is passed as an environment variable under the variable COUNTRY.
0053
0054 Who asks for regulatory domains?
0055 --------------------------------
0056
0057 * Users
0058
0059 Users can use iw:
0060
0061 https://wireless.wiki.kernel.org/en/users/Documentation/iw
0062
0063 An example::
0064
0065 # set regulatory domain to "Costa Rica"
0066 iw reg set CR
0067
0068 This will request the kernel to set the regulatory domain to
0069 the specificied alpha2. The kernel in turn will then ask userspace
0070 to provide a regulatory domain for the alpha2 specified by the user
0071 by sending a uevent.
0072
0073 * Wireless subsystems for Country Information elements
0074
0075 The kernel will send a uevent to inform userspace a new
0076 regulatory domain is required. More on this to be added
0077 as its integration is added.
0078
0079 * Drivers
0080
0081 If drivers determine they need a specific regulatory domain
0082 set they can inform the wireless core using regulatory_hint().
0083 They have two options -- they either provide an alpha2 so that
0084 crda can provide back a regulatory domain for that country or
0085 they can build their own regulatory domain based on internal
0086 custom knowledge so the wireless core can respect it.
0087
0088 *Most* drivers will rely on the first mechanism of providing a
0089 regulatory hint with an alpha2. For these drivers there is an additional
0090 check that can be used to ensure compliance based on custom EEPROM
0091 regulatory data. This additional check can be used by drivers by
0092 registering on its struct wiphy a reg_notifier() callback. This notifier
0093 is called when the core's regulatory domain has been changed. The driver
0094 can use this to review the changes made and also review who made them
0095 (driver, user, country IE) and determine what to allow based on its
0096 internal EEPROM data. Devices drivers wishing to be capable of world
0097 roaming should use this callback. More on world roaming will be
0098 added to this document when its support is enabled.
0099
0100 Device drivers who provide their own built regulatory domain
0101 do not need a callback as the channels registered by them are
0102 the only ones that will be allowed and therefore *additional*
0103 channels cannot be enabled.
0104
0105 Example code - drivers hinting an alpha2:
0106 ------------------------------------------
0107
0108 This example comes from the zd1211rw device driver. You can start
0109 by having a mapping of your device's EEPROM country/regulatory
0110 domain value to a specific alpha2 as follows::
0111
0112 static struct zd_reg_alpha2_map reg_alpha2_map[] = {
0113 { ZD_REGDOMAIN_FCC, "US" },
0114 { ZD_REGDOMAIN_IC, "CA" },
0115 { ZD_REGDOMAIN_ETSI, "DE" }, /* Generic ETSI, use most restrictive */
0116 { ZD_REGDOMAIN_JAPAN, "JP" },
0117 { ZD_REGDOMAIN_JAPAN_ADD, "JP" },
0118 { ZD_REGDOMAIN_SPAIN, "ES" },
0119 { ZD_REGDOMAIN_FRANCE, "FR" },
0120
0121 Then you can define a routine to map your read EEPROM value to an alpha2,
0122 as follows::
0123
0124 static int zd_reg2alpha2(u8 regdomain, char *alpha2)
0125 {
0126 unsigned int i;
0127 struct zd_reg_alpha2_map *reg_map;
0128 for (i = 0; i < ARRAY_SIZE(reg_alpha2_map); i++) {
0129 reg_map = ®_alpha2_map[i];
0130 if (regdomain == reg_map->reg) {
0131 alpha2[0] = reg_map->alpha2[0];
0132 alpha2[1] = reg_map->alpha2[1];
0133 return 0;
0134 }
0135 }
0136 return 1;
0137 }
0138
0139 Lastly, you can then hint to the core of your discovered alpha2, if a match
0140 was found. You need to do this after you have registered your wiphy. You
0141 are expected to do this during initialization.
0142
0143 ::
0144
0145 r = zd_reg2alpha2(mac->regdomain, alpha2);
0146 if (!r)
0147 regulatory_hint(hw->wiphy, alpha2);
0148
0149 Example code - drivers providing a built in regulatory domain:
0150 --------------------------------------------------------------
0151
0152 [NOTE: This API is not currently available, it can be added when required]
0153
0154 If you have regulatory information you can obtain from your
0155 driver and you *need* to use this we let you build a regulatory domain
0156 structure and pass it to the wireless core. To do this you should
0157 kmalloc() a structure big enough to hold your regulatory domain
0158 structure and you should then fill it with your data. Finally you simply
0159 call regulatory_hint() with the regulatory domain structure in it.
0160
0161 Bellow is a simple example, with a regulatory domain cached using the stack.
0162 Your implementation may vary (read EEPROM cache instead, for example).
0163
0164 Example cache of some regulatory domain::
0165
0166 struct ieee80211_regdomain mydriver_jp_regdom = {
0167 .n_reg_rules = 3,
0168 .alpha2 = "JP",
0169 //.alpha2 = "99", /* If I have no alpha2 to map it to */
0170 .reg_rules = {
0171 /* IEEE 802.11b/g, channels 1..14 */
0172 REG_RULE(2412-10, 2484+10, 40, 6, 20, 0),
0173 /* IEEE 802.11a, channels 34..48 */
0174 REG_RULE(5170-10, 5240+10, 40, 6, 20,
0175 NL80211_RRF_NO_IR),
0176 /* IEEE 802.11a, channels 52..64 */
0177 REG_RULE(5260-10, 5320+10, 40, 6, 20,
0178 NL80211_RRF_NO_IR|
0179 NL80211_RRF_DFS),
0180 }
0181 };
0182
0183 Then in some part of your code after your wiphy has been registered::
0184
0185 struct ieee80211_regdomain *rd;
0186 int size_of_regd;
0187 int num_rules = mydriver_jp_regdom.n_reg_rules;
0188 unsigned int i;
0189
0190 size_of_regd = sizeof(struct ieee80211_regdomain) +
0191 (num_rules * sizeof(struct ieee80211_reg_rule));
0192
0193 rd = kzalloc(size_of_regd, GFP_KERNEL);
0194 if (!rd)
0195 return -ENOMEM;
0196
0197 memcpy(rd, &mydriver_jp_regdom, sizeof(struct ieee80211_regdomain));
0198
0199 for (i=0; i < num_rules; i++)
0200 memcpy(&rd->reg_rules[i],
0201 &mydriver_jp_regdom.reg_rules[i],
0202 sizeof(struct ieee80211_reg_rule));
0203 regulatory_struct_hint(rd);
0204
0205 Statically compiled regulatory database
0206 ---------------------------------------
0207
0208 When a database should be fixed into the kernel, it can be provided as a
0209 firmware file at build time that is then linked into the kernel.