MT6620: add the new driver JB2 V1.0
[firefly-linux-kernel-4.4.55.git] / drivers / mtk_wcn_combo / drv_wlan / mt6620 / wlan / mgmt / scan.c
1 /*
2 ** $Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/mgmt/scan.c#3 $
3 */
4
5 /*! \file   "scan.c"
6     \brief  This file defines the scan profile and the processing function of
7             scan result for SCAN Module.
8
9     The SCAN Profile selection is part of SCAN MODULE and responsible for defining
10     SCAN Parameters - e.g. MIN_CHANNEL_TIME, number of scan channels.
11     In this file we also define the process of SCAN Result including adding, searching
12     and removing SCAN record from the list.
13 */
14
15
16
17 /*
18 ** $Log: scan.c $
19 **
20 ** 01 16 2013 yuche.tsai
21 ** [ALPS00431980] [WFD]Aupus one ?play game 10 minitues?wfd connection automaticlly disconnect
22 ** Fix possible FW assert issue.
23  *
24  * 07 17 2012 yuche.tsai
25  * NULL
26  * Let netdev bring up.
27  *
28  * 07 17 2012 yuche.tsai
29  * NULL
30  * Compile no error before trial run.
31  *
32  * 06 25 2012 cp.wu
33  * [WCXRP00001258] [MT6620][MT5931][MT6628][Driver] Do not use stale scan result for deciding connection target
34  * drop off scan result which is older than 5 seconds when choosing which BSS to join
35  *
36  * 03 02 2012 terry.wu
37  * NULL
38  * Sync CFG80211 modification from branch 2,2.
39  *
40  * 01 16 2012 cp.wu
41  * [WCXRP00001169] [MT6620 Wi-Fi][Driver] API and behavior modification for preferred band configuration with corresponding network configuration
42  * correct typo.
43  *
44  * 01 16 2012 cp.wu
45  * [MT6620 Wi-Fi][Driver] API and behavior modification for preferred band configuration with corresponding network configuration 
46  * add wlanSetPreferBandByNetwork() for glue layer to invoke for setting preferred band configuration corresponding to network type.
47  *
48  * 12 05 2011 cp.wu
49  * [WCXRP00001131] [MT6620 Wi-Fi][Driver][AIS] Implement connect-by-BSSID path
50  * add CONNECT_BY_BSSID policy
51  *
52  * 11 23 2011 cp.wu
53  * [WCXRP00001123] [MT6620 Wi-Fi][Driver] Add option to disable beacon content change detection
54  * add compile option to disable beacon content change detection.
55  *
56  * 11 04 2011 cp.wu
57  * [WCXRP00001085] [MT6628 Wi-Fi][Driver] deprecate old BSS-DESC if timestamp is reset with received beacon/probe response frames
58  * deprecate old BSS-DESC when timestamp in received beacon/probe response frames showed a smaller value than before
59  *
60  * 10 11 2011 cm.chang
61  * [WCXRP00001031] [All Wi-Fi][Driver] Check HT IE length to avoid wrong SCO parameter
62  * Ignore HT OP IE if its length field is not valid
63  *
64  * 09 30 2011 cp.wu
65  * [WCXRP00001021] [MT5931][Driver] Correct scan result generation for conversion between BSS type and operation mode
66  * correct type casting issue.
67  *
68  * 08 23 2011 yuche.tsai
69  * NULL
70  * Fix multicast address list issue.
71  *
72  * 08 11 2011 cp.wu
73  * [WCXRP00000830] [MT6620 Wi-Fi][Firmware] Use MDRDY counter to detect empty channel for shortening scan time
74  * sparse channel detection:
75  * driver: collect sparse channel information with scan-done event
76  *
77  * 08 10 2011 cp.wu
78  * [WCXRP00000922] [MT6620 Wi-Fi][Driver] traverse whole BSS-DESC list for removing
79  * traverse whole BSS-DESC list because BSSID is not unique anymore.
80  *
81  * 07 12 2011 cp.wu
82  * [WCXRP00000815] [MT6620 Wi-Fi][Driver] allow single BSSID with multiple SSID settings to work around some tricky AP which use space character as hidden SSID
83  * for multiple BSS descriptior detecting issue:
84  * 1) check BSSID for infrastructure network
85  * 2) check SSID for AdHoc network
86  *
87  * 07 12 2011 cp.wu
88  * [WCXRP00000815] [MT6620 Wi-Fi][Driver] allow single BSSID with multiple SSID settings to work around some tricky AP which use space character as hidden SSID
89  * check for BSSID for beacons used to update DTIM
90  *
91  * 07 12 2011 cp.wu
92  * [WCXRP00000815] [MT6620 Wi-Fi][Driver] allow single BSSID with multiple SSID settings to work around some tricky AP which use space character as hidden SSID
93  * do not check BSS descriptor for connected flag due to linksys's hidden SSID will use another BSS descriptor and never connected
94  *
95  * 07 11 2011 cp.wu
96  * [WCXRP00000815] [MT6620 Wi-Fi][Driver] allow single BSSID with multiple SSID settings to work around some tricky AP which use space character as hidden SSID
97  * just pass beacons with the same BSSID.
98  *
99  * 07 11 2011 wh.su
100  * [WCXRP00000849] [MT6620 Wi-Fi][Driver] Remove some of the WAPI define for make sure the value is initialize, for customer not enable WAPI
101  * For make sure wapi initial value is set.
102  *
103  * 06 28 2011 cp.wu
104  * [WCXRP00000815] [MT6620 Wi-Fi][Driver] allow single BSSID with multiple SSID settings to work around some tricky AP which use space character as hidden SSID
105  * Do not check for SSID as beacon content change due to the existence of single BSSID with multiple SSID AP configuration
106  *
107  * 06 27 2011 cp.wu
108  * [WCXRP00000815] [MT6620 Wi-Fi][Driver] allow single BSSID with multiple SSID settings to work around some tricky AP which use space character as hidden SSID
109  * 1. correct logic
110  * 2. replace only BSS-DESC which doesn't have a valid SSID.
111  *
112  * 06 27 2011 cp.wu
113  * [WCXRP00000815] [MT6620 Wi-Fi][Driver] allow single BSSID with multiple SSID settings to work around some tricky AP which use space character as hidden SSID
114  * remove unused temporal variable reference.
115  *
116  * 06 27 2011 cp.wu
117  * [WCXRP00000815] [MT6620 Wi-Fi][Driver] allow single BSSID with multiple SSID settings to work around some tricky AP which use space character as hidden SSID
118  * allow to have a single BSSID with multiple SSID to be presented in scanning result
119  *
120  * 06 02 2011 cp.wu
121  * [WCXRP00000757] [MT6620 Wi-Fi][Driver][SCN] take use of RLM API to filter out BSS in disallowed channels
122  * filter out BSS in disallowed channel by
123  * 1. do not add to scan result array if BSS is at disallowed channel
124  * 2. do not allow to search for BSS-DESC in disallowed channels
125  *
126  * 05 02 2011 cm.chang
127  * [WCXRP00000691] [MT6620 Wi-Fi][Driver] Workaround about AP's wrong HT capability IE to have wrong channel number
128  * Refine range of valid channel number
129  *
130  * 05 02 2011 cp.wu
131  * [MT6620 Wi-Fi][Driver] Take parsed result for channel information instead of hardware channel number passed from firmware domain
132  * take parsed result for generating scanning result with channel information.
133  *
134  * 05 02 2011 cm.chang
135  * [WCXRP00000691] [MT6620 Wi-Fi][Driver] Workaround about AP's wrong HT capability IE to have wrong channel number
136  * Check if channel is valided before record ing BSS channel
137  *
138  * 04 18 2011 terry.wu
139  * [WCXRP00000660] [MT6620 Wi-Fi][Driver] Remove flag CFG_WIFI_DIRECT_MOVED
140  * Remove flag CFG_WIFI_DIRECT_MOVED.
141  *
142  * 04 14 2011 cm.chang
143  * [WCXRP00000634] [MT6620 Wi-Fi][Driver][FW] 2nd BSS will not support 40MHz bandwidth for concurrency
144  * .
145  *
146  * 04 12 2011 eddie.chen
147  * [WCXRP00000617] [MT6620 Wi-Fi][DRV/FW] Fix for sigma
148  * Fix the sta index in processing security frame
149  * Simple flow control for TC4 to avoid mgt frames for PS STA to occupy the TC4
150  * Add debug message.
151  *
152  * 03 25 2011 yuche.tsai
153  * NULL
154  * Always update Bss Type, for Bss Type for P2P Network is changing every time.
155  *
156  * 03 23 2011 yuche.tsai
157  * NULL
158  * Fix concurrent issue when AIS scan result would overwrite p2p scan result.
159  *
160  * 03 14 2011 cp.wu
161  * [WCXRP00000535] [MT6620 Wi-Fi][Driver] Fixed channel operation when AIS and Tethering are operating concurrently
162  * filtering out other BSS coming from adjacent channels
163  *
164  * 03 11 2011 chinglan.wang
165  * [WCXRP00000537] [MT6620 Wi-Fi][Driver] Can not connect to 802.11b/g/n mixed AP with WEP security.
166  * .
167  *
168  * 03 11 2011 cp.wu
169  * [WCXRP00000535] [MT6620 Wi-Fi][Driver] Fixed channel operation when AIS and Tethering are operating concurrently
170  * When fixed channel operation is necessary, AIS-FSM would scan and only connect for BSS on the specific channel
171  *
172  * 02 24 2011 cp.wu
173  * [WCXRP00000490] [MT6620 Wi-Fi][Driver][Win32] modify kalMsleep() implementation because NdisMSleep() won't sleep long enough for specified interval such as 500ms
174  * implement beacon change detection by checking SSID and supported rate.
175  *
176  * 02 22 2011 yuche.tsai
177  * [WCXRP00000480] [Volunteer Patch][MT6620][Driver] WCS IE format issue
178  * Fix WSC big endian issue.
179  *
180  * 02 21 2011 terry.wu
181  * [WCXRP00000476] [MT6620 Wi-Fi][Driver] Clean P2P scan list while removing P2P
182  * Clean P2P scan list while removing P2P.
183  *
184  * 01 27 2011 yuche.tsai
185  * [WCXRP00000399] [Volunteer Patch][MT6620/MT5931][Driver] Fix scan side effect after P2P module separate.
186  * Fix scan channel extension issue when p2p module is not registered.
187  *
188  * 01 26 2011 cm.chang
189  * [WCXRP00000395] [MT6620 Wi-Fi][Driver][FW] Search STA_REC with additional net type index argument
190  * .
191  *
192  * 01 21 2011 cp.wu
193  * [WCXRP00000380] [MT6620 Wi-Fi][Driver] SSID information should come from buffered BSS_DESC_T rather than using beacon-carried information
194  * SSID should come from buffered prBssDesc rather than beacon-carried information
195  *
196  * 01 14 2011 yuche.tsai
197  * [WCXRP00000352] [Volunteer Patch][MT6620][Driver] P2P Statsion Record Client List Issue
198  * Fix compile error.
199  *
200  * 01 14 2011 yuche.tsai
201  * [WCXRP00000352] [Volunteer Patch][MT6620][Driver] P2P Statsion Record Client List Issue
202  * Memfree for P2P Descriptor & P2P Descriptor List.
203  *
204  * 01 14 2011 yuche.tsai
205  * [WCXRP00000352] [Volunteer Patch][MT6620][Driver] P2P Statsion Record Client List Issue
206  * Free P2P Descriptor List & Descriptor under BSS Descriptor.
207  *
208  * 01 04 2011 cp.wu
209  * [WCXRP00000338] [MT6620 Wi-Fi][Driver] Separate kalMemAlloc into kmalloc and vmalloc implementations to ease physically continous memory demands
210  * 1) correct typo in scan.c
211  * 2) TX descriptors, RX descriptos and management buffer should use virtually continous buffer instead of physically contineous one
212  *
213  * 01 04 2011 cp.wu
214  * [WCXRP00000338] [MT6620 Wi-Fi][Driver] Separate kalMemAlloc into kmalloc and vmalloc implementations to ease physically continous memory demands
215  * separate kalMemAlloc() into virtually-continous and physically-continous type to ease slab system pressure
216  *
217  * 12 31 2010 cp.wu
218  * [WCXRP00000327] [MT6620 Wi-Fi][Driver] Improve HEC WHQA 6972 workaround coverage in driver side
219  * while being unloaded, clear all pending interrupt then set LP-own to firmware
220  *
221  * 12 21 2010 cp.wu
222  * [WCXRP00000280] [MT6620 Wi-Fi][Driver] Enable BSS selection with best RCPI policy in SCN module
223  * SCN: enable BEST RSSI selection policy support
224  *
225  * 11 29 2010 cp.wu
226  * [WCXRP00000210] [MT6620 Wi-Fi][Driver][FW] Set RCPI value in STA_REC for initial TX rate selection of auto-rate algorithm
227  * update ucRcpi of STA_RECORD_T for AIS when
228  * 1) Beacons for IBSS merge is received
229  * 2) Associate Response for a connecting peer is received
230  *
231  * 11 03 2010 wh.su
232  * [WCXRP00000124] [MT6620 Wi-Fi] [Driver] Support the dissolve P2P Group
233  * Refine the HT rate disallow TKIP pairwise cipher .
234  *
235  * 10 12 2010 cp.wu
236  * [WCXRP00000091] [MT6620 Wi-Fi][Driver] Add scanning logic to filter out beacons which is received on the folding frequency
237  * trust HT IE if available for 5GHz band
238  *
239  * 10 11 2010 cp.wu
240  * [WCXRP00000091] [MT6620 Wi-Fi][Driver] Add scanning logic to filter out beacons which is received on the folding frequency
241  * add timing and strenght constraint for filtering out beacons with same SSID/TA but received on different channels
242  *
243  * 10 08 2010 wh.su
244  * [WCXRP00000085] [MT6620 Wif-Fi] [Driver] update the modified p2p state machine
245  * update the frog's new p2p state machine.
246  *
247  * 10 01 2010 yuche.tsai
248  * NULL
249  * [MT6620 P2P] Fix Big Endian Issue when parse P2P device name TLV.
250  *
251  * 09 24 2010 cp.wu
252  * [WCXRP00000052] [MT6620 Wi-Fi][Driver] Eliminate Linux Compile Warning
253  * eliminate unused variables which lead gcc to argue
254  *
255  * 09 08 2010 cp.wu
256  * NULL
257  * use static memory pool for storing IEs of scanning result.
258  *
259  * 09 07 2010 yuche.tsai
260  * NULL
261  * When indicate scan result, append IE buffer information in the scan result.
262  *
263  * 09 03 2010 yuche.tsai
264  * NULL
265  * 1. Update Beacon RX count when running SLT.
266  * 2. Ignore Beacon when running SLT, would not update information from Beacon.
267  *
268  * 09 03 2010 kevin.huang
269  * NULL
270  * Refine #include sequence and solve recursive/nested #include issue
271  *
272  * 08 31 2010 kevin.huang
273  * NULL
274  * Use LINK LIST operation to process SCAN result
275  *
276  * 08 29 2010 yuche.tsai
277  * NULL
278  * 1. Fix P2P Descriptor List to be a link list, to avoid link corrupt after Bss Descriptor Free.
279  * 2.. Fix P2P Device Name Length BE issue.
280  *
281  * 08 23 2010 yuche.tsai
282  * NULL
283  * Add P2P Device Found Indication to supplicant
284  *
285  * 08 20 2010 cp.wu
286  * NULL
287  * reset BSS_DESC_T variables before parsing IE due to peer might have been reconfigured.
288  *
289  * 08 20 2010 yuche.tsai
290  * NULL
291  * Workaround for P2P Descriptor Infinite loop issue.
292  *
293  * 08 16 2010 cp.wu
294  * NULL
295  * Replace CFG_SUPPORT_BOW by CFG_ENABLE_BT_OVER_WIFI.
296  * There is no CFG_SUPPORT_BOW in driver domain source.
297  *
298  * 08 16 2010 yuche.tsai
299  * NULL
300  * Modify code of processing Probe Resonse frame for P2P.
301  *
302  * 08 12 2010 yuche.tsai
303  * NULL
304  * Add function to get P2P descriptor of BSS descriptor directly.
305  *
306  * 08 11 2010 yuche.tsai
307  * NULL
308  * Modify Scan result processing for P2P module.
309  *
310  * 08 05 2010 yuche.tsai
311  * NULL
312  * Update P2P Device Discovery result add function.
313  *
314  * 08 03 2010 cp.wu
315  * NULL
316  * surpress compilation warning.
317  *
318  * 07 26 2010 yuche.tsai
319  *
320  * Add support for Probe Request & Response parsing.
321  *
322  * 07 21 2010 cp.wu
323  *
324  * 1) change BG_SCAN to ONLINE_SCAN for consistent term
325  * 2) only clear scanning result when scan is permitted to do
326  *
327  * 07 21 2010 yuche.tsai
328  *
329  * Fix compile error for SCAN module while disabling P2P feature.
330  *
331  * 07 21 2010 yuche.tsai
332  *
333  * Add P2P Scan & Scan Result Parsing & Saving.
334  *
335  * 07 19 2010 wh.su
336  *
337  * update for security supporting.
338  *
339  * 07 19 2010 cp.wu
340  *
341  * [WPD00003833] [MT6620 and MT5931] Driver migration.
342  * Add Ad-Hoc support to AIS-FSM
343  *
344  * 07 19 2010 cp.wu
345  *
346  * [WPD00003833] [MT6620 and MT5931] Driver migration.
347  * SCN module is now able to handle multiple concurrent scanning requests
348  *
349  * 07 15 2010 cp.wu
350  *
351  * [WPD00003833] [MT6620 and MT5931] Driver migration.
352  * driver no longer generates probe request frames
353  *
354  * 07 14 2010 cp.wu
355  *
356  * [WPD00003833] [MT6620 and MT5931] Driver migration.
357  * remove timer in DRV-SCN.
358  *
359  * 07 09 2010 cp.wu
360  *
361  * 1) separate AIS_FSM state for two kinds of scanning. (OID triggered scan, and scan-for-connection)
362  * 2) eliminate PRE_BSS_DESC_T, Beacon/PrebResp is now parsed in single pass
363  * 3) implment DRV-SCN module, currently only accepts single scan request, other request will be directly dropped by returning BUSY
364  *
365  * 07 08 2010 cp.wu
366  *
367  * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository.
368  *
369  * 07 08 2010 cp.wu
370  * [WPD00003833][MT6620 and MT5931] Driver migration
371  * take use of RLM module for parsing/generating HT IEs for 11n capability
372  *
373  * 07 05 2010 cp.wu
374  * [WPD00003833][MT6620 and MT5931] Driver migration
375  * 1) ignore RSN checking when RSN is not turned on.
376  * 2) set STA-REC deactivation callback as NULL
377  * 3) add variable initialization API based on PHY configuration
378  *
379  * 07 05 2010 cp.wu
380  * [WPD00003833][MT6620 and MT5931] Driver migration
381  * correct BSS_DESC_T initialization after allocated.
382  *
383  * 07 02 2010 cp.wu
384  * [WPD00003833][MT6620 and MT5931] Driver migration
385  * 1) for event packet, no need to fill RFB.
386  * 2) when wlanAdapterStart() failed, no need to initialize state machines
387  * 3) after Beacon/ProbeResp parsing, corresponding BSS_DESC_T should be marked as IE-parsed
388  *
389  * 07 01 2010 cp.wu
390  * [WPD00003833][MT6620 and MT5931] Driver migration
391  * add scan uninitialization procedure
392  *
393  * 06 30 2010 cp.wu
394  * [WPD00003833][MT6620 and MT5931] Driver migration
395  * if beacon/probe-resp is received in 2.4GHz bands and there is ELEM_ID_DS_PARAM_SET IE available,
396  * trust IE instead of RMAC information
397  *
398  * 06 29 2010 cp.wu
399  * [WPD00003833][MT6620 and MT5931] Driver migration
400  * 1) sync to. CMD/EVENT document v0.03
401  * 2) simplify DTIM period parsing in scan.c only, bss.c no longer parses it again.
402  * 3) send command packet to indicate FW-PM after
403  *     a) 1st beacon is received after AIS has connected to an AP
404  *     b) IBSS-ALONE has been created
405  *     c) IBSS-MERGE has occured
406  *
407  * 06 28 2010 cp.wu
408  * [WPD00003833][MT6620 and MT5931] Driver migration
409  * send MMPDU in basic rate.
410  *
411  * 06 25 2010 cp.wu
412  * [WPD00003833][MT6620 and MT5931] Driver migration
413  * modify Beacon/ProbeResp to complete parsing,
414  * because host software has looser memory usage restriction
415  *
416  * 06 23 2010 cp.wu
417  * [WPD00003833][MT6620 and MT5931] Driver migration
418  * integrate .
419  *
420  * 06 22 2010 cp.wu
421  * [WPD00003833][MT6620 and MT5931] Driver migration
422  * comment out RLM APIs by CFG_RLM_MIGRATION.
423  *
424  * 06 21 2010 yuche.tsai
425  * [WPD00003839][MT6620 5931][P2P] Feature migration
426  * Update P2P Function call.
427  *
428  * 06 21 2010 cp.wu
429  * [WPD00003833][MT6620 and MT5931] Driver migration
430  * RSN/PRIVACY compilation flag awareness correction
431  *
432  * 06 21 2010 cp.wu
433  * [WPD00003833][MT6620 and MT5931] Driver migration
434  * specify correct value for management frames.
435  *
436  * 06 18 2010 cm.chang
437  * [WPD00003841][LITE Driver] Migrate RLM/CNM to host driver
438  * Provide cnmMgtPktAlloc() and alloc/free function of msg/buf
439  *
440  * 06 18 2010 wh.su
441  * [WPD00003840][MT6620 5931] Security migration
442  * migration from MT6620 firmware.
443  *
444  * 06 17 2010 yuche.tsai
445  * [WPD00003839][MT6620 5931][P2P] Feature migration
446  * Fix compile error when enable P2P function.
447  *
448  * 06 15 2010 cp.wu
449  * [WPD00003833][MT6620 and MT5931] Driver migration
450  * correct when ADHOC support is turned on.
451  *
452  * 06 15 2010 cp.wu
453  * [WPD00003833][MT6620 and MT5931] Driver migration
454  * add scan.c.
455  *
456  * 06 04 2010 george.huang
457  * [BORA00000678][MT6620]WiFi LP integration
458  * [PM] Support U-APSD for STA mode
459  *
460  * 05 28 2010 wh.su
461  * [BORA00000680][MT6620] Support the statistic for Microsoft os query
462  * adding the TKIP disallow join a HT AP code.
463  *
464  * 05 14 2010 kevin.huang
465  * [BORA00000794][WIFISYS][New Feature]Power Management Support
466  * Add more chance of JOIN retry for BG_SCAN
467  *
468  * 05 12 2010 kevin.huang
469  * [BORA00000794][WIFISYS][New Feature]Power Management Support
470  * Add Power Management - Legacy PS-POLL support.
471  *
472  * 04 29 2010 wh.su
473  * [BORA00000637][MT6620 Wi-Fi] [Bug] WPA2 pre-authentication timer not correctly initialize
474  * adjsut the pre-authentication code.
475  *
476  * 04 27 2010 kevin.huang
477  * [BORA00000663][WIFISYS][New Feature] AdHoc Mode Support
478  * Add Set Slot Time and Beacon Timeout Support for AdHoc Mode
479  *
480  * 04 24 2010 cm.chang
481  * [BORA00000018]Integrate WIFI part into BORA for the 1st time
482  * g_aprBssInfo[] depends on CFG_SUPPORT_P2P and CFG_SUPPORT_BOW
483  *
484  * 04 19 2010 kevin.huang
485  * [BORA00000714][WIFISYS][New Feature]Beacon Timeout Support
486  * Add Beacon Timeout Support and will send Null frame to diagnose connection
487  *
488  * 04 13 2010 kevin.huang
489  * [BORA00000663][WIFISYS][New Feature] AdHoc Mode Support
490  * Add new HW CH macro support
491  *
492  * 04 06 2010 wh.su
493  * [BORA00000680][MT6620] Support the statistic for Microsoft os query
494  * fixed the firmware return the broadcast frame at wrong tc.
495  *
496  * 03 29 2010 wh.su
497  * [BORA00000605][WIFISYS] Phase3 Integration
498  * let the rsn wapi IE always parsing.
499  *
500  * 03 24 2010 cm.chang
501  * [BORA00000018]Integrate WIFI part into BORA for the 1st time
502  * Not carry  HT cap when being associated with b/g only AP
503  *
504  * 03 18 2010 kevin.huang
505  * [BORA00000663][WIFISYS][New Feature] AdHoc Mode Support
506  * Solve the compile warning for 'return non-void' function
507  *
508  * 03 16 2010 kevin.huang
509  * [BORA00000663][WIFISYS][New Feature] AdHoc Mode Support
510  * Add AdHoc Mode
511  *
512  * 03 10 2010 kevin.huang
513  * [BORA00000654][WIFISYS][New Feature] CNM Module - Ch Manager Support
514  *
515  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  * Add Channel Manager for arbitration of JOIN and SCAN Req
516  *
517  * 03 03 2010 wh.su
518  * [BORA00000637][MT6620 Wi-Fi] [Bug] WPA2 pre-authentication timer not correctly initialize
519  * move the AIS specific variable for security to AIS specific structure.
520  *
521  * 03 01 2010 wh.su
522  * [BORA00000605][WIFISYS] Phase3 Integration
523  * Refine the variable and parameter for security.
524  *
525  * 02 26 2010 kevin.huang
526  * [BORA00000603][WIFISYS] [New Feature] AAA Module Support
527  * Fix No PKT_INFO_T issue
528  *
529  * 02 26 2010 kevin.huang
530  * [BORA00000603][WIFISYS] [New Feature] AAA Module Support
531  * Update outgoing ProbeRequest Frame's TX data rate
532  *
533  * 02 23 2010 wh.su
534  * [BORA00000592][MT6620 Wi-Fi] Adding the security related code for driver
535  * refine the scan procedure, reduce the WPA and WAPI IE parsing, and move the parsing to the time for join.
536  *
537  * 02 23 2010 kevin.huang
538  * [BORA00000603][WIFISYS] [New Feature] AAA Module Support
539  * Add support scan channel 1~14 and update scan result's frequency infou1rwduu`wvpghlqg|n`slk+mpdkb
540  *
541  * 02 04 2010 kevin.huang
542  * [BORA00000603][WIFISYS] [New Feature] AAA Module Support
543  * Add AAA Module Support, Revise Net Type to Net Type Index for array lookup
544  *
545  * 01 27 2010 wh.su
546  * [BORA00000476][Wi-Fi][firmware] Add the security module initialize code
547  * add and fixed some security function.
548  *
549  * 01 22 2010 cm.chang
550  * [BORA00000018]Integrate WIFI part into BORA for the 1st time
551  * Support protection and bandwidth switch
552  *
553  * 01 20 2010 kevin.huang
554  * [BORA00000569][WIFISYS] Phase 2 Integration Test
555  * Add PHASE_2_INTEGRATION_WORK_AROUND and CFG_SUPPORT_BCM flags
556  *
557  * 01 11 2010 kevin.huang
558  * [BORA00000018]Integrate WIFI part into BORA for the 1st time
559  * Add Deauth and Disassoc Handler
560  *
561  * 01 08 2010 kevin.huang
562  * [BORA00000018]Integrate WIFI part into BORA for the 1st time
563  *
564  * Refine Beacon processing, add read RF channel from RX Status
565  *
566  * 01 04 2010 tehuang.liu
567  * [BORA00000018]Integrate WIFI part into BORA for the 1st time
568  * For working out the first connection Chariot-verified version
569  *
570  * 12 18 2009 cm.chang
571  * [BORA00000018]Integrate WIFI part into BORA for the 1st time
572  * .
573  *
574  * Dec 12 2009 mtk01104
575  * [BORA00000018] Integrate WIFI part into BORA for the 1st time
576  * Modify u2EstimatedExtraIELen for probe request
577  *
578  * Dec 9 2009 mtk01104
579  * [BORA00000018] Integrate WIFI part into BORA for the 1st time
580  * Add HT cap IE to probe request
581  *
582  * Dec 7 2009 mtk01461
583  * [BORA00000018] Integrate WIFI part into BORA for the 1st time
584  * Fix lint warning
585  *
586  *
587  * Dec 3 2009 mtk01461
588  * [BORA00000018] Integrate WIFI part into BORA for the 1st time
589  * Update the process of SCAN Result by adding more Phy Attributes
590  *
591  * Dec 1 2009 mtk01088
592  * [BORA00000476] [Wi-Fi][firmware] Add the security module initialize code
593  * adjust the function and code for meet the new define
594  *
595  * Nov 30 2009 mtk01461
596  * [BORA00000018] Integrate WIFI part into BORA for the 1st time
597  * Rename u4RSSI to i4RSSI
598  *
599  * Nov 30 2009 mtk01461
600  * [BORA00000018] Integrate WIFI part into BORA for the 1st time
601  * Report event of scan result to host
602  *
603  * Nov 26 2009 mtk01461
604  * [BORA00000018] Integrate WIFI part into BORA for the 1st time
605  * Fix SCAN Record update
606  *
607  * Nov 24 2009 mtk01461
608  * [BORA00000018] Integrate WIFI part into BORA for the 1st time
609  * Revise MGMT Handler with Retain Status and Integrate with TXM
610  *
611  * Nov 23 2009 mtk01461
612  * [BORA00000018] Integrate WIFI part into BORA for the 1st time
613  * Add (Ext)Support Rate Set IE to ProbeReq
614  *
615  * Nov 20 2009 mtk02468
616  * [BORA00000337] To check in codes for FPGA emulation
617  * Removed the use of SW_RFB->u2FrameLength
618  *
619  * Nov 20 2009 mtk01461
620  * [BORA00000018] Integrate WIFI part into BORA for the 1st time
621  * Fix uninitial aucMacAddress[] for ProbeReq
622  *
623  * Nov 16 2009 mtk01461
624  * [BORA00000018] Integrate WIFI part into BORA for the 1st time
625  * Add scanSearchBssDescByPolicy()
626  *
627  * Nov 5 2009 mtk01461
628  * [BORA00000018] Integrate WIFI part into BORA for the 1st time
629  * Add Send Probe Request Frame
630  *
631  * Oct 30 2009 mtk01461
632  * [BORA00000018] Integrate WIFI part into BORA for the 1st time
633  *
634 */
635
636 /*******************************************************************************
637 *                         C O M P I L E R   F L A G S
638 ********************************************************************************
639 */
640
641 /*******************************************************************************
642 *                    E X T E R N A L   R E F E R E N C E S
643 ********************************************************************************
644 */
645 #include "precomp.h"
646
647 /*******************************************************************************
648 *                              C O N S T A N T S
649 ********************************************************************************
650 */
651 #define REPLICATED_BEACON_TIME_THRESHOLD        (3000)
652 #define REPLICATED_BEACON_FRESH_PERIOD          (10000)
653 #define REPLICATED_BEACON_STRENGTH_THRESHOLD    (32)
654
655 #define ROAMING_NO_SWING_RCPI_STEP              (10)
656
657 /*******************************************************************************
658 *                             D A T A   T Y P E S
659 ********************************************************************************
660 */
661
662 /*******************************************************************************
663 *                            P U B L I C   D A T A
664 ********************************************************************************
665 */
666
667 /*******************************************************************************
668 *                           P R I V A T E   D A T A
669 ********************************************************************************
670 */
671
672 /*******************************************************************************
673 *                                 M A C R O S
674 ********************************************************************************
675 */
676
677 /*******************************************************************************
678 *                   F U N C T I O N   D E C L A R A T I O N S
679 ********************************************************************************
680 */
681
682 /*******************************************************************************
683 *                              F U N C T I O N S
684 ********************************************************************************
685 */
686 /*----------------------------------------------------------------------------*/
687 /*!
688 * @brief This function is used by SCN to initialize its variables
689 *
690 * @param (none)
691 *
692 * @return (none)
693 */
694 /*----------------------------------------------------------------------------*/
695 VOID
696 scnInit (
697     IN P_ADAPTER_T prAdapter
698     )
699 {
700     P_SCAN_INFO_T prScanInfo;
701     P_BSS_DESC_T prBSSDesc;
702     PUINT_8 pucBSSBuff;
703     UINT_32 i;
704
705
706     ASSERT(prAdapter);
707
708     prScanInfo = &(prAdapter->rWifiVar.rScanInfo);
709     pucBSSBuff = &prScanInfo->aucScanBuffer[0];
710
711
712     DBGLOG(SCN, INFO, ("->scnInit()\n"));
713
714     //4 <1> Reset STATE and Message List
715     prScanInfo->eCurrentState = SCAN_STATE_IDLE;
716
717     prScanInfo->rLastScanCompletedTime = (OS_SYSTIME)0;
718
719     LINK_INITIALIZE(&prScanInfo->rPendingMsgList);
720
721
722     //4 <2> Reset link list of BSS_DESC_T
723     kalMemZero((PVOID) pucBSSBuff, SCN_MAX_BUFFER_SIZE);
724
725     LINK_INITIALIZE(&prScanInfo->rFreeBSSDescList);
726     LINK_INITIALIZE(&prScanInfo->rBSSDescList);
727
728     for (i = 0; i < CFG_MAX_NUM_BSS_LIST; i++) {
729
730         prBSSDesc = (P_BSS_DESC_T)pucBSSBuff;
731
732         LINK_INSERT_TAIL(&prScanInfo->rFreeBSSDescList, &prBSSDesc->rLinkEntry);
733
734         pucBSSBuff += ALIGN_4(sizeof(BSS_DESC_T));
735     }
736     /* Check if the memory allocation consist with this initialization function */
737     ASSERT(((UINT_32)pucBSSBuff - (UINT_32)&prScanInfo->aucScanBuffer[0]) == SCN_MAX_BUFFER_SIZE);
738
739     /* reset freest channel information */
740     prScanInfo->fgIsSparseChannelValid = FALSE;
741
742     return;
743 } /* end of scnInit() */
744
745
746 /*----------------------------------------------------------------------------*/
747 /*!
748 * @brief This function is used by SCN to uninitialize its variables
749 *
750 * @param (none)
751 *
752 * @return (none)
753 */
754 /*----------------------------------------------------------------------------*/
755 VOID
756 scnUninit (
757     IN P_ADAPTER_T prAdapter
758     )
759 {
760     P_SCAN_INFO_T prScanInfo;
761
762
763     ASSERT(prAdapter);
764     prScanInfo = &(prAdapter->rWifiVar.rScanInfo);
765
766     DBGLOG(SCN, INFO, ("->scnUninit()\n"));
767
768     //4 <1> Reset STATE and Message List
769     prScanInfo->eCurrentState = SCAN_STATE_IDLE;
770
771     prScanInfo->rLastScanCompletedTime = (OS_SYSTIME)0;
772
773     /* NOTE(Kevin): Check rPendingMsgList ? */
774
775     //4 <2> Reset link list of BSS_DESC_T
776     LINK_INITIALIZE(&prScanInfo->rFreeBSSDescList);
777     LINK_INITIALIZE(&prScanInfo->rBSSDescList);
778
779     return;
780 } /* end of scnUninit() */
781
782
783
784 /*----------------------------------------------------------------------------*/
785 /*!
786 * @brief Find the corresponding BSS Descriptor according to given BSSID
787 *
788 * @param[in] prAdapter          Pointer to the Adapter structure.
789 * @param[in] aucBSSID           Given BSSID.
790 *
791 * @return   Pointer to BSS Descriptor, if found. NULL, if not found
792 */
793 /*----------------------------------------------------------------------------*/
794 P_BSS_DESC_T
795 scanSearchBssDescByBssid (
796     IN P_ADAPTER_T prAdapter,
797     IN UINT_8 aucBSSID[]
798     )
799 {
800     return scanSearchBssDescByBssidAndSsid(prAdapter,
801             aucBSSID,
802             FALSE,
803             NULL);
804 }
805
806
807 /*----------------------------------------------------------------------------*/
808 /*!
809 * @brief Find the corresponding BSS Descriptor according to given BSSID
810 *
811 * @param[in] prAdapter          Pointer to the Adapter structure.
812 * @param[in] aucBSSID           Given BSSID.
813 * @param[in] fgCheckSsid        Need to check SSID or not. (for multiple SSID with single BSSID cases)
814 * @param[in] prSsid             Specified SSID
815 *
816 * @return   Pointer to BSS Descriptor, if found. NULL, if not found
817 */
818 /*----------------------------------------------------------------------------*/
819 P_BSS_DESC_T
820 scanSearchBssDescByBssidAndSsid (
821     IN P_ADAPTER_T prAdapter,
822     IN UINT_8 aucBSSID[],
823     IN BOOLEAN fgCheckSsid,
824     IN P_PARAM_SSID_T prSsid
825     )
826 {
827     P_SCAN_INFO_T prScanInfo;
828     P_LINK_T prBSSDescList;
829     P_BSS_DESC_T prBssDesc;
830     P_BSS_DESC_T prDstBssDesc = (P_BSS_DESC_T)NULL;
831
832
833     ASSERT(prAdapter);
834     ASSERT(aucBSSID);
835
836     prScanInfo = &(prAdapter->rWifiVar.rScanInfo);
837
838     prBSSDescList = &prScanInfo->rBSSDescList;
839
840     /* Search BSS Desc from current SCAN result list. */
841     LINK_FOR_EACH_ENTRY(prBssDesc, prBSSDescList, rLinkEntry, BSS_DESC_T) {
842
843         if (EQUAL_MAC_ADDR(prBssDesc->aucBSSID, aucBSSID)) {
844             if(fgCheckSsid == FALSE || prSsid == NULL) {
845                 return prBssDesc;
846             }
847             else {
848                 if(EQUAL_SSID(prBssDesc->aucSSID,
849                             prBssDesc->ucSSIDLen,
850                             prSsid->aucSsid,
851                             prSsid->u4SsidLen)) {
852                     return prBssDesc;
853                 }
854                 else if(prDstBssDesc == NULL && prBssDesc->fgIsHiddenSSID == TRUE) {
855                     prDstBssDesc = prBssDesc;
856                 }
857                 else {
858                     /* 20120206 frog: Equal BSSID but not SSID, SSID not hidden, SSID must be updated. */
859                     COPY_SSID(prBssDesc->aucSSID,
860                             prBssDesc->ucSSIDLen,
861                             prSsid->aucSsid,
862                             prSsid->u4SsidLen);
863                     return prBssDesc;
864                 }
865             }
866         }
867     }
868
869     return prDstBssDesc;
870
871 } /* end of scanSearchBssDescByBssid() */
872
873
874 /*----------------------------------------------------------------------------*/
875 /*!
876 * @brief Find the corresponding BSS Descriptor according to given Transmitter Address.
877 *
878 * @param[in] prAdapter          Pointer to the Adapter structure.
879 * @param[in] aucSrcAddr         Given Source Address(TA).
880 *
881 * @return   Pointer to BSS Descriptor, if found. NULL, if not found
882 */
883 /*----------------------------------------------------------------------------*/
884 P_BSS_DESC_T
885 scanSearchBssDescByTA (
886     IN P_ADAPTER_T prAdapter,
887     IN UINT_8 aucSrcAddr[]
888     )
889 {
890     return scanSearchBssDescByTAAndSsid(prAdapter,
891             aucSrcAddr,
892             FALSE,
893             NULL);
894 }
895
896 /*----------------------------------------------------------------------------*/
897 /*!
898 * @brief Find the corresponding BSS Descriptor according to given Transmitter Address.
899 *
900 * @param[in] prAdapter          Pointer to the Adapter structure.
901 * @param[in] aucSrcAddr         Given Source Address(TA).
902 * @param[in] fgCheckSsid        Need to check SSID or not. (for multiple SSID with single BSSID cases)
903 * @param[in] prSsid             Specified SSID
904 *
905 * @return   Pointer to BSS Descriptor, if found. NULL, if not found
906 */
907 /*----------------------------------------------------------------------------*/
908 P_BSS_DESC_T
909 scanSearchBssDescByTAAndSsid (
910     IN P_ADAPTER_T prAdapter,
911     IN UINT_8 aucSrcAddr[],
912     IN BOOLEAN fgCheckSsid,
913     IN P_PARAM_SSID_T prSsid
914     )
915 {
916     P_SCAN_INFO_T prScanInfo;
917     P_LINK_T prBSSDescList;
918     P_BSS_DESC_T prBssDesc;
919     P_BSS_DESC_T prDstBssDesc = (P_BSS_DESC_T)NULL;
920
921
922     ASSERT(prAdapter);
923     ASSERT(aucSrcAddr);
924
925     prScanInfo = &(prAdapter->rWifiVar.rScanInfo);
926
927     prBSSDescList = &prScanInfo->rBSSDescList;
928
929     /* Search BSS Desc from current SCAN result list. */
930     LINK_FOR_EACH_ENTRY(prBssDesc, prBSSDescList, rLinkEntry, BSS_DESC_T) {
931
932         if (EQUAL_MAC_ADDR(prBssDesc->aucSrcAddr, aucSrcAddr)) {
933             if(fgCheckSsid == FALSE || prSsid == NULL) {
934                 return prBssDesc;
935             }
936             else {
937                 if(EQUAL_SSID(prBssDesc->aucSSID,
938                             prBssDesc->ucSSIDLen,
939                             prSsid->aucSsid,
940                             prSsid->u4SsidLen)) {
941                     return prBssDesc;
942                 }
943                 else if(prDstBssDesc == NULL && prBssDesc->fgIsHiddenSSID == TRUE) {
944                     prDstBssDesc = prBssDesc;
945                 }
946             }
947         }
948     }
949
950     return prDstBssDesc;
951
952 } /* end of scanSearchBssDescByTA() */
953
954
955 /*----------------------------------------------------------------------------*/
956 /*!
957 * @brief Find the corresponding BSS Descriptor according to
958 *        given eBSSType, BSSID and Transmitter Address
959 *
960 * @param[in] prAdapter  Pointer to the Adapter structure.
961 * @param[in] eBSSType   BSS Type of incoming Beacon/ProbeResp frame.
962 * @param[in] aucBSSID   Given BSSID of Beacon/ProbeResp frame.
963 * @param[in] aucSrcAddr Given source address (TA) of Beacon/ProbeResp frame.
964 *
965 * @return   Pointer to BSS Descriptor, if found. NULL, if not found
966 */
967 /*----------------------------------------------------------------------------*/
968 P_BSS_DESC_T
969 scanSearchExistingBssDesc (
970     IN P_ADAPTER_T prAdapter,
971     IN ENUM_BSS_TYPE_T eBSSType,
972     IN UINT_8 aucBSSID[],
973     IN UINT_8 aucSrcAddr[]
974     )
975 {
976     return scanSearchExistingBssDescWithSsid(prAdapter,
977             eBSSType,
978             aucBSSID,
979             aucSrcAddr,
980             FALSE,
981             NULL);
982 }
983
984
985 /*----------------------------------------------------------------------------*/
986 /*!
987 * @brief Find the corresponding BSS Descriptor according to
988 *        given eBSSType, BSSID and Transmitter Address
989 *
990 * @param[in] prAdapter  Pointer to the Adapter structure.
991 * @param[in] eBSSType   BSS Type of incoming Beacon/ProbeResp frame.
992 * @param[in] aucBSSID   Given BSSID of Beacon/ProbeResp frame.
993 * @param[in] aucSrcAddr Given source address (TA) of Beacon/ProbeResp frame.
994 * @param[in] fgCheckSsid Need to check SSID or not. (for multiple SSID with single BSSID cases)
995 * @param[in] prSsid     Specified SSID
996 *
997 * @return   Pointer to BSS Descriptor, if found. NULL, if not found
998 */
999 /*----------------------------------------------------------------------------*/
1000 P_BSS_DESC_T
1001 scanSearchExistingBssDescWithSsid (
1002     IN P_ADAPTER_T prAdapter,
1003     IN ENUM_BSS_TYPE_T eBSSType,
1004     IN UINT_8 aucBSSID[],
1005     IN UINT_8 aucSrcAddr[],
1006     IN BOOLEAN fgCheckSsid,
1007     IN P_PARAM_SSID_T prSsid
1008     )
1009 {
1010     P_SCAN_INFO_T prScanInfo;
1011     P_BSS_DESC_T prBssDesc, prIBSSBssDesc;
1012
1013     ASSERT(prAdapter);
1014     ASSERT(aucSrcAddr);
1015
1016     prScanInfo = &(prAdapter->rWifiVar.rScanInfo);
1017
1018
1019     switch (eBSSType) {
1020     case BSS_TYPE_P2P_DEVICE:
1021         fgCheckSsid = FALSE;
1022     case BSS_TYPE_INFRASTRUCTURE:
1023     case BSS_TYPE_BOW_DEVICE:
1024     {
1025         prBssDesc = scanSearchBssDescByBssidAndSsid(prAdapter, aucBSSID, fgCheckSsid, prSsid);
1026
1027         /* if (eBSSType == prBssDesc->eBSSType) */
1028
1029         return prBssDesc;
1030     }
1031
1032     case BSS_TYPE_IBSS:
1033     {
1034         prIBSSBssDesc = scanSearchBssDescByBssidAndSsid(prAdapter, aucBSSID, fgCheckSsid, prSsid);
1035         prBssDesc = scanSearchBssDescByTAAndSsid(prAdapter, aucSrcAddr, fgCheckSsid, prSsid);
1036
1037         /* NOTE(Kevin):
1038          * Rules to maintain the SCAN Result:
1039          * For AdHoc -
1040          *    CASE I    We have TA1(BSSID1), but it change its BSSID to BSSID2
1041          *              -> Update TA1 entry's BSSID.
1042          *    CASE II   We have TA1(BSSID1), and get TA1(BSSID1) again
1043          *              -> Update TA1 entry's contain.
1044          *    CASE III  We have a SCAN result TA1(BSSID1), and TA2(BSSID2). Sooner or
1045          *               later, TA2 merge into TA1, we get TA2(BSSID1)
1046          *              -> Remove TA2 first and then replace TA1 entry's TA with TA2, Still have only one entry of BSSID.
1047          *    CASE IV   We have a SCAN result TA1(BSSID1), and another TA2 also merge into BSSID1.
1048          *              -> Replace TA1 entry's TA with TA2, Still have only one entry.
1049          *    CASE V    New IBSS
1050          *              -> Add this one to SCAN result.
1051          */
1052         if (prBssDesc) {
1053             if ((!prIBSSBssDesc) || // CASE I
1054                 (prBssDesc == prIBSSBssDesc)) { // CASE II
1055
1056                 return prBssDesc;
1057             }
1058             else { // CASE III
1059                 P_LINK_T prBSSDescList;
1060                 P_LINK_T prFreeBSSDescList;
1061
1062
1063                 prBSSDescList = &prScanInfo->rBSSDescList;
1064                 prFreeBSSDescList = &prScanInfo->rFreeBSSDescList;
1065
1066                 /* Remove this BSS Desc from the BSS Desc list */
1067                 LINK_REMOVE_KNOWN_ENTRY(prBSSDescList, prBssDesc);
1068
1069                 /* Return this BSS Desc to the free BSS Desc list. */
1070                 LINK_INSERT_TAIL(prFreeBSSDescList, &prBssDesc->rLinkEntry);
1071
1072                 return prIBSSBssDesc;
1073             }
1074         }
1075
1076         if (prIBSSBssDesc) { // CASE IV
1077
1078             return prIBSSBssDesc;
1079         }
1080
1081         // CASE V
1082         break; // Return NULL;
1083     }
1084
1085     default:
1086         break;
1087     }
1088
1089
1090     return (P_BSS_DESC_T)NULL;
1091
1092 } /* end of scanSearchExistingBssDesc() */
1093
1094
1095 /*----------------------------------------------------------------------------*/
1096 /*!
1097 * @brief Delete BSS Descriptors from current list according to given Remove Policy.
1098 *
1099 * @param[in] u4RemovePolicy     Remove Policy.
1100 *
1101 * @return (none)
1102 */
1103 /*----------------------------------------------------------------------------*/
1104 VOID
1105 scanRemoveBssDescsByPolicy (
1106     IN P_ADAPTER_T prAdapter,
1107     IN UINT_32 u4RemovePolicy
1108     )
1109 {
1110     P_CONNECTION_SETTINGS_T prConnSettings;
1111     P_SCAN_INFO_T prScanInfo;
1112     P_LINK_T prBSSDescList;
1113     P_LINK_T prFreeBSSDescList;
1114     P_BSS_DESC_T prBssDesc;
1115
1116
1117     ASSERT(prAdapter);
1118
1119     prConnSettings = &(prAdapter->rWifiVar.rConnSettings);
1120     prScanInfo = &(prAdapter->rWifiVar.rScanInfo);
1121     prBSSDescList = &prScanInfo->rBSSDescList;
1122     prFreeBSSDescList = &prScanInfo->rFreeBSSDescList;
1123
1124     //DBGLOG(SCN, TRACE, ("Before Remove - Number Of SCAN Result = %ld\n",
1125         //prBSSDescList->u4NumElem));
1126
1127     if (u4RemovePolicy & SCN_RM_POLICY_TIMEOUT) {
1128         P_BSS_DESC_T prBSSDescNext;
1129         OS_SYSTIME rCurrentTime;
1130
1131
1132         GET_CURRENT_SYSTIME(&rCurrentTime);
1133
1134         /* Search BSS Desc from current SCAN result list. */
1135         LINK_FOR_EACH_ENTRY_SAFE(prBssDesc, prBSSDescNext, prBSSDescList, rLinkEntry, BSS_DESC_T) {
1136
1137             if ((u4RemovePolicy & SCN_RM_POLICY_EXCLUDE_CONNECTED) &&
1138                 (prBssDesc->fgIsConnected || prBssDesc->fgIsConnecting)) {
1139                 /* Don't remove the one currently we are connected. */
1140                 continue;
1141             }
1142
1143             if (CHECK_FOR_TIMEOUT(rCurrentTime, prBssDesc->rUpdateTime,
1144                                    SEC_TO_SYSTIME(SCN_BSS_DESC_REMOVE_TIMEOUT_SEC)) ) {
1145
1146                 //DBGLOG(SCN, TRACE, ("Remove TIMEOUT BSS DESC(%#x): MAC: "MACSTR", Current Time = %08lx, Update Time = %08lx\n",
1147                     //prBssDesc, MAC2STR(prBssDesc->aucBSSID), rCurrentTime, prBssDesc->rUpdateTime));
1148
1149                 /* Remove this BSS Desc from the BSS Desc list */
1150                 LINK_REMOVE_KNOWN_ENTRY(prBSSDescList, prBssDesc);
1151
1152                 /* Return this BSS Desc to the free BSS Desc list. */
1153                 LINK_INSERT_TAIL(prFreeBSSDescList, &prBssDesc->rLinkEntry);
1154             }
1155         }
1156     }
1157     else if (u4RemovePolicy & SCN_RM_POLICY_OLDEST_HIDDEN) {
1158         P_BSS_DESC_T prBssDescOldest = (P_BSS_DESC_T)NULL;
1159
1160
1161         /* Search BSS Desc from current SCAN result list. */
1162         LINK_FOR_EACH_ENTRY(prBssDesc, prBSSDescList, rLinkEntry, BSS_DESC_T) {
1163
1164             if ((u4RemovePolicy & SCN_RM_POLICY_EXCLUDE_CONNECTED) &&
1165                 (prBssDesc->fgIsConnected || prBssDesc->fgIsConnecting)) {
1166                 /* Don't remove the one currently we are connected. */
1167                 continue;
1168             }
1169
1170             if (!prBssDesc->fgIsHiddenSSID) {
1171                 continue;
1172             }
1173
1174             if (!prBssDescOldest) { /* 1st element */
1175                 prBssDescOldest = prBssDesc;
1176                 continue;
1177             }
1178
1179             if (TIME_BEFORE(prBssDesc->rUpdateTime, prBssDescOldest->rUpdateTime)) {
1180                 prBssDescOldest = prBssDesc;
1181             }
1182         }
1183
1184         if (prBssDescOldest) {
1185
1186             //DBGLOG(SCN, TRACE, ("Remove OLDEST HIDDEN BSS DESC(%#x): MAC: "MACSTR", Update Time = %08lx\n",
1187                 //prBssDescOldest, MAC2STR(prBssDescOldest->aucBSSID), prBssDescOldest->rUpdateTime));
1188
1189             /* Remove this BSS Desc from the BSS Desc list */
1190             LINK_REMOVE_KNOWN_ENTRY(prBSSDescList, prBssDescOldest);
1191
1192             /* Return this BSS Desc to the free BSS Desc list. */
1193             LINK_INSERT_TAIL(prFreeBSSDescList, &prBssDescOldest->rLinkEntry);
1194         }
1195     }
1196     else if (u4RemovePolicy & SCN_RM_POLICY_SMART_WEAKEST) {
1197         P_BSS_DESC_T prBssDescWeakest = (P_BSS_DESC_T)NULL;
1198         P_BSS_DESC_T prBssDescWeakestSameSSID = (P_BSS_DESC_T)NULL;
1199         UINT_32 u4SameSSIDCount = 0;
1200
1201
1202         /* Search BSS Desc from current SCAN result list. */
1203         LINK_FOR_EACH_ENTRY(prBssDesc, prBSSDescList, rLinkEntry, BSS_DESC_T) {
1204
1205             if ((u4RemovePolicy & SCN_RM_POLICY_EXCLUDE_CONNECTED) &&
1206                 (prBssDesc->fgIsConnected || prBssDesc->fgIsConnecting)) {
1207                 /* Don't remove the one currently we are connected. */
1208                 continue;
1209             }
1210
1211             if ((!prBssDesc->fgIsHiddenSSID) &&
1212                 (EQUAL_SSID(prBssDesc->aucSSID,
1213                            prBssDesc->ucSSIDLen,
1214                            prConnSettings->aucSSID,
1215                            prConnSettings->ucSSIDLen))) {
1216
1217                 u4SameSSIDCount++;
1218
1219                 if (!prBssDescWeakestSameSSID) {
1220                     prBssDescWeakestSameSSID = prBssDesc;
1221                 }
1222                 else if (prBssDesc->ucRCPI < prBssDescWeakestSameSSID->ucRCPI) {
1223                     prBssDescWeakestSameSSID = prBssDesc;
1224                 }
1225             }
1226
1227             if (!prBssDescWeakest) { /* 1st element */
1228                 prBssDescWeakest = prBssDesc;
1229                 continue;
1230             }
1231
1232             if (prBssDesc->ucRCPI < prBssDescWeakest->ucRCPI) {
1233                 prBssDescWeakest = prBssDesc;
1234             }
1235
1236         }
1237
1238         if ((u4SameSSIDCount >= SCN_BSS_DESC_SAME_SSID_THRESHOLD) &&
1239             (prBssDescWeakestSameSSID)) {
1240             prBssDescWeakest = prBssDescWeakestSameSSID;
1241         }
1242
1243         if (prBssDescWeakest) {
1244
1245             //DBGLOG(SCN, TRACE, ("Remove WEAKEST BSS DESC(%#x): MAC: "MACSTR", Update Time = %08lx\n",
1246                 //prBssDescOldest, MAC2STR(prBssDescOldest->aucBSSID), prBssDescOldest->rUpdateTime));
1247
1248             /* Remove this BSS Desc from the BSS Desc list */
1249             LINK_REMOVE_KNOWN_ENTRY(prBSSDescList, prBssDescWeakest);
1250
1251             /* Return this BSS Desc to the free BSS Desc list. */
1252             LINK_INSERT_TAIL(prFreeBSSDescList, &prBssDescWeakest->rLinkEntry);
1253         }
1254     }
1255     else if (u4RemovePolicy & SCN_RM_POLICY_ENTIRE) {
1256         P_BSS_DESC_T prBSSDescNext;
1257
1258         LINK_FOR_EACH_ENTRY_SAFE(prBssDesc, prBSSDescNext, prBSSDescList, rLinkEntry, BSS_DESC_T) {
1259
1260             if ((u4RemovePolicy & SCN_RM_POLICY_EXCLUDE_CONNECTED) &&
1261                 (prBssDesc->fgIsConnected || prBssDesc->fgIsConnecting)) {
1262                 /* Don't remove the one currently we are connected. */
1263                 continue;
1264             }
1265
1266             /* Remove this BSS Desc from the BSS Desc list */
1267             LINK_REMOVE_KNOWN_ENTRY(prBSSDescList, prBssDesc);
1268
1269             /* Return this BSS Desc to the free BSS Desc list. */
1270             LINK_INSERT_TAIL(prFreeBSSDescList, &prBssDesc->rLinkEntry);
1271         }
1272
1273     }
1274
1275     return;
1276
1277 } /* end of scanRemoveBssDescsByPolicy() */
1278
1279
1280 /*----------------------------------------------------------------------------*/
1281 /*!
1282 * @brief Delete BSS Descriptors from current list according to given BSSID.
1283 *
1284 * @param[in] prAdapter  Pointer to the Adapter structure.
1285 * @param[in] aucBSSID   Given BSSID.
1286 *
1287 * @return (none)
1288 */
1289 /*----------------------------------------------------------------------------*/
1290 VOID
1291 scanRemoveBssDescByBssid (
1292     IN P_ADAPTER_T prAdapter,
1293     IN UINT_8 aucBSSID[]
1294     )
1295 {
1296     P_SCAN_INFO_T prScanInfo;
1297     P_LINK_T prBSSDescList;
1298     P_LINK_T prFreeBSSDescList;
1299     P_BSS_DESC_T prBssDesc = (P_BSS_DESC_T)NULL;
1300     P_BSS_DESC_T prBSSDescNext;
1301
1302
1303     ASSERT(prAdapter);
1304     ASSERT(aucBSSID);
1305
1306     prScanInfo = &(prAdapter->rWifiVar.rScanInfo);
1307     prBSSDescList = &prScanInfo->rBSSDescList;
1308     prFreeBSSDescList = &prScanInfo->rFreeBSSDescList;
1309
1310     /* Check if such BSS Descriptor exists in a valid list */
1311     LINK_FOR_EACH_ENTRY_SAFE(prBssDesc, prBSSDescNext, prBSSDescList, rLinkEntry, BSS_DESC_T) {
1312
1313         if (EQUAL_MAC_ADDR(prBssDesc->aucBSSID, aucBSSID)) {
1314
1315             /* Remove this BSS Desc from the BSS Desc list */
1316             LINK_REMOVE_KNOWN_ENTRY(prBSSDescList, prBssDesc);
1317
1318             /* Return this BSS Desc to the free BSS Desc list. */
1319             LINK_INSERT_TAIL(prFreeBSSDescList, &prBssDesc->rLinkEntry);
1320
1321             /* BSSID is not unique, so need to traverse whols link-list */
1322         }
1323     }
1324
1325     return;
1326 } /* end of scanRemoveBssDescByBssid() */
1327
1328
1329 /*----------------------------------------------------------------------------*/
1330 /*!
1331 * @brief Delete BSS Descriptors from current list according to given band configuration
1332 *
1333 * @param[in] prAdapter  Pointer to the Adapter structure.
1334 * @param[in] eBand      Given band
1335 * @param[in] eNetTypeIndex  AIS - Remove IBSS/Infrastructure BSS
1336 *                           BOW - Remove BOW BSS
1337 *                           P2P - Remove P2P BSS
1338 *
1339 * @return (none)
1340 */
1341 /*----------------------------------------------------------------------------*/
1342 VOID
1343 scanRemoveBssDescByBandAndNetwork (
1344     IN P_ADAPTER_T prAdapter,
1345     IN ENUM_BAND_T eBand,
1346     IN ENUM_NETWORK_TYPE_INDEX_T eNetTypeIndex
1347     )
1348 {
1349     P_SCAN_INFO_T prScanInfo;
1350     P_LINK_T prBSSDescList;
1351     P_LINK_T prFreeBSSDescList;
1352     P_BSS_DESC_T prBssDesc = (P_BSS_DESC_T)NULL;
1353     P_BSS_DESC_T prBSSDescNext;
1354     BOOLEAN fgToRemove;
1355
1356     ASSERT(prAdapter);
1357     ASSERT(eBand <= BAND_NUM);
1358     ASSERT(eNetTypeIndex <= NETWORK_TYPE_INDEX_NUM);
1359
1360     prScanInfo = &(prAdapter->rWifiVar.rScanInfo);
1361     prBSSDescList = &prScanInfo->rBSSDescList;
1362     prFreeBSSDescList = &prScanInfo->rFreeBSSDescList;
1363
1364
1365     if(eBand == BAND_NULL) {
1366         return; /* no need to do anything, keep all scan result */
1367     }
1368
1369     /* Check if such BSS Descriptor exists in a valid list */
1370     LINK_FOR_EACH_ENTRY_SAFE(prBssDesc, prBSSDescNext, prBSSDescList, rLinkEntry, BSS_DESC_T) {
1371         fgToRemove = FALSE;
1372
1373         if(prBssDesc->eBand == eBand) {
1374             switch (eNetTypeIndex) {
1375             case NETWORK_TYPE_AIS_INDEX:
1376                 if((prBssDesc->eBSSType == BSS_TYPE_INFRASTRUCTURE)
1377                         || (prBssDesc->eBSSType == BSS_TYPE_IBSS)) {
1378                     fgToRemove = TRUE;
1379                 }
1380                 break;
1381
1382             case NETWORK_TYPE_P2P_INDEX:
1383                 if(prBssDesc->eBSSType == BSS_TYPE_P2P_DEVICE) {
1384                     fgToRemove = TRUE;
1385                 }
1386                 break;
1387                 
1388             case NETWORK_TYPE_BOW_INDEX:
1389                 if(prBssDesc->eBSSType == BSS_TYPE_BOW_DEVICE) {
1390                     fgToRemove = TRUE;
1391                 }
1392                 break;
1393             
1394             default:
1395                 ASSERT(0);
1396                 break;
1397             }
1398         }
1399
1400         if(fgToRemove == TRUE) {
1401             /* Remove this BSS Desc from the BSS Desc list */
1402             LINK_REMOVE_KNOWN_ENTRY(prBSSDescList, prBssDesc);
1403
1404             /* Return this BSS Desc to the free BSS Desc list. */
1405             LINK_INSERT_TAIL(prFreeBSSDescList, &prBssDesc->rLinkEntry);
1406         }
1407     }
1408
1409     return;
1410 } /* end of scanRemoveBssDescByBand() */
1411
1412
1413 /*----------------------------------------------------------------------------*/
1414 /*!
1415 * @brief Clear the CONNECTION FLAG of a specified BSS Descriptor.
1416 *
1417 * @param[in] aucBSSID   Given BSSID.
1418 *
1419 * @return (none)
1420 */
1421 /*----------------------------------------------------------------------------*/
1422 VOID
1423 scanRemoveConnFlagOfBssDescByBssid (
1424     IN P_ADAPTER_T prAdapter,
1425     IN UINT_8 aucBSSID[]
1426     )
1427 {
1428     P_SCAN_INFO_T prScanInfo;
1429     P_LINK_T prBSSDescList;
1430     P_BSS_DESC_T prBssDesc = (P_BSS_DESC_T)NULL;
1431
1432
1433     ASSERT(prAdapter);
1434     ASSERT(aucBSSID);
1435
1436     prScanInfo = &(prAdapter->rWifiVar.rScanInfo);
1437     prBSSDescList = &prScanInfo->rBSSDescList;
1438
1439     /* Search BSS Desc from current SCAN result list. */
1440     LINK_FOR_EACH_ENTRY(prBssDesc, prBSSDescList, rLinkEntry, BSS_DESC_T) {
1441
1442         if (EQUAL_MAC_ADDR(prBssDesc->aucBSSID, aucBSSID)) {
1443             prBssDesc->fgIsConnected = FALSE;
1444             prBssDesc->fgIsConnecting = FALSE;
1445
1446             /* BSSID is not unique, so need to traverse whols link-list */
1447         }
1448     }
1449
1450     return;
1451
1452 } /* end of scanRemoveConnectionFlagOfBssDescByBssid() */
1453
1454
1455 /*----------------------------------------------------------------------------*/
1456 /*!
1457 * @brief Allocate new BSS_DESC_T
1458 *
1459 * @param[in] prAdapter          Pointer to the Adapter structure.
1460 *
1461 * @return   Pointer to BSS Descriptor, if has free space. NULL, if has no space.
1462 */
1463 /*----------------------------------------------------------------------------*/
1464 P_BSS_DESC_T
1465 scanAllocateBssDesc (
1466     IN P_ADAPTER_T prAdapter
1467     )
1468 {
1469     P_SCAN_INFO_T prScanInfo;
1470     P_LINK_T prFreeBSSDescList;
1471     P_BSS_DESC_T prBssDesc;
1472
1473
1474     ASSERT(prAdapter);
1475     prScanInfo =  &(prAdapter->rWifiVar.rScanInfo);
1476
1477     prFreeBSSDescList = &prScanInfo->rFreeBSSDescList;
1478
1479     LINK_REMOVE_HEAD(prFreeBSSDescList, prBssDesc, P_BSS_DESC_T);
1480
1481     if (prBssDesc) {
1482         P_LINK_T prBSSDescList;
1483
1484         kalMemZero(prBssDesc, sizeof(BSS_DESC_T));
1485
1486 #if CFG_ENABLE_WIFI_DIRECT
1487         LINK_INITIALIZE(&(prBssDesc->rP2pDeviceList));
1488         prBssDesc->fgIsP2PPresent = FALSE;
1489 #endif /* CFG_ENABLE_WIFI_DIRECT */
1490
1491         prBSSDescList = &prScanInfo->rBSSDescList;
1492
1493         /* NOTE(Kevin): In current design, this new empty BSS_DESC_T will be
1494          * inserted to BSSDescList immediately.
1495          */
1496         LINK_INSERT_TAIL(prBSSDescList, &prBssDesc->rLinkEntry);
1497     }
1498
1499     return prBssDesc;
1500
1501 } /* end of scanAllocateBssDesc() */
1502
1503
1504 /*----------------------------------------------------------------------------*/
1505 /*!
1506 * @brief This API parses Beacon/ProbeResp frame and insert extracted BSS_DESC_T
1507 *        with IEs into prAdapter->rWifiVar.rScanInfo.aucScanBuffer
1508 *
1509 * @param[in] prAdapter      Pointer to the Adapter structure.
1510 * @param[in] prSwRfb        Pointer to the receiving frame buffer.
1511 *
1512 * @return   Pointer to BSS Descriptor
1513 *           NULL if the Beacon/ProbeResp frame is invalid
1514 */
1515 /*----------------------------------------------------------------------------*/
1516 P_BSS_DESC_T
1517 scanAddToBssDesc (
1518     IN P_ADAPTER_T prAdapter,
1519     IN P_SW_RFB_T prSwRfb
1520     )
1521 {
1522     P_BSS_DESC_T prBssDesc = NULL;
1523     UINT_16 u2CapInfo;
1524     ENUM_BSS_TYPE_T eBSSType = BSS_TYPE_INFRASTRUCTURE;
1525
1526     PUINT_8 pucIE;
1527     UINT_16 u2IELength;
1528     UINT_16 u2Offset = 0;
1529
1530     P_WLAN_BEACON_FRAME_T prWlanBeaconFrame = (P_WLAN_BEACON_FRAME_T)NULL;
1531     P_IE_SSID_T prIeSsid = (P_IE_SSID_T)NULL;
1532     P_IE_SUPPORTED_RATE_T prIeSupportedRate = (P_IE_SUPPORTED_RATE_T)NULL;
1533     P_IE_EXT_SUPPORTED_RATE_T prIeExtSupportedRate = (P_IE_EXT_SUPPORTED_RATE_T)NULL;
1534     P_HIF_RX_HEADER_T prHifRxHdr;
1535     UINT_8 ucHwChannelNum = 0;
1536     UINT_8 ucIeDsChannelNum = 0;
1537     UINT_8 ucIeHtChannelNum = 0;
1538     BOOLEAN fgIsValidSsid = FALSE, fgEscape = FALSE;
1539     PARAM_SSID_T rSsid;
1540     UINT_64 u8Timestamp;
1541         BOOLEAN fgIsNewBssDesc = FALSE;
1542
1543     UINT_32 i;
1544     UINT_8 ucSSIDChar;
1545
1546     ASSERT(prAdapter);
1547     ASSERT(prSwRfb);
1548
1549     prWlanBeaconFrame = (P_WLAN_BEACON_FRAME_T)prSwRfb->pvHeader;
1550
1551     WLAN_GET_FIELD_16(&prWlanBeaconFrame->u2CapInfo, &u2CapInfo);
1552     WLAN_GET_FIELD_64(&prWlanBeaconFrame->au4Timestamp[0], &u8Timestamp);
1553
1554     // decide BSS type
1555     switch (u2CapInfo & CAP_INFO_BSS_TYPE) {
1556     case CAP_INFO_ESS:
1557         /* It can also be Group Owner of P2P Group. */
1558         eBSSType = BSS_TYPE_INFRASTRUCTURE;
1559         break;
1560
1561     case CAP_INFO_IBSS:
1562         eBSSType = BSS_TYPE_IBSS;
1563         break;
1564     case 0:
1565         /* The P2P Device shall set the ESS bit of the Capabilities field in the Probe Response fame to 0 and IBSS bit to 0. (3.1.2.1.1) */
1566         eBSSType = BSS_TYPE_P2P_DEVICE;
1567         break;
1568
1569 #if CFG_ENABLE_BT_OVER_WIFI
1570         // @TODO: add rule to identify BOW beacons
1571 #endif
1572
1573     default:
1574         return NULL;
1575     }
1576
1577     //4 <1.1> Pre-parse SSID IE
1578     pucIE = prWlanBeaconFrame->aucInfoElem;
1579     u2IELength = (prSwRfb->u2PacketLen - prSwRfb->u2HeaderLen) -
1580         (UINT_16)OFFSET_OF(WLAN_BEACON_FRAME_BODY_T, aucInfoElem[0]);
1581
1582     if (u2IELength > CFG_IE_BUFFER_SIZE) {
1583         u2IELength = CFG_IE_BUFFER_SIZE;
1584     }
1585
1586     IE_FOR_EACH(pucIE, u2IELength, u2Offset) {
1587         switch (IE_ID(pucIE)) {
1588         case ELEM_ID_SSID:
1589             if (IE_LEN(pucIE) <= ELEM_MAX_LEN_SSID) {
1590                 ucSSIDChar = '\0';
1591
1592                 /* D-Link DWL-900AP+ */
1593                 if (IE_LEN(pucIE) == 0) {
1594                     fgIsValidSsid = FALSE;
1595                 }
1596                 /* Cisco AP1230A - (IE_LEN(pucIE) == 1) && (SSID_IE(pucIE)->aucSSID[0] == '\0') */
1597                 /* Linksys WRK54G/ASUS WL520g - (IE_LEN(pucIE) == n) && (SSID_IE(pucIE)->aucSSID[0~(n-1)] == '\0') */
1598                 else {
1599                     for (i = 0; i < IE_LEN(pucIE); i++) {
1600                         ucSSIDChar |= SSID_IE(pucIE)->aucSSID[i];
1601                     }
1602
1603                     if (ucSSIDChar) {
1604                         fgIsValidSsid = TRUE;
1605                     }
1606                 }
1607
1608                 /* Update SSID to BSS Descriptor only if SSID is not hidden. */
1609                 if (fgIsValidSsid == TRUE) {
1610                     COPY_SSID(rSsid.aucSsid,
1611                               rSsid.u4SsidLen,
1612                               SSID_IE(pucIE)->aucSSID,
1613                               SSID_IE(pucIE)->ucLength);
1614                 }
1615             }
1616             fgEscape = TRUE;
1617             break;
1618         default:
1619             break;
1620         }
1621
1622         if(fgEscape == TRUE) {
1623             break;
1624         }
1625     }
1626
1627
1628     //4 <1.2> Replace existing BSS_DESC_T or allocate a new one
1629     prBssDesc = scanSearchExistingBssDescWithSsid(prAdapter,
1630                                           eBSSType,
1631                                           (PUINT_8)prWlanBeaconFrame->aucBSSID,
1632                                           (PUINT_8)prWlanBeaconFrame->aucSrcAddr,
1633                                           fgIsValidSsid,
1634                                           fgIsValidSsid == TRUE ? &rSsid : NULL);
1635
1636     if (prBssDesc == (P_BSS_DESC_T)NULL) {
1637                 fgIsNewBssDesc = TRUE;
1638                 
1639         do {
1640             //4 <1.2.1> First trial of allocation
1641             prBssDesc = scanAllocateBssDesc(prAdapter);
1642             if (prBssDesc) {
1643                 break;
1644             }
1645
1646             //4 <1.2.2> Hidden is useless, remove the oldest hidden ssid. (for passive scan)
1647             scanRemoveBssDescsByPolicy(prAdapter,
1648                     (SCN_RM_POLICY_EXCLUDE_CONNECTED | SCN_RM_POLICY_OLDEST_HIDDEN));
1649
1650             //4 <1.2.3> Second tail of allocation
1651             prBssDesc = scanAllocateBssDesc(prAdapter);
1652             if (prBssDesc) {
1653                 break;
1654             }
1655
1656             //4 <1.2.4> Remove the weakest one
1657             /* If there are more than half of BSS which has the same ssid as connection
1658              * setting, remove the weakest one from them.
1659              * Else remove the weakest one.
1660              */
1661             scanRemoveBssDescsByPolicy(prAdapter,
1662                     (SCN_RM_POLICY_EXCLUDE_CONNECTED | SCN_RM_POLICY_SMART_WEAKEST));
1663
1664             //4 <1.2.5> reallocation
1665             prBssDesc = scanAllocateBssDesc(prAdapter);
1666             if (prBssDesc) {
1667                 break;
1668             }
1669
1670             //4 <1.2.6> no space, should not happen
1671             //ASSERT(0); // still no space available ?
1672             return NULL;
1673
1674         }
1675         while(FALSE);
1676
1677     }
1678     else {
1679         OS_SYSTIME rCurrentTime;
1680
1681         // WCXRP00000091
1682         // if the received strength is much weaker than the original one,
1683         // ignore it due to it might be received on the folding frequency
1684
1685         GET_CURRENT_SYSTIME(&rCurrentTime);
1686
1687         prBssDesc->eBSSType = eBSSType;
1688
1689         if(HIF_RX_HDR_GET_CHNL_NUM(prSwRfb->prHifRxHdr) != prBssDesc->ucChannelNum &&
1690                 prBssDesc->ucRCPI > prSwRfb->prHifRxHdr->ucRcpi) {
1691
1692             // for signal strength is too much weaker and previous beacon is not stale
1693             if((prBssDesc->ucRCPI - prSwRfb->prHifRxHdr->ucRcpi) >= REPLICATED_BEACON_STRENGTH_THRESHOLD &&
1694                     rCurrentTime - prBssDesc->rUpdateTime <= REPLICATED_BEACON_FRESH_PERIOD) {
1695                 return prBssDesc;
1696             }
1697             // for received beacons too close in time domain
1698             else if(rCurrentTime - prBssDesc->rUpdateTime <= REPLICATED_BEACON_TIME_THRESHOLD) {
1699                 return prBssDesc;
1700             }
1701         }
1702
1703         /* if Timestamp has been reset, re-generate BSS DESC 'cause AP should have reset itself */
1704         if(prBssDesc->eBSSType == BSS_TYPE_INFRASTRUCTURE && u8Timestamp < prBssDesc->u8TimeStamp.QuadPart) {
1705             BOOLEAN fgIsConnected, fgIsConnecting;
1706
1707                         /* set flag for indicating this is a new BSS-DESC */
1708             fgIsNewBssDesc = TRUE;
1709
1710             /* backup 2 flags for APs which reset timestamp unexpectedly */
1711             fgIsConnected = prBssDesc->fgIsConnected;
1712             fgIsConnecting = prBssDesc->fgIsConnecting;
1713             scanRemoveBssDescByBssid(prAdapter, prBssDesc->aucBSSID);
1714
1715             prBssDesc = scanAllocateBssDesc(prAdapter);
1716             if (!prBssDesc) {
1717                 return NULL;
1718             }
1719
1720             /* restore */
1721             prBssDesc->fgIsConnected = fgIsConnected;
1722             prBssDesc->fgIsConnecting = fgIsConnecting;
1723         }
1724     }
1725
1726     /* NOTE: Keep consistency of Scan Record during JOIN process */
1727     if ((fgIsNewBssDesc == FALSE) && prBssDesc->fgIsConnecting) {
1728         return prBssDesc;
1729     }
1730
1731     //4 <2> Get information from Fixed Fields
1732     prBssDesc->eBSSType = eBSSType; /* Update the latest BSS type information. */
1733
1734     COPY_MAC_ADDR(prBssDesc->aucSrcAddr, prWlanBeaconFrame->aucSrcAddr);
1735
1736     COPY_MAC_ADDR(prBssDesc->aucBSSID, prWlanBeaconFrame->aucBSSID);
1737
1738     prBssDesc->u8TimeStamp.QuadPart = u8Timestamp;
1739
1740     WLAN_GET_FIELD_16(&prWlanBeaconFrame->u2BeaconInterval, &prBssDesc->u2BeaconInterval);
1741
1742     prBssDesc->u2CapInfo = u2CapInfo;
1743
1744
1745     //4 <2.1> Retrieve IEs for later parsing
1746     u2IELength = (prSwRfb->u2PacketLen - prSwRfb->u2HeaderLen) -
1747         (UINT_16)OFFSET_OF(WLAN_BEACON_FRAME_BODY_T, aucInfoElem[0]);
1748
1749     if (u2IELength > CFG_IE_BUFFER_SIZE) {
1750         u2IELength = CFG_IE_BUFFER_SIZE;
1751         prBssDesc->fgIsIEOverflow = TRUE;
1752     }
1753     else {
1754         prBssDesc->fgIsIEOverflow = FALSE;
1755     }
1756     prBssDesc->u2IELength = u2IELength;
1757
1758     kalMemCopy(prBssDesc->aucIEBuf, prWlanBeaconFrame->aucInfoElem, u2IELength);
1759
1760     //4 <2.2> reset prBssDesc variables in case that AP has been reconfigured
1761     prBssDesc->fgIsERPPresent = FALSE;
1762     prBssDesc->fgIsHTPresent = FALSE;
1763     prBssDesc->eSco = CHNL_EXT_SCN;
1764     prBssDesc->fgIEWAPI = FALSE;
1765 #if CFG_RSN_MIGRATION
1766     prBssDesc->fgIERSN = FALSE;
1767 #endif
1768 #if CFG_PRIVACY_MIGRATION
1769     prBssDesc->fgIEWPA = FALSE;
1770 #endif
1771
1772
1773     //4 <3.1> Full IE parsing on SW_RFB_T
1774     pucIE = prWlanBeaconFrame->aucInfoElem;
1775
1776
1777     IE_FOR_EACH(pucIE, u2IELength, u2Offset) {
1778
1779         switch (IE_ID(pucIE)) {
1780         case ELEM_ID_SSID:
1781             if ((!prIeSsid) && /* NOTE(Kevin): for Atheros IOT #1 */
1782                 (IE_LEN(pucIE) <= ELEM_MAX_LEN_SSID)) {
1783                 BOOLEAN fgIsHiddenSSID = FALSE;
1784                 ucSSIDChar = '\0';
1785
1786
1787                 prIeSsid = (P_IE_SSID_T)pucIE;
1788
1789                 /* D-Link DWL-900AP+ */
1790                 if (IE_LEN(pucIE) == 0) {
1791                     fgIsHiddenSSID = TRUE;
1792                 }
1793                 /* Cisco AP1230A - (IE_LEN(pucIE) == 1) && (SSID_IE(pucIE)->aucSSID[0] == '\0') */
1794                 /* Linksys WRK54G/ASUS WL520g - (IE_LEN(pucIE) == n) && (SSID_IE(pucIE)->aucSSID[0~(n-1)] == '\0') */
1795                 else {
1796                     for (i = 0; i < IE_LEN(pucIE); i++) {
1797                         ucSSIDChar |= SSID_IE(pucIE)->aucSSID[i];
1798                     }
1799
1800                     if (!ucSSIDChar) {
1801                         fgIsHiddenSSID = TRUE;
1802                     }
1803                 }
1804
1805                 /* Update SSID to BSS Descriptor only if SSID is not hidden. */
1806                 if (!fgIsHiddenSSID) {
1807                     COPY_SSID(prBssDesc->aucSSID,
1808                               prBssDesc->ucSSIDLen,
1809                               SSID_IE(pucIE)->aucSSID,
1810                               SSID_IE(pucIE)->ucLength);
1811                 }
1812
1813             }
1814             break;
1815
1816         case ELEM_ID_SUP_RATES:
1817             /* NOTE(Kevin): Buffalo WHR-G54S's supported rate set IE exceed 8.
1818              * IE_LEN(pucIE) == 12, "1(B), 2(B), 5.5(B), 6(B), 9(B), 11(B),
1819              * 12(B), 18(B), 24(B), 36(B), 48(B), 54(B)"
1820              */
1821             /* TP-LINK will set extra and incorrect ie with ELEM_ID_SUP_RATES */
1822             if ((!prIeSupportedRate) && (IE_LEN(pucIE) <= RATE_NUM)) {
1823                 prIeSupportedRate = SUP_RATES_IE(pucIE);
1824             }
1825             break;
1826
1827         case ELEM_ID_DS_PARAM_SET:
1828             if (IE_LEN(pucIE) == ELEM_MAX_LEN_DS_PARAMETER_SET) {
1829                 ucIeDsChannelNum = DS_PARAM_IE(pucIE)->ucCurrChnl;
1830             }
1831             break;
1832
1833         case ELEM_ID_TIM:
1834             if (IE_LEN(pucIE) <= ELEM_MAX_LEN_TIM) {
1835                 prBssDesc->ucDTIMPeriod = TIM_IE(pucIE)->ucDTIMPeriod;
1836             }
1837             break;
1838
1839         case ELEM_ID_IBSS_PARAM_SET:
1840             if (IE_LEN(pucIE) == ELEM_MAX_LEN_IBSS_PARAMETER_SET){
1841                 prBssDesc->u2ATIMWindow = IBSS_PARAM_IE(pucIE)->u2ATIMWindow;
1842             }
1843             break;
1844
1845 #if 0 //CFG_SUPPORT_802_11D
1846         case ELEM_ID_COUNTRY_INFO:
1847             prBssDesc->prIECountry = (P_IE_COUNTRY_T)pucIE;
1848             break;
1849 #endif
1850
1851         case ELEM_ID_ERP_INFO:
1852             if (IE_LEN(pucIE) == ELEM_MAX_LEN_ERP) {
1853                 prBssDesc->fgIsERPPresent = TRUE;
1854             }
1855             break;
1856
1857         case ELEM_ID_EXTENDED_SUP_RATES:
1858             if (!prIeExtSupportedRate) {
1859                 prIeExtSupportedRate = EXT_SUP_RATES_IE(pucIE);
1860             }
1861             break;
1862
1863 #if CFG_RSN_MIGRATION
1864         case ELEM_ID_RSN:
1865             if (rsnParseRsnIE(prAdapter, RSN_IE(pucIE), &prBssDesc->rRSNInfo)) {
1866                 prBssDesc->fgIERSN = TRUE;
1867                 prBssDesc->u2RsnCap = prBssDesc->rRSNInfo.u2RsnCap;
1868                 if (prAdapter->rWifiVar.rConnSettings.eAuthMode == AUTH_MODE_WPA2) {
1869                     rsnCheckPmkidCache(prAdapter, prBssDesc);
1870                 }
1871             }
1872             break;
1873 #endif
1874
1875         case ELEM_ID_HT_CAP:
1876             prBssDesc->fgIsHTPresent = TRUE;
1877             break;
1878
1879         case ELEM_ID_HT_OP:
1880             if (IE_LEN(pucIE) != (sizeof(IE_HT_OP_T) - 2)) {
1881                 break;
1882             }
1883
1884             if ((((P_IE_HT_OP_T) pucIE)->ucInfo1 & HT_OP_INFO1_SCO) != CHNL_EXT_RES) {
1885             prBssDesc->eSco = (ENUM_CHNL_EXT_T)
1886                 (((P_IE_HT_OP_T) pucIE)->ucInfo1 & HT_OP_INFO1_SCO);
1887             }
1888             ucIeHtChannelNum = ((P_IE_HT_OP_T) pucIE)->ucPrimaryChannel;
1889
1890             break;
1891
1892 #if CFG_SUPPORT_WAPI
1893         case ELEM_ID_WAPI:
1894             if (wapiParseWapiIE(WAPI_IE(pucIE), &prBssDesc->rIEWAPI)) {
1895                 prBssDesc->fgIEWAPI = TRUE;
1896             }
1897             break;
1898 #endif
1899
1900         case ELEM_ID_VENDOR:  // ELEM_ID_P2P, ELEM_ID_WMM
1901             {
1902                 UINT_8 ucOuiType;
1903                 UINT_16 u2SubTypeVersion;
1904 #if CFG_PRIVACY_MIGRATION
1905                 if (rsnParseCheckForWFAInfoElem(prAdapter, pucIE, &ucOuiType, &u2SubTypeVersion)) {
1906                     if ((ucOuiType == VENDOR_OUI_TYPE_WPA) &&
1907                             (u2SubTypeVersion == VERSION_WPA)) {
1908
1909                         if (rsnParseWpaIE(prAdapter, WPA_IE(pucIE), &prBssDesc->rWPAInfo)) {
1910                             prBssDesc->fgIEWPA = TRUE;
1911                         }
1912                     }
1913                 }
1914 #endif
1915
1916 #if CFG_ENABLE_WIFI_DIRECT
1917                 if(prAdapter->fgIsP2PRegistered) {
1918                     if (p2pFuncParseCheckForP2PInfoElem(prAdapter, pucIE, &ucOuiType)) {
1919                         if (ucOuiType == VENDOR_OUI_TYPE_P2P) {
1920                             prBssDesc->fgIsP2PPresent = TRUE;
1921                         }
1922                     }
1923                 }
1924 #endif /* CFG_ENABLE_WIFI_DIRECT */
1925             }
1926             break;
1927
1928         /* no default */
1929         }
1930     }
1931
1932
1933     //4 <3.2> Save information from IEs - SSID
1934     /* Update Flag of Hidden SSID for used in SEARCH STATE. */
1935
1936     /* NOTE(Kevin): in current driver, the ucSSIDLen == 0 represent
1937      * all cases of hidden SSID.
1938      * If the fgIsHiddenSSID == TRUE, it means we didn't get the ProbeResp with
1939      * valid SSID.
1940      */
1941     if (prBssDesc->ucSSIDLen == 0) {
1942         prBssDesc->fgIsHiddenSSID = TRUE;
1943     }
1944     else {
1945         prBssDesc->fgIsHiddenSSID = FALSE;
1946     }
1947
1948
1949     //4 <3.3> Check rate information in related IEs.
1950     if (prIeSupportedRate || prIeExtSupportedRate) {
1951         rateGetRateSetFromIEs(prIeSupportedRate,
1952                               prIeExtSupportedRate,
1953                               &prBssDesc->u2OperationalRateSet,
1954                               &prBssDesc->u2BSSBasicRateSet,
1955                               &prBssDesc->fgIsUnknownBssBasicRate);
1956     }
1957
1958
1959     //4 <4> Update information from HIF RX Header
1960     {
1961         prHifRxHdr = prSwRfb->prHifRxHdr;
1962
1963         ASSERT(prHifRxHdr);
1964
1965         //4 <4.1> Get TSF comparison result
1966         prBssDesc->fgIsLargerTSF = HIF_RX_HDR_GET_TCL_FLAG(prHifRxHdr);
1967
1968         //4 <4.2> Get Band information
1969         prBssDesc->eBand = HIF_RX_HDR_GET_RF_BAND(prHifRxHdr);
1970
1971         //4 <4.2> Get channel and RCPI information
1972         ucHwChannelNum = HIF_RX_HDR_GET_CHNL_NUM(prHifRxHdr);
1973
1974         if (BAND_2G4 == prBssDesc->eBand) {
1975
1976             /* Update RCPI if in right channel */
1977             if (ucIeDsChannelNum >= 1 && ucIeDsChannelNum <= 14) {
1978
1979                 // Receive Beacon/ProbeResp frame from adjacent channel.
1980                 if ((ucIeDsChannelNum == ucHwChannelNum) ||
1981                     (prHifRxHdr->ucRcpi > prBssDesc->ucRCPI)) {
1982                     prBssDesc->ucRCPI = prHifRxHdr->ucRcpi;
1983                 }
1984
1985                 // trust channel information brought by IE
1986                 prBssDesc->ucChannelNum = ucIeDsChannelNum;
1987             }
1988             else if(ucIeHtChannelNum >= 1 && ucIeHtChannelNum <= 14) {
1989                 // Receive Beacon/ProbeResp frame from adjacent channel.
1990                 if ((ucIeHtChannelNum == ucHwChannelNum) ||
1991                     (prHifRxHdr->ucRcpi > prBssDesc->ucRCPI)) {
1992                     prBssDesc->ucRCPI = prHifRxHdr->ucRcpi;
1993                 }
1994
1995                 // trust channel information brought by IE
1996                 prBssDesc->ucChannelNum = ucIeHtChannelNum;
1997             }
1998             else {
1999                 prBssDesc->ucRCPI = prHifRxHdr->ucRcpi;
2000
2001                 prBssDesc->ucChannelNum = ucHwChannelNum;
2002             }
2003         }
2004         // 5G Band
2005         else {
2006             if(ucIeHtChannelNum >= 1 && ucIeHtChannelNum < 200) {
2007                 // Receive Beacon/ProbeResp frame from adjacent channel.
2008                 if ((ucIeHtChannelNum == ucHwChannelNum) ||
2009                     (prHifRxHdr->ucRcpi > prBssDesc->ucRCPI)) {
2010                     prBssDesc->ucRCPI = prHifRxHdr->ucRcpi;
2011                 }
2012
2013                 // trust channel information brought by IE
2014                 prBssDesc->ucChannelNum = ucIeHtChannelNum;
2015             }
2016             else {
2017                 /* Always update RCPI */
2018                 prBssDesc->ucRCPI = prHifRxHdr->ucRcpi;
2019
2020                 prBssDesc->ucChannelNum = ucHwChannelNum;
2021             }
2022         }
2023     }
2024
2025
2026     //4 <5> PHY type setting
2027     prBssDesc->ucPhyTypeSet = 0;
2028
2029     if (BAND_2G4 == prBssDesc->eBand) {
2030         /* check if support 11n */
2031         if (prBssDesc->fgIsHTPresent) {
2032             prBssDesc->ucPhyTypeSet |= PHY_TYPE_BIT_HT;
2033         }
2034
2035         /* if not 11n only */
2036         if (!(prBssDesc->u2BSSBasicRateSet & RATE_SET_BIT_HT_PHY)) {
2037             /* check if support 11g */
2038             if ((prBssDesc->u2OperationalRateSet & RATE_SET_OFDM) ||
2039                     prBssDesc->fgIsERPPresent) {
2040                 prBssDesc->ucPhyTypeSet |= PHY_TYPE_BIT_ERP;
2041             }
2042
2043             /* if not 11g only */
2044             if (!(prBssDesc->u2BSSBasicRateSet & RATE_SET_OFDM)) {
2045                 /* check if support 11b */
2046                 if ((prBssDesc->u2OperationalRateSet & RATE_SET_HR_DSSS)) {
2047                     prBssDesc->ucPhyTypeSet |= PHY_TYPE_BIT_HR_DSSS;
2048                 }
2049             }
2050         }
2051     }
2052     else { /* (BAND_5G == prBssDesc->eBande) */
2053         /* check if support 11n */
2054         if (prBssDesc->fgIsHTPresent) {
2055             prBssDesc->ucPhyTypeSet |= PHY_TYPE_BIT_HT;
2056         }
2057
2058         /* if not 11n only */
2059         if (!(prBssDesc->u2BSSBasicRateSet & RATE_SET_BIT_HT_PHY)) {
2060             /* Support 11a definitely */
2061             prBssDesc->ucPhyTypeSet |= PHY_TYPE_BIT_OFDM;
2062
2063             ASSERT(!(prBssDesc->u2OperationalRateSet & RATE_SET_HR_DSSS));
2064         }
2065     }
2066
2067
2068     //4 <6> Update BSS_DESC_T's Last Update TimeStamp.
2069     GET_CURRENT_SYSTIME(&prBssDesc->rUpdateTime);
2070
2071     return prBssDesc;
2072 }
2073
2074
2075 /*----------------------------------------------------------------------------*/
2076 /*!
2077 * @brief Convert the Beacon or ProbeResp Frame in SW_RFB_T to scan result for query
2078 *
2079 * @param[in] prSwRfb            Pointer to the receiving SW_RFB_T structure.
2080 *
2081 * @retval WLAN_STATUS_SUCCESS   It is a valid Scan Result and been sent to the host.
2082 * @retval WLAN_STATUS_FAILURE   It is not a valid Scan Result.
2083 */
2084 /*----------------------------------------------------------------------------*/
2085 WLAN_STATUS
2086 scanAddScanResult (
2087     IN P_ADAPTER_T prAdapter,
2088     IN P_BSS_DESC_T prBssDesc,
2089     IN P_SW_RFB_T prSwRfb
2090     )
2091 {
2092     P_SCAN_INFO_T prScanInfo;
2093     UINT_8 aucRatesEx[PARAM_MAX_LEN_RATES_EX];
2094     P_WLAN_BEACON_FRAME_T prWlanBeaconFrame;
2095     PARAM_MAC_ADDRESS rMacAddr;
2096     PARAM_SSID_T rSsid;
2097     ENUM_PARAM_NETWORK_TYPE_T eNetworkType;
2098     PARAM_802_11_CONFIG_T rConfiguration;
2099     ENUM_PARAM_OP_MODE_T eOpMode;
2100     UINT_8 ucRateLen = 0;
2101     UINT_32 i;
2102
2103     ASSERT(prAdapter);
2104     ASSERT(prSwRfb);
2105
2106     prScanInfo =  &(prAdapter->rWifiVar.rScanInfo);
2107
2108     if (prBssDesc->eBand == BAND_2G4) {
2109         if ((prBssDesc->u2OperationalRateSet & RATE_SET_OFDM)
2110                 || prBssDesc->fgIsERPPresent) {
2111             eNetworkType = PARAM_NETWORK_TYPE_OFDM24;
2112         }
2113         else {
2114             eNetworkType = PARAM_NETWORK_TYPE_DS;
2115         }
2116     }
2117     else {
2118         ASSERT(prBssDesc->eBand == BAND_5G);
2119         eNetworkType = PARAM_NETWORK_TYPE_OFDM5;
2120     }
2121
2122     if(prBssDesc->eBSSType == BSS_TYPE_P2P_DEVICE) {
2123         /* NOTE(Kevin): Not supported by WZC(TBD) */
2124         return WLAN_STATUS_FAILURE;
2125     }
2126
2127     prWlanBeaconFrame = (P_WLAN_BEACON_FRAME_T)prSwRfb->pvHeader;
2128     COPY_MAC_ADDR(rMacAddr, prWlanBeaconFrame->aucBSSID);
2129     COPY_SSID(rSsid.aucSsid,
2130             rSsid.u4SsidLen,
2131             prBssDesc->aucSSID,
2132             prBssDesc->ucSSIDLen);
2133
2134     rConfiguration.u4Length             = sizeof(PARAM_802_11_CONFIG_T);
2135     rConfiguration.u4BeaconPeriod       = (UINT_32) prWlanBeaconFrame->u2BeaconInterval;
2136     rConfiguration.u4ATIMWindow         = prBssDesc->u2ATIMWindow;
2137     rConfiguration.u4DSConfig           = nicChannelNum2Freq(prBssDesc->ucChannelNum);
2138     rConfiguration.rFHConfig.u4Length   = sizeof(PARAM_802_11_CONFIG_FH_T);
2139
2140     rateGetDataRatesFromRateSet(prBssDesc->u2OperationalRateSet,
2141                                 0,
2142                                 aucRatesEx,
2143                                 &ucRateLen);
2144
2145     /* NOTE(Kevin): Set unused entries, if any, at the end of the array to 0.
2146      * from OID_802_11_BSSID_LIST
2147      */
2148     for (i = ucRateLen; i < sizeof(aucRatesEx) / sizeof(aucRatesEx[0]) ; i++) {
2149         aucRatesEx[i] = 0;
2150     }
2151
2152     switch(prBssDesc->eBSSType) {
2153     case BSS_TYPE_IBSS:
2154         eOpMode = NET_TYPE_IBSS;
2155         break;
2156
2157     case BSS_TYPE_INFRASTRUCTURE:
2158     case BSS_TYPE_P2P_DEVICE:
2159     case BSS_TYPE_BOW_DEVICE:
2160     default:
2161         eOpMode = NET_TYPE_INFRA;
2162         break;
2163     }
2164
2165     kalIndicateBssInfo(prAdapter->prGlueInfo,
2166             (PUINT_8)prSwRfb->pvHeader,
2167             prSwRfb->u2PacketLen,
2168             prBssDesc->ucChannelNum,
2169             RCPI_TO_dBm(prBssDesc->ucRCPI));
2170
2171     nicAddScanResult(prAdapter,
2172             rMacAddr,
2173             &rSsid,
2174             prWlanBeaconFrame->u2CapInfo & CAP_INFO_PRIVACY ? 1 : 0,
2175             RCPI_TO_dBm(prBssDesc->ucRCPI),
2176             eNetworkType,
2177             &rConfiguration,
2178             eOpMode,
2179             aucRatesEx,
2180             prSwRfb->u2PacketLen - prSwRfb->u2HeaderLen,
2181             (PUINT_8)((UINT_32)(prSwRfb->pvHeader) + WLAN_MAC_MGMT_HEADER_LEN));
2182
2183     return WLAN_STATUS_SUCCESS;
2184
2185 } /* end of scanAddScanResult() */
2186
2187
2188 /*----------------------------------------------------------------------------*/
2189 /*!
2190 * @brief Parse the content of given Beacon or ProbeResp Frame.
2191 *
2192 * @param[in] prSwRfb            Pointer to the receiving SW_RFB_T structure.
2193 *
2194 * @retval WLAN_STATUS_SUCCESS           if not report this SW_RFB_T to host
2195 * @retval WLAN_STATUS_PENDING           if report this SW_RFB_T to host as scan result
2196 */
2197 /*----------------------------------------------------------------------------*/
2198 WLAN_STATUS
2199 scanProcessBeaconAndProbeResp (
2200     IN P_ADAPTER_T prAdapter,
2201     IN P_SW_RFB_T prSwRfb
2202     )
2203 {
2204     P_CONNECTION_SETTINGS_T prConnSettings;
2205     P_BSS_DESC_T prBssDesc = (P_BSS_DESC_T)NULL;
2206     WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS;
2207     P_BSS_INFO_T prAisBssInfo;
2208     P_WLAN_BEACON_FRAME_T prWlanBeaconFrame = (P_WLAN_BEACON_FRAME_T)NULL;
2209 #if CFG_SLT_SUPPORT
2210     P_SLT_INFO_T prSltInfo = (P_SLT_INFO_T)NULL;
2211 #endif
2212
2213     ASSERT(prAdapter);
2214     ASSERT(prSwRfb);
2215
2216     //4 <0> Ignore invalid Beacon Frame
2217     if ((prSwRfb->u2PacketLen - prSwRfb->u2HeaderLen) <
2218             (TIMESTAMP_FIELD_LEN + BEACON_INTERVAL_FIELD_LEN + CAP_INFO_FIELD_LEN)) {
2219 #ifndef _lint
2220         ASSERT(0);
2221 #endif /* _lint */
2222         return rStatus;
2223     }
2224
2225 #if CFG_SLT_SUPPORT
2226     prSltInfo = &prAdapter->rWifiVar.rSltInfo;
2227
2228     if (prSltInfo->fgIsDUT) {
2229         DBGLOG(P2P, INFO, ("\n\rBCN: RX\n"));
2230         prSltInfo->u4BeaconReceiveCnt++;
2231         return WLAN_STATUS_SUCCESS;
2232     }
2233     else {
2234         return WLAN_STATUS_SUCCESS;
2235     }
2236 #endif
2237
2238
2239     prConnSettings = &(prAdapter->rWifiVar.rConnSettings);
2240     prAisBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_AIS_INDEX]);
2241     prWlanBeaconFrame = (P_WLAN_BEACON_FRAME_T)prSwRfb->pvHeader;
2242
2243     //4 <1> Parse and add into BSS_DESC_T
2244     prBssDesc = scanAddToBssDesc(prAdapter, prSwRfb);
2245
2246     if (prBssDesc) {
2247
2248         //4 <1.1> Beacon Change Detection for Connected BSS
2249         if(prAisBssInfo->eConnectionState == PARAM_MEDIA_STATE_CONNECTED &&
2250                 ((prBssDesc->eBSSType == BSS_TYPE_INFRASTRUCTURE && prConnSettings->eOPMode != NET_TYPE_IBSS)
2251                  || (prBssDesc->eBSSType == BSS_TYPE_IBSS && prConnSettings->eOPMode != NET_TYPE_INFRA)) &&
2252                 EQUAL_MAC_ADDR(prBssDesc->aucBSSID, prAisBssInfo->aucBSSID) &&
2253                 EQUAL_SSID(prBssDesc->aucSSID, prBssDesc->ucSSIDLen, prAisBssInfo->aucSSID, prAisBssInfo->ucSSIDLen)) {
2254             BOOLEAN fgNeedDisconnect = FALSE;
2255
2256 #if CFG_SUPPORT_BEACON_CHANGE_DETECTION
2257             // <1.1.2> check if supported rate differs
2258             if(prAisBssInfo->u2OperationalRateSet != prBssDesc->u2OperationalRateSet) {
2259                 fgNeedDisconnect = TRUE;
2260             }
2261 #endif
2262
2263             // <1.1.3> beacon content change detected, disconnect immediately
2264             if(fgNeedDisconnect == TRUE) {
2265                 aisBssBeaconTimeout(prAdapter);
2266             }
2267         }
2268
2269         //4 <1.1> Update AIS_BSS_INFO
2270         if(((prBssDesc->eBSSType == BSS_TYPE_INFRASTRUCTURE && prConnSettings->eOPMode != NET_TYPE_IBSS)
2271                     || (prBssDesc->eBSSType == BSS_TYPE_IBSS && prConnSettings->eOPMode != NET_TYPE_INFRA))) {
2272             if (prAisBssInfo->eConnectionState == PARAM_MEDIA_STATE_CONNECTED) {
2273
2274                 /* *not* checking prBssDesc->fgIsConnected anymore,
2275                  * due to Linksys AP uses " " as hidden SSID, and would have different BSS descriptor */
2276                 if ((!prAisBssInfo->ucDTIMPeriod) &&
2277                     EQUAL_MAC_ADDR(prBssDesc->aucBSSID, prAisBssInfo->aucBSSID) &&
2278                     (prAisBssInfo->eCurrentOPMode == OP_MODE_INFRASTRUCTURE) &&
2279                     ((prWlanBeaconFrame->u2FrameCtrl & MASK_FRAME_TYPE) == MAC_FRAME_BEACON)) {
2280
2281                     prAisBssInfo->ucDTIMPeriod = prBssDesc->ucDTIMPeriod;
2282
2283                     /* sync with firmware for beacon information */
2284                     nicPmIndicateBssConnected(prAdapter, NETWORK_TYPE_AIS_INDEX);
2285                 }
2286             }
2287
2288 #if CFG_SUPPORT_ADHOC
2289             if (EQUAL_SSID(prBssDesc->aucSSID,
2290                         prBssDesc->ucSSIDLen,
2291                         prConnSettings->aucSSID,
2292                         prConnSettings->ucSSIDLen) &&
2293                     (prBssDesc->eBSSType == BSS_TYPE_IBSS) &&
2294                     (prAisBssInfo->eCurrentOPMode == OP_MODE_IBSS)) {
2295
2296                 ibssProcessMatchedBeacon(prAdapter, prAisBssInfo, prBssDesc, prSwRfb->prHifRxHdr->ucRcpi);
2297             }
2298 #endif /* CFG_SUPPORT_ADHOC */
2299         }
2300
2301         rlmProcessBcn(prAdapter,
2302                 prSwRfb,
2303                 ((P_WLAN_BEACON_FRAME_T)(prSwRfb->pvHeader))->aucInfoElem,
2304                 (prSwRfb->u2PacketLen - prSwRfb->u2HeaderLen) -
2305                 (UINT_16)(OFFSET_OF(WLAN_BEACON_FRAME_BODY_T, aucInfoElem[0])));
2306
2307         //4 <3> Send SW_RFB_T to HIF when we perform SCAN for HOST
2308         if(prBssDesc->eBSSType == BSS_TYPE_INFRASTRUCTURE
2309                 || prBssDesc->eBSSType == BSS_TYPE_IBSS) {
2310             /* for AIS, send to host */
2311             if (prConnSettings->fgIsScanReqIssued &&
2312                     rlmDomainIsLegalChannel(prAdapter, prBssDesc->eBand, prBssDesc->ucChannelNum) == TRUE) {
2313                 ENUM_BAND_T eBand;
2314                 UINT_8 ucChannel;
2315                 BOOLEAN fgAddToScanResult;
2316
2317                 /* check ucChannelNum/eBand for adjacement channel filtering */
2318                 if(cnmAisInfraChannelFixed(prAdapter, &eBand, &ucChannel) == TRUE &&
2319                         (eBand != prBssDesc->eBand || ucChannel != prBssDesc->ucChannelNum)) {
2320                     fgAddToScanResult = FALSE;
2321                 }
2322                 else {
2323                     fgAddToScanResult = TRUE;
2324                 }
2325
2326                 if(fgAddToScanResult == TRUE) {
2327                     rStatus = scanAddScanResult(prAdapter, prBssDesc, prSwRfb);
2328                 }
2329             }
2330         }
2331
2332 #if CFG_ENABLE_WIFI_DIRECT
2333         if(prAdapter->fgIsP2PRegistered) {
2334             scanP2pProcessBeaconAndProbeResp(
2335                         prAdapter,
2336                         prSwRfb,
2337                         &rStatus,
2338                         prBssDesc,
2339                         prWlanBeaconFrame);
2340         }
2341 #endif
2342     }
2343
2344     return rStatus;
2345
2346 } /* end of scanProcessBeaconAndProbeResp() */
2347
2348
2349 /*----------------------------------------------------------------------------*/
2350 /*!
2351 * \brief Search the Candidate of BSS Descriptor for JOIN(Infrastructure) or
2352 *        MERGE(AdHoc) according to current Connection Policy.
2353 *
2354 * \return   Pointer to BSS Descriptor, if found. NULL, if not found
2355 */
2356 /*----------------------------------------------------------------------------*/
2357 P_BSS_DESC_T
2358 scanSearchBssDescByPolicy (
2359     IN P_ADAPTER_T prAdapter,
2360     IN ENUM_NETWORK_TYPE_INDEX_T eNetTypeIndex
2361     )
2362 {
2363     P_CONNECTION_SETTINGS_T prConnSettings;
2364     P_BSS_INFO_T prBssInfo;
2365     P_AIS_SPECIFIC_BSS_INFO_T prAisSpecBssInfo;
2366     P_SCAN_INFO_T prScanInfo;
2367
2368     P_LINK_T prBSSDescList;
2369
2370     P_BSS_DESC_T prBssDesc = (P_BSS_DESC_T)NULL;
2371     P_BSS_DESC_T prPrimaryBssDesc = (P_BSS_DESC_T)NULL;
2372     P_BSS_DESC_T prCandidateBssDesc = (P_BSS_DESC_T)NULL;
2373
2374     P_STA_RECORD_T prStaRec = (P_STA_RECORD_T)NULL;
2375     P_STA_RECORD_T prPrimaryStaRec;
2376     P_STA_RECORD_T prCandidateStaRec = (P_STA_RECORD_T)NULL;
2377
2378     OS_SYSTIME rCurrentTime;
2379     
2380     /* The first one reach the check point will be our candidate */
2381     BOOLEAN fgIsFindFirst = (BOOLEAN)FALSE;
2382
2383     BOOLEAN fgIsFindBestRSSI = (BOOLEAN)FALSE;
2384     BOOLEAN fgIsFindBestEncryptionLevel = (BOOLEAN)FALSE;
2385     //BOOLEAN fgIsFindMinChannelLoad = (BOOLEAN)FALSE;
2386
2387     /* TODO(Kevin): Support Min Channel Load */
2388     //UINT_8 aucChannelLoad[CHANNEL_NUM] = {0};
2389
2390     BOOLEAN fgIsFixedChannel;
2391     ENUM_BAND_T eBand;
2392     UINT_8 ucChannel;
2393
2394     ASSERT(prAdapter);
2395
2396     prConnSettings = &(prAdapter->rWifiVar.rConnSettings);
2397     prBssInfo = &(prAdapter->rWifiVar.arBssInfo[eNetTypeIndex]);
2398
2399     prAisSpecBssInfo = &(prAdapter->rWifiVar.rAisSpecificBssInfo);
2400
2401     prScanInfo = &(prAdapter->rWifiVar.rScanInfo);
2402     prBSSDescList = &prScanInfo->rBSSDescList;
2403
2404     GET_CURRENT_SYSTIME(&rCurrentTime);
2405
2406     /* check for fixed channel operation */
2407     if(eNetTypeIndex == NETWORK_TYPE_AIS_INDEX) {
2408         fgIsFixedChannel = cnmAisInfraChannelFixed(prAdapter, &eBand, &ucChannel);
2409     }
2410     else {
2411         fgIsFixedChannel = FALSE;
2412     }
2413
2414 #if DBG
2415     if (prConnSettings->ucSSIDLen < ELEM_MAX_LEN_SSID) {
2416         prConnSettings->aucSSID[prConnSettings->ucSSIDLen] = '\0';
2417     }
2418 #endif
2419
2420     DBGLOG(SCN, INFO, ("SEARCH: Num Of BSS_DESC_T = %d, Look for SSID: %s\n",
2421         prBSSDescList->u4NumElem, prConnSettings->aucSSID));
2422
2423
2424     //4 <1> The outer loop to search for a candidate.
2425     LINK_FOR_EACH_ENTRY(prBssDesc, prBSSDescList, rLinkEntry, BSS_DESC_T) {
2426
2427         /* TODO(Kevin): Update Minimum Channel Load Information here */
2428
2429         DBGLOG(SCN, INFO, ("SEARCH: ["MACSTR"], SSID:%s\n",
2430                             MAC2STR(prBssDesc->aucBSSID), prBssDesc->aucSSID));
2431
2432
2433         //4 <2> Check PHY Type and attributes
2434         //4 <2.1> Check Unsupported BSS PHY Type
2435         if (!(prBssDesc->ucPhyTypeSet & (prAdapter->rWifiVar.ucAvailablePhyTypeSet))) {
2436
2437             DBGLOG(SCN, INFO, ("SEARCH: Ignore unsupported ucPhyTypeSet = %x\n",
2438                                prBssDesc->ucPhyTypeSet));
2439             continue;
2440         }
2441
2442         //4 <2.2> Check if has unknown NonHT BSS Basic Rate Set.
2443         if (prBssDesc->fgIsUnknownBssBasicRate) {
2444
2445             continue;
2446         }
2447
2448         //4 <2.3> Check if fixed operation cases should be aware
2449         if (fgIsFixedChannel == TRUE &&
2450                 (prBssDesc->eBand != eBand || prBssDesc->ucChannelNum != ucChannel)) {
2451             continue;
2452         }
2453
2454         //4 <2.4> Check if the channel is legal under regulatory domain
2455         if(rlmDomainIsLegalChannel(prAdapter, prBssDesc->eBand, prBssDesc->ucChannelNum) == FALSE) {
2456             continue;
2457         }
2458
2459         //4 <2.5> Check if this BSS_DESC_T is stale
2460         if (CHECK_FOR_TIMEOUT(rCurrentTime, prBssDesc->rUpdateTime,
2461                                    SEC_TO_SYSTIME(SCN_BSS_DESC_REMOVE_TIMEOUT_SEC)) ) {
2462
2463             continue;
2464         }
2465
2466         //4 <3> Check if reach the excessive join retry limit
2467         /* NOTE(Kevin): STA_RECORD_T is recorded by TA. */
2468         prStaRec = cnmGetStaRecByAddress(prAdapter, (UINT_8) eNetTypeIndex,
2469                                             prBssDesc->aucSrcAddr);
2470
2471         if (prStaRec) {
2472             /* NOTE(Kevin):
2473              * The Status Code is the result of a Previous Connection Request, we use this as SCORE for choosing a proper
2474              * candidate (Also used for compare see <6>)
2475              * The Reason Code is an indication of the reason why AP reject us, we use this Code for "Reject"
2476              * a SCAN result to become our candidate(Like a blacklist).
2477              */
2478 #if 0 /* TODO(Kevin): */
2479             if (prStaRec->u2ReasonCode != REASON_CODE_RESERVED) {
2480                 DBGLOG(SCN, INFO, ("SEARCH: Ignore BSS with previous Reason Code = %d\n",
2481                     prStaRec->u2ReasonCode));
2482                 continue;
2483             }
2484             else
2485 #endif
2486             if (prStaRec->u2StatusCode != STATUS_CODE_SUCCESSFUL) {
2487                 /* NOTE(Kevin): greedy association - after timeout, we'll still
2488                  * try to associate to the AP whose STATUS of conection attempt
2489                  * was not success.
2490                  * We may also use (ucJoinFailureCount x JOIN_RETRY_INTERVAL_SEC) for
2491                  * time bound.
2492                  */
2493                 if ((prStaRec->ucJoinFailureCount < JOIN_MAX_RETRY_FAILURE_COUNT) ||
2494                     (CHECK_FOR_TIMEOUT(rCurrentTime,
2495                                        prStaRec->rLastJoinTime,
2496                                        SEC_TO_SYSTIME(JOIN_RETRY_INTERVAL_SEC)))) {
2497
2498                     /* NOTE(Kevin): Every JOIN_RETRY_INTERVAL_SEC interval, we can retry
2499                      * JOIN_MAX_RETRY_FAILURE_COUNT times.
2500                      */
2501                     if (prStaRec->ucJoinFailureCount >= JOIN_MAX_RETRY_FAILURE_COUNT) {
2502                         prStaRec->ucJoinFailureCount = 0;
2503                     }
2504                     DBGLOG(SCN, INFO, ("SEARCH: Try to join BSS again which has Status Code = %d (Curr = %ld/Last Join = %ld)\n",
2505                         prStaRec->u2StatusCode, rCurrentTime, prStaRec->rLastJoinTime));
2506                 }
2507                 else {
2508                     DBGLOG(SCN, INFO, ("SEARCH: Ignore BSS which reach maximum Join Retry Count = %d \n",
2509                         JOIN_MAX_RETRY_FAILURE_COUNT));
2510                     continue;
2511                 }
2512
2513             }
2514         }
2515
2516
2517         //4 <4> Check for various NETWORK conditions
2518         if (eNetTypeIndex == NETWORK_TYPE_AIS_INDEX) {
2519
2520             //4 <4.1> Check BSS Type for the corresponding Operation Mode in Connection Setting
2521             /* NOTE(Kevin): For NET_TYPE_AUTO_SWITCH, we will always pass following check. */
2522             if (((prConnSettings->eOPMode == NET_TYPE_INFRA) &&
2523                  (prBssDesc->eBSSType != BSS_TYPE_INFRASTRUCTURE)) ||
2524                 ((prConnSettings->eOPMode == NET_TYPE_IBSS || prConnSettings->eOPMode == NET_TYPE_DEDICATED_IBSS) &&
2525                  (prBssDesc->eBSSType != BSS_TYPE_IBSS))) {
2526
2527                 DBGLOG(SCN, INFO, ("SEARCH: Ignore eBSSType = %s\n",
2528                     ((prBssDesc->eBSSType == BSS_TYPE_INFRASTRUCTURE) ?
2529                         "INFRASTRUCTURE" : "IBSS")));
2530                 continue;
2531             }
2532
2533             //4 <4.2> Check AP's BSSID if OID_802_11_BSSID has been set.
2534             if ((prConnSettings->fgIsConnByBssidIssued) &&
2535                 (prBssDesc->eBSSType == BSS_TYPE_INFRASTRUCTURE)) {
2536
2537                 if (UNEQUAL_MAC_ADDR(prConnSettings->aucBSSID, prBssDesc->aucBSSID)) {
2538
2539                     DBGLOG(SCN, INFO, ("SEARCH: Ignore due to BSSID was not matched!\n"));
2540                     continue;
2541                 }
2542             }
2543
2544 #if CFG_SUPPORT_ADHOC
2545             //4 <4.3> Check for AdHoc Mode
2546             if (prBssDesc->eBSSType == BSS_TYPE_IBSS) {
2547                 OS_SYSTIME rCurrentTime;
2548
2549                 //4 <4.3.1> Check if this SCAN record has been updated recently for IBSS.
2550                 /* NOTE(Kevin): Because some STA may change its BSSID frequently after it
2551                  * create the IBSS - e.g. IPN2220, so we need to make sure we get the new one.
2552                  * For BSS, if the old record was matched, however it won't be able to pass
2553                  * the Join Process later.
2554                  */
2555                 GET_CURRENT_SYSTIME(&rCurrentTime);
2556                 if (CHECK_FOR_TIMEOUT(rCurrentTime, prBssDesc->rUpdateTime,
2557                                       SEC_TO_SYSTIME(SCN_ADHOC_BSS_DESC_TIMEOUT_SEC))) {
2558                     DBGLOG(SCN, LOUD, ("SEARCH: Skip old record of BSS Descriptor - BSSID:["MACSTR"]\n\n",
2559                               MAC2STR(prBssDesc->aucBSSID)));
2560                     continue;
2561                 }
2562
2563                 //4 <4.3.2> Check Peer's capability
2564                 if (ibssCheckCapabilityForAdHocMode(prAdapter, prBssDesc) == WLAN_STATUS_FAILURE) {
2565
2566                     DBGLOG(SCN, INFO,
2567                         ("SEARCH: Ignore BSS DESC MAC: "MACSTR", Capability is not supported for current AdHoc Mode.\n",
2568                         MAC2STR(prPrimaryBssDesc->aucBSSID)));
2569
2570                     continue;
2571                 }
2572
2573
2574                 //4 <4.3.3> Compare TSF
2575                 if (prBssInfo->fgIsBeaconActivated &&
2576                     UNEQUAL_MAC_ADDR(prBssInfo->aucBSSID, prBssDesc->aucBSSID)) {
2577
2578                     DBGLOG(SCN, LOUD,
2579                         ("SEARCH: prBssDesc->fgIsLargerTSF = %d\n",
2580                             prBssDesc->fgIsLargerTSF));
2581
2582                     if (!prBssDesc->fgIsLargerTSF) {
2583                         DBGLOG(SCN, INFO,
2584                             ("SEARCH: Ignore BSS DESC MAC: ["MACSTR"], Smaller TSF\n", MAC2STR(prBssDesc->aucBSSID)));
2585                         continue;
2586                     }
2587                 }
2588             }
2589 #endif /* CFG_SUPPORT_ADHOC */
2590
2591         }
2592
2593
2594
2595
2596 #if 0 /* TODO(Kevin): For IBSS */
2597         //4 <2.c> Check if this SCAN record has been updated recently for IBSS.
2598         /* NOTE(Kevin): Because some STA may change its BSSID frequently after it
2599          * create the IBSS, so we need to make sure we get the new one.
2600          * For BSS, if the old record was matched, however it won't be able to pass
2601          * the Join Process later.
2602          */
2603         if (prBssDesc->eBSSType == BSS_TYPE_IBSS) {
2604             OS_SYSTIME rCurrentTime;
2605
2606             GET_CURRENT_SYSTIME(&rCurrentTime);
2607             if (CHECK_FOR_TIMEOUT(rCurrentTime, prBssDesc->rUpdateTime,
2608                                   SEC_TO_SYSTIME(BSS_DESC_TIMEOUT_SEC))) {
2609                 DBGLOG(SCAN, TRACE, ("Skip old record of BSS Descriptor - BSSID:["MACSTR"]\n\n",
2610                           MAC2STR(prBssDesc->aucBSSID)));
2611                 continue;
2612             }
2613         }
2614
2615         if ((prBssDesc->eBSSType == BSS_TYPE_INFRASTRUCTURE) &&
2616             (prAdapter->eConnectionState == MEDIA_STATE_CONNECTED)) {
2617             OS_SYSTIME rCurrentTime;
2618
2619             GET_CURRENT_SYSTIME(&rCurrentTime);
2620             if (CHECK_FOR_TIMEOUT(rCurrentTime, prBssDesc->rUpdateTime,
2621                                   SEC_TO_SYSTIME(BSS_DESC_TIMEOUT_SEC))) {
2622                 DBGLOG(SCAN, TRACE, ("Skip old record of BSS Descriptor - BSSID:["MACSTR"]\n\n",
2623                           MAC2STR(prBssDesc->aucBSSID)));
2624                 continue;
2625             }
2626         }
2627
2628
2629         //4 <4B> Check for IBSS AdHoc Mode.
2630         /* Skip if one or more BSS Basic Rate are not supported by current AdHocMode */
2631         if (prPrimaryBssDesc->eBSSType == BSS_TYPE_IBSS) {
2632             //4 <4B.1> Check if match the Capability of current IBSS AdHoc Mode.
2633             if (ibssCheckCapabilityForAdHocMode(prAdapter, prPrimaryBssDesc) == WLAN_STATUS_FAILURE) {
2634
2635                 DBGLOG(SCAN, TRACE,
2636                     ("Ignore BSS DESC MAC: "MACSTR", Capability is not supported for current AdHoc Mode.\n",
2637                     MAC2STR(prPrimaryBssDesc->aucBSSID)));
2638
2639                 continue;
2640             }
2641
2642
2643             //4 <4B.2> IBSS Merge Decision Flow for SEARCH STATE.
2644             if (prAdapter->fgIsIBSSActive &&
2645                 UNEQUAL_MAC_ADDR(prBssInfo->aucBSSID, prPrimaryBssDesc->aucBSSID)) {
2646
2647                 if (!fgIsLocalTSFRead) {
2648                     NIC_GET_CURRENT_TSF(prAdapter, &rCurrentTsf);
2649
2650                     DBGLOG(SCAN, TRACE,
2651                         ("\n\nCurrent TSF : %08lx-%08lx\n\n",
2652                             rCurrentTsf.u.HighPart, rCurrentTsf.u.LowPart));
2653                 }
2654
2655                 if (rCurrentTsf.QuadPart > prPrimaryBssDesc->u8TimeStamp.QuadPart) {
2656                     DBGLOG(SCAN, TRACE,
2657                         ("Ignore BSS DESC MAC: ["MACSTR"], Current BSSID: ["MACSTR"].\n",
2658                             MAC2STR(prPrimaryBssDesc->aucBSSID), MAC2STR(prBssInfo->aucBSSID)));
2659
2660                     DBGLOG(SCAN, TRACE,
2661                         ("\n\nBSS's TSF : %08lx-%08lx\n\n",
2662                             prPrimaryBssDesc->u8TimeStamp.u.HighPart, prPrimaryBssDesc->u8TimeStamp.u.LowPart));
2663
2664                     prPrimaryBssDesc->fgIsLargerTSF = FALSE;
2665                     continue;
2666                 }
2667                 else {
2668                     prPrimaryBssDesc->fgIsLargerTSF = TRUE;
2669                 }
2670
2671             }
2672         }
2673
2674         //4 <5> Check the Encryption Status.
2675         if (rsnPerformPolicySelection(prPrimaryBssDesc)) {
2676
2677             if (prPrimaryBssDesc->ucEncLevel > 0) {
2678                 fgIsFindBestEncryptionLevel = TRUE;
2679
2680                 fgIsFindFirst = FALSE;
2681             }
2682         }
2683         else {
2684             /* Can't pass the Encryption Status Check, get next one */
2685             continue;
2686         }
2687
2688         /* For RSN Pre-authentication, update the PMKID canidate list for
2689            same SSID and encrypt status */
2690         /* Update PMKID candicate list. */
2691         if (prAdapter->rWifiVar.rConnSettings.eAuthMode == AUTH_MODE_WPA2) {
2692             rsnUpdatePmkidCandidateList(prPrimaryBssDesc);
2693             if (prAdapter->rWifiVar.rAisBssInfo.u4PmkidCandicateCount) {
2694                 prAdapter->rWifiVar.rAisBssInfo.fgIndicatePMKID = rsnCheckPmkidCandicate();
2695             }
2696         }
2697
2698 #endif
2699
2700
2701         prPrimaryBssDesc = (P_BSS_DESC_T)NULL;
2702
2703         //4 <6> Check current Connection Policy.
2704         switch (prConnSettings->eConnectionPolicy) {
2705         case CONNECT_BY_SSID_BEST_RSSI:
2706             /* Choose Hidden SSID to join only if the `fgIsEnableJoin...` is TRUE */
2707             if (prAdapter->rWifiVar.fgEnableJoinToHiddenSSID && prBssDesc->fgIsHiddenSSID) {
2708                 /* NOTE(Kevin): following if () statement means that
2709                  * If Target is hidden, then we won't connect when user specify SSID_ANY policy.
2710                  */
2711                 if (prConnSettings->ucSSIDLen) {
2712                     prPrimaryBssDesc = prBssDesc;
2713
2714                     fgIsFindBestRSSI = TRUE;
2715                 }
2716
2717             }
2718             else if (EQUAL_SSID(prBssDesc->aucSSID,
2719                                 prBssDesc->ucSSIDLen,
2720                                 prConnSettings->aucSSID,
2721                                 prConnSettings->ucSSIDLen)) {
2722                 prPrimaryBssDesc = prBssDesc;
2723
2724                 fgIsFindBestRSSI = TRUE;
2725             }
2726             break;
2727
2728         case CONNECT_BY_SSID_ANY:
2729             /* NOTE(Kevin): In this policy, we don't know the desired
2730              * SSID from user, so we should exclude the Hidden SSID from scan list.
2731              * And because we refuse to connect to Hidden SSID node at the beginning, so
2732              * when the JOIN Module deal with a BSS_DESC_T which has fgIsHiddenSSID == TRUE,
2733              * then the Connection Settings must be valid without doubt.
2734              */
2735             if (!prBssDesc->fgIsHiddenSSID) {
2736                 prPrimaryBssDesc = prBssDesc;
2737
2738                 fgIsFindFirst = TRUE;
2739             }
2740             break;
2741
2742         case CONNECT_BY_BSSID:
2743             if(EQUAL_MAC_ADDR(prBssDesc->aucBSSID, prConnSettings->aucBSSID)) {
2744                 prPrimaryBssDesc = prBssDesc;
2745             }
2746             break;
2747
2748         default:
2749             break;
2750         }
2751
2752
2753         /* Primary Candidate was not found */
2754         if (prPrimaryBssDesc == NULL) {
2755             continue;
2756         }
2757
2758         //4 <7> Check the Encryption Status.
2759         if (prPrimaryBssDesc->eBSSType == BSS_TYPE_INFRASTRUCTURE) {
2760 #if CFG_SUPPORT_WAPI
2761             if (prAdapter->rWifiVar.rConnSettings.fgWapiMode) {
2762                 if (wapiPerformPolicySelection(prAdapter, prPrimaryBssDesc)) {
2763                     fgIsFindFirst = TRUE;
2764                 }
2765                 else {
2766                     /* Can't pass the Encryption Status Check, get next one */
2767                     continue;
2768                 }
2769             }
2770             else
2771 #endif
2772 #if CFG_RSN_MIGRATION
2773             if (rsnPerformPolicySelection(prAdapter, prPrimaryBssDesc)) {
2774                 if (prAisSpecBssInfo->fgCounterMeasure) {
2775                     DBGLOG(RSN, INFO, ("Skip while at counter measure period!!!\n"));
2776                     continue;
2777                 }
2778
2779                 if (prPrimaryBssDesc->ucEncLevel > 0) {
2780                     fgIsFindBestEncryptionLevel = TRUE;
2781
2782                     fgIsFindFirst = FALSE;
2783                 }
2784
2785 #if 0
2786                 /* Update PMKID candicate list. */
2787                 if (prAdapter->rWifiVar.rConnSettings.eAuthMode == AUTH_MODE_WPA2) {
2788                     rsnUpdatePmkidCandidateList(prPrimaryBssDesc);
2789                     if (prAisSpecBssInfo->u4PmkidCandicateCount) {
2790                         if (rsnCheckPmkidCandicate()) {
2791                             DBGLOG(RSN, WARN, ("Prepare a timer to indicate candidate "MACSTR"\n",
2792                                 MAC2STR(prAisSpecBssInfo->arPmkidCache[prAisSpecBssInfo->u4PmkidCacheCount].rBssidInfo.aucBssid)));
2793                             cnmTimerStopTimer(&prAisSpecBssInfo->rPreauthenticationTimer);
2794                             cnmTimerStartTimer(&prAisSpecBssInfo->rPreauthenticationTimer,
2795                                     SEC_TO_MSEC(WAIT_TIME_IND_PMKID_CANDICATE_SEC));
2796                         }
2797                     }
2798                 }
2799 #endif
2800             }
2801             else {
2802                 /* Can't pass the Encryption Status Check, get next one */
2803                 continue;
2804             }
2805 #endif
2806         }
2807         else {
2808             /* Todo:: P2P and BOW Policy Selection */
2809         }
2810
2811         prPrimaryStaRec = prStaRec;
2812
2813         //4 <8> Compare the Candidate and the Primary Scan Record.
2814         if (!prCandidateBssDesc) {
2815             prCandidateBssDesc = prPrimaryBssDesc;
2816             prCandidateStaRec = prPrimaryStaRec;
2817
2818             //4 <8.1> Condition - Get the first matched one.
2819             if (fgIsFindFirst) {
2820                 break;
2821             }
2822         }
2823         else {
2824 #if 0 /* TODO(Kevin): For security(TBD) */
2825             //4 <6B> Condition - Choose the one with best Encryption Score.
2826             if (fgIsFindBestEncryptionLevel) {
2827                 if (prCandidateBssDesc->ucEncLevel <
2828                     prPrimaryBssDesc->ucEncLevel) {
2829
2830                     prCandidateBssDesc = prPrimaryBssDesc;
2831                     prCandidateStaRec = prPrimaryStaRec;
2832                     continue;
2833                 }
2834             }
2835
2836             /* If reach here, that means they have the same Encryption Score.
2837              */
2838
2839             //4 <6C> Condition - Give opportunity to the one we didn't connect before.
2840             // For roaming, only compare the candidates other than current associated BSSID.
2841             if (!prCandidateBssDesc->fgIsConnected && !prPrimaryBssDesc->fgIsConnected) {
2842                 if ((prCandidateStaRec != (P_STA_RECORD_T)NULL) &&
2843                     (prCandidateStaRec->u2StatusCode != STATUS_CODE_SUCCESSFUL)) {
2844
2845                     DBGLOG(SCAN, TRACE, ("So far -BSS DESC MAC: "MACSTR" has nonzero Status Code = %d\n",
2846                         MAC2STR(prCandidateBssDesc->aucBSSID), prCandidateStaRec->u2StatusCode));
2847
2848                     if (prPrimaryStaRec != (P_STA_RECORD_T)NULL) {
2849                         if (prPrimaryStaRec->u2StatusCode != STATUS_CODE_SUCCESSFUL) {
2850
2851                             /* Give opportunity to the one with smaller rLastJoinTime */
2852                             if (TIME_BEFORE(prCandidateStaRec->rLastJoinTime,
2853                                                         prPrimaryStaRec->rLastJoinTime)) {
2854                                 continue;
2855                             }
2856                             /* We've connect to CANDIDATE recently, let us try PRIMARY now */
2857                             else {
2858                                 prCandidateBssDesc = prPrimaryBssDesc;
2859                                 prCandidateStaRec = prPrimaryStaRec;
2860                                 continue;
2861                             }
2862                         }
2863                         /* PRIMARY's u2StatusCode = 0 */
2864                         else {
2865                             prCandidateBssDesc = prPrimaryBssDesc;
2866                             prCandidateStaRec = prPrimaryStaRec;
2867                             continue;
2868                         }
2869                     }
2870                     /* PRIMARY has no StaRec - We didn't connet to PRIMARY before */
2871                     else {
2872                         prCandidateBssDesc = prPrimaryBssDesc;
2873                         prCandidateStaRec = prPrimaryStaRec;
2874                         continue;
2875                     }
2876                 }
2877                 else {
2878                     if ((prPrimaryStaRec != (P_STA_RECORD_T)NULL) &&
2879                         (prPrimaryStaRec->u2StatusCode != STATUS_CODE_SUCCESSFUL)) {
2880                         continue;
2881                     }
2882                 }
2883             }
2884 #endif
2885
2886
2887             //4 <6D> Condition - Visible SSID win Hidden SSID.
2888             if (prCandidateBssDesc->fgIsHiddenSSID) {
2889                 if (!prPrimaryBssDesc->fgIsHiddenSSID) {
2890                     prCandidateBssDesc = prPrimaryBssDesc; /* The non Hidden SSID win. */
2891                     prCandidateStaRec = prPrimaryStaRec;
2892                     continue;
2893                 }
2894             }
2895             else {
2896                 if (prPrimaryBssDesc->fgIsHiddenSSID) {
2897                     continue;
2898                 }
2899             }
2900
2901
2902             //4 <6E> Condition - Choose the one with better RCPI(RSSI).
2903             if (fgIsFindBestRSSI) {
2904                 /* TODO(Kevin): We shouldn't compare the actual value, we should
2905                  * allow some acceptable tolerance of some RSSI percentage here.
2906                  */
2907                 DBGLOG(SCN, TRACE, ("Candidate ["MACSTR"]: RCPI = %d, Primary ["MACSTR"]: RCPI = %d\n",
2908                     MAC2STR(prCandidateBssDesc->aucBSSID), prCandidateBssDesc->ucRCPI,
2909                     MAC2STR(prPrimaryBssDesc->aucBSSID), prPrimaryBssDesc->ucRCPI));
2910
2911                 ASSERT(!(prCandidateBssDesc->fgIsConnected &&
2912                          prPrimaryBssDesc->fgIsConnected));
2913
2914                 /* NOTE: To prevent SWING, we do roaming only if target AP has at least 5dBm larger than us. */
2915                 if (prCandidateBssDesc->fgIsConnected) {
2916                     if (prCandidateBssDesc->ucRCPI + ROAMING_NO_SWING_RCPI_STEP <= prPrimaryBssDesc->ucRCPI) {
2917
2918                         prCandidateBssDesc = prPrimaryBssDesc;
2919                         prCandidateStaRec = prPrimaryStaRec;
2920                         continue;
2921                     }
2922                 }
2923                 else if (prPrimaryBssDesc->fgIsConnected) {
2924                     if (prCandidateBssDesc->ucRCPI < prPrimaryBssDesc->ucRCPI + ROAMING_NO_SWING_RCPI_STEP) {
2925
2926                         prCandidateBssDesc = prPrimaryBssDesc;
2927                         prCandidateStaRec = prPrimaryStaRec;
2928                         continue;
2929                     }
2930                 }
2931                 else if (prCandidateBssDesc->ucRCPI < prPrimaryBssDesc->ucRCPI) {
2932                     prCandidateBssDesc = prPrimaryBssDesc;
2933                     prCandidateStaRec = prPrimaryStaRec;
2934                     continue;
2935                 }
2936             }
2937
2938 #if 0
2939             /* If reach here, that means they have the same Encryption Score, and
2940              * both RSSI value are close too.
2941              */
2942             //4 <6F> Seek the minimum Channel Load for less interference.
2943             if (fgIsFindMinChannelLoad) {
2944
2945                 /* TODO(Kevin): Check which one has minimum channel load in its channel */
2946             }
2947 #endif
2948         }
2949     }
2950
2951     return prCandidateBssDesc;
2952
2953 } /* end of scanSearchBssDescByPolicy() */
2954
2955