| /* |
| * Copyright (c) 2011-2017 The Linux Foundation. All rights reserved. |
| * |
| * Previously licensed under the ISC license by Qualcomm Atheros, Inc. |
| * |
| * |
| * Permission to use, copy, modify, and/or distribute this software for |
| * any purpose with or without fee is hereby granted, provided that the |
| * above copyright notice and this permission notice appear in all |
| * copies. |
| * |
| * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL |
| * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED |
| * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE |
| * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL |
| * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR |
| * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER |
| * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR |
| * PERFORMANCE OF THIS SOFTWARE. |
| */ |
| |
| /* |
| * This file was originally distributed by Qualcomm Atheros, Inc. |
| * under proprietary terms before Copyright ownership was assigned |
| * to the Linux Foundation. |
| */ |
| |
| /* |
| * |
| * This file contains the source code for CFG API functions. |
| * |
| * Author: Kevin Nguyen |
| * Date: 04/09/02 |
| * History:- |
| * 04/09/02 Created. |
| * -------------------------------------------------------------------- |
| */ |
| |
| #include "palTypes.h" |
| #include "cfgPriv.h" |
| #include "cfgDebug.h" |
| #include "wlan_qct_wda.h" |
| |
| //--------------------------------------------------------------------- |
| // Static Variables |
| //---------------------------------------------------------------------- |
| static tCfgCtl __gCfgEntry[WNI_CFG_MAX] ; |
| static tANI_U32 __gCfgIBufMin[CFG_STA_IBUF_MAX_SIZE] ; |
| static tANI_U32 __gCfgIBufMax[CFG_STA_IBUF_MAX_SIZE] ; |
| static tANI_U32 __gCfgIBuf[CFG_STA_IBUF_MAX_SIZE] ; |
| static tANI_U8 __gCfgSBuf[CFG_STA_SBUF_MAX_SIZE] ; |
| static tANI_U8 __gSBuffer[CFG_MAX_STR_LEN] ; |
| |
| static void Notify(tpAniSirGlobal, tANI_U16, tANI_U32); |
| |
| |
| // --------------------------------------------------------------------- |
| tANI_U32 cfgNeedRestart(tpAniSirGlobal pMac, tANI_U16 cfgId) |
| { |
| if (!pMac->cfg.gCfgEntry) |
| { |
| PELOGE(cfgLog(pMac, LOGE, FL("gCfgEntry is NULL"));) |
| return 0; |
| } |
| return !!(pMac->cfg.gCfgEntry[cfgId].control & CFG_CTL_RESTART) ; |
| } |
| |
| // --------------------------------------------------------------------- |
| tANI_U32 cfgNeedReload(tpAniSirGlobal pMac, tANI_U16 cfgId) |
| { |
| if (!pMac->cfg.gCfgEntry) |
| { |
| PELOGE(cfgLog(pMac, LOGE, FL("gCfgEntry is NULL"));) |
| return 0; |
| } |
| return !!(pMac->cfg.gCfgEntry[cfgId].control & CFG_CTL_RELOAD) ; |
| } |
| |
| // --------------------------------------------------------------------- |
| /** |
| * wlan_cfgInit() |
| * |
| * FUNCTION: |
| * CFG initialization function. |
| * |
| * LOGIC: |
| * Please see Configuration & Statistic Collection Micro-Architecture |
| * specification for the pseudo code. |
| * |
| * ASSUMPTIONS: |
| * None. |
| * |
| * NOTE: |
| * This function must be called during system initialization. |
| * |
| * @param None |
| * @return None. |
| */ |
| |
| void |
| wlan_cfgInit(tpAniSirGlobal pMac) |
| { |
| // Set status to not-ready |
| pMac->cfg.gCfgStatus = CFG_INCOMPLETE; |
| |
| // Send CFG_DNLD_REQ to host |
| PELOGW(cfgLog(pMac, LOGW, FL("Sending CFG_DNLD_REQ"));) |
| cfgSendHostMsg(pMac, WNI_CFG_DNLD_REQ, WNI_CFG_DNLD_REQ_LEN, |
| WNI_CFG_DNLD_REQ_NUM, 0, 0, 0); |
| |
| } /*** end wlan_cfgInit() ***/ |
| |
| void cfg_get_str_index(tpAniSirGlobal mac_ctx, uint16_t cfg_id) |
| { |
| uint16_t i = 0; |
| |
| for (i = 0; i < CFG_MAX_STATIC_STRING; i++) { |
| if (cfg_id == cfg_static_string[i].cfg_id) |
| break; |
| } |
| |
| if (i == CFG_MAX_STATIC_STRING) { |
| PELOGE(cfgLog(mac_ctx, LOGE, |
| FL("Entry not found for cfg id :%d"), cfg_id);) |
| cfg_static[cfg_id].p_str_data = NULL; |
| return; |
| } |
| |
| cfg_static[cfg_id].p_str_data = &cfg_static_string[i]; |
| } |
| |
| |
| //--------------------------------------------------------------------- |
| tSirRetStatus cfgInit(tpAniSirGlobal pMac) |
| { |
| uint16_t i = 0; |
| pMac->cfg.gCfgIBufMin = __gCfgIBufMin; |
| pMac->cfg.gCfgIBufMax = __gCfgIBufMax; |
| pMac->cfg.gCfgIBuf = __gCfgIBuf; |
| pMac->cfg.gCfgSBuf = __gCfgSBuf; |
| pMac->cfg.gSBuffer = __gSBuffer; |
| pMac->cfg.gCfgEntry = __gCfgEntry; |
| |
| pMac->cfg.gCfgMaxIBufSize = CFG_STA_IBUF_MAX_SIZE; |
| pMac->cfg.gCfgMaxSBufSize = CFG_STA_SBUF_MAX_SIZE; |
| |
| for (i = 0; i < WNI_CFG_MAX; i++) { |
| if (!(cfg_static[i].control & CFG_CTL_INT)) |
| cfg_get_str_index(pMac, i); |
| else |
| cfg_static[i].p_str_data = NULL; |
| } |
| |
| return (eSIR_SUCCESS); |
| } |
| |
| //---------------------------------------------------------------------- |
| void cfgDeInit(tpAniSirGlobal pMac) |
| { |
| pMac->cfg.gCfgIBufMin = NULL; |
| pMac->cfg.gCfgIBufMax = NULL; |
| pMac->cfg.gCfgIBuf = NULL; |
| pMac->cfg.gCfgSBuf = NULL; |
| pMac->cfg.gSBuffer = NULL; |
| pMac->cfg.gCfgEntry = NULL; |
| } |
| |
| // --------------------------------------------------------------------- |
| /** |
| * cfgSetInt() |
| * |
| * FUNCTION: |
| * This function is called to update an integer parameter. |
| * |
| * LOGIC: |
| * |
| * ASSUMPTIONS: |
| * - Range checking is performed by the calling function. In case this |
| * function call is being triggered by a request from host, then host |
| * is responsible for performing range checking before sending the |
| * request. |
| * |
| * - Host RW permission checking should already be done prior to calling |
| * this function by the message processing function. |
| * |
| * NOTE: |
| * |
| * @param cfgId: 16-bit CFG parameter ID |
| * @param value: 32-bit unsigned value |
| * |
| * @return eSIR_SUCCESS : request completed successfully \n |
| * @return eSIR_CFG_INVALID_ID: invalid CFG parameter ID \n |
| */ |
| |
| tSirRetStatus |
| cfgSetInt(tpAniSirGlobal pMac, tANI_U16 cfgId, tANI_U32 value) |
| { |
| tANI_U32 index; |
| tANI_U32 control, mask; |
| tSirRetStatus retVal; |
| |
| if (cfgId >= WNI_CFG_MAX) |
| { |
| PELOGE(cfgLog(pMac, LOGE, FL("Invalid cfg id %d"), cfgId);) |
| return eSIR_CFG_INVALID_ID; |
| } |
| if (!pMac->cfg.gCfgEntry) |
| { |
| PELOGE(cfgLog(pMac, LOGE, FL("gCfgEntry is NULL"));) |
| return eSIR_CFG_INVALID_ID; |
| } |
| |
| control = pMac->cfg.gCfgEntry[cfgId].control; |
| index = control & CFG_BUF_INDX_MASK; |
| retVal = eSIR_SUCCESS; |
| |
| if (index >= CFG_STA_IBUF_MAX_SIZE) |
| { |
| PELOGE(cfgLog(pMac, LOGE, FL("cfg index out of bounds %d"), index);) |
| retVal = eSIR_CFG_INVALID_ID; |
| return retVal; |
| } |
| |
| // Check if parameter is valid |
| if ((control & CFG_CTL_VALID) == 0) |
| { |
| PELOGE(cfgLog(pMac, LOGE, FL("Not valid cfg id %d"), cfgId);) |
| retVal = eSIR_CFG_INVALID_ID; |
| } |
| else if ((pMac->cfg.gCfgIBufMin[index] > value) || |
| (pMac->cfg.gCfgIBufMax[index] < value)) |
| { |
| PELOGE(cfgLog(pMac, LOGE, FL("Value %d out of range [%d,%d] cfg id %d"), |
| value, pMac->cfg.gCfgIBufMin[index], |
| pMac->cfg.gCfgIBufMax[index], cfgId);) |
| retVal = eSIR_CFG_INVALID_ID; |
| } |
| else |
| { |
| // Write integer value |
| pMac->cfg.gCfgIBuf[index] = value; |
| |
| // Update hardware if necessary |
| mask = control & CFG_CTL_NTF_MASK; |
| if ((mask & CFG_CTL_NTF_HW) != 0) |
| PELOGE(cfgLog(pMac, LOGE, FL("CFG Notify HW not supported!!!"));) |
| |
| // Notify other modules if necessary |
| if ((mask & CFG_CTL_NTF_MASK) != 0) |
| Notify(pMac, cfgId, mask); |
| |
| } |
| |
| return (retVal); |
| |
| } /*** end cfgSetInt ***/ |
| |
| // --------------------------------------------------------------------- |
| /** |
| * cfgCheckValid() |
| * |
| * FUNCTION: |
| * This function is called to check if a parameter is valid |
| * |
| * LOGIC: |
| * |
| * ASSUMPTIONS: |
| * |
| * NOTE: |
| * |
| * @param cfgId: 16-bit CFG parameter ID |
| * |
| * @return eSIR_SUCCESS: request completed successfully |
| * @return eSIR_CFG_INVALID_ID: invalid CFG parameter ID |
| */ |
| |
| tSirRetStatus |
| cfgCheckValid(tpAniSirGlobal pMac, tANI_U16 cfgId) |
| { |
| tANI_U32 control; |
| |
| if (cfgId >= WNI_CFG_MAX) |
| { |
| PELOG3(cfgLog(pMac, LOG3, FL("Invalid cfg id %d"), cfgId);) |
| return(eSIR_CFG_INVALID_ID); |
| } |
| if (!pMac->cfg.gCfgEntry) |
| { |
| PELOGE(cfgLog(pMac, LOGE, FL("gCfgEntry is NULL"));) |
| return eSIR_CFG_INVALID_ID; |
| } |
| |
| control = pMac->cfg.gCfgEntry[cfgId].control; |
| |
| // Check if parameter is valid |
| if ((control & CFG_CTL_VALID) == 0) |
| { |
| PELOG3(cfgLog(pMac, LOG3, FL("Not valid cfg id %d"), cfgId);) |
| return(eSIR_CFG_INVALID_ID); |
| } |
| else |
| return(eSIR_SUCCESS); |
| |
| } /*** end cfgCheckValid() ***/ |
| |
| // --------------------------------------------------------------------- |
| /** |
| * wlan_cfgGetInt() |
| * |
| * FUNCTION: |
| * This function is called to read an integer parameter. |
| * |
| * LOGIC: |
| * |
| * ASSUMPTIONS: |
| * |
| * NOTE: |
| * |
| * @param cfgId: 16-bit CFG parameter ID |
| * @param pVal: address where parameter value will be written |
| * |
| * @return eSIR_SUCCESS: request completed successfully |
| * @return eSIR_CFG_INVALID_ID: invalid CFG parameter ID |
| */ |
| |
| tSirRetStatus |
| wlan_cfgGetInt(tpAniSirGlobal pMac, tANI_U16 cfgId, tANI_U32 *pValue) |
| { |
| tANI_U32 index; |
| tANI_U32 control; |
| tSirRetStatus retVal; |
| |
| if (cfgId >= WNI_CFG_MAX) |
| { |
| PELOGE(cfgLog(pMac, LOGE, FL("Invalid cfg id %d"), cfgId);) |
| retVal = eSIR_CFG_INVALID_ID; |
| return retVal; |
| } |
| if (!pMac->cfg.gCfgEntry) |
| { |
| PELOGE(cfgLog(pMac, LOGE, FL("gCfgEntry is NULL"));) |
| return eSIR_CFG_INVALID_ID; |
| } |
| |
| control = pMac->cfg.gCfgEntry[cfgId].control; |
| index = control & CFG_BUF_INDX_MASK; |
| retVal = eSIR_SUCCESS; |
| |
| if (index >= CFG_STA_IBUF_MAX_SIZE) |
| { |
| PELOGE(cfgLog(pMac, LOGE, FL("cfg index out of bounds %d"), index);) |
| retVal = eSIR_CFG_INVALID_ID; |
| return retVal; |
| } |
| |
| // Check if parameter is valid |
| if ((control & CFG_CTL_VALID) == 0) |
| { |
| PELOGE(cfgLog(pMac, LOGE, FL("Not valid cfg id %d"), cfgId);) |
| retVal = eSIR_CFG_INVALID_ID; |
| } |
| else { |
| // Get integer value |
| if (index < CFG_STA_IBUF_MAX_SIZE) |
| *pValue = pMac->cfg.gCfgIBuf[index]; |
| } |
| |
| return (retVal); |
| |
| } /*** end wlan_cfgGetInt() ***/ |
| |
| // --------------------------------------------------------------------- |
| /** |
| * cfgSetStr() |
| * |
| * FUNCTION: |
| * This function is called to set a string parameter. |
| * |
| * LOGIC: |
| * This function invokes the cfgSetStrNotify function passing the notify |
| * boolean value set to TRUE. This basically means that HAL needs to be |
| * notified. This is true in the case of non-integrated SOC's or Libra/Volans. |
| * In the case of Prima the cfgSetStrNotify is invoked with the boolean value |
| * set to FALSE. |
| * |
| * ASSUMPTIONS: |
| * - always Notify has to be called |
| * |
| * NOTE: |
| * |
| * @param cfgId: 16-bit CFG parameter ID |
| * @param pStr: address of string data |
| * @param len: string length |
| * |
| * @return eSIR_SUCCESS: request completed successfully |
| * @return eSIR_CFG_INVALID_ID: invalid CFG parameter ID |
| * @return eSIR_CFG_INVALID_LEN: invalid parameter length |
| * |
| */ |
| |
| tSirRetStatus cfgSetStr(tpAniSirGlobal pMac, tANI_U16 cfgId, tANI_U8 *pStr, |
| tANI_U32 length) |
| { |
| return cfgSetStrNotify( pMac, cfgId, pStr, length, TRUE ); |
| } |
| |
| // --------------------------------------------------------------------- |
| /** |
| * cfgSetStrNotify() |
| * |
| * FUNCTION: |
| * This function is called to set a string parameter. |
| * |
| * LOGIC: |
| * |
| * ASSUMPTIONS: |
| * - No length checking will be performed. Should be done by calling |
| * module. |
| * - Host RW permission should be checked prior to calling this |
| * function. |
| * |
| * NOTE: |
| * |
| * @param cfgId: 16-bit CFG parameter ID |
| * @param pStr: address of string data |
| * @param len: string length |
| * @param notifyMod. Notify respective Module |
| * |
| * @return eSIR_SUCCESS: request completed successfully |
| * @return eSIR_CFG_INVALID_ID: invalid CFG parameter ID |
| * @return eSIR_CFG_INVALID_LEN: invalid parameter length |
| * |
| */ |
| |
| tSirRetStatus |
| cfgSetStrNotify(tpAniSirGlobal pMac, tANI_U16 cfgId, tANI_U8 *pStr, |
| tANI_U32 length, int notifyMod) |
| { |
| tANI_U8 *pDst, *pDstEnd; |
| tANI_U32 index, paramLen, control, mask; |
| tSirRetStatus retVal; |
| |
| if (cfgId >= WNI_CFG_MAX) |
| { |
| PELOGE(cfgLog(pMac, LOGE, FL("Invalid cfg id %d"), cfgId);) |
| return eSIR_CFG_INVALID_ID; |
| } |
| if (!pMac->cfg.gCfgEntry) |
| { |
| PELOGE(cfgLog(pMac, LOGE, FL("gCfgEntry is NULL"));) |
| return eSIR_CFG_INVALID_ID; |
| } |
| |
| control = pMac->cfg.gCfgEntry[cfgId].control; |
| index = control & CFG_BUF_INDX_MASK; |
| retVal = eSIR_SUCCESS; |
| |
| // Check if parameter is valid |
| if ((control & CFG_CTL_VALID) == 0) |
| { |
| PELOGE(cfgLog(pMac, LOGE, FL("Invalid cfg id %d"), cfgId);) |
| retVal = eSIR_CFG_INVALID_ID; |
| } |
| else if (index >= CFG_STA_SBUF_MAX_SIZE) |
| { |
| PELOGE(cfgLog(pMac, LOGE, FL("Invalid Sbuf index %d (max size %d)"), |
| index, CFG_STA_SBUF_MAX_SIZE);) |
| retVal = eSIR_CFG_INVALID_ID; |
| } |
| else |
| { |
| pDst = &pMac->cfg.gCfgSBuf[index]; |
| paramLen = *pDst++; |
| if (length > paramLen) |
| { |
| PELOGE(cfgLog(pMac, LOGE, FL("Invalid length %d (>%d) cfg id %d"), |
| length, paramLen, cfgId);) |
| retVal = eSIR_CFG_INVALID_LEN; |
| } |
| else |
| { |
| *pDst++ = (tANI_U8)length; |
| pDstEnd = pDst + length; |
| while (pDst < pDstEnd) |
| { |
| *pDst++ = *pStr++; |
| } |
| |
| if(notifyMod) |
| { |
| // Update hardware if necessary |
| mask = control & CFG_CTL_NTF_MASK; |
| if ((mask & CFG_CTL_NTF_HW) != 0) |
| { |
| PELOGE(cfgLog(pMac, LOGE, FL("CFG Notify HW not supported!!!"));) |
| } |
| |
| // Notify other modules if necessary |
| if ( (mask & CFG_CTL_NTF_MASK) != 0) |
| { |
| Notify(pMac, cfgId, mask); |
| } |
| } |
| } |
| |
| } |
| |
| return (retVal); |
| |
| } /*** end cfgSetStrNotify() ***/ |
| |
| // --------------------------------------------------------------------- |
| /** |
| * wlan_cfgGetStr() |
| * |
| * FUNCTION: |
| * This function is called to get a string parameter. |
| * |
| * LOGIC: |
| * |
| * ASSUMPTIONS: |
| * - Host RW permission should be checked prior to calling this |
| * function. |
| * |
| * NOTE: |
| * |
| * @param cfgId: 16-bit CFG parameter ID |
| * @param pBuf: address of string buffer |
| * @param pLen: address of max buffer length |
| * actual length will be returned at this address |
| * |
| * @return eSIR_SUCCESS: request completed successfully |
| * @return eSIR_CFG_INVALID_ID: invalid CFG parameter ID |
| * @return eSIR_CFG_INVALID_LEN: invalid parameter length |
| * |
| */ |
| |
| tSirRetStatus |
| wlan_cfgGetStr(tpAniSirGlobal pMac, tANI_U16 cfgId, tANI_U8 *pBuf, tANI_U32 *pLength) |
| { |
| tANI_U8 *pSrc, *pSrcEnd; |
| tANI_U32 index, control; |
| tSirRetStatus retVal; |
| |
| if (cfgId >= WNI_CFG_MAX) |
| { |
| PELOGE(cfgLog(pMac, LOGE, FL("Invalid cfg id %d"), cfgId);) |
| retVal = eSIR_CFG_INVALID_ID; |
| return retVal; |
| } |
| if (!pMac->cfg.gCfgEntry) |
| { |
| PELOGE(cfgLog(pMac, LOGE, FL("gCfgEntry is NULL"));) |
| return eSIR_CFG_INVALID_ID; |
| } |
| |
| control = pMac->cfg.gCfgEntry[cfgId].control; |
| index = control & CFG_BUF_INDX_MASK; |
| retVal = eSIR_SUCCESS; |
| |
| if (index >= CFG_STA_SBUF_MAX_SIZE) |
| { |
| PELOGE(cfgLog(pMac, LOGE, FL("cfg index out of bounds %d"), index);) |
| retVal = eSIR_CFG_INVALID_ID; |
| return retVal; |
| } |
| |
| // Check if parameter is valid |
| if ((control & CFG_CTL_VALID) == 0) |
| { |
| PELOGE(cfgLog(pMac, LOGE, FL("Not valid cfg id %d"), cfgId);) |
| retVal = eSIR_CFG_INVALID_ID; |
| } |
| else |
| { |
| // Get string |
| pSrc = &pMac->cfg.gCfgSBuf[index]; |
| pSrc++; // skip over max length |
| if (*pLength < *pSrc) |
| { |
| PELOGE(cfgLog(pMac, LOGE, FL("Invalid length %d (<%d) cfg id %d"), |
| *pLength, *pSrc, cfgId);) |
| retVal = eSIR_CFG_INVALID_LEN; |
| } |
| else |
| { |
| *pLength = *pSrc++; // save parameter length |
| pSrcEnd = pSrc + *pLength; |
| while (pSrc < pSrcEnd) |
| *pBuf++ = *pSrc++; |
| } |
| } |
| |
| return (retVal); |
| |
| } /*** end wlan_cfgGetStr() ***/ |
| |
| // --------------------------------------------------------------------- |
| /** |
| * wlan_cfgGetStrMaxLen() |
| * |
| * FUNCTION: |
| * This function is called to get a string maximum length. |
| * |
| * LOGIC: |
| * |
| * ASSUMPTIONS: |
| * - Host RW permission should be checked prior to calling this |
| * function. |
| * |
| * NOTE: |
| * |
| * @param cfgId: 16-bit CFG parameter ID |
| * @param pLen: maximum length will be returned at this address |
| * |
| * @return eSIR_SUCCESS: request completed successfully |
| * @return eSIR_CFG_INVALID_ID: invalid CFG parameter ID |
| * |
| */ |
| |
| tSirRetStatus |
| wlan_cfgGetStrMaxLen(tpAniSirGlobal pMac, tANI_U16 cfgId, tANI_U32 *pLength) |
| { |
| tANI_U32 index, control; |
| tSirRetStatus retVal; |
| |
| if (cfgId >= WNI_CFG_MAX) |
| { |
| PELOGE(cfgLog(pMac, LOGE, FL("Invalid cfg id %d"), cfgId);) |
| retVal = eSIR_CFG_INVALID_ID; |
| } |
| if (!pMac->cfg.gCfgEntry) |
| { |
| PELOGE(cfgLog(pMac, LOGE, FL("gCfgEntry is NULL"));) |
| return eSIR_CFG_INVALID_ID; |
| } |
| |
| control = pMac->cfg.gCfgEntry[cfgId].control; |
| index = control & CFG_BUF_INDX_MASK; |
| retVal = eSIR_SUCCESS; |
| |
| if (index >= CFG_STA_SBUF_MAX_SIZE) |
| { |
| PELOGE(cfgLog(pMac, LOGE, FL("cfg index out of bounds %d"), index);) |
| retVal = eSIR_CFG_INVALID_ID; |
| return retVal; |
| } |
| |
| // Check if parameter is valid |
| if ((control & CFG_CTL_VALID) == 0) |
| { |
| PELOGE(cfgLog(pMac, LOGE, FL("Not valid cfg id %d"), cfgId);) |
| retVal = eSIR_CFG_INVALID_ID; |
| } |
| else |
| { |
| *pLength = pMac->cfg.gCfgSBuf[index]; |
| } |
| |
| return (retVal); |
| |
| } /*** end wlan_cfgGetStrMaxLen() ***/ |
| |
| // --------------------------------------------------------------------- |
| /** |
| * wlan_cfgGetStrLen() |
| * |
| * FUNCTION: |
| * This function is called to get a string length. |
| * |
| * LOGIC: |
| * |
| * ASSUMPTIONS: |
| * - Host RW permission should be checked prior to calling this |
| * function. |
| * |
| * NOTE: |
| * |
| * @param cfgId: 16-bit CFG parameter ID |
| * @param pLen: current length will be returned at this address |
| * |
| * @return eSIR_SUCCESS: request completed successfully |
| * @return eSIR_CFG_INVALID_ID: invalid CFG parameter ID |
| * |
| */ |
| |
| tSirRetStatus |
| wlan_cfgGetStrLen(tpAniSirGlobal pMac, tANI_U16 cfgId, tANI_U32 *pLength) |
| { |
| tANI_U32 index, control; |
| tSirRetStatus retVal; |
| |
| if (cfgId >= WNI_CFG_MAX) |
| { |
| PELOGE(cfgLog(pMac, LOGE, FL("Invalid cfg id %d"), cfgId);) |
| retVal = eSIR_CFG_INVALID_ID; |
| } |
| if (!pMac->cfg.gCfgEntry) |
| { |
| PELOGE(cfgLog(pMac, LOGE, FL("gCfgEntry is NULL"));) |
| return eSIR_CFG_INVALID_ID; |
| } |
| |
| control = pMac->cfg.gCfgEntry[cfgId].control; |
| index = control & CFG_BUF_INDX_MASK; |
| retVal = eSIR_SUCCESS; |
| |
| if (index >= CFG_STA_SBUF_MAX_SIZE-1) |
| { |
| PELOGE(cfgLog(pMac, LOGE, FL("cfg index out of bounds %d"), index);) |
| retVal = eSIR_CFG_INVALID_ID; |
| return retVal; |
| } |
| |
| // Check if parameter is valid |
| if ((control & CFG_CTL_VALID) == 0) |
| { |
| PELOGE(cfgLog(pMac, LOGE, FL("Not valid cfg id %d"), cfgId);) |
| retVal = eSIR_CFG_INVALID_ID; |
| } |
| else |
| { |
| *pLength = pMac->cfg.gCfgSBuf[index+1]; |
| } |
| |
| return (retVal); |
| |
| } /*** end wlan_cfgGetStrLen() ***/ |
| |
| |
| |
| /*------------------------------------------------------------- |
| \fn cfgGetDot11dTransmitPower |
| \brief This function returns the regulatory max transmit power |
| \param pMac |
| \return tPowerdBm - Power |
| \-------------------------------------------------------------*/ |
| static tPowerdBm |
| cfgGetDot11dTransmitPower(tpAniSirGlobal pMac, tANI_U16 cfgId, |
| tANI_U32 cfgLength, tANI_U8 channel) |
| { |
| tANI_U8 *pCountryInfo = NULL; |
| tANI_U8 count = 0; |
| tPowerdBm maxTxPwr = WDA_MAX_TXPOWER_INVALID; |
| |
| /* At least one element is present */ |
| if(cfgLength < sizeof(tSirMacChanInfo)) |
| { |
| PELOGE(cfgLog(pMac, LOGE, FL("Invalid CFGLENGTH %d while getting 11d txpower"), cfgLength);) |
| goto error; |
| } |
| |
| pCountryInfo = vos_mem_malloc(cfgLength); |
| if ( NULL == pCountryInfo ) |
| { |
| cfgLog(pMac, LOGP, FL(" failed to allocate memory")); |
| goto error; |
| } |
| /* The CSR will always update this CFG. The contents will be from country IE if regulatory domain |
| * is enabled on AP else will contain EEPROM contents |
| */ |
| if (wlan_cfgGetStr(pMac, cfgId, pCountryInfo, &cfgLength) != eSIR_SUCCESS) |
| { |
| vos_mem_free(pCountryInfo); |
| pCountryInfo = NULL; |
| |
| cfgLog(pMac, LOGP, FL("Failed to retrieve 11d configuration parameters while retrieving 11d tuples")); |
| goto error; |
| } |
| /* Identify the channel and max txpower */ |
| while(count <= (cfgLength - (sizeof(tSirMacChanInfo)))) |
| { |
| tANI_U8 firstChannel, maxChannels; |
| |
| firstChannel = pCountryInfo[count++]; |
| maxChannels = pCountryInfo[count++]; |
| maxTxPwr = pCountryInfo[count++]; |
| |
| if((channel >= firstChannel) && |
| (channel < (firstChannel + maxChannels))) |
| { |
| break; |
| } |
| } |
| |
| error: |
| if (NULL != pCountryInfo) |
| vos_mem_free(pCountryInfo); |
| |
| return maxTxPwr; |
| } |
| |
| |
| /**---------------------------------------------------------------------- |
| \fn cfgGetRegulatoryMaxTransmitPower |
| |
| \brief Gets regulatory tx power on the current channel. |
| |
| \param pMac |
| \param channel |
| \param rfBand |
| -----------------------------------------------------------------------*/ |
| tPowerdBm cfgGetRegulatoryMaxTransmitPower(tpAniSirGlobal pMac, tANI_U8 channel) |
| { |
| tANI_U32 cfgLength = 0; |
| tANI_U16 cfgId = 0; |
| tPowerdBm maxTxPwr; |
| eRfBandMode rfBand = eRF_BAND_UNKNOWN; |
| |
| if ((channel >= SIR_11A_CHANNEL_BEGIN) && |
| (channel <= SIR_11A_CHANNEL_END)) |
| rfBand = eRF_BAND_5_GHZ; |
| else |
| rfBand = eRF_BAND_2_4_GHZ; |
| |
| |
| /* Get the max transmit power for current channel for the current regulatory domain */ |
| switch (rfBand) |
| { |
| case eRF_BAND_2_4_GHZ: |
| cfgId = WNI_CFG_MAX_TX_POWER_2_4; |
| cfgLength = WNI_CFG_MAX_TX_POWER_2_4_LEN; |
| PELOG2(cfgLog(pMac, LOG2, FL("HAL: Reading CFG for 2.4 GHz channels to get regulatory max tx power"));) |
| break; |
| |
| case eRF_BAND_5_GHZ: |
| cfgId = WNI_CFG_MAX_TX_POWER_5; |
| cfgLength = WNI_CFG_MAX_TX_POWER_5_LEN; |
| PELOG2(cfgLog(pMac, LOG2, FL("HAL: Reading CFG for 5.0 GHz channels to get regulatory max tx power"));) |
| break; |
| |
| case eRF_BAND_UNKNOWN: |
| default: |
| PELOG2(cfgLog(pMac, LOG2, FL("HAL: Invalid current working band for the device"));) |
| return WDA_MAX_TXPOWER_INVALID; //Its return, not break. |
| } |
| |
| maxTxPwr = cfgGetDot11dTransmitPower(pMac, cfgId, cfgLength, channel); |
| |
| return (maxTxPwr); |
| } |
| |
| // --------------------------------------------------------------------- |
| /** |
| * cfgGetCapabilityInfo |
| * |
| * FUNCTION: |
| * |
| * LOGIC: |
| * |
| * ASSUMPTIONS: |
| * |
| * NOTE: |
| * |
| * @param None |
| * @return None |
| */ |
| |
| tSirRetStatus |
| cfgGetCapabilityInfo(tpAniSirGlobal pMac, tANI_U16 *pCap,tpPESession sessionEntry) |
| { |
| tANI_U32 val = 0; |
| tpSirMacCapabilityInfo pCapInfo; |
| |
| *pCap = 0; |
| pCapInfo = (tpSirMacCapabilityInfo) pCap; |
| |
| if (LIM_IS_IBSS_ROLE(sessionEntry)) |
| pCapInfo->ibss = 1; // IBSS bit |
| else if (LIM_IS_AP_ROLE(sessionEntry) || |
| LIM_IS_BT_AMP_AP_ROLE(sessionEntry) || |
| LIM_IS_BT_AMP_STA_ROLE(sessionEntry) || |
| LIM_IS_STA_ROLE(sessionEntry)) |
| pCapInfo->ess = 1; // ESS bit |
| else if (LIM_IS_P2P_DEVICE_ROLE(sessionEntry) || |
| LIM_IS_NDI_ROLE(sessionEntry)) { |
| pCapInfo->ess = 0; |
| pCapInfo->ibss = 0; |
| } |
| else |
| cfgLog(pMac, LOGP, FL("can't get capability, role is UNKNOWN!!")); |
| |
| |
| if (LIM_IS_AP_ROLE(sessionEntry)) { |
| val = sessionEntry->privacy; |
| #ifdef SAP_AUTH_OFFLOAD |
| /* Support software AP Authentication Offload feature, |
| * If Auth offload security Type is not disabled |
| * We need to enable privacy bit in beacon |
| */ |
| if (pMac->sap_auth_offload && pMac->sap_auth_offload_sec_type) { |
| val = 1; |
| } |
| #endif |
| } else { |
| // PRIVACY bit |
| if (wlan_cfgGetInt(pMac, WNI_CFG_PRIVACY_ENABLED, &val) != eSIR_SUCCESS) |
| { |
| cfgLog(pMac, LOGP, FL("cfg get WNI_CFG_PRIVACY_ENABLED failed")); |
| return eSIR_FAILURE; |
| } |
| } |
| if (val) |
| pCapInfo->privacy = 1; |
| |
| // Short preamble bit |
| if (wlan_cfgGetInt(pMac, WNI_CFG_SHORT_PREAMBLE, &val) != eSIR_SUCCESS) |
| { |
| cfgLog(pMac, LOGP, FL("cfg get WNI_CFG_SHORT_PREAMBLE failed")); |
| return eSIR_FAILURE; |
| } |
| if (val) |
| pCapInfo->shortPreamble = 1; |
| |
| |
| // PBCC bit |
| pCapInfo->pbcc = 0; |
| |
| // Channel agility bit |
| pCapInfo->channelAgility = 0; |
| //If STA/AP operating in 11B mode, don't set rest of the capability info bits. |
| if(sessionEntry->dot11mode == WNI_CFG_DOT11_MODE_11B) |
| return eSIR_SUCCESS; |
| |
| // Short slot time bit |
| if (LIM_IS_AP_ROLE(sessionEntry)) { |
| pCapInfo->shortSlotTime = sessionEntry->shortSlotTimeSupported; |
| } else { |
| if (wlan_cfgGetInt(pMac, WNI_CFG_11G_SHORT_SLOT_TIME_ENABLED, &val) |
| != eSIR_SUCCESS) |
| { |
| cfgLog(pMac, LOGP, |
| FL("cfg get WNI_CFG_11G_SHORT_SLOT_TIME failed")); |
| return eSIR_FAILURE; |
| } |
| /* When in STA mode, we need to check if short slot is enabled as well as check if the current operating |
| * mode is short slot time and then decide whether to enable short slot or not. It is safe to check both |
| * cfg values to determine short slot value in this funcn since this funcn is always used after assoc when |
| * these cfg values are already set based on peer's capability. Even in case of IBSS, its value is set to |
| * correct value either in delBSS as part of deleting the previous IBSS or in start BSS as part of coalescing |
| */ |
| if (val) |
| { |
| pCapInfo->shortSlotTime = sessionEntry->shortSlotTimeSupported; |
| } |
| } |
| |
| // Spectrum Management bit |
| if (!LIM_IS_IBSS_ROLE(sessionEntry) && sessionEntry->lim11hEnable) { |
| if (wlan_cfgGetInt(pMac, WNI_CFG_11H_ENABLED, &val) != eSIR_SUCCESS) |
| { |
| cfgLog(pMac, LOGP, FL("cfg get WNI_CFG_11H_ENABLED failed")); |
| return eSIR_FAILURE; |
| } |
| if (val) |
| pCapInfo->spectrumMgt = 1; |
| } |
| |
| // QoS bit |
| if (wlan_cfgGetInt(pMac, WNI_CFG_QOS_ENABLED, &val) != eSIR_SUCCESS) |
| { |
| cfgLog(pMac, LOGP, FL("cfg get WNI_CFG_QOS_ENABLED failed")); |
| return eSIR_FAILURE; |
| } |
| if (val) |
| pCapInfo->qos = 1; |
| |
| // APSD bit |
| if (wlan_cfgGetInt(pMac, WNI_CFG_APSD_ENABLED, &val) != eSIR_SUCCESS) |
| { |
| cfgLog(pMac, LOGP, FL("cfg get WNI_CFG_APSD_ENABLED failed")); |
| return eSIR_FAILURE; |
| } |
| if (val) |
| pCapInfo->apsd = 1; |
| |
| #if defined WLAN_FEATURE_VOWIFI |
| pCapInfo->rrm = pMac->rrm.rrmSmeContext.rrmConfig.rrm_enabled; |
| #if defined WLAN_VOWIFI_DEBUG |
| cfgLog( pMac, LOG1, "RRM = %d", pCapInfo->rrm); |
| #endif |
| #endif |
| |
| //DSSS-OFDM |
| //FIXME : no config defined yet. |
| |
| // Block ack bit |
| if (wlan_cfgGetInt(pMac, WNI_CFG_BLOCK_ACK_ENABLED, &val) != eSIR_SUCCESS) |
| { |
| cfgLog(pMac, LOGP, FL("cfg get WNI_CFG_BLOCK_ACK_ENABLED failed")); |
| return eSIR_FAILURE; |
| } |
| pCapInfo->delayedBA = (tANI_U16)((val >> WNI_CFG_BLOCK_ACK_ENABLED_DELAYED) & 1); |
| pCapInfo->immediateBA = (tANI_U16)((val >> WNI_CFG_BLOCK_ACK_ENABLED_IMMEDIATE) & 1); |
| |
| return eSIR_SUCCESS; |
| } |
| |
| // -------------------------------------------------------------------- |
| /** |
| * cfgSetCapabilityInfo |
| * |
| * FUNCTION: |
| * This function is called on BP based on the capabilities |
| * received in SME_JOIN/REASSOC_REQ message. |
| * |
| * LOGIC: |
| * |
| * ASSUMPTIONS: |
| * |
| * NOTE: 1. ESS/IBSS capabilities are based on system role. |
| * 2. Since PBCC, Channel agility and Extended capabilities |
| * are not supported, they're not set at CFG |
| * |
| * @param pMac Pointer to global MAC structure |
| * @param caps 16-bit Capability Info field |
| * @return None |
| */ |
| |
| void |
| cfgSetCapabilityInfo(tpAniSirGlobal pMac, tANI_U16 caps) |
| { |
| } |
| |
| |
| // --------------------------------------------------------------------- |
| /** |
| * cfgCleanup() |
| * |
| * FUNCTION: |
| * CFG clean up function. |
| * |
| * LOGIC: |
| * |
| * ASSUMPTIONS: |
| * None. |
| * |
| * NOTE: |
| * This function must be called during system shut down. |
| * |
| * @param None |
| * |
| * @return None. |
| * |
| */ |
| |
| void |
| cfgCleanup(tpAniSirGlobal pMac) |
| { |
| // Set status to not-ready |
| pMac->cfg.gCfgStatus = CFG_INCOMPLETE; |
| |
| } /*** end CfgCleanup() ***/ |
| |
| // --------------------------------------------------------------------- |
| /** |
| * Notify() |
| * |
| * FUNCTION: |
| * This function is called to notify other modules of parameter update. |
| * |
| * LOGIC: |
| * |
| * ASSUMPTIONS: |
| * |
| * NOTE: |
| * |
| * @param cfgId: configuration parameter ID |
| * @param mask: notification mask |
| * |
| * @return None. |
| * |
| */ |
| |
| static void |
| Notify(tpAniSirGlobal pMac, tANI_U16 cfgId, tANI_U32 ntfMask) |
| { |
| |
| tSirMsgQ mmhMsg; |
| |
| mmhMsg.type = SIR_CFG_PARAM_UPDATE_IND; |
| mmhMsg.bodyval = (tANI_U32)cfgId; |
| mmhMsg.bodyptr = NULL; |
| |
| if ((ntfMask & CFG_CTL_NTF_SCH) != 0) |
| schPostMessage(pMac, &mmhMsg); |
| |
| if ((ntfMask & CFG_CTL_NTF_LIM) != 0) |
| limPostMsgApi(pMac, &mmhMsg); |
| |
| if ((ntfMask & CFG_CTL_NTF_HAL) != 0) |
| wdaPostCtrlMsg(pMac, &mmhMsg); |
| |
| // Notify ARQ |
| |
| } /*** end Notify() ***/ |
| |
| /** |
| * cfg_get_vendor_ie_ptr_from_oui() - returns IE pointer in IE buffer given its |
| * OUI and OUI size |
| * @mac_ctx: mac context. |
| * @oui: OUI string. |
| * @oui_size: length of OUI string |
| * One can provide multiple line descriptions |
| * for arguments. |
| * @ie: ie buffer |
| * @ie_len: length of ie buffer |
| * |
| * This function parses the IE buffer and finds the given OUI and returns its |
| * pointer |
| * |
| * Return: pointer of given OUI IE else NULL |
| */ |
| uint8_t* cfg_get_vendor_ie_ptr_from_oui(tpAniSirGlobal mac_ctx, |
| uint8_t *oui, |
| uint8_t oui_size, |
| uint8_t *ie, |
| uint16_t ie_len) |
| { |
| int32_t left = ie_len; |
| uint8_t *ptr = ie; |
| uint8_t elem_id, elem_len; |
| |
| while(left >= 2) { |
| elem_id = ptr[0]; |
| elem_len = ptr[1]; |
| left -= 2; |
| if(elem_len > left) { |
| cfgLog(mac_ctx, LOGE, |
| FL("Invalid IEs eid = %d elem_len=%d left=%d"), |
| elem_id, elem_len, left); |
| return NULL; |
| } |
| if (SIR_MAC_EID_VENDOR == elem_id) { |
| if((elem_len>=oui_size) && |
| (memcmp(&ptr[2], oui, oui_size)==0)) |
| return ptr; |
| } |
| |
| left -= elem_len; |
| ptr += (elem_len + 2); |
| } |
| return NULL; |
| } |
| // --------------------------------------------------------------------- |