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