wlan: Add new DRIVER command SET_FCC_CHANNEL.
Due to airplane mode and subsequent change of country, there
may be a time gap till a new country code gets programmed into
the WLAN sub-system. In order to avoid FCC violation during this
period, provide command to enable/disable channels 12/13.
Change-Id: I38ca9d31edd3e5fb74e41f888efbe2c53f553afa
CRs-Fixed: 855016
diff --git a/CORE/HDD/src/wlan_hdd_main.c b/CORE/HDD/src/wlan_hdd_main.c
index 2049dd7..8a6f62c 100755
--- a/CORE/HDD/src/wlan_hdd_main.c
+++ b/CORE/HDD/src/wlan_hdd_main.c
@@ -2192,6 +2192,35 @@
return ret;
}
+static int hdd_cmd_setFccChannel(hdd_context_t *pHddCtx, tANI_U8 *cmd,
+ tANI_U8 cmd_len)
+{
+ tANI_U8 *value;
+ tANI_U8 fcc_constraint;
+
+ eHalStatus status;
+ int ret = 0;
+ value = cmd + cmd_len + 1;
+
+ ret = kstrtou8(value, 10, &fcc_constraint);
+ if ((ret < 0) || (fcc_constraint > 1)) {
+ /*
+ * If the input value is greater than max value of datatype,
+ * then also it is a failure
+ */
+ hddLog(VOS_TRACE_LEVEL_ERROR,
+ "%s: value out of range", __func__);
+ return -EINVAL;
+ }
+
+ status = sme_handleSetFccChannel(pHddCtx->hHal, fcc_constraint);
+ if (status != eHAL_STATUS_SUCCESS)
+ ret = -EPERM;
+
+ return ret;
+}
+
+
static int hdd_driver_command(hdd_adapter_t *pAdapter,
hdd_priv_data_t *ppriv_data)
@@ -4398,6 +4427,19 @@
}
}
+ else if (strncasecmp(command, "SET_FCC_CHANNEL", 15) == 0)
+ {
+ /*
+ * this command wld be called by user-space when it detects WLAN
+ * ON after airplane mode is set. When APM is set, WLAN turns off.
+ * But it can be turned back on. Otherwise; when APM is turned back
+ * off, WLAN wld turn back on. So at that point the command is
+ * expected to come down. 0 means disable, 1 means enable. The
+ * constraint is removed when parameter 1 is set or different
+ * country code is set
+ */
+ ret = hdd_cmd_setFccChannel(pHddCtx, command, 15);
+ }
else {
MTRACE(vos_trace(VOS_MODULE_ID_HDD,
TRACE_CODE_HDD_UNSUPPORTED_IOCTL,
diff --git a/CORE/SME/inc/csrInternal.h b/CORE/SME/inc/csrInternal.h
index 4df01a3..b5be859 100644
--- a/CORE/SME/inc/csrInternal.h
+++ b/CORE/SME/inc/csrInternal.h
@@ -804,6 +804,7 @@
csrScanCompleteCallback callback11dScanDone;
eCsrBand scanBandPreference; //This defines the band perference for scan
+ bool fcc_constraint;
}tCsrScanStruct;
diff --git a/CORE/SME/inc/sme_Api.h b/CORE/SME/inc/sme_Api.h
index b314251..dd6f005 100644
--- a/CORE/SME/inc/sme_Api.h
+++ b/CORE/SME/inc/sme_Api.h
@@ -3699,5 +3699,8 @@
-------------------------------------------------------------------------*/
eHalStatus sme_SetRtsCtsHtVht(tHalHandle hHal, tANI_U32 set_value);
+tANI_BOOLEAN sme_handleSetFccChannel(tHalHandle hHal,
+ tANI_U8 fcc_constraint);
+
#endif //#if !defined( __SME_API_H )
diff --git a/CORE/SME/src/csr/csrApiScan.c b/CORE/SME/src/csr/csrApiScan.c
index ccacbdf..57608cf 100644
--- a/CORE/SME/src/csr/csrApiScan.c
+++ b/CORE/SME/src/csr/csrApiScan.c
@@ -3580,6 +3580,30 @@
csrSetCfgCountryCode(pMac, countryCode);
}
+void csrUpdateFCCChannelList(tpAniSirGlobal pMac)
+{
+ tCsrChannel ChannelList;
+ tANI_U8 chnlIndx = 0;
+ int i;
+ chnlIndx = pMac->scan.base20MHzChannels.numChannels;
+
+ for ( i = 0; i < pMac->scan.base20MHzChannels.numChannels; i++ )
+ {
+ if (pMac->scan.fcc_constraint &&
+ ((pMac->scan.base20MHzChannels.channelList[i] == 12) ||
+ (pMac->scan.base20MHzChannels.channelList[i] == 13)))
+ {
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO,
+ FL("removing channel %d"),
+ pMac->scan.base20MHzChannels.channelList[i]);
+ continue;
+ }
+ ChannelList.channelList[i] = pMac->scan.base20MHzChannels.channelList[i];
+ chnlIndx++;
+ }
+ csrSetCfgValidChannelList(pMac, ChannelList.channelList, chnlIndx);
+
+}
void csrResetCountryInformation( tpAniSirGlobal pMac, tANI_BOOLEAN fForce, tANI_BOOLEAN updateRiva )
{
@@ -6238,6 +6262,16 @@
/* Skip CH 144 if firmware support not present */
if (pSrcReq->ChannelInfo.ChannelList[index] == 144 && !ch144_support)
continue;
+ /* Skip channel 12 and 13 when FCC constraint is true */
+ if ((pMac->scan.fcc_constraint) &&
+ ((pSrcReq->ChannelInfo.ChannelList[index] ==12) ||
+ (pSrcReq->ChannelInfo.ChannelList[index] ==13)))
+ {
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO,
+ FL("Ignoring channel : %d "),
+ pSrcReq->ChannelInfo.ChannelList[index]);
+ continue;
+ }
NVchannel_state = vos_nv_getChannelEnabledState(
pSrcReq->ChannelInfo.ChannelList[index]);
diff --git a/CORE/SME/src/csr/csrInsideApi.h b/CORE/SME/src/csr/csrInsideApi.h
index 2856a4e..aefbc12 100644
--- a/CORE/SME/src/csr/csrInsideApi.h
+++ b/CORE/SME/src/csr/csrInsideApi.h
@@ -384,6 +384,7 @@
tANI_U32 csrTranslateToWNICfgDot11Mode(tpAniSirGlobal pMac, eCsrCfgDot11Mode csrDot11Mode);
void csrSaveChannelPowerForBand( tpAniSirGlobal pMac, tANI_BOOLEAN fPopulate5GBand );
void csrApplyChannelPowerCountryInfo( tpAniSirGlobal pMac, tCsrChannel *pChannelList, tANI_U8 *countryCode, tANI_BOOLEAN updateRiva);
+void csrUpdateFCCChannelList(tpAniSirGlobal pMac);
void csrApplyPower2Current( tpAniSirGlobal pMac );
void csrAssignRssiForCategory(tpAniSirGlobal pMac, tANI_S8 bestApRssi, tANI_U8 catOffset);
tANI_BOOLEAN csrIsMacAddressZero( tpAniSirGlobal pMac, tCsrBssid *pMacAddr );
diff --git a/CORE/SME/src/sme_common/sme_Api.c b/CORE/SME/src/sme_common/sme_Api.c
index 12b5aa3..715fd76 100644
--- a/CORE/SME/src/sme_common/sme_Api.c
+++ b/CORE/SME/src/sme_common/sme_Api.c
@@ -7973,6 +7973,19 @@
static uNvTables nvTables;
pMsg = (tAniChangeCountryCodeReq *)pMsgBuf;
+ if (pMac->scan.fcc_constraint)
+ {
+ pMac->scan.fcc_constraint = false;
+ if (VOS_TRUE== vos_mem_compare(pMac->scan.countryCodeCurrent,
+ pMsg->countryCode, 2))
+ {
+ csrInitGetChannels(pMac);
+ csrResetCountryInformation(pMac, eANI_BOOLEAN_TRUE, eANI_BOOLEAN_TRUE);
+ csrScanFilterResults(pMac);
+ return status ;
+ }
+ }
+
/* if the reset Supplicant country code command is triggered, enable 11D, reset the NV country code and return */
if( VOS_TRUE == vos_mem_compare(pMsg->countryCode, SME_INVALID_COUNTRY_CODE, 2) )
@@ -12618,3 +12631,31 @@
return eHAL_STATUS_FAILURE;
}
+
+/**
+ * sme_handleSetFccChannel() - handle fcc constraint request
+ * @hal: HAL pointer
+ * @fcc_constraint: whether to apply or remove fcc constraint
+ *
+ * Return: tANI_BOOLEAN.
+ */
+tANI_BOOLEAN sme_handleSetFccChannel(tHalHandle hHal, tANI_U8 fcc_constraint)
+{
+ eHalStatus status = eHAL_STATUS_SUCCESS;
+ tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
+
+ status = sme_AcquireGlobalLock(&pMac->sme);
+
+ if (eHAL_STATUS_SUCCESS == status &&
+ (!sme_Is11dSupported(hHal)) )
+ {
+ pMac->scan.fcc_constraint = !fcc_constraint;
+ /* update the channel list to the firmware */
+ csrUpdateFCCChannelList(pMac);
+
+ }
+
+ sme_ReleaseGlobalLock(&pMac->sme);
+
+ return status;
+}