Blame view

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