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