support different wifi bt chip auto compatible
[firefly-linux-kernel-4.4.55.git] / drivers / net / wireless / rockchip_wlan / mt5931 / 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->fgIsInUse && prStaRec->ucStaState == STA_STATE_3 &&
487             prStaRec->ucNetTypeIndex == prBssInfo->ucNetTypeIndex) {
488             if (!(prStaRec->ucPhyTypeSet &
489                   (PHY_TYPE_SET_802_11GN | PHY_TYPE_SET_802_11A))) {
490                 /* B-only mode, so mode 1 (ERP protection) */
491                 fgErpProtectMode = TRUE;
492             }
493
494             if (!(prStaRec->ucPhyTypeSet & PHY_TYPE_SET_802_11N)) {
495                 /* BG-only or A-only */
496                 eHtProtectMode = HT_PROTECT_MODE_NON_HT;
497             }
498             else if (!(prStaRec->u2HtCapInfo & HT_CAP_INFO_SUP_CHNL_WIDTH)) {
499                 /* 20MHz-only */
500                 if (eHtProtectMode == HT_PROTECT_MODE_NONE) {
501                     eHtProtectMode = HT_PROTECT_MODE_20M;
502                 }
503             }
504
505             if (!(prStaRec->u2HtCapInfo & HT_CAP_INFO_HT_GF)) {
506                 eGfOperationMode = GF_MODE_PROTECT;
507             }
508
509             if (!(prStaRec->u2CapInfo & CAP_INFO_SHORT_PREAMBLE)) {
510                 fgUseShortPreamble = FALSE;
511             }
512
513             if (!(prStaRec->u2CapInfo & CAP_INFO_SHORT_SLOT_TIME)) {
514                 fgUseShortSlotTime = FALSE;
515             }
516
517             if (prStaRec->u2HtCapInfo & HT_CAP_INFO_40M_INTOLERANT) {
518                 fgSta40mIntolerant = TRUE;
519             }
520         }
521     } /* end of LINK_FOR_EACH_ENTRY */
522
523     /* Check if HT operation IE about 20/40M bandwidth shall be updated */
524     if (prBssInfo->eBssSCO != CHNL_EXT_SCN) {
525         if (/*!LINK_IS_EMPTY(prStaList) && */ !fgSta40mIntolerant &&
526             !prBssInfo->fgObssActionForcedTo20M &&
527             !prBssInfo->fgObssBeaconForcedTo20M) {
528
529             ucHtOpInfo1 = (UINT_8)
530                 (((UINT_32) prBssInfo->eBssSCO) | HT_OP_INFO1_STA_CHNL_WIDTH);
531         }
532     }
533
534     /* Check if any new parameter may be updated */
535     if (prBssInfo->fgErpProtectMode != fgErpProtectMode ||
536         prBssInfo->eHtProtectMode != eHtProtectMode ||
537         prBssInfo->eGfOperationMode != eGfOperationMode ||
538         prBssInfo->ucHtOpInfo1 != ucHtOpInfo1 ||
539         prBssInfo->fgUseShortPreamble != fgUseShortPreamble ||
540         prBssInfo->fgUseShortSlotTime != fgUseShortSlotTime) {
541
542         prBssInfo->fgErpProtectMode = fgErpProtectMode;
543         prBssInfo->eHtProtectMode = eHtProtectMode;
544         prBssInfo->eGfOperationMode = eGfOperationMode;
545         prBssInfo->ucHtOpInfo1 = ucHtOpInfo1;
546         prBssInfo->fgUseShortPreamble = fgUseShortPreamble;
547         prBssInfo->fgUseShortSlotTime = fgUseShortSlotTime;
548
549         if (fgUseShortSlotTime) {
550             prBssInfo->u2CapInfo |= CAP_INFO_SHORT_SLOT_TIME;
551         }
552         else {
553             prBssInfo->u2CapInfo &= ~CAP_INFO_SHORT_SLOT_TIME;
554         }
555
556         rlmSyncOperationParams(prAdapter, prBssInfo);
557         fgUpdateBeacon = TRUE;
558     }
559
560     /* Update Beacon content if related IE content is changed */
561     if (fgUpdateBeacon) {
562         bssUpdateBeaconContent(prAdapter, prBssInfo->ucNetTypeIndex);
563     }
564 }
565
566
567 /*----------------------------------------------------------------------------*/
568 /*!
569 * \brief    Initial the channel list from the domain information.
570 *                 This function is called after P2P initial and Domain information changed.
571 *                 Make sure the device is disconnected while changing domain information.
572 *
573 * \param[in] prAdapter  Pointer of ADAPTER_T
574 *
575 * \return boolean value if probe response frame is
576 */
577 /*----------------------------------------------------------------------------*/
578 VOID
579 rlmFuncInitialChannelList (
580     IN P_ADAPTER_T prAdapter
581     )
582 {
583     P_P2P_CONNECTION_SETTINGS_T prP2pConnSetting = (P_P2P_CONNECTION_SETTINGS_T)NULL;
584     P_DOMAIN_INFO_ENTRY prDomainInfoEntry = (P_DOMAIN_INFO_ENTRY)NULL;
585     P_DOMAIN_SUBBAND_INFO prDomainSubBand = (P_DOMAIN_SUBBAND_INFO)NULL;
586     P_CHANNEL_ENTRY_FIELD_T prChannelEntryField = (P_CHANNEL_ENTRY_FIELD_T)NULL;
587     UINT_32 u4Idx = 0, u4IdxII = 0;
588     UINT_8 ucBufferSize = P2P_MAX_SUPPORTED_CHANNEL_LIST_SIZE;
589 #if 0
590     UINT_8 ucSocialChnlSupport = 0, ucAutoChnl = 0;
591 #endif
592
593     do {
594         ASSERT_BREAK(prAdapter != NULL);
595
596         prP2pConnSetting = prAdapter->rWifiVar.prP2PConnSettings;
597 #if 0
598         ucAutoChnl = prP2pConnSetting->ucOperatingChnl;
599 #endif
600
601         prDomainInfoEntry = rlmDomainGetDomainInfo(prAdapter);
602
603         ASSERT_BREAK((prDomainInfoEntry != NULL) && (prP2pConnSetting != NULL));
604
605         prChannelEntryField = (P_CHANNEL_ENTRY_FIELD_T)prP2pConnSetting->aucChannelEntriesField;
606
607         for (u4Idx = 0; u4Idx < MAX_SUBBAND_NUM; u4Idx++) {
608             prDomainSubBand = &prDomainInfoEntry->rSubBand[u4Idx];
609
610
611             if (((prDomainSubBand->ucBand == BAND_5G) && (!prAdapter->fgEnable5GBand)) ||
612                     (prDomainSubBand->ucBand == BAND_NULL)) {
613                 continue;
614             }
615
616
617             if (ucBufferSize < (P2P_ATTRI_LEN_CHANNEL_ENTRY + prDomainSubBand->ucNumChannels)) {
618                 /* Buffer is not enough to include all supported channels. */
619                 break; // for
620             }
621
622             prChannelEntryField->ucRegulatoryClass = prDomainSubBand->ucRegClass;
623             prChannelEntryField->ucNumberOfChannels = prDomainSubBand->ucNumChannels;
624
625             for (u4IdxII = 0; u4IdxII < prDomainSubBand->ucNumChannels; u4IdxII++) {
626                 prChannelEntryField->aucChannelList[u4IdxII] = prDomainSubBand->ucFirstChannelNum +
627                             (u4IdxII * prDomainSubBand->ucChannelSpan);
628
629 #if 0
630                 switch (prChannelEntryField->aucChannelList[u4IdxII]) {
631                     case 1:
632                         ucSocialChnlSupport = 1;
633                         break;
634                     case 6:
635                         ucSocialChnlSupport = 6;
636                         break;
637                     case 11:
638                         ucSocialChnlSupport = 11;
639                         break;
640                     default:
641                         break;
642                 }
643
644 #endif
645             }
646
647             if (ucBufferSize >= (P2P_ATTRI_LEN_CHANNEL_ENTRY + prChannelEntryField->ucNumberOfChannels)) {
648                 ucBufferSize -= (P2P_ATTRI_LEN_CHANNEL_ENTRY + prChannelEntryField->ucNumberOfChannels);
649             }
650             else {
651                 break;
652             }
653
654
655             prChannelEntryField = (P_CHANNEL_ENTRY_FIELD_T)((UINT_32)prChannelEntryField +
656                                                                                     P2P_ATTRI_LEN_CHANNEL_ENTRY +
657                                                                                     (UINT_32)prChannelEntryField->ucNumberOfChannels);
658
659         }
660
661 #if 0
662         if (prP2pConnSetting->ucListenChnl == 0) {
663             prP2pConnSetting->ucListenChnl = P2P_DEFAULT_LISTEN_CHANNEL;
664
665             if (ucSocialChnlSupport != 0) {
666                 /* 1. User Not Set LISTEN channel.
667                   * 2. Social channel is not empty.
668                   */
669                 prP2pConnSetting->ucListenChnl = ucSocialChnlSupport;
670             }
671         }
672
673 #endif
674
675         // TODO: 20110921 frog -
676         /* If LISTEN channel is not set,
677           * a random supported channel would be set.
678           * If no social channel is supported, DEFAULT channel would be set.
679           */
680
681         prP2pConnSetting->ucRfChannelListSize = P2P_MAX_SUPPORTED_CHANNEL_LIST_SIZE - ucBufferSize;
682
683 #if 0
684         if (prP2pConnSetting->ucOperatingChnl == 0) {  /* User not set OPERATE channel. */
685
686             if (scnQuerySparseChannel(prAdapter, NULL, &ucAutoChnl)) {
687                 break; // while
688             }
689
690             ucBufferSize = prP2pConnSetting->ucRfChannelListSize;
691
692             prChannelEntryField = (P_CHANNEL_ENTRY_FIELD_T)prP2pConnSetting->aucChannelEntriesField;
693
694             while (ucBufferSize != 0) {
695                 if (prChannelEntryField->ucNumberOfChannels != 0) {
696                     ucAutoChnl = prChannelEntryField->aucChannelList[0];
697                     break; // while
698                 }
699
700                 else {
701                     prChannelEntryField = (P_CHANNEL_ENTRY_FIELD_T)((UINT_32)prChannelEntryField +
702                                                                                     P2P_ATTRI_LEN_CHANNEL_ENTRY +
703                                                                                     (UINT_32)prChannelEntryField->ucNumberOfChannels);
704
705                     ucBufferSize -= (P2P_ATTRI_LEN_CHANNEL_ENTRY + prChannelEntryField->ucNumberOfChannels);
706                 }
707
708             }
709
710
711
712         }
713
714 #endif
715         /* We assume user would not set a channel not in the channel list.
716           * If so, the operating channel still depends on target deivce supporting capability.
717           */
718
719         // TODO: 20110921 frog -
720         /* If the Operating channel is not set, a channel from supported channel list is set automatically.
721           * If there is no supported channel in channel list, a DEFAULT channel is set.
722           */
723
724     } while (FALSE);
725
726 #if 0
727     prP2pConnSetting->ucOperatingChnl = ucAutoChnl;
728 #endif
729     return;
730 } /* rlmFuncInitialChannelList */
731
732 /*----------------------------------------------------------------------------*/
733 /*!
734 * \brief    Find a common channel list from the local channel list info & target channel list info.
735 *
736 * \param[in] prAdapter  Pointer of ADAPTER_T
737 *
738 * \return boolean value if probe response frame is
739 */
740 /*----------------------------------------------------------------------------*/
741 VOID
742 rlmFuncCommonChannelList (
743     IN P_ADAPTER_T prAdapter,
744     IN P_CHANNEL_ENTRY_FIELD_T prChannelEntryII,
745     IN UINT_8 ucChannelListSize
746     )
747 {
748     P_P2P_CONNECTION_SETTINGS_T prP2pConnSetting = (P_P2P_CONNECTION_SETTINGS_T)NULL;
749     P_CHANNEL_ENTRY_FIELD_T prChannelEntryI = (P_CHANNEL_ENTRY_FIELD_T)NULL, prChannelEntryIII = (P_CHANNEL_ENTRY_FIELD_T)NULL;
750     UINT_8 aucCommonChannelList[P2P_MAX_SUPPORTED_CHANNEL_LIST_SIZE];
751     UINT_8 ucOriChnlSize = 0, ucNewChnlSize = 0;
752
753
754     do {
755
756         ASSERT_BREAK(prAdapter != NULL);
757
758         prP2pConnSetting = prAdapter->rWifiVar.prP2PConnSettings;
759
760         prChannelEntryIII = (P_CHANNEL_ENTRY_FIELD_T)aucCommonChannelList;
761
762         while (ucChannelListSize > 0) {
763
764             prChannelEntryI = (P_CHANNEL_ENTRY_FIELD_T)prP2pConnSetting->aucChannelEntriesField;
765             ucOriChnlSize = prP2pConnSetting->ucRfChannelListSize;
766
767             while (ucOriChnlSize > 0) {
768                 if (prChannelEntryI->ucRegulatoryClass == prChannelEntryII->ucRegulatoryClass) {
769                     prChannelEntryIII->ucRegulatoryClass = prChannelEntryI->ucRegulatoryClass;
770                     // TODO: Currently we assume that the regulatory class the same, the channels are the same.
771                     kalMemCopy(prChannelEntryIII->aucChannelList, prChannelEntryII->aucChannelList, prChannelEntryII->ucNumberOfChannels);
772                     prChannelEntryIII->ucNumberOfChannels = prChannelEntryII->ucNumberOfChannels;
773
774                     ucNewChnlSize += P2P_ATTRI_LEN_CHANNEL_ENTRY + prChannelEntryIII->ucNumberOfChannels;
775
776                     prChannelEntryIII = (P_CHANNEL_ENTRY_FIELD_T)((UINT_32)prChannelEntryIII +
777                                                                                 P2P_ATTRI_LEN_CHANNEL_ENTRY +
778                                                                                 (UINT_32)prChannelEntryIII->ucNumberOfChannels);
779                 }
780
781                 ucOriChnlSize -= (P2P_ATTRI_LEN_CHANNEL_ENTRY + prChannelEntryI->ucNumberOfChannels);
782
783                 prChannelEntryI = (P_CHANNEL_ENTRY_FIELD_T)((UINT_32)prChannelEntryI +
784                                                                                 P2P_ATTRI_LEN_CHANNEL_ENTRY +
785                                                                                 (UINT_32)prChannelEntryI->ucNumberOfChannels);
786
787
788             }
789
790
791             ucChannelListSize -= (P2P_ATTRI_LEN_CHANNEL_ENTRY + prChannelEntryII->ucNumberOfChannels);
792
793             prChannelEntryII = (P_CHANNEL_ENTRY_FIELD_T)((UINT_32)prChannelEntryII +
794                                                                                 P2P_ATTRI_LEN_CHANNEL_ENTRY +
795                                                                                 (UINT_32)prChannelEntryII->ucNumberOfChannels);
796
797
798         }
799
800
801         kalMemCopy(prP2pConnSetting->aucChannelEntriesField, aucCommonChannelList, ucNewChnlSize);
802         prP2pConnSetting->ucRfChannelListSize = ucNewChnlSize;
803
804     } while (FALSE);
805
806     return;
807 } /* rlmFuncCommonChannelList */
808
809
810 /*----------------------------------------------------------------------------*/
811 /*!
812 * \brief
813 *
814 * \param[in]
815 *
816 * \return none
817 */
818 /*----------------------------------------------------------------------------*/
819 UINT_8
820 rlmFuncFindOperatingClass (
821     IN P_ADAPTER_T prAdapter,
822     IN UINT_8 ucChannelNum
823     )
824 {
825     UINT_8 ucRegulatoryClass = 0, ucBufferSize = 0;
826     P_P2P_CONNECTION_SETTINGS_T prP2pConnSetting = (P_P2P_CONNECTION_SETTINGS_T)NULL;
827     P_CHANNEL_ENTRY_FIELD_T prChannelEntryField = (P_CHANNEL_ENTRY_FIELD_T)NULL;
828     UINT_32 u4Idx = 0;
829
830     do {
831         ASSERT_BREAK(prAdapter != NULL);
832
833         prP2pConnSetting = prAdapter->rWifiVar.prP2PConnSettings;
834         ucBufferSize = prP2pConnSetting->ucRfChannelListSize;
835         prChannelEntryField = (P_CHANNEL_ENTRY_FIELD_T)prP2pConnSetting->aucChannelEntriesField;
836
837         while (ucBufferSize != 0) {
838
839             for (u4Idx = 0; u4Idx < prChannelEntryField->ucNumberOfChannels; u4Idx++) {
840                 if (prChannelEntryField->aucChannelList[u4Idx] == ucChannelNum) {
841                     ucRegulatoryClass = prChannelEntryField->ucRegulatoryClass;
842                     break;
843                 }
844
845             }
846
847
848             if (ucRegulatoryClass != 0) {
849                 break; //while
850             }
851             else {
852                 prChannelEntryField = (P_CHANNEL_ENTRY_FIELD_T)((UINT_32)prChannelEntryField +
853                                                                                             P2P_ATTRI_LEN_CHANNEL_ENTRY +
854                                                                                             (UINT_32)prChannelEntryField->ucNumberOfChannels);
855
856                             ucBufferSize -= (P2P_ATTRI_LEN_CHANNEL_ENTRY + prChannelEntryField->ucNumberOfChannels);
857             }
858
859         }
860
861
862     } while (FALSE);
863
864     return ucRegulatoryClass;
865 } /* rlmFuncFindOperatingClass */
866
867
868 /*----------------------------------------------------------------------------*/
869 /*!
870 * \brief
871 *
872 * \param[in]
873 *
874 * \return none
875 */
876 /*----------------------------------------------------------------------------*/
877 BOOLEAN
878 rlmFuncFindAvailableChannel (
879     IN P_ADAPTER_T prAdapter,
880     IN UINT_8 ucCheckChnl,
881     IN PUINT_8 pucSuggestChannel,
882     IN BOOLEAN fgIsSocialChannel,
883     IN BOOLEAN fgIsDefaultChannel
884     )
885 {
886     BOOLEAN fgIsResultAvailable = FALSE;
887     P_CHANNEL_ENTRY_FIELD_T prChannelEntry = (P_CHANNEL_ENTRY_FIELD_T)NULL;
888     P_P2P_CONNECTION_SETTINGS_T prP2pConnSetting = (P_P2P_CONNECTION_SETTINGS_T)NULL;
889     UINT_8 ucBufferSize = 0, ucIdx = 0, ucChannelSelected = 0;
890
891     do {
892         ASSERT_BREAK(prAdapter != NULL);
893
894         if (fgIsDefaultChannel) {
895             ucChannelSelected = P2P_DEFAULT_LISTEN_CHANNEL;
896         }
897
898
899         prP2pConnSetting = prAdapter->rWifiVar.prP2PConnSettings;
900         ucBufferSize = prP2pConnSetting->ucRfChannelListSize;
901         prChannelEntry = (P_CHANNEL_ENTRY_FIELD_T)prP2pConnSetting->aucChannelEntriesField;
902
903         while ((ucBufferSize != 0) && (!fgIsResultAvailable)) {
904
905             for (ucIdx = 0; ucIdx < prChannelEntry->ucNumberOfChannels; ucIdx++) {
906                 if ((!fgIsSocialChannel) ||
907                         (prChannelEntry->aucChannelList[ucIdx] == 1) ||
908                         (prChannelEntry->aucChannelList[ucIdx] == 6) ||
909                         (prChannelEntry->aucChannelList[ucIdx] == 11)) {
910
911                     if (prChannelEntry->aucChannelList[ucIdx] <= 11) {
912                         /* 2.4G. */
913                         ucChannelSelected = prChannelEntry->aucChannelList[ucIdx];
914                     }
915                     else if ((prChannelEntry->aucChannelList[ucIdx] < 52) &&
916                             (prChannelEntry->aucChannelList[ucIdx] > 14)) {
917                         /* 2.4G + 5G. */
918                         ucChannelSelected = prChannelEntry->aucChannelList[ucIdx];
919                     }
920
921                     if (ucChannelSelected == ucCheckChnl) {
922                         fgIsResultAvailable = TRUE;
923                         break;
924                     }
925                 }
926
927             }
928
929
930             ucBufferSize -= (P2P_ATTRI_LEN_CHANNEL_ENTRY + prChannelEntry->ucNumberOfChannels);
931
932             prChannelEntry = (P_CHANNEL_ENTRY_FIELD_T)((UINT_32)prChannelEntry +
933                                                                                                 P2P_ATTRI_LEN_CHANNEL_ENTRY +
934                                                                                                 (UINT_32)prChannelEntry->ucNumberOfChannels);
935
936         }
937
938
939
940         if ((!fgIsResultAvailable) && (pucSuggestChannel != NULL)) {
941             DBGLOG(P2P, TRACE, ("The request channel %d is not available, sugguested channel:%d\n", ucCheckChnl, ucChannelSelected));
942             //  Given a suggested channel.
943             *pucSuggestChannel = ucChannelSelected;
944         }
945
946
947     } while (FALSE);
948
949     return fgIsResultAvailable;
950 }
951
952 /*----------------------------------------------------------------------------*/
953 /*!
954 * \brief
955 *
956 * \param[in]
957 *
958 * \return none
959 */
960 /*----------------------------------------------------------------------------*/
961 ENUM_CHNL_EXT_T
962 rlmDecideScoForAP (
963     P_ADAPTER_T     prAdapter,
964     P_BSS_INFO_T    prBssInfo
965     )
966 {
967     P_DOMAIN_SUBBAND_INFO   prSubband;
968     P_DOMAIN_INFO_ENTRY     prDomainInfo;
969     UINT_8                  ucSecondChannel, i, j;
970     ENUM_CHNL_EXT_T         eSCO;
971
972     eSCO = CHNL_EXT_SCN;
973
974     if (prBssInfo->eBand == BAND_2G4) {
975         if (prBssInfo->ucPrimaryChannel != 14) {
976             eSCO = (prBssInfo->ucPrimaryChannel > 7) ?
977                         CHNL_EXT_SCB : CHNL_EXT_SCA;
978         }
979     }
980     else {
981         prDomainInfo = rlmDomainGetDomainInfo(prAdapter);
982         ASSERT(prDomainInfo);
983
984         for (i = 0; i < MAX_SUBBAND_NUM; i++) {
985             prSubband = &prDomainInfo->rSubBand[i];
986             if (prSubband->ucBand == prBssInfo->eBand) {
987                 for (j = 0; j < prSubband->ucNumChannels; j++) {
988                     if ((prSubband->ucFirstChannelNum + j*prSubband->ucChannelSpan)
989                         == prBssInfo->ucPrimaryChannel) {
990                         eSCO = (j & 1) ? CHNL_EXT_SCB : CHNL_EXT_SCA;
991                         break;
992                     }
993                 }
994
995                 if (j < prSubband->ucNumChannels) {
996                     break; /* Found */
997                 }
998             }
999         }
1000     }
1001
1002     /* Check if it is boundary channel and 40MHz BW is permitted */
1003     if (eSCO != CHNL_EXT_SCN) {
1004         ucSecondChannel = (eSCO == CHNL_EXT_SCA) ?
1005             (prBssInfo->ucPrimaryChannel+ 4) : (prBssInfo->ucPrimaryChannel- 4);
1006
1007         if (!rlmDomainIsLegalChannel(prAdapter, prBssInfo->eBand, ucSecondChannel)){
1008             eSCO = CHNL_EXT_SCN;
1009         }
1010     }
1011
1012     return eSCO;
1013 }
1014