1 /* 2 * Copyright (c) 2014-2019 The Linux Foundation. All rights reserved. 3 * 4 * Permission to use, copy, modify, and/or distribute this software for 5 * any purpose with or without fee is hereby granted, provided that the 6 * above copyright notice and this permission notice appear in all 7 * copies. 8 * 9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL 10 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED 11 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE 12 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL 13 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR 14 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER 15 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 16 * PERFORMANCE OF THIS SOFTWARE. 17 */ 18 19 /** 20 * DOC: reg_opclass.c 21 * This file defines regulatory opclass functions. 22 */ 23 24 #include <qdf_types.h> 25 #include <wlan_cmn.h> 26 #include <reg_services_public_struct.h> 27 #include <wlan_objmgr_psoc_obj.h> 28 #include "reg_priv_objs.h" 29 #include "reg_getset.h" 30 #include "reg_db.h" 31 #include "reg_db_parser.h" 32 #include "reg_host_11d.h" 33 #include <scheduler_api.h> 34 #include "reg_build_chan_list.h" 35 #include "reg_opclass.h" 36 37 #ifdef HOST_OPCLASS 38 static struct reg_dmn_supp_op_classes reg_dmn_curr_supp_opp_classes = { 0 }; 39 #endif 40 41 static const struct reg_dmn_op_class_map_t global_op_class[] = { 42 {81, 25, BW20, {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13} }, 43 {82, 25, BW20, {14} }, 44 {83, 40, BW40_LOW_PRIMARY, {1, 2, 3, 4, 5, 6, 7, 8, 9} }, 45 {84, 40, BW40_HIGH_PRIMARY, {5, 6, 7, 8, 9, 10, 11, 12, 13} }, 46 {115, 20, BW20, {36, 40, 44, 48} }, 47 {116, 40, BW40_LOW_PRIMARY, {36, 44} }, 48 {117, 40, BW40_HIGH_PRIMARY, {40, 48} }, 49 {118, 20, BW20, {52, 56, 60, 64} }, 50 {119, 40, BW40_LOW_PRIMARY, {52, 60} }, 51 {120, 40, BW40_HIGH_PRIMARY, {56, 64} }, 52 {121, 20, BW20, 53 {100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140} }, 54 {122, 40, BW40_LOW_PRIMARY, {100, 108, 116, 124, 132} }, 55 {123, 40, BW40_HIGH_PRIMARY, {104, 112, 120, 128, 136} }, 56 {125, 20, BW20, {149, 153, 157, 161, 165, 169} }, 57 {126, 40, BW40_LOW_PRIMARY, {149, 157} }, 58 {127, 40, BW40_HIGH_PRIMARY, {153, 161} }, 59 {128, 80, BW80, {36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 60 112, 116, 120, 124, 128, 132, 136, 140, 144, 61 149, 153, 157, 161} }, 62 {0, 0, 0, {0} }, 63 }; 64 65 static const struct reg_dmn_op_class_map_t us_op_class[] = { 66 {1, 20, BW20, {36, 40, 44, 48} }, 67 {2, 20, BW20, {52, 56, 60, 64} }, 68 {4, 20, BW20, {100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 69 144} }, 70 {5, 20, BW20, {149, 153, 157, 161, 165} }, 71 {12, 25, BW20, {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11} }, 72 {22, 40, BW40_LOW_PRIMARY, {36, 44} }, 73 {23, 40, BW40_LOW_PRIMARY, {52, 60} }, 74 {24, 40, BW40_LOW_PRIMARY, {100, 108, 116, 124, 132} }, 75 {26, 40, BW40_LOW_PRIMARY, {149, 157} }, 76 {27, 40, BW40_HIGH_PRIMARY, {40, 48} }, 77 {28, 40, BW40_HIGH_PRIMARY, {56, 64} }, 78 {29, 40, BW40_HIGH_PRIMARY, {104, 112, 120, 128, 136} }, 79 {31, 40, BW40_HIGH_PRIMARY, {153, 161} }, 80 {32, 40, BW40_LOW_PRIMARY, {1, 2, 3, 4, 5, 6, 7} }, 81 {33, 40, BW40_HIGH_PRIMARY, {5, 6, 7, 8, 9, 10, 11} }, 82 {128, 80, BW80, {36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 83 112, 116, 120, 124, 128, 132, 136, 140, 144, 84 149, 153, 157, 161} }, 85 {0, 0, 0, {0} }, 86 }; 87 88 static const struct reg_dmn_op_class_map_t euro_op_class[] = { 89 {1, 20, BW20, {36, 40, 44, 48} }, 90 {2, 20, BW20, {52, 56, 60, 64} }, 91 {3, 20, BW20, {100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140} }, 92 {4, 25, BW20, {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13} }, 93 {5, 40, BW40_LOW_PRIMARY, {36, 44} }, 94 {6, 40, BW40_LOW_PRIMARY, {52, 60} }, 95 {7, 40, BW40_LOW_PRIMARY, {100, 108, 116, 124, 132} }, 96 {8, 40, BW40_HIGH_PRIMARY, {40, 48} }, 97 {9, 40, BW40_HIGH_PRIMARY, {56, 64} }, 98 {10, 40, BW40_HIGH_PRIMARY, {104, 112, 120, 128, 136} }, 99 {11, 40, BW40_LOW_PRIMARY, {1, 2, 3, 4, 5, 6, 7, 8, 9} }, 100 {12, 40, BW40_HIGH_PRIMARY, {5, 6, 7, 8, 9, 10, 11, 12, 13} }, 101 {17, 20, BW20, {149, 153, 157, 161, 165, 169} }, 102 {128, 80, BW80, {36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 103 116, 120, 124, 128} }, 104 {0, 0, 0, {0} }, 105 }; 106 107 static const struct reg_dmn_op_class_map_t japan_op_class[] = { 108 {1, 20, BW20, {36, 40, 44, 48} }, 109 {30, 25, BW20, {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13} }, 110 {31, 25, BW20, {14} }, 111 {32, 20, BW20, {52, 56, 60, 64} }, 112 {34, 20, BW20, 113 {100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140} }, 114 {36, 40, BW40_LOW_PRIMARY, {36, 44} }, 115 {37, 40, BW40_LOW_PRIMARY, {52, 60} }, 116 {39, 40, BW40_LOW_PRIMARY, {100, 108, 116, 124, 132} }, 117 {41, 40, BW40_HIGH_PRIMARY, {40, 48} }, 118 {42, 40, BW40_HIGH_PRIMARY, {56, 64} }, 119 {44, 40, BW40_HIGH_PRIMARY, {104, 112, 120, 128, 136} }, 120 {128, 80, BW80, {36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 121 116, 120, 124, 128} }, 122 {0, 0, 0, {0} }, 123 }; 124 125 #ifdef HOST_OPCLASS 126 uint16_t reg_dmn_get_chanwidth_from_opclass(uint8_t *country, uint8_t channel, 127 uint8_t opclass) 128 { 129 const struct reg_dmn_op_class_map_t *class; 130 uint16_t i; 131 132 if (!qdf_mem_cmp(country, "US", 2)) 133 class = us_op_class; 134 else if (!qdf_mem_cmp(country, "EU", 2)) 135 class = euro_op_class; 136 else if (!qdf_mem_cmp(country, "JP", 2)) 137 class = japan_op_class; 138 else 139 class = global_op_class; 140 141 while (class->op_class) { 142 if (opclass == class->op_class) { 143 for (i = 0; (i < REG_MAX_CHANNELS_PER_OPERATING_CLASS && 144 class->channels[i]); i++) { 145 if (channel == class->channels[i]) 146 return class->ch_spacing; 147 } 148 } 149 class++; 150 } 151 152 return 0; 153 } 154 155 uint16_t reg_dmn_get_opclass_from_channel(uint8_t *country, uint8_t channel, 156 uint8_t offset) 157 { 158 const struct reg_dmn_op_class_map_t *class = NULL; 159 uint16_t i = 0; 160 161 if (!qdf_mem_cmp(country, "US", 2)) 162 class = us_op_class; 163 else if (!qdf_mem_cmp(country, "EU", 2)) 164 class = euro_op_class; 165 else if (!qdf_mem_cmp(country, "JP", 2)) 166 class = japan_op_class; 167 else 168 class = global_op_class; 169 170 while (class->op_class) { 171 if ((offset == class->offset) || (offset == BWALL)) { 172 for (i = 0; (i < REG_MAX_CHANNELS_PER_OPERATING_CLASS && 173 class->channels[i]); i++) { 174 if (channel == class->channels[i]) 175 return class->op_class; 176 } 177 } 178 class++; 179 } 180 181 return 0; 182 } 183 184 uint16_t reg_dmn_set_curr_opclasses(uint8_t num_classes, uint8_t *class) 185 { 186 uint8_t i; 187 188 if (num_classes > REG_MAX_SUPP_OPER_CLASSES) { 189 reg_err("invalid num classes %d", num_classes); 190 return 0; 191 } 192 193 for (i = 0; i < num_classes; i++) 194 reg_dmn_curr_supp_opp_classes.classes[i] = class[i]; 195 196 reg_dmn_curr_supp_opp_classes.num_classes = num_classes; 197 198 return 0; 199 } 200 201 uint16_t reg_dmn_get_curr_opclasses(uint8_t *num_classes, uint8_t *class) 202 { 203 uint8_t i; 204 205 if (!num_classes || !class) { 206 reg_err("either num_classes or class is null"); 207 return 0; 208 } 209 210 for (i = 0; i < reg_dmn_curr_supp_opp_classes.num_classes; i++) 211 class[i] = reg_dmn_curr_supp_opp_classes.classes[i]; 212 213 *num_classes = reg_dmn_curr_supp_opp_classes.num_classes; 214 215 return 0; 216 } 217 #endif 218