xref: /wlan-dirver/qca-wifi-host-cmn/umac/regulatory/core/src/reg_db_parser.c (revision 3149adf58a329e17232a4c0e58d460d025edd55a)
1 /*
2  * Copyright (c) 2017-2018 The Linux Foundation. All rights reserved.
3  *
4  *
5  * Permission to use, copy, modify, and/or distribute this software for
6  * any purpose with or without fee is hereby granted, provided that the
7  * above copyright notice and this permission notice appear in all
8  * copies.
9  *
10  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
11  * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
12  * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
13  * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
14  * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
15  * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
16  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
17  * PERFORMANCE OF THIS SOFTWARE.
18  */
19 
20 /**
21  * DOC: reg_db_parser.c
22  * This file provides regulatory data base parser functions.
23  */
24 
25 #include <qdf_types.h>
26 #include "reg_db_parser.h"
27 #include <qdf_mem.h>
28 #include "reg_priv.h"
29 #include "reg_services.h"
30 
31 QDF_STATUS reg_is_country_code_valid(uint8_t alpha[3])
32 {
33 	uint16_t i;
34 	int num_countries;
35 
36 	reg_get_num_countries(&num_countries);
37 
38 	for (i = 0; i < num_countries; i++) {
39 		if ((g_all_countries[i].alpha2[0] == alpha[0]) &&
40 				(g_all_countries[i].alpha2[1] == alpha[1]) &&
41 				(g_all_countries[i].alpha2[2] == alpha[2]))
42 			return QDF_STATUS_SUCCESS;
43 		else
44 			continue;
45 	}
46 
47 	return QDF_STATUS_E_FAILURE;
48 }
49 
50 QDF_STATUS reg_regrules_assign(uint8_t dmn_id_2g,
51 	uint8_t dmn_id_5g,
52 	uint8_t ant_gain_2g,
53 	uint8_t ant_gain_5g,
54 	struct cur_regulatory_info *reg_info)
55 
56 {
57 	uint8_t k;
58 	uint8_t rule_index;
59 	struct cur_reg_rule *r_r_2g = reg_info->reg_rules_2g_ptr;
60 	struct cur_reg_rule *r_r_5g = reg_info->reg_rules_5g_ptr;
61 
62 	for (k = 0; k < reg_info->num_2g_reg_rules; k++) {
63 		rule_index = regdomains_2g[dmn_id_2g].reg_rule_id[k];
64 		r_r_2g->start_freq = reg_rules_2g[rule_index].start_freq;
65 		r_r_2g->end_freq = reg_rules_2g[rule_index].end_freq;
66 		r_r_2g->max_bw = reg_rules_2g[rule_index].max_bw;
67 		r_r_2g->reg_power = reg_rules_2g[rule_index].reg_power;
68 		r_r_2g->flags = reg_rules_2g[rule_index].flags;
69 		r_r_2g->ant_gain = ant_gain_2g;
70 		r_r_2g++;
71 	}
72 
73 	for (k = 0; k < reg_info->num_5g_reg_rules; k++) {
74 		rule_index = regdomains_5g[dmn_id_5g].reg_rule_id[k];
75 		r_r_5g->start_freq = reg_rules_5g[rule_index].start_freq;
76 		r_r_5g->end_freq = reg_rules_5g[rule_index].end_freq;
77 		r_r_5g->max_bw = reg_rules_5g[rule_index].max_bw;
78 		r_r_5g->reg_power = reg_rules_5g[rule_index].reg_power;
79 		r_r_5g->flags = reg_rules_5g[rule_index].flags;
80 		r_r_5g->ant_gain = ant_gain_5g;
81 		r_r_5g++;
82 	}
83 
84 	if ((r_r_2g == reg_info->reg_rules_2g_ptr) &&
85 			(r_r_5g == reg_info->reg_rules_5g_ptr))
86 		return QDF_STATUS_E_FAILURE;
87 
88 	return QDF_STATUS_SUCCESS;
89 }
90 
91 QDF_STATUS reg_get_rdpair_from_country_iso(uint8_t *alpha,
92 	uint16_t *country_index,
93 	uint16_t *regdmn_pair)
94 {
95 	uint16_t i, j;
96 	int num_countries;
97 	int num_reg_dmn;
98 
99 	reg_get_num_countries(&num_countries);
100 	reg_get_num_reg_dmn_pairs(&num_reg_dmn);
101 
102 	for (i = 0; i < num_countries; i++) {
103 		if ((g_all_countries[i].alpha2_11d[0] == alpha[0]) &&
104 			(g_all_countries[i].alpha2_11d[1] == alpha[1]))
105 			break;
106 	}
107 
108 	if (i == num_countries) {
109 		*country_index = -1;
110 		return QDF_STATUS_E_FAILURE;
111 	}
112 
113 	for (j = 0; j < num_reg_dmn; j++) {
114 		if (g_reg_dmn_pairs[j].reg_dmn_pair_id ==
115 				g_all_countries[i].reg_dmn_pair_id)
116 			break;
117 	}
118 
119 	if (j == num_reg_dmn) {
120 		*regdmn_pair = -1;
121 		return QDF_STATUS_E_FAILURE;
122 	}
123 
124 	*country_index = i;
125 	*regdmn_pair = j;
126 
127 	return QDF_STATUS_SUCCESS;
128 }
129 
130 QDF_STATUS reg_get_rdpair_from_regdmn_id(uint16_t regdmn_id,
131 		uint16_t *regdmn_pair)
132 {
133 	uint16_t j;
134 	int num_reg_dmn;
135 
136 	reg_get_num_reg_dmn_pairs(&num_reg_dmn);
137 
138 	for (j = 0; j < num_reg_dmn; j++) {
139 		if (g_reg_dmn_pairs[j].reg_dmn_pair_id == regdmn_id)
140 			break;
141 	}
142 
143 	if (j == num_reg_dmn) {
144 		*regdmn_pair = -1;
145 		return QDF_STATUS_E_FAILURE;
146 	}
147 
148 	*regdmn_pair = j;
149 
150 	return QDF_STATUS_SUCCESS;
151 }
152 
153 QDF_STATUS reg_get_rdpair_from_country_code(uint16_t cc,
154 		uint16_t *country_index,
155 		uint16_t *regdmn_pair)
156 {
157 	uint16_t i, j;
158 	int num_countries;
159 	int num_reg_dmn;
160 
161 	reg_get_num_countries(&num_countries);
162 	reg_get_num_reg_dmn_pairs(&num_reg_dmn);
163 
164 	for (i = 0; i < num_countries; i++) {
165 		if (g_all_countries[i].country_code == cc)
166 			break;
167 	}
168 
169 	if (i == num_countries) {
170 		*country_index = -1;
171 		return QDF_STATUS_E_FAILURE;
172 	}
173 
174 	for (j = 0; j < num_reg_dmn; j++) {
175 		if (g_reg_dmn_pairs[j].reg_dmn_pair_id ==
176 				g_all_countries[i].reg_dmn_pair_id)
177 			break;
178 	}
179 
180 	if (j == num_reg_dmn) {
181 		*regdmn_pair = -1;
182 		return QDF_STATUS_E_FAILURE;
183 	}
184 
185 	*country_index = i;
186 	*regdmn_pair = j;
187 
188 	return QDF_STATUS_SUCCESS;
189 }
190 
191 static inline QDF_STATUS reg_get_reginfo_form_country_code_and_regdmn_pair(
192 		struct cur_regulatory_info *reg_info,
193 		uint16_t country_index,
194 		uint16_t regdmn_pair)
195 {
196 	uint8_t rule_size_2g, rule_size_5g;
197 	uint8_t dmn_id_5g, dmn_id_2g;
198 	uint8_t ant_gain_2g, ant_gain_5g;
199 	QDF_STATUS err;
200 
201 	dmn_id_5g = g_reg_dmn_pairs[regdmn_pair].dmn_id_5g;
202 	dmn_id_2g = g_reg_dmn_pairs[regdmn_pair].dmn_id_2g;
203 
204 	rule_size_2g = QDF_ARRAY_SIZE(regdomains_2g[dmn_id_2g].reg_rule_id);
205 	rule_size_5g = QDF_ARRAY_SIZE(regdomains_5g[dmn_id_5g].reg_rule_id);
206 
207 	if (((rule_size_2g + rule_size_5g) >=
208 				regdomains_2g[dmn_id_2g].num_reg_rules +
209 				regdomains_5g[dmn_id_5g].num_reg_rules)) {
210 
211 		qdf_mem_copy(reg_info->alpha2,
212 			g_all_countries[country_index].alpha2_11d,
213 			sizeof(g_all_countries[country_index].alpha2_11d));
214 
215 		reg_info->ctry_code =
216 			g_all_countries[country_index].country_code;
217 		reg_info->reg_dmn_pair =
218 			g_reg_dmn_pairs[regdmn_pair].reg_dmn_pair_id;
219 		reg_info->dfs_region = regdomains_5g[dmn_id_5g].dfs_region;
220 		reg_info->phybitmap =
221 			g_all_countries[country_index].phymode_bitmap;
222 
223 		reg_info->max_bw_2g = g_all_countries[country_index].max_bw_2g;
224 		reg_info->max_bw_5g = g_all_countries[country_index].max_bw_5g;
225 
226 		reg_info->min_bw_2g = regdomains_2g[dmn_id_2g].min_bw;
227 		reg_info->min_bw_5g = regdomains_5g[dmn_id_5g].min_bw;
228 
229 		ant_gain_2g = regdomains_2g[dmn_id_2g].ant_gain;
230 		ant_gain_5g = regdomains_5g[dmn_id_5g].ant_gain;
231 
232 		reg_info->num_2g_reg_rules =
233 			regdomains_2g[dmn_id_2g].num_reg_rules;
234 		reg_info->num_5g_reg_rules =
235 			regdomains_5g[dmn_id_5g].num_reg_rules;
236 
237 		reg_info->reg_rules_2g_ptr = (struct cur_reg_rule *)
238 			qdf_mem_malloc((reg_info->num_2g_reg_rules) *
239 					sizeof(struct cur_reg_rule));
240 		reg_info->reg_rules_5g_ptr = (struct cur_reg_rule *)
241 			qdf_mem_malloc((reg_info->num_5g_reg_rules) *
242 					sizeof(struct cur_reg_rule));
243 
244 		err = reg_regrules_assign(dmn_id_2g, dmn_id_5g,
245 				ant_gain_2g, ant_gain_5g, reg_info);
246 
247 		if (err == QDF_STATUS_E_FAILURE) {
248 			reg_err("%s : No rule found for country index = %d regdmn_pair = %d\n",
249 					__func__, country_index, regdmn_pair);
250 			return QDF_STATUS_E_FAILURE;
251 		}
252 
253 		return QDF_STATUS_SUCCESS;
254 	} else if (!(((rule_size_2g + rule_size_5g) >=
255 				regdomains_2g[dmn_id_2g].num_reg_rules +
256 				regdomains_5g[dmn_id_5g].num_reg_rules)))
257 	    return QDF_STATUS_E_NOMEM;
258 
259 	return QDF_STATUS_SUCCESS;
260 }
261 
262 static inline QDF_STATUS reg_get_reginfo_form_regdmn_pair(
263 		struct cur_regulatory_info *reg_info,
264 		uint16_t regdmn_pair)
265 {
266 	uint8_t rule_size_2g, rule_size_5g;
267 	uint8_t dmn_id_5g, dmn_id_2g;
268 	uint8_t ant_gain_2g, ant_gain_5g;
269 	QDF_STATUS err;
270 
271 	dmn_id_5g = g_reg_dmn_pairs[regdmn_pair].dmn_id_5g;
272 	dmn_id_2g = g_reg_dmn_pairs[regdmn_pair].dmn_id_2g;
273 
274 	rule_size_2g = QDF_ARRAY_SIZE(regdomains_2g[dmn_id_2g].reg_rule_id);
275 	rule_size_5g = QDF_ARRAY_SIZE(regdomains_5g[dmn_id_5g].reg_rule_id);
276 
277 	if (((rule_size_2g + rule_size_5g) >=
278 		    regdomains_2g[dmn_id_2g].num_reg_rules +
279 		    regdomains_5g[dmn_id_5g].num_reg_rules)) {
280 
281 		qdf_mem_zero(reg_info->alpha2, sizeof(reg_info->alpha2));
282 
283 		reg_info->reg_dmn_pair =
284 			g_reg_dmn_pairs[regdmn_pair].reg_dmn_pair_id;
285 		reg_info->ctry_code = 0;
286 		reg_info->dfs_region = regdomains_5g[dmn_id_5g].dfs_region;
287 		reg_info->phybitmap = 0;
288 
289 		reg_info->max_bw_2g = 40;
290 		reg_info->max_bw_5g = 160;
291 
292 		reg_info->min_bw_2g = regdomains_2g[dmn_id_2g].min_bw;
293 		reg_info->min_bw_5g = regdomains_5g[dmn_id_5g].min_bw;
294 
295 		ant_gain_2g = regdomains_2g[dmn_id_2g].ant_gain;
296 		ant_gain_5g = regdomains_5g[dmn_id_5g].ant_gain;
297 
298 		reg_info->num_2g_reg_rules =
299 			regdomains_2g[dmn_id_2g].num_reg_rules;
300 		reg_info->num_5g_reg_rules =
301 			regdomains_5g[dmn_id_5g].num_reg_rules;
302 
303 		reg_info->reg_rules_2g_ptr = (struct cur_reg_rule *)
304 			qdf_mem_malloc((reg_info->num_2g_reg_rules) *
305 					sizeof(struct cur_reg_rule));
306 		reg_info->reg_rules_5g_ptr = (struct cur_reg_rule *)
307 			qdf_mem_malloc((reg_info->num_5g_reg_rules) *
308 					sizeof(struct cur_reg_rule));
309 
310 		err = reg_regrules_assign(dmn_id_2g, dmn_id_5g,
311 			ant_gain_2g, ant_gain_5g, reg_info);
312 		if (err == QDF_STATUS_E_FAILURE) {
313 			reg_err("%s : No rule found for regdmn_pair = %d\n",
314 					__func__, regdmn_pair);
315 			return QDF_STATUS_E_FAILURE;
316 		}
317 
318 		return QDF_STATUS_SUCCESS;
319 	} else if (!(((rule_size_2g + rule_size_5g) >=
320 			regdomains_2g[dmn_id_2g].num_reg_rules +
321 			regdomains_5g[dmn_id_5g].num_reg_rules)))
322 		return QDF_STATUS_E_NOMEM;
323 
324 	return QDF_STATUS_SUCCESS;
325 }
326 
327 /* Given a country code the function finds current  regulatory information */
328 QDF_STATUS reg_get_cur_reginfo(struct cur_regulatory_info *reg_info,
329 		uint16_t country_index,
330 		uint16_t regdmn_pair)
331 {
332 	if ((country_index != (uint16_t)(-1)) &&
333 			(regdmn_pair != (uint16_t)(-1)))
334 		return reg_get_reginfo_form_country_code_and_regdmn_pair(
335 				reg_info,
336 				country_index,
337 				regdmn_pair);
338 	else if (regdmn_pair != (uint16_t)(-1))
339 		return reg_get_reginfo_form_regdmn_pair(
340 				reg_info,
341 				regdmn_pair);
342 	else
343 		return QDF_STATUS_E_FAILURE;
344 
345 	return QDF_STATUS_SUCCESS;
346 }
347