blob: 3fa0089a95e500f90943e2c178c285a54784c68b [file] [log] [blame]
Jeff Johnson295189b2012-06-20 16:38:30 -07001/*
Jeff Johnson32d95a32012-09-10 13:15:23 -07002 * Copyright (c) 2012, The Linux Foundation. All rights reserved.
Jeff Johnson295189b2012-06-20 16:38:30 -07003 *
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
22/*============================================================================
23 FILE: vos_nvitem.c
24 OVERVIEW: This source file contains definitions for vOS NV Item APIs
25 DEPENDENCIES: NV, remote API client, WinCE REX
26 Copyright (c) 2008 QUALCOMM Incorporated.
27 All Rights Reserved.
28 Qualcomm Confidential and Proprietary
29============================================================================*/
30/*============================================================================
31 EDIT HISTORY FOR MODULE
32============================================================================*/
33// the following is used to disable warning for having too many labels in
34// the 'nv_items_enum_type'
35
36/*----------------------------------------------------------------------------
37 * Include Files
38 * -------------------------------------------------------------------------*/
39#include "vos_types.h"
40#include "aniGlobal.h"
41#include "vos_nvitem.h"
42#include "vos_trace.h"
43#include "vos_api.h"
44#include "wlan_hdd_misc.h"
45#include "vos_sched.h"
Madan Mohan Koyyalamudic3a240c2012-09-28 15:34:08 -070046#ifdef CONFIG_CFG80211
47#include "wlan_hdd_main.h"
48#include <net/cfg80211.h>
49static char crda_alpha2[2] = {0, 0}; /* country code from initial crda req */
50static char run_time_alpha2[2] = {0, 0}; /* country code from none-default country req */
51static v_BOOL_t crda_regulatory_entry_valid = VOS_FALSE;
52static v_BOOL_t crda_regulatory_run_time_entry_valid = VOS_FALSE;
53#endif
54
Jeff Johnson295189b2012-06-20 16:38:30 -070055/*----------------------------------------------------------------------------
56 * Preprocessor Definitions and Constants
57 * -------------------------------------------------------------------------*/
58#define VALIDITY_BITMAP_NV_ID NV_WLAN_VALIDITY_BITMAP_I
59#define VALIDITY_BITMAP_SIZE 32
60#define MAX_COUNTRY_COUNT 300
61//To be removed when NV support is fully functional
62#define VOS_HARD_CODED_MAC {0, 0x0a, 0xf5, 4, 5, 6}
Madan Mohan Koyyalamudi1dd5c882012-09-24 13:31:39 -070063
64#define DEFAULT_NV_VALIDITY_BITMAP 0xFFFFFFFF
65
Jeff Johnson295189b2012-06-20 16:38:30 -070066/*----------------------------------------------------------------------------
67 * Type Declarations
68 * -------------------------------------------------------------------------*/
69// this wrapper structure is identical to nv_cmd_type except the
70// data_ptr type is changed void* to avoid exceeding the debug information
71// module size as there are too many elements within nv_items_type union
72
73// structure for code and regulatory domain of a single country
74typedef struct
75{
76 v_U8_t regDomain;
77 v_COUNTRYCODE_t countryCode;
78} CountryInfo_t;
79// structure of table to map country code and regulatory domain
80typedef struct
81{
82 v_U16_t countryCount;
83 CountryInfo_t countryInfo[MAX_COUNTRY_COUNT];
84} CountryInfoTable_t;
85/*----------------------------------------------------------------------------
86 * Global Data Definitions
87 * -------------------------------------------------------------------------*/
88/*----------------------------------------------------------------------------
89 * Static Variable Definitions
90 * -------------------------------------------------------------------------*/
91// cache of country info table;
92// this is re-initialized from data on binary file
93// loaded on driver initialization if available
94static CountryInfoTable_t countryInfoTable =
95{
96 254,
97 {
Madan Mohan Koyyalamudi00ff26d2012-11-02 13:33:26 -070098 { REGDOMAIN_FCC, {'U', 'S'}}, //USA - must be the first country code
99 { REGDOMAIN_ETSI, {'A', 'D'}}, //ANDORRA
100 { REGDOMAIN_ETSI, {'A', 'E'}}, //UAE
101 { REGDOMAIN_N_AMER_EXC_FCC, {'A', 'F'}}, //AFGHANISTAN
102 { REGDOMAIN_WORLD, {'A', 'G'}}, //ANTIGUA AND BARBUDA
103 { REGDOMAIN_FCC, {'A', 'I'}}, //ANGUILLA
104 { REGDOMAIN_NO_5GHZ, {'A', 'L'}}, //ALBANIA
105 { REGDOMAIN_N_AMER_EXC_FCC, {'A', 'M'}}, //ARMENIA
106 { REGDOMAIN_ETSI, {'A', 'N'}}, //NETHERLANDS ANTILLES
107 { REGDOMAIN_NO_5GHZ, {'A', 'O'}}, //ANGOLA
108 { REGDOMAIN_WORLD, {'A', 'Q'}}, //ANTARCTICA
109 { REGDOMAIN_WORLD, {'A', 'R'}}, //ARGENTINA
110 { REGDOMAIN_FCC, {'A', 'S'}}, //AMERICAN SOMOA
111 { REGDOMAIN_ETSI, {'A', 'T'}}, //AUSTRIA
112 { REGDOMAIN_APAC, {'A', 'U'}}, //AUSTRALIA
113 { REGDOMAIN_ETSI, {'A', 'W'}}, //ARUBA
114 { REGDOMAIN_WORLD, {'A', 'X'}}, //ALAND ISLANDS
115 { REGDOMAIN_N_AMER_EXC_FCC, {'A', 'Z'}}, //AZERBAIJAN
116 { REGDOMAIN_ETSI, {'B', 'A'}}, //BOSNIA AND HERZEGOVINA
117 { REGDOMAIN_APAC, {'B', 'B'}}, //BARBADOS
118 { REGDOMAIN_NO_5GHZ, {'B', 'D'}}, //BANGLADESH
119 { REGDOMAIN_ETSI, {'B', 'E'}}, //BELGIUM
120 { REGDOMAIN_HI_5GHZ, {'B', 'F'}}, //BURKINA FASO
121 { REGDOMAIN_ETSI, {'B', 'G'}}, //BULGARIA
122 { REGDOMAIN_APAC, {'B', 'H'}}, //BAHRAIN
123 { REGDOMAIN_NO_5GHZ, {'B', 'I'}}, //BURUNDI
124 { REGDOMAIN_NO_5GHZ, {'B', 'J'}}, //BENIN
125 { REGDOMAIN_FCC, {'B', 'M'}}, //BERMUDA
126 { REGDOMAIN_APAC, {'B', 'N'}}, //BRUNEI DARUSSALAM
127 { REGDOMAIN_HI_5GHZ, {'B', 'O'}}, //BOLIVIA
128 { REGDOMAIN_WORLD, {'B', 'R'}}, //BRAZIL
129 { REGDOMAIN_APAC, {'B', 'S'}}, //BAHAMAS
130 { REGDOMAIN_NO_5GHZ, {'B', 'T'}}, //BHUTAN
131 { REGDOMAIN_WORLD, {'B', 'V'}}, //BOUVET ISLAND
132 { REGDOMAIN_ETSI, {'B', 'W'}}, //BOTSWANA
133 { REGDOMAIN_ETSI, {'B', 'Y'}}, //BELARUS
134 { REGDOMAIN_HI_5GHZ, {'B', 'Z'}}, //BELIZE
135 { REGDOMAIN_FCC, {'C', 'A'}}, //CANADA
136 { REGDOMAIN_WORLD, {'C', 'C'}}, //COCOS (KEELING) ISLANDS
137 { REGDOMAIN_NO_5GHZ, {'C', 'D'}}, //CONGO, THE DEMOCRATIC REPUBLIC OF THE
138 { REGDOMAIN_NO_5GHZ, {'C', 'F'}}, //CENTRAL AFRICAN REPUBLIC
139 { REGDOMAIN_NO_5GHZ, {'C', 'G'}}, //CONGO
140 { REGDOMAIN_ETSI, {'C', 'H'}}, //SWITZERLAND
141 { REGDOMAIN_NO_5GHZ, {'C', 'I'}}, //COTE D'IVOIRE
142 { REGDOMAIN_WORLD, {'C', 'K'}}, //COOK ISLANDS
143 { REGDOMAIN_APAC, {'C', 'L'}}, //CHILE
144 { REGDOMAIN_NO_5GHZ, {'C', 'M'}}, //CAMEROON
145 { REGDOMAIN_HI_5GHZ, {'C', 'N'}}, //CHINA
146 { REGDOMAIN_APAC, {'C', 'O'}}, //COLOMBIA
147 { REGDOMAIN_APAC, {'C', 'R'}}, //COSTA RICA
148 { REGDOMAIN_NO_5GHZ, {'C', 'U'}}, //CUBA
149 { REGDOMAIN_ETSI, {'C', 'V'}}, //CAPE VERDE
150 { REGDOMAIN_WORLD, {'C', 'X'}}, //CHRISTMAS ISLAND
151 { REGDOMAIN_ETSI, {'C', 'Y'}}, //CYPRUS
152 { REGDOMAIN_ETSI, {'C', 'Z'}}, //CZECH REPUBLIC
153 { REGDOMAIN_ETSI, {'D', 'E'}}, //GERMANY
154 { REGDOMAIN_NO_5GHZ, {'D', 'J'}}, //DJIBOUTI
155 { REGDOMAIN_ETSI, {'D', 'K'}}, //DENMARK
156 { REGDOMAIN_WORLD, {'D', 'M'}}, //DOMINICA
157 { REGDOMAIN_APAC, {'D', 'O'}}, //DOMINICAN REPUBLIC
158 { REGDOMAIN_NO_5GHZ, {'D', 'Z'}}, //ALGERIA
159 { REGDOMAIN_APAC, {'E', 'C'}}, //ECUADOR
160 { REGDOMAIN_ETSI, {'E', 'E'}}, //ESTONIA
161 { REGDOMAIN_N_AMER_EXC_FCC, {'E', 'G'}}, //EGYPT
162 { REGDOMAIN_WORLD, {'E', 'H'}}, //WESTERN SAHARA
163 { REGDOMAIN_NO_5GHZ, {'E', 'R'}}, //ERITREA
164 { REGDOMAIN_ETSI, {'E', 'S'}}, //SPAIN
165 { REGDOMAIN_ETSI, {'E', 'T'}}, //ETHIOPIA
166 { REGDOMAIN_ETSI, {'E', 'U'}}, //Europe (SSGFI)
167 { REGDOMAIN_ETSI, {'F', 'I'}}, //FINLAND
168 { REGDOMAIN_NO_5GHZ, {'F', 'J'}}, //FIJI
169 { REGDOMAIN_WORLD, {'F', 'K'}}, //FALKLAND ISLANDS (MALVINAS)
170 { REGDOMAIN_WORLD, {'F', 'M'}}, //MICRONESIA, FEDERATED STATES OF
171 { REGDOMAIN_WORLD, {'F', 'O'}}, //FAROE ISLANDS
172 { REGDOMAIN_ETSI, {'F', 'R'}}, //FRANCE
173 { REGDOMAIN_NO_5GHZ, {'G', 'A'}}, //GABON
174 { REGDOMAIN_ETSI, {'G', 'B'}}, //UNITED KINGDOM
175 { REGDOMAIN_WORLD, {'G', 'D'}}, //GRENADA
176 { REGDOMAIN_ETSI, {'G', 'E'}}, //GEORGIA
177 { REGDOMAIN_ETSI, {'G', 'F'}}, //FRENCH GUIANA
178 { REGDOMAIN_WORLD, {'G', 'G'}}, //GUERNSEY
179 { REGDOMAIN_WORLD, {'G', 'H'}}, //GHANA
180 { REGDOMAIN_WORLD, {'G', 'I'}}, //GIBRALTAR
181 { REGDOMAIN_ETSI, {'G', 'L'}}, //GREENLAND
182 { REGDOMAIN_NO_5GHZ, {'G', 'M'}}, //GAMBIA
183 { REGDOMAIN_NO_5GHZ, {'G', 'N'}}, //GUINEA
184 { REGDOMAIN_ETSI, {'G', 'P'}}, //GUADELOUPE
185 { REGDOMAIN_NO_5GHZ, {'G', 'Q'}}, //EQUATORIAL GUINEA
186 { REGDOMAIN_ETSI, {'G', 'R'}}, //GREECE
187 { REGDOMAIN_WORLD, {'G', 'S'}}, //SOUTH GEORGIA AND THE SOUTH SANDWICH ISLANDS
188 { REGDOMAIN_APAC, {'G', 'T'}}, //GUATEMALA
189 { REGDOMAIN_APAC, {'G', 'U'}}, //GUAM
190 { REGDOMAIN_NO_5GHZ, {'G', 'W'}}, //GUINEA-BISSAU
191 { REGDOMAIN_HI_5GHZ, {'G', 'Y'}}, //GUYANA
192 { REGDOMAIN_WORLD, {'H', 'K'}}, //HONGKONG
193 { REGDOMAIN_WORLD, {'H', 'M'}}, //HEARD ISLAND AND MCDONALD ISLANDS
194 { REGDOMAIN_WORLD, {'H', 'N'}}, //HONDURAS
195 { REGDOMAIN_ETSI, {'H', 'R'}}, //CROATIA
196 { REGDOMAIN_ETSI, {'H', 'T'}}, //HAITI
197 { REGDOMAIN_ETSI, {'H', 'U'}}, //HUNGARY
198 { REGDOMAIN_HI_5GHZ, {'I', 'D'}}, //INDONESIA
199 { REGDOMAIN_ETSI, {'I', 'E'}}, //IRELAND
200 { REGDOMAIN_NO_5GHZ, {'I', 'L'}}, //ISRAEL
201 { REGDOMAIN_WORLD, {'I', 'M'}}, //ISLE OF MAN
202 { REGDOMAIN_APAC, {'I', 'N'}}, //INDIA
203 { REGDOMAIN_WORLD, {'I', 'O'}}, //BRITISH INDIAN OCEAN TERRITORY
204 { REGDOMAIN_NO_5GHZ, {'I', 'Q'}}, //IRAQ
205 { REGDOMAIN_HI_5GHZ, {'I', 'R'}}, //IRAN, ISLAMIC REPUBLIC OF
206 { REGDOMAIN_ETSI, {'I', 'S'}}, //ICELAND
207 { REGDOMAIN_ETSI, {'I', 'T'}}, //ITALY
208 { REGDOMAIN_JAPAN, {'J', '1'}}, //Japan alternate 1
209 { REGDOMAIN_JAPAN, {'J', '2'}}, //Japan alternate 2
210 { REGDOMAIN_JAPAN, {'J', '3'}}, //Japan alternate 3
211 { REGDOMAIN_JAPAN, {'J', '4'}}, //Japan alternate 4
212 { REGDOMAIN_JAPAN, {'J', '5'}}, //Japan alternate 5
213 { REGDOMAIN_WORLD, {'J', 'E'}}, //JERSEY
214 { REGDOMAIN_WORLD, {'J', 'M'}}, //JAMAICA
215 { REGDOMAIN_WORLD, {'J', 'O'}}, //JORDAN
216 { REGDOMAIN_JAPAN, {'J', 'P'}}, //JAPAN
217 { REGDOMAIN_KOREA, {'K', '1'}}, //Korea alternate 1
218 { REGDOMAIN_KOREA, {'K', '2'}}, //Korea alternate 2
219 { REGDOMAIN_KOREA, {'K', '3'}}, //Korea alternate 3
220 { REGDOMAIN_KOREA, {'K', '4'}}, //Korea alternate 4
221 { REGDOMAIN_HI_5GHZ, {'K', 'E'}}, //KENYA
222 { REGDOMAIN_NO_5GHZ, {'K', 'G'}}, //KYRGYZSTAN
223 { REGDOMAIN_ETSI, {'K', 'H'}}, //CAMBODIA
224 { REGDOMAIN_WORLD, {'K', 'I'}}, //KIRIBATI
225 { REGDOMAIN_NO_5GHZ, {'K', 'M'}}, //COMOROS
226 { REGDOMAIN_WORLD, {'K', 'N'}}, //SAINT KITTS AND NEVIS
227 { REGDOMAIN_WORLD, {'K', 'P'}}, //KOREA, DEMOCRATIC PEOPLE'S REPUBLIC OF
228 { REGDOMAIN_KOREA, {'K', 'R'}}, //KOREA, REPUBLIC OF
229 { REGDOMAIN_N_AMER_EXC_FCC, {'K', 'W'}}, //KUWAIT
230 { REGDOMAIN_FCC, {'K', 'Y'}}, //CAYMAN ISLANDS
231 { REGDOMAIN_NO_5GHZ, {'K', 'Z'}}, //KAZAKHSTAN
232 { REGDOMAIN_WORLD, {'L', 'A'}}, //LAO PEOPLE'S DEMOCRATIC REPUBLIC
233 { REGDOMAIN_HI_5GHZ, {'L', 'B'}}, //LEBANON
234 { REGDOMAIN_WORLD, {'L', 'C'}}, //SAINT LUCIA
235 { REGDOMAIN_ETSI, {'L', 'I'}}, //LIECHTENSTEIN
236 { REGDOMAIN_WORLD, {'L', 'K'}}, //SRI LANKA
237 { REGDOMAIN_WORLD, {'L', 'R'}}, //LIBERIA
238 { REGDOMAIN_ETSI, {'L', 'S'}}, //LESOTHO
239 { REGDOMAIN_ETSI, {'L', 'T'}}, //LITHUANIA
240 { REGDOMAIN_ETSI, {'L', 'U'}}, //LUXEMBOURG
241 { REGDOMAIN_ETSI, {'L', 'V'}}, //LATVIA
242 { REGDOMAIN_NO_5GHZ, {'L', 'Y'}}, //LIBYAN ARAB JAMAHIRIYA
243 { REGDOMAIN_NO_5GHZ, {'M', 'A'}}, //MOROCCO
244 { REGDOMAIN_N_AMER_EXC_FCC, {'M', 'C'}}, //MONACO
245 { REGDOMAIN_ETSI, {'M', 'D'}}, //MOLDOVA, REPUBLIC OF
246 { REGDOMAIN_ETSI, {'M', 'E'}}, //MONTENEGRO
247 { REGDOMAIN_NO_5GHZ, {'M', 'G'}}, //MADAGASCAR
248 { REGDOMAIN_WORLD, {'M', 'H'}}, //MARSHALL ISLANDS
249 { REGDOMAIN_ETSI, {'M', 'K'}}, //MACEDONIA, THE FORMER YUGOSLAV REPUBLIC OF
250 { REGDOMAIN_NO_5GHZ, {'M', 'L'}}, //MALI
251 { REGDOMAIN_WORLD, {'M', 'M'}}, //MYANMAR
252 { REGDOMAIN_NO_5GHZ, {'M', 'N'}}, //MONGOLIA
253 { REGDOMAIN_APAC, {'M', 'O'}}, //MACAO
254 { REGDOMAIN_FCC, {'M', 'P'}}, //NORTHERN MARIANA ISLANDS
255 { REGDOMAIN_ETSI, {'M', 'Q'}}, //MARTINIQUE
256 { REGDOMAIN_ETSI, {'M', 'R'}}, //MAURITANIA
257 { REGDOMAIN_ETSI, {'M', 'S'}}, //MONTSERRAT
258 { REGDOMAIN_ETSI, {'M', 'T'}}, //MALTA
259 { REGDOMAIN_ETSI, {'M', 'U'}}, //MAURITIUS
260 { REGDOMAIN_APAC, {'M', 'V'}}, //MALDIVES
261 { REGDOMAIN_HI_5GHZ, {'M', 'W'}}, //MALAWI
262 { REGDOMAIN_APAC, {'M', 'X'}}, //MEXICO
263 { REGDOMAIN_APAC, {'M', 'Y'}}, //MALAYSIA
264 { REGDOMAIN_WORLD, {'M', 'Z'}}, //MOZAMBIQUE
265 { REGDOMAIN_WORLD, {'N', 'A'}}, //NAMIBIA
266 { REGDOMAIN_NO_5GHZ, {'N', 'C'}}, //NEW CALEDONIA
267 { REGDOMAIN_WORLD, {'N', 'E'}}, //NIGER
268 { REGDOMAIN_WORLD, {'N', 'F'}}, //NORFOLD ISLAND
269 { REGDOMAIN_WORLD, {'N', 'G'}}, //NIGERIA
270 { REGDOMAIN_WORLD, {'N', 'I'}}, //NICARAGUA
271 { REGDOMAIN_ETSI, {'N', 'L'}}, //NETHERLANDS
272 { REGDOMAIN_ETSI, {'N', 'O'}}, //NORWAY
273 { REGDOMAIN_HI_5GHZ, {'N', 'P'}}, //NEPAL
274 { REGDOMAIN_NO_5GHZ, {'N', 'R'}}, //NAURU
275 { REGDOMAIN_WORLD, {'N', 'U'}}, //NIUE
276 { REGDOMAIN_APAC, {'N', 'Z'}}, //NEW ZEALAND
277 { REGDOMAIN_WORLD, {'O', 'M'}}, //OMAN
278 { REGDOMAIN_APAC, {'P', 'A'}}, //PANAMA
279 { REGDOMAIN_HI_5GHZ, {'P', 'E'}}, //PERU
280 { REGDOMAIN_ETSI, {'P', 'F'}}, //FRENCH POLYNESIA
281 { REGDOMAIN_APAC, {'P', 'G'}}, //PAPUA NEW GUINEA
282 { REGDOMAIN_HI_5GHZ, {'P', 'H'}}, //PHILIPPINES
283 { REGDOMAIN_HI_5GHZ, {'P', 'K'}}, //PAKISTAN
284 { REGDOMAIN_ETSI, {'P', 'L'}}, //POLAND
285 { REGDOMAIN_WORLD, {'P', 'M'}}, //SAINT PIERRE AND MIQUELON
286 { REGDOMAIN_WORLD, {'P', 'N'}}, //WORLDPITCAIRN
287 { REGDOMAIN_FCC, {'P', 'R'}}, //PUERTO RICO
288 { REGDOMAIN_WORLD, {'P', 'S'}}, //PALESTINIAN TERRITORY, OCCUPIED
289 { REGDOMAIN_ETSI, {'P', 'T'}}, //PORTUGAL
290 { REGDOMAIN_WORLD, {'P', 'W'}}, //PALAU
291 { REGDOMAIN_WORLD, {'P', 'Y'}}, //PARAGUAY
292 { REGDOMAIN_HI_5GHZ, {'Q', 'A'}}, //QATAR
293 { REGDOMAIN_ETSI, {'R', 'E'}}, //REUNION
294 { REGDOMAIN_ETSI, {'R', 'O'}}, //ROMANIA
295 { REGDOMAIN_ETSI, {'R', 'S'}}, //SERBIA
296 { REGDOMAIN_HI_5GHZ, {'R', 'U'}}, //RUSSIA
297 { REGDOMAIN_HI_5GHZ, {'R', 'W'}}, //RWANDA
298 { REGDOMAIN_APAC, {'S', 'A'}}, //SAUDI ARABIA
299 { REGDOMAIN_NO_5GHZ, {'S', 'B'}}, //SOLOMON ISLANDS
300 { REGDOMAIN_NO_5GHZ, {'S', 'C'}}, //SEYCHELLES
301 { REGDOMAIN_WORLD, {'S', 'D'}}, //SUDAN
302 { REGDOMAIN_ETSI, {'S', 'E'}}, //SWEDEN
303 { REGDOMAIN_APAC, {'S', 'G'}}, //SINGAPORE
304 { REGDOMAIN_WORLD, {'S', 'H'}}, //SAINT HELENA
305 { REGDOMAIN_ETSI, {'S', 'I'}}, //SLOVENNIA
306 { REGDOMAIN_WORLD, {'S', 'J'}}, //SVALBARD AND JAN MAYEN
307 { REGDOMAIN_ETSI, {'S', 'K'}}, //SLOVAKIA
308 { REGDOMAIN_WORLD, {'S', 'L'}}, //SIERRA LEONE
309 { REGDOMAIN_ETSI, {'S', 'M'}}, //SAN MARINO
310 { REGDOMAIN_ETSI, {'S', 'N'}}, //SENEGAL
311 { REGDOMAIN_NO_5GHZ, {'S', 'O'}}, //SOMALIA
312 { REGDOMAIN_NO_5GHZ, {'S', 'R'}}, //SURINAME
313 { REGDOMAIN_WORLD, {'S', 'T'}}, //SAO TOME AND PRINCIPE
314 { REGDOMAIN_APAC, {'S', 'V'}}, //EL SALVADOR
315 { REGDOMAIN_NO_5GHZ, {'S', 'Y'}}, //SYRIAN ARAB REPUBLIC
316 { REGDOMAIN_NO_5GHZ, {'S', 'Z'}}, //SWAZILAND
317 { REGDOMAIN_ETSI, {'T', 'C'}}, //TURKS AND CAICOS ISLANDS
318 { REGDOMAIN_NO_5GHZ, {'T', 'D'}}, //CHAD
319 { REGDOMAIN_ETSI, {'T', 'F'}}, //FRENCH SOUTHERN TERRITORIES
320 { REGDOMAIN_NO_5GHZ, {'T', 'G'}}, //TOGO
321 { REGDOMAIN_WORLD, {'T', 'H'}}, //THAILAND
322 { REGDOMAIN_NO_5GHZ, {'T', 'J'}}, //TAJIKISTAN
323 { REGDOMAIN_WORLD, {'T', 'K'}}, //TOKELAU
324 { REGDOMAIN_WORLD, {'T', 'L'}}, //TIMOR-LESTE
325 { REGDOMAIN_NO_5GHZ, {'T', 'M'}}, //TURKMENISTAN
326 { REGDOMAIN_N_AMER_EXC_FCC, {'T', 'N'}}, //TUNISIA
327 { REGDOMAIN_NO_5GHZ, {'T', 'O'}}, //TONGA
328 { REGDOMAIN_N_AMER_EXC_FCC, {'T', 'R'}}, //TURKEY
329 { REGDOMAIN_WORLD, {'T', 'T'}}, //TRINIDAD AND TOBAGO
330 { REGDOMAIN_NO_5GHZ, {'T', 'V'}}, //TUVALU
331 { REGDOMAIN_WORLD, {'T', 'W'}}, //TAIWAN, PROVINCE OF CHINA
332 { REGDOMAIN_HI_5GHZ, {'T', 'Z'}}, //TANZANIA, UNITED REPUBLIC OF
333 { REGDOMAIN_NO_5GHZ, {'U', 'A'}}, //UKRAINE
334 { REGDOMAIN_WORLD, {'U', 'G'}}, //UGANDA
335 { REGDOMAIN_FCC, {'U', 'M'}}, //UNITED STATES MINOR OUTLYING ISLANDS
336 { REGDOMAIN_WORLD, {'U', 'Y'}}, //URUGUAY
337 { REGDOMAIN_WORLD, {'U', 'Z'}}, //UZBEKISTAN
338 { REGDOMAIN_ETSI, {'V', 'A'}}, //HOLY SEE (VATICAN CITY STATE)
339 { REGDOMAIN_WORLD, {'V', 'C'}}, //SAINT VINCENT AND THE GRENADINES
340 { REGDOMAIN_HI_5GHZ, {'V', 'E'}}, //VENEZUELA
341 { REGDOMAIN_ETSI, {'V', 'G'}}, //VIRGIN ISLANDS, BRITISH
342 { REGDOMAIN_FCC, {'V', 'I'}}, //VIRGIN ISLANDS, US
343 { REGDOMAIN_N_AMER_EXC_FCC, {'V', 'N'}}, //VIET NAM
344 { REGDOMAIN_NO_5GHZ, {'V', 'U'}}, //VANUATU
345 { REGDOMAIN_WORLD, {'W', 'F'}}, //WALLIS AND FUTUNA
346 { REGDOMAIN_N_AMER_EXC_FCC, {'W', 'S'}}, //SOMOA
347 { REGDOMAIN_NO_5GHZ, {'Y', 'E'}}, //YEMEN
348 { REGDOMAIN_ETSI, {'Y', 'T'}}, //MAYOTTE
349 { REGDOMAIN_WORLD, {'Z', 'A'}}, //SOUTH AFRICA
350 { REGDOMAIN_APAC, {'Z', 'M'}}, //ZAMBIA
351 { REGDOMAIN_NO_5GHZ, {'Z', 'W'}}, //ZIMBABWE
Jeff Johnson295189b2012-06-20 16:38:30 -0700352 }
353};
354typedef struct nvEFSTable_s
355{
356 v_U32_t nvValidityBitmap;
357 sHalNv halnv;
358} nvEFSTable_t;
Madan Mohan Koyyalamudidfd6aa82012-10-18 20:18:43 -0700359nvEFSTable_t *gnvEFSTable;
Jeff Johnson295189b2012-06-20 16:38:30 -0700360/* EFS Table to send the NV structure to HAL*/
Madan Mohan Koyyalamudidfd6aa82012-10-18 20:18:43 -0700361static nvEFSTable_t *pnvEFSTable;
Jeff Johnson295189b2012-06-20 16:38:30 -0700362
363const tRfChannelProps rfChannels[NUM_RF_CHANNELS] =
364{
365 //RF_SUBBAND_2_4_GHZ
366 //freq, chan#, band
367 { 2412, 1 , RF_SUBBAND_2_4_GHZ}, //RF_CHAN_1,
368 { 2417, 2 , RF_SUBBAND_2_4_GHZ}, //RF_CHAN_2,
369 { 2422, 3 , RF_SUBBAND_2_4_GHZ}, //RF_CHAN_3,
370 { 2427, 4 , RF_SUBBAND_2_4_GHZ}, //RF_CHAN_4,
371 { 2432, 5 , RF_SUBBAND_2_4_GHZ}, //RF_CHAN_5,
372 { 2437, 6 , RF_SUBBAND_2_4_GHZ}, //RF_CHAN_6,
373 { 2442, 7 , RF_SUBBAND_2_4_GHZ}, //RF_CHAN_7,
374 { 2447, 8 , RF_SUBBAND_2_4_GHZ}, //RF_CHAN_8,
375 { 2452, 9 , RF_SUBBAND_2_4_GHZ}, //RF_CHAN_9,
376 { 2457, 10 , RF_SUBBAND_2_4_GHZ}, //RF_CHAN_10,
377 { 2462, 11 , RF_SUBBAND_2_4_GHZ}, //RF_CHAN_11,
378 { 2467, 12 , RF_SUBBAND_2_4_GHZ}, //RF_CHAN_12,
379 { 2472, 13 , RF_SUBBAND_2_4_GHZ}, //RF_CHAN_13,
380 { 2484, 14 , RF_SUBBAND_2_4_GHZ}, //RF_CHAN_14,
381#ifdef FEATURE_WLAN_INTEGRATED_SOC
Madan Mohan Koyyalamudic3a240c2012-09-28 15:34:08 -0700382 { 4920, 240, RF_SUBBAND_4_9_GHZ}, //RF_CHAN_240,
383 { 4940, 244, RF_SUBBAND_4_9_GHZ}, //RF_CHAN_244,
384 { 4960, 248, RF_SUBBAND_4_9_GHZ}, //RF_CHAN_248,
385 { 4980, 252, RF_SUBBAND_4_9_GHZ}, //RF_CHAN_252,
386 { 5040, 208, RF_SUBBAND_4_9_GHZ}, //RF_CHAN_208,
387 { 5060, 212, RF_SUBBAND_4_9_GHZ}, //RF_CHAN_212,
388 { 5080, 216, RF_SUBBAND_4_9_GHZ}, //RF_CHAN_216,
Jeff Johnson295189b2012-06-20 16:38:30 -0700389 { 5180, 36 , RF_SUBBAND_5_LOW_GHZ}, //RF_CHAN_36,
390 { 5200, 40 , RF_SUBBAND_5_LOW_GHZ}, //RF_CHAN_40,
391 { 5220, 44 , RF_SUBBAND_5_LOW_GHZ}, //RF_CHAN_44,
392 { 5240, 48 , RF_SUBBAND_5_LOW_GHZ}, //RF_CHAN_48,
393 { 5260, 52 , RF_SUBBAND_5_LOW_GHZ}, //RF_CHAN_52,
394 { 5280, 56 , RF_SUBBAND_5_LOW_GHZ}, //RF_CHAN_56,
395 { 5300, 60 , RF_SUBBAND_5_LOW_GHZ}, //RF_CHAN_60,
396 { 5320, 64 , RF_SUBBAND_5_LOW_GHZ}, //RF_CHAN_64,
397 { 5500, 100, RF_SUBBAND_5_MID_GHZ}, //RF_CHAN_100,
398 { 5520, 104, RF_SUBBAND_5_MID_GHZ}, //RF_CHAN_104,
399 { 5540, 108, RF_SUBBAND_5_MID_GHZ}, //RF_CHAN_108,
400 { 5560, 112, RF_SUBBAND_5_MID_GHZ}, //RF_CHAN_112,
401 { 5580, 116, RF_SUBBAND_5_MID_GHZ}, //RF_CHAN_116,
402 { 5600, 120, RF_SUBBAND_5_MID_GHZ}, //RF_CHAN_120,
403 { 5620, 124, RF_SUBBAND_5_MID_GHZ}, //RF_CHAN_124,
404 { 5640, 128, RF_SUBBAND_5_MID_GHZ}, //RF_CHAN_128,
405 { 5660, 132, RF_SUBBAND_5_MID_GHZ}, //RF_CHAN_132,
406 { 5680, 136, RF_SUBBAND_5_MID_GHZ}, //RF_CHAN_136,
407 { 5700, 140, RF_SUBBAND_5_MID_GHZ}, //RF_CHAN_140,
408 { 5745, 149, RF_SUBBAND_5_HIGH_GHZ}, //RF_CHAN_149,
409 { 5765, 153, RF_SUBBAND_5_HIGH_GHZ}, //RF_CHAN_153,
410 { 5785, 157, RF_SUBBAND_5_HIGH_GHZ}, //RF_CHAN_157,
411 { 5805, 161, RF_SUBBAND_5_HIGH_GHZ}, //RF_CHAN_161,
412 { 5825, 165, RF_SUBBAND_5_HIGH_GHZ}, //RF_CHAN_165,
Madan Mohan Koyyalamudic3a240c2012-09-28 15:34:08 -0700413 { 2422, 3 , NUM_RF_SUBBANDS}, //RF_CHAN_BOND_3,
414 { 2427, 4 , NUM_RF_SUBBANDS}, //RF_CHAN_BOND_4,
415 { 2432, 5 , NUM_RF_SUBBANDS}, //RF_CHAN_BOND_5,
416 { 2437, 6 , NUM_RF_SUBBANDS}, //RF_CHAN_BOND_6,
417 { 2442, 7 , NUM_RF_SUBBANDS}, //RF_CHAN_BOND_7,
418 { 2447, 8 , NUM_RF_SUBBANDS}, //RF_CHAN_BOND_8,
419 { 2452, 9 , NUM_RF_SUBBANDS}, //RF_CHAN_BOND_9,
420 { 2457, 10 , NUM_RF_SUBBANDS}, //RF_CHAN_BOND_10,
421 { 2462, 11 , NUM_RF_SUBBANDS}, //RF_CHAN_BOND_11,
422 { 4930, 242, NUM_RF_SUBBANDS}, //RF_CHAN_BOND_242,
423 { 4950, 246, NUM_RF_SUBBANDS}, //RF_CHAN_BOND_246,
424 { 4970, 250, NUM_RF_SUBBANDS}, //RF_CHAN_BOND_250,
425 { 5050, 210, NUM_RF_SUBBANDS}, //RF_CHAN_BOND_210,
426 { 5070, 214, NUM_RF_SUBBANDS}, //RF_CHAN_BOND_214,
427 { 5190, 38 , NUM_RF_SUBBANDS}, //RF_CHAN_BOND_38,
428 { 5210, 42 , NUM_RF_SUBBANDS}, //RF_CHAN_BOND_42,
429 { 5230, 46 , NUM_RF_SUBBANDS}, //RF_CHAN_BOND_46,
430 { 5250, 50 , NUM_RF_SUBBANDS}, //RF_CHAN_BOND_50,
431 { 5270, 54 , NUM_RF_SUBBANDS}, //RF_CHAN_BOND_54,
432 { 5290, 58 , NUM_RF_SUBBANDS}, //RF_CHAN_BOND_58,
433 { 5310, 62 , NUM_RF_SUBBANDS}, //RF_CHAN_BOND_62,
434 { 5510, 102, NUM_RF_SUBBANDS}, //RF_CHAN_BOND_102,
435 { 5530, 106, NUM_RF_SUBBANDS}, //RF_CHAN_BOND_106,
436 { 5550, 110, NUM_RF_SUBBANDS}, //RF_CHAN_BOND_110,
437 { 5570, 114, NUM_RF_SUBBANDS}, //RF_CHAN_BOND_114,
438 { 5590, 118, NUM_RF_SUBBANDS}, //RF_CHAN_BOND_118,
439 { 5610, 122, NUM_RF_SUBBANDS}, //RF_CHAN_BOND_122,
440 { 5630, 126, NUM_RF_SUBBANDS}, //RF_CHAN_BOND_126,
441 { 5650, 130, NUM_RF_SUBBANDS}, //RF_CHAN_BOND_130,
442 { 5670, 134, NUM_RF_SUBBANDS}, //RF_CHAN_BOND_134,
443 { 5690, 138, NUM_RF_SUBBANDS}, //RF_CHAN_BOND_138,
444 { 5755, 151, NUM_RF_SUBBANDS}, //RF_CHAN_BOND_151,
445 { 5775, 155, NUM_RF_SUBBANDS}, //RF_CHAN_BOND_155,
446 { 5795, 159, NUM_RF_SUBBANDS}, //RF_CHAN_BOND_159,
447 { 5815, 163, NUM_RF_SUBBANDS}, //RF_CHAN_BOND_163,
Jeff Johnson295189b2012-06-20 16:38:30 -0700448#endif
449};
450
451extern const sHalNv nvDefaults;
452
453const sRegulatoryChannel * regChannels = nvDefaults.tables.regDomains[0].channels;
454
455/*----------------------------------------------------------------------------
456 Function Definitions and Documentation
457 * -------------------------------------------------------------------------*/
458VOS_STATUS wlan_write_to_efs (v_U8_t *pData, v_U16_t data_len);
459/**------------------------------------------------------------------------
460 \brief vos_nv_init() - initialize the NV module
461 The \a vos_nv_init() initializes the NV module. This read the binary
462 file for country code and regulatory domain information.
463 \return VOS_STATUS_SUCCESS - module is initialized successfully
464 otherwise - module is not initialized
465 \sa
466 -------------------------------------------------------------------------*/
467VOS_STATUS vos_nv_init(void)
468{
469 return VOS_STATUS_SUCCESS;
470}
471
472VOS_STATUS vos_nv_open(void)
473{
474 VOS_STATUS status = VOS_STATUS_SUCCESS;
475 v_CONTEXT_t pVosContext= NULL;
476 v_SIZE_t bufSize;
Madan Mohan Koyyalamudi1dd5c882012-09-24 13:31:39 -0700477 v_SIZE_t nvReadBufSize;
Jeff Johnson295189b2012-06-20 16:38:30 -0700478 v_BOOL_t itemIsValid = VOS_FALSE;
479
480 /*Get the global context */
481 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
Madan Mohan Koyyalamudi0b78e152012-11-28 15:46:51 -0800482
483 if(pVosContext == NULL)
484 {
485 return (eHAL_STATUS_FAILURE);
486 }
487
Jeff Johnson295189b2012-06-20 16:38:30 -0700488 bufSize = sizeof(nvEFSTable_t);
489 status = hdd_request_firmware(WLAN_NV_FILE,
490 ((VosContextType*)(pVosContext))->pHDDContext,
Madan Mohan Koyyalamudi1dd5c882012-09-24 13:31:39 -0700491 (v_VOID_t**)&gnvEFSTable, &nvReadBufSize);
Jeff Johnson295189b2012-06-20 16:38:30 -0700492
493 if ( (!VOS_IS_STATUS_SUCCESS( status )) || !gnvEFSTable)
494 {
495 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
496 "%s: unable to download NV file %s",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700497 __func__, WLAN_NV_FILE);
Jeff Johnson295189b2012-06-20 16:38:30 -0700498 return VOS_STATUS_E_RESOURCES;
499 }
500
501 /* Copying the read nv data to the globa NV EFS table */
502 {
503 /* Allocate memory to global NV table */
504 pnvEFSTable = (nvEFSTable_t *)vos_mem_malloc(sizeof(nvEFSTable_t));
505 if (NULL == pnvEFSTable)
506 {
507 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700508 "%s : failed to allocate memory for NV", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700509 return VOS_STATUS_E_NOMEM;
510 }
511
512 /*Copying the NV defaults */
513 vos_mem_copy(&(pnvEFSTable->halnv),&nvDefaults,sizeof(sHalNv));
Madan Mohan Koyyalamudi1dd5c882012-09-24 13:31:39 -0700514
515 if ( nvReadBufSize != bufSize)
516 {
517 pnvEFSTable->nvValidityBitmap = DEFAULT_NV_VALIDITY_BITMAP;
518 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
519 "!!!WARNING: INVALID NV FILE, DRIVER IS USING DEFAULT CAL VALUES %d %d!!!",
520 nvReadBufSize, bufSize);
Madan Mohan Koyyalamudi0b78e152012-11-28 15:46:51 -0800521 goto error;
Madan Mohan Koyyalamudi1dd5c882012-09-24 13:31:39 -0700522 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700523
Madan Mohan Koyyalamudi1dd5c882012-09-24 13:31:39 -0700524 pnvEFSTable->nvValidityBitmap = gnvEFSTable->nvValidityBitmap;
Jeff Johnson295189b2012-06-20 16:38:30 -0700525 /* Copy the valid fields to the NV Global structure */
526 if (vos_nv_getValidity(VNV_FIELD_IMAGE, &itemIsValid) ==
527 VOS_STATUS_SUCCESS)
528 {
529 if (itemIsValid == VOS_TRUE) {
530
531 if(vos_nv_read( VNV_FIELD_IMAGE, (v_VOID_t *)&pnvEFSTable->halnv.fields,
532 NULL, sizeof(sNvFields) ) != VOS_STATUS_SUCCESS)
Madan Mohan Koyyalamudi0b78e152012-11-28 15:46:51 -0800533 goto error;
Jeff Johnson295189b2012-06-20 16:38:30 -0700534 }
535 }
536
537 if (vos_nv_getValidity(VNV_RATE_TO_POWER_TABLE, &itemIsValid) ==
538 VOS_STATUS_SUCCESS)
539 {
540 if (itemIsValid == VOS_TRUE)
541 {
542 if(vos_nv_read( VNV_RATE_TO_POWER_TABLE,
543 (v_VOID_t *)&pnvEFSTable->halnv.tables.pwrOptimum[0],
544 NULL, sizeof(tRateGroupPwr) * NUM_RF_SUBBANDS ) != VOS_STATUS_SUCCESS)
Madan Mohan Koyyalamudi0b78e152012-11-28 15:46:51 -0800545 goto error;
Jeff Johnson295189b2012-06-20 16:38:30 -0700546 }
547 }
548
549 if (vos_nv_getValidity(VNV_REGULARTORY_DOMAIN_TABLE, &itemIsValid) ==
550 VOS_STATUS_SUCCESS)
551 {
552
553 if (itemIsValid == VOS_TRUE)
554 {
555 if(vos_nv_read( VNV_REGULARTORY_DOMAIN_TABLE,
556 (v_VOID_t *)&pnvEFSTable->halnv.tables.regDomains[0],
557 NULL, sizeof(sRegulatoryDomains) * NUM_REG_DOMAINS ) != VOS_STATUS_SUCCESS)
Madan Mohan Koyyalamudi0b78e152012-11-28 15:46:51 -0800558 goto error;
Jeff Johnson295189b2012-06-20 16:38:30 -0700559 }
560 }
561
562 if (vos_nv_getValidity(VNV_DEFAULT_LOCATION, &itemIsValid) ==
563 VOS_STATUS_SUCCESS)
564 {
565 if (itemIsValid == VOS_TRUE)
566 {
567 if(vos_nv_read( VNV_DEFAULT_LOCATION,
568 (v_VOID_t *)&pnvEFSTable->halnv.tables.defaultCountryTable,
569 NULL, sizeof(sDefaultCountry) ) != VOS_STATUS_SUCCESS)
Madan Mohan Koyyalamudi0b78e152012-11-28 15:46:51 -0800570 goto error;
Jeff Johnson295189b2012-06-20 16:38:30 -0700571 }
572 }
573
574 if (vos_nv_getValidity(VNV_TPC_POWER_TABLE, &itemIsValid) ==
575 VOS_STATUS_SUCCESS)
576 {
577 if (itemIsValid == VOS_TRUE)
578 {
579 if(vos_nv_read( VNV_TPC_POWER_TABLE,
580 (v_VOID_t *)&pnvEFSTable->halnv.tables.plutCharacterized[0],
581 NULL, sizeof(tTpcPowerTable) * NUM_RF_CHANNELS ) != VOS_STATUS_SUCCESS)
Madan Mohan Koyyalamudi0b78e152012-11-28 15:46:51 -0800582 goto error;
Jeff Johnson295189b2012-06-20 16:38:30 -0700583 }
584 }
585
586 if (vos_nv_getValidity(VNV_TPC_PDADC_OFFSETS, &itemIsValid) ==
587 VOS_STATUS_SUCCESS)
588 {
589 if (itemIsValid == VOS_TRUE)
590 {
591 if(vos_nv_read( VNV_TPC_PDADC_OFFSETS,
592 (v_VOID_t *)&pnvEFSTable->halnv.tables.plutPdadcOffset[0],
593 NULL, sizeof(tANI_U16) * NUM_RF_CHANNELS ) != VOS_STATUS_SUCCESS)
Madan Mohan Koyyalamudi0b78e152012-11-28 15:46:51 -0800594 goto error;
Jeff Johnson295189b2012-06-20 16:38:30 -0700595 }
596 }
597 if (vos_nv_getValidity(VNV_RSSI_CHANNEL_OFFSETS, &itemIsValid) ==
598 VOS_STATUS_SUCCESS)
599 {
600 if (itemIsValid == VOS_TRUE)
601 {
602 if(vos_nv_read( VNV_RSSI_CHANNEL_OFFSETS,
603 (v_VOID_t *)&pnvEFSTable->halnv.tables.rssiChanOffsets[0],
604 NULL, sizeof(sRssiChannelOffsets) * 2 ) != VOS_STATUS_SUCCESS)
Madan Mohan Koyyalamudi0b78e152012-11-28 15:46:51 -0800605 goto error;
Jeff Johnson295189b2012-06-20 16:38:30 -0700606 }
607 }
608
609 if (vos_nv_getValidity(VNV_RF_CAL_VALUES, &itemIsValid) ==
610 VOS_STATUS_SUCCESS)
611 {
612 if (itemIsValid == VOS_TRUE)
613 {
614 if(vos_nv_read( VNV_RF_CAL_VALUES, (v_VOID_t *)&pnvEFSTable->halnv
615 .tables.rFCalValues, NULL, sizeof(sRFCalValues) ) != VOS_STATUS_SUCCESS)
Madan Mohan Koyyalamudi0b78e152012-11-28 15:46:51 -0800616 goto error;
Jeff Johnson295189b2012-06-20 16:38:30 -0700617 }
618 }
619
620 if (vos_nv_getValidity(VNV_ANTENNA_PATH_LOSS, &itemIsValid) ==
621 VOS_STATUS_SUCCESS)
622 {
623 if (itemIsValid == VOS_TRUE)
624 {
625 if(vos_nv_read( VNV_ANTENNA_PATH_LOSS,
626 (v_VOID_t *)&pnvEFSTable->halnv.tables.antennaPathLoss[0], NULL,
627 sizeof(tANI_S16)*NUM_RF_CHANNELS ) != VOS_STATUS_SUCCESS)
Madan Mohan Koyyalamudi0b78e152012-11-28 15:46:51 -0800628 goto error;
Jeff Johnson295189b2012-06-20 16:38:30 -0700629 }
630 }
631 if (vos_nv_getValidity(VNV_PACKET_TYPE_POWER_LIMITS, &itemIsValid) ==
632 VOS_STATUS_SUCCESS)
633 {
634 if (itemIsValid == VOS_TRUE)
635 {
636 if(vos_nv_read( VNV_PACKET_TYPE_POWER_LIMITS,
637 (v_VOID_t *)&pnvEFSTable->halnv.tables.pktTypePwrLimits[0], NULL,
638 sizeof(tANI_S16)*NUM_802_11_MODES*NUM_RF_CHANNELS ) != VOS_STATUS_SUCCESS)
Madan Mohan Koyyalamudi0b78e152012-11-28 15:46:51 -0800639 goto error;
Jeff Johnson295189b2012-06-20 16:38:30 -0700640 }
641 }
642
643 if (vos_nv_getValidity(VNV_OFDM_CMD_PWR_OFFSET, &itemIsValid) ==
644 VOS_STATUS_SUCCESS)
645 {
646 if (itemIsValid == VOS_TRUE)
647 {
648 if(vos_nv_read( VNV_OFDM_CMD_PWR_OFFSET,
649 (v_VOID_t *)&pnvEFSTable->halnv.tables.ofdmCmdPwrOffset, NULL,
650 sizeof(sOfdmCmdPwrOffset)) != VOS_STATUS_SUCCESS)
Madan Mohan Koyyalamudi0b78e152012-11-28 15:46:51 -0800651 goto error;
Jeff Johnson295189b2012-06-20 16:38:30 -0700652 }
653 }
654
655 if (vos_nv_getValidity(VNV_TX_BB_FILTER_MODE, &itemIsValid) ==
656 VOS_STATUS_SUCCESS)
657 {
658 if (itemIsValid == VOS_TRUE)
659 {
660 if(vos_nv_read(VNV_TX_BB_FILTER_MODE,
661 (v_VOID_t *)&pnvEFSTable->halnv.tables.txbbFilterMode, NULL,
662 sizeof(sTxBbFilterMode)) != VOS_STATUS_SUCCESS)
Madan Mohan Koyyalamudi0b78e152012-11-28 15:46:51 -0800663 goto error;
Jeff Johnson295189b2012-06-20 16:38:30 -0700664 }
665 }
666 if (vos_nv_getValidity(VNV_TABLE_VIRTUAL_RATE, &itemIsValid) ==
667 VOS_STATUS_SUCCESS)
668 {
669 if (itemIsValid == VOS_TRUE)
670 {
671 if(vos_nv_read(VNV_TABLE_VIRTUAL_RATE,
672 (v_VOID_t *)&pnvEFSTable->halnv.tables.pwrOptimum_virtualRate, NULL,
673 sizeof(gnvEFSTable->halnv.tables.pwrOptimum_virtualRate)) != VOS_STATUS_SUCCESS)
Madan Mohan Koyyalamudi0b78e152012-11-28 15:46:51 -0800674 goto error;
Jeff Johnson295189b2012-06-20 16:38:30 -0700675 }
676 }
677 }
678
679 return VOS_STATUS_SUCCESS;
Madan Mohan Koyyalamudi0b78e152012-11-28 15:46:51 -0800680error:
681 vos_mem_free(pnvEFSTable);
682 return eHAL_STATUS_FAILURE ;
Jeff Johnson295189b2012-06-20 16:38:30 -0700683}
684
685VOS_STATUS vos_nv_close(void)
686{
687 VOS_STATUS status = VOS_STATUS_SUCCESS;
688 v_CONTEXT_t pVosContext= NULL;
689 /*Get the global context */
690 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
691 status = hdd_release_firmware(WLAN_NV_FILE, ((VosContextType*)(pVosContext))->pHDDContext);
692 if ( !VOS_IS_STATUS_SUCCESS( status ))
693 {
694 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
695 "%s : vos_open failed\n",__func__);
696 return VOS_STATUS_E_FAILURE;
697 }
698 vos_mem_free(pnvEFSTable);
699 gnvEFSTable=NULL;
700 return VOS_STATUS_SUCCESS;
701}
702/**------------------------------------------------------------------------
703 \brief vos_nv_getRegDomainFromCountryCode() - get the regulatory domain of
704 a country given its country code
705 The \a vos_nv_getRegDomainFromCountryCode() returns the regulatory domain of
706 a country given its country code. This is done from reading a cached
707 copy of the binary file.
708 \param pRegDomain - pointer to regulatory domain
709 \param countryCode - country code
710 \return VOS_STATUS_SUCCESS - regulatory domain is found for the given country
711 VOS_STATUS_E_FAULT - invalid pointer error
712 VOS_STATUS_E_EMPTY - country code table is empty
713 VOS_STATUS_E_EXISTS - given country code does not exist in table
714 \sa
715 -------------------------------------------------------------------------*/
716VOS_STATUS vos_nv_getRegDomainFromCountryCode( v_REGDOMAIN_t *pRegDomain,
717 const v_COUNTRYCODE_t countryCode )
718{
719 int i;
Madan Mohan Koyyalamudic3a240c2012-09-28 15:34:08 -0700720 v_CONTEXT_t pVosContext = NULL;
721 hdd_context_t *pHddCtx = NULL;
722 struct wiphy *wiphy = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -0700723 // sanity checks
724 if (NULL == pRegDomain)
725 {
726 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
727 ("Invalid reg domain pointer\r\n") );
728 return VOS_STATUS_E_FAULT;
729 }
730 *pRegDomain = REGDOMAIN_COUNT;
731
732 if (NULL == countryCode)
733 {
734 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
735 ("Country code array is NULL\r\n") );
736 return VOS_STATUS_E_FAULT;
737 }
738 if (0 == countryInfoTable.countryCount)
739 {
740 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
741 ("Reg domain table is empty\r\n") );
742 return VOS_STATUS_E_EMPTY;
743 }
Madan Mohan Koyyalamudic3a240c2012-09-28 15:34:08 -0700744#ifdef CONFIG_CFG80211
745 /* If CRDA regulatory settings is valid, i.e. crda is enabled
746 and reg_notifier is called back.
747 Intercept here and redirect to the Reg domain table's CRDA
748 entry if country code is crda's country.
749 last one NUM_REG_DOMAINS-1 is reserved for crda */
Madan Mohan Koyyalamudi2502e682012-12-06 13:02:53 -0800750 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_INFO_HIGH,
Madan Mohan Koyyalamudic3a240c2012-09-28 15:34:08 -0700751 "vos_nv_getRegDomainFromCountryCode %c%c\n",
752 countryCode[0], countryCode[1]);
753
754 if (crda_regulatory_entry_valid == VOS_TRUE)
755 {
756 if (crda_alpha2[0]==countryCode[0] && crda_alpha2[1]==countryCode[1])
757 {
758 *pRegDomain = NUM_REG_DOMAINS-1;
Madan Mohan Koyyalamudi2502e682012-12-06 13:02:53 -0800759 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_INFO_HIGH,
Madan Mohan Koyyalamudic3a240c2012-09-28 15:34:08 -0700760 "vos_nv_getRegDomainFromCountryCode return crda init entry\n");
761 return VOS_STATUS_SUCCESS;
762 }
763 if (run_time_alpha2[0]==countryCode[0] &&
764 run_time_alpha2[1]==countryCode[1] &&
765 crda_regulatory_run_time_entry_valid == VOS_TRUE)
766 {
767 *pRegDomain = NUM_REG_DOMAINS-2;
Madan Mohan Koyyalamudi2502e682012-12-06 13:02:53 -0800768 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_INFO_HIGH,
Madan Mohan Koyyalamudic3a240c2012-09-28 15:34:08 -0700769 "vos_nv_getRegDomainFromCountryCode return crda none-default country entry\n");
770 return VOS_STATUS_SUCCESS;
771 }
772 else
773 {
774 crda_regulatory_run_time_entry_valid = VOS_FALSE;
775 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
776 if (NULL != pVosContext)
777 pHddCtx = vos_get_context(VOS_MODULE_ID_HDD, pVosContext);
778 else
779 return VOS_STATUS_E_EXISTS;
780 wiphy = pHddCtx->wiphy;
781 init_completion(&pHddCtx->driver_crda_req);
782 regulatory_hint(wiphy, countryCode);
783 wait_for_completion_interruptible_timeout(&pHddCtx->driver_crda_req,
784 CRDA_WAIT_TIME);
785 if (crda_regulatory_run_time_entry_valid == VOS_TRUE)
786 {
Madan Mohan Koyyalamudi2502e682012-12-06 13:02:53 -0800787 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_INFO_HIGH,
Madan Mohan Koyyalamudic3a240c2012-09-28 15:34:08 -0700788 "vos_nv_getRegDomainFromCountryCode return crda new none-default country entry\n");
789 return VOS_STATUS_SUCCESS;
790 }
791 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
792 "vos_nv_getRegDomainFromCountryCode failed to get crda new none-default country entry\n");
793 return VOS_STATUS_E_EXISTS;
794 }
795 }
796#endif
797
Jeff Johnson295189b2012-06-20 16:38:30 -0700798 // iterate the country info table until end of table or the country code
799 // is found
800 for (i = 0; i < countryInfoTable.countryCount &&
801 REGDOMAIN_COUNT == *pRegDomain; i++)
802 {
803 if (memcmp(countryCode, countryInfoTable.countryInfo[i].countryCode,
804 VOS_COUNTRY_CODE_LEN) == 0)
805 {
806 // country code is found
807 *pRegDomain = countryInfoTable.countryInfo[i].regDomain;
808 }
809 }
810 if (REGDOMAIN_COUNT != *pRegDomain)
811 {
812 return VOS_STATUS_SUCCESS;
813 }
814 else
815 {
816 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_WARN,
817 ("country code is not found\r\n"));
818 return VOS_STATUS_E_EXISTS;
819 }
820}
821/**------------------------------------------------------------------------
822 \brief vos_nv_getSupportedCountryCode() - get the list of supported
823 country codes
824 The \a vos_nv_getSupportedCountryCode() encodes the list of supported
825 country codes with paddings in the provided buffer
826 \param pBuffer - pointer to buffer where supported country codes
827 and paddings are encoded; this may be set to NULL
828 if user wishes to query the required buffer size to
829 get the country code list
830 \param pBufferSize - this is the provided buffer size on input;
831 this is the required or consumed buffer size on output
832 \return VOS_STATUS_SUCCESS - country codes are successfully encoded
833 VOS_STATUS_E_NOMEM - country codes are not encoded because either
834 the buffer is NULL or buffer size is
835 sufficient
836 \sa
837 -------------------------------------------------------------------------*/
838VOS_STATUS vos_nv_getSupportedCountryCode( v_BYTE_t *pBuffer, v_SIZE_t *pBufferSize,
839 v_SIZE_t paddingSize )
840{
841 v_SIZE_t providedBufferSize = *pBufferSize;
842 int i;
843 // pBufferSize now points to the required buffer size
844 *pBufferSize = countryInfoTable.countryCount * (VOS_COUNTRY_CODE_LEN + paddingSize );
845 if ( NULL == pBuffer || providedBufferSize < *pBufferSize )
846 {
847 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_INFO,
848 ("Insufficient memory for country code list\r\n"));
849 return VOS_STATUS_E_NOMEM;
850 }
851 for (i = 0; i < countryInfoTable.countryCount; i++)
852 {
853 memcpy( pBuffer, countryInfoTable.countryInfo[i].countryCode, VOS_COUNTRY_CODE_LEN );
854 pBuffer += (VOS_COUNTRY_CODE_LEN + paddingSize );
855 }
856 return VOS_STATUS_SUCCESS;
857}
858/**------------------------------------------------------------------------
859 \brief vos_nv_readTxAntennaCount() - return number of TX antenna
860 \param pTxAntennaCount - antenna count
861 \return status of the NV read operation
862 \sa
863 -------------------------------------------------------------------------*/
864VOS_STATUS vos_nv_readTxAntennaCount( v_U8_t *pTxAntennaCount )
865{
866 sNvFields fieldImage;
867 VOS_STATUS status;
868 status = vos_nv_read( VNV_FIELD_IMAGE, &fieldImage, NULL,
869 sizeof(fieldImage) );
870 if (VOS_STATUS_SUCCESS == status)
871 {
872 *pTxAntennaCount = fieldImage.numOfTxChains;
873 }
874 return status;
875}
876/**------------------------------------------------------------------------
877 \brief vos_nv_readRxAntennaCount() - return number of RX antenna
878 \param pRxAntennaCount - antenna count
879 \return status of the NV read operation
880 \sa
881 -------------------------------------------------------------------------*/
882VOS_STATUS vos_nv_readRxAntennaCount( v_U8_t *pRxAntennaCount )
883{
884 sNvFields fieldImage;
885 VOS_STATUS status;
886 status = vos_nv_read( VNV_FIELD_IMAGE, &fieldImage, NULL,
887 sizeof(fieldImage) );
888 if (VOS_STATUS_SUCCESS == status)
889 {
890 *pRxAntennaCount = fieldImage.numOfRxChains;
891 }
892 return status;
893}
894
895/**------------------------------------------------------------------------
896 \brief vos_nv_readMacAddress() - return the MAC address
897 \param pMacAddress - MAC address
898 \return status of the NV read operation
899 \sa
900 -------------------------------------------------------------------------*/
901VOS_STATUS vos_nv_readMacAddress( v_MAC_ADDRESS_t pMacAddress )
902{
903 sNvFields fieldImage;
904 VOS_STATUS status;
905 status = vos_nv_read( VNV_FIELD_IMAGE, &fieldImage, NULL,
906 sizeof(fieldImage) );
907 if (VOS_STATUS_SUCCESS == status)
908 {
909 memcpy( pMacAddress, fieldImage.macAddr, VOS_MAC_ADDRESS_LEN );
910 }
911 else
912 {
913 //This part of the code can be removed when NV is programmed
914 const v_U8_t macAddr[VOS_MAC_ADDRESS_LEN] = VOS_HARD_CODED_MAC;
915 memcpy( pMacAddress, macAddr, VOS_MAC_ADDRESS_LEN );
916 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_WARN,
917 " fail to get MAC address from NV, hardcoded to %02X-%02X-%02X-%02X-%02X%02X",
918 macAddr[0], macAddr[1], macAddr[2], macAddr[3], macAddr[4], macAddr[5]);
919 status = VOS_STATUS_SUCCESS;
920 }
921 return status;
922}
923
924/**------------------------------------------------------------------------
925
926 \brief vos_nv_readMultiMacAddress() - return the Multiple MAC addresses
927
928 \param pMacAddress - MAC address
929 \param macCount - Count of valid MAC addresses to get from NV field
930
931 \return status of the NV read operation
932
933 \sa
934
935 -------------------------------------------------------------------------*/
936VOS_STATUS vos_nv_readMultiMacAddress( v_U8_t *pMacAddress,
937 v_U8_t macCount )
938{
939 sNvFields fieldImage;
940 VOS_STATUS status;
941 v_U8_t countLoop;
942 v_U8_t *pNVMacAddress;
943
944 if((0 == macCount) || (VOS_MAX_CONCURRENCY_PERSONA < macCount) ||
945 (NULL == pMacAddress))
946 {
947 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
948 " Invalid Parameter from NV Client macCount %d, pMacAddress 0x%x",
949 macCount, pMacAddress);
950 }
951
952 status = vos_nv_read( VNV_FIELD_IMAGE, &fieldImage, NULL,
953 sizeof(fieldImage) );
954 if (VOS_STATUS_SUCCESS == status)
955 {
956 pNVMacAddress = fieldImage.macAddr;
957 for(countLoop = 0; countLoop < macCount; countLoop++)
958 {
959 vos_mem_copy(pMacAddress + (countLoop * VOS_MAC_ADDRESS_LEN),
960 pNVMacAddress + (countLoop * VOS_MAC_ADDRESS_LEN),
961 VOS_MAC_ADDRESS_LEN);
962 }
963 }
964 else
965 {
966 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
967 "vos_nv_readMultiMacAddress Get NV Field Fail");
968 }
969
970 return status;
971}
972
973/**------------------------------------------------------------------------
974 \brief vos_nv_setValidity() - set the validity of an NV item.
975 The \a vos_nv_setValidity() validates and invalidates an NV item. The
976 validity information is stored in NV memory.
977 One would get the VOS_STATUS_E_EXISTS error when reading an invalid item.
978 An item becomes valid when one has written to it successfully.
979 \param type - NV item type
980 \param itemIsValid - boolean value indicating the item's validity
981 \return VOS_STATUS_SUCCESS - validity is set successfully
982 VOS_STATUS_E_INVAL - one of the parameters is invalid
983 VOS_STATUS_E_FAILURE - unknown error
984 \sa
985 -------------------------------------------------------------------------*/
986#ifndef WLAN_FTM_STUB
987
988VOS_STATUS vos_nv_setValidity( VNV_TYPE type, v_BOOL_t itemIsValid )
989{
990 v_U32_t lastNvValidityBitmap;
991 v_U32_t newNvValidityBitmap;
992 VOS_STATUS status = VOS_STATUS_SUCCESS;
Jeff Johnson43971f52012-07-17 12:26:56 -0700993
Jeff Johnson295189b2012-06-20 16:38:30 -0700994 // check if the current NV type is valid
Jeff Johnson43971f52012-07-17 12:26:56 -0700995 if (VNV_TYPE_COUNT <= type)
Jeff Johnson295189b2012-06-20 16:38:30 -0700996 {
997 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700998 ("%s: invalid type=%d"), __func__, type );
Jeff Johnson295189b2012-06-20 16:38:30 -0700999 return VOS_STATUS_E_INVAL;
1000 }
1001 // read the validity bitmap
1002 lastNvValidityBitmap = gnvEFSTable->nvValidityBitmap;
1003 // modify the validity bitmap
1004 if (itemIsValid)
1005 {
1006 newNvValidityBitmap = lastNvValidityBitmap | (1 << type);
1007 // commit to NV store if bitmap has been modified
1008 if (newNvValidityBitmap != lastNvValidityBitmap)
1009 {
1010 gnvEFSTable->nvValidityBitmap = newNvValidityBitmap;
1011 }
1012 }
1013 else
1014 {
1015 newNvValidityBitmap = lastNvValidityBitmap & (~(1 << type));
1016 if (newNvValidityBitmap != lastNvValidityBitmap)
1017 {
1018 gnvEFSTable->nvValidityBitmap = newNvValidityBitmap;
1019 status = wlan_write_to_efs((v_U8_t*)gnvEFSTable,sizeof(nvEFSTable_t));
1020 if (! VOS_IS_STATUS_SUCCESS(status)) {
1021 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, ("vos_nv_write_to_efs failed!!!\r\n"));
1022 status = VOS_STATUS_E_FAULT;
1023 }
1024 }
1025 }
1026
1027 return status;
1028}
1029#endif
1030/**------------------------------------------------------------------------
1031 \brief vos_nv_getValidity() - get the validity of an NV item.
1032 The \a vos_nv_getValidity() indicates if an NV item is valid. The
1033 validity information is stored in NV memory.
1034 One would get the VOS_STATUS_E_EXISTS error when reading an invalid item.
1035 An item becomes valid when one has written to it successfully.
1036 \param type - NV item type
1037 \param pItemIsValid- pointer to the boolean value indicating the item's
1038 validity
1039 \return VOS_STATUS_SUCCESS - validity is determined successfully
1040 VOS_STATUS_E_INVAL - one of the parameters is invalid
1041 VOS_STATUS_E_FAILURE - unknown error
1042 \sa
1043 -------------------------------------------------------------------------*/
1044VOS_STATUS vos_nv_getValidity( VNV_TYPE type, v_BOOL_t *pItemIsValid )
1045{
1046 v_U32_t nvValidityBitmap = gnvEFSTable->nvValidityBitmap;
1047 // check if the current NV type is valid
Jeff Johnson43971f52012-07-17 12:26:56 -07001048 if (VNV_TYPE_COUNT <= type)
Jeff Johnson295189b2012-06-20 16:38:30 -07001049 {
1050 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001051 ("%s: invalid type=%d"), __func__, type );
Jeff Johnson295189b2012-06-20 16:38:30 -07001052 return VOS_STATUS_E_INVAL;
1053 }
1054 *pItemIsValid = (v_BOOL_t)((nvValidityBitmap >> type) & 1);
1055 return VOS_STATUS_SUCCESS;
1056}
1057/**------------------------------------------------------------------------
1058 \brief vos_nv_read() - read a NV item to an output buffer
1059 The \a vos_nv_read() reads a NV item to an output buffer. If the item is
1060 an array, this function would read the entire array. One would get a
1061 VOS_STATUS_E_EXISTS error when reading an invalid item.
1062 For error conditions of VOS_STATUS_E_EXISTS and VOS_STATUS_E_FAILURE,
1063 if a default buffer is provided (with a non-NULL value),
1064 the default buffer content is copied to the output buffer.
1065 \param type - NV item type
1066 \param outputBuffer - output buffer
1067 \param defaultBuffer - default buffer
1068 \param bufferSize - output buffer size
1069 \return VOS_STATUS_SUCCESS - NV item is read successfully
1070 VOS_STATUS_E_INVAL - one of the parameters is invalid
1071 VOS_STATUS_E_FAULT - defaultBuffer point is NULL
1072 VOS_STATUS_E_EXISTS - NV type is unsupported
1073 VOS_STATUS_E_FAILURE - unknown error
1074 \sa
1075 -------------------------------------------------------------------------*/
1076VOS_STATUS vos_nv_read( VNV_TYPE type, v_VOID_t *outputVoidBuffer,
1077 v_VOID_t *defaultBuffer, v_SIZE_t bufferSize )
1078{
1079 VOS_STATUS status = VOS_STATUS_SUCCESS;
1080 v_SIZE_t itemSize;
1081 v_BOOL_t itemIsValid = VOS_TRUE;
1082
1083 // sanity check
Jeff Johnson43971f52012-07-17 12:26:56 -07001084 if (VNV_TYPE_COUNT <= type)
Jeff Johnson295189b2012-06-20 16:38:30 -07001085 {
1086 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001087 ("%s: invalid type=%d"), __func__, type );
Jeff Johnson295189b2012-06-20 16:38:30 -07001088 return VOS_STATUS_E_INVAL;
1089 }
1090 if (NULL == outputVoidBuffer)
1091 {
1092 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
1093 ("Buffer provided is NULL\r\n") );
1094 return VOS_STATUS_E_FAULT;
1095 }
1096 if (0 == bufferSize)
1097 {
1098 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
1099 ("NV type=%d is invalid\r\n"), type );
1100 return VOS_STATUS_E_INVAL;
1101 }
1102 // check if the NV item has valid data
1103 status = vos_nv_getValidity( type, &itemIsValid );
1104 if (!itemIsValid)
1105 {
1106 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_WARN,
1107 "NV type=%d does not have valid data\r\n", type );
1108 return VOS_STATUS_E_EMPTY;
1109 }
1110 switch(type)
1111 {
1112 case VNV_FIELD_IMAGE:
1113 itemSize = sizeof(gnvEFSTable->halnv.fields);
1114 if(bufferSize != itemSize) {
1115 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
1116 ("type = %d buffer size=%d is less than data size=%d\r\n"),type, bufferSize,
1117 itemSize);
1118 status = VOS_STATUS_E_INVAL;
1119 }
1120 else {
1121 memcpy(outputVoidBuffer,&gnvEFSTable->halnv.fields,bufferSize);
1122 }
1123 break;
1124 case VNV_RATE_TO_POWER_TABLE:
1125 itemSize = sizeof(gnvEFSTable->halnv.tables.pwrOptimum);
1126 if(bufferSize != itemSize) {
1127 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
1128 ("type = %d buffer size=%d is less than data size=%d\r\n"),type, bufferSize,
1129 itemSize);
1130 status = VOS_STATUS_E_INVAL;
1131 }
1132 else {
1133 memcpy(outputVoidBuffer,&gnvEFSTable->halnv.tables.pwrOptimum[0],bufferSize);
1134 }
1135 break;
1136 case VNV_REGULARTORY_DOMAIN_TABLE:
1137 itemSize = sizeof(gnvEFSTable->halnv.tables.regDomains);
1138 if(bufferSize != itemSize) {
1139 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
1140 ("type = %d buffer size=%d is less than data size=%d\r\n"),type, bufferSize,
1141 itemSize);
1142 status = VOS_STATUS_E_INVAL;
1143 }
1144 else {
1145 memcpy(outputVoidBuffer,&gnvEFSTable->halnv.tables.regDomains[0],bufferSize);
1146 }
1147 break;
1148 case VNV_DEFAULT_LOCATION:
1149 itemSize = sizeof(gnvEFSTable->halnv.tables.defaultCountryTable);
1150 if(bufferSize != itemSize) {
1151 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
1152 ("type = %d buffer size=%d is less than data size=%d\r\n"),type, bufferSize,
1153 itemSize);
1154 status = VOS_STATUS_E_INVAL;
1155 }
1156 else {
1157 memcpy(outputVoidBuffer,&gnvEFSTable->halnv.tables.defaultCountryTable,bufferSize);
1158 }
1159 break;
1160 case VNV_TPC_POWER_TABLE:
1161 itemSize = sizeof(gnvEFSTable->halnv.tables.plutCharacterized);
1162 if(bufferSize != itemSize) {
1163 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
1164 ("type = %d buffer size=%d is less than data size=%d\r\n"),type, bufferSize,
1165 itemSize);
1166 status = VOS_STATUS_E_INVAL;
1167 }
1168 else {
1169 memcpy(outputVoidBuffer,&gnvEFSTable->halnv.tables.plutCharacterized[0],bufferSize);
1170 }
1171 break;
1172 case VNV_TPC_PDADC_OFFSETS:
1173 itemSize = sizeof(gnvEFSTable->halnv.tables.plutPdadcOffset);
1174 if(bufferSize != itemSize) {
1175 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
1176 ("type = %d buffer size=%d is less than data size=%d\r\n"),type, bufferSize,
1177 itemSize);
1178 status = VOS_STATUS_E_INVAL;
1179 }
1180 else {
1181 memcpy(outputVoidBuffer,&gnvEFSTable->halnv.tables.plutPdadcOffset[0],bufferSize);
1182 }
1183 break;
1184 case VNV_RSSI_CHANNEL_OFFSETS:
1185
1186 itemSize = sizeof(gnvEFSTable->halnv.tables.rssiChanOffsets);
1187
1188 if(bufferSize != itemSize) {
1189
1190 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
1191 ("type = %d buffer size=%d is less than data size=%d\r\n"),type, bufferSize,
1192 itemSize);
1193 status = VOS_STATUS_E_INVAL;
1194 }
1195 else {
1196 memcpy(outputVoidBuffer,&gnvEFSTable->halnv.tables.rssiChanOffsets[0],bufferSize);
1197 }
1198 break;
1199 case VNV_RF_CAL_VALUES:
1200
1201 itemSize = sizeof(gnvEFSTable->halnv.tables.rFCalValues);
1202
1203 if(bufferSize != itemSize) {
1204
1205 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
1206 ("type = %d buffer size=%d is less than data size=%d\r\n"),type, bufferSize,
1207 itemSize);
1208 status = VOS_STATUS_E_INVAL;
1209 }
1210 else {
1211 memcpy(outputVoidBuffer,&gnvEFSTable->halnv.tables.rFCalValues,bufferSize);
1212 }
1213 break;
1214 case VNV_ANTENNA_PATH_LOSS:
1215 itemSize = sizeof(gnvEFSTable->halnv.tables.antennaPathLoss);
1216 if(bufferSize != itemSize) {
1217 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
1218 ("type = %d buffer size=%d is less than data size=%d\r\n"),type, bufferSize,
1219 itemSize);
1220 status = VOS_STATUS_E_INVAL;
1221 }
1222 else {
1223 memcpy(outputVoidBuffer,&gnvEFSTable->halnv.tables.antennaPathLoss[0],bufferSize);
1224 }
1225 break;
1226 case VNV_PACKET_TYPE_POWER_LIMITS:
1227 itemSize = sizeof(gnvEFSTable->halnv.tables.pktTypePwrLimits);
1228 if(bufferSize != itemSize) {
1229 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
1230 ("type = %d buffer size=%d is less than data size=%d\r\n"),type, bufferSize,
1231 itemSize);
1232 status = VOS_STATUS_E_INVAL;
1233 }
1234 else {
1235 memcpy(outputVoidBuffer,&gnvEFSTable->halnv.tables.pktTypePwrLimits[0][0],bufferSize);
1236 }
1237 break;
1238 case VNV_OFDM_CMD_PWR_OFFSET:
1239 itemSize = sizeof(gnvEFSTable->halnv.tables.ofdmCmdPwrOffset);
1240 if(bufferSize != itemSize) {
1241 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
1242 ("type = %d buffer size=%d is less than data size=%d\r\n"),type, bufferSize,
1243 itemSize);
1244 status = VOS_STATUS_E_INVAL;
1245 }
1246 else {
1247 memcpy(outputVoidBuffer,&gnvEFSTable->halnv.tables.ofdmCmdPwrOffset,bufferSize);
1248 }
1249 break;
1250 case VNV_TX_BB_FILTER_MODE:
1251 itemSize = sizeof(gnvEFSTable->halnv.tables.txbbFilterMode);
1252 if(bufferSize != itemSize) {
1253 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
1254 ("type = %d buffer size=%d is less than data size=%d\r\n"),type, bufferSize,
1255 itemSize);
1256 status = VOS_STATUS_E_INVAL;
1257 }
1258 else {
1259 memcpy(outputVoidBuffer,&gnvEFSTable->halnv.tables.txbbFilterMode,bufferSize);
1260 }
1261 break;
1262
1263#ifdef FEATURE_WLAN_NON_INTEGRATED_SOC
1264 case VNV_FREQUENCY_FOR_1_3V_SUPPLY:
1265 itemSize = sizeof(gnvEFSTable->halnv.tables.freqFor1p3VSupply);
1266 if(bufferSize != itemSize) {
1267 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
1268 ("type = %d buffer size=%d is less than data size=%d\r\n"),type, bufferSize,
1269 itemSize);
1270 status = VOS_STATUS_E_INVAL;
1271 }
1272 else {
1273 memcpy(outputVoidBuffer,&gnvEFSTable->halnv.tables.freqFor1p3VSupply,bufferSize);
1274 }
1275 break;
1276#endif /* FEATURE_WLAN_NON_INTEGRATED_SOC */
1277
1278 case VNV_TABLE_VIRTUAL_RATE:
1279 itemSize = sizeof(gnvEFSTable->halnv.tables.pwrOptimum_virtualRate);
1280 if(bufferSize != itemSize) {
1281 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
1282 ("type = %d buffer size=%d is less than data size=%d\r\n"),type, bufferSize,
1283 itemSize);
1284 status = VOS_STATUS_E_INVAL;
1285 }
1286 else {
1287 memcpy(outputVoidBuffer,&gnvEFSTable->halnv.tables.pwrOptimum_virtualRate,bufferSize);
1288 }
1289 break;
1290
1291 default:
1292 break;
1293 }
1294 return status;
1295}
1296#ifndef WLAN_FTM_STUB
1297
1298/**------------------------------------------------------------------------
1299 \brief vos_nv_write() - write to a NV item from an input buffer
1300 The \a vos_nv_write() writes to a NV item from an input buffer. This would
1301 validate the NV item if the write operation is successful.
1302 \param type - NV item type
1303 \param inputBuffer - input buffer
1304 \param inputBufferSize - input buffer size
1305 \return VOS_STATUS_SUCCESS - NV item is read successfully
1306 VOS_STATUS_E_INVAL - one of the parameters is invalid
1307 VOS_STATUS_E_FAULT - outputBuffer pointer is NULL
1308 VOS_STATUS_E_EXISTS - NV type is unsupported
1309 VOS_STATUS_E_FAILURE - unknown error
1310 \sa
1311 -------------------------------------------------------------------------*/
1312VOS_STATUS vos_nv_write( VNV_TYPE type, v_VOID_t *inputVoidBuffer,
1313 v_SIZE_t bufferSize )
1314{
1315 VOS_STATUS status = VOS_STATUS_SUCCESS;
1316 v_SIZE_t itemSize;
Jeff Johnson43971f52012-07-17 12:26:56 -07001317
1318 // sanity check
1319 if (VNV_TYPE_COUNT <= type)
Jeff Johnson295189b2012-06-20 16:38:30 -07001320 {
1321 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001322 ("%s: invalid type=%d"), __func__, type );
Jeff Johnson295189b2012-06-20 16:38:30 -07001323 return VOS_STATUS_E_INVAL;
1324 }
1325 if (NULL == inputVoidBuffer)
1326 {
1327 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
1328 ("Buffer provided is NULL\r\n") );
1329 return VOS_STATUS_E_FAULT;
1330 }
1331 if (0 == bufferSize)
1332 {
1333 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
1334 ("NV type=%d is invalid\r\n"), type );
1335 return VOS_STATUS_E_INVAL;
1336 }
1337 switch(type)
1338 {
1339 case VNV_FIELD_IMAGE:
1340 itemSize = sizeof(gnvEFSTable->halnv.fields);
1341 if(bufferSize != itemSize) {
1342 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
1343 ("type = %d buffer size=%d is less than data size=%d\r\n"),type, bufferSize,
1344 itemSize);
1345 status = VOS_STATUS_E_INVAL;
1346 }
1347 else {
1348 memcpy(&gnvEFSTable->halnv.fields,inputVoidBuffer,bufferSize);
1349 }
1350 break;
1351 case VNV_RATE_TO_POWER_TABLE:
1352 itemSize = sizeof(gnvEFSTable->halnv.tables.pwrOptimum);
1353 if(bufferSize != itemSize) {
1354 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
1355 ("type = %d buffer size=%d is less than data size=%d\r\n"),type, bufferSize,
1356 itemSize);
1357 status = VOS_STATUS_E_INVAL;
1358 }
1359 else {
1360 memcpy(&gnvEFSTable->halnv.tables.pwrOptimum[0],inputVoidBuffer,bufferSize);
1361 }
1362 break;
1363 case VNV_REGULARTORY_DOMAIN_TABLE:
1364 itemSize = sizeof(gnvEFSTable->halnv.tables.regDomains);
1365 if(bufferSize != itemSize) {
1366 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
1367 ("type = %d buffer size=%d is less than data size=%d\r\n"),type, bufferSize,
1368 itemSize);
1369 status = VOS_STATUS_E_INVAL;
1370 }
1371 else {
1372 memcpy(&gnvEFSTable->halnv.tables.regDomains[0],inputVoidBuffer,bufferSize);
1373 }
1374 break;
1375 case VNV_DEFAULT_LOCATION:
1376 itemSize = sizeof(gnvEFSTable->halnv.tables.defaultCountryTable);
1377 if(bufferSize != itemSize) {
1378 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
1379 ("type = %d buffer size=%d is less than data size=%d\r\n"),type, bufferSize,
1380 itemSize);
1381 status = VOS_STATUS_E_INVAL;
1382 }
1383 else {
1384 memcpy(&gnvEFSTable->halnv.tables.defaultCountryTable,inputVoidBuffer,bufferSize);
1385 }
1386 break;
1387 case VNV_TPC_POWER_TABLE:
1388 itemSize = sizeof(gnvEFSTable->halnv.tables.plutCharacterized);
1389 if(bufferSize != itemSize) {
1390 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
1391 ("type = %d buffer size=%d is less than data size=%d\r\n"),type, bufferSize,
1392 itemSize);
1393 status = VOS_STATUS_E_INVAL;
1394 }
1395 else {
1396 memcpy(&gnvEFSTable->halnv.tables.plutCharacterized[0],inputVoidBuffer,bufferSize);
1397 }
1398 break;
1399 case VNV_TPC_PDADC_OFFSETS:
1400 itemSize = sizeof(gnvEFSTable->halnv.tables.plutPdadcOffset);
1401 if(bufferSize != itemSize) {
1402 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
1403 ("type = %d buffer size=%d is less than data size=%d\r\n"),type, bufferSize,
1404 itemSize);
1405 status = VOS_STATUS_E_INVAL;
1406 }
1407 else {
1408 memcpy(&gnvEFSTable->halnv.tables.plutPdadcOffset[0],inputVoidBuffer,bufferSize);
1409 }
1410 break;
1411 case VNV_RSSI_CHANNEL_OFFSETS:
1412
1413 itemSize = sizeof(gnvEFSTable->halnv.tables.rssiChanOffsets);
1414
1415 if(bufferSize != itemSize) {
1416
1417 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
1418 ("type = %d buffer size=%d is less than data size=%d\r\n"),type, bufferSize,
1419 itemSize);
1420 status = VOS_STATUS_E_INVAL;
1421 }
1422 else {
1423 memcpy(&gnvEFSTable->halnv.tables.rssiChanOffsets[0],inputVoidBuffer,bufferSize);
1424 }
1425 break;
1426 case VNV_RF_CAL_VALUES:
1427
1428 itemSize = sizeof(gnvEFSTable->halnv.tables.rFCalValues);
1429
1430 if(bufferSize != itemSize) {
1431
1432 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
1433 ("type = %d buffer size=%d is less than data size=%d\r\n"),type, bufferSize,
1434 itemSize);
1435 status = VOS_STATUS_E_INVAL;
1436 }
1437 else {
1438 memcpy(&gnvEFSTable->halnv.tables.rFCalValues,inputVoidBuffer,bufferSize);
1439 }
1440 break;
1441 case VNV_ANTENNA_PATH_LOSS:
1442 itemSize = sizeof(gnvEFSTable->halnv.tables.antennaPathLoss);
1443 if(bufferSize != itemSize) {
1444 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
1445 ("type = %d buffer size=%d is less than data size=%d\r\n"),type, bufferSize,
1446 itemSize);
1447 status = VOS_STATUS_E_INVAL;
1448 }
1449 else {
1450 memcpy(&gnvEFSTable->halnv.tables.antennaPathLoss[0],inputVoidBuffer,bufferSize);
1451 }
1452 break;
1453
1454 case VNV_PACKET_TYPE_POWER_LIMITS:
1455 itemSize = sizeof(gnvEFSTable->halnv.tables.pktTypePwrLimits);
1456 if(bufferSize != itemSize) {
1457 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
1458 ("type = %d buffer size=%d is less than data size=%d\r\n"),type, bufferSize,
1459 itemSize);
1460 status = VOS_STATUS_E_INVAL;
1461 }
1462 else {
1463 memcpy(&gnvEFSTable->halnv.tables.pktTypePwrLimits[0][0],inputVoidBuffer,bufferSize);
1464 }
1465 break;
1466
1467 case VNV_OFDM_CMD_PWR_OFFSET:
1468 itemSize = sizeof(gnvEFSTable->halnv.tables.ofdmCmdPwrOffset);
1469 if(bufferSize != itemSize) {
1470 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
1471 ("type = %d buffer size=%d is less than data size=%d\r\n"),type, bufferSize,
1472 itemSize);
1473 status = VOS_STATUS_E_INVAL;
1474 }
1475 else {
1476 memcpy(&gnvEFSTable->halnv.tables.ofdmCmdPwrOffset,inputVoidBuffer,bufferSize);
1477 }
1478 break;
1479
1480 case VNV_TX_BB_FILTER_MODE:
1481 itemSize = sizeof(gnvEFSTable->halnv.tables.txbbFilterMode);
1482 if(bufferSize != itemSize) {
1483 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
1484 ("type = %d buffer size=%d is less than data size=%d\r\n"),type, bufferSize,
1485 itemSize);
1486 status = VOS_STATUS_E_INVAL;
1487 }
1488 else {
1489 memcpy(&gnvEFSTable->halnv.tables.txbbFilterMode,inputVoidBuffer,bufferSize);
1490 }
1491 break;
1492
1493#ifdef FEATURE_WLAN_NON_INTEGRATED_SOC
1494 case VNV_FREQUENCY_FOR_1_3V_SUPPLY:
1495 itemSize = sizeof(gnvEFSTable->halnv.tables.freqFor1p3VSupply);
1496 if(bufferSize != itemSize) {
1497 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
1498 ("type = %d buffer size=%d is less than data size=%d\r\n"),type, bufferSize,
1499 itemSize);
1500 status = VOS_STATUS_E_INVAL;
1501 }
1502 else {
1503 memcpy(&gnvEFSTable->halnv.tables.freqFor1p3VSupply,inputVoidBuffer,bufferSize);
1504 }
1505 break;
1506#endif /* FEATURE_WLAN_NON_INTEGRATED_SOC */
1507
1508 case VNV_TABLE_VIRTUAL_RATE:
1509 itemSize = sizeof(gnvEFSTable->halnv.tables.pwrOptimum_virtualRate);
1510 if(bufferSize != itemSize) {
1511 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
1512 ("type = %d buffer size=%d is less than data size=%d\r\n"),type, bufferSize,
1513 itemSize);
1514 status = VOS_STATUS_E_INVAL;
1515 }
1516 else {
1517 memcpy(&gnvEFSTable->halnv.tables.pwrOptimum_virtualRate,inputVoidBuffer,bufferSize);
1518 }
1519 break;
1520
1521 default:
1522 break;
1523 }
1524 if (VOS_STATUS_SUCCESS == status)
1525 {
1526 // set NV item to have valid data
1527 status = vos_nv_setValidity( type, VOS_TRUE );
1528 if (! VOS_IS_STATUS_SUCCESS(status)) {
1529 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, ("vos_nv_setValidity failed!!!\r\n"));
1530 status = VOS_STATUS_E_FAULT;
1531 }
1532 status = wlan_write_to_efs((v_U8_t*)gnvEFSTable,sizeof(nvEFSTable_t));
1533
1534 if (! VOS_IS_STATUS_SUCCESS(status)) {
1535 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, ("vos_nv_write_to_efs failed!!!\r\n"));
1536 status = VOS_STATUS_E_FAULT;
1537 }
1538 }
1539 return status;
1540}
1541#endif
1542
1543/**------------------------------------------------------------------------
1544 \brief vos_nv_getChannelListWithPower() - function to return the list of
1545 supported channels with the power limit info too.
1546 \param pChannels20MHz - list of 20 Mhz channels
1547 \param pNum20MHzChannelsFound - number of 20 Mhz channels
1548 \param pChannels40MHz - list of 20 Mhz channels
1549 \param pNum40MHzChannelsFound - number of 20 Mhz channels
1550 \return status of the NV read operation
1551 \Note: 40Mhz not currently supported
1552 \sa
1553 -------------------------------------------------------------------------*/
1554VOS_STATUS vos_nv_getChannelListWithPower(tChannelListWithPower *channels20MHz /*[NUM_LEGIT_RF_CHANNELS] */,
1555 tANI_U8 *num20MHzChannelsFound,
1556 tChannelListWithPower *channels40MHz /*[NUM_CHAN_BOND_CHANNELS] */,
1557 tANI_U8 *num40MHzChannelsFound
1558 )
1559{
1560 VOS_STATUS status = VOS_STATUS_SUCCESS;
1561 int i, count;
1562
1563 //TODO: Dont want to use pMac here...can we instead store the curRegDomain in NV
1564 // or pass it as a parameter to NV from SME?
1565
1566 if( channels20MHz && num20MHzChannelsFound )
1567 {
1568 count = 0;
1569 for( i = 0; i <= RF_CHAN_14; i++ )
1570 {
1571 if( regChannels[i].enabled )
1572 {
1573 channels20MHz[count].chanId = rfChannels[i].channelNum;
1574 channels20MHz[count++].pwr = regChannels[i].pwrLimit;
1575 }
1576 }
1577#ifdef FEATURE_WLAN_INTEGRATED_SOC
1578 for( i = RF_CHAN_36; i <= RF_CHAN_165; i++ )
1579 {
1580 if( regChannels[i].enabled )
1581 {
1582 channels20MHz[count].chanId = rfChannels[i].channelNum;
1583 channels20MHz[count++].pwr = regChannels[i].pwrLimit;
1584 }
1585 }
1586#endif
1587 *num20MHzChannelsFound = (tANI_U8)count;
1588 }
Jeff Johnsone7245742012-09-05 17:12:55 -07001589
1590 if( channels40MHz && num40MHzChannelsFound )
1591 {
1592 count = 0;
1593#ifdef FEATURE_WLAN_INTEGRATED_SOC
1594 //center channels for 2.4 Ghz 40 MHz channels
1595 for( i = RF_CHAN_BOND_3; i <= RF_CHAN_BOND_11; i++ )
1596 {
1597
1598 if( regChannels[i].enabled )
1599 {
1600 channels40MHz[count].chanId = rfChannels[i].channelNum;
1601 channels40MHz[count++].pwr = regChannels[i].pwrLimit;
1602 }
1603 }
1604 //center channels for 5 Ghz 40 MHz channels
1605 for( i = RF_CHAN_BOND_38; i <= RF_CHAN_BOND_163; i++ )
1606 {
1607
1608 if( regChannels[i].enabled )
1609 {
1610 channels40MHz[count].chanId = rfChannels[i].channelNum;
1611 channels40MHz[count++].pwr = regChannels[i].pwrLimit;
1612 }
1613 }
1614#endif
1615 *num40MHzChannelsFound = (tANI_U8)count;
1616 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001617 return (status);
1618}
1619
1620/**------------------------------------------------------------------------
1621 \brief vos_nv_getDefaultRegDomain() - return the default regulatory domain
1622 \return default regulatory domain
1623 \sa
1624 -------------------------------------------------------------------------*/
1625
1626v_REGDOMAIN_t vos_nv_getDefaultRegDomain( void )
1627{
1628 return countryInfoTable.countryInfo[0].regDomain;
1629}
1630
1631/**------------------------------------------------------------------------
1632 \brief vos_nv_getSupportedChannels() - function to return the list of
1633 supported channels
1634 \param p20MhzChannels - list of 20 Mhz channels
1635 \param pNum20MhzChannels - number of 20 Mhz channels
1636 \param p40MhzChannels - list of 40 Mhz channels
1637 \param pNum40MhzChannels - number of 40 Mhz channels
1638 \return status of the NV read operation
1639 \Note: 40Mhz not currently supported
1640 \sa
1641 -------------------------------------------------------------------------*/
1642VOS_STATUS vos_nv_getSupportedChannels( v_U8_t *p20MhzChannels, int *pNum20MhzChannels,
1643 v_U8_t *p40MhzChannels, int *pNum40MhzChannels)
1644{
1645 VOS_STATUS status = VOS_STATUS_E_INVAL;
1646 int i, count = 0;
1647
1648 if( p20MhzChannels && pNum20MhzChannels )
1649 {
1650 if( *pNum20MhzChannels >= NUM_RF_CHANNELS )
1651 {
1652 for( i = 0; i <= RF_CHAN_14; i++ )
1653 {
1654 p20MhzChannels[count++] = rfChannels[i].channelNum;
1655 }
1656#ifdef FEATURE_WLAN_INTEGRATED_SOC
1657 for( i = RF_CHAN_36; i <= RF_CHAN_165; i++ )
1658 {
1659 p20MhzChannels[count++] = rfChannels[i].channelNum;
1660 }
1661#endif
1662 status = VOS_STATUS_SUCCESS;
1663 }
1664 *pNum20MhzChannels = count;
1665 }
1666
1667 return (status);
1668}
1669
1670/**------------------------------------------------------------------------
1671 \brief vos_nv_readDefaultCountryTable() - return the default Country table
1672 \param table data - a union to return the default country table data in.
1673 \return status of the NV read operation
1674 \sa
1675 -------------------------------------------------------------------------*/
1676VOS_STATUS vos_nv_readDefaultCountryTable( uNvTables *tableData )
1677{
1678
Madan Mohan Koyyalamudic3a240c2012-09-28 15:34:08 -07001679 VOS_STATUS status = VOS_STATUS_SUCCESS;
1680 memcpy(&tableData->defaultCountryTable, &pnvEFSTable->halnv.tables.defaultCountryTable, sizeof(sDefaultCountry));
1681 pr_info("DefaultCountry is %c%c\n",
1682 tableData->defaultCountryTable.countryCode[0],
1683 tableData->defaultCountryTable.countryCode[1]);
Jeff Johnson295189b2012-06-20 16:38:30 -07001684 return status;
1685}
1686
1687/**------------------------------------------------------------------------
1688 \brief vos_nv_getBuffer -
1689 \param pBuffer - to return the buffer address
1690 pSize - buffer size.
1691 \return status of the NV read operation
1692 \sa
1693 -------------------------------------------------------------------------*/
1694VOS_STATUS vos_nv_getNVBuffer(v_VOID_t **pNvBuffer,v_SIZE_t *pSize)
1695{
1696
1697 /* Send the NV structure and size */
1698 *pNvBuffer = (v_VOID_t *)(&pnvEFSTable->halnv);
1699 *pSize = sizeof(sHalNv);
1700
1701 return VOS_STATUS_SUCCESS;
1702}
1703
1704#ifdef FEATURE_WLAN_INTEGRATED_SOC
1705/**------------------------------------------------------------------------
1706 \brief vos_nv_setRegDomain -
1707 \param clientCtxt - Client Context, Not used for PRIMA
1708 regId - Regulatory Domain ID
1709 \return status set REG domain operation
1710 \sa
1711 -------------------------------------------------------------------------*/
1712VOS_STATUS vos_nv_setRegDomain(void * clientCtxt, v_REGDOMAIN_t regId)
1713{
1714 /* Client Context Argumant not used for PRIMA */
1715 if(regId >= REGDOMAIN_COUNT)
1716 {
1717 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
1718 "VOS set reg domain, invalid REG domain ID %d", regId);
1719 return VOS_STATUS_E_INVAL;
1720 }
1721
1722 /* Set correct channel information based on REG Domain */
1723 regChannels = pnvEFSTable->halnv.tables.regDomains[regId].channels;
1724
1725 return VOS_STATUS_SUCCESS;
1726}
1727
1728/**------------------------------------------------------------------------
1729 \brief vos_nv_getChannelEnabledState -
1730 \param rfChannel - input channel enum to know evabled state
1731 \return eNVChannelEnabledType enabled state for channel
1732 * enabled
1733 * disabled
1734 * DFS
1735 \sa
1736 -------------------------------------------------------------------------*/
1737eNVChannelEnabledType vos_nv_getChannelEnabledState
1738(
1739 v_U32_t rfChannel
1740)
1741{
1742 v_U32_t channelLoop;
1743 eRfChannels channelEnum = INVALID_RF_CHANNEL;
1744
1745 for(channelLoop = 0; channelLoop <= RF_CHAN_165; channelLoop++)
1746 {
1747 if(rfChannels[channelLoop].channelNum == rfChannel)
1748 {
1749 channelEnum = (eRfChannels)channelLoop;
1750 break;
1751 }
1752 }
1753
1754 if(INVALID_RF_CHANNEL == channelEnum)
1755 {
1756 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
Jeff Johnsonb88db982012-12-10 13:34:59 -08001757 "vos_nv_getChannelEnabledState, invalid channel %d", rfChannel);
Jeff Johnson295189b2012-06-20 16:38:30 -07001758 return NV_CHANNEL_INVALID;
1759 }
1760
1761 return regChannels[channelEnum].enabled;
1762}
1763#endif /* FEATURE_WLAN_NON_INTEGRATED_SOC */
Madan Mohan Koyyalamudic3a240c2012-09-28 15:34:08 -07001764
1765/******************************************************************
1766 Add CRDA regulatory support
1767*******************************************************************/
1768#ifdef CONFIG_CFG80211
1769
1770static int bw20_ch_index_to_bw40_ch_index(int k)
1771{
1772 int m = -1;
1773 if (k >= RF_CHAN_1 && k <= RF_CHAN_14)
1774 {
1775 m = k - RF_CHAN_1 + RF_CHAN_BOND_3 ;
1776 if (m > RF_CHAN_BOND_11)
1777 m = RF_CHAN_BOND_11;
1778 }
1779 else if (k >= RF_CHAN_240 && k <= RF_CHAN_216)
1780 {
1781 m = k - RF_CHAN_240 + RF_CHAN_BOND_242 ;
1782 if (m > RF_CHAN_BOND_214)
1783 m = RF_CHAN_BOND_214;
1784 }
1785 else if (k >= RF_CHAN_36 && k <= RF_CHAN_64)
1786 {
1787 m = k - RF_CHAN_36 + RF_CHAN_BOND_38;
1788 if (m > RF_CHAN_BOND_62)
1789 m = RF_CHAN_BOND_62;
1790 }
1791 else if (k >= RF_CHAN_100 && k <= RF_CHAN_140)
1792 {
1793 m = k - RF_CHAN_100 + RF_CHAN_BOND_102;
1794 if (m > RF_CHAN_BOND_138)
1795 m = RF_CHAN_BOND_138;
1796 }
1797 else if (k >= RF_CHAN_149 && k <= RF_CHAN_165)
1798 {
1799 m = k - RF_CHAN_149 + RF_CHAN_BOND_151;
1800 if (m > RF_CHAN_BOND_163)
1801 m = RF_CHAN_BOND_163;
1802 }
1803return m;
1804}
1805
1806/* create_crda_regulatory_entry should be called from user command or 11d country IE */
1807static int create_crda_regulatory_entry(struct wiphy *wiphy,
1808 struct regulatory_request *request,
1809 v_U8_t nBandCapability)
1810{
1811 int i, j, m;
1812 int k = 0, n = 0;
1813
1814 if (run_time_alpha2[0]==request->alpha2[0] &&
1815 run_time_alpha2[1]==request->alpha2[1] &&
1816 crda_regulatory_run_time_entry_valid == VOS_TRUE)
1817 return 0; /* already created */
1818
1819 /* 20MHz channels */
1820 if (nBandCapability == eCSR_BAND_24)
1821 pr_info("BandCapability is set to 2G only.\n");
1822 for (i=0,m=0;i<IEEE80211_NUM_BANDS;i++)
1823 {
1824 if (i == IEEE80211_BAND_2GHZ && nBandCapability == eCSR_BAND_5G) // 5G only
1825 continue;
1826 else if (i == IEEE80211_BAND_5GHZ && nBandCapability == eCSR_BAND_24) // 2G only
1827 continue;
1828 if (wiphy->bands[i] == NULL)
1829 {
1830 pr_info("error: wiphy->bands[i] is NULL, i = %d\n", i);
1831 return -1;
1832 }
1833 // internal channels[] is one continous array for both 2G and 5G bands
1834 // m is internal starting channel index for each band
1835 if (i == 0)
1836 m = 0;
1837 else
1838 m = wiphy->bands[i-1]->n_channels + m;
1839 for (j=0;j<wiphy->bands[i]->n_channels;j++)
1840 {
1841 // k = (m + j) is internal current channel index for 20MHz channel
1842 // n is internal channel index for corresponding 40MHz channel
1843 k = m + j;
1844 n = bw20_ch_index_to_bw40_ch_index(k);
1845 if (n == -1)
1846 return -1;
1847 if (wiphy->bands[i]->channels[j].flags & IEEE80211_CHAN_DISABLED)
1848 {
1849 if (pnvEFSTable == NULL)
1850 {
1851 pr_info("error: pnvEFSTable is NULL, probably not parsed nv.bin yet\n");
1852 return -1;
1853 }
1854 pnvEFSTable->halnv.tables.regDomains[NUM_REG_DOMAINS-2].channels[k].enabled =
1855 NV_CHANNEL_DISABLE;
1856 pnvEFSTable->halnv.tables.regDomains[NUM_REG_DOMAINS-2].channels[n].enabled =
1857 NV_CHANNEL_DISABLE;
1858 //pr_info("CH %d disabled, no bonding centered on CH %d.\n", rfChannels[k].channelNum,
1859 // rfChannels[n].channelNum);
1860 }
1861 else if (wiphy->bands[i]->channels[j].flags & IEEE80211_CHAN_RADAR)
1862 {
1863 pnvEFSTable->halnv.tables.regDomains[NUM_REG_DOMAINS-2].channels[k].enabled =
1864 NV_CHANNEL_DFS;
1865 // max_power is in mBm = 100 * d
1866 pnvEFSTable->halnv.tables.regDomains[NUM_REG_DOMAINS-2].channels[k].pwrLimit =
1867 (tANI_S8) (wiphy->bands[i]->channels[j].max_power);
1868 pr_info("CH %d is enabled and DFS, max power %d dBm.\n", rfChannels[k].channelNum,
1869 pnvEFSTable->halnv.tables.regDomains[NUM_REG_DOMAINS-2].channels[k].pwrLimit);
1870 if ((wiphy->bands[i]->channels[j].flags & IEEE80211_CHAN_NO_HT40) == 0)
1871 {
1872 pnvEFSTable->halnv.tables.regDomains[NUM_REG_DOMAINS-2].channels[n].enabled =
1873 NV_CHANNEL_DFS;
1874 // 40MHz channel power is half of 20MHz (-3dB) ??
1875 pnvEFSTable->halnv.tables.regDomains[NUM_REG_DOMAINS-2].channels[n].pwrLimit =
1876 (tANI_S8) ((wiphy->bands[i]->channels[j].max_power)-3);
1877 pr_info(" CH %d is enabled for 40MHz and DFS, max power %d dBm.\n", rfChannels[n].channelNum,
1878 pnvEFSTable->halnv.tables.regDomains[NUM_REG_DOMAINS-2].channels[n].pwrLimit);
1879 }
1880 }
1881 else // Enable is only last flag we support
1882 {
1883 pnvEFSTable->halnv.tables.regDomains[NUM_REG_DOMAINS-2].channels[k].enabled =
1884 NV_CHANNEL_ENABLE;
1885 // max_power is in dBm
1886 pnvEFSTable->halnv.tables.regDomains[NUM_REG_DOMAINS-2].channels[k].pwrLimit =
1887 (tANI_S8) (wiphy->bands[i]->channels[j].max_power);
1888 pr_info("CH %d is enabled and no DFS, max power %d dBm.\n", rfChannels[k].channelNum,
1889 pnvEFSTable->halnv.tables.regDomains[NUM_REG_DOMAINS-2].channels[k].pwrLimit);
1890 if ((wiphy->bands[i]->channels[j].flags & IEEE80211_CHAN_NO_HT40) == 0)
1891 {
1892 pnvEFSTable->halnv.tables.regDomains[NUM_REG_DOMAINS-2].channels[n].enabled =
1893 NV_CHANNEL_ENABLE;
1894 // 40MHz channel power is half of 20MHz (-3dB) ??
1895 pnvEFSTable->halnv.tables.regDomains[NUM_REG_DOMAINS-2].channels[n].pwrLimit =
1896 (tANI_S8) ((wiphy->bands[i]->channels[j].max_power)-3);
1897 pr_info(" CH %d is enabled for 40MHz and no DFS, max power %d dBm.\n", rfChannels[n].channelNum,
1898 pnvEFSTable->halnv.tables.regDomains[NUM_REG_DOMAINS-2].channels[n].pwrLimit);
1899 }
1900 }
1901 /* ignore CRDA max_antenna_gain typical is 3dBi, nv.bin antennaGain is
1902 real gain which should be provided by the real design */
1903 }
1904 }
1905 if (k == 0)
1906 return -1;
1907 run_time_alpha2[0] = request->alpha2[0];
1908 run_time_alpha2[1] = request->alpha2[1];
1909 crda_regulatory_run_time_entry_valid = VOS_TRUE;
1910return 0;
1911}
1912v_BOOL_t is_crda_regulatory_entry_valid(void)
1913{
1914return crda_regulatory_entry_valid;
1915}
1916
1917/* Handling routines for the conversion from regd rules (start/end freq) to channel index
1918start freq + 10000 = center freq of the 20MHz start channel
1919end freq - 10000 = center freq of the 20MHz end channel
1920start freq + 20000 = center freq of the 40MHz start channel
1921end freq - 20000 = center freq of the 40MHz end channel
1922*/
1923static int bw20_start_freq_to_channel_index(u32 freq_khz)
1924{
1925int i;
1926u32 center_freq = freq_khz + 10000;
1927 //Has to compare from low freq to high freq
1928 //RF_SUBBAND_2_4_GHZ
1929 for (i=RF_CHAN_1;i<=RF_CHAN_14;i++)
1930 if (center_freq <= (u32) (rfChannels[i].targetFreq) * 1000)
1931 return i;
1932#ifdef FEATURE_WLAN_INTEGRATED_SOC
1933 //RF_SUBBAND_4_9_GHZ, Ch 240, 244, 248, 252, 208, 212, 216
1934 for (i=RF_CHAN_240;i<=RF_CHAN_216;i++)
1935 if (center_freq <= (u32) (rfChannels[i].targetFreq) * 1000)
1936 return i;
1937 //RF_SUBBAND_5_LOW_GHZ
1938 for (i=RF_CHAN_36;i<=RF_CHAN_64;i++)
1939 if (center_freq <= (u32) (rfChannels[i].targetFreq) * 1000)
1940 return i;
1941 //RF_SUBBAND_5_MID_GHZ
1942 for (i=RF_CHAN_100;i<=RF_CHAN_140;i++)
1943 if (center_freq <= (u32) (rfChannels[i].targetFreq) * 1000)
1944 return i;
1945 //RF_SUBBAND_5_HIGH_GHZ
1946 for (i=RF_CHAN_149;i<=RF_CHAN_165;i++)
1947 if (center_freq <= (u32) (rfChannels[i].targetFreq) * 1000)
1948 return i;
1949#endif
1950return -1;
1951}
1952
1953static int bw20_end_freq_to_channel_index(u32 freq_khz)
1954{
1955int i;
1956u32 center_freq = freq_khz - 10000;
1957 //Has to compare from high freq to low freq
1958#ifdef FEATURE_WLAN_INTEGRATED_SOC
1959 //RF_SUBBAND_5_HIGH_GHZ
1960 for (i=RF_CHAN_165;i>=RF_CHAN_149;i--)
1961 if (center_freq >= (u32) (rfChannels[i].targetFreq) * 1000)
1962 return i;
1963 //RF_SUBBAND_5_MID_GHZ
1964 for (i=RF_CHAN_140;i>=RF_CHAN_100;i--)
1965 if (center_freq >= (u32) (rfChannels[i].targetFreq) * 1000)
1966 return i;
1967 //RF_SUBBAND_5_LOW_GHZ
1968 for (i=RF_CHAN_64;i>=RF_CHAN_36;i--)
1969 if (center_freq >= (u32) (rfChannels[i].targetFreq) * 1000)
1970 return i;
1971 //RF_SUBBAND_4_9_GHZ, Ch 216, 212, 208, 252, 248, 244, 240
1972 for (i=RF_CHAN_216;i>=RF_CHAN_240;i--)
1973 if (center_freq >= (u32) (rfChannels[i].targetFreq) * 1000)
1974 return i;
1975#endif
1976 //RF_SUBBAND_2_4_GHZ
1977 for (i=RF_CHAN_14;i>=RF_CHAN_1;i--)
1978 if (center_freq >= (u32) (rfChannels[i].targetFreq) * 1000)
1979 return i;
1980return -1;
1981}
1982
1983static int bw40_start_freq_to_channel_index(u32 freq_khz)
1984{
1985int i;
1986u32 center_freq = freq_khz + 20000;
1987 //Has to compare from low freq to high freq
1988 //RF_SUBBAND_2_4_GHZ
1989 for (i=RF_CHAN_BOND_3;i<=RF_CHAN_BOND_11;i++)
1990 if (center_freq <= (u32) (rfChannels[i].targetFreq) * 1000)
1991 return i;
1992#ifdef FEATURE_WLAN_INTEGRATED_SOC
1993 //RF_SUBBAND_4_9_GHZ, Ch 242, 246, 250, 210, 214
1994 for (i=RF_CHAN_BOND_242;i<=RF_CHAN_BOND_214;i++)
1995 if (center_freq <= (u32) (rfChannels[i].targetFreq) * 1000)
1996 return i;
1997 //RF_SUBBAND_5_LOW_GHZ
1998 for (i=RF_CHAN_BOND_38;i<=RF_CHAN_BOND_62;i++)
1999 if (center_freq <= (u32) (rfChannels[i].targetFreq) * 1000)
2000 return i;
2001 //RF_SUBBAND_5_MID_GHZ
2002 for (i=RF_CHAN_BOND_102;i<=RF_CHAN_BOND_138;i++)
2003 if (center_freq <= (u32) (rfChannels[i].targetFreq) * 1000)
2004 return i;
2005 //RF_SUBBAND_5_HIGH_GHZ
2006 for (i=RF_CHAN_BOND_151;i<=RF_CHAN_BOND_163;i++)
2007 if (center_freq <= (u32) (rfChannels[i].targetFreq) * 1000)
2008 return i;
2009#endif
2010return -1;
2011}
2012
2013static int bw40_end_freq_to_channel_index(u32 freq_khz)
2014{
2015int i;
2016u32 center_freq = freq_khz - 20000;
2017 //Has to compare from high freq to low freq
2018#ifdef FEATURE_WLAN_INTEGRATED_SOC
2019 //RF_SUBBAND_5_HIGH_GHZ
2020 for (i=RF_CHAN_BOND_163;i>=RF_CHAN_BOND_151;i--)
2021 if (center_freq >= (u32) (rfChannels[i].targetFreq) * 1000)
2022 return i;
2023 //RF_SUBBAND_5_MID_GHZ
2024 for (i=RF_CHAN_BOND_138;i>=RF_CHAN_BOND_102;i--)
2025 if (center_freq >= (u32) (rfChannels[i].targetFreq) * 1000)
2026 return i;
2027 //RF_SUBBAND_5_LOW_GHZ
2028 for (i=RF_CHAN_BOND_62;i>=RF_CHAN_BOND_38;i--)
2029 if (center_freq >= (u32) (rfChannels[i].targetFreq) * 1000)
2030 return i;
2031 //RF_SUBBAND_4_9_GHZ, Ch 214, 210, 250, 246, 242
2032 for (i=RF_CHAN_BOND_214;i>=RF_CHAN_BOND_242;i--)
2033 if (center_freq >= (u32) (rfChannels[i].targetFreq) * 1000)
2034 return i;
2035#endif
2036 //RF_SUBBAND_2_4_GHZ
2037 for (i=RF_CHAN_BOND_11;i>=RF_CHAN_BOND_3;i--)
2038 if (center_freq >= (u32) (rfChannels[i].targetFreq) * 1000)
2039 return i;
2040return -1;
2041}
2042
2043static v_BOOL_t channel_in_capable_band(int j, v_U8_t nBandCapability)
2044{
2045 switch (nBandCapability)
2046 {
2047 case eCSR_BAND_ALL:
2048 return VOS_TRUE;
2049 case eCSR_BAND_24:
2050 if (j >= RF_CHAN_1 && j <= RF_CHAN_14)
2051 return VOS_TRUE;
2052 if (j >= RF_CHAN_BOND_3 && j <= RF_CHAN_BOND_11)
2053 return VOS_TRUE; // 2.4G 40MHz channel
2054 break;
2055 case eCSR_BAND_5G:
2056 if (j >= RF_CHAN_240 && j <= RF_CHAN_165)
2057 return VOS_TRUE;
2058 if (j >= RF_CHAN_BOND_242 && j <= RF_CHAN_BOND_163)
2059 return VOS_TRUE; // 2.4G 40MHz channel
2060 break;
2061 default:
2062 break;
2063 }
2064 return VOS_FALSE;
2065}
2066
2067/* create_crda_regulatory_entry_from_regd should be called during init time */
2068static int create_crda_regulatory_entry_from_regd(struct wiphy *wiphy,
2069 struct regulatory_request *request,
2070 v_U8_t nBandCapability)
2071{
2072 int i, j, n, domain_id;
2073 int bw20_start_channel_index, bw20_end_channel_index;
2074 int bw40_start_channel_index, bw40_end_channel_index;
2075
2076 if (wiphy == NULL || wiphy->regd == NULL)
2077 {
2078 wiphy_dbg(wiphy, "error: wiphy->regd is NULL\n");
2079 return -1;
2080 }
2081 if (crda_regulatory_entry_valid == VOS_FALSE)
2082 domain_id = NUM_REG_DOMAINS-1; /* init time */
2083 else
2084 domain_id = NUM_REG_DOMAINS-2; /* none-default country */
2085 for (n = 0; n < NUM_RF_CHANNELS; n++)
2086 pnvEFSTable->halnv.tables.regDomains[domain_id].channels[n].enabled = NV_CHANNEL_DISABLE;
2087
2088 for (i=0;i<wiphy->regd->n_reg_rules;i++)
2089 {
2090 wiphy_dbg(wiphy, "info: crda rule %d --------------------------------------------\n", i);
2091 bw20_start_channel_index =
2092 bw20_start_freq_to_channel_index(wiphy->regd->reg_rules[i].freq_range.start_freq_khz);
2093 bw20_end_channel_index =
2094 bw20_end_freq_to_channel_index(wiphy->regd->reg_rules[i].freq_range.end_freq_khz);
2095 if (bw20_start_channel_index == -1 || bw20_end_channel_index == -1)
2096 {
2097 wiphy_dbg(wiphy, "error: crda freq not supported, start freq (KHz) %d end freq %d\n",
2098 wiphy->regd->reg_rules[i].freq_range.start_freq_khz,
2099 wiphy->regd->reg_rules[i].freq_range.end_freq_khz);
2100 continue; // skip this rull, but continue to next rule
2101 }
2102 wiphy_dbg(wiphy, "20MHz start freq (KHz) %d end freq %d start ch index %d end ch index %d\n",
2103 wiphy->regd->reg_rules[i].freq_range.start_freq_khz,
2104 wiphy->regd->reg_rules[i].freq_range.end_freq_khz,
2105 bw20_start_channel_index, bw20_end_channel_index);
2106 for (j=bw20_start_channel_index;j<=bw20_end_channel_index;j++)
2107 {
2108 if (channel_in_capable_band(j, nBandCapability) == VOS_FALSE)
2109 {
2110 wiphy_dbg(wiphy, "info: CH %d is not in capable band\n",
2111 rfChannels[j].channelNum);
2112 continue; // skip this channel, continue to next
2113 }
2114 if (wiphy->regd->reg_rules[i].flags & NL80211_RRF_DFS)
2115 {
2116 pnvEFSTable->halnv.tables.regDomains[domain_id].channels[j].enabled = NV_CHANNEL_DFS;
2117 wiphy_dbg(wiphy, "info: CH %d is DFS, max EIRP (mBm) is %d\n", rfChannels[j].channelNum,
2118 wiphy->regd->reg_rules[i].power_rule.max_eirp);
2119 }
2120 else
2121 {
2122 pnvEFSTable->halnv.tables.regDomains[domain_id].channels[j].enabled = NV_CHANNEL_ENABLE;
2123 wiphy_dbg(wiphy, "info: CH %d is enabled, no DFS, max EIRP (mBm) is %d\n", rfChannels[j].channelNum,
2124 wiphy->regd->reg_rules[i].power_rule.max_eirp);
2125 }
2126 /* max_eirp is in mBm (= 100 * dBm) unit */
2127 pnvEFSTable->halnv.tables.regDomains[domain_id].channels[j].pwrLimit =
2128 (tANI_S8) ((wiphy->regd->reg_rules[i].power_rule.max_eirp)/100);
2129 }
2130 /* ignore CRDA max_antenna_gain typical is 3dBi, nv.bin antennaGain is
2131 real gain which should be provided by the real design */
2132 if (wiphy->regd->reg_rules[i].freq_range.max_bandwidth_khz == 40000)
2133 {
2134 wiphy_dbg(wiphy, "info: 40MHz (channel bonding) is allowed\n");
2135 bw40_start_channel_index =
2136 bw40_start_freq_to_channel_index(wiphy->regd->reg_rules[i].freq_range.start_freq_khz);
2137 bw40_end_channel_index =
2138 bw40_end_freq_to_channel_index(wiphy->regd->reg_rules[i].freq_range.end_freq_khz);
2139 if (bw40_start_channel_index == -1 || bw40_end_channel_index == -1)
2140 {
2141 wiphy_dbg(wiphy, "error: crda freq not supported, start_freq_khz %d end_freq_khz %d\n",
2142 wiphy->regd->reg_rules[i].freq_range.start_freq_khz,
2143 wiphy->regd->reg_rules[i].freq_range.end_freq_khz);
2144 continue; // skip this rull, but continue to next rule
2145 }
2146 wiphy_dbg(wiphy, "40MHz start freq (KHz) %d end freq %d start ch index %d end ch index %d\n",
2147 wiphy->regd->reg_rules[i].freq_range.start_freq_khz,
2148 wiphy->regd->reg_rules[i].freq_range.end_freq_khz,
2149 bw40_start_channel_index, bw40_end_channel_index);
2150 for (j=bw40_start_channel_index;j<=bw40_end_channel_index;j++)
2151 {
2152 if (channel_in_capable_band(j, nBandCapability) == VOS_FALSE)
2153 continue; // skip this channel, continue to next
2154 if (wiphy->regd->reg_rules[i].flags & NL80211_RRF_DFS)
2155 {
2156 pnvEFSTable->halnv.tables.regDomains[domain_id].channels[j].enabled = NV_CHANNEL_DFS;
2157 wiphy_dbg(wiphy, "info: 40MHz centered on CH %d is DFS\n", rfChannels[j].channelNum);
2158 }
2159 else
2160 {
2161 pnvEFSTable->halnv.tables.regDomains[domain_id].channels[j].enabled = NV_CHANNEL_ENABLE;
2162 wiphy_dbg(wiphy, "info: 40MHz centered on CH %d is enabled, no DFS\n", rfChannels[j].channelNum);
2163 }
2164 /* set 40MHz channel power as half (- 3 dB) of 20MHz */
2165 pnvEFSTable->halnv.tables.regDomains[domain_id].channels[j].pwrLimit =
2166 (tANI_S8) (((wiphy->regd->reg_rules[i].power_rule.max_eirp)/100)-3);
2167 }
2168 }
2169 }
2170 /* ToDo update other (than DFS) crda regulatory flags (NO_OUTDOOR,
2171 NO_OFDM, PASSIVE_SCAN, NO_IBSS) to pnvEFSTable which doesn't add
2172 these flags and has no implementation yet. */
2173 if (crda_regulatory_entry_valid == VOS_FALSE)
2174 { /* init time */
2175 crda_alpha2[0] = request->alpha2[0];
2176 crda_alpha2[1] = request->alpha2[1];
2177 crda_regulatory_entry_valid = VOS_TRUE;
2178 }
2179 else
2180 { /* none-default country */
2181 run_time_alpha2[0] = request->alpha2[0];
2182 run_time_alpha2[1] = request->alpha2[1];
2183 crda_regulatory_run_time_entry_valid = VOS_TRUE;
2184 }
2185 return 0;
2186}
2187
2188/*
2189 * Function: wlan_hdd_crda_reg_notifier
2190 * This function is called from cfg80211 core to provide regulatory settings
2191 * after new country is requested or intersected (init, user input or 11d)
2192 * This function is used to create a CRDA regulatory settings entry into internal
2193 * regulatory setting table.
2194 */
2195int wlan_hdd_crda_reg_notifier(struct wiphy *wiphy,
2196 struct regulatory_request *request)
2197{
2198 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
2199 wiphy_dbg(wiphy, "info: cfg80211 reg_notifier callback for country"
2200 " %c%c\n", request->alpha2[0], request->alpha2[1]);
2201 if (request->initiator == NL80211_REGDOM_SET_BY_USER)
2202 {
2203 wiphy_dbg(wiphy, "info: set by user\n");
2204 if (create_crda_regulatory_entry(wiphy, request, pHddCtx->cfg_ini->nBandCapability) != 0)
2205 return 0;
2206 // ToDo
2207 /* Don't change default country code to CRDA country code by user req */
2208 /* Shouldcall sme_ChangeCountryCode to send a message to trigger read
2209 regd for new country settings */
2210 //sme_ChangeCountryCode(pHddCtx->hHal, NULL,
2211 // &country_code[0], pAdapter, pHddCtx->pvosContext);
2212 }
2213 else if (request->initiator == NL80211_REGDOM_SET_BY_COUNTRY_IE)
2214 {
2215 wiphy_dbg(wiphy, "info: set by country IE\n");
2216 if (create_crda_regulatory_entry(wiphy, request, pHddCtx->cfg_ini->nBandCapability) != 0)
2217 return 0;
2218 // ToDo
2219 /* Intersect of 11d and crda settings */
2220
2221 /* Don't change default country code to CRDA country code by 11d req */
2222 /* for every adapter call sme_ChangeCountryCode to trigger read regd
2223 for intersected new country settings */
2224 // sme_ChangeCountryCode(pHddCtx->hHal, NULL,
2225 // &country_code[0], pAdapter, pHddCtx->pvosContext);
2226 }
2227 else if (request->initiator == NL80211_REGDOM_SET_BY_DRIVER)
2228 {
2229 wiphy_dbg(wiphy, "info: set by driver\n");
2230 /* if set by driver itself, it means driver can accept the crda
2231 regulatory settings and wiphy->regd should be populated with crda
2232 settings. iwiphy->bands doesn't seem to set ht40 flags in kernel
2233 correctly, this may be fixed by later kernel */
2234 if (create_crda_regulatory_entry_from_regd(wiphy, request, pHddCtx->cfg_ini->nBandCapability) == 0)
2235 {
2236 pr_info("crda entry created.\n");
2237 if (crda_alpha2[0] == request->alpha2[0] && crda_alpha2[1] == request->alpha2[1])
2238 { /* first CRDA request should be from init time */
2239 /* Change default country code to CRDA country code, assume indoor */
2240 pnvEFSTable->halnv.tables.defaultCountryTable.countryCode[0] = request->alpha2[0];
2241 pnvEFSTable->halnv.tables.defaultCountryTable.countryCode[1] = request->alpha2[1];
2242 pnvEFSTable->halnv.tables.defaultCountryTable.countryCode[2] = 'I';
2243 pnvEFSTable->halnv.tables.defaultCountryTable.regDomain = NUM_REG_DOMAINS-1;
2244 wiphy_dbg(wiphy, "info: init time default country code is %c%c%c\n",
2245 pnvEFSTable->halnv.tables.defaultCountryTable.countryCode[0],
2246 pnvEFSTable->halnv.tables.defaultCountryTable.countryCode[1],
2247 pnvEFSTable->halnv.tables.defaultCountryTable.countryCode[2]);
2248 }
2249 else /* second or later CRDA request after init time */
2250 {
2251 wiphy_dbg(wiphy, "info: crda none-default country code is %c%c\n",
2252 request->alpha2[0], request->alpha2[1]);
2253 }
2254 // hdd will read regd for this country after complete
2255 }
2256 complete(&pHddCtx->driver_crda_req);
2257
2258 /* Haven't seen any condition that will set by driver after init.
2259 If we do, then we should also call sme_ChangeCountryCode */
2260 }
2261return 0;
2262}
2263#endif