| /****************************************************************************** |
| * |
| * This file is provided under a dual license. When you use or |
| * distribute this software, you may choose to be licensed under |
| * version 2 of the GNU General Public License ("GPLv2 License") |
| * or BSD License. |
| * |
| * GPLv2 License |
| * |
| * Copyright(C) 2016 MediaTek Inc. |
| * |
| * This program is free software; you can redistribute it and/or modify |
| * it under the terms of version 2 of the GNU General Public License as |
| * published by the Free Software Foundation. |
| * |
| * This program is distributed in the hope that it will be useful, but |
| * WITHOUT ANY WARRANTY; without even the implied warranty of |
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. |
| * See http://www.gnu.org/licenses/gpl-2.0.html for more details. |
| * |
| * BSD LICENSE |
| * |
| * Copyright(C) 2016 MediaTek Inc. All rights reserved. |
| * |
| * Redistribution and use in source and binary forms, with or without |
| * modification, are permitted provided that the following conditions |
| * are met: |
| * |
| * * Redistributions of source code must retain the above copyright |
| * notice, this list of conditions and the following disclaimer. |
| * * Redistributions in binary form must reproduce the above copyright |
| * notice, this list of conditions and the following disclaimer in |
| * the documentation and/or other materials provided with the |
| * distribution. |
| * * Neither the name of the copyright holder nor the names of its |
| * contributors may be used to endorse or promote products derived |
| * from this software without specific prior written permission. |
| * |
| * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
| * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
| * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
| * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
| * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
| * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
| * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
| * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
| * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
| * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| * |
| *****************************************************************************/ |
| /* |
| ** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/mgmt/rlm_domain.c#2 |
| */ |
| |
| /*! \file "rlm_domain.c" |
| * \brief |
| * |
| */ |
| |
| |
| /******************************************************************************* |
| * C O M P I L E R F L A G S |
| ******************************************************************************** |
| */ |
| |
| /******************************************************************************* |
| * E X T E R N A L R E F E R E N C E S |
| ******************************************************************************** |
| */ |
| #include "precomp.h" |
| |
| #include "rlm_txpwr_init.h" |
| |
| |
| /******************************************************************************* |
| * C O N S T A N T S |
| ******************************************************************************** |
| */ |
| |
| /******************************************************************************* |
| * D A T A T Y P E S |
| ******************************************************************************** |
| */ |
| |
| /******************************************************************************* |
| * P U B L I C D A T A |
| ******************************************************************************** |
| */ |
| |
| /* The following country or domain shall be set from host driver. |
| * And host driver should pass specified DOMAIN_INFO_ENTRY to MT6620 as |
| * the channel list of being a STA to do scanning/searching AP or being an |
| * AP to choose an adequate channel if auto-channel is set. |
| */ |
| |
| /* Define mapping tables between country code and its channel set |
| */ |
| static const UINT_16 g_u2CountryGroup0[] = { |
| COUNTRY_CODE_AO, COUNTRY_CODE_BZ, COUNTRY_CODE_BJ, COUNTRY_CODE_BT, |
| COUNTRY_CODE_BO, COUNTRY_CODE_BI, COUNTRY_CODE_CM, COUNTRY_CODE_CF, |
| COUNTRY_CODE_TD, COUNTRY_CODE_KM, COUNTRY_CODE_CD, COUNTRY_CODE_CG, |
| COUNTRY_CODE_CI, COUNTRY_CODE_DJ, COUNTRY_CODE_GQ, COUNTRY_CODE_ER, |
| COUNTRY_CODE_FJ, COUNTRY_CODE_GA, COUNTRY_CODE_GM, COUNTRY_CODE_GN, |
| COUNTRY_CODE_GW, COUNTRY_CODE_RKS, COUNTRY_CODE_KG, COUNTRY_CODE_LY, |
| COUNTRY_CODE_MG, COUNTRY_CODE_ML, COUNTRY_CODE_NR, COUNTRY_CODE_NC, |
| COUNTRY_CODE_ST, COUNTRY_CODE_SC, COUNTRY_CODE_SL, COUNTRY_CODE_SB, |
| COUNTRY_CODE_SO, COUNTRY_CODE_SR, COUNTRY_CODE_SZ, COUNTRY_CODE_TJ, |
| COUNTRY_CODE_TG, COUNTRY_CODE_TO, COUNTRY_CODE_TM, COUNTRY_CODE_TV, |
| COUNTRY_CODE_VU, COUNTRY_CODE_YE |
| }; |
| |
| static const UINT_16 g_u2CountryGroup1[] = { |
| COUNTRY_CODE_AS, COUNTRY_CODE_AI, COUNTRY_CODE_BM, COUNTRY_CODE_CA, |
| COUNTRY_CODE_KY, COUNTRY_CODE_GU, COUNTRY_CODE_FM, COUNTRY_CODE_PR, |
| COUNTRY_CODE_US, COUNTRY_CODE_VI, |
| |
| }; |
| |
| static const UINT_16 g_u2CountryGroup2[] = { |
| COUNTRY_CODE_AR, COUNTRY_CODE_AU, COUNTRY_CODE_AZ, COUNTRY_CODE_BW, |
| COUNTRY_CODE_KH, COUNTRY_CODE_CX, COUNTRY_CODE_CO, COUNTRY_CODE_CR, |
| COUNTRY_CODE_EC, COUNTRY_CODE_GD, COUNTRY_CODE_GT, COUNTRY_CODE_HK, |
| COUNTRY_CODE_KI, COUNTRY_CODE_LB, COUNTRY_CODE_LR, COUNTRY_CODE_MN, |
| COUNTRY_CODE_AN, COUNTRY_CODE_NZ, COUNTRY_CODE_NI, COUNTRY_CODE_PW, |
| COUNTRY_CODE_PY, COUNTRY_CODE_PE, COUNTRY_CODE_PH, COUNTRY_CODE_WS, |
| COUNTRY_CODE_SG, COUNTRY_CODE_LK, COUNTRY_CODE_TH, COUNTRY_CODE_TT, |
| COUNTRY_CODE_UY, COUNTRY_CODE_VN |
| }; |
| |
| static const UINT_16 g_u2CountryGroup3[] = { |
| COUNTRY_CODE_AW, COUNTRY_CODE_LA, COUNTRY_CODE_SA, COUNTRY_CODE_AE, |
| COUNTRY_CODE_UG |
| }; |
| |
| static const UINT_16 g_u2CountryGroup4[] = { COUNTRY_CODE_MM }; |
| |
| static const UINT_16 g_u2CountryGroup5[] = { |
| COUNTRY_CODE_AL, COUNTRY_CODE_DZ, COUNTRY_CODE_AD, COUNTRY_CODE_AT, |
| COUNTRY_CODE_BY, COUNTRY_CODE_BE, COUNTRY_CODE_BA, COUNTRY_CODE_VG, |
| COUNTRY_CODE_BG, COUNTRY_CODE_CV, COUNTRY_CODE_HR, COUNTRY_CODE_CY, |
| COUNTRY_CODE_CZ, COUNTRY_CODE_DK, COUNTRY_CODE_EE, COUNTRY_CODE_ET, |
| COUNTRY_CODE_FI, COUNTRY_CODE_FR, COUNTRY_CODE_GF, COUNTRY_CODE_PF, |
| COUNTRY_CODE_TF, COUNTRY_CODE_GE, COUNTRY_CODE_DE, COUNTRY_CODE_GH, |
| COUNTRY_CODE_GR, COUNTRY_CODE_GP, COUNTRY_CODE_HU, COUNTRY_CODE_IS, |
| COUNTRY_CODE_IQ, COUNTRY_CODE_IE, COUNTRY_CODE_IT, COUNTRY_CODE_KE, |
| COUNTRY_CODE_LV, COUNTRY_CODE_LS, COUNTRY_CODE_LI, COUNTRY_CODE_LT, |
| COUNTRY_CODE_LU, COUNTRY_CODE_MK, COUNTRY_CODE_MT, COUNTRY_CODE_MQ, |
| COUNTRY_CODE_MR, COUNTRY_CODE_MU, COUNTRY_CODE_YT, COUNTRY_CODE_MD, |
| COUNTRY_CODE_MC, COUNTRY_CODE_ME, COUNTRY_CODE_MS, COUNTRY_CODE_NL, |
| COUNTRY_CODE_NO, COUNTRY_CODE_OM, COUNTRY_CODE_PL, COUNTRY_CODE_PT, |
| COUNTRY_CODE_RE, COUNTRY_CODE_RO, COUNTRY_CODE_MF, COUNTRY_CODE_SM, |
| COUNTRY_CODE_SN, COUNTRY_CODE_RS, COUNTRY_CODE_SK, COUNTRY_CODE_SI, |
| COUNTRY_CODE_ZA, COUNTRY_CODE_ES, COUNTRY_CODE_SE, COUNTRY_CODE_CH, |
| COUNTRY_CODE_TR, COUNTRY_CODE_TC, COUNTRY_CODE_GB, COUNTRY_CODE_VA, |
| COUNTRY_CODE_EU |
| }; |
| static const UINT_16 g_u2CountryGroup6[] = { COUNTRY_CODE_JP }; |
| |
| static const UINT_16 g_u2CountryGroup7[] = { |
| COUNTRY_CODE_AM, COUNTRY_CODE_IL, COUNTRY_CODE_KW, COUNTRY_CODE_MA, |
| COUNTRY_CODE_NE, COUNTRY_CODE_TN, |
| }; |
| static const UINT_16 g_u2CountryGroup8[] = { COUNTRY_CODE_NP }; |
| static const UINT_16 g_u2CountryGroup9[] = { COUNTRY_CODE_AF }; |
| |
| static const UINT_16 g_u2CountryGroup10[] = { |
| COUNTRY_CODE_AG, COUNTRY_CODE_BS, COUNTRY_CODE_BH, COUNTRY_CODE_BB, |
| COUNTRY_CODE_BN, COUNTRY_CODE_CL, COUNTRY_CODE_CN, COUNTRY_CODE_EG, |
| COUNTRY_CODE_SV, COUNTRY_CODE_IN, COUNTRY_CODE_MY, COUNTRY_CODE_MV, |
| COUNTRY_CODE_PA, COUNTRY_CODE_VE, COUNTRY_CODE_ZM, |
| |
| }; |
| static const UINT_16 g_u2CountryGroup11[] = { COUNTRY_CODE_JO, COUNTRY_CODE_PG }; |
| |
| static const UINT_16 g_u2CountryGroup12[] = { |
| COUNTRY_CODE_BF, COUNTRY_CODE_GY, COUNTRY_CODE_HT, COUNTRY_CODE_HN, |
| COUNTRY_CODE_JM, COUNTRY_CODE_MO, COUNTRY_CODE_MW, COUNTRY_CODE_PK, |
| COUNTRY_CODE_QA, COUNTRY_CODE_RW, COUNTRY_CODE_KN, COUNTRY_CODE_TZ, |
| |
| }; |
| static const UINT_16 g_u2CountryGroup13[] = { COUNTRY_CODE_ID }; |
| static const UINT_16 g_u2CountryGroup14[] = { COUNTRY_CODE_KR }; |
| static const UINT_16 g_u2CountryGroup15[] = { COUNTRY_CODE_NG }; |
| |
| static const UINT_16 g_u2CountryGroup16[] = { |
| COUNTRY_CODE_BD, COUNTRY_CODE_BR, COUNTRY_CODE_DM, COUNTRY_CODE_DO, |
| COUNTRY_CODE_FK, COUNTRY_CODE_KZ, COUNTRY_CODE_MX, COUNTRY_CODE_MZ, |
| COUNTRY_CODE_NA, COUNTRY_CODE_RU, COUNTRY_CODE_LC, COUNTRY_CODE_VC, |
| COUNTRY_CODE_UA, COUNTRY_CODE_UZ, COUNTRY_CODE_ZW |
| }; |
| static const UINT_16 g_u2CountryGroup17[] = { COUNTRY_CODE_MP }; |
| static const UINT_16 g_u2CountryGroup18[] = { COUNTRY_CODE_TW }; |
| |
| static const UINT_16 g_u2CountryGroup19[] = { |
| COUNTRY_CODE_CK, COUNTRY_CODE_CU, COUNTRY_CODE_TL, COUNTRY_CODE_FO, |
| COUNTRY_CODE_GI, COUNTRY_CODE_GG, COUNTRY_CODE_IR, COUNTRY_CODE_IM, |
| COUNTRY_CODE_JE, COUNTRY_CODE_KP, COUNTRY_CODE_MH, COUNTRY_CODE_NU, |
| COUNTRY_CODE_NF, COUNTRY_CODE_PS, COUNTRY_CODE_PN, COUNTRY_CODE_PM, |
| COUNTRY_CODE_SS, COUNTRY_CODE_SD, COUNTRY_CODE_SY |
| }; |
| |
| static const UINT_16 g_u2CountryGroup20[] = { |
| COUNTRY_CODE_DF |
| /* When country code is not found, this domain info will be used. |
| * So mark all country codes to reduce search time. 20110908 |
| */ |
| }; |
| |
| #if (CFG_SUPPORT_SINGLE_SKU == 1) |
| mtk_regd_control g_mtk_regd_control = { |
| .en = FALSE, |
| .state = REGD_STATE_UNDEFINED |
| }; |
| |
| #if (CFG_SUPPORT_SINGLE_SKU_LOCAL_DB == 1) |
| const struct ieee80211_regdomain default_regdom_ww = { |
| .n_reg_rules = 4, |
| .alpha2 = "99", |
| .reg_rules = { |
| /* channels 1..13 */ |
| REG_RULE_LIGHT(2412-10, 2472+10, 40, 0), |
| /* channels 14 */ |
| REG_RULE_LIGHT(2484-10, 2484+10, 20, 0), |
| /* channel 36..64 */ |
| REG_RULE_LIGHT(5150-10, 5350+10, 80, 0), |
| /* channel 100..165 */ |
| REG_RULE_LIGHT(5470-10, 5850+10, 80, 0), |
| } |
| }; |
| #endif |
| |
| const char *gTx_Pwr_Limit_Section[TX_PWR_LIMIT_SECTION_NUM] = { |
| "legacy", "ht20", "ht40", "vht20", "offset" |
| }; |
| |
| const u8 gTx_Pwr_Limit_Element_Num[TX_PWR_LIMIT_SECTION_NUM] = { |
| 7, 6, 7, 7, 5 |
| }; |
| |
| const char *gTx_Pwr_Limit_Element[TX_PWR_LIMIT_SECTION_NUM][TX_PWR_LIMIT_ELEMENT_NUM] = { |
| {"cck1_2", "cck_5_11", "ofdm6_9", "ofdm12_18", "ofdm24_36", "ofdm48", "ofdm54"}, |
| {"mcs0_8", "mcs1_2_9_10", "mcs3_4_11_12", "mcs5_13", "mcs6_14", "mcs7_15"}, |
| {"mcs0_8", "mcs1_2_9_10", "mcs3_4_11_12", "mcs5_13", "mcs6_14", "mcs7_15", "mcs32"}, |
| {"mcs0", "mcs1_2", "mcs3_4", "mcs5_6", "mcs7", "mcs8", "mcs9"}, |
| {"lg40", "lg80", "vht40", "vht80", "vht160nc"} |
| }; |
| |
| static const INT_8 gTx_Pwr_Limit_2g_Ch[] = { |
| 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14}; |
| static const INT_8 gTx_Pwr_Limit_5g_Ch[] = { |
| 36, 38, 40, 42, 44, 46, 48, 50, 52, 54, 56, 58, 60, 62, 64, 100, 102, |
| 104, 106, 108, 110, 112, 114, 116, 118, 120, 122, 124, 126, 128, 132, |
| 134, 136, 138, 140, 142, 144, 149, 151, 153, 155, 157, 159, 161, 165}; |
| |
| #define TX_PWR_LIMIT_2G_CH_NUM (ARRAY_SIZE(gTx_Pwr_Limit_2g_Ch)) |
| #define TX_PWR_LIMIT_5G_CH_NUM (ARRAY_SIZE(gTx_Pwr_Limit_5g_Ch)) |
| |
| |
| #endif |
| |
| DOMAIN_INFO_ENTRY arSupportedRegDomains[] = { |
| { |
| (PUINT_16) g_u2CountryGroup0, sizeof(g_u2CountryGroup0) / 2, |
| { |
| {81, BAND_2G4, CHNL_SPAN_5, 1, 13, FALSE} |
| , /* CH_SET_2G4_1_13 */ |
| |
| {115, BAND_NULL, 0, 0, 0, FALSE} |
| , /* CH_SET_UNII_LOW_NA */ |
| {118, BAND_NULL, 0, 0, 0, FALSE} |
| , /* CH_SET_UNII_MID_NA */ |
| {121, BAND_NULL, 0, 0, 0, FALSE} |
| , /* CH_SET_UNII_WW_NA */ |
| {125, BAND_NULL, 0, 0, 0, FALSE} |
| , /* CH_SET_UNII_UPPER_NA */ |
| {0, BAND_NULL, 0, 0, 0, FALSE} |
| } |
| } |
| , |
| { |
| (PUINT_16) g_u2CountryGroup1, sizeof(g_u2CountryGroup1) / 2, |
| { |
| {81, BAND_2G4, CHNL_SPAN_5, 1, 11, FALSE} |
| , /* CH_SET_2G4_1_11 */ |
| |
| {115, BAND_5G, CHNL_SPAN_20, 36, 4, FALSE} |
| , /* CH_SET_UNII_LOW_36_48 */ |
| {118, BAND_5G, CHNL_SPAN_20, 52, 4, TRUE} |
| , /* CH_SET_UNII_MID_52_64 */ |
| {121, BAND_5G, CHNL_SPAN_20, 100, 12, TRUE} |
| , /* CH_SET_UNII_WW_100_144 */ |
| {125, BAND_5G, CHNL_SPAN_20, 149, 5, FALSE} |
| , /* CH_SET_UNII_UPPER_149_165 */ |
| {0, BAND_NULL, 0, 0, 0, FALSE} |
| } |
| } |
| , |
| { |
| (PUINT_16) g_u2CountryGroup2, sizeof(g_u2CountryGroup2) / 2, |
| { |
| {81, BAND_2G4, CHNL_SPAN_5, 1, 13, FALSE} |
| , /* CH_SET_2G4_1_13 */ |
| |
| {115, BAND_5G, CHNL_SPAN_20, 36, 4, FALSE} |
| , /* CH_SET_UNII_LOW_36_48 */ |
| {118, BAND_5G, CHNL_SPAN_20, 52, 4, TRUE} |
| , /* CH_SET_UNII_MID_52_64 */ |
| {121, BAND_5G, CHNL_SPAN_20, 100, 12, TRUE} |
| , /* CH_SET_UNII_WW_100_144 */ |
| {125, BAND_5G, CHNL_SPAN_20, 149, 5, FALSE} |
| , /* CH_SET_UNII_UPPER_149_165 */ |
| {0, BAND_NULL, 0, 0, 0, FALSE} |
| } |
| } |
| , |
| { |
| (PUINT_16) g_u2CountryGroup3, sizeof(g_u2CountryGroup3) / 2, |
| { |
| {81, BAND_2G4, CHNL_SPAN_5, 1, 13, FALSE} |
| , /* CH_SET_2G4_1_13 */ |
| |
| {115, BAND_5G, CHNL_SPAN_20, 36, 4, FALSE} |
| , /* CH_SET_UNII_LOW_36_48 */ |
| {118, BAND_5G, CHNL_SPAN_20, 52, 4, TRUE} |
| , /* CH_SET_UNII_MID_52_64 */ |
| {121, BAND_5G, CHNL_SPAN_20, 100, 12, TRUE} |
| , /* CH_SET_UNII_WW_100_144 */ |
| {125, BAND_5G, CHNL_SPAN_20, 149, 4, FALSE} |
| , /* CH_SET_UNII_UPPER_149_161 */ |
| {0, BAND_NULL, 0, 0, 0, FALSE} |
| } |
| } |
| , |
| { |
| (PUINT_16) g_u2CountryGroup4, sizeof(g_u2CountryGroup4) / 2, |
| { |
| {81, BAND_2G4, CHNL_SPAN_5, 1, 13, FALSE} |
| , /* CH_SET_2G4_1_13 */ |
| |
| {115, BAND_5G, CHNL_SPAN_20, 36, 4, FALSE} |
| , /* CH_SET_UNII_LOW_36_48 */ |
| {118, BAND_5G, CHNL_SPAN_20, 52, 4, TRUE} |
| , /* CH_SET_UNII_MID_52_64 */ |
| {121, BAND_5G, CHNL_SPAN_20, 100, 12, TRUE} |
| , /* CH_SET_UNII_WW_100_144 */ |
| {125, BAND_NULL, 0, 0, 0, FALSE} |
| , /* CH_SET_UNII_UPPER_NA */ |
| {0, BAND_NULL, 0, 0, 0, FALSE} |
| } |
| } |
| , |
| { |
| (PUINT_16) g_u2CountryGroup5, sizeof(g_u2CountryGroup5) / 2, |
| { |
| {81, BAND_2G4, CHNL_SPAN_5, 1, 13, FALSE} |
| , /* CH_SET_2G4_1_13 */ |
| |
| {115, BAND_5G, CHNL_SPAN_20, 36, 4, FALSE} |
| , /* CH_SET_UNII_LOW_36_48 */ |
| {118, BAND_5G, CHNL_SPAN_20, 52, 4, TRUE} |
| , /* CH_SET_UNII_MID_52_64 */ |
| {121, BAND_5G, CHNL_SPAN_20, 100, 11, TRUE} |
| , /* CH_SET_UNII_WW_100_140 */ |
| {125, BAND_NULL, 0, 0, 0, FALSE} |
| , /* CH_SET_UNII_UPPER_NA */ |
| {0, BAND_NULL, 0, 0, 0, FALSE} |
| } |
| } |
| , |
| { |
| (PUINT_16) g_u2CountryGroup6, sizeof(g_u2CountryGroup6) / 2, |
| { |
| {81, BAND_2G4, CHNL_SPAN_5, 1, 13, FALSE} |
| , /* CH_SET_2G4_1_13 */ |
| {82, BAND_2G4, CHNL_SPAN_5, 14, 1, FALSE} |
| , /* CH_SET_2G4_14_14 */ |
| {115, BAND_5G, CHNL_SPAN_20, 36, 4, FALSE} |
| , /* CH_SET_UNII_LOW_36_48 */ |
| {118, BAND_5G, CHNL_SPAN_20, 52, 4, TRUE} |
| , /* CH_SET_UNII_MID_52_64 */ |
| {121, BAND_5G, CHNL_SPAN_20, 100, 11, TRUE} |
| , /* CH_SET_UNII_WW_100_140 */ |
| {125, BAND_NULL, 0, 0, 0, FALSE} |
| , /* CH_SET_UNII_UPPER_NA */ |
| } |
| } |
| , |
| { |
| (PUINT_16) g_u2CountryGroup7, sizeof(g_u2CountryGroup7) / 2, |
| { |
| {81, BAND_2G4, CHNL_SPAN_5, 1, 13, FALSE} |
| , /* CH_SET_2G4_1_13 */ |
| |
| {115, BAND_5G, CHNL_SPAN_20, 36, 4, FALSE} |
| , /* CH_SET_UNII_LOW_36_48 */ |
| {118, BAND_5G, CHNL_SPAN_20, 52, 4, TRUE} |
| , /* CH_SET_UNII_MID_52_64 */ |
| {121, BAND_NULL, 0, 0, 0, FALSE} |
| , /* CH_SET_UNII_WW_NA */ |
| {125, BAND_NULL, 0, 0, 0, FALSE} |
| , /* CH_SET_UNII_UPPER_NA */ |
| {0, BAND_NULL, 0, 0, 0, FALSE} |
| } |
| } |
| , |
| { |
| (PUINT_16) g_u2CountryGroup8, sizeof(g_u2CountryGroup8) / 2, |
| { |
| {81, BAND_2G4, CHNL_SPAN_5, 1, 13, FALSE} |
| , /* CH_SET_2G4_1_13 */ |
| |
| {115, BAND_5G, CHNL_SPAN_20, 36, 4, FALSE} |
| , /* CH_SET_UNII_LOW_36_48 */ |
| {118, BAND_5G, CHNL_SPAN_20, 52, 4, TRUE} |
| , /* CH_SET_UNII_MID_52_64 */ |
| {121, BAND_NULL, 0, 0, 0, FALSE} |
| , /* CH_SET_UNII_WW_NA */ |
| {125, BAND_5G, CHNL_SPAN_20, 149, 4, FALSE} |
| , /* CH_SET_UNII_UPPER_149_161 */ |
| {0, BAND_NULL, 0, 0, 0, FALSE} |
| } |
| } |
| , |
| { |
| (PUINT_16) g_u2CountryGroup9, sizeof(g_u2CountryGroup9) / 2, |
| { |
| {81, BAND_2G4, CHNL_SPAN_5, 1, 13, FALSE} |
| , /* CH_SET_2G4_1_13 */ |
| |
| {115, BAND_5G, CHNL_SPAN_20, 36, 4, FALSE} |
| , /* CH_SET_UNII_LOW_36_48 */ |
| {118, BAND_NULL, 0, 0, 0, FALSE} |
| , /* CH_SET_UNII_MID_NA */ |
| {121, BAND_NULL, 0, 0, 0, FALSE} |
| , /* CH_SET_UNII_WW_NA */ |
| {125, BAND_NULL, 0, 0, 0, FALSE} |
| , /* CH_SET_UNII_UPPER_NA */ |
| {0, BAND_NULL, 0, 0, 0, FALSE} |
| } |
| } |
| , |
| { |
| (PUINT_16) g_u2CountryGroup10, sizeof(g_u2CountryGroup10) / 2, |
| { |
| {81, BAND_2G4, CHNL_SPAN_5, 1, 13, FALSE} |
| , /* CH_SET_2G4_1_13 */ |
| |
| {115, BAND_5G, CHNL_SPAN_20, 36, 4, FALSE} |
| , /* CH_SET_UNII_LOW_36_48 */ |
| {118, BAND_5G, CHNL_SPAN_20, 52, 4, TRUE} |
| , /* CH_SET_UNII_MID_52_64 */ |
| {121, BAND_NULL, 0, 0, 0, FALSE} |
| , /* CH_SET_UNII_WW_NA */ |
| {125, BAND_5G, CHNL_SPAN_20, 149, 5, FALSE} |
| , /* CH_SET_UNII_UPPER_149_165 */ |
| {0, BAND_NULL, 0, 0, 0, FALSE} |
| } |
| } |
| , |
| { |
| (PUINT_16) g_u2CountryGroup11, sizeof(g_u2CountryGroup11) / 2, |
| { |
| {81, BAND_2G4, CHNL_SPAN_5, 1, 13, FALSE} |
| , /* CH_SET_2G4_1_13 */ |
| |
| {115, BAND_5G, CHNL_SPAN_20, 36, 4, FALSE} |
| , /* CH_SET_UNII_LOW_36_48 */ |
| {118, BAND_NULL, 0, 0, 0, FALSE} |
| , /* CH_SET_UNII_MID_NA */ |
| {121, BAND_NULL, 0, 0, 0, FALSE} |
| , /* CH_SET_UNII_WW_NA */ |
| {125, BAND_5G, CHNL_SPAN_20, 149, 5, FALSE} |
| , /* CH_SET_UNII_UPPER_149_165 */ |
| {0, BAND_NULL, 0, 0, 0, FALSE} |
| } |
| } |
| , |
| { |
| (PUINT_16) g_u2CountryGroup12, sizeof(g_u2CountryGroup12) / 2, |
| { |
| {81, BAND_2G4, CHNL_SPAN_5, 1, 13, FALSE} |
| , /* CH_SET_2G4_1_13 */ |
| |
| {115, BAND_NULL, 0, 0, 0, FALSE} |
| , /* CH_SET_UNII_LOW_NA */ |
| {118, BAND_NULL, 0, 0, 0, FALSE} |
| , /* CH_SET_UNII_MID_NA */ |
| {121, BAND_NULL, 0, 0, 0, FALSE} |
| , /* CH_SET_UNII_WW_NA */ |
| {125, BAND_5G, CHNL_SPAN_20, 149, 5, FALSE} |
| , /* CH_SET_UNII_UPPER_149_165 */ |
| {0, BAND_NULL, 0, 0, 0, FALSE} |
| } |
| } |
| , |
| { |
| (PUINT_16) g_u2CountryGroup13, sizeof(g_u2CountryGroup13) / 2, |
| { |
| {81, BAND_2G4, CHNL_SPAN_5, 1, 13, FALSE} |
| , /* CH_SET_2G4_1_13 */ |
| |
| {115, BAND_NULL, 0, 0, 0, FALSE} |
| , /* CH_SET_UNII_LOW_NA */ |
| {118, BAND_NULL, 0, 0, 0, FALSE} |
| , /* CH_SET_UNII_MID_NA */ |
| {121, BAND_NULL, 0, 0, 0, FALSE} |
| , /* CH_SET_UNII_WW_NA */ |
| {125, BAND_5G, CHNL_SPAN_20, 149, 4, FALSE} |
| , /* CH_SET_UNII_UPPER_149_161 */ |
| {0, BAND_NULL, 0, 0, 0, FALSE} |
| } |
| } |
| , |
| { |
| (PUINT_16) g_u2CountryGroup14, sizeof(g_u2CountryGroup14) / 2, |
| { |
| {81, BAND_2G4, CHNL_SPAN_5, 1, 13, FALSE} |
| , /* CH_SET_2G4_1_13 */ |
| |
| {115, BAND_5G, CHNL_SPAN_20, 36, 4, FALSE} |
| , /* CH_SET_UNII_LOW_36_48 */ |
| {118, BAND_5G, CHNL_SPAN_20, 52, 4, FALSE} |
| , /* CH_SET_UNII_MID_52_64 */ |
| {121, BAND_5G, CHNL_SPAN_20, 100, 8, FALSE} |
| , /* CH_SET_UNII_WW_100_128 */ |
| {125, BAND_5G, CHNL_SPAN_20, 149, 4, FALSE} |
| , /* CH_SET_UNII_UPPER_149_161 */ |
| {0, BAND_NULL, 0, 0, 0, FALSE} |
| } |
| } |
| , |
| { |
| (PUINT_16) g_u2CountryGroup15, sizeof(g_u2CountryGroup15) / 2, |
| { |
| {81, BAND_2G4, CHNL_SPAN_5, 1, 13, FALSE} |
| , /* CH_SET_2G4_1_13 */ |
| |
| {115, BAND_NULL, 0, 0, 0, FALSE} |
| , /* CH_SET_UNII_LOW_36_48 */ |
| {118, BAND_5G, CHNL_SPAN_20, 52, 4, TRUE} |
| , /* CH_SET_UNII_MID_52_64 */ |
| {121, BAND_5G, CHNL_SPAN_20, 100, 11, TRUE} |
| , /* CH_SET_UNII_WW_100_140 */ |
| {125, BAND_5G, CHNL_SPAN_20, 149, 5, FALSE} |
| , /* CH_SET_UNII_UPPER_149_165 */ |
| {0, BAND_NULL, 0, 0, 0, FALSE} |
| } |
| } |
| , |
| { |
| (PUINT_16) g_u2CountryGroup16, sizeof(g_u2CountryGroup16) / 2, |
| { |
| {81, BAND_2G4, CHNL_SPAN_5, 1, 13, FALSE} |
| , /* CH_SET_2G4_1_13 */ |
| |
| {115, BAND_5G, CHNL_SPAN_20, 36, 4, FALSE} |
| , /* CH_SET_UNII_LOW_36_48 */ |
| {118, BAND_5G, CHNL_SPAN_20, 52, 4, FALSE} |
| , /* CH_SET_UNII_MID_52_64 */ |
| {121, BAND_5G, CHNL_SPAN_20, 100, 11, TRUE} |
| , /* CH_SET_UNII_WW_100_140 */ |
| {125, BAND_5G, CHNL_SPAN_20, 149, 5, FALSE} |
| , /* CH_SET_UNII_UPPER_149_165 */ |
| {0, BAND_NULL, 0, 0, 0, FALSE} |
| } |
| } |
| , |
| { |
| (PUINT_16) g_u2CountryGroup17, sizeof(g_u2CountryGroup17) / 2, |
| { |
| {81, BAND_2G4, CHNL_SPAN_5, 1, 11, FALSE} |
| , /* CH_SET_2G4_1_11 */ |
| |
| {115, BAND_5G, CHNL_SPAN_20, 36, 4, FALSE} |
| , /* CH_SET_UNII_LOW_36_48 */ |
| {118, BAND_5G, CHNL_SPAN_20, 52, 4, TRUE} |
| , /* CH_SET_UNII_MID_52_64 */ |
| {121, BAND_5G, CHNL_SPAN_20, 100, 11, TRUE} |
| , /* CH_SET_UNII_WW_100_140 */ |
| {125, BAND_5G, CHNL_SPAN_20, 149, 5, FALSE} |
| , /* CH_SET_UNII_UPPER_149_165 */ |
| {0, BAND_NULL, 0, 0, 0, FALSE} |
| } |
| } |
| , |
| { |
| (PUINT_16) g_u2CountryGroup18, sizeof(g_u2CountryGroup18) / 2, |
| { |
| {81, BAND_2G4, CHNL_SPAN_5, 1, 11, FALSE} |
| , /* CH_SET_2G4_1_11 */ |
| |
| {115, BAND_5G, CHNL_SPAN_20, 36, 4, FALSE} |
| , /* CH_SET_UNII_LOW_36_48 */ |
| {118, BAND_5G, CHNL_SPAN_20, 52, 4, FALSE} |
| , /* CH_SET_UNII_MID_52_64 */ |
| {121, BAND_5G, CHNL_SPAN_20, 100, 11, FALSE} |
| , /* CH_SET_UNII_WW_100_140 */ |
| {125, BAND_5G, CHNL_SPAN_20, 149, 5, FALSE} |
| , /* CH_SET_UNII_UPPER_149_165 */ |
| {0, BAND_NULL, 0, 0, 0, FALSE} |
| } |
| } |
| , |
| { |
| (PUINT_16) g_u2CountryGroup19, sizeof(g_u2CountryGroup19) / 2, |
| { |
| {81, BAND_2G4, CHNL_SPAN_5, 1, 13, FALSE} |
| , /* CH_SET_2G4_1_13 */ |
| |
| {115, BAND_5G, CHNL_SPAN_20, 36, 4, FALSE} |
| , /* CH_SET_UNII_LOW_36_48 */ |
| {118, BAND_5G, CHNL_SPAN_20, 52, 4, TRUE} |
| , /* CH_SET_UNII_MID_52_64 */ |
| {121, BAND_5G, CHNL_SPAN_20, 100, 12, TRUE} |
| , /* CH_SET_UNII_WW_100_144 */ |
| {125, BAND_5G, CHNL_SPAN_20, 149, 5, FALSE} |
| , /* CH_SET_UNII_UPPER_149_165 */ |
| {0, BAND_NULL, 0, 0, 0, FALSE} |
| } |
| } |
| , |
| { |
| /* Note: The final one is for Europe union now.(Default group if no matched country code) */ |
| (PUINT_16) g_u2CountryGroup20, sizeof(g_u2CountryGroup20) / 2, |
| { |
| {81, BAND_2G4, CHNL_SPAN_5, 1, 13, FALSE} |
| , /* CH_SET_2G4_1_13 */ |
| |
| {115, BAND_5G, CHNL_SPAN_20, 36, 4, FALSE} |
| , /* CH_SET_UNII_LOW_36_48 */ |
| {118, BAND_5G, CHNL_SPAN_20, 52, 4, TRUE} |
| , /* CH_SET_UNII_MID_52_64 */ |
| {121, BAND_5G, CHNL_SPAN_20, 100, 12, TRUE} |
| , /* CH_SET_UNII_WW_100_144 */ |
| {125, BAND_5G, CHNL_SPAN_20, 149, 7, FALSE} |
| , /* CH_SET_UNII_UPPER_149_173 */ |
| {0, BAND_NULL, 0, 0, 0, FALSE} |
| } |
| } |
| }; |
| |
| #define REG_DOMAIN_PASSIVE_DEF_IDX 1 |
| |
| static const UINT_16 g_u2CountryGroup0_Passive[] = { |
| COUNTRY_CODE_TW |
| }; |
| |
| DOMAIN_INFO_ENTRY arSupportedRegDomains_Passive[] = { |
| { |
| (PUINT_16) g_u2CountryGroup0_Passive, sizeof(g_u2CountryGroup0_Passive) / 2, |
| { |
| {81, BAND_2G4, CHNL_SPAN_5, 1, 0, 0} |
| , /* CH_SET_2G4_1_14_NA */ |
| {82, BAND_2G4, CHNL_SPAN_5, 14, 0, 0} |
| , |
| |
| {115, BAND_5G, CHNL_SPAN_20, 36, 4, 0} |
| , /* CH_SET_UNII_LOW_36_48 */ |
| {118, BAND_5G, CHNL_SPAN_20, 52, 4, 0} |
| , /* CH_SET_UNII_MID_52_64 */ |
| {121, BAND_5G, CHNL_SPAN_20, 100, 11, 0} |
| , /* CH_SET_UNII_WW_100_140 */ |
| {125, BAND_5G, CHNL_SPAN_20, 149, 0, 0} |
| , /* CH_SET_UNII_UPPER_NA */ |
| } |
| } |
| , |
| |
| { |
| /* default passive channel table is empty */ |
| COUNTRY_CODE_NULL, 0, |
| { |
| {81, BAND_2G4, CHNL_SPAN_5, 1, 0, 0} |
| , /* CH_SET_2G4_1_14_NA */ |
| {82, BAND_2G4, CHNL_SPAN_5, 14, 0, 0} |
| , |
| |
| {115, BAND_5G, CHNL_SPAN_20, 36, 0, 0} |
| , /* CH_SET_UNII_LOW_NA */ |
| {118, BAND_5G, CHNL_SPAN_20, 52, 4, 0} |
| , /* CH_SET_UNII_MID_52_64 */ |
| {121, BAND_5G, CHNL_SPAN_20, 100, 12, 0} |
| , /* CH_SET_UNII_WW_100_144 */ |
| {125, BAND_5G, CHNL_SPAN_20, 149, 0, 0} |
| , /* CH_SET_UNII_UPPER_NA */ |
| } |
| } |
| |
| }; |
| |
| #define REG_DOMAIN_PASSIVE_GROUP_NUM \ |
| (sizeof(arSupportedRegDomains_Passive) / sizeof(DOMAIN_INFO_ENTRY)) |
| |
| |
| SUBBAND_CHANNEL_T g_rRlmSubBand[] = { |
| |
| {BAND_2G4_LOWER_BOUND, BAND_2G4_UPPER_BOUND, 1, 0} |
| , /* 2.4G */ |
| {UNII1_LOWER_BOUND, UNII1_UPPER_BOUND, 2, 0} |
| , /* ch36,38,40,..,48 */ |
| {UNII2A_LOWER_BOUND, UNII2A_UPPER_BOUND, 2, 0} |
| , /* ch52,54,56,..,64 */ |
| {UNII2C_LOWER_BOUND, UNII2C_UPPER_BOUND, 2, 0} |
| , /* ch100,102,104,...,144 */ |
| {UNII3_LOWER_BOUND, UNII3_UPPER_BOUND, 2, 0} /* ch149,151,153,....,173 */ |
| |
| }; |
| |
| /******************************************************************************* |
| * P R I V A T E D A T A |
| ******************************************************************************** |
| */ |
| |
| /******************************************************************************* |
| * M A C R O S |
| ******************************************************************************** |
| */ |
| |
| /******************************************************************************* |
| * F U N C T I O N D E C L A R A T I O N S |
| ******************************************************************************** |
| */ |
| |
| /******************************************************************************* |
| * F U N C T I O N S |
| ******************************************************************************** |
| */ |
| |
| /*----------------------------------------------------------------------------*/ |
| /*! |
| * \brief |
| * |
| * \param[in/out] |
| * |
| * \return none |
| */ |
| /*----------------------------------------------------------------------------*/ |
| P_DOMAIN_INFO_ENTRY rlmDomainGetDomainInfo(P_ADAPTER_T prAdapter) |
| { |
| #define REG_DOMAIN_DEF_IDX 20 /* EU (Europe Union) */ |
| #define REG_DOMAIN_GROUP_NUM \ |
| (sizeof(arSupportedRegDomains) / sizeof(DOMAIN_INFO_ENTRY)) |
| |
| P_DOMAIN_INFO_ENTRY prDomainInfo; |
| P_REG_INFO_T prRegInfo; |
| UINT_16 u2TargetCountryCode; |
| UINT_16 i, j; |
| |
| ASSERT(prAdapter); |
| |
| if (prAdapter->prDomainInfo) |
| return prAdapter->prDomainInfo; |
| |
| prRegInfo = &prAdapter->prGlueInfo->rRegInfo; |
| |
| DBGLOG(RLM, TRACE, "eRegChannelListMap=%d, u2CountryCode=0x%04x\n", |
| prRegInfo->eRegChannelListMap, |
| prAdapter->rWifiVar.rConnSettings.u2CountryCode); |
| |
| /* |
| * Domain info can be specified by given idx of arSupportedRegDomains table, |
| * customized, or searched by country code, |
| * only one is set among these three methods in NVRAM. |
| */ |
| if (prRegInfo->eRegChannelListMap == REG_CH_MAP_TBL_IDX && |
| prRegInfo->ucRegChannelListIndex < REG_DOMAIN_GROUP_NUM) { |
| /* by given table idx */ |
| DBGLOG(RLM, TRACE, "ucRegChannelListIndex=%d\n", prRegInfo->ucRegChannelListIndex); |
| prDomainInfo = &arSupportedRegDomains[prRegInfo->ucRegChannelListIndex]; |
| } else if (prRegInfo->eRegChannelListMap == REG_CH_MAP_CUSTOMIZED) { |
| /* by customized */ |
| prDomainInfo = &prRegInfo->rDomainInfo; |
| } else { |
| /* by country code */ |
| u2TargetCountryCode = prAdapter->rWifiVar.rConnSettings.u2CountryCode; |
| |
| for (i = 0; i < REG_DOMAIN_GROUP_NUM; i++) { |
| prDomainInfo = &arSupportedRegDomains[i]; |
| |
| if ((prDomainInfo->u4CountryNum && prDomainInfo->pu2CountryGroup) || |
| prDomainInfo->u4CountryNum == 0) { |
| for (j = 0; j < prDomainInfo->u4CountryNum; j++) { |
| if (prDomainInfo->pu2CountryGroup[j] == u2TargetCountryCode) |
| break; |
| } |
| if (j < prDomainInfo->u4CountryNum) |
| break; /* Found */ |
| } |
| } |
| |
| /* If no matched country code, use the default regulatory domain */ |
| if (i >= REG_DOMAIN_GROUP_NUM) { |
| DBGLOG(RLM, INFO, "No matched country code, use the default regulatory domain\n"); |
| prDomainInfo = &arSupportedRegDomains[REG_DOMAIN_DEF_IDX]; |
| } |
| } |
| |
| prAdapter->prDomainInfo = prDomainInfo; |
| return prDomainInfo; |
| } |
| |
| /*----------------------------------------------------------------------------*/ |
| /*! |
| * \brief |
| * |
| * \param[in/out] The input variable pointed by pucNumOfChannel is the max |
| * arrary size. The return value indciates meaning list size. |
| * |
| * \return none |
| */ |
| /*----------------------------------------------------------------------------*/ |
| VOID |
| rlmDomainGetChnlList_V2(P_ADAPTER_T prAdapter, |
| ENUM_BAND_T eSpecificBand, BOOLEAN fgNoDfs, |
| UINT_8 ucMaxChannelNum, PUINT_8 pucNumOfChannel, P_RF_CHANNEL_INFO_T paucChannelList) |
| { |
| #if (CFG_SUPPORT_SINGLE_SKU == 1) |
| ENUM_BAND_T band; |
| UINT_8 max_count, i, ucNum; |
| struct channel *prCh; |
| |
| if (eSpecificBand == BAND_2G4) { |
| i = 0; |
| max_count = rlmDomainGetActiveChannelCount(KAL_BAND_2GHZ); |
| } else if (eSpecificBand == BAND_5G) { |
| i = rlmDomainGetActiveChannelCount(KAL_BAND_2GHZ); |
| max_count = rlmDomainGetActiveChannelCount(KAL_BAND_5GHZ) + |
| rlmDomainGetActiveChannelCount(KAL_BAND_2GHZ); |
| } else { |
| i = 0; |
| max_count = rlmDomainGetActiveChannelCount(KAL_BAND_5GHZ) + |
| rlmDomainGetActiveChannelCount(KAL_BAND_2GHZ); |
| } |
| |
| ucNum = 0; |
| for (; i < max_count; i++) { |
| prCh = rlmDomainGetActiveChannels() + i; |
| if (fgNoDfs && (prCh->flags & IEEE80211_CHAN_RADAR)) |
| continue; /*not match*/ |
| |
| if (i < rlmDomainGetActiveChannelCount(KAL_BAND_2GHZ)) |
| band = BAND_2G4; |
| else |
| band = BAND_5G; |
| |
| paucChannelList[ucNum].eBand = band; |
| paucChannelList[ucNum].ucChannelNum = prCh->chNum; |
| |
| ucNum++; |
| if (ucMaxChannelNum == ucNum) |
| break; |
| } |
| |
| *pucNumOfChannel = ucNum; |
| #else |
| *pucNumOfChannel = 0; |
| #endif |
| } |
| |
| |
| VOID |
| rlmDomainGetChnlList(P_ADAPTER_T prAdapter, |
| ENUM_BAND_T eSpecificBand, BOOLEAN fgNoDfs, |
| UINT_8 ucMaxChannelNum, PUINT_8 pucNumOfChannel, P_RF_CHANNEL_INFO_T paucChannelList) |
| { |
| UINT_8 i, j, ucNum; |
| P_DOMAIN_SUBBAND_INFO prSubband; |
| P_DOMAIN_INFO_ENTRY prDomainInfo; |
| |
| ASSERT(prAdapter); |
| ASSERT(paucChannelList); |
| ASSERT(pucNumOfChannel); |
| |
| if (regd_is_single_sku_en()) |
| return rlmDomainGetChnlList_V2(prAdapter, eSpecificBand, |
| fgNoDfs, ucMaxChannelNum, |
| pucNumOfChannel, paucChannelList); |
| |
| /* If no matched country code, the final one will be used */ |
| prDomainInfo = rlmDomainGetDomainInfo(prAdapter); |
| ASSERT(prDomainInfo); |
| |
| ucNum = 0; |
| for (i = 0; i < MAX_SUBBAND_NUM; i++) { |
| prSubband = &prDomainInfo->rSubBand[i]; |
| |
| if (prSubband->ucBand == BAND_NULL || prSubband->ucBand >= BAND_NUM || |
| (prSubband->ucBand == BAND_5G && !prAdapter->fgEnable5GBand)) |
| continue; |
| |
| /*repoert to upper layer only non-DFS channel for ap mode usage*/ |
| if (fgNoDfs == TRUE && prSubband->fgDfs == TRUE) |
| continue; |
| |
| if (eSpecificBand == BAND_NULL || prSubband->ucBand == eSpecificBand) { |
| for (j = 0; j < prSubband->ucNumChannels; j++) { |
| if (ucNum >= ucMaxChannelNum) |
| break; |
| paucChannelList[ucNum].eBand = prSubband->ucBand; |
| paucChannelList[ucNum].ucChannelNum = |
| prSubband->ucFirstChannelNum + j * prSubband->ucChannelSpan; |
| ucNum++; |
| } |
| } |
| } |
| |
| *pucNumOfChannel = ucNum; |
| } |
| |
| /*----------------------------------------------------------------------------*/ |
| /*! |
| * @brief |
| * |
| * @param[in] |
| * |
| * @return (none) |
| */ |
| /*----------------------------------------------------------------------------*/ |
| VOID rlmDomainSendCmd(P_ADAPTER_T prAdapter, BOOLEAN fgIsOid) |
| { |
| if (!regd_is_single_sku_en()) |
| rlmDomainSendPassiveScanInfoCmd(prAdapter, fgIsOid); |
| rlmDomainSendDomainInfoCmd(prAdapter, fgIsOid); |
| #if CFG_SUPPORT_PWR_LIMIT_COUNTRY |
| rlmDomainSendPwrLimitCmd(prAdapter); |
| #endif |
| |
| |
| } |
| |
| |
| VOID rlmDomainSendDomainInfoCmd_V2(P_ADAPTER_T prAdapter, BOOLEAN fgIsOid) |
| { |
| #if (CFG_SUPPORT_SINGLE_SKU == 1) |
| u8 max_channel_count = 0; |
| u32 buff_max_size, buff_valid_size; |
| P_CMD_SET_DOMAIN_INFO_V2_T prCmd; |
| struct acctive_channel_list *prChs; |
| struct wiphy *pWiphy; |
| |
| |
| pWiphy = priv_to_wiphy(prAdapter->prGlueInfo); |
| if (pWiphy->bands[KAL_BAND_2GHZ] != NULL) |
| max_channel_count += pWiphy->bands[KAL_BAND_2GHZ]->n_channels; |
| if (pWiphy->bands[KAL_BAND_5GHZ] != NULL) |
| max_channel_count += pWiphy->bands[KAL_BAND_5GHZ]->n_channels; |
| |
| if (max_channel_count == 0) { |
| DBGLOG(RLM, ERROR, "%s, invalid channel count.\n", __func__); |
| ASSERT(0); |
| } |
| |
| |
| buff_max_size = sizeof(CMD_SET_DOMAIN_INFO_V2_T) + |
| max_channel_count * sizeof(struct channel); |
| |
| prCmd = cnmMemAlloc(prAdapter, RAM_TYPE_BUF, buff_max_size); |
| prChs = &(prCmd->active_chs); |
| |
| |
| |
| /* |
| * Fill in the active channels |
| */ |
| rlmExtractChannelInfo(max_channel_count, prChs); |
| |
| prCmd->u4CountryCode = rlmDomainGetCountryCode(); |
| prCmd->uc2G4Bandwidth = prAdapter->rWifiVar.rConnSettings.uc2G4BandwidthMode; |
| prCmd->uc5GBandwidth = prAdapter->rWifiVar.rConnSettings.uc5GBandwidthMode; |
| prCmd->aucReserved[0] = 0; |
| prCmd->aucReserved[1] = 0; |
| |
| buff_valid_size = sizeof(CMD_SET_DOMAIN_INFO_V2_T) + |
| (prChs->n_channels_2g + prChs->n_channels_5g) * |
| sizeof(struct channel); |
| |
| DBGLOG(RLM, INFO, "rlmDomainSendDomainInfoCmd_V2(), buff_valid_size = 0x%x\n", buff_valid_size); |
| |
| |
| /* Set domain info to chip */ |
| wlanSendSetQueryCmd(prAdapter, /* prAdapter */ |
| CMD_ID_SET_DOMAIN_INFO, /* ucCID */ |
| TRUE, /* fgSetQuery */ |
| FALSE, /* fgNeedResp */ |
| fgIsOid, /* fgIsOid */ |
| NULL, /* pfCmdDoneHandler */ |
| NULL, /* pfCmdTimeoutHandler */ |
| buff_valid_size, |
| (PUINT_8) prCmd, /* pucInfoBuffer */ |
| NULL, /* pvSetQueryBuffer */ |
| 0 /* u4SetQueryBufferLen */ |
| ); |
| |
| cnmMemFree(prAdapter, prCmd); |
| #endif |
| } |
| |
| |
| VOID rlmDomainSendDomainInfoCmd(P_ADAPTER_T prAdapter, BOOLEAN fgIsOid) |
| { |
| P_DOMAIN_INFO_ENTRY prDomainInfo; |
| P_CMD_SET_DOMAIN_INFO_T prCmd; |
| P_DOMAIN_SUBBAND_INFO prSubBand; |
| UINT_8 i; |
| |
| if (regd_is_single_sku_en()) |
| return rlmDomainSendDomainInfoCmd_V2(prAdapter, fgIsOid); |
| |
| |
| prDomainInfo = rlmDomainGetDomainInfo(prAdapter); |
| ASSERT(prDomainInfo); |
| |
| prCmd = cnmMemAlloc(prAdapter, RAM_TYPE_BUF, sizeof(CMD_SET_DOMAIN_INFO_T)); |
| if (!prCmd) { |
| DBGLOG(RLM, ERROR, "Alloc cmd buffer failed\n"); |
| return; |
| } |
| kalMemZero(prCmd, sizeof(CMD_SET_DOMAIN_INFO_T)); |
| |
| prCmd->u2CountryCode = prAdapter->rWifiVar.rConnSettings.u2CountryCode; |
| prCmd->u2IsSetPassiveScan = 0; |
| prCmd->uc2G4Bandwidth = prAdapter->rWifiVar.rConnSettings.uc2G4BandwidthMode; |
| prCmd->uc5GBandwidth = prAdapter->rWifiVar.rConnSettings.uc5GBandwidthMode; |
| prCmd->aucReserved[0] = 0; |
| prCmd->aucReserved[1] = 0; |
| |
| for (i = 0; i < MAX_SUBBAND_NUM; i++) { |
| prSubBand = &prDomainInfo->rSubBand[i]; |
| |
| prCmd->rSubBand[i].ucRegClass = prSubBand->ucRegClass; |
| prCmd->rSubBand[i].ucBand = prSubBand->ucBand; |
| |
| if (prSubBand->ucBand != BAND_NULL && prSubBand->ucBand < BAND_NUM) { |
| prCmd->rSubBand[i].ucChannelSpan = prSubBand->ucChannelSpan; |
| prCmd->rSubBand[i].ucFirstChannelNum = prSubBand->ucFirstChannelNum; |
| prCmd->rSubBand[i].ucNumChannels = prSubBand->ucNumChannels; |
| } |
| } |
| |
| /* Set domain info to chip */ |
| wlanSendSetQueryCmd(prAdapter, /* prAdapter */ |
| CMD_ID_SET_DOMAIN_INFO, /* ucCID */ |
| TRUE, /* fgSetQuery */ |
| FALSE, /* fgNeedResp */ |
| fgIsOid, /* fgIsOid */ |
| NULL, /* pfCmdDoneHandler */ |
| NULL, /* pfCmdTimeoutHandler */ |
| sizeof(CMD_SET_DOMAIN_INFO_T), /* u4SetQueryInfoLen */ |
| (PUINT_8) prCmd, /* pucInfoBuffer */ |
| NULL, /* pvSetQueryBuffer */ |
| 0 /* u4SetQueryBufferLen */ |
| ); |
| |
| cnmMemFree(prAdapter, prCmd); |
| } |
| |
| /*----------------------------------------------------------------------------*/ |
| /*! |
| * @brief |
| * |
| * @param[in] |
| * |
| * @return (none) |
| */ |
| /*----------------------------------------------------------------------------*/ |
| VOID rlmDomainSendPassiveScanInfoCmd(P_ADAPTER_T prAdapter, BOOLEAN fgIsOid) |
| { |
| P_DOMAIN_INFO_ENTRY prDomainInfo; |
| P_CMD_SET_DOMAIN_INFO_T prCmd; |
| WLAN_STATUS rStatus; |
| P_DOMAIN_SUBBAND_INFO prSubBand; |
| UINT_16 u2TargetCountryCode; |
| UINT_8 i, j; |
| |
| prCmd = cnmMemAlloc(prAdapter, RAM_TYPE_BUF, sizeof(CMD_SET_DOMAIN_INFO_T)); |
| if (!prCmd) { |
| DBGLOG(RLM, ERROR, "Alloc cmd buffer failed\n"); |
| return; |
| } |
| kalMemZero(prCmd, sizeof(CMD_SET_DOMAIN_INFO_T)); |
| |
| prCmd->u2CountryCode = prAdapter->rWifiVar.rConnSettings.u2CountryCode; |
| prCmd->u2IsSetPassiveScan = 1; |
| prCmd->uc2G4Bandwidth = prAdapter->rWifiVar.rConnSettings.uc2G4BandwidthMode; |
| prCmd->uc5GBandwidth = prAdapter->rWifiVar.rConnSettings.uc5GBandwidthMode; |
| prCmd->aucReserved[0] = 0; |
| prCmd->aucReserved[1] = 0; |
| |
| DBGLOG(RLM, TRACE, "u2CountryCode=0x%04x\n", prAdapter->rWifiVar.rConnSettings.u2CountryCode); |
| |
| u2TargetCountryCode = prAdapter->rWifiVar.rConnSettings.u2CountryCode; |
| |
| for (i = 0; i < REG_DOMAIN_PASSIVE_GROUP_NUM; i++) { |
| prDomainInfo = &arSupportedRegDomains_Passive[i]; |
| |
| for (j = 0; j < prDomainInfo->u4CountryNum; j++) { |
| if (prDomainInfo->pu2CountryGroup[j] == u2TargetCountryCode) |
| break; |
| } |
| if (j < prDomainInfo->u4CountryNum) |
| break; /* Found */ |
| } |
| |
| if (i >= REG_DOMAIN_PASSIVE_GROUP_NUM) |
| prDomainInfo = &arSupportedRegDomains_Passive[REG_DOMAIN_PASSIVE_DEF_IDX]; |
| |
| for (i = 0; i < MAX_SUBBAND_NUM; i++) { |
| prSubBand = &prDomainInfo->rSubBand[i]; |
| |
| prCmd->rSubBand[i].ucRegClass = prSubBand->ucRegClass; |
| prCmd->rSubBand[i].ucBand = prSubBand->ucBand; |
| |
| if (prSubBand->ucBand != BAND_NULL && prSubBand->ucBand < BAND_NUM) { |
| prCmd->rSubBand[i].ucChannelSpan = prSubBand->ucChannelSpan; |
| prCmd->rSubBand[i].ucFirstChannelNum = prSubBand->ucFirstChannelNum; |
| prCmd->rSubBand[i].ucNumChannels = prSubBand->ucNumChannels; |
| } |
| } |
| |
| /* Set passive scan channel info to chip */ |
| rStatus = wlanSendSetQueryCmd(prAdapter, /* prAdapter */ |
| CMD_ID_SET_DOMAIN_INFO, /* ucCID */ |
| TRUE, /* fgSetQuery */ |
| FALSE, /* fgNeedResp */ |
| fgIsOid, /* fgIsOid */ |
| NULL, /* pfCmdDoneHandler */ |
| NULL, /* pfCmdTimeoutHandler */ |
| sizeof(CMD_SET_DOMAIN_INFO_T), /* u4SetQueryInfoLen */ |
| (PUINT_8) prCmd, /* pucInfoBuffer */ |
| NULL, /* pvSetQueryBuffer */ |
| 0 /* u4SetQueryBufferLen */ |
| ); |
| |
| ASSERT(rStatus == WLAN_STATUS_PENDING); |
| |
| cnmMemFree(prAdapter, prCmd); |
| } |
| |
| /*----------------------------------------------------------------------------*/ |
| /*! |
| * \brief |
| * |
| * \param[in/out] |
| * |
| * \return TRUE Legal channel |
| * FALSE Illegal channel for current regulatory domain |
| */ |
| /*----------------------------------------------------------------------------*/ |
| BOOLEAN rlmDomainIsLegalChannel_V2(P_ADAPTER_T prAdapter, ENUM_BAND_T eBand, UINT_8 ucChannel) |
| { |
| #if (CFG_SUPPORT_SINGLE_SKU == 1) |
| UINT_8 idx, start_idx, end_idx; |
| struct channel *prCh; |
| |
| if (eBand == BAND_2G4) { |
| start_idx = 0; |
| end_idx = rlmDomainGetActiveChannelCount(KAL_BAND_2GHZ); |
| } else { |
| start_idx = rlmDomainGetActiveChannelCount(KAL_BAND_2GHZ); |
| end_idx = rlmDomainGetActiveChannelCount(KAL_BAND_2GHZ) + |
| rlmDomainGetActiveChannelCount(KAL_BAND_5GHZ); |
| } |
| |
| for (idx = start_idx; idx < end_idx; idx++) { |
| prCh = rlmDomainGetActiveChannels() + idx; |
| |
| if (prCh->chNum == ucChannel) |
| return TRUE; |
| } |
| |
| return FALSE; |
| #else |
| return FALSE; |
| #endif |
| } |
| |
| BOOLEAN rlmDomainIsLegalChannel(P_ADAPTER_T prAdapter, ENUM_BAND_T eBand, UINT_8 ucChannel) |
| { |
| UINT_8 i, j; |
| P_DOMAIN_SUBBAND_INFO prSubband; |
| P_DOMAIN_INFO_ENTRY prDomainInfo; |
| |
| if (regd_is_single_sku_en()) |
| return rlmDomainIsLegalChannel_V2(prAdapter, eBand, ucChannel); |
| |
| |
| prDomainInfo = rlmDomainGetDomainInfo(prAdapter); |
| ASSERT(prDomainInfo); |
| |
| for (i = 0; i < MAX_SUBBAND_NUM; i++) { |
| prSubband = &prDomainInfo->rSubBand[i]; |
| |
| if (prSubband->ucBand == BAND_5G && !prAdapter->fgEnable5GBand) |
| continue; |
| |
| if (prSubband->ucBand == eBand) { |
| for (j = 0; j < prSubband->ucNumChannels; j++) { |
| if ((prSubband->ucFirstChannelNum + j * prSubband->ucChannelSpan) |
| == ucChannel) { |
| return TRUE; |
| } |
| } |
| } |
| } |
| |
| return FALSE; |
| } |
| |
| /*----------------------------------------------------------------------------*/ |
| /*! |
| * \brief |
| * |
| * \param[in/out] |
| * |
| * \return none |
| */ |
| /*----------------------------------------------------------------------------*/ |
| |
| UINT_32 rlmDomainSupOperatingClassIeFill(PUINT_8 pBuf) |
| { |
| /* |
| * The Country element should only be included for Status Code 0 (Successful). |
| */ |
| UINT_32 u4IeLen; |
| UINT_8 aucClass[12] = { 0x01, 0x02, 0x03, 0x05, 0x16, 0x17, 0x19, 0x1b, |
| 0x1c, 0x1e, 0x20, 0x21 |
| }; |
| |
| /* |
| * The Supported Operating Classes element is used by a STA to advertise the |
| * operating classes that it is capable of operating with in this country. |
| * |
| * The Country element (see 8.4.2.10) allows a STA to configure its PHY and MAC |
| * for operation when the operating triplet of Operating Extension Identifier, |
| * Operating Class, and Coverage Class fields is present. |
| */ |
| SUP_OPERATING_CLASS_IE(pBuf)->ucId = ELEM_ID_SUP_OPERATING_CLASS; |
| SUP_OPERATING_CLASS_IE(pBuf)->ucLength = 1 + sizeof(aucClass); |
| SUP_OPERATING_CLASS_IE(pBuf)->ucCur = 0x0c; /* 0x51 */ |
| kalMemCopy(SUP_OPERATING_CLASS_IE(pBuf)->ucSup, aucClass, sizeof(aucClass)); |
| u4IeLen = (SUP_OPERATING_CLASS_IE(pBuf)->ucLength + 2); |
| pBuf += u4IeLen; |
| |
| COUNTRY_IE(pBuf)->ucId = ELEM_ID_COUNTRY_INFO; |
| COUNTRY_IE(pBuf)->ucLength = 6; |
| COUNTRY_IE(pBuf)->aucCountryStr[0] = 0x55; |
| COUNTRY_IE(pBuf)->aucCountryStr[1] = 0x53; |
| COUNTRY_IE(pBuf)->aucCountryStr[2] = 0x20; |
| COUNTRY_IE(pBuf)->arCountryStr[0].ucFirstChnlNum = 1; |
| COUNTRY_IE(pBuf)->arCountryStr[0].ucNumOfChnl = 11; |
| COUNTRY_IE(pBuf)->arCountryStr[0].cMaxTxPwrLv = 0x1e; |
| u4IeLen += (COUNTRY_IE(pBuf)->ucLength + 2); |
| |
| return u4IeLen; |
| } |
| |
| /*----------------------------------------------------------------------------*/ |
| /*! |
| * @brief |
| * |
| * @param[in] |
| * |
| * @return (fgValid) : 0 -> inValid, 1 -> Valid |
| */ |
| /*----------------------------------------------------------------------------*/ |
| BOOLEAN rlmDomainCheckChannelEntryValid(P_ADAPTER_T prAdapter, UINT_8 ucCentralCh) |
| { |
| BOOLEAN fgValid = FALSE; |
| UINT_8 ucTemp = 0xff; |
| UINT_8 i; |
| /*Check Power limit table channel efficient or not */ |
| |
| for (i = POWER_LIMIT_2G4; i < POWER_LIMIT_SUBAND_NUM; i++) { |
| if ((ucCentralCh >= g_rRlmSubBand[i].ucStartCh) && (ucCentralCh <= g_rRlmSubBand[i].ucEndCh)) |
| ucTemp = (ucCentralCh - g_rRlmSubBand[i].ucStartCh) % g_rRlmSubBand[i].ucInterval; |
| } |
| |
| #if 0 |
| /*2.4G, ex 1, 2, 3 */ |
| if (ucCentralCh >= BAND_2G4_LOWER_BOUND && ucCentralCh <= BAND_2G4_UPPER_BOUND) |
| ucTemp = 0; |
| /*FCC- Spec : Band UNII-1, ex 36, 38, 40.... */ |
| else if (ucCentralCh >= UNII1_LOWER_BOUND && ucCentralCh <= UNII1_UPPER_BOUND) |
| ucTemp = (ucCentralCh - UNII1_LOWER_BOUND) % 2; |
| /*FCC- Spec : Band UNII-2A, ex 52, 54, 56.... */ |
| else if (ucCentralCh >= UNII2A_LOWER_BOUND && ucCentralCh <= UNII2A_UPPER_BOUND) |
| ucTemp = (ucCentralCh - UNII2A_LOWER_BOUND) % 2; |
| /*FCC- Spec : Band UNII-2C, ex 100, 102, 104.... */ |
| else if (ucCentralCh >= UNII2C_LOWER_BOUND && ucCentralCh <= UNII2C_UPPER_BOUND) |
| ucTemp = (ucCentralCh - UNII2C_LOWER_BOUND) % 2; |
| /*FCC- Spec : Band UNII-3, ex 149, 151, 153... */ |
| else if (ucCentralCh >= UNII3_LOWER_BOUND && ucCentralCh <= UNII3_UPPER_BOUND) |
| ucTemp = (ucCentralCh - UNII3_LOWER_BOUND) % 2; |
| #endif |
| if (ucTemp == 0) |
| fgValid = TRUE; |
| return fgValid; |
| |
| } |
| |
| /*----------------------------------------------------------------------------*/ |
| /*! |
| * \brief |
| * |
| * \param[in] |
| * |
| * \return |
| */ |
| /*----------------------------------------------------------------------------*/ |
| UINT_8 rlmDomainGetCenterChannel(ENUM_BAND_T eBand, UINT_8 ucPriChannel, ENUM_CHNL_EXT_T eExtend) |
| { |
| UINT_8 ucCenterChannel; |
| |
| if (eExtend == CHNL_EXT_SCA) |
| ucCenterChannel = ucPriChannel + 2; |
| else if (eExtend == CHNL_EXT_SCB) |
| ucCenterChannel = ucPriChannel - 2; |
| else |
| ucCenterChannel = ucPriChannel; |
| |
| return ucCenterChannel; |
| } |
| |
| /*----------------------------------------------------------------------------*/ |
| /*! |
| * \brief |
| * |
| * \param[in] |
| * |
| * \return |
| */ |
| /*----------------------------------------------------------------------------*/ |
| BOOLEAN |
| rlmDomainIsValidRfSetting(P_ADAPTER_T prAdapter, |
| ENUM_BAND_T eBand, |
| UINT_8 ucPriChannel, |
| ENUM_CHNL_EXT_T eExtend, |
| ENUM_CHANNEL_WIDTH_T eChannelWidth, UINT_8 ucChannelS1, UINT_8 ucChannelS2) |
| { |
| UINT_8 ucCenterChannel = 0; |
| UINT_8 ucUpperChannel; |
| UINT_8 ucLowerChannel; |
| BOOLEAN fgValidChannel = TRUE; |
| BOOLEAN fgUpperChannel = TRUE; |
| BOOLEAN fgLowerChannel = TRUE; |
| BOOLEAN fgValidBW = TRUE; |
| BOOLEAN fgValidRfSetting = TRUE; |
| UINT_32 u4PrimaryOffset; |
| |
| /*DBG msg for Channel InValid */ |
| if (eChannelWidth == CW_20_40MHZ) { |
| ucCenterChannel = rlmDomainGetCenterChannel(eBand, ucPriChannel, eExtend); |
| |
| /* Check Central Channel Valid or Not */ |
| fgValidChannel = rlmDomainCheckChannelEntryValid(prAdapter, ucCenterChannel); |
| if (fgValidChannel == FALSE) |
| DBGLOG(RLM, WARN, "Rf20: CentralCh=%d\n", ucCenterChannel); |
| |
| /* Check Upper Channel and Lower Channel */ |
| switch (eExtend) { |
| case CHNL_EXT_SCA: |
| ucUpperChannel = ucPriChannel + 4; |
| ucLowerChannel = ucPriChannel; |
| break; |
| case CHNL_EXT_SCB: |
| ucUpperChannel = ucPriChannel; |
| ucLowerChannel = ucPriChannel - 4; |
| break; |
| default: |
| ucUpperChannel = ucPriChannel; |
| ucLowerChannel = ucPriChannel; |
| break; |
| } |
| |
| fgUpperChannel = rlmDomainCheckChannelEntryValid(prAdapter, ucUpperChannel); |
| if (fgUpperChannel == FALSE) |
| DBGLOG(RLM, WARN, "Rf20: UpperCh=%d\n", ucUpperChannel); |
| |
| fgLowerChannel = rlmDomainCheckChannelEntryValid(prAdapter, ucLowerChannel); |
| if (fgLowerChannel == FALSE) |
| DBGLOG(RLM, WARN, "Rf20: LowerCh=%d\n", ucLowerChannel); |
| |
| } else if ((eChannelWidth == CW_80MHZ) || (eChannelWidth == CW_160MHZ)) { |
| ucCenterChannel = ucChannelS1; |
| |
| /* Check Central Channel Valid or Not */ |
| if (eChannelWidth != CW_160MHZ) { |
| /*BW not check , ex: primary 36 and central channel 50 will fail the check*/ |
| fgValidChannel = rlmDomainCheckChannelEntryValid(prAdapter, ucCenterChannel); |
| } |
| |
| if (fgValidChannel == FALSE) |
| DBGLOG(RLM, WARN, "Rf80/160C: CentralCh=%d\n", ucCenterChannel); |
| } else if (eChannelWidth == CW_80P80MHZ) { |
| ucCenterChannel = ucChannelS1; |
| |
| fgValidChannel = rlmDomainCheckChannelEntryValid(prAdapter, ucCenterChannel); |
| |
| if (fgValidChannel == FALSE) |
| DBGLOG(RLM, WARN, "Rf160NC: CentralCh1=%d\n", ucCenterChannel); |
| |
| ucCenterChannel = ucChannelS2; |
| |
| fgValidChannel = rlmDomainCheckChannelEntryValid(prAdapter, ucCenterChannel); |
| |
| if (fgValidChannel == FALSE) |
| DBGLOG(RLM, WARN, "Rf160NC: CentralCh2=%d\n", ucCenterChannel); |
| |
| /* Check Central Channel Valid or Not */ |
| } else { |
| DBGLOG(RLM, ERROR, "Wrong BW =%d\n", eChannelWidth); |
| fgValidChannel = FALSE; |
| } |
| |
| /* Check BW Setting Correct or Not */ |
| if (eBand == BAND_2G4) { |
| if (eChannelWidth != CW_20_40MHZ) { |
| fgValidBW = FALSE; |
| DBGLOG(RLM, WARN, "Rf: B=%d, W=%d\n", eBand, eChannelWidth); |
| } |
| } else { |
| if ((eChannelWidth == CW_80MHZ) || (eChannelWidth == CW_80P80MHZ)) { |
| u4PrimaryOffset = CAL_CH_OFFSET_80M(ucPriChannel, ucChannelS1); |
| if (u4PrimaryOffset > 4) { |
| fgValidBW = FALSE; |
| DBGLOG(RLM, WARN, "Rf: PriOffSet=%d, W=%d\n", u4PrimaryOffset, eChannelWidth); |
| } |
| } else if (eChannelWidth == CW_160MHZ) { |
| u4PrimaryOffset = CAL_CH_OFFSET_160M(ucPriChannel, ucCenterChannel); |
| if (u4PrimaryOffset > 8) { |
| fgValidBW = FALSE; |
| DBGLOG(RLM, WARN, "Rf: PriOffSet=%d, W=%d\n", u4PrimaryOffset, eChannelWidth); |
| } |
| } |
| } |
| |
| if ((fgValidBW == FALSE) || (fgValidChannel == FALSE) || (fgUpperChannel == FALSE) || (fgLowerChannel == FALSE)) |
| fgValidRfSetting = FALSE; |
| |
| return fgValidRfSetting; |
| |
| } |
| |
| #if (CFG_SUPPORT_SINGLE_SKU == 1) |
| |
| /* |
| * This function coverts country code from alphabet chars to u32, |
| * the caller need to pass country code chars and do size check |
| */ |
| UINT_32 rlmDomainAlpha2ToU32(PCHAR pcAlpha2, UINT_8 ucAlpha2Size) |
| { |
| UINT_8 ucIdx; |
| UINT_32 u4CountryCode = 0; |
| |
| if (ucAlpha2Size > TX_PWR_LIMIT_COUNTRY_STR_MAX_LEN) { |
| DBGLOG(RLM, ERROR, "alpha2 size %d is invalid!(max: %d)\n", |
| ucAlpha2Size, TX_PWR_LIMIT_COUNTRY_STR_MAX_LEN); |
| ucAlpha2Size = TX_PWR_LIMIT_COUNTRY_STR_MAX_LEN; |
| } |
| |
| for (ucIdx = 0; ucIdx < ucAlpha2Size; ucIdx++) |
| u4CountryCode |= (pcAlpha2[ucIdx] << (ucIdx * 8)); |
| |
| return u4CountryCode; |
| } |
| |
| /*----------------------------------------------------------------------------*/ |
| /*! |
| * \brief Search the tx power limit setting range of the specified in the text file |
| * |
| * \param[IN] u4CountryCode The u32 type of the specified country. |
| * \param[IN] pucBuf The content of the text file. |
| * \param[IN] u4cBufLen End boundary of the text file. |
| * \param[OUT] pu4CountryStart Store the start position of the desired country settings. |
| * \param[OUT] pu4CountryEnd Store the end position of the desired country settings. |
| * |
| * \retval TRUE Success. |
| * \retval FALSE Failure. |
| */ |
| /*----------------------------------------------------------------------------*/ |
| |
| BOOL rlmDomainTxPwrLimitGetCountryRange( |
| UINT_32 u4CountryCode, PUINT_8 pucBuf, UINT_32 u4BufLen, |
| PUINT_32 pu4CountryStart, PUINT_32 pu4CountryEnd) |
| { |
| UINT_32 u4TmpPos = 0; |
| char pcrCountryStr[TX_PWR_LIMIT_COUNTRY_STR_MAX_LEN + 1] = {0}; |
| UINT_8 cIdx = 0; |
| |
| while (1) { |
| while (u4TmpPos < u4BufLen && pucBuf[u4TmpPos] != '[') |
| u4TmpPos++; |
| |
| u4TmpPos++; /* skip the '[' char */ |
| |
| cIdx = 0; |
| while (u4TmpPos < u4BufLen && cIdx < TX_PWR_LIMIT_COUNTRY_STR_MAX_LEN && |
| pucBuf[u4TmpPos] != ']') { |
| pcrCountryStr[cIdx++] = pucBuf[u4TmpPos]; |
| u4TmpPos++; |
| } |
| |
| u4TmpPos++; /* skip the ']' char */ |
| |
| if (u4TmpPos >= u4BufLen || cIdx > TX_PWR_LIMIT_COUNTRY_STR_MAX_LEN) |
| return FALSE; |
| |
| if (u4CountryCode == rlmDomainAlpha2ToU32(pcrCountryStr, cIdx)) { |
| DBGLOG(RLM, INFO, "Found TxPwrLimit table for CountryCode \"%s\"\n", |
| pcrCountryStr); |
| *pu4CountryStart = u4TmpPos; /* the location after char ']' */ |
| break; |
| } |
| } |
| |
| while (u4TmpPos < u4BufLen && pucBuf[u4TmpPos] != '[') |
| u4TmpPos++; |
| |
| *pu4CountryEnd = u4TmpPos; |
| |
| return TRUE; |
| } |
| |
| BOOL rlmDomainTxPwrLimitSearchSection(const char *pSectionName, |
| PINT_8 pucBuf, PUINT_32 pu4Pos, UINT_32 u4BufEnd) |
| { |
| UINT_32 u4TmpPos = *pu4Pos; |
| UINT_8 uSectionNameLen = kalStrLen(pSectionName); |
| |
| while (1) { |
| while (u4TmpPos < u4BufEnd && pucBuf[u4TmpPos] != '<') |
| u4TmpPos++; |
| |
| u4TmpPos++; /* skip char '<' */ |
| |
| if (u4TmpPos + uSectionNameLen >= u4BufEnd) |
| return FALSE; |
| |
| if (kalStrnCmp(&pucBuf[u4TmpPos], pSectionName, uSectionNameLen) == 0) { |
| |
| /* Go to the end of section header line */ |
| while (u4TmpPos < u4BufEnd && pucBuf[u4TmpPos] != '\n') |
| u4TmpPos++; |
| |
| *pu4Pos = u4TmpPos; |
| |
| break; |
| } |
| } |
| |
| return TRUE; |
| } |
| |
| BOOL rlmDomainTxPwrLimitSectionEnd(PUINT_8 pucBuf, |
| const char *pSectionName, PUINT_32 pu4Pos, UINT_32 u4BufEnd) |
| { |
| UINT_32 u4TmpPos = *pu4Pos; |
| char cTmpChar = 0; |
| UINT_8 uSectionNameLen = kalStrLen(pSectionName); |
| |
| while (u4TmpPos < u4BufEnd) { |
| cTmpChar = pucBuf[u4TmpPos]; |
| |
| /* skip blank lines */ |
| if (cTmpChar == ' ' || cTmpChar == '\t' || |
| cTmpChar == '\n' || cTmpChar == '\r') { |
| u4TmpPos++; |
| continue; |
| } |
| |
| break; |
| } |
| |
| if (u4TmpPos + uSectionNameLen + 2 >= u4BufEnd) {/* 2 means '/' and '>' */ |
| *pu4Pos = u4BufEnd; |
| return FALSE; |
| } |
| |
| if (pucBuf[u4TmpPos] != '<') |
| return FALSE; |
| |
| if (pucBuf[u4TmpPos + 1] != '/' || |
| pucBuf[u4TmpPos + 2 + uSectionNameLen] != '>' || |
| kalStrnCmp(&pucBuf[u4TmpPos + 2], pSectionName, uSectionNameLen)) { |
| |
| *pu4Pos = u4TmpPos + uSectionNameLen + 2; |
| return FALSE; |
| } |
| |
| *pu4Pos = u4TmpPos + uSectionNameLen + 3; /* 3 means go to the location after '>' */ |
| |
| return TRUE; |
| } |
| |
| INT_8 rlmDomainTxPwrLimitGetChIdx( |
| struct TX_PWR_LIMIT_DATA *pTxPwrLimit, UINT_8 ucChannel) |
| { |
| INT_8 cIdx = 0; |
| |
| for (cIdx = 0; cIdx < pTxPwrLimit->ucChNum; cIdx++) |
| if (ucChannel == pTxPwrLimit->rChannelTxPwrLimit[cIdx].ucChannel) |
| return cIdx; |
| |
| DBGLOG(RLM, ERROR, "Can't find idx of channel %d in TxPwrLimit data\n", |
| ucChannel); |
| |
| return -1; |
| } |
| |
| BOOL rlmDomainTxPwrLimitLoadChannelSetting( |
| PUINT_8 pucBuf, PUINT_32 pu4Pos, UINT_32 u4BufEnd, |
| struct TX_PWR_LIMIT_DATA *pTxPwrLimit, UINT_8 ucSectionIdx) |
| { |
| UINT_32 u4TmpPos = *pu4Pos; |
| char cTmpChar = 0; |
| struct CHANNEL_TX_PWR_LIMIT *prChTxPwrLimit = NULL; |
| BOOL bNeg = FALSE; |
| INT_8 cLimitValue = 0, cChIdx = 0; |
| UINT_8 ucIdx = 0, ucChannel = 0; |
| |
| /* skip blank lines */ |
| while (u4TmpPos < u4BufEnd) { |
| cTmpChar = pucBuf[u4TmpPos]; |
| |
| if (cTmpChar == ' ' || cTmpChar == '\t' || |
| cTmpChar == '\n' || cTmpChar == '\r') { |
| u4TmpPos++; |
| continue; |
| } |
| |
| break; |
| } |
| |
| /* current is at the location of 'c', check remaining buf length for 'chxxx' */ |
| if (u4TmpPos + 5 >= u4BufEnd) { |
| DBGLOG(RLM, ERROR, |
| "Invalid location of ch setting: %u/%u\n", |
| u4TmpPos, u4BufEnd); |
| return FALSE; |
| } |
| |
| if (pucBuf[u4TmpPos] == 'c' && pucBuf[u4TmpPos + 1] == 'h') { |
| ucChannel = (pucBuf[u4TmpPos + 2] - '0') * 100 + |
| (pucBuf[u4TmpPos + 3] - '0') * 10 + |
| (pucBuf[u4TmpPos + 4] - '0'); |
| } else { /* invalid format */ |
| *pu4Pos = u4TmpPos; |
| DBGLOG(RLM, ERROR, "Invalid ch setting starting chars: %c%c\n", |
| pucBuf[u4TmpPos], pucBuf[u4TmpPos + 1]); |
| |
| /* goto next line */ |
| while (*pu4Pos < u4BufEnd && pucBuf[*pu4Pos] != '\n') |
| (*pu4Pos)++; |
| |
| return TRUE; |
| } |
| |
| cChIdx = rlmDomainTxPwrLimitGetChIdx(pTxPwrLimit, ucChannel); |
| |
| if (cChIdx == -1) { |
| *pu4Pos = u4TmpPos; |
| DBGLOG(RLM, ERROR, "Invalid ch %u %c%c%c\n", ucChannel, |
| pucBuf[u4TmpPos + 2], pucBuf[u4TmpPos + 3], pucBuf[u4TmpPos + 4]); |
| |
| /* goto next line */ |
| while (*pu4Pos < u4BufEnd && pucBuf[*pu4Pos] != '\n') |
| (*pu4Pos)++; |
| |
| return TRUE; |
| } |
| |
| u4TmpPos += 5; |
| |
| prChTxPwrLimit = &pTxPwrLimit->rChannelTxPwrLimit[cChIdx]; |
| |
| /* read the channel TxPwrLimit settings */ |
| for (ucIdx = 0; ucIdx < gTx_Pwr_Limit_Element_Num[ucSectionIdx]; ucIdx++) { |
| |
| /* skip blank and comma */ |
| while (u4TmpPos < u4BufEnd) { |
| cTmpChar = pucBuf[u4TmpPos]; |
| |
| if (cTmpChar == ' ' || cTmpChar == '\t' || cTmpChar == ',') { |
| u4TmpPos++; |
| continue; |
| } |
| break; |
| } |
| |
| if (u4TmpPos >= u4BufEnd) { |
| *pu4Pos = u4BufEnd; |
| DBGLOG(RLM, ERROR, |
| "Invalid location of ch tx pwr limit val: %u/%u\n", |
| u4TmpPos, u4BufEnd); |
| return FALSE; |
| } |
| |
| bNeg = FALSE; |
| |
| cTmpChar = pucBuf[u4TmpPos]; |
| |
| if (cTmpChar == '-') { |
| bNeg = TRUE; |
| u4TmpPos++; |
| } else if (cTmpChar == 'x') { |
| prChTxPwrLimit->rTxPwrLimitValue[ucSectionIdx][ucIdx] = |
| TX_PWR_LIMIT_MAX_VAL; |
| u4TmpPos++; |
| continue; |
| } |
| |
| cLimitValue = 0; |
| while (u4TmpPos < u4BufEnd) { |
| cTmpChar = pucBuf[u4TmpPos]; |
| |
| if (cTmpChar < '0' || cTmpChar > '9') |
| break; |
| |
| cLimitValue = (cLimitValue * 10) + (cTmpChar - '0'); |
| u4TmpPos++; |
| } |
| |
| if (bNeg) |
| cLimitValue = -cLimitValue; |
| |
| prChTxPwrLimit->rTxPwrLimitValue[ucSectionIdx][ucIdx] = cLimitValue; |
| } |
| |
| *pu4Pos = u4TmpPos; |
| return TRUE; |
| } |
| |
| VOID rlmDomainTxPwrLimitRemoveComments( |
| PUINT_8 pucBuf, UINT_32 u4BufLen) |
| { |
| UINT_32 u4TmpPos = 0; |
| char cTmpChar = 0; |
| |
| while (u4TmpPos < u4BufLen) { |
| cTmpChar = pucBuf[u4TmpPos]; |
| |
| if (cTmpChar == '#') { |
| while (cTmpChar != '\n') { |
| pucBuf[u4TmpPos] = ' '; |
| |
| u4TmpPos++; |
| if (u4TmpPos >= u4BufLen) |
| break; |
| |
| cTmpChar = pucBuf[u4TmpPos]; |
| } |
| } |
| u4TmpPos++; |
| } |
| } |
| |
| BOOL rlmDomainTxPwrLimitLoad( |
| P_ADAPTER_T prAdapter, PUINT_8 pucBuf, UINT_32 u4BufLen, |
| UINT_32 u4CountryCode, struct TX_PWR_LIMIT_DATA *pTxPwrLimit) |
| { |
| UINT_8 uSecIdx = 0; |
| UINT_32 u4CountryStart = 0, u4CountryEnd = 0, u4Pos = 0; |
| |
| rlmDomainTxPwrLimitRemoveComments(pucBuf, u4BufLen); |
| |
| if (!rlmDomainTxPwrLimitGetCountryRange(u4CountryCode, pucBuf, |
| u4BufLen, &u4CountryStart, &u4CountryEnd)) { |
| DBGLOG(RLM, ERROR, "Can't find specified table in %s\n", |
| WLAN_TX_PWR_LIMIT_FILE_NAME); |
| return FALSE; |
| } |
| |
| u4Pos = u4CountryStart; |
| |
| for (uSecIdx = 0; uSecIdx < TX_PWR_LIMIT_SECTION_NUM; uSecIdx++) { |
| if (!rlmDomainTxPwrLimitSearchSection(gTx_Pwr_Limit_Section[uSecIdx], |
| pucBuf, &u4Pos, u4CountryEnd)) { |
| DBGLOG(RLM, ERROR, "Can't find specified section %s in %s\n", |
| gTx_Pwr_Limit_Section[uSecIdx], WLAN_TX_PWR_LIMIT_FILE_NAME); |
| return FALSE; |
| } |
| |
| DBGLOG(RLM, INFO, "Find specified section %s in %s\n", |
| gTx_Pwr_Limit_Section[uSecIdx], WLAN_TX_PWR_LIMIT_FILE_NAME); |
| |
| while (!rlmDomainTxPwrLimitSectionEnd(pucBuf, |
| gTx_Pwr_Limit_Section[uSecIdx], &u4Pos, u4CountryEnd) && |
| u4Pos < u4CountryEnd) { |
| if (!rlmDomainTxPwrLimitLoadChannelSetting(pucBuf, &u4Pos, |
| u4CountryEnd, pTxPwrLimit, uSecIdx)) |
| return FALSE; |
| } |
| } |
| |
| DBGLOG(RLM, INFO, "Load %s finished\n", WLAN_TX_PWR_LIMIT_FILE_NAME); |
| return TRUE; |
| } |
| |
| VOID rlmDomainTxPwrLimitSetChValues( |
| P_CMD_CHANNEL_POWER_LIMIT_V2 pCmd, struct CHANNEL_TX_PWR_LIMIT *pChTxPwrLimit) |
| { |
| UINT_8 section = 0, e = 0; |
| |
| pCmd->tx_pwr_dsss_cck = pChTxPwrLimit->rTxPwrLimitValue[0][0]; |
| pCmd->tx_pwr_dsss_bpsk = pChTxPwrLimit->rTxPwrLimitValue[0][1]; |
| |
| pCmd->tx_pwr_ofdm_bpsk = pChTxPwrLimit->rTxPwrLimitValue[0][2]; /* 6M, 9M */ |
| pCmd->tx_pwr_ofdm_qpsk = pChTxPwrLimit->rTxPwrLimitValue[0][3]; /* 12M, 18M */ |
| pCmd->tx_pwr_ofdm_16qam = pChTxPwrLimit->rTxPwrLimitValue[0][4]; /* 24M, 36M */ |
| pCmd->tx_pwr_ofdm_48m = pChTxPwrLimit->rTxPwrLimitValue[0][5]; |
| pCmd->tx_pwr_ofdm_54m = pChTxPwrLimit->rTxPwrLimitValue[0][6]; |
| |
| pCmd->tx_pwr_ht20_bpsk = pChTxPwrLimit->rTxPwrLimitValue[1][0]; /* MCS0*/ |
| pCmd->tx_pwr_ht20_qpsk = pChTxPwrLimit->rTxPwrLimitValue[1][1]; /* MCS1, MCS2*/ |
| pCmd->tx_pwr_ht20_16qam = pChTxPwrLimit->rTxPwrLimitValue[1][2]; /* MCS3, MCS4*/ |
| pCmd->tx_pwr_ht20_mcs5 = pChTxPwrLimit->rTxPwrLimitValue[1][3]; /* MCS5*/ |
| pCmd->tx_pwr_ht20_mcs6 = pChTxPwrLimit->rTxPwrLimitValue[1][4]; /* MCS6*/ |
| pCmd->tx_pwr_ht20_mcs7 = pChTxPwrLimit->rTxPwrLimitValue[1][5]; /* MCS7*/ |
| |
| pCmd->tx_pwr_ht40_bpsk = pChTxPwrLimit->rTxPwrLimitValue[2][0]; /* MCS0*/ |
| pCmd->tx_pwr_ht40_qpsk = pChTxPwrLimit->rTxPwrLimitValue[2][1]; /* MCS1, MCS2*/ |
| pCmd->tx_pwr_ht40_16qam = pChTxPwrLimit->rTxPwrLimitValue[2][2]; /* MCS3, MCS4*/ |
| pCmd->tx_pwr_ht40_mcs5 = pChTxPwrLimit->rTxPwrLimitValue[2][3]; /* MCS5*/ |
| pCmd->tx_pwr_ht40_mcs6 = pChTxPwrLimit->rTxPwrLimitValue[2][4]; /* MCS6*/ |
| pCmd->tx_pwr_ht40_mcs7 = pChTxPwrLimit->rTxPwrLimitValue[2][5]; /* MCS7*/ |
| pCmd->tx_pwr_ht40_mcs32 = pChTxPwrLimit->rTxPwrLimitValue[2][6]; /* MCS32*/ |
| |
| pCmd->tx_pwr_vht20_bpsk = pChTxPwrLimit->rTxPwrLimitValue[3][0]; /* MCS0*/ |
| pCmd->tx_pwr_vht20_qpsk = pChTxPwrLimit->rTxPwrLimitValue[3][1]; /* MCS1, MCS2*/ |
| pCmd->tx_pwr_vht20_16qam = pChTxPwrLimit->rTxPwrLimitValue[3][2]; /* MCS3, MCS4*/ |
| pCmd->tx_pwr_vht20_64qam = pChTxPwrLimit->rTxPwrLimitValue[3][3]; /* MCS5, MCS6*/ |
| pCmd->tx_pwr_vht20_mcs7 = pChTxPwrLimit->rTxPwrLimitValue[3][4]; |
| pCmd->tx_pwr_vht20_mcs8 = pChTxPwrLimit->rTxPwrLimitValue[3][5]; |
| pCmd->tx_pwr_vht20_mcs9 = pChTxPwrLimit->rTxPwrLimitValue[3][6]; |
| |
| pCmd->tx_pwr_vht_40 = pChTxPwrLimit->rTxPwrLimitValue[4][2]; |
| pCmd->tx_pwr_vht_80 = pChTxPwrLimit->rTxPwrLimitValue[4][3]; |
| pCmd->tx_pwr_vht_160c = pChTxPwrLimit->rTxPwrLimitValue[4][5]; |
| pCmd->tx_pwr_vht_160nc = pChTxPwrLimit->rTxPwrLimitValue[4][4]; |
| pCmd->tx_pwr_lg_40 = pChTxPwrLimit->rTxPwrLimitValue[4][0]; |
| pCmd->tx_pwr_lg_80 = pChTxPwrLimit->rTxPwrLimitValue[4][1]; |
| |
| |
| DBGLOG(RLM, TRACE, "ch %d\n", pCmd->ucCentralCh); |
| for (section = 0; section < TX_PWR_LIMIT_SECTION_NUM; section++) |
| for (e = 0; e < gTx_Pwr_Limit_Element_Num[section]; e++) |
| DBGLOG(RLM, TRACE, "TxPwrLimit[%s][%s]= %d\n", |
| gTx_Pwr_Limit_Section[section], |
| gTx_Pwr_Limit_Element[section][e], |
| pChTxPwrLimit->rTxPwrLimitValue[section][e]); |
| } |
| |
| VOID rlmDomainTxPwrLimitSetValues( |
| P_CMD_SET_COUNTRY_CHANNEL_POWER_LIMIT_V2_T pSetCmd, |
| struct TX_PWR_LIMIT_DATA *pTxPwrLimit) |
| { |
| UINT_8 ucIdx = 0; |
| INT_8 cChIdx = 0; |
| P_CMD_CHANNEL_POWER_LIMIT_V2 pCmd = NULL; |
| struct CHANNEL_TX_PWR_LIMIT *pChTxPwrLimit = NULL; |
| |
| if (!pSetCmd || !pTxPwrLimit) { |
| DBGLOG(RLM, ERROR, "%s: Invalid request!!!\n", __func__); |
| return; |
| } |
| |
| for (ucIdx = 0; ucIdx < pSetCmd->ucNum; ucIdx++) { |
| pCmd = &(pSetCmd->rChannelPowerLimit[ucIdx]); |
| cChIdx = rlmDomainTxPwrLimitGetChIdx(pTxPwrLimit, pCmd->ucCentralCh); |
| if (cChIdx == -1) { |
| DBGLOG(RLM, ERROR, "Invalid ch idx found while assigning values\n"); |
| continue; |
| } |
| pChTxPwrLimit = &pTxPwrLimit->rChannelTxPwrLimit[cChIdx]; |
| rlmDomainTxPwrLimitSetChValues(pCmd, pChTxPwrLimit); |
| } |
| } |
| |
| BOOL rlmDomainTxPwrLimitLoadFromFile(P_ADAPTER_T prAdapter, |
| UINT_32 u4CountryCode, struct TX_PWR_LIMIT_DATA *pTxPwrLimit) |
| { |
| PUINT_8 pucConfigBuf; |
| UINT_32 u4ConfigReadLen; |
| BOOL bRet = TRUE; |
| |
| pucConfigBuf = (PUINT_8) kalMemAlloc(WLAN_TX_PWR_LIMIT_FILE_BUF_SIZE, VIR_MEM_TYPE); |
| |
| if (!pucConfigBuf) |
| return FALSE; |
| |
| kalMemZero(pucConfigBuf, WLAN_TX_PWR_LIMIT_FILE_BUF_SIZE); |
| u4ConfigReadLen = 0; |
| |
| if (wlanGetFileContent(prAdapter, WLAN_TX_PWR_LIMIT_FILE_NAME, pucConfigBuf, |
| WLAN_TX_PWR_LIMIT_FILE_BUF_SIZE, &u4ConfigReadLen, TRUE) == 0) { |
| /* ToDo:: Nothing */ |
| } else if (wlanGetFileContent(prAdapter, "/storage/sdcard0/" WLAN_TX_PWR_LIMIT_FILE_NAME, pucConfigBuf, |
| WLAN_TX_PWR_LIMIT_FILE_BUF_SIZE, &u4ConfigReadLen, FALSE) == 0) { |
| /* ToDo:: Nothing */ |
| } else if (wlanGetFileContent(prAdapter, "/data/misc/" WLAN_TX_PWR_LIMIT_FILE_NAME, pucConfigBuf, |
| WLAN_TX_PWR_LIMIT_FILE_BUF_SIZE, &u4ConfigReadLen, FALSE) == 0) { |
| /* ToDo:: Nothing */ |
| } else if (wlanGetFileContent(prAdapter, "/data/misc/wifi/" WLAN_TX_PWR_LIMIT_FILE_NAME, pucConfigBuf, |
| WLAN_TX_PWR_LIMIT_FILE_BUF_SIZE, &u4ConfigReadLen, FALSE) == 0) { |
| /* ToDo:: Nothing */ |
| } else { |
| bRet = FALSE; |
| goto error; |
| } |
| |
| if (pucConfigBuf[0] == '\0' || u4ConfigReadLen == 0) { |
| bRet = FALSE; |
| goto error; |
| } |
| |
| if (!rlmDomainTxPwrLimitLoad(prAdapter, pucConfigBuf, u4ConfigReadLen, |
| u4CountryCode, pTxPwrLimit)) { |
| bRet = FALSE; |
| goto error; |
| } |
| |
| error: |
| kalMemFree(pucConfigBuf, VIR_MEM_TYPE, WLAN_TX_PWR_LIMIT_FILE_BUF_SIZE); |
| return bRet; |
| } |
| |
| BOOLEAN rlmDomainGetTxPwrLimit(u32 country_code, |
| P_GLUE_INFO_T prGlueInfo, |
| P_CMD_SET_COUNTRY_CHANNEL_POWER_LIMIT_V2_T pSetCmd_2g, |
| P_CMD_SET_COUNTRY_CHANNEL_POWER_LIMIT_V2_T pSetCmd_5g |
| ) |
| { |
| int bRet = TRUE; |
| UINT_8 ucIdx = 0, ucCnt = 0; |
| struct TX_PWR_LIMIT_DATA *pTxPwrLimit = |
| (struct TX_PWR_LIMIT_DATA *) kalMemAlloc(sizeof(struct TX_PWR_LIMIT_DATA), VIR_MEM_TYPE); |
| |
| if (!pTxPwrLimit) { |
| bRet = FALSE; |
| DBGLOG(RLM, ERROR, "Alloc buffer for TxPwrLimit main struct failed\n"); |
| return bRet; |
| } |
| |
| pTxPwrLimit->ucChNum = (pSetCmd_2g ? pSetCmd_2g->ucNum : 0) + (pSetCmd_5g ? pSetCmd_5g->ucNum : 0); |
| |
| pTxPwrLimit->rChannelTxPwrLimit = |
| (struct CHANNEL_TX_PWR_LIMIT *) kalMemAlloc(sizeof(struct CHANNEL_TX_PWR_LIMIT) * |
| (pTxPwrLimit->ucChNum), VIR_MEM_TYPE); |
| |
| if (!pTxPwrLimit->rChannelTxPwrLimit) { |
| bRet = FALSE; |
| DBGLOG(RLM, ERROR, "Alloc buffer for TxPwrLimit ch values failed\n"); |
| goto error; |
| } |
| |
| kalMemSet(pTxPwrLimit->rChannelTxPwrLimit, MAX_TX_POWER, |
| sizeof(struct CHANNEL_TX_PWR_LIMIT) * (pTxPwrLimit->ucChNum)); |
| |
| if (pSetCmd_2g) |
| for (ucIdx = 0; ucIdx < pSetCmd_2g->ucNum; ucIdx++) { |
| pTxPwrLimit->rChannelTxPwrLimit[ucCnt].ucChannel = |
| pSetCmd_2g->rChannelPowerLimit[ucIdx].ucCentralCh; |
| ucCnt++; |
| } |
| |
| if (pSetCmd_5g) |
| for (ucIdx = 0; ucIdx < pSetCmd_5g->ucNum; ucIdx++) { |
| pTxPwrLimit->rChannelTxPwrLimit[ucCnt].ucChannel = |
| pSetCmd_5g->rChannelPowerLimit[ucIdx].ucCentralCh; |
| ucCnt++; |
| } |
| |
| bRet = rlmDomainTxPwrLimitLoadFromFile(prGlueInfo->prAdapter, |
| country_code, pTxPwrLimit); |
| |
| if (bRet) { |
| rlmDomainTxPwrLimitSetValues(pSetCmd_2g, pTxPwrLimit); |
| rlmDomainTxPwrLimitSetValues(pSetCmd_5g, pTxPwrLimit); |
| } |
| |
| kalMemFree(pTxPwrLimit->rChannelTxPwrLimit, VIR_MEM_TYPE, |
| sizeof(CHANNEL_TX_PWR_LIMIT) * pTxPwrLimit->ucChNum); |
| |
| error: |
| kalMemFree(pTxPwrLimit, VIR_MEM_TYPE, sizeof(TX_PWR_LIMIT_DATA)); |
| |
| return bRet; |
| } |
| |
| #endif |
| |
| #if CFG_SUPPORT_PWR_LIMIT_COUNTRY |
| |
| /*----------------------------------------------------------------------------*/ |
| /*! |
| * @brief |
| * |
| * @param[in] |
| * |
| * @return (fgValid) : 0 -> inValid, 1 -> Valid |
| */ |
| /*----------------------------------------------------------------------------*/ |
| BOOLEAN |
| rlmDomainCheckPowerLimitValid(P_ADAPTER_T prAdapter, |
| COUNTRY_POWER_LIMIT_TABLE_CONFIGURATION rPowerLimitTableConfiguration, |
| UINT_8 ucPwrLimitNum) |
| { |
| UINT_8 i; |
| BOOLEAN fgValid = TRUE; |
| PINT_8 prPwrLimit; |
| |
| prPwrLimit = &rPowerLimitTableConfiguration.aucPwrLimit[0]; |
| |
| for (i = 0; i < ucPwrLimitNum; i++, prPwrLimit++) { |
| if (*prPwrLimit > MAX_TX_POWER || *prPwrLimit < MIN_TX_POWER) { |
| fgValid = FALSE; |
| break; /*Find out Wrong Power limit */ |
| } |
| } |
| return fgValid; |
| |
| } |
| |
| /*----------------------------------------------------------------------------*/ |
| /*! |
| * @brief |
| * |
| * @param[in] |
| * |
| * @return (none) |
| */ |
| /*----------------------------------------------------------------------------*/ |
| VOID rlmDomainCheckCountryPowerLimitTable(P_ADAPTER_T prAdapter) |
| { |
| UINT_8 i, j; |
| UINT_16 u2CountryCodeTable, u2CountryCodeCheck; |
| BOOLEAN fgChannelValid = FALSE; |
| BOOLEAN fgPowerLimitValid = FALSE; |
| BOOLEAN fgEntryRepetetion = FALSE; |
| BOOLEAN fgTableValid = TRUE; |
| |
| /*Configuration Table Check */ |
| for (i = 0; i < sizeof(g_rRlmPowerLimitConfiguration) / sizeof(COUNTRY_POWER_LIMIT_TABLE_CONFIGURATION); i++) { |
| /*Table Country Code */ |
| WLAN_GET_FIELD_BE16(&g_rRlmPowerLimitConfiguration[i].aucCountryCode[0], &u2CountryCodeTable); |
| |
| /*Repetition Entry Check */ |
| for (j = i + 1; |
| j < ARRAY_SIZE(g_rRlmPowerLimitConfiguration); |
| j++) { |
| |
| WLAN_GET_FIELD_BE16(&g_rRlmPowerLimitConfiguration[j].aucCountryCode[0], &u2CountryCodeCheck); |
| if (((g_rRlmPowerLimitConfiguration[i].ucCentralCh) == |
| g_rRlmPowerLimitConfiguration[j].ucCentralCh) |
| && (u2CountryCodeTable == u2CountryCodeCheck)) { |
| fgEntryRepetetion = TRUE; |
| DBGLOG(RLM, INFO, "Domain: Configuration Repetition CC=%c%c, Ch=%d\n", |
| g_rRlmPowerLimitConfiguration[i].aucCountryCode[0], |
| g_rRlmPowerLimitConfiguration[i].aucCountryCode[1], |
| g_rRlmPowerLimitConfiguration[i].ucCentralCh); |
| } |
| } |
| |
| /*Channel Number Check */ |
| fgChannelValid = |
| rlmDomainCheckChannelEntryValid(prAdapter, g_rRlmPowerLimitConfiguration[i].ucCentralCh); |
| |
| /*Power Limit Check */ |
| fgPowerLimitValid = |
| rlmDomainCheckPowerLimitValid(prAdapter, g_rRlmPowerLimitConfiguration[i], PWR_LIMIT_NUM); |
| |
| if (fgChannelValid == FALSE || fgPowerLimitValid == FALSE) { |
| fgTableValid = FALSE; |
| DBGLOG(RLM, INFO, "Domain: CC=%c%c, Ch=%d, Limit: %d,%d,%d,%d,%d\n", |
| g_rRlmPowerLimitConfiguration[i].aucCountryCode[0], |
| g_rRlmPowerLimitConfiguration[i].aucCountryCode[1], |
| g_rRlmPowerLimitConfiguration[i].ucCentralCh, |
| g_rRlmPowerLimitConfiguration[i].aucPwrLimit[PWR_LIMIT_CCK], |
| g_rRlmPowerLimitConfiguration[i].aucPwrLimit[PWR_LIMIT_20M], |
| g_rRlmPowerLimitConfiguration[i].aucPwrLimit[PWR_LIMIT_40M], |
| g_rRlmPowerLimitConfiguration[i].aucPwrLimit[PWR_LIMIT_80M], |
| g_rRlmPowerLimitConfiguration[i].aucPwrLimit[PWR_LIMIT_160M]); |
| } |
| |
| if (u2CountryCodeTable == COUNTRY_CODE_NULL) { |
| DBGLOG(RLM, INFO, "Domain: Full search down\n"); |
| break; /*End of country table entry */ |
| } |
| |
| } |
| |
| if (fgEntryRepetetion == FALSE) |
| DBGLOG(RLM, INFO, "Domain: Configuration Table no Repetiton.\n"); |
| |
| /*Configuration Table no error */ |
| if (fgTableValid == TRUE) |
| prAdapter->fgIsPowerLimitTableValid = TRUE; |
| else |
| prAdapter->fgIsPowerLimitTableValid = FALSE; |
| |
| /*Default Table Check */ |
| fgEntryRepetetion = FALSE; |
| for (i = 0; i < sizeof(g_rRlmPowerLimitDefault) / sizeof(COUNTRY_POWER_LIMIT_TABLE_DEFAULT); i++) { |
| |
| WLAN_GET_FIELD_BE16(&g_rRlmPowerLimitDefault[i].aucCountryCode[0], &u2CountryCodeTable); |
| |
| for (j = i + 1; j < sizeof(g_rRlmPowerLimitDefault) / sizeof(COUNTRY_POWER_LIMIT_TABLE_DEFAULT); j++) { |
| WLAN_GET_FIELD_BE16(&g_rRlmPowerLimitDefault[j].aucCountryCode[0], &u2CountryCodeCheck); |
| if (u2CountryCodeTable == u2CountryCodeCheck) { |
| fgEntryRepetetion = TRUE; |
| DBGLOG(RLM, INFO, |
| "Domain: Default Repetition CC=%c%c\n", |
| g_rRlmPowerLimitDefault[j].aucCountryCode[0], |
| g_rRlmPowerLimitDefault[j].aucCountryCode[1]); |
| } |
| } |
| } |
| if (fgEntryRepetetion == FALSE) |
| DBGLOG(RLM, INFO, "Domain: Default Table no Repetiton.\n"); |
| } |
| |
| /*----------------------------------------------------------------------------*/ |
| /*! |
| * @brief |
| * |
| * @param[in] |
| * |
| * @return (u2TableIndex) : if 0xFFFF -> No Table Match |
| */ |
| /*----------------------------------------------------------------------------*/ |
| UINT_16 rlmDomainPwrLimitDefaultTableDecision(P_ADAPTER_T prAdapter, UINT_16 u2CountryCode) |
| { |
| |
| UINT_16 i; |
| UINT_16 u2CountryCodeTable = COUNTRY_CODE_NULL; |
| UINT_16 u2TableIndex = POWER_LIMIT_TABLE_NULL; /* No Table Match */ |
| |
| /*Default Table Index */ |
| for (i = 0; i < sizeof(g_rRlmPowerLimitDefault) / sizeof(COUNTRY_POWER_LIMIT_TABLE_DEFAULT); i++) { |
| |
| WLAN_GET_FIELD_BE16(&g_rRlmPowerLimitDefault[i].aucCountryCode[0], &u2CountryCodeTable); |
| |
| if (u2CountryCodeTable == u2CountryCode) { |
| u2TableIndex = i; |
| break; /*match country code */ |
| } else if (u2CountryCodeTable == COUNTRY_CODE_NULL) { |
| u2TableIndex = i; |
| break; /*find last one country- Default */ |
| } |
| } |
| |
| DBGLOG(RLM, INFO, "Domain: Default Table Index = %d\n", u2TableIndex); |
| |
| return u2TableIndex; |
| } |
| |
| /*----------------------------------------------------------------------------*/ |
| /*! |
| * @brief |
| * |
| * @param[in] |
| * |
| * @return (none) |
| */ |
| /*----------------------------------------------------------------------------*/ |
| VOID rlmDomainBuildCmdByDefaultTable(P_CMD_SET_COUNTRY_CHANNEL_POWER_LIMIT_T prCmd, UINT_16 u2DefaultTableIndex) |
| { |
| UINT_8 i, k; |
| P_COUNTRY_POWER_LIMIT_TABLE_DEFAULT prPwrLimitSubBand; |
| P_CMD_CHANNEL_POWER_LIMIT prCmdPwrLimit; |
| |
| prCmdPwrLimit = &prCmd->rChannelPowerLimit[0]; |
| prPwrLimitSubBand = &g_rRlmPowerLimitDefault[u2DefaultTableIndex]; |
| |
| /*Build power limit cmd by default table information */ |
| |
| for (i = POWER_LIMIT_2G4; i < POWER_LIMIT_SUBAND_NUM; i++) { |
| if (prPwrLimitSubBand->aucPwrLimitSubBand[i] < MAX_TX_POWER) { |
| for (k = g_rRlmSubBand[i].ucStartCh; k <= g_rRlmSubBand[i].ucEndCh; |
| k += g_rRlmSubBand[i].ucInterval) { |
| if ((prPwrLimitSubBand->ucPwrUnit & BIT(i)) == 0) { |
| prCmdPwrLimit->ucCentralCh = k; |
| kalMemSet(&prCmdPwrLimit->cPwrLimitCCK, |
| prPwrLimitSubBand->aucPwrLimitSubBand[i], PWR_LIMIT_NUM); |
| prCmdPwrLimit++; |
| prCmd->ucNum++; |
| |
| } else { |
| /* ex: 40MHz power limit(mW\MHz) = 20MHz power limit(mW\MHz) * 2 |
| * ---> 40MHz power limit(dBm) = 20MHz power limit(dBm) + 6; |
| */ |
| prCmdPwrLimit->ucCentralCh = k; |
| prCmdPwrLimit->cPwrLimitCCK = prPwrLimitSubBand->aucPwrLimitSubBand[i]; |
| prCmdPwrLimit->cPwrLimit20 = prPwrLimitSubBand->aucPwrLimitSubBand[i]; |
| prCmdPwrLimit->cPwrLimit40 = prPwrLimitSubBand->aucPwrLimitSubBand[i] + 6; |
| if (prCmdPwrLimit->cPwrLimit40 > MAX_TX_POWER) |
| prCmdPwrLimit->cPwrLimit40 = MAX_TX_POWER; |
| prCmdPwrLimit->cPwrLimit80 = prPwrLimitSubBand->aucPwrLimitSubBand[i] + 12; |
| if (prCmdPwrLimit->cPwrLimit80 > MAX_TX_POWER) |
| prCmdPwrLimit->cPwrLimit80 = MAX_TX_POWER; |
| prCmdPwrLimit->cPwrLimit160 = prPwrLimitSubBand->aucPwrLimitSubBand[i] + 18; |
| if (prCmdPwrLimit->cPwrLimit160 > MAX_TX_POWER) |
| prCmdPwrLimit->cPwrLimit160 = MAX_TX_POWER; |
| prCmdPwrLimit++; |
| prCmd->ucNum++; |
| } |
| } |
| } |
| } |
| |
| #if 0 |
| if (prPwrLimitSubBand->aucPwrLimitSubBand[POWER_LIMIT_2G4] < MAX_TX_POWER) { |
| for (i = BAND_2G4_LOWER_BOUND; i <= BAND_2G4_UPPER_BOUND; i++) { |
| prCmdPwrLimit->ucCentralCh = i; |
| kalMemSet(&prCmdPwrLimit->cPwrLimitCCK, prPwrLimitSubBand->aucPwrLimitSubBand[POWER_LIMIT_2G4], |
| PWR_LIMIT_NUM); |
| prCmdPwrLimit++; |
| prCmd->ucNum++; |
| } |
| } |
| |
| if (prPwrLimitSubBand->aucPwrLimitSubBand[POWER_LIMIT_UNII1] < MAX_TX_POWER) { |
| if (prCmd->u2CountryCode != COUNTRY_CODE_KR) { |
| for (i = UNII1_LOWER_BOUND; i <= UNII1_UPPER_BOUND; i += 2) { |
| prCmdPwrLimit->ucCentralCh = i; |
| kalMemSet(&prCmdPwrLimit->cPwrLimitCCK, |
| prPwrLimitSubBand->aucPwrLimitSubBand[POWER_LIMIT_UNII1], PWR_LIMIT_NUM); |
| prCmdPwrLimit++; |
| prCmd->ucNum++; |
| } |
| } else { |
| for (i = UNII1_LOWER_BOUND; i <= UNII1_UPPER_BOUND; i += 2) { |
| /* ex: 40MHz power limit(mW\MHz) = 20MHz power limit(mW\MHz) * 2 |
| * ---> 40MHz power limit(dBm) = 20MHz power limit(dBm) + 6; |
| */ |
| prCmdPwrLimit->ucCentralCh = i; |
| prCmdPwrLimit->cPwrLimitCCK = |
| g_rRlmPowerLimitDefault[u2DefaultTableIndex].cPwrLimitUnii1; |
| prCmdPwrLimit->cPwrLimit20 = |
| g_rRlmPowerLimitDefault[u2DefaultTableIndex].cPwrLimitUnii1; |
| prCmdPwrLimit->cPwrLimit40 = |
| g_rRlmPowerLimitDefault[u2DefaultTableIndex].cPwrLimitUnii1 + 6; |
| prCmdPwrLimit->cPwrLimit80 = |
| g_rRlmPowerLimitDefault[u2DefaultTableIndex].cPwrLimitUnii1 + 12; |
| prCmdPwrLimit->cPwrLimit160 = |
| g_rRlmPowerLimitDefault[u2DefaultTableIndex].cPwrLimitUnii1 + 18; |
| prCmdPwrLimit++; |
| prCmd->ucNum++; |
| } |
| } |
| } |
| |
| if (prPwrLimitSubBand->aucPwrLimitSubBand[POWER_LIMIT_UNII2A] < MAX_TX_POWER) { |
| for (i = UNII2A_LOWER_BOUND; i <= UNII2A_UPPER_BOUND; i += 2) { |
| prCmdPwrLimit->ucCentralCh = i; |
| kalMemSet(&prCmdPwrLimit->cPwrLimitCCK, |
| prPwrLimitSubBand->aucPwrLimitSubBand[POWER_LIMIT_UNII2A], PWR_LIMIT_NUM); |
| prCmdPwrLimit++; |
| prCmd->ucNum++; |
| } |
| } |
| |
| if (prPwrLimitSubBand->aucPwrLimitSubBand[POWER_LIMIT_UNII2C] < MAX_TX_POWER) { |
| for (i = UNII2C_LOWER_BOUND; i <= UNII2C_UPPER_BOUND; i += 2) { |
| prCmdPwrLimit->ucCentralCh = i; |
| kalMemSet(&prCmdPwrLimit->cPwrLimitCCK, |
| prPwrLimitSubBand->aucPwrLimitSubBand[POWER_LIMIT_UNII2C], PWR_LIMIT_NUM); |
| prCmdPwrLimit++; |
| prCmd->ucNum++; |
| } |
| } |
| if (prPwrLimitSubBand->aucPwrLimitSubBand[POWER_LIMIT_UNII3] < MAX_TX_POWER) { |
| for (i = UNII3_LOWER_BOUND; i <= UNII3_UPPER_BOUND; i += 2) { |
| prCmdPwrLimit->ucCentralCh = i; |
| kalMemSet(&prCmdPwrLimit->cPwrLimitCCK, |
| prPwrLimitSubBand->aucPwrLimitSubBand[POWER_LIMIT_UNII3], PWR_LIMIT_NUM); |
| prCmdPwrLimit++; |
| prCmd->ucNum++; |
| } |
| } |
| #endif |
| } |
| |
| /*----------------------------------------------------------------------------*/ |
| /*! |
| * @brief |
| * |
| * @param[in] |
| * |
| * @return (none) |
| */ |
| /*----------------------------------------------------------------------------*/ |
| VOID rlmDomainBuildCmdByConfigTable(P_ADAPTER_T prAdapter, P_CMD_SET_COUNTRY_CHANNEL_POWER_LIMIT_T prCmd) |
| { |
| UINT_8 i, k; |
| UINT_16 u2CountryCodeTable = COUNTRY_CODE_NULL; |
| P_CMD_CHANNEL_POWER_LIMIT prCmdPwrLimit; |
| BOOLEAN fgChannelValid; |
| |
| /*Build power limit cmd by configuration table information */ |
| |
| for (i = 0; i < sizeof(g_rRlmPowerLimitConfiguration) / sizeof(COUNTRY_POWER_LIMIT_TABLE_CONFIGURATION); i++) { |
| |
| WLAN_GET_FIELD_BE16(&g_rRlmPowerLimitConfiguration[i].aucCountryCode[0], &u2CountryCodeTable); |
| |
| fgChannelValid = |
| rlmDomainCheckChannelEntryValid(prAdapter, g_rRlmPowerLimitConfiguration[i].ucCentralCh); |
| |
| if (u2CountryCodeTable == COUNTRY_CODE_NULL) { |
| DBGLOG(RLM, INFO, "Domain: full search configuration table done.\n"); |
| break; /*end of configuration table */ |
| } else if ((u2CountryCodeTable == prCmd->u2CountryCode) && (fgChannelValid == TRUE)) { |
| |
| prCmdPwrLimit = &prCmd->rChannelPowerLimit[0]; |
| |
| if (prCmd->ucNum != 0) { |
| for (k = 0; k < prCmd->ucNum; k++) { |
| if (prCmdPwrLimit->ucCentralCh == |
| g_rRlmPowerLimitConfiguration[i].ucCentralCh) { |
| |
| /*Cmd setting (Default table information) and |
| * Configuration table has repetition channel entry, |
| * ex : Default table (ex: 2.4G, limit = 20dBm) --> |
| * ch1~14 limit =20dBm, |
| * Configuration table (ex: ch1, limit = 22dBm) --> |
| * ch 1 = 22 dBm |
| * Cmd final setting --> ch1 = 22dBm, ch12~14 = 20dBm |
| */ |
| kalMemCopy(&prCmdPwrLimit->cPwrLimitCCK, |
| &g_rRlmPowerLimitConfiguration[i].aucPwrLimit, |
| PWR_LIMIT_NUM); |
| |
| DBGLOG(RLM, INFO, |
| "Domain: CC=%c%c,ConfigCh=%d,Limit=%d,%d,%d,%d,%d,Fg=%d\n", |
| ((prCmd->u2CountryCode & 0xff00) >> 8), |
| (prCmd->u2CountryCode & 0x00ff), prCmdPwrLimit->ucCentralCh, |
| prCmdPwrLimit->cPwrLimitCCK, prCmdPwrLimit->cPwrLimit20, |
| prCmdPwrLimit->cPwrLimit40, prCmdPwrLimit->cPwrLimit80, |
| prCmdPwrLimit->cPwrLimit160, prCmdPwrLimit->ucFlag); |
| |
| break; |
| } |
| prCmdPwrLimit++; |
| } |
| if (k == prCmd->ucNum) { |
| |
| /*Full search cmd (Default table setting) no match channey, |
| * ex : Default table (ex: 2.4G, limit = 20dBm) --> |
| * ch1~14 limit =20dBm, |
| * Configuration table (ex: ch36, limit = 22dBm) --> |
| * ch 36 = 22 dBm |
| * Cmd final setting --> ch1~14 = 20dBm, ch36= 22dBm |
| */ |
| kalMemCopy(&prCmdPwrLimit->cPwrLimitCCK, |
| &g_rRlmPowerLimitConfiguration[i].aucPwrLimit, PWR_LIMIT_NUM); |
| prCmd->ucNum++; |
| |
| DBGLOG(RLM, INFO, |
| "Domain: Full CC=%c%c,ConfigCh=%d,Limit=%d,%d,%d,%d,%d,Fg=%d\n", |
| ((prCmd->u2CountryCode & 0xff00) >> 8), (prCmd->u2CountryCode & 0x00ff), |
| prCmdPwrLimit->ucCentralCh, prCmdPwrLimit->cPwrLimitCCK, |
| prCmdPwrLimit->cPwrLimit20, prCmdPwrLimit->cPwrLimit40, |
| prCmdPwrLimit->cPwrLimit80, prCmdPwrLimit->cPwrLimit160, |
| prCmdPwrLimit->ucFlag); |
| |
| } |
| } else { |
| |
| /*Default table power limit value are 63--> cmd table no channel entry |
| * ex : Default table (ex: 2.4G, limit = 63Bm) --> no channel entry in cmd, |
| * Configuration table (ex: ch36, limit = 22dBm) --> ch 36 = 22 dBm |
| * Cmd final setting --> ch36= 22dBm |
| */ |
| prCmdPwrLimit->ucCentralCh = g_rRlmPowerLimitConfiguration[i].ucCentralCh; |
| kalMemCopy(&prCmdPwrLimit->cPwrLimitCCK, &g_rRlmPowerLimitConfiguration[i].aucPwrLimit, |
| PWR_LIMIT_NUM); |
| prCmd->ucNum++; |
| |
| DBGLOG(RLM, INFO, "Domain: Default table power limit value are 63.\n"); |
| DBGLOG(RLM, INFO, "Domain: CC=%c%c,ConfigCh=%d,Limit=%d,%d,%d,%d,%d,Fg=%d\n", |
| ((prCmd->u2CountryCode & 0xff00) >> 8), |
| (prCmd->u2CountryCode & 0x00ff), prCmdPwrLimit->ucCentralCh, |
| prCmdPwrLimit->cPwrLimitCCK, prCmdPwrLimit->cPwrLimit20, |
| prCmdPwrLimit->cPwrLimit40, prCmdPwrLimit->cPwrLimit80, |
| prCmdPwrLimit->cPwrLimit160, prCmdPwrLimit->ucFlag); |
| |
| } |
| } |
| } |
| } |
| |
| /*----------------------------------------------------------------------------*/ |
| /*! |
| * @brief |
| * |
| * @param[in] |
| * |
| * @return (none) |
| */ |
| /*----------------------------------------------------------------------------*/ |
| VOID rlmDomainSendPwrLimitCmd_V2(P_ADAPTER_T prAdapter) |
| { |
| #if (CFG_SUPPORT_SINGLE_SKU == 1) |
| WLAN_STATUS rStatus; |
| UINT_32 u4SetQueryInfoLen; |
| UINT_32 ch_cnt; |
| struct wiphy *wiphy; |
| u8 band_idx, ch_idx; |
| P_CMD_SET_COUNTRY_CHANNEL_POWER_LIMIT_V2_T prCmd[KAL_NUM_BANDS] = {NULL}; |
| UINT_32 u4SetCmdTableMaxSize[KAL_NUM_BANDS] = {0}; |
| const INT_8 *prChannelList = NULL; |
| |
| |
| DBGLOG(RLM, INFO, "rlmDomainSendPwrLimitCmd()\n"); |
| |
| wiphy = priv_to_wiphy(prAdapter->prGlueInfo); |
| for (band_idx = 0; band_idx < KAL_NUM_BANDS; band_idx++) { |
| if (band_idx != KAL_BAND_2GHZ && band_idx != KAL_BAND_5GHZ) |
| continue; |
| |
| prChannelList = (band_idx == KAL_BAND_2GHZ) ? |
| gTx_Pwr_Limit_2g_Ch : gTx_Pwr_Limit_5g_Ch; |
| |
| ch_cnt = (band_idx == KAL_BAND_2GHZ) ? TX_PWR_LIMIT_2G_CH_NUM : |
| TX_PWR_LIMIT_5G_CH_NUM; |
| |
| if (!ch_cnt) |
| continue; |
| |
| u4SetCmdTableMaxSize[band_idx] = |
| sizeof(CMD_SET_COUNTRY_CHANNEL_POWER_LIMIT_V2_T) + |
| ch_cnt * sizeof(CMD_CHANNEL_POWER_LIMIT_V2); |
| |
| /* compile time assertion on firmware command structs */ |
| DATA_STRUCT_INSPECTING_ASSERT(sizeof(CMD_SET_COUNTRY_CHANNEL_POWER_LIMIT_V2_T) == 8); |
| DATA_STRUCT_INSPECTING_ASSERT(sizeof(CMD_CHANNEL_POWER_LIMIT_V2) == 40); |
| DATA_STRUCT_INSPECTING_ASSERT( |
| OFFSET_OF(CMD_SET_COUNTRY_CHANNEL_POWER_LIMIT_V2_T, rChannelPowerLimit) == |
| sizeof(CMD_SET_COUNTRY_CHANNEL_POWER_LIMIT_V2_T)); |
| DATA_STRUCT_INSPECTING_ASSERT( |
| OFFSET_OF(CMD_SET_COUNTRY_CHANNEL_POWER_LIMIT_V2_T, rChannelPowerLimit[1]) == |
| sizeof(CMD_SET_COUNTRY_CHANNEL_POWER_LIMIT_V2_T) + 1 * sizeof(CMD_CHANNEL_POWER_LIMIT_V2)); |
| DATA_STRUCT_INSPECTING_ASSERT( |
| OFFSET_OF(CMD_SET_COUNTRY_CHANNEL_POWER_LIMIT_V2_T, rChannelPowerLimit[2]) == |
| sizeof(CMD_SET_COUNTRY_CHANNEL_POWER_LIMIT_V2_T) + 2 * sizeof(CMD_CHANNEL_POWER_LIMIT_V2)); |
| |
| prCmd[band_idx] = cnmMemAlloc(prAdapter, RAM_TYPE_BUF, u4SetCmdTableMaxSize[band_idx]); |
| |
| |
| if (!prCmd[band_idx]) { |
| DBGLOG(RLM, ERROR, "Domain: no buf to send cmd\n"); |
| goto error; |
| } |
| |
| /*initialize tw pwr table*/ |
| kalMemSet(prCmd[band_idx], MAX_TX_POWER, u4SetCmdTableMaxSize[band_idx]); |
| |
| prCmd[band_idx]->ucNum = ch_cnt; |
| prCmd[band_idx]->eband = (band_idx == KAL_BAND_2GHZ) ? BAND_2G4 : BAND_5G; |
| prCmd[band_idx]->countryCode = rlmDomainGetCountryCode(); |
| |
| DBGLOG(RLM, INFO, "%s, active n_channels=%d, band=%d\n", __func__, ch_cnt, prCmd[band_idx]->eband); |
| |
| for (ch_idx = 0; ch_idx < ch_cnt; ch_idx++) { |
| prCmd[band_idx]->rChannelPowerLimit[ch_idx].ucCentralCh = |
| prChannelList[ch_idx]; |
| } |
| } |
| |
| |
| /* |
| * Get Max Tx Power from MT_TxPwrLimit.dat |
| */ |
| rlmDomainGetTxPwrLimit(rlmDomainGetCountryCode(), |
| prAdapter->prGlueInfo, |
| prCmd[KAL_BAND_2GHZ], |
| prCmd[KAL_BAND_5GHZ]); |
| |
| |
| for (band_idx = 0; band_idx < KAL_NUM_BANDS; band_idx++) { |
| UINT_8 ucRemainChNum, i, ucTempChNum, prCmdBatchNum; |
| UINT_32 u4BufSize = 0; |
| P_CMD_SET_COUNTRY_CHANNEL_POWER_LIMIT_V2_T prTempCmd = NULL; |
| ENUM_BAND_T eBand = (band_idx == KAL_BAND_2GHZ) ? |
| BAND_2G4 : BAND_5G; |
| |
| if (!prCmd[band_idx]) |
| continue; |
| |
| ucRemainChNum = prCmd[band_idx]->ucNum; |
| prCmdBatchNum = |
| (ucRemainChNum + TX_PWR_LIMIT_CMD_CH_NUM_THRESHOLD - 1) / |
| TX_PWR_LIMIT_CMD_CH_NUM_THRESHOLD; |
| |
| for (i = 0; i < prCmdBatchNum; i++) { |
| if (i == prCmdBatchNum - 1) |
| ucTempChNum = ucRemainChNum; |
| else |
| ucTempChNum = TX_PWR_LIMIT_CMD_CH_NUM_THRESHOLD; |
| |
| u4BufSize = sizeof(CMD_SET_COUNTRY_CHANNEL_POWER_LIMIT_V2_T) + |
| ucTempChNum * sizeof(CMD_CHANNEL_POWER_LIMIT_V2); |
| |
| prTempCmd = cnmMemAlloc(prAdapter, RAM_TYPE_BUF, u4BufSize); |
| |
| if (!prTempCmd) { |
| DBGLOG(RLM, ERROR, "Domain: no buf to send cmd\n"); |
| goto error; |
| } |
| |
| /*copy partial tx pwr limit*/ |
| prTempCmd->ucNum = ucTempChNum; |
| prTempCmd->eband = eBand; |
| prTempCmd->countryCode = rlmDomainGetCountryCode(); |
| kalMemCopy(&prTempCmd->rChannelPowerLimit[0], |
| &prCmd[band_idx]->rChannelPowerLimit[i * TX_PWR_LIMIT_CMD_CH_NUM_THRESHOLD], |
| ucTempChNum * sizeof(CMD_CHANNEL_POWER_LIMIT_V2)); |
| |
| u4SetQueryInfoLen = u4BufSize; |
| /* Update tx max. power info to chip */ |
| rStatus = wlanSendSetQueryCmd(prAdapter, /* prAdapter */ |
| CMD_ID_SET_COUNTRY_POWER_LIMIT, /* ucCID */ |
| TRUE, /* fgSetQuery */ |
| FALSE, /* fgNeedResp */ |
| FALSE, /* fgIsOid */ |
| NULL, /* pfCmdDoneHandler */ |
| NULL, /* pfCmdTimeoutHandler */ |
| u4SetQueryInfoLen, /* u4SetQueryInfoLen */ |
| (PUINT_8) prTempCmd, /* pucInfoBuffer */ |
| NULL, /* pvSetQueryBuffer */ |
| 0 /* u4SetQueryBufferLen */ |
| ); |
| |
| cnmMemFree(prAdapter, prTempCmd); |
| |
| ucRemainChNum -= ucTempChNum; |
| } |
| } |
| |
| error: |
| for (band_idx = 0; band_idx < KAL_NUM_BANDS; band_idx++) { |
| if (prCmd[band_idx]) |
| cnmMemFree(prAdapter, prCmd[band_idx]); |
| } |
| #endif |
| } |
| |
| VOID rlmDomainSendPwrLimitCmd(P_ADAPTER_T prAdapter) |
| { |
| P_CMD_SET_COUNTRY_CHANNEL_POWER_LIMIT_T prCmd; |
| WLAN_STATUS rStatus; |
| UINT_8 i; |
| UINT_16 u2DefaultTableIndex; |
| UINT_32 u4SetCmdTableMaxSize; |
| UINT_32 u4SetQueryInfoLen; |
| P_CMD_CHANNEL_POWER_LIMIT prCmdPwrLimit; /* for print usage */ |
| |
| if (regd_is_single_sku_en()) |
| return rlmDomainSendPwrLimitCmd_V2(prAdapter); |
| |
| |
| u4SetCmdTableMaxSize = |
| sizeof(CMD_SET_COUNTRY_CHANNEL_POWER_LIMIT_T) + |
| MAX_CMD_SUPPORT_CHANNEL_NUM * sizeof(CMD_CHANNEL_POWER_LIMIT); |
| |
| prCmd = cnmMemAlloc(prAdapter, RAM_TYPE_BUF, u4SetCmdTableMaxSize); |
| |
| if (!prCmd) { |
| DBGLOG(RLM, ERROR, "Domain: no buf to send cmd\n"); |
| return; |
| } |
| kalMemZero(prCmd, u4SetCmdTableMaxSize); |
| |
| u2DefaultTableIndex = |
| rlmDomainPwrLimitDefaultTableDecision(prAdapter, prAdapter->rWifiVar.rConnSettings.u2CountryCode); |
| |
| if (u2DefaultTableIndex != POWER_LIMIT_TABLE_NULL) { |
| |
| WLAN_GET_FIELD_BE16(&g_rRlmPowerLimitDefault[u2DefaultTableIndex].aucCountryCode[0], |
| &prCmd->u2CountryCode); |
| |
| prCmd->ucNum = 0; |
| |
| if (prCmd->u2CountryCode != COUNTRY_CODE_NULL) { |
| /*Command - default table information */ |
| rlmDomainBuildCmdByDefaultTable(prCmd, u2DefaultTableIndex); |
| |
| /*Command - configuration table information */ |
| rlmDomainBuildCmdByConfigTable(prAdapter, prCmd); |
| } |
| } |
| #if 0 |
| u4SetCmdTableMaxSize = |
| sizeof(CMD_SET_COUNTRY_CHANNEL_POWER_LIMIT_T) + |
| MAX_CMD_SUPPORT_CHANNEL_NUM * sizeof(CMD_CHANNEL_POWER_LIMIT); |
| |
| prCmd = cnmMemAlloc(prAdapter, RAM_TYPE_BUF, u4SetCmdTableMaxSize); |
| ASSERT(prCmd); |
| |
| /* To do: exception handle */ |
| if (!prCmd) { |
| DBGLOG(RLM, ERROR, "Domain: no buf to send cmd\n"); |
| return; |
| } |
| kalMemZero(prCmd, u4SetCmdTableMaxSize); /* TODO memzero */ |
| |
| if (u2TableIndex != POWER_LIMIT_TABLE_NULL && u2TableIndex < MAX_DEFAULT_TABLE_COUNTRY_NUM) { |
| |
| prCmd->u2CountryCode = (((UINT_16) g_rRlmCountryPowerLimitTable[u2TableIndex].aucCountryCode[0]) << 8) | |
| (((UINT_16) g_rRlmCountryPowerLimitTable[u2TableIndex].aucCountryCode[1]) & BITS(0, 7)); |
| prChPwrLimit = &g_rRlmCountryPowerLimitTable[u2TableIndex].rChannelPowerLimit[0]; |
| prCmdPwrLimit = &prCmd->rChannelPowerLimit[0]; |
| prCmd->ucNum = 0; |
| for (i = 0; i < MAX_CMD_SUPPORT_CHANNEL_NUM; i++) { |
| |
| if (prChPwrLimit->ucCentralCh != ENDCH) { |
| |
| /*Check Power limit table channel efficient or not */ |
| fgChannelValid = rlmDomainCheckChannelEntryValid(prAdapter, prChPwrLimit->ucCentralCh); |
| |
| /*Cmd set up */ |
| if (fgChannelValid) { |
| kalMemCopy(prCmdPwrLimit, prChPwrLimit, sizeof(CMD_CHANNEL_POWER_LIMIT)); |
| DBGLOG(RLM, INFO, |
| "Domain: ValidCh=%d,Limit=%d,%d,%d,%d,%d,Fg=%d\n", |
| prCmdPwrLimit->ucCentralCh, prCmdPwrLimit->cPwrLimitCCK, |
| prCmdPwrLimit->cPwrLimit20, prCmdPwrLimit->cPwrLimit40, |
| prCmdPwrLimit->cPwrLimit80, prCmdPwrLimit->cPwrLimit160, |
| prCmdPwrLimit->ucFlag); |
| prCmd->ucNum++; |
| prCmdPwrLimit++; |
| } else { |
| DBGLOG(RLM, INFO, |
| "Domain: Non-Ch=%d,Limit=%d,%d,%d,%d,%d,Fg=%d\n", |
| prChPwrLimit->ucCentralCh, prChPwrLimit->cPwrLimitCCK, |
| prChPwrLimit->cPwrLimit20, prChPwrLimit->cPwrLimit40, |
| prChPwrLimit->cPwrLimit80, prChPwrLimit->cPwrLimit160, |
| prChPwrLimit->ucFlag); |
| } |
| prChPwrLimit++; |
| } else { |
| /*End of the chanel entry */ |
| break; |
| } |
| }; |
| } |
| #endif |
| |
| if (prCmd->u2CountryCode != 0) { |
| DBGLOG(RLM, INFO, |
| "Domain: ValidCC =%c%c, ChNum=%d\n", ((prCmd->u2CountryCode & 0xff00) >> 8), |
| (prCmd->u2CountryCode & 0x00ff), prCmd->ucNum); |
| } else { |
| DBGLOG(RLM, INFO, "Domain: ValidCC =0x%04x, ChNum=%d\n", prCmd->u2CountryCode, prCmd->ucNum); |
| } |
| prCmdPwrLimit = &prCmd->rChannelPowerLimit[0]; |
| |
| for (i = 0; i < prCmd->ucNum; i++) { |
| DBGLOG(RLM, INFO, "Domain: Ch=%d,Limit=%d,%d,%d,%d,%d,Fg=%d\n", prCmdPwrLimit->ucCentralCh, |
| prCmdPwrLimit->cPwrLimitCCK, prCmdPwrLimit->cPwrLimit20, prCmdPwrLimit->cPwrLimit40, |
| prCmdPwrLimit->cPwrLimit80, prCmdPwrLimit->cPwrLimit160, prCmdPwrLimit->ucFlag); |
| prCmdPwrLimit++; |
| } |
| |
| u4SetQueryInfoLen = |
| (sizeof(CMD_SET_COUNTRY_CHANNEL_POWER_LIMIT_T) + (prCmd->ucNum) * sizeof(CMD_CHANNEL_POWER_LIMIT)); |
| |
| /* Update domain info to chip */ |
| if (prCmd->ucNum <= MAX_CMD_SUPPORT_CHANNEL_NUM) { |
| rStatus = wlanSendSetQueryCmd(prAdapter, /* prAdapter */ |
| CMD_ID_SET_COUNTRY_POWER_LIMIT, /* ucCID */ |
| TRUE, /* fgSetQuery */ |
| FALSE, /* fgNeedResp */ |
| FALSE, /* fgIsOid */ |
| NULL, /* pfCmdDoneHandler */ |
| NULL, /* pfCmdTimeoutHandler */ |
| u4SetQueryInfoLen, /* u4SetQueryInfoLen */ |
| (PUINT_8) prCmd, /* pucInfoBuffer */ |
| NULL, /* pvSetQueryBuffer */ |
| 0 /* u4SetQueryBufferLen */ |
| ); |
| } else { |
| DBGLOG(RLM, INFO, "Domain: illegal power limit table"); |
| } |
| |
| /* ASSERT(rStatus == WLAN_STATUS_PENDING); */ |
| |
| cnmMemFree(prAdapter, prCmd); |
| |
| } |
| #endif |
| BOOLEAN regd_is_single_sku_en(void) |
| { |
| #if (CFG_SUPPORT_SINGLE_SKU == 1) |
| return g_mtk_regd_control.en; |
| #else |
| return FALSE; |
| #endif |
| } |
| |
| #if (CFG_SUPPORT_SINGLE_SKU == 1) |
| BOOLEAN rlmDomainIsCtrlStateEqualTo(enum regd_state state) |
| { |
| return (g_mtk_regd_control.state == state) ? TRUE : FALSE; |
| } |
| |
| enum regd_state rlmDomainGetCtrlState(void) |
| { |
| return g_mtk_regd_control.state; |
| } |
| |
| |
| void rlmDomainResetActiveChannel(void) |
| { |
| g_mtk_regd_control.n_channel_active_2g = 0; |
| g_mtk_regd_control.n_channel_active_5g = 0; |
| } |
| |
| void rlmDomainAddActiveChannel(u8 band) |
| |
| { |
| if (band == KAL_BAND_2GHZ) |
| g_mtk_regd_control.n_channel_active_2g += 1; |
| else if (band == KAL_BAND_5GHZ) |
| g_mtk_regd_control.n_channel_active_5g += 1; |
| } |
| |
| u8 rlmDomainGetActiveChannelCount(u8 band) |
| { |
| if (band == KAL_BAND_2GHZ) |
| return g_mtk_regd_control.n_channel_active_2g; |
| else if (band == KAL_BAND_5GHZ) |
| return g_mtk_regd_control.n_channel_active_5g; |
| else |
| return 0; |
| } |
| |
| struct channel *rlmDomainGetActiveChannels(void) |
| { |
| return g_mtk_regd_control.channels; |
| } |
| |
| void rlmDomainSetDefaultCountryCode(void) |
| { |
| g_mtk_regd_control.alpha2 = COUNTRY_CODE_WW; |
| } |
| |
| void rlmDomainResetCtrlInfo(void) |
| { |
| if (g_mtk_regd_control.state == REGD_STATE_UNDEFINED) { |
| |
| memset(&g_mtk_regd_control, 0, sizeof(mtk_regd_control)); |
| |
| g_mtk_regd_control.state = REGD_STATE_INIT; |
| |
| rlmDomainSetDefaultCountryCode(); |
| |
| #if (CFG_SUPPORT_SINGLE_SKU_LOCAL_DB == 1) |
| g_mtk_regd_control.flag |= REGD_CTRL_FLAG_SUPPORT_LOCAL_REGD_DB; |
| #endif |
| } |
| } |
| |
| BOOLEAN rlmDomainIsUsingLocalRegDomainDataBase(void) |
| { |
| #if (CFG_SUPPORT_SINGLE_SKU_LOCAL_DB == 1) |
| return (g_mtk_regd_control.flag & REGD_CTRL_FLAG_SUPPORT_LOCAL_REGD_DB) ? TRUE : FALSE; |
| #else |
| return FALSE; |
| #endif |
| } |
| |
| bool rlmDomainIsSameCountryCode(char *alpha2, u8 size_of_alpha2) |
| { |
| u8 idx; |
| u32 alpha2_hex = 0; |
| |
| for (idx = 0; idx < size_of_alpha2; idx++) |
| alpha2_hex |= (alpha2[idx] << (idx * 8)); |
| |
| return (rlmDomainGetCountryCode() == alpha2_hex) ? TRUE : FALSE; |
| } |
| |
| void rlmDomainSetCountryCode(char *alpha2, u8 size_of_alpha2) |
| { |
| u8 max; |
| u8 buf_size; |
| |
| buf_size = sizeof(g_mtk_regd_control.alpha2); |
| max = (buf_size < size_of_alpha2) ? buf_size : size_of_alpha2; |
| |
| g_mtk_regd_control.alpha2 = rlmDomainAlpha2ToU32(alpha2, max); |
| } |
| void rlmDomainSetDfsRegion(enum nl80211_dfs_regions dfs_region) |
| { |
| g_mtk_regd_control.dfs_region = dfs_region; |
| } |
| |
| enum nl80211_dfs_regions rlmDomainGetDfsRegion(void) |
| { |
| return g_mtk_regd_control.dfs_region; |
| } |
| |
| void rlmDomainSetTempCountryCode(char *alpha2, u8 size_of_alpha2) |
| { |
| u8 idx, max; |
| u8 buf_size; |
| |
| buf_size = sizeof(g_mtk_regd_control.tmp_alpha2); |
| max = (buf_size < size_of_alpha2) ? buf_size : size_of_alpha2; |
| |
| g_mtk_regd_control.tmp_alpha2 = 0; |
| |
| for (idx = 0; idx < max; idx++) |
| g_mtk_regd_control.tmp_alpha2 |= (alpha2[idx] << (idx * 8)); |
| |
| } |
| |
| enum regd_state rlmDomainStateTransition(enum regd_state request_state, struct regulatory_request *pRequest) |
| { |
| enum regd_state next_state, old_state; |
| bool the_same = 0; |
| |
| old_state = g_mtk_regd_control.state; |
| next_state = REGD_STATE_INVALID; |
| |
| if (old_state == REGD_STATE_INVALID) |
| DBGLOG(RLM, ERROR, "%s(): invalid state. trasntion is not allowed.\n", __func__); |
| |
| |
| switch (request_state) { |
| case REGD_STATE_SET_WW_CORE: |
| if ((old_state == REGD_STATE_SET_WW_CORE) || (old_state == REGD_STATE_INIT) |
| || old_state == REGD_STATE_SET_COUNTRY_USER |
| || old_state == REGD_STATE_SET_COUNTRY_IE) |
| next_state = request_state; |
| |
| break; |
| |
| case REGD_STATE_SET_COUNTRY_USER: |
| /* Allow user to set multiple times */ |
| if ((old_state == REGD_STATE_SET_WW_CORE) || (old_state == REGD_STATE_INIT) |
| || old_state == REGD_STATE_SET_COUNTRY_USER |
| || old_state == REGD_STATE_SET_COUNTRY_IE) |
| next_state = request_state; |
| else |
| DBGLOG(RLM, ERROR, "Invalid old state = %d\n", old_state); |
| break; |
| case REGD_STATE_SET_COUNTRY_DRIVER: |
| if (old_state == REGD_STATE_SET_COUNTRY_USER) { |
| /* |
| * Error. |
| * Mixing using set_country_by_user and set_country_by_driver |
| * is not allowed. |
| */ |
| break; |
| } |
| |
| next_state = request_state; |
| break; |
| |
| case REGD_STATE_SET_COUNTRY_IE: |
| next_state = request_state; |
| break; |
| |
| default: |
| break; |
| } |
| |
| if (next_state == REGD_STATE_INVALID) { |
| DBGLOG(RLM, ERROR, "%s(): ERROR. trasntion to invalid state. o=%x, r=%x, s=%x\n", |
| __func__, old_state, request_state, the_same); |
| } else |
| DBGLOG(RLM, INFO, "%s(): trasntion to state = %x (old = %x)\n", |
| __func__, next_state, g_mtk_regd_control.state); |
| |
| g_mtk_regd_control.state = next_state; |
| |
| return g_mtk_regd_control.state; |
| } |
| |
| void rlmDomainSetRefWiphy(struct wiphy *pWiphy) |
| { |
| g_mtk_regd_control.pRefWiphy = pWiphy; |
| } |
| |
| struct wiphy *rlmDomainGetRefWiphy(void) |
| { |
| return g_mtk_regd_control.pRefWiphy; |
| } |
| |
| /** |
| * rlmDomainChannelFlagString - Transform channel flags to readable string |
| * |
| * @ flags: the ieee80211_channel->flags for a channel |
| * @ buf: string buffer to put the transformed string |
| * @ buf_size: size of the buf |
| **/ |
| void rlmDomainChannelFlagString(u32 flags, char *buf, size_t buf_size) |
| { |
| INT_32 buf_written = 0; |
| |
| if (!flags || !buf || !buf_size) |
| return; |
| |
| if (flags & IEEE80211_CHAN_DISABLED) { |
| LOGBUF(buf, ((INT_32)buf_size), buf_written, "DISABLED "); |
| /* If DISABLED, don't need to check other flags */ |
| return; |
| } |
| if (flags & IEEE80211_CHAN_PASSIVE_FLAG) |
| LOGBUF(buf, ((INT_32)buf_size), buf_written, IEEE80211_CHAN_PASSIVE_STR " "); |
| if (flags & IEEE80211_CHAN_RADAR) |
| LOGBUF(buf, ((INT_32)buf_size), buf_written, "RADAR "); |
| if (flags & IEEE80211_CHAN_NO_HT40PLUS) |
| LOGBUF(buf, ((INT_32)buf_size), buf_written, "NO_HT40PLUS "); |
| if (flags & IEEE80211_CHAN_NO_HT40MINUS) |
| LOGBUF(buf, ((INT_32)buf_size), buf_written, "NO_HT40MINUS "); |
| if (flags & IEEE80211_CHAN_NO_80MHZ) |
| LOGBUF(buf, ((INT_32)buf_size), buf_written, "NO_80MHZ "); |
| if (flags & IEEE80211_CHAN_NO_160MHZ) |
| LOGBUF(buf, ((INT_32)buf_size), buf_written, "NO_160MHZ "); |
| } |
| |
| void rlmDomainParsingChannel(IN struct wiphy *pWiphy) |
| { |
| u32 band_idx, ch_idx; |
| u32 ch_count; |
| struct ieee80211_supported_band *sband; |
| struct ieee80211_channel *chan; |
| struct channel *pCh; |
| char chan_flag_string[64] = {0}; |
| |
| |
| if (!pWiphy) { |
| DBGLOG(RLM, ERROR, "%s(): ERROR. pWiphy = NULL.\n", __func__); |
| ASSERT(0); |
| return; |
| } |
| |
| |
| /* |
| * Ready to parse the channel for bands |
| */ |
| |
| rlmDomainResetActiveChannel(); |
| rlmDomainSetRefWiphy(pWiphy); |
| |
| ch_count = 0; |
| for (band_idx = 0; band_idx < KAL_NUM_BANDS; band_idx++) { |
| sband = pWiphy->bands[band_idx]; |
| if (!sband) |
| continue; |
| |
| for (ch_idx = 0; ch_idx < sband->n_channels; ch_idx++) { |
| chan = &sband->channels[ch_idx]; |
| pCh = (rlmDomainGetActiveChannels() + ch_count); |
| /* Parse flags and get readable string */ |
| rlmDomainChannelFlagString(chan->flags, chan_flag_string, sizeof(chan_flag_string)); |
| |
| if (chan->flags & IEEE80211_CHAN_DISABLED) { |
| DBGLOG(RLM, INFO, "channels[%d][%d]: ch%d (freq = %d) flags=0x%x [ %s]\n", |
| band_idx, ch_idx, chan->hw_value, chan->center_freq, chan->flags, |
| chan_flag_string); |
| continue; |
| } |
| |
| /* Allowable channel */ |
| if (ch_count == MAX_SUPPORTED_CH_COUNT) { |
| DBGLOG(RLM, ERROR, "%s(): no buffer to store channel information.\n", __func__); |
| break; |
| } |
| |
| rlmDomainAddActiveChannel(band_idx); |
| |
| DBGLOG(RLM, INFO, "channels[%d][%d]: ch%d (freq = %d) flgs=0x%x [ %s]\n", |
| band_idx, ch_idx, chan->hw_value, chan->center_freq, chan->flags, |
| chan_flag_string); |
| |
| pCh->chNum = chan->hw_value; |
| pCh->flags = chan->flags; |
| |
| ch_count += 1; |
| } |
| |
| } |
| } |
| void rlmExtractChannelInfo(u32 max_ch_count, struct acctive_channel_list *prBuff) |
| { |
| u32 ch_count, idx; |
| struct channel *pCh; |
| |
| prBuff->n_channels_2g = rlmDomainGetActiveChannelCount(KAL_BAND_2GHZ); |
| prBuff->n_channels_5g = rlmDomainGetActiveChannelCount(KAL_BAND_5GHZ); |
| ch_count = prBuff->n_channels_2g + prBuff->n_channels_5g; |
| |
| if (ch_count > max_ch_count) { |
| ch_count = max_ch_count; |
| DBGLOG(RLM, WARN, "%s(); active channel list is not a complete one.\n", __func__); |
| } |
| |
| for (idx = 0; idx < ch_count; idx++) { |
| pCh = &(prBuff->channels[idx]); |
| |
| pCh->chNum = (rlmDomainGetActiveChannels() + idx)->chNum; |
| pCh->flags = (rlmDomainGetActiveChannels() + idx)->flags; |
| } |
| |
| } |
| |
| const struct ieee80211_regdomain *rlmDomainSearchRegdomainFromLocalDataBase(char *alpha2) |
| { |
| #if (CFG_SUPPORT_SINGLE_SKU_LOCAL_DB == 1) |
| u8 idx; |
| const struct mtk_regdomain *prRegd; |
| |
| idx = 0; |
| while (g_prRegRuleTable[idx]) { |
| prRegd = g_prRegRuleTable[idx]; |
| |
| if ((prRegd->country_code[0] == alpha2[0]) && |
| (prRegd->country_code[1] == alpha2[1]) && |
| (prRegd->country_code[2] == alpha2[2]) && |
| (prRegd->country_code[3] == alpha2[3])) |
| return prRegd->prRegdRules; |
| |
| idx++; |
| } |
| |
| DBGLOG(RLM, ERROR, "%s(): Error, Cannot find the correct RegDomain. country = %s.\n", |
| __func__, alpha2); |
| DBGLOG(RLM, INFO, " Set as default WW.\n"); |
| |
| return &default_regdom_ww; /*default world wide*/ |
| #else |
| return NULL; |
| #endif |
| } |
| |
| |
| const struct ieee80211_regdomain *rlmDomainGetLocalDefaultRegd(void) |
| { |
| #if (CFG_SUPPORT_SINGLE_SKU_LOCAL_DB == 1) |
| return &default_regdom_ww; |
| #else |
| return NULL; |
| #endif |
| } |
| P_GLUE_INFO_T rlmDomainGetGlueInfo(void) |
| { |
| return g_mtk_regd_control.pGlueInfo; |
| } |
| |
| bool rlmDomainIsEfuseUsed(void) |
| { |
| return g_mtk_regd_control.isEfuseCountryCodeUsed; |
| } |
| #endif |
| |
| WLAN_STATUS rlmDomainExtractSingleSkuInfoFromFirmware(IN P_ADAPTER_T prAdapter, IN PUINT_8 pucEventBuf) |
| { |
| #if (CFG_SUPPORT_SINGLE_SKU == 1) |
| P_SINGLE_SKU_INFO prSkuInfo = (P_SINGLE_SKU_INFO)pucEventBuf; |
| |
| g_mtk_regd_control.en = TRUE; |
| |
| if (prSkuInfo->isEfuseValid) { |
| if (!rlmDomainIsUsingLocalRegDomainDataBase()) { |
| |
| DBGLOG(RLM, ERROR, "%s(): Error. In efuse mode, must use local data base.\n", __func__); |
| |
| ASSERT(0); |
| return WLAN_STATUS_NOT_SUPPORTED; /*force using local db if getting country code from efuse*/ |
| } |
| |
| rlmDomainSetCountryCode((char *)&prSkuInfo->u4EfuseCountryCode, sizeof(prSkuInfo->u4EfuseCountryCode)); |
| g_mtk_regd_control.isEfuseCountryCodeUsed = TRUE; |
| |
| } |
| #endif |
| |
| return WLAN_STATUS_SUCCESS; |
| } |
| |
| void rlmDomainSendInfoToFirmware(IN P_ADAPTER_T prAdapter) |
| { |
| #if (CFG_SUPPORT_SINGLE_SKU == 1) |
| struct regulatory_request request; |
| struct regulatory_request *prReq = NULL; |
| |
| if (!regd_is_single_sku_en()) |
| return; /*not support single sku*/ |
| |
| if (g_mtk_regd_control.isEfuseCountryCodeUsed) { |
| request.initiator = NL80211_REGDOM_SET_BY_DRIVER; |
| prReq = &request; |
| } |
| |
| g_mtk_regd_control.pGlueInfo = prAdapter->prGlueInfo; |
| mtk_reg_notify(priv_to_wiphy(prAdapter->prGlueInfo), prReq); |
| #endif |
| } |
| |
| ENUM_CHNL_EXT_T rlmSelectSecondaryChannelType(P_ADAPTER_T prAdapter, ENUM_BAND_T band, u8 primary_ch) |
| { |
| #if (CFG_SUPPORT_SINGLE_SKU == 1) |
| u8 below_ch, above_ch; |
| |
| below_ch = primary_ch - CHNL_SPAN_20; |
| above_ch = primary_ch + CHNL_SPAN_20; |
| |
| if (rlmDomainIsLegalChannel(prAdapter, band, above_ch)) |
| return CHNL_EXT_SCA; |
| |
| if (rlmDomainIsLegalChannel(prAdapter, band, below_ch)) |
| return CHNL_EXT_SCB; |
| |
| #endif |
| |
| return CHNL_EXT_SCN; |
| } |
| |
| void rlmDomainOidSetCountry(IN P_ADAPTER_T prAdapter, char *country, u8 size_of_country) |
| { |
| #if (CFG_SUPPORT_SINGLE_SKU == 1) |
| struct regulatory_request request; |
| |
| if (rlmDomainIsUsingLocalRegDomainDataBase()) { |
| rlmDomainSetTempCountryCode(country, size_of_country); |
| request.initiator = NL80211_REGDOM_SET_BY_DRIVER; |
| mtk_reg_notify(priv_to_wiphy(prAdapter->prGlueInfo), &request); |
| } else { |
| DBGLOG(RLM, INFO, "%s(): Using driver hint to query CRDA getting regd.\n", __func__); |
| regulatory_hint(priv_to_wiphy(prAdapter->prGlueInfo), country); |
| } |
| #endif |
| } |
| |
| u32 rlmDomainGetCountryCode(void) |
| { |
| #if (CFG_SUPPORT_SINGLE_SKU == 1) |
| return g_mtk_regd_control.alpha2; |
| #else |
| return 0; |
| #endif |
| } |
| |
| u32 rlmDomainGetTempCountryCode(void) |
| { |
| #if (CFG_SUPPORT_SINGLE_SKU == 1) |
| return g_mtk_regd_control.tmp_alpha2; |
| #else |
| return 0; |
| #endif |
| } |
| |
| void rlmDomainAssert(BOOLEAN cond) |
| { |
| /* bypass this check because single sku is not enable */ |
| if (!regd_is_single_sku_en()) |
| return; |
| |
| if (!cond) { |
| WARN_ON(1); |
| DBGLOG(RLM, ERROR, "[WARNING!!] RLM unexpected case.\n"); |
| } |
| |
| } |
| |
| |