blob: 53a4a3f849c630edb5e1230be8484672656d651b [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 *
24 * Airgo Networks, Inc proprietary. All rights reserved.
25 * This file contains CFG functions for processing host messages.
26 *
27 * Author: Kevin Nguyen
28 * Date: 04/09/02
29 * History:-
30 * 04/09/02 Created.
31 * --------------------------------------------------------------------
32 */
33#include "palTypes.h"
34#include "aniGlobal.h"
35#include "cfgPriv.h"
36#include "cfgDebug.h"
37#include "wlan_qct_wda.h"
38
39
40/*--------------------------------------------------------------------*/
41/* Static function prototypes */
42/*--------------------------------------------------------------------*/
43static void ProcDnldRsp (tpAniSirGlobal, tANI_U16, tANI_U32*);
44static void ProcGetReq (tpAniSirGlobal, tANI_U16, tANI_U32*);
45static void ProcSetReq (tpAniSirGlobal, tANI_U16, tANI_U32*);
46static void ProcSetReqNoRsp (tpAniSirGlobal, tANI_U16, tANI_U32*);
47
48static tANI_U8 CheckParam(tpAniSirGlobal, tANI_U16, tANI_U32, tANI_U32, tANI_U32*);
49static void GetStrValue(tANI_U8*, tANI_U8*, tANI_U32);
50
51
52/*--------------------------------------------------------------------*/
53/* Module global variables */
54/*--------------------------------------------------------------------*/
55
56// CFG function table
57void (*gCfgFunc[])(tpAniSirGlobal, tANI_U16, tANI_U32*) =
58{ ProcDnldRsp,
59 ProcGetReq,
60 ProcSetReq,
61 ProcSetReqNoRsp
62};
63
64/**---------------------------------------------------------------------
65 * cfgProcessMbMsg()
66 *
67 *FUNCTION:
68 * CFG mailbox message processing function.
69 *
70 *LOGIC:
71 *
72 *ASSUMPTIONS:
73 * None.
74 *
75 *NOTE:
76 *
77 * @param pMsg Message pointer
78 *
79 * @return None.
80 *
81 */
82void
83cfgProcessMbMsg(tpAniSirGlobal pMac, tSirMbMsg *pMsg)
84{
85 tANI_U16 index;
86 tANI_U16 len;
87 tANI_U32 *pParam;
88
89 // Use type[7:0] as index to function table
90#if defined(ANI_OS_TYPE_LINUX)
91 index = CFG_GET_FUNC_INDX(sirReadU16N((tANI_U8*)pMsg));
92#else
93 index = CFG_GET_FUNC_INDX(pMsg->type);
94#endif
95
96 if (index >= (sizeof(gCfgFunc) / sizeof(gCfgFunc[0])))
97 return;
98#if defined(ANI_OS_TYPE_LINUX)
99 len = sirReadU16N((tANI_U8*)pMsg+2) - WNI_CFG_MB_HDR_LEN;
100#else
101 len = pMsg->msgLen - WNI_CFG_MB_HDR_LEN;
102#endif
103 pParam = ((tANI_U32*)pMsg) + 1;
104
105 // Call processing function
106 gCfgFunc[index](pMac, len, pParam);
107
108 // Free up buffer
109 palFreeMemory( pMac->hHdd, (void*)pMsg);
110
111} /*** end cfgProcessMbMsg() ***/
112
113/**---------------------------------------------------------------------
114 * ProcDnldRsp()
115 *
116 * FUNCTION:
117 * This function processes CFG_DNLD_RSP message from host.
118 *
119 * LOGIC:
120 *
121 * ASSUMPTIONS:
122 *
123 * NOTE:
124 *
125 * @param length: message length
126 * @param pParam: parameter list pointer
127 *
128 * @return None
129 *
130 */
131static void
132ProcDnldRsp(tpAniSirGlobal pMac, tANI_U16 length, tANI_U32 *pParam)
133{
134 tANI_S32 i;
135 #if defined(ANI_PRODUCT_TYPE_AP)
136 tANI_U32 ap;
137 #endif
138
139 tANI_U32 expLen, retVal, bufStart, bufEnd;
140 tANI_U32 *pSrc, *pDst, *pDstEnd;
141 tANI_U32 strSize, j;
142 tANI_U8 pStr[CFG_MAX_STR_LEN];
143 tpCfgBinHdr pHdr;
144 tANI_U32 logLevel;
145 tSirMsgQ mmhMsg;
146
147 // First Dword must contain the AP or STA magic dword
148 PELOGW(cfgLog(pMac, LOGW, FL("CFG size %d bytes MAGIC dword is 0x%x\n"),
149 length, sirReadU32N((tANI_U8*)pParam) );)
150
151 // if the string is not correct, return failure
152#if defined(ANI_PRODUCT_TYPE_AP)
153#if defined(ANI_OS_TYPE_LINUX) || defined(ANI_OS_TYPE_OSX)
154 if (sirReadU32N((tANI_U8*)pParam) == CFG_AP_MAGIC_DWORD)
155#else
156 if (*pParam == CFG_AP_MAGIC_DWORD)
157#endif
158 ap = 1;
159 else
160
161
162#if defined(ANI_OS_TYPE_LINUX) || defined(ANI_OS_TYPE_OSX)
163 if (sirReadU32N((tANI_U8*)pParam) == CFG_STA_MAGIC_DWORD)
164#else
165 if (*pParam == CFG_STA_MAGIC_DWORD)
166#endif
167
168 ap = 0;
169#else /* ANI_PRODUCT_TYPE_AP*/
170 if (*pParam == CFG_STA_MAGIC_DWORD) {}
171
172#endif/* ANI_PRODUCT_TYPE_AP*/
173
174
175
176 else
177 {
178 PELOGE(cfgLog(pMac, LOGE, FL("Invalid magic dword 0x%x\n"),sirReadU32N((tANI_U8*)pParam) );)
179 retVal = WNI_CFG_INVALID_LEN;
180 goto end;
181 }
182
183 pParam++;
184 length -= 4;
185
186 // Verify message length
187#ifdef ANI_PRODUCT_TYPE_AP
188 if (ap)
189 {
190 pMac->cfg.gCfgMaxIBufSize = CFG_AP_IBUF_MAX_SIZE;
191 pMac->cfg.gCfgMaxSBufSize = CFG_AP_SBUF_MAX_SIZE;
192 }
193 else
194#endif /* (WNI_POLARIS_FW_PRODUCT == AP) */
195 {
196 pMac->cfg.gCfgMaxIBufSize = CFG_STA_IBUF_MAX_SIZE;
197 pMac->cfg.gCfgMaxSBufSize = CFG_STA_SBUF_MAX_SIZE;
198 }
199
200 // Parse the Cfg header
201#if defined(ANI_OS_TYPE_LINUX) || defined(ANI_OS_TYPE_OSX)
202 tCfgBinHdr hdr;
203
204 hdr.hdrInfo = sirReadU32N((tANI_U8*)pParam); pParam++;
205 hdr.controlSize = sirReadU32N((tANI_U8*)pParam); pParam++;
206 hdr.iBufSize = sirReadU32N((tANI_U8*)pParam); pParam++;
207 hdr.sBufSize = sirReadU32N((tANI_U8*)pParam); pParam++;
208 pHdr=&hdr;
209#else
210 pHdr = (tpCfgBinHdr) pParam;
211 pParam += (sizeof(tCfgBinHdr) >> 2);
212#endif
213 PELOGW(cfgLog(pMac, LOGW, FL("CFG hdr totParams %d intParams %d strBufSize %d/%d\n"),
214 pHdr->controlSize, pHdr->iBufSize, pHdr->sBufSize, pMac->cfg.gCfgMaxSBufSize);)
215
216 expLen = ((CFG_PARAM_MAX_NUM + 3 * pMac->cfg.gCfgMaxIBufSize) << 2) +
217 pHdr->sBufSize + sizeof(tCfgBinHdr);
218
219 if (length != expLen)
220 {
221 PELOGE(cfgLog(pMac, LOGE, FL("<CFG> DNLD_RSP invalid length %d (exp %d)\n"),
222 length, expLen);)
223 retVal = WNI_CFG_INVALID_LEN;
224 goto end;
225 }
226
227
228 if (pHdr->controlSize != CFG_PARAM_MAX_NUM)
229 {
230 PELOGE(cfgLog(pMac, LOGE, FL("<CFG> Total parameter count mismatch\n"));)
231 retVal = WNI_CFG_INVALID_LEN;
232 goto end;
233 }
234
235 if (pHdr->iBufSize != pMac->cfg.gCfgMaxIBufSize)
236 {
237 PELOGE(cfgLog(pMac, LOGE, FL("<CFG> Integer parameter count mismatch\n"));)
238 retVal = WNI_CFG_INVALID_LEN;
239 goto end;
240 }
241
242 // Copy control array
243 pDst = (tANI_U32*)pMac->cfg.gCfgEntry;
244 pDstEnd = pDst + CFG_PARAM_MAX_NUM;
245 pSrc = pParam;
246 while (pDst < pDstEnd)
247 {
248#if defined(ANI_OS_TYPE_LINUX) || defined(ANI_OS_TYPE_OSX)
249 *pDst++ = sirReadU32N((tANI_U8*)pSrc);
250 pSrc++;
251#else
252 *pDst++ = *pSrc++;
253#endif
254 }
255 // Copy default values
256 pDst = pMac->cfg.gCfgIBuf;
257 pDstEnd = pDst + pMac->cfg.gCfgMaxIBufSize;
258 while (pDst < pDstEnd)
259 {
260#if defined(ANI_OS_TYPE_LINUX) || defined(ANI_OS_TYPE_OSX)
261 *pDst++ = sirReadU32N((tANI_U8*)pSrc);
262 pSrc++;
263#else
264 *pDst++ = *pSrc++;
265#endif
266 }
267
268 // Copy min values
269 pDst = pMac->cfg.gCfgIBufMin;
270 pDstEnd = pDst + pMac->cfg.gCfgMaxIBufSize;
271 while (pDst < pDstEnd)
272 {
273#if defined(ANI_OS_TYPE_LINUX) || defined(ANI_OS_TYPE_OSX)
274 *pDst++ = sirReadU32N((tANI_U8*)pSrc);
275 pSrc++;
276#else
277 *pDst++ = *pSrc++;
278#endif
279 }
280
281 // Copy max values
282 pDst = pMac->cfg.gCfgIBufMax;
283 pDstEnd = pDst + pMac->cfg.gCfgMaxIBufSize;
284 while (pDst < pDstEnd)
285 {
286#if defined(ANI_OS_TYPE_LINUX) || defined(ANI_OS_TYPE_OSX)
287 *pDst++ = sirReadU32N((tANI_U8*)pSrc);
288 pSrc++;
289#else
290 *pDst++ = *pSrc++;
291#endif
292 }
293
294 for (i=0; i<pMac->cfg.gCfgMaxIBufSize; i++)
295 if (pMac->cfg.gCfgIBuf[i] < pMac->cfg.gCfgIBufMin[i] ||
296 pMac->cfg.gCfgIBuf[i] > pMac->cfg.gCfgIBufMax[i])
297 {
298 PELOGE(cfgLog(pMac, LOGE, FL("cfg id %d Invalid def value %d "
299 "min %d max %d\n"),
300 i, pMac->cfg.gCfgIBuf[i], pMac->cfg.gCfgIBufMin[i],
301 pMac->cfg.gCfgIBufMax[i]);)
302 }
303
304 // Calculate max string buffer lengths for all string parameters
305 bufEnd = pMac->cfg.gCfgMaxSBufSize;
306 for (i = CFG_PARAM_MAX_NUM - 1; i >= 0; i--)
307 {
308 if ((pMac->cfg.gCfgEntry[i].control & CFG_CTL_INT) != 0)
309 continue;
310
311 if ((pMac->cfg.gCfgEntry[i].control & CFG_CTL_VALID) == 0)
312 continue;
313
314 bufStart = pMac->cfg.gCfgEntry[i].control & CFG_BUF_INDX_MASK;
315 pMac->cfg.gCfgSBuf[bufStart] = (tANI_U8)(bufEnd - bufStart - 2);
316
317 PELOG1(cfgLog(pMac, LOG1, FL("id %d max %d bufStart %d bufEnd %d\n"),
318 i, pMac->cfg.gCfgSBuf[bufStart], bufStart, bufEnd);)
319
320 bufEnd = bufStart;
321 }
322
323 // Initialize string defaults
324 strSize = pHdr->sBufSize;
325 while (strSize)
326 {
327 tANI_U32 paramId, paramLen, paramLenCeil4;
328
329 if (strSize < 4)
330 {
331 PELOGE(cfgLog(pMac, LOGE, FL("Error parsing str defaults, rem %d bytes\n"), strSize);)
332 retVal = WNI_CFG_INVALID_LEN;
333 goto end;
334 }
335#if defined(ANI_OS_TYPE_LINUX) || defined(ANI_OS_TYPE_OSX)
336 paramId = sirReadU32N((tANI_U8*)pSrc) >> 16;
337 paramLen = sirReadU32N((tANI_U8*)pSrc) & 0xff;
338#else
339 paramId = *pSrc >> 16;
340 paramLen = *pSrc & 0xff;
341#endif
342 pSrc++;
343 strSize -= 4;
344
345 paramLenCeil4 = ((paramLen + 3) >> 2);
346 if (strSize < paramLenCeil4 << 2)
347 {
348 PELOGE(cfgLog(pMac, LOGE, FL("Error parsing str defaults, rem %d bytes\n"), strSize);)
349 PELOGE(cfgLog(pMac, LOGE, FL("param id %d len %d bytes\n"), paramId, paramLen);)
350 retVal = WNI_CFG_INVALID_LEN;
351 goto end;
352 }
353 for (j=0; j < paramLenCeil4; j++)
354 {
355#if defined(ANI_OS_TYPE_LINUX) || defined(ANI_OS_TYPE_OSX)
356 pStr[4*j] = (tANI_U8) ((sirReadU32N((tANI_U8*)pSrc) >> 24) & 0xff);
357 pStr[4*j+1] = (tANI_U8) ((sirReadU32N((tANI_U8*)pSrc) >> 16) & 0xff);
358 pStr[4*j+2] = (tANI_U8) ((sirReadU32N((tANI_U8*)pSrc) >> 8) & 0xff);
359 pStr[4*j+3] = (tANI_U8) (sirReadU32N((tANI_U8*)pSrc) & 0xff);
360#else
361 pStr[4*j] = (tANI_U8) (*pSrc >> 24) & 0xff;
362 pStr[4*j+1] = (tANI_U8) (*pSrc >> 16) & 0xff;
363 pStr[4*j+2] = (tANI_U8) (*pSrc >> 8) & 0xff;
364 pStr[4*j+3] = (tANI_U8) (*pSrc) & 0xff;
365#endif
366
367 pSrc++;
368 strSize -= 4;
369 }
370
371 PELOG1(cfgLog(pMac, LOG1, FL("set str id %d len %d\n"), paramId, paramLen);)
372
373 if (cfgSetStr(pMac, (tANI_U16) paramId, pStr, paramLen) != eSIR_SUCCESS)
374 {
375 PELOGE(cfgLog(pMac, LOGE, FL("Error setting str default param %d len %d\n"), paramId, paramLen);)
376 retVal = WNI_CFG_INVALID_LEN;
377 goto end;
378 }
379 }
380
381 // Set the default log level based on config
382 wlan_cfgGetInt(pMac, WNI_CFG_LOG_LEVEL, &logLevel);
383 for (i = 0; i < LOG_ENTRY_NUM; i++)
384#ifdef LX5280
385 pMac->utils.gLogEvtLevel[i] = pMac->utils.gLogDbgLevel[i] = LOGE;
386#else
387#if defined(ANI_OS_TYPE_WINCE)
388 pMac->utils.gLogEvtLevel[i] = pMac->utils.gLogDbgLevel[i] = LOGE;
389#else //#if defined(ANI_OS_TYPE_WINCE)
390 pMac->utils.gLogEvtLevel[i] = pMac->utils.gLogDbgLevel[i] = logLevel;
391#endif //#if defined(ANI_OS_TYPE_WINCE)
392#endif
393
394 // Set status to READY
395 pMac->cfg.gCfgStatus = CFG_SUCCESS;
396 retVal = WNI_CFG_SUCCESS;
397 PELOG1(cfgLog(pMac, LOG1, "<CFG> Completed successfully\n");)
398
399 end:
400
401 if ( retVal != WNI_CFG_SUCCESS )
402 pMac->cfg.gCfgStatus = CFG_FAILURE;
403
404 // Send response message to host
405#if defined(ANI_OS_TYPE_LINUX)
406 sirStoreU32N((tANI_U8 *) &(pMac->cfg.gParamList[WNI_CFG_DNLD_CNF_RES]), retVal);
407#else
408 pMac->cfg.gParamList[WNI_CFG_DNLD_CNF_RES] = retVal;
409#endif
410 cfgSendHostMsg(pMac, WNI_CFG_DNLD_CNF, WNI_CFG_DNLD_CNF_LEN,
411 WNI_CFG_DNLD_CNF_NUM, pMac->cfg.gParamList, 0, 0);
412
413 // Notify WDA that the config has downloaded
414 mmhMsg.type = SIR_CFG_DOWNLOAD_COMPLETE_IND;
415 mmhMsg.bodyptr = NULL;
416 mmhMsg.bodyval = 0;
417
Jeff Johnsone7245742012-09-05 17:12:55 -0700418 MTRACE(macTraceMsgTx(pMac, NO_SESSION, mmhMsg.type));
Jeff Johnson295189b2012-06-20 16:38:30 -0700419 if (wdaPostCtrlMsg(pMac, &mmhMsg) != eSIR_SUCCESS)
420 {
421 PELOGE(cfgLog(pMac, LOGE, FL("WDAPostMsgApi failed!\n"));)
422 }
423
424} /*** end procDnldRsp() ***/
425
426
427/**---------------------------------------------------------------------
428 * ProcGetReq()
429 *
430 * FUNCTION:
431 * This function processes CFG_GET_REQ message from host.
432 *
433 * LOGIC:
434 *
435 * ASSUMPTIONS:
436 *
437 * NOTE:
438 * For every parameter ID specified on the list, CFG will send a separate
439 * CFG_GET_RSP back to host.
440 *
441 * @param length: message length
442 * @param pParam: parameter list pointer
443 *
444 * @return None
445 *
446 */
447static void
448ProcGetReq(tpAniSirGlobal pMac, tANI_U16 length, tANI_U32 *pParam)
449{
450 tANI_U16 cfgId, i;
451 tANI_U32 value, valueLen, result;
452 tANI_U32 *pValue;
453
454 PELOG1(cfgLog(pMac, LOG1, FL("Rcvd cfg get request %d bytes\n"), length);)
455 for (i=0; i<length/4; i++)
456 PELOG2(cfgLog(pMac, LOG2, FL("[%2d] 0x%08x\n"), i, pParam[i]);)
457
458 if (!pMac->cfg.gCfgStatus)
459 {
460 cfgId = (tANI_U16)sirReadU32N((tANI_U8*)pParam);
461 PELOGE(cfgLog(pMac, LOGE, FL("CFG not ready, param %d\n"), cfgId);)
462#if defined(ANI_OS_TYPE_LINUX) || defined(ANI_OS_TYPE_OSX)
463 sirStoreU32N((tANI_U8 *) &(pMac->cfg.gParamList[WNI_CFG_GET_RSP_RES]),
464 WNI_CFG_NOT_READY);
465 sirStoreU32N((tANI_U8 *) &(pMac->cfg.gParamList[WNI_CFG_GET_RSP_PID]),
466 cfgId);
467 sirStoreU32N((tANI_U8 *) &(pMac->cfg.gParamList[WNI_CFG_GET_RSP_PLEN]),
468 0);
469#else
470 pMac->cfg.gParamList[WNI_CFG_GET_RSP_RES] = WNI_CFG_NOT_READY;
471 pMac->cfg.gParamList[WNI_CFG_GET_RSP_PID] = cfgId;
472 pMac->cfg.gParamList[WNI_CFG_GET_RSP_PLEN] = 0;
473#endif
474 cfgSendHostMsg(pMac, WNI_CFG_GET_RSP, WNI_CFG_GET_RSP_PARTIAL_LEN,
475 WNI_CFG_GET_RSP_NUM, pMac->cfg.gParamList, 0, 0);
476 }
477 else
478 {
479 // Process all parameter ID's on the list
480 while (length >= sizeof(tANI_U32))
481 {
482#if defined(ANI_OS_TYPE_LINUX)
483 cfgId = (tANI_U16)sirReadU32N((tANI_U8*) pParam); pParam++;
484#else
485 cfgId = (tANI_U16)*pParam++;
486#endif
487 pValue = 0;
488 valueLen = 0;
489
490 PELOG1(cfgLog(pMac, LOG1, FL("Cfg get param %d\n"), cfgId);)
491
492 // Check for valid parameter ID, etc...
493 if (CheckParam(pMac, cfgId, CFG_CTL_RE, WNI_CFG_WO_PARAM, &result))
494 {
495 if ((pMac->cfg.gCfgEntry[cfgId].control & CFG_CTL_INT) != 0)
496 {
497 // Get integer parameter
498 result = (wlan_cfgGetInt(pMac, cfgId, &value) == eSIR_SUCCESS ?
499 WNI_CFG_SUCCESS : WNI_CFG_OTHER_ERROR);
500 pValue = &value;
501 valueLen = sizeof(tANI_U32);
502 }
503 else
504 {
505 // Get string parameter
506 valueLen = sizeof(pMac->cfg.gSBuffer);
507 result = (wlan_cfgGetStr(pMac, cfgId, pMac->cfg.gSBuffer, &valueLen)
508 == eSIR_SUCCESS ?
509 WNI_CFG_SUCCESS : WNI_CFG_OTHER_ERROR);
510 pValue = (tANI_U32*)pMac->cfg.gSBuffer;
511 }
512 }
513 else
514 {
515 PELOGE(cfgLog(pMac, LOGE, FL("Check param failed, param %d\n"), cfgId);)
516 result = WNI_CFG_INVALID_LEN;
517 }
518
519 // Send response message to host
520#if defined(ANI_OS_TYPE_LINUX)
521 sirStoreU32N((tANI_U8 *) &(pMac->cfg.gParamList[WNI_CFG_GET_RSP_RES]),
522 result);
523 sirStoreU32N((tANI_U8 *) &(pMac->cfg.gParamList[WNI_CFG_GET_RSP_PID]),
524 cfgId);
525 sirStoreU32N((tANI_U8 *) &(pMac->cfg.gParamList[WNI_CFG_GET_RSP_PLEN]),
526 valueLen);
527#else
528 pMac->cfg.gParamList[WNI_CFG_GET_RSP_RES] = result;
529 pMac->cfg.gParamList[WNI_CFG_GET_RSP_PID] = cfgId;
530 pMac->cfg.gParamList[WNI_CFG_GET_RSP_PLEN] = valueLen;
531#endif
532
533 // We need to round up buffer length to word-increment
534 valueLen = (((valueLen + 3) >> 2) << 2);
535 cfgSendHostMsg(pMac, WNI_CFG_GET_RSP,
536 WNI_CFG_GET_RSP_PARTIAL_LEN + valueLen,
537 WNI_CFG_GET_RSP_NUM, pMac->cfg.gParamList, valueLen, pValue);
538
539 // Decrement length
540 length -= sizeof(tANI_U32);
541 }
542 }
543
544} /*** end procGetReq() ***/
545
546
547
548/**---------------------------------------------------------------------
549 * ProcSetReqInternal()
550 *
551 * FUNCTION:
552 * This function processes CFG_SET_REQ message from host.
553 *
554 * LOGIC:
555 *
556 * ASSUMPTIONS:
557 * - The message content is coded in TLV format.
558 * - For string parameter, the length field is byte accurate. However,
559 * the next TLV set will begin on the next word boundary.
560 *
561 * NOTE:
562 * - For every parameter ID specified on the list, CFG will send a separate
563 * CFG_SET_RSP back to host.
564 *
565 * @param length: message length
566 * @param pParam: parameter list pointer
567 * @param fRsp: whether to send response to host. TRUE means sending.
568 * @return None
569 *
570 */
571static void
572ProcSetReqInternal(tpAniSirGlobal pMac, tANI_U16 length, tANI_U32 *pParam, tANI_BOOLEAN fRsp)
573{
574 tANI_U16 cfgId, valueLen, valueLenRoundedUp4;
575 tANI_U32 value, result;
576
577 PELOG1(cfgLog(pMac, LOGW, FL("Rcvd cfg set request %d bytes\n"), length);)
578 //for (i=0; i<length/4; i++)
579 // PELOG2(cfgLog(pMac, LOG2, FL("[%2d] 0x%08x\n"), i, pParam[i]);)
580
581 if (!pMac->cfg.gCfgStatus)
582 {
583 cfgId = (tANI_U16)sirReadU32N((tANI_U8*)pParam);
584 PELOGE(cfgLog(pMac, LOGE, FL("CFG not ready, param %d\n"), cfgId);)
585#if defined(ANI_OS_TYPE_LINUX) || defined(ANI_OS_TYPE_OSX)
586 sirStoreU32N((tANI_U8 *) &(pMac->cfg.gParamList[WNI_CFG_SET_CNF_RES]),
587 WNI_CFG_NOT_READY);
588 sirStoreU32N((tANI_U8 *) &(pMac->cfg.gParamList[WNI_CFG_SET_CNF_PID]),
589 cfgId);
590#else
591 pMac->cfg.gParamList[WNI_CFG_SET_CNF_RES] = WNI_CFG_NOT_READY;
592 pMac->cfg.gParamList[WNI_CFG_SET_CNF_PID] = cfgId;
593#endif
594 if( fRsp )
595 {
596 cfgSendHostMsg(pMac, WNI_CFG_SET_CNF, WNI_CFG_SET_CNF_LEN,
597 WNI_CFG_SET_CNF_NUM, pMac->cfg.gParamList, 0, 0);
598 }
599 }
600 else
601 {
602 // Process all TLVs in buffer
603 while (length >= (sizeof(tANI_U32) * 2))
604 {
605#if defined(ANI_OS_TYPE_LINUX)
606 // Get TYPE (cfgID) and LENGTH (length)
607 cfgId = (tANI_U16)sirReadU32N((tANI_U8*)pParam);pParam++;
608 valueLen = (tANI_U16)sirReadU32N((tANI_U8*)pParam);pParam++;
609#else
610 cfgId = (tANI_U16) *pParam++;
611 valueLen = (tANI_U16) *pParam++;
612#endif
613 length -= (sizeof(tANI_U32) * 2);
614 // value length rounded up to a 4 byte multiple
615 valueLenRoundedUp4 = (((valueLen + 3) >> 2) << 2);
616
617 // Check for valid request before proceeding
618 if (CheckParam(pMac, cfgId, CFG_CTL_WE, WNI_CFG_RO_PARAM, &result))
619 {
620 PELOG1(cfgLog(pMac, LOGW, (char *) gCfgParamName[cfgId]);)
621 // Process integer parameter
622 if ((pMac->cfg.gCfgEntry[cfgId].control & CFG_CTL_INT) != 0)
623 {
624 // Set VALUE
625 if (valueLen != sizeof(tANI_U32))
626 {
627 PELOGE(cfgLog(pMac, LOGE, FL("Invalid value length %d in set param %d (tot %d)\n"),
628 valueLen, cfgId, length);)
629 result = WNI_CFG_INVALID_LEN;
630 }
631 else
632 {
633#if defined(ANI_OS_TYPE_LINUX)
634 value = sirReadU32N((tANI_U8*) pParam);
635#else
636 value = *pParam;
637#endif
638 PELOG1(cfgLog(pMac, LOGW, FL("Cfg set int %d len %d(%d) val %d\n"),
639 cfgId, valueLen, valueLenRoundedUp4, value);)
640 result = (cfgSetInt(pMac, cfgId, value) == eSIR_SUCCESS ?
641 WNI_CFG_SUCCESS : WNI_CFG_OTHER_ERROR);
642 if (result == WNI_CFG_SUCCESS)
643 {
644 if (cfgNeedRestart(pMac, cfgId))
645 {
646 result = WNI_CFG_NEED_RESTART ;
647 }
648 else
649 if (cfgNeedReload(pMac, cfgId))
650 {
651 result = WNI_CFG_NEED_RELOAD ;
652 }
653 }
654 }
655 }
656 // Process string parameter
657 else
658 {
659 if (valueLenRoundedUp4 > length)
660 {
661 PELOGE(cfgLog(pMac, LOGE, FL("Invalid string length %d in set param %d (tot %d)\n"),
662 valueLen, cfgId, length);)
663 result = WNI_CFG_INVALID_LEN;
664 }
665 else
666 {
667 GetStrValue((tANI_U8*)pParam, pMac->cfg.gSBuffer, valueLen);
668 PELOG1(cfgLog(pMac, LOGW, FL("Cfg set str %d len %d(%d) bytes\n"),
669 cfgId, valueLen, valueLenRoundedUp4);)
670 result = (cfgSetStr(pMac, cfgId, pMac->cfg.gSBuffer, valueLen) == eSIR_SUCCESS ?
671 WNI_CFG_SUCCESS : WNI_CFG_OTHER_ERROR);
672 if (result == WNI_CFG_SUCCESS)
673 {
674 if (cfgNeedRestart(pMac, cfgId))
675 {
676 result = WNI_CFG_NEED_RESTART ;
677 }
678 else
679 if (cfgNeedReload(pMac, cfgId))
680 {
681 result = WNI_CFG_NEED_RELOAD ;
682 }
683 }
684 }
685 }
686 }
687 else
688 {
689 PELOGE(cfgLog(pMac, LOGE, FL("Check param failed, param %d\n"), cfgId);)
690 result = WNI_CFG_INVALID_LEN;
691 }
692
693 // Send confirm message to host
694#if defined(ANI_OS_TYPE_LINUX)
695 sirStoreU32N((tANI_U8 *) &(pMac->cfg.gParamList[WNI_CFG_SET_CNF_RES]),
696 result);
697 sirStoreU32N((tANI_U8 *) &(pMac->cfg.gParamList[WNI_CFG_SET_CNF_PID]),
698 cfgId);
699#else
700 pMac->cfg.gParamList[WNI_CFG_SET_CNF_RES] = result;
701 pMac->cfg.gParamList[WNI_CFG_SET_CNF_PID] = cfgId;
702#endif
703 if( fRsp )
704 {
705 cfgSendHostMsg(pMac, WNI_CFG_SET_CNF, WNI_CFG_SET_CNF_LEN,
706 WNI_CFG_SET_CNF_NUM, pMac->cfg.gParamList, 0, 0);
707 }
708 else
709 {
Mohit Khanna23863762012-09-11 17:40:09 -0700710 PELOGW(cfgLog( pMac, LOG2, " CFGID %d no rsp\n", cfgId);)
Jeff Johnson295189b2012-06-20 16:38:30 -0700711 }
712
713 if (valueLenRoundedUp4 > length)
714 length = 0;
715 else
716 {
717 length -= valueLenRoundedUp4;
718 pParam += (valueLenRoundedUp4 >> 2);
719 }
720 }
721 }
722}
723
724
725
726static void
727ProcSetReq(tpAniSirGlobal pMac, tANI_U16 length, tANI_U32 *pParam)
728{
729 ProcSetReqInternal( pMac, length, pParam, eANI_BOOLEAN_TRUE );
730}
731
732static void
733ProcSetReqNoRsp(tpAniSirGlobal pMac, tANI_U16 length, tANI_U32 *pParam)
734{
735 ProcSetReqInternal( pMac, length, pParam, eANI_BOOLEAN_FALSE );
736}
737
738
739
740/**---------------------------------------------------------------------
741 * CheckParam()
742 *
743 * FUNCTION:
744 * This function is called to perform various check on a parameter.
745 *
746 * LOGIC:
747 * - If cfgId is out of bound or parameter is not valid, result
748 * WNI_CFG_INVALID_PID is returned at address specified in pResult.
749 *
750 * - If specified 'flag' is not set in the parameter control entry,
751 * 'failedResult' is returned at address specified in pResult.
752 *
753 * ASSUMPTIONS:
754 * Since this function is used internally, 'pResult' is always valid.
755 *
756 * NOTE:
757 *
758 * @param None
759 *
760 * @return true: Parameter is valid and matches checked condition \n
761 * @return false: Parameter either is not valid or does not match
762 * checked condition.
763 *
764 */
765static tANI_U8
766CheckParam(tpAniSirGlobal pMac, tANI_U16 cfgId, tANI_U32 flag, tANI_U32 failedResult, tANI_U32 *pResult)
767{
768 // Check if parameter ID is out of bound
769 if (cfgId >= CFG_PARAM_MAX_NUM)
770 {
771 PELOGE(cfgLog(pMac, LOGE, FL("Invalid param id %d\n"), cfgId);)
772 *pResult = WNI_CFG_INVALID_PID;
773 }
774 else
775 {
776 // Check if parameter is valid
777 if ((pMac->cfg.gCfgEntry[cfgId].control & CFG_CTL_VALID) == 0)
778 {
779 PELOGE(cfgLog(pMac, LOGE, FL("Param id %d not valid\n"), cfgId);)
780 *pResult = WNI_CFG_INVALID_PID;
781 }
782 else
783 {
784 // Check control field against flag
785 if ((pMac->cfg.gCfgEntry[cfgId].control & flag) == 0)
786 {
787 PELOGE(cfgLog(pMac, LOGE, FL("Param id %d wrong permissions %x\n"),
788 cfgId, pMac->cfg.gCfgEntry[cfgId].control);)
789 *pResult = failedResult;
790 }
791 else
792 return(true);
793 }
794 }
795 return(false);
796
797} /*** cfgParamCheck() ***/
798
799
800/**---------------------------------------------------------------------
801 * GetStrValue()
802 *
803 * FUNCTION:
804 * This function copies a string value from the specified buffer.
805 *
806 * LOGIC:
807 *
808 * ASSUMPTIONS:
809 *
810 * NOTE:
811 *
812 * @param pBuf: input data buffer
813 * @param pValue: address where data is returned
814 * @param length: number of bytes to copy
815 *
816 * @return None
817 *
818 */
819static void
820GetStrValue(tANI_U8 *pBuf, tANI_U8 *pValue, tANI_U32 length)
821{
822 tANI_U8 *pEnd;
823
824 pEnd = pValue + length;
825 while (pValue < pEnd)
826 *pValue++ = *pBuf++;
827} /*** end GetStrValue() ***/
828
829
830/**---------------------------------------------------------------------
831 * processCfgDownloadReq()
832 *
833 * FUNCTION: This function does the Cfg Download and is invoked
834 * only in the case of Prima or the Integrated SOC
835 * solutions. Not applicable to Volans or Libra
836 *
837 * LOGIC:
838 *
839 * ASSUMPTIONS:
840 *
841 * NOTE:
842 *
843 * @param length: message length
844 * @param pConfig: parameter list pointer
845 *
846 * @return None
847 *
848 */
849
850void
851processCfgDownloadReq(tpAniSirGlobal pMac, tANI_U16 length,
852 tANI_U32 *pConfig)
853{
854 tANI_S32 i;
855
856 tANI_U32 expLen, retVal, bufStart, bufEnd;
857 tANI_U32 *pSrc, *pDst, *pDstEnd;
858 tANI_U32 strSize, j;
859 tANI_U8 pStr[CFG_MAX_STR_LEN];
860 tpCfgBinHdr pHdr;
861 tANI_U32 logLevel;
862
863 // First Dword must contain the AP or STA magic dword
864 PELOGW(cfgLog(pMac, LOGW, FL("CFG size %d bytes MAGIC dword is 0x%x\n"),
865 length, sirReadU32N((tANI_U8*)pConfig) );)
866
867 // if the string is not correct, return failure
868 if (CFG_STA_MAGIC_DWORD != *pConfig)
869 {
870 PELOGE(cfgLog(pMac, LOGE, FL("Invalid magic dword 0x%x\n"),
871 sirReadU32N((tANI_U8*)pConfig) );)
872 retVal = WNI_CFG_INVALID_LEN;
873 goto end;
874 }
875
876 pConfig++;
877 length -= 4;
878
879 // Verify message length
880 pMac->cfg.gCfgMaxIBufSize = CFG_STA_IBUF_MAX_SIZE;
881 pMac->cfg.gCfgMaxSBufSize = CFG_STA_SBUF_MAX_SIZE;
882
883 // Parse the Cfg header
884 pHdr = (tpCfgBinHdr) pConfig;
885 pConfig += (sizeof(tCfgBinHdr) >> 2);
886
887 PELOGW(cfgLog(pMac, LOGW, FL("CFG hdr totParams %d intParams %d strBufSize %d/%d\n"),
888 pHdr->controlSize,pHdr->iBufSize,
889 pHdr->sBufSize, pMac->cfg.gCfgMaxSBufSize);)
890
891 expLen = ((CFG_PARAM_MAX_NUM + 3 * pMac->cfg.gCfgMaxIBufSize) << 2) +
892 pHdr->sBufSize + sizeof(tCfgBinHdr);
893
894 if (length != expLen)
895 {
896 PELOGE(cfgLog(pMac, LOGE, FL("<CFG> DNLD_RSP invalid length %d (exp %d)\n"),
897 length, expLen);)
898 retVal = WNI_CFG_INVALID_LEN;
899 goto end;
900 }
901
902
903 if (CFG_PARAM_MAX_NUM != pHdr->controlSize )
904 {
905 PELOGE(cfgLog(pMac, LOGE, FL("<CFG> Total parameter count mismatch\n"));)
906 retVal = WNI_CFG_INVALID_LEN;
907 goto end;
908 }
909
910 if (pHdr->iBufSize != pMac->cfg.gCfgMaxIBufSize)
911 {
912 PELOGE(cfgLog(pMac, LOGE, FL("<CFG> Integer parameter count mismatch\n"));)
913 retVal = WNI_CFG_INVALID_LEN;
914 goto end;
915 }
916
917 // Copy control array
918 pDst = (tANI_U32*)pMac->cfg.gCfgEntry;
919 pDstEnd = pDst + CFG_PARAM_MAX_NUM;
920 pSrc = pConfig;
921 while (pDst < pDstEnd)
922 {
923 *pDst++ = *pSrc++;
924 }
925
926 // Copy default values
927 pDst = pMac->cfg.gCfgIBuf;
928 pDstEnd = pDst + pMac->cfg.gCfgMaxIBufSize;
929 while (pDst < pDstEnd)
930 {
931 *pDst++ = *pSrc++;
932 }
933
934 // Copy min values
935 pDst = pMac->cfg.gCfgIBufMin;
936 pDstEnd = pDst + pMac->cfg.gCfgMaxIBufSize;
937 while (pDst < pDstEnd)
938 {
939 *pDst++ = *pSrc++;
940 }
941
942 // Copy max values
943 pDst = pMac->cfg.gCfgIBufMax;
944 pDstEnd = pDst + pMac->cfg.gCfgMaxIBufSize;
945 while (pDst < pDstEnd)
946 {
947 *pDst++ = *pSrc++;
948 }
949
950 for (i=0; i<pMac->cfg.gCfgMaxIBufSize; i++)
951 {
952 if (pMac->cfg.gCfgIBuf[i] < pMac->cfg.gCfgIBufMin[i] ||
953 pMac->cfg.gCfgIBuf[i] > pMac->cfg.gCfgIBufMax[i])
954 {
955 PELOGE(cfgLog(pMac, LOGE, FL("cfg id %d Invalid def value %d "
956 "min %d max %d\n"),
957 i, pMac->cfg.gCfgIBuf[i], pMac->cfg.gCfgIBufMin[i],
958 pMac->cfg.gCfgIBufMax[i]);)
959 }
960 }
961
962 // Calculate max string buffer lengths for all string parameters
963 bufEnd = pMac->cfg.gCfgMaxSBufSize;
964 for (i = CFG_PARAM_MAX_NUM - 1; i >= 0; i--)
965 {
966 if ((pMac->cfg.gCfgEntry[i].control & CFG_CTL_INT) != 0)
967 continue;
968
969 if ((pMac->cfg.gCfgEntry[i].control & CFG_CTL_VALID) == 0)
970 continue;
971
972 bufStart = pMac->cfg.gCfgEntry[i].control & CFG_BUF_INDX_MASK;
973 pMac->cfg.gCfgSBuf[bufStart] = (tANI_U8)(bufEnd - bufStart - 2);
974
975 PELOG1(cfgLog(pMac, LOG1, FL("id %d max %d bufStart %d bufEnd %d\n"),
976 i, pMac->cfg.gCfgSBuf[bufStart], bufStart, bufEnd);)
977
978 bufEnd = bufStart;
979 }
980
981 // Initialize string defaults
982 strSize = pHdr->sBufSize;
983 while (strSize)
984 {
985 tANI_U32 paramId, paramLen, paramLenCeil4;
986
987 if (strSize < 4)
988 {
989 PELOGE(cfgLog(pMac, LOGE, FL("Error parsing str defaults, rem %d bytes\n"),
990 strSize);)
991 retVal = WNI_CFG_INVALID_LEN;
992 goto end;
993 }
994 paramId = *pSrc >> 16;
995 paramLen = *pSrc & 0xff;
996
997 pSrc++;
998 strSize -= 4;
999
1000 paramLenCeil4 = ((paramLen + 3) >> 2);
1001 if (strSize < paramLenCeil4 << 2)
1002 {
1003 PELOGE(cfgLog(pMac, LOGE, FL("Error parsing str defaults, rem %d"
1004 "bytes\n"), strSize);)
1005 PELOGE(cfgLog(pMac, LOGE, FL("param id %d len %d bytes\n"),
1006 paramId, paramLen);)
1007 retVal = WNI_CFG_INVALID_LEN;
1008 goto end;
1009 }
1010
1011 for (j=0; j < paramLenCeil4; j++)
1012 {
1013 pStr[4*j] = (tANI_U8) (*pSrc >> 24) & 0xff;
1014 pStr[4*j+1] = (tANI_U8) (*pSrc >> 16) & 0xff;
1015 pStr[4*j+2] = (tANI_U8) (*pSrc >> 8) & 0xff;
1016 pStr[4*j+3] = (tANI_U8) (*pSrc) & 0xff;
1017
1018 pSrc++;
1019 strSize -= 4;
1020 }
1021
1022 PELOG1(cfgLog(pMac, LOG1, FL("set str id %d len %d\n"), paramId, paramLen);)
1023
1024 if (cfgSetStrNotify(pMac, (tANI_U16)paramId, pStr, paramLen, FALSE) != eSIR_SUCCESS)
1025 {
1026 PELOGE(cfgLog(pMac, LOGE, FL("Error setting str default param %d "
1027 "len %d\n"), paramId, paramLen);)
1028 retVal = WNI_CFG_INVALID_LEN;
1029 goto end;
1030 }
1031 }
1032
1033 // Set the default log level based on config
1034 wlan_cfgGetInt(pMac, WNI_CFG_LOG_LEVEL, &logLevel);
1035 for (i = 0; i < LOG_ENTRY_NUM; i++)
1036 pMac->utils.gLogEvtLevel[i] = pMac->utils.gLogDbgLevel[i] = logLevel;
1037
1038 // Set status to READY
1039 pMac->cfg.gCfgStatus = CFG_SUCCESS;
1040 retVal = WNI_CFG_SUCCESS;
1041 PELOG1(cfgLog(pMac, LOG1, "<CFG> Completed successfully\n");)
1042
1043end:
1044
1045 if ( WNI_CFG_SUCCESS != retVal )
1046 pMac->cfg.gCfgStatus = CFG_FAILURE;
1047
1048 pMac->cfg.gParamList[WNI_CFG_DNLD_CNF_RES] = retVal;
1049
1050} /*** end ProcessDownloadReq() ***/
1051
1052
1053
1054