xref: /wlan-dirver/qca-wifi-host-cmn/umac/regulatory/core/src/reg_db_parser.c (revision 6ecd284e5a94a1c96e26d571dd47419ac305990d)
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 *alpha2)
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] == alpha2[0]) &&
40 				(g_all_countries[i].alpha2[1] == alpha2[1]))
41 			return QDF_STATUS_SUCCESS;
42 		else
43 			continue;
44 	}
45 
46 	return QDF_STATUS_E_FAILURE;
47 }
48 
49 QDF_STATUS reg_regrules_assign(uint8_t dmn_id_2g,
50 	uint8_t dmn_id_5g,
51 	uint8_t ant_gain_2g,
52 	uint8_t ant_gain_5g,
53 	struct cur_regulatory_info *reg_info)
54 
55 {
56 	uint8_t k;
57 	uint8_t rule_index;
58 	struct cur_reg_rule *r_r_2g = reg_info->reg_rules_2g_ptr;
59 	struct cur_reg_rule *r_r_5g = reg_info->reg_rules_5g_ptr;
60 
61 	for (k = 0; k < reg_info->num_2g_reg_rules; k++) {
62 		rule_index = regdomains_2g[dmn_id_2g].reg_rule_id[k];
63 		r_r_2g->start_freq = reg_rules_2g[rule_index].start_freq;
64 		r_r_2g->end_freq = reg_rules_2g[rule_index].end_freq;
65 		r_r_2g->max_bw = reg_rules_2g[rule_index].max_bw;
66 		r_r_2g->reg_power = reg_rules_2g[rule_index].reg_power;
67 		r_r_2g->flags = reg_rules_2g[rule_index].flags;
68 		r_r_2g->ant_gain = ant_gain_2g;
69 		r_r_2g++;
70 	}
71 
72 	for (k = 0; k < reg_info->num_5g_reg_rules; k++) {
73 		rule_index = regdomains_5g[dmn_id_5g].reg_rule_id[k];
74 		r_r_5g->start_freq = reg_rules_5g[rule_index].start_freq;
75 		r_r_5g->end_freq = reg_rules_5g[rule_index].end_freq;
76 		r_r_5g->max_bw = reg_rules_5g[rule_index].max_bw;
77 		r_r_5g->reg_power = reg_rules_5g[rule_index].reg_power;
78 		r_r_5g->flags = reg_rules_5g[rule_index].flags;
79 		r_r_5g->ant_gain = ant_gain_5g;
80 		r_r_5g++;
81 	}
82 
83 	if ((r_r_2g == reg_info->reg_rules_2g_ptr) &&
84 			(r_r_5g == reg_info->reg_rules_5g_ptr))
85 		return QDF_STATUS_E_FAILURE;
86 
87 	return QDF_STATUS_SUCCESS;
88 }
89 
90 QDF_STATUS reg_get_rdpair_from_country_iso(uint8_t *alpha2,
91 	uint16_t *country_index,
92 	uint16_t *regdmn_pair)
93 {
94 	uint16_t i, j;
95 	int num_countries;
96 	int num_reg_dmn;
97 
98 	reg_get_num_countries(&num_countries);
99 	reg_get_num_reg_dmn_pairs(&num_reg_dmn);
100 
101 	for (i = 0; i < num_countries; i++) {
102 		if ((g_all_countries[i].alpha2[0] == alpha2[0]) &&
103 			(g_all_countries[i].alpha2[1] == alpha2[1]))
104 			break;
105 	}
106 
107 	if (i == num_countries) {
108 		*country_index = -1;
109 		return QDF_STATUS_E_FAILURE;
110 	}
111 
112 	for (j = 0; j < num_reg_dmn; j++) {
113 		if (g_reg_dmn_pairs[j].reg_dmn_pair_id ==
114 				g_all_countries[i].reg_dmn_pair_id)
115 			break;
116 	}
117 
118 	if (j == num_reg_dmn) {
119 		*regdmn_pair = -1;
120 		return QDF_STATUS_E_FAILURE;
121 	}
122 
123 	*country_index = i;
124 	*regdmn_pair = j;
125 
126 	return QDF_STATUS_SUCCESS;
127 }
128 
129 QDF_STATUS reg_get_rdpair_from_regdmn_id(uint16_t regdmn_id,
130 		uint16_t *regdmn_pair)
131 {
132 	uint16_t j;
133 	int num_reg_dmn;
134 
135 	reg_get_num_reg_dmn_pairs(&num_reg_dmn);
136 
137 	for (j = 0; j < num_reg_dmn; j++) {
138 		if (g_reg_dmn_pairs[j].reg_dmn_pair_id == regdmn_id)
139 			break;
140 	}
141 
142 	if (j == num_reg_dmn) {
143 		*regdmn_pair = -1;
144 		return QDF_STATUS_E_FAILURE;
145 	}
146 
147 	*regdmn_pair = j;
148 
149 	return QDF_STATUS_SUCCESS;
150 }
151 
152 QDF_STATUS reg_get_rdpair_from_country_code(uint16_t cc,
153 		uint16_t *country_index,
154 		uint16_t *regdmn_pair)
155 {
156 	uint16_t i, j;
157 	int num_countries;
158 	int num_reg_dmn;
159 
160 	reg_get_num_countries(&num_countries);
161 	reg_get_num_reg_dmn_pairs(&num_reg_dmn);
162 
163 	for (i = 0; i < num_countries; i++) {
164 		if (g_all_countries[i].country_code == cc)
165 			break;
166 	}
167 
168 	if (i == num_countries) {
169 		*country_index = -1;
170 		return QDF_STATUS_E_FAILURE;
171 	}
172 
173 	for (j = 0; j < num_reg_dmn; j++) {
174 		if (g_reg_dmn_pairs[j].reg_dmn_pair_id ==
175 				g_all_countries[i].reg_dmn_pair_id)
176 			break;
177 	}
178 
179 	if (j == num_reg_dmn) {
180 		*regdmn_pair = -1;
181 		return QDF_STATUS_E_FAILURE;
182 	}
183 
184 	*country_index = i;
185 	*regdmn_pair = j;
186 
187 	return QDF_STATUS_SUCCESS;
188 }
189 
190 static inline QDF_STATUS reg_get_reginfo_form_country_code_and_regdmn_pair(
191 		struct cur_regulatory_info *reg_info,
192 		uint16_t country_index,
193 		uint16_t regdmn_pair)
194 {
195 	uint8_t rule_size_2g, rule_size_5g;
196 	uint8_t dmn_id_5g, dmn_id_2g;
197 	uint8_t ant_gain_2g, ant_gain_5g;
198 	QDF_STATUS err;
199 
200 	dmn_id_5g = g_reg_dmn_pairs[regdmn_pair].dmn_id_5g;
201 	dmn_id_2g = g_reg_dmn_pairs[regdmn_pair].dmn_id_2g;
202 
203 	rule_size_2g = QDF_ARRAY_SIZE(regdomains_2g[dmn_id_2g].reg_rule_id);
204 	rule_size_5g = QDF_ARRAY_SIZE(regdomains_5g[dmn_id_5g].reg_rule_id);
205 
206 	if (((rule_size_2g + rule_size_5g) >=
207 				regdomains_2g[dmn_id_2g].num_reg_rules +
208 				regdomains_5g[dmn_id_5g].num_reg_rules)) {
209 
210 		qdf_mem_copy(reg_info->alpha2,
211 			g_all_countries[country_index].alpha2,
212 			sizeof(g_all_countries[country_index].alpha2));
213 
214 		reg_info->ctry_code =
215 			g_all_countries[country_index].country_code;
216 		reg_info->reg_dmn_pair =
217 			g_reg_dmn_pairs[regdmn_pair].reg_dmn_pair_id;
218 		reg_info->dfs_region = regdomains_5g[dmn_id_5g].dfs_region;
219 		reg_info->phybitmap =
220 			g_all_countries[country_index].phymode_bitmap;
221 
222 		reg_info->max_bw_2g = g_all_countries[country_index].max_bw_2g;
223 		reg_info->max_bw_5g = g_all_countries[country_index].max_bw_5g;
224 
225 		reg_info->min_bw_2g = regdomains_2g[dmn_id_2g].min_bw;
226 		reg_info->min_bw_5g = regdomains_5g[dmn_id_5g].min_bw;
227 
228 		ant_gain_2g = regdomains_2g[dmn_id_2g].ant_gain;
229 		ant_gain_5g = regdomains_5g[dmn_id_5g].ant_gain;
230 
231 		reg_info->num_2g_reg_rules =
232 			regdomains_2g[dmn_id_2g].num_reg_rules;
233 		reg_info->num_5g_reg_rules =
234 			regdomains_5g[dmn_id_5g].num_reg_rules;
235 
236 		reg_info->reg_rules_2g_ptr = (struct cur_reg_rule *)
237 			qdf_mem_malloc((reg_info->num_2g_reg_rules) *
238 					sizeof(struct cur_reg_rule));
239 		reg_info->reg_rules_5g_ptr = (struct cur_reg_rule *)
240 			qdf_mem_malloc((reg_info->num_5g_reg_rules) *
241 					sizeof(struct cur_reg_rule));
242 
243 		err = reg_regrules_assign(dmn_id_2g, dmn_id_5g,
244 				ant_gain_2g, ant_gain_5g, reg_info);
245 
246 		if (err == QDF_STATUS_E_FAILURE) {
247 			reg_err("%s : No rule found for country index = %d regdmn_pair = %d\n",
248 					__func__, country_index, regdmn_pair);
249 			return QDF_STATUS_E_FAILURE;
250 		}
251 
252 		return QDF_STATUS_SUCCESS;
253 	} else if (!(((rule_size_2g + rule_size_5g) >=
254 				regdomains_2g[dmn_id_2g].num_reg_rules +
255 				regdomains_5g[dmn_id_5g].num_reg_rules)))
256 	    return QDF_STATUS_E_NOMEM;
257 
258 	return QDF_STATUS_SUCCESS;
259 }
260 
261 static inline QDF_STATUS reg_get_reginfo_form_regdmn_pair(
262 		struct cur_regulatory_info *reg_info,
263 		uint16_t regdmn_pair)
264 {
265 	uint8_t rule_size_2g, rule_size_5g;
266 	uint8_t dmn_id_5g, dmn_id_2g;
267 	uint8_t ant_gain_2g, ant_gain_5g;
268 	QDF_STATUS err;
269 
270 	dmn_id_5g = g_reg_dmn_pairs[regdmn_pair].dmn_id_5g;
271 	dmn_id_2g = g_reg_dmn_pairs[regdmn_pair].dmn_id_2g;
272 
273 	rule_size_2g = QDF_ARRAY_SIZE(regdomains_2g[dmn_id_2g].reg_rule_id);
274 	rule_size_5g = QDF_ARRAY_SIZE(regdomains_5g[dmn_id_5g].reg_rule_id);
275 
276 	if (((rule_size_2g + rule_size_5g) >=
277 		    regdomains_2g[dmn_id_2g].num_reg_rules +
278 		    regdomains_5g[dmn_id_5g].num_reg_rules)) {
279 
280 		qdf_mem_zero(reg_info->alpha2, sizeof(reg_info->alpha2));
281 
282 		reg_info->reg_dmn_pair =
283 			g_reg_dmn_pairs[regdmn_pair].reg_dmn_pair_id;
284 		reg_info->ctry_code = 0;
285 		reg_info->dfs_region = regdomains_5g[dmn_id_5g].dfs_region;
286 		reg_info->phybitmap = 0;
287 
288 		reg_info->max_bw_2g = 40;
289 		reg_info->max_bw_5g = 160;
290 
291 		reg_info->min_bw_2g = regdomains_2g[dmn_id_2g].min_bw;
292 		reg_info->min_bw_5g = regdomains_5g[dmn_id_5g].min_bw;
293 
294 		ant_gain_2g = regdomains_2g[dmn_id_2g].ant_gain;
295 		ant_gain_5g = regdomains_5g[dmn_id_5g].ant_gain;
296 
297 		reg_info->num_2g_reg_rules =
298 			regdomains_2g[dmn_id_2g].num_reg_rules;
299 		reg_info->num_5g_reg_rules =
300 			regdomains_5g[dmn_id_5g].num_reg_rules;
301 
302 		reg_info->reg_rules_2g_ptr = (struct cur_reg_rule *)
303 			qdf_mem_malloc((reg_info->num_2g_reg_rules) *
304 					sizeof(struct cur_reg_rule));
305 		reg_info->reg_rules_5g_ptr = (struct cur_reg_rule *)
306 			qdf_mem_malloc((reg_info->num_5g_reg_rules) *
307 					sizeof(struct cur_reg_rule));
308 
309 		err = reg_regrules_assign(dmn_id_2g, dmn_id_5g,
310 			ant_gain_2g, ant_gain_5g, reg_info);
311 		if (err == QDF_STATUS_E_FAILURE) {
312 			reg_err("%s : No rule found for regdmn_pair = %d\n",
313 					__func__, regdmn_pair);
314 			return QDF_STATUS_E_FAILURE;
315 		}
316 
317 		return QDF_STATUS_SUCCESS;
318 	} else if (!(((rule_size_2g + rule_size_5g) >=
319 			regdomains_2g[dmn_id_2g].num_reg_rules +
320 			regdomains_5g[dmn_id_5g].num_reg_rules)))
321 		return QDF_STATUS_E_NOMEM;
322 
323 	return QDF_STATUS_SUCCESS;
324 }
325 
326 /* Given a country code the function finds current  regulatory information */
327 QDF_STATUS reg_get_cur_reginfo(struct cur_regulatory_info *reg_info,
328 		uint16_t country_index,
329 		uint16_t regdmn_pair)
330 {
331 	if ((country_index != (uint16_t)(-1)) &&
332 			(regdmn_pair != (uint16_t)(-1)))
333 		return reg_get_reginfo_form_country_code_and_regdmn_pair(
334 				reg_info,
335 				country_index,
336 				regdmn_pair);
337 	else if (regdmn_pair != (uint16_t)(-1))
338 		return reg_get_reginfo_form_regdmn_pair(
339 				reg_info,
340 				regdmn_pair);
341 	else
342 		return QDF_STATUS_E_FAILURE;
343 
344 	return QDF_STATUS_SUCCESS;
345 }
346