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