p2p_rlm.c 31 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955
  1. /*
  2. ** Id: @(#) p2p_rlm.c@@
  3. */
  4. /*! \file "p2p_rlm.c"
  5. \brief
  6. */
  7. /*******************************************************************************
  8. * C O M P I L E R F L A G S
  9. ********************************************************************************
  10. */
  11. /*******************************************************************************
  12. * E X T E R N A L R E F E R E N C E S
  13. ********************************************************************************
  14. */
  15. #include "precomp.h"
  16. #include "rlm.h"
  17. /*******************************************************************************
  18. * C O N S T A N T S
  19. ********************************************************************************
  20. */
  21. /*******************************************************************************
  22. * D A T A T Y P E S
  23. ********************************************************************************
  24. */
  25. /*******************************************************************************
  26. * P U B L I C D A T A
  27. ********************************************************************************
  28. */
  29. /*******************************************************************************
  30. * P R I V A T E D A T A
  31. ********************************************************************************
  32. */
  33. /*******************************************************************************
  34. * M A C R O S
  35. ********************************************************************************
  36. */
  37. /*******************************************************************************
  38. * F U N C T I O N D E C L A R A T I O N S
  39. ********************************************************************************
  40. */
  41. /*******************************************************************************
  42. * F U N C T I O N S
  43. ********************************************************************************
  44. */
  45. /*----------------------------------------------------------------------------*/
  46. /*!
  47. * \brief Init AP Bss
  48. *
  49. * \param[in]
  50. *
  51. * \return none
  52. */
  53. /*----------------------------------------------------------------------------*/
  54. VOID rlmBssInitForAP(P_ADAPTER_T prAdapter, P_BSS_INFO_T prBssInfo)
  55. {
  56. ENUM_BAND_T eBand;
  57. UINT_8 ucChannel, i;
  58. ENUM_CHNL_EXT_T eSCO;
  59. ASSERT(prAdapter);
  60. ASSERT(prBssInfo);
  61. if (prBssInfo->eCurrentOPMode != OP_MODE_ACCESS_POINT)
  62. return;
  63. /* Operation band, channel shall be ready before invoking this function.
  64. * Bandwidth may be ready if other network is connected
  65. */
  66. prBssInfo->fg40mBwAllowed = FALSE;
  67. prBssInfo->fgAssoc40mBwAllowed = FALSE;
  68. prBssInfo->eBssSCO = CHNL_EXT_SCN;
  69. /* Check if AP BW can set to 40MHz
  70. * If any of BSS is setup in 40MHz, the second BSS would prefer to use 20MHz
  71. * in order to remain in SCC case
  72. */
  73. if (cnmBss40mBwPermitted(prAdapter, prBssInfo->ucBssIndex)) {
  74. /* In this case, the first BSS's SCO is 40MHz and known, so AP can
  75. * apply 40MHz bandwidth, but the first BSS's SCO may be changed
  76. * later if its Beacon lost timeout occurs
  77. */
  78. if (cnmPreferredChannel(prAdapter, &eBand, &ucChannel, &eSCO) &&
  79. eSCO != CHNL_EXT_SCN && ucChannel == prBssInfo->ucPrimaryChannel && eBand == prBssInfo->eBand) {
  80. prBssInfo->eBssSCO = eSCO;
  81. } else {
  82. prBssInfo->eBssSCO = rlmDecideScoForAP(prAdapter, prBssInfo);
  83. }
  84. if (prBssInfo->eBssSCO != CHNL_EXT_SCN) {
  85. prBssInfo->fg40mBwAllowed = TRUE;
  86. prBssInfo->fgAssoc40mBwAllowed = TRUE;
  87. prBssInfo->ucHtOpInfo1 = (UINT_8)
  88. (((UINT_32) prBssInfo->eBssSCO) | HT_OP_INFO1_STA_CHNL_WIDTH);
  89. rlmUpdateBwByChListForAP(prAdapter, prBssInfo);
  90. }
  91. }
  92. /* Filled the VHT BW/S1/S2 and MCS rate set */
  93. if (prBssInfo->ucPhyTypeSet & PHY_TYPE_BIT_VHT) {
  94. for (i = 0; i < 8; i++)
  95. prBssInfo->u2VhtBasicMcsSet |= BITS(2 * i, (2 * i + 1));
  96. prBssInfo->u2VhtBasicMcsSet &= (VHT_CAP_INFO_MCS_MAP_MCS9 << VHT_CAP_INFO_MCS_1SS_OFFSET);
  97. if (cnmGetBssMaxBw(prAdapter, prBssInfo->ucBssIndex) < MAX_BW_80MHZ || prBssInfo->eBand == BAND_2G4) {
  98. prBssInfo->ucVhtChannelWidth = VHT_OP_CHANNEL_WIDTH_20_40;
  99. prBssInfo->ucVhtChannelFrequencyS1 = 0;
  100. prBssInfo->ucVhtChannelFrequencyS2 = 0;
  101. } else if (cnmGetBssMaxBw(prAdapter, prBssInfo->ucBssIndex) == MAX_BW_80MHZ) {
  102. prBssInfo->ucVhtChannelWidth = VHT_OP_CHANNEL_WIDTH_80;
  103. prBssInfo->ucVhtChannelFrequencyS1 = nicGetVhtS1(prBssInfo->ucPrimaryChannel);
  104. prBssInfo->ucVhtChannelFrequencyS2 = 0;
  105. } else {
  106. /* 4 TODO: BW160 / BW80+80 support */
  107. }
  108. } else {
  109. prBssInfo->ucVhtChannelWidth = VHT_OP_CHANNEL_WIDTH_20_40;
  110. prBssInfo->ucVhtChannelFrequencyS1 = 0;
  111. prBssInfo->ucVhtChannelFrequencyS2 = 0;
  112. }
  113. DBGLOG(RLM, INFO, "AP SCO=%d VhtChannelWidth=%d VhtFreqS1=%d VhtFreqS2=%d Band=%d\n",
  114. prBssInfo->eBssSCO,
  115. prBssInfo->ucVhtChannelWidth,
  116. prBssInfo->ucVhtChannelFrequencyS1,
  117. prBssInfo->ucVhtChannelFrequencyS2,
  118. prBssInfo->eBand);
  119. }
  120. /*----------------------------------------------------------------------------*/
  121. /*!
  122. * \brief For probe response (GO, IBSS) and association response
  123. *
  124. * \param[in]
  125. *
  126. * \return none
  127. */
  128. /*----------------------------------------------------------------------------*/
  129. VOID rlmRspGenerateObssScanIE(P_ADAPTER_T prAdapter, P_MSDU_INFO_T prMsduInfo)
  130. {
  131. P_BSS_INFO_T prBssInfo;
  132. P_IE_OBSS_SCAN_PARAM_T prObssScanIe;
  133. P_STA_RECORD_T prStaRec = (P_STA_RECORD_T) NULL;
  134. ASSERT(prAdapter);
  135. ASSERT(prMsduInfo);
  136. prStaRec = cnmGetStaRecByIndex(prAdapter, prMsduInfo->ucStaRecIndex);
  137. prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, prMsduInfo->ucBssIndex);
  138. if (!prBssInfo)
  139. return;
  140. if (!IS_BSS_ACTIVE(prBssInfo))
  141. return;
  142. if (RLM_NET_IS_11N(prBssInfo) && /* !RLM_NET_IS_BOW(prBssInfo) && FIXME. */
  143. prBssInfo->eCurrentOPMode == OP_MODE_ACCESS_POINT &&
  144. (!prStaRec || (prStaRec->ucPhyTypeSet & PHY_TYPE_SET_802_11N)) &&
  145. prBssInfo->eBand == BAND_2G4 && prBssInfo->eBssSCO != CHNL_EXT_SCN) {
  146. prObssScanIe = (P_IE_OBSS_SCAN_PARAM_T)
  147. (((PUINT_8) prMsduInfo->prPacket) + prMsduInfo->u2FrameLength);
  148. /* Add 20/40 BSS coexistence IE */
  149. prObssScanIe->ucId = ELEM_ID_OBSS_SCAN_PARAMS;
  150. prObssScanIe->ucLength = sizeof(IE_OBSS_SCAN_PARAM_T) - ELEM_HDR_LEN;
  151. prObssScanIe->u2ScanPassiveDwell = dot11OBSSScanPassiveDwell;
  152. prObssScanIe->u2ScanActiveDwell = dot11OBSSScanActiveDwell;
  153. prObssScanIe->u2TriggerScanInterval = dot11BSSWidthTriggerScanInterval;
  154. prObssScanIe->u2ScanPassiveTotalPerChnl = dot11OBSSScanPassiveTotalPerChannel;
  155. prObssScanIe->u2ScanActiveTotalPerChnl = dot11OBSSScanActiveTotalPerChannel;
  156. prObssScanIe->u2WidthTransDelayFactor = dot11BSSWidthChannelTransitionDelayFactor;
  157. prObssScanIe->u2ScanActivityThres = dot11OBSSScanActivityThreshold;
  158. ASSERT(IE_SIZE(prObssScanIe) <= (ELEM_HDR_LEN + ELEM_MAX_LEN_OBSS_SCAN));
  159. prMsduInfo->u2FrameLength += IE_SIZE(prObssScanIe);
  160. }
  161. }
  162. /*----------------------------------------------------------------------------*/
  163. /*!
  164. * \brief P2P GO.
  165. *
  166. * \param[in]
  167. *
  168. * \return none
  169. */
  170. /*----------------------------------------------------------------------------*/
  171. BOOLEAN rlmUpdateBwByChListForAP(P_ADAPTER_T prAdapter, P_BSS_INFO_T prBssInfo)
  172. {
  173. UINT_8 ucLevel;
  174. BOOLEAN fgBwChange;
  175. ASSERT(prAdapter);
  176. ASSERT(prBssInfo);
  177. fgBwChange = FALSE;
  178. if (prBssInfo->eBssSCO == CHNL_EXT_SCN)
  179. return fgBwChange;
  180. ucLevel = rlmObssChnlLevel(prBssInfo, prBssInfo->eBand, prBssInfo->ucPrimaryChannel, prBssInfo->eBssSCO);
  181. if (ucLevel == CHNL_LEVEL0) {
  182. /* Forced to 20MHz, so extended channel is SCN and STA width is zero */
  183. prBssInfo->fgObssActionForcedTo20M = TRUE;
  184. if (prBssInfo->ucHtOpInfo1 != (UINT_8) CHNL_EXT_SCN) {
  185. prBssInfo->ucHtOpInfo1 = (UINT_8) CHNL_EXT_SCN;
  186. fgBwChange = TRUE;
  187. }
  188. cnmTimerStartTimer(prAdapter, &prBssInfo->rObssScanTimer, OBSS_20_40M_TIMEOUT * MSEC_PER_SEC);
  189. }
  190. /* Clear up all channel lists */
  191. prBssInfo->auc2G_20mReqChnlList[0] = 0;
  192. prBssInfo->auc2G_NonHtChnlList[0] = 0;
  193. prBssInfo->auc2G_PriChnlList[0] = 0;
  194. prBssInfo->auc2G_SecChnlList[0] = 0;
  195. prBssInfo->auc5G_20mReqChnlList[0] = 0;
  196. prBssInfo->auc5G_NonHtChnlList[0] = 0;
  197. prBssInfo->auc5G_PriChnlList[0] = 0;
  198. prBssInfo->auc5G_SecChnlList[0] = 0;
  199. return fgBwChange;
  200. }
  201. /*----------------------------------------------------------------------------*/
  202. /*!
  203. * \brief
  204. *
  205. * \param[in]
  206. *
  207. * \return none
  208. */
  209. /*----------------------------------------------------------------------------*/
  210. VOID rlmProcessPublicAction(P_ADAPTER_T prAdapter, P_SW_RFB_T prSwRfb)
  211. {
  212. P_ACTION_20_40_COEXIST_FRAME prRxFrame;
  213. P_IE_20_40_COEXIST_T prCoexist;
  214. P_IE_INTOLERANT_CHNL_REPORT_T prChnlReport;
  215. P_BSS_INFO_T prBssInfo;
  216. P_STA_RECORD_T prStaRec;
  217. PUINT_8 pucIE;
  218. UINT_16 u2IELength, u2Offset;
  219. UINT_8 i, j;
  220. ASSERT(prAdapter);
  221. ASSERT(prSwRfb);
  222. prRxFrame = (P_ACTION_20_40_COEXIST_FRAME) prSwRfb->pvHeader;
  223. prStaRec = cnmGetStaRecByIndex(prAdapter, prSwRfb->ucStaRecIdx);
  224. if (prRxFrame->ucAction != ACTION_PUBLIC_20_40_COEXIST || !prStaRec || prStaRec->ucStaState != STA_STATE_3 ||
  225. prSwRfb->u2PacketLen < (WLAN_MAC_MGMT_HEADER_LEN + 5) || prSwRfb->prStaRec->ucBssIndex !=
  226. /* HIF_RX_HDR_GET_NETWORK_IDX(prSwRfb->prHifRxHdr) != */
  227. prStaRec->ucBssIndex) {
  228. return;
  229. }
  230. prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, prStaRec->ucBssIndex);
  231. ASSERT(prBssInfo);
  232. if (!IS_BSS_ACTIVE(prBssInfo) ||
  233. prBssInfo->eCurrentOPMode != OP_MODE_ACCESS_POINT || prBssInfo->eBssSCO == CHNL_EXT_SCN) {
  234. return;
  235. }
  236. prCoexist = &prRxFrame->rBssCoexist;
  237. if (prCoexist->ucData & (BSS_COEXIST_40M_INTOLERANT | BSS_COEXIST_20M_REQ)) {
  238. ASSERT(prBssInfo->auc2G_20mReqChnlList[0] <= CHNL_LIST_SZ_2G);
  239. for (i = 1; i <= prBssInfo->auc2G_20mReqChnlList[0] && i <= CHNL_LIST_SZ_2G; i++) {
  240. if (prBssInfo->auc2G_20mReqChnlList[i] == prBssInfo->ucPrimaryChannel)
  241. break;
  242. }
  243. if ((i > prBssInfo->auc2G_20mReqChnlList[0]) && (i <= CHNL_LIST_SZ_2G)) {
  244. prBssInfo->auc2G_20mReqChnlList[i] = prBssInfo->ucPrimaryChannel;
  245. prBssInfo->auc2G_20mReqChnlList[0]++;
  246. }
  247. }
  248. /* Process intolerant channel report IE */
  249. pucIE = (PUINT_8) &prRxFrame->rChnlReport;
  250. u2IELength = prSwRfb->u2PacketLen - (WLAN_MAC_MGMT_HEADER_LEN + 5);
  251. IE_FOR_EACH(pucIE, u2IELength, u2Offset) {
  252. switch (IE_ID(pucIE)) {
  253. case ELEM_ID_20_40_INTOLERANT_CHNL_REPORT:
  254. prChnlReport = (P_IE_INTOLERANT_CHNL_REPORT_T) pucIE;
  255. if (prChnlReport->ucLength <= 1)
  256. break;
  257. /* To do: process regulatory class. Now we assume 2.4G band */
  258. for (j = 0; j < prChnlReport->ucLength - 1; j++) {
  259. /* Update non-HT channel list */
  260. ASSERT(prBssInfo->auc2G_NonHtChnlList[0] <= CHNL_LIST_SZ_2G);
  261. for (i = 1; i <= prBssInfo->auc2G_NonHtChnlList[0] && i <= CHNL_LIST_SZ_2G; i++) {
  262. if (prBssInfo->auc2G_NonHtChnlList[i] == prChnlReport->aucChannelList[j])
  263. break;
  264. }
  265. if ((i > prBssInfo->auc2G_NonHtChnlList[0]) && (i <= CHNL_LIST_SZ_2G)) {
  266. prBssInfo->auc2G_NonHtChnlList[i] = prChnlReport->aucChannelList[j];
  267. prBssInfo->auc2G_NonHtChnlList[0]++;
  268. }
  269. }
  270. break;
  271. default:
  272. break;
  273. }
  274. } /* end of IE_FOR_EACH */
  275. if (rlmUpdateBwByChListForAP(prAdapter, prBssInfo)) {
  276. bssUpdateBeaconContent(prAdapter, prBssInfo->ucBssIndex);
  277. rlmSyncOperationParams(prAdapter, prBssInfo);
  278. }
  279. /* Check if OBSS scan exemption response should be sent */
  280. if (prCoexist->ucData & BSS_COEXIST_OBSS_SCAN_EXEMPTION_REQ)
  281. rlmObssScanExemptionRsp(prAdapter, prBssInfo, prSwRfb);
  282. }
  283. /*----------------------------------------------------------------------------*/
  284. /*!
  285. * \brief
  286. *
  287. * \param[in]
  288. *
  289. * \return none
  290. */
  291. /*----------------------------------------------------------------------------*/
  292. VOID rlmProcessHtAction(P_ADAPTER_T prAdapter, P_SW_RFB_T prSwRfb)
  293. {
  294. P_ACTION_NOTIFY_CHNL_WIDTH_FRAME prRxFrame;
  295. P_STA_RECORD_T prStaRec;
  296. ASSERT(prAdapter);
  297. ASSERT(prSwRfb);
  298. prRxFrame = (P_ACTION_NOTIFY_CHNL_WIDTH_FRAME) prSwRfb->pvHeader;
  299. prStaRec = cnmGetStaRecByIndex(prAdapter, prSwRfb->ucStaRecIdx);
  300. if (prRxFrame->ucAction != ACTION_HT_NOTIFY_CHANNEL_WIDTH ||
  301. !prStaRec || prStaRec->ucStaState != STA_STATE_3 ||
  302. prSwRfb->u2PacketLen < sizeof(ACTION_NOTIFY_CHNL_WIDTH_FRAME)) {
  303. return;
  304. }
  305. /* To do: depending regulation class 13 and 14 based on spec
  306. * Note: (ucChannelWidth==1) shall restored back to original capability,
  307. * not current setting to 40MHz BW here
  308. */
  309. if (prRxFrame->ucChannelWidth == 0)
  310. prStaRec->u2HtCapInfo &= ~HT_CAP_INFO_SUP_CHNL_WIDTH;
  311. else if (prRxFrame->ucChannelWidth == 1)
  312. prStaRec->u2HtCapInfo |= HT_CAP_INFO_SUP_CHNL_WIDTH;
  313. cnmStaRecChangeState(prAdapter, prStaRec, STA_STATE_3);
  314. }
  315. /*----------------------------------------------------------------------------*/
  316. /*!
  317. * \brief
  318. *
  319. * \param[in]
  320. *
  321. * \return none
  322. */
  323. /*----------------------------------------------------------------------------*/
  324. VOID rlmHandleObssStatusEventPkt(P_ADAPTER_T prAdapter, P_EVENT_AP_OBSS_STATUS_T prObssStatus)
  325. {
  326. P_BSS_INFO_T prBssInfo;
  327. ASSERT(prAdapter);
  328. ASSERT(prObssStatus);
  329. ASSERT(prObssStatus->ucBssIndex < MAX_BSS_INDEX);
  330. prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, prObssStatus->ucBssIndex);
  331. if (prBssInfo->eCurrentOPMode != OP_MODE_ACCESS_POINT)
  332. return;
  333. prBssInfo->fgObssErpProtectMode = (BOOLEAN) prObssStatus->ucObssErpProtectMode;
  334. prBssInfo->eObssHtProtectMode = (ENUM_HT_PROTECT_MODE_T) prObssStatus->ucObssHtProtectMode;
  335. prBssInfo->eObssGfOperationMode = (ENUM_GF_MODE_T) prObssStatus->ucObssGfOperationMode;
  336. prBssInfo->fgObssRifsOperationMode = (BOOLEAN) prObssStatus->ucObssRifsOperationMode;
  337. prBssInfo->fgObssBeaconForcedTo20M = (BOOLEAN) prObssStatus->ucObssBeaconForcedTo20M;
  338. /* Check if Beacon content need to be updated */
  339. rlmUpdateParamsForAP(prAdapter, prBssInfo, TRUE);
  340. }
  341. /*----------------------------------------------------------------------------*/
  342. /*!
  343. * \brief It is only for AP mode in NETWORK_TYPE_P2P_INDEX.
  344. *
  345. * \param[in]
  346. *
  347. * \return none
  348. */
  349. /*----------------------------------------------------------------------------*/
  350. VOID rlmUpdateParamsForAP(P_ADAPTER_T prAdapter, P_BSS_INFO_T prBssInfo, BOOLEAN fgUpdateBeacon)
  351. {
  352. P_LINK_T prStaList;
  353. P_STA_RECORD_T prStaRec;
  354. BOOLEAN fgErpProtectMode, fgSta40mIntolerant;
  355. BOOLEAN fgUseShortPreamble, fgUseShortSlotTime;
  356. ENUM_HT_PROTECT_MODE_T eHtProtectMode;
  357. ENUM_GF_MODE_T eGfOperationMode;
  358. UINT_8 ucHtOpInfo1;
  359. ASSERT(prAdapter);
  360. ASSERT(prBssInfo);
  361. if (!IS_BSS_ACTIVE(prBssInfo) || prBssInfo->eCurrentOPMode != OP_MODE_ACCESS_POINT)
  362. return;
  363. fgErpProtectMode = FALSE;
  364. eHtProtectMode = HT_PROTECT_MODE_NONE;
  365. eGfOperationMode = GF_MODE_NORMAL;
  366. fgSta40mIntolerant = FALSE;
  367. fgUseShortPreamble = prBssInfo->fgIsShortPreambleAllowed;
  368. fgUseShortSlotTime = TRUE;
  369. ucHtOpInfo1 = (UINT_8) CHNL_EXT_SCN;
  370. prStaList = &prBssInfo->rStaRecOfClientList;
  371. LINK_FOR_EACH_ENTRY(prStaRec, prStaList, rLinkEntry, STA_RECORD_T) {
  372. if (!prStaRec) {
  373. DBGLOG(P2P, WARN, "NULL STA_REC ptr in BSS client list\n");
  374. bssDumpClientList(prAdapter, prBssInfo);
  375. break;
  376. }
  377. if (prStaRec->fgIsInUse && prStaRec->ucStaState == STA_STATE_3 &&
  378. prStaRec->ucBssIndex == prBssInfo->ucBssIndex) {
  379. if (!(prStaRec->ucPhyTypeSet & (PHY_TYPE_SET_802_11GN | PHY_TYPE_SET_802_11A))) {
  380. /* B-only mode, so mode 1 (ERP protection) */
  381. fgErpProtectMode = TRUE;
  382. }
  383. if (!(prStaRec->ucPhyTypeSet & PHY_TYPE_SET_802_11N)) {
  384. /* BG-only or A-only */
  385. eHtProtectMode = HT_PROTECT_MODE_NON_HT;
  386. } else if (!(prStaRec->u2HtCapInfo & HT_CAP_INFO_SUP_CHNL_WIDTH)) {
  387. /* 20MHz-only */
  388. if ((eHtProtectMode == HT_PROTECT_MODE_NONE) && (prBssInfo->eBssSCO != CHNL_EXT_SCN))
  389. eHtProtectMode = HT_PROTECT_MODE_20M;
  390. }
  391. if (!(prStaRec->u2HtCapInfo & HT_CAP_INFO_HT_GF))
  392. eGfOperationMode = GF_MODE_PROTECT;
  393. if (!(prStaRec->u2CapInfo & CAP_INFO_SHORT_PREAMBLE))
  394. fgUseShortPreamble = FALSE;
  395. if (!(prStaRec->u2CapInfo & CAP_INFO_SHORT_SLOT_TIME))
  396. fgUseShortSlotTime = FALSE;
  397. if (prStaRec->u2HtCapInfo & HT_CAP_INFO_40M_INTOLERANT)
  398. fgSta40mIntolerant = TRUE;
  399. }
  400. } /* end of LINK_FOR_EACH_ENTRY */
  401. /* Check if HT operation IE about 20/40M bandwidth shall be updated */
  402. if (prBssInfo->eBssSCO != CHNL_EXT_SCN) {
  403. if (/*!LINK_IS_EMPTY(prStaList) && */ !fgSta40mIntolerant &&
  404. !prBssInfo->fgObssActionForcedTo20M && !prBssInfo->fgObssBeaconForcedTo20M) {
  405. ucHtOpInfo1 = (UINT_8)
  406. (((UINT_32) prBssInfo->eBssSCO) | HT_OP_INFO1_STA_CHNL_WIDTH);
  407. }
  408. }
  409. /* Check if any new parameter may be updated */
  410. if (prBssInfo->fgErpProtectMode != fgErpProtectMode ||
  411. prBssInfo->eHtProtectMode != eHtProtectMode ||
  412. prBssInfo->eGfOperationMode != eGfOperationMode ||
  413. prBssInfo->ucHtOpInfo1 != ucHtOpInfo1 ||
  414. prBssInfo->fgUseShortPreamble != fgUseShortPreamble ||
  415. prBssInfo->fgUseShortSlotTime != fgUseShortSlotTime) {
  416. prBssInfo->fgErpProtectMode = fgErpProtectMode;
  417. prBssInfo->eHtProtectMode = eHtProtectMode;
  418. prBssInfo->eGfOperationMode = eGfOperationMode;
  419. prBssInfo->ucHtOpInfo1 = ucHtOpInfo1;
  420. prBssInfo->fgUseShortPreamble = fgUseShortPreamble;
  421. prBssInfo->fgUseShortSlotTime = fgUseShortSlotTime;
  422. if (fgUseShortSlotTime)
  423. prBssInfo->u2CapInfo |= CAP_INFO_SHORT_SLOT_TIME;
  424. else
  425. prBssInfo->u2CapInfo &= ~CAP_INFO_SHORT_SLOT_TIME;
  426. rlmSyncOperationParams(prAdapter, prBssInfo);
  427. fgUpdateBeacon = TRUE;
  428. }
  429. /* Update Beacon content if related IE content is changed */
  430. if (fgUpdateBeacon)
  431. bssUpdateBeaconContent(prAdapter, prBssInfo->ucBssIndex);
  432. }
  433. /*----------------------------------------------------------------------------*/
  434. /*!
  435. * \brief Initial the channel list from the domain information.
  436. * This function is called after P2P initial and Domain information changed.
  437. * Make sure the device is disconnected while changing domain information.
  438. *
  439. * \param[in] prAdapter Pointer of ADAPTER_T
  440. *
  441. * \return boolean value if probe response frame is
  442. */
  443. /*----------------------------------------------------------------------------*/
  444. VOID rlmFuncInitialChannelList(IN P_ADAPTER_T prAdapter)
  445. {
  446. P_P2P_CONNECTION_SETTINGS_T prP2pConnSetting = (P_P2P_CONNECTION_SETTINGS_T) NULL;
  447. P_DOMAIN_INFO_ENTRY prDomainInfoEntry = (P_DOMAIN_INFO_ENTRY) NULL;
  448. P_DOMAIN_SUBBAND_INFO prDomainSubBand = (P_DOMAIN_SUBBAND_INFO) NULL;
  449. P_CHANNEL_ENTRY_FIELD_T prChannelEntryField = (P_CHANNEL_ENTRY_FIELD_T) NULL;
  450. UINT_32 u4Idx = 0, u4IdxII = 0;
  451. UINT_8 ucBufferSize = P2P_MAX_SUPPORTED_CHANNEL_LIST_SIZE;
  452. #if 0
  453. UINT_8 ucSocialChnlSupport = 0, ucAutoChnl = 0;
  454. #endif
  455. do {
  456. ASSERT_BREAK(prAdapter != NULL);
  457. prP2pConnSetting = prAdapter->rWifiVar.prP2PConnSettings;
  458. #if 0
  459. ucAutoChnl = prP2pConnSetting->ucOperatingChnl;
  460. #endif
  461. prDomainInfoEntry = rlmDomainGetDomainInfo(prAdapter);
  462. ASSERT_BREAK((prDomainInfoEntry != NULL) && (prP2pConnSetting != NULL));
  463. prChannelEntryField = (P_CHANNEL_ENTRY_FIELD_T) prP2pConnSetting->aucChannelEntriesField;
  464. for (u4Idx = 0; u4Idx < MAX_SUBBAND_NUM; u4Idx++) {
  465. prDomainSubBand = &prDomainInfoEntry->rSubBand[u4Idx];
  466. if (((prDomainSubBand->ucBand == BAND_5G) && (!prAdapter->fgEnable5GBand))
  467. || (prDomainSubBand->ucBand == BAND_NULL)) {
  468. continue;
  469. }
  470. if (ucBufferSize < (P2P_ATTRI_LEN_CHANNEL_ENTRY + prDomainSubBand->ucNumChannels)) {
  471. /* Buffer is not enough to include all supported channels. */
  472. break; /* for */
  473. }
  474. prChannelEntryField->ucRegulatoryClass = prDomainSubBand->ucRegClass;
  475. prChannelEntryField->ucNumberOfChannels = prDomainSubBand->ucNumChannels;
  476. for (u4IdxII = 0; u4IdxII < prDomainSubBand->ucNumChannels; u4IdxII++) {
  477. prChannelEntryField->aucChannelList[u4IdxII] =
  478. prDomainSubBand->ucFirstChannelNum + (u4IdxII * prDomainSubBand->ucChannelSpan);
  479. #if 0
  480. switch (prChannelEntryField->aucChannelList[u4IdxII]) {
  481. case 1:
  482. ucSocialChnlSupport = 1;
  483. break;
  484. case 6:
  485. ucSocialChnlSupport = 6;
  486. break;
  487. case 11:
  488. ucSocialChnlSupport = 11;
  489. break;
  490. default:
  491. break;
  492. }
  493. #endif
  494. }
  495. if (ucBufferSize >= (P2P_ATTRI_LEN_CHANNEL_ENTRY + prChannelEntryField->ucNumberOfChannels))
  496. ucBufferSize -= (P2P_ATTRI_LEN_CHANNEL_ENTRY + prChannelEntryField->ucNumberOfChannels);
  497. else
  498. break;
  499. prChannelEntryField =
  500. (P_CHANNEL_ENTRY_FIELD_T) ((ULONG) prChannelEntryField +
  501. P2P_ATTRI_LEN_CHANNEL_ENTRY +
  502. (ULONG) prChannelEntryField->ucNumberOfChannels);
  503. }
  504. #if 0
  505. if (prP2pConnSetting->ucListenChnl == 0) {
  506. prP2pConnSetting->ucListenChnl = P2P_DEFAULT_LISTEN_CHANNEL;
  507. if (ucSocialChnlSupport != 0) {
  508. /* 1. User Not Set LISTEN channel.
  509. * 2. Social channel is not empty.
  510. */
  511. prP2pConnSetting->ucListenChnl = ucSocialChnlSupport;
  512. }
  513. }
  514. #endif
  515. /* TODO: 20110921 frog - */
  516. /* If LISTEN channel is not set,
  517. * a random supported channel would be set.
  518. * If no social channel is supported, DEFAULT channel would be set.
  519. */
  520. prP2pConnSetting->ucRfChannelListSize = P2P_MAX_SUPPORTED_CHANNEL_LIST_SIZE - ucBufferSize;
  521. #if 0
  522. if (prP2pConnSetting->ucOperatingChnl == 0) { /* User not set OPERATE channel. */
  523. if (scnQuerySparseChannel(prAdapter, NULL, &ucAutoChnl))
  524. break; /* while */
  525. ucBufferSize = prP2pConnSetting->ucRfChannelListSize;
  526. prChannelEntryField = (P_CHANNEL_ENTRY_FIELD_T) prP2pConnSetting->aucChannelEntriesField;
  527. while (ucBufferSize != 0) {
  528. if (prChannelEntryField->ucNumberOfChannels != 0) {
  529. ucAutoChnl = prChannelEntryField->aucChannelList[0];
  530. break; /* while */
  531. }
  532. else {
  533. prChannelEntryField =
  534. (P_CHANNEL_ENTRY_FIELD_T) ((UINT_32) prChannelEntryField
  535. + P2P_ATTRI_LEN_CHANNEL_ENTRY + (UINT_32)
  536. prChannelEntryField->ucNumberOfChannels);
  537. ucBufferSize -=
  538. (P2P_ATTRI_LEN_CHANNEL_ENTRY + prChannelEntryField->ucNumberOfChannels);
  539. }
  540. }
  541. }
  542. #endif
  543. /* We assume user would not set a channel not in the channel list.
  544. * If so, the operating channel still depends on target device supporting capability.
  545. */
  546. /* TODO: 20110921 frog - */
  547. /* If the Operating channel is not set, a channel from supported channel list is set automatically.
  548. * If there is no supported channel in channel list, a DEFAULT channel is set.
  549. */
  550. } while (FALSE);
  551. #if 0
  552. prP2pConnSetting->ucOperatingChnl = ucAutoChnl;
  553. #endif
  554. } /* rlmFuncInitialChannelList */
  555. /*----------------------------------------------------------------------------*/
  556. /*!
  557. * \brief Find a common channel list from the local channel list info & target channel list info.
  558. *
  559. * \param[in] prAdapter Pointer of ADAPTER_T
  560. *
  561. * \return boolean value if probe response frame is
  562. */
  563. /*----------------------------------------------------------------------------*/
  564. VOID
  565. rlmFuncCommonChannelList(IN P_ADAPTER_T prAdapter,
  566. IN P_CHANNEL_ENTRY_FIELD_T prChannelEntryII, IN UINT_8 ucChannelListSize)
  567. {
  568. P_P2P_CONNECTION_SETTINGS_T prP2pConnSetting = (P_P2P_CONNECTION_SETTINGS_T) NULL;
  569. P_CHANNEL_ENTRY_FIELD_T prChannelEntryI =
  570. (P_CHANNEL_ENTRY_FIELD_T) NULL, prChannelEntryIII = (P_CHANNEL_ENTRY_FIELD_T) NULL;
  571. UINT_8 aucCommonChannelList[P2P_MAX_SUPPORTED_CHANNEL_LIST_SIZE];
  572. UINT_8 ucOriChnlSize = 0, ucNewChnlSize = 0;
  573. do {
  574. ASSERT_BREAK(prAdapter != NULL);
  575. prP2pConnSetting = prAdapter->rWifiVar.prP2PConnSettings;
  576. prChannelEntryIII = (P_CHANNEL_ENTRY_FIELD_T) aucCommonChannelList;
  577. while (ucChannelListSize > 0) {
  578. prChannelEntryI = (P_CHANNEL_ENTRY_FIELD_T) prP2pConnSetting->aucChannelEntriesField;
  579. ucOriChnlSize = prP2pConnSetting->ucRfChannelListSize;
  580. while (ucOriChnlSize > 0) {
  581. if (prChannelEntryI->ucRegulatoryClass == prChannelEntryII->ucRegulatoryClass) {
  582. prChannelEntryIII->ucRegulatoryClass = prChannelEntryI->ucRegulatoryClass;
  583. /* TODO: Currently we assume that the regulatory class the same,
  584. * the channels are the same. */
  585. kalMemCopy(prChannelEntryIII->aucChannelList,
  586. prChannelEntryII->aucChannelList,
  587. prChannelEntryII->ucNumberOfChannels);
  588. prChannelEntryIII->ucNumberOfChannels = prChannelEntryII->ucNumberOfChannels;
  589. ucNewChnlSize +=
  590. P2P_ATTRI_LEN_CHANNEL_ENTRY + prChannelEntryIII->ucNumberOfChannels;
  591. prChannelEntryIII =
  592. (P_CHANNEL_ENTRY_FIELD_T) ((ULONG) prChannelEntryIII +
  593. P2P_ATTRI_LEN_CHANNEL_ENTRY +
  594. (ULONG) prChannelEntryIII->ucNumberOfChannels);
  595. }
  596. ucOriChnlSize -= (P2P_ATTRI_LEN_CHANNEL_ENTRY + prChannelEntryI->ucNumberOfChannels);
  597. prChannelEntryI =
  598. (P_CHANNEL_ENTRY_FIELD_T) ((ULONG) prChannelEntryI +
  599. P2P_ATTRI_LEN_CHANNEL_ENTRY +
  600. (ULONG) prChannelEntryI->ucNumberOfChannels);
  601. }
  602. ucChannelListSize -= (P2P_ATTRI_LEN_CHANNEL_ENTRY + prChannelEntryII->ucNumberOfChannels);
  603. prChannelEntryII = (P_CHANNEL_ENTRY_FIELD_T) ((ULONG) prChannelEntryII +
  604. P2P_ATTRI_LEN_CHANNEL_ENTRY +
  605. (ULONG) prChannelEntryII->ucNumberOfChannels);
  606. }
  607. kalMemCopy(prP2pConnSetting->aucChannelEntriesField, aucCommonChannelList, ucNewChnlSize);
  608. prP2pConnSetting->ucRfChannelListSize = ucNewChnlSize;
  609. } while (FALSE);
  610. } /* rlmFuncCommonChannelList */
  611. /*----------------------------------------------------------------------------*/
  612. /*!
  613. * \brief
  614. *
  615. * \param[in]
  616. *
  617. * \return none
  618. */
  619. /*----------------------------------------------------------------------------*/
  620. UINT_8 rlmFuncFindOperatingClass(IN P_ADAPTER_T prAdapter, IN UINT_8 ucChannelNum)
  621. {
  622. UINT_8 ucRegulatoryClass = 0, ucBufferSize = 0;
  623. P_P2P_CONNECTION_SETTINGS_T prP2pConnSetting = (P_P2P_CONNECTION_SETTINGS_T) NULL;
  624. P_CHANNEL_ENTRY_FIELD_T prChannelEntryField = (P_CHANNEL_ENTRY_FIELD_T) NULL;
  625. UINT_32 u4Idx = 0;
  626. do {
  627. ASSERT_BREAK(prAdapter != NULL);
  628. prP2pConnSetting = prAdapter->rWifiVar.prP2PConnSettings;
  629. ucBufferSize = prP2pConnSetting->ucRfChannelListSize;
  630. prChannelEntryField = (P_CHANNEL_ENTRY_FIELD_T) prP2pConnSetting->aucChannelEntriesField;
  631. while (ucBufferSize != 0) {
  632. for (u4Idx = 0; u4Idx < prChannelEntryField->ucNumberOfChannels; u4Idx++) {
  633. if (prChannelEntryField->aucChannelList[u4Idx] == ucChannelNum) {
  634. ucRegulatoryClass = prChannelEntryField->ucRegulatoryClass;
  635. break;
  636. }
  637. }
  638. if (ucRegulatoryClass != 0)
  639. break; /* while */
  640. prChannelEntryField =
  641. (P_CHANNEL_ENTRY_FIELD_T) ((ULONG) prChannelEntryField +
  642. P2P_ATTRI_LEN_CHANNEL_ENTRY +
  643. (ULONG) prChannelEntryField->ucNumberOfChannels);
  644. ucBufferSize -= (P2P_ATTRI_LEN_CHANNEL_ENTRY + prChannelEntryField->ucNumberOfChannels);
  645. }
  646. } while (FALSE);
  647. return ucRegulatoryClass;
  648. } /* rlmFuncFindOperatingClass */
  649. /*----------------------------------------------------------------------------*/
  650. /*!
  651. * \brief
  652. *
  653. * \param[in]
  654. *
  655. * \return none
  656. */
  657. /*----------------------------------------------------------------------------*/
  658. BOOLEAN
  659. rlmFuncFindAvailableChannel(IN P_ADAPTER_T prAdapter,
  660. IN UINT_8 ucCheckChnl,
  661. IN PUINT_8 pucSuggestChannel, IN BOOLEAN fgIsSocialChannel, IN BOOLEAN fgIsDefaultChannel)
  662. {
  663. BOOLEAN fgIsResultAvailable = FALSE;
  664. P_CHANNEL_ENTRY_FIELD_T prChannelEntry = (P_CHANNEL_ENTRY_FIELD_T) NULL;
  665. P_P2P_CONNECTION_SETTINGS_T prP2pConnSetting = (P_P2P_CONNECTION_SETTINGS_T) NULL;
  666. UINT_8 ucBufferSize = 0, ucIdx = 0, ucChannelSelected = 0;
  667. do {
  668. ASSERT_BREAK(prAdapter != NULL);
  669. if (fgIsDefaultChannel)
  670. ucChannelSelected = P2P_DEFAULT_LISTEN_CHANNEL;
  671. prP2pConnSetting = prAdapter->rWifiVar.prP2PConnSettings;
  672. ucBufferSize = prP2pConnSetting->ucRfChannelListSize;
  673. prChannelEntry = (P_CHANNEL_ENTRY_FIELD_T) prP2pConnSetting->aucChannelEntriesField;
  674. while ((ucBufferSize != 0) && (!fgIsResultAvailable)) {
  675. for (ucIdx = 0; ucIdx < prChannelEntry->ucNumberOfChannels; ucIdx++) {
  676. if ((!fgIsSocialChannel) ||
  677. (prChannelEntry->aucChannelList[ucIdx] == 1) ||
  678. (prChannelEntry->aucChannelList[ucIdx] == 6) ||
  679. (prChannelEntry->aucChannelList[ucIdx] == 11)) {
  680. if (prChannelEntry->aucChannelList[ucIdx] <= 11) {
  681. /* 2.4G. */
  682. ucChannelSelected = prChannelEntry->aucChannelList[ucIdx];
  683. } else if ((prChannelEntry->aucChannelList[ucIdx] < 52)
  684. && (prChannelEntry->aucChannelList[ucIdx] > 14)) {
  685. /* 2.4G + 5G. */
  686. ucChannelSelected = prChannelEntry->aucChannelList[ucIdx];
  687. }
  688. if (ucChannelSelected == ucCheckChnl) {
  689. fgIsResultAvailable = TRUE;
  690. break;
  691. }
  692. }
  693. }
  694. ucBufferSize -= (P2P_ATTRI_LEN_CHANNEL_ENTRY + prChannelEntry->ucNumberOfChannels);
  695. prChannelEntry = (P_CHANNEL_ENTRY_FIELD_T) ((ULONG) prChannelEntry +
  696. P2P_ATTRI_LEN_CHANNEL_ENTRY +
  697. (ULONG) prChannelEntry->ucNumberOfChannels);
  698. }
  699. if ((!fgIsResultAvailable) && (pucSuggestChannel != NULL)) {
  700. DBGLOG(P2P, TRACE,
  701. "The request channel %d is not available, sugguested channel:%d\n",
  702. ucCheckChnl, ucChannelSelected);
  703. /* Given a suggested channel. */
  704. *pucSuggestChannel = ucChannelSelected;
  705. }
  706. } while (FALSE);
  707. return fgIsResultAvailable;
  708. }
  709. /*----------------------------------------------------------------------------*/
  710. /*!
  711. * \brief
  712. *
  713. * \param[in]
  714. *
  715. * \return none
  716. */
  717. /*----------------------------------------------------------------------------*/
  718. ENUM_CHNL_EXT_T rlmDecideScoForAP(P_ADAPTER_T prAdapter, P_BSS_INFO_T prBssInfo)
  719. {
  720. P_DOMAIN_SUBBAND_INFO prSubband;
  721. P_DOMAIN_INFO_ENTRY prDomainInfo;
  722. UINT_8 ucSecondChannel, i, j;
  723. ENUM_CHNL_EXT_T eSCO;
  724. ENUM_CHNL_EXT_T eTempSCO;
  725. eSCO = CHNL_EXT_SCN;
  726. eTempSCO = CHNL_EXT_SCN;
  727. if (prBssInfo->eBand == BAND_2G4) {
  728. if (prBssInfo->ucPrimaryChannel != 14)
  729. eSCO = (prBssInfo->ucPrimaryChannel > 7) ? CHNL_EXT_SCB : CHNL_EXT_SCA;
  730. } else {
  731. prDomainInfo = rlmDomainGetDomainInfo(prAdapter);
  732. ASSERT(prDomainInfo);
  733. for (i = 0; i < MAX_SUBBAND_NUM; i++) {
  734. prSubband = &prDomainInfo->rSubBand[i];
  735. if (prSubband->ucBand == prBssInfo->eBand) {
  736. for (j = 0; j < prSubband->ucNumChannels; j++) {
  737. if ((prSubband->ucFirstChannelNum + j * prSubband->ucChannelSpan)
  738. == prBssInfo->ucPrimaryChannel) {
  739. eSCO = (j & 1) ? CHNL_EXT_SCB : CHNL_EXT_SCA;
  740. break;
  741. }
  742. }
  743. if (j < prSubband->ucNumChannels)
  744. break; /* Found */
  745. }
  746. }
  747. }
  748. /* Check if it is boundary channel and 40MHz BW is permitted */
  749. if (eSCO != CHNL_EXT_SCN) {
  750. ucSecondChannel = (eSCO == CHNL_EXT_SCA) ?
  751. (prBssInfo->ucPrimaryChannel + 4) : (prBssInfo->ucPrimaryChannel - 4);
  752. if (!rlmDomainIsLegalChannel(prAdapter, prBssInfo->eBand, ucSecondChannel))
  753. eSCO = CHNL_EXT_SCN;
  754. }
  755. /* Overwrite SCO settings by wifi cfg */
  756. if (IS_BSS_P2P(prBssInfo)) {
  757. /* AP mode */
  758. if (p2pFuncIsAPMode(prAdapter->rWifiVar.prP2PConnSettings)) {
  759. if (prAdapter->rWifiVar.ucApSco == CHNL_EXT_SCA || prAdapter->rWifiVar.ucApSco == CHNL_EXT_SCB)
  760. eTempSCO = (ENUM_CHNL_EXT_T) prAdapter->rWifiVar.ucApSco;
  761. }
  762. /* P2P mode */
  763. else {
  764. if (prAdapter->rWifiVar.ucP2pGoSco == CHNL_EXT_SCA ||
  765. prAdapter->rWifiVar.ucP2pGoSco == CHNL_EXT_SCB) {
  766. eTempSCO = (ENUM_CHNL_EXT_T) prAdapter->rWifiVar.ucP2pGoSco;
  767. }
  768. }
  769. /* Check again if it is boundary channel and 40MHz BW is permitted */
  770. if (eTempSCO != CHNL_EXT_SCN) {
  771. ucSecondChannel = (eTempSCO == CHNL_EXT_SCA) ?
  772. (prBssInfo->ucPrimaryChannel + 4) : (prBssInfo->ucPrimaryChannel - 4);
  773. if (rlmDomainIsLegalChannel(prAdapter, prBssInfo->eBand, ucSecondChannel))
  774. eSCO = eTempSCO;
  775. }
  776. }
  777. return eSCO;
  778. }