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