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 = ®_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