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