1 /** @file mlan_scan.c
2  *
3  *  @brief  This file provides wlan scan IOCTL and firmware command APIs
4  *
5  *  Copyright 2008-2024 NXP
6  *
7  *  SPDX-License-Identifier: BSD-3-Clause
8  *
9  */
10 
11 /******************************************************
12 Change log:
13     10/28/2008: initial version
14 ******************************************************/
15 #include <mlan_api.h>
16 
17 /* Additional WMSDK header files */
18 #include <wmerrno.h>
19 #include <osa.h>
20 
21 /* Always keep this include at the end of all include files */
22 #include <mlan_remap_mem_operations.h>
23 /********************************************************
24                 Local Constants
25 ********************************************************/
26 #if defined(RW610) || defined(SD9177)
27 /** minimum scan time for passive to active scan */
28 #define MIN_PASSIVE_TO_ACTIVE_SCAN_TIME 150
29 #endif
30 
31 /** The maximum number of channels the firmware can scan per command */
32 #define MRVDRV_MAX_CHANNELS_PER_SPECIFIC_SCAN 3
33 
34 /**
35  * Number of channels to scan per firmware scan command issuance.
36  *
37  * Number restricted to prevent hitting the limit on the amount of scan data
38  * returned in a single firmware scan command.
39  */
40 #define MRVDRV_CHANNELS_PER_SCAN_CMD 4
41 
42 /** Memory needed to store a max sized Channel List TLV for a firmware scan */
43 #define CHAN_TLV_MAX_SIZE \
44     (sizeof(MrvlIEtypesHeader_t) + (MRVDRV_MAX_CHANNELS_PER_SPECIFIC_SCAN * sizeof(ChanScanParamSet_t)))
45 
46 /** Memory needed to store supported rate */
47 #define RATE_TLV_MAX_SIZE (sizeof(MrvlIEtypes_RatesParamSet_t) + HOSTCMD_SUPPORTED_RATES)
48 
49 /** Memory needed to store a max number/size WildCard SSID TLV for a firmware scan */
50 #define WILDCARD_SSID_TLV_MAX_SIZE \
51     (MRVDRV_MAX_SSID_LIST_LENGTH * (sizeof(MrvlIEtypes_WildCardSsIdParamSet_t) + MRVDRV_MAX_SSID_LENGTH))
52 
53 /** WPS TLV MAX size is MAX IE size plus 2 bytes for t_u16 MRVL TLV extension */
54 #define WPS_TLV_MAX_SIZE (sizeof(IEEEtypes_VendorSpecific_t) + 2)
55 /** Maximum memory needed for a wlan_scan_cmd_config with all TLVs at max */
56 #define MAX_SCAN_CFG_ALLOC                                                                          \
57     (sizeof(wlan_scan_cmd_config) + sizeof(MrvlIEtypes_NumProbes_t) + sizeof(MrvlIETypes_HTCap_t) + \
58      CHAN_TLV_MAX_SIZE + RATE_TLV_MAX_SIZE + WILDCARD_SSID_TLV_MAX_SIZE + WPS_TLV_MAX_SIZE)
59 
60 /********************************************************
61                 Local Variables
62 ********************************************************/
63 
64 /* Global data required for split scan requests */
65 static bool abort_split_scan;
66 
67 #if CONFIG_MEM_POOLS
68 static BSSDescriptor_t s_bss_new_entry;
69 #if CONFIG_MULTI_BSSID_SUPPORT
70 static BSSDescriptor_t s2_bss_new_entry;
71 #endif
72 #endif
73 
74 int get_split_scan_delay_ms(void);
75 
76 /**
77  * Interally used to send a configured scan cmd between driver routines
78  */
79 typedef union
80 {
81     /** Scan configuration (variable length) */
82     wlan_scan_cmd_config config;
83     /** Max allocated block */
84     t_u8 config_alloc_buf[MAX_SCAN_CFG_ALLOC];
85 } wlan_scan_cmd_config_tlv;
86 
87 /********************************************************
88                 Global Variables
89 ********************************************************/
90 bool split_scan_in_progress;
91 
92 /********************************************************
93                 Local Functions
94 ********************************************************/
95 /** Cipher suite definition */
96 typedef enum cipher_suite
97 {
98     CIPHER_SUITE_TKIP,
99     CIPHER_SUITE_CCMP,
100     CIPHER_SUITE_MAX
101 } cipher_suite;
102 
103 static t_u8 wpa_oui[CIPHER_SUITE_MAX][4] = {
104     {0x00, 0x50, 0xf2, 0x02}, /* TKIP */
105     {0x00, 0x50, 0xf2, 0x04}, /* AES */
106 };
107 
108 static t_u8 rsn_oui[CIPHER_SUITE_MAX][4] = {
109     {0x00, 0x0f, 0xac, 0x02}, /* TKIP */
110     {0x00, 0x0f, 0xac, 0x04}, /* AES */
111 };
112 
113 static t_u32 wlan_find_worst_network_in_list(const BSSDescriptor_t *pbss_desc, t_u32 num_entries);
114 
is_split_scan_complete(void)115 bool is_split_scan_complete(void)
116 {
117     return (split_scan_in_progress == false);
118 }
119 
120 /*
121  * wmsdk: Split scan needs to be aborted at times by the application. This
122  * API will help the caller do that.
123  */
wlan_abort_split_scan(void)124 void wlan_abort_split_scan(void)
125 {
126 #if CONFIG_WPA_SUPP
127     int supp_scan_in_process = 0;
128 
129     if(wm_wifi.supp_if_callbk_fns->is_supp_scan_in_progress_callbk_fn)
130     {
131         supp_scan_in_process = wm_wifi.supp_if_callbk_fns->is_supp_scan_in_progress_callbk_fn(wm_wifi.if_priv);
132     }
133 #endif
134     /*Also check the state of supplicant scan, if it is in progress, abort it*/
135     if ((split_scan_in_progress == true)
136 #if CONFIG_WPA_SUPP
137         || (supp_scan_in_process == true)
138 #endif
139         )
140     {
141         if(split_scan_in_progress)
142         {
143             abort_split_scan = true;
144         }
145 #if CONFIG_WPA_SUPP
146         if (wm_wifi.supp_if_callbk_fns->scan_done_callbk_fn)
147         {
148             wm_wifi.supp_if_callbk_fns->scan_done_callbk_fn(wm_wifi.if_priv, 1, 0);
149         }
150 #endif
151     }
152 }
153 
154 /**
155  *  @brief This function will parse a given IE for a given OUI
156  *
157  *  Parse a given WPA/RSN IE to find if it has a given oui in PTK,
158  *  if no OUI found for PTK it returns 0.
159  *
160  *  @param pbss_desc       A pointer to current BSS descriptor
161  *  @return                0 on failure to find OUI, 1 on success.
162  */
search_oui_in_ie(mlan_adapter * pmadapter,IEBody * ie_body,t_u8 * oui)163 static t_u8 search_oui_in_ie(mlan_adapter *pmadapter, IEBody *ie_body, t_u8 *oui)
164 {
165     t_u8 count;
166 
167     count = ie_body->PtkCnt[0];
168 
169     ENTER();
170     /* There could be multiple OUIs for PTK hence 1) Take the length. 2) Check
171        all the OUIs for AES. 3) If one of them is AES then pass success. */
172     while (count != 0U)
173     {
174         if (!__memcmp(pmadapter, ie_body->PtkBody, oui, sizeof(ie_body->PtkBody)))
175         {
176             LEAVE();
177             return MLAN_OUI_PRESENT;
178         }
179 
180         --count;
181         if (count != 0U)
182         {
183             ie_body = (IEBody *)(void *)((t_u8 *)ie_body + sizeof(ie_body->PtkBody));
184         }
185     }
186 
187     PRINTM(MINFO, "The OUI %x:%x:%x:%x is not found in PTK \n", oui[0], oui[1], oui[2], oui[3]);
188     LEAVE();
189     return MLAN_OUI_NOT_PRESENT;
190 }
191 
192 /**
193  *  @brief This function will pass the correct ie and oui to search_oui_in_ie
194  *
195  *  Check the pbss_desc for appropriate IE and then check if RSN IE has AES
196  *  OUI in it. If RSN IE does not have AES in PTK then return 0;
197  *
198  *  @param pbss_desc       A pointer to current BSS descriptor
199  *  @return                0 on failure to find AES OUI, 1 on success.
200  */
is_rsn_oui_present(mlan_adapter * pmadapter,BSSDescriptor_t * pbss_desc,cipher_suite cipher)201 static t_u8 is_rsn_oui_present(mlan_adapter *pmadapter, BSSDescriptor_t *pbss_desc, cipher_suite cipher)
202 {
203     t_u8 *oui       = MNULL;
204     IEBody *ie_body = MNULL;
205     t_u8 ret        = MLAN_OUI_NOT_PRESENT;
206 
207     ENTER();
208     if (((pbss_desc->prsn_ie != MNULL) && ((*(pbss_desc->prsn_ie)).ieee_hdr.element_id == RSN_IE)))
209     {
210         ie_body = (IEBody *)(void *)(((t_u8 *)pbss_desc->prsn_ie->data) + RSN_GTK_OUI_OFFSET);
211         oui     = &rsn_oui[cipher][0];
212         if ((ret = search_oui_in_ie(pmadapter, ie_body, oui)) != 0U)
213         {
214             LEAVE();
215             return ret;
216         }
217     }
218     LEAVE();
219     return ret;
220 }
221 
222 /**
223  *  @brief This function will pass the correct ie and oui to search_oui_in_ie
224  *
225  *  Check the pbss_desc for appropriate IE and then check if WPA IE has AES
226  *  OUI in it. If WPA IE does not have AES in PTK then return 0;
227  *
228  *  @param pbss_desc       A pointer to current BSS descriptor
229  *  @return                0 on failure to find AES OUI, 1 on success.
230  */
is_wpa_oui_present(mlan_adapter * pmadapter,BSSDescriptor_t * pbss_desc,cipher_suite cipher)231 static t_u8 is_wpa_oui_present(mlan_adapter *pmadapter, BSSDescriptor_t *pbss_desc, cipher_suite cipher)
232 {
233     t_u8 *oui       = MNULL;
234     IEBody *ie_body = MNULL;
235     t_u8 ret        = MLAN_OUI_NOT_PRESENT;
236 
237     ENTER();
238     if (((pbss_desc->pwpa_ie != MNULL) && ((*(pbss_desc->pwpa_ie)).vend_hdr.element_id == WPA_IE)))
239     {
240         ie_body = (IEBody *)(void *)pbss_desc->pwpa_ie->data;
241         oui     = &wpa_oui[(int)cipher][0];
242         if ((ret = search_oui_in_ie(pmadapter, ie_body, oui)) != 0U)
243         {
244             LEAVE();
245             return ret;
246         }
247     }
248     LEAVE();
249     return ret;
250 }
251 
252 /**
253  *  @brief Convert radio type scan parameter to a band config used in join cmd
254  *
255  *  @param radio_type Scan parameter indicating the radio used for a channel
256  *                    in a scan command.
257  *
258  *  @return          Band type conversion of scanBand used in join/assoc cmds
259  *
260  */
radio_type_to_band(t_u8 radio_type)261 static t_u16 radio_type_to_band(t_u8 radio_type)
262 {
263     t_u16 ret_band;
264 
265     switch (radio_type)
266     {
267         case HostCmd_SCAN_RADIO_TYPE_A:
268             ret_band = BAND_A;
269             break;
270         case HostCmd_SCAN_RADIO_TYPE_BG:
271         default:
272             ret_band = BAND_G;
273             break;
274     }
275 
276     return ret_band;
277 }
278 
279 #if CONFIG_SCAN_CHANNEL_GAP
280 /**
281  *  @brief This function will update the channel statistics from scan result
282  *
283  *  @param pmpriv           A pointer to mlan_private structure
284  *  @param pchanstats_tlv   A pointer to MrvlIEtypes_ChannelStats_t tlv
285  *
286  *  @return                NA
287  */
wlan_update_chan_statistics(mlan_private * pmpriv,MrvlIEtypes_ChannelStats_t * pchanstats_tlv)288 static void wlan_update_chan_statistics(mlan_private *pmpriv, MrvlIEtypes_ChannelStats_t *pchanstats_tlv)
289 {
290     mlan_adapter *pmadapter = pmpriv->adapter;
291     t_u8 i;
292     chan_statistics_t *pchan_stats = (chan_statistics_t *)((t_u8 *)pchanstats_tlv + sizeof(MrvlIEtypesHeader_t));
293     t_u8 num_chan                  = wlan_le16_to_cpu(pchanstats_tlv->header.len) / sizeof(chan_statistics_t);
294 
295     ENTER();
296 
297     for (i = 0; i < num_chan; i++)
298     {
299         if (pchan_stats->chan_num == 0U)
300         {
301             break;
302         }
303 
304         if (pmadapter->idx_chan_stats >= pmadapter->num_in_chan_stats)
305         {
306             wifi_d("Over flow: idx_chan_stats=%d, num_in_chan_stats=%d", pmadapter->idx_chan_stats,
307                    pmadapter->num_in_chan_stats);
308             break;
309         }
310         pchan_stats->total_networks    = wlan_le16_to_cpu(pchan_stats->total_networks);
311         pchan_stats->cca_scan_duration = wlan_le16_to_cpu(pchan_stats->cca_scan_duration);
312         pchan_stats->cca_busy_duration = wlan_le16_to_cpu(pchan_stats->cca_busy_duration);
313         wifi_d("chan=%d, noise=%d, total_network=%d scan_duration=%d, busy_duration=%d", pchan_stats->chan_num,
314                pchan_stats->noise, pchan_stats->total_networks, pchan_stats->cca_scan_duration,
315                pchan_stats->cca_busy_duration);
316         __memcpy(pmadapter, (chan_statistics_t *)&pmadapter->pchan_stats[pmadapter->idx_chan_stats], pchan_stats,
317                  sizeof(chan_statistics_t));
318         pmadapter->idx_chan_stats++;
319         pchan_stats++;
320     }
321     LEAVE();
322     return;
323 }
324 #endif
325 
326 /**
327  *  @brief compare config band and a band from the scan result,
328  *  which is defined by functiion radio_type_to_band(t_u8 radio_type) above
329  *
330  *  @param cfg_band:  band configured
331  *         scan_band: band from scan result
332  *
333  *  @return  matched: non-zero. unmatched: 0
334  *
335  */
wlan_is_band_compatible(t_u16 cfg_band,t_u16 scan_band)336 static t_u8 wlan_is_band_compatible(t_u16 cfg_band, t_u16 scan_band)
337 {
338     t_u16 band;
339     switch (scan_band)
340     {
341         case BAND_A:
342             band = (BAND_A | BAND_AN | BAND_AAC);
343             break;
344         case BAND_G:
345         default:
346             band = (BAND_B | BAND_G | BAND_GN | BAND_GAC);
347             break;
348     }
349     return (cfg_band & band);
350 }
351 
352 /**
353  *  @brief Create a channel list for the driver to scan based on region info
354  *
355  *  Use the driver region/band information to construct a comprehensive list
356  *    of channels to scan.  This routine is used for any scan that is not
357  *    provided a specific channel list to scan.
358  *
359  *  @param pmpriv           A pointer to mlan_private structure
360  *  @param puser_scan_in    MNULL or pointer to scan configuration parameters
361  *  @param pscan_chan_list  Output parameter: Resulting channel list to scan
362  *  @param filtered_scan    Flag indicating whether or not a BSSID or SSID filter
363  *                          is being sent in the command to firmware.  Used to
364  *                          increase the number of channels sent in a scan
365  *                          command and to disable the firmware channel scan
366  *                          filter.
367  *
368  *  @return                 N/A
369  */
wlan_scan_create_channel_list(IN mlan_private * pmpriv,IN const wlan_user_scan_cfg * puser_scan_in,OUT ChanScanParamSet_t * pscan_chan_list,IN t_u8 filtered_scan)370 static t_void wlan_scan_create_channel_list(IN mlan_private *pmpriv,
371                                             IN const wlan_user_scan_cfg *puser_scan_in,
372                                             OUT ChanScanParamSet_t *pscan_chan_list,
373                                             IN t_u8 filtered_scan)
374 {
375     mlan_adapter *pmadapter = pmpriv->adapter;
376     region_chan_t *pscan_region;
377     const chan_freq_power_t *cfp;
378     t_u32 region_idx;
379     t_u32 chan_idx = 0;
380     t_u32 next_chan;
381     mlan_scan_type scan_type;
382     t_u8 radio_type;
383 
384     ENTER();
385 
386     for (region_idx = 0; region_idx < NELEMENTS(pmadapter->region_channel); region_idx++)
387     {
388         if (wlan_11d_support_is_enabled(pmpriv) && wlan_11d_is_enabled(pmpriv) && pmpriv->media_connected != MTRUE)
389         {
390             /* Scan all the supported chan for the first scan */
391             if (!pmadapter->universal_channel[region_idx].valid)
392             {
393                 continue;
394             }
395             pscan_region = &pmadapter->universal_channel[region_idx];
396         }
397         else
398         {
399             if (!pmadapter->region_channel[region_idx].valid)
400             {
401                 continue;
402             }
403             pscan_region = &pmadapter->region_channel[region_idx];
404         }
405 
406         if ((puser_scan_in != MNULL) && !puser_scan_in->chan_list[0].chan_number &&
407             puser_scan_in->chan_list[0].radio_type & BAND_SPECIFIED)
408         {
409             radio_type = (t_u8)(puser_scan_in->chan_list[0].radio_type & ~BAND_SPECIFIED);
410             if (!radio_type && (pscan_region->band != BAND_B) && (pscan_region->band != BAND_G))
411             {
412                 continue;
413             }
414             if (radio_type && (pscan_region->band != BAND_A))
415             {
416                 continue;
417             }
418         }
419         if (!wlan_is_band_compatible(pmpriv->config_bands, pscan_region->band))
420         {
421             continue;
422         }
423         for (next_chan = 0; next_chan < pscan_region->num_cfp; next_chan++)
424         {
425             /* Set the default scan type to the user specified type, will later
426                be changed to passive on a per channel basis if restricted by
427                regulatory requirements (11d or 11h) */
428             scan_type = pmadapter->scan_type;
429             cfp       = pscan_region->pcfp + next_chan;
430             if ((cfp->dynamic.flags & NXP_CHANNEL_DISABLED) != 0U)
431             {
432                 continue;
433             }
434 
435             switch (pscan_region->band)
436             {
437 #if CONFIG_5GHz_SUPPORT
438                 case BAND_A:
439                     pscan_chan_list[chan_idx].radio_type = HostCmd_SCAN_RADIO_TYPE_A;
440                     /* 11D not available... play it safe on DFS channels */
441                     if (wlan_11h_radar_detect_required(pmpriv, (t_u8)cfp->channel))
442                     {
443                         /* Skip DFS channels if required */
444                         if (pmadapter->skip_dfs)
445                             continue;
446 #if defined(RW610) || defined(SD9177)
447                         scan_type = MLAN_SCAN_TYPE_PASSIVE_TO_ACTIVE;
448 #else
449                         scan_type = MLAN_SCAN_TYPE_PASSIVE;
450 #endif
451                     }
452                     break;
453 #endif
454                 case BAND_B:
455                 case BAND_G:
456                     if (wlan_bg_scan_type_is_passive(pmpriv, (t_u8)cfp->channel))
457                     {
458                         scan_type = MLAN_SCAN_TYPE_PASSIVE;
459                     }
460                     pscan_chan_list[chan_idx].radio_type = HostCmd_SCAN_RADIO_TYPE_BG;
461                     break;
462                 default:
463                     pscan_chan_list[chan_idx].radio_type = HostCmd_SCAN_RADIO_TYPE_BG;
464                     break;
465             }
466 
467             if ((puser_scan_in != MNULL) && puser_scan_in->chan_list[0].scan_time)
468             {
469                 pscan_chan_list[chan_idx].max_scan_time =
470                     wlan_cpu_to_le16((t_u16)puser_scan_in->chan_list[0].scan_time);
471             }
472 #if defined(RW610) || defined(SD9177)
473             else if (scan_type == MLAN_SCAN_TYPE_PASSIVE || scan_type == MLAN_SCAN_TYPE_PASSIVE_TO_ACTIVE)
474 #else
475             else if (scan_type == MLAN_SCAN_TYPE_PASSIVE)
476 #endif
477             {
478                 pscan_chan_list[chan_idx].max_scan_time = wlan_cpu_to_le16(pmadapter->passive_scan_time);
479             }
480             else if (filtered_scan != 0U)
481             {
482                 pscan_chan_list[chan_idx].max_scan_time = wlan_cpu_to_le16(pmadapter->specific_scan_time);
483             }
484             else
485             {
486                 pscan_chan_list[chan_idx].max_scan_time = wlan_cpu_to_le16(pmadapter->active_scan_time);
487             }
488 
489 #if defined(RW610) || defined(SD9177)
490             if (scan_type == MLAN_SCAN_TYPE_PASSIVE_TO_ACTIVE)
491             {
492                 pscan_chan_list[chan_idx].max_scan_time =
493                     wlan_cpu_to_le16(MAX(pmadapter->passive_scan_time, MIN_PASSIVE_TO_ACTIVE_SCAN_TIME));
494                 pscan_chan_list[chan_idx].chan_scan_mode.passive_to_active_scan = MTRUE;
495             }
496 #endif
497 #if defined(RW610) || defined(SD9177)
498             if (scan_type == MLAN_SCAN_TYPE_PASSIVE || scan_type == MLAN_SCAN_TYPE_PASSIVE_TO_ACTIVE)
499 #else
500             if (scan_type == MLAN_SCAN_TYPE_PASSIVE)
501 #endif
502             {
503                 pscan_chan_list[chan_idx].chan_scan_mode.passive_scan       = MTRUE;
504                 pscan_chan_list[chan_idx].chan_scan_mode.hidden_ssid_report = MTRUE;
505             }
506             else
507             {
508                 pscan_chan_list[chan_idx].chan_scan_mode.passive_scan = MFALSE;
509             }
510 
511             pscan_chan_list[chan_idx].chan_number = (t_u8)cfp->channel;
512 
513 #if defined(RW610) || defined(SD9177)
514             wscan_d("Channel: %d Type: %s %d", cfp->channel,
515                     scan_type == MLAN_SCAN_TYPE_PASSIVE           ? "Passive" :
516                     scan_type == MLAN_SCAN_TYPE_PASSIVE_TO_ACTIVE ? "PassiveToActive" :
517                                                                     "Active",
518                     cfp->max_tx_power);
519 #else
520             wscan_d("Channel: %d Type: %s %d", cfp->channel, scan_type == MLAN_SCAN_TYPE_PASSIVE ? "Passive" : "Active",
521                     cfp->max_tx_power);
522 #endif
523             chan_idx++;
524         }
525     }
526 
527     LEAVE();
528 }
529 
530 #if CONFIG_WPA_SUPP
531 #if CONFIG_WPA_SUPP_WPS
532 /**
533  *  @brief Add WPS IE to probe request frame
534  *
535  *  @param pmpriv             A pointer to mlan_private structure
536  *  @param pptlv_out          A pointer to TLV to fill in
537  *
538  *  @return                   N/A
539  */
wlan_add_wps_probe_request_ie(IN mlan_private * pmpriv,OUT t_u8 ** pptlv_out)540 static void wlan_add_wps_probe_request_ie(IN mlan_private *pmpriv, OUT t_u8 **pptlv_out)
541 {
542     MrvlIEtypesHeader_t *tlv;
543 
544     ENTER();
545 
546     if (pmpriv->wps.wps_ie.vend_hdr.len)
547     {
548         tlv       = (MrvlIEtypesHeader_t *)*pptlv_out;
549         tlv->type = wlan_cpu_to_le16(VENDOR_SPECIFIC_221);
550         tlv->len  = wlan_cpu_to_le16(pmpriv->wps.wps_ie.vend_hdr.len);
551         *pptlv_out += sizeof(MrvlIEtypesHeader_t);
552         (void)__memcpy(pmpriv->adapter, *pptlv_out, pmpriv->wps.wps_ie.vend_hdr.oui, pmpriv->wps.wps_ie.vend_hdr.len);
553         *pptlv_out += (pmpriv->wps.wps_ie.vend_hdr.len + sizeof(MrvlIEtypesHeader_t));
554         *pptlv_out += pmpriv->wps.wps_ie.vend_hdr.len;
555     }
556     LEAVE();
557 }
558 #endif
559 
560 /**
561  *  @brief Add IE to probe request frame
562  *
563  *  @param pmpriv             A pointer to mlan_private structure
564  *  @param pptlv_out          A pointer to TLV to fill in
565  *
566  *  @return                   N/A
567  */
wlan_add_probe_request_ie(IN mlan_private * pmpriv,OUT t_u8 ** pptlv_out)568 static void wlan_add_probe_request_ie(IN mlan_private *pmpriv, OUT t_u8 **pptlv_out)
569 {
570     MrvlIEtypesHeader_t *tlv;
571     t_u8 *ies                     = MNULL;
572     t_u8 ies_len                  = 0;
573     t_u32 bytes_left              = 0;
574     t_u8 *pcurrent_ptr            = MNULL;
575     IEEEtypes_Header_t *pieee_hdr = MNULL;
576 
577     ENTER();
578 
579     if (pmpriv->default_scan_ies_len != 0)
580     {
581         ies     = pmpriv->default_scan_ies;
582         ies_len = pmpriv->default_scan_ies_len;
583     }
584     else if (pmpriv->gen_ie_buf_len != 0)
585     {
586         ies     = pmpriv->gen_ie_buf;
587         ies_len = pmpriv->gen_ie_buf_len;
588     }
589     else
590     {
591         return;
592     }
593 
594     bytes_left   = ies_len;
595     pcurrent_ptr = ies;
596 
597     while (bytes_left >= sizeof(IEEEtypes_Header_t))
598     {
599         pieee_hdr = (IEEEtypes_Header_t *)pcurrent_ptr;
600 
601         if (pieee_hdr->element_id == EXT_CAPABILITY)
602         {
603             goto skip;
604         }
605 
606         tlv       = (MrvlIEtypesHeader_t *)*pptlv_out;
607         tlv->type = wlan_cpu_to_le16(pieee_hdr->element_id);
608         tlv->len  = wlan_cpu_to_le16(pieee_hdr->len);
609         *pptlv_out += sizeof(MrvlIEtypesHeader_t);
610         (void)__memcpy(pmpriv->adapter, *pptlv_out, pcurrent_ptr + sizeof(IEEEtypes_Header_t), pieee_hdr->len);
611         *pptlv_out += pieee_hdr->len;
612 
613     skip:
614         pcurrent_ptr += pieee_hdr->len + sizeof(IEEEtypes_Header_t);
615         bytes_left -= pieee_hdr->len + sizeof(IEEEtypes_Header_t);
616     }
617 
618     LEAVE();
619 }
620 #endif
621 
622 /**
623  *  @brief Construct and send multiple scan config commands to the firmware
624  *
625  *  Previous routines have created a wlan_scan_cmd_config with any requested
626  *   TLVs.  This function splits the channel TLV into max_chan_per_scan lists
627  *   and sends the portion of the channel TLV along with the other TLVs
628  *   to the wlan_cmd routines for execution in the firmware.
629  *
630  *  @param pmpriv             A pointer to mlan_private structure
631  *  @param pioctl_buf         A pointer to MLAN IOCTL Request buffer
632  *  @param max_chan_per_scan  Maximum number channels to be included in each
633  *                            scan command sent to firmware
634  *  @param filtered_scan      Flag indicating whether or not a BSSID or SSID
635  *                            filter is being used for the firmware command
636  *                            scan command sent to firmware
637  *  @param pscan_cfg_out      Scan configuration used for this scan.
638  *  @param pchan_tlv_out      Pointer in the pscan_cfg_out where the channel TLV
639  *                            should start.  This is past any other TLVs that
640  *                            must be sent down in each firmware command.
641  *  @param pscan_chan_list    List of channels to scan in max_chan_per_scan segments
642  *
643  *  @return                   MLAN_STATUS_SUCCESS or error return otherwise
644  */
wlan_scan_channel_list(IN mlan_private * pmpriv,IN t_void * pioctl_buf,IN t_u32 max_chan_per_scan,IN t_u8 filtered_scan,OUT wlan_scan_cmd_config * pscan_cfg_out,OUT MrvlIEtypes_ChanListParamSet_t * pchan_tlv_out,IN ChanScanParamSet_t * pscan_chan_list)645 static mlan_status wlan_scan_channel_list(IN mlan_private *pmpriv,
646                                           IN t_void *pioctl_buf,
647                                           IN t_u32 max_chan_per_scan,
648                                           IN t_u8 filtered_scan,
649                                           OUT wlan_scan_cmd_config *pscan_cfg_out,
650                                           OUT MrvlIEtypes_ChanListParamSet_t *pchan_tlv_out,
651                                           IN ChanScanParamSet_t *pscan_chan_list)
652 {
653     mlan_status ret         = MLAN_STATUS_SUCCESS;
654     mlan_adapter *pmadapter = pmpriv->adapter;
655     MrvlIEtypes_ChanListParamSet_t *pchan_tlv_out_temp;
656     ChanScanParamSet_t *ptmp_chan_list;
657     ChanScanParamSet_t *pstart_chan;
658     pmlan_ioctl_req pioctl_req = (mlan_ioctl_req *)pioctl_buf;
659 
660     t_u32 tlv_idx;
661     t_u32 total_scan_time;
662     t_u32 done_early;
663     t_u32 cmd_no;
664 
665 #if CONFIG_11AX
666     MrvlIEtypes_Extension_t *phe_cap;
667     t_u16 len = 0;
668 #endif
669 
670     ENTER();
671 
672     if ((pscan_cfg_out == MNULL) || (pchan_tlv_out == MNULL) || (pscan_chan_list == MNULL))
673     {
674         PRINTM(MINFO, "Scan: Null detect: %p, %p, %p\n", pscan_cfg_out, pchan_tlv_out, pscan_chan_list);
675         if (pioctl_req != MNULL)
676         {
677             pioctl_req->status_code = MLAN_ERROR_CMD_SCAN_FAIL;
678         }
679         LEAVE();
680         return MLAN_STATUS_FAILURE;
681     }
682     if (!pscan_chan_list->chan_number)
683     {
684         PRINTM(MERROR, "Scan: No channel configured\n");
685         if (pioctl_req != MNULL)
686         {
687             pioctl_req->status_code = MLAN_ERROR_CMD_SCAN_FAIL;
688         }
689         LEAVE();
690         return MLAN_STATUS_FAILURE;
691     }
692 
693     pchan_tlv_out->header.type = wlan_cpu_to_le16(TLV_TYPE_CHANLIST);
694 
695     pchan_tlv_out_temp = pchan_tlv_out;
696 
697     /* Set the temp channel struct pointer to the start of the desired list */
698     ptmp_chan_list = pscan_chan_list;
699 
700 #if CONFIG_BG_SCAN
701     if (pmpriv->roaming_configured)
702     {
703         pmpriv->roaming_configured = MFALSE;
704         /* Cancel bg scan */
705         ret = wifi_stop_bgscan();
706         if (ret)
707             return MLAN_STATUS_FAILURE;
708     }
709 #endif
710 
711     /* Loop through the desired channel list, sending a new firmware scan
712        commands for each max_chan_per_scan channels (or for 1,6,11 individually
713        if configured accordingly) */
714     while (ptmp_chan_list->chan_number != 0U)
715     {
716         tlv_idx                   = 0;
717         total_scan_time           = 0;
718         pchan_tlv_out->header.len = 0;
719         pstart_chan               = ptmp_chan_list;
720         done_early                = MFALSE;
721 
722         t_u8 *ptlv_pos = (t_u8 *)pchan_tlv_out_temp;
723         MrvlIEtypes_RatesParamSet_t *prates_tlv;
724         t_u16 config_bands;
725         WLAN_802_11_RATES rates;
726         t_u32 rates_size;
727 
728         config_bands = pmpriv->config_bands;
729         if (pstart_chan->chan_number > MAX_CHANNELS_BG)
730         {
731             config_bands &= ~(BAND_B | BAND_G | BAND_GN
732 #if CONFIG_11AC
733                               | BAND_GAC
734 #endif
735 #if CONFIG_11AX
736                               | BAND_GAX
737 #endif
738             );
739         }
740         else
741         {
742 #if CONFIG_11AX
743             config_bands &= ~(BAND_AAX);
744 #endif
745         }
746 
747         config_bands = (pmpriv->bss_mode == MLAN_BSS_MODE_INFRA) ? config_bands : pmadapter->adhoc_start_band;
748 
749         /* Append rates tlv */
750         (void)__memset(pmadapter, rates, 0, sizeof(rates));
751         rates_size              = wlan_get_supported_rates(pmpriv, pmpriv->bss_mode, config_bands, rates);
752         prates_tlv              = (MrvlIEtypes_RatesParamSet_t *)ptlv_pos;
753         prates_tlv->header.type = wlan_cpu_to_le16(TLV_TYPE_RATES);
754         prates_tlv->header.len  = wlan_cpu_to_le16((t_u16)rates_size);
755 
756         if (rates_size != 0U && rates_size <= sizeof(prates_tlv->rates))
757         {
758             (void)__memcpy(pmadapter, prates_tlv->rates, rates, rates_size);
759         }
760 
761         ptlv_pos += sizeof(prates_tlv->header) + rates_size;
762         PRINTM(MINFO, "SCAN_CMD: Rates size = %d\n", rates_size);
763 
764 #if CONFIG_11AX
765         if (IS_FW_SUPPORT_11AX(pmadapter) && ((config_bands & BAND_GAX) || (config_bands & BAND_AAX)))
766         {
767             phe_cap = (MrvlIEtypes_Extension_t *)ptlv_pos;
768             len     = wlan_fill_he_cap_tlv(pmpriv, config_bands, phe_cap, MFALSE);
769             HEXDUMP("SCAN: HE_CAPABILITIES IE", (t_u8 *)phe_cap, len);
770             ptlv_pos += len;
771         }
772 #endif
773 
774         pchan_tlv_out              = (MrvlIEtypes_ChanListParamSet_t *)ptlv_pos;
775         pchan_tlv_out->header.type = wlan_cpu_to_le16(TLV_TYPE_CHANLIST);
776         pchan_tlv_out->header.len  = 0;
777 
778         /*
779          * Construct the Channel TLV for the scan command.  Continue to
780          * insert channel TLVs until:
781          *   - the tlv_idx hits the maximum configured per scan command
782          *   - the next channel to insert is 0 (end of desired channel list)
783          *   - done_early is set (controlling individual scanning of 1,6,11)
784          */
785         while (tlv_idx < max_chan_per_scan && ptmp_chan_list->chan_number && !done_early)
786         {
787             wscan_d("Scan: Chan(%3d), Radio(%d), Mode(%d,%d), Dur(%d)", ptmp_chan_list->chan_number,
788                     ptmp_chan_list->radio_type, ptmp_chan_list->chan_scan_mode.passive_scan,
789                     ptmp_chan_list->chan_scan_mode.disable_chan_filt, wlan_le16_to_cpu(ptmp_chan_list->max_scan_time));
790 
791             /* Copy the current channel TLV to the command being prepared */
792             (void)__memcpy(pmadapter, pchan_tlv_out->chan_scan_param + tlv_idx, ptmp_chan_list,
793                            sizeof(pchan_tlv_out->chan_scan_param));
794 
795             /* Increment the TLV header length by the size appended */
796             pchan_tlv_out->header.len += (t_u16)sizeof(pchan_tlv_out->chan_scan_param);
797 
798             /*
799              * The tlv buffer length is set to the number of bytes of the
800              *   between the channel tlv pointer and the start of the
801              *   tlv buffer.  This compensates for any TLVs that were appended
802              *   before the channel list.
803              */
804             pscan_cfg_out->tlv_buf_len = (t_u32)((t_u8 *)pchan_tlv_out - pscan_cfg_out->tlv_buf);
805 
806             /* Add the size of the channel tlv header and the data length */
807             pscan_cfg_out->tlv_buf_len += (sizeof(pchan_tlv_out->header) + pchan_tlv_out->header.len);
808 
809             /* Increment the index to the channel tlv we are constructing */
810             tlv_idx++;
811 
812             /* Count the total scan time per command */
813             total_scan_time += wlan_le16_to_cpu(ptmp_chan_list->max_scan_time);
814 
815             done_early = MFALSE;
816 
817             /* Stop the loop if the *current* channel is in the 1,6,11 set and
818                we are not filtering on a BSSID or SSID. */
819             if (!filtered_scan && (ptmp_chan_list->chan_number == 1U || ptmp_chan_list->chan_number == 6U ||
820                                    ptmp_chan_list->chan_number == 11U))
821             {
822                 done_early = MTRUE;
823             }
824 
825             /* Increment the tmp pointer to the next channel to be scanned */
826             ptmp_chan_list++;
827 
828             /* Stop the loop if the *next* channel is in the 1,6,11 set.  This
829                will cause it to be the only channel scanned on the next
830                interation */
831             if (!filtered_scan && (ptmp_chan_list->chan_number == 1U || ptmp_chan_list->chan_number == 6U ||
832                                    ptmp_chan_list->chan_number == 11U))
833             {
834                 done_early = MTRUE;
835             }
836 
837             /* Stop the loop if the *next* channel is 36. Get supported rates for 2G/5G channels seperately */
838             if (ptmp_chan_list->chan_number == 36)
839             {
840                 done_early = MTRUE;
841             }
842         }
843 
844         /* The total scan time should be less than scan command timeout value */
845         if (total_scan_time > MRVDRV_MAX_TOTAL_SCAN_TIME)
846         {
847             wscan_d("Total scan time %d ms is over limit (%d ms), scan skipped", total_scan_time,
848                     MRVDRV_MAX_TOTAL_SCAN_TIME);
849             if (pioctl_req != MNULL)
850             {
851                 pioctl_req->status_code = MLAN_ERROR_CMD_SCAN_FAIL;
852             }
853             ret = MLAN_STATUS_FAILURE;
854             break;
855         }
856 
857         pchan_tlv_out->header.len = wlan_cpu_to_le16(pchan_tlv_out->header.len);
858 
859         pmadapter->pscan_channels = pstart_chan;
860 
861         /* Do sleep confirm handshake if received sleep event.
862          * Fw will delay all events if handshake is not done
863          * yet after ps sleep event.
864          */
865         if (mlan_adap->ps_state == PS_STATE_PRE_SLEEP && split_scan_in_progress)
866         {
867             send_sleep_confirm_command((mlan_bss_type)WLAN_BSS_TYPE_STA);
868         }
869 
870         if (!ptmp_chan_list->chan_number)
871         {
872             /* wmsdk: Once we set this the response handling code can
873                send event to the WLC manager. Since the event is send
874                only after command response we can be sure that there
875                is no race condition */
876             split_scan_in_progress = false;
877         }
878 
879         /* Send the scan command to the firmware with the specified cfg */
880 #if CONFIG_EXT_SCAN_SUPPORT
881         if (pmadapter->ext_scan)
882         {
883             cmd_no = HostCmd_CMD_802_11_SCAN_EXT;
884         }
885         else
886 #endif
887         {
888             cmd_no = HostCmd_CMD_802_11_SCAN;
889         }
890         ret = wlan_prepare_cmd(pmpriv, (t_u16)cmd_no, HostCmd_ACT_GEN_SET, 0, pioctl_buf, pscan_cfg_out);
891         if (ret != MLAN_STATUS_SUCCESS)
892         {
893             break;
894         }
895 
896         if (pmpriv->media_connected == MTRUE)
897         {
898             OSA_TimeDelay((uint32_t)get_split_scan_delay_ms());
899         }
900 
901         if (abort_split_scan)
902         {
903 #if CONFIG_WPA_SUPP
904             BSSDescriptor_t *bss_entry = NULL;
905             int i;
906 #endif
907             abort_split_scan       = false;
908             split_scan_in_progress = false;
909 #if CONFIG_WPA_SUPP
910             for (i = 0; i < pmadapter->num_in_scan_table; i++)
911             {
912                 bss_entry = &pmadapter->pscan_table[i];
913                 if (bss_entry && bss_entry->ies != NULL)
914                 {
915                     OSA_MemoryFree(bss_entry->ies);
916                 }
917             }
918 
919             pmadapter->num_in_scan_table = 0;
920             ret                          = MLAN_STATUS_FAILURE;
921 #endif
922             break;
923         }
924     }
925 
926     LEAVE();
927 
928     if (ret != MLAN_STATUS_SUCCESS)
929     {
930         return MLAN_STATUS_FAILURE;
931     }
932 
933     return MLAN_STATUS_SUCCESS;
934 }
935 
936 /**
937  *  @brief Construct a wlan_scan_cmd_config structure to use in scan commands
938  *
939  *  Application layer or other functions can invoke wlan_scan_networks
940  *    with a scan configuration supplied in a wlan_ioctl_user_scan_cfg struct.
941  *    This structure is used as the basis of one or many wlan_scan_cmd_config
942  *    commands that are sent to the command processing module and sent to
943  *    firmware.
944  *
945  *  Create a wlan_scan_cmd_config based on the following user supplied
946  *    parameters (if present):
947  *             - SSID filter
948  *             - BSSID filter
949  *             - Number of Probes to be sent
950  *             - Channel list
951  *
952  *  If the SSID or BSSID filter is not present, disable/clear the filter.
953  *  If the number of probes is not set, use the adapter default setting
954  *  Qualify the channel
955  *
956  *  @param pmpriv              A pointer to mlan_private structure
957  *  @param puser_scan_in       MNULL or pointer to scan config parameters
958  *  @param pscan_cfg_out       Output parameter: Resulting scan configuration
959  *  @param ppchan_list_out     Output parameter: Pointer to the start of the
960  *                             channel TLV portion of the output scan config
961  *  @param pscan_chan_list     Output parameter: Pointer to the resulting
962  *                             channel list to scan
963  *  @param pmax_chan_per_scan  Output parameter: Number of channels to scan for
964  *                             each issuance of the firmware scan command
965  *  @param pfiltered_scan      Output parameter: Flag indicating whether or not
966  *                             a BSSID or SSID filter is being sent in the
967  *                             command to firmware. Used to increase the number
968  *                             of channels sent in a scan command and to
969  *                             disable the firmware channel scan filter.
970  *  @param pscan_current_only  Output parameter: Flag indicating whether or not
971  *                             we are only scanning our current active channel
972  *
973  *  @return                 MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
974  */
wlan_scan_setup_scan_config(IN mlan_private * pmpriv,IN const wlan_user_scan_cfg * puser_scan_in,OUT wlan_scan_cmd_config * pscan_cfg_out,OUT MrvlIEtypes_ChanListParamSet_t ** ppchan_list_out,OUT ChanScanParamSet_t * pscan_chan_list,OUT t_u8 * pmax_chan_per_scan,OUT t_u8 * pfiltered_scan,OUT t_u8 * pscan_current_only)975 static mlan_status wlan_scan_setup_scan_config(IN mlan_private *pmpriv,
976                                                IN const wlan_user_scan_cfg *puser_scan_in,
977                                                OUT wlan_scan_cmd_config *pscan_cfg_out,
978                                                OUT MrvlIEtypes_ChanListParamSet_t **ppchan_list_out,
979                                                OUT ChanScanParamSet_t *pscan_chan_list,
980                                                OUT t_u8 *pmax_chan_per_scan,
981                                                OUT t_u8 *pfiltered_scan,
982                                                OUT t_u8 *pscan_current_only)
983 {
984     mlan_adapter *pmadapter = pmpriv->adapter;
985     mlan_status ret         = MLAN_STATUS_SUCCESS;
986     MrvlIEtypes_NumProbes_t *pnum_probes_tlv;
987     MrvlIEtypes_WildCardSsIdParamSet_t *pwildcard_ssid_tlv;
988 #if CONFIG_EXT_SCAN_SUPPORT
989     MrvlIEtypes_Bssid_List_t *pbssid_tlv;
990 #endif
991 #if CONFIG_SCAN_WITH_RSSIFILTER
992     MrvlIEtypes_RssiThresholdParamSet_t *prssi_threshold_tlv;
993 #endif
994     const t_u8 zero_mac[MLAN_MAC_ADDR_LENGTH] = {0, 0, 0, 0, 0, 0};
995     t_u8 *ptlv_pos;
996     t_u32 num_probes;
997     t_u32 ssid_len;
998     t_u32 chan_idx;
999     mlan_scan_type scan_type;
1000     t_u16 scan_dur;
1001     t_u8 channel;
1002     t_u8 radio_type;
1003     t_u32 ssid_idx;
1004     t_u8 ssid_filter;
1005 #if CONFIG_SCAN_WITH_RSSIFILTER
1006     t_u8 rssi_threshold_enable;
1007     t_s16 rssi_threshold;
1008 #endif
1009     MrvlIETypes_HTCap_t *pht_cap;
1010 #if CONFIG_11AC
1011     MrvlIETypes_VHTCap_t *pvht_cap;
1012 #endif
1013 #if CONFIG_SCAN_CHANNEL_GAP
1014     MrvlIEtypes_ScanChanGap_t *pscan_gap_tlv;
1015 #endif
1016     ENTER();
1017 
1018     pmpriv->ssid_filter = MFALSE;
1019     (void)memset(&pmpriv->filter_ssid[0], 0x00, sizeof(pmpriv->filter_ssid));
1020 
1021     /* The tlv_buf_len is calculated for each scan command.  The TLVs added in
1022        this routine will be preserved since the routine that sends the command
1023        will append channelTLVs at *ppchan_list_out.  The difference between the
1024        *ppchan_list_out and the tlv_buf start will be used to calculate the
1025        size of anything we add in this routine. */
1026     pscan_cfg_out->tlv_buf_len = 0;
1027 
1028     /* Running tlv pointer.  Assigned to ppchan_list_out at end of function so
1029        later routines know where channels can be added to the command buf */
1030     ptlv_pos = pscan_cfg_out->tlv_buf;
1031 
1032     /* Initialize the scan as un-filtered; the flag is later set to TRUE below
1033        if a SSID or BSSID filter is sent in the command */
1034     *pfiltered_scan = MFALSE;
1035 
1036     /* Initialize the scan as not being only on the current channel.  If the
1037        channel list is customized, only contains one channel, and is the active
1038        channel, this is set true and data flow is not halted. */
1039     *pscan_current_only = MFALSE;
1040 
1041     if (puser_scan_in != MNULL)
1042     {
1043         ssid_filter = MFALSE;
1044 
1045         /* Set the bss type scan filter, use Adapter setting if unset */
1046         pscan_cfg_out->bss_mode =
1047             (puser_scan_in->bss_mode ? (t_u8)puser_scan_in->bss_mode : (t_u8)pmadapter->scan_mode);
1048 
1049         /* Set the number of probes to send, use Adapter setting if unset */
1050         num_probes = (puser_scan_in->num_probes ? puser_scan_in->num_probes : pmadapter->scan_probes);
1051 
1052 #if CONFIG_SCAN_WITH_RSSIFILTER
1053         /* Set the threshold value of rssi to send */
1054         rssi_threshold = puser_scan_in->rssi_threshold;
1055         /* Enable/Disable rssi threshold function */
1056         rssi_threshold_enable = (rssi_threshold < 0 ? MTRUE : MFALSE);
1057 #endif
1058         /*
1059          * Set the BSSID filter to the incoming configuration,
1060          *   if non-zero.  If not set, it will remain disabled (all zeros).
1061          */
1062         (void)__memcpy(pmadapter, pscan_cfg_out->specific_bssid, puser_scan_in->specific_bssid,
1063                        sizeof(pscan_cfg_out->specific_bssid));
1064 
1065 #if CONFIG_EXT_SCAN_SUPPORT
1066         if (pmadapter->ext_scan && __memcmp(pmadapter, pscan_cfg_out->specific_bssid, &zero_mac, sizeof(zero_mac)))
1067         {
1068             pbssid_tlv              = (MrvlIEtypes_Bssid_List_t *)ptlv_pos;
1069             pbssid_tlv->header.type = TLV_TYPE_BSSID;
1070             pbssid_tlv->header.len  = MLAN_MAC_ADDR_LENGTH;
1071             (void)__memcpy(pmadapter, pbssid_tlv->bssid, puser_scan_in->specific_bssid, MLAN_MAC_ADDR_LENGTH);
1072             ptlv_pos += sizeof(MrvlIEtypes_Bssid_List_t);
1073         }
1074 #endif
1075 
1076         for (ssid_idx = 0; ((ssid_idx < NELEMENTS(puser_scan_in->ssid_list)) &&
1077                             (*puser_scan_in->ssid_list[ssid_idx].ssid || puser_scan_in->ssid_list[ssid_idx].max_len));
1078              ssid_idx++)
1079         {
1080             ssid_len = wlan_strlen((const char *)puser_scan_in->ssid_list[ssid_idx].ssid);
1081 
1082             pwildcard_ssid_tlv                  = (MrvlIEtypes_WildCardSsIdParamSet_t *)(void *)ptlv_pos;
1083             pwildcard_ssid_tlv->header.type     = wlan_cpu_to_le16(TLV_TYPE_WILDCARDSSID);
1084             pwildcard_ssid_tlv->header.len      = (t_u16)(ssid_len + sizeof(pwildcard_ssid_tlv->max_ssid_length));
1085             pwildcard_ssid_tlv->max_ssid_length = puser_scan_in->ssid_list[ssid_idx].max_len;
1086 
1087             if ((ssid_len > 0) && (ssid_len <= MLAN_MAX_SSID_LENGTH))
1088             {
1089                 (void)__memcpy(pmadapter, pwildcard_ssid_tlv->ssid, puser_scan_in->ssid_list[ssid_idx].ssid,
1090                                MIN(MLAN_MAX_SSID_LENGTH, ssid_len));
1091             }
1092 
1093             ptlv_pos += (sizeof(pwildcard_ssid_tlv->header) + pwildcard_ssid_tlv->header.len);
1094 
1095             pwildcard_ssid_tlv->header.len = wlan_cpu_to_le16(pwildcard_ssid_tlv->header.len);
1096 
1097             PRINTM(MINFO, "Scan: ssid_list[%d]: %s, %d\n", ssid_idx, pwildcard_ssid_tlv->ssid,
1098                    pwildcard_ssid_tlv->max_ssid_length);
1099 
1100             if (ssid_len != 0U)
1101             {
1102                 ssid_filter = MTRUE;
1103                 (void)__memcpy(pmadapter, pmpriv->filter_ssid[ssid_idx].ssid, puser_scan_in->ssid_list[ssid_idx].ssid,
1104                                MIN(MLAN_MAX_SSID_LENGTH, ssid_len));
1105                 pmpriv->filter_ssid[ssid_idx].ssid_len = ssid_len;
1106             }
1107         }
1108 
1109         /*
1110          *  The default number of channels sent in the command is low to
1111          *    ensure the response buffer from the firmware does not truncate
1112          *    scan results.  That is not an issue with an SSID or BSSID
1113          *    filter applied to the scan results in the firmware.
1114          */
1115         if ((ssid_idx && ssid_filter) ||
1116             __memcmp(pmadapter, pscan_cfg_out->specific_bssid, &zero_mac, sizeof(zero_mac)))
1117         {
1118             if (ssid_filter)
1119             {
1120                 pmpriv->ssid_filter = ssid_filter;
1121             }
1122             *pfiltered_scan = MTRUE;
1123         }
1124     }
1125     else
1126     {
1127         pscan_cfg_out->bss_mode = (t_u8)pmadapter->scan_mode;
1128         num_probes              = pmadapter->scan_probes;
1129 #if CONFIG_SCAN_WITH_RSSIFILTER
1130         rssi_threshold        = 0;
1131         rssi_threshold_enable = 0;
1132 #endif
1133     }
1134 
1135     /*
1136      *  If a specific BSSID or SSID is used, the number of channels in the
1137      *  scan command will be increased to the absolute maximum.
1138      */
1139     if (*pfiltered_scan == MTRUE)
1140     {
1141         *pmax_chan_per_scan = MRVDRV_MAX_CHANNELS_PER_SPECIFIC_SCAN;
1142     }
1143     else
1144     {
1145         *pmax_chan_per_scan = MRVDRV_CHANNELS_PER_SCAN_CMD;
1146     }
1147 #if CONFIG_SCAN_CHANNEL_GAP
1148     if (puser_scan_in)
1149     {
1150         if (puser_scan_in->scan_chan_gap)
1151         {
1152             *pmax_chan_per_scan = MRVDRV_MAX_CHANNELS_PER_SPECIFIC_SCAN;
1153             PRINTM(MCMND, "Scan: channel gap = 0x%x\n", puser_scan_in->scan_chan_gap);
1154             pscan_gap_tlv              = (MrvlIEtypes_ScanChanGap_t *)ptlv_pos;
1155             pscan_gap_tlv->header.type = wlan_cpu_to_le16(TLV_TYPE_SCAN_CHANNEL_GAP);
1156             pscan_gap_tlv->header.len  = sizeof(pscan_gap_tlv->gap);
1157             pscan_gap_tlv->gap         = wlan_cpu_to_le16((t_u16)puser_scan_in->scan_chan_gap);
1158             ptlv_pos += sizeof(pscan_gap_tlv->header) + pscan_gap_tlv->header.len;
1159             pscan_gap_tlv->header.len = wlan_cpu_to_le16(pscan_gap_tlv->header.len);
1160         }
1161     }
1162     else if (pmadapter->scan_chan_gap)
1163     {
1164         *pmax_chan_per_scan = MRVDRV_MAX_CHANNELS_PER_SPECIFIC_SCAN;
1165         PRINTM(MCMND, "Scan: channel gap = 0x%x\n", pmadapter->scan_chan_gap);
1166         pscan_gap_tlv              = (MrvlIEtypes_ScanChanGap_t *)ptlv_pos;
1167         pscan_gap_tlv->header.type = wlan_cpu_to_le16(TLV_TYPE_SCAN_CHANNEL_GAP);
1168         pscan_gap_tlv->header.len  = sizeof(pscan_gap_tlv->gap);
1169         pscan_gap_tlv->gap         = wlan_cpu_to_le16((t_u16)pmadapter->scan_chan_gap);
1170         ptlv_pos += sizeof(pscan_gap_tlv->header) + pscan_gap_tlv->header.len;
1171         pscan_gap_tlv->header.len = wlan_cpu_to_le16(pscan_gap_tlv->header.len);
1172     }
1173 #endif
1174     /* If the input config or adapter has the number of Probes set, add tlv */
1175     if (num_probes != 0U)
1176     {
1177         PRINTM(MINFO, "Scan: num_probes = %d\n", num_probes);
1178 
1179         pnum_probes_tlv              = (MrvlIEtypes_NumProbes_t *)(void *)ptlv_pos;
1180         pnum_probes_tlv->header.type = wlan_cpu_to_le16(TLV_TYPE_NUMPROBES);
1181         pnum_probes_tlv->header.len  = (t_u16)sizeof(pnum_probes_tlv->num_probes);
1182         pnum_probes_tlv->num_probes  = wlan_cpu_to_le16((t_u16)num_probes);
1183 
1184         ptlv_pos += sizeof(pnum_probes_tlv->header) + pnum_probes_tlv->header.len;
1185 
1186         pnum_probes_tlv->header.len = wlan_cpu_to_le16(pnum_probes_tlv->header.len);
1187     }
1188 
1189     if (ISSUPP_11NENABLED(pmpriv->adapter->fw_cap_info) &&
1190         (pmpriv->config_bands & BAND_GN || pmpriv->config_bands & BAND_AN) && wmsdk_is_11N_enabled())
1191     {
1192         pht_cap = (MrvlIETypes_HTCap_t *)(void *)ptlv_pos;
1193         (void)__memset(pmadapter, pht_cap, 0, sizeof(MrvlIETypes_HTCap_t));
1194         pht_cap->header.type = wlan_cpu_to_le16(HT_CAPABILITY);
1195         pht_cap->header.len  = (t_u16)sizeof(HTCap_t);
1196         wlan_fill_ht_cap_tlv(pmpriv, pht_cap, pmpriv->config_bands);
1197         HEXDUMP("SCAN: HT_CAPABILITIES IE", (t_u8 *)pht_cap, sizeof(MrvlIETypes_HTCap_t));
1198         ptlv_pos += sizeof(MrvlIETypes_HTCap_t);
1199         pht_cap->header.len = wlan_cpu_to_le16(pht_cap->header.len);
1200     }
1201 
1202 #if CONFIG_11AC
1203     if (ISSUPP_11ACENABLED(pmpriv->adapter->fw_cap_info) && (pmpriv->config_bands & BAND_AAC))
1204     {
1205         pvht_cap = (MrvlIETypes_VHTCap_t *)(void *)ptlv_pos;
1206         (void)__memset(pmadapter, pvht_cap, 0, sizeof(MrvlIETypes_VHTCap_t));
1207         pvht_cap->header.type = wlan_cpu_to_le16(VHT_CAPABILITY);
1208         pvht_cap->header.len  = (t_u16)sizeof(VHT_capa_t);
1209         wlan_fill_vht_cap_tlv(pmpriv, pvht_cap, pmpriv->config_bands, MFALSE);
1210         HEXDUMP("SCAN: VHT_CAPABILITIES IE", (t_u8 *)pvht_cap, sizeof(MrvlIETypes_VHTCap_t));
1211         ptlv_pos += sizeof(MrvlIETypes_VHTCap_t);
1212         pvht_cap->header.len = wlan_cpu_to_le16(pvht_cap->header.len);
1213     }
1214 #endif
1215 
1216 #if CONFIG_SCAN_WITH_RSSIFILTER
1217     /*
1218      * Append rssi threshold tlv
1219      *
1220      * Note: According to the value of rssi_threshold, it is divided into three situations:
1221      *     rssi_threshold  |  rssi_threshold_enable  |  Whether to carry TLV
1222      *           <0        |          MTRUE          |          Yes
1223      *            0        |          MFALSE         |          No
1224      *           >0        |          MFALSE         |          Yes
1225      */
1226     if (rssi_threshold)
1227     {
1228         prssi_threshold_tlv              = (MrvlIEtypes_RssiThresholdParamSet_t *)ptlv_pos;
1229         prssi_threshold_tlv->header.type = wlan_cpu_to_le16(TLV_TYPE_RSSI_THRESHOLD);
1230         prssi_threshold_tlv->header.len =
1231             (t_u16)(sizeof(prssi_threshold_tlv->enable) + sizeof(prssi_threshold_tlv->rssi_threshold) +
1232                     sizeof(prssi_threshold_tlv->reserved));
1233         prssi_threshold_tlv->enable         = rssi_threshold_enable;
1234         prssi_threshold_tlv->rssi_threshold = rssi_threshold;
1235 
1236         ptlv_pos += sizeof(prssi_threshold_tlv->header) + prssi_threshold_tlv->header.len;
1237 
1238         prssi_threshold_tlv->header.len = wlan_cpu_to_le16(prssi_threshold_tlv->header.len);
1239 
1240         pmadapter->rssi_threshold = (rssi_threshold < 0 ? rssi_threshold : 0);
1241 
1242         PRINTM(MINFO, "SCAN_CMD: Rssi threshold = %d\n", rssi_threshold);
1243     }
1244 #endif
1245 
1246 #if CONFIG_WPA_SUPP
1247 #if CONFIG_WPA_SUPP_WPS
1248     wlan_add_wps_probe_request_ie(pmpriv, &ptlv_pos);
1249 #endif
1250     wlan_add_probe_request_ie(pmpriv, &ptlv_pos);
1251 #endif
1252 
1253 #if (CONFIG_DRIVER_MBO) || (CONFIG_WPA_SUPP)
1254     wlan_add_ext_capa_info_ie(pmpriv, NULL, &ptlv_pos);
1255 #endif
1256 
1257     /*
1258      * Set the output for the channel TLV to the address in the tlv buffer
1259      *   past any TLVs that were added in this function (SSID, num_probes).
1260      *   Channel TLVs will be added past this for each scan command, preserving
1261      *   the TLVs that were previously added.
1262      */
1263     *ppchan_list_out = (MrvlIEtypes_ChanListParamSet_t *)(void *)ptlv_pos;
1264 
1265     if ((puser_scan_in != MNULL) && puser_scan_in->chan_list[0].chan_number)
1266     {
1267         PRINTM(MINFO, "Scan: Using supplied channel list\n");
1268 
1269         for (chan_idx = 0; chan_idx < WLAN_USER_SCAN_CHAN_MAX && puser_scan_in->chan_list[chan_idx].chan_number;
1270              chan_idx++)
1271         {
1272             radio_type = puser_scan_in->chan_list[chan_idx].radio_type;
1273             if (!wlan_is_band_compatible(pmpriv->config_bands, radio_type_to_band(radio_type)))
1274             {
1275                 continue;
1276             }
1277 
1278             channel                                   = puser_scan_in->chan_list[chan_idx].chan_number;
1279             (pscan_chan_list + chan_idx)->chan_number = channel;
1280 
1281             (pscan_chan_list + chan_idx)->radio_type = radio_type;
1282 
1283             scan_type = puser_scan_in->chan_list[chan_idx].scan_type;
1284             if (scan_type == MLAN_SCAN_TYPE_UNCHANGED)
1285             {
1286                 scan_type = pmadapter->scan_type;
1287             }
1288 
1289             if (radio_type == HostCmd_SCAN_RADIO_TYPE_A)
1290             {
1291                 if ((pmadapter->fw_bands & BAND_A) != 0U)
1292                 {
1293                     PRINTM(MINFO, "UserScan request for A Band channel %d!!\n", channel);
1294                 }
1295                 else
1296                 {
1297                     PRINTM(MERROR, "Scan in A band is not allowed!!\n");
1298                     ret = MLAN_STATUS_FAILURE;
1299                     LEAVE();
1300                     return ret;
1301                 }
1302             }
1303 
1304             if (pmadapter->active_scan_triggered == MFALSE)
1305             {
1306                 /* Prevent active scanning on a radar controlled channel */
1307 #if CONFIG_5GHz_SUPPORT
1308                 if (radio_type == HostCmd_SCAN_RADIO_TYPE_A)
1309                 {
1310                     if (wlan_11h_radar_detect_required(pmpriv, channel))
1311                     {
1312                         /* Skip DFS channels if required */
1313                         if (pmadapter->skip_dfs)
1314                             continue;
1315 #if defined(RW610) || defined(SD9177)
1316                         scan_type = MLAN_SCAN_TYPE_PASSIVE_TO_ACTIVE;
1317 #else
1318                         scan_type = MLAN_SCAN_TYPE_PASSIVE;
1319 #endif
1320                     }
1321                 }
1322 #endif
1323                 if (radio_type == HostCmd_SCAN_RADIO_TYPE_BG)
1324                 {
1325                     if (wlan_bg_scan_type_is_passive(pmpriv, channel))
1326                     {
1327                         scan_type = MLAN_SCAN_TYPE_PASSIVE;
1328                     }
1329                 }
1330             }
1331 #if defined(RW610) || defined(SD9177)
1332             if (scan_type == MLAN_SCAN_TYPE_PASSIVE || scan_type == MLAN_SCAN_TYPE_PASSIVE_TO_ACTIVE)
1333 #else
1334             if (scan_type == MLAN_SCAN_TYPE_PASSIVE)
1335 #endif
1336             {
1337                 (pscan_chan_list + chan_idx)->chan_scan_mode.passive_scan       = MTRUE;
1338                 (pscan_chan_list + chan_idx)->chan_scan_mode.hidden_ssid_report = MTRUE;
1339             }
1340             else
1341             {
1342                 (pscan_chan_list + chan_idx)->chan_scan_mode.passive_scan = MFALSE;
1343             }
1344 
1345             if (puser_scan_in->chan_list[chan_idx].scan_time != 0U)
1346             {
1347                 scan_dur = (t_u16)puser_scan_in->chan_list[chan_idx].scan_time;
1348             }
1349             else
1350             {
1351 #if defined(RW610) || defined(SD9177)
1352                 if (scan_type == MLAN_SCAN_TYPE_PASSIVE || scan_type == MLAN_SCAN_TYPE_PASSIVE_TO_ACTIVE)
1353 #else
1354                 if (scan_type == MLAN_SCAN_TYPE_PASSIVE)
1355 #endif
1356                 {
1357                     scan_dur = pmadapter->passive_scan_time;
1358                 }
1359                 else if (*pfiltered_scan == MTRUE)
1360                 {
1361                     scan_dur = pmadapter->specific_scan_time;
1362                 }
1363                 else
1364                 {
1365                     scan_dur = pmadapter->active_scan_time;
1366                 }
1367             }
1368 
1369 #if defined(RW610) || defined(SD9177)
1370             if (scan_type == MLAN_SCAN_TYPE_PASSIVE_TO_ACTIVE)
1371             {
1372                 (pscan_chan_list + chan_idx)->chan_scan_mode.passive_to_active_scan = MTRUE;
1373                 scan_dur = MAX(MIN_PASSIVE_TO_ACTIVE_SCAN_TIME, scan_dur);
1374             }
1375 #endif
1376             (pscan_chan_list + chan_idx)->min_scan_time = wlan_cpu_to_le16(scan_dur);
1377             (pscan_chan_list + chan_idx)->max_scan_time = wlan_cpu_to_le16(scan_dur);
1378 
1379 #if defined(RW610) || defined(SD9177)
1380             wscan_d("Channel: %d Type: %s ", channel,
1381                     scan_type == MLAN_SCAN_TYPE_PASSIVE           ? "Passive" :
1382                     scan_type == MLAN_SCAN_TYPE_PASSIVE_TO_ACTIVE ? "PassiveToActive" :
1383                                                                     "Active");
1384 #else
1385             wscan_d("Channel: %d Type: %s ", channel, scan_type == MLAN_SCAN_TYPE_PASSIVE ? "Passive" : "Active");
1386 #endif
1387         }
1388 
1389         /* Check if we are only scanning the current channel */
1390         if ((chan_idx == 1U) &&
1391             (puser_scan_in->chan_list[0].chan_number == pmpriv->curr_bss_params.bss_descriptor.channel))
1392         {
1393             *pscan_current_only = MTRUE;
1394             PRINTM(MINFO, "Scan: Scanning current channel only\n");
1395         }
1396     }
1397     else
1398     {
1399         PRINTM(MINFO, "Scan: Creating full region channel list\n");
1400         wlan_scan_create_channel_list(pmpriv, puser_scan_in, pscan_chan_list, *pfiltered_scan);
1401     }
1402 
1403     LEAVE();
1404     return ret;
1405 }
1406 
1407 #if (CONFIG_WPS2) || (CONFIG_WPA_SUPP_WPS)
1408 void check_for_wps_ie(const uint8_t *poui,
1409                       t_u8 oui_type,
1410                       bool *wps_IE_exist,
1411                       t_u16 *wps_session,
1412                       void *element_data,
1413                       unsigned element_len);
1414 #endif /* CONFIG_WPA_SUPP_WPS */
1415 
1416 /**
1417  *  @brief Interpret a BSS scan response returned from the firmware
1418  *
1419  *  Parse the various fixed fields and IEs passed back for a BSS probe
1420  *   response or beacon from the scan command.  Record information as needed
1421  *   in the scan table BSSDescriptor_t for that entry.
1422  *
1423  *  @param pmadapter    A pointer to mlan_adapter structure
1424  *  @param pbss_entry   Output parameter: Pointer to the BSS Entry
1425  *  @param pbeacon_info Pointer to the Beacon information
1426  *  @param bytes_left   Number of bytes left to parse
1427  *
1428  *  @return             MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
1429  */
wlan_interpret_bss_desc_with_ie(IN pmlan_adapter pmadapter,OUT BSSDescriptor_t * pbss_entry,IN t_u8 ** pbeacon_info,IN t_u32 * bytes_left,IN t_u8 ext_scan)1430 static mlan_status wlan_interpret_bss_desc_with_ie(IN pmlan_adapter pmadapter,
1431                                                    OUT BSSDescriptor_t *pbss_entry,
1432                                                    IN t_u8 **pbeacon_info,
1433                                                    IN t_u32 *bytes_left,
1434                                                    IN t_u8 ext_scan)
1435 {
1436     mlan_status ret = MLAN_STATUS_SUCCESS;
1437     IEEEtypes_ElementId_e element_id;
1438     IEEEtypes_FhParamSet_t *pfh_param_set;
1439     IEEEtypes_DsParamSet_t *pds_param_set;
1440     IEEEtypes_DtimParamSet_t *pdtim_param_set;
1441     IEEEtypes_CfParamSet_t *pcf_param_set;
1442     IEEEtypes_IbssParamSet_t *pibss_param_set;
1443     IEEEtypes_CapInfo_t *pcap_info;
1444     WLAN_802_11_FIXED_IEs fixed_ie;
1445     t_u8 *pcurrent_ptr;
1446     t_u8 *prate;
1447     t_u8 element_len;
1448     t_u16 total_ie_len;
1449     t_u8 bytes_to_copy;
1450     t_u8 rate_size;
1451     t_u16 beacon_size;
1452     t_u8 found_data_rate_ie;
1453     t_u32 bytes_left_for_current_beacon;
1454     /* IEEEtypes_ERPInfo_t *perp_info; */
1455 
1456     IEEEtypes_VendorSpecific_t *pvendor_ie;
1457     const t_u8 wpa_oui[3]       = {0x00, 0x50, 0xf2};
1458     const t_u8 wpa_type[1]      = {0x01};
1459     const t_u8 wmm_oui[3]       = {0x00, 0x50, 0xf2};
1460     const t_u8 wmm_type[1]      = {0x02};
1461     const t_u8 brcm_oui[3]      = {0x00, 0x10, 0x18};
1462     const t_u8 brcm_type[1]     = {0x02};
1463     const t_u8 epigram_oui[3]   = {0x00, 0x90, 0x4c};
1464     const t_u8 epigram_type1[1] = {0x33};
1465     const t_u8 epigram_type2[1] = {0x34};
1466 
1467 #if CONFIG_DRIVER_OWE
1468     const t_u8 owe_oui[3]  = {0x50, 0x6f, 0x9a};
1469     const t_u8 owe_type[1] = {0x01c};
1470 #endif
1471 #if CONFIG_DRIVER_MBO
1472     const t_u8 scan_mbo_oui[3]  = {0x50, 0x6f, 0x9a};
1473     const t_u8 scan_mbo_type[1] = {0x016};
1474 #endif
1475 
1476     IEEEtypes_CountryInfoSet_t *pcountry_info;
1477 #if CONFIG_11AX
1478     IEEEtypes_Extension_t *pext_tlv;
1479 #endif
1480 
1481     ENTER();
1482 
1483     found_data_rate_ie = MFALSE;
1484     rate_size          = 0;
1485     beacon_size        = 0;
1486 
1487     if (*bytes_left >= sizeof(beacon_size))
1488     {
1489         /* Extract & convert beacon size from the command buffer */
1490         (void)__memcpy(pmadapter, &beacon_size, *pbeacon_info, sizeof(beacon_size));
1491         beacon_size = wlan_le16_to_cpu(beacon_size);
1492         *bytes_left -= sizeof(beacon_size);
1493         *pbeacon_info += sizeof(beacon_size);
1494     }
1495 
1496     if (!beacon_size || beacon_size > *bytes_left)
1497     {
1498         *pbeacon_info += *bytes_left;
1499         *bytes_left = 0;
1500 
1501         LEAVE();
1502         return MLAN_STATUS_FAILURE;
1503     }
1504 
1505     /* Initialize the current working beacon pointer for this BSS iteration */
1506     pcurrent_ptr = *pbeacon_info;
1507 
1508     /* Advance the return beacon pointer past the current beacon */
1509     *pbeacon_info += beacon_size;
1510     *bytes_left -= beacon_size;
1511 
1512     bytes_left_for_current_beacon = beacon_size;
1513 
1514     if (bytes_left_for_current_beacon < (MLAN_MAC_ADDR_LENGTH + sizeof(t_u8) + sizeof(WLAN_802_11_FIXED_IEs)))
1515     {
1516         PRINTM(MERROR, "InterpretIE: Not enough bytes left\n");
1517         LEAVE();
1518         return MLAN_STATUS_FAILURE;
1519     }
1520 
1521     (void)__memcpy(pmadapter, pbss_entry->mac_address, pcurrent_ptr, MLAN_MAC_ADDR_LENGTH);
1522     wifi_d("InterpretIE: AP MAC Addr-%02x:%02x:%02x:%02x:%02x:%02x", pbss_entry->mac_address[0],
1523            pbss_entry->mac_address[1], pbss_entry->mac_address[2], pbss_entry->mac_address[3],
1524            pbss_entry->mac_address[4], pbss_entry->mac_address[5]);
1525 
1526     pcurrent_ptr += MLAN_MAC_ADDR_LENGTH;
1527     bytes_left_for_current_beacon -= MLAN_MAC_ADDR_LENGTH;
1528 
1529     /*
1530      * Next 4 fields are RSSI (for legacy scan only), time stamp,
1531      *   beacon interval, and capability information
1532      */
1533 #if CONFIG_EXT_SCAN_SUPPORT
1534     if (ext_scan == (t_u8)0U)
1535     {
1536 #endif
1537         /* RSSI is 1 byte long */
1538         pbss_entry->rssi = (t_s32)(*pcurrent_ptr);
1539         PRINTM(MINFO, "InterpretIE: RSSI=%02X\n", *pcurrent_ptr);
1540         pcurrent_ptr += 1;
1541         bytes_left_for_current_beacon -= 1U;
1542 #if CONFIG_EXT_SCAN_SUPPORT
1543     }
1544 #endif
1545 
1546     /*
1547      *  The RSSI is not part of the beacon/probe response.  After we have
1548      *    advanced pcurrent_ptr past the RSSI field, save the remaining
1549      *    data for use at the application layer
1550      */
1551     pbss_entry->pbeacon_buf     = pcurrent_ptr;
1552     pbss_entry->beacon_buf_size = bytes_left_for_current_beacon;
1553 
1554     (void)__memcpy(pmadapter, pbss_entry->time_stamp, pcurrent_ptr, 8);
1555 
1556     pbss_entry->scan_result_tsf = (OSA_TimeGetMsec() * 1000);
1557 
1558     pcurrent_ptr += 8;
1559     bytes_left_for_current_beacon -= 8U;
1560 
1561     /* Beacon interval is 2 bytes long */
1562     (void)__memcpy(pmadapter, &fixed_ie.beacon_interval, pcurrent_ptr, 2);
1563     pbss_entry->beacon_period = wlan_le16_to_cpu(fixed_ie.beacon_interval);
1564     pcurrent_ptr += 2;
1565     bytes_left_for_current_beacon -= 2U;
1566 
1567     /* Capability information is 2 bytes long */
1568     (void)__memcpy(pmadapter, &fixed_ie.capabilities, pcurrent_ptr, 2);
1569     PRINTM(MINFO, "InterpretIE: fixed_ie.capabilities=0x%X\n", fixed_ie.capabilities);
1570     fixed_ie.capabilities = wlan_le16_to_cpu(fixed_ie.capabilities);
1571     pcap_info             = (IEEEtypes_CapInfo_t *)(void *)&fixed_ie.capabilities;
1572     (void)__memcpy(pmadapter, &pbss_entry->cap_info, pcap_info, sizeof(IEEEtypes_CapInfo_t));
1573     pcurrent_ptr += 2;
1574     bytes_left_for_current_beacon -= 2U;
1575 
1576     /* Rest of the current buffer are IE's */
1577     wifi_d("InterpretIE: IELength for this AP = %d", bytes_left_for_current_beacon);
1578 
1579     HEXDUMP("InterpretIE: IE info", (t_u8 *)pcurrent_ptr, bytes_left_for_current_beacon);
1580 
1581 #if CONFIG_WPA_SUPP
1582     /* Store IE pointer and len for wpa supplicant scan result, no need to process each IE below*/
1583     if (pmadapter->wpa_supp_scan_triggered == MTRUE)
1584     {
1585         wifi_d("Alloc ies for BSS");
1586         pbss_entry->ies = (u8 *)OSA_MemoryAllocate(bytes_left_for_current_beacon);
1587         if (pbss_entry->ies == MNULL)
1588         {
1589             wifi_d("Failed to alloc memory for BSS ies");
1590             return MLAN_STATUS_FAILURE;
1591         }
1592         (void)__memcpy(pmadapter, pbss_entry->ies, (t_u8 *)pcurrent_ptr, bytes_left_for_current_beacon);
1593         pbss_entry->ies_len = bytes_left_for_current_beacon;
1594     }
1595 #endif
1596 
1597     if (pcap_info->privacy == MTRUE)
1598     {
1599         PRINTM(MINFO, "InterpretIE: AP WEP enabled\n");
1600         pbss_entry->privacy = (t_u32)Wlan802_11PrivFilter8021xWEP;
1601     }
1602     else
1603     {
1604         pbss_entry->privacy = (t_u32)Wlan802_11PrivFilterAcceptAll;
1605     }
1606 
1607     if (pcap_info->ibss == 1U)
1608     {
1609         pbss_entry->bss_mode = MLAN_BSS_MODE_IBSS;
1610     }
1611     else
1612     {
1613         pbss_entry->bss_mode = MLAN_BSS_MODE_INFRA;
1614     }
1615 
1616     /* Process variable IE */
1617     while (bytes_left_for_current_beacon >= 2U)
1618     {
1619         element_id   = (IEEEtypes_ElementId_e)(*((t_u8 *)pcurrent_ptr));
1620         element_len  = *((t_u8 *)pcurrent_ptr + 1);
1621         total_ie_len = (t_u16)(element_len + sizeof(IEEEtypes_Header_t));
1622 
1623         if (bytes_left_for_current_beacon < total_ie_len)
1624         {
1625             PRINTM(MERROR,
1626                    "InterpretIE: Error in processing IE, "
1627                    "bytes left < IE length\n");
1628             bytes_left_for_current_beacon = 0;
1629             continue;
1630         }
1631 
1632         switch (element_id)
1633         {
1634             case SSID:
1635                 if (element_len > MRVDRV_MAX_SSID_LENGTH)
1636                 {
1637                     bytes_left_for_current_beacon = 0;
1638                     continue;
1639                 }
1640                 pbss_entry->ssid.ssid_len = element_len;
1641                 (void)__memcpy(pmadapter, pbss_entry->ssid.ssid, (pcurrent_ptr + 2), element_len);
1642                 wscan_d("AP: %s", pbss_entry->ssid.ssid);
1643                 PRINTM(MINFO, "InterpretIE: ssid: %-32s\n", pbss_entry->ssid.ssid);
1644                 break;
1645 
1646             case SUPPORTED_RATES:
1647                 if (element_len > WLAN_SUPPORTED_RATES)
1648                 {
1649                     bytes_left_for_current_beacon = 0;
1650                     continue;
1651                 }
1652                 (void)__memcpy(pmadapter, pbss_entry->data_rates, pcurrent_ptr + 2, element_len);
1653                 (void)__memcpy(pmadapter, pbss_entry->supported_rates, pcurrent_ptr + 2, element_len);
1654                 HEXDUMP("InterpretIE: SupportedRates:", pbss_entry->supported_rates, element_len);
1655                 rate_size          = element_len;
1656                 found_data_rate_ie = MTRUE;
1657                 break;
1658 
1659             case FH_PARAM_SET:
1660                 pfh_param_set                = (IEEEtypes_FhParamSet_t *)(void *)pcurrent_ptr;
1661                 pbss_entry->network_type_use = Wlan802_11FH;
1662                 (void)__memcpy(pmadapter, &pbss_entry->phy_param_set.fh_param_set, pfh_param_set,
1663                                MIN(total_ie_len, sizeof(IEEEtypes_FhParamSet_t)));
1664                 pbss_entry->phy_param_set.fh_param_set.len =
1665                     MIN(element_len, (sizeof(IEEEtypes_FhParamSet_t) - sizeof(IEEEtypes_Header_t)));
1666                 pbss_entry->phy_param_set.fh_param_set.dwell_time =
1667                     wlan_le16_to_cpu(pbss_entry->phy_param_set.fh_param_set.dwell_time);
1668                 break;
1669 
1670             case DS_PARAM_SET:
1671                 pds_param_set = (IEEEtypes_DsParamSet_t *)(void *)pcurrent_ptr;
1672 
1673                 pbss_entry->network_type_use = Wlan802_11DS;
1674                 pbss_entry->channel          = pds_param_set->current_chan;
1675 
1676                 (void)__memcpy(pmadapter, &pbss_entry->phy_param_set.ds_param_set, pds_param_set,
1677                                MIN(total_ie_len, sizeof(IEEEtypes_DsParamSet_t)));
1678                 pbss_entry->phy_param_set.ds_param_set.len =
1679                     MIN(element_len, (sizeof(IEEEtypes_DsParamSet_t) - sizeof(IEEEtypes_Header_t)));
1680                 break;
1681 
1682             case CF_PARAM_SET:
1683                 pcf_param_set = (IEEEtypes_CfParamSet_t *)(void *)pcurrent_ptr;
1684                 (void)__memcpy(pmadapter, &pbss_entry->ss_param_set.cf_param_set, pcf_param_set,
1685                                MIN(total_ie_len, sizeof(IEEEtypes_CfParamSet_t)));
1686                 pbss_entry->ss_param_set.cf_param_set.len =
1687                     MIN(element_len, (sizeof(IEEEtypes_CfParamSet_t) - sizeof(IEEEtypes_Header_t)));
1688                 break;
1689 
1690             case DTIM_PARAM_SET:
1691                 pdtim_param_set = (IEEEtypes_DtimParamSet_t *)(void *)pcurrent_ptr;
1692 
1693                 pbss_entry->dtim_period = pdtim_param_set->dtim_period;
1694                 break;
1695 
1696             case IBSS_PARAM_SET:
1697                 pibss_param_set         = (IEEEtypes_IbssParamSet_t *)(void *)pcurrent_ptr;
1698                 pbss_entry->atim_window = wlan_le16_to_cpu(pibss_param_set->atim_window);
1699                 (void)__memcpy(pmadapter, &pbss_entry->ss_param_set.ibss_param_set, pibss_param_set,
1700                                MIN(total_ie_len, sizeof(IEEEtypes_IbssParamSet_t)));
1701                 pbss_entry->ss_param_set.ibss_param_set.len =
1702                     MIN(element_len, (sizeof(IEEEtypes_IbssParamSet_t) - sizeof(IEEEtypes_Header_t)));
1703                 break;
1704 
1705                 /* Handle Country Info IE */
1706             case COUNTRY_INFO:
1707                 /* Disabling this because IEEEtypes_CountryInfoSet_t size
1708                    is 254 bytes. Check later if can be optimized */
1709                 pcountry_info = (IEEEtypes_CountryInfoSet_t *)(void *)pcurrent_ptr;
1710 
1711                 if (pcountry_info->len < sizeof(pcountry_info->country_code) ||
1712                     (unsigned)(pcountry_info->len + 2) > sizeof(IEEEtypes_CountryInfoFullSet_t))
1713                 {
1714                     PRINTM(MERROR,
1715                            "InterpretIE: 11D- Err "
1716                            "country_info len =%d min=%d max=%d\n",
1717                            pcountry_info->len, sizeof(pcountry_info->country_code),
1718                            sizeof(IEEEtypes_CountryInfoFullSet_t));
1719                     LEAVE();
1720                     return MLAN_STATUS_FAILURE;
1721                 }
1722 
1723                 (void)__memcpy(pmadapter, &pbss_entry->country_info, pcountry_info, pcountry_info->len + 2);
1724                 HEXDUMP("InterpretIE: 11D- country_info:", (t_u8 *)pcountry_info, (t_u32)(pcountry_info->len + 2));
1725                 break;
1726             case POWER_CONSTRAINT:
1727             case POWER_CAPABILITY:
1728             case TPC_REPORT:
1729             case CHANNEL_SWITCH_ANN:
1730             case QUIET:
1731             case IBSS_DFS:
1732             case SUPPORTED_CHANNELS:
1733             case TPC_REQUEST:
1734                 /* fixme: Not enabled yet */
1735                 /* wlan_11h_process_bss_elem(pmadapter, &pbss_entry->wlan_11h_bss_info, */
1736                 /*                       pcurrent_ptr); */
1737                 break;
1738             case EXTENDED_SUPPORTED_RATES:
1739                 /*
1740                  * Only process extended supported rate
1741                  * if data rate is already found.
1742                  * Data rate IE should come before
1743                  * extended supported rate IE
1744                  */
1745                 if (found_data_rate_ie == MTRUE)
1746                 {
1747                     if ((element_len + rate_size) > WLAN_SUPPORTED_RATES)
1748                     {
1749                         bytes_to_copy = (WLAN_SUPPORTED_RATES - rate_size);
1750                     }
1751                     else
1752                     {
1753                         bytes_to_copy = element_len;
1754                     }
1755 
1756                     prate = (t_u8 *)pbss_entry->data_rates;
1757                     prate += rate_size;
1758                     (void)__memcpy(pmadapter, prate, pcurrent_ptr + 2, bytes_to_copy);
1759 
1760                     prate = (t_u8 *)pbss_entry->supported_rates;
1761                     prate += rate_size;
1762                     (void)__memcpy(pmadapter, prate, pcurrent_ptr + 2, bytes_to_copy);
1763                 }
1764                 HEXDUMP("InterpretIE: ExtSupportedRates:", pbss_entry->supported_rates, element_len + rate_size);
1765                 break;
1766 
1767             case VENDOR_SPECIFIC_221:
1768                 pvendor_ie = (IEEEtypes_VendorSpecific_t *)(void *)pcurrent_ptr;
1769 
1770                 if ((__memcmp(pmadapter, pvendor_ie->vend_hdr.oui, wpa_oui, sizeof(wpa_oui))) == 0 &&
1771                     (pvendor_ie->vend_hdr.oui_type == wpa_type[0]))
1772                 {
1773                     /* Save it here since we do not have beacon buffer */
1774                     /* fixme : Verify if this is the right approach. This had to be
1775                        done because IEEEtypes_Rsn_t was not the correct data
1776                        structure to map here  */
1777                     if (element_len <= (sizeof(pbss_entry->wpa_ie_buff) - sizeof(IEEEtypes_Header_t)))
1778                     {
1779                         (void)__memcpy(NULL, pbss_entry->wpa_ie_buff, pcurrent_ptr,
1780                                        element_len + sizeof(IEEEtypes_Header_t));
1781                         pbss_entry->pwpa_ie         = (IEEEtypes_VendorSpecific_t *)(void *)pbss_entry->wpa_ie_buff;
1782                         pbss_entry->wpa_ie_buff_len = element_len + sizeof(IEEEtypes_Header_t);
1783 
1784                         if (wifi_check_bss_entry_wpa2_entp_only(pbss_entry, VENDOR_SPECIFIC_221) != MLAN_STATUS_SUCCESS)
1785                         {
1786                             return MLAN_STATUS_RESOURCE;
1787                         }
1788                     }
1789                     else
1790                     {
1791                         wifi_e("Insufficient space to save WPA_IE size: %d", element_len);
1792                     }
1793 
1794                     /* pbss_entry->pwpa_ie = */
1795                     /*     (IEEEtypes_VendorSpecific_t *) pcurrent_ptr; */
1796                     /* pbss_entry->wpa_offset = */
1797                     /*     (t_u16) (pcurrent_ptr - pbss_entry->pbeacon_buf); */
1798                     HEXDUMP("InterpretIE: Resp WPA_IE", (t_u8 *)pbss_entry->pwpa_ie,
1799                             ((*(pbss_entry->pwpa_ie)).vend_hdr.len + sizeof(IEEEtypes_Header_t)));
1800                 }
1801                 else if ((__memcmp(pmadapter, pvendor_ie->vend_hdr.oui, wmm_oui, sizeof(wmm_oui))) == 0 &&
1802                          (pvendor_ie->vend_hdr.oui_type == wmm_type[0]))
1803                 {
1804                     if (total_ie_len == sizeof(IEEEtypes_WmmParameter_t) || total_ie_len == sizeof(IEEEtypes_WmmInfo_t))
1805                     {
1806                         /*
1807                          * Only accept and copy the WMM IE if it matches
1808                          * the size expected for the WMM Info IE or the
1809                          * WMM Parameter IE.
1810                          */
1811                         (void)__memcpy(pmadapter, (t_u8 *)&pbss_entry->wmm_ie, pcurrent_ptr, total_ie_len);
1812                         HEXDUMP("InterpretIE: Resp WMM_IE", (t_u8 *)&pbss_entry->wmm_ie, total_ie_len);
1813                     }
1814                 }
1815                 else if ((__memcmp(pmadapter, pvendor_ie->vend_hdr.oui, brcm_oui, sizeof(brcm_oui))) == 0 &&
1816                          (pvendor_ie->vend_hdr.oui_type == brcm_type[0]))
1817                 {
1818                     pbss_entry->brcm_ie_exist = 1;
1819                 }
1820                 else if ((__memcmp(pmadapter, pvendor_ie->vend_hdr.oui, epigram_oui, sizeof(epigram_oui))) == 0 &&
1821                          (pvendor_ie->vend_hdr.oui_type == epigram_type1[0] ||
1822                           pvendor_ie->vend_hdr.oui_type == epigram_type2[0]))
1823                 {
1824                     pbss_entry->epigram_ie_exist = 1;
1825                 }
1826 #if CONFIG_DRIVER_OWE
1827                 else if (IS_FW_SUPPORT_EMBEDDED_OWE(pmadapter) &&
1828                          (!__memcmp(pmadapter, pvendor_ie->vend_hdr.oui, owe_oui, sizeof(owe_oui)) &&
1829                           (pvendor_ie->vend_hdr.oui_type == owe_type[0])))
1830                 {
1831                     /* Current Format of OWE IE is element_id:element_len:oui:MAC Address:SSID length:SSID */
1832                     t_u8 trans_ssid_len =
1833                         *(pcurrent_ptr + sizeof(IEEEtypes_Header_t) + sizeof(owe_oui) + sizeof(owe_type) + MLAN_MAC_ADDR_LENGTH);
1834 
1835                     if (!trans_ssid_len || trans_ssid_len > MRVDRV_MAX_SSID_LENGTH)
1836                     {
1837                         bytes_left_for_current_beacon = 0;
1838                         continue;
1839                     }
1840                     if (!pcap_info->privacy)
1841                     {
1842                         pbss_entry->owe_transition_mode = OWE_TRANS_MODE_OPEN;
1843                     }
1844                     else
1845                     {
1846                         pbss_entry->owe_transition_mode = OWE_TRANS_MODE_OWE;
1847                     }
1848 
1849                     (void)__memcpy(pmadapter, pbss_entry->trans_mac_address,
1850                                    (pcurrent_ptr + sizeof(IEEEtypes_Header_t) + sizeof(owe_oui) + sizeof(owe_type)), MLAN_MAC_ADDR_LENGTH);
1851                     pbss_entry->trans_ssid.ssid_len = trans_ssid_len;
1852                     (void)__memcpy(pmadapter, pbss_entry->trans_ssid.ssid,
1853                                    (pcurrent_ptr + sizeof(IEEEtypes_Header_t) + sizeof(owe_oui) + sizeof(owe_type) + MLAN_MAC_ADDR_LENGTH +
1854                                     sizeof(t_u8)),
1855                                    trans_ssid_len);
1856 
1857                     PRINTM(MCMND, "InterpretIE: OWE Transition AP privacy=%d MAC Addr-" MACSTR " ssid %s\n",
1858                            pbss_entry->owe_transition_mode, MAC2STR(pbss_entry->trans_mac_address),
1859                            pbss_entry->trans_ssid.ssid);
1860                 }
1861 #endif
1862 #if CONFIG_DRIVER_MBO
1863                 else if (__memcmp(pmadapter, pvendor_ie->vend_hdr.oui, scan_mbo_oui, sizeof(scan_mbo_oui)) == 0 &&
1864                          (pvendor_ie->vend_hdr.oui_type == scan_mbo_type[0]))
1865                 {
1866                     t_u8 *pcurrent_attr = pcurrent_ptr + MBO_IE_HEADER_LEN;
1867                     t_u8 mbo_attr_id;
1868                     t_u8 mbo_attr_len = 0;
1869                     t_u8 mbo_cur_len  = MBO_IE_HEADER_LEN - sizeof(IEEEtypes_Header_t);
1870 
1871                     pbss_entry->mbo_assoc_disallowed = false;
1872 
1873                     while (mbo_cur_len < element_len)
1874                     {
1875                         mbo_attr_id  = *((t_u8 *)pcurrent_attr);
1876                         mbo_attr_len = *((t_u8 *)pcurrent_attr + 1);
1877 
1878                         if (mbo_attr_id == 0x4U)
1879                         {
1880                             pbss_entry->mbo_assoc_disallowed = true;
1881                         }
1882 
1883                         mbo_cur_len += (t_u8)MBO_ATTR_HEADER_LEN + mbo_attr_len;
1884                         pcurrent_attr = pcurrent_attr + MBO_ATTR_HEADER_LEN + mbo_attr_len;
1885                     }
1886                 }
1887 #endif
1888 #if CONFIG_11K
1889                 /* Voice Enterprise Test Plan V1.2, test case 5.4, store other vendor specific ie */
1890                 else
1891                 {
1892                     if (pbss_entry->vendor_ie_len + element_len + (t_u8)sizeof(IEEEtypes_Header_t) <
1893                         (t_u8)sizeof(pbss_entry->vendor_ie_buff))
1894                     {
1895                         (void)__memcpy(pmadapter, pbss_entry->vendor_ie_buff + pbss_entry->vendor_ie_len, pcurrent_ptr,
1896                                        element_len + sizeof(IEEEtypes_Header_t));
1897                         pbss_entry->vendor_ie_len += element_len + (t_u8)sizeof(IEEEtypes_Header_t);
1898                     }
1899                 }
1900 #else
1901                 else
1902                 {
1903                     /* Do Nothing */
1904                 }
1905 #endif
1906 
1907 #if (CONFIG_WPS2) || (CONFIG_WPA_SUPP_WPS)
1908                 /* fixme: Added for WMSDK. Check if can be merged properly with
1909                    mlan. There should be a better way */
1910                 check_for_wps_ie(pvendor_ie->vend_hdr.oui, pvendor_ie->vend_hdr.oui_type, &pbss_entry->wps_IE_exist,
1911                                  &pbss_entry->wps_session, pcurrent_ptr + 2, element_len);
1912 #endif /* CONFIG_WPA_SUPP_WPS */
1913                 break;
1914             case RSN_IE:
1915                 /* Save it here since we do not have beacon buffer */
1916                 /* fixme : Verify if this is the right approach. This had to be
1917                    done because IEEEtypes_Rsn_t was not the correct data
1918                    structure to map here  */
1919                 if (element_len <= (sizeof(pbss_entry->rsn_ie_buff) - sizeof(IEEEtypes_Header_t)))
1920                 {
1921                     (void)__memcpy(NULL, pbss_entry->rsn_ie_buff, pcurrent_ptr,
1922                                    element_len + sizeof(IEEEtypes_Header_t));
1923                     pbss_entry->rsn_ie_buff_len = element_len + sizeof(IEEEtypes_Header_t);
1924                     pbss_entry->prsn_ie         = (IEEEtypes_Generic_t *)(void *)pbss_entry->rsn_ie_buff;
1925 
1926                     if (wifi_check_bss_entry_wpa2_entp_only(pbss_entry, RSN_IE) != MLAN_STATUS_SUCCESS)
1927                     {
1928                         return MLAN_STATUS_RESOURCE;
1929                     }
1930                 }
1931                 else
1932                 {
1933                     wifi_e("Insufficient space to save RSN_IE size: %d", element_len);
1934                 }
1935 
1936                 /* pbss_entry->prsn_ie = (IEEEtypes_Generic_t *) pcurrent_ptr; */
1937                 /* pbss_entry->rsn_offset = */
1938                 /*     (t_u16) (pcurrent_ptr - pbss_entry->pbeacon_buf); */
1939                 HEXDUMP("InterpretIE: Resp RSN_IE", (t_u8 *)pbss_entry->prsn_ie,
1940                         (*(pbss_entry->prsn_ie)).ieee_hdr.len + sizeof(IEEEtypes_Header_t));
1941                 break;
1942 #if (CONFIG_11R) || (CONFIG_11K)
1943             case MOBILITY_DOMAIN:
1944                 if (element_len <= (sizeof(pbss_entry->md_ie_buff) - sizeof(IEEEtypes_Header_t)))
1945                 {
1946                     (void)__memcpy(NULL, pbss_entry->md_ie_buff, pcurrent_ptr,
1947                                    element_len + sizeof(IEEEtypes_Header_t));
1948                     pbss_entry->md_ie_buff_len   = element_len + sizeof(IEEEtypes_Header_t);
1949                     pbss_entry->pmd_ie           = (IEEEtypes_MobilityDomain_t *)(void *)pbss_entry->md_ie_buff;
1950                     pbss_entry->mob_domain_exist = 1;
1951                     /* dump_hex(pbss_entry->pmd_ie, pbss_entry->md_ie_buff_len); */
1952                 }
1953                 else
1954                 {
1955                     wifi_e("Insufficient space to save MD_IE size: %d", element_len);
1956                 }
1957                 break;
1958 #endif
1959 #if CONFIG_11K
1960             case RRM_ENABLED_CAP:
1961                 /* Save it here since we do not have beacon buffer */
1962                 (void)__memcpy(NULL, &pbss_entry->rm_cap_saved, pcurrent_ptr, sizeof(IEEEtypes_RrmElement_t));
1963                 pbss_entry->rm_cap_exist = 1;
1964                 break;
1965 #endif
1966             case WAPI_IE:
1967                 break;
1968 #if CONFIG_MULTI_BSSID_SUPPORT
1969             case MULTI_BSSID:
1970                 if (IS_FW_SUPPORT_MULTIBSSID(pmadapter))
1971                 {
1972                     pbss_entry->multi_bssid_ap = MULTI_BSSID_AP;
1973                     HEXDUMP("InterpretIE: Multi BSSID IE", (t_u8 *)pcurrent_ptr, total_ie_len);
1974                 }
1975                 break;
1976 #endif
1977             case HT_CAPABILITY:
1978                 /* Save it here since we do not have beacon buffer */
1979                 (void)__memcpy(NULL, &pbss_entry->ht_cap_saved, pcurrent_ptr, sizeof(IEEEtypes_HTCap_t));
1980                 pbss_entry->pht_cap = &pbss_entry->ht_cap_saved;
1981                 /* pbss_entry->pht_cap = (IEEEtypes_HTCap_t *) pcurrent_ptr; */
1982                 /* pbss_entry->ht_cap_offset = */
1983                 /*     (t_u16) (pcurrent_ptr - pbss_entry->pbeacon_buf); */
1984                 HEXDUMP("InterpretIE: Resp HTCAP_IE", (t_u8 *)pbss_entry->pht_cap,
1985                         (*(pbss_entry->pht_cap)).ieee_hdr.len + sizeof(IEEEtypes_Header_t));
1986                 break;
1987             case HT_OPERATION:
1988                 /* Save it here since we do not have beacon buffer */
1989                 (void)__memcpy(NULL, &pbss_entry->ht_info_saved, pcurrent_ptr, sizeof(IEEEtypes_HTInfo_t));
1990                 pbss_entry->pht_info = &pbss_entry->ht_info_saved;
1991                 /* pbss_entry->pht_info = (IEEEtypes_HTInfo_t *) pcurrent_ptr; */
1992                 /* pbss_entry->ht_info_offset = */
1993                 /*     (t_u16) (pcurrent_ptr - pbss_entry->pbeacon_buf); */
1994                 HEXDUMP("InterpretIE: Resp HTINFO_IE", (t_u8 *)pbss_entry->pht_info,
1995                         (*(pbss_entry->pht_info)).ieee_hdr.len + sizeof(IEEEtypes_Header_t));
1996                 break;
1997             case BSSCO_2040:
1998                 /* Save it here since we do not have beacon buffer */
1999                 (void)__memcpy(NULL, &pbss_entry->bss_co_2040_saved, pcurrent_ptr, sizeof(IEEEtypes_2040BSSCo_t));
2000                 pbss_entry->pbss_co_2040 = &pbss_entry->bss_co_2040_saved;
2001                 /* pbss_entry->pbss_co_2040 = (IEEEtypes_2040BSSCo_t *) pcurrent_ptr; */
2002                 /* pbss_entry->bss_co_2040_offset = */
2003                 /*     (t_u16) (pcurrent_ptr - pbss_entry->pbeacon_buf); */
2004                 HEXDUMP("InterpretIE: Resp 2040BSSCOEXISTANCE_IE", (t_u8 *)pbss_entry->pbss_co_2040,
2005                         (*(pbss_entry->pbss_co_2040)).ieee_hdr.len + sizeof(IEEEtypes_Header_t));
2006                 break;
2007 #if CONFIG_11AC
2008             case VHT_CAPABILITY:
2009                 /* Save it here since we do not have beacon buffer */
2010                 (void)__memcpy(NULL, &pbss_entry->vht_cap_saved, pcurrent_ptr, sizeof(IEEEtypes_VHTCap_t));
2011                 pbss_entry->pvht_cap = &pbss_entry->vht_cap_saved;
2012                 break;
2013             case VHT_OPERATION:
2014                 /* Save it here since we do not have beacon buffer */
2015                 (void)__memcpy(NULL, &pbss_entry->vht_oprat_saved, pcurrent_ptr, sizeof(IEEEtypes_VHTOprat_t));
2016                 pbss_entry->pvht_oprat = &pbss_entry->vht_oprat_saved;
2017                 break;
2018             case VHT_TX_POWER_ENV:
2019                 /* Save it here since we do not have beacon buffer */
2020                 (void)__memcpy(NULL, &pbss_entry->vht_txpower_saved, pcurrent_ptr, sizeof(IEEEtypes_VHTtxpower_t));
2021                 pbss_entry->pvht_txpower = &pbss_entry->vht_txpower_saved;
2022                 break;
2023             case OPER_MODE_NTF:
2024                 /* Save it here since we do not have beacon buffer */
2025                 (void)__memcpy(NULL, &pbss_entry->poper_mode_saved, pcurrent_ptr, sizeof(IEEEtypes_OperModeNtf_t));
2026                 pbss_entry->ppoper_mode = &pbss_entry->poper_mode_saved;
2027                 break;
2028 #endif
2029             case EXT_CAPABILITY:
2030                 /* Save it here since we do not have beacon buffer */
2031                 (void)__memcpy(NULL, &pbss_entry->ext_cap_saved, pcurrent_ptr, sizeof(IEEEtypes_ExtCap_t));
2032                 pbss_entry->pext_cap = &pbss_entry->ext_cap_saved;
2033                 break;
2034 #if CONFIG_11AX
2035             case EXTENSION:
2036                 pext_tlv = (IEEEtypes_Extension_t *)pcurrent_ptr;
2037                 switch (pext_tlv->ext_id)
2038                 {
2039                     case HE_CAPABILITY:
2040                         /* Save it here since we do not have beacon buffer */
2041                         (void)__memcpy(NULL, &pbss_entry->he_cap_saved, pcurrent_ptr, sizeof(IEEEtypes_HECap_t));
2042                         pbss_entry->phe_cap = &pbss_entry->he_cap_saved;
2043                         break;
2044                     case HE_OPERATION:
2045                         /* Save it here since we do not have beacon buffer */
2046                         (void)__memcpy(NULL, &pbss_entry->he_oprat_saved, pcurrent_ptr, MIN(total_ie_len, sizeof(IEEEtypes_HeOp_t)));
2047                         pbss_entry->phe_oprat = &pbss_entry->he_oprat_saved;
2048                         break;
2049                     default:
2050                         PRINTM(MINFO, "Unexpected extension id\n");
2051                         break;
2052                 }
2053                 break;
2054 #endif
2055             case RSNX_IE:
2056                 (void)__memcpy(NULL, &pbss_entry->rsnx_ie_saved, pcurrent_ptr, sizeof(pbss_entry->rsnx_ie_saved));
2057                 pbss_entry->prsnx_ie = &pbss_entry->rsnx_ie_saved;
2058                 wscan_d("RSNX_IE: tag len %d data 0x%02x", pbss_entry->prsnx_ie->ieee_hdr.len,
2059                         pbss_entry->prsnx_ie->data[0]);
2060                 break;
2061 
2062             default:
2063                 PRINTM(MINFO, "Unexpected IE \n");
2064                 break;
2065         }
2066 
2067         pcurrent_ptr += element_len + 2U;
2068 
2069         /* Need to account for IE ID and IE Len */
2070         bytes_left_for_current_beacon -= (element_len + 2U);
2071 
2072     } /* while (bytes_left_for_current_beacon > 2) */
2073 
2074     if (wifi_check_bss_entry_wpa2_entp_only(pbss_entry, SSID) != MLAN_STATUS_SUCCESS)
2075     {
2076         return MLAN_STATUS_RESOURCE;
2077     }
2078 
2079     LEAVE();
2080     return ret;
2081 }
2082 
2083 #if CONFIG_SCAN_CHANNEL_GAP
2084 /**
2085  *  @brief get the chan load from chan stats.
2086  *
2087  *  @param pmadapter    A pointer to mlan_adapter structure
2088  *  @param channel      channel  *
2089  *
2090  *  @return             channel load
2091  */
wlan_get_chan_load(mlan_adapter * pmadapter,t_u8 channel)2092 static t_u16 wlan_get_chan_load(mlan_adapter *pmadapter, t_u8 channel)
2093 {
2094     t_u16 chan_load = 0;
2095     int i;
2096     for (i = 0; i < (int)pmadapter->num_in_chan_stats; i++)
2097     {
2098         if ((pmadapter->pchan_stats[i].chan_num == channel) && pmadapter->pchan_stats[i].cca_scan_duration)
2099         {
2100             chan_load =
2101                 (pmadapter->pchan_stats[i].cca_busy_duration * 100) / pmadapter->pchan_stats[i].cca_scan_duration;
2102             break;
2103         }
2104     }
2105     return chan_load;
2106 }
2107 
wlan_get_chan_noise(mlan_adapter * pmadapter,t_u8 channel)2108 static t_u16 wlan_get_chan_noise(mlan_adapter *pmadapter, t_u8 channel)
2109 {
2110     t_u16 chan_noise = 0;
2111     int i;
2112     for (i = 0; i < (int)pmadapter->num_in_chan_stats; i++)
2113     {
2114         if ((pmadapter->pchan_stats[i].chan_num == channel) && pmadapter->pchan_stats[i].noise)
2115         {
2116             chan_noise = pmadapter->pchan_stats[i].noise;
2117             break;
2118         }
2119     }
2120     return chan_noise;
2121 }
2122 
2123 /**
2124  *  @brief get the chan min/max rssi
2125  *
2126  *  @param pmadapter    A pointer to mlan_adapter structure
2127  *  @param channel      channel  *
2128  *  @param min_flag     flag to get min rssi
2129  *  @return             rssi
2130  */
wlan_get_chan_rssi(mlan_adapter * pmadapter,t_u8 channel,t_u8 min_flag)2131 static t_u8 wlan_get_chan_rssi(mlan_adapter *pmadapter, t_u8 channel, t_u8 min_flag)
2132 {
2133     t_u8 rssi = 0;
2134     int i;
2135     for (i = 0; i < (int)pmadapter->num_in_scan_table; i++)
2136     {
2137         if (pmadapter->pscan_table[i].channel == channel)
2138         {
2139             if (rssi == 0)
2140                 rssi = (t_s32)pmadapter->pscan_table[i].rssi;
2141             else
2142             {
2143                 if (min_flag)
2144                     rssi = MIN(rssi, pmadapter->pscan_table[i].rssi);
2145                 else
2146                     rssi = MAX(rssi, pmadapter->pscan_table[i].rssi);
2147             }
2148         }
2149     }
2150     return rssi;
2151 }
2152 
2153 /**
2154  *  @brief update the min/max rssi for channel statistics.
2155  *
2156  *  @param pmadapter    A pointer to mlan_adapter structure
2157  *	@return             N/A
2158  */
wlan_update_chan_rssi(mlan_adapter * pmadapter)2159 static t_void wlan_update_chan_rssi(mlan_adapter *pmadapter)
2160 {
2161     int i;
2162     t_s8 min_rssi = 0;
2163     t_s8 max_rssi = 0;
2164     t_s8 rss      = 0;
2165     for (i = 0; i < (int)pmadapter->num_in_chan_stats; i++)
2166     {
2167         if (pmadapter->pchan_stats[i].chan_num && pmadapter->pchan_stats[i].cca_scan_duration)
2168         {
2169             min_rssi = -wlan_get_chan_rssi(pmadapter, pmadapter->pchan_stats[i].chan_num, MFALSE);
2170             max_rssi = -wlan_get_chan_rssi(pmadapter, pmadapter->pchan_stats[i].chan_num, MTRUE);
2171             rss      = min_rssi - pmadapter->pchan_stats[i].noise;
2172             // rss should always > 0, FW need fix the wrong
2173             // rssi/noise in scantable
2174             if (rss > 0)
2175                 pmadapter->pchan_stats[i].min_rss = rss;
2176             else
2177                 pmadapter->pchan_stats[i].min_rss = 0;
2178 
2179             rss = max_rssi - pmadapter->pchan_stats[i].noise;
2180             if (rss > 0)
2181                 pmadapter->pchan_stats[i].max_rss = rss;
2182             else
2183                 pmadapter->pchan_stats[i].max_rss = 0;
2184             PRINTM(MCMND, "chan=%d, min_rssi=%d, max_rssi=%d noise=%d min_rss=%d, max_rss=%d\n",
2185                    pmadapter->pchan_stats[i].chan_num, min_rssi, max_rssi, pmadapter->pchan_stats[i].noise,
2186                    pmadapter->pchan_stats[i].min_rss, pmadapter->pchan_stats[i].max_rss);
2187         }
2188     }
2189     return;
2190 }
2191 #endif
2192 
2193 /**
2194  *  @brief Post process the scan table after a new scan command has completed
2195  *
2196  *  Inspect each entry of the scan table and try to find an entry that
2197  *    matches our current associated/joined network from the scan.  If
2198  *    one is found, update the stored copy of the BSSDescriptor for our
2199  *    current network.
2200  *
2201  *  Debug dump the current scan table contents if compiled accordingly.
2202  *
2203  *  @param pmpriv       A pointer to mlan_private structure
2204  *
2205  *  @return             N/A
2206  */
wlan_scan_process_results(IN mlan_private * pmpriv)2207 /* static */ void wlan_scan_process_results(IN mlan_private *pmpriv)
2208 {
2209     mlan_adapter *pmadapter = pmpriv->adapter;
2210     t_u32 i;
2211 
2212     for (i = 0; i < pmadapter->num_in_scan_table; i++)
2213     {
2214         PRINTM(MINFO,
2215                "Scan:(%02d) %02x:%02x:%02x:%02x:%02x:%02x, "
2216                "RSSI[%03d], SSID[%s]\n",
2217                i, pmadapter->pscan_table[i].mac_address[0], pmadapter->pscan_table[i].mac_address[1],
2218                pmadapter->pscan_table[i].mac_address[2], pmadapter->pscan_table[i].mac_address[3],
2219                pmadapter->pscan_table[i].mac_address[4], pmadapter->pscan_table[i].mac_address[5],
2220                (t_s32)pmadapter->pscan_table[i].rssi, pmadapter->pscan_table[i].ssid.ssid);
2221 #if CONFIG_SCAN_CHANNEL_GAP
2222         pmadapter->pscan_table[i].chan_load  = wlan_get_chan_load(pmadapter, pmadapter->pscan_table[i].channel);
2223         pmadapter->pscan_table[i].chan_noise = wlan_get_chan_noise(pmadapter, pmadapter->pscan_table[i].channel);
2224 #endif
2225     }
2226 #if CONFIG_SCAN_CHANNEL_GAP
2227     wlan_update_chan_rssi(pmadapter);
2228 #endif
2229     /*
2230      * Prepares domain info from scan table and downloads the
2231      *   domain info command to the FW.
2232      */
2233     if (wlan_11d_support_is_enabled(pmpriv))
2234     {
2235         if (pmpriv->support_11d != NULL)
2236         {
2237             (void)pmpriv->support_11d->wlan_11d_prepare_dnld_domain_info_cmd_p(pmpriv);
2238         }
2239     }
2240 
2241     LEAVE();
2242 }
2243 
2244 /********************************************************
2245                 Global Functions
2246 ********************************************************/
2247 
2248 /**
2249  *  @brief Check if a scanned network compatible with the driver settings
2250  *
2251  *   WEP     WPA     WPA2    ad-hoc  encrypt                      Network
2252  * enabled enabled  enabled   AES     mode   Privacy  WPA  WPA2  Compatible
2253  *    0       0        0       0      NONE      0      0    0   yes No security
2254  *    0       1        0       0       x        1x     1    x   yes WPA (disable HT if no AES)
2255  *    0       0        1       0       x        1x     x    1   yes WPA2 (disable HT if no AES)
2256  *    0       0        0       1      NONE      1      0    0   yes Ad-hoc AES
2257  *    1       0        0       0      NONE      1      0    0   yes Static WEP (disable HT)
2258  *    0       0        0       0     !=NONE     1      0    0   yes Dynamic WEP
2259  *
2260  *  @param pmpriv  A pointer to mlan_private
2261  *  @param index   Index in scan table to check against current driver settings
2262  *  @param mode    Network mode: Infrastructure or IBSS
2263  *
2264  *  @return        Index in ScanTable, or negative value if error
2265  */
wlan_is_network_compatible(IN mlan_private * pmpriv,IN t_u32 index,IN mlan_bss_mode mode)2266 t_s32 wlan_is_network_compatible(IN mlan_private *pmpriv, IN t_u32 index, IN mlan_bss_mode mode)
2267 {
2268     mlan_adapter *pmadapter = pmpriv->adapter;
2269     BSSDescriptor_t *pbss_desc;
2270 
2271     ENTER();
2272 
2273     pbss_desc              = &pmadapter->pscan_table[index];
2274     pbss_desc->disable_11n = MFALSE;
2275 
2276     /* Don't check for compatibility if roaming */
2277     if ((pmpriv->media_connected == MTRUE) && (pmpriv->bss_mode == MLAN_BSS_MODE_INFRA) &&
2278         (pbss_desc->bss_mode == MLAN_BSS_MODE_INFRA))
2279     {
2280         LEAVE();
2281         return (t_s32)index;
2282     }
2283 
2284 #if CONFIG_11AC
2285     /* if the VHT CAP IE exists, the HT CAP IE should exist too */
2286     if ((pbss_desc->pvht_cap != MNULL) && (pbss_desc->pht_cap == MNULL))
2287     {
2288         PRINTM(MINFO, "Disable 11n if HT CAP IE is not found from the 11AC AP\n");
2289         pbss_desc->disable_11n = MTRUE;
2290     }
2291 #endif
2292 #if CONFIG_11AX
2293     /* if the HE CAP IE exists, HT CAP IE should exist too */
2294     /* 2.4G AX AP, don't have VHT CAP */
2295     if (pbss_desc->phe_cap && !pbss_desc->pht_cap)
2296     {
2297         PRINTM(MINFO, "Disable 11n if VHT CAP/HT CAP IE is not found from the 11AX AP\n");
2298         pbss_desc->disable_11n = MTRUE;
2299     }
2300 #endif
2301 
2302 #if (CONFIG_WPS2) || (CONFIG_WPA_SUPP_WPS)
2303     if (pmpriv->wps.session_enable == MTRUE)
2304     {
2305         PRINTM(MINFO, "Return success directly in WPS period\n");
2306         LEAVE();
2307         return index;
2308     }
2309 #endif /* CONFIG_WPS2 */
2310 #if CONFIG_DRIVER_OWE
2311     if ((pbss_desc->owe_transition_mode == OWE_TRANS_MODE_OPEN) &&
2312         (pmpriv->sec_info.authentication_mode != MLAN_AUTH_MODE_OWE))
2313     {
2314         PRINTM(MINFO, "Return success directly in OWE Transition mode\n");
2315         LEAVE();
2316         return index;
2317     }
2318 #endif
2319     if ((pbss_desc->bss_mode == mode) && (pmpriv->sec_info.ewpa_enabled == MTRUE))
2320     {
2321         if (((pbss_desc->pwpa_ie != MNULL) && ((*(pbss_desc->pwpa_ie)).vend_hdr.element_id == WPA_IE)) ||
2322             ((pbss_desc->prsn_ie != MNULL) && ((*(pbss_desc->prsn_ie)).ieee_hdr.element_id == RSN_IE)))
2323         {
2324             if (((pmpriv->adapter->config_bands & BAND_GN || pmpriv->adapter->config_bands & BAND_AN) &&
2325                  (pbss_desc->pht_cap != MNULL)) &&
2326                 (pmpriv->bss_mode == MLAN_BSS_MODE_INFRA) &&
2327                 !is_wpa_oui_present(pmpriv->adapter, pbss_desc, CIPHER_SUITE_CCMP) &&
2328                 !is_rsn_oui_present(pmpriv->adapter, pbss_desc, CIPHER_SUITE_CCMP))
2329             {
2330                 if (is_wpa_oui_present(pmpriv->adapter, pbss_desc, CIPHER_SUITE_TKIP) ||
2331                     is_rsn_oui_present(pmpriv->adapter, pbss_desc, CIPHER_SUITE_TKIP))
2332                 {
2333                     PRINTM(MINFO, "Disable 11n if AES is not supported by AP\n");
2334                     pbss_desc->disable_11n = MTRUE;
2335                 }
2336                 else
2337                 {
2338                     LEAVE();
2339                     return -1;
2340                 }
2341             }
2342             LEAVE();
2343             return (t_s32)index;
2344         }
2345         else
2346         {
2347             PRINTM(MINFO, "ewpa_enabled: Ignore none WPA/WPA2 AP\n");
2348             LEAVE();
2349             return -1;
2350         }
2351     }
2352 
2353     if (pmpriv->sec_info.wapi_enabled &&
2354         ((pbss_desc->pwapi_ie != MNULL) && ((*(pbss_desc->pwapi_ie)).ieee_hdr.element_id == WAPI_IE)))
2355     {
2356         PRINTM(MINFO, "Return success for WAPI AP\n");
2357         LEAVE();
2358         return (t_s32)index;
2359     }
2360 
2361     if (pbss_desc->bss_mode == mode)
2362     {
2363         if (pmpriv->sec_info.wep_status == Wlan802_11WEPDisabled && !pmpriv->sec_info.wpa_enabled &&
2364             !pmpriv->sec_info.wpa2_enabled &&
2365             ((pbss_desc->pwpa_ie == MNULL) || ((*(pbss_desc->pwpa_ie)).vend_hdr.element_id != WPA_IE)) &&
2366             ((pbss_desc->prsn_ie == MNULL) || ((*(pbss_desc->prsn_ie)).ieee_hdr.element_id != RSN_IE)) &&
2367             !pmpriv->adhoc_aes_enabled && pmpriv->sec_info.encryption_mode == MLAN_ENCRYPTION_MODE_NONE &&
2368             !pbss_desc->privacy)
2369         {
2370             /* No security */
2371             LEAVE();
2372             return (t_s32)index;
2373         }
2374         else if (pmpriv->sec_info.wep_status == Wlan802_11WEPEnabled && !pmpriv->sec_info.wpa_enabled &&
2375                  !pmpriv->sec_info.wpa2_enabled && !pmpriv->adhoc_aes_enabled && pbss_desc->privacy)
2376         {
2377             /* Static WEP enabled */
2378             PRINTM(MINFO, "Disable 11n in WEP mode\n");
2379             pbss_desc->disable_11n = MTRUE;
2380             LEAVE();
2381             return (t_s32)index;
2382         }
2383         else if (pmpriv->sec_info.wep_status == Wlan802_11WEPDisabled && pmpriv->sec_info.wpa_enabled &&
2384                  !pmpriv->sec_info.wpa2_enabled &&
2385                  ((pbss_desc->pwpa_ie != MNULL) && ((*(pbss_desc->pwpa_ie)).vend_hdr.element_id == WPA_IE)) &&
2386                  !pmpriv->adhoc_aes_enabled
2387                  /*
2388                   * Privacy bit may NOT be set in some APs like LinkSys WRT54G
2389                   * && pbss_desc->privacy
2390                   */
2391         )
2392         {
2393             /* WPA enabled */
2394             PRINTM(MINFO,
2395                    "wlan_is_network_compatible() WPA: index=%d wpa_ie=%#x "
2396                    "rsn_ie=%#x WEP=%s WPA=%s WPA2=%s EncMode=%#x "
2397                    "privacy=%#x\n",
2398                    index, (pbss_desc->pwpa_ie) ? (*(pbss_desc->pwpa_ie)).vend_hdr.element_id : 0,
2399                    (pbss_desc->prsn_ie) ? (*(pbss_desc->prsn_ie)).ieee_hdr.element_id : 0,
2400                    (pmpriv->sec_info.wep_status == Wlan802_11WEPEnabled) ? "e" : "d",
2401                    (pmpriv->sec_info.wpa_enabled) ? "e" : "d", (pmpriv->sec_info.wpa2_enabled) ? "e" : "d",
2402                    pmpriv->sec_info.encryption_mode, pbss_desc->privacy);
2403             if (((pmpriv->adapter->config_bands & BAND_GN || pmpriv->adapter->config_bands & BAND_AN) &&
2404                  (pbss_desc->pht_cap != MNULL)) &&
2405                 (pmpriv->bss_mode == MLAN_BSS_MODE_INFRA) &&
2406                 !is_wpa_oui_present(pmpriv->adapter, pbss_desc, CIPHER_SUITE_CCMP))
2407             {
2408                 if (is_wpa_oui_present(pmpriv->adapter, pbss_desc, CIPHER_SUITE_TKIP) != 0U)
2409                 {
2410                     PRINTM(MINFO, "Disable 11n if AES is not supported by AP\n");
2411                     pbss_desc->disable_11n = MTRUE;
2412                 }
2413                 else
2414                 {
2415                     LEAVE();
2416                     return -1;
2417                 }
2418             }
2419             LEAVE();
2420             return (t_s32)index;
2421         }
2422         else if (pmpriv->sec_info.wep_status == Wlan802_11WEPDisabled && !pmpriv->sec_info.wpa_enabled &&
2423                  pmpriv->sec_info.wpa2_enabled &&
2424                  ((pbss_desc->prsn_ie != MNULL) && ((*(pbss_desc->prsn_ie)).ieee_hdr.element_id == RSN_IE)) &&
2425                  !pmpriv->adhoc_aes_enabled
2426                  /*
2427                   * Privacy bit may NOT be set in some APs like LinkSys WRT54G
2428                   * && pbss_desc->privacy
2429                   */
2430         )
2431         {
2432             /* WPA2 enabled */
2433             PRINTM(MINFO,
2434                    "wlan_is_network_compatible() WPA2: index=%d wpa_ie=%#x "
2435                    "rsn_ie=%#x WEP=%s WPA=%s WPA2=%s EncMode=%#x "
2436                    "privacy=%#x\n",
2437                    index, (pbss_desc->pwpa_ie) ? (*(pbss_desc->pwpa_ie)).vend_hdr.element_id : 0,
2438                    (pbss_desc->prsn_ie) ? (*(pbss_desc->prsn_ie)).ieee_hdr.element_id : 0,
2439                    (pmpriv->sec_info.wep_status == Wlan802_11WEPEnabled) ? "e" : "d",
2440                    (pmpriv->sec_info.wpa_enabled) ? "e" : "d", (pmpriv->sec_info.wpa2_enabled) ? "e" : "d",
2441                    pmpriv->sec_info.encryption_mode, pbss_desc->privacy);
2442             if (((pmpriv->adapter->config_bands & BAND_GN || pmpriv->adapter->config_bands & BAND_AN) &&
2443                  (pbss_desc->pht_cap != MNULL)) &&
2444                 (pmpriv->bss_mode == MLAN_BSS_MODE_INFRA) &&
2445                 !is_rsn_oui_present(pmpriv->adapter, pbss_desc, CIPHER_SUITE_CCMP))
2446             {
2447                 if (is_rsn_oui_present(pmpriv->adapter, pbss_desc, CIPHER_SUITE_TKIP) != 0U)
2448                 {
2449                     PRINTM(MINFO, "Disable 11n if AES is not supported by AP\n");
2450                     pbss_desc->disable_11n = MTRUE;
2451                 }
2452                 else
2453                 {
2454                     LEAVE();
2455                     return -1;
2456                 }
2457             }
2458             LEAVE();
2459             return (t_s32)index;
2460         }
2461         else if (pmpriv->sec_info.wep_status == Wlan802_11WEPDisabled && !pmpriv->sec_info.wpa_enabled &&
2462                  !pmpriv->sec_info.wpa2_enabled &&
2463                  ((pbss_desc->pwpa_ie == MNULL) || ((*(pbss_desc->pwpa_ie)).vend_hdr.element_id != WPA_IE)) &&
2464                  ((pbss_desc->prsn_ie == MNULL) || ((*(pbss_desc->prsn_ie)).ieee_hdr.element_id != RSN_IE)) &&
2465                  pmpriv->adhoc_aes_enabled && pmpriv->sec_info.encryption_mode == MLAN_ENCRYPTION_MODE_NONE &&
2466                  pbss_desc->privacy)
2467         {
2468             /* Ad-hoc AES enabled */
2469             LEAVE();
2470             return (t_s32)index;
2471         }
2472         else if (pmpriv->sec_info.wep_status == Wlan802_11WEPDisabled && !pmpriv->sec_info.wpa_enabled &&
2473                  !pmpriv->sec_info.wpa2_enabled &&
2474                  ((pbss_desc->pwpa_ie == MNULL) || ((*(pbss_desc->pwpa_ie)).vend_hdr.element_id != WPA_IE)) &&
2475                  ((pbss_desc->prsn_ie == MNULL) || ((*(pbss_desc->prsn_ie)).ieee_hdr.element_id != RSN_IE)) &&
2476                  !pmpriv->adhoc_aes_enabled && pmpriv->sec_info.encryption_mode != MLAN_ENCRYPTION_MODE_NONE &&
2477                  pbss_desc->privacy)
2478         {
2479             /* Dynamic WEP enabled */
2480             PRINTM(MINFO,
2481                    "wlan_is_network_compatible() dynamic WEP: index=%d "
2482                    "wpa_ie=%#x rsn_ie=%#x EncMode=%#x privacy=%#x\n",
2483                    index, (pbss_desc->pwpa_ie) ? (*(pbss_desc->pwpa_ie)).vend_hdr.element_id : 0,
2484                    (pbss_desc->prsn_ie) ? (*(pbss_desc->prsn_ie)).ieee_hdr.element_id : 0,
2485                    pmpriv->sec_info.encryption_mode, pbss_desc->privacy);
2486             LEAVE();
2487             return (t_s32)index;
2488         }
2489 
2490         else
2491         {
2492             /* Security doesn't match */
2493             PRINTM(MINFO,
2494                    "wlan_is_network_compatible() FAILED: index=%d wpa_ie=%#x "
2495                    "rsn_ie=%#x WEP=%s WPA=%s WPA2=%s EncMode=%#x privacy=%#x\n",
2496                    index, (pbss_desc->pwpa_ie) ? (*(pbss_desc->pwpa_ie)).vend_hdr.element_id : 0,
2497                    (pbss_desc->prsn_ie) ? (*(pbss_desc->prsn_ie)).ieee_hdr.element_id : 0,
2498                    (pmpriv->sec_info.wep_status == Wlan802_11WEPEnabled) ? "e" : "d",
2499                    (pmpriv->sec_info.wpa_enabled) ? "e" : "d", (pmpriv->sec_info.wpa2_enabled) ? "e" : "d",
2500                    pmpriv->sec_info.encryption_mode, pbss_desc->privacy);
2501             LEAVE();
2502             return -1;
2503         }
2504     }
2505 
2506     /* Mode doesn't match */
2507     LEAVE();
2508     return -1;
2509 }
2510 
2511 /**
2512  *  @brief Internal function used to start a scan based on an input config
2513  *
2514  *  Use the input user scan configuration information when provided in
2515  *    order to send the appropriate scan commands to firmware to populate or
2516  *    update the internal driver scan table
2517  *
2518  *  @param pmpriv          A pointer to mlan_private structure
2519  *  @param pioctl_buf      A pointer to MLAN IOCTL Request buffer
2520  *  @param puser_scan_in   Pointer to the input configuration for the requested
2521  *                         scan.
2522  *
2523  *  @return              MLAN_STATUS_SUCCESS or < 0 if error
2524  */
wlan_scan_networks(IN mlan_private * pmpriv,IN t_void * pioctl_buf,IN const wlan_user_scan_cfg * puser_scan_in)2525 mlan_status wlan_scan_networks(IN mlan_private *pmpriv,
2526                                IN t_void *pioctl_buf,
2527                                IN const wlan_user_scan_cfg *puser_scan_in)
2528 {
2529     mlan_status ret         = MLAN_STATUS_SUCCESS;
2530     mlan_adapter *pmadapter = pmpriv->adapter;
2531     mlan_callbacks *pcb     = (mlan_callbacks *)&pmadapter->callbacks;
2532     /* cmd_ctrl_node *pcmd_node = MNULL; */
2533     pmlan_ioctl_req pioctl_req = (mlan_ioctl_req *)pioctl_buf;
2534 
2535     wlan_scan_cmd_config_tlv *pscan_cfg_out = MNULL;
2536     MrvlIEtypes_ChanListParamSet_t *pchan_list_out;
2537     t_u32 buf_size;
2538     ChanScanParamSet_t *pscan_chan_list;
2539 
2540     t_u8 keep_previous_scan;
2541     t_u8 filtered_scan;
2542     t_u8 scan_current_chan_only;
2543     t_u8 max_chan_per_scan;
2544 
2545     ENTER();
2546 
2547 #if !CONFIG_MEM_POOLS
2548     ret = pcb->moal_malloc(pmadapter->pmoal_handle, sizeof(wlan_scan_cmd_config_tlv), MLAN_MEM_DEF,
2549                            (t_u8 **)(void **)&pscan_cfg_out);
2550     if (ret != MLAN_STATUS_SUCCESS || (pscan_cfg_out == MNULL))
2551 #else
2552     pscan_cfg_out = (wlan_scan_cmd_config_tlv *)OSA_MemoryPoolAllocate(buf_768_MemoryPool);
2553     if (pscan_cfg_out == MNULL)
2554 #endif
2555     {
2556         PRINTM(MERROR, "Memory allocation for pscan_cfg_out failed!\n");
2557         if (pioctl_req != MNULL)
2558         {
2559             pioctl_req->status_code = MLAN_ERROR_NO_MEM;
2560         }
2561         LEAVE();
2562         return MLAN_STATUS_FAILURE;
2563     }
2564 
2565     buf_size = sizeof(ChanScanParamSet_t) * WLAN_USER_SCAN_CHAN_MAX;
2566 #if !CONFIG_MEM_POOLS
2567     ret = pcb->moal_malloc(pmadapter->pmoal_handle, buf_size, MLAN_MEM_DEF, (t_u8 **)(void **)&pscan_chan_list);
2568     if (ret != MLAN_STATUS_SUCCESS || (pscan_chan_list == MNULL))
2569 #else
2570     pscan_chan_list = (ChanScanParamSet_t *)OSA_MemoryPoolAllocate(buf_512_MemoryPool);
2571     if (pscan_chan_list == MNULL)
2572 #endif
2573     {
2574         PRINTM(MERROR, "Failed to allocate scan_chan_list\n");
2575         (void)pcb->moal_mfree(pmadapter->pmoal_handle, (t_u8 *)pscan_cfg_out);
2576         if (pioctl_req != MNULL)
2577         {
2578             pioctl_req->status_code = MLAN_ERROR_NO_MEM;
2579         }
2580         LEAVE();
2581         return MLAN_STATUS_FAILURE;
2582     }
2583 
2584     (void)__memset(pmadapter, pscan_chan_list, 0x00, buf_size);
2585     (void)__memset(pmadapter, pscan_cfg_out, 0x00, sizeof(wlan_scan_cmd_config_tlv));
2586 
2587     keep_previous_scan = MFALSE;
2588 
2589     ret = wlan_scan_setup_scan_config(pmpriv, puser_scan_in, &pscan_cfg_out->config, &pchan_list_out, pscan_chan_list,
2590                                       &max_chan_per_scan, &filtered_scan, &scan_current_chan_only);
2591     if (ret != MLAN_STATUS_SUCCESS)
2592     {
2593         PRINTM(MERROR, "Failed to setup scan config\n");
2594 #if !CONFIG_MEM_POOLS
2595         (void)pcb->moal_mfree(pmadapter->pmoal_handle, (t_u8 *)pscan_cfg_out);
2596         (void)pcb->moal_mfree(pmadapter->pmoal_handle, (t_u8 *)pscan_chan_list);
2597 #else
2598         OSA_MemoryPoolFree(buf_768_MemoryPool, pscan_cfg_out);
2599         OSA_MemoryPoolFree(buf_512_MemoryPool, pscan_chan_list);
2600 #endif
2601         if (pioctl_req != MNULL)
2602         {
2603             pioctl_req->status_code = MLAN_ERROR_INVALID_PARAMETER;
2604         }
2605         LEAVE();
2606         return MLAN_STATUS_FAILURE;
2607     }
2608 
2609     if (puser_scan_in != MNULL)
2610     {
2611         keep_previous_scan = puser_scan_in->keep_previous_scan;
2612     }
2613 
2614     if (keep_previous_scan == MFALSE)
2615     {
2616 #if CONFIG_WPA_SUPP
2617         BSSDescriptor_t *bss_entry = NULL;
2618         int i;
2619 
2620         for (i = 0; i < pmadapter->num_in_scan_table; i++)
2621         {
2622             bss_entry = &pmadapter->pscan_table[i];
2623             if (bss_entry && bss_entry->ies != NULL)
2624             {
2625                 OSA_MemoryFree(bss_entry->ies);
2626             }
2627         }
2628 #endif
2629         (void)__memset(pmadapter, pmadapter->pscan_table, 0x00, sizeof(BSSDescriptor_t) * MRVDRV_MAX_BSSID_LIST);
2630         pmadapter->num_in_scan_table = 0;
2631     }
2632 
2633 #if CONFIG_SCAN_CHANNEL_GAP
2634     pmadapter->idx_chan_stats = 0;
2635 #endif
2636 
2637     split_scan_in_progress = true;
2638     ret = wlan_scan_channel_list(pmpriv, pioctl_buf, max_chan_per_scan, filtered_scan, &pscan_cfg_out->config,
2639                                  pchan_list_out, pscan_chan_list);
2640 #if !CONFIG_MEM_POOLS
2641     (void)pcb->moal_mfree(pmadapter->pmoal_handle, (t_u8 *)pscan_cfg_out);
2642     (void)pcb->moal_mfree(pmadapter->pmoal_handle, (t_u8 *)pscan_chan_list);
2643 #else
2644     OSA_MemoryPoolFree(buf_768_MemoryPool, pscan_cfg_out);
2645     OSA_MemoryPoolFree(buf_512_MemoryPool, pscan_chan_list);
2646 #endif
2647 
2648     LEAVE();
2649     return ret;
2650 }
2651 
2652 #if !CONFIG_EXT_SCAN_SUPPORT
2653 /**
2654  *  @brief Prepare a scan command to be sent to the firmware
2655  *
2656  *  Use the wlan_scan_cmd_config sent to the command processing module in
2657  *   the wlan_prepare_cmd to configure a HostCmd_DS_802_11_SCAN command
2658  *   struct to send to firmware.
2659  *
2660  *  The fixed fields specifying the BSS type and BSSID filters as well as a
2661  *   variable number/length of TLVs are sent in the command to firmware.
2662  *
2663  *  @param pmpriv     A pointer to mlan_private structure
2664  *  @param pcmd       A pointer to HostCmd_DS_COMMAND structure to be sent to
2665  *                    firmware with the HostCmd_DS_801_11_SCAN structure
2666  *  @param pdata_buf  Void pointer cast of a wlan_scan_cmd_config struct used
2667  *                    to set the fields/TLVs for the command sent to firmware
2668  *
2669  *  @return           MLAN_STATUS_SUCCESS
2670  */
wlan_cmd_802_11_scan(IN mlan_private * pmpriv,IN HostCmd_DS_COMMAND * pcmd,IN t_void * pdata_buf)2671 mlan_status wlan_cmd_802_11_scan(IN mlan_private *pmpriv, IN HostCmd_DS_COMMAND *pcmd, IN t_void *pdata_buf)
2672 {
2673     HostCmd_DS_802_11_SCAN *pscan_cmd = &pcmd->params.scan;
2674     wlan_scan_cmd_config *pscan_cfg;
2675 
2676     ENTER();
2677 
2678     pscan_cfg = (wlan_scan_cmd_config *)pdata_buf;
2679 
2680     /* Set fixed field variables in scan command */
2681     pscan_cmd->bss_mode = pscan_cfg->bss_mode;
2682     (void)__memcpy(pmpriv->adapter, pscan_cmd->bssid, pscan_cfg->specific_bssid, sizeof(pscan_cmd->bssid));
2683     (void)__memcpy(pmpriv->adapter, pscan_cmd->tlv_buffer, pscan_cfg->tlv_buf, pscan_cfg->tlv_buf_len);
2684 
2685     pcmd->command = wlan_cpu_to_le16(HostCmd_CMD_802_11_SCAN);
2686 
2687     /* Size is equal to the sizeof(fixed portions) + the TLV len + header */
2688     pcmd->size = (t_u16)wlan_cpu_to_le16(
2689         (t_u16)(sizeof(pscan_cmd->bss_mode) + sizeof(pscan_cmd->bssid) + pscan_cfg->tlv_buf_len + S_DS_GEN));
2690 
2691     LEAVE();
2692     return MLAN_STATUS_SUCCESS;
2693 }
2694 #endif
2695 
2696 /*
2697  * Fills the pointer variables with correct address.
2698  *
2699  * Original mlan stores the entire beacon. We cannot do that as it would
2700  * take approx 4K RAM per entry. Instead we have added some variables to
2701  * the original BSSDescriptor_t structure. These will keep the data needed
2702  * later. The pointers in this structure which would (ideally) point to
2703  * addresses in beacon buffer now point to these internal variables.
2704  *
2705  * Due beacon parsing a separate structure was used. That is mem-copied
2706  * into an entry in the static BSS_List. After this copy the internal
2707  * pointers still point to buffer addresses in the separate structure. We
2708  * will update them here.
2709  */
adjust_pointers_to_internal_buffers(BSSDescriptor_t * pbss_entry,BSSDescriptor_t * pbss_new_entry)2710 static void adjust_pointers_to_internal_buffers(BSSDescriptor_t *pbss_entry, BSSDescriptor_t *pbss_new_entry)
2711 {
2712     if (pbss_entry->pht_cap != NULL)
2713     {
2714         pbss_entry->pht_cap = &pbss_entry->ht_cap_saved;
2715     }
2716     if (pbss_entry->pht_info != NULL)
2717     {
2718         pbss_entry->pht_info = &pbss_entry->ht_info_saved;
2719     }
2720 #if CONFIG_11AC
2721     if (pbss_entry->pvht_cap != NULL)
2722     {
2723         pbss_entry->pvht_cap = &pbss_entry->vht_cap_saved;
2724     }
2725     if (pbss_entry->pvht_oprat != NULL)
2726     {
2727         pbss_entry->pvht_oprat = &pbss_entry->vht_oprat_saved;
2728     }
2729     if (pbss_entry->pvht_txpower != NULL)
2730     {
2731         pbss_entry->pvht_txpower = &pbss_entry->vht_txpower_saved;
2732     }
2733     if (pbss_entry->ppoper_mode != NULL)
2734     {
2735         pbss_entry->ppoper_mode = &pbss_entry->poper_mode_saved;
2736     }
2737     if (pbss_entry->pext_cap != NULL)
2738     {
2739         pbss_entry->pext_cap = &pbss_entry->ext_cap_saved;
2740     }
2741 #endif
2742 #if CONFIG_11AX
2743     if (pbss_entry->phe_cap != NULL)
2744     {
2745         pbss_entry->phe_cap = &pbss_entry->he_cap_saved;
2746     }
2747     if (pbss_entry->phe_oprat != NULL)
2748     {
2749         pbss_entry->phe_oprat = &pbss_entry->he_oprat_saved;
2750     }
2751  #endif
2752     if (pbss_entry->pbss_co_2040 != NULL)
2753     {
2754         pbss_entry->pbss_co_2040 = &pbss_entry->bss_co_2040_saved;
2755     }
2756     if (pbss_entry->pwpa_ie != NULL)
2757     {
2758         pbss_entry->pwpa_ie = (IEEEtypes_VendorSpecific_t *)(void *)pbss_entry->wpa_ie_buff;
2759     }
2760     if (pbss_entry->prsn_ie != NULL)
2761     {
2762         pbss_entry->prsn_ie = (IEEEtypes_Generic_t *)(void *)pbss_entry->rsn_ie_buff;
2763     }
2764     if (pbss_entry->prsnx_ie != NULL)
2765     {
2766         pbss_entry->prsnx_ie = &pbss_entry->rsnx_ie_saved;
2767     }
2768 #if CONFIG_WPA_SUPP
2769     if (pbss_new_entry->ies != NULL)
2770     {
2771         pbss_entry->ies = pbss_new_entry->ies;
2772     }
2773 #endif
2774 }
2775 
2776 #if !(CONFIG_EXT_SCAN_SUPPORT) || (CONFIG_BG_SCAN)
2777 /**
2778  *  @brief This function handles the command response of scan
2779  *
2780  *   The response buffer for the scan command has the following
2781  *      memory layout:
2782  *
2783  *     .-------------------------------------------------------------.
2784  *     |  Header (4 * sizeof(t_u16)):  Standard command response hdr |
2785  *     .-------------------------------------------------------------.
2786  *     |  BufSize (t_u16) : sizeof the BSS Description data          |
2787  *     .-------------------------------------------------------------.
2788  *     |  NumOfSet (t_u8) : Number of BSS Descs returned             |
2789  *     .-------------------------------------------------------------.
2790  *     |  BSSDescription data (variable, size given in BufSize)      |
2791  *     .-------------------------------------------------------------.
2792  *     |  TLV data (variable, size calculated using Header->Size,    |
2793  *     |            BufSize and sizeof the fixed fields above)       |
2794  *     .-------------------------------------------------------------.
2795  *
2796  *  @param pmpriv       A pointer to mlan_private structure
2797  *  @param resp         A pointer to HostCmd_DS_COMMAND
2798  *  @param pioctl_buf   A pointer to mlan_ioctl_req structure
2799  *
2800  *  @return             MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
2801  */
wlan_ret_802_11_scan(IN mlan_private * pmpriv,IN HostCmd_DS_COMMAND * resp,IN t_void * pioctl_buf)2802 mlan_status wlan_ret_802_11_scan(IN mlan_private *pmpriv, IN HostCmd_DS_COMMAND *resp, IN t_void *pioctl_buf)
2803 {
2804     mlan_status ret         = MLAN_STATUS_SUCCESS;
2805     mlan_adapter *pmadapter = pmpriv->adapter;
2806 #if !CONFIG_MEM_POOLS
2807     mlan_callbacks *pcb        = MNULL;
2808     mlan_ioctl_req *pioctl_req = (mlan_ioctl_req *)pioctl_buf;
2809 #endif
2810     /* cmd_ctrl_node *pcmd_node = MNULL; */
2811     HostCmd_DS_802_11_SCAN_RSP *pscan_rsp = MNULL;
2812     BSSDescriptor_t *bss_new_entry        = MNULL;
2813     MrvlIEtypes_Data_t *ptlv;
2814     MrvlIEtypes_TsfTimestamp_t *ptsf_tlv = MNULL;
2815     t_u8 *pbss_info;
2816     t_u32 scan_resp_size;
2817     t_u32 bytes_left;
2818     t_u32 num_in_table;
2819     t_u32 bss_idx;
2820     t_u32 idx;
2821     t_u32 tlv_buf_size;
2822     t_u64 tsf_val;
2823     const chan_freq_power_t *cfp;
2824     MrvlIEtypes_ChanBandListParamSet_t *pchan_band_tlv = MNULL;
2825     ChanBandParamSet_t *pchan_band;
2826     t_u16 band;
2827 #if CONFIG_BG_SCAN
2828     t_u8 is_bgscan_resp;
2829 #endif
2830     /* t_u32 age_ts_usec; */
2831     t_u32 lowest_rssi_index = 0;
2832 #if CONFIG_SCAN_CHANNEL_GAP
2833     MrvlIEtypes_ChannelStats_t *pchanstats_tlv = MNULL;
2834 #endif
2835     t_u8 null_ssid[MLAN_MAX_SSID_LENGTH] = {0};
2836     MrvlIEtypes_Data_t *pcurrent_tlv;
2837     t_u32 tlv_buf_left;
2838     t_u16 tlv_type;
2839     t_u16 tlv_len;
2840 
2841     ENTER();
2842 #if !CONFIG_MEM_POOLS
2843     pcb = (pmlan_callbacks)&pmadapter->callbacks;
2844 #endif
2845 
2846 #if CONFIG_BG_SCAN
2847     is_bgscan_resp = ((resp->command & HostCmd_CMD_ID_MASK) == HostCmd_CMD_802_11_BG_SCAN_QUERY);
2848     if (is_bgscan_resp)
2849     {
2850         pscan_rsp = &resp->params.bg_scan_query_resp.scan_resp;
2851     }
2852     else
2853 #endif
2854     {
2855         pscan_rsp = &resp->params.scan_resp;
2856     }
2857 
2858     /* Note: We do not expect to have the entire list of AP's with us in
2859        the driver. This is because we are memory constrained. So will
2860        modify the handling of the AP list and keep only AP's with high RSSI */
2861     bytes_left = wlan_le16_to_cpu(pscan_rsp->bss_descript_size);
2862     PRINTM(MINFO, "SCAN_RESP: bss_descript_size %d\n", bytes_left);
2863 
2864     if ((pscan_rsp->number_of_sets == 0U) && (bytes_left == 0U))
2865     {
2866         wscan_d("SCAN_RESP: number of sets are zero");
2867         goto done;
2868     }
2869 
2870     scan_resp_size = resp->size;
2871 
2872     PRINTM(MINFO, "SCAN_RESP: returned %d APs before parsing\n", pscan_rsp->number_of_sets);
2873 
2874     num_in_table = pmadapter->num_in_scan_table;
2875     pbss_info    = pscan_rsp->bss_desc_and_tlv_buffer;
2876 
2877     /*
2878      * The size of the TLV buffer is equal to the entire command response
2879      *   size (scan_resp_size) minus the fixed fields (sizeof()'s), the
2880      *   BSS Descriptions (bss_descript_size as bytesLef) and the command
2881      *   response header (S_DS_GEN)
2882      */
2883     tlv_buf_size = scan_resp_size -
2884                    (bytes_left + sizeof(pscan_rsp->bss_descript_size) + sizeof(pscan_rsp->number_of_sets) + S_DS_GEN);
2885 
2886 #if CONFIG_BG_SCAN
2887     if (is_bgscan_resp && (tlv_buf_size > sizeof(resp->params.bg_scan_query_resp.report_condition)))
2888     {
2889         tlv_buf_size -= sizeof(resp->params.bg_scan_query_resp.report_condition);
2890     }
2891 #endif
2892     ptlv = (MrvlIEtypes_Data_t *)(void *)(pscan_rsp->bss_desc_and_tlv_buffer + bytes_left);
2893 
2894     pcurrent_tlv = ptlv;
2895     tlv_buf_left = tlv_buf_size;
2896 
2897     wscan_d("SCAN_RESP: tlv_buf_size = %d", tlv_buf_size);
2898 
2899     while (tlv_buf_left >= sizeof(MrvlIEtypesHeader_t))
2900     {
2901         /* Barriers are normally not required but do ensure the code is
2902          * completely within the specified behaviour for the architecture. */
2903         __asm volatile("dsb" ::: "memory");
2904         __asm volatile("isb");
2905         tlv_type = wlan_le16_to_cpu(pcurrent_tlv->header.type);
2906         tlv_len  = wlan_le16_to_cpu(pcurrent_tlv->header.len);
2907 
2908         if (sizeof(ptlv->header) + tlv_len > tlv_buf_left)
2909         {
2910             wscan_d("SCAN_RESP: TLV buffer corrupt");
2911             break;
2912         }
2913 
2914         switch (tlv_type)
2915         {
2916             case TLV_TYPE_TSFTIMESTAMP:
2917                 wscan_d("SCAN_RESP: TSF Timestamp TLV, len = %d", tlv_len);
2918                 ptsf_tlv = (MrvlIEtypes_TsfTimestamp_t *)pcurrent_tlv;
2919                 break;
2920             case TLV_TYPE_CHANNELBANDLIST:
2921                 wscan_d("SCAN_RESP: CHANNEL BAND LIST TLV, len = %d", tlv_len);
2922                 pchan_band_tlv = (MrvlIEtypes_ChanBandListParamSet_t *)pcurrent_tlv;
2923                 break;
2924 #if CONFIG_SCAN_CHANNEL_GAP
2925             case TLV_TYPE_CHANNEL_STATS:
2926                 wscan_d("SCAN_RESP: CHANNEL STATS TLV, len = %d", tlv_len);
2927                 pchanstats_tlv = (MrvlIEtypes_ChannelStats_t *)pcurrent_tlv;
2928                 break;
2929 #endif
2930             default:
2931                 wscan_d("SCAN_RESP: Unhandled TLV = %d", tlv_type);
2932                 break;
2933         }
2934 
2935         tlv_buf_left -= (sizeof(ptlv->header) + tlv_len);
2936         pcurrent_tlv = (MrvlIEtypes_Data_t *)(void *)(pcurrent_tlv->data + tlv_len);
2937 
2938     } /* while */
2939 
2940 #if CONFIG_SCAN_CHANNEL_GAP
2941     if (pchanstats_tlv != MNULL)
2942     {
2943         wlan_update_chan_statistics(pmpriv, pchanstats_tlv);
2944     }
2945 #endif
2946 
2947     /*
2948      *  Process each scan response returned (pscan_rsp->number_of_sets).  Save
2949      *    the information in the bss_new_entry and then insert into the
2950      *    driver scan table either as an update to an existing entry
2951      *    or as an addition at the end of the table
2952      */
2953 #if !CONFIG_MEM_POOLS
2954     ret = pcb->moal_malloc(pmadapter->pmoal_handle, sizeof(BSSDescriptor_t), MLAN_MEM_DEF,
2955                            (t_u8 **)(void **)&bss_new_entry);
2956 
2957     if (ret != MLAN_STATUS_SUCCESS || (bss_new_entry == MNULL))
2958     {
2959         PRINTM(MERROR, "Memory allocation for bss_new_entry failed!\n");
2960         if (pioctl_req != MNULL)
2961         {
2962             pioctl_req->status_code = MLAN_ERROR_NO_MEM;
2963         }
2964         ret = MLAN_STATUS_FAILURE;
2965         goto done;
2966     }
2967 #else
2968     bss_new_entry = &s_bss_new_entry;
2969 #endif
2970 
2971     idx = 0;
2972     while (idx < pscan_rsp->number_of_sets && bytes_left)
2973     {
2974         /* Zero out the bss_new_entry we are about to store info in */
2975         (void)__memset(pmadapter, bss_new_entry, 0x00, sizeof(BSSDescriptor_t));
2976 
2977         /* Process the data fields and IEs returned for this BSS */
2978         if (wlan_interpret_bss_desc_with_ie(pmadapter, bss_new_entry, &pbss_info, &bytes_left, MFALSE) ==
2979             MLAN_STATUS_SUCCESS)
2980         {
2981             wscan_d("SCAN_RESP: BSSID = %02x:%02x:%02x:%02x:%02x:%02x", bss_new_entry->mac_address[0],
2982                     bss_new_entry->mac_address[1], bss_new_entry->mac_address[2], bss_new_entry->mac_address[3],
2983                     bss_new_entry->mac_address[4], bss_new_entry->mac_address[5]);
2984 
2985 #if CONFIG_WPA_SUPP
2986 #if CONFIG_WPA_SUPP_WPS
2987             if (pmpriv->wps.session_enable == MTRUE)
2988             {
2989                 if ((bss_new_entry->wps_IE_exist == MFALSE) || (bss_new_entry->wps_session == 0xffff))
2990                 {
2991                     if (bss_new_entry->ies != NULL)
2992                     {
2993                         OSA_MemoryFree(bss_new_entry->ies);
2994                         bss_new_entry->ies = NULL;
2995                     }
2996                     continue;
2997                 }
2998             }
2999 #endif /* CONFIG_WPA_SUPP_WPS */
3000 #endif
3001 
3002             /*
3003              * Search the scan table for the same bssid
3004              */
3005             for (bss_idx = 0; bss_idx < num_in_table; bss_idx++)
3006             {
3007                 if (!__memcmp(pmadapter, bss_new_entry->mac_address, pmadapter->pscan_table[bss_idx].mac_address,
3008                               sizeof(bss_new_entry->mac_address)))
3009                 {
3010                     /*
3011                      * If the SSID matches as well, it is a duplicate of
3012                      *   this entry.  Keep the bss_idx set to this
3013                      *   entry so we replace the old contents in the table
3014                      */
3015                     if ((bss_new_entry->ssid.ssid_len == pmadapter->pscan_table[bss_idx].ssid.ssid_len) &&
3016                         (!__memcmp(pmadapter, bss_new_entry->ssid.ssid, pmadapter->pscan_table[bss_idx].ssid.ssid,
3017                                    bss_new_entry->ssid.ssid_len)))
3018                     {
3019                         wscan_d("SCAN_RESP: Duplicate of index: %d", bss_idx);
3020                         break;
3021                     }
3022                     /*
3023                      * If the SSID is NULL for same BSSID
3024                      * keep the bss_idx set to this entry
3025                      * so we replace the old contents in
3026                      * the table
3027                      */
3028                     if (!__memcmp(pmadapter, pmadapter->pscan_table[bss_idx].ssid.ssid, null_ssid,
3029                                   pmadapter->pscan_table[bss_idx].ssid.ssid_len))
3030                     {
3031                         wscan_d("SCAN_RESP: Duplicate of index: %d", bss_idx);
3032                         break;
3033                     }
3034                 }
3035             }
3036             /*
3037              * If the bss_idx is equal to the number of entries in the table,
3038              *   the new entry was not a duplicate; append it to the scan
3039              *   table
3040              */
3041             if (bss_idx == num_in_table)
3042             {
3043                 /* Range check the bss_idx, keep it limited to the last entry */
3044                 if (bss_idx == MRVDRV_MAX_BSSID_LIST)
3045                 {
3046                     lowest_rssi_index = wlan_find_worst_network_in_list(pmadapter->pscan_table, MRVDRV_MAX_BSSID_LIST);
3047                 }
3048                 else
3049                 {
3050                     num_in_table++;
3051                 }
3052             }
3053             else
3054             {
3055                 if ((bss_new_entry->channel != pmadapter->pscan_table[bss_idx].channel) &&
3056                     (bss_new_entry->rssi > pmadapter->pscan_table[bss_idx].rssi))
3057                 {
3058                     wscan_d("skip update the duplicate entry with low rssi");
3059 #if CONFIG_WPA_SUPP
3060                     if (bss_new_entry->ies != NULL)
3061                     {
3062                         OSA_MemoryFree(bss_new_entry->ies);
3063                         bss_new_entry->ies = NULL;
3064                     }
3065 #endif
3066                     continue;
3067                 }
3068             }
3069 
3070             /*
3071              * If the TSF TLV was appended to the scan results, save
3072              *   this entry's TSF value in the networkTSF field.  The
3073              *   networkTSF is the firmware's TSF value at the time the
3074              *   beacon or probe response was received.
3075              */
3076             if (ptsf_tlv != MNULL)
3077             {
3078                 (void)__memcpy(pmpriv->adapter, &tsf_val, &ptsf_tlv->tsf_data[idx * TSF_DATA_SIZE], sizeof(tsf_val));
3079                 tsf_val = wlan_le64_to_cpu(tsf_val);
3080                 (void)__memcpy(pmpriv->adapter, &bss_new_entry->network_tsf, &tsf_val,
3081                                sizeof(bss_new_entry->network_tsf));
3082             }
3083             band = BAND_G;
3084             if (pchan_band_tlv != MNULL)
3085             {
3086                 pchan_band = &pchan_band_tlv->chan_band_param[idx];
3087                 if (bss_new_entry->channel == 0)
3088                 {
3089                     bss_new_entry->channel = pchan_band->chan_number;
3090                 }
3091                 band = radio_type_to_band(pchan_band->radio_type & (MBIT(0) | MBIT(1)));
3092             }
3093 
3094             /* Save the band designation for this entry for use in join */
3095             bss_new_entry->bss_band = band;
3096             cfp = wlan_find_cfp_by_band_and_channel(pmadapter, bss_new_entry->bss_band, (t_u16)bss_new_entry->channel);
3097 
3098             if (cfp != MNULL)
3099             {
3100                 bss_new_entry->freq = cfp->freq;
3101             }
3102             else
3103             {
3104                 bss_new_entry->freq = 0;
3105             }
3106 
3107 #if CONFIG_BG_SCAN
3108             if ((is_bgscan_resp) && (pmpriv->roaming_enabled == MTRUE))
3109             {
3110                 if (num_in_table == 2U)
3111                 {
3112                     if (pmadapter->pscan_table[0].rssi > bss_new_entry->rssi)
3113                     {
3114 #if CONFIG_WPA_SUPP
3115                         /* If the scan table is full, free ies of the lowest rssi entry before this entry is replaced */
3116                         if (pmadapter->pscan_table[0].ies != NULL)
3117                         {
3118                             OSA_MemoryFree(pmadapter->pscan_table[0].ies);
3119                             pmadapter->pscan_table[0].ies = NULL;
3120                         }
3121 #endif
3122                         (void)__memcpy(pmadapter, &pmadapter->pscan_table[0], bss_new_entry,
3123                                        sizeof(pmadapter->pscan_table[0]));
3124                         adjust_pointers_to_internal_buffers(&pmadapter->pscan_table[0], bss_new_entry);
3125                     }
3126 #if CONFIG_WPA_SUPP
3127                     /* If the scan table is full, free ies of the new entry with lowest rssi, which won't be added into
3128                      * table */
3129                     else
3130                     {
3131                         if (bss_new_entry->ies != NULL)
3132                         {
3133                             OSA_MemoryFree(bss_new_entry->ies);
3134                             bss_new_entry->ies = NULL;
3135                         }
3136                     }
3137 #endif
3138                     num_in_table--;
3139                     continue;
3140                 }
3141             }
3142 #endif
3143 
3144             if (bss_idx == MRVDRV_MAX_BSSID_LIST)
3145             {
3146                 if (pmadapter->pscan_table[lowest_rssi_index].rssi > bss_new_entry->rssi)
3147                 {
3148 #if CONFIG_WPA_SUPP
3149                     /* If the scan table is full, free ies of the lowest rssi entry before this entry is replaced */
3150                     if (pmadapter->pscan_table[lowest_rssi_index].ies != NULL)
3151                     {
3152                         OSA_MemoryFree(pmadapter->pscan_table[lowest_rssi_index].ies);
3153                         pmadapter->pscan_table[lowest_rssi_index].ies = NULL;
3154                     }
3155 #endif
3156                     (void)__memcpy(pmadapter, &pmadapter->pscan_table[lowest_rssi_index], bss_new_entry,
3157                                    sizeof(pmadapter->pscan_table[lowest_rssi_index]));
3158                     adjust_pointers_to_internal_buffers(&pmadapter->pscan_table[lowest_rssi_index], bss_new_entry);
3159                 }
3160 #if CONFIG_WPA_SUPP
3161                 /* If the scan table is full, free ies of the new entry with lowest rssi, which won't be added into
3162                  * table */
3163                 else
3164                 {
3165                     if (bss_new_entry->ies != NULL)
3166                     {
3167                         OSA_MemoryFree(bss_new_entry->ies);
3168                         bss_new_entry->ies = NULL;
3169                     }
3170                 }
3171 #endif
3172             }
3173             else
3174             {
3175 #if CONFIG_WPA_SUPP
3176                 /* Free ies of the old entry if it's duplicate entry */
3177                 if (pmadapter->pscan_table[bss_idx].ies != NULL)
3178                 {
3179                     OSA_MemoryFree(pmadapter->pscan_table[bss_idx].ies);
3180                     pmadapter->pscan_table[bss_idx].ies = NULL;
3181                 }
3182 #endif
3183 
3184                 /* Copy the locally created bss_new_entry to the scan table */
3185                 (void)__memcpy(pmadapter, &pmadapter->pscan_table[bss_idx], bss_new_entry,
3186                                sizeof(pmadapter->pscan_table[bss_idx]));
3187                 adjust_pointers_to_internal_buffers(&pmadapter->pscan_table[bss_idx], bss_new_entry);
3188             }
3189         }
3190         else
3191         {
3192             /* Error parsing/interpreting the scan response, skipped */
3193             PRINTM(MERROR, "SCAN_RESP: wlan_interpret_bss_desc_with_ie returned error\n");
3194 #if CONFIG_WPA_SUPP
3195             if (bss_new_entry->ies != NULL)
3196             {
3197                 OSA_MemoryFree(bss_new_entry->ies);
3198                 bss_new_entry->ies = NULL;
3199             }
3200 #endif
3201         }
3202         idx++;
3203     }
3204 
3205     wscan_d("SCAN_RESP: Scanned %2d APs, %d valid, %d total", pscan_rsp->number_of_sets,
3206             num_in_table - pmadapter->num_in_scan_table, num_in_table);
3207 
3208     /* Update the total number of BSSIDs in the scan table */
3209     pmadapter->num_in_scan_table = num_in_table;
3210 
3211 done:
3212 #if !CONFIG_MEM_POOLS
3213     if (bss_new_entry != MNULL)
3214     {
3215         (void)pcb->moal_mfree(pmadapter->pmoal_handle, (t_u8 *)bss_new_entry);
3216     }
3217 #endif
3218 
3219     LEAVE();
3220     return ret;
3221 }
3222 #endif
3223 
3224 #if (CONFIG_EXT_SCAN_SUPPORT)
3225 /**
3226  *  @brief Prepare an extended scan command to be sent to the firmware
3227  *
3228  *  Use the wlan_scan_cmd_config sent to the command processing module in
3229  *   the wlan_prepare_cmd to configure a HostCmd_DS_802_11_SCAN_EXT command
3230  *   struct to send to firmware.
3231  *
3232  *  @param pmpriv     A pointer to mlan_private structure
3233  *  @param pcmd       A pointer to HostCmd_DS_COMMAND structure to be sent to
3234  *                    firmware with the HostCmd_DS_802_11_SCAN_EXT structure
3235  *  @param pdata_buf  Void pointer cast of a wlan_scan_cmd_config struct used
3236  *                    to set the fields/TLVs for the command sent to firmware
3237  *
3238  *  @return           MLAN_STATUS_SUCCESS
3239  */
wlan_cmd_802_11_scan_ext(IN mlan_private * pmpriv,IN HostCmd_DS_COMMAND * pcmd,IN t_void * pdata_buf)3240 mlan_status wlan_cmd_802_11_scan_ext(IN mlan_private *pmpriv, IN HostCmd_DS_COMMAND *pcmd, IN t_void *pdata_buf)
3241 {
3242     HostCmd_DS_802_11_SCAN_EXT *pext_scan_cmd = &pcmd->params.ext_scan;
3243     wlan_scan_cmd_config *pscan_cfg           = MNULL;
3244 
3245     ENTER();
3246 
3247     pscan_cfg = (wlan_scan_cmd_config *)pdata_buf;
3248 
3249     /* Set fixed field variables in scan command */
3250     pext_scan_cmd->reserved = 0x00;
3251     (void)__memcpy(pmpriv->adapter, pext_scan_cmd->tlv_buffer, pscan_cfg->tlv_buf, pscan_cfg->tlv_buf_len);
3252 
3253     pcmd->command = wlan_cpu_to_le16(HostCmd_CMD_802_11_SCAN_EXT);
3254 
3255     /* Size is equal to the sizeof(fixed portions) + the TLV len + header */
3256     pcmd->size = wlan_cpu_to_le16((t_u16)(sizeof(pext_scan_cmd->reserved) + pscan_cfg->tlv_buf_len + S_DS_GEN));
3257 
3258     LEAVE();
3259 
3260     return MLAN_STATUS_SUCCESS;
3261 }
3262 
3263 /**
3264  *  @brief This function handles the command response of extended scan
3265  *
3266  *  @param pmpriv       A pointer to mlan_private structure
3267  *  @param resp         A pointer to HostCmd_DS_COMMAND
3268  *  @param pioctl_buf   A pointer to mlan_ioctl_req structure
3269  *
3270  *  @return             MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
3271  */
wlan_ret_802_11_scan_ext(IN mlan_private * pmpriv,IN HostCmd_DS_COMMAND * resp,IN t_void * pioctl_buf)3272 mlan_status wlan_ret_802_11_scan_ext(IN mlan_private *pmpriv, IN HostCmd_DS_COMMAND *resp, IN t_void *pioctl_buf)
3273 {
3274 #if (CONFIG_SCAN_CHANNEL_GAP) || defined(EXT_SCAN_ENH)
3275     HostCmd_DS_802_11_SCAN_EXT *pext_scan_cmd = &(resp->params.ext_scan);
3276 #endif
3277 #if CONFIG_SCAN_CHANNEL_GAP
3278     MrvlIEtypesHeader_t *tlv                  = MNULL;
3279     MrvlIEtypes_ChannelStats_t *tlv_chanstats = MNULL;
3280     t_u16 tlv_buf_left                        = 0;
3281     t_u16 tlv_type                            = 0;
3282     t_u16 tlv_len                             = 0;
3283 #endif
3284 #ifdef EXT_SCAN_ENH
3285     t_u32 ext_scan_type;
3286     mlan_callbacks *pcb        = (mlan_callbacks *)&pmpriv->adapter->callbacks;
3287     pmlan_ioctl_req pioctl_req = (pmlan_ioctl_req)pioctl_buf;
3288     mlan_adapter *pmadapter    = pmpriv->adapter;
3289 #endif
3290     ENTER();
3291 
3292     PRINTM(MINFO, "EXT scan returns successfully\n");
3293 #ifdef EXT_SCAN_ENH
3294     pmadapter->scan_state |= wlan_get_ext_scan_state(resp);
3295     ext_scan_type = pext_scan_cmd->ext_scan_type;
3296     if (ext_scan_type == EXT_SCAN_CANCEL)
3297     {
3298         PRINTM(MCMND, "Cancel scan command completed!\n");
3299         wlan_request_cmd_lock(pmadapter);
3300         pmadapter->scan_processing = MFALSE;
3301         pmadapter->scan_state |= SCAN_STATE_SCAN_COMPLETE;
3302         pmadapter->ext_scan_type = EXT_SCAN_DEFAULT;
3303 #ifdef HOST_CCX
3304         pmadapter->scan_data_block = MFALSE;
3305 #endif
3306         wlan_release_cmd_lock(pmadapter);
3307         /* Need to indicate IOCTL complete */
3308         if (pioctl_req != MNULL)
3309         {
3310             pioctl_req->status_code = MLAN_STATUS_SUCCESS;
3311             /* Indicate ioctl complete */
3312             pcb->moal_ioctl_complete(pmadapter->pmoal_handle, (pmlan_ioctl_req)pioctl_req, MLAN_STATUS_SUCCESS);
3313         }
3314         LEAVE();
3315         return MLAN_STATUS_SUCCESS;
3316     }
3317     else if (ext_scan_type == EXT_SCAN_ENHANCE)
3318     {
3319         /* Setup the timer after scan command response */
3320         pcb->moal_start_timer(pmpriv->adapter->pmoal_handle, pmpriv->adapter->pmlan_cmd_timer, MFALSE,
3321                               MRVDRV_TIMER_10S * 2);
3322         pmpriv->adapter->cmd_timer_is_set = MTRUE;
3323         LEAVE();
3324         return MLAN_STATUS_SUCCESS;
3325     }
3326 #endif
3327 #if CONFIG_SCAN_CHANNEL_GAP
3328     tlv          = (MrvlIEtypesHeader_t *)pext_scan_cmd->tlv_buffer;
3329     tlv_buf_left = resp->size - (sizeof(HostCmd_DS_802_11_SCAN_EXT) - 1 + S_DS_GEN);
3330     while (tlv_buf_left >= sizeof(MrvlIEtypesHeader_t))
3331     {
3332         tlv_type = wlan_le16_to_cpu(tlv->type);
3333         tlv_len  = wlan_le16_to_cpu(tlv->len);
3334         if (tlv_buf_left < (tlv_len + sizeof(MrvlIEtypesHeader_t)))
3335         {
3336             PRINTM(MERROR, "Error processing scan gap TLV\n");
3337             break;
3338         }
3339         switch (tlv_type)
3340         {
3341             case TLV_TYPE_CHANNEL_STATS:
3342                 tlv_chanstats = (MrvlIEtypes_ChannelStats_t *)tlv;
3343                 wlan_update_chan_statistics(pmpriv, tlv_chanstats);
3344                 break;
3345             default:
3346                 break;
3347         }
3348         tlv_buf_left -= tlv_len + sizeof(MrvlIEtypesHeader_t);
3349         tlv = (MrvlIEtypesHeader_t *)((t_u8 *)tlv + tlv_len + sizeof(MrvlIEtypesHeader_t));
3350     }
3351 #endif
3352     LEAVE();
3353     return MLAN_STATUS_SUCCESS;
3354 }
3355 
3356 #if CONFIG_MULTI_BSSID_SUPPORT
3357 /** 8 bytes timestamp, 2 bytest interval, 2 bytes capability */
3358 #define BEACON_FIX_SIZE 12
3359 
3360 /**
3361  *  @brief This function realloc the beacon buffer and update ssid for new entry
3362  *
3363  *  @param pmadpater        A pointer to mlan_adapter structure
3364  *  @param pbss_entry       A pointer to the bss_entry which has multi-bssid IE
3365  *  @param pnew_entry       A pinter to new entry
3366  *  @param pssid            A pointer to ssid IE
3367  *  @param pnew_extcap      A pointer to EXT CAP IE
3368  *  @param pnew_rsnx        A pointer to RSNX IE
3369  *  @param pnew_rsn         A pointer to RSN IE
3370  *
3371  *  @return                MLAN_STATUS_FAILURE/MLAN_STATUS_SUCCESS
3372  */
wlan_update_ssid_in_beacon_buf(mlan_adapter * pmadapter,BSSDescriptor_t * pbss_entry,BSSDescriptor_t * pnew_entry,IEEEtypes_Ssid_t * pssid,IEEEtypes_ExtCap_t * pnew_extcap,IEEEtypes_Generic_t * pnew_rsnx,IEEEtypes_Generic_t * pnew_rsn)3373 static mlan_status wlan_update_ssid_in_beacon_buf(mlan_adapter *pmadapter,
3374                                                   BSSDescriptor_t *pbss_entry,
3375                                                   BSSDescriptor_t *pnew_entry,
3376                                                   IEEEtypes_Ssid_t *pssid,
3377                                                   IEEEtypes_ExtCap_t *pnew_extcap,
3378                                                   IEEEtypes_Generic_t *pnew_rsnx,
3379                                                   IEEEtypes_Generic_t *pnew_rsn)
3380 {
3381 #if CONFIG_WPA_SUPP
3382     mlan_callbacks *pcb = (pmlan_callbacks)&pmadapter->callbacks;
3383     t_u8 *pbeacon_buf   = MNULL;
3384 #endif
3385     t_u32 beacon_buf_size = 0;
3386     t_s8 offset           = pnew_entry->ssid.ssid_len - pbss_entry->ssid.ssid_len;
3387     mlan_status ret       = MLAN_STATUS_FAILURE;
3388 
3389     if (pnew_entry->ssid.ssid_len >= pbss_entry->ssid.ssid_len)
3390         beacon_buf_size = pbss_entry->beacon_buf_size + (pnew_entry->ssid.ssid_len - pbss_entry->ssid.ssid_len);
3391     else
3392         beacon_buf_size = pbss_entry->beacon_buf_size - (pbss_entry->ssid.ssid_len - pnew_entry->ssid.ssid_len);
3393 
3394     if (pnew_rsnx)
3395         beacon_buf_size += pnew_rsnx->ieee_hdr.len + sizeof(IEEEtypes_Header_t);
3396 #if CONFIG_WPA_SUPP
3397     ret = pcb->moal_malloc(pmadapter->pmoal_handle, beacon_buf_size, MLAN_MEM_DEF, (t_u8 **)&pbeacon_buf);
3398     if (ret != MLAN_STATUS_SUCCESS || !pbeacon_buf)
3399     {
3400         wifi_d("Memory allocation for beacon buf for bss_new_entry");
3401         goto done;
3402     }
3403 #endif
3404 
3405 #if CONFIG_WIFI_IO_DUMP
3406     wifi_d("BSS Entry");
3407     dump_hex(pbss_entry->pbeacon_buf, pbss_entry->beacon_buf_size);
3408 #endif
3409 
3410     pnew_entry->beacon_buf_size = beacon_buf_size;
3411 #if CONFIG_WPA_SUPP
3412     pnew_entry->pbeacon_buf = pbeacon_buf;
3413 #else
3414     pnew_entry->pbeacon_buf = pbss_entry->pbeacon_buf;
3415 #endif
3416     if (pnew_entry->pext_cap)
3417     {
3418         pnew_entry->ext_cap_offset += offset;
3419         if (pnew_extcap)
3420         {
3421             (void)__memcpy(pmadapter, &pnew_entry->ext_cap_saved, pnew_extcap, sizeof(IEEEtypes_ExtCap_t));
3422             pnew_entry->pext_cap = &pnew_entry->ext_cap_saved;
3423         }
3424     }
3425     if (pnew_rsnx)
3426     {
3427         (void)__memcpy(pmadapter, &pnew_entry->rsnx_ie_saved, pnew_rsnx,
3428                        pnew_rsnx->ieee_hdr.len + sizeof(IEEEtypes_Header_t));
3429         pnew_entry->prsnx_ie = &pnew_entry->rsnx_ie_saved;
3430     }
3431 
3432     if (pnew_rsn)
3433     {
3434         (void)__memcpy(pmadapter, pnew_entry->rsn_ie_buff, pnew_rsn,
3435                        pnew_rsn->ieee_hdr.len + sizeof(IEEEtypes_Header_t));
3436         pnew_entry->rsn_ie_buff_len = pnew_rsn->ieee_hdr.len + sizeof(IEEEtypes_Header_t);
3437         pnew_entry->prsn_ie         = (IEEEtypes_Generic_t *)pnew_entry->rsn_ie_buff;
3438     }
3439 
3440 #if CONFIG_WPA_SUPP
3441     /** copy fixed IE */
3442     (void)__memcpy(pmadapter, pbeacon_buf, pbss_entry->pbeacon_buf, BEACON_FIX_SIZE);
3443     /** copy new ssid ie */
3444     (void)__memcpy(pmadapter, pbeacon_buf + BEACON_FIX_SIZE, (t_u8 *)pssid, pssid->len + sizeof(IEEEtypes_Header_t));
3445     /** copy left IE to new beacon buffer */
3446     (void)__memcpy(
3447         pmadapter, pbeacon_buf + BEACON_FIX_SIZE + pssid->len + sizeof(IEEEtypes_Header_t),
3448         pbss_entry->pbeacon_buf + BEACON_FIX_SIZE + pbss_entry->ssid.ssid_len + sizeof(IEEEtypes_Header_t),
3449         pbss_entry->beacon_buf_size - BEACON_FIX_SIZE - (pbss_entry->ssid.ssid_len + sizeof(IEEEtypes_Header_t)));
3450 #if 0
3451     /* adjust the ie pointer */
3452     if (pnew_entry->pwpa_ie)
3453         pnew_entry->wpa_offset += offset;
3454     if (pnew_entry->prsn_ie)
3455         pnew_entry->rsn_offset += offset;
3456 #ifdef WAPI
3457     if (pnew_entry->pwapi_ie)
3458         pnew_entry->wapi_offset += offset;
3459 #endif /* WAPI */
3460 
3461 #ifdef ENABLE_HOTSPOT
3462     if (pnew_entry->posen_ie)
3463         pnew_entry->osen_offset += offset;
3464 #endif /* ENABLE_HOTSPOT */
3465 #if CONFIG_11R
3466     if (pnew_entry->pmd_ie)
3467         pnew_entry->md_offset += offset;
3468 #endif /* ENABLE_HOTSPOT */
3469     if (pnew_entry->pht_cap)
3470         pnew_entry->ht_cap_offset += offset;
3471     if (pnew_entry->pht_info)
3472         pnew_entry->ht_info_offset += offset;
3473     if (pnew_entry->pbss_co_2040)
3474         pnew_entry->bss_co_2040_offset += offset;
3475     if (pnew_entry->poverlap_bss_scan_param)
3476         pnew_entry->overlap_bss_offset += offset;
3477 #if CONFIG_11AC
3478     if (pnew_entry->pvht_cap)
3479         pnew_entry->vht_cap_offset += offset;
3480     if (pnew_entry->pvht_oprat)
3481         pnew_entry->vht_oprat_offset += offset;
3482     if (pnew_entry->pvht_txpower)
3483         pnew_entry->vht_txpower_offset += offset;
3484     if (pnew_entry->pext_pwer)
3485         pnew_entry->ext_pwer_offset += offset;
3486     if (pnew_entry->pext_bssload)
3487         pnew_entry->ext_bssload_offset += offset;
3488     if (pnew_entry->pquiet_chan)
3489         pnew_entry->quiet_chan_offset += offset;
3490     if (pnew_entry->poper_mode)
3491         pnew_entry->oper_mode_offset += offset;
3492 #endif /* CONFIG_11AC */
3493 #if CONFIG_11AX
3494     if (pnew_entry->phe_cap)
3495         pnew_entry->he_cap_offset += offset;
3496     if (pnew_entry->phe_oprat)
3497         pnew_entry->he_oprat_offset += offset;
3498 #endif /* CONFIG_11AX */
3499 #ifdef ENABLE_802_116E
3500     if (pnew_entry->phe_6g_cap)
3501         pnew_entry->he_6g_cap_offset += offset;
3502 #endif
3503 #endif
3504 
3505 #if CONFIG_WIFI_IO_DUMP
3506     wifi_d("BSS New Entry");
3507     dump_hex(pbeacon_buf, beacon_buf_size);
3508 #endif
3509 #endif
3510     ret = MLAN_STATUS_SUCCESS;
3511 #if CONFIG_WPA_SUPP
3512 done:
3513 #endif
3514     return ret;
3515 }
3516 
3517 /**
3518  *  @brief This function generate the bssid from bssid_idx
3519  *
3520  *  @param pmadpater        A pointer to mlan_adapter structure
3521  *  @param pbss_entry       A pointer to the bss_entry which has multi-bssid IE
3522  *  @param pnew_entry       A pinter to new entry
3523  *  @param bssid_index      bssid_index from BSSID_IDX IE
3524  *
3525  *  @return                N/A
3526  */
wlan_gen_multi_bssid_by_bssid_index(pmlan_adapter pmadapter,BSSDescriptor_t * pbss_entry,BSSDescriptor_t * pnew_entry,t_u8 bssid_index,t_u8 max_bssid_indicator)3527 static void wlan_gen_multi_bssid_by_bssid_index(pmlan_adapter pmadapter,
3528                                                 BSSDescriptor_t *pbss_entry,
3529                                                 BSSDescriptor_t *pnew_entry,
3530                                                 t_u8 bssid_index,
3531                                                 t_u8 max_bssid_indicator)
3532 {
3533     t_u8 mask = 0xff;
3534     t_u8 new_bssid[6];
3535     t_u8 bssid_a;
3536     t_u8 src_bssid[6];
3537     (void)__memcpy(pmadapter, (t_u8 *)src_bssid, pbss_entry->mac_address,
3538                    MIN(sizeof(mlan_802_11_mac_addr), sizeof(src_bssid)));
3539     (void)__memcpy(pmadapter, (t_u8 *)new_bssid, (t_u8 *)&pbss_entry->mac_address,
3540                    MIN(sizeof(mlan_802_11_mac_addr), sizeof(new_bssid)));
3541 
3542     mask         = (mask >> (8 - max_bssid_indicator));
3543     bssid_a      = src_bssid[5] & (~mask);
3544     src_bssid[5] = (src_bssid[5] + bssid_index) & mask;
3545     new_bssid[5] = bssid_a | src_bssid[5];
3546 
3547     (void)__memcpy(pmadapter, (t_u8 *)&pnew_entry->mac_address, new_bssid,
3548                    MIN(sizeof(new_bssid), sizeof(mlan_802_11_mac_addr)));
3549     (void)__memcpy(pmadapter, (t_u8 *)&pnew_entry->multi_bssid_ap_addr, (t_u8 *)&pbss_entry->mac_address,
3550                    MIN(sizeof(mlan_802_11_mac_addr), sizeof(mlan_802_11_mac_addr)));
3551 }
3552 
3553 /**
3554  *  @brief This function parse the non_trans_bssid_profile
3555  *
3556  *  @param pmadapter        A pointer to mlan_adapter structure
3557  *  @param pbss_entry       A pointer to BSSDescriptor_t which has multi-bssid
3558  * IE
3559  *  @param pbss_profile     A pointer to IEEEtypes_NonTransBSSIDprofile_t
3560  *  @param num_in_table     A pointer to buffer to save num of entry in scan
3561  * table.
3562  *  @param  max_bssid_indicator max bssid indicator
3563  *
3564  *  @return                 N/A
3565  */
wlan_parse_non_trans_bssid_profile(mlan_private * pmpriv,BSSDescriptor_t * pbss_entry,IEEEtypes_NonTransBSSIDProfile_t * pbss_profile,t_u32 * num_in_table,t_u8 max_bssid_indicator)3566 static t_void wlan_parse_non_trans_bssid_profile(mlan_private *pmpriv,
3567                                                  BSSDescriptor_t *pbss_entry,
3568                                                  IEEEtypes_NonTransBSSIDProfile_t *pbss_profile,
3569                                                  t_u32 *num_in_table,
3570                                                  t_u8 max_bssid_indicator)
3571 {
3572     mlan_adapter *pmadapter                   = pmpriv->adapter;
3573     IEEEtypes_Header_t *pheader               = (IEEEtypes_Header_t *)pbss_profile->profile_data;
3574     IEEEtypes_MultiBSSIDIndex_t *pbssid_index = MNULL;
3575     IEEEtypes_Ssid_t *pssid                   = MNULL;
3576     IEEEtypes_Generic_t *prsn                 = MNULL;
3577     IEEEtypes_NotxBssCap_t *pcap              = (IEEEtypes_NotxBssCap_t *)pbss_profile->profile_data;
3578     t_u8 *pos                                 = pbss_profile->profile_data;
3579     t_s8 left_len                             = pbss_profile->ieee_hdr.len;
3580     t_u8 ret                                  = MFALSE;
3581     t_u32 bss_idx;
3582     t_u32 lowest_rssi_index        = 0;
3583     t_u32 num_in_tbl               = *num_in_table;
3584     mlan_callbacks *pcb            = (pmlan_callbacks)&pmadapter->callbacks;
3585     BSSDescriptor_t *bss_new_entry = MNULL;
3586 #if CONFIG_WPA_SUPP
3587     t_u8 *pbeacon_buf = MNULL;
3588 #endif
3589     IEEEtypes_ExtCap_t *pextcap = MNULL;
3590     IEEEtypes_Generic_t *prsnx  = MNULL;
3591 
3592     ENTER();
3593 
3594     /* The first element within the Nontransmitted
3595      * BSSID Profile is not the Nontransmitted
3596      * BSSID Capability element.
3597      */
3598     if (pcap->element_id != NONTX_BSSID_CAP || pcap->len != 2)
3599     {
3600         PRINTM(MERROR,
3601                "The first element within the Nontransmitted BSSID Profile is not the NontransmittedBSSID Capability "
3602                "element\n");
3603         LEAVE();
3604         return;
3605     }
3606 
3607     while (left_len >= 2)
3608     {
3609         pheader = (IEEEtypes_Header_t *)pos;
3610         if ((t_s8)(pheader->len + sizeof(IEEEtypes_Header_t)) > left_len)
3611         {
3612             PRINTM(MMSG, "invalid IE length = %d left len %d\n", pheader->len, left_len);
3613             break;
3614         }
3615         switch (pheader->element_id)
3616         {
3617             case MBSSID_INDEX:
3618                 pbssid_index = (IEEEtypes_MultiBSSIDIndex_t *)pos;
3619                 if (pbssid_index->bssid_index == 0 || pbssid_index->bssid_index > 46)
3620                 {
3621                     PRINTM(MERROR, " No valid Multiple BSSID-Index element\n");
3622                     goto done;
3623                 }
3624                 PRINTM(MCMND, "MBSSID: Find mbssid_index=%d\n", pbssid_index->bssid_index);
3625                 ret = MTRUE;
3626                 break;
3627             case EXT_CAPABILITY:
3628                 pextcap = (IEEEtypes_ExtCap_t *)pos;
3629                 DBG_HEXDUMP(MCMD_D, "MBSSID extcap", pos, pextcap->ieee_hdr.len + sizeof(IEEEtypes_Header_t));
3630                 break;
3631             case RSNX_IE:
3632                 prsnx = (IEEEtypes_Generic_t *)pos;
3633                 DBG_HEXDUMP(MCMD_D, "MBSSID RSNX", pos, prsnx->ieee_hdr.len + sizeof(IEEEtypes_Header_t));
3634                 break;
3635             case SSID:
3636                 pssid = (IEEEtypes_Ssid_t *)pos;
3637                 PRINTM(MCMND, "MBSSID: Find mbssid ssid=%s\n", pssid->ssid);
3638                 break;
3639             case RSN_IE:
3640                 prsn = (IEEEtypes_Generic_t *)pos;
3641                 DBG_HEXDUMP(MCMD_D, "MBSSID RSN", pos, prsn->ieee_hdr.len + sizeof(IEEEtypes_Header_t));
3642                 break;
3643             default:
3644                 break;
3645         }
3646         left_len -= pheader->len + sizeof(IEEEtypes_Header_t);
3647         pos += pheader->len + sizeof(IEEEtypes_Header_t);
3648     }
3649     if (ret == MTRUE)
3650     {
3651 #if !CONFIG_MEM_POOLS
3652         ret = pcb->moal_malloc(pmadapter->pmoal_handle, sizeof(BSSDescriptor_t), MLAN_MEM_DEF, (t_u8 **)&bss_new_entry);
3653         if (ret != MLAN_STATUS_SUCCESS || !bss_new_entry)
3654         {
3655             PRINTM(MERROR, "Memory allocation for bss_new_entry failed!\n");
3656             goto done;
3657         }
3658 #else
3659 #if CONFIG_MULTI_BSSID_SUPPORT
3660         bss_new_entry = &s2_bss_new_entry;
3661 #endif
3662 #endif
3663         (void)__memcpy(pmadapter, bss_new_entry, pbss_entry, sizeof(BSSDescriptor_t));
3664         wlan_gen_multi_bssid_by_bssid_index(pmadapter, pbss_entry, bss_new_entry, pbssid_index->bssid_index,
3665                                             max_bssid_indicator);
3666         if (pssid)
3667         {
3668             __memset(pmadapter, (t_u8 *)&bss_new_entry->ssid, 0, sizeof(mlan_802_11_ssid));
3669             bss_new_entry->ssid.ssid_len = pssid->len;
3670             (void)__memcpy(pmadapter, bss_new_entry->ssid.ssid, pssid->ssid, MIN(pssid->len, MLAN_MAX_SSID_LENGTH));
3671             if (MLAN_STATUS_SUCCESS !=
3672                 wlan_update_ssid_in_beacon_buf(pmadapter, pbss_entry, bss_new_entry, pssid, pextcap, prsnx, prsn))
3673             {
3674                 PRINTM(MERROR, "Fail to update MBSSID beacon buf\n");
3675                 pcb->moal_mfree(pmadapter->pmoal_handle, (t_u8 *)bss_new_entry);
3676                 goto done;
3677             }
3678 #if CONFIG_WPA_SUPP
3679             pbeacon_buf = bss_new_entry->pbeacon_buf;
3680 #endif
3681         }
3682         (void)__memcpy(pmadapter, &bss_new_entry->cap_info, &pcap->cap,
3683                        MIN(sizeof(IEEEtypes_CapInfo_t), sizeof(IEEEtypes_CapInfo_t)));
3684         bss_new_entry->multi_bssid_ap = MULTI_BSSID_SUB_AP;
3685 #if CONFIG_WPA_SUPP
3686         if (pmadapter->wpa_supp_scan_triggered == MTRUE)
3687         {
3688             wifi_d("Alloc ies for Multi BSS. ies_len=%d", bss_new_entry->beacon_buf_size);
3689             bss_new_entry->ies = (u8 *)OSA_MemoryAllocate(bss_new_entry->beacon_buf_size - BEACON_FIX_SIZE);
3690             if (bss_new_entry->ies == MNULL)
3691             {
3692                 wifi_d("Failed to alloc memory for Multi BSS ies");
3693                 goto done;
3694             }
3695             (void)__memcpy(pmadapter, bss_new_entry->ies, bss_new_entry->pbeacon_buf + BEACON_FIX_SIZE,
3696                            bss_new_entry->beacon_buf_size - BEACON_FIX_SIZE);
3697             bss_new_entry->ies_len = bss_new_entry->beacon_buf_size;
3698         }
3699 #endif
3700         /*add to scan table*/
3701         /*
3702          * Search the scan table for the same bssid
3703          */
3704         for (bss_idx = 0; bss_idx < num_in_tbl; bss_idx++)
3705         {
3706             if (!__memcmp(pmadapter, bss_new_entry->mac_address, pmadapter->pscan_table[bss_idx].mac_address,
3707                           sizeof(bss_new_entry->mac_address)))
3708             {
3709                 /*
3710                  * If the SSID matches as well, it is a duplicate of
3711                  *   this entry.  Keep the bss_idx set to this
3712                  *   entry so we replace the old contents in the table
3713                  */
3714                 if ((bss_new_entry->ssid.ssid_len == pmadapter->pscan_table[bss_idx].ssid.ssid_len) &&
3715                     (!__memcmp(pmadapter, bss_new_entry->ssid.ssid, pmadapter->pscan_table[bss_idx].ssid.ssid,
3716                                bss_new_entry->ssid.ssid_len)))
3717                 {
3718                     PRINTM(MINFO, "SCAN_RESP: Duplicate of index: %d\n", bss_idx);
3719                     break;
3720                 }
3721             }
3722         }
3723         if (bss_idx == num_in_tbl)
3724         {
3725             /* Range check the bss_idx, keep it limited to the last entry */
3726             if (bss_idx == MRVDRV_MAX_BSSID_LIST)
3727             {
3728                 lowest_rssi_index = wlan_find_worst_network_in_list(pmadapter->pscan_table, MRVDRV_MAX_BSSID_LIST);
3729             }
3730             else
3731             {
3732                 num_in_tbl++;
3733             }
3734         }
3735 
3736         if (bss_idx == MRVDRV_MAX_BSSID_LIST)
3737         {
3738             if (pmadapter->pscan_table[lowest_rssi_index].rssi > bss_new_entry->rssi)
3739             {
3740 #if CONFIG_WPA_SUPP
3741                 if (pmadapter->pscan_table[lowest_rssi_index].ies != NULL)
3742                 {
3743                     OSA_MemoryFree(pmadapter->pscan_table[lowest_rssi_index].ies);
3744                     pmadapter->pscan_table[lowest_rssi_index].ies = NULL;
3745                 }
3746 #endif
3747                 (void)__memcpy(pmadapter, &pmadapter->pscan_table[lowest_rssi_index], bss_new_entry,
3748                                sizeof(pmadapter->pscan_table[lowest_rssi_index]));
3749                 adjust_pointers_to_internal_buffers(&pmadapter->pscan_table[lowest_rssi_index], bss_new_entry);
3750             }
3751 #if CONFIG_WPA_SUPP
3752             /* If the scan table is full, free ies of the new entry with lowest rssi, which won't be added into table */
3753             else
3754             {
3755                 if (bss_new_entry->ies != NULL)
3756                 {
3757                     OSA_MemoryFree(bss_new_entry->ies);
3758                     bss_new_entry->ies = NULL;
3759                 }
3760             }
3761 #endif
3762         }
3763         else
3764         {
3765             /* Copy the locally created bss_new_entry to the scan table */
3766 #if CONFIG_WPA_SUPP
3767             if (pmadapter->pscan_table[bss_idx].ies != NULL)
3768             {
3769                 OSA_MemoryFree(pmadapter->pscan_table[bss_idx].ies);
3770                 pmadapter->pscan_table[bss_idx].ies = NULL;
3771             }
3772 #endif
3773             (void)__memcpy(pmadapter, &pmadapter->pscan_table[bss_idx], bss_new_entry,
3774                            sizeof(pmadapter->pscan_table[bss_idx]));
3775             adjust_pointers_to_internal_buffers(&pmadapter->pscan_table[bss_idx], bss_new_entry);
3776         }
3777 #if CONFIG_WPA_SUPP
3778         if (pssid && pbeacon_buf)
3779             pcb->moal_mfree(pmadapter->pmoal_handle, (t_u8 *)pbeacon_buf);
3780 #endif
3781 #if !CONFIG_MEM_POOLS
3782         pcb->moal_mfree(pmadapter->pmoal_handle, (t_u8 *)bss_new_entry);
3783 #endif
3784     }
3785 done:
3786     *num_in_table = num_in_tbl;
3787     LEAVE();
3788     return;
3789 }
3790 
3791 /**
3792  *  @brief This function parse the multi_bssid IE from pbss_entry
3793  *
3794  *  @param pmpriv        A pointer to mlan_private structure
3795  *  @param pbss_entry       A pointer to BSSDescriptor_t which has multi-bssid
3796  * IE
3797  *  @param num_in_table     A pointer to buffer to save num of entry in scan
3798  * table.
3799  *
3800  *  @return                 number entry in scan table
3801  */
wlan_parse_multi_bssid_ie(mlan_private * pmpriv,BSSDescriptor_t * pbss_entry,IEEEtypes_MultiBSSID_t * pmulti_bssid,t_u32 * num_in_table)3802 static t_void wlan_parse_multi_bssid_ie(mlan_private *pmpriv,
3803                                         BSSDescriptor_t *pbss_entry,
3804                                         IEEEtypes_MultiBSSID_t *pmulti_bssid,
3805                                         t_u32 *num_in_table)
3806 {
3807     t_u32 bytes_left                                 = 0;
3808     t_u8 *pcurrent_ptr                               = MNULL;
3809     IEEEtypes_NonTransBSSIDProfile_t *pbssid_profile = MNULL;
3810 
3811     if (!pmulti_bssid)
3812         return;
3813     bytes_left   = pmulti_bssid->ieee_hdr.len - 1;
3814     pcurrent_ptr = pmulti_bssid->sub_elem_data;
3815     while (bytes_left >= 2)
3816     {
3817         pbssid_profile = (IEEEtypes_NonTransBSSIDProfile_t *)pcurrent_ptr;
3818         if (pbssid_profile->ieee_hdr.element_id != NONTRANS_BSSID_PROFILE_SUBELEM_ID)
3819         {
3820             PRINTM(MERROR, "Invalid multi-bssid IE\n");
3821             break;
3822         }
3823         if (bytes_left < (t_u32)(pbssid_profile->ieee_hdr.len + 2))
3824         {
3825             PRINTM(MERROR, "Invalid multi-bssid IE\n");
3826             break;
3827         }
3828         wlan_parse_non_trans_bssid_profile(pmpriv, pbss_entry, pbssid_profile, num_in_table,
3829                                            pmulti_bssid->max_bssid_indicator);
3830         pcurrent_ptr += pbssid_profile->ieee_hdr.len + 2;
3831         bytes_left -= pbssid_profile->ieee_hdr.len + 2;
3832     }
3833     return;
3834 }
3835 
3836 /**
3837  *  @brief This function search all the mbssid IE in the beacon buffer
3838  *
3839  *  @param pmpriv           A pointer to mlan_private structure
3840  *  @param pbss_entry       A pointer to BSSDescriptor_t which has multi-bssid
3841  * IE
3842  *  @param num_in_table     A pointer to buffer to save num of entry in scan
3843  * table.
3844  *
3845  *  @return                 N/A
3846  */
wlan_parse_multi_bssid_ap(mlan_private * pmpriv,BSSDescriptor_t * pbss_entry,t_u32 * num_in_table)3847 static void wlan_parse_multi_bssid_ap(mlan_private *pmpriv, BSSDescriptor_t *pbss_entry, t_u32 *num_in_table)
3848 {
3849     IEEEtypes_ElementId_e element_id;
3850     t_u8 element_len;
3851     t_u16 total_ie_len;
3852     t_u32 bytes_left        = pbss_entry->beacon_buf_size - BEACON_FIX_SIZE;
3853     t_u8 *pcurrent_ptr      = pbss_entry->pbeacon_buf + BEACON_FIX_SIZE;
3854     IEEEtypes_Ssid_t *pssid = (IEEEtypes_Ssid_t *)pcurrent_ptr;
3855 
3856     if (pssid->element_id != SSID)
3857     {
3858         PRINTM(MERROR, "Invalid beacon ie, ssid should be in the first element\n");
3859         return;
3860     }
3861     /* Process variable IE */
3862     while (bytes_left >= 2)
3863     {
3864         element_id   = (IEEEtypes_ElementId_e)(*((t_u8 *)pcurrent_ptr));
3865         element_len  = *((t_u8 *)pcurrent_ptr + 1);
3866         total_ie_len = element_len + sizeof(IEEEtypes_Header_t);
3867 
3868         if (bytes_left < total_ie_len)
3869         {
3870             PRINTM(MERROR,
3871                    "InterpretIE: Error in processing IE, "
3872                    "bytes left < IE length\n");
3873             bytes_left = 0;
3874             continue;
3875         }
3876         if (element_id == MULTI_BSSID)
3877             wlan_parse_multi_bssid_ie(pmpriv, pbss_entry, (IEEEtypes_MultiBSSID_t *)pcurrent_ptr, num_in_table);
3878         pcurrent_ptr += total_ie_len;
3879         bytes_left -= total_ie_len;
3880     }
3881     return;
3882 }
3883 #endif
3884 
3885 /**
3886  *  @brief This function parse and store the extended scan results
3887  *
3888  *  @param pmpriv           A pointer to mlan_private structure
3889  *  @param number_of_sets   Number of BSS
3890  *  @param pscan_resp       A pointer to scan response buffer
3891  *  @param scan_resp_size   Size of scan response buffer
3892  *
3893  *  @return             MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
3894  */
wlan_parse_ext_scan_result(IN mlan_private * pmpriv,IN t_u8 number_of_sets,IN t_u8 * pscan_resp,IN t_u16 scan_resp_size)3895 static mlan_status wlan_parse_ext_scan_result(IN mlan_private *pmpriv,
3896                                               IN t_u8 number_of_sets,
3897                                               IN t_u8 *pscan_resp,
3898                                               IN t_u16 scan_resp_size)
3899 {
3900     mlan_status ret         = MLAN_STATUS_SUCCESS;
3901     mlan_adapter *pmadapter = pmpriv->adapter;
3902 #if !CONFIG_MEM_POOLS
3903     mlan_callbacks *pcb = MNULL;
3904 #endif
3905     BSSDescriptor_t *bss_new_entry = MNULL;
3906     t_u8 *pbss_info;
3907     t_u32 bytes_left;
3908     t_u32 bytes_left_for_tlv;
3909     t_u32 num_in_table;
3910     t_u32 bss_idx;
3911     t_u32 idx;
3912     t_u32 idx2;
3913     t_u64 tsf_val;
3914     const chan_freq_power_t *cfp;
3915     t_u16 tlv_type, tlv_len;
3916     MrvlIEtypes_Data_t *ptlv                    = MNULL;
3917     MrvlIEtypes_Bss_Scan_Rsp_t *pscan_rsp_tlv   = MNULL;
3918     MrvlIEtypes_Bss_Scan_Info_t *pscan_info_tlv = MNULL;
3919     t_u16 band;
3920     /* t_u32 age_ts_usec; */
3921     t_u32 lowest_rssi_index              = 0;
3922     t_u8 null_ssid[MLAN_MAX_SSID_LENGTH] = {0};
3923 
3924     ENTER();
3925 
3926 #if !CONFIG_MEM_POOLS
3927     pcb = (pmlan_callbacks)&pmadapter->callbacks;
3928 #endif
3929 
3930     bytes_left = scan_resp_size;
3931     PRINTM(MINFO, "EXT_SCAN: bss_descript_size %d\n", scan_resp_size);
3932     PRINTM(MINFO, "EXT_SCAN: returned %d APs before parsing\n", number_of_sets);
3933 
3934     if ((number_of_sets == 0U) && (bytes_left == 0U))
3935     {
3936         wscan_d("SCAN_RESP: number of sets are zero");
3937         goto done;
3938     }
3939 
3940     num_in_table = pmadapter->num_in_scan_table;
3941     ptlv         = (MrvlIEtypes_Data_t *)pscan_resp;
3942 
3943     /*
3944      *  Process each scan response returned number_of_sets. Save
3945      *    the information in the bss_new_entry and then insert into the
3946      *    driver scan table either as an update to an existing entry
3947      *    or as an addition at the end of the table
3948      */
3949 #if !CONFIG_MEM_POOLS
3950     ret = pcb->moal_malloc(pmadapter->pmoal_handle, sizeof(BSSDescriptor_t), MLAN_MEM_DEF, (t_u8 **)&bss_new_entry);
3951 
3952     if (ret != MLAN_STATUS_SUCCESS || !bss_new_entry)
3953     {
3954         PRINTM(MERROR, "Memory allocation for bss_new_entry failed!\n");
3955         ret = MLAN_STATUS_FAILURE;
3956         goto done;
3957     }
3958 #else
3959     bss_new_entry = &s_bss_new_entry;
3960 #endif
3961 
3962     for (idx = 0; idx < number_of_sets && bytes_left > sizeof(MrvlIEtypesHeader_t); idx++)
3963     {
3964         tlv_type = wlan_le16_to_cpu(ptlv->header.type);
3965         tlv_len  = wlan_le16_to_cpu(ptlv->header.len);
3966         if (bytes_left < sizeof(MrvlIEtypesHeader_t) + tlv_len)
3967         {
3968             PRINTM(MERROR, "EXT_SCAN: Error bytes left < TLV length\n");
3969             break;
3970         }
3971         pscan_rsp_tlv      = MNULL;
3972         pscan_info_tlv     = MNULL;
3973         bytes_left_for_tlv = bytes_left;
3974         /* BSS response TLV with beacon or probe response buffer at the initial
3975            position of each descriptor */
3976         if (tlv_type == TLV_TYPE_BSS_SCAN_RSP)
3977         {
3978             pbss_info     = (t_u8 *)ptlv;
3979             pscan_rsp_tlv = (MrvlIEtypes_Bss_Scan_Rsp_t *)ptlv;
3980             ptlv          = (MrvlIEtypes_Data_t *)(ptlv->data + tlv_len);
3981             bytes_left_for_tlv -= (tlv_len + sizeof(MrvlIEtypesHeader_t));
3982         }
3983         else
3984             break;
3985 
3986         /* Process variable TLV */
3987         // coverity[sensitive_memory_access:SUPPRESS]
3988         while (bytes_left_for_tlv >= sizeof(MrvlIEtypesHeader_t) &&
3989                wlan_le16_to_cpu(ptlv->header.type) != TLV_TYPE_BSS_SCAN_RSP)
3990         {
3991             /* Barriers are normally not required but do ensure the code is
3992              * completely within the specified behaviour for the architecture. */
3993             __asm volatile("dsb" ::: "memory");
3994             __asm volatile("isb");
3995             tlv_type = wlan_le16_to_cpu(ptlv->header.type);
3996             tlv_len  = wlan_le16_to_cpu(ptlv->header.len);
3997             if (bytes_left_for_tlv < sizeof(MrvlIEtypesHeader_t) + tlv_len)
3998             {
3999                 PRINTM(MERROR,
4000                        "EXT_SCAN: Error in processing TLV, "
4001                        "bytes left < TLV length\n");
4002                 pscan_rsp_tlv      = MNULL;
4003                 bytes_left_for_tlv = 0;
4004                 continue;
4005             }
4006             switch (tlv_type)
4007             {
4008                 case TLV_TYPE_BSS_SCAN_INFO:
4009                     pscan_info_tlv = (MrvlIEtypes_Bss_Scan_Info_t *)ptlv;
4010                     if (tlv_len != sizeof(MrvlIEtypes_Bss_Scan_Info_t) - sizeof(MrvlIEtypesHeader_t))
4011                     {
4012                         bytes_left_for_tlv = 0;
4013                         continue;
4014                     }
4015                     break;
4016                 default:
4017                     PRINTM(MINFO, "Unexpected tlv in scan result\n");
4018                     break;
4019             }
4020             ptlv = (MrvlIEtypes_Data_t *)(ptlv->data + tlv_len);
4021             bytes_left -= (tlv_len + sizeof(MrvlIEtypesHeader_t));
4022             bytes_left_for_tlv -= (tlv_len + sizeof(MrvlIEtypesHeader_t));
4023         }
4024         /* No BSS response TLV */
4025         if (pscan_rsp_tlv == MNULL)
4026             break;
4027 
4028         /* Advance pointer to the beacon buffer length and update the bytes
4029            count so that the function wlan_interpret_bss_desc_with_ie() can
4030            handle the scan buffer withut any change */
4031         pbss_info += sizeof(t_u16);
4032         bytes_left -= sizeof(t_u16);
4033 
4034         /* Zero out the bss_new_entry we are about to store info in */
4035         (void)__memset(pmadapter, bss_new_entry, 0x00, sizeof(BSSDescriptor_t));
4036 
4037         /* Process the data fields and IEs returned for this BSS */
4038         if (wlan_interpret_bss_desc_with_ie(pmadapter, bss_new_entry, &pbss_info, &bytes_left, MTRUE) ==
4039             MLAN_STATUS_SUCCESS)
4040         {
4041             PRINTM(MINFO, "EXT_SCAN: BSSID = %02x:%02x:%02x:%02x:%02x:%02x\n", bss_new_entry->mac_address[0],
4042                    bss_new_entry->mac_address[1], bss_new_entry->mac_address[2], bss_new_entry->mac_address[3],
4043                    bss_new_entry->mac_address[4], bss_new_entry->mac_address[5]);
4044 
4045 #if CONFIG_WPA_SUPP
4046 #if CONFIG_WPA_SUPP_WPS
4047             if (pmpriv->wps.session_enable == MTRUE)
4048             {
4049                 if ((bss_new_entry->wps_IE_exist == MFALSE) || (bss_new_entry->wps_session == 0xffff))
4050                 {
4051                     if (bss_new_entry->ies != NULL)
4052                     {
4053                         OSA_MemoryFree(bss_new_entry->ies);
4054                         bss_new_entry->ies = NULL;
4055                     }
4056                     continue;
4057                 }
4058             }
4059 #endif /* CONFIG_WPA_SUPP_WPS */
4060 #endif
4061 
4062             band = BAND_G;
4063             /*
4064              * If the BSS info TLV was appended to the scan results, save
4065              *   this entry's TSF value in the networkTSF field. The
4066              *   networkTSF is the firmware's TSF value at the time the
4067              *   beacon or probe response was received.
4068              */
4069             if (pscan_info_tlv)
4070             {
4071                 /* RSSI is 2 byte long */
4072                 bss_new_entry->rssi = -(t_s32)(wlan_le16_to_cpu(pscan_info_tlv->rssi));
4073 #if 0
4074                 if(bss_new_entry->rssi > 0x7f)
4075                     bss_new_entry->rssi = - (256 - bss_new_entry->rssi);
4076 #endif
4077                 PRINTM(MINFO, "EXT_SCAN: RSSI=%d\n", bss_new_entry->rssi);
4078                 (void)__memcpy(pmpriv->adapter, &tsf_val, &pscan_info_tlv->tsf, sizeof(tsf_val));
4079                 tsf_val = wlan_le64_to_cpu(tsf_val);
4080                 (void)__memcpy(pmpriv->adapter, &bss_new_entry->network_tsf, &tsf_val,
4081                                sizeof(bss_new_entry->network_tsf));
4082                 band = radio_type_to_band(pscan_info_tlv->band);
4083                 if (bss_new_entry->channel == 0)
4084                     bss_new_entry->channel = pscan_info_tlv->channel;
4085             }
4086             /* Save the band designation for this entry for use in join */
4087             bss_new_entry->bss_band = band;
4088             cfp = wlan_find_cfp_by_band_and_channel(pmadapter, bss_new_entry->bss_band, (t_u16)bss_new_entry->channel);
4089 
4090             if (cfp)
4091                 bss_new_entry->freq = cfp->freq;
4092             else
4093                 bss_new_entry->freq = 0;
4094 #if CONFIG_MULTI_BSSID_SUPPORT
4095             if (IS_FW_SUPPORT_MULTIBSSID(pmadapter))
4096             {
4097                 if (bss_new_entry->multi_bssid_ap == MULTI_BSSID_AP)
4098                     wlan_parse_multi_bssid_ap(pmpriv, bss_new_entry, &num_in_table);
4099             }
4100 #endif
4101 
4102             if (pmpriv->ssid_filter)
4103             {
4104                 for (idx2 = 0; idx2 < NELEMENTS(pmpriv->filter_ssid); idx2 ++)
4105                 {
4106                     if (pmpriv->filter_ssid[idx2].ssid_len && (bss_new_entry->ssid.ssid_len == pmpriv->filter_ssid[idx2].ssid_len)
4107                        && (!__memcmp(pmadapter, bss_new_entry->ssid.ssid, pmpriv->filter_ssid[idx2].ssid, bss_new_entry->ssid.ssid_len)))
4108                     {
4109                         break;
4110                     }
4111                 }
4112 
4113                 if (idx2 == NELEMENTS(pmpriv->filter_ssid))
4114                 {
4115 #if CONFIG_WPA_SUPP
4116                     if (bss_new_entry->ies != NULL)
4117                     {
4118                         OSA_MemoryFree(bss_new_entry->ies);
4119                         bss_new_entry->ies = NULL;
4120                     }
4121 #endif
4122                     continue;
4123                 }
4124             }
4125 
4126             /*
4127              * Search the scan table for the same bssid
4128              */
4129             for (bss_idx = 0; bss_idx < num_in_table; bss_idx++)
4130             {
4131                 if (!__memcmp(pmadapter, bss_new_entry->mac_address, pmadapter->pscan_table[bss_idx].mac_address,
4132                               sizeof(bss_new_entry->mac_address)))
4133                 {
4134                     /*
4135                      * If the SSID matches as well, it is a duplicate of
4136                      *   this entry.  Keep the bss_idx set to this
4137                      *   entry so we replace the old contents in the table
4138                      */
4139                     if ((bss_new_entry->ssid.ssid_len == pmadapter->pscan_table[bss_idx].ssid.ssid_len) &&
4140                         (!__memcmp(pmadapter, bss_new_entry->ssid.ssid, pmadapter->pscan_table[bss_idx].ssid.ssid,
4141                                    bss_new_entry->ssid.ssid_len)))
4142                     {
4143                         PRINTM(MINFO, "EXT_SCAN: Duplicate of index: %d\n", bss_idx);
4144                         break;
4145                     }
4146                     /*
4147                      * If the SSID is NULL for same BSSID
4148                      * keep the bss_idx set to this entry
4149                      * so we replace the old contents in
4150                      * the table
4151                      */
4152                     if (!__memcmp(pmadapter, pmadapter->pscan_table[bss_idx].ssid.ssid, null_ssid,
4153                                   pmadapter->pscan_table[bss_idx].ssid.ssid_len))
4154                     {
4155                         PRINTM(MINFO, "SCAN_RESP: Duplicate of index: %d\n", bss_idx);
4156                         break;
4157                     }
4158                 }
4159             }
4160             /*
4161              * If the bss_idx is equal to the number of entries in the table,
4162              *   the new entry was not a duplicate; append it to the scan
4163              *   table
4164              */
4165             if (bss_idx == num_in_table)
4166             {
4167                 /* Range check the bss_idx, keep it limited to the last entry */
4168                 if (bss_idx == MRVDRV_MAX_BSSID_LIST)
4169                 {
4170                     lowest_rssi_index = wlan_find_worst_network_in_list(pmadapter->pscan_table, MRVDRV_MAX_BSSID_LIST);
4171                 }
4172                 else
4173                 {
4174                     num_in_table++;
4175                 }
4176             }
4177             else
4178             {
4179                 if ((bss_new_entry->channel != pmadapter->pscan_table[bss_idx].channel) &&
4180                     (bss_new_entry->rssi > pmadapter->pscan_table[bss_idx].rssi))
4181                 {
4182                     PRINTM(MCMND, "skip update the duplicate entry with low rssi\n");
4183 #if CONFIG_WPA_SUPP
4184                     if (bss_new_entry->ies != NULL)
4185                     {
4186                         OSA_MemoryFree(bss_new_entry->ies);
4187                         bss_new_entry->ies = NULL;
4188                     }
4189 #endif
4190                     continue;
4191                 }
4192             }
4193 
4194             if (bss_idx == MRVDRV_MAX_BSSID_LIST)
4195             {
4196                 if (pmadapter->pscan_table[lowest_rssi_index].rssi > bss_new_entry->rssi)
4197                 {
4198 #if CONFIG_WPA_SUPP
4199                     if (pmadapter->pscan_table[lowest_rssi_index].ies != NULL)
4200                     {
4201                         OSA_MemoryFree(pmadapter->pscan_table[lowest_rssi_index].ies);
4202                         pmadapter->pscan_table[lowest_rssi_index].ies = NULL;
4203                     }
4204 #endif
4205                     (void)__memcpy(pmadapter, &pmadapter->pscan_table[lowest_rssi_index], bss_new_entry,
4206                                    sizeof(pmadapter->pscan_table[lowest_rssi_index]));
4207                     adjust_pointers_to_internal_buffers(&pmadapter->pscan_table[lowest_rssi_index], bss_new_entry);
4208                 }
4209 #if CONFIG_WPA_SUPP
4210                 /* If the scan table is full, free ies of the new entry with lowest rssi, which won't be added into
4211                  * table */
4212                 else
4213                 {
4214                     if (bss_new_entry->ies != NULL)
4215                     {
4216                         OSA_MemoryFree(bss_new_entry->ies);
4217                         bss_new_entry->ies = NULL;
4218                     }
4219                 }
4220 #endif
4221             }
4222             else
4223             {
4224                 /* Copy the locally created bss_new_entry to the scan table */
4225 #if CONFIG_WPA_SUPP
4226                 if (pmadapter->pscan_table[bss_idx].ies != NULL)
4227                 {
4228                     OSA_MemoryFree(pmadapter->pscan_table[bss_idx].ies);
4229                     pmadapter->pscan_table[bss_idx].ies = NULL;
4230                 }
4231 #endif
4232                 (void)__memcpy(pmadapter, &pmadapter->pscan_table[bss_idx], bss_new_entry,
4233                                sizeof(pmadapter->pscan_table[bss_idx]));
4234                 adjust_pointers_to_internal_buffers(&pmadapter->pscan_table[bss_idx], bss_new_entry);
4235             }
4236         }
4237         else
4238         {
4239             /* Error parsing/interpreting the scan response, skipped */
4240             PRINTM(MERROR, "EXT_SCAN: wlan_interpret_bss_desc_with_ie returned error\n");
4241 #if CONFIG_WPA_SUPP
4242             if (bss_new_entry->ies != NULL)
4243             {
4244                 OSA_MemoryFree(bss_new_entry->ies);
4245                 bss_new_entry->ies = NULL;
4246             }
4247 #endif
4248         }
4249     }
4250 
4251     PRINTM(MINFO, "EXT_SCAN: Scanned %2d APs, %d valid, %d total\n", number_of_sets,
4252            num_in_table - pmadapter->num_in_scan_table, num_in_table);
4253 
4254     /* Update the total number of BSSIDs in the scan table */
4255     pmadapter->num_in_scan_table = num_in_table;
4256 
4257 done:
4258 #if !CONFIG_MEM_POOLS
4259     if (bss_new_entry)
4260     {
4261         pcb->moal_mfree(pmadapter->pmoal_handle, (t_u8 *)bss_new_entry);
4262     }
4263 #endif
4264 
4265     LEAVE();
4266     return ret;
4267 }
4268 
4269 /**
4270  *  @brief This function handles the event extended scan report
4271  *
4272  *  @param pmpriv       A pointer to mlan_private structure
4273  *  @param pmbuf        A pointer to mlan_buffer
4274  *
4275  *  @return             MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
4276  */
wlan_handle_event_ext_scan_report(IN mlan_private * pmpriv,IN t_u8 * pmbuf)4277 mlan_status wlan_handle_event_ext_scan_report(IN mlan_private *pmpriv, IN t_u8 *pmbuf)
4278 {
4279     /* mlan_adapter *pmadapter = pmpriv->adapter;
4280     mlan_callbacks *pcb = &pmadapter->callbacks;
4281     mlan_ioctl_req *pioctl_req = MNULL;
4282     cmd_ctrl_node *pcmd_node = MNULL; */
4283     mlan_status ret = MLAN_STATUS_SUCCESS;
4284 
4285     mlan_event_scan_result *pevent_scan = (pmlan_event_scan_result)(pmbuf);
4286     t_u8 *ptlv                          = (pmbuf + sizeof(mlan_event_scan_result));
4287     t_u16 tlv_buf_left                  = wlan_cpu_to_le16(pevent_scan->buf_size);
4288 
4289     ret = wlan_parse_ext_scan_result(pmpriv, pevent_scan->num_of_set, ptlv, tlv_buf_left);
4290 
4291 #if 0
4292     if (!pevent_scan->more_event) {
4293         pioctl_req = pmadapter->pext_scan_ioctl_req;
4294         if (!util_peek_list(pmadapter->pmoal_handle,
4295                             &pmadapter->scan_pending_q, pcb->moal_spin_lock,
4296                             pcb->moal_spin_unlock)) {
4297             pmadapter->pext_scan_ioctl_req = MNULL;
4298             wlan_request_cmd_lock(pmadapter);
4299             pmadapter->scan_processing = MFALSE;
4300             wlan_release_cmd_lock(pmadapter);
4301             /*
4302              * Process the resulting scan table:
4303              *   - Remove any bad ssids
4304              *   - Update our current BSS information from scan data
4305              */
4306             wlan_scan_process_results(pmpriv);
4307 
4308             /* Need to indicate IOCTL complete */
4309             if (pioctl_req != MNULL) {
4310                 pioctl_req->status_code = MLAN_ERROR_NO_ERROR;
4311                 /* Indicate ioctl complete */
4312                 pcb->moal_ioctl_complete(pmadapter->pmoal_handle,
4313                                          (pmlan_ioctl_req) pioctl_req,
4314                                          MLAN_STATUS_SUCCESS);
4315             }
4316             wlan_recv_event(pmpriv, MLAN_EVENT_ID_DRV_SCAN_REPORT, MNULL);
4317         } else {
4318             /* If firmware not ready, do not issue any more scan commands */
4319             if (pmadapter->hw_status != WlanHardwareStatusReady) {
4320                 /* Flush all pending scan commands */
4321                 wlan_flush_scan_queue(pmadapter);
4322                 /* Indicate IOCTL complete */
4323                 if (pioctl_req != MNULL) {
4324                     pioctl_req->status_code = MLAN_ERROR_FW_NOT_READY;
4325 
4326                     /* Indicate ioctl complete */
4327                     pcb->moal_ioctl_complete(pmadapter->pmoal_handle,
4328                                              (pmlan_ioctl_req) pioctl_req,
4329                                              MLAN_STATUS_FAILURE);
4330                 }
4331             } else {
4332                 /* Get scan command from scan_pending_q and put to
4333                    cmd_pending_q */
4334                 pcmd_node =
4335                     (cmd_ctrl_node *) util_dequeue_list(pmadapter->pmoal_handle,
4336                                                         &pmadapter->
4337                                                         scan_pending_q,
4338                                                         pcb->moal_spin_lock,
4339                                                         pcb->moal_spin_unlock);
4340                 wlan_insert_cmd_to_pending_q(pmadapter, pcmd_node, MTRUE);
4341             }
4342         }
4343     }
4344 #endif
4345     LEAVE();
4346     return ret;
4347 }
4348 #endif /* CONFIG_EXT_SCAN_SUPPORT */
4349 
4350 #if CONFIG_BG_SCAN
4351 /**
4352  *  @brief This function prepares command of bg_scan_query.
4353  *
4354  *  @param pmpriv     A pointer to mlan_private structure
4355  *  @param pcmd       A pointer to HostCmd_DS_COMMAND structure
4356  *  @param pdata_buf  Void pointer cast of a wlan_scan_cmd_config struct used
4357  *                    to set the fields/TLVs for the command sent to firmware
4358  *
4359  *  @return           MLAN_STATUS_SUCCESS
4360  */
wlan_cmd_802_11_bg_scan_query(IN mlan_private * pmpriv,IN HostCmd_DS_COMMAND * pcmd,IN t_u16 cmd_action)4361 mlan_status wlan_cmd_802_11_bg_scan_query(IN mlan_private *pmpriv, IN HostCmd_DS_COMMAND *pcmd, IN t_u16 cmd_action)
4362 {
4363     HostCmd_DS_802_11_BG_SCAN_QUERY *bg_query = &pcmd->params.bg_scan_query;
4364 
4365     ENTER();
4366 
4367     pcmd->command = wlan_cpu_to_le16(HostCmd_CMD_802_11_BG_SCAN_QUERY);
4368     pcmd->size    = wlan_cpu_to_le16(sizeof(HostCmd_DS_802_11_BG_SCAN_QUERY) + S_DS_GEN);
4369 
4370     bg_query->flush = MTRUE;
4371 
4372     LEAVE();
4373     return MLAN_STATUS_SUCCESS;
4374 }
4375 
4376 /**
4377  *  @brief Create a channel list for the driver to scan based on region info
4378  *
4379  *  Use the driver region/band information to construct a comprehensive list
4380  *    of channels to scan.  This routine is used for any scan that is not
4381  *    provided a specific channel list to scan.
4382  *
4383  *  @param pmpriv           A pointer to mlan_private structure
4384  *  @param pbg_scan_in      pointer to scan configuration parameters
4385  *  @param tlv_chan_list    A pointer to structure MrvlIEtypes_ChanListParamSet_t
4386  *
4387  *  @return                 channel number
4388  */
wlan_bgscan_create_channel_list(IN mlan_private * pmpriv,IN const wlan_bgscan_cfg * pbg_scan_in,MrvlIEtypes_ChanListParamSet_t * tlv_chan_list)4389 static t_u8 wlan_bgscan_create_channel_list(IN mlan_private *pmpriv,
4390                                             IN const wlan_bgscan_cfg *pbg_scan_in,
4391                                             MrvlIEtypes_ChanListParamSet_t *tlv_chan_list)
4392 {
4393     mlan_adapter *pmadapter = pmpriv->adapter;
4394     region_chan_t *pscan_region;
4395     const chan_freq_power_t *cfp;
4396     t_u32 region_idx;
4397     t_u32 chan_idx = 0;
4398     t_u32 next_chan;
4399     t_u8 scan_type;
4400     t_u8 radio_type;
4401 
4402     ENTER();
4403 
4404     for (region_idx = 0; region_idx < NELEMENTS(pmadapter->region_channel); region_idx++)
4405     {
4406         if (wlan_11d_is_enabled(pmpriv) && pmpriv->media_connected != MTRUE)
4407         {
4408             /* Scan all the supported chan for the first scan */
4409             if (!pmadapter->universal_channel[region_idx].valid)
4410                 continue;
4411             pscan_region = &pmadapter->universal_channel[region_idx];
4412         }
4413         else
4414         {
4415             if (!pmadapter->region_channel[region_idx].valid)
4416                 continue;
4417             pscan_region = &pmadapter->region_channel[region_idx];
4418         }
4419 
4420         if (pbg_scan_in && !pbg_scan_in->chan_list[0].chan_number &&
4421             pbg_scan_in->chan_list[0].radio_type & BAND_SPECIFIED)
4422         {
4423             radio_type = pbg_scan_in->chan_list[0].radio_type & ~BAND_SPECIFIED;
4424             if (!radio_type && (pscan_region->band != BAND_B) && (pscan_region->band != BAND_G))
4425                 continue;
4426             if (radio_type && (pscan_region->band != BAND_A))
4427                 continue;
4428         }
4429         if (!wlan_is_band_compatible(pmpriv->config_bands | pmadapter->adhoc_start_band, pscan_region->band))
4430             continue;
4431         for (next_chan = 0; next_chan < pscan_region->num_cfp; next_chan++, chan_idx++)
4432         {
4433             if (chan_idx >= WLAN_BG_SCAN_CHAN_MAX)
4434                 break;
4435             /* Set the default scan type to ACTIVE SCAN type, will later be
4436                changed to passive on a per channel basis if restricted by
4437                regulatory requirements (11d or 11h) */
4438             scan_type = MLAN_SCAN_TYPE_ACTIVE;
4439             cfp       = pscan_region->pcfp + next_chan;
4440             if (scan_type == MLAN_SCAN_TYPE_ACTIVE && wlan_11d_support_is_enabled(pmpriv))
4441             {
4442                 scan_type = wlan_11d_get_scan_type(pmpriv, pscan_region->band, (t_u8)cfp->channel,
4443                                                    &pmadapter->parsed_region_chan);
4444             }
4445             switch (pscan_region->band)
4446             {
4447 #if CONFIG_5GHz_SUPPORT
4448                 case BAND_A:
4449                     tlv_chan_list->chan_scan_param[chan_idx].radio_type = HostCmd_SCAN_RADIO_TYPE_A;
4450                     if (!wlan_11d_is_enabled(pmpriv))
4451                     {
4452                         /* 11D not available... play it safe on DFS channels */
4453                         if (wlan_11h_radar_detect_required(pmpriv, (t_u8)cfp->channel))
4454                             scan_type = MLAN_SCAN_TYPE_PASSIVE;
4455                     }
4456                     break;
4457 #endif
4458                 case BAND_B:
4459                 case BAND_G:
4460                     if (wlan_bg_scan_type_is_passive(pmpriv, (t_u8)cfp->channel))
4461                         scan_type = MLAN_SCAN_TYPE_PASSIVE;
4462                 default:
4463                     tlv_chan_list->chan_scan_param[chan_idx].radio_type = HostCmd_SCAN_RADIO_TYPE_BG;
4464                     break;
4465             }
4466 
4467             if (pbg_scan_in && pbg_scan_in->chan_list[0].scan_time)
4468             {
4469                 tlv_chan_list->chan_scan_param[chan_idx].max_scan_time =
4470                     wlan_cpu_to_le16((t_u16)pbg_scan_in->chan_list[0].scan_time);
4471                 tlv_chan_list->chan_scan_param[chan_idx].min_scan_time =
4472                     wlan_cpu_to_le16((t_u16)pbg_scan_in->chan_list[0].scan_time);
4473             }
4474             else if (scan_type == MLAN_SCAN_TYPE_PASSIVE)
4475             {
4476                 tlv_chan_list->chan_scan_param[chan_idx].max_scan_time = wlan_cpu_to_le16(pmadapter->passive_scan_time);
4477                 tlv_chan_list->chan_scan_param[chan_idx].min_scan_time = wlan_cpu_to_le16(pmadapter->passive_scan_time);
4478             }
4479             else
4480             {
4481                 tlv_chan_list->chan_scan_param[chan_idx].max_scan_time =
4482                     wlan_cpu_to_le16(pmadapter->specific_scan_time);
4483                 tlv_chan_list->chan_scan_param[chan_idx].min_scan_time =
4484                     wlan_cpu_to_le16(pmadapter->specific_scan_time);
4485             }
4486 
4487             if (scan_type == MLAN_SCAN_TYPE_PASSIVE)
4488             {
4489                 tlv_chan_list->chan_scan_param[chan_idx].chan_scan_mode.passive_scan = MTRUE;
4490             }
4491             else
4492             {
4493                 tlv_chan_list->chan_scan_param[chan_idx].chan_scan_mode.passive_scan = MFALSE;
4494             }
4495 
4496             tlv_chan_list->chan_scan_param[chan_idx].chan_number = (t_u8)cfp->channel;
4497         }
4498     }
4499 
4500     LEAVE();
4501     return chan_idx;
4502 }
4503 /**
4504  *  @brief This function prepares command of bg_scan_config
4505  *
4506  *  @param pmpriv     A pointer to mlan_private structure
4507  *  @param pcmd       A pointer to HostCmd_DS_COMMAND structure
4508  *  @param pdata_buf  Void pointer cast of a wlan_scan_cmd_config struct used
4509  *                    to set the fields/TLVs for the command sent to firmware
4510  *
4511  *  @return           MLAN_STATUS_SUCCESS
4512  */
wlan_cmd_bgscan_config(IN mlan_private * pmpriv,IN HostCmd_DS_COMMAND * pcmd,IN t_u16 cmd_action,IN t_void * pdata_buf)4513 mlan_status wlan_cmd_bgscan_config(IN mlan_private *pmpriv,
4514                                    IN HostCmd_DS_COMMAND *pcmd,
4515                                    IN t_u16 cmd_action,
4516                                    IN t_void *pdata_buf)
4517 {
4518     mlan_adapter *pmadapter                                = pmpriv->adapter;
4519     HostCmd_DS_802_11_BG_SCAN_CONFIG *bg_scan              = &pcmd->params.bg_scan_config;
4520     wlan_bgscan_cfg *bg_scan_in                            = (wlan_bgscan_cfg *)pdata_buf;
4521     t_u16 cmd_size                                         = 0;
4522     MrvlIEtypes_NumProbes_t *pnum_probes_tlv               = MNULL;
4523     MrvlIEtypes_BeaconLowRssiThreshold_t *rssi_tlv         = MNULL;
4524     MrvlIEtypes_BeaconLowSnrThreshold_t *snr_tlv           = MNULL;
4525     MrvlIEtypes_WildCardSsIdParamSet_t *pwildcard_ssid_tlv = MNULL;
4526     MrvlIEtypes_ChanListParamSet_t *tlv_chan_list          = MNULL;
4527     MrvlIEtypes_StartLater_t *tlv_start_later              = MNULL;
4528     MrvlIEtypes_RepeatCount_t *tlv_repeat                  = MNULL;
4529     MrvlIETypes_HTCap_t *pht_cap                           = MNULL;
4530 #if CONFIG_11AC
4531     MrvlIETypes_VHTCap_t *pvht_cap = MNULL;
4532 #endif
4533 #if CONFIG_11AX
4534     MrvlIEtypes_Extension_t *phe_cap = MNULL;
4535 #endif
4536 #if CONFIG_SCAN_CHANNEL_GAP
4537     MrvlIEtypes_ScanChanGap_t *pscan_gap_tlv;
4538 #endif
4539     t_u8 *tlv        = MNULL;
4540     t_u16 num_probes = 0;
4541     t_u16 len        = 0;
4542     t_u32 ssid_idx;
4543     t_u32 ssid_len = 0;
4544     t_u32 chan_idx;
4545     t_u32 chan_num;
4546     t_u8 radio_type;
4547     t_u16 scan_dur;
4548     t_u8 scan_type;
4549     t_u8 max_bgscan_chan = 0;
4550 #if CONFIG_SCAN_CHANNEL_GAP
4551     t_u16 scan_chan_gap = 0;
4552 #endif
4553 
4554     ENTER();
4555 
4556     max_bgscan_chan = WLAN_BG_SCAN_CHAN_MAX;
4557 
4558 #if CONFIG_UNII4_BAND_SUPPORT
4559 #if defined(SD9177)
4560     max_bgscan_chan = WLAN_BG_SCAN_CHAN_MAX_UNII_4;
4561 #endif
4562 #endif
4563 
4564     pcmd->command     = wlan_cpu_to_le16(HostCmd_CMD_802_11_BG_SCAN_CONFIG);
4565     bg_scan->action   = wlan_cpu_to_le16(bg_scan_in->action);
4566     bg_scan->enable   = bg_scan_in->enable;
4567     bg_scan->bss_type = bg_scan_in->bss_type;
4568     cmd_size          = sizeof(HostCmd_DS_802_11_BG_SCAN_CONFIG) + S_DS_GEN;
4569     if (bg_scan_in->scan_interval)
4570         bg_scan->scan_interval = wlan_cpu_to_le32(bg_scan_in->scan_interval);
4571     else
4572         bg_scan->scan_interval = wlan_cpu_to_le32(DEFAULT_BGSCAN_INTERVAL);
4573     bg_scan->report_condition = wlan_cpu_to_le32(bg_scan_in->report_condition);
4574 
4575     if ((bg_scan_in->action == BG_SCAN_ACT_GET)
4576 #if CONFIG_WMM_UAPSD
4577         || (bg_scan_in->action == BG_SCAN_ACT_GET_PPS_UAPSD)
4578 #endif
4579         || (!bg_scan->enable))
4580         goto done;
4581 
4582     tlv        = (t_u8 *)bg_scan + sizeof(HostCmd_DS_802_11_BG_SCAN_CONFIG);
4583     num_probes = (bg_scan_in->num_probes ? bg_scan_in->num_probes : pmadapter->scan_probes);
4584     if (num_probes)
4585     {
4586         pnum_probes_tlv = (MrvlIEtypes_NumProbes_t *)tlv;
4587         // coverity[overrun-local:SUPPRESS]
4588         // coverity[overrun-local:SUPPRESS]
4589         pnum_probes_tlv->header.type = wlan_cpu_to_le16(TLV_TYPE_NUMPROBES);
4590         pnum_probes_tlv->header.len  = wlan_cpu_to_le16(sizeof(pnum_probes_tlv->num_probes));
4591         pnum_probes_tlv->num_probes  = wlan_cpu_to_le16((t_u16)num_probes);
4592         tlv += sizeof(MrvlIEtypes_NumProbes_t);
4593         cmd_size += sizeof(MrvlIEtypes_NumProbes_t);
4594     }
4595     if (bg_scan_in->rssi_threshold)
4596     {
4597         rssi_tlv              = (MrvlIEtypes_BeaconLowRssiThreshold_t *)tlv;
4598         rssi_tlv->header.type = wlan_cpu_to_le16(TLV_TYPE_RSSI_LOW);
4599         rssi_tlv->header.len =
4600             wlan_cpu_to_le16(sizeof(MrvlIEtypes_BeaconLowRssiThreshold_t) - sizeof(MrvlIEtypesHeader_t));
4601         rssi_tlv->value     = bg_scan_in->rssi_threshold;
4602         rssi_tlv->frequency = 0;
4603         tlv += sizeof(MrvlIEtypes_BeaconLowRssiThreshold_t);
4604         cmd_size += sizeof(MrvlIEtypes_BeaconLowRssiThreshold_t);
4605     }
4606     if (bg_scan_in->snr_threshold)
4607     {
4608         snr_tlv              = (MrvlIEtypes_BeaconLowSnrThreshold_t *)tlv;
4609         snr_tlv->header.type = wlan_cpu_to_le16(TLV_TYPE_SNR_LOW);
4610         snr_tlv->header.len =
4611             wlan_cpu_to_le16(sizeof(MrvlIEtypes_BeaconLowSnrThreshold_t) - sizeof(MrvlIEtypesHeader_t));
4612         snr_tlv->value     = bg_scan_in->snr_threshold;
4613         snr_tlv->frequency = 0;
4614         tlv += sizeof(MrvlIEtypes_BeaconLowRssiThreshold_t);
4615         cmd_size += sizeof(MrvlIEtypes_BeaconLowRssiThreshold_t);
4616     }
4617     if (bg_scan_in->repeat_count)
4618     {
4619         tlv_repeat               = (MrvlIEtypes_RepeatCount_t *)tlv;
4620         tlv_repeat->header.type  = wlan_cpu_to_le16(TLV_TYPE_REPEAT_COUNT);
4621         tlv_repeat->header.len   = wlan_cpu_to_le16(sizeof(MrvlIEtypes_RepeatCount_t) - sizeof(MrvlIEtypesHeader_t));
4622         tlv_repeat->repeat_count = wlan_cpu_to_le16(bg_scan_in->repeat_count);
4623         tlv += sizeof(MrvlIEtypes_RepeatCount_t);
4624         cmd_size += sizeof(MrvlIEtypes_RepeatCount_t);
4625     }
4626 #if CONFIG_SCAN_CHANNEL_GAP
4627     scan_chan_gap = (bg_scan_in->scan_chan_gap ? bg_scan_in->scan_chan_gap : pmadapter->scan_chan_gap);
4628     if (scan_chan_gap)
4629     {
4630         pscan_gap_tlv = (MrvlIEtypes_ScanChanGap_t *)tlv;
4631         PRINTM(MCMND, "bgScan: channel gap = 0x%x\n", scan_chan_gap);
4632         pscan_gap_tlv->header.type = wlan_cpu_to_le16(TLV_TYPE_SCAN_CHANNEL_GAP);
4633         pscan_gap_tlv->header.len  = sizeof(pscan_gap_tlv->gap);
4634         pscan_gap_tlv->gap         = wlan_cpu_to_le16((t_u16)scan_chan_gap);
4635         /** indicate FW, gap is optional */
4636         pscan_gap_tlv->gap |= GAP_FLAG_OPTIONAL;
4637         tlv += sizeof(pscan_gap_tlv->header) + pscan_gap_tlv->header.len;
4638         cmd_size += sizeof(MrvlIEtypes_ScanChanGap_t);
4639     }
4640 #endif
4641     for (ssid_idx = 0; ((ssid_idx < NELEMENTS(bg_scan_in->ssid_list)) &&
4642                         (*bg_scan_in->ssid_list[ssid_idx].ssid || bg_scan_in->ssid_list[ssid_idx].max_len));
4643          ssid_idx++)
4644     {
4645         ssid_len                            = wlan_strlen((t_s8 *)bg_scan_in->ssid_list[ssid_idx].ssid);
4646         pwildcard_ssid_tlv                  = (MrvlIEtypes_WildCardSsIdParamSet_t *)tlv;
4647         pwildcard_ssid_tlv->header.type     = wlan_cpu_to_le16(TLV_TYPE_WILDCARDSSID);
4648         pwildcard_ssid_tlv->header.len      = (t_u16)(ssid_len + sizeof(pwildcard_ssid_tlv->max_ssid_length));
4649         pwildcard_ssid_tlv->max_ssid_length = bg_scan_in->ssid_list[ssid_idx].max_len;
4650 
4651         if (ssid_len != 0U)
4652         {
4653             (void)__memcpy(pmadapter, pwildcard_ssid_tlv->ssid, bg_scan_in->ssid_list[ssid_idx].ssid,
4654                            MIN(MLAN_MAX_SSID_LENGTH, ssid_len));
4655         }
4656 
4657         tlv += sizeof(pwildcard_ssid_tlv->header) + pwildcard_ssid_tlv->header.len;
4658         cmd_size += sizeof(pwildcard_ssid_tlv->header) + pwildcard_ssid_tlv->header.len;
4659         pwildcard_ssid_tlv->header.len = wlan_cpu_to_le16(pwildcard_ssid_tlv->header.len);
4660         PRINTM(MINFO, "Scan: ssid_list[%d]: %s, %d\n", ssid_idx, pwildcard_ssid_tlv->ssid,
4661                pwildcard_ssid_tlv->max_ssid_length);
4662     }
4663     if (bg_scan_in->chan_list[0].chan_number)
4664     {
4665         tlv_chan_list = (MrvlIEtypes_ChanListParamSet_t *)tlv;
4666         PRINTM(MINFO, "Scan: Using supplied channel list\n");
4667         chan_num = 0;
4668         for (chan_idx = 0; chan_idx < WLAN_BG_SCAN_CHAN_MAX && bg_scan_in->chan_list[chan_idx].chan_number; chan_idx++)
4669         {
4670             radio_type = bg_scan_in->chan_list[chan_idx].radio_type;
4671             if (!wlan_is_band_compatible(pmpriv->config_bands | pmadapter->adhoc_start_band,
4672                                          radio_type_to_band(radio_type)))
4673                 continue;
4674             scan_type = bg_scan_in->chan_list[chan_idx].scan_type;
4675             /* Prevent active scanning on a radar controlled channel */
4676 #if CONFIG_5GHz_SUPPORT
4677             if (radio_type == HostCmd_SCAN_RADIO_TYPE_A)
4678             {
4679                 if (wlan_11h_radar_detect_required(pmpriv, bg_scan_in->chan_list[chan_idx].chan_number))
4680                 {
4681                     scan_type = MLAN_SCAN_TYPE_PASSIVE;
4682                 }
4683             }
4684 #endif
4685             if (radio_type == HostCmd_SCAN_RADIO_TYPE_BG)
4686             {
4687                 if (wlan_bg_scan_type_is_passive(pmpriv, bg_scan_in->chan_list[chan_idx].chan_number))
4688                 {
4689                     scan_type = MLAN_SCAN_TYPE_PASSIVE;
4690                 }
4691             }
4692             tlv_chan_list->chan_scan_param[chan_num].chan_number = bg_scan_in->chan_list[chan_idx].chan_number;
4693             tlv_chan_list->chan_scan_param[chan_num].radio_type  = bg_scan_in->chan_list[chan_idx].radio_type;
4694 
4695             if (scan_type == MLAN_SCAN_TYPE_PASSIVE)
4696             {
4697                 tlv_chan_list->chan_scan_param[chan_num].chan_scan_mode.passive_scan = MTRUE;
4698             }
4699             else
4700             {
4701                 tlv_chan_list->chan_scan_param[chan_num].chan_scan_mode.passive_scan = MFALSE;
4702             }
4703             if (bg_scan_in->chan_list[chan_idx].scan_time)
4704             {
4705                 scan_dur = (t_u16)bg_scan_in->chan_list[chan_idx].scan_time;
4706             }
4707             else
4708             {
4709                 if (scan_type == MLAN_SCAN_TYPE_PASSIVE)
4710                 {
4711                     scan_dur = pmadapter->passive_scan_time;
4712                 }
4713                 else
4714                 {
4715                     scan_dur = pmadapter->specific_scan_time;
4716                 }
4717             }
4718             tlv_chan_list->chan_scan_param[chan_num].min_scan_time = wlan_cpu_to_le16(scan_dur);
4719             tlv_chan_list->chan_scan_param[chan_num].max_scan_time = wlan_cpu_to_le16(scan_dur);
4720             chan_num++;
4721         }
4722         tlv_chan_list->header.type = wlan_cpu_to_le16(TLV_TYPE_CHANLIST);
4723         tlv_chan_list->header.len  = wlan_cpu_to_le16(sizeof(ChanScanParamSet_t) * chan_num);
4724         tlv += sizeof(MrvlIEtypesHeader_t) + sizeof(ChanScanParamSet_t) * chan_num;
4725         cmd_size += sizeof(MrvlIEtypesHeader_t) + sizeof(ChanScanParamSet_t) * chan_num;
4726     }
4727     else
4728     {
4729         tlv_chan_list              = (MrvlIEtypes_ChanListParamSet_t *)tlv;
4730         chan_num                   = wlan_bgscan_create_channel_list(pmpriv, bg_scan_in, tlv_chan_list);
4731         tlv_chan_list->header.type = wlan_cpu_to_le16(TLV_TYPE_CHANLIST);
4732         tlv_chan_list->header.len  = wlan_cpu_to_le16(sizeof(ChanScanParamSet_t) * chan_num);
4733         tlv += sizeof(MrvlIEtypesHeader_t) + sizeof(ChanScanParamSet_t) * chan_num;
4734         cmd_size += sizeof(MrvlIEtypesHeader_t) + sizeof(ChanScanParamSet_t) * chan_num;
4735     }
4736     if (bg_scan_in->chan_per_scan)
4737     {
4738         bg_scan->chan_per_scan = MIN(max_bgscan_chan, bg_scan_in->chan_per_scan);
4739     }
4740     else
4741     {
4742         if (bg_scan_in->report_condition & BG_SCAN_WAIT_ALL_CHAN_DONE)
4743             bg_scan->chan_per_scan = chan_num;
4744         else
4745             bg_scan->chan_per_scan = MRVDRV_MAX_CHANNELS_PER_SPECIFIC_SCAN;
4746     }
4747     if (ISSUPP_11NENABLED(pmpriv->adapter->fw_cap_info) && (pmpriv->config_bands & BAND_GN
4748 #if CONFIG_5GHz_SUPPORT
4749                                                             || pmpriv->config_bands & BAND_AN
4750 #endif
4751                                                             ))
4752     {
4753         pht_cap = (MrvlIETypes_HTCap_t *)tlv;
4754         (void)__memset(pmadapter, pht_cap, 0, sizeof(MrvlIETypes_HTCap_t));
4755         pht_cap->header.type = wlan_cpu_to_le16(HT_CAPABILITY);
4756         pht_cap->header.len  = sizeof(HTCap_t);
4757         wlan_fill_ht_cap_tlv(pmpriv, pht_cap, pmpriv->config_bands);
4758         DBG_HEXDUMP(MCMD_D, "BGSCAN: HT_CAPABILITIES IE", (t_u8 *)pht_cap, sizeof(MrvlIETypes_HTCap_t));
4759         tlv += sizeof(MrvlIETypes_HTCap_t);
4760         cmd_size += sizeof(MrvlIETypes_HTCap_t);
4761         pht_cap->header.len = wlan_cpu_to_le16(pht_cap->header.len);
4762     }
4763 #if CONFIG_11AC
4764     if (ISSUPP_11ACENABLED(pmpriv->adapter->fw_cap_info) && (pmpriv->config_bands & BAND_AAC))
4765     {
4766         pvht_cap = (MrvlIETypes_VHTCap_t *)tlv;
4767         (void)__memset(pmadapter, pvht_cap, 0, sizeof(MrvlIETypes_VHTCap_t));
4768         pvht_cap->header.type = wlan_cpu_to_le16(VHT_CAPABILITY);
4769         pvht_cap->header.len  = sizeof(VHT_capa_t);
4770         wlan_fill_vht_cap_tlv(pmpriv, pvht_cap, pmpriv->config_bands, MFALSE);
4771         DBG_HEXDUMP(MCMD_D, "BGSCAN: VHT_CAPABILITIES IE", (t_u8 *)pvht_cap, sizeof(MrvlIETypes_VHTCap_t));
4772         tlv += sizeof(MrvlIETypes_VHTCap_t);
4773         cmd_size += sizeof(MrvlIETypes_VHTCap_t);
4774         pvht_cap->header.len = wlan_cpu_to_le16(pvht_cap->header.len);
4775     }
4776 #endif
4777 
4778 #if CONFIG_11AX
4779     if (IS_FW_SUPPORT_11AX(pmadapter) && ((pmpriv->config_bands & BAND_GAX) ||
4780 #if CONFIG_5GHz_SUPPORT
4781                                           (pmpriv->config_bands & BAND_AAX)
4782 #endif
4783                                               ))
4784     {
4785         phe_cap = (MrvlIEtypes_Extension_t *)tlv;
4786         len     = wlan_fill_he_cap_tlv(pmpriv, pmpriv->config_bands, phe_cap, MFALSE);
4787         DBG_HEXDUMP(MCMD_D, "BGSCAN: HE_CAPABILITIES IE", (t_u8 *)phe_cap, len);
4788         tlv += len;
4789         cmd_size += len;
4790     }
4791 #endif
4792 
4793 #if (CONFIG_DRIVER_MBO) || (CONFIG_WPA_SUPP)
4794     wlan_add_ext_capa_info_ie(pmpriv, MNULL, &tlv);
4795     cmd_size += sizeof(MrvlIETypes_ExtCap_t);
4796 #endif
4797 
4798     if (pmpriv->adapter->ecsa_enable)
4799     {
4800         t_u8 bandwidth  = BW_20MHZ;
4801         t_u8 oper_class = 1;
4802         t_u32 usr_dot_11n_dev_cap;
4803         if (pmpriv->media_connected)
4804         {
4805 #if CONFIG_5GHz_SUPPORT
4806             if (pmpriv->config_bands & BAND_A)
4807                 usr_dot_11n_dev_cap = pmadapter->usr_dot_11n_dev_cap_a;
4808             else
4809 #endif
4810                 usr_dot_11n_dev_cap = pmadapter->usr_dot_11n_dev_cap_bg;
4811             if (usr_dot_11n_dev_cap & MBIT(17))
4812             {
4813                 bandwidth = BW_40MHZ;
4814 #if CONFIG_11AC
4815                 if (ISSUPP_11ACENABLED(pmadapter->fw_cap_info) && (pmpriv->config_bands & BAND_AAC))
4816                     bandwidth = BW_80MHZ;
4817 #endif
4818             }
4819             wlan_get_curr_oper_class(pmpriv, pmpriv->curr_bss_params.bss_descriptor.channel, bandwidth, &oper_class);
4820         }
4821         len = wlan_add_supported_oper_class_ie(pmpriv, &tlv, oper_class);
4822         cmd_size += len;
4823     }
4824 
4825     tlv_start_later              = (MrvlIEtypes_StartLater_t *)tlv;
4826     tlv_start_later->header.type = wlan_cpu_to_le16(TLV_TYPE_STARTBGSCANLATER);
4827     tlv_start_later->header.len  = wlan_cpu_to_le16(sizeof(MrvlIEtypes_StartLater_t) - sizeof(MrvlIEtypesHeader_t));
4828     tlv_start_later->value       = bg_scan_in->start_later;
4829     tlv += sizeof(MrvlIEtypes_StartLater_t);
4830     cmd_size += sizeof(MrvlIEtypes_StartLater_t);
4831 done:
4832     pcmd->size = wlan_cpu_to_le16(cmd_size);
4833 
4834     LEAVE();
4835     return MLAN_STATUS_SUCCESS;
4836 }
4837 /**
4838  *  @brief This function handles the command response of extended scan
4839  *
4840  *  @param pmpriv       A pointer to mlan_private structure
4841  *  @param resp         A pointer to HostCmd_DS_COMMAND
4842  *  @param pioctl_buf   A pointer to mlan_ioctl_req structure
4843  *
4844  *  @return             MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
4845  */
wlan_ret_bgscan_config(IN mlan_private * pmpriv,IN HostCmd_DS_COMMAND * resp,IN mlan_ioctl_req * pioctl_buf)4846 mlan_status wlan_ret_bgscan_config(IN mlan_private *pmpriv, IN HostCmd_DS_COMMAND *resp, IN mlan_ioctl_req *pioctl_buf)
4847 {
4848     mlan_ds_scan *pscan                       = MNULL;
4849     HostCmd_DS_802_11_BG_SCAN_CONFIG *bg_scan = &resp->params.bg_scan_config;
4850     wlan_bgscan_cfg *bg_scan_out              = MNULL;
4851 
4852     ENTER();
4853     if (pioctl_buf)
4854     {
4855         pscan               = (mlan_ds_scan *)pioctl_buf->pbuf;
4856         bg_scan_out         = (wlan_bgscan_cfg *)pscan->param.user_scan.scan_cfg_buf;
4857         bg_scan_out->action = wlan_le16_to_cpu(bg_scan->action);
4858 #if CONFIG_WMM_UAPSD
4859         if ((bg_scan_out->action == BG_SCAN_ACT_GET) && (bg_scan_out->action == BG_SCAN_ACT_GET_PPS_UAPSD))
4860         {
4861             bg_scan_out->enable           = bg_scan->enable;
4862             bg_scan_out->bss_type         = bg_scan->bss_type;
4863             bg_scan_out->chan_per_scan    = bg_scan->chan_per_scan;
4864             bg_scan_out->scan_interval    = wlan_le32_to_cpu(bg_scan->scan_interval);
4865             bg_scan_out->report_condition = wlan_le32_to_cpu(bg_scan->report_condition);
4866             pioctl_buf->data_read_written = sizeof(mlan_ds_scan) + MLAN_SUB_COMMAND_SIZE;
4867         }
4868 #endif
4869     }
4870     LEAVE();
4871     return MLAN_STATUS_SUCCESS;
4872 }
4873 #endif
4874 
4875 /**
4876  *  @brief This function finds ssid in ssid list.
4877  *
4878  *  @param pmpriv       A pointer to mlan_private structure
4879  *  @param ssid         SSID to find in the list
4880  *  @param bssid        BSSID to qualify the SSID selection (if provided)
4881  *  @param mode         Network mode: Infrastructure or IBSS
4882  *
4883  *  @return             index in BSSID list or < 0 if error
4884  */
wlan_find_ssid_in_list(IN mlan_private * pmpriv,IN mlan_802_11_ssid * ssid,IN t_u8 * bssid,IN mlan_bss_mode mode)4885 t_s32 wlan_find_ssid_in_list(IN mlan_private *pmpriv, IN mlan_802_11_ssid *ssid, IN t_u8 *bssid, IN mlan_bss_mode mode)
4886 {
4887     mlan_adapter *pmadapter = pmpriv->adapter;
4888     t_s32 net               = -1, j;
4889     t_u8 best_rssi          = 0;
4890     t_u32 i                 = 0U;
4891 
4892     ENTER();
4893     PRINTM(MINFO, "Num of entries in scan table = %d\n", pmadapter->num_in_scan_table);
4894 
4895     /*
4896      * Loop through the table until the maximum is reached or until a match
4897      *   is found based on the bssid field comparison
4898      */
4899     while (i < pmadapter->num_in_scan_table && (bssid == MNULL || net < 0))
4900     {
4901         if ((wlan_ssid_cmp(pmadapter, &pmadapter->pscan_table[i].ssid, ssid) == 0) &&
4902             ((bssid == MNULL) ||
4903              (__memcmp(pmadapter, pmadapter->pscan_table[i].mac_address, bssid, MLAN_MAC_ADDR_LENGTH) == 0)))
4904         {
4905             if (((mode == MLAN_BSS_MODE_INFRA) &&
4906                  (wlan_is_band_compatible(pmpriv->config_bands, pmadapter->pscan_table[i].bss_band) == 0U)) ||
4907                 (wlan_find_cfp_by_band_and_channel(pmadapter, pmadapter->pscan_table[i].bss_band,
4908                                                    (t_u16)pmadapter->pscan_table[i].channel) == MNULL))
4909             {
4910                 i++;
4911                 continue;
4912             }
4913 
4914             switch (mode)
4915             {
4916                 case MLAN_BSS_MODE_INFRA:
4917                 case MLAN_BSS_MODE_IBSS:
4918                     j = wlan_is_network_compatible(pmpriv, (t_u32)i, mode);
4919 
4920                     if (j >= 0)
4921                     {
4922                         if (SCAN_RSSI(pmadapter->pscan_table[i].rssi) > best_rssi)
4923                         {
4924                             best_rssi = (t_u8)(SCAN_RSSI(pmadapter->pscan_table[i].rssi));
4925                             net       = (t_s32)i;
4926                         }
4927                     }
4928                     else
4929                     {
4930                         if (net == -1)
4931                         {
4932                             net = j;
4933                         }
4934                     }
4935                     break;
4936                 case MLAN_BSS_MODE_AUTO:
4937                 default:
4938                     /*
4939                      * Do not check compatibility if the mode requested is
4940                      *   Auto/Unknown.  Allows generic find to work without
4941                      *   verifying against the Adapter security settings
4942                      */
4943                     if (SCAN_RSSI(pmadapter->pscan_table[i].rssi) > best_rssi)
4944                     {
4945                         best_rssi = (t_u8)(SCAN_RSSI(pmadapter->pscan_table[i].rssi));
4946                         net       = (t_s32)i;
4947                     }
4948                     break;
4949             }
4950         }
4951         i++;
4952     }
4953 
4954     LEAVE();
4955     return net;
4956 }
4957 
4958 /**
4959  *  @brief This function finds a specific compatible BSSID in the scan list
4960  *
4961  *  @param pmpriv       A pointer to mlan_private structure
4962  *  @param bssid        BSSID to find in the scan list
4963  *  @param mode         Network mode: Infrastructure or IBSS
4964  *
4965  *  @return             index in BSSID list or < 0 if error
4966  */
wlan_find_bssid_in_list(IN mlan_private * pmpriv,IN const t_u8 * bssid,IN mlan_bss_mode mode)4967 t_s32 wlan_find_bssid_in_list(IN mlan_private *pmpriv, IN const t_u8 *bssid, IN mlan_bss_mode mode)
4968 {
4969     mlan_adapter *pmadapter = pmpriv->adapter;
4970     t_s32 net               = -1;
4971     t_u32 i                 = 0U;
4972 
4973     ENTER();
4974 
4975     if (bssid == MNULL)
4976     {
4977         LEAVE();
4978         return -1;
4979     }
4980 
4981     PRINTM(MINFO, "FindBSSID: Num of BSSIDs = %d\n", pmadapter->num_in_scan_table);
4982 
4983     /*
4984      * Look through the scan table for a compatible match. The ret return
4985      *   variable will be equal to the index in the scan table (greater
4986      *   than zero) if the network is compatible.  The loop will continue
4987      *   past a matched bssid that is not compatible in case there is an
4988      *   AP with multiple SSIDs assigned to the same BSSID
4989      */
4990     while (i < pmadapter->num_in_scan_table)
4991     {
4992         if ((__memcmp(pmadapter, pmadapter->pscan_table[i].mac_address, bssid, MLAN_MAC_ADDR_LENGTH) == 0))
4993         {
4994             if (((mode == MLAN_BSS_MODE_INFRA) &&
4995                  (wlan_is_band_compatible(pmpriv->config_bands, pmadapter->pscan_table[i].bss_band) == 0U)) ||
4996                 (wlan_find_cfp_by_band_and_channel(pmadapter, pmadapter->pscan_table[i].bss_band,
4997                                                    (t_u16)pmadapter->pscan_table[i].channel) == MNULL))
4998             {
4999                 i++;
5000                 continue;
5001             }
5002             switch (mode)
5003             {
5004                 case MLAN_BSS_MODE_INFRA:
5005                 case MLAN_BSS_MODE_IBSS:
5006                     /* fixme: temp disable. enable after below function is enabled */
5007                     /* net = wlan_is_network_compatible(pmpriv, i, mode); */
5008                     break;
5009                 default:
5010                     net = (t_s32)i;
5011                     if (pmadapter->pscan_table[i].ssid.ssid_len != 0)
5012                         break;
5013             }
5014         }
5015         i++;
5016     }
5017 
5018     LEAVE();
5019     return net;
5020 }
5021 
5022 /**
5023  *  @brief Compare two SSIDs
5024  *
5025  *  @param pmadapter A pointer to mlan_adapter structure
5026  *  @param ssid1     A pointer to ssid to compare
5027  *  @param ssid2     A pointer to ssid to compare
5028  *
5029  *  @return         0--ssid is same, otherwise is different
5030  */
wlan_ssid_cmp(IN pmlan_adapter pmadapter,IN mlan_802_11_ssid * ssid1,IN mlan_802_11_ssid * ssid2)5031 t_s32 wlan_ssid_cmp(IN pmlan_adapter pmadapter, IN mlan_802_11_ssid *ssid1, IN mlan_802_11_ssid *ssid2)
5032 {
5033     ENTER();
5034 
5035     if ((ssid1 == MNULL) || (ssid2 == MNULL))
5036     {
5037         LEAVE();
5038         return -1;
5039     }
5040 
5041     if (ssid1->ssid_len != ssid2->ssid_len)
5042     {
5043         LEAVE();
5044         return -1;
5045     }
5046 
5047     LEAVE();
5048     return __memcmp(pmadapter, ssid1->ssid, ssid2->ssid, ssid1->ssid_len);
5049 }
5050 
wlan_find_worst_network_in_list(const BSSDescriptor_t * pbss_desc,t_u32 num_entries)5051 static t_u32 wlan_find_worst_network_in_list(const BSSDescriptor_t *pbss_desc, t_u32 num_entries)
5052 {
5053     t_u32 worst_net = 0U;
5054     /* To start with */
5055     t_s32 worst_rssi = pbss_desc[worst_net].rssi;
5056     t_u32 i          = 0U;
5057 
5058     ENTER();
5059 
5060     for (i = 1; i < num_entries; i++)
5061     {
5062         /* Smaller is better i.e. smaller rssi value here means better
5063            signal strength */
5064         if (pbss_desc[i].rssi > worst_rssi)
5065         {
5066             worst_rssi = pbss_desc[i].rssi;
5067             worst_net  = i;
5068         }
5069     }
5070 
5071     LEAVE();
5072     return worst_net;
5073 }
5074