support different wifi bt chip auto compatible
[firefly-linux-kernel-4.4.55.git] / drivers / net / wireless / rockchip_wlan / mt5931 / mgmt / scan_fsm.c
1 /*
2 ** $Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/mgmt/scan_fsm.c#1 $
3 */
4
5 /*! \file   "scan_fsm.c"
6     \brief  This file defines the state transition function for SCAN FSM.
7
8     The SCAN FSM is part of SCAN MODULE and responsible for performing basic SCAN
9     behavior as metioned in IEEE 802.11 2007 11.1.3.1 & 11.1.3.2 .
10 */
11
12
13
14 /*
15 ** $Log: scan_fsm.c $
16  *
17  * 06 13 2012 yuche.tsai
18  * NULL
19  * Update maintrunk driver.
20  * Add support for driver compose assoc request frame.
21  *
22  * 11 24 2011 wh.su
23  * [WCXRP00001078] [MT6620 Wi-Fi][Driver] Adding the mediatek log improment support : XLOG
24  * Adjust code for DBG and CONFIG_XLOG.
25  *
26  * 11 14 2011 yuche.tsai
27  * [WCXRP00001095] [Volunteer Patch][Driver] Always Scan before enable Hot-Spot.
28  * Fix bug when unregister P2P network..
29  *
30  * 11 11 2011 wh.su
31  * [WCXRP00001078] [MT6620 Wi-Fi][Driver] Adding the mediatek log improment support : XLOG
32  * modify the xlog related code.
33  *
34  * 11 02 2011 wh.su
35  * [WCXRP00001078] [MT6620 Wi-Fi][Driver] Adding the mediatek log improment support : XLOG
36  * adding the code for XLOG.
37  *
38  * 08 11 2011 cp.wu
39  * [WCXRP00000830] [MT6620 Wi-Fi][Firmware] Use MDRDY counter to detect empty channel for shortening scan time
40  * sparse channel detection:
41  * driver: collect sparse channel information with scan-done event
42
43  *
44  * 07 18 2011 cp.wu
45  * [WCXRP00000858] [MT5931][Driver][Firmware] Add support for scan to search for more than one SSID in a single scanning request
46  * free mailbox message afte parsing is completed.
47  *
48  * 07 18 2011 cp.wu
49  * [WCXRP00000858] [MT5931][Driver][Firmware] Add support for scan to search for more than one SSID in a single scanning request
50  * add framework in driver domain for supporting new SCAN_REQ_V2 for more than 1 SSID support as well as uProbeDelay in NDIS 6.x driver model
51  *
52  * 04 18 2011 terry.wu
53  * [WCXRP00000660] [MT6620 Wi-Fi][Driver] Remove flag CFG_WIFI_DIRECT_MOVED
54  * Remove flag CFG_WIFI_DIRECT_MOVED.
55  *
56  * 03 29 2011 cp.wu
57  * [WCXRP00000604] [MT6620 Wi-Fi][Driver] Surpress Klockwork Warning
58  * surpress klock warning with code path rewritten
59  *
60  * 03 18 2011 cm.chang
61  * [WCXRP00000576] [MT6620 Wi-Fi][Driver][FW] Remove P2P compile option in scan req/cancel command
62  * As CR title
63  *
64  * 02 18 2011 yuche.tsai
65  * [WCXRP00000478] [Volunteer Patch][MT6620][Driver] Probe request frame during search phase do not contain P2P wildcard SSID.
66  * Take P2P wildcard SSID into consideration.
67  *
68  * 01 27 2011 yuche.tsai
69  * [WCXRP00000399] [Volunteer Patch][MT6620/MT5931][Driver] Fix scan side effect after P2P module separate.
70  * Fix scan channel extension issue when p2p module is not registered.
71  *
72  * 01 26 2011 yuche.tsai
73  * [WCXRP00000388] [Volunteer Patch][MT6620][Driver/Fw] change Station Type in station record.
74  * .
75  *
76  * 01 25 2011 yuche.tsai
77  * [WCXRP00000388] [Volunteer Patch][MT6620][Driver/Fw] change Station Type in station record.
78  * Fix Compile Error when DBG is disabled.
79  *
80  * 12 07 2010 cm.chang
81  * [WCXRP00000238] MT6620 Wi-Fi][Driver][FW] Support regulation domain setting from NVRAM and supplicant
82  * 1. Country code is from NVRAM or supplicant
83  * 2. Change band definition in CMD/EVENT.
84  *
85  * 09 03 2010 kevin.huang
86  * NULL
87  * Refine #include sequence and solve recursive/nested #include issue
88  *
89  * 08 30 2010 cp.wu
90  * NULL
91  * eliminate klockwork errors
92  *
93  * 08 16 2010 cp.wu
94  * NULL
95  * add interface for RLM to trigger OBSS-SCAN.
96  *
97  * 08 16 2010 yuche.tsai
98  * NULL
99  * Fix bug for processing queued scan request.
100  *
101  * 08 11 2010 yuche.tsai
102  * NULL
103  * Add a function for returning channel.
104  *
105  * 08 05 2010 yuche.tsai
106  * NULL
107  * Update SCAN FSM for support P2P Device discovery scan.
108  *
109  * 08 03 2010 cp.wu
110  * NULL
111  * surpress compilation warning.
112  *
113  * 07 26 2010 yuche.tsai
114  *
115  * Add option of channel extension while cancelling scan request.
116  *
117  * 07 21 2010 yuche.tsai
118  *
119  * Add P2P Scan & Scan Result Parsing & Saving.
120  *
121  * 07 20 2010 cp.wu
122  *
123  * pass band information for scan in an efficient way by mapping ENUM_BAND_T into UINT_8..
124  *
125  * 07 19 2010 cp.wu
126  *
127  * due to FW/DRV won't be sync. precisely, some strict assertions should be eased.
128  *
129  * 07 19 2010 cp.wu
130  *
131  * [WPD00003833] [MT6620 and MT5931] Driver migration.
132  * SCN module is now able to handle multiple concurrent scanning requests
133  *
134  * 07 16 2010 cp.wu
135  *
136  * [WPD00003833] [MT6620 and MT5931] Driver migration.
137  * bugfix for SCN migration
138  * 1) modify QUEUE_CONCATENATE_QUEUES() so it could be used to concatence with an empty queue
139  * 2) before AIS issues scan request, network(BSS) needs to be activated first
140  * 3) only invoke COPY_SSID when using specified SSID for scan
141  *
142  * 07 15 2010 cp.wu
143  *
144  * [WPD00003833] [MT6620 and MT5931] Driver migration.
145  * driver no longer generates probe request frames
146  *
147  * 07 14 2010 cp.wu
148  *
149  * [WPD00003833] [MT6620 and MT5931] Driver migration.
150  * pass band with channel number information as scan parameter
151  *
152  * 07 14 2010 cp.wu
153  *
154  * [WPD00003833] [MT6620 and MT5931] Driver migration.
155  * remove timer in DRV-SCN.
156  *
157  * 07 09 2010 cp.wu
158  *
159  * 1) separate AIS_FSM state for two kinds of scanning. (OID triggered scan, and scan-for-connection)
160  * 2) eliminate PRE_BSS_DESC_T, Beacon/PrebResp is now parsed in single pass
161  * 3) implment DRV-SCN module, currently only accepts single scan request, other request will be directly dropped by returning BUSY
162  *
163  * 07 08 2010 cp.wu
164  *
165  * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository.
166  *
167  * 07 08 2010 cp.wu
168  * [WPD00003833][MT6620 and MT5931] Driver migration
169  * take use of RLM module for parsing/generating HT IEs for 11n capability
170  *
171  * 07 02 2010 cp.wu
172  * [WPD00003833][MT6620 and MT5931] Driver migration
173  * when returning to SCAN_IDLE state, send a correct message to source FSM.
174  *
175  * 07 01 2010 cp.wu
176  * [WPD00003833][MT6620 and MT5931] Driver migration
177  * implementation of DRV-SCN and related mailbox message handling.
178  *
179  * 06 22 2010 cp.wu
180  * [WPD00003833][MT6620 and MT5931] Driver migration
181  * comment out RLM APIs by CFG_RLM_MIGRATION.
182  *
183  * 06 21 2010 cp.wu
184  * [WPD00003833][MT6620 and MT5931] Driver migration
185  * add scan_fsm into building.
186  *
187  * 05 14 2010 kevin.huang
188  * [BORA00000794][WIFISYS][New Feature]Power Management Support
189  * Refine the order of Stop TX Queue and Switch Channel
190  *
191  * 05 12 2010 kevin.huang
192  * [BORA00000794][WIFISYS][New Feature]Power Management Support
193  * Update pause/resume/flush API to new Bitmap API
194  *
195  * 05 12 2010 kevin.huang
196  * [BORA00000794][WIFISYS][New Feature]Power Management Support
197  * Add Power Management - Legacy PS-POLL support.
198  *
199  * 03 18 2010 kevin.huang
200  * [BORA00000663][WIFISYS][New Feature] AdHoc Mode Support
201  * Ignore the PROBE_DELAY state if the value of Probe Delay == 0
202  *
203  * 03 10 2010 kevin.huang
204  * [BORA00000654][WIFISYS][New Feature] CNM Module - Ch Manager Support
205  * Add Channel Manager for arbitration of JOIN and SCAN Req
206  *
207  * 02 23 2010 kevin.huang
208  * [BORA00000603][WIFISYS] [New Feature] AAA Module Support
209  * Add support scan channel 1~14 and update scan result's frequency infou1rwduu`wvpghlqg|n`slk+mpdkb
210  *
211  * 01 08 2010 kevin.huang
212  * [BORA00000018]Integrate WIFI part into BORA for the 1st time
213  * Add set RX Filter to receive BCN from different BSSID during SCAN
214  *
215  * 12 18 2009 cm.chang
216  * [BORA00000018]Integrate WIFI part into BORA for the 1st time
217  * .
218  *
219  * Nov 25 2009 mtk01461
220  * [BORA00000018] Integrate WIFI part into BORA for the 1st time
221  * Remove flag of CFG_TEST_MGMT_FSM
222  *
223  * Nov 20 2009 mtk01461
224  * [BORA00000018] Integrate WIFI part into BORA for the 1st time
225  * Change parameter of scanSendProbeReqFrames()
226  *
227  * Nov 16 2009 mtk01461
228  * [BORA00000018] Integrate WIFI part into BORA for the 1st time
229  * Update scnFsmSteps()
230  *
231  * Nov 5 2009 mtk01461
232  * [BORA00000018] Integrate WIFI part into BORA for the 1st time
233  * Fix typo
234  *
235  * Nov 5 2009 mtk01461
236  * [BORA00000018] Integrate WIFI part into BORA for the 1st time
237  *
238 */
239
240 /*******************************************************************************
241 *                         C O M P I L E R   F L A G S
242 ********************************************************************************
243 */
244
245 /*******************************************************************************
246 *                    E X T E R N A L   R E F E R E N C E S
247 ********************************************************************************
248 */
249 #include "precomp.h"
250
251 /*******************************************************************************
252 *                              C O N S T A N T S
253 ********************************************************************************
254 */
255
256 /*******************************************************************************
257 *                             D A T A   T Y P E S
258 ********************************************************************************
259 */
260
261 /*******************************************************************************
262 *                            P U B L I C   D A T A
263 ********************************************************************************
264 */
265
266 /*******************************************************************************
267 *                           P R I V A T E   D A T A
268 ********************************************************************************
269 */
270 #if DBG
271 /*lint -save -e64 Type mismatch */
272 static PUINT_8 apucDebugScanState[SCAN_STATE_NUM] = {
273     (PUINT_8)DISP_STRING("SCAN_STATE_IDLE"),
274     (PUINT_8)DISP_STRING("SCAN_STATE_SCANNING"),
275 };
276 /*lint -restore */
277 #endif /* DBG */
278
279 /*******************************************************************************
280 *                                 M A C R O S
281 ********************************************************************************
282 */
283
284 /*******************************************************************************
285 *                   F U N C T I O N   D E C L A R A T I O N S
286 ********************************************************************************
287 */
288
289 /*******************************************************************************
290 *                              F U N C T I O N S
291 ********************************************************************************
292 */
293 /*----------------------------------------------------------------------------*/
294 /*!
295 * \brief
296 *
297 * \param[in]
298 *
299 * \return none
300 */
301 /*----------------------------------------------------------------------------*/
302 VOID
303 scnFsmSteps (
304     IN P_ADAPTER_T prAdapter,
305     IN ENUM_SCAN_STATE_T eNextState
306     )
307 {
308     P_SCAN_INFO_T prScanInfo;
309     P_SCAN_PARAM_T prScanParam;
310     P_MSG_HDR_T prMsgHdr;
311
312     BOOLEAN fgIsTransition = (BOOLEAN)FALSE;
313
314     prScanInfo = &(prAdapter->rWifiVar.rScanInfo);
315     prScanParam = &prScanInfo->rScanParam;
316
317     do {
318
319 #if DBG
320         DBGLOG(SCN, STATE, ("TRANSITION: [%s] -> [%s]\n",
321                              apucDebugScanState[prScanInfo->eCurrentState],
322                              apucDebugScanState[eNextState]));
323 #else
324         DBGLOG(SCN, STATE, ("[%d] TRANSITION: [%d] -> [%d]\n",
325                              DBG_SCN_IDX,
326                              prScanInfo->eCurrentState,
327                              eNextState));
328 #endif
329
330         /* NOTE(Kevin): This is the only place to change the eCurrentState(except initial) */
331         prScanInfo->eCurrentState = eNextState;
332
333         fgIsTransition = (BOOLEAN)FALSE;
334
335         switch (prScanInfo->eCurrentState) {
336         case SCAN_STATE_IDLE:
337             /* check for pending scanning requests */
338             if(!LINK_IS_EMPTY(&(prScanInfo->rPendingMsgList))) {
339                 // load next message from pending list as scan parameters
340                 LINK_REMOVE_HEAD(&(prScanInfo->rPendingMsgList), prMsgHdr, P_MSG_HDR_T);
341
342                 if(prMsgHdr->eMsgId == MID_AIS_SCN_SCAN_REQ
343                         || prMsgHdr->eMsgId == MID_BOW_SCN_SCAN_REQ
344                         || prMsgHdr->eMsgId == MID_P2P_SCN_SCAN_REQ
345                         || prMsgHdr->eMsgId == MID_RLM_SCN_SCAN_REQ) {
346                     scnFsmHandleScanMsg(prAdapter, (P_MSG_SCN_SCAN_REQ)prMsgHdr);
347                 }
348                 else {
349                     scnFsmHandleScanMsgV2(prAdapter, (P_MSG_SCN_SCAN_REQ_V2)prMsgHdr);
350                 }
351
352                 /* switch to next state */
353                 eNextState = SCAN_STATE_SCANNING;
354                 fgIsTransition = TRUE;
355
356                 cnmMemFree(prAdapter, prMsgHdr);
357             }
358             break;
359
360         case SCAN_STATE_SCANNING:
361             if(prScanParam->fgIsScanV2 == FALSE) {
362                 scnSendScanReq(prAdapter);
363             }
364             else {
365                 scnSendScanReqV2(prAdapter);
366             }
367             break;
368
369         default:
370             ASSERT(0);
371             break;
372
373         }
374     }
375     while (fgIsTransition);
376
377     return;
378 }
379
380
381 /*----------------------------------------------------------------------------*/
382 /*!
383 * \brief        Generate CMD_ID_SCAN_REQ command
384 *
385 * \param[in]
386 *
387 * \return none
388 */
389 /*----------------------------------------------------------------------------*/
390 VOID
391 scnSendScanReq (
392     IN P_ADAPTER_T prAdapter
393     )
394 {
395     P_SCAN_INFO_T prScanInfo;
396     P_SCAN_PARAM_T prScanParam;
397     CMD_SCAN_REQ rCmdScanReq;
398     UINT_32 i;
399
400     ASSERT(prAdapter);
401
402     prScanInfo = &(prAdapter->rWifiVar.rScanInfo);
403     prScanParam = &prScanInfo->rScanParam;
404
405     // send command packet for scan
406     kalMemZero(&rCmdScanReq, sizeof(CMD_SCAN_REQ));
407
408     rCmdScanReq.ucSeqNum        = prScanParam->ucSeqNum;
409     rCmdScanReq.ucNetworkType   = (UINT_8)prScanParam->eNetTypeIndex;
410     rCmdScanReq.ucScanType      = (UINT_8)prScanParam->eScanType;
411     rCmdScanReq.ucSSIDType      = prScanParam->ucSSIDType;
412
413     if(prScanParam->ucSSIDNum == 1) {
414         COPY_SSID(rCmdScanReq.aucSSID,
415                 rCmdScanReq.ucSSIDLength,
416                 prScanParam->aucSpecifiedSSID[0],
417                 prScanParam->ucSpecifiedSSIDLen[0]);
418     }
419
420     rCmdScanReq.ucChannelType       = (UINT_8)prScanParam->eScanChannel;
421
422     if (prScanParam->eScanChannel == SCAN_CHANNEL_SPECIFIED) {
423         /* P2P would use:
424          * 1. Specified Listen Channel of passive scan for LISTEN state.
425          * 2. Specified Listen Channel of Target Device of active scan for SEARCH state. (Target != NULL)
426          */
427         rCmdScanReq.ucChannelListNum    = prScanParam->ucChannelListNum;
428
429         for(i = 0 ; i < rCmdScanReq.ucChannelListNum ; i++) {
430             rCmdScanReq.arChannelList[i].ucBand =
431                 (UINT_8) prScanParam->arChnlInfoList[i].eBand;
432
433             rCmdScanReq.arChannelList[i].ucChannelNum =
434                 (UINT_8)prScanParam->arChnlInfoList[i].ucChannelNum;
435         }
436     }
437
438 #if CFG_ENABLE_WIFI_DIRECT
439     if(prScanParam->eNetTypeIndex == NETWORK_TYPE_P2P_INDEX) {
440         rCmdScanReq.u2ChannelDwellTime = prScanParam->u2PassiveListenInterval;
441     }
442 #endif
443 #if RSSI_ENHANCE
444     //add by gwl
445     rCmdScanReq.u2ChannelDwellTime = 200;
446         rCmdScanReq.u2ChannelMinDwellTime = 200;
447 #endif
448     if(prScanParam->u2IELen <= MAX_IE_LENGTH) {
449         rCmdScanReq.u2IELen = prScanParam->u2IELen;
450     }
451     else {
452         rCmdScanReq.u2IELen = MAX_IE_LENGTH;
453     }
454
455     if (prScanParam->u2IELen) {
456         kalMemCopy(rCmdScanReq.aucIE,
457                 prScanParam->aucIE,
458                 sizeof(UINT_8) * rCmdScanReq.u2IELen);
459     }
460
461     wlanSendSetQueryCmd(prAdapter,
462             CMD_ID_SCAN_REQ,
463             TRUE,
464             FALSE,
465             FALSE,
466             NULL,
467             NULL,
468             OFFSET_OF(CMD_SCAN_REQ, aucIE) + rCmdScanReq.u2IELen,
469             (PUINT_8)&rCmdScanReq,
470             NULL,
471             0);
472 }
473
474
475 /*----------------------------------------------------------------------------*/
476 /*!
477 * \brief        Generate CMD_ID_SCAN_REQ_V2 command
478 *
479 * \param[in]
480 *
481 * \return none
482 */
483 /*----------------------------------------------------------------------------*/
484 VOID
485 scnSendScanReqV2 (
486     IN P_ADAPTER_T prAdapter
487     )
488 {
489     P_SCAN_INFO_T prScanInfo;
490     P_SCAN_PARAM_T prScanParam;
491     CMD_SCAN_REQ_V2 rCmdScanReq;
492     UINT_32 i;
493
494     ASSERT(prAdapter);
495
496     prScanInfo = &(prAdapter->rWifiVar.rScanInfo);
497     prScanParam = &prScanInfo->rScanParam;
498
499     // send command packet for scan
500     kalMemZero(&rCmdScanReq, sizeof(CMD_SCAN_REQ_V2));
501
502     rCmdScanReq.ucSeqNum        = prScanParam->ucSeqNum;
503     rCmdScanReq.ucNetworkType   = (UINT_8)prScanParam->eNetTypeIndex;
504     rCmdScanReq.ucScanType      = (UINT_8)prScanParam->eScanType;
505     rCmdScanReq.ucSSIDType      = prScanParam->ucSSIDType;
506
507     for (i = 0 ; i < prScanParam->ucSSIDNum; i++) {
508         COPY_SSID(rCmdScanReq.arSSID[i].aucSsid,
509                 rCmdScanReq.arSSID[i].u4SsidLen,
510                 prScanParam->aucSpecifiedSSID[i],
511                 prScanParam->ucSpecifiedSSIDLen[i]);
512     }
513
514     rCmdScanReq.u2ProbeDelayTime    = (UINT_8)prScanParam->u2ProbeDelayTime;
515     rCmdScanReq.ucChannelType       = (UINT_8)prScanParam->eScanChannel;
516
517     if (prScanParam->eScanChannel == SCAN_CHANNEL_SPECIFIED) {
518         /* P2P would use:
519          * 1. Specified Listen Channel of passive scan for LISTEN state.
520          * 2. Specified Listen Channel of Target Device of active scan for SEARCH state. (Target != NULL)
521          */
522         rCmdScanReq.ucChannelListNum    = prScanParam->ucChannelListNum;
523
524         for(i = 0 ; i < rCmdScanReq.ucChannelListNum ; i++) {
525             rCmdScanReq.arChannelList[i].ucBand =
526                 (UINT_8) prScanParam->arChnlInfoList[i].eBand;
527
528             rCmdScanReq.arChannelList[i].ucChannelNum =
529                 (UINT_8)prScanParam->arChnlInfoList[i].ucChannelNum;
530         }
531     }
532
533 #if CFG_ENABLE_WIFI_DIRECT
534     if(prScanParam->eNetTypeIndex == NETWORK_TYPE_P2P_INDEX) {
535         rCmdScanReq.u2ChannelDwellTime = prScanParam->u2PassiveListenInterval;
536     }
537 #endif
538
539     if(prScanParam->u2IELen <= MAX_IE_LENGTH) {
540         rCmdScanReq.u2IELen = prScanParam->u2IELen;
541     }
542     else {
543         rCmdScanReq.u2IELen = MAX_IE_LENGTH;
544     }
545
546     if (prScanParam->u2IELen) {
547         kalMemCopy(rCmdScanReq.aucIE,
548                 prScanParam->aucIE,
549                 sizeof(UINT_8) * rCmdScanReq.u2IELen);
550     }
551
552     wlanSendSetQueryCmd(prAdapter,
553             CMD_ID_SCAN_REQ_V2,
554             TRUE,
555             FALSE,
556             FALSE,
557             NULL,
558             NULL,
559             OFFSET_OF(CMD_SCAN_REQ_V2, aucIE) + rCmdScanReq.u2IELen,
560             (PUINT_8)&rCmdScanReq,
561             NULL,
562             0);
563
564 }
565
566
567 /*----------------------------------------------------------------------------*/
568 /*!
569 * \brief
570 *
571 * \param[in]
572 *
573 * \return none
574 */
575 /*----------------------------------------------------------------------------*/
576 VOID
577 scnFsmMsgStart (
578     IN P_ADAPTER_T prAdapter,
579     IN P_MSG_HDR_T prMsgHdr
580     )
581 {
582     P_SCAN_INFO_T prScanInfo;
583     P_SCAN_PARAM_T prScanParam;
584
585     ASSERT(prMsgHdr);
586
587     prScanInfo = &(prAdapter->rWifiVar.rScanInfo);
588     prScanParam = &prScanInfo->rScanParam;
589
590
591     if (prScanInfo->eCurrentState == SCAN_STATE_IDLE) {
592         if(prMsgHdr->eMsgId == MID_AIS_SCN_SCAN_REQ
593                 || prMsgHdr->eMsgId == MID_BOW_SCN_SCAN_REQ
594                 || prMsgHdr->eMsgId == MID_P2P_SCN_SCAN_REQ
595                 || prMsgHdr->eMsgId == MID_RLM_SCN_SCAN_REQ) {
596             scnFsmHandleScanMsg(prAdapter, (P_MSG_SCN_SCAN_REQ)prMsgHdr);
597         }
598         else if(prMsgHdr->eMsgId == MID_AIS_SCN_SCAN_REQ_V2
599                 || prMsgHdr->eMsgId == MID_BOW_SCN_SCAN_REQ_V2
600                 || prMsgHdr->eMsgId == MID_P2P_SCN_SCAN_REQ_V2
601                 || prMsgHdr->eMsgId == MID_RLM_SCN_SCAN_REQ_V2) {
602             scnFsmHandleScanMsgV2(prAdapter, (P_MSG_SCN_SCAN_REQ_V2)prMsgHdr);
603         }
604         else {
605             // should not deliver to this function
606             ASSERT(0);
607         }
608
609         cnmMemFree(prAdapter, prMsgHdr);
610         scnFsmSteps(prAdapter, SCAN_STATE_SCANNING);
611     }
612     else {
613         LINK_INSERT_TAIL(&prScanInfo->rPendingMsgList, &prMsgHdr->rLinkEntry);
614     }
615
616     return;
617 }
618
619
620
621 /*----------------------------------------------------------------------------*/
622 /*!
623 * \brief
624 *
625 * \param[in]
626 *
627 * \return none
628 */
629 /*----------------------------------------------------------------------------*/
630 VOID
631 scnFsmMsgAbort (
632     IN P_ADAPTER_T prAdapter,
633     IN P_MSG_HDR_T prMsgHdr
634     )
635 {
636     P_MSG_SCN_SCAN_CANCEL prScanCancel;
637     P_SCAN_INFO_T prScanInfo;
638     P_SCAN_PARAM_T prScanParam;
639     CMD_SCAN_CANCEL rCmdScanCancel;
640
641     ASSERT(prMsgHdr);
642
643     prScanCancel = (P_MSG_SCN_SCAN_CANCEL)prMsgHdr;
644     prScanInfo = &(prAdapter->rWifiVar.rScanInfo);
645     prScanParam = &prScanInfo->rScanParam;
646
647     if (prScanInfo->eCurrentState != SCAN_STATE_IDLE) {
648         if(prScanCancel->ucSeqNum == prScanParam->ucSeqNum &&
649                 prScanCancel->ucNetTypeIndex == (UINT_8)prScanParam->eNetTypeIndex) {
650             /* send cancel message to firmware domain */
651             rCmdScanCancel.ucSeqNum = prScanParam->ucSeqNum;
652
653 #if CFG_ENABLE_WIFI_DIRECT
654             if(prScanParam->eNetTypeIndex == NETWORK_TYPE_P2P_INDEX) {
655                 rCmdScanCancel.ucIsExtChannel = (UINT_8) prScanCancel->fgIsChannelExt;
656             }
657             else {
658                 rCmdScanCancel.ucIsExtChannel = (UINT_8) FALSE;
659             }
660 #endif
661
662             wlanSendSetQueryCmd(prAdapter,
663                     CMD_ID_SCAN_CANCEL,
664                     TRUE,
665                     FALSE,
666                     FALSE,
667                     NULL,
668                     NULL,
669                     sizeof(CMD_SCAN_CANCEL),
670                     (PUINT_8)&rCmdScanCancel,
671                     NULL,
672                     0);
673
674             /* generate scan-done event for caller */
675             scnFsmGenerateScanDoneMsg(prAdapter,
676                     prScanParam->ucSeqNum,
677                     (UINT_8)prScanParam->eNetTypeIndex,
678                     SCAN_STATUS_CANCELLED);
679
680             /* switch to next pending scan */
681             scnFsmSteps(prAdapter, SCAN_STATE_IDLE);
682         }
683         else {
684             scnFsmRemovePendingMsg(prAdapter, prScanCancel->ucSeqNum, prScanCancel->ucNetTypeIndex);
685         }
686     }
687
688     cnmMemFree(prAdapter, prMsgHdr);
689
690     return;
691 }
692
693
694 /*----------------------------------------------------------------------------*/
695 /*!
696 * \brief            Scan Message Parsing (Legacy)
697 *
698 * \param[in]
699 *
700 * \return none
701 */
702 /*----------------------------------------------------------------------------*/
703 VOID
704 scnFsmHandleScanMsg (
705     IN P_ADAPTER_T prAdapter,
706     IN P_MSG_SCN_SCAN_REQ prScanReqMsg
707     )
708 {
709     P_SCAN_INFO_T prScanInfo;
710     P_SCAN_PARAM_T prScanParam;
711     UINT_32 i;
712
713     ASSERT(prAdapter);
714     ASSERT(prScanReqMsg);
715
716     prScanInfo = &(prAdapter->rWifiVar.rScanInfo);
717     prScanParam = &prScanInfo->rScanParam;
718
719     prScanParam->eScanType      = prScanReqMsg->eScanType;
720     prScanParam->eNetTypeIndex  = (ENUM_NETWORK_TYPE_INDEX_T)prScanReqMsg->ucNetTypeIndex;
721     prScanParam->ucSSIDType     = prScanReqMsg->ucSSIDType;
722     if (prScanParam->ucSSIDType & (SCAN_REQ_SSID_SPECIFIED | SCAN_REQ_SSID_P2P_WILDCARD)) {
723         prScanParam->ucSSIDNum = 1;
724
725         COPY_SSID(prScanParam->aucSpecifiedSSID[0],
726                 prScanParam->ucSpecifiedSSIDLen[0],
727                 prScanReqMsg->aucSSID,
728                 prScanReqMsg->ucSSIDLength);
729
730         // reset SSID length to zero for rest array entries
731         for(i = 1 ; i < SCN_SSID_MAX_NUM ; i++) {
732             prScanParam->ucSpecifiedSSIDLen[i] = 0;
733         }
734     }
735     else {
736         prScanParam->ucSSIDNum = 0;
737
738         for(i = 0 ; i < SCN_SSID_MAX_NUM ; i++) {
739             prScanParam->ucSpecifiedSSIDLen[i] = 0;
740         }
741     }
742
743     prScanParam->u2ProbeDelayTime   = 0;
744     prScanParam->eScanChannel   = prScanReqMsg->eScanChannel;
745     if(prScanParam->eScanChannel == SCAN_CHANNEL_SPECIFIED) {
746         if(prScanReqMsg->ucChannelListNum <= MAXIMUM_OPERATION_CHANNEL_LIST) {
747             prScanParam->ucChannelListNum   = prScanReqMsg->ucChannelListNum;
748         }
749         else {
750             prScanParam->ucChannelListNum   = MAXIMUM_OPERATION_CHANNEL_LIST;
751         }
752
753         kalMemCopy(prScanParam->arChnlInfoList,
754                 prScanReqMsg->arChnlInfoList,
755                 sizeof(RF_CHANNEL_INFO_T) * prScanParam->ucChannelListNum);
756     }
757
758     if(prScanReqMsg->u2IELen <= MAX_IE_LENGTH) {
759         prScanParam->u2IELen    = prScanReqMsg->u2IELen;
760     }
761     else {
762         prScanParam->u2IELen    = MAX_IE_LENGTH;
763     }
764
765     if(prScanParam->u2IELen) {
766         kalMemCopy(prScanParam->aucIE, prScanReqMsg->aucIE, prScanParam->u2IELen);
767     }
768
769 #if CFG_ENABLE_WIFI_DIRECT
770     if(prScanParam->eNetTypeIndex == NETWORK_TYPE_P2P_INDEX) {
771         prScanParam->u2PassiveListenInterval = prScanReqMsg->u2ChannelDwellTime;
772     }
773 #endif
774     prScanParam->ucSeqNum       = prScanReqMsg->ucSeqNum;
775
776     if(prScanReqMsg->rMsgHdr.eMsgId == MID_RLM_SCN_SCAN_REQ) {
777         prScanParam->fgIsObssScan   = TRUE;
778     }
779     else {
780         prScanParam->fgIsObssScan   = FALSE;
781     }
782
783     prScanParam->fgIsScanV2 = FALSE;
784
785     return;
786 }
787
788
789 /*----------------------------------------------------------------------------*/
790 /*!
791 * \brief            Scan Message Parsing - V2 with multiple SSID support
792 *
793 * \param[in]
794 *
795 * \return none
796 */
797 /*----------------------------------------------------------------------------*/
798 VOID
799 scnFsmHandleScanMsgV2 (
800     IN P_ADAPTER_T prAdapter,
801     IN P_MSG_SCN_SCAN_REQ_V2 prScanReqMsg
802     )
803 {
804     P_SCAN_INFO_T prScanInfo;
805     P_SCAN_PARAM_T prScanParam;
806     UINT_32 i;
807
808     ASSERT(prAdapter);
809     ASSERT(prScanReqMsg);
810     ASSERT(prScanReqMsg->ucSSIDNum <= SCN_SSID_MAX_NUM);
811
812     prScanInfo = &(prAdapter->rWifiVar.rScanInfo);
813     prScanParam = &prScanInfo->rScanParam;
814
815     prScanParam->eScanType      = prScanReqMsg->eScanType;
816     prScanParam->eNetTypeIndex  = (ENUM_NETWORK_TYPE_INDEX_T)prScanReqMsg->ucNetTypeIndex;
817     prScanParam->ucSSIDType     = prScanReqMsg->ucSSIDType;
818     prScanParam->ucSSIDNum      = prScanReqMsg->ucSSIDNum;
819
820     for(i = 0 ; i < prScanReqMsg->ucSSIDNum ; i++) {
821         COPY_SSID(prScanParam->aucSpecifiedSSID[i],
822                 prScanParam->ucSpecifiedSSIDLen[i],
823                 prScanReqMsg->prSsid[i].aucSsid,
824                 (UINT_8)prScanReqMsg->prSsid[i].u4SsidLen);
825     }
826
827     prScanParam->u2ProbeDelayTime   = prScanReqMsg->u2ProbeDelay;
828     prScanParam->eScanChannel       = prScanReqMsg->eScanChannel;
829     if(prScanParam->eScanChannel == SCAN_CHANNEL_SPECIFIED) {
830         if(prScanReqMsg->ucChannelListNum <= MAXIMUM_OPERATION_CHANNEL_LIST) {
831             prScanParam->ucChannelListNum   = prScanReqMsg->ucChannelListNum;
832         }
833         else {
834             prScanParam->ucChannelListNum   = MAXIMUM_OPERATION_CHANNEL_LIST;
835         }
836
837         kalMemCopy(prScanParam->arChnlInfoList,
838                 prScanReqMsg->arChnlInfoList,
839                 sizeof(RF_CHANNEL_INFO_T) * prScanParam->ucChannelListNum);
840     }
841
842     if(prScanReqMsg->u2IELen <= MAX_IE_LENGTH) {
843         prScanParam->u2IELen    = prScanReqMsg->u2IELen;
844     }
845     else {
846         prScanParam->u2IELen    = MAX_IE_LENGTH;
847     }
848
849     if(prScanParam->u2IELen) {
850         kalMemCopy(prScanParam->aucIE, prScanReqMsg->aucIE, prScanParam->u2IELen);
851     }
852
853 #if CFG_ENABLE_WIFI_DIRECT
854     if(prScanParam->eNetTypeIndex == NETWORK_TYPE_P2P_INDEX) {
855         prScanParam->u2PassiveListenInterval = prScanReqMsg->u2ChannelDwellTime;
856     }
857 #endif
858     prScanParam->ucSeqNum       = prScanReqMsg->ucSeqNum;
859
860     if(prScanReqMsg->rMsgHdr.eMsgId == MID_RLM_SCN_SCAN_REQ) {
861         prScanParam->fgIsObssScan   = TRUE;
862     }
863     else {
864         prScanParam->fgIsObssScan   = FALSE;
865     }
866
867     prScanParam->fgIsScanV2 = TRUE;
868
869     return;
870 }
871
872
873 /*----------------------------------------------------------------------------*/
874 /*!
875 * \brief            Remove pending scan request
876 *
877 * \param[in]
878 *
879 * \return none
880 */
881 /*----------------------------------------------------------------------------*/
882 VOID
883 scnFsmRemovePendingMsg (
884     IN P_ADAPTER_T  prAdapter,
885     IN UINT_8       ucSeqNum,
886     IN UINT_8       ucNetTypeIndex
887     )
888 {
889     P_SCAN_INFO_T prScanInfo;
890     P_SCAN_PARAM_T prScanParam;
891     P_MSG_HDR_T prPendingMsgHdr, prPendingMsgHdrNext, prRemoveMsgHdr = NULL;
892     P_LINK_ENTRY_T prRemoveLinkEntry = NULL;
893
894     ASSERT(prAdapter);
895
896     prScanInfo = &(prAdapter->rWifiVar.rScanInfo);
897     prScanParam = &prScanInfo->rScanParam;
898
899     /* traverse through rPendingMsgList for removal */
900     LINK_FOR_EACH_ENTRY_SAFE(prPendingMsgHdr,
901             prPendingMsgHdrNext,
902             &(prScanInfo->rPendingMsgList),
903             rLinkEntry,
904             MSG_HDR_T) {
905         if(prPendingMsgHdr->eMsgId == MID_AIS_SCN_SCAN_REQ
906                 || prPendingMsgHdr->eMsgId == MID_BOW_SCN_SCAN_REQ
907                 || prPendingMsgHdr->eMsgId == MID_P2P_SCN_SCAN_REQ
908                 || prPendingMsgHdr->eMsgId == MID_RLM_SCN_SCAN_REQ) {
909             P_MSG_SCN_SCAN_REQ prScanReqMsg = (P_MSG_SCN_SCAN_REQ)prPendingMsgHdr;
910
911             if(ucSeqNum == prScanReqMsg->ucSeqNum &&
912                     ucNetTypeIndex == prScanReqMsg->ucNetTypeIndex) {
913                 prRemoveLinkEntry = &(prScanReqMsg->rMsgHdr.rLinkEntry);
914                 prRemoveMsgHdr = prPendingMsgHdr;
915             }
916         }
917         else if(prPendingMsgHdr->eMsgId == MID_AIS_SCN_SCAN_REQ_V2
918                 || prPendingMsgHdr->eMsgId == MID_BOW_SCN_SCAN_REQ_V2
919                 || prPendingMsgHdr->eMsgId == MID_P2P_SCN_SCAN_REQ_V2
920                 || prPendingMsgHdr->eMsgId == MID_RLM_SCN_SCAN_REQ_V2) {
921             P_MSG_SCN_SCAN_REQ_V2 prScanReqMsgV2 = (P_MSG_SCN_SCAN_REQ_V2)prPendingMsgHdr;
922
923             if(ucSeqNum == prScanReqMsgV2->ucSeqNum &&
924                     ucNetTypeIndex == prScanReqMsgV2->ucNetTypeIndex) {
925                 prRemoveLinkEntry = &(prScanReqMsgV2->rMsgHdr.rLinkEntry);
926                 prRemoveMsgHdr = prPendingMsgHdr;
927             }
928         }
929
930         if(prRemoveLinkEntry) {
931             /* generate scan-done event for caller */
932             scnFsmGenerateScanDoneMsg(prAdapter,
933                     ucSeqNum,
934                     ucNetTypeIndex,
935                     SCAN_STATUS_CANCELLED);
936
937             /* remove from pending list */
938             LINK_REMOVE_KNOWN_ENTRY(&(prScanInfo->rPendingMsgList), prRemoveLinkEntry);
939             cnmMemFree(prAdapter, prRemoveMsgHdr);
940
941             break;
942         }
943     }
944
945     return;
946 }
947
948
949 /*----------------------------------------------------------------------------*/
950 /*!
951 * \brief
952 *
953 * \param[in]
954 *
955 * \return none
956 */
957 /*----------------------------------------------------------------------------*/
958 VOID
959 scnEventScanDone (
960     IN P_ADAPTER_T          prAdapter,
961     IN P_EVENT_SCAN_DONE    prScanDone
962     )
963 {
964     P_SCAN_INFO_T prScanInfo;
965     P_SCAN_PARAM_T prScanParam;
966
967     prScanInfo = &(prAdapter->rWifiVar.rScanInfo);
968     prScanParam = &prScanInfo->rScanParam;
969
970     // buffer empty channel information
971     if(prScanParam->eScanChannel == SCAN_CHANNEL_FULL
972             || prScanParam->eScanChannel == SCAN_CHANNEL_2G4) {
973         if(prScanDone->ucSparseChannelValid) {
974             prScanInfo->fgIsSparseChannelValid      = TRUE;
975             prScanInfo->rSparseChannel.eBand        = (ENUM_BAND_T)prScanDone->rSparseChannel.ucBand;
976             prScanInfo->rSparseChannel.ucChannelNum = prScanDone->rSparseChannel.ucChannelNum;
977         }
978         else {
979             prScanInfo->fgIsSparseChannelValid      = FALSE;
980         }
981     }
982
983     if(prScanInfo->eCurrentState == SCAN_STATE_SCANNING &&
984             prScanDone->ucSeqNum == prScanParam->ucSeqNum) {
985         /* generate scan-done event for caller */
986         scnFsmGenerateScanDoneMsg(prAdapter,
987                 prScanParam->ucSeqNum,
988                 (UINT_8)prScanParam->eNetTypeIndex,
989                 SCAN_STATUS_DONE);
990
991         /* switch to next pending scan */
992         scnFsmSteps(prAdapter, SCAN_STATE_IDLE);
993     }
994     else {
995         DBGLOG(SCN, LOUD, ("Unexpected SCAN-DONE event: SeqNum = %d, Current State = %d\n",
996                  prScanDone->ucSeqNum,
997                  prScanInfo->eCurrentState));
998     }
999
1000     return;
1001 } /* end of scnEventScanDone */
1002
1003
1004 /*----------------------------------------------------------------------------*/
1005 /*!
1006 * \brief
1007 *
1008 * \param[in]
1009 *
1010 * \return none
1011 */
1012 /*----------------------------------------------------------------------------*/
1013 VOID
1014 scnFsmGenerateScanDoneMsg (
1015     IN P_ADAPTER_T          prAdapter,
1016     IN UINT_8               ucSeqNum,
1017     IN UINT_8               ucNetTypeIndex,
1018     IN ENUM_SCAN_STATUS     eScanStatus
1019     )
1020 {
1021     P_SCAN_INFO_T prScanInfo;
1022     P_SCAN_PARAM_T prScanParam;
1023     P_MSG_SCN_SCAN_DONE prScanDoneMsg;
1024
1025     ASSERT(prAdapter);
1026
1027     prScanInfo = &(prAdapter->rWifiVar.rScanInfo);
1028     prScanParam = &prScanInfo->rScanParam;
1029
1030     prScanDoneMsg = (P_MSG_SCN_SCAN_DONE)cnmMemAlloc(prAdapter, RAM_TYPE_MSG, sizeof(MSG_SCN_SCAN_DONE));
1031     if (!prScanDoneMsg) {
1032         ASSERT(0); // Can't indicate SCAN FSM Complete
1033         return;
1034     }
1035
1036     if(prScanParam->fgIsObssScan == TRUE) {
1037         prScanDoneMsg->rMsgHdr.eMsgId = MID_SCN_RLM_SCAN_DONE;
1038     }
1039     else {
1040         switch((ENUM_NETWORK_TYPE_INDEX_T)ucNetTypeIndex) {
1041         case NETWORK_TYPE_AIS_INDEX:
1042             prScanDoneMsg->rMsgHdr.eMsgId = MID_SCN_AIS_SCAN_DONE;
1043             break;
1044
1045 #if CFG_ENABLE_WIFI_DIRECT
1046         case NETWORK_TYPE_P2P_INDEX:
1047             prScanDoneMsg->rMsgHdr.eMsgId = MID_SCN_P2P_SCAN_DONE;
1048             break;
1049 #endif
1050
1051 #if CFG_ENABLE_BT_OVER_WIFI
1052         case NETWORK_TYPE_BOW_INDEX:
1053             prScanDoneMsg->rMsgHdr.eMsgId = MID_SCN_BOW_SCAN_DONE;
1054             break;
1055 #endif
1056
1057         default:
1058             DBGLOG(SCN, LOUD, ("Unexpected Network Type: %d\n", ucNetTypeIndex));
1059             ASSERT(0);
1060             break;
1061         }
1062     }
1063
1064     prScanDoneMsg->ucSeqNum         = ucSeqNum;
1065     prScanDoneMsg->ucNetTypeIndex   = ucNetTypeIndex;
1066     prScanDoneMsg->eScanStatus      = eScanStatus;
1067
1068     mboxSendMsg(prAdapter,
1069             MBOX_ID_0,
1070             (P_MSG_HDR_T) prScanDoneMsg,
1071             MSG_SEND_METHOD_BUF);
1072
1073 } /* end of scnFsmGenerateScanDoneMsg() */
1074
1075
1076 /*----------------------------------------------------------------------------*/
1077 /*!
1078 * \brief        Query for most sparse channel
1079 *
1080 * \param[in]
1081 *
1082 * \return none
1083 */
1084 /*----------------------------------------------------------------------------*/
1085 BOOLEAN
1086 scnQuerySparseChannel (
1087     IN P_ADAPTER_T      prAdapter,
1088     P_ENUM_BAND_T       prSparseBand,
1089     PUINT_8             pucSparseChannel
1090     )
1091 {
1092     P_SCAN_INFO_T prScanInfo;
1093
1094     ASSERT(prAdapter);
1095
1096     prScanInfo = &(prAdapter->rWifiVar.rScanInfo);
1097
1098     if(prScanInfo->fgIsSparseChannelValid == TRUE) {
1099         if(prSparseBand) {
1100             *prSparseBand = prScanInfo->rSparseChannel.eBand;
1101         }
1102
1103         if(pucSparseChannel) {
1104             *pucSparseChannel = prScanInfo->rSparseChannel.ucChannelNum;
1105         }
1106
1107         return TRUE;
1108     }
1109     else {
1110         return FALSE;
1111     }
1112 }
1113