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