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