blob: 6836d712c922c651370949de9733d898c64cbf0b [file] [log] [blame]
Jeff Johnson295189b2012-06-20 16:38:30 -07001/*
Gopichand Nakkala9c070ad2013-01-08 21:16:34 -08002 * Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
3 *
4 * Previously licensed under the ISC license by Qualcomm Atheros, Inc.
5 *
6 *
7 * Permission to use, copy, modify, and/or distribute this software for
8 * any purpose with or without fee is hereby granted, provided that the
9 * above copyright notice and this permission notice appear in all
10 * copies.
11 *
12 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
13 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
14 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
15 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
16 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
17 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
18 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
19 * PERFORMANCE OF THIS SOFTWARE.
20 */
21/*
Jeff Johnson32d95a32012-09-10 13:15:23 -070022 * Copyright (c) 2012, The Linux Foundation. All rights reserved.
Jeff Johnson295189b2012-06-20 16:38:30 -070023 *
24 * Previously licensed under the ISC license by Qualcomm Atheros, Inc.
25 *
26 *
27 * Permission to use, copy, modify, and/or distribute this software for
28 * any purpose with or without fee is hereby granted, provided that the
29 * above copyright notice and this permission notice appear in all
30 * copies.
31 *
32 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
33 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
34 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
35 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
36 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
37 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
38 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
39 * PERFORMANCE OF THIS SOFTWARE.
40 */
41
42/*============================================================================
43 FILE: vos_nvitem.c
44 OVERVIEW: This source file contains definitions for vOS NV Item APIs
45 DEPENDENCIES: NV, remote API client, WinCE REX
46 Copyright (c) 2008 QUALCOMM Incorporated.
47 All Rights Reserved.
48 Qualcomm Confidential and Proprietary
49============================================================================*/
50/*============================================================================
51 EDIT HISTORY FOR MODULE
52============================================================================*/
53// the following is used to disable warning for having too many labels in
54// the 'nv_items_enum_type'
55
56/*----------------------------------------------------------------------------
57 * Include Files
58 * -------------------------------------------------------------------------*/
59#include "vos_types.h"
60#include "aniGlobal.h"
61#include "vos_nvitem.h"
62#include "vos_trace.h"
63#include "vos_api.h"
64#include "wlan_hdd_misc.h"
65#include "vos_sched.h"
Kiet Lam5e565ef2013-10-12 23:13:13 -070066#include "sme_Api.h"
Prasanna Kumar0833aa82013-04-11 20:05:21 -070067#include "wlan_nv_parser.h"
Madan Mohan Koyyalamudic3a240c2012-09-28 15:34:08 -070068#include "wlan_hdd_main.h"
69#include <net/cfg80211.h>
Amar Singhal61cbd962013-09-05 13:03:40 -070070
Tushnim Bhattacharyyab676a2e2013-10-29 17:27:43 -070071#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,9,0))
72#define IEEE80211_CHAN_NO_80MHZ 1<<7
73#endif
Amar Singhal9a65a6a2013-10-08 18:37:44 -070074
Amar Singhal61cbd962013-09-05 13:03:40 -070075#ifdef CONFIG_ENABLE_LINUX_REG
Amar Singhal9a65a6a2013-10-08 18:37:44 -070076
77static v_REGDOMAIN_t cur_reg_domain = REGDOMAIN_COUNT;
Amar Singhal61cbd962013-09-05 13:03:40 -070078static char linux_reg_cc[2] = {0, 0};
Amar Singhal61cbd962013-09-05 13:03:40 -070079static v_REGDOMAIN_t temp_reg_domain = REGDOMAIN_COUNT;
Amar Singhal9a65a6a2013-10-08 18:37:44 -070080
Amar Singhal61cbd962013-09-05 13:03:40 -070081#endif
82
Amar Singhal9a65a6a2013-10-08 18:37:44 -070083static char crda_alpha2[2] = {0, 0}; /* country code from initial crda req */
84static char run_time_alpha2[2] = {0, 0}; /* country code from none-default country req */
85static v_BOOL_t crda_regulatory_entry_valid = VOS_FALSE;
86static v_BOOL_t crda_regulatory_run_time_entry_valid = VOS_FALSE;
87
88
Madan Mohan Koyyalamudic3a240c2012-09-28 15:34:08 -070089
Jeff Johnson295189b2012-06-20 16:38:30 -070090/*----------------------------------------------------------------------------
91 * Preprocessor Definitions and Constants
92 * -------------------------------------------------------------------------*/
93#define VALIDITY_BITMAP_NV_ID NV_WLAN_VALIDITY_BITMAP_I
94#define VALIDITY_BITMAP_SIZE 32
95#define MAX_COUNTRY_COUNT 300
96//To be removed when NV support is fully functional
97#define VOS_HARD_CODED_MAC {0, 0x0a, 0xf5, 4, 5, 6}
Madan Mohan Koyyalamudi1dd5c882012-09-24 13:31:39 -070098
99#define DEFAULT_NV_VALIDITY_BITMAP 0xFFFFFFFF
Prasanna Kumar0833aa82013-04-11 20:05:21 -0700100#define MAGIC_NUMBER 0xCAFEBABE
Madan Mohan Koyyalamudi1dd5c882012-09-24 13:31:39 -0700101
Jeff Johnson295189b2012-06-20 16:38:30 -0700102/*----------------------------------------------------------------------------
103 * Type Declarations
104 * -------------------------------------------------------------------------*/
105// this wrapper structure is identical to nv_cmd_type except the
106// data_ptr type is changed void* to avoid exceeding the debug information
107// module size as there are too many elements within nv_items_type union
108
109// structure for code and regulatory domain of a single country
110typedef struct
111{
112 v_U8_t regDomain;
113 v_COUNTRYCODE_t countryCode;
114} CountryInfo_t;
115// structure of table to map country code and regulatory domain
116typedef struct
117{
118 v_U16_t countryCount;
119 CountryInfo_t countryInfo[MAX_COUNTRY_COUNT];
120} CountryInfoTable_t;
121/*----------------------------------------------------------------------------
122 * Global Data Definitions
123 * -------------------------------------------------------------------------*/
124/*----------------------------------------------------------------------------
125 * Static Variable Definitions
126 * -------------------------------------------------------------------------*/
Amar Singhal9a65a6a2013-10-08 18:37:44 -0700127// cache of country info table;
128// this is re-initialized from data on binary file
129// loaded on driver initialization if available
Amar Singhal61cbd962013-09-05 13:03:40 -0700130
131#ifdef CONFIG_ENABLE_LINUX_REG
132
133static CountryInfoTable_t countryInfoTable =
134{
135 /* the first entry in the table is always the world domain */
136 138,
137 {
138 {REGDOMAIN_WORLD, {'0', '0'}}, // WORLD DOMAIN
139 {REGDOMAIN_FCC, {'A', 'D'}}, // ANDORRA
140 {REGDOMAIN_ETSI, {'A', 'E'}}, //UAE
141 {REGDOMAIN_ETSI, {'A', 'L'}}, //ALBANIA
142 {REGDOMAIN_ETSI, {'A', 'M'}}, //ARMENIA
143 {REGDOMAIN_ETSI, {'A', 'N'}}, //NETHERLANDS ANTILLES
144 {REGDOMAIN_FCC, {'A', 'R'}}, //ARGENTINA
145 {REGDOMAIN_FCC, {'A', 'S'}}, //AMERICAN SOMOA
146 {REGDOMAIN_ETSI, {'A', 'T'}}, //AUSTRIA
147 {REGDOMAIN_FCC, {'A', 'U'}}, //AUSTRALIA
148 {REGDOMAIN_ETSI , {'A', 'W'}}, //ARUBA
149 {REGDOMAIN_ETSI, {'A', 'Z'}}, //AZERBAIJAN
150 {REGDOMAIN_ETSI, {'B', 'A'}}, //BOSNIA AND HERZEGOVINA
151 {REGDOMAIN_FCC, {'B', 'B'}}, //BARBADOS
152 {REGDOMAIN_ETSI, {'B', 'D'}}, //BANGLADESH
153 {REGDOMAIN_ETSI, { 'B', 'E'}}, //BELGIUM
154 {REGDOMAIN_ETSI, {'B', 'G'}}, //BULGARIA
155 {REGDOMAIN_ETSI, {'B', 'H'}}, //BAHRAIN
156 {REGDOMAIN_ETSI, {'B', 'L'}}, //
157 {REGDOMAIN_FCC, {'B', 'M'}}, //BERMUDA
158 {REGDOMAIN_ETSI, {'B', 'N'}}, //BRUNEI DARUSSALAM
159 {REGDOMAIN_ETSI, {'B', 'O'}}, //BOLIVIA
160 {REGDOMAIN_ETSI, {'B', 'R'}}, //BRAZIL
161 {REGDOMAIN_FCC, {'B', 'S'}}, //BAHAMAS
162 {REGDOMAIN_ETSI, {'B', 'Y'}}, //BELARUS
163 {REGDOMAIN_ETSI, {'B', 'Z'}}, //BELIZE
164 {REGDOMAIN_FCC, {'C', 'A'}}, //CANADA
165 {REGDOMAIN_ETSI, {'C', 'H'}}, //SWITZERLAND
166 {REGDOMAIN_ETSI, {'C', 'L'}}, //CHILE
167 {REGDOMAIN_FCC, {'C', 'N'}}, //CHINA
168 {REGDOMAIN_FCC, {'C', 'O'}}, //COLOMBIA
169 {REGDOMAIN_ETSI, {'C', 'R'}}, //COSTA RICA
170 {REGDOMAIN_ETSI, {'C', 'S'}},
171 {REGDOMAIN_ETSI, {'C', 'Y'}}, //CYPRUS
172 {REGDOMAIN_ETSI, {'C', 'Z'}}, //CZECH REPUBLIC
173 {REGDOMAIN_ETSI, {'D', 'E'}}, //GERMANY
174 {REGDOMAIN_ETSI, {'D', 'K'}}, //DENMARK
175 {REGDOMAIN_FCC, {'D', 'O'}}, //DOMINICAN REPUBLIC
176 {REGDOMAIN_ETSI, {'D', 'Z'}}, //ALGERIA
177 {REGDOMAIN_ETSI, {'E', 'C'}}, //ECUADOR
178 {REGDOMAIN_ETSI, {'E', 'E'}}, //ESTONIA
179 {REGDOMAIN_ETSI, {'E', 'G'}}, //EGYPT
180 {REGDOMAIN_ETSI, {'E', 'S'}}, //SPAIN
181 {REGDOMAIN_ETSI, {'F', 'I'}}, //FINLAND
182 {REGDOMAIN_ETSI, {'F', 'R'}}, //FRANCE
183 {REGDOMAIN_ETSI, {'G', 'B'}}, //UNITED KINGDOM
184 {REGDOMAIN_FCC, {'G', 'D'}}, //GRENADA
185 {REGDOMAIN_ETSI, {'G', 'E'}}, //GEORGIA
186 {REGDOMAIN_ETSI, {'G', 'F'}}, //FRENCH GUIANA
187 {REGDOMAIN_ETSI, {'G', 'L'}}, //GREENLAND
188 {REGDOMAIN_ETSI, {'G', 'P'}}, //GUADELOUPE
189 {REGDOMAIN_ETSI, {'G', 'R'}}, //GREECE
190 {REGDOMAIN_FCC, {'G', 'T'}}, //GUATEMALA
191 {REGDOMAIN_FCC, {'G', 'U'}}, //GUAM
192 {REGDOMAIN_ETSI, {'H', 'U'}}, //HUNGARY
193 {REGDOMAIN_FCC, {'I', 'D'}}, //INDONESIA
194 {REGDOMAIN_ETSI, {'I', 'E'}}, //IRELAND
195 {REGDOMAIN_ETSI, {'I', 'L'}}, //ISRAEL
196 {REGDOMAIN_ETSI, {'I', 'N'}}, //INDIA
197 {REGDOMAIN_ETSI, {'I', 'R'}}, //IRAN, ISLAMIC REPUBLIC OF
198 {REGDOMAIN_ETSI, {'I', 'S'}}, //ICELNAD
199 {REGDOMAIN_ETSI, {'I', 'T'}}, //ITALY
200 {REGDOMAIN_FCC, {'J', 'M'}}, //JAMAICA
201 {REGDOMAIN_JAPAN, {'J', 'P'}}, //JAPAN
202 {REGDOMAIN_ETSI, {'J', 'O'}}, //JORDAN
203 {REGDOMAIN_ETSI, {'K', 'E'}}, //KENYA
204 {REGDOMAIN_ETSI, {'K', 'H'}}, //CAMBODIA
205 {REGDOMAIN_ETSI, {'K', 'P'}}, //KOREA, DEMOCRATIC PEOPLE's REPUBLIC OF
206 {REGDOMAIN_ETSI, {'K', 'R'}}, //KOREA, REPUBLIC OF
207 {REGDOMAIN_ETSI, {'K', 'W'}}, //KUWAIT
208 {REGDOMAIN_ETSI, {'K', 'Z'}}, //KAZAKHSTAN
209 {REGDOMAIN_ETSI, {'L', 'B'}}, //LEBANON
210 {REGDOMAIN_ETSI, {'L', 'I'}}, //LIECHTENSTEIN
211 {REGDOMAIN_ETSI, {'L', 'K'}}, //SRI-LANKA
212 {REGDOMAIN_ETSI, {'L', 'T'}}, //LITHUANIA
213 {REGDOMAIN_ETSI, {'L', 'U'}}, //LUXEMBOURG
214 {REGDOMAIN_ETSI, {'L','V'}}, //LATVIA
215 {REGDOMAIN_ETSI, {'M', 'A'}}, //MOROCCO
216 {REGDOMAIN_ETSI, {'M', 'C'}}, //MONACO
217 {REGDOMAIN_ETSI, {'M', 'K'}}, //MACEDONIA, THE FORMER YUGOSLAV REPUBLIC OF
218 {REGDOMAIN_FCC, {'M','N'}}, //MONGOLIA
219 {REGDOMAIN_FCC, {'M', 'O'}}, //MACAO
220 {REGDOMAIN_FCC, {'M', 'P'}}, //NORTHERN MARIANA ISLANDS
221 {REGDOMAIN_ETSI, {'M', 'Q'}}, //MARTINIQUE
222 {REGDOMAIN_FCC, {'M', 'T'}}, //MALTA
223 {REGDOMAIN_ETSI, {'M', 'U'}}, //MAURITIUS
224 {REGDOMAIN_ETSI, {'M', 'W'}}, //MALAWI
225 {REGDOMAIN_FCC, {'M', 'X'}}, //MEXICO
226 {REGDOMAIN_ETSI, {'M', 'Y'}}, //MALAYSIA
227 {REGDOMAIN_ETSI, {'N', 'G'}}, //NIGERIA
228 {REGDOMAIN_FCC, {'N', 'I'}}, //NICARAGUA
229 {REGDOMAIN_ETSI, {'N', 'L'}}, //NETHERLANDS
230 {REGDOMAIN_ETSI, {'N', 'O'}}, //NORWAY
231 {REGDOMAIN_ETSI, {'N', 'P'}}, //NEPAL
232 {REGDOMAIN_FCC, {'N', 'Z'}}, //NEW-ZEALAND
233 {REGDOMAIN_FCC, {'O', 'M'}}, //OMAN
234 {REGDOMAIN_FCC, {'P', 'A'}}, //PANAMA
235 {REGDOMAIN_ETSI, {'P', 'E'}}, //PERU
236 {REGDOMAIN_ETSI, {'P', 'F'}}, //FRENCH POLYNESIA
237 {REGDOMAIN_ETSI, {'P', 'G'}}, //PAPUA NEW GUINEA
238 {REGDOMAIN_FCC, {'P', 'H'}}, //PHILIPPINES
239 {REGDOMAIN_ETSI, {'P', 'K'}}, //PAKISTAN
240 {REGDOMAIN_ETSI, {'P', 'L'}}, //POLAND
241 {REGDOMAIN_FCC, {'P', 'R'}}, //PUERTO RICO
242 {REGDOMAIN_FCC, {'P', 'S'}}, //PALESTINIAN TERRITORY, OCCUPIED
243 {REGDOMAIN_ETSI, {'P', 'T'}}, //PORTUGAL
244 {REGDOMAIN_FCC, {'P', 'Y'}}, //PARAGUAY
245 {REGDOMAIN_ETSI, {'Q', 'A'}}, //QATAR
246 {REGDOMAIN_ETSI, {'R', 'E'}}, //REUNION
247 {REGDOMAIN_ETSI, {'R', 'O'}}, //ROMAINIA
248 {REGDOMAIN_ETSI, {'R', 'S'}}, //SERBIA
249 {REGDOMAIN_ETSI, {'R', 'U'}}, //RUSSIA
250 {REGDOMAIN_FCC, {'R', 'W'}}, //RWANDA
251 {REGDOMAIN_ETSI, {'S', 'A'}}, //SAUDI ARABIA
252 {REGDOMAIN_ETSI, {'S', 'E'}}, //SWEDEN
253 {REGDOMAIN_ETSI, {'S', 'G'}}, //SINGAPORE
254 {REGDOMAIN_ETSI, {'S', 'I'}}, //SLOVENNIA
255 {REGDOMAIN_ETSI, {'S', 'K'}}, //SLOVAKIA
256 {REGDOMAIN_ETSI, {'S', 'V'}}, //EL SALVADOR
257 {REGDOMAIN_ETSI, {'S', 'Y'}}, //SYRIAN ARAB REPUBLIC
258 {REGDOMAIN_ETSI, {'T', 'H'}}, //THAILAND
259 {REGDOMAIN_ETSI, {'T', 'N'}}, //TUNISIA
260 {REGDOMAIN_ETSI, {'T', 'R'}}, //TURKEY
261 {REGDOMAIN_ETSI, {'T', 'T'}}, //TRINIDAD AND TOBAGO
262 {REGDOMAIN_FCC, {'T', 'W'}}, //TAIWAN, PRIVINCE OF CHINA
263 {REGDOMAIN_FCC, {'T', 'Z'}}, //TANZANIA, UNITED REPUBLIC OF
264 {REGDOMAIN_ETSI, {'U', 'A'}}, //UKRAINE
265 {REGDOMAIN_ETSI, {'U', 'G'}}, //UGANDA
266 {REGDOMAIN_FCC, {'U', 'S'}}, //USA
267 {REGDOMAIN_ETSI, {'U', 'Y'}}, //URUGUAY
268 {REGDOMAIN_FCC, {'U', 'Z'}}, //UZBEKISTAN
269 {REGDOMAIN_ETSI, {'V', 'E'}}, //VENEZUELA
270 {REGDOMAIN_FCC, {'V', 'I'}}, //VIRGIN ISLANDS, US
271 {REGDOMAIN_ETSI, {'V', 'N'}}, //VIETNAM
272 {REGDOMAIN_ETSI, {'Y', 'E'}}, //YEMEN
273 {REGDOMAIN_ETSI, {'Y', 'T'}}, //MAYOTTE
274 {REGDOMAIN_ETSI, {'Z', 'A'}}, //SOUTH AFRICA
275 {REGDOMAIN_ETSI, {'Z', 'W'}}, //ZIMBABWE
276 }
277};
278
279#else
280
Jeff Johnson295189b2012-06-20 16:38:30 -0700281// cache of country info table;
282// this is re-initialized from data on binary file
283// loaded on driver initialization if available
284static CountryInfoTable_t countryInfoTable =
285{
286 254,
287 {
Madan Mohan Koyyalamudi00ff26d2012-11-02 13:33:26 -0700288 { REGDOMAIN_FCC, {'U', 'S'}}, //USA - must be the first country code
289 { REGDOMAIN_ETSI, {'A', 'D'}}, //ANDORRA
290 { REGDOMAIN_ETSI, {'A', 'E'}}, //UAE
291 { REGDOMAIN_N_AMER_EXC_FCC, {'A', 'F'}}, //AFGHANISTAN
292 { REGDOMAIN_WORLD, {'A', 'G'}}, //ANTIGUA AND BARBUDA
293 { REGDOMAIN_FCC, {'A', 'I'}}, //ANGUILLA
Yue Ma9e047ce2013-06-10 10:52:22 -0700294 { REGDOMAIN_ETSI, {'A', 'L'}}, //ALBANIA
Madan Mohan Koyyalamudi00ff26d2012-11-02 13:33:26 -0700295 { REGDOMAIN_N_AMER_EXC_FCC, {'A', 'M'}}, //ARMENIA
296 { REGDOMAIN_ETSI, {'A', 'N'}}, //NETHERLANDS ANTILLES
297 { REGDOMAIN_NO_5GHZ, {'A', 'O'}}, //ANGOLA
298 { REGDOMAIN_WORLD, {'A', 'Q'}}, //ANTARCTICA
299 { REGDOMAIN_WORLD, {'A', 'R'}}, //ARGENTINA
300 { REGDOMAIN_FCC, {'A', 'S'}}, //AMERICAN SOMOA
301 { REGDOMAIN_ETSI, {'A', 'T'}}, //AUSTRIA
Madan Mohan Koyyalamudidf813dd2013-07-16 20:19:08 +0530302 { REGDOMAIN_WORLD, {'A', 'U'}}, //AUSTRALIA
Madan Mohan Koyyalamudi00ff26d2012-11-02 13:33:26 -0700303 { REGDOMAIN_ETSI, {'A', 'W'}}, //ARUBA
304 { REGDOMAIN_WORLD, {'A', 'X'}}, //ALAND ISLANDS
305 { REGDOMAIN_N_AMER_EXC_FCC, {'A', 'Z'}}, //AZERBAIJAN
306 { REGDOMAIN_ETSI, {'B', 'A'}}, //BOSNIA AND HERZEGOVINA
307 { REGDOMAIN_APAC, {'B', 'B'}}, //BARBADOS
Yue Ma2f134332013-07-10 11:18:57 -0700308 { REGDOMAIN_HI_5GHZ, {'B', 'D'}}, //BANGLADESH
Madan Mohan Koyyalamudi00ff26d2012-11-02 13:33:26 -0700309 { REGDOMAIN_ETSI, {'B', 'E'}}, //BELGIUM
310 { REGDOMAIN_HI_5GHZ, {'B', 'F'}}, //BURKINA FASO
311 { REGDOMAIN_ETSI, {'B', 'G'}}, //BULGARIA
312 { REGDOMAIN_APAC, {'B', 'H'}}, //BAHRAIN
313 { REGDOMAIN_NO_5GHZ, {'B', 'I'}}, //BURUNDI
314 { REGDOMAIN_NO_5GHZ, {'B', 'J'}}, //BENIN
315 { REGDOMAIN_FCC, {'B', 'M'}}, //BERMUDA
316 { REGDOMAIN_APAC, {'B', 'N'}}, //BRUNEI DARUSSALAM
317 { REGDOMAIN_HI_5GHZ, {'B', 'O'}}, //BOLIVIA
318 { REGDOMAIN_WORLD, {'B', 'R'}}, //BRAZIL
319 { REGDOMAIN_APAC, {'B', 'S'}}, //BAHAMAS
320 { REGDOMAIN_NO_5GHZ, {'B', 'T'}}, //BHUTAN
321 { REGDOMAIN_WORLD, {'B', 'V'}}, //BOUVET ISLAND
322 { REGDOMAIN_ETSI, {'B', 'W'}}, //BOTSWANA
323 { REGDOMAIN_ETSI, {'B', 'Y'}}, //BELARUS
324 { REGDOMAIN_HI_5GHZ, {'B', 'Z'}}, //BELIZE
325 { REGDOMAIN_FCC, {'C', 'A'}}, //CANADA
326 { REGDOMAIN_WORLD, {'C', 'C'}}, //COCOS (KEELING) ISLANDS
327 { REGDOMAIN_NO_5GHZ, {'C', 'D'}}, //CONGO, THE DEMOCRATIC REPUBLIC OF THE
328 { REGDOMAIN_NO_5GHZ, {'C', 'F'}}, //CENTRAL AFRICAN REPUBLIC
329 { REGDOMAIN_NO_5GHZ, {'C', 'G'}}, //CONGO
330 { REGDOMAIN_ETSI, {'C', 'H'}}, //SWITZERLAND
331 { REGDOMAIN_NO_5GHZ, {'C', 'I'}}, //COTE D'IVOIRE
332 { REGDOMAIN_WORLD, {'C', 'K'}}, //COOK ISLANDS
333 { REGDOMAIN_APAC, {'C', 'L'}}, //CHILE
334 { REGDOMAIN_NO_5GHZ, {'C', 'M'}}, //CAMEROON
Gopichand Nakkala718353c2013-04-23 18:36:17 +0530335 { REGDOMAIN_APAC, {'C', 'N'}}, //CHINA
Madan Mohan Koyyalamudi00ff26d2012-11-02 13:33:26 -0700336 { REGDOMAIN_APAC, {'C', 'O'}}, //COLOMBIA
337 { REGDOMAIN_APAC, {'C', 'R'}}, //COSTA RICA
338 { REGDOMAIN_NO_5GHZ, {'C', 'U'}}, //CUBA
339 { REGDOMAIN_ETSI, {'C', 'V'}}, //CAPE VERDE
340 { REGDOMAIN_WORLD, {'C', 'X'}}, //CHRISTMAS ISLAND
341 { REGDOMAIN_ETSI, {'C', 'Y'}}, //CYPRUS
342 { REGDOMAIN_ETSI, {'C', 'Z'}}, //CZECH REPUBLIC
343 { REGDOMAIN_ETSI, {'D', 'E'}}, //GERMANY
344 { REGDOMAIN_NO_5GHZ, {'D', 'J'}}, //DJIBOUTI
345 { REGDOMAIN_ETSI, {'D', 'K'}}, //DENMARK
346 { REGDOMAIN_WORLD, {'D', 'M'}}, //DOMINICA
347 { REGDOMAIN_APAC, {'D', 'O'}}, //DOMINICAN REPUBLIC
Yue Ma9e047ce2013-06-10 10:52:22 -0700348 { REGDOMAIN_ETSI, {'D', 'Z'}}, //ALGERIA
Madan Mohan Koyyalamudi00ff26d2012-11-02 13:33:26 -0700349 { REGDOMAIN_APAC, {'E', 'C'}}, //ECUADOR
350 { REGDOMAIN_ETSI, {'E', 'E'}}, //ESTONIA
351 { REGDOMAIN_N_AMER_EXC_FCC, {'E', 'G'}}, //EGYPT
352 { REGDOMAIN_WORLD, {'E', 'H'}}, //WESTERN SAHARA
353 { REGDOMAIN_NO_5GHZ, {'E', 'R'}}, //ERITREA
354 { REGDOMAIN_ETSI, {'E', 'S'}}, //SPAIN
355 { REGDOMAIN_ETSI, {'E', 'T'}}, //ETHIOPIA
356 { REGDOMAIN_ETSI, {'E', 'U'}}, //Europe (SSGFI)
357 { REGDOMAIN_ETSI, {'F', 'I'}}, //FINLAND
358 { REGDOMAIN_NO_5GHZ, {'F', 'J'}}, //FIJI
359 { REGDOMAIN_WORLD, {'F', 'K'}}, //FALKLAND ISLANDS (MALVINAS)
360 { REGDOMAIN_WORLD, {'F', 'M'}}, //MICRONESIA, FEDERATED STATES OF
361 { REGDOMAIN_WORLD, {'F', 'O'}}, //FAROE ISLANDS
362 { REGDOMAIN_ETSI, {'F', 'R'}}, //FRANCE
363 { REGDOMAIN_NO_5GHZ, {'G', 'A'}}, //GABON
364 { REGDOMAIN_ETSI, {'G', 'B'}}, //UNITED KINGDOM
365 { REGDOMAIN_WORLD, {'G', 'D'}}, //GRENADA
366 { REGDOMAIN_ETSI, {'G', 'E'}}, //GEORGIA
367 { REGDOMAIN_ETSI, {'G', 'F'}}, //FRENCH GUIANA
368 { REGDOMAIN_WORLD, {'G', 'G'}}, //GUERNSEY
369 { REGDOMAIN_WORLD, {'G', 'H'}}, //GHANA
370 { REGDOMAIN_WORLD, {'G', 'I'}}, //GIBRALTAR
371 { REGDOMAIN_ETSI, {'G', 'L'}}, //GREENLAND
372 { REGDOMAIN_NO_5GHZ, {'G', 'M'}}, //GAMBIA
373 { REGDOMAIN_NO_5GHZ, {'G', 'N'}}, //GUINEA
374 { REGDOMAIN_ETSI, {'G', 'P'}}, //GUADELOUPE
375 { REGDOMAIN_NO_5GHZ, {'G', 'Q'}}, //EQUATORIAL GUINEA
376 { REGDOMAIN_ETSI, {'G', 'R'}}, //GREECE
377 { REGDOMAIN_WORLD, {'G', 'S'}}, //SOUTH GEORGIA AND THE SOUTH SANDWICH ISLANDS
378 { REGDOMAIN_APAC, {'G', 'T'}}, //GUATEMALA
Yue Ma9e047ce2013-06-10 10:52:22 -0700379 { REGDOMAIN_FCC, {'G', 'U'}}, //GUAM
Madan Mohan Koyyalamudi00ff26d2012-11-02 13:33:26 -0700380 { REGDOMAIN_NO_5GHZ, {'G', 'W'}}, //GUINEA-BISSAU
381 { REGDOMAIN_HI_5GHZ, {'G', 'Y'}}, //GUYANA
382 { REGDOMAIN_WORLD, {'H', 'K'}}, //HONGKONG
383 { REGDOMAIN_WORLD, {'H', 'M'}}, //HEARD ISLAND AND MCDONALD ISLANDS
384 { REGDOMAIN_WORLD, {'H', 'N'}}, //HONDURAS
385 { REGDOMAIN_ETSI, {'H', 'R'}}, //CROATIA
386 { REGDOMAIN_ETSI, {'H', 'T'}}, //HAITI
387 { REGDOMAIN_ETSI, {'H', 'U'}}, //HUNGARY
388 { REGDOMAIN_HI_5GHZ, {'I', 'D'}}, //INDONESIA
389 { REGDOMAIN_ETSI, {'I', 'E'}}, //IRELAND
Yue Ma9e047ce2013-06-10 10:52:22 -0700390 { REGDOMAIN_N_AMER_EXC_FCC, {'I', 'L'}}, //ISRAEL
Madan Mohan Koyyalamudi00ff26d2012-11-02 13:33:26 -0700391 { REGDOMAIN_WORLD, {'I', 'M'}}, //ISLE OF MAN
392 { REGDOMAIN_APAC, {'I', 'N'}}, //INDIA
393 { REGDOMAIN_WORLD, {'I', 'O'}}, //BRITISH INDIAN OCEAN TERRITORY
394 { REGDOMAIN_NO_5GHZ, {'I', 'Q'}}, //IRAQ
395 { REGDOMAIN_HI_5GHZ, {'I', 'R'}}, //IRAN, ISLAMIC REPUBLIC OF
396 { REGDOMAIN_ETSI, {'I', 'S'}}, //ICELAND
397 { REGDOMAIN_ETSI, {'I', 'T'}}, //ITALY
398 { REGDOMAIN_JAPAN, {'J', '1'}}, //Japan alternate 1
399 { REGDOMAIN_JAPAN, {'J', '2'}}, //Japan alternate 2
400 { REGDOMAIN_JAPAN, {'J', '3'}}, //Japan alternate 3
401 { REGDOMAIN_JAPAN, {'J', '4'}}, //Japan alternate 4
402 { REGDOMAIN_JAPAN, {'J', '5'}}, //Japan alternate 5
403 { REGDOMAIN_WORLD, {'J', 'E'}}, //JERSEY
404 { REGDOMAIN_WORLD, {'J', 'M'}}, //JAMAICA
Yue Ma9e047ce2013-06-10 10:52:22 -0700405 { REGDOMAIN_APAC, {'J', 'O'}}, //JORDAN
Madan Mohan Koyyalamudi00ff26d2012-11-02 13:33:26 -0700406 { REGDOMAIN_JAPAN, {'J', 'P'}}, //JAPAN
407 { REGDOMAIN_KOREA, {'K', '1'}}, //Korea alternate 1
408 { REGDOMAIN_KOREA, {'K', '2'}}, //Korea alternate 2
409 { REGDOMAIN_KOREA, {'K', '3'}}, //Korea alternate 3
410 { REGDOMAIN_KOREA, {'K', '4'}}, //Korea alternate 4
Yue Ma2f134332013-07-10 11:18:57 -0700411 { REGDOMAIN_APAC, {'K', 'E'}}, //KENYA
Madan Mohan Koyyalamudi00ff26d2012-11-02 13:33:26 -0700412 { REGDOMAIN_NO_5GHZ, {'K', 'G'}}, //KYRGYZSTAN
413 { REGDOMAIN_ETSI, {'K', 'H'}}, //CAMBODIA
414 { REGDOMAIN_WORLD, {'K', 'I'}}, //KIRIBATI
415 { REGDOMAIN_NO_5GHZ, {'K', 'M'}}, //COMOROS
416 { REGDOMAIN_WORLD, {'K', 'N'}}, //SAINT KITTS AND NEVIS
417 { REGDOMAIN_WORLD, {'K', 'P'}}, //KOREA, DEMOCRATIC PEOPLE'S REPUBLIC OF
418 { REGDOMAIN_KOREA, {'K', 'R'}}, //KOREA, REPUBLIC OF
419 { REGDOMAIN_N_AMER_EXC_FCC, {'K', 'W'}}, //KUWAIT
420 { REGDOMAIN_FCC, {'K', 'Y'}}, //CAYMAN ISLANDS
Yue Ma9e047ce2013-06-10 10:52:22 -0700421 { REGDOMAIN_WORLD, {'K', 'Z'}}, //KAZAKHSTAN
Madan Mohan Koyyalamudi00ff26d2012-11-02 13:33:26 -0700422 { REGDOMAIN_WORLD, {'L', 'A'}}, //LAO PEOPLE'S DEMOCRATIC REPUBLIC
Yue Ma2f134332013-07-10 11:18:57 -0700423 { REGDOMAIN_WORLD, {'L', 'B'}}, //LEBANON
Madan Mohan Koyyalamudi00ff26d2012-11-02 13:33:26 -0700424 { REGDOMAIN_WORLD, {'L', 'C'}}, //SAINT LUCIA
425 { REGDOMAIN_ETSI, {'L', 'I'}}, //LIECHTENSTEIN
426 { REGDOMAIN_WORLD, {'L', 'K'}}, //SRI LANKA
427 { REGDOMAIN_WORLD, {'L', 'R'}}, //LIBERIA
428 { REGDOMAIN_ETSI, {'L', 'S'}}, //LESOTHO
429 { REGDOMAIN_ETSI, {'L', 'T'}}, //LITHUANIA
430 { REGDOMAIN_ETSI, {'L', 'U'}}, //LUXEMBOURG
431 { REGDOMAIN_ETSI, {'L', 'V'}}, //LATVIA
432 { REGDOMAIN_NO_5GHZ, {'L', 'Y'}}, //LIBYAN ARAB JAMAHIRIYA
Yue Ma9e047ce2013-06-10 10:52:22 -0700433 { REGDOMAIN_APAC, {'M', 'A'}}, //MOROCCO
Yue Ma2f134332013-07-10 11:18:57 -0700434 { REGDOMAIN_ETSI, {'M', 'C'}}, //MONACO
Madan Mohan Koyyalamudi00ff26d2012-11-02 13:33:26 -0700435 { REGDOMAIN_ETSI, {'M', 'D'}}, //MOLDOVA, REPUBLIC OF
436 { REGDOMAIN_ETSI, {'M', 'E'}}, //MONTENEGRO
437 { REGDOMAIN_NO_5GHZ, {'M', 'G'}}, //MADAGASCAR
438 { REGDOMAIN_WORLD, {'M', 'H'}}, //MARSHALL ISLANDS
439 { REGDOMAIN_ETSI, {'M', 'K'}}, //MACEDONIA, THE FORMER YUGOSLAV REPUBLIC OF
440 { REGDOMAIN_NO_5GHZ, {'M', 'L'}}, //MALI
441 { REGDOMAIN_WORLD, {'M', 'M'}}, //MYANMAR
Yue Ma346a7932013-06-19 10:36:42 -0700442 { REGDOMAIN_WORLD, {'M', 'N'}}, //MONGOLIA
Madan Mohan Koyyalamudi00ff26d2012-11-02 13:33:26 -0700443 { REGDOMAIN_APAC, {'M', 'O'}}, //MACAO
444 { REGDOMAIN_FCC, {'M', 'P'}}, //NORTHERN MARIANA ISLANDS
445 { REGDOMAIN_ETSI, {'M', 'Q'}}, //MARTINIQUE
446 { REGDOMAIN_ETSI, {'M', 'R'}}, //MAURITANIA
447 { REGDOMAIN_ETSI, {'M', 'S'}}, //MONTSERRAT
448 { REGDOMAIN_ETSI, {'M', 'T'}}, //MALTA
449 { REGDOMAIN_ETSI, {'M', 'U'}}, //MAURITIUS
450 { REGDOMAIN_APAC, {'M', 'V'}}, //MALDIVES
451 { REGDOMAIN_HI_5GHZ, {'M', 'W'}}, //MALAWI
452 { REGDOMAIN_APAC, {'M', 'X'}}, //MEXICO
453 { REGDOMAIN_APAC, {'M', 'Y'}}, //MALAYSIA
454 { REGDOMAIN_WORLD, {'M', 'Z'}}, //MOZAMBIQUE
455 { REGDOMAIN_WORLD, {'N', 'A'}}, //NAMIBIA
456 { REGDOMAIN_NO_5GHZ, {'N', 'C'}}, //NEW CALEDONIA
457 { REGDOMAIN_WORLD, {'N', 'E'}}, //NIGER
458 { REGDOMAIN_WORLD, {'N', 'F'}}, //NORFOLD ISLAND
459 { REGDOMAIN_WORLD, {'N', 'G'}}, //NIGERIA
460 { REGDOMAIN_WORLD, {'N', 'I'}}, //NICARAGUA
461 { REGDOMAIN_ETSI, {'N', 'L'}}, //NETHERLANDS
462 { REGDOMAIN_ETSI, {'N', 'O'}}, //NORWAY
Yue Ma9e047ce2013-06-10 10:52:22 -0700463 { REGDOMAIN_APAC, {'N', 'P'}}, //NEPAL
Madan Mohan Koyyalamudi00ff26d2012-11-02 13:33:26 -0700464 { REGDOMAIN_NO_5GHZ, {'N', 'R'}}, //NAURU
465 { REGDOMAIN_WORLD, {'N', 'U'}}, //NIUE
466 { REGDOMAIN_APAC, {'N', 'Z'}}, //NEW ZEALAND
Yue Ma2f134332013-07-10 11:18:57 -0700467 { REGDOMAIN_ETSI, {'O', 'M'}}, //OMAN
Madan Mohan Koyyalamudi00ff26d2012-11-02 13:33:26 -0700468 { REGDOMAIN_APAC, {'P', 'A'}}, //PANAMA
Yue Ma9e047ce2013-06-10 10:52:22 -0700469 { REGDOMAIN_WORLD, {'P', 'E'}}, //PERU
Madan Mohan Koyyalamudi00ff26d2012-11-02 13:33:26 -0700470 { REGDOMAIN_ETSI, {'P', 'F'}}, //FRENCH POLYNESIA
Yue Ma2f134332013-07-10 11:18:57 -0700471 { REGDOMAIN_WORLD, {'P', 'G'}}, //PAPUA NEW GUINEA
472 { REGDOMAIN_WORLD, {'P', 'H'}}, //PHILIPPINES
Madan Mohan Koyyalamudi00ff26d2012-11-02 13:33:26 -0700473 { REGDOMAIN_HI_5GHZ, {'P', 'K'}}, //PAKISTAN
474 { REGDOMAIN_ETSI, {'P', 'L'}}, //POLAND
475 { REGDOMAIN_WORLD, {'P', 'M'}}, //SAINT PIERRE AND MIQUELON
476 { REGDOMAIN_WORLD, {'P', 'N'}}, //WORLDPITCAIRN
477 { REGDOMAIN_FCC, {'P', 'R'}}, //PUERTO RICO
478 { REGDOMAIN_WORLD, {'P', 'S'}}, //PALESTINIAN TERRITORY, OCCUPIED
479 { REGDOMAIN_ETSI, {'P', 'T'}}, //PORTUGAL
480 { REGDOMAIN_WORLD, {'P', 'W'}}, //PALAU
481 { REGDOMAIN_WORLD, {'P', 'Y'}}, //PARAGUAY
482 { REGDOMAIN_HI_5GHZ, {'Q', 'A'}}, //QATAR
483 { REGDOMAIN_ETSI, {'R', 'E'}}, //REUNION
484 { REGDOMAIN_ETSI, {'R', 'O'}}, //ROMANIA
485 { REGDOMAIN_ETSI, {'R', 'S'}}, //SERBIA
Yue Ma9e047ce2013-06-10 10:52:22 -0700486 { REGDOMAIN_APAC, {'R', 'U'}}, //RUSSIA
487 { REGDOMAIN_WORLD, {'R', 'W'}}, //RWANDA
488 { REGDOMAIN_WORLD, {'S', 'A'}}, //SAUDI ARABIA
Madan Mohan Koyyalamudi00ff26d2012-11-02 13:33:26 -0700489 { REGDOMAIN_NO_5GHZ, {'S', 'B'}}, //SOLOMON ISLANDS
490 { REGDOMAIN_NO_5GHZ, {'S', 'C'}}, //SEYCHELLES
491 { REGDOMAIN_WORLD, {'S', 'D'}}, //SUDAN
492 { REGDOMAIN_ETSI, {'S', 'E'}}, //SWEDEN
493 { REGDOMAIN_APAC, {'S', 'G'}}, //SINGAPORE
494 { REGDOMAIN_WORLD, {'S', 'H'}}, //SAINT HELENA
495 { REGDOMAIN_ETSI, {'S', 'I'}}, //SLOVENNIA
496 { REGDOMAIN_WORLD, {'S', 'J'}}, //SVALBARD AND JAN MAYEN
497 { REGDOMAIN_ETSI, {'S', 'K'}}, //SLOVAKIA
498 { REGDOMAIN_WORLD, {'S', 'L'}}, //SIERRA LEONE
499 { REGDOMAIN_ETSI, {'S', 'M'}}, //SAN MARINO
500 { REGDOMAIN_ETSI, {'S', 'N'}}, //SENEGAL
501 { REGDOMAIN_NO_5GHZ, {'S', 'O'}}, //SOMALIA
502 { REGDOMAIN_NO_5GHZ, {'S', 'R'}}, //SURINAME
503 { REGDOMAIN_WORLD, {'S', 'T'}}, //SAO TOME AND PRINCIPE
504 { REGDOMAIN_APAC, {'S', 'V'}}, //EL SALVADOR
505 { REGDOMAIN_NO_5GHZ, {'S', 'Y'}}, //SYRIAN ARAB REPUBLIC
506 { REGDOMAIN_NO_5GHZ, {'S', 'Z'}}, //SWAZILAND
507 { REGDOMAIN_ETSI, {'T', 'C'}}, //TURKS AND CAICOS ISLANDS
508 { REGDOMAIN_NO_5GHZ, {'T', 'D'}}, //CHAD
509 { REGDOMAIN_ETSI, {'T', 'F'}}, //FRENCH SOUTHERN TERRITORIES
510 { REGDOMAIN_NO_5GHZ, {'T', 'G'}}, //TOGO
511 { REGDOMAIN_WORLD, {'T', 'H'}}, //THAILAND
512 { REGDOMAIN_NO_5GHZ, {'T', 'J'}}, //TAJIKISTAN
513 { REGDOMAIN_WORLD, {'T', 'K'}}, //TOKELAU
514 { REGDOMAIN_WORLD, {'T', 'L'}}, //TIMOR-LESTE
515 { REGDOMAIN_NO_5GHZ, {'T', 'M'}}, //TURKMENISTAN
516 { REGDOMAIN_N_AMER_EXC_FCC, {'T', 'N'}}, //TUNISIA
517 { REGDOMAIN_NO_5GHZ, {'T', 'O'}}, //TONGA
Yue Ma2f134332013-07-10 11:18:57 -0700518 { REGDOMAIN_ETSI, {'T', 'R'}}, //TURKEY
Madan Mohan Koyyalamudi00ff26d2012-11-02 13:33:26 -0700519 { REGDOMAIN_WORLD, {'T', 'T'}}, //TRINIDAD AND TOBAGO
520 { REGDOMAIN_NO_5GHZ, {'T', 'V'}}, //TUVALU
Yue Ma9e047ce2013-06-10 10:52:22 -0700521 { REGDOMAIN_FCC, {'T', 'W'}}, //TAIWAN, PROVINCE OF CHINA
Madan Mohan Koyyalamudi00ff26d2012-11-02 13:33:26 -0700522 { REGDOMAIN_HI_5GHZ, {'T', 'Z'}}, //TANZANIA, UNITED REPUBLIC OF
Yue Ma9e047ce2013-06-10 10:52:22 -0700523 { REGDOMAIN_WORLD, {'U', 'A'}}, //UKRAINE
524 { REGDOMAIN_KOREA, {'U', 'G'}}, //UGANDA
Madan Mohan Koyyalamudi00ff26d2012-11-02 13:33:26 -0700525 { REGDOMAIN_FCC, {'U', 'M'}}, //UNITED STATES MINOR OUTLYING ISLANDS
526 { REGDOMAIN_WORLD, {'U', 'Y'}}, //URUGUAY
Yue Ma9e047ce2013-06-10 10:52:22 -0700527 { REGDOMAIN_FCC, {'U', 'Z'}}, //UZBEKISTAN
Madan Mohan Koyyalamudi00ff26d2012-11-02 13:33:26 -0700528 { REGDOMAIN_ETSI, {'V', 'A'}}, //HOLY SEE (VATICAN CITY STATE)
529 { REGDOMAIN_WORLD, {'V', 'C'}}, //SAINT VINCENT AND THE GRENADINES
530 { REGDOMAIN_HI_5GHZ, {'V', 'E'}}, //VENEZUELA
531 { REGDOMAIN_ETSI, {'V', 'G'}}, //VIRGIN ISLANDS, BRITISH
532 { REGDOMAIN_FCC, {'V', 'I'}}, //VIRGIN ISLANDS, US
Yue Ma2f134332013-07-10 11:18:57 -0700533 { REGDOMAIN_FCC, {'V', 'N'}}, //VIET NAM
Madan Mohan Koyyalamudi00ff26d2012-11-02 13:33:26 -0700534 { REGDOMAIN_NO_5GHZ, {'V', 'U'}}, //VANUATU
535 { REGDOMAIN_WORLD, {'W', 'F'}}, //WALLIS AND FUTUNA
536 { REGDOMAIN_N_AMER_EXC_FCC, {'W', 'S'}}, //SOMOA
537 { REGDOMAIN_NO_5GHZ, {'Y', 'E'}}, //YEMEN
538 { REGDOMAIN_ETSI, {'Y', 'T'}}, //MAYOTTE
539 { REGDOMAIN_WORLD, {'Z', 'A'}}, //SOUTH AFRICA
540 { REGDOMAIN_APAC, {'Z', 'M'}}, //ZAMBIA
Yue Ma9e047ce2013-06-10 10:52:22 -0700541 { REGDOMAIN_ETSI, {'Z', 'W'}}, //ZIMBABWE
Jeff Johnson295189b2012-06-20 16:38:30 -0700542 }
543};
Amar Singhal61cbd962013-09-05 13:03:40 -0700544
545#endif
546
Amar Singhal9a65a6a2013-10-08 18:37:44 -0700547
Jeff Johnson295189b2012-06-20 16:38:30 -0700548typedef struct nvEFSTable_s
549{
550 v_U32_t nvValidityBitmap;
551 sHalNv halnv;
552} nvEFSTable_t;
Madan Mohan Koyyalamudidfd6aa82012-10-18 20:18:43 -0700553nvEFSTable_t *gnvEFSTable;
Amar Singhal61cbd962013-09-05 13:03:40 -0700554/* EFS Table to send the NV structure to HAL*/
Madan Mohan Koyyalamudidfd6aa82012-10-18 20:18:43 -0700555static nvEFSTable_t *pnvEFSTable;
Prasanna Kumar0833aa82013-04-11 20:05:21 -0700556static v_U8_t *pnvEncodedBuf;
557static v_U8_t *pDictFile;
558static v_U8_t *pEncodedBuf;
559static v_SIZE_t nvReadEncodeBufSize;
560static v_SIZE_t nDictionarySize;
561static v_U32_t magicNumber;
Jeff Johnson295189b2012-06-20 16:38:30 -0700562
563const tRfChannelProps rfChannels[NUM_RF_CHANNELS] =
564{
565 //RF_SUBBAND_2_4_GHZ
566 //freq, chan#, band
567 { 2412, 1 , RF_SUBBAND_2_4_GHZ}, //RF_CHAN_1,
568 { 2417, 2 , RF_SUBBAND_2_4_GHZ}, //RF_CHAN_2,
569 { 2422, 3 , RF_SUBBAND_2_4_GHZ}, //RF_CHAN_3,
570 { 2427, 4 , RF_SUBBAND_2_4_GHZ}, //RF_CHAN_4,
571 { 2432, 5 , RF_SUBBAND_2_4_GHZ}, //RF_CHAN_5,
572 { 2437, 6 , RF_SUBBAND_2_4_GHZ}, //RF_CHAN_6,
573 { 2442, 7 , RF_SUBBAND_2_4_GHZ}, //RF_CHAN_7,
574 { 2447, 8 , RF_SUBBAND_2_4_GHZ}, //RF_CHAN_8,
575 { 2452, 9 , RF_SUBBAND_2_4_GHZ}, //RF_CHAN_9,
576 { 2457, 10 , RF_SUBBAND_2_4_GHZ}, //RF_CHAN_10,
577 { 2462, 11 , RF_SUBBAND_2_4_GHZ}, //RF_CHAN_11,
578 { 2467, 12 , RF_SUBBAND_2_4_GHZ}, //RF_CHAN_12,
579 { 2472, 13 , RF_SUBBAND_2_4_GHZ}, //RF_CHAN_13,
580 { 2484, 14 , RF_SUBBAND_2_4_GHZ}, //RF_CHAN_14,
Madan Mohan Koyyalamudic3a240c2012-09-28 15:34:08 -0700581 { 4920, 240, RF_SUBBAND_4_9_GHZ}, //RF_CHAN_240,
582 { 4940, 244, RF_SUBBAND_4_9_GHZ}, //RF_CHAN_244,
583 { 4960, 248, RF_SUBBAND_4_9_GHZ}, //RF_CHAN_248,
584 { 4980, 252, RF_SUBBAND_4_9_GHZ}, //RF_CHAN_252,
585 { 5040, 208, RF_SUBBAND_4_9_GHZ}, //RF_CHAN_208,
586 { 5060, 212, RF_SUBBAND_4_9_GHZ}, //RF_CHAN_212,
587 { 5080, 216, RF_SUBBAND_4_9_GHZ}, //RF_CHAN_216,
Jeff Johnson295189b2012-06-20 16:38:30 -0700588 { 5180, 36 , RF_SUBBAND_5_LOW_GHZ}, //RF_CHAN_36,
589 { 5200, 40 , RF_SUBBAND_5_LOW_GHZ}, //RF_CHAN_40,
590 { 5220, 44 , RF_SUBBAND_5_LOW_GHZ}, //RF_CHAN_44,
591 { 5240, 48 , RF_SUBBAND_5_LOW_GHZ}, //RF_CHAN_48,
592 { 5260, 52 , RF_SUBBAND_5_LOW_GHZ}, //RF_CHAN_52,
593 { 5280, 56 , RF_SUBBAND_5_LOW_GHZ}, //RF_CHAN_56,
594 { 5300, 60 , RF_SUBBAND_5_LOW_GHZ}, //RF_CHAN_60,
595 { 5320, 64 , RF_SUBBAND_5_LOW_GHZ}, //RF_CHAN_64,
596 { 5500, 100, RF_SUBBAND_5_MID_GHZ}, //RF_CHAN_100,
597 { 5520, 104, RF_SUBBAND_5_MID_GHZ}, //RF_CHAN_104,
598 { 5540, 108, RF_SUBBAND_5_MID_GHZ}, //RF_CHAN_108,
599 { 5560, 112, RF_SUBBAND_5_MID_GHZ}, //RF_CHAN_112,
600 { 5580, 116, RF_SUBBAND_5_MID_GHZ}, //RF_CHAN_116,
601 { 5600, 120, RF_SUBBAND_5_MID_GHZ}, //RF_CHAN_120,
602 { 5620, 124, RF_SUBBAND_5_MID_GHZ}, //RF_CHAN_124,
603 { 5640, 128, RF_SUBBAND_5_MID_GHZ}, //RF_CHAN_128,
604 { 5660, 132, RF_SUBBAND_5_MID_GHZ}, //RF_CHAN_132,
605 { 5680, 136, RF_SUBBAND_5_MID_GHZ}, //RF_CHAN_136,
606 { 5700, 140, RF_SUBBAND_5_MID_GHZ}, //RF_CHAN_140,
607 { 5745, 149, RF_SUBBAND_5_HIGH_GHZ}, //RF_CHAN_149,
608 { 5765, 153, RF_SUBBAND_5_HIGH_GHZ}, //RF_CHAN_153,
609 { 5785, 157, RF_SUBBAND_5_HIGH_GHZ}, //RF_CHAN_157,
610 { 5805, 161, RF_SUBBAND_5_HIGH_GHZ}, //RF_CHAN_161,
611 { 5825, 165, RF_SUBBAND_5_HIGH_GHZ}, //RF_CHAN_165,
Madan Mohan Koyyalamudic3a240c2012-09-28 15:34:08 -0700612 { 2422, 3 , NUM_RF_SUBBANDS}, //RF_CHAN_BOND_3,
613 { 2427, 4 , NUM_RF_SUBBANDS}, //RF_CHAN_BOND_4,
614 { 2432, 5 , NUM_RF_SUBBANDS}, //RF_CHAN_BOND_5,
615 { 2437, 6 , NUM_RF_SUBBANDS}, //RF_CHAN_BOND_6,
616 { 2442, 7 , NUM_RF_SUBBANDS}, //RF_CHAN_BOND_7,
617 { 2447, 8 , NUM_RF_SUBBANDS}, //RF_CHAN_BOND_8,
618 { 2452, 9 , NUM_RF_SUBBANDS}, //RF_CHAN_BOND_9,
619 { 2457, 10 , NUM_RF_SUBBANDS}, //RF_CHAN_BOND_10,
620 { 2462, 11 , NUM_RF_SUBBANDS}, //RF_CHAN_BOND_11,
621 { 4930, 242, NUM_RF_SUBBANDS}, //RF_CHAN_BOND_242,
622 { 4950, 246, NUM_RF_SUBBANDS}, //RF_CHAN_BOND_246,
623 { 4970, 250, NUM_RF_SUBBANDS}, //RF_CHAN_BOND_250,
624 { 5050, 210, NUM_RF_SUBBANDS}, //RF_CHAN_BOND_210,
625 { 5070, 214, NUM_RF_SUBBANDS}, //RF_CHAN_BOND_214,
626 { 5190, 38 , NUM_RF_SUBBANDS}, //RF_CHAN_BOND_38,
627 { 5210, 42 , NUM_RF_SUBBANDS}, //RF_CHAN_BOND_42,
628 { 5230, 46 , NUM_RF_SUBBANDS}, //RF_CHAN_BOND_46,
629 { 5250, 50 , NUM_RF_SUBBANDS}, //RF_CHAN_BOND_50,
630 { 5270, 54 , NUM_RF_SUBBANDS}, //RF_CHAN_BOND_54,
631 { 5290, 58 , NUM_RF_SUBBANDS}, //RF_CHAN_BOND_58,
632 { 5310, 62 , NUM_RF_SUBBANDS}, //RF_CHAN_BOND_62,
633 { 5510, 102, NUM_RF_SUBBANDS}, //RF_CHAN_BOND_102,
634 { 5530, 106, NUM_RF_SUBBANDS}, //RF_CHAN_BOND_106,
635 { 5550, 110, NUM_RF_SUBBANDS}, //RF_CHAN_BOND_110,
636 { 5570, 114, NUM_RF_SUBBANDS}, //RF_CHAN_BOND_114,
637 { 5590, 118, NUM_RF_SUBBANDS}, //RF_CHAN_BOND_118,
638 { 5610, 122, NUM_RF_SUBBANDS}, //RF_CHAN_BOND_122,
639 { 5630, 126, NUM_RF_SUBBANDS}, //RF_CHAN_BOND_126,
640 { 5650, 130, NUM_RF_SUBBANDS}, //RF_CHAN_BOND_130,
641 { 5670, 134, NUM_RF_SUBBANDS}, //RF_CHAN_BOND_134,
642 { 5690, 138, NUM_RF_SUBBANDS}, //RF_CHAN_BOND_138,
643 { 5755, 151, NUM_RF_SUBBANDS}, //RF_CHAN_BOND_151,
644 { 5775, 155, NUM_RF_SUBBANDS}, //RF_CHAN_BOND_155,
645 { 5795, 159, NUM_RF_SUBBANDS}, //RF_CHAN_BOND_159,
646 { 5815, 163, NUM_RF_SUBBANDS}, //RF_CHAN_BOND_163,
Jeff Johnson295189b2012-06-20 16:38:30 -0700647};
648
649extern const sHalNv nvDefaults;
650
651const sRegulatoryChannel * regChannels = nvDefaults.tables.regDomains[0].channels;
652
653/*----------------------------------------------------------------------------
654 Function Definitions and Documentation
655 * -------------------------------------------------------------------------*/
656VOS_STATUS wlan_write_to_efs (v_U8_t *pData, v_U16_t data_len);
657/**------------------------------------------------------------------------
658 \brief vos_nv_init() - initialize the NV module
659 The \a vos_nv_init() initializes the NV module. This read the binary
660 file for country code and regulatory domain information.
661 \return VOS_STATUS_SUCCESS - module is initialized successfully
662 otherwise - module is not initialized
663 \sa
664 -------------------------------------------------------------------------*/
665VOS_STATUS vos_nv_init(void)
666{
667 return VOS_STATUS_SUCCESS;
668}
669
Prasanna Kumar0833aa82013-04-11 20:05:21 -0700670/**------------------------------------------------------------------------
671 \brief vos_nv_get_dictionary_data() - get the dictionary data required for
672 \ tools
673 \return VOS_STATUS_SUCCESS - dictionary data is read successfully
674 otherwise - not successful
675 \sa
676-------------------------------------------------------------------------*/
677VOS_STATUS vos_nv_get_dictionary_data(void)
678{
679 VOS_STATUS vosStatus = VOS_STATUS_E_FAILURE;
680
681 if (MAGIC_NUMBER != magicNumber)
682 {
683 return VOS_STATUS_SUCCESS;
684 }
685
686 nDictionarySize = 0;
687
688 vosStatus = vos_get_binary_blob( VOS_BINARY_ID_DICT_CONFIG, NULL,
689 &nDictionarySize );
690 if (VOS_STATUS_E_NOMEM != vosStatus)
691 {
692 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
693 "Error obtaining binary size" );
694/// NOTE:
695/// We can still work without a dictionary file..
696 return VOS_STATUS_SUCCESS;
697 }
698
699 // malloc a buffer to read in the Configuration binary file.
700 pDictFile = vos_mem_malloc( nDictionarySize );
701 if (NULL == pDictFile)
702 {
703 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
704 "Unable to allocate memory for the CFG binary [size= %d bytes]",
705 nDictionarySize );
706 vosStatus = VOS_STATUS_E_NOMEM;
707 goto fail;
708 }
709
710 /* Get the entire CFG file image... */
711 vosStatus = vos_get_binary_blob( VOS_BINARY_ID_DICT_CONFIG, pDictFile,
712 &nDictionarySize );
713 if (!VOS_IS_STATUS_SUCCESS( vosStatus ))
714 {
715 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
716 "Error: Cannot retrieve CFG file image from vOSS. [size= %d bytes]",
717 nDictionarySize );
718 return VOS_STATUS_SUCCESS;
719 }
720
721 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_INFO_HIGH,
722 "Dict file image from vOSS. [size= %d bytes]", nDictionarySize );
723
724fail:
725 return vosStatus;
726}
727
Jeff Johnson295189b2012-06-20 16:38:30 -0700728VOS_STATUS vos_nv_open(void)
729{
730 VOS_STATUS status = VOS_STATUS_SUCCESS;
731 v_CONTEXT_t pVosContext= NULL;
732 v_SIZE_t bufSize;
Madan Mohan Koyyalamudi1dd5c882012-09-24 13:31:39 -0700733 v_SIZE_t nvReadBufSize;
Jeff Johnson295189b2012-06-20 16:38:30 -0700734 v_BOOL_t itemIsValid = VOS_FALSE;
Prasanna Kumar0833aa82013-04-11 20:05:21 -0700735 v_U32_t dataOffset;
736 sHalNv *pnvData = NULL;
737
Jeff Johnson295189b2012-06-20 16:38:30 -0700738 /*Get the global context */
739 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
Prasanna Kumar0833aa82013-04-11 20:05:21 -0700740
741 if (NULL == pVosContext)
Madan Mohan Koyyalamudi0b78e152012-11-28 15:46:51 -0800742 {
743 return (eHAL_STATUS_FAILURE);
744 }
745
Jeff Johnson295189b2012-06-20 16:38:30 -0700746 bufSize = sizeof(nvEFSTable_t);
747 status = hdd_request_firmware(WLAN_NV_FILE,
748 ((VosContextType*)(pVosContext))->pHDDContext,
Prasanna Kumar0833aa82013-04-11 20:05:21 -0700749 (v_VOID_t**)&pnvEncodedBuf, &nvReadBufSize);
Jeff Johnson295189b2012-06-20 16:38:30 -0700750
Prasanna Kumar0833aa82013-04-11 20:05:21 -0700751 if ((!VOS_IS_STATUS_SUCCESS( status )) || (!pnvEncodedBuf))
Jeff Johnson295189b2012-06-20 16:38:30 -0700752 {
Prasanna Kumar0833aa82013-04-11 20:05:21 -0700753 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
Jeff Johnson295189b2012-06-20 16:38:30 -0700754 "%s: unable to download NV file %s",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700755 __func__, WLAN_NV_FILE);
Prasanna Kumar0833aa82013-04-11 20:05:21 -0700756 return VOS_STATUS_E_RESOURCES;
Jeff Johnson295189b2012-06-20 16:38:30 -0700757 }
758
Prasanna Kumar0833aa82013-04-11 20:05:21 -0700759 memcpy(&magicNumber, &pnvEncodedBuf[sizeof(v_U32_t)], sizeof(v_U32_t));
760
761 /// Allocate buffer with maximum length..
762 pEncodedBuf = (v_U8_t *)vos_mem_malloc(nvReadBufSize);
763
764 if (NULL == pEncodedBuf)
765 {
766 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
767 "%s : failed to allocate memory for NV", __func__);
768 return VOS_STATUS_E_NOMEM;
769 }
770
771 gnvEFSTable = (nvEFSTable_t*)pnvEncodedBuf;
772
773 if (MAGIC_NUMBER == magicNumber)
774 {
775 pnvData = (sHalNv *)vos_mem_malloc(sizeof(sHalNv));
776
777 if (NULL == pnvData)
778 {
779 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
780 "%s : failed to allocate memory for NV", __func__);
781 return VOS_STATUS_E_NOMEM;
782 }
783
784 memset(pnvData, 0, sizeof(sHalNv));
785
786 /// Data starts from offset of validity bit map + magic number..
787 dataOffset = sizeof(v_U32_t) + sizeof(v_U32_t);
788
789 status = nvParser(&pnvEncodedBuf[dataOffset],
790 (nvReadBufSize-dataOffset), pnvData);
791
792 ///ignore validity bit map
793 nvReadEncodeBufSize = nvReadBufSize - sizeof(v_U32_t);
794
795 vos_mem_copy(pEncodedBuf, &pnvEncodedBuf[sizeof(v_U32_t)],
796 nvReadEncodeBufSize);
797
798 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
799 "readEncodeBufSize %d",nvReadEncodeBufSize);
800
801 if (VOS_STATUS_SUCCESS == status) {
802 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
803 "Embedded NV parsed success !!productId %d couple Type %d wlan RevId %d",
804 pnvData->fields.productId,
805 pnvData->fields.couplerType,
806 pnvData->fields.wlanNvRevId);
807
808 vos_mem_copy(&gnvEFSTable->halnv, pnvData, sizeof(sHalNv));
809
810 nvReadBufSize = sizeof(sHalNv) + sizeof(v_U32_t);
811 }
812 else
813 {
814 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
815 "nvParser failed %d",status);
816
817 nvReadBufSize = 0;
818
819 vos_mem_copy(pEncodedBuf, &nvDefaults, sizeof(sHalNv));
820
821 nvReadEncodeBufSize = sizeof(sHalNv);
822 }
823 }
824 else
825 {
826 dataOffset = sizeof(v_U32_t);
827 nvReadEncodeBufSize = sizeof(sHalNv);
828 memcpy(pEncodedBuf, &pnvEncodedBuf[dataOffset], nvReadEncodeBufSize);
829 }
830
831 if (NULL != pnvData)
832 {
833 vos_mem_free(pnvData);
834 }
835
836 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
Gopichand Nakkalacaf27cd2013-01-04 11:45:31 -0800837 "INFO: NV binary file version=%d Driver default NV version=%d, continue...\n",
838 gnvEFSTable->halnv.fields.nvVersion, WLAN_NV_VERSION);
839
Jeff Johnson295189b2012-06-20 16:38:30 -0700840 /* Copying the read nv data to the globa NV EFS table */
841 {
842 /* Allocate memory to global NV table */
843 pnvEFSTable = (nvEFSTable_t *)vos_mem_malloc(sizeof(nvEFSTable_t));
Prasanna Kumar0833aa82013-04-11 20:05:21 -0700844 if ( NULL == pnvEFSTable )
Jeff Johnson295189b2012-06-20 16:38:30 -0700845 {
846 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700847 "%s : failed to allocate memory for NV", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700848 return VOS_STATUS_E_NOMEM;
849 }
850
851 /*Copying the NV defaults */
Prasanna Kumar0833aa82013-04-11 20:05:21 -0700852 vos_mem_copy(&(pnvEFSTable->halnv), &nvDefaults, sizeof(sHalNv));
Gopichand Nakkalacaf27cd2013-01-04 11:45:31 -0800853
854 /* Size mismatch */
Madan Mohan Koyyalamudi1dd5c882012-09-24 13:31:39 -0700855 if ( nvReadBufSize != bufSize)
856 {
857 pnvEFSTable->nvValidityBitmap = DEFAULT_NV_VALIDITY_BITMAP;
858 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
859 "!!!WARNING: INVALID NV FILE, DRIVER IS USING DEFAULT CAL VALUES %d %d!!!",
860 nvReadBufSize, bufSize);
Gopichand Nakkalacaf27cd2013-01-04 11:45:31 -0800861 return VOS_STATUS_SUCCESS;
Madan Mohan Koyyalamudi1dd5c882012-09-24 13:31:39 -0700862 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700863
Gopichand Nakkalacaf27cd2013-01-04 11:45:31 -0800864 /* Version mismatch */
865 if (gnvEFSTable->halnv.fields.nvVersion != WLAN_NV_VERSION)
866 {
867 if ((WLAN_NV_VERSION == NV_VERSION_11N_11AC_FW_CONFIG) &&
868 (gnvEFSTable->halnv.fields.nvVersion == NV_VERSION_11N_11AC_COUPER_TYPE))
869 {
870 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
871 "!!!WARNING: Using Coupler Type field instead of Fw Config table,\n"
872 "Make sure that this is intented or may impact performance!!!\n");
873 }
874 else
875 {
876 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
877 "!!!WARNING: NV binary file version doesn't match with Driver default NV version\n"
878 "Driver NV defaults will be used, may impact performance!!!\n");
879
880 return VOS_STATUS_SUCCESS;
881 }
882 }
883
Madan Mohan Koyyalamudi1dd5c882012-09-24 13:31:39 -0700884 pnvEFSTable->nvValidityBitmap = gnvEFSTable->nvValidityBitmap;
Amar Singhal61cbd962013-09-05 13:03:40 -0700885 /* Copy the valid fields to the NV Global structure */
886 if (vos_nv_getValidity(VNV_FIELD_IMAGE, &itemIsValid) ==
Jeff Johnson295189b2012-06-20 16:38:30 -0700887 VOS_STATUS_SUCCESS)
888 {
889 if (itemIsValid == VOS_TRUE) {
890
891 if(vos_nv_read( VNV_FIELD_IMAGE, (v_VOID_t *)&pnvEFSTable->halnv.fields,
892 NULL, sizeof(sNvFields) ) != VOS_STATUS_SUCCESS)
Madan Mohan Koyyalamudi0b78e152012-11-28 15:46:51 -0800893 goto error;
Jeff Johnson295189b2012-06-20 16:38:30 -0700894 }
895 }
896
Amar Singhal61cbd962013-09-05 13:03:40 -0700897 if (vos_nv_getValidity(VNV_RATE_TO_POWER_TABLE, &itemIsValid) ==
Jeff Johnson295189b2012-06-20 16:38:30 -0700898 VOS_STATUS_SUCCESS)
899 {
900 if (itemIsValid == VOS_TRUE)
901 {
Amar Singhal61cbd962013-09-05 13:03:40 -0700902 if(vos_nv_read( VNV_RATE_TO_POWER_TABLE,
Jeff Johnson295189b2012-06-20 16:38:30 -0700903 (v_VOID_t *)&pnvEFSTable->halnv.tables.pwrOptimum[0],
904 NULL, sizeof(tRateGroupPwr) * NUM_RF_SUBBANDS ) != VOS_STATUS_SUCCESS)
Madan Mohan Koyyalamudi0b78e152012-11-28 15:46:51 -0800905 goto error;
Jeff Johnson295189b2012-06-20 16:38:30 -0700906 }
907 }
908
Amar Singhal61cbd962013-09-05 13:03:40 -0700909 if (vos_nv_getValidity(VNV_REGULARTORY_DOMAIN_TABLE, &itemIsValid) ==
Jeff Johnson295189b2012-06-20 16:38:30 -0700910 VOS_STATUS_SUCCESS)
911 {
Amar Singhal61cbd962013-09-05 13:03:40 -0700912
Jeff Johnson295189b2012-06-20 16:38:30 -0700913 if (itemIsValid == VOS_TRUE)
914 {
915 if(vos_nv_read( VNV_REGULARTORY_DOMAIN_TABLE,
916 (v_VOID_t *)&pnvEFSTable->halnv.tables.regDomains[0],
917 NULL, sizeof(sRegulatoryDomains) * NUM_REG_DOMAINS ) != VOS_STATUS_SUCCESS)
Madan Mohan Koyyalamudi0b78e152012-11-28 15:46:51 -0800918 goto error;
Jeff Johnson295189b2012-06-20 16:38:30 -0700919 }
920 }
921
Amar Singhal61cbd962013-09-05 13:03:40 -0700922 if (vos_nv_getValidity(VNV_DEFAULT_LOCATION, &itemIsValid) ==
Jeff Johnson295189b2012-06-20 16:38:30 -0700923 VOS_STATUS_SUCCESS)
924 {
925 if (itemIsValid == VOS_TRUE)
926 {
927 if(vos_nv_read( VNV_DEFAULT_LOCATION,
928 (v_VOID_t *)&pnvEFSTable->halnv.tables.defaultCountryTable,
929 NULL, sizeof(sDefaultCountry) ) != VOS_STATUS_SUCCESS)
Madan Mohan Koyyalamudi0b78e152012-11-28 15:46:51 -0800930 goto error;
Jeff Johnson295189b2012-06-20 16:38:30 -0700931 }
932 }
Amar Singhal61cbd962013-09-05 13:03:40 -0700933
934 if (vos_nv_getValidity(VNV_TPC_POWER_TABLE, &itemIsValid) ==
Jeff Johnson295189b2012-06-20 16:38:30 -0700935 VOS_STATUS_SUCCESS)
936 {
937 if (itemIsValid == VOS_TRUE)
938 {
Amar Singhal61cbd962013-09-05 13:03:40 -0700939 if(vos_nv_read( VNV_TPC_POWER_TABLE,
Jeff Johnson295189b2012-06-20 16:38:30 -0700940 (v_VOID_t *)&pnvEFSTable->halnv.tables.plutCharacterized[0],
941 NULL, sizeof(tTpcPowerTable) * NUM_RF_CHANNELS ) != VOS_STATUS_SUCCESS)
Madan Mohan Koyyalamudi0b78e152012-11-28 15:46:51 -0800942 goto error;
Jeff Johnson295189b2012-06-20 16:38:30 -0700943 }
944 }
Amar Singhal61cbd962013-09-05 13:03:40 -0700945
946 if (vos_nv_getValidity(VNV_TPC_PDADC_OFFSETS, &itemIsValid) ==
Jeff Johnson295189b2012-06-20 16:38:30 -0700947 VOS_STATUS_SUCCESS)
948 {
949 if (itemIsValid == VOS_TRUE)
950 {
951 if(vos_nv_read( VNV_TPC_PDADC_OFFSETS,
952 (v_VOID_t *)&pnvEFSTable->halnv.tables.plutPdadcOffset[0],
953 NULL, sizeof(tANI_U16) * NUM_RF_CHANNELS ) != VOS_STATUS_SUCCESS)
Madan Mohan Koyyalamudi0b78e152012-11-28 15:46:51 -0800954 goto error;
Jeff Johnson295189b2012-06-20 16:38:30 -0700955 }
956 }
Amar Singhal61cbd962013-09-05 13:03:40 -0700957 if (vos_nv_getValidity(VNV_RSSI_CHANNEL_OFFSETS, &itemIsValid) ==
Jeff Johnson295189b2012-06-20 16:38:30 -0700958 VOS_STATUS_SUCCESS)
959 {
960 if (itemIsValid == VOS_TRUE)
961 {
962 if(vos_nv_read( VNV_RSSI_CHANNEL_OFFSETS,
963 (v_VOID_t *)&pnvEFSTable->halnv.tables.rssiChanOffsets[0],
964 NULL, sizeof(sRssiChannelOffsets) * 2 ) != VOS_STATUS_SUCCESS)
Madan Mohan Koyyalamudi0b78e152012-11-28 15:46:51 -0800965 goto error;
Jeff Johnson295189b2012-06-20 16:38:30 -0700966 }
967 }
Amar Singhal61cbd962013-09-05 13:03:40 -0700968
969 if (vos_nv_getValidity(VNV_HW_CAL_VALUES, &itemIsValid) ==
Jeff Johnson295189b2012-06-20 16:38:30 -0700970 VOS_STATUS_SUCCESS)
971 {
972 if (itemIsValid == VOS_TRUE)
973 {
Gopichand Nakkalacaf27cd2013-01-04 11:45:31 -0800974 if(vos_nv_read( VNV_HW_CAL_VALUES, (v_VOID_t *)&pnvEFSTable->halnv
975 .tables.hwCalValues, NULL, sizeof(sHwCalValues) ) != VOS_STATUS_SUCCESS)
976 goto error;
977 }
978 }
979
Amar Singhal61cbd962013-09-05 13:03:40 -0700980 if (vos_nv_getValidity(VNV_FW_CONFIG, &itemIsValid) ==
Gopichand Nakkalacaf27cd2013-01-04 11:45:31 -0800981 VOS_STATUS_SUCCESS)
982 {
983 if (itemIsValid == VOS_TRUE)
984 {
985 if(vos_nv_read( VNV_FW_CONFIG, (v_VOID_t *)&pnvEFSTable->halnv
986 .tables.fwConfig, NULL, sizeof(sFwConfig) ) != VOS_STATUS_SUCCESS)
Madan Mohan Koyyalamudi0b78e152012-11-28 15:46:51 -0800987 goto error;
Jeff Johnson295189b2012-06-20 16:38:30 -0700988 }
989 }
990
Amar Singhal61cbd962013-09-05 13:03:40 -0700991 if (vos_nv_getValidity(VNV_ANTENNA_PATH_LOSS, &itemIsValid) ==
Jeff Johnson295189b2012-06-20 16:38:30 -0700992 VOS_STATUS_SUCCESS)
993 {
994 if (itemIsValid == VOS_TRUE)
995 {
996 if(vos_nv_read( VNV_ANTENNA_PATH_LOSS,
Amar Singhal61cbd962013-09-05 13:03:40 -0700997 (v_VOID_t *)&pnvEFSTable->halnv.tables.antennaPathLoss[0], NULL,
Jeff Johnson295189b2012-06-20 16:38:30 -0700998 sizeof(tANI_S16)*NUM_RF_CHANNELS ) != VOS_STATUS_SUCCESS)
Madan Mohan Koyyalamudi0b78e152012-11-28 15:46:51 -0800999 goto error;
Jeff Johnson295189b2012-06-20 16:38:30 -07001000 }
1001 }
Amar Singhal61cbd962013-09-05 13:03:40 -07001002 if (vos_nv_getValidity(VNV_PACKET_TYPE_POWER_LIMITS, &itemIsValid) ==
Jeff Johnson295189b2012-06-20 16:38:30 -07001003 VOS_STATUS_SUCCESS)
1004 {
1005 if (itemIsValid == VOS_TRUE)
1006 {
Amar Singhal61cbd962013-09-05 13:03:40 -07001007 if(vos_nv_read( VNV_PACKET_TYPE_POWER_LIMITS,
1008 (v_VOID_t *)&pnvEFSTable->halnv.tables.pktTypePwrLimits[0], NULL,
Jeff Johnson295189b2012-06-20 16:38:30 -07001009 sizeof(tANI_S16)*NUM_802_11_MODES*NUM_RF_CHANNELS ) != VOS_STATUS_SUCCESS)
Madan Mohan Koyyalamudi0b78e152012-11-28 15:46:51 -08001010 goto error;
Jeff Johnson295189b2012-06-20 16:38:30 -07001011 }
1012 }
1013
Amar Singhal61cbd962013-09-05 13:03:40 -07001014 if (vos_nv_getValidity(VNV_OFDM_CMD_PWR_OFFSET, &itemIsValid) ==
Jeff Johnson295189b2012-06-20 16:38:30 -07001015 VOS_STATUS_SUCCESS)
1016 {
1017 if (itemIsValid == VOS_TRUE)
1018 {
Amar Singhal61cbd962013-09-05 13:03:40 -07001019 if(vos_nv_read( VNV_OFDM_CMD_PWR_OFFSET,
1020 (v_VOID_t *)&pnvEFSTable->halnv.tables.ofdmCmdPwrOffset, NULL,
Jeff Johnson295189b2012-06-20 16:38:30 -07001021 sizeof(sOfdmCmdPwrOffset)) != VOS_STATUS_SUCCESS)
Madan Mohan Koyyalamudi0b78e152012-11-28 15:46:51 -08001022 goto error;
Jeff Johnson295189b2012-06-20 16:38:30 -07001023 }
1024 }
1025
Amar Singhal61cbd962013-09-05 13:03:40 -07001026 if (vos_nv_getValidity(VNV_TX_BB_FILTER_MODE, &itemIsValid) ==
Jeff Johnson295189b2012-06-20 16:38:30 -07001027 VOS_STATUS_SUCCESS)
1028 {
1029 if (itemIsValid == VOS_TRUE)
1030 {
Amar Singhal61cbd962013-09-05 13:03:40 -07001031 if(vos_nv_read(VNV_TX_BB_FILTER_MODE,
1032 (v_VOID_t *)&pnvEFSTable->halnv.tables.txbbFilterMode, NULL,
Jeff Johnson295189b2012-06-20 16:38:30 -07001033 sizeof(sTxBbFilterMode)) != VOS_STATUS_SUCCESS)
Madan Mohan Koyyalamudi0b78e152012-11-28 15:46:51 -08001034 goto error;
Jeff Johnson295189b2012-06-20 16:38:30 -07001035 }
1036 }
Amar Singhal61cbd962013-09-05 13:03:40 -07001037 if (vos_nv_getValidity(VNV_TABLE_VIRTUAL_RATE, &itemIsValid) ==
Jeff Johnson295189b2012-06-20 16:38:30 -07001038 VOS_STATUS_SUCCESS)
1039 {
1040 if (itemIsValid == VOS_TRUE)
1041 {
Amar Singhal61cbd962013-09-05 13:03:40 -07001042 if(vos_nv_read(VNV_TABLE_VIRTUAL_RATE,
1043 (v_VOID_t *)&pnvEFSTable->halnv.tables.pwrOptimum_virtualRate, NULL,
Jeff Johnson295189b2012-06-20 16:38:30 -07001044 sizeof(gnvEFSTable->halnv.tables.pwrOptimum_virtualRate)) != VOS_STATUS_SUCCESS)
Madan Mohan Koyyalamudi0b78e152012-11-28 15:46:51 -08001045 goto error;
Jeff Johnson295189b2012-06-20 16:38:30 -07001046 }
1047 }
1048 }
1049
1050 return VOS_STATUS_SUCCESS;
Madan Mohan Koyyalamudi0b78e152012-11-28 15:46:51 -08001051error:
1052 vos_mem_free(pnvEFSTable);
Prasanna Kumar0833aa82013-04-11 20:05:21 -07001053 vos_mem_free(pEncodedBuf);
Madan Mohan Koyyalamudi0b78e152012-11-28 15:46:51 -08001054 return eHAL_STATUS_FAILURE ;
Jeff Johnson295189b2012-06-20 16:38:30 -07001055}
1056
1057VOS_STATUS vos_nv_close(void)
1058{
1059 VOS_STATUS status = VOS_STATUS_SUCCESS;
1060 v_CONTEXT_t pVosContext= NULL;
1061 /*Get the global context */
1062 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
1063 status = hdd_release_firmware(WLAN_NV_FILE, ((VosContextType*)(pVosContext))->pHDDContext);
1064 if ( !VOS_IS_STATUS_SUCCESS( status ))
1065 {
1066 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
1067 "%s : vos_open failed\n",__func__);
1068 return VOS_STATUS_E_FAILURE;
1069 }
1070 vos_mem_free(pnvEFSTable);
Prasanna Kumar0833aa82013-04-11 20:05:21 -07001071 vos_mem_free(pEncodedBuf);
1072 vos_mem_free(pDictFile);
1073
Jeff Johnson295189b2012-06-20 16:38:30 -07001074 gnvEFSTable=NULL;
1075 return VOS_STATUS_SUCCESS;
1076}
Jeff Johnson295189b2012-06-20 16:38:30 -07001077
Jeff Johnson295189b2012-06-20 16:38:30 -07001078/**------------------------------------------------------------------------
1079 \brief vos_nv_getSupportedCountryCode() - get the list of supported
1080 country codes
1081 The \a vos_nv_getSupportedCountryCode() encodes the list of supported
1082 country codes with paddings in the provided buffer
1083 \param pBuffer - pointer to buffer where supported country codes
1084 and paddings are encoded; this may be set to NULL
1085 if user wishes to query the required buffer size to
1086 get the country code list
1087 \param pBufferSize - this is the provided buffer size on input;
1088 this is the required or consumed buffer size on output
1089 \return VOS_STATUS_SUCCESS - country codes are successfully encoded
1090 VOS_STATUS_E_NOMEM - country codes are not encoded because either
1091 the buffer is NULL or buffer size is
1092 sufficient
1093 \sa
1094 -------------------------------------------------------------------------*/
1095VOS_STATUS vos_nv_getSupportedCountryCode( v_BYTE_t *pBuffer, v_SIZE_t *pBufferSize,
1096 v_SIZE_t paddingSize )
1097{
1098 v_SIZE_t providedBufferSize = *pBufferSize;
1099 int i;
1100 // pBufferSize now points to the required buffer size
1101 *pBufferSize = countryInfoTable.countryCount * (VOS_COUNTRY_CODE_LEN + paddingSize );
1102 if ( NULL == pBuffer || providedBufferSize < *pBufferSize )
1103 {
1104 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_INFO,
Amar Singhal9a65a6a2013-10-08 18:37:44 -07001105 ("Insufficient memory for country code list\n"));
Jeff Johnson295189b2012-06-20 16:38:30 -07001106 return VOS_STATUS_E_NOMEM;
1107 }
1108 for (i = 0; i < countryInfoTable.countryCount; i++)
1109 {
1110 memcpy( pBuffer, countryInfoTable.countryInfo[i].countryCode, VOS_COUNTRY_CODE_LEN );
1111 pBuffer += (VOS_COUNTRY_CODE_LEN + paddingSize );
1112 }
1113 return VOS_STATUS_SUCCESS;
1114}
1115/**------------------------------------------------------------------------
1116 \brief vos_nv_readTxAntennaCount() - return number of TX antenna
1117 \param pTxAntennaCount - antenna count
1118 \return status of the NV read operation
1119 \sa
1120 -------------------------------------------------------------------------*/
1121VOS_STATUS vos_nv_readTxAntennaCount( v_U8_t *pTxAntennaCount )
1122{
1123 sNvFields fieldImage;
1124 VOS_STATUS status;
1125 status = vos_nv_read( VNV_FIELD_IMAGE, &fieldImage, NULL,
1126 sizeof(fieldImage) );
1127 if (VOS_STATUS_SUCCESS == status)
1128 {
1129 *pTxAntennaCount = fieldImage.numOfTxChains;
1130 }
1131 return status;
1132}
1133/**------------------------------------------------------------------------
1134 \brief vos_nv_readRxAntennaCount() - return number of RX antenna
1135 \param pRxAntennaCount - antenna count
1136 \return status of the NV read operation
1137 \sa
1138 -------------------------------------------------------------------------*/
1139VOS_STATUS vos_nv_readRxAntennaCount( v_U8_t *pRxAntennaCount )
1140{
1141 sNvFields fieldImage;
1142 VOS_STATUS status;
1143 status = vos_nv_read( VNV_FIELD_IMAGE, &fieldImage, NULL,
1144 sizeof(fieldImage) );
1145 if (VOS_STATUS_SUCCESS == status)
1146 {
1147 *pRxAntennaCount = fieldImage.numOfRxChains;
1148 }
1149 return status;
1150}
1151
1152/**------------------------------------------------------------------------
1153 \brief vos_nv_readMacAddress() - return the MAC address
1154 \param pMacAddress - MAC address
1155 \return status of the NV read operation
1156 \sa
1157 -------------------------------------------------------------------------*/
1158VOS_STATUS vos_nv_readMacAddress( v_MAC_ADDRESS_t pMacAddress )
1159{
1160 sNvFields fieldImage;
1161 VOS_STATUS status;
1162 status = vos_nv_read( VNV_FIELD_IMAGE, &fieldImage, NULL,
1163 sizeof(fieldImage) );
1164 if (VOS_STATUS_SUCCESS == status)
1165 {
1166 memcpy( pMacAddress, fieldImage.macAddr, VOS_MAC_ADDRESS_LEN );
1167 }
1168 else
1169 {
1170 //This part of the code can be removed when NV is programmed
1171 const v_U8_t macAddr[VOS_MAC_ADDRESS_LEN] = VOS_HARD_CODED_MAC;
1172 memcpy( pMacAddress, macAddr, VOS_MAC_ADDRESS_LEN );
1173 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_WARN,
1174 " fail to get MAC address from NV, hardcoded to %02X-%02X-%02X-%02X-%02X%02X",
1175 macAddr[0], macAddr[1], macAddr[2], macAddr[3], macAddr[4], macAddr[5]);
1176 status = VOS_STATUS_SUCCESS;
1177 }
1178 return status;
1179}
1180
1181/**------------------------------------------------------------------------
1182
1183 \brief vos_nv_readMultiMacAddress() - return the Multiple MAC addresses
1184
1185 \param pMacAddress - MAC address
1186 \param macCount - Count of valid MAC addresses to get from NV field
1187
1188 \return status of the NV read operation
1189
1190 \sa
1191
1192 -------------------------------------------------------------------------*/
1193VOS_STATUS vos_nv_readMultiMacAddress( v_U8_t *pMacAddress,
1194 v_U8_t macCount )
1195{
1196 sNvFields fieldImage;
1197 VOS_STATUS status;
1198 v_U8_t countLoop;
1199 v_U8_t *pNVMacAddress;
1200
1201 if((0 == macCount) || (VOS_MAX_CONCURRENCY_PERSONA < macCount) ||
1202 (NULL == pMacAddress))
1203 {
1204 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
Gopichand Nakkalae8997bd2013-04-10 11:36:29 +05301205 " Invalid Parameter from NV Client macCount %d, pMacAddress %p",
Jeff Johnson295189b2012-06-20 16:38:30 -07001206 macCount, pMacAddress);
1207 }
1208
1209 status = vos_nv_read( VNV_FIELD_IMAGE, &fieldImage, NULL,
1210 sizeof(fieldImage) );
1211 if (VOS_STATUS_SUCCESS == status)
1212 {
1213 pNVMacAddress = fieldImage.macAddr;
1214 for(countLoop = 0; countLoop < macCount; countLoop++)
1215 {
1216 vos_mem_copy(pMacAddress + (countLoop * VOS_MAC_ADDRESS_LEN),
1217 pNVMacAddress + (countLoop * VOS_MAC_ADDRESS_LEN),
1218 VOS_MAC_ADDRESS_LEN);
1219 }
1220 }
1221 else
1222 {
1223 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
1224 "vos_nv_readMultiMacAddress Get NV Field Fail");
1225 }
1226
1227 return status;
1228}
1229
1230/**------------------------------------------------------------------------
1231 \brief vos_nv_setValidity() - set the validity of an NV item.
1232 The \a vos_nv_setValidity() validates and invalidates an NV item. The
1233 validity information is stored in NV memory.
1234 One would get the VOS_STATUS_E_EXISTS error when reading an invalid item.
1235 An item becomes valid when one has written to it successfully.
1236 \param type - NV item type
1237 \param itemIsValid - boolean value indicating the item's validity
1238 \return VOS_STATUS_SUCCESS - validity is set successfully
1239 VOS_STATUS_E_INVAL - one of the parameters is invalid
1240 VOS_STATUS_E_FAILURE - unknown error
1241 \sa
1242 -------------------------------------------------------------------------*/
Jeff Johnson295189b2012-06-20 16:38:30 -07001243
1244VOS_STATUS vos_nv_setValidity( VNV_TYPE type, v_BOOL_t itemIsValid )
1245{
1246 v_U32_t lastNvValidityBitmap;
1247 v_U32_t newNvValidityBitmap;
1248 VOS_STATUS status = VOS_STATUS_SUCCESS;
Jeff Johnson43971f52012-07-17 12:26:56 -07001249
Jeff Johnson295189b2012-06-20 16:38:30 -07001250 // check if the current NV type is valid
Jeff Johnson43971f52012-07-17 12:26:56 -07001251 if (VNV_TYPE_COUNT <= type)
Jeff Johnson295189b2012-06-20 16:38:30 -07001252 {
1253 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001254 ("%s: invalid type=%d"), __func__, type );
Jeff Johnson295189b2012-06-20 16:38:30 -07001255 return VOS_STATUS_E_INVAL;
1256 }
1257 // read the validity bitmap
1258 lastNvValidityBitmap = gnvEFSTable->nvValidityBitmap;
1259 // modify the validity bitmap
1260 if (itemIsValid)
1261 {
1262 newNvValidityBitmap = lastNvValidityBitmap | (1 << type);
1263 // commit to NV store if bitmap has been modified
1264 if (newNvValidityBitmap != lastNvValidityBitmap)
1265 {
1266 gnvEFSTable->nvValidityBitmap = newNvValidityBitmap;
1267 }
1268 }
1269 else
1270 {
1271 newNvValidityBitmap = lastNvValidityBitmap & (~(1 << type));
1272 if (newNvValidityBitmap != lastNvValidityBitmap)
1273 {
1274 gnvEFSTable->nvValidityBitmap = newNvValidityBitmap;
1275 status = wlan_write_to_efs((v_U8_t*)gnvEFSTable,sizeof(nvEFSTable_t));
1276 if (! VOS_IS_STATUS_SUCCESS(status)) {
Amar Singhal9a65a6a2013-10-08 18:37:44 -07001277 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, ("vos_nv_write_to_efs failed!!!\r\n"));
Jeff Johnson295189b2012-06-20 16:38:30 -07001278 status = VOS_STATUS_E_FAULT;
1279 }
1280 }
1281 }
1282
1283 return status;
1284}
Jeff Johnson295189b2012-06-20 16:38:30 -07001285/**------------------------------------------------------------------------
1286 \brief vos_nv_getValidity() - get the validity of an NV item.
1287 The \a vos_nv_getValidity() indicates if an NV item is valid. The
1288 validity information is stored in NV memory.
1289 One would get the VOS_STATUS_E_EXISTS error when reading an invalid item.
1290 An item becomes valid when one has written to it successfully.
1291 \param type - NV item type
1292 \param pItemIsValid- pointer to the boolean value indicating the item's
1293 validity
1294 \return VOS_STATUS_SUCCESS - validity is determined successfully
1295 VOS_STATUS_E_INVAL - one of the parameters is invalid
1296 VOS_STATUS_E_FAILURE - unknown error
1297 \sa
1298 -------------------------------------------------------------------------*/
1299VOS_STATUS vos_nv_getValidity( VNV_TYPE type, v_BOOL_t *pItemIsValid )
1300{
1301 v_U32_t nvValidityBitmap = gnvEFSTable->nvValidityBitmap;
1302 // check if the current NV type is valid
Jeff Johnson43971f52012-07-17 12:26:56 -07001303 if (VNV_TYPE_COUNT <= type)
Jeff Johnson295189b2012-06-20 16:38:30 -07001304 {
1305 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001306 ("%s: invalid type=%d"), __func__, type );
Jeff Johnson295189b2012-06-20 16:38:30 -07001307 return VOS_STATUS_E_INVAL;
1308 }
1309 *pItemIsValid = (v_BOOL_t)((nvValidityBitmap >> type) & 1);
1310 return VOS_STATUS_SUCCESS;
1311}
1312/**------------------------------------------------------------------------
1313 \brief vos_nv_read() - read a NV item to an output buffer
1314 The \a vos_nv_read() reads a NV item to an output buffer. If the item is
1315 an array, this function would read the entire array. One would get a
1316 VOS_STATUS_E_EXISTS error when reading an invalid item.
1317 For error conditions of VOS_STATUS_E_EXISTS and VOS_STATUS_E_FAILURE,
1318 if a default buffer is provided (with a non-NULL value),
1319 the default buffer content is copied to the output buffer.
1320 \param type - NV item type
1321 \param outputBuffer - output buffer
1322 \param defaultBuffer - default buffer
1323 \param bufferSize - output buffer size
1324 \return VOS_STATUS_SUCCESS - NV item is read successfully
1325 VOS_STATUS_E_INVAL - one of the parameters is invalid
1326 VOS_STATUS_E_FAULT - defaultBuffer point is NULL
1327 VOS_STATUS_E_EXISTS - NV type is unsupported
1328 VOS_STATUS_E_FAILURE - unknown error
1329 \sa
1330 -------------------------------------------------------------------------*/
1331VOS_STATUS vos_nv_read( VNV_TYPE type, v_VOID_t *outputVoidBuffer,
1332 v_VOID_t *defaultBuffer, v_SIZE_t bufferSize )
1333{
1334 VOS_STATUS status = VOS_STATUS_SUCCESS;
1335 v_SIZE_t itemSize;
1336 v_BOOL_t itemIsValid = VOS_TRUE;
1337
Amar Singhal9a65a6a2013-10-08 18:37:44 -07001338 // sanity check
Jeff Johnson43971f52012-07-17 12:26:56 -07001339 if (VNV_TYPE_COUNT <= type)
Jeff Johnson295189b2012-06-20 16:38:30 -07001340 {
1341 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001342 ("%s: invalid type=%d"), __func__, type );
Jeff Johnson295189b2012-06-20 16:38:30 -07001343 return VOS_STATUS_E_INVAL;
1344 }
1345 if (NULL == outputVoidBuffer)
1346 {
1347 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
Amar Singhal9a65a6a2013-10-08 18:37:44 -07001348 ("Buffer provided is NULL\r\n") );
Jeff Johnson295189b2012-06-20 16:38:30 -07001349 return VOS_STATUS_E_FAULT;
1350 }
1351 if (0 == bufferSize)
1352 {
1353 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
Amar Singhal9a65a6a2013-10-08 18:37:44 -07001354 ("NV type=%d is invalid\r\n"), type );
Jeff Johnson295189b2012-06-20 16:38:30 -07001355 return VOS_STATUS_E_INVAL;
1356 }
1357 // check if the NV item has valid data
1358 status = vos_nv_getValidity( type, &itemIsValid );
1359 if (!itemIsValid)
1360 {
1361 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_WARN,
Amar Singhal9a65a6a2013-10-08 18:37:44 -07001362 "NV type=%d does not have valid data\r\n", type );
Jeff Johnson295189b2012-06-20 16:38:30 -07001363 return VOS_STATUS_E_EMPTY;
1364 }
1365 switch(type)
1366 {
1367 case VNV_FIELD_IMAGE:
1368 itemSize = sizeof(gnvEFSTable->halnv.fields);
1369 if(bufferSize != itemSize) {
1370 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
Amar Singhal9a65a6a2013-10-08 18:37:44 -07001371 ("type = %d buffer size=%d is less than data size=%d\r\n"),type, bufferSize,
Jeff Johnson295189b2012-06-20 16:38:30 -07001372 itemSize);
1373 status = VOS_STATUS_E_INVAL;
1374 }
1375 else {
1376 memcpy(outputVoidBuffer,&gnvEFSTable->halnv.fields,bufferSize);
1377 }
1378 break;
1379 case VNV_RATE_TO_POWER_TABLE:
1380 itemSize = sizeof(gnvEFSTable->halnv.tables.pwrOptimum);
1381 if(bufferSize != itemSize) {
1382 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
Amar Singhal9a65a6a2013-10-08 18:37:44 -07001383 ("type = %d buffer size=%d is less than data size=%d\r\n"),type, bufferSize,
Jeff Johnson295189b2012-06-20 16:38:30 -07001384 itemSize);
1385 status = VOS_STATUS_E_INVAL;
1386 }
1387 else {
1388 memcpy(outputVoidBuffer,&gnvEFSTable->halnv.tables.pwrOptimum[0],bufferSize);
1389 }
1390 break;
1391 case VNV_REGULARTORY_DOMAIN_TABLE:
1392 itemSize = sizeof(gnvEFSTable->halnv.tables.regDomains);
1393 if(bufferSize != itemSize) {
1394 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
Amar Singhal9a65a6a2013-10-08 18:37:44 -07001395 ("type = %d buffer size=%d is less than data size=%d\r\n"),type, bufferSize,
Jeff Johnson295189b2012-06-20 16:38:30 -07001396 itemSize);
1397 status = VOS_STATUS_E_INVAL;
1398 }
1399 else {
1400 memcpy(outputVoidBuffer,&gnvEFSTable->halnv.tables.regDomains[0],bufferSize);
1401 }
1402 break;
1403 case VNV_DEFAULT_LOCATION:
1404 itemSize = sizeof(gnvEFSTable->halnv.tables.defaultCountryTable);
1405 if(bufferSize != itemSize) {
1406 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
Amar Singhal9a65a6a2013-10-08 18:37:44 -07001407 ("type = %d buffer size=%d is less than data size=%d\r\n"),type, bufferSize,
Jeff Johnson295189b2012-06-20 16:38:30 -07001408 itemSize);
1409 status = VOS_STATUS_E_INVAL;
1410 }
1411 else {
1412 memcpy(outputVoidBuffer,&gnvEFSTable->halnv.tables.defaultCountryTable,bufferSize);
1413 }
1414 break;
1415 case VNV_TPC_POWER_TABLE:
1416 itemSize = sizeof(gnvEFSTable->halnv.tables.plutCharacterized);
1417 if(bufferSize != itemSize) {
1418 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
Amar Singhal9a65a6a2013-10-08 18:37:44 -07001419 ("type = %d buffer size=%d is less than data size=%d\r\n"),type, bufferSize,
Jeff Johnson295189b2012-06-20 16:38:30 -07001420 itemSize);
1421 status = VOS_STATUS_E_INVAL;
1422 }
1423 else {
1424 memcpy(outputVoidBuffer,&gnvEFSTable->halnv.tables.plutCharacterized[0],bufferSize);
1425 }
1426 break;
1427 case VNV_TPC_PDADC_OFFSETS:
1428 itemSize = sizeof(gnvEFSTable->halnv.tables.plutPdadcOffset);
1429 if(bufferSize != itemSize) {
1430 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
Amar Singhal9a65a6a2013-10-08 18:37:44 -07001431 ("type = %d buffer size=%d is less than data size=%d\r\n"),type, bufferSize,
Jeff Johnson295189b2012-06-20 16:38:30 -07001432 itemSize);
1433 status = VOS_STATUS_E_INVAL;
1434 }
1435 else {
1436 memcpy(outputVoidBuffer,&gnvEFSTable->halnv.tables.plutPdadcOffset[0],bufferSize);
1437 }
1438 break;
1439 case VNV_RSSI_CHANNEL_OFFSETS:
1440
1441 itemSize = sizeof(gnvEFSTable->halnv.tables.rssiChanOffsets);
1442
1443 if(bufferSize != itemSize) {
1444
1445 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
Amar Singhal9a65a6a2013-10-08 18:37:44 -07001446 ("type = %d buffer size=%d is less than data size=%d\r\n"),type, bufferSize,
Jeff Johnson295189b2012-06-20 16:38:30 -07001447 itemSize);
1448 status = VOS_STATUS_E_INVAL;
1449 }
1450 else {
1451 memcpy(outputVoidBuffer,&gnvEFSTable->halnv.tables.rssiChanOffsets[0],bufferSize);
1452 }
1453 break;
Gopichand Nakkalacaf27cd2013-01-04 11:45:31 -08001454 case VNV_HW_CAL_VALUES:
Jeff Johnson295189b2012-06-20 16:38:30 -07001455
Gopichand Nakkalacaf27cd2013-01-04 11:45:31 -08001456 itemSize = sizeof(gnvEFSTable->halnv.tables.hwCalValues);
Jeff Johnson295189b2012-06-20 16:38:30 -07001457
1458 if(bufferSize != itemSize) {
1459
1460 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
Amar Singhal9a65a6a2013-10-08 18:37:44 -07001461 ("type = %d buffer size=%d is less than data size=%d\r\n"),type, bufferSize,
Jeff Johnson295189b2012-06-20 16:38:30 -07001462 itemSize);
1463 status = VOS_STATUS_E_INVAL;
1464 }
1465 else {
Gopichand Nakkalacaf27cd2013-01-04 11:45:31 -08001466 memcpy(outputVoidBuffer,&gnvEFSTable->halnv.tables.hwCalValues,bufferSize);
1467 }
1468 break;
1469 case VNV_FW_CONFIG:
Amar Singhal61cbd962013-09-05 13:03:40 -07001470
Gopichand Nakkalacaf27cd2013-01-04 11:45:31 -08001471 itemSize = sizeof(gnvEFSTable->halnv.tables.fwConfig);
Amar Singhal61cbd962013-09-05 13:03:40 -07001472
Gopichand Nakkalacaf27cd2013-01-04 11:45:31 -08001473 if(bufferSize != itemSize) {
Amar Singhal61cbd962013-09-05 13:03:40 -07001474
Gopichand Nakkalacaf27cd2013-01-04 11:45:31 -08001475 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
Amar Singhal9a65a6a2013-10-08 18:37:44 -07001476 ("type = %d buffer size=%d is less than data size=%d\r\n"),type, bufferSize,
Gopichand Nakkalacaf27cd2013-01-04 11:45:31 -08001477 itemSize);
1478 status = VOS_STATUS_E_INVAL;
1479 }
1480 else {
1481 memcpy(outputVoidBuffer,&gnvEFSTable->halnv.tables.fwConfig,bufferSize);
Jeff Johnson295189b2012-06-20 16:38:30 -07001482 }
1483 break;
1484 case VNV_ANTENNA_PATH_LOSS:
1485 itemSize = sizeof(gnvEFSTable->halnv.tables.antennaPathLoss);
1486 if(bufferSize != itemSize) {
1487 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
Amar Singhal9a65a6a2013-10-08 18:37:44 -07001488 ("type = %d buffer size=%d is less than data size=%d\r\n"),type, bufferSize,
Jeff Johnson295189b2012-06-20 16:38:30 -07001489 itemSize);
1490 status = VOS_STATUS_E_INVAL;
1491 }
1492 else {
1493 memcpy(outputVoidBuffer,&gnvEFSTable->halnv.tables.antennaPathLoss[0],bufferSize);
1494 }
1495 break;
1496 case VNV_PACKET_TYPE_POWER_LIMITS:
1497 itemSize = sizeof(gnvEFSTable->halnv.tables.pktTypePwrLimits);
1498 if(bufferSize != itemSize) {
1499 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
Amar Singhal9a65a6a2013-10-08 18:37:44 -07001500 ("type = %d buffer size=%d is less than data size=%d\r\n"),type, bufferSize,
Jeff Johnson295189b2012-06-20 16:38:30 -07001501 itemSize);
1502 status = VOS_STATUS_E_INVAL;
1503 }
1504 else {
Tushnim Bhattacharyya95341d32013-03-20 20:15:03 -07001505 memcpy(outputVoidBuffer,gnvEFSTable->halnv.tables.pktTypePwrLimits,bufferSize);
Jeff Johnson295189b2012-06-20 16:38:30 -07001506 }
1507 break;
1508 case VNV_OFDM_CMD_PWR_OFFSET:
1509 itemSize = sizeof(gnvEFSTable->halnv.tables.ofdmCmdPwrOffset);
1510 if(bufferSize != itemSize) {
1511 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
Amar Singhal9a65a6a2013-10-08 18:37:44 -07001512 ("type = %d buffer size=%d is less than data size=%d\r\n"),type, bufferSize,
Jeff Johnson295189b2012-06-20 16:38:30 -07001513 itemSize);
1514 status = VOS_STATUS_E_INVAL;
1515 }
1516 else {
1517 memcpy(outputVoidBuffer,&gnvEFSTable->halnv.tables.ofdmCmdPwrOffset,bufferSize);
1518 }
1519 break;
1520 case VNV_TX_BB_FILTER_MODE:
1521 itemSize = sizeof(gnvEFSTable->halnv.tables.txbbFilterMode);
1522 if(bufferSize != itemSize) {
1523 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
Amar Singhal9a65a6a2013-10-08 18:37:44 -07001524 ("type = %d buffer size=%d is less than data size=%d\r\n"),type, bufferSize,
Jeff Johnson295189b2012-06-20 16:38:30 -07001525 itemSize);
1526 status = VOS_STATUS_E_INVAL;
1527 }
1528 else {
1529 memcpy(outputVoidBuffer,&gnvEFSTable->halnv.tables.txbbFilterMode,bufferSize);
1530 }
1531 break;
1532
Jeff Johnson295189b2012-06-20 16:38:30 -07001533
1534 case VNV_TABLE_VIRTUAL_RATE:
1535 itemSize = sizeof(gnvEFSTable->halnv.tables.pwrOptimum_virtualRate);
1536 if(bufferSize != itemSize) {
1537 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
Amar Singhal9a65a6a2013-10-08 18:37:44 -07001538 ("type = %d buffer size=%d is less than data size=%d\r\n"),type, bufferSize,
Jeff Johnson295189b2012-06-20 16:38:30 -07001539 itemSize);
1540 status = VOS_STATUS_E_INVAL;
1541 }
1542 else {
1543 memcpy(outputVoidBuffer,&gnvEFSTable->halnv.tables.pwrOptimum_virtualRate,bufferSize);
1544 }
1545 break;
1546
1547 default:
1548 break;
1549 }
1550 return status;
1551}
Jeff Johnson295189b2012-06-20 16:38:30 -07001552
1553/**------------------------------------------------------------------------
1554 \brief vos_nv_write() - write to a NV item from an input buffer
1555 The \a vos_nv_write() writes to a NV item from an input buffer. This would
1556 validate the NV item if the write operation is successful.
1557 \param type - NV item type
1558 \param inputBuffer - input buffer
1559 \param inputBufferSize - input buffer size
1560 \return VOS_STATUS_SUCCESS - NV item is read successfully
1561 VOS_STATUS_E_INVAL - one of the parameters is invalid
1562 VOS_STATUS_E_FAULT - outputBuffer pointer is NULL
1563 VOS_STATUS_E_EXISTS - NV type is unsupported
1564 VOS_STATUS_E_FAILURE - unknown error
1565 \sa
1566 -------------------------------------------------------------------------*/
1567VOS_STATUS vos_nv_write( VNV_TYPE type, v_VOID_t *inputVoidBuffer,
1568 v_SIZE_t bufferSize )
1569{
1570 VOS_STATUS status = VOS_STATUS_SUCCESS;
1571 v_SIZE_t itemSize;
Jeff Johnson43971f52012-07-17 12:26:56 -07001572
Amar Singhal9a65a6a2013-10-08 18:37:44 -07001573 // sanity check
Jeff Johnson43971f52012-07-17 12:26:56 -07001574 if (VNV_TYPE_COUNT <= type)
Jeff Johnson295189b2012-06-20 16:38:30 -07001575 {
1576 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001577 ("%s: invalid type=%d"), __func__, type );
Jeff Johnson295189b2012-06-20 16:38:30 -07001578 return VOS_STATUS_E_INVAL;
1579 }
1580 if (NULL == inputVoidBuffer)
1581 {
1582 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
Amar Singhal9a65a6a2013-10-08 18:37:44 -07001583 ("Buffer provided is NULL\r\n") );
Jeff Johnson295189b2012-06-20 16:38:30 -07001584 return VOS_STATUS_E_FAULT;
1585 }
1586 if (0 == bufferSize)
1587 {
1588 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
Amar Singhal9a65a6a2013-10-08 18:37:44 -07001589 ("NV type=%d is invalid\r\n"), type );
Jeff Johnson295189b2012-06-20 16:38:30 -07001590 return VOS_STATUS_E_INVAL;
1591 }
1592 switch(type)
1593 {
1594 case VNV_FIELD_IMAGE:
1595 itemSize = sizeof(gnvEFSTable->halnv.fields);
1596 if(bufferSize != itemSize) {
1597 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
Amar Singhal9a65a6a2013-10-08 18:37:44 -07001598 ("type = %d buffer size=%d is less than data size=%d\r\n"),type, bufferSize,
Jeff Johnson295189b2012-06-20 16:38:30 -07001599 itemSize);
1600 status = VOS_STATUS_E_INVAL;
1601 }
1602 else {
1603 memcpy(&gnvEFSTable->halnv.fields,inputVoidBuffer,bufferSize);
1604 }
1605 break;
1606 case VNV_RATE_TO_POWER_TABLE:
1607 itemSize = sizeof(gnvEFSTable->halnv.tables.pwrOptimum);
1608 if(bufferSize != itemSize) {
1609 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
Amar Singhal9a65a6a2013-10-08 18:37:44 -07001610 ("type = %d buffer size=%d is less than data size=%d\r\n"),type, bufferSize,
Jeff Johnson295189b2012-06-20 16:38:30 -07001611 itemSize);
1612 status = VOS_STATUS_E_INVAL;
1613 }
1614 else {
1615 memcpy(&gnvEFSTable->halnv.tables.pwrOptimum[0],inputVoidBuffer,bufferSize);
1616 }
1617 break;
1618 case VNV_REGULARTORY_DOMAIN_TABLE:
1619 itemSize = sizeof(gnvEFSTable->halnv.tables.regDomains);
1620 if(bufferSize != itemSize) {
1621 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
Amar Singhal9a65a6a2013-10-08 18:37:44 -07001622 ("type = %d buffer size=%d is less than data size=%d\r\n"),type, bufferSize,
Jeff Johnson295189b2012-06-20 16:38:30 -07001623 itemSize);
1624 status = VOS_STATUS_E_INVAL;
1625 }
1626 else {
1627 memcpy(&gnvEFSTable->halnv.tables.regDomains[0],inputVoidBuffer,bufferSize);
1628 }
1629 break;
1630 case VNV_DEFAULT_LOCATION:
1631 itemSize = sizeof(gnvEFSTable->halnv.tables.defaultCountryTable);
1632 if(bufferSize != itemSize) {
1633 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
Amar Singhal9a65a6a2013-10-08 18:37:44 -07001634 ("type = %d buffer size=%d is less than data size=%d\r\n"),type, bufferSize,
Jeff Johnson295189b2012-06-20 16:38:30 -07001635 itemSize);
1636 status = VOS_STATUS_E_INVAL;
1637 }
1638 else {
1639 memcpy(&gnvEFSTable->halnv.tables.defaultCountryTable,inputVoidBuffer,bufferSize);
1640 }
1641 break;
1642 case VNV_TPC_POWER_TABLE:
1643 itemSize = sizeof(gnvEFSTable->halnv.tables.plutCharacterized);
1644 if(bufferSize != itemSize) {
1645 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
Amar Singhal9a65a6a2013-10-08 18:37:44 -07001646 ("type = %d buffer size=%d is less than data size=%d\r\n"),type, bufferSize,
Jeff Johnson295189b2012-06-20 16:38:30 -07001647 itemSize);
1648 status = VOS_STATUS_E_INVAL;
1649 }
1650 else {
1651 memcpy(&gnvEFSTable->halnv.tables.plutCharacterized[0],inputVoidBuffer,bufferSize);
1652 }
1653 break;
1654 case VNV_TPC_PDADC_OFFSETS:
1655 itemSize = sizeof(gnvEFSTable->halnv.tables.plutPdadcOffset);
1656 if(bufferSize != itemSize) {
1657 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
Amar Singhal9a65a6a2013-10-08 18:37:44 -07001658 ("type = %d buffer size=%d is less than data size=%d\r\n"),type, bufferSize,
Jeff Johnson295189b2012-06-20 16:38:30 -07001659 itemSize);
1660 status = VOS_STATUS_E_INVAL;
1661 }
1662 else {
1663 memcpy(&gnvEFSTable->halnv.tables.plutPdadcOffset[0],inputVoidBuffer,bufferSize);
1664 }
1665 break;
1666 case VNV_RSSI_CHANNEL_OFFSETS:
1667
1668 itemSize = sizeof(gnvEFSTable->halnv.tables.rssiChanOffsets);
1669
1670 if(bufferSize != itemSize) {
1671
1672 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
Amar Singhal9a65a6a2013-10-08 18:37:44 -07001673 ("type = %d buffer size=%d is less than data size=%d\r\n"),type, bufferSize,
Jeff Johnson295189b2012-06-20 16:38:30 -07001674 itemSize);
1675 status = VOS_STATUS_E_INVAL;
1676 }
1677 else {
1678 memcpy(&gnvEFSTable->halnv.tables.rssiChanOffsets[0],inputVoidBuffer,bufferSize);
1679 }
1680 break;
Gopichand Nakkalacaf27cd2013-01-04 11:45:31 -08001681 case VNV_HW_CAL_VALUES:
Jeff Johnson295189b2012-06-20 16:38:30 -07001682
Gopichand Nakkalacaf27cd2013-01-04 11:45:31 -08001683 itemSize = sizeof(gnvEFSTable->halnv.tables.hwCalValues);
Jeff Johnson295189b2012-06-20 16:38:30 -07001684
1685 if(bufferSize != itemSize) {
1686
1687 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
Amar Singhal9a65a6a2013-10-08 18:37:44 -07001688 ("type = %d buffer size=%d is less than data size=%d\r\n"),type, bufferSize,
Jeff Johnson295189b2012-06-20 16:38:30 -07001689 itemSize);
1690 status = VOS_STATUS_E_INVAL;
1691 }
1692 else {
Gopichand Nakkalacaf27cd2013-01-04 11:45:31 -08001693 memcpy(&gnvEFSTable->halnv.tables.hwCalValues,inputVoidBuffer,bufferSize);
Jeff Johnson295189b2012-06-20 16:38:30 -07001694 }
1695 break;
Gopichand Nakkalacaf27cd2013-01-04 11:45:31 -08001696 case VNV_FW_CONFIG:
Amar Singhal61cbd962013-09-05 13:03:40 -07001697
Gopichand Nakkalacaf27cd2013-01-04 11:45:31 -08001698 itemSize = sizeof(gnvEFSTable->halnv.tables.fwConfig);
Amar Singhal61cbd962013-09-05 13:03:40 -07001699
Gopichand Nakkalacaf27cd2013-01-04 11:45:31 -08001700 if(bufferSize != itemSize) {
Amar Singhal61cbd962013-09-05 13:03:40 -07001701
Gopichand Nakkalacaf27cd2013-01-04 11:45:31 -08001702 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
Amar Singhal9a65a6a2013-10-08 18:37:44 -07001703 ("type = %d buffer size=%d is less than data size=%d\r\n"),type, bufferSize,
Gopichand Nakkalacaf27cd2013-01-04 11:45:31 -08001704 itemSize);
1705 status = VOS_STATUS_E_INVAL;
1706 }
1707 else {
1708 memcpy(&gnvEFSTable->halnv.tables.fwConfig,inputVoidBuffer,bufferSize);
1709 }
1710 break;
Jeff Johnson295189b2012-06-20 16:38:30 -07001711 case VNV_ANTENNA_PATH_LOSS:
1712 itemSize = sizeof(gnvEFSTable->halnv.tables.antennaPathLoss);
1713 if(bufferSize != itemSize) {
1714 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
Amar Singhal9a65a6a2013-10-08 18:37:44 -07001715 ("type = %d buffer size=%d is less than data size=%d\r\n"),type, bufferSize,
Jeff Johnson295189b2012-06-20 16:38:30 -07001716 itemSize);
1717 status = VOS_STATUS_E_INVAL;
1718 }
1719 else {
1720 memcpy(&gnvEFSTable->halnv.tables.antennaPathLoss[0],inputVoidBuffer,bufferSize);
1721 }
1722 break;
1723
1724 case VNV_PACKET_TYPE_POWER_LIMITS:
1725 itemSize = sizeof(gnvEFSTable->halnv.tables.pktTypePwrLimits);
1726 if(bufferSize != itemSize) {
1727 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
Amar Singhal9a65a6a2013-10-08 18:37:44 -07001728 ("type = %d buffer size=%d is less than data size=%d\r\n"),type, bufferSize,
Jeff Johnson295189b2012-06-20 16:38:30 -07001729 itemSize);
1730 status = VOS_STATUS_E_INVAL;
1731 }
1732 else {
Tushnim Bhattacharyya95341d32013-03-20 20:15:03 -07001733 memcpy(gnvEFSTable->halnv.tables.pktTypePwrLimits,inputVoidBuffer,bufferSize);
Jeff Johnson295189b2012-06-20 16:38:30 -07001734 }
1735 break;
1736
1737 case VNV_OFDM_CMD_PWR_OFFSET:
1738 itemSize = sizeof(gnvEFSTable->halnv.tables.ofdmCmdPwrOffset);
1739 if(bufferSize != itemSize) {
1740 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
Amar Singhal9a65a6a2013-10-08 18:37:44 -07001741 ("type = %d buffer size=%d is less than data size=%d\r\n"),type, bufferSize,
Jeff Johnson295189b2012-06-20 16:38:30 -07001742 itemSize);
1743 status = VOS_STATUS_E_INVAL;
1744 }
1745 else {
1746 memcpy(&gnvEFSTable->halnv.tables.ofdmCmdPwrOffset,inputVoidBuffer,bufferSize);
1747 }
1748 break;
1749
1750 case VNV_TX_BB_FILTER_MODE:
1751 itemSize = sizeof(gnvEFSTable->halnv.tables.txbbFilterMode);
1752 if(bufferSize != itemSize) {
1753 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
Amar Singhal9a65a6a2013-10-08 18:37:44 -07001754 ("type = %d buffer size=%d is less than data size=%d\r\n"),type, bufferSize,
Jeff Johnson295189b2012-06-20 16:38:30 -07001755 itemSize);
1756 status = VOS_STATUS_E_INVAL;
1757 }
1758 else {
1759 memcpy(&gnvEFSTable->halnv.tables.txbbFilterMode,inputVoidBuffer,bufferSize);
1760 }
1761 break;
Amar Singhal61cbd962013-09-05 13:03:40 -07001762
Jeff Johnson295189b2012-06-20 16:38:30 -07001763
1764 case VNV_TABLE_VIRTUAL_RATE:
1765 itemSize = sizeof(gnvEFSTable->halnv.tables.pwrOptimum_virtualRate);
1766 if(bufferSize != itemSize) {
1767 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
Amar Singhal9a65a6a2013-10-08 18:37:44 -07001768 ("type = %d buffer size=%d is less than data size=%d\r\n"),type, bufferSize,
Jeff Johnson295189b2012-06-20 16:38:30 -07001769 itemSize);
1770 status = VOS_STATUS_E_INVAL;
1771 }
1772 else {
1773 memcpy(&gnvEFSTable->halnv.tables.pwrOptimum_virtualRate,inputVoidBuffer,bufferSize);
1774 }
1775 break;
1776
1777 default:
1778 break;
1779 }
1780 if (VOS_STATUS_SUCCESS == status)
1781 {
1782 // set NV item to have valid data
1783 status = vos_nv_setValidity( type, VOS_TRUE );
1784 if (! VOS_IS_STATUS_SUCCESS(status)) {
Amar Singhal9a65a6a2013-10-08 18:37:44 -07001785 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, ("vos_nv_setValidity failed!!!\r\n"));
Jeff Johnson295189b2012-06-20 16:38:30 -07001786 status = VOS_STATUS_E_FAULT;
1787 }
1788 status = wlan_write_to_efs((v_U8_t*)gnvEFSTable,sizeof(nvEFSTable_t));
1789
1790 if (! VOS_IS_STATUS_SUCCESS(status)) {
Amar Singhal9a65a6a2013-10-08 18:37:44 -07001791 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, ("vos_nv_write_to_efs failed!!!\r\n"));
Jeff Johnson295189b2012-06-20 16:38:30 -07001792 status = VOS_STATUS_E_FAULT;
1793 }
1794 }
1795 return status;
1796}
Venkata Prathyusha Kuntupallib2cb77c2013-02-26 22:16:52 -08001797
Jeff Johnson295189b2012-06-20 16:38:30 -07001798/**------------------------------------------------------------------------
1799 \brief vos_nv_getChannelListWithPower() - function to return the list of
1800 supported channels with the power limit info too.
1801 \param pChannels20MHz - list of 20 Mhz channels
1802 \param pNum20MHzChannelsFound - number of 20 Mhz channels
1803 \param pChannels40MHz - list of 20 Mhz channels
1804 \param pNum40MHzChannelsFound - number of 20 Mhz channels
1805 \return status of the NV read operation
1806 \Note: 40Mhz not currently supported
1807 \sa
1808 -------------------------------------------------------------------------*/
1809VOS_STATUS vos_nv_getChannelListWithPower(tChannelListWithPower *channels20MHz /*[NUM_LEGIT_RF_CHANNELS] */,
1810 tANI_U8 *num20MHzChannelsFound,
1811 tChannelListWithPower *channels40MHz /*[NUM_CHAN_BOND_CHANNELS] */,
1812 tANI_U8 *num40MHzChannelsFound
1813 )
1814{
1815 VOS_STATUS status = VOS_STATUS_SUCCESS;
1816 int i, count;
Amar Singhal61cbd962013-09-05 13:03:40 -07001817
Jeff Johnson295189b2012-06-20 16:38:30 -07001818 //TODO: Dont want to use pMac here...can we instead store the curRegDomain in NV
1819 // or pass it as a parameter to NV from SME?
1820
1821 if( channels20MHz && num20MHzChannelsFound )
1822 {
1823 count = 0;
1824 for( i = 0; i <= RF_CHAN_14; i++ )
1825 {
1826 if( regChannels[i].enabled )
1827 {
1828 channels20MHz[count].chanId = rfChannels[i].channelNum;
1829 channels20MHz[count++].pwr = regChannels[i].pwrLimit;
1830 }
1831 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001832 for( i = RF_CHAN_36; i <= RF_CHAN_165; i++ )
1833 {
1834 if( regChannels[i].enabled )
1835 {
1836 channels20MHz[count].chanId = rfChannels[i].channelNum;
1837 channels20MHz[count++].pwr = regChannels[i].pwrLimit;
1838 }
1839 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001840 *num20MHzChannelsFound = (tANI_U8)count;
1841 }
Jeff Johnsone7245742012-09-05 17:12:55 -07001842
1843 if( channels40MHz && num40MHzChannelsFound )
1844 {
1845 count = 0;
Jeff Johnsone7245742012-09-05 17:12:55 -07001846 //center channels for 2.4 Ghz 40 MHz channels
1847 for( i = RF_CHAN_BOND_3; i <= RF_CHAN_BOND_11; i++ )
1848 {
Amar Singhal61cbd962013-09-05 13:03:40 -07001849
Jeff Johnsone7245742012-09-05 17:12:55 -07001850 if( regChannels[i].enabled )
1851 {
1852 channels40MHz[count].chanId = rfChannels[i].channelNum;
1853 channels40MHz[count++].pwr = regChannels[i].pwrLimit;
1854 }
1855 }
1856 //center channels for 5 Ghz 40 MHz channels
1857 for( i = RF_CHAN_BOND_38; i <= RF_CHAN_BOND_163; i++ )
1858 {
Amar Singhal61cbd962013-09-05 13:03:40 -07001859
Jeff Johnsone7245742012-09-05 17:12:55 -07001860 if( regChannels[i].enabled )
1861 {
1862 channels40MHz[count].chanId = rfChannels[i].channelNum;
1863 channels40MHz[count++].pwr = regChannels[i].pwrLimit;
1864 }
1865 }
Jeff Johnsone7245742012-09-05 17:12:55 -07001866 *num40MHzChannelsFound = (tANI_U8)count;
1867 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001868 return (status);
1869}
1870
1871/**------------------------------------------------------------------------
1872 \brief vos_nv_getDefaultRegDomain() - return the default regulatory domain
1873 \return default regulatory domain
1874 \sa
1875 -------------------------------------------------------------------------*/
1876
1877v_REGDOMAIN_t vos_nv_getDefaultRegDomain( void )
1878{
1879 return countryInfoTable.countryInfo[0].regDomain;
1880}
1881
1882/**------------------------------------------------------------------------
1883 \brief vos_nv_getSupportedChannels() - function to return the list of
1884 supported channels
1885 \param p20MhzChannels - list of 20 Mhz channels
1886 \param pNum20MhzChannels - number of 20 Mhz channels
1887 \param p40MhzChannels - list of 40 Mhz channels
1888 \param pNum40MhzChannels - number of 40 Mhz channels
1889 \return status of the NV read operation
1890 \Note: 40Mhz not currently supported
1891 \sa
1892 -------------------------------------------------------------------------*/
1893VOS_STATUS vos_nv_getSupportedChannels( v_U8_t *p20MhzChannels, int *pNum20MhzChannels,
1894 v_U8_t *p40MhzChannels, int *pNum40MhzChannels)
1895{
1896 VOS_STATUS status = VOS_STATUS_E_INVAL;
1897 int i, count = 0;
1898
1899 if( p20MhzChannels && pNum20MhzChannels )
1900 {
1901 if( *pNum20MhzChannels >= NUM_RF_CHANNELS )
1902 {
1903 for( i = 0; i <= RF_CHAN_14; i++ )
1904 {
1905 p20MhzChannels[count++] = rfChannels[i].channelNum;
1906 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001907 for( i = RF_CHAN_36; i <= RF_CHAN_165; i++ )
1908 {
1909 p20MhzChannels[count++] = rfChannels[i].channelNum;
1910 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001911 status = VOS_STATUS_SUCCESS;
1912 }
1913 *pNum20MhzChannels = count;
1914 }
1915
1916 return (status);
1917}
1918
1919/**------------------------------------------------------------------------
1920 \brief vos_nv_readDefaultCountryTable() - return the default Country table
1921 \param table data - a union to return the default country table data in.
1922 \return status of the NV read operation
1923 \sa
1924 -------------------------------------------------------------------------*/
1925VOS_STATUS vos_nv_readDefaultCountryTable( uNvTables *tableData )
1926{
Amar Singhal61cbd962013-09-05 13:03:40 -07001927
Madan Mohan Koyyalamudic3a240c2012-09-28 15:34:08 -07001928 VOS_STATUS status = VOS_STATUS_SUCCESS;
1929 memcpy(&tableData->defaultCountryTable, &pnvEFSTable->halnv.tables.defaultCountryTable, sizeof(sDefaultCountry));
1930 pr_info("DefaultCountry is %c%c\n",
1931 tableData->defaultCountryTable.countryCode[0],
1932 tableData->defaultCountryTable.countryCode[1]);
Jeff Johnson295189b2012-06-20 16:38:30 -07001933 return status;
1934}
1935
1936/**------------------------------------------------------------------------
Amar Singhal61cbd962013-09-05 13:03:40 -07001937 \brief vos_nv_getBuffer -
Jeff Johnson295189b2012-06-20 16:38:30 -07001938 \param pBuffer - to return the buffer address
1939 pSize - buffer size.
1940 \return status of the NV read operation
1941 \sa
1942 -------------------------------------------------------------------------*/
1943VOS_STATUS vos_nv_getNVBuffer(v_VOID_t **pNvBuffer,v_SIZE_t *pSize)
1944{
Jeff Johnson295189b2012-06-20 16:38:30 -07001945 /* Send the NV structure and size */
1946 *pNvBuffer = (v_VOID_t *)(&pnvEFSTable->halnv);
1947 *pSize = sizeof(sHalNv);
1948
1949 return VOS_STATUS_SUCCESS;
1950}
1951
Jeff Johnson295189b2012-06-20 16:38:30 -07001952/**------------------------------------------------------------------------
Prasanna Kumar0833aa82013-04-11 20:05:21 -07001953 \brief vos_nv_getBuffer -
1954 \param pBuffer - to return the buffer address
1955 pSize - buffer size.
1956 \return status of the NV read operation
1957 \sa
1958 -------------------------------------------------------------------------*/
1959VOS_STATUS vos_nv_getNVEncodedBuffer(v_VOID_t **pNvBuffer,v_SIZE_t *pSize)
1960{
1961 /* Send the NV structure and size */
1962 VOS_STATUS status;
1963
1964 status = vos_nv_isEmbeddedNV();
1965
1966 if (VOS_STATUS_SUCCESS == status)
1967 {
1968 *pNvBuffer = (v_VOID_t *)(pEncodedBuf);
1969 *pSize = nvReadEncodeBufSize;
1970 }
1971 else
1972 {
1973 *pNvBuffer = (v_VOID_t *)(&pnvEFSTable->halnv);
1974 *pSize = sizeof(sHalNv);
1975 }
1976
1977 return VOS_STATUS_SUCCESS;
1978}
1979
1980
1981VOS_STATUS vos_nv_getNVDictionary(v_VOID_t **pNvBuffer,v_SIZE_t *pSize)
1982{
1983 /* Send the NV structure and size */
1984 *pNvBuffer = (v_VOID_t *)(pDictFile);
1985 *pSize = nDictionarySize;
1986
1987 return VOS_STATUS_SUCCESS;
1988}
1989
1990VOS_STATUS vos_nv_isEmbeddedNV(v_VOID_t)
1991{
1992 if (MAGIC_NUMBER == magicNumber)
1993 {
1994 return VOS_STATUS_SUCCESS;
1995 }
1996
1997 return VOS_STATUS_E_FAILURE;
1998}
1999
2000VOS_STATUS vos_nv_setNVEncodedBuffer(v_U8_t *pNvBuffer, v_SIZE_t size)
2001{
2002 vos_mem_copy(pEncodedBuf, &pNvBuffer[sizeof(v_U32_t)],
2003 (size-sizeof(v_U32_t)));
2004
2005 return VOS_STATUS_SUCCESS;
2006}
2007
2008/**------------------------------------------------------------------------
Amar Singhal61cbd962013-09-05 13:03:40 -07002009 \brief vos_nv_getChannelEnabledState -
Jeff Johnson295189b2012-06-20 16:38:30 -07002010 \param rfChannel - input channel enum to know evabled state
2011 \return eNVChannelEnabledType enabled state for channel
2012 * enabled
2013 * disabled
2014 * DFS
2015 \sa
2016 -------------------------------------------------------------------------*/
2017eNVChannelEnabledType vos_nv_getChannelEnabledState
2018(
2019 v_U32_t rfChannel
2020)
2021{
2022 v_U32_t channelLoop;
2023 eRfChannels channelEnum = INVALID_RF_CHANNEL;
2024
2025 for(channelLoop = 0; channelLoop <= RF_CHAN_165; channelLoop++)
2026 {
2027 if(rfChannels[channelLoop].channelNum == rfChannel)
2028 {
2029 channelEnum = (eRfChannels)channelLoop;
2030 break;
2031 }
2032 }
2033
2034 if(INVALID_RF_CHANNEL == channelEnum)
2035 {
2036 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
Jeff Johnsonbf9616f2012-12-10 13:34:59 -08002037 "vos_nv_getChannelEnabledState, invalid channel %d", rfChannel);
Jeff Johnson295189b2012-06-20 16:38:30 -07002038 return NV_CHANNEL_INVALID;
2039 }
2040
2041 return regChannels[channelEnum].enabled;
2042}
Madan Mohan Koyyalamudic3a240c2012-09-28 15:34:08 -07002043
2044/******************************************************************
Amar Singhal9a65a6a2013-10-08 18:37:44 -07002045 Add CRDA regulatory support
Madan Mohan Koyyalamudic3a240c2012-09-28 15:34:08 -07002046*******************************************************************/
Madan Mohan Koyyalamudic3a240c2012-09-28 15:34:08 -07002047
2048static int bw20_ch_index_to_bw40_ch_index(int k)
2049{
2050 int m = -1;
2051 if (k >= RF_CHAN_1 && k <= RF_CHAN_14)
2052 {
Amar Singhal9a65a6a2013-10-08 18:37:44 -07002053 m = k - RF_CHAN_1 + RF_CHAN_BOND_3 ;
2054 if (m > RF_CHAN_BOND_11)
2055 m = RF_CHAN_BOND_11;
Madan Mohan Koyyalamudic3a240c2012-09-28 15:34:08 -07002056 }
2057 else if (k >= RF_CHAN_240 && k <= RF_CHAN_216)
2058 {
Amar Singhal9a65a6a2013-10-08 18:37:44 -07002059 m = k - RF_CHAN_240 + RF_CHAN_BOND_242 ;
2060 if (m > RF_CHAN_BOND_214)
2061 m = RF_CHAN_BOND_214;
Madan Mohan Koyyalamudic3a240c2012-09-28 15:34:08 -07002062 }
2063 else if (k >= RF_CHAN_36 && k <= RF_CHAN_64)
2064 {
Amar Singhal9a65a6a2013-10-08 18:37:44 -07002065 m = k - RF_CHAN_36 + RF_CHAN_BOND_38;
2066 if (m > RF_CHAN_BOND_62)
2067 m = RF_CHAN_BOND_62;
Madan Mohan Koyyalamudic3a240c2012-09-28 15:34:08 -07002068 }
2069 else if (k >= RF_CHAN_100 && k <= RF_CHAN_140)
2070 {
Amar Singhal9a65a6a2013-10-08 18:37:44 -07002071 m = k - RF_CHAN_100 + RF_CHAN_BOND_102;
2072 if (m > RF_CHAN_BOND_138)
2073 m = RF_CHAN_BOND_138;
Madan Mohan Koyyalamudic3a240c2012-09-28 15:34:08 -07002074 }
2075 else if (k >= RF_CHAN_149 && k <= RF_CHAN_165)
2076 {
Amar Singhal9a65a6a2013-10-08 18:37:44 -07002077 m = k - RF_CHAN_149 + RF_CHAN_BOND_151;
2078 if (m > RF_CHAN_BOND_163)
2079 m = RF_CHAN_BOND_163;
Madan Mohan Koyyalamudic3a240c2012-09-28 15:34:08 -07002080 }
Amar Singhal9a65a6a2013-10-08 18:37:44 -07002081return m;
Madan Mohan Koyyalamudic3a240c2012-09-28 15:34:08 -07002082}
2083
Amar Singhal9a65a6a2013-10-08 18:37:44 -07002084void crda_regulatory_entry_default(v_U8_t *countryCode, int domain_id)
Yunsen Wang73baad32013-04-05 15:04:43 -07002085{
Amar Singhal9a65a6a2013-10-08 18:37:44 -07002086 int k;
2087 pr_info("Country %c%c domain_id %d\n enable ch 1 - 11.\n",
2088 countryCode[0], countryCode[1], domain_id);
2089 for (k = RF_CHAN_1; k <= RF_CHAN_11; k++) {
2090 pnvEFSTable->halnv.tables.regDomains[domain_id].channels[k].enabled =
2091 NV_CHANNEL_ENABLE;
2092 /* Max Tx Power 20dBm */
2093 pnvEFSTable->halnv.tables.regDomains[domain_id].channels[k].pwrLimit = 20;
2094 }
2095 /* enable ch 12 to ch 14 passive scan */
2096 pr_info(" enable ch 12 - 14 to scan passively by setting DFS flag.\n");
2097 for (k = RF_CHAN_12; k <= MAX_2_4GHZ_CHANNEL; k++) {
2098 pnvEFSTable->halnv.tables.regDomains[domain_id].channels[k].enabled =
2099 NV_CHANNEL_DFS;
2100 pnvEFSTable->halnv.tables.regDomains[domain_id].channels[k].pwrLimit = 0;
2101 }
2102 pr_info(" enable 5GHz to scan passively by setting DFS flag.\n");
2103 for (k = MIN_5GHZ_CHANNEL; k <= MAX_5GHZ_CHANNEL; k++) {
2104 pnvEFSTable->halnv.tables.regDomains[domain_id].channels[k].enabled =
2105 NV_CHANNEL_DFS;
2106 pnvEFSTable->halnv.tables.regDomains[domain_id].channels[k].pwrLimit = 0;
2107 }
2108#ifdef PASSIVE_SCAN_4_9GHZ
2109 pr_info(" enable 4.9 GHz to scan passively by setting DFS flag.\n");
2110 for (k = RF_CHAN_240; k <= RF_CHAN_216; k++) {
2111 pnvEFSTable->halnv.tables.regDomains[domain_id].channels[k].enabled =
2112 NV_CHANNEL_DFS;
2113 pnvEFSTable->halnv.tables.regDomains[domain_id].channels[k].pwrLimit = 0;
2114 }
2115#endif
2116 if (domain_id == NUM_REG_DOMAINS-1)
2117 { /* init time */
2118 crda_alpha2[0] = countryCode[0];
2119 crda_alpha2[1] = countryCode[1];
2120 crda_regulatory_entry_valid = VOS_TRUE;
2121 pnvEFSTable->halnv.tables.defaultCountryTable.countryCode[0] = countryCode[0];
2122 pnvEFSTable->halnv.tables.defaultCountryTable.countryCode[1] = countryCode[1];
2123 pnvEFSTable->halnv.tables.defaultCountryTable.countryCode[2] = 'I';
2124 pnvEFSTable->halnv.tables.defaultCountryTable.regDomain = NUM_REG_DOMAINS-1;
2125 }
2126 if (domain_id == NUM_REG_DOMAINS-2)
2127 { /* none-default country */
2128 run_time_alpha2[0] = countryCode[0];
2129 run_time_alpha2[1] = countryCode[1];
2130 crda_regulatory_run_time_entry_valid = VOS_TRUE;
2131 }
2132}
Yunsen Wang73baad32013-04-05 15:04:43 -07002133
Amar Singhal9a65a6a2013-10-08 18:37:44 -07002134static int crda_regulatory_entry_post_processing(struct wiphy *wiphy,
2135 struct regulatory_request *request,
2136 v_U8_t nBandCapability,
2137 int domain_id)
2138{
2139 if (request->alpha2[0] == '0' && request->alpha2[1] == '0') {
2140 pr_info("Country 00 special handling to enable passive scan.\n");
2141 crda_regulatory_entry_default(request->alpha2, domain_id);
2142 }
2143 return 0;
2144}
Yunsen Wang73baad32013-04-05 15:04:43 -07002145
Amar Singhal9a65a6a2013-10-08 18:37:44 -07002146/* create_crda_regulatory_entry should be called from user command or 11d country IE */
2147static int create_crda_regulatory_entry(struct wiphy *wiphy,
2148 struct regulatory_request *request,
2149 v_U8_t nBandCapability)
2150{
2151 int i, j, m;
2152 int k = 0, n = 0;
2153
2154 if (run_time_alpha2[0]==request->alpha2[0] &&
2155 run_time_alpha2[1]==request->alpha2[1] &&
2156 crda_regulatory_run_time_entry_valid == VOS_TRUE)
2157 return 0; /* already created */
2158
2159 /* 20MHz channels */
Madan Mohan Koyyalamudic3a240c2012-09-28 15:34:08 -07002160 if (nBandCapability == eCSR_BAND_24)
2161 pr_info("BandCapability is set to 2G only.\n");
Amar Singhal9a65a6a2013-10-08 18:37:44 -07002162 for (i=0,m=0;i<IEEE80211_NUM_BANDS;i++)
Madan Mohan Koyyalamudic3a240c2012-09-28 15:34:08 -07002163 {
2164 if (i == IEEE80211_BAND_2GHZ && nBandCapability == eCSR_BAND_5G) // 5G only
2165 continue;
2166 else if (i == IEEE80211_BAND_5GHZ && nBandCapability == eCSR_BAND_24) // 2G only
2167 continue;
2168 if (wiphy->bands[i] == NULL)
2169 {
2170 pr_info("error: wiphy->bands[i] is NULL, i = %d\n", i);
2171 return -1;
2172 }
Amar Singhal9a65a6a2013-10-08 18:37:44 -07002173 // internal channels[] is one continous array for both 2G and 5G bands
2174 // m is internal starting channel index for each band
Madan Mohan Koyyalamudic3a240c2012-09-28 15:34:08 -07002175 if (i == 0)
2176 m = 0;
2177 else
2178 m = wiphy->bands[i-1]->n_channels + m;
Amar Singhal9a65a6a2013-10-08 18:37:44 -07002179 for (j=0;j<wiphy->bands[i]->n_channels;j++)
Madan Mohan Koyyalamudic3a240c2012-09-28 15:34:08 -07002180 {
Amar Singhal9a65a6a2013-10-08 18:37:44 -07002181 // k = (m + j) is internal current channel index for 20MHz channel
2182 // n is internal channel index for corresponding 40MHz channel
Madan Mohan Koyyalamudic3a240c2012-09-28 15:34:08 -07002183 k = m + j;
2184 n = bw20_ch_index_to_bw40_ch_index(k);
2185 if (n == -1)
Amar Singhal9a65a6a2013-10-08 18:37:44 -07002186 return -1;
Madan Mohan Koyyalamudic3a240c2012-09-28 15:34:08 -07002187 if (wiphy->bands[i]->channels[j].flags & IEEE80211_CHAN_DISABLED)
2188 {
Amar Singhal9a65a6a2013-10-08 18:37:44 -07002189 if (pnvEFSTable == NULL)
2190 {
2191 pr_info("error: pnvEFSTable is NULL, probably not parsed nv.bin yet\n");
2192 return -1;
2193 }
2194 pnvEFSTable->halnv.tables.regDomains[NUM_REG_DOMAINS-2].channels[k].enabled =
2195 NV_CHANNEL_DISABLE;
2196 pnvEFSTable->halnv.tables.regDomains[NUM_REG_DOMAINS-2].channels[n].enabled =
2197 NV_CHANNEL_DISABLE;
2198 //pr_info("CH %d disabled, no bonding centered on CH %d.\n", rfChannels[k].channelNum,
2199 // rfChannels[n].channelNum);
Madan Mohan Koyyalamudic3a240c2012-09-28 15:34:08 -07002200 }
2201 else if (wiphy->bands[i]->channels[j].flags & IEEE80211_CHAN_RADAR)
2202 {
Amar Singhal9a65a6a2013-10-08 18:37:44 -07002203 pnvEFSTable->halnv.tables.regDomains[NUM_REG_DOMAINS-2].channels[k].enabled =
2204 NV_CHANNEL_DFS;
2205 // max_power is in mBm = 100 * dBm
2206 pnvEFSTable->halnv.tables.regDomains[NUM_REG_DOMAINS-2].channels[k].pwrLimit =
2207 (tANI_S8) ((wiphy->bands[i]->channels[j].max_power)/100);
2208 if ((wiphy->bands[i]->channels[j].flags & IEEE80211_CHAN_NO_HT40) == 0)
2209 {
2210 pnvEFSTable->halnv.tables.regDomains[NUM_REG_DOMAINS-2].channels[n].enabled =
2211 NV_CHANNEL_DFS;
2212 // 40MHz channel power is half of 20MHz (-3dB) ??
2213 pnvEFSTable->halnv.tables.regDomains[NUM_REG_DOMAINS-2].channels[n].pwrLimit =
2214 (tANI_S8) (((wiphy->bands[i]->channels[j].max_power)/100)-3);
2215 }
Madan Mohan Koyyalamudic3a240c2012-09-28 15:34:08 -07002216 }
2217 else // Enable is only last flag we support
2218 {
Amar Singhal9a65a6a2013-10-08 18:37:44 -07002219 pnvEFSTable->halnv.tables.regDomains[NUM_REG_DOMAINS-2].channels[k].enabled =
2220 NV_CHANNEL_ENABLE;
2221 // max_power is in dBm
2222 pnvEFSTable->halnv.tables.regDomains[NUM_REG_DOMAINS-2].channels[k].pwrLimit =
2223 (tANI_S8) ((wiphy->bands[i]->channels[j].max_power)/100);
2224 if ((wiphy->bands[i]->channels[j].flags & IEEE80211_CHAN_NO_HT40) == 0)
2225 {
2226 pnvEFSTable->halnv.tables.regDomains[NUM_REG_DOMAINS-2].channels[n].enabled =
2227 NV_CHANNEL_ENABLE;
2228 // 40MHz channel power is half of 20MHz (-3dB) ??
2229 pnvEFSTable->halnv.tables.regDomains[NUM_REG_DOMAINS-2].channels[n].pwrLimit =
2230 (tANI_S8) (((wiphy->bands[i]->channels[j].max_power)/100)-3);
2231 }
Madan Mohan Koyyalamudic3a240c2012-09-28 15:34:08 -07002232 }
Amar Singhal9a65a6a2013-10-08 18:37:44 -07002233 /* ignore CRDA max_antenna_gain typical is 3dBi, nv.bin antennaGain is
2234 real gain which should be provided by the real design */
Madan Mohan Koyyalamudic3a240c2012-09-28 15:34:08 -07002235 }
2236 }
2237 if (k == 0)
2238 return -1;
Amar Singhal9a65a6a2013-10-08 18:37:44 -07002239 run_time_alpha2[0] = request->alpha2[0];
2240 run_time_alpha2[1] = request->alpha2[1];
2241 crda_regulatory_run_time_entry_valid = VOS_TRUE;
2242 crda_regulatory_entry_post_processing(wiphy, request, nBandCapability, NUM_REG_DOMAINS-2);
2243return 0;
2244}
Kiet Lam5e565ef2013-10-12 23:13:13 -07002245
2246
Amar Singhal9a65a6a2013-10-08 18:37:44 -07002247v_BOOL_t is_crda_regulatory_entry_valid(void)
2248{
2249return crda_regulatory_entry_valid;
Madan Mohan Koyyalamudic3a240c2012-09-28 15:34:08 -07002250}
2251
Amar Singhal9a65a6a2013-10-08 18:37:44 -07002252/* Handling routines for the conversion from regd rules (start/end freq) to channel index
2253start freq + 10000 = center freq of the 20MHz start channel
2254end freq - 10000 = center freq of the 20MHz end channel
2255start freq + 20000 = center freq of the 40MHz start channel
2256end freq - 20000 = center freq of the 40MHz end channel
Madan Mohan Koyyalamudic3a240c2012-09-28 15:34:08 -07002257*/
Amar Singhal9a65a6a2013-10-08 18:37:44 -07002258static int bw20_start_freq_to_channel_index(u32 freq_khz)
Madan Mohan Koyyalamudic3a240c2012-09-28 15:34:08 -07002259{
Amar Singhal9a65a6a2013-10-08 18:37:44 -07002260int i;
2261u32 center_freq = freq_khz + 10000;
2262 //Has to compare from low freq to high freq
2263 //RF_SUBBAND_2_4_GHZ
2264 for (i=RF_CHAN_1;i<=RF_CHAN_14;i++)
2265 if (center_freq <= (u32) (rfChannels[i].targetFreq) * 1000)
2266 return i;
2267 //RF_SUBBAND_4_9_GHZ, Ch 240, 244, 248, 252, 208, 212, 216
2268 for (i=RF_CHAN_240;i<=RF_CHAN_216;i++)
2269 if (center_freq <= (u32) (rfChannels[i].targetFreq) * 1000)
2270 return i;
2271 //RF_SUBBAND_5_LOW_GHZ
2272 for (i=RF_CHAN_36;i<=RF_CHAN_64;i++)
2273 if (center_freq <= (u32) (rfChannels[i].targetFreq) * 1000)
2274 return i;
2275 //RF_SUBBAND_5_MID_GHZ
2276 for (i=RF_CHAN_100;i<=RF_CHAN_140;i++)
2277 if (center_freq <= (u32) (rfChannels[i].targetFreq) * 1000)
2278 return i;
2279 //RF_SUBBAND_5_HIGH_GHZ
2280 for (i=RF_CHAN_149;i<=RF_CHAN_165;i++)
2281 if (center_freq <= (u32) (rfChannels[i].targetFreq) * 1000)
2282 return i;
2283return -1;
2284}
2285
2286static int bw20_end_freq_to_channel_index(u32 freq_khz)
2287{
2288int i;
2289u32 center_freq = freq_khz - 10000;
2290 //Has to compare from high freq to low freq
2291 //RF_SUBBAND_5_HIGH_GHZ
2292 for (i=RF_CHAN_165;i>=RF_CHAN_149;i--)
2293 if (center_freq >= (u32) (rfChannels[i].targetFreq) * 1000)
2294 return i;
2295 //RF_SUBBAND_5_MID_GHZ
2296 for (i=RF_CHAN_140;i>=RF_CHAN_100;i--)
2297 if (center_freq >= (u32) (rfChannels[i].targetFreq) * 1000)
2298 return i;
2299 //RF_SUBBAND_5_LOW_GHZ
2300 for (i=RF_CHAN_64;i>=RF_CHAN_36;i--)
2301 if (center_freq >= (u32) (rfChannels[i].targetFreq) * 1000)
2302 return i;
2303 //RF_SUBBAND_4_9_GHZ, Ch 216, 212, 208, 252, 248, 244, 240
2304 for (i=RF_CHAN_216;i>=RF_CHAN_240;i--)
2305 if (center_freq >= (u32) (rfChannels[i].targetFreq) * 1000)
2306 return i;
2307 //RF_SUBBAND_2_4_GHZ
2308 for (i=RF_CHAN_14;i>=RF_CHAN_1;i--)
2309 if (center_freq >= (u32) (rfChannels[i].targetFreq) * 1000)
2310 return i;
2311return -1;
2312}
2313
2314static int bw40_start_freq_to_channel_index(u32 freq_khz)
2315{
2316int i;
2317u32 center_freq = freq_khz + 20000;
2318 //Has to compare from low freq to high freq
2319 //RF_SUBBAND_2_4_GHZ
2320 for (i=RF_CHAN_BOND_3;i<=RF_CHAN_BOND_11;i++)
2321 if (center_freq <= (u32) (rfChannels[i].targetFreq) * 1000)
2322 return i;
2323 //RF_SUBBAND_4_9_GHZ, Ch 242, 246, 250, 210, 214
2324 for (i=RF_CHAN_BOND_242;i<=RF_CHAN_BOND_214;i++)
2325 if (center_freq <= (u32) (rfChannels[i].targetFreq) * 1000)
2326 return i;
2327 //RF_SUBBAND_5_LOW_GHZ
2328 for (i=RF_CHAN_BOND_38;i<=RF_CHAN_BOND_62;i++)
2329 if (center_freq <= (u32) (rfChannels[i].targetFreq) * 1000)
2330 return i;
2331 //RF_SUBBAND_5_MID_GHZ
2332 for (i=RF_CHAN_BOND_102;i<=RF_CHAN_BOND_138;i++)
2333 if (center_freq <= (u32) (rfChannels[i].targetFreq) * 1000)
2334 return i;
2335 //RF_SUBBAND_5_HIGH_GHZ
2336 for (i=RF_CHAN_BOND_151;i<=RF_CHAN_BOND_163;i++)
2337 if (center_freq <= (u32) (rfChannels[i].targetFreq) * 1000)
2338 return i;
2339return -1;
2340}
2341
2342static int bw40_end_freq_to_channel_index(u32 freq_khz)
2343{
2344int i;
2345u32 center_freq = freq_khz - 20000;
2346 //Has to compare from high freq to low freq
2347 //RF_SUBBAND_5_HIGH_GHZ
2348 for (i=RF_CHAN_BOND_163;i>=RF_CHAN_BOND_151;i--)
2349 if (center_freq >= (u32) (rfChannels[i].targetFreq) * 1000)
2350 return i;
2351 //RF_SUBBAND_5_MID_GHZ
2352 for (i=RF_CHAN_BOND_138;i>=RF_CHAN_BOND_102;i--)
2353 if (center_freq >= (u32) (rfChannels[i].targetFreq) * 1000)
2354 return i;
2355 //RF_SUBBAND_5_LOW_GHZ
2356 for (i=RF_CHAN_BOND_62;i>=RF_CHAN_BOND_38;i--)
2357 if (center_freq >= (u32) (rfChannels[i].targetFreq) * 1000)
2358 return i;
2359 //RF_SUBBAND_4_9_GHZ, Ch 214, 210, 250, 246, 242
2360 for (i=RF_CHAN_BOND_214;i>=RF_CHAN_BOND_242;i--)
2361 if (center_freq >= (u32) (rfChannels[i].targetFreq) * 1000)
2362 return i;
2363 //RF_SUBBAND_2_4_GHZ
2364 for (i=RF_CHAN_BOND_11;i>=RF_CHAN_BOND_3;i--)
2365 if (center_freq >= (u32) (rfChannels[i].targetFreq) * 1000)
2366 return i;
2367return -1;
2368}
2369
2370static v_BOOL_t channel_in_capable_band(int j, v_U8_t nBandCapability)
2371{
2372 switch (nBandCapability)
2373 {
2374 case eCSR_BAND_ALL:
2375 return VOS_TRUE;
2376 case eCSR_BAND_24:
2377 if (j >= RF_CHAN_1 && j <= RF_CHAN_14)
2378 return VOS_TRUE;
2379 if (j >= RF_CHAN_BOND_3 && j <= RF_CHAN_BOND_11)
2380 return VOS_TRUE; // 2.4G 40MHz channel
2381 break;
2382 case eCSR_BAND_5G:
2383 if (j >= RF_CHAN_240 && j <= RF_CHAN_165)
2384 return VOS_TRUE;
2385 if (j >= RF_CHAN_BOND_242 && j <= RF_CHAN_BOND_163)
2386 return VOS_TRUE; // 2.4G 40MHz channel
2387 break;
2388 default:
2389 break;
2390 }
2391 return VOS_FALSE;
2392}
2393
2394/* create_crda_regulatory_entry_from_regd should be called during init time */
2395static int create_crda_regulatory_entry_from_regd(struct wiphy *wiphy,
2396 struct regulatory_request *request,
2397 v_U8_t nBandCapability)
2398{
2399 int i, j, n, domain_id;
2400 int bw20_start_channel_index, bw20_end_channel_index;
2401 int bw40_start_channel_index, bw40_end_channel_index;
2402
2403 if (wiphy == NULL || wiphy->regd == NULL)
2404 {
2405 wiphy_dbg(wiphy, "error: wiphy->regd is NULL\n");
2406 return -1;
2407 }
2408 if (crda_regulatory_entry_valid == VOS_FALSE)
2409 domain_id = NUM_REG_DOMAINS-1; /* init time */
2410 else
2411 domain_id = NUM_REG_DOMAINS-2; /* none-default country */
2412 for (n = 0; n < NUM_RF_CHANNELS; n++)
2413 pnvEFSTable->halnv.tables.regDomains[domain_id].channels[n].enabled = NV_CHANNEL_DISABLE;
2414
2415 for (i=0;i<wiphy->regd->n_reg_rules;i++)
2416 {
2417 wiphy_dbg(wiphy, "info: crda rule %d --------------------------------------------\n", i);
2418 bw20_start_channel_index =
2419 bw20_start_freq_to_channel_index(wiphy->regd->reg_rules[i].freq_range.start_freq_khz);
2420 bw20_end_channel_index =
2421 bw20_end_freq_to_channel_index(wiphy->regd->reg_rules[i].freq_range.end_freq_khz);
2422 if (bw20_start_channel_index == -1 || bw20_end_channel_index == -1)
2423 {
2424 wiphy_dbg(wiphy, "error: crda freq not supported, start freq (KHz) %d end freq %d\n",
2425 wiphy->regd->reg_rules[i].freq_range.start_freq_khz,
2426 wiphy->regd->reg_rules[i].freq_range.end_freq_khz);
2427 continue; // skip this rull, but continue to next rule
2428 }
2429 wiphy_dbg(wiphy, "20MHz start freq (KHz) %d end freq %d start ch index %d end ch index %d\n",
2430 wiphy->regd->reg_rules[i].freq_range.start_freq_khz,
2431 wiphy->regd->reg_rules[i].freq_range.end_freq_khz,
2432 bw20_start_channel_index, bw20_end_channel_index);
2433 for (j=bw20_start_channel_index;j<=bw20_end_channel_index;j++)
2434 {
2435 if (channel_in_capable_band(j, nBandCapability) == VOS_FALSE)
2436 {
2437 wiphy_dbg(wiphy, "info: CH %d is not in capable band\n",
2438 rfChannels[j].channelNum);
2439 continue; // skip this channel, continue to next
2440 }
2441 if (wiphy->regd->reg_rules[i].flags & NL80211_RRF_DFS)
2442 {
2443 pnvEFSTable->halnv.tables.regDomains[domain_id].channels[j].enabled = NV_CHANNEL_DFS;
2444 wiphy_dbg(wiphy, "info: CH %d is DFS, max EIRP (mBm) is %d\n", rfChannels[j].channelNum,
2445 wiphy->regd->reg_rules[i].power_rule.max_eirp);
2446 }
Kiet Lame2689e42013-10-25 19:35:12 +05302447 if (wiphy->regd->reg_rules[i].flags & NL80211_RRF_PASSIVE_SCAN)
2448 {
2449 pnvEFSTable->halnv.tables.regDomains[domain_id].channels[j].enabled = NV_CHANNEL_DFS;
2450 wiphy_dbg(wiphy, "info: CH %d is Passive, max EIRP (mBm) is %d\n", rfChannels[j].channelNum,
2451 wiphy->regd->reg_rules[i].power_rule.max_eirp);
2452 }
Amar Singhal9a65a6a2013-10-08 18:37:44 -07002453 else
2454 {
2455 pnvEFSTable->halnv.tables.regDomains[domain_id].channels[j].enabled = NV_CHANNEL_ENABLE;
2456 wiphy_dbg(wiphy, "info: CH %d is enabled, no DFS, max EIRP (mBm) is %d\n", rfChannels[j].channelNum,
2457 wiphy->regd->reg_rules[i].power_rule.max_eirp);
2458 }
2459 /* max_eirp is in mBm (= 100 * dBm) unit */
2460 pnvEFSTable->halnv.tables.regDomains[domain_id].channels[j].pwrLimit =
2461 (tANI_S8) ((wiphy->regd->reg_rules[i].power_rule.max_eirp)/100);
2462 }
2463 /* ignore CRDA max_antenna_gain typical is 3dBi, nv.bin antennaGain is
2464 real gain which should be provided by the real design */
2465 if (wiphy->regd->reg_rules[i].freq_range.max_bandwidth_khz == 40000)
2466 {
2467 wiphy_dbg(wiphy, "info: 40MHz (channel bonding) is allowed\n");
2468 bw40_start_channel_index =
2469 bw40_start_freq_to_channel_index(wiphy->regd->reg_rules[i].freq_range.start_freq_khz);
2470 bw40_end_channel_index =
2471 bw40_end_freq_to_channel_index(wiphy->regd->reg_rules[i].freq_range.end_freq_khz);
2472 if (bw40_start_channel_index == -1 || bw40_end_channel_index == -1)
2473 {
2474 wiphy_dbg(wiphy, "error: crda freq not supported, start_freq_khz %d end_freq_khz %d\n",
2475 wiphy->regd->reg_rules[i].freq_range.start_freq_khz,
2476 wiphy->regd->reg_rules[i].freq_range.end_freq_khz);
2477 continue; // skip this rull, but continue to next rule
2478 }
2479 wiphy_dbg(wiphy, "40MHz start freq (KHz) %d end freq %d start ch index %d end ch index %d\n",
2480 wiphy->regd->reg_rules[i].freq_range.start_freq_khz,
2481 wiphy->regd->reg_rules[i].freq_range.end_freq_khz,
2482 bw40_start_channel_index, bw40_end_channel_index);
2483 for (j=bw40_start_channel_index;j<=bw40_end_channel_index;j++)
2484 {
2485 if (channel_in_capable_band(j, nBandCapability) == VOS_FALSE)
2486 continue; // skip this channel, continue to next
2487 if (wiphy->regd->reg_rules[i].flags & NL80211_RRF_DFS)
2488 {
2489 pnvEFSTable->halnv.tables.regDomains[domain_id].channels[j].enabled = NV_CHANNEL_DFS;
2490 wiphy_dbg(wiphy, "info: 40MHz centered on CH %d is DFS\n", rfChannels[j].channelNum);
2491 }
2492 else
2493 {
2494 pnvEFSTable->halnv.tables.regDomains[domain_id].channels[j].enabled = NV_CHANNEL_ENABLE;
2495 wiphy_dbg(wiphy, "info: 40MHz centered on CH %d is enabled, no DFS\n", rfChannels[j].channelNum);
2496 }
2497 /* set 40MHz channel power as half (- 3 dB) of 20MHz */
2498 pnvEFSTable->halnv.tables.regDomains[domain_id].channels[j].pwrLimit =
2499 (tANI_S8) (((wiphy->regd->reg_rules[i].power_rule.max_eirp)/100)-3);
2500 }
2501 }
2502 }
2503 /* ToDo update other (than DFS) crda regulatory flags (NO_OUTDOOR,
2504 NO_OFDM, PASSIVE_SCAN, NO_IBSS) to pnvEFSTable which doesn't add
2505 these flags and has no implementation yet. */
2506 if (crda_regulatory_entry_valid == VOS_FALSE)
2507 { /* init time */
2508 crda_alpha2[0] = request->alpha2[0];
2509 crda_alpha2[1] = request->alpha2[1];
2510 crda_regulatory_entry_valid = VOS_TRUE;
2511 }
2512 else
2513 { /* none-default country */
2514 run_time_alpha2[0] = request->alpha2[0];
2515 run_time_alpha2[1] = request->alpha2[1];
2516 crda_regulatory_run_time_entry_valid = VOS_TRUE;
2517 }
2518 crda_regulatory_entry_post_processing(wiphy, request, nBandCapability, domain_id);
2519 return 0;
2520}
2521
2522#ifdef CONFIG_ENABLE_LINUX_REG
2523
2524/**------------------------------------------------------------------------
2525 \brief vos_nv_setRegDomain -
2526 \param clientCtxt - Client Context, Not used for PRIMA
2527 regId - Regulatory Domain ID
2528 \return status set REG domain operation
2529 \sa
2530 -------------------------------------------------------------------------*/
2531VOS_STATUS vos_nv_setRegDomain(void * clientCtxt, v_REGDOMAIN_t regId)
2532{
2533
2534 if (regId >= REGDOMAIN_COUNT)
2535 {
2536 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
2537 "VOS set reg domain, invalid REG domain ID %d", regId);
2538 return VOS_STATUS_E_INVAL;
2539 }
2540
2541 /* Set correct channel information based on REG Domain */
2542 regChannels = pnvEFSTable->halnv.tables.regDomains[regId].channels;
2543
2544 return VOS_STATUS_SUCCESS;
2545}
2546
2547/**------------------------------------------------------------------------
2548 \brief vos_nv_getRegDomainFromCountryCode() - get the regulatory domain of
2549 a country given its country code
2550 The \a vos_nv_getRegDomainFromCountryCode() returns the regulatory domain of
2551 a country given its country code. This is done from reading a cached
2552 copy of the binary file.
2553 \param pRegDomain - pointer to regulatory domain
2554 \param countryCode - country code
Kiet Lamb5dffeb2013-10-14 05:37:09 +05302555 \param source - source of the country code
Amar Singhal9a65a6a2013-10-08 18:37:44 -07002556 \return VOS_STATUS_SUCCESS - regulatory domain is found for the given country
2557 VOS_STATUS_E_FAULT - invalid pointer error
2558 VOS_STATUS_E_EMPTY - country code table is empty
2559 VOS_STATUS_E_EXISTS - given country code does not exist in table
2560 \sa
2561 -------------------------------------------------------------------------*/
2562VOS_STATUS vos_nv_getRegDomainFromCountryCode( v_REGDOMAIN_t *pRegDomain,
Kiet Lamb5dffeb2013-10-14 05:37:09 +05302563 const v_COUNTRYCODE_t country_code, v_CountryInfoSource_t source)
Amar Singhal9a65a6a2013-10-08 18:37:44 -07002564{
2565
Amar Singhal61cbd962013-09-05 13:03:40 -07002566 v_CONTEXT_t pVosContext = NULL;
2567 hdd_context_t *pHddCtx = NULL;
2568 struct wiphy *wiphy = NULL;
2569 int i;
Amar Singhal9a65a6a2013-10-08 18:37:44 -07002570 int wait_result;
Madan Mohan Koyyalamudic3a240c2012-09-28 15:34:08 -07002571
Amar Singhal61cbd962013-09-05 13:03:40 -07002572 /* sanity checks */
2573 if (NULL == pRegDomain)
2574 {
2575 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
2576 ("Invalid reg domain pointer") );
2577 return VOS_STATUS_E_FAULT;
2578 }
Madan Mohan Koyyalamudic3a240c2012-09-28 15:34:08 -07002579
Amar Singhal61cbd962013-09-05 13:03:40 -07002580 *pRegDomain = REGDOMAIN_COUNT;
Madan Mohan Koyyalamudic3a240c2012-09-28 15:34:08 -07002581
Amar Singhal9a65a6a2013-10-08 18:37:44 -07002582 if (NULL == country_code)
Amar Singhal61cbd962013-09-05 13:03:40 -07002583 {
2584 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
2585 ("Country code array is NULL"));
2586 return VOS_STATUS_E_FAULT;
2587 }
Madan Mohan Koyyalamudic3a240c2012-09-28 15:34:08 -07002588
Amar Singhal61cbd962013-09-05 13:03:40 -07002589 if (0 == countryInfoTable.countryCount)
2590 {
2591 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
2592 ("Reg domain table is empty") );
2593 return VOS_STATUS_E_EMPTY;
2594 }
Madan Mohan Koyyalamudic3a240c2012-09-28 15:34:08 -07002595
Madan Mohan Koyyalamudic3a240c2012-09-28 15:34:08 -07002596
Amar Singhal61cbd962013-09-05 13:03:40 -07002597 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
Madan Mohan Koyyalamudic3a240c2012-09-28 15:34:08 -07002598
Amar Singhal61cbd962013-09-05 13:03:40 -07002599 if (NULL != pVosContext)
2600 pHddCtx = vos_get_context(VOS_MODULE_ID_HDD, pVosContext);
2601 else
2602 return VOS_STATUS_E_EXISTS;
2603
2604 if (NULL == pHddCtx)
2605 {
2606 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
2607 ("Invalid pHddCtx pointer") );
2608 return VOS_STATUS_E_FAULT;
2609 }
2610
Kiet Lamb5dffeb2013-10-14 05:37:09 +05302611 temp_reg_domain = REGDOMAIN_COUNT;
2612 /* lookup the country in the local database */
2613 for (i = 0; i < countryInfoTable.countryCount &&
2614 REGDOMAIN_COUNT == temp_reg_domain; i++)
2615 {
2616 if (memcmp(country_code, countryInfoTable.countryInfo[i].countryCode,
2617 VOS_COUNTRY_CODE_LEN) == 0)
2618 {
2619 /* country code is found */
2620 /* record the temporary regulatory_domain as well */
2621 temp_reg_domain = countryInfoTable.countryInfo[i].regDomain;
2622 break;
2623 }
2624 }
2625
2626 if (REGDOMAIN_COUNT == temp_reg_domain) {
2627
2628 /* the country was not found in the driver database */
2629 /* so we will return the REGDOMAIN_WORLD to SME/CSR */
2630
2631 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
2632 ("Country does not map to any Regulatory domain"));
2633
2634 temp_reg_domain = REGDOMAIN_WORLD;
2635 }
2636
2637 if (COUNTRY_QUERY == source)
2638 {
2639 *pRegDomain = temp_reg_domain;
2640 return VOS_STATUS_SUCCESS;
2641 }
2642
Amar Singhal61cbd962013-09-05 13:03:40 -07002643 wiphy = pHddCtx->wiphy;
2644
Amar Singhal9a65a6a2013-10-08 18:37:44 -07002645 if (false == wiphy->registered)
2646 {
2647 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
2648 ("wiphy is not yet registered with the kernel") );
2649 return VOS_STATUS_E_FAULT;
2650 }
Amar Singhal61cbd962013-09-05 13:03:40 -07002651
2652 /* We need to query the kernel to get the regulatory information
2653 for this country */
2654
Kiet Lam5e565ef2013-10-12 23:13:13 -07002655
2656 /* First compare the country code with the existing current country code
2657 . If both are same there is no need to query any database */
2658
2659 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_INFO,
2660 ("regdomain request"));
2661
2662 if ((country_code[0] == linux_reg_cc[0]) &&
2663 (country_code[1] == linux_reg_cc[1])) {
2664
2665 /* country code already exists */
Amar Singhal61cbd962013-09-05 13:03:40 -07002666
Amar Singhal9a65a6a2013-10-08 18:37:44 -07002667 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_INFO,
Kiet Lam5e565ef2013-10-12 23:13:13 -07002668 (" country code already exists"));
Amar Singhal9a65a6a2013-10-08 18:37:44 -07002669
Kiet Lam5e565ef2013-10-12 23:13:13 -07002670 *pRegDomain = cur_reg_domain;
Amar Singhal61cbd962013-09-05 13:03:40 -07002671
Kiet Lam5e565ef2013-10-12 23:13:13 -07002672 return VOS_STATUS_SUCCESS;
2673 }
2674 else {
Amar Singhal61cbd962013-09-05 13:03:40 -07002675
Kiet Lam5e565ef2013-10-12 23:13:13 -07002676 /* get the regulatory information from the kernel
2677 database */
Amar Singhal9a65a6a2013-10-08 18:37:44 -07002678
Kiet Lam5e565ef2013-10-12 23:13:13 -07002679 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_WARN,
2680 (" get country information from kernel db"));
2681
Kiet Lam5e565ef2013-10-12 23:13:13 -07002682
Kiet Lamb5dffeb2013-10-14 05:37:09 +05302683 if (COUNTRY_NV == source)
2684 {
2685 INIT_COMPLETION(pHddCtx->linux_reg_req);
2686 regulatory_hint(wiphy, country_code);
2687 wait_result = wait_for_completion_interruptible_timeout(
2688 &pHddCtx->linux_reg_req,
2689 LINUX_REG_WAIT_TIME);
Kiet Lam5e565ef2013-10-12 23:13:13 -07002690
Kiet Lamb5dffeb2013-10-14 05:37:09 +05302691 /* if the country information does not exist with the kernel,
2692 then the driver callback would not be called */
Kiet Lam5e565ef2013-10-12 23:13:13 -07002693
Kiet Lamb5dffeb2013-10-14 05:37:09 +05302694 if (wait_result >= 0) {
Amar Singhal61cbd962013-09-05 13:03:40 -07002695
Kiet Lamb5dffeb2013-10-14 05:37:09 +05302696 /* the driver callback was called. this means the country
2697 regulatory information was found in the kernel database.
2698 The callback would have updated the internal database. Here
2699 update the country and the return value for the regulatory
2700 domain */
Amar Singhal61cbd962013-09-05 13:03:40 -07002701
Kiet Lamb5dffeb2013-10-14 05:37:09 +05302702 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_INFO,
2703 ("runtime country code is found in kernel db"));
2704
2705 *pRegDomain = temp_reg_domain;
2706 cur_reg_domain = temp_reg_domain;
2707 linux_reg_cc[0] = country_code[0];
2708 linux_reg_cc[1] = country_code[1];
2709
2710 return VOS_STATUS_SUCCESS;
2711 }
2712 else {
2713
2714 /* the country information has not been found in the kernel
2715 database, return failure */
2716
2717 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_WARN,
2718 ("runtime country code is not found in kernel db"));
2719
2720 return VOS_STATUS_E_EXISTS;
2721 }
2722 }
2723 else if (COUNTRY_IE == source || COUNTRY_USER == source)
2724 {
2725#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,9,0))
2726 regulatory_hint_user(country_code,NL80211_USER_REG_HINT_USER);
2727#else
2728 regulatory_hint_user(country_code);
2729#endif
Kiet Lam5e565ef2013-10-12 23:13:13 -07002730 *pRegDomain = temp_reg_domain;
Amar Singhal61cbd962013-09-05 13:03:40 -07002731 }
Amar Singhal61cbd962013-09-05 13:03:40 -07002732
Kiet Lamb5dffeb2013-10-14 05:37:09 +05302733 }
Amar Singhal61cbd962013-09-05 13:03:40 -07002734
Kiet Lamb5dffeb2013-10-14 05:37:09 +05302735 return VOS_STATUS_SUCCESS;
Madan Mohan Koyyalamudic3a240c2012-09-28 15:34:08 -07002736}
2737
Amar Singhal9a65a6a2013-10-08 18:37:44 -07002738/* create_crda_regulatory_entry_from_regd should be called during init time */
2739static int create_linux_regulatory_entry_from_regd(struct wiphy *wiphy,
2740 struct regulatory_request *request,
2741 v_U8_t nBandCapability)
2742{
2743 int i, j, n, domain_id;
2744 int bw20_start_channel_index, bw20_end_channel_index;
2745 int bw40_start_channel_index, bw40_end_channel_index;
Tushnim Bhattacharyyaf0951bd2013-10-14 16:22:56 -07002746 v_CONTEXT_t pVosContext = NULL;
2747 hdd_context_t *pHddCtx = NULL;
Amar Singhal9a65a6a2013-10-08 18:37:44 -07002748
2749 if (wiphy->regd == NULL)
2750 {
2751 wiphy_dbg(wiphy, "error: wiphy->regd is NULL\n");
2752 return -1;
2753 }
Tushnim Bhattacharyyaf0951bd2013-10-14 16:22:56 -07002754 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
2755
2756 if (NULL != pVosContext)
2757 {
2758 pHddCtx = vos_get_context(VOS_MODULE_ID_HDD, pVosContext);
2759 if (NULL == pHddCtx)
2760 {
2761 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
2762 ("Invalid pHddCtx pointer") );
2763 }
2764 else
2765 {
2766 pHddCtx->isVHT80Allowed = 0;
2767 }
2768 }
2769 else
2770 {
2771 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
2772 ("Invalid pVosContext pointer") );
2773 }
Amar Singhal9a65a6a2013-10-08 18:37:44 -07002774
2775 domain_id = temp_reg_domain;
2776
2777 for (n = 0; n < NUM_RF_CHANNELS; n++)
2778 pnvEFSTable->halnv.tables.regDomains[domain_id].channels[n].enabled = NV_CHANNEL_DISABLE;
2779
2780 for (i = 0; i < wiphy->regd->n_reg_rules; i++)
2781 {
2782
2783 wiphy_dbg(wiphy, "info: crda rule %d --------------------------------------------\n", i);
2784 bw20_start_channel_index =
2785 bw20_start_freq_to_channel_index(wiphy->regd->reg_rules[i].freq_range.start_freq_khz);
2786 bw20_end_channel_index =
2787 bw20_end_freq_to_channel_index(wiphy->regd->reg_rules[i].freq_range.end_freq_khz);
2788
2789 if (bw20_start_channel_index == -1 || bw20_end_channel_index == -1)
2790 {
2791 wiphy_dbg(wiphy, "error: crda freq not supported, start freq (KHz) %d end freq %d\n",
2792 wiphy->regd->reg_rules[i].freq_range.start_freq_khz,
2793 wiphy->regd->reg_rules[i].freq_range.end_freq_khz);
2794 continue; // skip this rull, but continue to next rule
2795 }
2796
2797 wiphy_dbg(wiphy, "20MHz start freq (KHz) %d end freq %d start ch index %d end ch index %d\n",
2798 wiphy->regd->reg_rules[i].freq_range.start_freq_khz,
2799 wiphy->regd->reg_rules[i].freq_range.end_freq_khz,
2800 bw20_start_channel_index, bw20_end_channel_index);
2801
2802 for (j=bw20_start_channel_index;j<=bw20_end_channel_index;j++)
2803 {
2804 if (channel_in_capable_band(j, nBandCapability) == VOS_FALSE)
2805 {
2806 wiphy_dbg(wiphy, "info: CH %d is not in capable band\n",
2807 rfChannels[j].channelNum);
2808 continue; // skip this channel, continue to next
2809 }
2810
2811 if (wiphy->regd->reg_rules[i].flags & NL80211_RRF_DFS)
2812 {
2813 pnvEFSTable->halnv.tables.regDomains[domain_id].channels[j].enabled = NV_CHANNEL_DFS;
2814 wiphy_dbg(wiphy, "info: CH %d is DFS, max EIRP (mBm) is %d\n", rfChannels[j].channelNum,
2815 wiphy->regd->reg_rules[i].power_rule.max_eirp);
2816 }
2817 else
2818 {
2819 pnvEFSTable->halnv.tables.regDomains[domain_id].channels[j].enabled = NV_CHANNEL_ENABLE;
2820 wiphy_dbg(wiphy, "info: CH %d is enabled, no DFS, max EIRP (mBm) is %d\n", rfChannels[j].channelNum,
2821 wiphy->regd->reg_rules[i].power_rule.max_eirp);
2822 }
2823
2824 /* max_eirp is in mBm (= 100 * dBm) unit */
2825 pnvEFSTable->halnv.tables.regDomains[domain_id].channels[j].pwrLimit =
2826 (tANI_S8) ((wiphy->regd->reg_rules[i].power_rule.max_eirp)/100);
2827 }
2828
2829 /* ignore CRDA max_antenna_gain typical is 3dBi, nv.bin antennaGain is
2830 real gain which should be provided by the real design */
Tushnim Bhattacharyyaf0951bd2013-10-14 16:22:56 -07002831 if (wiphy->regd->reg_rules[i].freq_range.max_bandwidth_khz >= 40000)
Amar Singhal9a65a6a2013-10-08 18:37:44 -07002832 {
Tushnim Bhattacharyyaf0951bd2013-10-14 16:22:56 -07002833 if (wiphy->regd->reg_rules[i].freq_range.max_bandwidth_khz >= 80000)
2834 {
2835 wiphy_dbg(wiphy, "info: 80MHz (channel bonding) is allowed\n");
2836 if (NULL == pHddCtx)
2837 {
2838 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
2839 ("Invalid pHddCtx pointer") );
2840 }
2841 else
2842 {
2843 pHddCtx->isVHT80Allowed = 1;
2844 }
2845
2846
2847 }
2848 else
2849 {
2850 wiphy_dbg(wiphy, "info: ONLY 40MHz (channel bonding) is allowed\n");
2851 }
Amar Singhal9a65a6a2013-10-08 18:37:44 -07002852 bw40_start_channel_index =
2853 bw40_start_freq_to_channel_index(wiphy->regd->reg_rules[i].freq_range.start_freq_khz);
2854 bw40_end_channel_index =
2855 bw40_end_freq_to_channel_index(wiphy->regd->reg_rules[i].freq_range.end_freq_khz);
2856 if (bw40_start_channel_index == -1 || bw40_end_channel_index == -1)
2857 {
2858 wiphy_dbg(wiphy, "error: crda freq not supported, start_freq_khz %d end_freq_khz %d\n",
2859 wiphy->regd->reg_rules[i].freq_range.start_freq_khz,
2860 wiphy->regd->reg_rules[i].freq_range.end_freq_khz);
2861 continue; // skip this rull, but continue to next rule
2862 }
2863
2864 wiphy_dbg(wiphy, "40MHz start freq (KHz) %d end freq %d start ch index %d end ch index %d\n",
2865 wiphy->regd->reg_rules[i].freq_range.start_freq_khz,
2866 wiphy->regd->reg_rules[i].freq_range.end_freq_khz,
2867 bw40_start_channel_index, bw40_end_channel_index);
2868 for (j=bw40_start_channel_index;j<=bw40_end_channel_index;j++)
2869 {
2870 if (channel_in_capable_band(j, nBandCapability) == VOS_FALSE)
2871 continue; // skip this channel, continue to next
2872 if (wiphy->regd->reg_rules[i].flags & NL80211_RRF_DFS)
2873 {
2874 pnvEFSTable->halnv.tables.regDomains[domain_id].channels[j].enabled = NV_CHANNEL_DFS;
2875 wiphy_dbg(wiphy, "info: 40MHz centered on CH %d is DFS\n", rfChannels[j].channelNum);
2876 }
2877 else
2878 {
2879 pnvEFSTable->halnv.tables.regDomains[domain_id].channels[j].enabled = NV_CHANNEL_ENABLE;
2880 wiphy_dbg(wiphy, "info: 40MHz centered on CH %d is enabled, no DFS\n", rfChannels[j].channelNum);
2881 }
2882 /* set 40MHz channel power as half (- 3 dB) of 20MHz */
2883 pnvEFSTable->halnv.tables.regDomains[domain_id].channels[j].pwrLimit =
2884 (tANI_S8) (((wiphy->regd->reg_rules[i].power_rule.max_eirp)/100)-3);
2885 }
2886 }
2887 }
2888
2889 return 0;
2890}
2891
Kiet Lam5e565ef2013-10-12 23:13:13 -07002892/* create_linux_regulatory_entry to populate internal structures from wiphy */
2893static int create_linux_regulatory_entry(struct wiphy *wiphy,
2894 struct regulatory_request *request,
2895 v_U8_t nBandCapability)
2896{
2897 int i, j, m;
2898 int k = 0, n = 0;
Kiet Lame2689e42013-10-25 19:35:12 +05302899#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,9,0))
2900 int err;
2901#endif
2902 const struct ieee80211_reg_rule *reg_rule;
Tushnim Bhattacharyyaf0951bd2013-10-14 16:22:56 -07002903 v_CONTEXT_t pVosContext = NULL;
2904 hdd_context_t *pHddCtx = NULL;
2905
2906 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
2907
2908 if (NULL != pVosContext)
2909 {
2910 pHddCtx = vos_get_context(VOS_MODULE_ID_HDD, pVosContext);
2911 if (NULL == pHddCtx)
2912 {
2913 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
2914 ("Invalid pHddCtx pointer") );
2915 }
2916 else
2917 {
2918 pHddCtx->isVHT80Allowed = 0;
2919 }
2920 }
2921 else
2922 {
2923 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
2924 ("Invalid pVosContext pointer") );
2925 }
Kiet Lam5e565ef2013-10-12 23:13:13 -07002926
2927 /* 20MHz channels */
2928 if (nBandCapability == eCSR_BAND_24)
2929 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_INFO,
2930 "BandCapability is set to 2G only\n");
2931
2932 for (i = 0, m = 0; i<IEEE80211_NUM_BANDS; i++)
2933 {
2934 /* 5G only */
2935 if (i == IEEE80211_BAND_2GHZ && nBandCapability == eCSR_BAND_5G)
2936 continue;
2937
2938 /* 2G only */
2939 else if (i == IEEE80211_BAND_5GHZ && nBandCapability == eCSR_BAND_24)
2940 continue;
2941
2942 if (wiphy->bands[i] == NULL)
2943 {
2944
2945 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
2946 "error: wiphy->bands is NULL, i = %d\n", i);
2947 return -1;
2948 }
2949
2950 /* internal channels[] is one continous array for both 2G and 5G bands
2951 m is internal starting channel index for each band */
2952
2953 if (i == 0)
2954 m = 0;
2955 else
2956 m = wiphy->bands[i-1]->n_channels + m;
2957
2958 for (j = 0; j < wiphy->bands[i]->n_channels; j++)
2959 {
2960 /* k = (m + j) is internal current channel index for 20MHz channel
2961 n is internal channel index for corresponding 40MHz channel */
2962
2963 k = m + j;
2964 n = bw20_ch_index_to_bw40_ch_index(k);
2965
2966 if (n == -1)
2967 return -1;
2968
Kiet Lame2689e42013-10-25 19:35:12 +05302969 /* If the regulatory rules for a country do not explicilty
2970 * require a passive scan on a frequency, lift the passive
2971 * scan restriction
2972 */
2973#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,9,0))
2974 reg_rule = freq_reg_info(wiphy,
2975 MHZ_TO_KHZ(wiphy->bands[i]->channels[j].center_freq));
2976#else
2977 err = freq_reg_info(wiphy,
2978 MHZ_TO_KHZ(wiphy->bands[i]->channels[j].center_freq),
2979 0, &reg_rule);
2980#endif
2981
2982#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,9,0))
2983 if (!IS_ERR(reg_rule))
2984#else
2985 if (0 == err)
2986#endif
2987 {
2988 if (!(reg_rule->flags & NL80211_RRF_PASSIVE_SCAN))
2989 {
2990 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_INFO,
2991 "%s: Remove passive scan restriction for %u",
2992 __func__, wiphy->bands[i]->channels[j].center_freq);
2993 wiphy->bands[i]->channels[j].flags &= ~IEEE80211_CHAN_PASSIVE_SCAN;
2994 }
2995 }
2996
Kiet Lam5e565ef2013-10-12 23:13:13 -07002997 if (wiphy->bands[i]->channels[j].flags & IEEE80211_CHAN_DISABLED)
2998 {
2999 if (pnvEFSTable == NULL)
3000 {
3001 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
3002 "error: pnvEFSTable is NULL, probably not parsed nv.bin yet\n");
3003 return -1;
3004 }
3005 pnvEFSTable->halnv.tables.regDomains[temp_reg_domain].channels[k].enabled =
3006 NV_CHANNEL_DISABLE;
3007 pnvEFSTable->halnv.tables.regDomains[temp_reg_domain].channels[n].enabled =
3008 NV_CHANNEL_DISABLE;
3009 }
Kiet Lame2689e42013-10-25 19:35:12 +05303010 /* nv cannot distinguish between DFS and passive channels */
3011 else if (wiphy->bands[i]->channels[j].flags &
3012 (IEEE80211_CHAN_RADAR | IEEE80211_CHAN_PASSIVE_SCAN))
Kiet Lam5e565ef2013-10-12 23:13:13 -07003013 {
3014 pnvEFSTable->halnv.tables.regDomains[temp_reg_domain].channels[k].enabled =
3015 NV_CHANNEL_DFS;
3016
3017 /* max_power is in mBm = 100 * dBm */
3018 pnvEFSTable->halnv.tables.regDomains[temp_reg_domain].channels[k].pwrLimit =
3019 (tANI_S8) ((wiphy->bands[i]->channels[j].max_power)/100);
3020 if ((wiphy->bands[i]->channels[j].flags & IEEE80211_CHAN_NO_HT40) == 0)
3021 {
3022 pnvEFSTable->halnv.tables.regDomains[temp_reg_domain].channels[n].enabled =
3023 NV_CHANNEL_DFS;
3024
3025 /* 40MHz channel power is half of 20MHz (-3dB) ?? */
3026 pnvEFSTable->halnv.tables.regDomains[temp_reg_domain].channels[n].pwrLimit =
3027 (tANI_S8) (((wiphy->bands[i]->channels[j].max_power)/100)-3);
3028 }
Tushnim Bhattacharyyaf0951bd2013-10-14 16:22:56 -07003029 if ((wiphy->bands[i]->channels[j].flags & IEEE80211_CHAN_NO_80MHZ) == 0)
3030 {
3031 if (NULL == pHddCtx)
3032 {
3033 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
3034 ("Invalid pHddCtx pointer") );
3035 }
3036 else
3037 {
3038 pHddCtx->isVHT80Allowed = 1;
3039 }
3040 }
Kiet Lam5e565ef2013-10-12 23:13:13 -07003041 }
3042 else /* Enable is only last flag we support */
3043 {
3044 pnvEFSTable->halnv.tables.regDomains[temp_reg_domain].channels[k].enabled =
3045 NV_CHANNEL_ENABLE;
3046
3047 /* max_power is in dBm */
3048 pnvEFSTable->halnv.tables.regDomains[temp_reg_domain].channels[k].pwrLimit =
3049 (tANI_S8) ((wiphy->bands[i]->channels[j].max_power)/100);
3050 if ((wiphy->bands[i]->channels[j].flags & IEEE80211_CHAN_NO_HT40) == 0)
3051 {
3052 pnvEFSTable->halnv.tables.regDomains[temp_reg_domain].channels[n].enabled =
3053 NV_CHANNEL_ENABLE;
3054 /* 40MHz channel power is half of 20MHz (-3dB) */
3055 pnvEFSTable->halnv.tables.regDomains[temp_reg_domain].channels[n].pwrLimit =
3056 (tANI_S8) (((wiphy->bands[i]->channels[j].max_power)/100)-3);
3057 }
Tushnim Bhattacharyyaf0951bd2013-10-14 16:22:56 -07003058 if ((wiphy->bands[i]->channels[j].flags & IEEE80211_CHAN_NO_80MHZ) == 0)
3059 {
3060 if (NULL == pHddCtx)
3061 {
3062 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
3063 ("Invalid pHddCtx pointer") );
3064 }
3065 else
3066 {
3067 pHddCtx->isVHT80Allowed = 1;
3068 }
3069 }
3070
Kiet Lam5e565ef2013-10-12 23:13:13 -07003071 }
3072
Kiet Lame2689e42013-10-25 19:35:12 +05303073
Kiet Lam5e565ef2013-10-12 23:13:13 -07003074 }
3075 }
3076
3077 if (k == 0)
3078 return -1;
3079
3080 return 0;
3081}
3082
3083
Madan Mohan Koyyalamudic3a240c2012-09-28 15:34:08 -07003084/*
Amar Singhal61cbd962013-09-05 13:03:40 -07003085 * Function: wlan_hdd_linux_reg_notifier
Madan Mohan Koyyalamudic3a240c2012-09-28 15:34:08 -07003086 * This function is called from cfg80211 core to provide regulatory settings
3087 * after new country is requested or intersected (init, user input or 11d)
Amar Singhal9a65a6a2013-10-08 18:37:44 -07003088 * This function is used to create a CRDA regulatory settings entry into internal
3089 * regulatory setting table.
Madan Mohan Koyyalamudic3a240c2012-09-28 15:34:08 -07003090 */
Amar Singhal9a65a6a2013-10-08 18:37:44 -07003091#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,9,0))
Amar Singhal61cbd962013-09-05 13:03:40 -07003092void wlan_hdd_linux_reg_notifier(struct wiphy *wiphy,
Yue Ma04177002013-08-19 12:04:25 -07003093 struct regulatory_request *request)
3094#else
Amar Singhal9a65a6a2013-10-08 18:37:44 -07003095int wlan_hdd_linux_reg_notifier(struct wiphy *wiphy,
Madan Mohan Koyyalamudic3a240c2012-09-28 15:34:08 -07003096 struct regulatory_request *request)
Yue Ma04177002013-08-19 12:04:25 -07003097#endif
Madan Mohan Koyyalamudic3a240c2012-09-28 15:34:08 -07003098{
3099 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
Amar Singhal9a65a6a2013-10-08 18:37:44 -07003100 tANI_U8 nBandCapability;
Kiet Lam5e565ef2013-10-12 23:13:13 -07003101 v_COUNTRYCODE_t country_code;
3102 int i;
Tushnim Bhattacharyyaf0951bd2013-10-14 16:22:56 -07003103 v_BOOL_t isVHT80Allowed;
Amar Singhal61cbd962013-09-05 13:03:40 -07003104
Amar Singhal9a65a6a2013-10-08 18:37:44 -07003105 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_INFO,
Tushnim Bhattacharyyab676a2e2013-10-29 17:27:43 -07003106 "cfg80211 reg notifier callback for country for initiator %d", request->initiator);
Amar Singhal61cbd962013-09-05 13:03:40 -07003107
Arif Hussain600c6122013-10-03 11:49:23 -07003108 if (pHddCtx->isLoadUnloadInProgress)
3109 {
3110 wiphy_dbg(wiphy, "info: %s: Unloading/Loading in Progress. Ignore!!!",
3111 __func__);
3112 return;
3113 }
Amar Singhal61cbd962013-09-05 13:03:40 -07003114 /* first check if this callback is in response to the driver callback */
3115
Amar Singhal9a65a6a2013-10-08 18:37:44 -07003116 if (request->initiator == NL80211_REGDOM_SET_BY_DRIVER)
3117 {
Amar Singhal61cbd962013-09-05 13:03:40 -07003118
Kiet Lam5e565ef2013-10-12 23:13:13 -07003119 nBandCapability = pHddCtx->cfg_ini->nBandCapability;
Tushnim Bhattacharyyaf0951bd2013-10-14 16:22:56 -07003120 isVHT80Allowed = pHddCtx->isVHT80Allowed;
Kiet Lam5e565ef2013-10-12 23:13:13 -07003121 if (create_linux_regulatory_entry(wiphy, request, pHddCtx->cfg_ini->nBandCapability) == 0)
3122 {
Amar Singhal61cbd962013-09-05 13:03:40 -07003123
Kiet Lam5e565ef2013-10-12 23:13:13 -07003124 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_INFO,
Amar Singhal9a65a6a2013-10-08 18:37:44 -07003125 (" regulatory entry created"));
Kiet Lam5e565ef2013-10-12 23:13:13 -07003126 }
Tushnim Bhattacharyyaf0951bd2013-10-14 16:22:56 -07003127 if (pHddCtx->isVHT80Allowed != isVHT80Allowed)
3128 {
3129 hdd_checkandupdate_phymode( pHddCtx);
3130 }
Amar Singhal61cbd962013-09-05 13:03:40 -07003131
Kiet Lam5e565ef2013-10-12 23:13:13 -07003132 complete(&pHddCtx->linux_reg_req);
3133 }
3134
3135 else if (request->initiator == NL80211_REGDOM_SET_BY_USER)
3136 {
3137
3138 /* first lookup the country in the local database */
3139
3140 country_code[0] = request->alpha2[0];
3141 country_code[1] = request->alpha2[1];
3142
3143 temp_reg_domain = REGDOMAIN_COUNT;
3144 for (i = 0; i < countryInfoTable.countryCount &&
3145 REGDOMAIN_COUNT == temp_reg_domain; i++)
3146 {
3147 if (memcmp(country_code, countryInfoTable.countryInfo[i].countryCode,
3148 VOS_COUNTRY_CODE_LEN) == 0)
3149 {
3150 /* country code is found */
3151 /* record the temporary regulatory_domain as well */
3152 temp_reg_domain = countryInfoTable.countryInfo[i].regDomain;
3153 break;
3154 }
3155 }
3156
3157 if (REGDOMAIN_COUNT == temp_reg_domain)
3158 temp_reg_domain = REGDOMAIN_WORLD;
3159
3160 nBandCapability = pHddCtx->cfg_ini->nBandCapability;
Tushnim Bhattacharyyaf0951bd2013-10-14 16:22:56 -07003161 isVHT80Allowed = pHddCtx->isVHT80Allowed;
Kiet Lam5e565ef2013-10-12 23:13:13 -07003162 if (create_linux_regulatory_entry(wiphy, request,
3163 pHddCtx->cfg_ini->nBandCapability) == 0)
3164 {
3165 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_INFO,
3166 (" regulatory entry created"));
3167
3168 }
Tushnim Bhattacharyyaf0951bd2013-10-14 16:22:56 -07003169 if (pHddCtx->isVHT80Allowed != isVHT80Allowed)
3170 {
3171 hdd_checkandupdate_phymode( pHddCtx);
3172 }
Kiet Lam5e565ef2013-10-12 23:13:13 -07003173
3174 cur_reg_domain = temp_reg_domain;
3175 linux_reg_cc[0] = country_code[0];
3176 linux_reg_cc[1] = country_code[1];
3177
3178 /* now pass the new country information to sme */
3179 sme_GenericChangeCountryCode(pHddCtx->hHal, country_code,
3180 temp_reg_domain);
3181
Madan Mohan Koyyalamudic3a240c2012-09-28 15:34:08 -07003182 }
Tushnim Bhattacharyyab676a2e2013-10-29 17:27:43 -07003183 else if (request->initiator == NL80211_REGDOM_SET_BY_CORE)
3184 {
3185 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
3186 "CC from kernel %c %c", request->alpha2[0], request->alpha2[1]);
3187
3188 /* now pass the country information to sme to make sure driver is in
3189 sync in case we are back to world mode*/
3190 if (request->alpha2[0] == '0' && request->alpha2[1] == '0')
3191 {
3192 nBandCapability = pHddCtx->cfg_ini->nBandCapability;
3193 isVHT80Allowed = pHddCtx->isVHT80Allowed;
3194 if (create_linux_regulatory_entry(wiphy, request,
3195 pHddCtx->cfg_ini->nBandCapability) == 0)
3196 {
3197 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
3198 (" regulatory entry created"));
3199
3200 }
3201 if (pHddCtx->isVHT80Allowed != isVHT80Allowed)
3202 {
3203 hdd_checkandupdate_phymode( pHddCtx);
3204 }
3205
3206 cur_reg_domain = REGDOMAIN_WORLD;
3207 linux_reg_cc[0] = country_code[0];
3208 linux_reg_cc[1] = country_code[1];
3209
3210 country_code[0] = request->alpha2[0];
3211 country_code[1] = request->alpha2[1];
3212 sme_GenericChangeCountryCode(pHddCtx->hHal, country_code,
3213 REGDOMAIN_COUNT);
3214 }
3215 }
Madan Mohan Koyyalamudia97a5f12013-05-16 12:52:48 +05303216
Amar Singhal9a65a6a2013-10-08 18:37:44 -07003217#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,9,0))
Yue Ma04177002013-08-19 12:04:25 -07003218 return;
Amar Singhal9a65a6a2013-10-08 18:37:44 -07003219#else
3220 return 0;
3221#endif
Madan Mohan Koyyalamudic3a240c2012-09-28 15:34:08 -07003222}
Amar Singhal61cbd962013-09-05 13:03:40 -07003223
Kiet Lam5e565ef2013-10-12 23:13:13 -07003224
Kiet Lam53522172013-10-11 20:57:16 -07003225/* initialize wiphy from NV.bin */
3226VOS_STATUS vos_init_wiphy_from_nv_bin(void)
3227{
3228 int i, j, m;
3229 int k = 0;
3230 v_REGDOMAIN_t reg_domain;
3231 v_CONTEXT_t pVosContext = NULL;
3232 hdd_context_t *pHddCtx = NULL;
3233 struct wiphy *wiphy = NULL;
3234
3235 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
3236
3237 if (NULL != pVosContext)
3238 pHddCtx = vos_get_context(VOS_MODULE_ID_HDD, pVosContext);
3239 else
3240 return VOS_STATUS_E_EXISTS;
3241
3242 if (NULL == pHddCtx)
3243 {
3244 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
3245 ("Invalid pHddCtx pointer") );
3246 return VOS_STATUS_E_FAULT;
3247 }
3248
3249 wiphy = pHddCtx->wiphy;
3250
3251 if (('0' == pnvEFSTable->halnv.tables.defaultCountryTable.countryCode[0])
3252 &&
3253 ('0' == pnvEFSTable->halnv.tables.defaultCountryTable.countryCode[1]))
3254 {
3255 /* default country is world roaming */
3256
3257 reg_domain = REGDOMAIN_WORLD;
3258 wiphy->flags |= WIPHY_FLAG_CUSTOM_REGULATORY;
3259 }
3260 else if (REGDOMAIN_WORLD ==
3261 pnvEFSTable->halnv.tables.defaultCountryTable.regDomain) {
3262
3263 reg_domain = pnvEFSTable->halnv.tables.defaultCountryTable.regDomain;
3264 wiphy->flags |= WIPHY_FLAG_CUSTOM_REGULATORY;
3265 }
3266 else {
3267
3268 reg_domain = pnvEFSTable->halnv.tables.defaultCountryTable.regDomain;
3269 wiphy->flags |= WIPHY_FLAG_STRICT_REGULATORY;
3270 }
3271
Kiet Lam19a0d0e2013-11-16 13:57:41 -08003272 m = 0;
Kiet Lam53522172013-10-11 20:57:16 -07003273 for (i = 0; i < IEEE80211_NUM_BANDS; i++)
3274 {
3275
3276 if (wiphy->bands[i] == NULL)
3277 {
3278 pr_info("error: wiphy->bands[i] is NULL, i = %d\n", i);
Kiet Lam19a0d0e2013-11-16 13:57:41 -08003279 continue;
Kiet Lam53522172013-10-11 20:57:16 -07003280 }
3281
3282 /* internal channels[] is one continous array for both 2G and 5G bands
3283 m is internal starting channel index for each band */
Kiet Lam53522172013-10-11 20:57:16 -07003284
3285 for (j = 0; j < wiphy->bands[i]->n_channels; j++)
3286 {
3287 /* k = (m + j) is internal current channel index */
3288 k = m + j;
3289
3290 if (pnvEFSTable->halnv.tables.regDomains[reg_domain].channels[k].enabled ==
3291 NV_CHANNEL_DISABLE)
3292 wiphy->bands[i]->channels[j].flags |= IEEE80211_CHAN_DISABLED;
3293
3294 else if (pnvEFSTable->halnv.tables.regDomains[reg_domain].channels[k].enabled ==
3295 NV_CHANNEL_DFS) {
3296
3297 wiphy->bands[i]->channels[j].flags |= IEEE80211_CHAN_PASSIVE_SCAN;
3298
3299 wiphy->bands[i]->channels[j].max_power =
3300 (pnvEFSTable->halnv.tables.regDomains[reg_domain].channels[k].pwrLimit)*100;
3301 }
3302
3303 else if (pnvEFSTable->halnv.tables.regDomains[reg_domain].channels[k].enabled ==
3304 NV_CHANNEL_ENABLE) {
3305
3306 wiphy->bands[i]->channels[j].max_power =
3307 (pnvEFSTable->halnv.tables.regDomains[reg_domain].channels[k].pwrLimit)*100;
3308 }
3309 }
Kiet Lam19a0d0e2013-11-16 13:57:41 -08003310
3311 m += wiphy->bands[i]->n_channels;
Kiet Lam53522172013-10-11 20:57:16 -07003312 }
3313
3314 return VOS_STATUS_SUCCESS;
3315}
3316
3317
Amar Singhal61cbd962013-09-05 13:03:40 -07003318#else
3319
3320/**------------------------------------------------------------------------
Amar Singhal9a65a6a2013-10-08 18:37:44 -07003321 \brief vos_nv_setRegDomain -
3322 \param clientCtxt - Client Context, Not used for PRIMA
3323 regId - Regulatory Domain ID
3324 \return status set REG domain operation
3325 \sa
3326 -------------------------------------------------------------------------*/
3327VOS_STATUS vos_nv_setRegDomain(void * clientCtxt, v_REGDOMAIN_t regId)
3328{
3329 v_CONTEXT_t pVosContext = NULL;
3330 hdd_context_t *pHddCtx = NULL;
3331 struct wiphy *wiphy = NULL;
3332 /* Client Context Argumant not used for PRIMA */
3333 if (regId >= REGDOMAIN_COUNT)
3334 {
3335 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
3336 "VOS set reg domain, invalid REG domain ID %d", regId);
3337 return VOS_STATUS_E_INVAL;
3338 }
3339
3340 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
3341 if (NULL != pVosContext)
3342 pHddCtx = vos_get_context(VOS_MODULE_ID_HDD, pVosContext);
3343 else
3344 return VOS_STATUS_E_EXISTS;
3345 /* Set correct channel information based on REG Domain */
3346 regChannels = pnvEFSTable->halnv.tables.regDomains[regId].channels;
3347
3348 /* when CRDA is not running then we are world roaming.
3349 In this case if 11d is enabled, then country code should
3350 be update on basis of world roaming */
3351 if (NULL != pHddCtx)
3352 {
3353 wiphy = pHddCtx->wiphy;
3354 regulatory_hint(wiphy, "00");
3355 }
3356 return VOS_STATUS_SUCCESS;
3357}
3358
3359
3360/**------------------------------------------------------------------------
Amar Singhal61cbd962013-09-05 13:03:40 -07003361 \brief vos_nv_getRegDomainFromCountryCode() - get the regulatory domain of
3362 a country given its country code
3363 The \a vos_nv_getRegDomainFromCountryCode() returns the regulatory domain of
3364 a country given its country code. This is done from reading a cached
3365 copy of the binary file.
3366 \param pRegDomain - pointer to regulatory domain
3367 \param countryCode - country code
Kiet Lamb5dffeb2013-10-14 05:37:09 +05303368 \param source - source of the country code
Amar Singhal61cbd962013-09-05 13:03:40 -07003369 \return VOS_STATUS_SUCCESS - regulatory domain is found for the given country
3370 VOS_STATUS_E_FAULT - invalid pointer error
3371 VOS_STATUS_E_EMPTY - country code table is empty
3372 VOS_STATUS_E_EXISTS - given country code does not exist in table
3373 \sa
3374 -------------------------------------------------------------------------*/
3375VOS_STATUS vos_nv_getRegDomainFromCountryCode( v_REGDOMAIN_t *pRegDomain,
Kiet Lamb5dffeb2013-10-14 05:37:09 +05303376 const v_COUNTRYCODE_t countryCode, v_CountryInfoSource_t source)
Amar Singhal61cbd962013-09-05 13:03:40 -07003377{
Amar Singhal9a65a6a2013-10-08 18:37:44 -07003378 int i;
3379 v_CONTEXT_t pVosContext = NULL;
3380 hdd_context_t *pHddCtx = NULL;
3381 struct wiphy *wiphy = NULL;
3382 int status;
Kiet Lam5e565ef2013-10-12 23:13:13 -07003383
Amar Singhal9a65a6a2013-10-08 18:37:44 -07003384 // sanity checks
3385 if (NULL == pRegDomain)
3386 {
3387 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
3388 ("Invalid reg domain pointer\n") );
3389 return VOS_STATUS_E_FAULT;
3390 }
3391 *pRegDomain = REGDOMAIN_COUNT;
Amar Singhal61cbd962013-09-05 13:03:40 -07003392
Amar Singhal9a65a6a2013-10-08 18:37:44 -07003393 if (NULL == countryCode)
3394 {
3395 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
3396 ("Country code array is NULL\r\n") );
3397 return VOS_STATUS_E_FAULT;
3398 }
3399 if (0 == countryInfoTable.countryCount)
3400 {
3401 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
3402 ("Reg domain table is empty\r\n") );
3403 return VOS_STATUS_E_EMPTY;
3404 }
3405 /* If CRDA regulatory settings is valid, i.e. crda is enabled
3406 and reg_notifier is called back.
3407 Intercept here and redirect to the Reg domain table's CRDA
3408 entry if country code is crda's country.
3409 last one NUM_REG_DOMAINS-1 is reserved for crda */
3410 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_INFO_HIGH,
3411 "vos_nv_getRegDomainFromCountryCode %c%c\n",
3412 countryCode[0], countryCode[1]);
3413
3414 if (crda_regulatory_entry_valid == VOS_TRUE)
3415 {
3416 if (crda_alpha2[0]==countryCode[0] && crda_alpha2[1]==countryCode[1])
3417 {
3418 *pRegDomain = NUM_REG_DOMAINS-1;
3419 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_INFO_HIGH,
3420 "vos_nv_getRegDomainFromCountryCode return crda init entry\n");
3421 return VOS_STATUS_SUCCESS;
3422 }
3423 if (run_time_alpha2[0]==countryCode[0] &&
3424 run_time_alpha2[1]==countryCode[1] &&
3425 crda_regulatory_run_time_entry_valid == VOS_TRUE)
3426 {
3427 *pRegDomain = NUM_REG_DOMAINS-2;
3428 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_INFO_HIGH,
3429 "vos_nv_getRegDomainFromCountryCode return crda none-default country entry\n");
3430 return VOS_STATUS_SUCCESS;
3431 }
3432 else
3433 {
3434 crda_regulatory_run_time_entry_valid = VOS_FALSE;
3435 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
3436 if (NULL != pVosContext)
3437 pHddCtx = vos_get_context(VOS_MODULE_ID_HDD, pVosContext);
3438 else
3439 return VOS_STATUS_E_EXISTS;
3440 if (NULL == pHddCtx)
3441 {
3442 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
3443 ("Invalid pHddCtx pointer\r\n") );
3444 return VOS_STATUS_E_FAULT;
3445 }
3446
3447 wiphy = pHddCtx->wiphy;
3448
3449 INIT_COMPLETION(pHddCtx->driver_crda_req);
3450 regulatory_hint(wiphy, countryCode);
3451 status = wait_for_completion_interruptible_timeout(
3452 &pHddCtx->driver_crda_req,
3453 msecs_to_jiffies(CRDA_WAIT_TIME));
3454 if (!status)
3455 {
3456 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
3457 "%s: Timeout waiting for CRDA REQ", __func__);
3458 }
3459
3460 if (crda_regulatory_run_time_entry_valid == VOS_TRUE)
3461 {
3462 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_INFO_HIGH,
3463 "vos_nv_getRegDomainFromCountryCode return crda new none-default country entry\n");
3464 return VOS_STATUS_SUCCESS;
3465 }
3466 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
3467 "vos_nv_getRegDomainFromCountryCode failed to get crda new none-default country entry\n");
3468 return VOS_STATUS_E_EXISTS;
3469 }
3470 }
3471
3472 // iterate the country info table until end of table or the country code
3473 // is found
3474 for (i = 0; i < countryInfoTable.countryCount &&
3475 REGDOMAIN_COUNT == *pRegDomain; i++)
3476 {
3477 if (memcmp(countryCode, countryInfoTable.countryInfo[i].countryCode,
3478 VOS_COUNTRY_CODE_LEN) == 0)
3479 {
3480 // country code is found
3481 *pRegDomain = countryInfoTable.countryInfo[i].regDomain;
3482 }
3483 }
3484 if (REGDOMAIN_COUNT != *pRegDomain)
3485 {
3486 return VOS_STATUS_SUCCESS;
3487 }
3488 else
3489 {
3490 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_WARN,
3491 ("country code is not found\r\n"));
3492 return VOS_STATUS_E_EXISTS;
3493 }
3494}
3495
3496
3497/*
3498 * Function: wlan_hdd_crda_reg_notifier
3499 * This function is called from cfg80211 core to provide regulatory settings
3500 * after new country is requested or intersected (init, user input or 11d)
3501 * This function is used to create a CRDA regulatory settings entry into internal
3502 * regulatory setting table.
3503 */
3504#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,9,0))
3505void wlan_hdd_crda_reg_notifier(struct wiphy *wiphy,
3506 struct regulatory_request *request)
3507#else
3508int wlan_hdd_crda_reg_notifier(struct wiphy *wiphy,
3509 struct regulatory_request *request)
3510#endif
3511{
3512 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
3513 v_REGDOMAIN_t domainIdCurrent;
3514 tANI_U8 ccode[WNI_CFG_COUNTRY_CODE_LEN];
3515 tANI_U8 uBufLen = WNI_CFG_COUNTRY_CODE_LEN;
3516 tANI_U8 nBandCapability;
3517 int i,j,k,m;
3518
3519 wiphy_dbg(wiphy, "info: cfg80211 reg_notifier callback for country"
3520 " %c%c\n", request->alpha2[0], request->alpha2[1]);
3521 if (request->initiator == NL80211_REGDOM_SET_BY_USER)
Amar Singhal61cbd962013-09-05 13:03:40 -07003522 {
Amar Singhal9a65a6a2013-10-08 18:37:44 -07003523 wiphy_dbg(wiphy, "info: set by user\n");
3524 if (create_crda_regulatory_entry(wiphy, request, pHddCtx->cfg_ini->nBandCapability) != 0)
3525#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,9,0))
3526 return;
3527#else
3528 return 0;
3529#endif
3530 // ToDo
3531 /* Don't change default country code to CRDA country code by user req */
3532 /* Shouldcall sme_ChangeCountryCode to send a message to trigger read
3533 regd for new country settings */
3534 //sme_ChangeCountryCode(pHddCtx->hHal, NULL,
3535 // &country_code[0], pAdapter, pHddCtx->pvosContext);
Amar Singhal61cbd962013-09-05 13:03:40 -07003536 }
Amar Singhal9a65a6a2013-10-08 18:37:44 -07003537 else if (request->initiator == NL80211_REGDOM_SET_BY_COUNTRY_IE)
Amar Singhal61cbd962013-09-05 13:03:40 -07003538 {
Amar Singhal9a65a6a2013-10-08 18:37:44 -07003539 wiphy_dbg(wiphy, "info: set by country IE\n");
3540 if (create_crda_regulatory_entry(wiphy, request, pHddCtx->cfg_ini->nBandCapability) != 0)
3541#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,9,0))
3542 return;
3543#else
3544 return 0;
3545#endif
3546 // ToDo
3547 /* Intersect of 11d and crda settings */
Amar Singhal61cbd962013-09-05 13:03:40 -07003548
Amar Singhal9a65a6a2013-10-08 18:37:44 -07003549 /* Don't change default country code to CRDA country code by 11d req */
3550 /* for every adapter call sme_ChangeCountryCode to trigger read regd
3551 for intersected new country settings */
3552 // sme_ChangeCountryCode(pHddCtx->hHal, NULL,
3553 // &country_code[0], pAdapter, pHddCtx->pvosContext);
3554 }
3555 else if (request->initiator == NL80211_REGDOM_SET_BY_DRIVER ||
3556 (request->initiator == NL80211_REGDOM_SET_BY_CORE))
Amar Singhal61cbd962013-09-05 13:03:40 -07003557 {
Amar Singhal9a65a6a2013-10-08 18:37:44 -07003558 if ( eHAL_STATUS_SUCCESS != sme_GetCountryCode(pHddCtx->hHal, ccode, &uBufLen))
3559 {
3560 wiphy_dbg(wiphy, "info: set by driver CCODE ERROR\n");
3561#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,9,0))
3562 return;
3563#else
3564 return 0;
3565#endif
3566 }
3567 if (eHAL_STATUS_SUCCESS != sme_GetRegulatoryDomainForCountry (pHddCtx->hHal,
3568 ccode, (v_REGDOMAIN_t *) &domainIdCurrent))
3569 {
3570 wiphy_dbg(wiphy, "info: set by driver ERROR\n");
3571#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,9,0))
3572 return;
3573#else
3574 return 0;
3575#endif
3576 }
3577
3578 wiphy_dbg(wiphy, "country: %c%c set by driver\n",ccode[0],ccode[1]);
3579 /* if set by driver itself, it means driver can accept the crda
3580 regulatory settings and wiphy->regd should be populated with crda
3581 settings. iwiphy->bands doesn't seem to set ht40 flags in kernel
3582 correctly, this may be fixed by later kernel */
3583
3584 nBandCapability = pHddCtx->cfg_ini->nBandCapability;
3585 for (i = 0, m = 0; i < IEEE80211_NUM_BANDS; i++)
3586 {
3587 if (NULL == wiphy->bands[i])
3588 {
3589 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
3590 "error: wiphy->bands[i] is NULL, i = %d", i);
3591 continue;
3592 }
3593
3594 // internal channels[] is one continous array for both 2G and 5G bands
3595 // m is internal starting channel index for each band
3596 if (0 == i)
3597 {
3598 m = 0;
3599 }
3600 else
3601 {
3602 m = wiphy->bands[i-1]?wiphy->bands[i-1]->n_channels + m:m;
3603 }
3604
3605 for (j=0; j<wiphy->bands[i]->n_channels; j++)
3606 {
3607 // k = (m + j) is internal current channel index for 20MHz channel
3608 // n is internal channel index for corresponding 40MHz channel
3609 k = m + j;
3610 if (IEEE80211_BAND_2GHZ == i && eCSR_BAND_5G == nBandCapability) // 5G only
3611 {
3612 // Enable social channels for P2P
3613 if ((2412 == wiphy->bands[i]->channels[j].center_freq ||
3614 2437 == wiphy->bands[i]->channels[j].center_freq ||
3615 2462 == wiphy->bands[i]->channels[j].center_freq ) &&
3616 NV_CHANNEL_ENABLE == regChannels[k].enabled)
3617 {
3618 wiphy->bands[i]->channels[j].flags &= ~IEEE80211_CHAN_DISABLED;
3619 }
3620 else
3621 {
3622 wiphy->bands[i]->channels[j].flags |= IEEE80211_CHAN_DISABLED;
3623 }
3624 continue;
3625 }
3626 else if (IEEE80211_BAND_5GHZ == i && eCSR_BAND_24 == nBandCapability) // 2G only
3627 {
3628 wiphy->bands[i]->channels[j].flags |= IEEE80211_CHAN_DISABLED;
3629 continue;
3630 }
3631
3632 if (NV_CHANNEL_DISABLE == regChannels[k].enabled ||
3633 NV_CHANNEL_INVALID == regChannels[k].enabled)
3634 {
3635 wiphy->bands[i]->channels[j].flags |= IEEE80211_CHAN_DISABLED;
3636 }
3637 else if (NV_CHANNEL_DFS == regChannels[k].enabled)
3638 {
3639 wiphy->bands[i]->channels[j].flags &= ~(IEEE80211_CHAN_DISABLED
3640 |IEEE80211_CHAN_RADAR);
3641 wiphy->bands[i]->channels[j].flags |= IEEE80211_CHAN_PASSIVE_SCAN;
3642 }
3643 else
3644 {
3645 wiphy->bands[i]->channels[j].flags &= ~(IEEE80211_CHAN_DISABLED
3646 |IEEE80211_CHAN_PASSIVE_SCAN
3647 |IEEE80211_CHAN_NO_IBSS
3648 |IEEE80211_CHAN_RADAR);
3649 }
3650 }
3651 }
3652
3653 /* Haven't seen any condition that will set by driver after init.
3654 If we do, then we should also call sme_ChangeCountryCode */
3655 if (wiphy->bands[IEEE80211_BAND_5GHZ])
3656 {
3657 for (j=0; j<wiphy->bands[IEEE80211_BAND_5GHZ]->n_channels; j++)
3658 {
Kiet Lam90d08242013-11-06 21:49:53 +05303659 // UNII-1 band channels are passive when domain is FCC.
Amar Singhal9a65a6a2013-10-08 18:37:44 -07003660 if ((wiphy->bands[IEEE80211_BAND_5GHZ ]->channels[j].center_freq == 5180 ||
3661 wiphy->bands[IEEE80211_BAND_5GHZ]->channels[j].center_freq == 5200 ||
3662 wiphy->bands[IEEE80211_BAND_5GHZ]->channels[j].center_freq == 5220 ||
3663 wiphy->bands[IEEE80211_BAND_5GHZ]->channels[j].center_freq == 5240) &&
Kiet Lam90d08242013-11-06 21:49:53 +05303664 ((ccode[0]== 'U'&& ccode[1]=='S') && pHddCtx->nEnableStrictRegulatoryForFCC))
Amar Singhal9a65a6a2013-10-08 18:37:44 -07003665 {
3666 wiphy->bands[IEEE80211_BAND_5GHZ]->channels[j].flags |= IEEE80211_CHAN_PASSIVE_SCAN;
3667 }
3668 else if ((wiphy->bands[IEEE80211_BAND_5GHZ]->channels[j].center_freq == 5180 ||
3669 wiphy->bands[IEEE80211_BAND_5GHZ]->channels[j].center_freq == 5200 ||
3670 wiphy->bands[IEEE80211_BAND_5GHZ]->channels[j].center_freq == 5220 ||
3671 wiphy->bands[IEEE80211_BAND_5GHZ]->channels[j].center_freq == 5240) &&
Kiet Lam90d08242013-11-06 21:49:53 +05303672 ((ccode[0]!= 'U'&& ccode[1]!='S') || !pHddCtx->nEnableStrictRegulatoryForFCC))
Amar Singhal9a65a6a2013-10-08 18:37:44 -07003673 {
3674 wiphy->bands[IEEE80211_BAND_5GHZ]->channels[j].flags &= ~IEEE80211_CHAN_PASSIVE_SCAN;
3675 }
3676 }
3677 }
3678
3679 if (request->initiator == NL80211_REGDOM_SET_BY_CORE)
3680 {
3681 request->processed = 1;
3682 }
Amar Singhal61cbd962013-09-05 13:03:40 -07003683 }
3684
Kiet Lam90d08242013-11-06 21:49:53 +05303685 complete(&pHddCtx->wiphy_channel_update_event);
3686
Amar Singhal9a65a6a2013-10-08 18:37:44 -07003687#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,9,0))
3688 return;
3689#else
3690 return 0;
3691#endif
Amar Singhal61cbd962013-09-05 13:03:40 -07003692}
3693
3694#endif