1 /** @file mlan_scan.c
2 *
3 * @brief Functions implementing wlan scan IOCTL and firmware command APIs
4 *
5 * IOCTL handlers as well as command preparation and response routines
6 * for sending scan commands to the firmware.
7 *
8 *
9 * Copyright 2008-2022 NXP
10 *
11 * This software file (the File) is distributed by NXP
12 * under the terms of the GNU General Public License Version 2, June 1991
13 * (the License). You may use, redistribute and/or modify the File in
14 * accordance with the terms and conditions of the License, a copy of which
15 * is available by writing to the Free Software Foundation, Inc.,
16 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
17 * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
18 *
19 * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
20 * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
21 * ARE EXPRESSLY DISCLAIMED. The License provides additional details about
22 * this warranty disclaimer.
23 *
24 */
25
26 /******************************************************
27 Change log:
28 10/28/2008: initial version
29 ******************************************************/
30
31 #include "mlan.h"
32 #include "mlan_join.h"
33 #include "mlan_util.h"
34 #include "mlan_fw.h"
35 #include "mlan_main.h"
36 #include "mlan_11n.h"
37 #include "mlan_11ac.h"
38 #include "mlan_11ax.h"
39 #include "mlan_11h.h"
40 #ifdef DRV_EMBEDDED_SUPPLICANT
41 #include "authenticator_api.h"
42 #endif
43 /********************************************************
44 Local Constants
45 ********************************************************/
46 /** minimum scan time for passive to active scan */
47 #define MIN_PASSIVE_TO_ACTIVE_SCAN_TIME 150
48
49 #define MRVDRV_MAX_CHANNELS_PER_SCAN 38
50 /** The maximum number of channels the firmware can scan per command */
51 #define MRVDRV_MAX_CHANNELS_PER_SPECIFIC_SCAN 4
52
53 /**
54 * Number of channels to scan per firmware scan command issuance.
55 *
56 * Number restricted to prevent hitting the limit on the amount of scan data
57 * returned in a single firmware scan command.
58 */
59 #define MRVDRV_CHANNELS_PER_SCAN_CMD 4
60
61 /** Memory needed to store a max sized Channel List TLV for a firmware scan */
62 #define CHAN_TLV_MAX_SIZE \
63 (sizeof(MrvlIEtypesHeader_t) + \
64 (MRVDRV_MAX_CHANNELS_PER_SPECIFIC_SCAN * sizeof(ChanScanParamSet_t)))
65
66 /** Memory needed to store supported rate */
67 #define RATE_TLV_MAX_SIZE \
68 (sizeof(MrvlIEtypes_RatesParamSet_t) + HOSTCMD_SUPPORTED_RATES)
69
70 /** Memory needed to store a max number/size WildCard
71 * SSID TLV for a firmware scan */
72 #define WILDCARD_SSID_TLV_MAX_SIZE \
73 (MRVDRV_MAX_SSID_LIST_LENGTH * \
74 (sizeof(MrvlIEtypes_WildCardSsIdParamSet_t) + \
75 MRVDRV_MAX_SSID_LENGTH))
76
77 /** Memory needed to store a max number/size BSSID TLV for a firmware scan */
78 #define BSSID_LIST_TLV_MAX_SIZE \
79 (sizeof(MrvlIEtypesHeader_t) + \
80 (MRVDRV_MAX_BSSID_LIST * MLAN_MAC_ADDR_LENGTH))
81
82 /** WPS TLV MAX size is MAX IE size plus 2 bytes for
83 * t_u16 MRVL TLV extension */
84 #define WPS_TLV_MAX_SIZE (sizeof(IEEEtypes_VendorSpecific_t) + 2)
85 /** Maximum memory needed for a wlan_scan_cmd_config
86 * with all TLVs at max */
87 #define MAX_SCAN_CFG_ALLOC \
88 (sizeof(wlan_scan_cmd_config) + sizeof(MrvlIEtypes_NumProbes_t) + \
89 sizeof(MrvlIETypes_HTCap_t) + CHAN_TLV_MAX_SIZE + RATE_TLV_MAX_SIZE + \
90 WILDCARD_SSID_TLV_MAX_SIZE + BSSID_LIST_TLV_MAX_SIZE + \
91 WPS_TLV_MAX_SIZE)
92
93 /********************************************************
94 Local Variables
95 ********************************************************/
96
97 /**
98 * Interally used to send a configured scan cmd between
99 * driver routines
100 */
101 typedef union {
102 /** Scan configuration (variable length) */
103 wlan_scan_cmd_config config;
104 /** Max allocated block */
105 t_u8 config_alloc_buf[MAX_SCAN_CFG_ALLOC];
106 } wlan_scan_cmd_config_tlv;
107
108 /********************************************************
109 Global Variables
110 ********************************************************/
111
112 /********************************************************
113 Local Functions
114 ********************************************************/
115 /** Cipher suite definition */
116 enum cipher_suite {
117 CIPHER_SUITE_WEP40,
118 CIPHER_SUITE_TKIP,
119 CIPHER_SUITE_CCMP,
120 CIPHER_SUITE_WEP104,
121 CIPHER_SUITE_GCMP,
122 CIPHER_SUITE_GCMP_256,
123 CIPHER_SUITE_CCMP_256,
124 CIPHER_SUITE_MAX
125 };
126
127 static t_u8 wpa_ouis[CIPHER_SUITE_MAX][4] = {
128 {0x00, 0x50, 0xf2, 0x01}, /* WEP40 */
129 {0x00, 0x50, 0xf2, 0x02}, /* TKIP */
130 {0x00, 0x50, 0xf2, 0x04}, /* AES */
131 {0x00, 0x50, 0xf2, 0x05}, /* WEP104 */
132 };
133
134 static t_u8 rsn_oui[CIPHER_SUITE_MAX][4] = {
135 {0x00, 0x0f, 0xac, 0x01}, /* WEP40 */
136 {0x00, 0x0f, 0xac, 0x02}, /* TKIP */
137 {0x00, 0x0f, 0xac, 0x04}, /* AES */
138 {0x00, 0x0f, 0xac, 0x05}, /* WEP104 */
139 {0x00, 0x0f, 0xac, 0x08}, /* GCMP */
140 {0x00, 0x0f, 0xac, 0x09}, /* GCMP-256 */
141 {0x00, 0x0f, 0xac, 0x0a}, /* CCMP-256 */
142 };
143
144 /**
145 * @brief Convert radio type scan parameter to a band config used in join cmd
146 *
147 * @param radio_type Scan parameter indicating the radio used for a channel
148 * in a scan command.
149 *
150 * @return Band type conversion of scanBand used in join/assoc cmds
151 *
152 */
radio_type_to_band(t_u8 radio_type)153 t_u16 radio_type_to_band(t_u8 radio_type)
154 {
155 t_u16 ret_band;
156
157 switch (radio_type) {
158 case BAND_5GHZ:
159 ret_band = BAND_A;
160 break;
161 case BAND_2GHZ:
162 default:
163 ret_band = BAND_G;
164 break;
165 }
166
167 return ret_band;
168 }
169
170 /**
171 * @brief This function will update the channel statistics from scan result
172 *
173 * @param pmpriv A pointer to mlan_private structure
174 * @param pchanstats_tlv A pointer to MrvlIEtypes_ChannelStats_t tlv
175 *
176 * @return NA
177 */
178 static void
wlan_update_chan_statistics(mlan_private * pmpriv,MrvlIEtypes_ChannelStats_t * pchanstats_tlv)179 wlan_update_chan_statistics(mlan_private *pmpriv,
180 MrvlIEtypes_ChannelStats_t *pchanstats_tlv)
181 {
182 mlan_adapter *pmadapter = pmpriv->adapter;
183 t_u8 i;
184 chan_statistics_t *pchan_stats =
185 (chan_statistics_t *)((t_u8 *)pchanstats_tlv +
186 sizeof(MrvlIEtypesHeader_t));
187 t_u8 num_chan = wlan_le16_to_cpu(pchanstats_tlv->header.len) /
188 sizeof(chan_statistics_t);
189
190 ENTER();
191
192 for (i = 0; i < num_chan; i++) {
193 if (pmadapter->idx_chan_stats >= pmadapter->num_in_chan_stats) {
194 PRINTM(MERROR,
195 "Over flow: idx_chan_stats=%d, num_in_chan_stats=%d\n",
196 pmadapter->idx_chan_stats,
197 pmadapter->num_in_chan_stats);
198 break;
199 }
200 pchan_stats->total_networks =
201 wlan_le16_to_cpu(pchan_stats->total_networks);
202 pchan_stats->cca_scan_duration =
203 wlan_le16_to_cpu(pchan_stats->cca_scan_duration);
204 pchan_stats->cca_busy_duration =
205 wlan_le16_to_cpu(pchan_stats->cca_busy_duration);
206 PRINTM(MCMND,
207 "chan=%d, noise=%d, total_network=%d scan_duration=%d, busy_duration=%d\n",
208 pchan_stats->chan_num, pchan_stats->noise,
209 pchan_stats->total_networks,
210 pchan_stats->cca_scan_duration,
211 pchan_stats->cca_busy_duration);
212 memcpy_ext(pmadapter,
213 (chan_statistics_t *)&pmadapter
214 ->pchan_stats[pmadapter->idx_chan_stats],
215 pchan_stats, sizeof(chan_statistics_t),
216 sizeof(chan_statistics_t));
217 pmadapter->idx_chan_stats++;
218 pchan_stats++;
219 }
220 LEAVE();
221 return;
222 }
223
224 /**
225 * @brief This function will parse a given IE for a given OUI
226 *
227 * Parse a given WPA/RSN IE to find if it has a given oui in PTK,
228 * if no OUI found for PTK it returns 0.
229 *
230 * @param pbss_desc A pointer to current BSS descriptor
231 * @return 0 on failure to find OUI, 1 on success.
232 */
search_oui_in_ie(mlan_adapter * pmadapter,IEBody * ie_body,t_u8 * oui)233 static t_u8 search_oui_in_ie(mlan_adapter *pmadapter, IEBody *ie_body,
234 t_u8 *oui)
235 {
236 t_u8 count;
237
238 count = ie_body->PtkCnt[0];
239
240 ENTER();
241 /* There could be multiple OUIs for PTK hence
242 * 1) Take the length.
243 * 2) Check all the OUIs for AES.
244 * 3) If one of them is AES then pass success.
245 */
246 while (count) {
247 if (!memcmp(pmadapter, ie_body->PtkBody, oui,
248 sizeof(ie_body->PtkBody))) {
249 LEAVE();
250 return MLAN_OUI_PRESENT;
251 }
252
253 --count;
254 if (count) {
255 ie_body = (IEBody *)((t_u8 *)ie_body +
256 sizeof(ie_body->PtkBody));
257 }
258 }
259
260 PRINTM(MINFO, "The OUI %x:%x:%x:%x is not found in PTK\n", oui[0],
261 oui[1], oui[2], oui[3]);
262 LEAVE();
263 return MLAN_OUI_NOT_PRESENT;
264 }
265
266 /**
267 * @brief This function will pass the correct ie and oui to search_oui_in_ie
268 *
269 * Check the pbss_desc for appropriate IE and then check if RSN IE has AES
270 * OUI in it. If RSN IE does not have AES in PTK then return 0;
271 *
272 * @param pbss_desc A pointer to current BSS descriptor
273 * @return 0 on failure to find AES OUI, 1 on success.
274 */
is_rsn_oui_present(mlan_adapter * pmadapter,BSSDescriptor_t * pbss_desc,t_u32 cipher_suite)275 static t_u8 is_rsn_oui_present(mlan_adapter *pmadapter,
276 BSSDescriptor_t *pbss_desc, t_u32 cipher_suite)
277 {
278 t_u8 *oui = MNULL;
279 IEBody *ie_body = MNULL;
280 t_u8 ret = MLAN_OUI_NOT_PRESENT;
281
282 ENTER();
283 if (pbss_desc->prsn_ie &&
284 (pbss_desc->prsn_ie->ieee_hdr.element_id == RSN_IE) &&
285 (pbss_desc->prsn_ie->ieee_hdr.len > RSN_GTK_OUI_OFFSET)) {
286 ie_body = (IEBody *)(((t_u8 *)pbss_desc->prsn_ie->data) +
287 RSN_GTK_OUI_OFFSET);
288 oui = &rsn_oui[cipher_suite][0];
289 ret = search_oui_in_ie(pmadapter, ie_body, oui);
290 if (ret) {
291 LEAVE();
292 return ret;
293 }
294 }
295 LEAVE();
296 return ret;
297 }
298
299 /**
300 * @brief This function will pass the correct ie and oui to search_oui_in_ie
301 *
302 * Check the wpa_ie for appropriate IE and then check if RSN IE has AES
303 * OUI in it. If RSN IE does not have AES in PTK then return 0;
304 *
305 * @param pmadapter A pointer to mlan adapter.
306 * @return 0 on failure to find AES OUI, 1 on success.
307 */
is_rsn_oui_present_in_wpa_ie(mlan_private * pmpriv,t_u32 cipher_suite)308 static t_u8 is_rsn_oui_present_in_wpa_ie(mlan_private *pmpriv,
309 t_u32 cipher_suite)
310 {
311 mlan_adapter *pmadapter = pmpriv->adapter;
312 t_u8 *oui = MNULL;
313 IEBody *ie_body = MNULL;
314 IEEEtypes_Generic_t *prsn_ie = MNULL;
315 t_u8 ret = MLAN_OUI_NOT_PRESENT;
316
317 ENTER();
318 prsn_ie = (IEEEtypes_Generic_t *)pmpriv->wpa_ie;
319
320 if (prsn_ie && (prsn_ie->ieee_hdr.element_id == RSN_IE) &&
321 (prsn_ie->ieee_hdr.len > RSN_GTK_OUI_OFFSET)) {
322 ie_body = (IEBody *)(prsn_ie->data + RSN_GTK_OUI_OFFSET);
323 oui = &rsn_oui[cipher_suite][0];
324 ret = search_oui_in_ie(pmadapter, ie_body, oui);
325 if (ret) {
326 LEAVE();
327 return ret;
328 }
329 }
330
331 LEAVE();
332 return ret;
333 }
334
335 /**
336 * @brief This function will pass the correct ie and oui to search_oui_in_ie
337 *
338 * Check the pbss_desc for appropriate IE and then check if WPA IE has AES
339 * OUI in it. If WPA IE does not have AES in PTK then return 0;
340 *
341 * @param pbss_desc A pointer to current BSS descriptor
342 * @return 0 on failure to find AES OUI, 1 on success.
343 */
is_wpa_oui_present(mlan_adapter * pmadapter,BSSDescriptor_t * pbss_desc,t_u32 cipher_suite)344 static t_u8 is_wpa_oui_present(mlan_adapter *pmadapter,
345 BSSDescriptor_t *pbss_desc, t_u32 cipher_suite)
346 {
347 t_u8 *oui = MNULL;
348 IEBody *ie_body = MNULL;
349 t_u8 ret = MLAN_OUI_NOT_PRESENT;
350
351 ENTER();
352 if (((pbss_desc->pwpa_ie) &&
353 ((*(pbss_desc->pwpa_ie)).vend_hdr.element_id == WPA_IE))) {
354 ie_body = (IEBody *)pbss_desc->pwpa_ie->data;
355 oui = &wpa_ouis[cipher_suite][0];
356 ret = search_oui_in_ie(pmadapter, ie_body, oui);
357 if (ret) {
358 LEAVE();
359 return ret;
360 }
361 }
362 LEAVE();
363 return ret;
364 }
365
366 /**
367 * @brief compare config band and a band from the scan result,
368 * which is defined by functiion radio_type_to_band(t_u8 radio_type) above
369 *
370 * @param cfg_band: band configured
371 * scan_band: band from scan result
372 *
373 * @return matched: non-zero. unmatched: 0
374 *
375 */
wlan_is_band_compatible(t_u8 cfg_band,t_u8 scan_band)376 static t_u8 wlan_is_band_compatible(t_u8 cfg_band, t_u8 scan_band)
377 {
378 t_u16 band;
379 switch (scan_band) {
380 case BAND_A:
381 band = BAND_A | BAND_AN | BAND_AAC;
382 break;
383 case BAND_G:
384 default:
385 band = BAND_B | BAND_G | BAND_GN | BAND_GAC;
386 }
387 return cfg_band & band;
388 }
389
390 /**
391 * @brief This function finds the best SSID in the Scan List
392 *
393 * Search the scan table for the best SSID that also matches the current
394 * adapter network preference (infrastructure or adhoc)
395 *
396 * @param pmpriv A pointer to mlan_private structure
397 * @return index in BSSID list
398 */
wlan_find_best_network_in_list(mlan_private * pmpriv)399 static t_s32 wlan_find_best_network_in_list(mlan_private *pmpriv)
400 {
401 mlan_adapter *pmadapter = pmpriv->adapter;
402 t_u32 mode = pmpriv->bss_mode;
403 t_s32 best_net = -1;
404 t_s32 best_rssi = 0;
405 t_u32 i;
406
407 ENTER();
408
409 PRINTM(MINFO, "Num of BSSIDs = %d\n", pmadapter->num_in_scan_table);
410
411 for (i = 0; i < pmadapter->num_in_scan_table; i++) {
412 switch (mode) {
413 case MLAN_BSS_MODE_INFRA:
414 case MLAN_BSS_MODE_IBSS:
415 if (wlan_is_network_compatible(pmpriv, i, mode) >= 0) {
416 if (SCAN_RSSI(pmadapter->pscan_table[i].rssi) >
417 best_rssi) {
418 best_rssi = SCAN_RSSI(
419 pmadapter->pscan_table[i].rssi);
420 best_net = i;
421 }
422 }
423 break;
424 case MLAN_BSS_MODE_AUTO:
425 default:
426 if (SCAN_RSSI(pmadapter->pscan_table[i].rssi) >
427 best_rssi) {
428 best_rssi = SCAN_RSSI(
429 pmadapter->pscan_table[i].rssi);
430 best_net = i;
431 }
432 break;
433 }
434 }
435
436 LEAVE();
437 return best_net;
438 }
439
440 /**
441 * @brief Create a channel list for the driver to scan based on region info
442 *
443 * Use the driver region/band information to construct a comprehensive list
444 * of channels to scan. This routine is used for any scan that is not
445 * provided a specific channel list to scan.
446 *
447 * @param pmpriv A pointer to mlan_private structure
448 * @param puser_scan_in MNULL or pointer to scan configuration parameters
449 * @param pscan_chan_list Output parameter: Resulting channel list to scan
450 * @param filtered_scan Flag indicating whether or not a BSSID or SSID
451 * filter is being sent in the command to firmware. Used to increase the number
452 * of channels sent in a scan command and to disable the firmware channel scan
453 * filter.
454 *
455 * @return num of channel
456 */
wlan_scan_create_channel_list(mlan_private * pmpriv,const wlan_user_scan_cfg * puser_scan_in,ChanScanParamSet_t * pscan_chan_list,t_u8 filtered_scan)457 static t_u8 wlan_scan_create_channel_list(
458 mlan_private *pmpriv, const wlan_user_scan_cfg *puser_scan_in,
459 ChanScanParamSet_t *pscan_chan_list, t_u8 filtered_scan)
460 {
461 mlan_adapter *pmadapter = pmpriv->adapter;
462 region_chan_t *pscan_region;
463 chan_freq_power_t *cfp;
464 t_u32 region_idx;
465 t_u32 chan_idx = 0;
466 t_u32 next_chan;
467 t_u8 scan_type;
468 t_u8 radio_type;
469 t_u16 band;
470 t_u16 scan_dur = 0;
471
472 ENTER();
473
474 for (region_idx = 0; region_idx < NELEMENTS(pmadapter->region_channel);
475 region_idx++) {
476 if (wlan_11d_is_enabled(pmpriv) &&
477 pmpriv->media_connected != MTRUE) {
478 /* Scan all the supported chan for the first scan */
479 if (!pmadapter->universal_channel[region_idx].valid)
480 continue;
481 pscan_region =
482 &pmadapter->universal_channel[region_idx];
483 } else {
484 if (!pmadapter->region_channel[region_idx].valid)
485 continue;
486 pscan_region = &pmadapter->region_channel[region_idx];
487 }
488
489 if (puser_scan_in && !puser_scan_in->chan_list[0].chan_number &&
490 puser_scan_in->chan_list[0].radio_type & BAND_SPECIFIED) {
491 radio_type = puser_scan_in->chan_list[0].radio_type &
492 ~BAND_SPECIFIED;
493 if (!radio_type && (pscan_region->band != BAND_B) &&
494 (pscan_region->band != BAND_G))
495 continue;
496 if (radio_type && (pscan_region->band != BAND_A))
497 continue;
498 }
499 PRINTM(MCMD_D,
500 "create_channel_list: region=%d band=%d num_cfp=%d\n",
501 pscan_region->region, pscan_region->band,
502 pscan_region->num_cfp);
503 if ((puser_scan_in &&
504 (puser_scan_in->bss_mode == MLAN_SCAN_MODE_IBSS)) ||
505 pmpriv->bss_mode == MLAN_BSS_MODE_IBSS)
506 band = pmadapter->adhoc_start_band;
507 else
508 band = pmpriv->config_bands;
509 if (!wlan_is_band_compatible(band, pscan_region->band))
510 continue;
511 for (next_chan = 0; next_chan < pscan_region->num_cfp;
512 next_chan++) {
513 /* Set the default scan type to the user specified type,
514 * will later be changed to passive on a per channel
515 * basis if restricted by regulatory requirements (11d
516 * or 11h)
517 */
518 scan_type = pmadapter->scan_type;
519 cfp = pscan_region->pcfp + next_chan;
520 if (cfp->dynamic.flags & NXP_CHANNEL_DISABLED)
521 continue;
522
523 if (wlan_is_chan_passive(pmpriv, pscan_region->band,
524 (t_u8)cfp->channel)) {
525 /* do not send probe requests on this channel */
526 scan_type = MLAN_SCAN_TYPE_PASSIVE;
527 }
528 switch (pscan_region->band) {
529 case BAND_A:
530 pscan_chan_list[chan_idx].bandcfg.chanBand =
531 BAND_5GHZ;
532 /* Passive scan on DFS channels */
533 if (wlan_11h_radar_detect_required(
534 pmpriv, (t_u8)cfp->channel) &&
535 scan_type == MLAN_SCAN_TYPE_PASSIVE)
536 scan_type =
537 MLAN_SCAN_TYPE_PASSIVE_TO_ACTIVE;
538 break;
539 case BAND_B:
540 case BAND_G:
541 if (wlan_bg_scan_type_is_passive(
542 pmpriv, (t_u8)cfp->channel)) {
543 scan_type = MLAN_SCAN_TYPE_PASSIVE;
544 }
545 pscan_chan_list[chan_idx].bandcfg.chanBand =
546 BAND_2GHZ;
547 break;
548 default:
549 pscan_chan_list[chan_idx].bandcfg.chanBand =
550 BAND_2GHZ;
551 break;
552 }
553
554 if (puser_scan_in &&
555 puser_scan_in->chan_list[0].scan_time) {
556 scan_dur = (t_u16)puser_scan_in->chan_list[0]
557 .scan_time;
558 } else if (scan_type == MLAN_SCAN_TYPE_PASSIVE ||
559 scan_type ==
560 MLAN_SCAN_TYPE_PASSIVE_TO_ACTIVE) {
561 scan_dur = pmadapter->passive_scan_time;
562 } else if (filtered_scan) {
563 scan_dur = pmadapter->specific_scan_time;
564 } else {
565 scan_dur = pmadapter->active_scan_time;
566 }
567 if (scan_type == MLAN_SCAN_TYPE_PASSIVE_TO_ACTIVE &&
568 pmadapter->passive_to_active_scan ==
569 MLAN_PASS_TO_ACT_SCAN_EN) {
570 scan_dur = MAX(scan_dur,
571 MIN_PASSIVE_TO_ACTIVE_SCAN_TIME);
572 pscan_chan_list[chan_idx]
573 .chan_scan_mode.passive_to_active_scan =
574 MTRUE;
575 }
576
577 pscan_chan_list[chan_idx].max_scan_time =
578 wlan_cpu_to_le16(scan_dur);
579
580 if (scan_type == MLAN_SCAN_TYPE_PASSIVE ||
581 scan_type == MLAN_SCAN_TYPE_PASSIVE_TO_ACTIVE) {
582 pscan_chan_list[chan_idx]
583 .chan_scan_mode.passive_scan = MTRUE;
584 pscan_chan_list[chan_idx]
585 .chan_scan_mode.hidden_ssid_report =
586 MTRUE;
587 } else {
588 pscan_chan_list[chan_idx]
589 .chan_scan_mode.passive_scan = MFALSE;
590 }
591
592 pscan_chan_list[chan_idx].chan_number =
593 (t_u8)cfp->channel;
594 PRINTM(MCMD_D,
595 "chan=%d, mode=%d, passive_to_active=%d\n",
596 pscan_chan_list[chan_idx].chan_number,
597 pscan_chan_list[chan_idx]
598 .chan_scan_mode.passive_scan,
599 pscan_chan_list[chan_idx]
600 .chan_scan_mode.passive_to_active_scan);
601 chan_idx++;
602 }
603 }
604
605 LEAVE();
606 return chan_idx;
607 }
608
609 /**
610 * @brief Add WPS IE to probe request frame
611 *
612 * @param pmpriv A pointer to mlan_private structure
613 * @param pptlv_out A pointer to TLV to fill in
614 *
615 * @return N/A
616 */
wlan_add_wps_probe_request_ie(mlan_private * pmpriv,t_u8 ** pptlv_out)617 static void wlan_add_wps_probe_request_ie(mlan_private *pmpriv,
618 t_u8 **pptlv_out)
619 {
620 MrvlIEtypesHeader_t *tlv;
621
622 ENTER();
623
624 if (pmpriv->wps.wps_ie.vend_hdr.len) {
625 tlv = (MrvlIEtypesHeader_t *)*pptlv_out;
626 tlv->type = wlan_cpu_to_le16(VENDOR_SPECIFIC_221);
627 tlv->len = wlan_cpu_to_le16(pmpriv->wps.wps_ie.vend_hdr.len);
628 *pptlv_out += sizeof(MrvlIEtypesHeader_t);
629 memcpy_ext(pmpriv->adapter, *pptlv_out,
630 pmpriv->wps.wps_ie.vend_hdr.oui,
631 pmpriv->wps.wps_ie.vend_hdr.len,
632 pmpriv->wps.wps_ie.vend_hdr.len);
633 *pptlv_out += (pmpriv->wps.wps_ie.vend_hdr.len +
634 sizeof(MrvlIEtypesHeader_t));
635 }
636 LEAVE();
637 }
638
639 /**
640 * @brief Construct and send multiple scan config commands to the firmware
641 *
642 * Previous routines have created a wlan_scan_cmd_config with any requested
643 * TLVs. This function splits the channel TLV into max_chan_per_scan lists
644 * and sends the portion of the channel TLV along with the other TLVs
645 * to the wlan_cmd routines for execution in the firmware.
646 *
647 * @param pmpriv A pointer to mlan_private structure
648 * @param pioctl_buf A pointer to MLAN IOCTL Request buffer
649 * @param max_chan_per_scan Maximum number channels to be included in each
650 * scan command sent to firmware
651 * @param filtered_scan Flag indicating whether or not a BSSID or SSID
652 * filter is being used for the firmware command
653 * scan command sent to firmware
654 * @param pscan_cfg_out Scan configuration used for this scan.
655 * @param pchan_tlv_out Pointer in the pscan_cfg_out where the channel TLV
656 * should start. This is past any other TLVs that
657 * must be sent down in each firmware command.
658 * @param pscan_chan_list List of channels to scan in max_chan_per_scan
659 * segments
660 *
661 * @return MLAN_STATUS_SUCCESS or error return otherwise
662 */
663 static mlan_status
wlan_scan_channel_list(mlan_private * pmpriv,t_void * pioctl_buf,t_u32 max_chan_per_scan,t_u8 filtered_scan,wlan_scan_cmd_config * pscan_cfg_out,MrvlIEtypes_ChanListParamSet_t * pchan_tlv_out,ChanScanParamSet_t * pscan_chan_list)664 wlan_scan_channel_list(mlan_private *pmpriv, t_void *pioctl_buf,
665 t_u32 max_chan_per_scan, t_u8 filtered_scan,
666 wlan_scan_cmd_config *pscan_cfg_out,
667 MrvlIEtypes_ChanListParamSet_t *pchan_tlv_out,
668 ChanScanParamSet_t *pscan_chan_list)
669 {
670 mlan_status ret = MLAN_STATUS_SUCCESS;
671 mlan_adapter *pmadapter = pmpriv->adapter;
672 ChanScanParamSet_t *ptmp_chan_list;
673 ChanScanParamSet_t *pstart_chan;
674 pmlan_ioctl_req pioctl_req = (mlan_ioctl_req *)pioctl_buf;
675 t_u8 *pchan_tlv_out_temp = MNULL;
676 t_u8 *ptlv_temp = MNULL;
677 t_bool foundJPch14 = MFALSE;
678 t_u16 tlv_buf_len = 0;
679 t_u32 tlv_idx;
680 t_u32 total_scan_time;
681 t_u32 done_early;
682 t_u32 cmd_no;
683 t_u32 first_chan = 1;
684 t_u8 *ptlv_pos;
685 MrvlIETypes_HTCap_t *pht_cap;
686
687 MrvlIETypes_VHTCap_t *pvht_cap;
688 MrvlIEtypes_Extension_t *phe_cap;
689 t_u16 len = 0;
690 t_u8 radio_type = 0;
691
692 mlan_callbacks *pcb = (mlan_callbacks *)&pmadapter->callbacks;
693
694 ENTER();
695
696 if (!pscan_cfg_out || !pchan_tlv_out || !pscan_chan_list) {
697 PRINTM(MINFO, "Scan: Null detect: %p, %p, %p\n", pscan_cfg_out,
698 pchan_tlv_out, pscan_chan_list);
699 if (pioctl_req)
700 pioctl_req->status_code = MLAN_ERROR_CMD_SCAN_FAIL;
701 LEAVE();
702 return MLAN_STATUS_FAILURE;
703 }
704 if (!pscan_chan_list->chan_number) {
705 PRINTM(MERROR, "Scan: No channel configured\n");
706 if (pioctl_req)
707 pioctl_req->status_code = MLAN_ERROR_CMD_SCAN_FAIL;
708 LEAVE();
709 return MLAN_STATUS_FAILURE;
710 }
711
712 /* check expiry before preparing scan list - may affect blacklist */
713 wlan_11h_get_csa_closed_channel(pmpriv);
714
715 pchan_tlv_out->header.type = wlan_cpu_to_le16(TLV_TYPE_CHANLIST);
716
717 /* Set the temp channel struct pointer to the start of the desired list
718 */
719 ptmp_chan_list = pscan_chan_list;
720
721 /*
722 * Loop through the desired channel list, sending a new firmware scan
723 * commands for each max_chan_per_scan channels (or for 1,6,11
724 * individually if configured accordingly)
725 */
726 while (ptmp_chan_list->chan_number) {
727 tlv_idx = 0;
728 total_scan_time = 0;
729 pchan_tlv_out->header.len = 0;
730 pstart_chan = ptmp_chan_list;
731 done_early = MFALSE;
732
733 /*
734 * Construct the Channel TLV for the scan command. Continue to
735 * insert channel TLVs until:
736 * - the tlv_idx hits the maximum configured per scan command
737 * - the next channel to insert is 0 (end of desired
738 * channel list)
739 * - done_early is set (controlling individual
740 * scanning of 1,6,11)
741 */
742 while (tlv_idx < max_chan_per_scan &&
743 ptmp_chan_list->chan_number && !done_early) {
744 if (wlan_is_chan_blacklisted(
745 pmpriv,
746 radio_type_to_band(
747 ptmp_chan_list->bandcfg.chanBand),
748 ptmp_chan_list->chan_number) ||
749 wlan_is_chan_disabled(
750 pmpriv,
751 radio_type_to_band(
752 ptmp_chan_list->bandcfg.chanBand),
753 ptmp_chan_list->chan_number)) {
754 PRINTM(MCMND, "Block scan chan = %d\n",
755 ptmp_chan_list->chan_number);
756 ptmp_chan_list++;
757 continue;
758 }
759
760 if (first_chan) {
761 ptmp_chan_list->chan_scan_mode.first_chan =
762 MTRUE;
763 first_chan = 0;
764 }
765 radio_type = ptmp_chan_list->bandcfg.chanBand;
766 PRINTM(MCMD_D,
767 "Scan: Chan(%3d), bandcfg(%x), Mode(%d,%d), Dur(%d)\n",
768 ptmp_chan_list->chan_number,
769 ptmp_chan_list->bandcfg,
770 ptmp_chan_list->chan_scan_mode.passive_scan,
771 ptmp_chan_list->chan_scan_mode.disable_chan_filt,
772 wlan_le16_to_cpu(ptmp_chan_list->max_scan_time));
773
774 if (foundJPch14 == MTRUE) {
775 foundJPch14 = MFALSE;
776 /* Restore the TLV buffer */
777 pchan_tlv_out =
778 (MrvlIEtypes_ChanListParamSet_t *)
779 pchan_tlv_out_temp;
780 pchan_tlv_out->header.type =
781 wlan_cpu_to_le16(TLV_TYPE_CHANLIST);
782 pchan_tlv_out->header.len = 0;
783 if (ptlv_temp) {
784 memcpy_ext(pmadapter,
785 pscan_cfg_out->tlv_buf,
786 ptlv_temp, tlv_buf_len,
787 tlv_buf_len);
788 pcb->moal_mfree(pmadapter->pmoal_handle,
789 ptlv_temp);
790 ptlv_temp = MNULL;
791 }
792 }
793
794 /* Special Case: For Japan, Scan on CH14 for 11G rates
795 is not allowed
796 Hence Rates TLV needs to be updated to support only
797 11B rates */
798 if ((pmadapter->region_code == COUNTRY_CODE_JP_40 ||
799 pmadapter->region_code == COUNTRY_CODE_JP_FF) &&
800 (ptmp_chan_list->chan_number == 14) &&
801 (pmadapter->ext_scan_type != EXT_SCAN_ENHANCE)) {
802 t_u8 *ptlv_pos = pscan_cfg_out->tlv_buf;
803 t_u16 old_ratetlv_len, new_ratetlv_len;
804 MrvlIEtypesHeader_t *header;
805 MrvlIEtypes_RatesParamSet_t *prates_tlv;
806
807 /* Preserve the current TLV buffer */
808 ret = pcb->moal_malloc(
809 pmadapter->pmoal_handle,
810 MAX_SCAN_CFG_ALLOC - CHAN_TLV_MAX_SIZE,
811 MLAN_MEM_DEF | MOAL_MEM_FLAG_ATOMIC,
812 (t_u8 **)&ptlv_temp);
813 if (ret != MLAN_STATUS_SUCCESS || !ptlv_temp) {
814 PRINTM(MERROR,
815 "Memory allocation for pscan_cfg_out failed!\n");
816 if (pioctl_req)
817 pioctl_req->status_code =
818 MLAN_ERROR_NO_MEM;
819 LEAVE();
820 return MLAN_STATUS_FAILURE;
821 }
822 pchan_tlv_out_temp = (t_u8 *)pchan_tlv_out;
823 tlv_buf_len = (t_u32)(pchan_tlv_out_temp -
824 pscan_cfg_out->tlv_buf);
825 memcpy_ext(pmadapter, ptlv_temp, ptlv_pos,
826 tlv_buf_len,
827 MAX_SCAN_CFG_ALLOC -
828 CHAN_TLV_MAX_SIZE);
829
830 /* Search for Rates TLV */
831 while ((!foundJPch14) &&
832 (ptlv_pos < pchan_tlv_out_temp)) {
833 header =
834 (MrvlIEtypesHeader_t *)ptlv_pos;
835 if (header->type ==
836 wlan_cpu_to_le16(TLV_TYPE_RATES))
837 foundJPch14 = MTRUE;
838 else
839 ptlv_pos +=
840 (sizeof(MrvlIEtypesHeader_t) +
841 wlan_le16_to_cpu(
842 header->len));
843 }
844
845 if (foundJPch14) {
846 /* Update the TLV buffer with *new*
847 * Rates TLV and rearrange remaining TLV
848 * buffer*/
849 prates_tlv =
850 (MrvlIEtypes_RatesParamSet_t *)
851 ptlv_pos;
852 old_ratetlv_len =
853 sizeof(MrvlIEtypesHeader_t) +
854 wlan_le16_to_cpu(
855 prates_tlv->header.len);
856
857 prates_tlv->header.len = wlan_copy_rates(
858 prates_tlv->rates, 0,
859 SupportedRates_B,
860 sizeof(SupportedRates_B));
861 new_ratetlv_len =
862 sizeof(MrvlIEtypesHeader_t) +
863 prates_tlv->header.len;
864 prates_tlv->header.len =
865 wlan_cpu_to_le16(
866 prates_tlv->header.len);
867
868 memmove(pmadapter,
869 ptlv_pos + new_ratetlv_len,
870 ptlv_pos + old_ratetlv_len,
871 (t_u32)(pchan_tlv_out_temp -
872 (ptlv_pos +
873 old_ratetlv_len)));
874 pchan_tlv_out =
875 (MrvlIEtypes_ChanListParamSet_t
876 *)(pchan_tlv_out_temp -
877 (old_ratetlv_len -
878 new_ratetlv_len));
879 pchan_tlv_out->header.type =
880 wlan_cpu_to_le16(
881 TLV_TYPE_CHANLIST);
882 pchan_tlv_out->header.len = 0;
883 }
884 }
885
886 /* Copy the current channel TLV to the command being
887 * prepared */
888 memcpy_ext(pmadapter,
889 pchan_tlv_out->chan_scan_param + tlv_idx,
890 ptmp_chan_list,
891 sizeof(pchan_tlv_out->chan_scan_param),
892 sizeof(pchan_tlv_out->chan_scan_param));
893
894 /* Increment the TLV header length by the size appended
895 */
896 pchan_tlv_out->header.len +=
897 sizeof(pchan_tlv_out->chan_scan_param);
898
899 /*
900 * The tlv buffer length is set to the number of
901 * bytes of the between the channel tlv pointer
902 * and the start of the tlv buffer. This
903 * compensates for any TLVs that were appended
904 * before the channel list.
905 */
906 pscan_cfg_out->tlv_buf_len = (t_u32)(
907 (t_u8 *)pchan_tlv_out - pscan_cfg_out->tlv_buf);
908
909 /* Add the size of the channel tlv header and the data
910 * length */
911 pscan_cfg_out->tlv_buf_len +=
912 (sizeof(pchan_tlv_out->header) +
913 pchan_tlv_out->header.len);
914
915 /* Increment the index to the channel tlv we are
916 * constructing */
917 tlv_idx++;
918
919 /* Count the total scan time per command */
920 total_scan_time +=
921 wlan_le16_to_cpu(ptmp_chan_list->max_scan_time);
922
923 done_early = MFALSE;
924
925 /*
926 * Stop the loop if the *current* channel is in the
927 * 1,6,11 set and we are not filtering on a BSSID or
928 * SSID.
929 */
930 if (!filtered_scan &&
931 (ptmp_chan_list->chan_number == 1 ||
932 ptmp_chan_list->chan_number == 6 ||
933 ptmp_chan_list->chan_number == 11)) {
934 done_early = MTRUE;
935 }
936
937 /*
938 * Stop the loop if the *current* channel is 14
939 * and region code is Japan (0x40 or 0xFF)
940 */
941 if ((pmadapter->region_code == COUNTRY_CODE_JP_40 ||
942 pmadapter->region_code == COUNTRY_CODE_JP_FF) &&
943 (ptmp_chan_list->chan_number == 14)) {
944 done_early = MTRUE;
945 }
946
947 /* Increment the tmp pointer to the next channel to be
948 * scanned */
949 ptmp_chan_list++;
950
951 /*
952 * Stop the loop if the *next* channel is in the 1,6,11
953 * set. This will cause it to be the only channel
954 * scanned on the next interation
955 */
956 if (!filtered_scan &&
957 (ptmp_chan_list->chan_number == 1 ||
958 ptmp_chan_list->chan_number == 6 ||
959 ptmp_chan_list->chan_number == 11)) {
960 done_early = MTRUE;
961 }
962
963 /*
964 * Stop the loop if the *next* channel is 14
965 * and region code is Japan (0x40 or 0xFF)
966 */
967 if ((pmadapter->region_code == COUNTRY_CODE_JP_40 ||
968 pmadapter->region_code == COUNTRY_CODE_JP_FF) &&
969 (ptmp_chan_list->chan_number == 14)) {
970 done_early = MTRUE;
971 }
972 if (pmadapter->ext_scan && pmadapter->ext_scan_enh &&
973 pmadapter->ext_scan_type == EXT_SCAN_ENHANCE)
974 done_early = MFALSE;
975 }
976
977 /* The total scan time should be less than scan command timeout
978 * value */
979 if (!total_scan_time ||
980 total_scan_time > MRVDRV_MAX_TOTAL_SCAN_TIME) {
981 PRINTM(MMSG,
982 "Total scan time %d ms is invalid, limit (%d ms), scan skipped\n",
983 total_scan_time, MRVDRV_MAX_TOTAL_SCAN_TIME);
984 if (pioctl_req)
985 pioctl_req->status_code =
986 MLAN_ERROR_CMD_SCAN_FAIL;
987 ret = MLAN_STATUS_FAILURE;
988 break;
989 }
990 ptlv_pos = (t_u8 *)pchan_tlv_out + pchan_tlv_out->header.len +
991 sizeof(MrvlIEtypesHeader_t);
992
993 pchan_tlv_out->header.len =
994 wlan_cpu_to_le16(pchan_tlv_out->header.len);
995
996 if (ISSUPP_11NENABLED(pmpriv->adapter->fw_cap_info) &&
997 (pmpriv->config_bands & BAND_GN ||
998 pmpriv->config_bands & BAND_AN)) {
999 pht_cap = (MrvlIETypes_HTCap_t *)ptlv_pos;
1000 memset(pmadapter, pht_cap, 0,
1001 sizeof(MrvlIETypes_HTCap_t));
1002 pht_cap->header.type = wlan_cpu_to_le16(HT_CAPABILITY);
1003 pht_cap->header.len = sizeof(HTCap_t);
1004 wlan_fill_ht_cap_tlv(pmpriv, pht_cap,
1005 pmpriv->config_bands, MTRUE);
1006 HEXDUMP("SCAN: HT_CAPABILITIES IE", (t_u8 *)pht_cap,
1007 sizeof(MrvlIETypes_HTCap_t));
1008 ptlv_pos += sizeof(MrvlIETypes_HTCap_t);
1009 pht_cap->header.len =
1010 wlan_cpu_to_le16(pht_cap->header.len);
1011 }
1012
1013 if (ISSUPP_11ACENABLED(pmpriv->adapter->fw_cap_info) &&
1014 (pmpriv->config_bands & BAND_AAC)) {
1015 pvht_cap = (MrvlIETypes_VHTCap_t *)ptlv_pos;
1016 memset(pmadapter, pvht_cap, 0,
1017 sizeof(MrvlIETypes_VHTCap_t));
1018 pvht_cap->header.type =
1019 wlan_cpu_to_le16(VHT_CAPABILITY);
1020 pvht_cap->header.len = sizeof(VHT_capa_t);
1021 wlan_fill_vht_cap_tlv(pmpriv, pvht_cap,
1022 pmpriv->config_bands, MFALSE,
1023 MFALSE);
1024 HEXDUMP("SCAN: VHT_CAPABILITIES IE", (t_u8 *)pvht_cap,
1025 sizeof(MrvlIETypes_VHTCap_t));
1026 ptlv_pos += sizeof(MrvlIETypes_VHTCap_t);
1027 pvht_cap->header.len =
1028 wlan_cpu_to_le16(pvht_cap->header.len);
1029 }
1030
1031 if (IS_FW_SUPPORT_11AX(pmadapter) &&
1032 ((pmpriv->config_bands & BAND_GAX) ||
1033 (pmpriv->config_bands & BAND_AAX))) {
1034 phe_cap = (MrvlIEtypes_Extension_t *)ptlv_pos;
1035 len = wlan_fill_he_cap_tlv(pmpriv, pmpriv->config_bands,
1036 phe_cap, MFALSE);
1037 HEXDUMP("SCAN: HE_CAPABILITIES IE", (t_u8 *)phe_cap,
1038 len);
1039 ptlv_pos += len;
1040 }
1041
1042 pscan_cfg_out->tlv_buf_len =
1043 (t_u32)((t_u8 *)ptlv_pos - pscan_cfg_out->tlv_buf);
1044
1045 pmadapter->pscan_channels = pstart_chan;
1046
1047 /* Send the scan command to the firmware with the specified cfg
1048 */
1049 if (pmadapter->ext_scan
1050 #ifdef USB8801
1051 && !IS_USB8801(pmadapter->card_type)
1052 #endif
1053 )
1054 cmd_no = HostCmd_CMD_802_11_SCAN_EXT;
1055 else
1056 cmd_no = HostCmd_CMD_802_11_SCAN;
1057 ret = wlan_prepare_cmd(pmpriv, cmd_no, HostCmd_ACT_GEN_SET, 0,
1058 MNULL, pscan_cfg_out);
1059 if (ret)
1060 break;
1061 }
1062
1063 LEAVE();
1064
1065 if (ptlv_temp)
1066 pcb->moal_mfree(pmadapter->pmoal_handle, ptlv_temp);
1067
1068 if (ret)
1069 return MLAN_STATUS_FAILURE;
1070
1071 return MLAN_STATUS_SUCCESS;
1072 }
1073
1074 /**
1075 * @brief Construct a wlan_scan_cmd_config structure to use in scan commands
1076 *
1077 * Application layer or other functions can invoke wlan_scan_networks
1078 * with a scan configuration supplied in a wlan_ioctl_user_scan_cfg struct.
1079 * This structure is used as the basis of one or many wlan_scan_cmd_config
1080 * commands that are sent to the command processing module and sent to
1081 * firmware.
1082 *
1083 * Create a wlan_scan_cmd_config based on the following user supplied
1084 * parameters (if present):
1085 * - SSID filter
1086 * - BSSID filter
1087 * - Number of Probes to be sent
1088 * - Channel list
1089 *
1090 * If the SSID or BSSID filter is not present, disable/clear the filter.
1091 * If the number of probes is not set, use the adapter default setting
1092 * Qualify the channel
1093 *
1094 * @param pmpriv A pointer to mlan_private structure
1095 * @param puser_scan_in MNULL or pointer to scan config parameters
1096 * @param pscan_cfg_out Output parameter: Resulting scan configuration
1097 * @param ppchan_list_out Output parameter: Pointer to the start of the
1098 * channel TLV portion of the output scan config
1099 * @param pscan_chan_list Output parameter: Pointer to the resulting
1100 * channel list to scan
1101 * @param pmax_chan_per_scan Output parameter: Number of channels to scan for
1102 * each issuance of the firmware scan command
1103 * @param pfiltered_scan Output parameter: Flag indicating whether or not
1104 * a BSSID or SSID filter is being sent in the
1105 * command to firmware. Used to increase the number
1106 * of channels sent in a scan command and to
1107 * disable the firmware channel scan filter.
1108 * @param pscan_current_only Output parameter: Flag indicating whether or not
1109 * we are only scanning our current active channel
1110 *
1111 * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
1112 */
wlan_scan_setup_scan_config(mlan_private * pmpriv,wlan_user_scan_cfg * puser_scan_in,wlan_scan_cmd_config * pscan_cfg_out,MrvlIEtypes_ChanListParamSet_t ** ppchan_list_out,ChanScanParamSet_t * pscan_chan_list,t_u8 * pmax_chan_per_scan,t_u8 * pfiltered_scan,t_u8 * pscan_current_only)1113 static mlan_status wlan_scan_setup_scan_config(
1114 mlan_private *pmpriv, wlan_user_scan_cfg *puser_scan_in,
1115 wlan_scan_cmd_config *pscan_cfg_out,
1116 MrvlIEtypes_ChanListParamSet_t **ppchan_list_out,
1117 ChanScanParamSet_t *pscan_chan_list, t_u8 *pmax_chan_per_scan,
1118 t_u8 *pfiltered_scan, t_u8 *pscan_current_only)
1119 {
1120 mlan_adapter *pmadapter = pmpriv->adapter;
1121 mlan_status ret = MLAN_STATUS_SUCCESS;
1122 MrvlIEtypes_NumProbes_t *pnum_probes_tlv;
1123 MrvlIEtypes_WildCardSsIdParamSet_t *pwildcard_ssid_tlv;
1124 MrvlIEtypes_RatesParamSet_t *prates_tlv;
1125 MrvlIEtypes_Bssid_List_t *pbssid_tlv;
1126
1127 const t_u8 zero_mac[MLAN_MAC_ADDR_LENGTH] = {0, 0, 0, 0, 0, 0};
1128 t_u8 *ptlv_pos;
1129 t_u32 num_probes;
1130 t_u32 ssid_len;
1131 t_u32 chan_idx;
1132 t_u32 chan_list_idx = 0;
1133 t_u32 scan_type;
1134 t_u16 scan_dur;
1135 t_u8 channel;
1136 t_u8 radio_type;
1137 t_u32 ssid_idx;
1138 t_u8 ssid_filter;
1139 WLAN_802_11_RATES rates;
1140 t_u32 rates_size;
1141 MrvlIEtypes_ScanChanGap_t *pscan_gap_tlv;
1142 MrvlIEtypes_BssMode_t *pbss_mode;
1143 t_u8 num_of_channel = 0;
1144
1145 ENTER();
1146
1147 /* The tlv_buf_len is calculated for each scan command. The TLVs added
1148 * in this routine will be preserved since the routine that sends
1149 * the command will append channelTLVs at *ppchan_list_out. The
1150 * difference between the *ppchan_list_out and the tlv_buf start will
1151 * be used to calculate the size of anything we add in this routine.
1152 */
1153 pscan_cfg_out->tlv_buf_len = 0;
1154
1155 /* Running tlv pointer. Assigned to ppchan_list_out at end of function
1156 * so later routines know where channels can be added to the command
1157 * buf
1158 */
1159 ptlv_pos = pscan_cfg_out->tlv_buf;
1160
1161 /* Initialize the scan as un-filtered; the flag is later set to
1162 * TRUE below if a SSID or BSSID filter is sent in the command
1163 */
1164 *pfiltered_scan = MFALSE;
1165
1166 /* Initialize the scan as not being only on the current channel. If
1167 * the channel list is customized, only contains one channel, and
1168 * is the active channel, this is set true and data flow is not
1169 * halted.
1170 */
1171 *pscan_current_only = MFALSE;
1172
1173 if (puser_scan_in) {
1174 ssid_filter = MFALSE;
1175
1176 /* Set the bss type scan filter, use Adapter setting if unset */
1177 pscan_cfg_out->bss_mode =
1178 (puser_scan_in->bss_mode ?
1179 (t_u8)puser_scan_in->bss_mode :
1180 (t_u8)pmadapter->scan_mode);
1181
1182 /* Set the number of probes to send, use Adapter setting if
1183 * unset */
1184 num_probes =
1185 (puser_scan_in->num_probes ? puser_scan_in->num_probes :
1186 pmadapter->scan_probes);
1187 /*
1188 * Set the BSSID filter to the incoming configuration,
1189 * if non-zero. If not set, it will remain disabled
1190 * (all zeros).
1191 */
1192 memcpy_ext(pmadapter, pscan_cfg_out->specific_bssid,
1193 puser_scan_in->specific_bssid,
1194 sizeof(pscan_cfg_out->specific_bssid),
1195 sizeof(pscan_cfg_out->specific_bssid));
1196
1197 if (pmadapter->ext_scan) {
1198 if (puser_scan_in->bssid_num) {
1199 pbssid_tlv =
1200 (MrvlIEtypes_Bssid_List_t *)ptlv_pos;
1201 pbssid_tlv->header.type = TLV_TYPE_BSSID;
1202 pbssid_tlv->header.len = wlan_cpu_to_le16(
1203 MLAN_MAC_ADDR_LENGTH *
1204 puser_scan_in->bssid_num);
1205 memcpy_ext(pmadapter, pbssid_tlv->bssid,
1206 puser_scan_in->bssid_list,
1207 MLAN_MAC_ADDR_LENGTH *
1208 puser_scan_in->bssid_num,
1209 MLAN_MAC_ADDR_LENGTH *
1210 puser_scan_in->bssid_num);
1211 ptlv_pos += sizeof(MrvlIEtypesHeader_t) +
1212 MLAN_MAC_ADDR_LENGTH *
1213 puser_scan_in->bssid_num;
1214 DBG_HEXDUMP(
1215 MCMD_D, "scan bssid filter", pbssid_tlv,
1216 sizeof(MrvlIEtypesHeader_t) +
1217 MLAN_MAC_ADDR_LENGTH *
1218 puser_scan_in
1219 ->bssid_num);
1220 } else if (memcmp(pmadapter,
1221 pscan_cfg_out->specific_bssid,
1222 &zero_mac, sizeof(zero_mac))) {
1223 pbssid_tlv =
1224 (MrvlIEtypes_Bssid_List_t *)ptlv_pos;
1225 pbssid_tlv->header.type = TLV_TYPE_BSSID;
1226 pbssid_tlv->header.len =
1227 wlan_cpu_to_le16(MLAN_MAC_ADDR_LENGTH);
1228 memcpy_ext(pmadapter, pbssid_tlv->bssid,
1229 puser_scan_in->specific_bssid,
1230 MLAN_MAC_ADDR_LENGTH,
1231 MLAN_MAC_ADDR_LENGTH);
1232 ptlv_pos += sizeof(MrvlIEtypes_Bssid_List_t);
1233 }
1234 }
1235
1236 for (ssid_idx = 0;
1237 ((ssid_idx < NELEMENTS(puser_scan_in->ssid_list)) &&
1238 (*puser_scan_in->ssid_list[ssid_idx].ssid ||
1239 puser_scan_in->ssid_list[ssid_idx].max_len));
1240 ssid_idx++) {
1241 ssid_len = wlan_strlen(
1242 (char *)puser_scan_in->ssid_list[ssid_idx].ssid);
1243
1244 pwildcard_ssid_tlv =
1245 (MrvlIEtypes_WildCardSsIdParamSet_t *)ptlv_pos;
1246 pwildcard_ssid_tlv->header.type =
1247 wlan_cpu_to_le16(TLV_TYPE_WILDCARDSSID);
1248 pwildcard_ssid_tlv->header.len = (t_u16)(
1249 ssid_len +
1250 sizeof(pwildcard_ssid_tlv->max_ssid_length));
1251 pwildcard_ssid_tlv->max_ssid_length =
1252 puser_scan_in->ssid_list[ssid_idx].max_len;
1253
1254 memcpy_ext(pmadapter, pwildcard_ssid_tlv->ssid,
1255 puser_scan_in->ssid_list[ssid_idx].ssid,
1256 ssid_len, MLAN_MAX_SSID_LENGTH);
1257
1258 ptlv_pos += (sizeof(pwildcard_ssid_tlv->header) +
1259 pwildcard_ssid_tlv->header.len);
1260
1261 pwildcard_ssid_tlv->header.len = wlan_cpu_to_le16(
1262 pwildcard_ssid_tlv->header.len);
1263
1264 PRINTM(MINFO, "Scan: ssid_list[%d]: %s, %d\n", ssid_idx,
1265 pwildcard_ssid_tlv->ssid,
1266 pwildcard_ssid_tlv->max_ssid_length);
1267
1268 if (ssid_len) {
1269 ssid_filter = MTRUE;
1270 if (!puser_scan_in->ssid_list[ssid_idx].max_len) {
1271 PRINTM(MCMND, "user scan: %s\n",
1272 pwildcard_ssid_tlv->ssid);
1273 puser_scan_in->ssid_filter = MTRUE;
1274 }
1275 }
1276 }
1277
1278 /*
1279 * The default number of channels sent in the command is low to
1280 * ensure the response buffer from the firmware does not
1281 * truncate scan results. That is not an issue with an SSID or
1282 * BSSID filter applied to the scan results in the firmware.
1283 */
1284 if ((ssid_idx && ssid_filter) ||
1285 memcmp(pmadapter, pscan_cfg_out->specific_bssid, &zero_mac,
1286 sizeof(zero_mac))) {
1287 *pfiltered_scan = MTRUE;
1288 }
1289
1290 } else {
1291 pscan_cfg_out->bss_mode = (t_u8)pmadapter->scan_mode;
1292 num_probes = pmadapter->scan_probes;
1293 }
1294
1295 /*
1296 * If a specific BSSID or SSID is used, the number of channels in
1297 * the scan command will be increased to the absolute maximum.
1298 */
1299 if (*pfiltered_scan)
1300 *pmax_chan_per_scan = MRVDRV_MAX_CHANNELS_PER_SPECIFIC_SCAN;
1301 else
1302 *pmax_chan_per_scan = MRVDRV_CHANNELS_PER_SCAN_CMD;
1303
1304 if (puser_scan_in) {
1305 if (puser_scan_in->scan_chan_gap) {
1306 *pmax_chan_per_scan =
1307 MRVDRV_MAX_CHANNELS_PER_SPECIFIC_SCAN;
1308 PRINTM(MCMND, "Scan: channel gap = 0x%x\n",
1309 puser_scan_in->scan_chan_gap);
1310 pscan_gap_tlv = (MrvlIEtypes_ScanChanGap_t *)ptlv_pos;
1311 pscan_gap_tlv->header.type =
1312 wlan_cpu_to_le16(TLV_TYPE_SCAN_CHANNEL_GAP);
1313 pscan_gap_tlv->header.len = sizeof(pscan_gap_tlv->gap);
1314 pscan_gap_tlv->gap = wlan_cpu_to_le16(
1315 (t_u16)puser_scan_in->scan_chan_gap);
1316 ptlv_pos += sizeof(pscan_gap_tlv->header) +
1317 pscan_gap_tlv->header.len;
1318 pscan_gap_tlv->header.len =
1319 wlan_cpu_to_le16(pscan_gap_tlv->header.len);
1320 }
1321 } else if (pmadapter->scan_chan_gap) {
1322 *pmax_chan_per_scan = MRVDRV_MAX_CHANNELS_PER_SPECIFIC_SCAN;
1323 PRINTM(MCMND, "Scan: channel gap = 0x%x\n",
1324 pmadapter->scan_chan_gap);
1325 pscan_gap_tlv = (MrvlIEtypes_ScanChanGap_t *)ptlv_pos;
1326 pscan_gap_tlv->header.type =
1327 wlan_cpu_to_le16(TLV_TYPE_SCAN_CHANNEL_GAP);
1328 pscan_gap_tlv->header.len = sizeof(pscan_gap_tlv->gap);
1329 pscan_gap_tlv->gap =
1330 wlan_cpu_to_le16((t_u16)pmadapter->scan_chan_gap);
1331 ptlv_pos += sizeof(pscan_gap_tlv->header) +
1332 pscan_gap_tlv->header.len;
1333 }
1334 if (pmadapter->ext_scan) {
1335 pbss_mode = (MrvlIEtypes_BssMode_t *)ptlv_pos;
1336 pbss_mode->header.type = wlan_cpu_to_le16(TLV_TYPE_BSS_MODE);
1337 pbss_mode->header.len = sizeof(pbss_mode->bss_mode);
1338 pbss_mode->bss_mode = pscan_cfg_out->bss_mode;
1339 ptlv_pos += sizeof(pbss_mode->header) + pbss_mode->header.len;
1340 pbss_mode->header.len = wlan_cpu_to_le16(pbss_mode->header.len);
1341 if (pmadapter->ext_scan_enh) {
1342 if (puser_scan_in) {
1343 if (puser_scan_in->ext_scan_type ==
1344 EXT_SCAN_ENHANCE)
1345 pmadapter->ext_scan_type =
1346 EXT_SCAN_ENHANCE;
1347 else
1348 pmadapter->ext_scan_type =
1349 EXT_SCAN_DEFAULT;
1350 } else if (pmadapter->ext_scan == EXT_SCAN_TYPE_ENH)
1351 pmadapter->ext_scan_type = EXT_SCAN_ENHANCE;
1352 else
1353 pmadapter->ext_scan_type = EXT_SCAN_DEFAULT;
1354 if (pmadapter->ext_scan_type == EXT_SCAN_ENHANCE)
1355 *pmax_chan_per_scan =
1356 MRVDRV_MAX_CHANNELS_PER_SCAN;
1357 }
1358 }
1359 /* If the input config or adapter has the number of Probes set, add tlv
1360 */
1361 if (num_probes) {
1362 PRINTM(MINFO, "Scan: num_probes = %d\n", num_probes);
1363
1364 pnum_probes_tlv = (MrvlIEtypes_NumProbes_t *)ptlv_pos;
1365 pnum_probes_tlv->header.type =
1366 wlan_cpu_to_le16(TLV_TYPE_NUMPROBES);
1367 pnum_probes_tlv->header.len =
1368 sizeof(pnum_probes_tlv->num_probes);
1369 pnum_probes_tlv->num_probes =
1370 wlan_cpu_to_le16((t_u16)num_probes);
1371
1372 ptlv_pos += sizeof(pnum_probes_tlv->header) +
1373 pnum_probes_tlv->header.len;
1374
1375 pnum_probes_tlv->header.len =
1376 wlan_cpu_to_le16(pnum_probes_tlv->header.len);
1377 }
1378
1379 /* Append rates tlv */
1380 memset(pmadapter, rates, 0, sizeof(rates));
1381
1382 rates_size = wlan_get_supported_rates(
1383 pmpriv, pmpriv->bss_mode,
1384 (pmpriv->bss_mode == MLAN_BSS_MODE_INFRA) ?
1385 pmpriv->config_bands :
1386 pmadapter->adhoc_start_band,
1387 rates);
1388
1389 prates_tlv = (MrvlIEtypes_RatesParamSet_t *)ptlv_pos;
1390 prates_tlv->header.type = wlan_cpu_to_le16(TLV_TYPE_RATES);
1391 prates_tlv->header.len = wlan_cpu_to_le16((t_u16)rates_size);
1392 memcpy_ext(pmadapter, prates_tlv->rates, rates, rates_size, rates_size);
1393 ptlv_pos += sizeof(prates_tlv->header) + rates_size;
1394
1395 PRINTM(MINFO, "SCAN_CMD: Rates size = %d\n", rates_size);
1396
1397 if (wlan_is_ext_capa_support(pmpriv))
1398 wlan_add_ext_capa_info_ie(pmpriv, MNULL, &ptlv_pos);
1399 if (pmpriv->adapter->ecsa_enable) {
1400 t_u8 bandwidth = BW_20MHZ;
1401 t_u8 oper_class = 1;
1402 t_u32 usr_dot_11n_dev_cap;
1403 if (pmpriv->media_connected) {
1404 if (pmpriv->config_bands & BAND_A)
1405 usr_dot_11n_dev_cap =
1406 pmpriv->usr_dot_11n_dev_cap_a;
1407 else
1408 usr_dot_11n_dev_cap =
1409 pmpriv->usr_dot_11n_dev_cap_bg;
1410 if (usr_dot_11n_dev_cap & MBIT(17)) {
1411 bandwidth = BW_40MHZ;
1412 if (ISSUPP_11ACENABLED(
1413 pmadapter->fw_cap_info) &&
1414 (pmpriv->config_bands & BAND_AAC))
1415 bandwidth = BW_80MHZ;
1416 }
1417 wlan_get_curr_oper_class(
1418 pmpriv,
1419 pmpriv->curr_bss_params.bss_descriptor.channel,
1420 bandwidth, &oper_class);
1421 }
1422 wlan_add_supported_oper_class_ie(pmpriv, &ptlv_pos, oper_class);
1423 }
1424 wlan_add_wps_probe_request_ie(pmpriv, &ptlv_pos);
1425
1426 if (puser_scan_in && puser_scan_in->proberesp_only) {
1427 MrvlIEtypes_OnlyProberesp_t *proberesp_only =
1428 (MrvlIEtypes_OnlyProberesp_t *)ptlv_pos;
1429 memset(pmadapter, proberesp_only, 0,
1430 sizeof(MrvlIEtypes_OnlyProberesp_t));
1431 proberesp_only->header.type =
1432 wlan_cpu_to_le16(TLV_TYPE_ONLYPROBERESP);
1433 proberesp_only->header.len = wlan_cpu_to_le16(sizeof(t_u8));
1434 proberesp_only->proberesp_only = puser_scan_in->proberesp_only;
1435 ptlv_pos += sizeof(MrvlIEtypes_OnlyProberesp_t);
1436 }
1437
1438 if (puser_scan_in && memcmp(pmadapter, puser_scan_in->random_mac,
1439 zero_mac, MLAN_MAC_ADDR_LENGTH)) {
1440 MrvlIEtypes_MacAddr_t *randomMacParam =
1441 (MrvlIEtypes_MacAddr_t *)ptlv_pos;
1442 memset(pmadapter, randomMacParam, 0,
1443 sizeof(MrvlIEtypes_MacAddr_t));
1444 randomMacParam->header.type =
1445 wlan_cpu_to_le16(TLV_TYPE_RANDOM_MAC);
1446 randomMacParam->header.len =
1447 wlan_cpu_to_le16(MLAN_MAC_ADDR_LENGTH);
1448 memcpy_ext(pmadapter, randomMacParam->mac,
1449 puser_scan_in->random_mac, MLAN_MAC_ADDR_LENGTH,
1450 MLAN_MAC_ADDR_LENGTH);
1451 ptlv_pos += sizeof(MrvlIEtypes_MacAddr_t);
1452 }
1453 /*
1454 * Set the output for the channel TLV to the address in the tlv buffer
1455 * past any TLVs that were added in this function (SSID, num_probes).
1456 * Channel TLVs will be added past this for each scan command,
1457 * preserving the TLVs that were previously added.
1458 */
1459 *ppchan_list_out = (MrvlIEtypes_ChanListParamSet_t *)ptlv_pos;
1460
1461 if (puser_scan_in && puser_scan_in->chan_list[0].chan_number) {
1462 PRINTM(MINFO, "Scan: Using supplied channel list\n");
1463
1464 for (chan_idx = 0;
1465 chan_idx < WLAN_USER_SCAN_CHAN_MAX &&
1466 puser_scan_in->chan_list[chan_idx].chan_number;
1467 chan_idx++) {
1468 radio_type =
1469 puser_scan_in->chan_list[chan_idx].radio_type;
1470 /*Ignore 5G/2G channels if radio_type do not match
1471 * band*/
1472 if (!wlan_is_band_compatible(
1473 pmpriv->config_bands,
1474 radio_type_to_band(radio_type)))
1475 continue;
1476 (pscan_chan_list + chan_list_idx)->bandcfg.chanBand =
1477 radio_type;
1478
1479 channel =
1480 puser_scan_in->chan_list[chan_idx].chan_number;
1481 (pscan_chan_list + chan_list_idx)->chan_number =
1482 channel;
1483
1484 scan_type =
1485 puser_scan_in->chan_list[chan_idx].scan_type;
1486 if (scan_type == MLAN_SCAN_TYPE_UNCHANGED)
1487 scan_type = pmadapter->scan_type;
1488
1489 if (radio_type == BAND_5GHZ) {
1490 if (pmadapter->fw_bands & BAND_A)
1491 PRINTM(MINFO,
1492 "UserScan request for A Band channel %d!!\n",
1493 channel);
1494 else {
1495 PRINTM(MERROR,
1496 "Scan in A band is not allowed!!\n");
1497 ret = MLAN_STATUS_FAILURE;
1498 LEAVE();
1499 return ret;
1500 }
1501 }
1502 if (!puser_scan_in->scan_cfg_only) {
1503 if (wlan_is_chan_passive(
1504 pmpriv,
1505 radio_type_to_band(radio_type),
1506 channel)) {
1507 /* do not send probe requests on this
1508 * channel */
1509 scan_type = MLAN_SCAN_TYPE_PASSIVE;
1510 }
1511 }
1512 /* Prevent active scanning on a radar controlled channel
1513 */
1514 if (radio_type == BAND_5GHZ &&
1515 scan_type == MLAN_SCAN_TYPE_PASSIVE) {
1516 if (pmadapter->active_scan_triggered == MFALSE)
1517 if (wlan_11h_radar_detect_required(
1518 pmpriv, channel)) {
1519 scan_type =
1520 MLAN_SCAN_TYPE_PASSIVE_TO_ACTIVE;
1521 }
1522 }
1523 if (radio_type == BAND_2GHZ &&
1524 !puser_scan_in->scan_cfg_only &&
1525 scan_type != MLAN_SCAN_TYPE_PASSIVE) {
1526 if (pmadapter->active_scan_triggered == MFALSE)
1527 if (wlan_bg_scan_type_is_passive(
1528 pmpriv, channel)) {
1529 scan_type =
1530 MLAN_SCAN_TYPE_PASSIVE;
1531 }
1532 }
1533 if (scan_type == MLAN_SCAN_TYPE_PASSIVE ||
1534 scan_type == MLAN_SCAN_TYPE_PASSIVE_TO_ACTIVE) {
1535 (pscan_chan_list + chan_list_idx)
1536 ->chan_scan_mode.passive_scan = MTRUE;
1537 (pscan_chan_list + chan_list_idx)
1538 ->chan_scan_mode.hidden_ssid_report =
1539 MTRUE;
1540 } else {
1541 (pscan_chan_list + chan_list_idx)
1542 ->chan_scan_mode.passive_scan = MFALSE;
1543 }
1544
1545 if (puser_scan_in->chan_list[chan_idx].scan_time) {
1546 scan_dur = (t_u16)puser_scan_in
1547 ->chan_list[chan_idx]
1548 .scan_time;
1549 } else {
1550 if (scan_type == MLAN_SCAN_TYPE_PASSIVE ||
1551 scan_type ==
1552 MLAN_SCAN_TYPE_PASSIVE_TO_ACTIVE) {
1553 scan_dur = pmadapter->passive_scan_time;
1554 } else if (*pfiltered_scan) {
1555 scan_dur =
1556 pmadapter->specific_scan_time;
1557 } else {
1558 scan_dur = pmadapter->active_scan_time;
1559 }
1560 }
1561
1562 if (pmadapter->coex_scan &&
1563 pmadapter->coex_min_scan_time &&
1564 (pmadapter->coex_min_scan_time > scan_dur))
1565 scan_dur = pmadapter->coex_min_scan_time;
1566 if (scan_type == MLAN_SCAN_TYPE_PASSIVE_TO_ACTIVE &&
1567 pmadapter->passive_to_active_scan ==
1568 MLAN_PASS_TO_ACT_SCAN_EN) {
1569 (pscan_chan_list + chan_list_idx)
1570 ->chan_scan_mode.passive_to_active_scan =
1571 MTRUE;
1572 scan_dur = MAX(MIN_PASSIVE_TO_ACTIVE_SCAN_TIME,
1573 scan_dur);
1574 }
1575 PRINTM(MINFO,
1576 "chan=%d, mode=%d, passive_to_active=%d\n",
1577 (pscan_chan_list + chan_list_idx)->chan_number,
1578 (pscan_chan_list + chan_list_idx)
1579 ->chan_scan_mode.passive_scan,
1580 (pscan_chan_list + chan_list_idx)
1581 ->chan_scan_mode.passive_to_active_scan);
1582
1583 (pscan_chan_list + chan_list_idx)->min_scan_time =
1584 wlan_cpu_to_le16(scan_dur);
1585 (pscan_chan_list + chan_list_idx)->max_scan_time =
1586 wlan_cpu_to_le16(scan_dur);
1587 chan_list_idx++;
1588 }
1589
1590 /* Check if we are only scanning the current channel */
1591 if ((chan_idx == 1) &&
1592 (puser_scan_in->chan_list[0].chan_number ==
1593 pmpriv->curr_bss_params.bss_descriptor.channel)) {
1594 *pscan_current_only = MTRUE;
1595 PRINTM(MINFO, "Scan: Scanning current channel only\n");
1596 }
1597
1598 } else {
1599 num_of_channel =
1600 wlan_scan_create_channel_list(pmpriv, puser_scan_in,
1601 pscan_chan_list,
1602 *pfiltered_scan);
1603 PRINTM(MCMND, "Scan: Creating full region channel list %d\n",
1604 num_of_channel);
1605 }
1606
1607 LEAVE();
1608 return ret;
1609 }
1610
1611 /**
1612 * @brief Inspect the scan response buffer for pointers to expected TLVs
1613 *
1614 * TLVs can be included at the end of the scan response BSS information.
1615 * Parse the data in the buffer for pointers to TLVs that can potentially
1616 * be passed back in the response
1617 *
1618 * @param pmadapter Pointer to the mlan_adapter structure
1619 * @param ptlv Pointer to the start of the TLV buffer to parse
1620 * @param tlv_buf_size Size of the TLV buffer
1621 * @param req_tlv_type Request TLV's type
1622 * @param pptlv Output parameter: Pointer to the request TLV if
1623 * found
1624 *
1625 * @return N/A
1626 */
wlan_ret_802_11_scan_get_tlv_ptrs(pmlan_adapter pmadapter,MrvlIEtypes_Data_t * ptlv,t_u32 tlv_buf_size,t_u32 req_tlv_type,MrvlIEtypes_Data_t ** pptlv)1627 static t_void wlan_ret_802_11_scan_get_tlv_ptrs(pmlan_adapter pmadapter,
1628 MrvlIEtypes_Data_t *ptlv,
1629 t_u32 tlv_buf_size,
1630 t_u32 req_tlv_type,
1631 MrvlIEtypes_Data_t **pptlv)
1632 {
1633 MrvlIEtypes_Data_t *pcurrent_tlv;
1634 t_u32 tlv_buf_left;
1635 t_u32 tlv_type;
1636 t_u32 tlv_len;
1637
1638 ENTER();
1639
1640 pcurrent_tlv = ptlv;
1641 tlv_buf_left = tlv_buf_size;
1642 *pptlv = MNULL;
1643
1644 PRINTM(MINFO, "SCAN_RESP: tlv_buf_size = %d\n", tlv_buf_size);
1645
1646 while (tlv_buf_left >= sizeof(MrvlIEtypesHeader_t)) {
1647 tlv_type = wlan_le16_to_cpu(pcurrent_tlv->header.type);
1648 tlv_len = wlan_le16_to_cpu(pcurrent_tlv->header.len);
1649
1650 if (sizeof(ptlv->header) + tlv_len > tlv_buf_left) {
1651 PRINTM(MERROR, "SCAN_RESP: TLV buffer corrupt\n");
1652 break;
1653 }
1654
1655 if (req_tlv_type == tlv_type) {
1656 switch (tlv_type) {
1657 case TLV_TYPE_TSFTIMESTAMP:
1658 PRINTM(MINFO,
1659 "SCAN_RESP: TSF Timestamp TLV, len = %d\n",
1660 tlv_len);
1661 *pptlv = (MrvlIEtypes_Data_t *)pcurrent_tlv;
1662 break;
1663 case TLV_TYPE_CHANNELBANDLIST:
1664 PRINTM(MINFO,
1665 "SCAN_RESP: CHANNEL BAND LIST TLV, len = %d\n",
1666 tlv_len);
1667 *pptlv = (MrvlIEtypes_Data_t *)pcurrent_tlv;
1668 break;
1669 case TLV_TYPE_CHANNEL_STATS:
1670 PRINTM(MINFO,
1671 "SCAN_RESP: CHANNEL STATS TLV, len = %d\n",
1672 tlv_len);
1673 *pptlv = (MrvlIEtypes_Data_t *)pcurrent_tlv;
1674 break;
1675 default:
1676 PRINTM(MERROR,
1677 "SCAN_RESP: Unhandled TLV = %d\n",
1678 tlv_type);
1679 /* Give up, this seems corrupted */
1680 LEAVE();
1681 return;
1682 }
1683 }
1684
1685 if (*pptlv) {
1686 /* HEXDUMP("SCAN_RESP: TLV Buf", (t_u8 *)*pptlv+4,
1687 * tlv_len); */
1688 break;
1689 }
1690
1691 tlv_buf_left -= (sizeof(ptlv->header) + tlv_len);
1692 pcurrent_tlv =
1693 (MrvlIEtypes_Data_t *)(pcurrent_tlv->data + tlv_len);
1694
1695 } /* while */
1696
1697 LEAVE();
1698 }
1699
1700 /**
1701 * @brief Interpret a BSS scan response returned from the firmware
1702 *
1703 * Parse the various fixed fields and IEs passed back for a BSS probe
1704 * response or beacon from the scan command. Record information as needed
1705 * in the scan table BSSDescriptor_t for that entry.
1706 *
1707 * @param pmadapter A pointer to mlan_adapter structure
1708 * @param pbss_entry Output parameter: Pointer to the BSS Entry
1709 * @param pbeacon_info Pointer to the Beacon information
1710 * @param bytes_left Number of bytes left to parse
1711 * @param ext_scan extended scan
1712 *
1713 * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
1714 */
wlan_interpret_bss_desc_with_ie(pmlan_adapter pmadapter,BSSDescriptor_t * pbss_entry,t_u8 ** pbeacon_info,t_u32 * bytes_left,t_u8 ext_scan)1715 static mlan_status wlan_interpret_bss_desc_with_ie(pmlan_adapter pmadapter,
1716 BSSDescriptor_t *pbss_entry,
1717 t_u8 **pbeacon_info,
1718 t_u32 *bytes_left,
1719 t_u8 ext_scan)
1720 {
1721 mlan_status ret = MLAN_STATUS_SUCCESS;
1722 IEEEtypes_ElementId_e element_id;
1723 IEEEtypes_FhParamSet_t *pfh_param_set;
1724 IEEEtypes_DsParamSet_t *pds_param_set;
1725 IEEEtypes_CfParamSet_t *pcf_param_set;
1726 IEEEtypes_IbssParamSet_t *pibss_param_set;
1727 IEEEtypes_CapInfo_t *pcap_info;
1728 WLAN_802_11_FIXED_IEs fixed_ie;
1729 t_u8 *pcurrent_ptr;
1730 t_u8 *prate;
1731 t_u8 element_len;
1732 t_u16 total_ie_len;
1733 t_u8 bytes_to_copy;
1734 t_u8 rate_size;
1735 t_u16 beacon_size;
1736 t_u8 found_data_rate_ie;
1737 t_u32 bytes_left_for_current_beacon;
1738 IEEEtypes_ERPInfo_t *perp_info;
1739
1740 IEEEtypes_VendorSpecific_t *pvendor_ie;
1741 const t_u8 wpa_oui[4] = {0x00, 0x50, 0xf2, 0x01};
1742 const t_u8 wmm_oui[4] = {0x00, 0x50, 0xf2, 0x02};
1743 const t_u8 osen_oui[] = {0x50, 0x6f, 0x9a, 0x12};
1744
1745 IEEEtypes_CountryInfoSet_t *pcountry_info;
1746 IEEEtypes_Extension_t *pext_tlv;
1747
1748 ENTER();
1749
1750 found_data_rate_ie = MFALSE;
1751 rate_size = 0;
1752 beacon_size = 0;
1753
1754 if (*bytes_left >= sizeof(beacon_size)) {
1755 /* Extract & convert beacon size from the command buffer */
1756 memcpy_ext(pmadapter, &beacon_size, *pbeacon_info,
1757 sizeof(beacon_size), sizeof(beacon_size));
1758 beacon_size = wlan_le16_to_cpu(beacon_size);
1759 *bytes_left -= sizeof(beacon_size);
1760 *pbeacon_info += sizeof(beacon_size);
1761 }
1762
1763 if (!beacon_size || beacon_size > *bytes_left) {
1764 *pbeacon_info += *bytes_left;
1765 *bytes_left = 0;
1766
1767 LEAVE();
1768 return MLAN_STATUS_FAILURE;
1769 }
1770
1771 /* Initialize the current working beacon pointer for this BSS iteration
1772 */
1773 pcurrent_ptr = *pbeacon_info;
1774
1775 /* Advance the return beacon pointer past the current beacon */
1776 *pbeacon_info += beacon_size;
1777 *bytes_left -= beacon_size;
1778
1779 bytes_left_for_current_beacon = beacon_size;
1780
1781 if (bytes_left_for_current_beacon <
1782 (MLAN_MAC_ADDR_LENGTH + sizeof(t_u8) +
1783 sizeof(WLAN_802_11_FIXED_IEs))) {
1784 PRINTM(MERROR, "InterpretIE: Not enough bytes left\n");
1785 LEAVE();
1786 return MLAN_STATUS_FAILURE;
1787 }
1788
1789 memcpy_ext(pmadapter, pbss_entry->mac_address, pcurrent_ptr,
1790 MLAN_MAC_ADDR_LENGTH, MLAN_MAC_ADDR_LENGTH);
1791 PRINTM(MINFO, "InterpretIE: AP MAC Addr-" MACSTR "\n",
1792 MAC2STR(pbss_entry->mac_address));
1793
1794 pcurrent_ptr += MLAN_MAC_ADDR_LENGTH;
1795 bytes_left_for_current_beacon -= MLAN_MAC_ADDR_LENGTH;
1796
1797 /*
1798 * Next 4 fields are RSSI (for legacy scan only), time stamp,
1799 * beacon interval, and capability information
1800 */
1801 if (!ext_scan) {
1802 /* RSSI is 1 byte long */
1803 pbss_entry->rssi = (t_s32)(*pcurrent_ptr);
1804 PRINTM(MINFO, "InterpretIE: RSSI=%02X\n", *pcurrent_ptr);
1805 pcurrent_ptr += 1;
1806 bytes_left_for_current_beacon -= 1;
1807 }
1808
1809 /*
1810 * The RSSI is not part of the beacon/probe response. After we have
1811 * advanced pcurrent_ptr past the RSSI field, save the remaining
1812 * data for use at the application layer
1813 */
1814 pbss_entry->pbeacon_buf = pcurrent_ptr;
1815 pbss_entry->beacon_buf_size = bytes_left_for_current_beacon;
1816
1817 /* Time stamp is 8 bytes long */
1818 memcpy_ext(pmadapter, fixed_ie.time_stamp, pcurrent_ptr, 8,
1819 sizeof(fixed_ie.time_stamp));
1820 memcpy_ext(pmadapter, pbss_entry->time_stamp, pcurrent_ptr, 8,
1821 sizeof(pbss_entry->time_stamp));
1822 pcurrent_ptr += 8;
1823 bytes_left_for_current_beacon -= 8;
1824
1825 /* Beacon interval is 2 bytes long */
1826 memcpy_ext(pmadapter, &fixed_ie.beacon_interval, pcurrent_ptr, 2,
1827 sizeof(fixed_ie.beacon_interval));
1828 pbss_entry->beacon_period = wlan_le16_to_cpu(fixed_ie.beacon_interval);
1829 pcurrent_ptr += 2;
1830 bytes_left_for_current_beacon -= 2;
1831
1832 /* Capability information is 2 bytes long */
1833 memcpy_ext(pmadapter, &fixed_ie.capabilities, pcurrent_ptr, 2,
1834 sizeof(fixed_ie.capabilities));
1835 PRINTM(MINFO, "InterpretIE: fixed_ie.capabilities=0x%X\n",
1836 fixed_ie.capabilities);
1837 fixed_ie.capabilities = wlan_le16_to_cpu(fixed_ie.capabilities);
1838 pcap_info = (IEEEtypes_CapInfo_t *)&fixed_ie.capabilities;
1839 memcpy_ext(pmadapter, &pbss_entry->cap_info, pcap_info,
1840 sizeof(IEEEtypes_CapInfo_t), sizeof(IEEEtypes_CapInfo_t));
1841 pcurrent_ptr += 2;
1842 bytes_left_for_current_beacon -= 2;
1843
1844 /* Rest of the current buffer are IE's */
1845 PRINTM(MINFO, "InterpretIE: IELength for this AP = %d\n",
1846 bytes_left_for_current_beacon);
1847
1848 HEXDUMP("InterpretIE: IE info", (t_u8 *)pcurrent_ptr,
1849 bytes_left_for_current_beacon);
1850
1851 if (pcap_info->privacy) {
1852 PRINTM(MINFO, "InterpretIE: AP WEP enabled\n");
1853 pbss_entry->privacy = Wlan802_11PrivFilter8021xWEP;
1854 } else {
1855 pbss_entry->privacy = Wlan802_11PrivFilterAcceptAll;
1856 }
1857
1858 if (pcap_info->ibss == 1)
1859 pbss_entry->bss_mode = MLAN_BSS_MODE_IBSS;
1860 else
1861 pbss_entry->bss_mode = MLAN_BSS_MODE_INFRA;
1862
1863 if (pcap_info->spectrum_mgmt == 1) {
1864 PRINTM(MINFO, "InterpretIE: 11h- Spectrum Management "
1865 "capability bit found\n");
1866 pbss_entry->wlan_11h_bss_info.sensed_11h = 1;
1867 }
1868
1869 /* Process variable IE */
1870 while (bytes_left_for_current_beacon >= 2) {
1871 element_id = (IEEEtypes_ElementId_e)(*((t_u8 *)pcurrent_ptr));
1872 element_len = *((t_u8 *)pcurrent_ptr + 1);
1873 total_ie_len = element_len + sizeof(IEEEtypes_Header_t);
1874
1875 if (bytes_left_for_current_beacon < total_ie_len) {
1876 PRINTM(MERROR, "InterpretIE: Error in processing IE, "
1877 "bytes left < IE length\n");
1878 bytes_left_for_current_beacon = 0;
1879 ret = MLAN_STATUS_FAILURE;
1880 continue;
1881 }
1882
1883 switch (element_id) {
1884 case SSID:
1885 if (element_len > MRVDRV_MAX_SSID_LENGTH) {
1886 bytes_left_for_current_beacon = 0;
1887 ret = MLAN_STATUS_FAILURE;
1888 continue;
1889 }
1890 if (!pbss_entry->ssid.ssid_len) {
1891 pbss_entry->ssid.ssid_len = element_len;
1892 memcpy_ext(pmadapter, pbss_entry->ssid.ssid,
1893 (pcurrent_ptr + 2), element_len,
1894 sizeof(pbss_entry->ssid.ssid));
1895 }
1896 PRINTM(MINFO, "InterpretIE: ssid: %-32s\n",
1897 pbss_entry->ssid.ssid);
1898 break;
1899
1900 case SUPPORTED_RATES:
1901 if (element_len > WLAN_SUPPORTED_RATES) {
1902 bytes_left_for_current_beacon = 0;
1903 ret = MLAN_STATUS_FAILURE;
1904 continue;
1905 }
1906 memcpy_ext(pmadapter, pbss_entry->data_rates,
1907 pcurrent_ptr + 2, element_len,
1908 sizeof(pbss_entry->data_rates));
1909 memcpy_ext(pmadapter, pbss_entry->supported_rates,
1910 pcurrent_ptr + 2, element_len,
1911 sizeof(pbss_entry->supported_rates));
1912 HEXDUMP("InterpretIE: SupportedRates:",
1913 pbss_entry->supported_rates, element_len);
1914 rate_size = element_len;
1915 found_data_rate_ie = MTRUE;
1916 break;
1917
1918 case FH_PARAM_SET:
1919 pfh_param_set = (IEEEtypes_FhParamSet_t *)pcurrent_ptr;
1920 pbss_entry->network_type_use = Wlan802_11FH;
1921 memcpy_ext(pmadapter,
1922 &pbss_entry->phy_param_set.fh_param_set,
1923 pfh_param_set, total_ie_len,
1924 sizeof(IEEEtypes_FhParamSet_t));
1925 pbss_entry->phy_param_set.fh_param_set.len = MIN(
1926 element_len, (sizeof(IEEEtypes_FhParamSet_t) -
1927 sizeof(IEEEtypes_Header_t)));
1928 pbss_entry->phy_param_set.fh_param_set.dwell_time =
1929 wlan_le16_to_cpu(
1930 pbss_entry->phy_param_set.fh_param_set
1931 .dwell_time);
1932 break;
1933
1934 case DS_PARAM_SET:
1935 pds_param_set = (IEEEtypes_DsParamSet_t *)pcurrent_ptr;
1936
1937 pbss_entry->network_type_use = Wlan802_11DS;
1938 pbss_entry->channel = pds_param_set->current_chan;
1939
1940 memcpy_ext(pmadapter,
1941 &pbss_entry->phy_param_set.ds_param_set,
1942 pds_param_set, total_ie_len,
1943 sizeof(IEEEtypes_DsParamSet_t));
1944 pbss_entry->phy_param_set.ds_param_set.len = MIN(
1945 element_len, (sizeof(IEEEtypes_DsParamSet_t) -
1946 sizeof(IEEEtypes_Header_t)));
1947 break;
1948
1949 case CF_PARAM_SET:
1950 pcf_param_set = (IEEEtypes_CfParamSet_t *)pcurrent_ptr;
1951 memcpy_ext(pmadapter,
1952 &pbss_entry->ss_param_set.cf_param_set,
1953 pcf_param_set, total_ie_len,
1954 sizeof(IEEEtypes_CfParamSet_t));
1955 pbss_entry->ss_param_set.cf_param_set.len = MIN(
1956 element_len, (sizeof(IEEEtypes_CfParamSet_t) -
1957 sizeof(IEEEtypes_Header_t)));
1958 break;
1959
1960 case IBSS_PARAM_SET:
1961 pibss_param_set =
1962 (IEEEtypes_IbssParamSet_t *)pcurrent_ptr;
1963 pbss_entry->atim_window =
1964 wlan_le16_to_cpu(pibss_param_set->atim_window);
1965 memcpy_ext(pmadapter,
1966 &pbss_entry->ss_param_set.ibss_param_set,
1967 pibss_param_set, total_ie_len,
1968 sizeof(IEEEtypes_IbssParamSet_t));
1969 pbss_entry->ss_param_set.ibss_param_set.len = MIN(
1970 element_len, (sizeof(IEEEtypes_IbssParamSet_t) -
1971 sizeof(IEEEtypes_Header_t)));
1972 break;
1973
1974 /* Handle Country Info IE */
1975 case COUNTRY_INFO:
1976 pcountry_info =
1977 (IEEEtypes_CountryInfoSet_t *)pcurrent_ptr;
1978
1979 if (pcountry_info->len <
1980 sizeof(pcountry_info->country_code) ||
1981 (unsigned)(pcountry_info->len + 2) >
1982 sizeof(IEEEtypes_CountryInfoFullSet_t)) {
1983 PRINTM(MERROR,
1984 "InterpretIE: 11D- Err "
1985 "country_info len =%d min=%d max=%d\n",
1986 pcountry_info->len,
1987 sizeof(pcountry_info->country_code),
1988 sizeof(IEEEtypes_CountryInfoFullSet_t));
1989 LEAVE();
1990 return MLAN_STATUS_FAILURE;
1991 }
1992
1993 memcpy_ext(pmadapter, &pbss_entry->country_info,
1994 pcountry_info, pcountry_info->len + 2,
1995 sizeof(pbss_entry->country_info));
1996 HEXDUMP("InterpretIE: 11D- country_info:",
1997 (t_u8 *)pcountry_info,
1998 (t_u32)(pcountry_info->len + 2));
1999 break;
2000
2001 case ERP_INFO:
2002 perp_info = (IEEEtypes_ERPInfo_t *)pcurrent_ptr;
2003 pbss_entry->erp_flags = perp_info->erp_flags;
2004 break;
2005
2006 case POWER_CONSTRAINT:
2007 case POWER_CAPABILITY:
2008 case TPC_REPORT:
2009 case CHANNEL_SWITCH_ANN:
2010 case QUIET:
2011 case IBSS_DFS:
2012 case SUPPORTED_CHANNELS:
2013 case TPC_REQUEST:
2014 wlan_11h_process_bss_elem(
2015 pmadapter, &pbss_entry->wlan_11h_bss_info,
2016 pcurrent_ptr);
2017 break;
2018 case EXTENDED_SUPPORTED_RATES:
2019 /*
2020 * Only process extended supported rate
2021 * if data rate is already found.
2022 * Data rate IE should come before
2023 * extended supported rate IE
2024 */
2025 if (found_data_rate_ie) {
2026 if ((element_len + rate_size) >
2027 WLAN_SUPPORTED_RATES) {
2028 bytes_to_copy = (WLAN_SUPPORTED_RATES -
2029 rate_size);
2030 } else {
2031 bytes_to_copy = element_len;
2032 }
2033
2034 prate = (t_u8 *)pbss_entry->data_rates;
2035 prate += rate_size;
2036 memcpy_ext(pmadapter, prate, pcurrent_ptr + 2,
2037 bytes_to_copy, bytes_to_copy);
2038
2039 prate = (t_u8 *)pbss_entry->supported_rates;
2040 prate += rate_size;
2041 memcpy_ext(pmadapter, prate, pcurrent_ptr + 2,
2042 bytes_to_copy, bytes_to_copy);
2043 }
2044 HEXDUMP("InterpretIE: ExtSupportedRates:",
2045 pbss_entry->supported_rates,
2046 element_len + rate_size);
2047 break;
2048
2049 case VENDOR_SPECIFIC_221:
2050 pvendor_ie = (IEEEtypes_VendorSpecific_t *)pcurrent_ptr;
2051
2052 if (!memcmp(pmadapter, pvendor_ie->vend_hdr.oui,
2053 wpa_oui, sizeof(wpa_oui))) {
2054 pbss_entry->pwpa_ie =
2055 (IEEEtypes_VendorSpecific_t *)
2056 pcurrent_ptr;
2057 pbss_entry->wpa_offset = (t_u16)(
2058 pcurrent_ptr - pbss_entry->pbeacon_buf);
2059 HEXDUMP("InterpretIE: Resp WPA_IE",
2060 (t_u8 *)pbss_entry->pwpa_ie,
2061 ((*(pbss_entry->pwpa_ie)).vend_hdr.len +
2062 sizeof(IEEEtypes_Header_t)));
2063 } else if (!memcmp(pmadapter, pvendor_ie->vend_hdr.oui,
2064 wmm_oui, sizeof(wmm_oui))) {
2065 if (total_ie_len ==
2066 sizeof(IEEEtypes_WmmParameter_t) ||
2067 total_ie_len ==
2068 sizeof(IEEEtypes_WmmInfo_t)) {
2069 /*
2070 * Only accept and copy the WMM IE if
2071 * it matches the size expected for the
2072 * WMM Info IE or the WMM Parameter IE.
2073 */
2074 memcpy_ext(pmadapter,
2075 (t_u8 *)&pbss_entry->wmm_ie,
2076 pcurrent_ptr, total_ie_len,
2077 sizeof(pbss_entry->wmm_ie));
2078 HEXDUMP("InterpretIE: Resp WMM_IE",
2079 (t_u8 *)&pbss_entry->wmm_ie,
2080 total_ie_len);
2081 }
2082 } else if (!memcmp(pmadapter, pvendor_ie->vend_hdr.oui,
2083 osen_oui, sizeof(osen_oui))) {
2084 pbss_entry->posen_ie =
2085 (IEEEtypes_Generic_t *)pcurrent_ptr;
2086 pbss_entry->osen_offset = (t_u16)(
2087 pcurrent_ptr - pbss_entry->pbeacon_buf);
2088 HEXDUMP("InterpretIE: Resp OSEN_IE",
2089 (t_u8 *)pbss_entry->posen_ie,
2090 (*(pbss_entry->posen_ie)).ieee_hdr.len +
2091 sizeof(IEEEtypes_Header_t));
2092 }
2093 break;
2094 case RSN_IE:
2095 pbss_entry->prsn_ie =
2096 (IEEEtypes_Generic_t *)pcurrent_ptr;
2097 pbss_entry->rsn_offset =
2098 (t_u16)(pcurrent_ptr - pbss_entry->pbeacon_buf);
2099 HEXDUMP("InterpretIE: Resp RSN_IE",
2100 (t_u8 *)pbss_entry->prsn_ie,
2101 (*(pbss_entry->prsn_ie)).ieee_hdr.len +
2102 sizeof(IEEEtypes_Header_t));
2103 break;
2104 case RSNX_IE:
2105 pbss_entry->prsnx_ie =
2106 (IEEEtypes_Generic_t *)pcurrent_ptr;
2107 pbss_entry->rsnx_offset =
2108 (t_u16)(pcurrent_ptr - pbss_entry->pbeacon_buf);
2109 HEXDUMP("InterpretIE: Resp RSNX_IE",
2110 (t_u8 *)pbss_entry->prsnx_ie,
2111 (*(pbss_entry->prsnx_ie)).ieee_hdr.len +
2112 sizeof(IEEEtypes_Header_t));
2113 break;
2114 case WAPI_IE:
2115 pbss_entry->pwapi_ie =
2116 (IEEEtypes_Generic_t *)pcurrent_ptr;
2117 pbss_entry->wapi_offset =
2118 (t_u16)(pcurrent_ptr - pbss_entry->pbeacon_buf);
2119 HEXDUMP("InterpretIE: Resp WAPI_IE",
2120 (t_u8 *)pbss_entry->pwapi_ie,
2121 (*(pbss_entry->pwapi_ie)).ieee_hdr.len +
2122 sizeof(IEEEtypes_Header_t));
2123 break;
2124 case MULTI_BSSID:
2125 if (IS_FW_SUPPORT_MULTIBSSID(pmadapter)) {
2126 pbss_entry->multi_bssid_ap = MULTI_BSSID_AP;
2127 HEXDUMP("InterpretIE: Multi BSSID IE",
2128 (t_u8 *)pcurrent_ptr, total_ie_len);
2129 }
2130 break;
2131 case HT_CAPABILITY:
2132 pbss_entry->pht_cap = (IEEEtypes_HTCap_t *)pcurrent_ptr;
2133 pbss_entry->ht_cap_offset =
2134 (t_u16)(pcurrent_ptr - pbss_entry->pbeacon_buf);
2135 HEXDUMP("InterpretIE: Resp HTCAP_IE",
2136 (t_u8 *)pbss_entry->pht_cap,
2137 (*(pbss_entry->pht_cap)).ieee_hdr.len +
2138 sizeof(IEEEtypes_Header_t));
2139 break;
2140 case HT_OPERATION:
2141 pbss_entry->pht_info =
2142 (IEEEtypes_HTInfo_t *)pcurrent_ptr;
2143 pbss_entry->ht_info_offset =
2144 (t_u16)(pcurrent_ptr - pbss_entry->pbeacon_buf);
2145 HEXDUMP("InterpretIE: Resp HTINFO_IE",
2146 (t_u8 *)pbss_entry->pht_info,
2147 (*(pbss_entry->pht_info)).ieee_hdr.len +
2148 sizeof(IEEEtypes_Header_t));
2149 break;
2150 case BSSCO_2040:
2151 pbss_entry->pbss_co_2040 =
2152 (IEEEtypes_2040BSSCo_t *)pcurrent_ptr;
2153 pbss_entry->bss_co_2040_offset =
2154 (t_u16)(pcurrent_ptr - pbss_entry->pbeacon_buf);
2155 HEXDUMP("InterpretIE: Resp 2040BSSCOEXISTANCE_IE",
2156 (t_u8 *)pbss_entry->pbss_co_2040,
2157 (*(pbss_entry->pbss_co_2040)).ieee_hdr.len +
2158 sizeof(IEEEtypes_Header_t));
2159 break;
2160 case EXT_CAPABILITY:
2161 pbss_entry->pext_cap =
2162 (IEEEtypes_ExtCap_t *)pcurrent_ptr;
2163 pbss_entry->ext_cap_offset =
2164 (t_u16)(pcurrent_ptr - pbss_entry->pbeacon_buf);
2165 HEXDUMP("InterpretIE: Resp EXTCAP_IE",
2166 (t_u8 *)pbss_entry->pext_cap,
2167 (*(pbss_entry->pext_cap)).ieee_hdr.len +
2168 sizeof(IEEEtypes_Header_t));
2169 break;
2170 case OVERLAPBSSSCANPARAM:
2171 pbss_entry->poverlap_bss_scan_param =
2172 (IEEEtypes_OverlapBSSScanParam_t *)pcurrent_ptr;
2173 pbss_entry->overlap_bss_offset =
2174 (t_u16)(pcurrent_ptr - pbss_entry->pbeacon_buf);
2175 HEXDUMP("InterpretIE: Resp OBSS_IE",
2176 (t_u8 *)pbss_entry->poverlap_bss_scan_param,
2177 (*(pbss_entry->poverlap_bss_scan_param))
2178 .ieee_hdr.len +
2179 sizeof(IEEEtypes_Header_t));
2180 break;
2181 case VHT_CAPABILITY:
2182 pbss_entry->pvht_cap =
2183 (IEEEtypes_VHTCap_t *)pcurrent_ptr;
2184 pbss_entry->vht_cap_offset =
2185 (t_u16)(pcurrent_ptr - pbss_entry->pbeacon_buf);
2186 HEXDUMP("InterpretIE: Resp VHTCAP_IE",
2187 (t_u8 *)pbss_entry->pvht_cap,
2188 (*(pbss_entry->pvht_cap)).ieee_hdr.len +
2189 sizeof(IEEEtypes_Header_t));
2190 break;
2191 case VHT_OPERATION:
2192 pbss_entry->pvht_oprat =
2193 (IEEEtypes_VHTOprat_t *)pcurrent_ptr;
2194 pbss_entry->vht_oprat_offset =
2195 (t_u16)(pcurrent_ptr - pbss_entry->pbeacon_buf);
2196 HEXDUMP("InterpretIE: Resp VHTOPER_IE",
2197 (t_u8 *)pbss_entry->pvht_oprat,
2198 (*(pbss_entry->pvht_oprat)).ieee_hdr.len +
2199 sizeof(IEEEtypes_Header_t));
2200 break;
2201 case EXT_BSS_LOAD:
2202 pbss_entry->pext_bssload =
2203 (IEEEtypes_ExtBSSload_t *)pcurrent_ptr;
2204 pbss_entry->ext_bssload_offset =
2205 (t_u16)(pcurrent_ptr - pbss_entry->pbeacon_buf);
2206 HEXDUMP("InterpretIE: Resp EXTBSSLOAD_IE",
2207 (t_u8 *)pbss_entry->pext_bssload,
2208 (*(pbss_entry->pext_bssload)).ieee_hdr.len +
2209 sizeof(IEEEtypes_Header_t));
2210 break;
2211 case VHT_TX_POWER_ENV:
2212 pbss_entry->pvht_txpower =
2213 (IEEEtypes_VHTtxpower_t *)pcurrent_ptr;
2214 pbss_entry->vht_txpower_offset =
2215 (t_u16)(pcurrent_ptr - pbss_entry->pbeacon_buf);
2216 HEXDUMP("InterpretIE: Resp TXPOW_IE",
2217 (t_u8 *)pbss_entry->pvht_txpower,
2218 (*(pbss_entry->pvht_txpower)).ieee_hdr.len +
2219 sizeof(IEEEtypes_Header_t));
2220 break;
2221 case EXT_POWER_CONSTR:
2222 pbss_entry->pext_pwer =
2223 (IEEEtypes_ExtPwerCons_t *)pcurrent_ptr;
2224 pbss_entry->ext_pwer_offset =
2225 (t_u16)(pcurrent_ptr - pbss_entry->pbeacon_buf);
2226 HEXDUMP("InterpretIE: Resp EXTPOW_IE",
2227 (t_u8 *)pbss_entry->pext_pwer,
2228 (*(pbss_entry->pext_pwer)).ieee_hdr.len +
2229 sizeof(IEEEtypes_Header_t));
2230 break;
2231 case QUIET_CHAN:
2232 pbss_entry->pquiet_chan =
2233 (IEEEtypes_QuietChan_t *)pcurrent_ptr;
2234 pbss_entry->quiet_chan_offset =
2235 (t_u16)(pcurrent_ptr - pbss_entry->pbeacon_buf);
2236 HEXDUMP("InterpretIE: Resp QUIETCHAN_IE",
2237 (t_u8 *)pbss_entry->pquiet_chan,
2238 (*(pbss_entry->pquiet_chan)).ieee_hdr.len +
2239 sizeof(IEEEtypes_Header_t));
2240 break;
2241 case BW_CHANNEL_SWITCH:
2242 /* RANDYTODO */
2243 break;
2244 case AID_INFO:
2245 break;
2246 case OPER_MODE_NTF:
2247 pbss_entry->poper_mode =
2248 (IEEEtypes_OperModeNtf_t *)pcurrent_ptr;
2249 pbss_entry->oper_mode_offset =
2250 (t_u16)(pcurrent_ptr - pbss_entry->pbeacon_buf);
2251 HEXDUMP("InterpretIE: Resp OPERMODENTF_IE",
2252 (t_u8 *)pbss_entry->poper_mode,
2253 (*(pbss_entry->poper_mode)).ieee_hdr.len +
2254 sizeof(IEEEtypes_Header_t));
2255 break;
2256 case EXTENSION:
2257 pext_tlv = (IEEEtypes_Extension_t *)pcurrent_ptr;
2258 switch (pext_tlv->ext_id) {
2259 case HE_CAPABILITY:
2260 pbss_entry->phe_cap =
2261 (IEEEtypes_HECap_t *)pcurrent_ptr;
2262 pbss_entry->he_cap_offset = (t_u16)(
2263 pcurrent_ptr - pbss_entry->pbeacon_buf);
2264 break;
2265 case HE_OPERATION:
2266 pbss_entry->phe_oprat = pext_tlv;
2267 pbss_entry->he_oprat_offset = (t_u16)(
2268 pcurrent_ptr - pbss_entry->pbeacon_buf);
2269 break;
2270 default:
2271 break;
2272 }
2273 break;
2274 case MOBILITY_DOMAIN:
2275 PRINTM(MCMND, "Mobility Domain IE received in Scan\n");
2276 pbss_entry->pmd_ie =
2277 (IEEEtypes_MobilityDomain_t *)pcurrent_ptr;
2278 pbss_entry->md_offset =
2279 (t_u16)(pcurrent_ptr - pbss_entry->pbeacon_buf);
2280 HEXDUMP("InterpretIE: Resp Mobility Domain IE",
2281 (t_u8 *)pbss_entry->pmd_ie,
2282 (*(pbss_entry->pmd_ie)).ieee_hdr.len +
2283 sizeof(IEEEtypes_Header_t));
2284 break;
2285 default:
2286 break;
2287 }
2288
2289 pcurrent_ptr += element_len + 2;
2290
2291 /* Need to account for IE ID and IE Len */
2292 bytes_left_for_current_beacon -= (element_len + 2);
2293
2294 } /* while (bytes_left_for_current_beacon > 2) */
2295
2296 LEAVE();
2297 return ret;
2298 }
2299
2300 /**
2301 * @brief Adjust ie's position in BSSDescriptor_t
2302 *
2303 * @param pmpriv A pointer to mlan_private structure
2304 * @param pbss_entry A pointer to BSSDescriptor_t structure
2305 *
2306 * @return N/A
2307 */
wlan_adjust_ie_in_bss_entry(mlan_private * pmpriv,BSSDescriptor_t * pbss_entry)2308 static t_void wlan_adjust_ie_in_bss_entry(mlan_private *pmpriv,
2309 BSSDescriptor_t *pbss_entry)
2310 {
2311 ENTER();
2312 if (pbss_entry->pbeacon_buf) {
2313 if (pbss_entry->pwpa_ie) {
2314 pbss_entry->pwpa_ie =
2315 (IEEEtypes_VendorSpecific_t
2316 *)(pbss_entry->pbeacon_buf +
2317 pbss_entry->wpa_offset);
2318 }
2319 if (pbss_entry->prsn_ie) {
2320 pbss_entry->prsn_ie =
2321 (IEEEtypes_Generic_t *)(pbss_entry->pbeacon_buf +
2322 pbss_entry->rsn_offset);
2323 }
2324 if (pbss_entry->pwapi_ie) {
2325 pbss_entry->pwapi_ie =
2326 (IEEEtypes_Generic_t *)(pbss_entry->pbeacon_buf +
2327 pbss_entry->wapi_offset);
2328 }
2329
2330 if (pbss_entry->posen_ie) {
2331 pbss_entry->posen_ie =
2332 (IEEEtypes_Generic_t *)(pbss_entry->pbeacon_buf +
2333 pbss_entry->osen_offset);
2334 }
2335 if (pbss_entry->pmd_ie) {
2336 pbss_entry->pmd_ie =
2337 (IEEEtypes_MobilityDomain_t
2338 *)(pbss_entry->pbeacon_buf +
2339 pbss_entry->md_offset);
2340 }
2341 if (pbss_entry->pht_cap) {
2342 pbss_entry->pht_cap =
2343 (IEEEtypes_HTCap_t *)(pbss_entry->pbeacon_buf +
2344 pbss_entry->ht_cap_offset);
2345 }
2346 if (pbss_entry->pht_info) {
2347 pbss_entry->pht_info =
2348 (IEEEtypes_HTInfo_t
2349 *)(pbss_entry->pbeacon_buf +
2350 pbss_entry->ht_info_offset);
2351 }
2352 if (pbss_entry->pbss_co_2040) {
2353 pbss_entry->pbss_co_2040 =
2354 (IEEEtypes_2040BSSCo_t
2355 *)(pbss_entry->pbeacon_buf +
2356 pbss_entry->bss_co_2040_offset);
2357 }
2358 if (pbss_entry->pext_cap) {
2359 pbss_entry->pext_cap =
2360 (IEEEtypes_ExtCap_t
2361 *)(pbss_entry->pbeacon_buf +
2362 pbss_entry->ext_cap_offset);
2363 }
2364 if (pbss_entry->poverlap_bss_scan_param) {
2365 pbss_entry->poverlap_bss_scan_param =
2366 (IEEEtypes_OverlapBSSScanParam_t
2367 *)(pbss_entry->pbeacon_buf +
2368 pbss_entry->overlap_bss_offset);
2369 }
2370 if (pbss_entry->pvht_cap) {
2371 pbss_entry->pvht_cap =
2372 (IEEEtypes_VHTCap_t
2373 *)(pbss_entry->pbeacon_buf +
2374 pbss_entry->vht_cap_offset);
2375 }
2376 if (pbss_entry->pvht_oprat) {
2377 pbss_entry->pvht_oprat =
2378 (IEEEtypes_VHTOprat_t
2379 *)(pbss_entry->pbeacon_buf +
2380 pbss_entry->vht_oprat_offset);
2381 }
2382 if (pbss_entry->pvht_txpower) {
2383 pbss_entry->pvht_txpower =
2384 (IEEEtypes_VHTtxpower_t
2385 *)(pbss_entry->pbeacon_buf +
2386 pbss_entry->vht_txpower_offset);
2387 }
2388 if (pbss_entry->pext_pwer) {
2389 pbss_entry->pext_pwer =
2390 (IEEEtypes_ExtPwerCons_t
2391 *)(pbss_entry->pbeacon_buf +
2392 pbss_entry->ext_pwer_offset);
2393 }
2394 if (pbss_entry->pext_bssload) {
2395 pbss_entry->pext_bssload =
2396 (IEEEtypes_ExtBSSload_t
2397 *)(pbss_entry->pbeacon_buf +
2398 pbss_entry->ext_bssload_offset);
2399 }
2400 if (pbss_entry->pquiet_chan) {
2401 pbss_entry->pquiet_chan =
2402 (IEEEtypes_QuietChan_t
2403 *)(pbss_entry->pbeacon_buf +
2404 pbss_entry->quiet_chan_offset);
2405 }
2406 if (pbss_entry->poper_mode) {
2407 pbss_entry->poper_mode =
2408 (IEEEtypes_OperModeNtf_t
2409 *)(pbss_entry->pbeacon_buf +
2410 pbss_entry->oper_mode_offset);
2411 }
2412 if (pbss_entry->phe_cap) {
2413 pbss_entry->phe_cap =
2414 (IEEEtypes_HECap_t *)(pbss_entry->pbeacon_buf +
2415 pbss_entry->he_cap_offset);
2416 }
2417
2418 if (pbss_entry->phe_oprat) {
2419 pbss_entry->phe_oprat =
2420 (IEEEtypes_Extension_t
2421 *)(pbss_entry->pbeacon_buf +
2422 pbss_entry->he_oprat_offset);
2423 }
2424 if (pbss_entry->prsnx_ie) {
2425 pbss_entry->prsnx_ie =
2426 (IEEEtypes_Generic_t *)(pbss_entry->pbeacon_buf +
2427 pbss_entry->rsnx_offset);
2428 }
2429 } else {
2430 pbss_entry->pwpa_ie = MNULL;
2431 pbss_entry->wpa_offset = 0;
2432 pbss_entry->prsn_ie = MNULL;
2433 pbss_entry->rsn_offset = 0;
2434 pbss_entry->pwapi_ie = MNULL;
2435 pbss_entry->wapi_offset = 0;
2436
2437 pbss_entry->posen_ie = MNULL;
2438 pbss_entry->osen_offset = 0;
2439 pbss_entry->pmd_ie = MNULL;
2440 pbss_entry->md_offset = 0;
2441 pbss_entry->pht_cap = MNULL;
2442 pbss_entry->ht_cap_offset = 0;
2443 pbss_entry->pht_info = MNULL;
2444 pbss_entry->ht_info_offset = 0;
2445 pbss_entry->pbss_co_2040 = MNULL;
2446 pbss_entry->bss_co_2040_offset = 0;
2447 pbss_entry->pext_cap = MNULL;
2448 pbss_entry->ext_cap_offset = 0;
2449 pbss_entry->poverlap_bss_scan_param = MNULL;
2450 pbss_entry->overlap_bss_offset = 0;
2451 }
2452 LEAVE();
2453 return;
2454 }
2455
2456 /**
2457 * @brief Store a beacon or probe response for a BSS returned in the scan
2458 *
2459 * Store a new scan response or an update for a previous scan response. New
2460 * entries need to verify that they do not exceed the total amount of
2461 * memory allocated for the table.
2462
2463 * Replacement entries need to take into consideration the amount of space
2464 * currently allocated for the beacon/probe response and adjust the entry
2465 * as needed.
2466 *
2467 * A small amount of extra pad (SCAN_BEACON_ENTRY_PAD) is generally reserved
2468 * for an entry in case it is a beacon since a probe response for the
2469 * network will by larger per the standard. This helps to reduce the
2470 * amount of memory copying to fit a new probe response into an entry
2471 * already occupied by a network's previously stored beacon.
2472 *
2473 * @param pmpriv A pointer to mlan_private structure
2474 * @param beacon_idx Index in the scan table to store this entry; may be
2475 * replacing an older duplicate entry for this BSS
2476 * @param num_of_ent Number of entries currently in the table
2477 * @param pnew_beacon Pointer to the new beacon/probe response to save
2478 *
2479 * @return N/A
2480 */
wlan_ret_802_11_scan_store_beacon(mlan_private * pmpriv,t_u32 beacon_idx,t_u32 num_of_ent,BSSDescriptor_t * pnew_beacon)2481 static t_void wlan_ret_802_11_scan_store_beacon(mlan_private *pmpriv,
2482 t_u32 beacon_idx,
2483 t_u32 num_of_ent,
2484 BSSDescriptor_t *pnew_beacon)
2485 {
2486 mlan_adapter *pmadapter = pmpriv->adapter;
2487 t_u8 *pbcn_store;
2488 t_u32 new_bcn_size;
2489 t_u32 old_bcn_size;
2490 t_u32 bcn_space;
2491 t_u32 adj_idx;
2492 mlan_status ret = MLAN_STATUS_SUCCESS;
2493 t_u8 *tmp_buf;
2494 t_u32 bcn_size = 0;
2495 t_u32 bcn_offset = 0;
2496
2497 ENTER();
2498
2499 if (pmadapter->pscan_table[beacon_idx].pbeacon_buf) {
2500 new_bcn_size = pnew_beacon->beacon_buf_size;
2501 old_bcn_size =
2502 pmadapter->pscan_table[beacon_idx].beacon_buf_size;
2503 bcn_space =
2504 pmadapter->pscan_table[beacon_idx].beacon_buf_size_max;
2505 pbcn_store = pmadapter->pscan_table[beacon_idx].pbeacon_buf;
2506
2507 /* Set the max to be the same as current entry unless changed
2508 * below */
2509 pnew_beacon->beacon_buf_size_max = bcn_space;
2510
2511 if (new_bcn_size == old_bcn_size) {
2512 /*
2513 * Beacon is the same size as the previous entry.
2514 * Replace the previous contents with the scan result
2515 */
2516 memcpy_ext(pmadapter, pbcn_store,
2517 pnew_beacon->pbeacon_buf,
2518 pnew_beacon->beacon_buf_size,
2519 pnew_beacon->beacon_buf_size);
2520
2521 } else if (new_bcn_size <= bcn_space) {
2522 /*
2523 * New beacon size will fit in the amount of space
2524 * we have previously allocated for it
2525 */
2526
2527 /* Copy the new beacon buffer entry over the old one */
2528 memcpy_ext(pmadapter, pbcn_store,
2529 pnew_beacon->pbeacon_buf, new_bcn_size,
2530 new_bcn_size);
2531
2532 /*
2533 * If the old beacon size was less than the
2534 * maximum we had allotted for the entry, and
2535 * the new entry is even smaller, reset the
2536 * max size to the old beacon entry and compress
2537 * the storage space (leaving a new pad space of
2538 * (old_bcn_size - new_bcn_size).
2539 */
2540 if (old_bcn_size < bcn_space &&
2541 new_bcn_size <= old_bcn_size) {
2542 /*
2543 * Old Beacon size is smaller than the
2544 * allotted storage size. Shrink the
2545 * allotted storage space.
2546 */
2547 PRINTM(MINFO,
2548 "AppControl: Smaller Duplicate Beacon (%d), "
2549 "old = %d, new = %d, space = %d, left = %d\n",
2550 beacon_idx, old_bcn_size, new_bcn_size,
2551 bcn_space,
2552 (pmadapter->bcn_buf_size -
2553 (pmadapter->pbcn_buf_end -
2554 pmadapter->bcn_buf)));
2555
2556 /*
2557 * memmove (since the memory overlaps) the data
2558 * after the beacon we just stored to the end
2559 * of the current beacon. This cleans up any
2560 * unused space the old larger beacon was using
2561 * in the buffer
2562 */
2563 memmove(pmadapter,
2564 (void *)((t_ptr)pbcn_store +
2565 (t_ptr)old_bcn_size),
2566 (void *)((t_ptr)pbcn_store +
2567 (t_ptr)bcn_space),
2568 (t_u32)((t_ptr)pmadapter->pbcn_buf_end -
2569 ((t_ptr)pbcn_store +
2570 (t_ptr)bcn_space)));
2571
2572 /*
2573 * Decrement the end pointer by the difference
2574 * between the old larger size and the new
2575 * smaller size since we are using less space
2576 * due to the new beacon being smaller
2577 */
2578 pmadapter->pbcn_buf_end -=
2579 (bcn_space - old_bcn_size);
2580
2581 /*
2582 * Set the maximum storage size to the old
2583 * beacon size
2584 */
2585 pnew_beacon->beacon_buf_size_max = old_bcn_size;
2586
2587 /* Adjust beacon buffer pointers that are past
2588 * the current */
2589 for (adj_idx = 0; adj_idx < num_of_ent;
2590 adj_idx++) {
2591 if (pmadapter->pscan_table[adj_idx]
2592 .pbeacon_buf > pbcn_store) {
2593 pmadapter->pscan_table[adj_idx]
2594 .pbeacon_buf -=
2595 (bcn_space -
2596 old_bcn_size);
2597 wlan_adjust_ie_in_bss_entry(
2598 pmpriv,
2599 &pmadapter->pscan_table
2600 [adj_idx]);
2601 }
2602 }
2603 }
2604 } else if (pmadapter->pbcn_buf_end +
2605 (new_bcn_size - bcn_space) <
2606 (pmadapter->bcn_buf + pmadapter->bcn_buf_size)) {
2607 /*
2608 * Beacon is larger than space previously allocated
2609 * (bcn_space) and there is enough space left in the
2610 * beaconBuffer to store the additional data
2611 */
2612 PRINTM(MINFO,
2613 "AppControl: Larger Duplicate Beacon (%d), "
2614 "old = %d, new = %d, space = %d, left = %d\n",
2615 beacon_idx, old_bcn_size, new_bcn_size,
2616 bcn_space,
2617 (pmadapter->bcn_buf_size -
2618 (pmadapter->pbcn_buf_end - pmadapter->bcn_buf)));
2619
2620 /*
2621 * memmove (since the memory overlaps) the data
2622 * after the beacon we just stored to the end of
2623 * the current beacon. This moves the data for
2624 * the beacons after this further in memory to
2625 * make space for the new larger beacon we are
2626 * about to copy in.
2627 */
2628 memmove(pmadapter,
2629 (void *)((t_ptr)pbcn_store +
2630 (t_ptr)new_bcn_size),
2631 (void *)((t_ptr)pbcn_store + (t_ptr)bcn_space),
2632 (t_u32)((t_ptr)pmadapter->pbcn_buf_end -
2633 ((t_ptr)pbcn_store + (t_ptr)bcn_space)));
2634
2635 /* Copy the new beacon buffer entry over the old one */
2636 memcpy_ext(pmadapter, pbcn_store,
2637 pnew_beacon->pbeacon_buf, new_bcn_size,
2638 new_bcn_size);
2639
2640 /*
2641 * Move the beacon end pointer by the amount of new
2642 * beacon data we are adding
2643 */
2644 pmadapter->pbcn_buf_end += (new_bcn_size - bcn_space);
2645
2646 /*
2647 * This entry is bigger than the allotted max space
2648 * previously reserved. Increase the max space to
2649 * be equal to the new beacon size
2650 */
2651 pnew_beacon->beacon_buf_size_max = new_bcn_size;
2652
2653 /* Adjust beacon buffer pointers that are past the
2654 * current */
2655 for (adj_idx = 0; adj_idx < num_of_ent; adj_idx++) {
2656 if (pmadapter->pscan_table[adj_idx].pbeacon_buf >
2657 pbcn_store) {
2658 pmadapter->pscan_table[adj_idx]
2659 .pbeacon_buf +=
2660 (new_bcn_size - bcn_space);
2661 wlan_adjust_ie_in_bss_entry(
2662 pmpriv,
2663 &pmadapter->pscan_table[adj_idx]);
2664 }
2665 }
2666 } else {
2667 /*
2668 * Beacon is larger than the previously allocated
2669 * space, but there is not enough free space to
2670 * store the additional data
2671 */
2672 PRINTM(MERROR,
2673 "AppControl: Failed: Larger Duplicate Beacon (%d),"
2674 " old = %d, new = %d, space = %d, left = %d\n",
2675 beacon_idx, old_bcn_size, new_bcn_size,
2676 bcn_space,
2677 (pmadapter->bcn_buf_size -
2678 (pmadapter->pbcn_buf_end - pmadapter->bcn_buf)));
2679
2680 /* Storage failure, keep old beacon intact */
2681 pnew_beacon->beacon_buf_size = old_bcn_size;
2682 if (pnew_beacon->pwpa_ie)
2683 pnew_beacon->wpa_offset =
2684 pmadapter->pscan_table[beacon_idx]
2685 .wpa_offset;
2686 if (pnew_beacon->prsn_ie)
2687 pnew_beacon->rsn_offset =
2688 pmadapter->pscan_table[beacon_idx]
2689 .rsn_offset;
2690 if (pnew_beacon->pwapi_ie)
2691 pnew_beacon->wapi_offset =
2692 pmadapter->pscan_table[beacon_idx]
2693 .wapi_offset;
2694
2695 if (pnew_beacon->posen_ie)
2696 pnew_beacon->osen_offset =
2697 pmadapter->pscan_table[beacon_idx]
2698 .osen_offset;
2699 if (pnew_beacon->pmd_ie)
2700 pnew_beacon->md_offset =
2701 pmadapter->pscan_table[beacon_idx]
2702 .md_offset;
2703 if (pnew_beacon->pht_cap)
2704 pnew_beacon->ht_cap_offset =
2705 pmadapter->pscan_table[beacon_idx]
2706 .ht_cap_offset;
2707 if (pnew_beacon->pht_info)
2708 pnew_beacon->ht_info_offset =
2709 pmadapter->pscan_table[beacon_idx]
2710 .ht_info_offset;
2711 if (pnew_beacon->pbss_co_2040)
2712 pnew_beacon->bss_co_2040_offset =
2713 pmadapter->pscan_table[beacon_idx]
2714 .bss_co_2040_offset;
2715 if (pnew_beacon->pext_cap)
2716 pnew_beacon->ext_cap_offset =
2717 pmadapter->pscan_table[beacon_idx]
2718 .ext_cap_offset;
2719 if (pnew_beacon->poverlap_bss_scan_param)
2720 pnew_beacon->overlap_bss_offset =
2721 pmadapter->pscan_table[beacon_idx]
2722 .overlap_bss_offset;
2723 if (pnew_beacon->pvht_cap)
2724 pnew_beacon->vht_cap_offset =
2725 pmadapter->pscan_table[beacon_idx]
2726 .vht_cap_offset;
2727 if (pnew_beacon->pvht_oprat)
2728 pnew_beacon->vht_oprat_offset =
2729 pmadapter->pscan_table[beacon_idx]
2730 .vht_oprat_offset;
2731 if (pnew_beacon->pvht_txpower)
2732 pnew_beacon->vht_txpower_offset =
2733 pmadapter->pscan_table[beacon_idx]
2734 .vht_txpower_offset;
2735 if (pnew_beacon->pext_pwer)
2736 pnew_beacon->ext_pwer_offset =
2737 pmadapter->pscan_table[beacon_idx]
2738 .ext_pwer_offset;
2739 if (pnew_beacon->pext_bssload)
2740 pnew_beacon->ext_bssload_offset =
2741 pmadapter->pscan_table[beacon_idx]
2742 .ext_bssload_offset;
2743 if (pnew_beacon->pquiet_chan)
2744 pnew_beacon->quiet_chan_offset =
2745 pmadapter->pscan_table[beacon_idx]
2746 .quiet_chan_offset;
2747 if (pnew_beacon->poper_mode)
2748 pnew_beacon->oper_mode_offset =
2749 pmadapter->pscan_table[beacon_idx]
2750 .oper_mode_offset;
2751 if (pnew_beacon->phe_cap)
2752 pnew_beacon->he_cap_offset =
2753 pmadapter->pscan_table[beacon_idx]
2754 .he_cap_offset;
2755 if (pnew_beacon->phe_oprat)
2756 pnew_beacon->he_oprat_offset =
2757 pmadapter->pscan_table[beacon_idx]
2758 .he_oprat_offset;
2759 if (pnew_beacon->prsnx_ie)
2760 pnew_beacon->rsnx_offset =
2761 pmadapter->pscan_table[beacon_idx]
2762 .rsnx_offset;
2763 }
2764 /* Point the new entry to its permanent storage space */
2765 pnew_beacon->pbeacon_buf = pbcn_store;
2766 wlan_adjust_ie_in_bss_entry(pmpriv, pnew_beacon);
2767 } else {
2768 if ((pmadapter->pbcn_buf_end + pnew_beacon->beacon_buf_size +
2769 SCAN_BEACON_ENTRY_PAD >
2770 (pmadapter->bcn_buf + pmadapter->bcn_buf_size)) &&
2771 (pmadapter->bcn_buf_size < MAX_SCAN_BEACON_BUFFER)) {
2772 /* no space for this entry, realloc bcn buffer */
2773 if (pmadapter->callbacks.moal_vmalloc &&
2774 pmadapter->callbacks.moal_vfree)
2775 ret = pmadapter->callbacks.moal_vmalloc(
2776 pmadapter->pmoal_handle,
2777 pmadapter->bcn_buf_size +
2778 DEFAULT_SCAN_BEACON_BUFFER,
2779 (t_u8 **)&tmp_buf);
2780 else
2781 ret = pmadapter->callbacks.moal_malloc(
2782 pmadapter->pmoal_handle,
2783 pmadapter->bcn_buf_size +
2784 DEFAULT_SCAN_BEACON_BUFFER,
2785 MLAN_MEM_DEF, (t_u8 **)&tmp_buf);
2786
2787 if ((ret == MLAN_STATUS_SUCCESS) && (tmp_buf)) {
2788 PRINTM(MCMND,
2789 "Realloc Beacon buffer, old size=%d, new_size=%d\n",
2790 pmadapter->bcn_buf_size,
2791 pmadapter->bcn_buf_size +
2792 DEFAULT_SCAN_BEACON_BUFFER);
2793 bcn_size = pmadapter->pbcn_buf_end -
2794 pmadapter->bcn_buf;
2795 memcpy_ext(pmadapter, tmp_buf,
2796 pmadapter->bcn_buf, bcn_size,
2797 bcn_size);
2798 /* Adjust beacon buffer pointers that are past
2799 * the current */
2800 for (adj_idx = 0; adj_idx < num_of_ent;
2801 adj_idx++) {
2802 bcn_offset =
2803 pmadapter->pscan_table[adj_idx]
2804 .pbeacon_buf -
2805 pmadapter->bcn_buf;
2806 pmadapter->pscan_table[adj_idx]
2807 .pbeacon_buf =
2808 tmp_buf + bcn_offset;
2809 wlan_adjust_ie_in_bss_entry(
2810 pmpriv,
2811 &pmadapter->pscan_table[adj_idx]);
2812 }
2813 pmadapter->pbcn_buf_end = tmp_buf + bcn_size;
2814 if (pmadapter->callbacks.moal_vmalloc &&
2815 pmadapter->callbacks.moal_vfree)
2816 pmadapter->callbacks.moal_vfree(
2817 pmadapter->pmoal_handle,
2818 (t_u8 *)pmadapter->bcn_buf);
2819 else
2820 pmadapter->callbacks.moal_mfree(
2821 pmadapter->pmoal_handle,
2822 (t_u8 *)pmadapter->bcn_buf);
2823 pmadapter->bcn_buf = tmp_buf;
2824 pmadapter->bcn_buf_size +=
2825 DEFAULT_SCAN_BEACON_BUFFER;
2826 }
2827 }
2828 /*
2829 * No existing beacon data exists for this entry, check to see
2830 * if we can fit it in the remaining space
2831 */
2832 if (pmadapter->pbcn_buf_end + pnew_beacon->beacon_buf_size +
2833 SCAN_BEACON_ENTRY_PAD <
2834 (pmadapter->bcn_buf + pmadapter->bcn_buf_size)) {
2835 /*
2836 * Copy the beacon buffer data from the local entry
2837 * to the adapter dev struct buffer space used to
2838 * store the raw beacon data for each entry in the
2839 * scan table
2840 */
2841 memcpy_ext(pmadapter, pmadapter->pbcn_buf_end,
2842 pnew_beacon->pbeacon_buf,
2843 pnew_beacon->beacon_buf_size,
2844 pnew_beacon->beacon_buf_size);
2845
2846 /*
2847 * Update the beacon ptr to point to the table
2848 * save area
2849 */
2850 pnew_beacon->pbeacon_buf = pmadapter->pbcn_buf_end;
2851 pnew_beacon->beacon_buf_size_max =
2852 (pnew_beacon->beacon_buf_size +
2853 SCAN_BEACON_ENTRY_PAD);
2854 wlan_adjust_ie_in_bss_entry(pmpriv, pnew_beacon);
2855
2856 /* Increment the end pointer by the size reserved */
2857 pmadapter->pbcn_buf_end +=
2858 pnew_beacon->beacon_buf_size_max;
2859
2860 PRINTM(MINFO,
2861 "AppControl: Beacon[%02d] sz=%03d,"
2862 " used = %04d, left = %04d\n",
2863 beacon_idx, pnew_beacon->beacon_buf_size,
2864 (pmadapter->pbcn_buf_end - pmadapter->bcn_buf),
2865 (pmadapter->bcn_buf_size -
2866 (pmadapter->pbcn_buf_end - pmadapter->bcn_buf)));
2867 } else {
2868 /*
2869 * No space for new beacon
2870 */
2871 PRINTM(MCMND,
2872 "AppControl: No space beacon (%d): " MACSTR
2873 "; sz=%03d, left=%03d\n",
2874 beacon_idx, MAC2STR(pnew_beacon->mac_address),
2875 pnew_beacon->beacon_buf_size,
2876 (pmadapter->bcn_buf_size -
2877 (pmadapter->pbcn_buf_end - pmadapter->bcn_buf)));
2878
2879 /*
2880 * Storage failure; clear storage records
2881 * for this bcn
2882 */
2883 pnew_beacon->pbeacon_buf = MNULL;
2884 pnew_beacon->beacon_buf_size = 0;
2885 pnew_beacon->beacon_buf_size_max = 0;
2886 wlan_adjust_ie_in_bss_entry(pmpriv, pnew_beacon);
2887 }
2888 }
2889
2890 LEAVE();
2891 }
2892
2893 /**
2894 * @brief update beacon buffer of the current bss descriptor
2895 *
2896 * @param pmpriv A pointer to mlan_private structure
2897 *
2898 * @return MLAN_STATUS_SUCCESS, otherwise failure
2899 */
wlan_update_curr_bcn(mlan_private * pmpriv)2900 static mlan_status wlan_update_curr_bcn(mlan_private *pmpriv)
2901 {
2902 BSSDescriptor_t *pcurr_bss = &pmpriv->curr_bss_params.bss_descriptor;
2903 mlan_status ret = MLAN_STATUS_SUCCESS;
2904
2905 ENTER();
2906
2907 if (pmpriv->pcurr_bcn_buf && pmpriv->curr_bcn_size) {
2908 pcurr_bss->pbeacon_buf = pmpriv->pcurr_bcn_buf;
2909 pcurr_bss->beacon_buf_size = pmpriv->curr_bcn_size;
2910 pcurr_bss->beacon_buf_size_max = pmpriv->curr_bcn_size;
2911
2912 /* adjust the pointers in the current bss descriptor */
2913 if (pcurr_bss->pwpa_ie) {
2914 pcurr_bss->pwpa_ie =
2915 (IEEEtypes_VendorSpecific_t
2916 *)(pcurr_bss->pbeacon_buf +
2917 pcurr_bss->wpa_offset);
2918 }
2919 if (pcurr_bss->prsn_ie) {
2920 pcurr_bss->prsn_ie =
2921 (IEEEtypes_Generic_t *)(pcurr_bss->pbeacon_buf +
2922 pcurr_bss->rsn_offset);
2923 }
2924 if (pcurr_bss->pmd_ie) {
2925 pcurr_bss->pmd_ie = (IEEEtypes_MobilityDomain_t
2926 *)(pcurr_bss->pbeacon_buf +
2927 pcurr_bss->md_offset);
2928 }
2929 if (pcurr_bss->pht_cap) {
2930 pcurr_bss->pht_cap =
2931 (IEEEtypes_HTCap_t *)(pcurr_bss->pbeacon_buf +
2932 pcurr_bss->ht_cap_offset);
2933 }
2934
2935 if (pcurr_bss->pht_info) {
2936 pcurr_bss->pht_info =
2937 (IEEEtypes_HTInfo_t
2938 *)(pcurr_bss->pbeacon_buf +
2939 pcurr_bss->ht_info_offset);
2940 }
2941
2942 if (pcurr_bss->pbss_co_2040) {
2943 pcurr_bss->pbss_co_2040 =
2944 (IEEEtypes_2040BSSCo_t
2945 *)(pcurr_bss->pbeacon_buf +
2946 pcurr_bss->bss_co_2040_offset);
2947 }
2948
2949 if (pcurr_bss->pext_cap) {
2950 pcurr_bss->pext_cap =
2951 (IEEEtypes_ExtCap_t
2952 *)(pcurr_bss->pbeacon_buf +
2953 pcurr_bss->ext_cap_offset);
2954 }
2955
2956 if (pcurr_bss->poverlap_bss_scan_param) {
2957 pcurr_bss->poverlap_bss_scan_param =
2958 (IEEEtypes_OverlapBSSScanParam_t
2959 *)(pcurr_bss->pbeacon_buf +
2960 pcurr_bss->overlap_bss_offset);
2961 }
2962
2963 if (pcurr_bss->pvht_cap) {
2964 pcurr_bss->pvht_cap =
2965 (IEEEtypes_VHTCap_t
2966 *)(pcurr_bss->pbeacon_buf +
2967 pcurr_bss->vht_cap_offset);
2968 }
2969
2970 if (pcurr_bss->pvht_oprat) {
2971 pcurr_bss->pvht_oprat =
2972 (IEEEtypes_VHTOprat_t
2973 *)(pcurr_bss->pbeacon_buf +
2974 pcurr_bss->vht_oprat_offset);
2975 }
2976
2977 if (pcurr_bss->pvht_txpower) {
2978 pcurr_bss->pvht_txpower =
2979 (IEEEtypes_VHTtxpower_t
2980 *)(pcurr_bss->pbeacon_buf +
2981 pcurr_bss->vht_txpower_offset);
2982 }
2983
2984 if (pcurr_bss->pext_pwer) {
2985 pcurr_bss->pext_pwer =
2986 (IEEEtypes_ExtPwerCons_t
2987 *)(pcurr_bss->pbeacon_buf +
2988 pcurr_bss->ext_pwer_offset);
2989 }
2990
2991 if (pcurr_bss->pext_bssload) {
2992 pcurr_bss->pext_bssload =
2993 (IEEEtypes_ExtBSSload_t
2994 *)(pcurr_bss->pbeacon_buf +
2995 pcurr_bss->ext_bssload_offset);
2996 }
2997
2998 if (pcurr_bss->pquiet_chan) {
2999 pcurr_bss->pquiet_chan =
3000 (IEEEtypes_QuietChan_t
3001 *)(pcurr_bss->pbeacon_buf +
3002 pcurr_bss->quiet_chan_offset);
3003 }
3004
3005 if (pcurr_bss->poper_mode) {
3006 pcurr_bss->poper_mode =
3007 (IEEEtypes_OperModeNtf_t
3008 *)(pcurr_bss->pbeacon_buf +
3009 pcurr_bss->oper_mode_offset);
3010 }
3011 if (pcurr_bss->phe_cap) {
3012 pcurr_bss->phe_cap =
3013 (IEEEtypes_HECap_t *)(pcurr_bss->pbeacon_buf +
3014 pcurr_bss->he_cap_offset);
3015 }
3016
3017 if (pcurr_bss->phe_oprat) {
3018 pcurr_bss->phe_oprat =
3019 (IEEEtypes_Extension_t
3020 *)(pcurr_bss->pbeacon_buf +
3021 pcurr_bss->he_oprat_offset);
3022 }
3023 if (pcurr_bss->prsnx_ie) {
3024 pcurr_bss->prsnx_ie =
3025 (IEEEtypes_Generic_t *)(pcurr_bss->pbeacon_buf +
3026 pcurr_bss->rsnx_offset);
3027 }
3028
3029 PRINTM(MINFO, "current beacon restored %d\n",
3030 pmpriv->curr_bcn_size);
3031 } else {
3032 PRINTM(MERROR, "curr_bcn_buf not saved\n");
3033 ret = MLAN_STATUS_FAILURE;
3034 }
3035
3036 LEAVE();
3037 return ret;
3038 }
3039
3040 /**
3041 * @brief get the chan load from chan stats.
3042 *
3043 * @param pmadapter A pointer to mlan_adapter structure
3044 * @param channel channel *
3045 *
3046 * @return channel load
3047 */
wlan_get_chan_load(mlan_adapter * pmadapter,t_u8 channel)3048 static t_u16 wlan_get_chan_load(mlan_adapter *pmadapter, t_u8 channel)
3049 {
3050 t_u16 chan_load = 0;
3051 int i;
3052 for (i = 0; i < (int)pmadapter->num_in_chan_stats; i++) {
3053 if ((pmadapter->pchan_stats[i].chan_num == channel) &&
3054 pmadapter->pchan_stats[i].cca_scan_duration) {
3055 chan_load =
3056 (pmadapter->pchan_stats[i].cca_busy_duration *
3057 100) /
3058 pmadapter->pchan_stats[i].cca_scan_duration;
3059 break;
3060 }
3061 }
3062 return chan_load;
3063 }
3064
3065 /**
3066 * @brief get the chan min/max rssi
3067 *
3068 * @param pmadapter A pointer to mlan_adapter structure
3069 * @param channel channel *
3070 * @param min_flag flag to get min rssi
3071 * @return rssi
3072 */
wlan_get_chan_rssi(mlan_adapter * pmadapter,t_u8 channel,t_u8 min_flag)3073 static t_u8 wlan_get_chan_rssi(mlan_adapter *pmadapter, t_u8 channel,
3074 t_u8 min_flag)
3075 {
3076 t_u8 rssi = 0;
3077 int i;
3078 for (i = 0; i < (int)pmadapter->num_in_scan_table; i++) {
3079 if (pmadapter->pscan_table[i].channel == channel) {
3080 if (rssi == 0)
3081 rssi = (t_s32)pmadapter->pscan_table[i].rssi;
3082 else {
3083 if (min_flag)
3084 rssi = MIN(
3085 rssi,
3086 pmadapter->pscan_table[i].rssi);
3087 else
3088 rssi = MAX(
3089 rssi,
3090 pmadapter->pscan_table[i].rssi);
3091 }
3092 }
3093 }
3094 return rssi;
3095 }
3096
3097 /**
3098 * @brief update the min/max rssi for channel statistics.
3099 *
3100 * @param pmadapter A pointer to mlan_adapter structure
3101 * @return N/A
3102 */
wlan_update_chan_rssi(mlan_adapter * pmadapter)3103 static t_void wlan_update_chan_rssi(mlan_adapter *pmadapter)
3104 {
3105 int i;
3106 t_s8 min_rssi = 0;
3107 t_s8 max_rssi = 0;
3108 t_s8 rss = 0;
3109 for (i = 0; i < (int)pmadapter->num_in_chan_stats; i++) {
3110 if (pmadapter->pchan_stats[i].chan_num &&
3111 pmadapter->pchan_stats[i].cca_scan_duration) {
3112 min_rssi = -wlan_get_chan_rssi(
3113 pmadapter, pmadapter->pchan_stats[i].chan_num,
3114 MFALSE);
3115 max_rssi = -wlan_get_chan_rssi(
3116 pmadapter, pmadapter->pchan_stats[i].chan_num,
3117 MTRUE);
3118 rss = min_rssi - pmadapter->pchan_stats[i].noise;
3119 // rss should always > 0, FW need fix the wrong
3120 // rssi/noise in scantable
3121 if (rss > 0)
3122 pmadapter->pchan_stats[i].min_rss = rss;
3123 else
3124 pmadapter->pchan_stats[i].min_rss = 0;
3125
3126 rss = max_rssi - pmadapter->pchan_stats[i].noise;
3127 if (rss > 0)
3128 pmadapter->pchan_stats[i].max_rss = rss;
3129 else
3130 pmadapter->pchan_stats[i].max_rss = 0;
3131 PRINTM(MCMND,
3132 "chan=%d, min_rssi=%d, max_rssi=%d noise=%d min_rss=%d, max_rss=%d\n",
3133 pmadapter->pchan_stats[i].chan_num, min_rssi,
3134 max_rssi, pmadapter->pchan_stats[i].noise,
3135 pmadapter->pchan_stats[i].min_rss,
3136 pmadapter->pchan_stats[i].max_rss);
3137 }
3138 }
3139 return;
3140 }
3141
3142 /**
3143 * @brief Post process the scan table after a new scan command has completed
3144 *
3145 * Inspect each entry of the scan table and try to find an entry that
3146 * matches our current associated/joined network from the scan. If
3147 * one is found, update the stored copy of the BSSDescriptor for our
3148 * current network.
3149 *
3150 * Debug dump the current scan table contents if compiled accordingly.
3151 *
3152 * @param pmpriv A pointer to mlan_private structure
3153 *
3154 * @return N/A
3155 */
wlan_scan_process_results(mlan_private * pmpriv)3156 static t_void wlan_scan_process_results(mlan_private *pmpriv)
3157 {
3158 mlan_adapter *pmadapter = pmpriv->adapter;
3159 t_s32 j;
3160 t_u32 i;
3161 mlan_status ret = MLAN_STATUS_SUCCESS;
3162 BSSDescriptor_t *bss_new_entry = MNULL;
3163 pmlan_callbacks pcb = &pmadapter->callbacks;
3164
3165 ENTER();
3166
3167 if (pmpriv->media_connected == MTRUE) {
3168 j = wlan_find_bssid_in_list(
3169 pmpriv,
3170 pmpriv->curr_bss_params.bss_descriptor.mac_address,
3171 pmpriv->bss_mode);
3172
3173 if (j >= 0) {
3174 memcpy_ext(pmadapter, &pmadapter->pscan_table[j].ssid,
3175 &pmpriv->curr_bss_params.bss_descriptor.ssid,
3176 sizeof(mlan_802_11_ssid),
3177 sizeof(mlan_802_11_ssid));
3178 pmadapter->callbacks.moal_spin_lock(
3179 pmadapter->pmoal_handle,
3180 pmpriv->curr_bcn_buf_lock);
3181 pmpriv->curr_bss_params.bss_descriptor.pwpa_ie = MNULL;
3182 pmpriv->curr_bss_params.bss_descriptor.wpa_offset = 0;
3183 pmpriv->curr_bss_params.bss_descriptor.prsn_ie = MNULL;
3184 pmpriv->curr_bss_params.bss_descriptor.rsn_offset = 0;
3185 pmpriv->curr_bss_params.bss_descriptor.pwapi_ie = MNULL;
3186 pmpriv->curr_bss_params.bss_descriptor.wapi_offset = 0;
3187
3188 pmpriv->curr_bss_params.bss_descriptor.posen_ie = MNULL;
3189 pmpriv->curr_bss_params.bss_descriptor.osen_offset = 0;
3190 pmpriv->curr_bss_params.bss_descriptor.pmd_ie = MNULL;
3191 pmpriv->curr_bss_params.bss_descriptor.md_offset = 0;
3192 pmpriv->curr_bss_params.bss_descriptor.pht_cap = MNULL;
3193 pmpriv->curr_bss_params.bss_descriptor.ht_cap_offset =
3194 0;
3195 pmpriv->curr_bss_params.bss_descriptor.pht_info = MNULL;
3196 pmpriv->curr_bss_params.bss_descriptor.ht_info_offset =
3197 0;
3198 pmpriv->curr_bss_params.bss_descriptor.pbss_co_2040 =
3199 MNULL;
3200 pmpriv->curr_bss_params.bss_descriptor
3201 .bss_co_2040_offset = 0;
3202 pmpriv->curr_bss_params.bss_descriptor.pext_cap = MNULL;
3203 pmpriv->curr_bss_params.bss_descriptor.ext_cap_offset =
3204 0;
3205 pmpriv->curr_bss_params.bss_descriptor
3206 .poverlap_bss_scan_param = MNULL;
3207 pmpriv->curr_bss_params.bss_descriptor
3208 .overlap_bss_offset = 0;
3209 pmpriv->curr_bss_params.bss_descriptor.pvht_cap = MNULL;
3210 pmpriv->curr_bss_params.bss_descriptor.vht_cap_offset =
3211 0;
3212 pmpriv->curr_bss_params.bss_descriptor.pvht_oprat =
3213 MNULL;
3214 pmpriv->curr_bss_params.bss_descriptor.vht_oprat_offset =
3215 0;
3216 pmpriv->curr_bss_params.bss_descriptor.pvht_txpower =
3217 MNULL;
3218 pmpriv->curr_bss_params.bss_descriptor
3219 .vht_txpower_offset = 0;
3220 pmpriv->curr_bss_params.bss_descriptor.pext_pwer =
3221 MNULL;
3222 pmpriv->curr_bss_params.bss_descriptor.ext_pwer_offset =
3223 0;
3224 pmpriv->curr_bss_params.bss_descriptor.pext_bssload =
3225 MNULL;
3226 pmpriv->curr_bss_params.bss_descriptor
3227 .ext_bssload_offset = 0;
3228 pmpriv->curr_bss_params.bss_descriptor.pquiet_chan =
3229 MNULL;
3230 pmpriv->curr_bss_params.bss_descriptor
3231 .quiet_chan_offset = 0;
3232 pmpriv->curr_bss_params.bss_descriptor.poper_mode =
3233 MNULL;
3234 pmpriv->curr_bss_params.bss_descriptor.oper_mode_offset =
3235 0;
3236 pmpriv->curr_bss_params.bss_descriptor.phe_cap = MNULL;
3237 pmpriv->curr_bss_params.bss_descriptor.he_cap_offset =
3238 0;
3239 pmpriv->curr_bss_params.bss_descriptor.phe_oprat =
3240 MNULL;
3241 pmpriv->curr_bss_params.bss_descriptor.he_oprat_offset =
3242 0;
3243 pmpriv->curr_bss_params.bss_descriptor.prsnx_ie = MNULL;
3244 pmpriv->curr_bss_params.bss_descriptor.rsnx_offset = 0;
3245 pmpriv->curr_bss_params.bss_descriptor.pbeacon_buf =
3246 MNULL;
3247 pmpriv->curr_bss_params.bss_descriptor.beacon_buf_size =
3248 0;
3249 pmpriv->curr_bss_params.bss_descriptor
3250 .beacon_buf_size_max = 0;
3251
3252 PRINTM(MINFO,
3253 "Found current ssid/bssid in list @ index #%d\n",
3254 j);
3255 /* Make a copy of current BSSID descriptor */
3256 memcpy_ext(
3257 pmadapter,
3258 &pmpriv->curr_bss_params.bss_descriptor,
3259 &pmadapter->pscan_table[j],
3260 sizeof(pmpriv->curr_bss_params.bss_descriptor),
3261 sizeof(pmpriv->curr_bss_params.bss_descriptor));
3262
3263 pmadapter->callbacks.moal_spin_unlock(
3264 pmadapter->pmoal_handle,
3265 pmpriv->curr_bcn_buf_lock);
3266 wlan_save_curr_bcn(pmpriv);
3267 } else {
3268 // Apend to the end of scan table
3269 if (pmpriv->pcurr_bcn_buf && pmpriv->curr_bcn_size) {
3270 ret = pcb->moal_malloc(pmadapter->pmoal_handle,
3271 sizeof(BSSDescriptor_t),
3272 MLAN_MEM_DEF,
3273 (t_u8 **)&bss_new_entry);
3274 if (ret == MLAN_STATUS_SUCCESS &&
3275 bss_new_entry) {
3276 memcpy_ext(
3277 pmadapter, bss_new_entry,
3278 &pmpriv->curr_bss_params
3279 .bss_descriptor,
3280 sizeof(pmpriv->curr_bss_params
3281 .bss_descriptor),
3282 sizeof(BSSDescriptor_t));
3283 if (pmadapter->num_in_scan_table <
3284 MRVDRV_MAX_BSSID_LIST)
3285 pmadapter->num_in_scan_table++;
3286 pmadapter
3287 ->pscan_table
3288 [pmadapter->num_in_scan_table -
3289 1]
3290 .pbeacon_buf = MNULL;
3291 wlan_ret_802_11_scan_store_beacon(
3292 pmpriv,
3293 pmadapter->num_in_scan_table -
3294 1,
3295 pmadapter->num_in_scan_table,
3296 bss_new_entry);
3297 if (bss_new_entry->pbeacon_buf == MNULL)
3298 pmadapter->num_in_scan_table--;
3299 else
3300 memcpy_ext(
3301 pmadapter,
3302 &pmadapter->pscan_table
3303 [pmadapter->num_in_scan_table -
3304 1],
3305 bss_new_entry,
3306 sizeof(BSSDescriptor_t),
3307 sizeof(BSSDescriptor_t));
3308 pcb->moal_mfree(pmadapter->pmoal_handle,
3309 (t_u8 *)bss_new_entry);
3310 }
3311 }
3312 }
3313 }
3314
3315 for (i = 0; i < pmadapter->num_in_scan_table; i++) {
3316 PRINTM(MINFO,
3317 "Scan:(%02d) " MACSTR ", "
3318 "RSSI[%03d], SSID[%s]\n",
3319 i, MAC2STR(pmadapter->pscan_table[i].mac_address),
3320 (t_s32)pmadapter->pscan_table[i].rssi,
3321 pmadapter->pscan_table[i].ssid.ssid);
3322 pmadapter->pscan_table[i].chan_load = wlan_get_chan_load(
3323 pmadapter, pmadapter->pscan_table[i].channel);
3324 }
3325 wlan_update_chan_rssi(pmadapter);
3326
3327 /*
3328 * Prepares domain info from scan table and downloads the
3329 * domain info command to the FW.
3330 */
3331 wlan_11d_prepare_dnld_domain_info_cmd(pmpriv);
3332 PRINTM(MMSG, "wlan: SCAN COMPLETED: scanned AP count=%d\n",
3333 pmadapter->num_in_scan_table);
3334 LEAVE();
3335 }
3336
3337 /**
3338 * @brief Delete a specific indexed entry from the scan table.
3339 *
3340 * Delete the scan table entry indexed by table_idx. Compact the remaining
3341 * entries and adjust any buffering of beacon/probe response data
3342 * if needed.
3343 *
3344 * @param pmpriv A pointer to mlan_private structure
3345 * @param table_idx Scan table entry index to delete from the table
3346 *
3347 * @return N/A
3348 *
3349 * @pre table_idx must be an index to a valid entry
3350 */
wlan_scan_delete_table_entry(mlan_private * pmpriv,t_s32 table_idx)3351 static t_void wlan_scan_delete_table_entry(mlan_private *pmpriv,
3352 t_s32 table_idx)
3353 {
3354 mlan_adapter *pmadapter = pmpriv->adapter;
3355 t_u32 del_idx;
3356 t_u32 beacon_buf_adj;
3357 t_u8 *pbeacon_buf;
3358
3359 ENTER();
3360
3361 /*
3362 * Shift the saved beacon buffer data for the scan table back over the
3363 * entry being removed. Update the end of buffer pointer. Save the
3364 * deleted buffer allocation size for pointer adjustments for entries
3365 * compacted after the deleted index.
3366 */
3367 beacon_buf_adj = pmadapter->pscan_table[table_idx].beacon_buf_size_max;
3368
3369 PRINTM(MINFO,
3370 "Scan: Delete Entry %d, beacon buffer removal = %d bytes\n",
3371 table_idx, beacon_buf_adj);
3372
3373 /* Check if the table entry had storage allocated for its beacon */
3374 if (beacon_buf_adj) {
3375 pbeacon_buf = pmadapter->pscan_table[table_idx].pbeacon_buf;
3376
3377 /*
3378 * Remove the entry's buffer space, decrement the table
3379 * end pointer by the amount we are removing
3380 */
3381 pmadapter->pbcn_buf_end -= beacon_buf_adj;
3382
3383 PRINTM(MINFO,
3384 "Scan: Delete Entry %d, compact data: %p <- %p (sz = %d)\n",
3385 table_idx, pbeacon_buf, pbeacon_buf + beacon_buf_adj,
3386 pmadapter->pbcn_buf_end - pbeacon_buf);
3387
3388 /*
3389 * Compact data storage. Copy all data after the deleted
3390 * entry's end address (pbeacon_buf + beacon_buf_adj) back to
3391 * the original start address (pbeacon_buf).
3392 *
3393 * Scan table entries affected by the move will have their entry
3394 * pointer adjusted below.
3395 *
3396 * Use memmove since the dest/src memory regions overlap.
3397 */
3398 memmove(pmadapter, pbeacon_buf,
3399 (void *)((t_ptr)pbeacon_buf + (t_ptr)beacon_buf_adj),
3400 (t_u32)((t_ptr)pmadapter->pbcn_buf_end -
3401 (t_ptr)pbeacon_buf));
3402 }
3403
3404 PRINTM(MINFO, "Scan: Delete Entry %d, num_in_scan_table = %d\n",
3405 table_idx, pmadapter->num_in_scan_table);
3406
3407 /*
3408 * Shift all of the entries after the table_idx back by one, compacting
3409 * the table and removing the requested entry
3410 */
3411 for (del_idx = table_idx; (del_idx + 1) < pmadapter->num_in_scan_table;
3412 del_idx++) {
3413 /* Copy the next entry over this one */
3414 memcpy_ext(pmadapter, pmadapter->pscan_table + del_idx,
3415 pmadapter->pscan_table + del_idx + 1,
3416 sizeof(BSSDescriptor_t), sizeof(BSSDescriptor_t));
3417
3418 /*
3419 * Adjust this entry's pointer to its beacon buffer based on the
3420 * removed/compacted entry from the deleted index. Don't
3421 * decrement if the buffer pointer is MNULL (no data stored for
3422 * this entry).
3423 */
3424 if (pmadapter->pscan_table[del_idx].pbeacon_buf) {
3425 pmadapter->pscan_table[del_idx].pbeacon_buf -=
3426 beacon_buf_adj;
3427 if (pmadapter->pscan_table[del_idx].pwpa_ie) {
3428 pmadapter->pscan_table[del_idx].pwpa_ie =
3429 (IEEEtypes_VendorSpecific_t
3430 *)(pmadapter
3431 ->pscan_table[del_idx]
3432 .pbeacon_buf +
3433 pmadapter
3434 ->pscan_table[del_idx]
3435 .wpa_offset);
3436 }
3437 if (pmadapter->pscan_table[del_idx].prsn_ie) {
3438 pmadapter->pscan_table[del_idx].prsn_ie =
3439 (IEEEtypes_Generic_t
3440 *)(pmadapter
3441 ->pscan_table[del_idx]
3442 .pbeacon_buf +
3443 pmadapter
3444 ->pscan_table[del_idx]
3445 .rsn_offset);
3446 }
3447 if (pmadapter->pscan_table[del_idx].pwapi_ie) {
3448 pmadapter->pscan_table[del_idx].pwapi_ie =
3449 (IEEEtypes_Generic_t
3450 *)(pmadapter
3451 ->pscan_table[del_idx]
3452 .pbeacon_buf +
3453 pmadapter
3454 ->pscan_table[del_idx]
3455 .wapi_offset);
3456 }
3457
3458 if (pmadapter->pscan_table[del_idx].posen_ie) {
3459 pmadapter->pscan_table[del_idx].posen_ie =
3460 (IEEEtypes_Generic_t
3461 *)(pmadapter
3462 ->pscan_table[del_idx]
3463 .pbeacon_buf +
3464 pmadapter
3465 ->pscan_table[del_idx]
3466 .osen_offset);
3467 }
3468 if (pmadapter->pscan_table[del_idx].pmd_ie) {
3469 pmadapter->pscan_table[del_idx].pmd_ie =
3470 (IEEEtypes_MobilityDomain_t
3471 *)(pmadapter
3472 ->pscan_table[del_idx]
3473 .pbeacon_buf +
3474 pmadapter
3475 ->pscan_table[del_idx]
3476 .md_offset);
3477 }
3478 if (pmadapter->pscan_table[del_idx].pht_cap) {
3479 pmadapter->pscan_table[del_idx].pht_cap =
3480 (IEEEtypes_HTCap_t
3481 *)(pmadapter
3482 ->pscan_table[del_idx]
3483 .pbeacon_buf +
3484 pmadapter
3485 ->pscan_table[del_idx]
3486 .ht_cap_offset);
3487 }
3488
3489 if (pmadapter->pscan_table[del_idx].pht_info) {
3490 pmadapter->pscan_table[del_idx].pht_info =
3491 (IEEEtypes_HTInfo_t
3492 *)(pmadapter
3493 ->pscan_table[del_idx]
3494 .pbeacon_buf +
3495 pmadapter
3496 ->pscan_table[del_idx]
3497 .ht_info_offset);
3498 }
3499 if (pmadapter->pscan_table[del_idx].pbss_co_2040) {
3500 pmadapter->pscan_table[del_idx].pbss_co_2040 =
3501 (IEEEtypes_2040BSSCo_t
3502 *)(pmadapter
3503 ->pscan_table[del_idx]
3504 .pbeacon_buf +
3505 pmadapter
3506 ->pscan_table[del_idx]
3507 .bss_co_2040_offset);
3508 }
3509 if (pmadapter->pscan_table[del_idx].pext_cap) {
3510 pmadapter->pscan_table[del_idx].pext_cap =
3511 (IEEEtypes_ExtCap_t
3512 *)(pmadapter
3513 ->pscan_table[del_idx]
3514 .pbeacon_buf +
3515 pmadapter
3516 ->pscan_table[del_idx]
3517 .ext_cap_offset);
3518 }
3519 if (pmadapter->pscan_table[del_idx]
3520 .poverlap_bss_scan_param) {
3521 pmadapter->pscan_table[del_idx]
3522 .poverlap_bss_scan_param =
3523 (IEEEtypes_OverlapBSSScanParam_t
3524 *)(pmadapter
3525 ->pscan_table[del_idx]
3526 .pbeacon_buf +
3527 pmadapter
3528 ->pscan_table[del_idx]
3529 .overlap_bss_offset);
3530 }
3531
3532 if (pmadapter->pscan_table[del_idx].pvht_cap) {
3533 pmadapter->pscan_table[del_idx].pvht_cap =
3534 (IEEEtypes_VHTCap_t
3535 *)(pmadapter
3536 ->pscan_table[del_idx]
3537 .pbeacon_buf +
3538 pmadapter
3539 ->pscan_table[del_idx]
3540 .vht_cap_offset);
3541 }
3542
3543 if (pmadapter->pscan_table[del_idx].pvht_oprat) {
3544 pmadapter->pscan_table[del_idx].pvht_oprat =
3545 (IEEEtypes_VHTOprat_t
3546 *)(pmadapter
3547 ->pscan_table[del_idx]
3548 .pbeacon_buf +
3549 pmadapter
3550 ->pscan_table[del_idx]
3551 .vht_oprat_offset);
3552 }
3553 if (pmadapter->pscan_table[del_idx].pvht_txpower) {
3554 pmadapter->pscan_table[del_idx].pvht_txpower =
3555 (IEEEtypes_VHTtxpower_t
3556 *)(pmadapter
3557 ->pscan_table[del_idx]
3558 .pbeacon_buf +
3559 pmadapter
3560 ->pscan_table[del_idx]
3561 .vht_txpower_offset);
3562 }
3563 if (pmadapter->pscan_table[del_idx].pext_pwer) {
3564 pmadapter->pscan_table[del_idx].pext_pwer =
3565 (IEEEtypes_ExtPwerCons_t
3566 *)(pmadapter
3567 ->pscan_table[del_idx]
3568 .pbeacon_buf +
3569 pmadapter
3570 ->pscan_table[del_idx]
3571 .ext_pwer_offset);
3572 }
3573 if (pmadapter->pscan_table[del_idx].pext_bssload) {
3574 pmadapter->pscan_table[del_idx].pext_bssload =
3575 (IEEEtypes_ExtBSSload_t
3576 *)(pmadapter
3577 ->pscan_table[del_idx]
3578 .pbeacon_buf +
3579 pmadapter
3580 ->pscan_table[del_idx]
3581 .ext_bssload_offset);
3582 }
3583 if (pmadapter->pscan_table[del_idx].pquiet_chan) {
3584 pmadapter->pscan_table[del_idx].pquiet_chan =
3585 (IEEEtypes_QuietChan_t
3586 *)(pmadapter
3587 ->pscan_table[del_idx]
3588 .pbeacon_buf +
3589 pmadapter
3590 ->pscan_table[del_idx]
3591 .quiet_chan_offset);
3592 }
3593 if (pmadapter->pscan_table[del_idx].poper_mode) {
3594 pmadapter->pscan_table[del_idx].poper_mode =
3595 (IEEEtypes_OperModeNtf_t
3596 *)(pmadapter
3597 ->pscan_table[del_idx]
3598 .pbeacon_buf +
3599 pmadapter
3600 ->pscan_table[del_idx]
3601 .oper_mode_offset);
3602 }
3603 if (pmadapter->pscan_table[del_idx].phe_cap) {
3604 pmadapter->pscan_table[del_idx].phe_cap =
3605 (IEEEtypes_HECap_t
3606 *)(pmadapter
3607 ->pscan_table[del_idx]
3608 .pbeacon_buf +
3609 pmadapter
3610 ->pscan_table[del_idx]
3611 .he_cap_offset);
3612 }
3613 if (pmadapter->pscan_table[del_idx].phe_oprat) {
3614 pmadapter->pscan_table[del_idx].phe_oprat =
3615 (IEEEtypes_Extension_t
3616 *)(pmadapter
3617 ->pscan_table[del_idx]
3618 .pbeacon_buf +
3619 pmadapter
3620 ->pscan_table[del_idx]
3621 .he_oprat_offset);
3622 }
3623 }
3624 }
3625
3626 /* The last entry is invalid now that it has been deleted or moved back
3627 */
3628 memset(pmadapter,
3629 pmadapter->pscan_table + pmadapter->num_in_scan_table - 1, 0x00,
3630 sizeof(BSSDescriptor_t));
3631
3632 pmadapter->num_in_scan_table--;
3633
3634 LEAVE();
3635 }
3636
3637 /**
3638 * @brief Delete all entry's age out
3639 *
3640 * @param pmpriv A pointer to mlan_private structure
3641 *
3642 * @return N/A
3643 */
wlan_scan_delete_ageout_entry(mlan_private * pmpriv)3644 static void wlan_scan_delete_ageout_entry(mlan_private *pmpriv)
3645 {
3646 BSSDescriptor_t *pbss_entry;
3647 mlan_adapter *pmadapter = pmpriv->adapter;
3648 t_s32 table_idx = pmadapter->num_in_scan_table - 1;
3649 t_u32 i = 0;
3650 t_u32 age_in_secs = 0;
3651 t_u32 age_ts_usec = 0;
3652
3653 ENTER();
3654 #define SCAN_RESULT_AGEOUT 10
3655 pmadapter->callbacks.moal_get_system_time(pmadapter->pmoal_handle,
3656 &age_in_secs, &age_ts_usec);
3657
3658 for (i = 0; i < pmadapter->num_in_scan_table; i++) {
3659 pbss_entry = &pmadapter->pscan_table[table_idx];
3660 if (age_in_secs >
3661 (pbss_entry->age_in_secs + SCAN_RESULT_AGEOUT)) {
3662 PRINTM(MCMND,
3663 "SCAN: ageout AP MAC Addr-" MACSTR
3664 " ssid: %-32s\n",
3665 MAC2STR(pbss_entry->mac_address),
3666 pbss_entry->ssid.ssid);
3667 wlan_scan_delete_table_entry(pmpriv, table_idx);
3668 }
3669 table_idx--;
3670 }
3671 LEAVE();
3672 return;
3673 }
3674
3675 /**
3676 * @brief Delete all occurrences of a given SSID from the scan table
3677 *
3678 * Iterate through the scan table and delete all entries that match a given
3679 * SSID. Compact the remaining scan table entries.
3680 *
3681 * @param pmpriv A pointer to mlan_private structure
3682 * @param pdel_ssid Pointer to an SSID to be used in deleting all
3683 * matching SSIDs from the scan table
3684 *
3685 * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
3686 */
3687 static mlan_status
wlan_scan_delete_ssid_table_entry(mlan_private * pmpriv,mlan_802_11_ssid * pdel_ssid)3688 wlan_scan_delete_ssid_table_entry(mlan_private *pmpriv,
3689 mlan_802_11_ssid *pdel_ssid)
3690 {
3691 mlan_status ret = MLAN_STATUS_FAILURE;
3692 t_s32 table_idx;
3693
3694 ENTER();
3695
3696 PRINTM(MINFO, "Scan: Delete Ssid Entry: %-32s\n", pdel_ssid->ssid);
3697
3698 /*
3699 * If the requested SSID is found in the table, delete it. Then keep
3700 * searching the table for multiple entries for the SSID until no
3701 * more are found
3702 */
3703 while ((table_idx = wlan_find_ssid_in_list(pmpriv, pdel_ssid, MNULL,
3704 MLAN_BSS_MODE_AUTO)) >= 0) {
3705 PRINTM(MINFO, "Scan: Delete SSID Entry: Found Idx = %d\n",
3706 table_idx);
3707 ret = MLAN_STATUS_SUCCESS;
3708 wlan_scan_delete_table_entry(pmpriv, table_idx);
3709 }
3710
3711 LEAVE();
3712 return ret;
3713 }
3714
3715 /********************************************************
3716 Global Functions
3717 ********************************************************/
3718
3719 /**
3720 * @brief Check if a scanned network compatible with the driver settings
3721 *
3722 * WEP WPA WPA2 ad-hoc encrypt Network
3723 * enabled enabled enabled AES mode Privacy WPA WPA2 Compatible
3724 * 0 0 0 0 NONE 0 0 0 yes No security
3725 * 0 1 0 0 x 1x 1 x yes WPA (disable
3726 * HT if no AES) 0 0 1 0 x 1x x 1 yes
3727 * WPA2 (disable HT if no AES) 0 0 0 1 NONE 1 0 0
3728 * yes Ad-hoc AES 1 0 0 0 NONE 1 0 0 yes
3729 * Static WEP (disable HT) 0 0 0 0 !=NONE 1 0 0
3730 * yes Dynamic WEP
3731 *
3732 * @param pmpriv A pointer to mlan_private
3733 * @param index Index in scan table to check against current driver settings
3734 * @param mode Network mode: Infrastructure or IBSS
3735 *
3736 * @return Index in ScanTable, or negative value if error
3737 */
wlan_is_network_compatible(mlan_private * pmpriv,t_u32 index,t_u32 mode)3738 t_s32 wlan_is_network_compatible(mlan_private *pmpriv, t_u32 index, t_u32 mode)
3739 {
3740 mlan_adapter *pmadapter = pmpriv->adapter;
3741 BSSDescriptor_t *pbss_desc;
3742
3743 ENTER();
3744
3745 pbss_desc = &pmadapter->pscan_table[index];
3746 /* Don't check for compatibility if roaming */
3747 if ((pmpriv->media_connected == MTRUE) &&
3748 (pmpriv->bss_mode == MLAN_BSS_MODE_INFRA) &&
3749 (pbss_desc->bss_mode == MLAN_BSS_MODE_INFRA)) {
3750 LEAVE();
3751 return index;
3752 }
3753
3754 pbss_desc->disable_11n = MFALSE;
3755
3756 /* if the HE CAP IE exists, HT CAP IE should exist too */
3757 /* 2.4G AX AP, don't have VHT CAP */
3758 if (pbss_desc->phe_cap && !pbss_desc->pht_cap) {
3759 PRINTM(MINFO,
3760 "Disable 11n if VHT CAP/HT CAP IE is not found from the 11AX AP\n");
3761 pbss_desc->disable_11n = MTRUE;
3762 }
3763
3764 /* if the VHT CAP IE exists, the HT CAP IE should exist too */
3765 if (pbss_desc->pvht_cap && !pbss_desc->pht_cap) {
3766 PRINTM(MINFO,
3767 "Disable 11n if HT CAP IE is not found from the 11AC AP\n");
3768 pbss_desc->disable_11n = MTRUE;
3769 }
3770
3771 if (pbss_desc->wlan_11h_bss_info.chan_switch_ann.element_id ==
3772 CHANNEL_SWITCH_ANN) {
3773 PRINTM(MINFO,
3774 "Don't connect to AP with CHANNEL_SWITCH_ANN IE.\n");
3775 LEAVE();
3776 return -1;
3777 }
3778
3779 if (pmpriv->wps.session_enable == MTRUE) {
3780 PRINTM(MINFO, "Return success directly in WPS period\n");
3781 LEAVE();
3782 return index;
3783 }
3784
3785 if (pmpriv->sec_info.osen_enabled && pbss_desc->posen_ie &&
3786 ((*(pbss_desc->posen_ie)).ieee_hdr.element_id ==
3787 VENDOR_SPECIFIC_221)) {
3788 /* Hotspot 2.0 OSEN AKM */
3789 PRINTM(MMSG,
3790 "Return success directly in Hotspot OSEN: index=%d "
3791 "encryption_mode=%#x\n",
3792 index, pmpriv->sec_info.encryption_mode);
3793 LEAVE();
3794 return index;
3795 }
3796
3797 if ((pbss_desc->bss_mode == mode) &&
3798 (pmpriv->sec_info.ewpa_enabled == MTRUE
3799 #ifdef DRV_EMBEDDED_SUPPLICANT
3800 || supplicantIsEnabled(pmpriv->psapriv)
3801 #endif
3802 )) {
3803 if (((pbss_desc->pwpa_ie) &&
3804 ((*(pbss_desc->pwpa_ie)).vend_hdr.element_id == WPA_IE)) ||
3805 ((pbss_desc->prsn_ie) &&
3806 ((*(pbss_desc->prsn_ie)).ieee_hdr.element_id == RSN_IE))) {
3807 if (((pmpriv->adapter->config_bands & BAND_GN ||
3808 pmpriv->adapter->config_bands & BAND_AN) &&
3809 pbss_desc->pht_cap) &&
3810 (pmpriv->bss_mode == MLAN_BSS_MODE_INFRA) &&
3811 !is_wpa_oui_present(pmpriv->adapter, pbss_desc,
3812 CIPHER_SUITE_CCMP) &&
3813 !is_rsn_oui_present(pmpriv->adapter, pbss_desc,
3814 CIPHER_SUITE_CCMP) &&
3815 !is_rsn_oui_present(pmpriv->adapter, pbss_desc,
3816 CIPHER_SUITE_GCMP) &&
3817 !is_rsn_oui_present(pmpriv->adapter, pbss_desc,
3818 CIPHER_SUITE_GCMP_256) &&
3819 !is_rsn_oui_present(pmpriv->adapter, pbss_desc,
3820 CIPHER_SUITE_CCMP_256)) {
3821 if (is_wpa_oui_present(pmpriv->adapter,
3822 pbss_desc,
3823 CIPHER_SUITE_TKIP) ||
3824 is_rsn_oui_present(pmpriv->adapter,
3825 pbss_desc,
3826 CIPHER_SUITE_TKIP)) {
3827 PRINTM(MINFO,
3828 "Disable 11n if AES is not supported by AP\n");
3829 pbss_desc->disable_11n = MTRUE;
3830 } else {
3831 LEAVE();
3832 return -1;
3833 }
3834 }
3835 LEAVE();
3836 return index;
3837 } else {
3838 PRINTM(MINFO,
3839 "ewpa_enabled: Ignore none WPA/WPA2 AP\n");
3840 LEAVE();
3841 return -1;
3842 }
3843 }
3844
3845 if (pmpriv->sec_info.wapi_enabled &&
3846 (pbss_desc->pwapi_ie &&
3847 ((*(pbss_desc->pwapi_ie)).ieee_hdr.element_id == WAPI_IE))) {
3848 PRINTM(MINFO, "Return success for WAPI AP\n");
3849 LEAVE();
3850 return index;
3851 }
3852
3853 if (pbss_desc->bss_mode == mode) {
3854 if (pmpriv->sec_info.wep_status == Wlan802_11WEPDisabled &&
3855 !pmpriv->sec_info.wpa_enabled &&
3856 !pmpriv->sec_info.wpa2_enabled &&
3857 ((!pbss_desc->pwpa_ie) ||
3858 ((*(pbss_desc->pwpa_ie)).vend_hdr.element_id != WPA_IE)) &&
3859 ((!pbss_desc->prsn_ie) ||
3860 ((*(pbss_desc->prsn_ie)).ieee_hdr.element_id != RSN_IE)) &&
3861 pmpriv->sec_info.encryption_mode ==
3862 MLAN_ENCRYPTION_MODE_NONE &&
3863 !pbss_desc->privacy) {
3864 /* No security */
3865 LEAVE();
3866 return index;
3867 } else if (pmpriv->sec_info.wep_status ==
3868 Wlan802_11WEPEnabled &&
3869 !pmpriv->sec_info.wpa_enabled &&
3870 !pmpriv->sec_info.wpa2_enabled &&
3871 pbss_desc->privacy) {
3872 /* Static WEP enabled */
3873 PRINTM(MINFO, "Disable 11n in WEP mode\n");
3874 pbss_desc->disable_11n = MTRUE;
3875 /* Reject the following cases: */
3876 /*
3877 * case 1: RSN IE w/o WEP OUI and WPA IE w/o WEP OUI
3878 * case 2: RSN IE w/o WEP OUI and No WPA IE
3879 * case 3: WPA IE w/o WEP OUI and No RSN IE
3880 */
3881 if (((pbss_desc->prsn_ie) &&
3882 ((*(pbss_desc->prsn_ie)).ieee_hdr.element_id ==
3883 RSN_IE)) ||
3884 ((pbss_desc->pwpa_ie) &&
3885 ((*(pbss_desc->pwpa_ie)).vend_hdr.element_id ==
3886 WPA_IE))) {
3887 if (!is_rsn_oui_present(pmpriv->adapter,
3888 pbss_desc,
3889 CIPHER_SUITE_WEP40) &&
3890 !is_rsn_oui_present(pmpriv->adapter,
3891 pbss_desc,
3892 CIPHER_SUITE_WEP104) &&
3893 !is_wpa_oui_present(pmpriv->adapter,
3894 pbss_desc,
3895 CIPHER_SUITE_WEP40) &&
3896 !is_wpa_oui_present(pmpriv->adapter,
3897 pbss_desc,
3898 CIPHER_SUITE_WEP104))
3899 index = -1;
3900 }
3901
3902 LEAVE();
3903 return index;
3904 } else if (pmpriv->sec_info.wep_status ==
3905 Wlan802_11WEPDisabled &&
3906 pmpriv->sec_info.wpa_enabled &&
3907 !pmpriv->sec_info.wpa2_enabled &&
3908 ((pbss_desc->pwpa_ie) &&
3909 ((*(pbss_desc->pwpa_ie)).vend_hdr.element_id ==
3910 WPA_IE))
3911 /*
3912 * Privacy bit may NOT be set in some APs like
3913 * LinkSys WRT54G && pbss_desc->privacy
3914 */
3915 ) {
3916 PRINTM(MINFO,
3917 "wlan_is_network_compatible() WPA: index=%d wpa_ie=%#x "
3918 "rsn_ie=%#x WEP=%s WPA=%s WPA2=%s EncMode=%#x "
3919 "privacy=%#x\n",
3920 index,
3921 (pbss_desc->pwpa_ie) ?
3922 (*(pbss_desc->pwpa_ie))
3923 .vend_hdr.element_id :
3924 0,
3925 (pbss_desc->prsn_ie) ?
3926 (*(pbss_desc->prsn_ie))
3927 .ieee_hdr.element_id :
3928 0,
3929 (pmpriv->sec_info.wep_status ==
3930 Wlan802_11WEPEnabled) ?
3931 "e" :
3932 "d",
3933 (pmpriv->sec_info.wpa_enabled) ? "e" : "d",
3934 (pmpriv->sec_info.wpa2_enabled) ? "e" : "d",
3935 pmpriv->sec_info.encryption_mode,
3936 pbss_desc->privacy);
3937 if (((pmpriv->adapter->config_bands & BAND_GN ||
3938 pmpriv->adapter->config_bands & BAND_AN) &&
3939 pbss_desc->pht_cap) &&
3940 (pmpriv->bss_mode == MLAN_BSS_MODE_INFRA) &&
3941 !is_wpa_oui_present(pmpriv->adapter, pbss_desc,
3942 CIPHER_SUITE_CCMP)) {
3943 if (is_wpa_oui_present(pmpriv->adapter,
3944 pbss_desc,
3945 CIPHER_SUITE_TKIP)) {
3946 PRINTM(MINFO,
3947 "Disable 11n if AES is not supported by AP\n");
3948 pbss_desc->disable_11n = MTRUE;
3949 } else {
3950 LEAVE();
3951 return -1;
3952 }
3953 }
3954 LEAVE();
3955 return index;
3956 } else if (pmpriv->sec_info.wep_status ==
3957 Wlan802_11WEPDisabled &&
3958 !pmpriv->sec_info.wpa_enabled &&
3959 pmpriv->sec_info.wpa2_enabled &&
3960 ((pbss_desc->prsn_ie) &&
3961 ((*(pbss_desc->prsn_ie)).ieee_hdr.element_id ==
3962 RSN_IE))
3963 /*
3964 * Privacy bit may NOT be set in some APs like
3965 * LinkSys WRT54G && pbss_desc->privacy
3966 */
3967 ) {
3968 /* WPA2 enabled */
3969 PRINTM(MINFO,
3970 "wlan_is_network_compatible() WPA2: index=%d wpa_ie=%#x "
3971 "rsn_ie=%#x WEP=%s WPA=%s WPA2=%s EncMode=%#x "
3972 "privacy=%#x\n",
3973 index,
3974 (pbss_desc->pwpa_ie) ?
3975 (*(pbss_desc->pwpa_ie))
3976 .vend_hdr.element_id :
3977 0,
3978 (pbss_desc->prsn_ie) ?
3979 (*(pbss_desc->prsn_ie))
3980 .ieee_hdr.element_id :
3981 0,
3982 (pmpriv->sec_info.wep_status ==
3983 Wlan802_11WEPEnabled) ?
3984 "e" :
3985 "d",
3986 (pmpriv->sec_info.wpa_enabled) ? "e" : "d",
3987 (pmpriv->sec_info.wpa2_enabled) ? "e" : "d",
3988 pmpriv->sec_info.encryption_mode,
3989 pbss_desc->privacy);
3990 if (((pmpriv->adapter->config_bands & BAND_GN ||
3991 pmpriv->adapter->config_bands & BAND_AN) &&
3992 pbss_desc->pht_cap) &&
3993 (pmpriv->bss_mode == MLAN_BSS_MODE_INFRA) &&
3994 !is_rsn_oui_present(pmpriv->adapter, pbss_desc,
3995 CIPHER_SUITE_CCMP) &&
3996 !is_rsn_oui_present(pmpriv->adapter, pbss_desc,
3997 CIPHER_SUITE_GCMP) &&
3998 !is_rsn_oui_present(pmpriv->adapter, pbss_desc,
3999 CIPHER_SUITE_GCMP_256) &&
4000 !is_rsn_oui_present(pmpriv->adapter, pbss_desc,
4001 CIPHER_SUITE_CCMP_256)) {
4002 if (is_rsn_oui_present(pmpriv->adapter,
4003 pbss_desc,
4004 CIPHER_SUITE_TKIP)) {
4005 PRINTM(MINFO,
4006 "Disable 11n if AES is not supported by AP\n");
4007 pbss_desc->disable_11n = MTRUE;
4008 } else if (is_rsn_oui_present_in_wpa_ie(
4009 pmpriv, CIPHER_SUITE_CCMP) ||
4010 is_rsn_oui_present_in_wpa_ie(
4011 pmpriv, CIPHER_SUITE_GCMP) ||
4012 is_rsn_oui_present_in_wpa_ie(
4013 pmpriv,
4014 CIPHER_SUITE_GCMP_256) ||
4015 is_rsn_oui_present_in_wpa_ie(
4016 pmpriv,
4017 CIPHER_SUITE_CCMP_256)) {
4018 LEAVE();
4019 return index;
4020 } else {
4021 LEAVE();
4022 return -1;
4023 }
4024 }
4025 LEAVE();
4026 return index;
4027 } else if (pmpriv->sec_info.wep_status ==
4028 Wlan802_11WEPDisabled &&
4029 !pmpriv->sec_info.wpa_enabled &&
4030 !pmpriv->sec_info.wpa2_enabled &&
4031 ((!pbss_desc->pwpa_ie) ||
4032 ((*(pbss_desc->pwpa_ie)).vend_hdr.element_id !=
4033 WPA_IE)) &&
4034 ((!pbss_desc->prsn_ie) ||
4035 ((*(pbss_desc->prsn_ie)).ieee_hdr.element_id !=
4036 RSN_IE)) &&
4037 pmpriv->sec_info.encryption_mode !=
4038 MLAN_ENCRYPTION_MODE_NONE &&
4039 pbss_desc->privacy) {
4040 /* Dynamic WEP enabled */
4041 pbss_desc->disable_11n = MTRUE;
4042 PRINTM(MINFO,
4043 "wlan_is_network_compatible() dynamic WEP: index=%d "
4044 "wpa_ie=%#x rsn_ie=%#x EncMode=%#x privacy=%#x\n",
4045 index,
4046 (pbss_desc->pwpa_ie) ?
4047 (*(pbss_desc->pwpa_ie))
4048 .vend_hdr.element_id :
4049 0,
4050 (pbss_desc->prsn_ie) ?
4051 (*(pbss_desc->prsn_ie))
4052 .ieee_hdr.element_id :
4053 0,
4054 pmpriv->sec_info.encryption_mode,
4055 pbss_desc->privacy);
4056 LEAVE();
4057 return index;
4058 }
4059 /* Security doesn't match */
4060 PRINTM(MINFO,
4061 "wlan_is_network_compatible() FAILED: index=%d wpa_ie=%#x "
4062 "rsn_ie=%#x WEP=%s WPA=%s WPA2=%s EncMode=%#x privacy=%#x\n",
4063 index,
4064 (pbss_desc->pwpa_ie) ?
4065 (*(pbss_desc->pwpa_ie)).vend_hdr.element_id :
4066 0,
4067 (pbss_desc->prsn_ie) ?
4068 (*(pbss_desc->prsn_ie)).ieee_hdr.element_id :
4069 0,
4070 (pmpriv->sec_info.wep_status == Wlan802_11WEPEnabled) ?
4071 "e" :
4072 "d",
4073 (pmpriv->sec_info.wpa_enabled) ? "e" : "d",
4074 (pmpriv->sec_info.wpa2_enabled) ? "e" : "d",
4075 pmpriv->sec_info.encryption_mode, pbss_desc->privacy);
4076 LEAVE();
4077 return -1;
4078 }
4079 /* Mode doesn't match */
4080 LEAVE();
4081 return -1;
4082 }
4083
4084 /**
4085 * @brief Internal function used to flush the scan list
4086 *
4087 * @param pmadapter A pointer to mlan_adapter structure
4088 *
4089 * @return MLAN_STATUS_SUCCESS
4090 */
wlan_flush_scan_table(pmlan_adapter pmadapter)4091 mlan_status wlan_flush_scan_table(pmlan_adapter pmadapter)
4092 {
4093 t_u8 i = 0;
4094 ENTER();
4095
4096 PRINTM(MINFO, "Flushing scan table\n");
4097
4098 memset(pmadapter, pmadapter->pscan_table, 0,
4099 (sizeof(BSSDescriptor_t) * MRVDRV_MAX_BSSID_LIST));
4100 pmadapter->num_in_scan_table = 0;
4101
4102 memset(pmadapter, pmadapter->bcn_buf, 0, pmadapter->bcn_buf_size);
4103 pmadapter->pbcn_buf_end = pmadapter->bcn_buf;
4104
4105 for (i = 0; i < pmadapter->num_in_chan_stats; i++)
4106 pmadapter->pchan_stats[i].cca_scan_duration = 0;
4107 pmadapter->idx_chan_stats = 0;
4108
4109 LEAVE();
4110 return MLAN_STATUS_SUCCESS;
4111 }
4112
4113 /**
4114 * @brief Internal function used to start a scan based on an input config
4115 *
4116 * Use the input user scan configuration information when provided in
4117 * order to send the appropriate scan commands to firmware to populate or
4118 * update the internal driver scan table
4119 *
4120 * @param pmpriv A pointer to mlan_private structure
4121 * @param pioctl_buf A pointer to MLAN IOCTL Request buffer
4122 * @param puser_scan_in Pointer to the input configuration for the requested
4123 * scan.
4124 *
4125 * @return MLAN_STATUS_SUCCESS or < 0 if error
4126 */
wlan_scan_networks(mlan_private * pmpriv,t_void * pioctl_buf,wlan_user_scan_cfg * puser_scan_in)4127 mlan_status wlan_scan_networks(mlan_private *pmpriv, t_void *pioctl_buf,
4128 wlan_user_scan_cfg *puser_scan_in)
4129 {
4130 mlan_status ret = MLAN_STATUS_SUCCESS;
4131 mlan_adapter *pmadapter = pmpriv->adapter;
4132 mlan_callbacks *pcb = (mlan_callbacks *)&pmadapter->callbacks;
4133 cmd_ctrl_node *pcmd_node = MNULL;
4134 pmlan_ioctl_req pioctl_req = (mlan_ioctl_req *)pioctl_buf;
4135
4136 wlan_scan_cmd_config_tlv *pscan_cfg_out = MNULL;
4137 MrvlIEtypes_ChanListParamSet_t *pchan_list_out;
4138 t_u32 buf_size;
4139 ChanScanParamSet_t *pscan_chan_list;
4140
4141 t_u8 keep_previous_scan;
4142 t_u8 filtered_scan;
4143 t_u8 scan_current_chan_only;
4144 t_u8 max_chan_per_scan;
4145 t_u8 i;
4146
4147 ENTER();
4148
4149 ret = pcb->moal_malloc(pmadapter->pmoal_handle,
4150 sizeof(wlan_scan_cmd_config_tlv),
4151 MLAN_MEM_DEF | MLAN_MEM_FLAG_ATOMIC,
4152 (t_u8 **)&pscan_cfg_out);
4153 if (ret != MLAN_STATUS_SUCCESS || !pscan_cfg_out) {
4154 PRINTM(MERROR, "Memory allocation for pscan_cfg_out failed!\n");
4155 if (pioctl_req)
4156 pioctl_req->status_code = MLAN_ERROR_NO_MEM;
4157 LEAVE();
4158 return MLAN_STATUS_FAILURE;
4159 }
4160
4161 buf_size = sizeof(ChanScanParamSet_t) * WLAN_USER_SCAN_CHAN_MAX;
4162 ret = pcb->moal_malloc(pmadapter->pmoal_handle, buf_size,
4163 MLAN_MEM_DEF | MLAN_MEM_FLAG_ATOMIC,
4164 (t_u8 **)&pscan_chan_list);
4165 if (ret != MLAN_STATUS_SUCCESS || !pscan_chan_list) {
4166 PRINTM(MERROR, "Failed to allocate scan_chan_list\n");
4167 if (pscan_cfg_out)
4168 pcb->moal_mfree(pmadapter->pmoal_handle,
4169 (t_u8 *)pscan_cfg_out);
4170 if (pioctl_req)
4171 pioctl_req->status_code = MLAN_ERROR_NO_MEM;
4172 LEAVE();
4173 return MLAN_STATUS_FAILURE;
4174 }
4175
4176 memset(pmadapter, pscan_chan_list, 0x00, buf_size);
4177 memset(pmadapter, pscan_cfg_out, 0x00,
4178 sizeof(wlan_scan_cmd_config_tlv));
4179
4180 keep_previous_scan = MFALSE;
4181
4182 ret = wlan_scan_setup_scan_config(pmpriv, puser_scan_in,
4183 &pscan_cfg_out->config,
4184 &pchan_list_out, pscan_chan_list,
4185 &max_chan_per_scan, &filtered_scan,
4186 &scan_current_chan_only);
4187 if (ret != MLAN_STATUS_SUCCESS) {
4188 PRINTM(MERROR, "Failed to setup scan config\n");
4189 if (pscan_cfg_out)
4190 pcb->moal_mfree(pmadapter->pmoal_handle,
4191 (t_u8 *)pscan_cfg_out);
4192 if (pscan_chan_list)
4193 pcb->moal_mfree(pmadapter->pmoal_handle,
4194 (t_u8 *)pscan_chan_list);
4195 if (pioctl_req)
4196 pioctl_req->status_code = MLAN_ERROR_INVALID_PARAMETER;
4197 LEAVE();
4198 return MLAN_STATUS_FAILURE;
4199 }
4200
4201 if (puser_scan_in)
4202 keep_previous_scan = puser_scan_in->keep_previous_scan;
4203
4204 if (keep_previous_scan == MFALSE) {
4205 memset(pmadapter, pmadapter->pscan_table, 0x00,
4206 sizeof(BSSDescriptor_t) * MRVDRV_MAX_BSSID_LIST);
4207 pmadapter->num_in_scan_table = 0;
4208 pmadapter->pbcn_buf_end = pmadapter->bcn_buf;
4209 } else {
4210 wlan_scan_delete_ageout_entry(pmpriv);
4211 }
4212 for (i = 0; i < pmadapter->num_in_chan_stats; i++)
4213 pmadapter->pchan_stats[i].cca_scan_duration = 0;
4214 pmadapter->idx_chan_stats = 0;
4215
4216 ret = wlan_scan_channel_list(pmpriv, pioctl_buf, max_chan_per_scan,
4217 filtered_scan, &pscan_cfg_out->config,
4218 pchan_list_out, pscan_chan_list);
4219
4220 /* Get scan command from scan_pending_q and put to cmd_pending_q */
4221 if (ret == MLAN_STATUS_SUCCESS) {
4222 wlan_request_cmd_lock(pmadapter);
4223 if (util_peek_list(pmadapter->pmoal_handle,
4224 &pmadapter->scan_pending_q, MNULL, MNULL)) {
4225 pcmd_node = (cmd_ctrl_node *)util_dequeue_list(
4226 pmadapter->pmoal_handle,
4227 &pmadapter->scan_pending_q, MNULL, MNULL);
4228 pmadapter->pscan_ioctl_req = pioctl_req;
4229 pmadapter->scan_processing = MTRUE;
4230 pmadapter->scan_state = SCAN_STATE_SCAN_START;
4231 wlan_insert_cmd_to_pending_q(pmadapter, pcmd_node,
4232 MTRUE);
4233 }
4234 wlan_release_cmd_lock(pmadapter);
4235 }
4236 if (pscan_cfg_out)
4237 pcb->moal_mfree(pmadapter->pmoal_handle, (t_u8 *)pscan_cfg_out);
4238
4239 if (pscan_chan_list)
4240 pcb->moal_mfree(pmadapter->pmoal_handle,
4241 (t_u8 *)pscan_chan_list);
4242
4243 LEAVE();
4244 return ret;
4245 }
4246
4247 /**
4248 * @brief Prepare a scan command to be sent to the firmware
4249 *
4250 * Use the wlan_scan_cmd_config sent to the command processing module in
4251 * the wlan_prepare_cmd to configure a HostCmd_DS_802_11_SCAN command
4252 * struct to send to firmware.
4253 *
4254 * The fixed fields specifying the BSS type and BSSID filters as well as a
4255 * variable number/length of TLVs are sent in the command to firmware.
4256 *
4257 * @param pmpriv A pointer to mlan_private structure
4258 * @param pcmd A pointer to HostCmd_DS_COMMAND structure to be sent to
4259 * firmware with the HostCmd_DS_801_11_SCAN structure
4260 * @param pdata_buf Void pointer cast of a wlan_scan_cmd_config struct used
4261 * to set the fields/TLVs for the command sent to firmware
4262 *
4263 * @return MLAN_STATUS_SUCCESS
4264 */
wlan_cmd_802_11_scan(mlan_private * pmpriv,HostCmd_DS_COMMAND * pcmd,t_void * pdata_buf)4265 mlan_status wlan_cmd_802_11_scan(mlan_private *pmpriv, HostCmd_DS_COMMAND *pcmd,
4266 t_void *pdata_buf)
4267 {
4268 HostCmd_DS_802_11_SCAN *pscan_cmd = &pcmd->params.scan;
4269 wlan_scan_cmd_config *pscan_cfg;
4270
4271 ENTER();
4272
4273 pscan_cfg = (wlan_scan_cmd_config *)pdata_buf;
4274
4275 /* Set fixed field variables in scan command */
4276 pscan_cmd->bss_mode = pscan_cfg->bss_mode;
4277 memcpy_ext(pmpriv->adapter, pscan_cmd->bssid, pscan_cfg->specific_bssid,
4278 sizeof(pscan_cmd->bssid), sizeof(pscan_cmd->bssid));
4279 memcpy_ext(pmpriv->adapter, pscan_cmd->tlv_buffer, pscan_cfg->tlv_buf,
4280 pscan_cfg->tlv_buf_len, pscan_cfg->tlv_buf_len);
4281
4282 pcmd->command = wlan_cpu_to_le16(HostCmd_CMD_802_11_SCAN);
4283
4284 /* Size is equal to the sizeof(fixed portions) + the TLV len + header */
4285 pcmd->size = (t_u16)wlan_cpu_to_le16(
4286 (t_u16)(sizeof(pscan_cmd->bss_mode) + sizeof(pscan_cmd->bssid) +
4287 pscan_cfg->tlv_buf_len + S_DS_GEN));
4288
4289 LEAVE();
4290 return MLAN_STATUS_SUCCESS;
4291 }
4292
4293 /**
4294 * @brief Check if any hidden SSID found in passive scan channels
4295 * and do specific SSID active scan for those channels
4296 *
4297 * @param pmpriv A pointer to mlan_private structure
4298 * @param pioctl_buf A pointer to mlan_ioctl_req structure
4299 *
4300 * @return MTRUE/MFALSE
4301 */
4302
wlan_active_scan_req_for_passive_chan(mlan_private * pmpriv,mlan_ioctl_req * pioctl_buf)4303 static t_bool wlan_active_scan_req_for_passive_chan(mlan_private *pmpriv,
4304 mlan_ioctl_req *pioctl_buf)
4305 {
4306 t_bool ret = MFALSE;
4307 mlan_adapter *pmadapter = pmpriv->adapter;
4308 t_bool scan_reqd = MFALSE;
4309 t_bool chan_listed = MFALSE;
4310 t_u8 id = 0;
4311 t_u32 bss_idx, i;
4312 t_u8 null_ssid[MLAN_MAX_SSID_LENGTH] = {0};
4313 mlan_callbacks *pcb = (mlan_callbacks *)&pmpriv->adapter->callbacks;
4314 wlan_user_scan_cfg *user_scan_cfg;
4315 mlan_ds_scan *pscan = (mlan_ds_scan *)pioctl_buf->pbuf;
4316 mlan_scan_req *pscan_req = MNULL;
4317 wlan_user_scan_cfg *puser_scan_in = MNULL;
4318
4319 ENTER();
4320
4321 if (pscan->sub_command == MLAN_OID_SCAN_USER_CONFIG) {
4322 puser_scan_in = (wlan_user_scan_cfg *)
4323 pscan->param.user_scan.scan_cfg_buf;
4324 if (!puser_scan_in->ssid_filter)
4325 goto done;
4326 }
4327
4328 if (pmadapter->active_scan_triggered) {
4329 pmadapter->active_scan_triggered = MFALSE;
4330 goto done;
4331 }
4332
4333 if ((pcb->moal_malloc(pmadapter->pmoal_handle,
4334 sizeof(wlan_user_scan_cfg), MLAN_MEM_DEF,
4335 (t_u8 **)&user_scan_cfg) !=
4336 MLAN_STATUS_SUCCESS) ||
4337 !user_scan_cfg) {
4338 PRINTM(MERROR, "Memory allocation for user_scan_cfg failed\n");
4339 goto done;
4340 }
4341 memset(pmadapter, user_scan_cfg, 0, sizeof(wlan_user_scan_cfg));
4342 for (bss_idx = 0; bss_idx < pmadapter->num_in_scan_table; bss_idx++) {
4343 scan_reqd = MFALSE;
4344 if (!memcmp(pmadapter,
4345 pmadapter->pscan_table[bss_idx].ssid.ssid,
4346 null_ssid,
4347 pmadapter->pscan_table[bss_idx].ssid.ssid_len)) {
4348 if (puser_scan_in &&
4349 puser_scan_in->chan_list[0].chan_number) {
4350 for (i = 0;
4351 i < WLAN_USER_SCAN_CHAN_MAX &&
4352 puser_scan_in->chan_list[i].chan_number;
4353 i++) {
4354 if (puser_scan_in->chan_list[i]
4355 .chan_number ==
4356 pmadapter->pscan_table[bss_idx]
4357 .channel) {
4358 if (puser_scan_in->chan_list[i]
4359 .scan_type ==
4360 MLAN_SCAN_TYPE_PASSIVE)
4361 scan_reqd = MTRUE;
4362 break;
4363 }
4364 }
4365 } else if (pmadapter->scan_type ==
4366 MLAN_SCAN_TYPE_PASSIVE) {
4367 scan_reqd = MTRUE;
4368 } else {
4369 if ((pmadapter->pscan_table[bss_idx].bss_band &
4370 BAND_A) &&
4371 wlan_11h_radar_detect_required(
4372 pmpriv,
4373 pmadapter->pscan_table[bss_idx]
4374 .channel))
4375 scan_reqd = MTRUE;
4376 if (pmadapter->pscan_table[bss_idx].bss_band &
4377 (BAND_B | BAND_G) &&
4378 wlan_bg_scan_type_is_passive(
4379 pmpriv,
4380 pmadapter->pscan_table[bss_idx]
4381 .channel))
4382 scan_reqd = MTRUE;
4383 }
4384
4385 if (scan_reqd) {
4386 chan_listed = MFALSE;
4387 for (i = 0; i < id; i++) {
4388 if ((user_scan_cfg->chan_list[i]
4389 .chan_number ==
4390 pmadapter->pscan_table[bss_idx]
4391 .channel) &&
4392 (user_scan_cfg->chan_list[i]
4393 .radio_type &
4394 pmadapter->pscan_table[bss_idx]
4395 .bss_band)) {
4396 chan_listed = MTRUE;
4397 break;
4398 }
4399 }
4400 if (chan_listed == MTRUE)
4401 continue;
4402 user_scan_cfg->chan_list[id].chan_number =
4403 pmadapter->pscan_table[bss_idx].channel;
4404 if (pmadapter->pscan_table[bss_idx].bss_band &
4405 (BAND_B | BAND_G))
4406 user_scan_cfg->chan_list[id].radio_type =
4407 BAND_2GHZ;
4408 if (pmadapter->pscan_table[bss_idx].bss_band &
4409 BAND_A)
4410 user_scan_cfg->chan_list[id].radio_type =
4411 BAND_5GHZ;
4412 user_scan_cfg->chan_list[id].scan_type =
4413 MLAN_SCAN_TYPE_ACTIVE;
4414 id++;
4415 }
4416 }
4417 }
4418 if (id) {
4419 pmadapter->active_scan_triggered = MTRUE;
4420 if (pscan->sub_command == MLAN_OID_SCAN_USER_CONFIG) {
4421 memcpy_ext(pmpriv->adapter, user_scan_cfg->ssid_list,
4422 puser_scan_in->ssid_list,
4423 sizeof(user_scan_cfg->ssid_list),
4424 sizeof(user_scan_cfg->ssid_list));
4425 } else {
4426 pscan_req = &pscan->param.scan_req;
4427 memcpy_ext(pmpriv->adapter,
4428 user_scan_cfg->ssid_list[0].ssid,
4429 pscan_req->scan_ssid.ssid,
4430 pscan_req->scan_ssid.ssid_len,
4431 MLAN_MAX_SSID_LENGTH);
4432 }
4433 user_scan_cfg->keep_previous_scan = MTRUE;
4434 if (MLAN_STATUS_SUCCESS !=
4435 wlan_scan_networks(pmpriv, pioctl_buf, user_scan_cfg)) {
4436 goto done;
4437 }
4438 ret = MTRUE;
4439 }
4440 if (user_scan_cfg)
4441 pcb->moal_mfree(pmadapter->pmoal_handle, (t_u8 *)user_scan_cfg);
4442
4443 done:
4444 LEAVE();
4445 return ret;
4446 }
4447
4448 /**
4449 * @brief This function handles the command response of scan
4450 *
4451 * The response buffer for the scan command has the following
4452 * memory layout:
4453 *
4454 * .-------------------------------------------------------------.
4455 * | Header (4 * sizeof(t_u16)): Standard command response hdr |
4456 * .-------------------------------------------------------------.
4457 * | BufSize (t_u16) : sizeof the BSS Description data |
4458 * .-------------------------------------------------------------.
4459 * | NumOfSet (t_u8) : Number of BSS Descs returned |
4460 * .-------------------------------------------------------------.
4461 * | BSSDescription data (variable, size given in BufSize) |
4462 * .-------------------------------------------------------------.
4463 * | TLV data (variable, size calculated using Header->Size, |
4464 * | BufSize and sizeof the fixed fields above) |
4465 * .-------------------------------------------------------------.
4466 *
4467 * @param pmpriv A pointer to mlan_private structure
4468 * @param resp A pointer to HostCmd_DS_COMMAND
4469 * @param pioctl_buf A pointer to mlan_ioctl_req structure
4470 *
4471 * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
4472 */
wlan_ret_802_11_scan(mlan_private * pmpriv,HostCmd_DS_COMMAND * resp,t_void * pioctl_buf)4473 mlan_status wlan_ret_802_11_scan(mlan_private *pmpriv, HostCmd_DS_COMMAND *resp,
4474 t_void *pioctl_buf)
4475 {
4476 mlan_status ret = MLAN_STATUS_SUCCESS;
4477 mlan_adapter *pmadapter = pmpriv->adapter;
4478 mlan_callbacks *pcb = MNULL;
4479 cmd_ctrl_node *pcmd_node = MNULL;
4480 HostCmd_DS_802_11_SCAN_RSP *pscan_rsp = MNULL;
4481 BSSDescriptor_t *bss_new_entry = MNULL;
4482 MrvlIEtypes_Data_t *ptlv;
4483 MrvlIEtypes_TsfTimestamp_t *ptsf_tlv = MNULL;
4484 MrvlIEtypes_ChannelStats_t *pchanstats_tlv = MNULL;
4485 t_u8 *pbss_info;
4486 t_u32 scan_resp_size;
4487 t_u32 bytes_left;
4488 t_u32 num_in_table;
4489 t_u32 bss_idx;
4490 t_u32 idx;
4491 t_u32 tlv_buf_size;
4492 t_u64 tsf_val;
4493 chan_freq_power_t *cfp;
4494 MrvlIEtypes_ChanBandListParamSet_t *pchan_band_tlv = MNULL;
4495 ChanBandParamSet_t *pchan_band;
4496 t_u16 band;
4497 t_u8 is_bgscan_resp;
4498 t_u32 age_ts_usec;
4499 t_u8 null_ssid[MLAN_MAX_SSID_LENGTH] = {0};
4500 t_u32 status_code = 0;
4501 pmlan_ioctl_req pscan_ioctl_req = MNULL;
4502
4503 ENTER();
4504 pcb = (pmlan_callbacks)&pmadapter->callbacks;
4505
4506 is_bgscan_resp = (resp->command == HostCmd_CMD_802_11_BG_SCAN_QUERY);
4507 if (is_bgscan_resp)
4508 pscan_rsp = &resp->params.bg_scan_query_resp.scan_resp;
4509 else
4510 pscan_rsp = &resp->params.scan_resp;
4511
4512 if (pscan_rsp->number_of_sets > MRVDRV_MAX_BSSID_LIST) {
4513 PRINTM(MERROR,
4514 "SCAN_RESP: Invalid number of AP returned (%d)!!\n",
4515 pscan_rsp->number_of_sets);
4516 status_code = MLAN_ERROR_CMD_SCAN_FAIL;
4517 ret = MLAN_STATUS_FAILURE;
4518 goto done;
4519 }
4520
4521 bytes_left = wlan_le16_to_cpu(pscan_rsp->bss_descript_size);
4522 PRINTM(MINFO, "SCAN_RESP: bss_descript_size %d\n", bytes_left);
4523
4524 scan_resp_size = resp->size;
4525
4526 PRINTM(MINFO, "SCAN_RESP: returned %d APs before parsing\n",
4527 pscan_rsp->number_of_sets);
4528
4529 /* Update the age_in_second */
4530 pmadapter->callbacks.moal_get_system_time(
4531 pmadapter->pmoal_handle, &pmadapter->age_in_secs, &age_ts_usec);
4532
4533 num_in_table = pmadapter->num_in_scan_table;
4534 pbss_info = pscan_rsp->bss_desc_and_tlv_buffer;
4535
4536 /*
4537 * The size of the TLV buffer is equal to the entire command response
4538 * size (scan_resp_size) minus the fixed fields (sizeof()'s), the
4539 * BSS Descriptions (bss_descript_size as bytesLef) and the command
4540 * response header (S_DS_GEN)
4541 */
4542 tlv_buf_size = scan_resp_size -
4543 (bytes_left + sizeof(pscan_rsp->bss_descript_size) +
4544 sizeof(pscan_rsp->number_of_sets) + S_DS_GEN);
4545 if (is_bgscan_resp)
4546 tlv_buf_size -= sizeof(
4547 resp->params.bg_scan_query_resp.report_condition);
4548
4549 ptlv = (MrvlIEtypes_Data_t *)(pscan_rsp->bss_desc_and_tlv_buffer +
4550 bytes_left);
4551
4552 /*
4553 * Search the TLV buffer space in the scan response
4554 * for any valid TLVs
4555 */
4556 wlan_ret_802_11_scan_get_tlv_ptrs(pmadapter, ptlv, tlv_buf_size,
4557 TLV_TYPE_TSFTIMESTAMP,
4558 (MrvlIEtypes_Data_t **)&ptsf_tlv);
4559
4560 /*
4561 * Search the TLV buffer space in the scan response
4562 * for any valid TLVs
4563 */
4564 wlan_ret_802_11_scan_get_tlv_ptrs(
4565 pmadapter, ptlv, tlv_buf_size, TLV_TYPE_CHANNELBANDLIST,
4566 (MrvlIEtypes_Data_t **)&pchan_band_tlv);
4567 wlan_ret_802_11_scan_get_tlv_ptrs(
4568 pmadapter, ptlv, tlv_buf_size, TLV_TYPE_CHANNEL_STATS,
4569 (MrvlIEtypes_Data_t **)&pchanstats_tlv);
4570
4571 if (pchanstats_tlv)
4572 wlan_update_chan_statistics(pmpriv, pchanstats_tlv);
4573
4574 /*
4575 * Process each scan response returned (pscan_rsp->number_of_sets).
4576 * Save the information in the bss_new_entry and then insert into
4577 * the driver scan table either as an update to an existing entry
4578 * or as an addition at the end of the table
4579 */
4580 ret = pcb->moal_malloc(pmadapter->pmoal_handle, sizeof(BSSDescriptor_t),
4581 MLAN_MEM_DEF, (t_u8 **)&bss_new_entry);
4582
4583 if (ret != MLAN_STATUS_SUCCESS || !bss_new_entry) {
4584 PRINTM(MERROR, "Memory allocation for bss_new_entry failed!\n");
4585 status_code = MLAN_ERROR_NO_MEM;
4586 ret = MLAN_STATUS_FAILURE;
4587 goto done;
4588 }
4589
4590 for (idx = 0; idx < pscan_rsp->number_of_sets && bytes_left; idx++) {
4591 /* Zero out the bss_new_entry we are about to store info in */
4592 memset(pmadapter, bss_new_entry, 0x00, sizeof(BSSDescriptor_t));
4593
4594 /* Process the data fields and IEs returned for this BSS */
4595 if (wlan_interpret_bss_desc_with_ie(
4596 pmadapter, bss_new_entry, &pbss_info, &bytes_left,
4597 MFALSE) == MLAN_STATUS_SUCCESS) {
4598 PRINTM(MINFO, "SCAN_RESP: BSSID = " MACSTR "\n",
4599 MAC2STR(bss_new_entry->mac_address));
4600
4601 band = BAND_G;
4602 if (pchan_band_tlv) {
4603 pchan_band =
4604 &pchan_band_tlv->chan_band_param[idx];
4605 band = radio_type_to_band(
4606 pchan_band->bandcfg.chanBand);
4607 if (!bss_new_entry->channel)
4608 bss_new_entry->channel =
4609 pchan_band->chan_number;
4610 }
4611 /*
4612 * Save the band designation for this entry
4613 * for use in join
4614 */
4615 bss_new_entry->bss_band = band;
4616 bss_new_entry->age_in_secs = pmadapter->age_in_secs;
4617 cfp = wlan_find_cfp_by_band_and_channel(
4618 pmadapter, bss_new_entry->bss_band,
4619 (t_u16)bss_new_entry->channel);
4620 if (cfp)
4621 bss_new_entry->freq = cfp->freq;
4622 else
4623 bss_new_entry->freq = 0;
4624
4625 /* Skip entry if on blacklisted channel */
4626 if (cfp && cfp->dynamic.blacklist) {
4627 PRINTM(MINFO,
4628 "SCAN_RESP: dropping entry on blacklist channel.\n");
4629 continue;
4630 }
4631
4632 /*
4633 * Search the scan table for the same bssid
4634 */
4635 for (bss_idx = 0; bss_idx < num_in_table; bss_idx++) {
4636 if (!memcmp(pmadapter,
4637 bss_new_entry->mac_address,
4638 pmadapter->pscan_table[bss_idx]
4639 .mac_address,
4640 sizeof(bss_new_entry->mac_address))) {
4641 /*
4642 * If the SSID matches as well, it is a
4643 * duplicate of this entry. Keep the
4644 * bss_idx set to this entry so we
4645 * replace the old contents in the table
4646 */
4647 if ((bss_new_entry->ssid.ssid_len ==
4648 pmadapter->pscan_table[bss_idx]
4649 .ssid.ssid_len) &&
4650 (!memcmp(
4651 pmadapter,
4652 bss_new_entry->ssid.ssid,
4653 pmadapter
4654 ->pscan_table[bss_idx]
4655 .ssid.ssid,
4656 bss_new_entry->ssid
4657 .ssid_len))) {
4658 PRINTM(MINFO,
4659 "SCAN_RESP: Duplicate of index: %d\n",
4660 bss_idx);
4661
4662 break;
4663 }
4664 /*
4665 * If the SSID is NULL for same BSSID
4666 * keep the bss_idx set to this entry
4667 * so we replace the old contents in
4668 * the table
4669 */
4670 if (!memcmp(pmadapter,
4671 pmadapter
4672 ->pscan_table[bss_idx]
4673 .ssid.ssid,
4674 null_ssid,
4675 pmadapter
4676 ->pscan_table[bss_idx]
4677 .ssid.ssid_len)) {
4678 PRINTM(MINFO,
4679 "SCAN_RESP: Duplicate of index: %d\n",
4680 bss_idx);
4681 break;
4682 }
4683 }
4684 }
4685 /*
4686 * If the bss_idx is equal to the number of entries
4687 * in the table, the new entry was not a duplicate;
4688 * append it to the scan table
4689 */
4690 if (bss_idx == num_in_table) {
4691 /*
4692 * Range check the bss_idx, keep it limited
4693 * to the last entry
4694 */
4695 if (bss_idx == MRVDRV_MAX_BSSID_LIST)
4696 bss_idx--;
4697 else
4698 num_in_table++;
4699 } else {
4700 if ((bss_new_entry->channel !=
4701 pmadapter->pscan_table[bss_idx].channel) &&
4702 (bss_new_entry->rssi >
4703 pmadapter->pscan_table[bss_idx].rssi)) {
4704 PRINTM(MCMND,
4705 "skip update the duplicate entry with low rssi\n");
4706 continue;
4707 }
4708 }
4709 /*
4710 * Save the beacon/probe response returned for later
4711 * application retrieval. Duplicate beacon/probe
4712 * responses are updated if possible
4713 */
4714 wlan_ret_802_11_scan_store_beacon(
4715 pmpriv, bss_idx, num_in_table, bss_new_entry);
4716 if (bss_new_entry->pbeacon_buf == MNULL) {
4717 PRINTM(MCMND,
4718 "No space for beacon, drop this entry\n");
4719 num_in_table--;
4720 continue;
4721 }
4722 /*
4723 * If the TSF TLV was appended to the scan results, save
4724 * this entry's TSF value in the networkTSF field. The
4725 * networkTSF is the firmware's TSF value at the time
4726 * the beacon or probe response was received.
4727 */
4728 if (ptsf_tlv) {
4729 memcpy_ext(
4730 pmpriv->adapter, &tsf_val,
4731 &ptsf_tlv->tsf_data[idx * TSF_DATA_SIZE],
4732 sizeof(tsf_val), sizeof(tsf_val));
4733 tsf_val = wlan_le64_to_cpu(tsf_val);
4734 memcpy_ext(pmpriv->adapter,
4735 &bss_new_entry->network_tsf,
4736 &tsf_val,
4737 sizeof(bss_new_entry->network_tsf),
4738 sizeof(bss_new_entry->network_tsf));
4739 }
4740
4741 /* Copy the locally created bss_new_entry to the scan
4742 * table */
4743 memcpy_ext(pmadapter, &pmadapter->pscan_table[bss_idx],
4744 bss_new_entry,
4745 sizeof(pmadapter->pscan_table[bss_idx]),
4746 sizeof(pmadapter->pscan_table[bss_idx]));
4747
4748 } else {
4749 /* Error parsing/interpreting the scan response, skipped
4750 */
4751 PRINTM(MERROR,
4752 "SCAN_RESP: wlan_interpret_bss_desc_with_ie returned error\n");
4753 }
4754 }
4755
4756 PRINTM(MINFO, "SCAN_RESP: Scanned %2d APs, %d valid, %d total\n",
4757 pscan_rsp->number_of_sets,
4758 num_in_table - pmadapter->num_in_scan_table, num_in_table);
4759
4760 /* Update the total number of BSSIDs in the scan table */
4761 pmadapter->num_in_scan_table = num_in_table;
4762 if (is_bgscan_resp)
4763 goto done;
4764 wlan_request_cmd_lock(pmadapter);
4765 if (!util_peek_list(pmadapter->pmoal_handle, &pmadapter->scan_pending_q,
4766 MNULL, MNULL)) {
4767 wlan_release_cmd_lock(pmadapter);
4768 if (pmadapter->pscan_ioctl_req) {
4769 if (((mlan_ds_scan *)pmadapter->pscan_ioctl_req->pbuf)
4770 ->sub_command ==
4771 MLAN_OID_SCAN_SPECIFIC_SSID ||
4772 ((mlan_ds_scan *)pmadapter->pscan_ioctl_req->pbuf)
4773 ->sub_command ==
4774 MLAN_OID_SCAN_USER_CONFIG) {
4775 if (wlan_active_scan_req_for_passive_chan(
4776 pmpriv,
4777 pmadapter->pscan_ioctl_req)) {
4778 goto done;
4779 }
4780 }
4781 }
4782 /*
4783 * Process the resulting scan table:
4784 * - Remove any bad ssids
4785 * - Update our current BSS information from scan data
4786 */
4787 wlan_scan_process_results(pmpriv);
4788
4789 wlan_request_cmd_lock(pmadapter);
4790 pmadapter->scan_processing = MFALSE;
4791 pscan_ioctl_req = pmadapter->pscan_ioctl_req;
4792 pmadapter->pscan_ioctl_req = MNULL;
4793 /* Need to indicate IOCTL complete */
4794 if (pscan_ioctl_req) {
4795 pscan_ioctl_req->status_code = MLAN_ERROR_NO_ERROR;
4796 /* Indicate ioctl complete */
4797 pcb->moal_ioctl_complete(
4798 pmadapter->pmoal_handle,
4799 (pmlan_ioctl_req)pscan_ioctl_req,
4800 MLAN_STATUS_SUCCESS);
4801 }
4802 wlan_release_cmd_lock(pmadapter);
4803 pmadapter->bgscan_reported = MFALSE;
4804 wlan_recv_event(pmpriv, MLAN_EVENT_ID_DRV_SCAN_REPORT, MNULL);
4805 } else {
4806 /* If firmware not ready, do not issue any more scan commands */
4807 if (pmadapter->hw_status != WlanHardwareStatusReady) {
4808 wlan_release_cmd_lock(pmadapter);
4809 status_code = MLAN_ERROR_FW_NOT_READY;
4810 ret = MLAN_STATUS_FAILURE;
4811 goto done;
4812 } else {
4813 /* Get scan command from scan_pending_q and put to
4814 * cmd_pending_q */
4815 pcmd_node = (cmd_ctrl_node *)util_dequeue_list(
4816 pmadapter->pmoal_handle,
4817 &pmadapter->scan_pending_q, MNULL, MNULL);
4818 wlan_insert_cmd_to_pending_q(pmadapter, pcmd_node,
4819 MTRUE);
4820 wlan_release_cmd_lock(pmadapter);
4821 }
4822 }
4823
4824 done:
4825 if (bss_new_entry)
4826 pcb->moal_mfree(pmadapter->pmoal_handle, (t_u8 *)bss_new_entry);
4827 if (ret) {
4828 /* Flush all pending scan commands */
4829 wlan_flush_scan_queue(pmadapter);
4830 wlan_request_cmd_lock(pmadapter);
4831 pmadapter->scan_processing = MFALSE;
4832 pscan_ioctl_req = pmadapter->pscan_ioctl_req;
4833 pmadapter->pscan_ioctl_req = MNULL;
4834 if (pscan_ioctl_req) {
4835 pscan_ioctl_req->status_code = status_code;
4836 /* Indicate ioctl complete */
4837 pcb->moal_ioctl_complete(pmadapter->pmoal_handle,
4838 pscan_ioctl_req,
4839 MLAN_STATUS_FAILURE);
4840 }
4841 wlan_release_cmd_lock(pmadapter);
4842 }
4843 LEAVE();
4844 return ret;
4845 }
4846
4847 /**
4848 * @brief Get ext_scan state from ext_scan_type
4849 *
4850 *
4851 * @param pcmd A pointer to HostCmd_DS_COMMAND structure to be sent to
4852 * firmware with the HostCmd_DS_802_11_SCAN_EXT structure
4853 *
4854 * @return
4855 * SCAN_STATE_EXT_SCAN_ENH/SCAN_STATE_EXT_SCAN_CANCEL/SCAN_STATE_EXT_SCAN_ENH
4856 */
wlan_get_ext_scan_state(HostCmd_DS_COMMAND * pcmd)4857 t_u8 wlan_get_ext_scan_state(HostCmd_DS_COMMAND *pcmd)
4858 {
4859 HostCmd_DS_802_11_SCAN_EXT *pext_scan_cmd = &pcmd->params.ext_scan;
4860 if (pext_scan_cmd->ext_scan_type == EXT_SCAN_ENHANCE)
4861 return SCAN_STATE_EXT_SCAN_ENH;
4862 if (pext_scan_cmd->ext_scan_type == EXT_SCAN_CANCEL)
4863 return SCAN_STATE_EXT_SCAN_CANCEL;
4864 return SCAN_STATE_EXT_SCAN;
4865 }
4866
4867 /**
4868 * @brief Prepare an extended scan command to be sent to the firmware
4869 *
4870 * Use the wlan_scan_cmd_config sent to the command processing module in
4871 * the wlan_prepare_cmd to configure a HostCmd_DS_802_11_SCAN_EXT command
4872 * struct to send to firmware.
4873 *
4874 * @param pmpriv A pointer to mlan_private structure
4875 * @param pcmd A pointer to HostCmd_DS_COMMAND structure to be sent to
4876 * firmware with the HostCmd_DS_802_11_SCAN_EXT structure
4877 * @param pdata_buf Void pointer cast of a wlan_scan_cmd_config struct used
4878 * to set the fields/TLVs for the command sent to firmware
4879 *
4880 * @return MLAN_STATUS_SUCCESS
4881 */
wlan_cmd_802_11_scan_ext(mlan_private * pmpriv,HostCmd_DS_COMMAND * pcmd,t_void * pdata_buf)4882 mlan_status wlan_cmd_802_11_scan_ext(mlan_private *pmpriv,
4883 HostCmd_DS_COMMAND *pcmd,
4884 t_void *pdata_buf)
4885 {
4886 HostCmd_DS_802_11_SCAN_EXT *pext_scan_cmd = &pcmd->params.ext_scan;
4887 wlan_scan_cmd_config *pscan_cfg = MNULL;
4888
4889 ENTER();
4890
4891 pcmd->command = wlan_cpu_to_le16(HostCmd_CMD_802_11_SCAN_EXT);
4892
4893 if (pmpriv->adapter->ext_scan_enh == MTRUE) {
4894 if (pdata_buf) {
4895 if (pmpriv->adapter->ext_scan_type == EXT_SCAN_ENHANCE)
4896 pext_scan_cmd->ext_scan_type = EXT_SCAN_ENHANCE;
4897 else
4898 pext_scan_cmd->ext_scan_type = EXT_SCAN_DEFAULT;
4899 } else {
4900 pcmd->size = wlan_cpu_to_le16((t_u16)(
4901 sizeof(pext_scan_cmd->ext_scan_type) +
4902 (t_u16)(sizeof(pext_scan_cmd->reserved)) +
4903 S_DS_GEN));
4904 pext_scan_cmd->ext_scan_type = EXT_SCAN_CANCEL;
4905 LEAVE();
4906 return MLAN_STATUS_SUCCESS;
4907 }
4908 }
4909 if (!pdata_buf) {
4910 PRINTM(MERROR, "wlan_cmd_802_11_scan_ext: pdata_buf is null\n");
4911 LEAVE();
4912 return MLAN_STATUS_FAILURE;
4913 }
4914 pscan_cfg = (wlan_scan_cmd_config *)pdata_buf;
4915
4916 memcpy_ext(pmpriv->adapter, pext_scan_cmd->tlv_buffer,
4917 pscan_cfg->tlv_buf, pscan_cfg->tlv_buf_len,
4918 pscan_cfg->tlv_buf_len);
4919
4920 /* Size is equal to the sizeof(fixed portions) + the TLV len + header */
4921 pcmd->size = wlan_cpu_to_le16(
4922 (t_u16)(sizeof(pext_scan_cmd->ext_scan_type) +
4923 (t_u16)sizeof(pext_scan_cmd->reserved) +
4924 pscan_cfg->tlv_buf_len + S_DS_GEN));
4925
4926 LEAVE();
4927 return MLAN_STATUS_SUCCESS;
4928 }
4929
4930 /**
4931 * @brief This function handles the command response of extended scan
4932 *
4933 * @param pmpriv A pointer to mlan_private structure
4934 * @param resp A pointer to HostCmd_DS_COMMAND
4935 * @param pioctl_buf A pointer to mlan_ioctl_req structure
4936 *
4937 * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
4938 */
wlan_ret_802_11_scan_ext(mlan_private * pmpriv,HostCmd_DS_COMMAND * resp,t_void * pioctl_buf)4939 mlan_status wlan_ret_802_11_scan_ext(mlan_private *pmpriv,
4940 HostCmd_DS_COMMAND *resp,
4941 t_void *pioctl_buf)
4942 {
4943 HostCmd_DS_802_11_SCAN_EXT *pext_scan_cmd = &(resp->params.ext_scan);
4944 MrvlIEtypesHeader_t *tlv = MNULL;
4945 MrvlIEtypes_ChannelStats_t *tlv_chanstats = MNULL;
4946 t_u16 tlv_buf_left = 0;
4947 t_u16 tlv_type = 0;
4948 t_u16 tlv_len = 0;
4949 t_u32 ext_scan_type;
4950 mlan_callbacks *pcb = (mlan_callbacks *)&pmpriv->adapter->callbacks;
4951 pmlan_ioctl_req pioctl_req = (pmlan_ioctl_req)pioctl_buf;
4952 mlan_adapter *pmadapter = pmpriv->adapter;
4953 ENTER();
4954
4955 PRINTM(MINFO, "EXT scan returns successfully\n");
4956 pmadapter->scan_state |= wlan_get_ext_scan_state(resp);
4957 ext_scan_type = pext_scan_cmd->ext_scan_type;
4958 if (ext_scan_type == EXT_SCAN_CANCEL) {
4959 PRINTM(MCMND, "Cancel scan command completed!\n");
4960 wlan_request_cmd_lock(pmadapter);
4961 pmadapter->scan_processing = MFALSE;
4962 pmadapter->scan_state |= SCAN_STATE_SCAN_COMPLETE;
4963 pmadapter->ext_scan_type = EXT_SCAN_DEFAULT;
4964 wlan_release_cmd_lock(pmadapter);
4965 /* Need to indicate IOCTL complete */
4966 if (pioctl_req != MNULL) {
4967 pioctl_req->status_code = MLAN_STATUS_SUCCESS;
4968 /* Indicate ioctl complete */
4969 pcb->moal_ioctl_complete(pmadapter->pmoal_handle,
4970 (pmlan_ioctl_req)pioctl_req,
4971 MLAN_STATUS_SUCCESS);
4972 }
4973 LEAVE();
4974 return MLAN_STATUS_SUCCESS;
4975 } else if (ext_scan_type == EXT_SCAN_ENHANCE) {
4976 /* Setup the timer after scan command response */
4977 pcb->moal_start_timer(pmpriv->adapter->pmoal_handle,
4978 pmpriv->adapter->pmlan_cmd_timer, MFALSE,
4979 MRVDRV_TIMER_10S * 2);
4980 pmpriv->adapter->cmd_timer_is_set = MTRUE;
4981 LEAVE();
4982 return MLAN_STATUS_SUCCESS;
4983 }
4984 tlv = (MrvlIEtypesHeader_t *)pext_scan_cmd->tlv_buffer;
4985 tlv_buf_left = resp->size -
4986 (sizeof(HostCmd_DS_802_11_SCAN_EXT) - 1 + S_DS_GEN);
4987 while (tlv_buf_left >= sizeof(MrvlIEtypesHeader_t)) {
4988 tlv_type = wlan_le16_to_cpu(tlv->type);
4989 tlv_len = wlan_le16_to_cpu(tlv->len);
4990 if (tlv_buf_left < (tlv_len + sizeof(MrvlIEtypesHeader_t))) {
4991 PRINTM(MERROR, "Error processing scan gap TLV\n");
4992 break;
4993 }
4994 switch (tlv_type) {
4995 case TLV_TYPE_CHANNEL_STATS:
4996 tlv_chanstats = (MrvlIEtypes_ChannelStats_t *)tlv;
4997 wlan_update_chan_statistics(pmpriv, tlv_chanstats);
4998 break;
4999 default:
5000 break;
5001 }
5002 tlv_buf_left -= tlv_len + sizeof(MrvlIEtypesHeader_t);
5003 tlv = (MrvlIEtypesHeader_t *)((t_u8 *)tlv + tlv_len +
5004 sizeof(MrvlIEtypesHeader_t));
5005 }
5006 LEAVE();
5007 return MLAN_STATUS_SUCCESS;
5008 }
5009
5010 /**
5011 * @brief This function add a new entry to scan_table
5012 *
5013 * @param pmpriv A pointer to mlan_private structure
5014 * @param bss_new_entry A pointer to the bss_new_entry
5015 * @param num_in_tbl number of scan entry in scan_table
5016 *
5017 * @return N/A
5018 */
wlan_add_new_entry_to_scan_table(mlan_private * pmpriv,BSSDescriptor_t * bss_new_entry,t_u32 * num_in_tbl)5019 static t_void wlan_add_new_entry_to_scan_table(mlan_private *pmpriv,
5020 BSSDescriptor_t *bss_new_entry,
5021 t_u32 *num_in_tbl)
5022 {
5023 mlan_adapter *pmadapter = pmpriv->adapter;
5024 t_u32 bss_idx;
5025 t_u32 num_in_table = *num_in_tbl;
5026 t_u8 null_ssid[MLAN_MAX_SSID_LENGTH] = {0};
5027
5028 /*
5029 * Search the scan table for the same bssid
5030 */
5031 for (bss_idx = 0; bss_idx < num_in_table; bss_idx++) {
5032 if (!memcmp(pmadapter, bss_new_entry->mac_address,
5033 pmadapter->pscan_table[bss_idx].mac_address,
5034 sizeof(bss_new_entry->mac_address))) {
5035 /*
5036 * If the SSID matches as well, it is a
5037 * duplicate of this entry. Keep the
5038 * bss_idx set to this entry so we
5039 * replace the old contents in the table
5040 */
5041 if ((bss_new_entry->ssid.ssid_len ==
5042 pmadapter->pscan_table[bss_idx].ssid.ssid_len) &&
5043 (!memcmp(pmadapter, bss_new_entry->ssid.ssid,
5044 pmadapter->pscan_table[bss_idx].ssid.ssid,
5045 bss_new_entry->ssid.ssid_len))) {
5046 PRINTM(MINFO,
5047 "EXT_SCAN: Duplicate of index: %d\n",
5048 bss_idx);
5049 break;
5050 }
5051 /*
5052 * If the SSID is NULL for same BSSID
5053 * keep the bss_idx set to this entry
5054 * so we replace the old contents in
5055 * the table
5056 */
5057 if (!memcmp(pmadapter,
5058 pmadapter->pscan_table[bss_idx].ssid.ssid,
5059 null_ssid,
5060 pmadapter->pscan_table[bss_idx]
5061 .ssid.ssid_len)) {
5062 PRINTM(MINFO,
5063 "EXT_SCAN: Duplicate of index: %d\n",
5064 bss_idx);
5065 break;
5066 }
5067 }
5068 }
5069 /* If the bss_idx is equal to the number of entries
5070 * in the table, the new entry was not a duplicate;
5071 * append it to the scan table
5072 */
5073 if (bss_idx == num_in_table) {
5074 /* Range check the bss_idx, keep it limited to the last entry */
5075 if (bss_idx == MRVDRV_MAX_BSSID_LIST)
5076 bss_idx--;
5077 else
5078 num_in_table++;
5079 } else {
5080 if ((bss_new_entry->channel !=
5081 pmadapter->pscan_table[bss_idx].channel) &&
5082 (bss_new_entry->rssi >
5083 pmadapter->pscan_table[bss_idx].rssi)) {
5084 PRINTM(MCMND,
5085 "skip update the duplicate entry with low rssi\n");
5086 return;
5087 }
5088 }
5089 /*
5090 * Save the beacon/probe response returned for later
5091 * application retrieval. Duplicate beacon/probe
5092 * responses are updated if possible
5093 */
5094 wlan_ret_802_11_scan_store_beacon(pmpriv, bss_idx, num_in_table,
5095 bss_new_entry);
5096 if (bss_new_entry->pbeacon_buf == MNULL) {
5097 PRINTM(MCMND, "No space for beacon, drop this entry\n");
5098 num_in_table--;
5099 goto done;
5100 } else {
5101 /* Copy the locally created bss_new_entry to the scan table */
5102 memcpy_ext(pmadapter, &pmadapter->pscan_table[bss_idx],
5103 bss_new_entry,
5104 sizeof(pmadapter->pscan_table[bss_idx]),
5105 sizeof(pmadapter->pscan_table[bss_idx]));
5106 }
5107 done:
5108 *num_in_tbl = num_in_table;
5109 return;
5110 }
5111
5112 /** 8 bytes timestamp, 2 bytest interval, 2 bytes capability */
5113 #define BEACON_FIX_SIZE 12
5114
5115 /**
5116 * @brief This function realloc the beacon buffer and update ssid for new entry
5117 *
5118 * @param pmadpater A pointer to mlan_adapter structure
5119 * @param pbss_entry A pointer to the bss_entry which has multi-bssid IE
5120 * @param pnew_entry A pinter to new entry
5121 * @param pssid A pointer to ssid IE
5122 *
5123 * @return MLAN_STATUS_FAILURE/MLAN_STATUS_SUCCESS
5124 */
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)5125 static mlan_status wlan_update_ssid_in_beacon_buf(
5126 mlan_adapter *pmadapter, BSSDescriptor_t *pbss_entry,
5127 BSSDescriptor_t *pnew_entry, IEEEtypes_Ssid_t *pssid,
5128 IEEEtypes_ExtCap_t *pnew_extcap, IEEEtypes_Generic_t *pnew_rsnx)
5129 {
5130 mlan_callbacks *pcb = (pmlan_callbacks)&pmadapter->callbacks;
5131 t_u8 *pbeacon_buf = MNULL;
5132 t_u32 beacon_buf_size = 0;
5133 t_s8 offset = pnew_entry->ssid.ssid_len - pbss_entry->ssid.ssid_len;
5134 IEEEtypes_ExtCap_t *pextcap;
5135 mlan_status ret = MLAN_STATUS_FAILURE;
5136 t_u32 rsnx_offset = 0;
5137
5138 if (pnew_entry->ssid.ssid_len >= pbss_entry->ssid.ssid_len)
5139 beacon_buf_size =
5140 pbss_entry->beacon_buf_size +
5141 (pnew_entry->ssid.ssid_len - pbss_entry->ssid.ssid_len);
5142 else
5143 beacon_buf_size =
5144 pbss_entry->beacon_buf_size -
5145 (pbss_entry->ssid.ssid_len - pnew_entry->ssid.ssid_len);
5146
5147 rsnx_offset = beacon_buf_size;
5148 if (pnew_rsnx)
5149 beacon_buf_size +=
5150 pnew_rsnx->ieee_hdr.len + sizeof(IEEEtypes_Header_t);
5151
5152 ret = pcb->moal_malloc(pmadapter->pmoal_handle, beacon_buf_size,
5153 MLAN_MEM_DEF, (t_u8 **)&pbeacon_buf);
5154 if (ret != MLAN_STATUS_SUCCESS || !pbeacon_buf) {
5155 PRINTM(MERROR,
5156 "Memory allocation for beacon buf for bss_new_entry\n");
5157 goto done;
5158 }
5159 pnew_entry->beacon_buf_size = beacon_buf_size;
5160 pnew_entry->pbeacon_buf = pbeacon_buf;
5161 /** copy fixed IE */
5162 memcpy_ext(pmadapter, pbeacon_buf, pbss_entry->pbeacon_buf,
5163 BEACON_FIX_SIZE, BEACON_FIX_SIZE);
5164 /** copy new ssid ie */
5165 memcpy_ext(pmadapter, pbeacon_buf + BEACON_FIX_SIZE, (t_u8 *)pssid,
5166 pssid->len + sizeof(IEEEtypes_Header_t),
5167 pssid->len + sizeof(IEEEtypes_Header_t));
5168 /** copy left IE to new beacon buffer */
5169 memcpy_ext(pmadapter,
5170 pbeacon_buf + BEACON_FIX_SIZE + pssid->len +
5171 sizeof(IEEEtypes_Header_t),
5172 pbss_entry->pbeacon_buf + BEACON_FIX_SIZE +
5173 pbss_entry->ssid.ssid_len +
5174 sizeof(IEEEtypes_Header_t),
5175 pbss_entry->beacon_buf_size - BEACON_FIX_SIZE -
5176 (pbss_entry->ssid.ssid_len +
5177 sizeof(IEEEtypes_Header_t)),
5178 pbss_entry->beacon_buf_size - BEACON_FIX_SIZE -
5179 (pbss_entry->ssid.ssid_len +
5180 sizeof(IEEEtypes_Header_t)));
5181
5182 /* adjust the ie pointer */
5183 if (pnew_entry->pwpa_ie)
5184 pnew_entry->wpa_offset += offset;
5185 if (pnew_entry->prsn_ie)
5186 pnew_entry->rsn_offset += offset;
5187 if (pnew_entry->pwapi_ie)
5188 pnew_entry->wapi_offset += offset;
5189
5190 if (pnew_entry->posen_ie)
5191 pnew_entry->osen_offset += offset;
5192 if (pnew_entry->pmd_ie)
5193 pnew_entry->md_offset += offset;
5194 if (pnew_entry->pht_cap)
5195 pnew_entry->ht_cap_offset += offset;
5196 if (pnew_entry->pht_info)
5197 pnew_entry->ht_info_offset += offset;
5198 if (pnew_entry->pbss_co_2040)
5199 pnew_entry->bss_co_2040_offset += offset;
5200 if (pnew_entry->pext_cap) {
5201 pnew_entry->ext_cap_offset += offset;
5202 if (pnew_extcap) {
5203 pextcap = (IEEEtypes_ExtCap_t
5204 *)(pnew_entry->pbeacon_buf +
5205 pnew_entry->ext_cap_offset);
5206 memcpy_ext(pmadapter,
5207 pbeacon_buf + pnew_entry->ext_cap_offset,
5208 (t_u8 *)pnew_extcap,
5209 pnew_extcap->ieee_hdr.len +
5210 sizeof(IEEEtypes_Header_t),
5211 pextcap->ieee_hdr.len +
5212 sizeof(IEEEtypes_Header_t));
5213 }
5214 }
5215 if (pnew_entry->poverlap_bss_scan_param)
5216 pnew_entry->overlap_bss_offset += offset;
5217 if (pnew_entry->pvht_cap)
5218 pnew_entry->vht_cap_offset += offset;
5219 if (pnew_entry->pvht_oprat)
5220 pnew_entry->vht_oprat_offset += offset;
5221 if (pnew_entry->pvht_txpower)
5222 pnew_entry->vht_txpower_offset += offset;
5223 if (pnew_entry->pext_pwer)
5224 pnew_entry->ext_pwer_offset += offset;
5225 if (pnew_entry->pext_bssload)
5226 pnew_entry->ext_bssload_offset += offset;
5227 if (pnew_entry->pquiet_chan)
5228 pnew_entry->quiet_chan_offset += offset;
5229 if (pnew_entry->poper_mode)
5230 pnew_entry->oper_mode_offset += offset;
5231 if (pnew_entry->phe_cap)
5232 pnew_entry->he_cap_offset += offset;
5233 if (pnew_entry->phe_oprat)
5234 pnew_entry->he_oprat_offset += offset;
5235 if (pnew_rsnx)
5236 memcpy_ext(
5237 pmadapter, pbeacon_buf + rsnx_offset, (t_u8 *)pnew_rsnx,
5238 pnew_rsnx->ieee_hdr.len + sizeof(IEEEtypes_Header_t),
5239 pnew_rsnx->ieee_hdr.len + sizeof(IEEEtypes_Header_t));
5240 DBG_HEXDUMP(MCMD_D, "MBSSID beacon buf", pbeacon_buf, beacon_buf_size);
5241 ret = MLAN_STATUS_SUCCESS;
5242 done:
5243 return ret;
5244 }
5245
5246 /**
5247 * @brief This function generate the bssid from bssid_idx
5248 *
5249 * @param pmadpater A pointer to mlan_adapter structure
5250 * @param pbss_entry A pointer to the bss_entry which has multi-bssid IE
5251 * @param pnew_entry A pinter to new entry
5252 * @param bssid_index bssid_index from BSSID_IDX IE
5253 *
5254 * @return N/A
5255 */
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)5256 static void wlan_gen_multi_bssid_by_bssid_index(pmlan_adapter pmadapter,
5257 BSSDescriptor_t *pbss_entry,
5258 BSSDescriptor_t *pnew_entry,
5259 t_u8 bssid_index,
5260 t_u8 max_bssid_indicator)
5261 {
5262 t_u8 mask = 0xff;
5263 t_u8 new_bssid[6];
5264 t_u8 bssid_a;
5265 t_u8 src_bssid[6];
5266
5267 memcpy_ext(pmadapter, (t_u8 *)src_bssid, pbss_entry->mac_address,
5268 sizeof(mlan_802_11_mac_addr), sizeof(src_bssid));
5269 memcpy_ext(pmadapter, (t_u8 *)new_bssid,
5270 (t_u8 *)&pbss_entry->mac_address,
5271 sizeof(mlan_802_11_mac_addr), sizeof(new_bssid));
5272
5273 mask = (mask >> (8 - max_bssid_indicator));
5274 bssid_a = src_bssid[5] & (~mask);
5275 src_bssid[5] = (src_bssid[5] + bssid_index) & mask;
5276 new_bssid[5] = bssid_a | src_bssid[5];
5277
5278 memcpy_ext(pmadapter, (t_u8 *)&pnew_entry->mac_address, new_bssid,
5279 sizeof(new_bssid), sizeof(mlan_802_11_mac_addr));
5280 memcpy_ext(pmadapter, (t_u8 *)&pnew_entry->multi_bssid_ap_addr,
5281 (t_u8 *)&pbss_entry->mac_address,
5282 sizeof(mlan_802_11_mac_addr), sizeof(mlan_802_11_mac_addr));
5283 }
5284
5285 /**
5286 * @brief This function parse the non_trans_bssid_profile
5287 *
5288 * @param pmadapter A pointer to mlan_adapter structure
5289 * @param pbss_entry A pointer to BSSDescriptor_t which has multi-bssid
5290 * IE
5291 * @param pbss_profile A pointer to IEEEtypes_NonTransBSSIDprofile_t
5292 * @param num_in_table A pointer to buffer to save num of entry in scan
5293 * table.
5294 * @param max_bssid_indicator max bssid indicator
5295 *
5296 * @return N/A
5297 */
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)5298 static t_void wlan_parse_non_trans_bssid_profile(
5299 mlan_private *pmpriv, BSSDescriptor_t *pbss_entry,
5300 IEEEtypes_NonTransBSSIDProfile_t *pbss_profile, t_u32 *num_in_table,
5301 t_u8 max_bssid_indicator)
5302 {
5303 mlan_adapter *pmadapter = pmpriv->adapter;
5304 IEEEtypes_Header_t *pheader =
5305 (IEEEtypes_Header_t *)pbss_profile->profile_data;
5306 IEEEtypes_MultiBSSIDIndex_t *pbssid_index = MNULL;
5307 IEEEtypes_Ssid_t *pssid = MNULL;
5308 IEEEtypes_NotxBssCap_t *pcap =
5309 (IEEEtypes_NotxBssCap_t *)pbss_profile->profile_data;
5310 t_u8 *pos = pbss_profile->profile_data;
5311 t_s8 left_len = pbss_profile->ieee_hdr.len;
5312 t_u8 ret = MFALSE;
5313 mlan_callbacks *pcb = (pmlan_callbacks)&pmadapter->callbacks;
5314 BSSDescriptor_t *bss_new_entry = MNULL;
5315 t_u8 *pbeacon_buf = MNULL;
5316 IEEEtypes_ExtCap_t *pextcap = MNULL;
5317 IEEEtypes_Generic_t *prsnx = MNULL;
5318
5319 ENTER();
5320
5321 /* The first element within the Nontransmitted
5322 * BSSID Profile is not the Nontransmitted
5323 * BSSID Capability element.
5324 */
5325 if (pcap->element_id != NONTX_BSSID_CAP || pcap->len != 2) {
5326 PRINTM(MERROR,
5327 "The first element within the Nontransmitted BSSID Profile is not the NontransmittedBSSID Capability element\n");
5328 LEAVE();
5329 return;
5330 }
5331
5332 while (left_len >= 2) {
5333 pheader = (IEEEtypes_Header_t *)pos;
5334 if ((t_s8)(pheader->len + sizeof(IEEEtypes_Header_t)) >
5335 left_len) {
5336 PRINTM(MMSG, "invalid IE length = %d left len %d\n",
5337 pheader->len, left_len);
5338 break;
5339 }
5340 switch (pheader->element_id) {
5341 case MBSSID_INDEX:
5342 pbssid_index = (IEEEtypes_MultiBSSIDIndex_t *)pos;
5343 if (pbssid_index->bssid_index == 0 ||
5344 pbssid_index->bssid_index > 46) {
5345 PRINTM(MERROR,
5346 " No valid Multiple BSSID-Index element\n");
5347 goto done;
5348 }
5349 PRINTM(MCMND, "MBSSID: Find mbssid_index=%d\n",
5350 pbssid_index->bssid_index);
5351 ret = MTRUE;
5352 break;
5353 case EXT_CAPABILITY:
5354 pextcap = (IEEEtypes_ExtCap_t *)pos;
5355 DBG_HEXDUMP(MCMD_D, "MBSSID extcap", pos,
5356 pextcap->ieee_hdr.len +
5357 sizeof(IEEEtypes_Header_t));
5358 break;
5359 case RSNX_IE:
5360 prsnx = (IEEEtypes_Generic_t *)pos;
5361 DBG_HEXDUMP(MCMD_D, "MBSSID RSNX", pos,
5362 prsnx->ieee_hdr.len +
5363 sizeof(IEEEtypes_Header_t));
5364 break;
5365 case SSID:
5366 pssid = (IEEEtypes_Ssid_t *)pos;
5367 PRINTM(MCMND, "MBSSID: Find mbssid ssid=%s\n",
5368 pssid->ssid);
5369 break;
5370 default:
5371 break;
5372 }
5373 left_len -= pheader->len + sizeof(IEEEtypes_Header_t);
5374 pos += pheader->len + sizeof(IEEEtypes_Header_t);
5375 }
5376 if (ret == MTRUE) {
5377 ret = pcb->moal_malloc(pmadapter->pmoal_handle,
5378 sizeof(BSSDescriptor_t), MLAN_MEM_DEF,
5379 (t_u8 **)&bss_new_entry);
5380 if (ret != MLAN_STATUS_SUCCESS || !bss_new_entry) {
5381 PRINTM(MERROR,
5382 "Memory allocation for bss_new_entry failed!\n");
5383 goto done;
5384 }
5385 memcpy_ext(pmadapter, bss_new_entry, pbss_entry,
5386 sizeof(BSSDescriptor_t), sizeof(BSSDescriptor_t));
5387 wlan_gen_multi_bssid_by_bssid_index(pmadapter, pbss_entry,
5388 bss_new_entry,
5389 pbssid_index->bssid_index,
5390 max_bssid_indicator);
5391 if (pssid) {
5392 memset(pmadapter, (t_u8 *)&bss_new_entry->ssid, 0,
5393 sizeof(mlan_802_11_ssid));
5394 bss_new_entry->ssid.ssid_len = pssid->len;
5395 memcpy_ext(pmadapter, bss_new_entry->ssid.ssid,
5396 pssid->ssid, pssid->len,
5397 MLAN_MAX_SSID_LENGTH);
5398 if (MLAN_STATUS_SUCCESS !=
5399 wlan_update_ssid_in_beacon_buf(
5400 pmadapter, pbss_entry, bss_new_entry, pssid,
5401 pextcap, prsnx)) {
5402 PRINTM(MERROR,
5403 "Fail to update MBSSID beacon buf\n");
5404 pcb->moal_mfree(pmadapter->pmoal_handle,
5405 (t_u8 *)bss_new_entry);
5406 goto done;
5407 }
5408 pbeacon_buf = bss_new_entry->pbeacon_buf;
5409 }
5410 memcpy_ext(pmadapter, &bss_new_entry->cap_info, &pcap->cap,
5411 sizeof(IEEEtypes_CapInfo_t),
5412 sizeof(IEEEtypes_CapInfo_t));
5413 bss_new_entry->multi_bssid_ap = MULTI_BSSID_SUB_AP;
5414 wlan_add_new_entry_to_scan_table(pmpriv, bss_new_entry,
5415 num_in_table);
5416 if (pssid && pbeacon_buf)
5417 pcb->moal_mfree(pmadapter->pmoal_handle,
5418 (t_u8 *)pbeacon_buf);
5419 pcb->moal_mfree(pmadapter->pmoal_handle, (t_u8 *)bss_new_entry);
5420 }
5421 done:
5422 LEAVE();
5423 return;
5424 }
5425
5426 /**
5427 * @brief This function parse the multi_bssid IE from pbss_entry
5428 *
5429 * @param pmpriv A pointer to mlan_private structure
5430 * @param pbss_entry A pointer to BSSDescriptor_t which has multi-bssid
5431 * IE
5432 * @param num_in_table A pointer to buffer to save num of entry in scan
5433 * table.
5434 *
5435 * @return number entry in scan table
5436 */
wlan_parse_multi_bssid_ie(mlan_private * pmpriv,BSSDescriptor_t * pbss_entry,IEEEtypes_MultiBSSID_t * pmulti_bssid,t_u32 * num_in_table)5437 static t_void wlan_parse_multi_bssid_ie(mlan_private *pmpriv,
5438 BSSDescriptor_t *pbss_entry,
5439 IEEEtypes_MultiBSSID_t *pmulti_bssid,
5440 t_u32 *num_in_table)
5441 {
5442 t_u32 bytes_left = 0;
5443 t_u8 *pcurrent_ptr = MNULL;
5444 IEEEtypes_NonTransBSSIDProfile_t *pbssid_profile = MNULL;
5445
5446 if (!pmulti_bssid)
5447 return;
5448 bytes_left = pmulti_bssid->ieee_hdr.len - 1;
5449 pcurrent_ptr = pmulti_bssid->sub_elem_data;
5450 while (bytes_left >= 2) {
5451 pbssid_profile =
5452 (IEEEtypes_NonTransBSSIDProfile_t *)pcurrent_ptr;
5453 if (pbssid_profile->ieee_hdr.element_id !=
5454 NONTRANS_BSSID_PROFILE_SUBELEM_ID) {
5455 PRINTM(MERROR, "Invalid multi-bssid IE\n");
5456 break;
5457 }
5458 if (bytes_left < (t_u32)(pbssid_profile->ieee_hdr.len + 2)) {
5459 PRINTM(MERROR, "Invalid multi-bssid IE\n");
5460 break;
5461 }
5462 wlan_parse_non_trans_bssid_profile(
5463 pmpriv, pbss_entry, pbssid_profile, num_in_table,
5464 pmulti_bssid->max_bssid_indicator);
5465 pcurrent_ptr += pbssid_profile->ieee_hdr.len + 2;
5466 bytes_left -= pbssid_profile->ieee_hdr.len + 2;
5467 }
5468 return;
5469 }
5470
5471 /**
5472 * @brief This function search all the mbssid IE in the beacon buffer
5473 *
5474 * @param pmpriv A pointer to mlan_private structure
5475 * @param pbss_entry A pointer to BSSDescriptor_t which has multi-bssid
5476 * IE
5477 * @param num_in_table A pointer to buffer to save num of entry in scan
5478 * table.
5479 *
5480 * @return N/A
5481 */
wlan_parse_multi_bssid_ap(mlan_private * pmpriv,BSSDescriptor_t * pbss_entry,t_u32 * num_in_table)5482 static void wlan_parse_multi_bssid_ap(mlan_private *pmpriv,
5483 BSSDescriptor_t *pbss_entry,
5484 t_u32 *num_in_table)
5485 {
5486 IEEEtypes_ElementId_e element_id;
5487 t_u8 element_len;
5488 t_u16 total_ie_len;
5489 t_u32 bytes_left = pbss_entry->beacon_buf_size - BEACON_FIX_SIZE;
5490 t_u8 *pcurrent_ptr = pbss_entry->pbeacon_buf + BEACON_FIX_SIZE;
5491 IEEEtypes_Ssid_t *pssid = (IEEEtypes_Ssid_t *)pcurrent_ptr;
5492
5493 if (pssid->element_id != SSID) {
5494 PRINTM(MERROR,
5495 "Invalid beacon ie, ssid should be in the first element\n");
5496 return;
5497 }
5498 /* Process variable IE */
5499 while (bytes_left >= 2) {
5500 element_id = (IEEEtypes_ElementId_e)(*((t_u8 *)pcurrent_ptr));
5501 element_len = *((t_u8 *)pcurrent_ptr + 1);
5502 total_ie_len = element_len + sizeof(IEEEtypes_Header_t);
5503
5504 if (bytes_left < total_ie_len) {
5505 PRINTM(MERROR, "InterpretIE: Error in processing IE, "
5506 "bytes left < IE length\n");
5507 bytes_left = 0;
5508 continue;
5509 }
5510 if (element_id == MULTI_BSSID)
5511 wlan_parse_multi_bssid_ie(
5512 pmpriv, pbss_entry,
5513 (IEEEtypes_MultiBSSID_t *)pcurrent_ptr,
5514 num_in_table);
5515 pcurrent_ptr += total_ie_len;
5516 bytes_left -= total_ie_len;
5517 }
5518 return;
5519 }
5520
5521 /**
5522 * @brief This function parse and store the extended scan results
5523 *
5524 * @param pmpriv A pointer to mlan_private structure
5525 * @param number_of_sets Number of BSS
5526 * @param pscan_resp A pointer to scan response buffer
5527 * @param scan_resp_size Size of scan response buffer
5528 *
5529 * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
5530 */
wlan_parse_ext_scan_result(mlan_private * pmpriv,t_u8 number_of_sets,t_u8 * pscan_resp,t_u16 scan_resp_size)5531 static mlan_status wlan_parse_ext_scan_result(mlan_private *pmpriv,
5532 t_u8 number_of_sets,
5533 t_u8 *pscan_resp,
5534 t_u16 scan_resp_size)
5535 {
5536 mlan_status ret = MLAN_STATUS_SUCCESS;
5537 mlan_adapter *pmadapter = pmpriv->adapter;
5538 mlan_callbacks *pcb = MNULL;
5539 BSSDescriptor_t *bss_new_entry = MNULL;
5540 t_u8 *pbss_info;
5541 t_u32 bytes_left;
5542 t_u32 bytes_left_for_tlv;
5543 t_u32 num_in_table;
5544 t_u32 idx;
5545 t_u64 tsf_val;
5546 chan_freq_power_t *cfp;
5547 t_u16 tlv_type, tlv_len;
5548 MrvlIEtypes_Data_t *ptlv = MNULL;
5549 MrvlIEtypes_Bss_Scan_Rsp_t *pscan_rsp_tlv = MNULL;
5550 MrvlIEtypes_Bss_Scan_Info_t *pscan_info_tlv = MNULL;
5551 t_u16 band;
5552 t_u32 age_ts_usec;
5553
5554 ENTER();
5555 pcb = (pmlan_callbacks)&pmadapter->callbacks;
5556
5557 if (number_of_sets > MRVDRV_MAX_BSSID_LIST) {
5558 PRINTM(MERROR,
5559 "EXT_SCAN: Invalid number of AP returned (%d)!!\n",
5560 number_of_sets);
5561 ret = MLAN_STATUS_FAILURE;
5562 goto done;
5563 }
5564
5565 bytes_left = scan_resp_size;
5566 PRINTM(MINFO, "EXT_SCAN: bss_descript_size %d\n", scan_resp_size);
5567 PRINTM(MINFO, "EXT_SCAN: returned %d APs before parsing\n",
5568 number_of_sets);
5569 /* Update the age_in_second */
5570 pmadapter->callbacks.moal_get_system_time(
5571 pmadapter->pmoal_handle, &pmadapter->age_in_secs, &age_ts_usec);
5572
5573 num_in_table = pmadapter->num_in_scan_table;
5574 ptlv = (MrvlIEtypes_Data_t *)pscan_resp;
5575
5576 /*
5577 * Process each scan response returned number_of_sets. Save
5578 * the information in the bss_new_entry and then insert into the
5579 * driver scan table either as an update to an existing entry
5580 * or as an addition at the end of the table
5581 */
5582 ret = pcb->moal_malloc(pmadapter->pmoal_handle, sizeof(BSSDescriptor_t),
5583 MLAN_MEM_DEF, (t_u8 **)&bss_new_entry);
5584
5585 if (ret != MLAN_STATUS_SUCCESS || !bss_new_entry) {
5586 PRINTM(MERROR, "Memory allocation for bss_new_entry failed!\n");
5587 ret = MLAN_STATUS_FAILURE;
5588 goto done;
5589 }
5590
5591 for (idx = 0;
5592 idx < number_of_sets && bytes_left > sizeof(MrvlIEtypesHeader_t);
5593 idx++) {
5594 tlv_type = wlan_le16_to_cpu(ptlv->header.type);
5595 tlv_len = wlan_le16_to_cpu(ptlv->header.len);
5596 if (bytes_left < sizeof(MrvlIEtypesHeader_t) + tlv_len) {
5597 PRINTM(MERROR,
5598 "EXT_SCAN: Error bytes left < TLV length\n");
5599 break;
5600 }
5601 pscan_rsp_tlv = MNULL;
5602 pscan_info_tlv = MNULL;
5603 bytes_left_for_tlv = bytes_left;
5604 /*
5605 * BSS response TLV with beacon or probe response buffer
5606 * at the initial position of each descriptor
5607 */
5608 if (tlv_type == TLV_TYPE_BSS_SCAN_RSP) {
5609 pbss_info = (t_u8 *)ptlv;
5610 pscan_rsp_tlv = (MrvlIEtypes_Bss_Scan_Rsp_t *)ptlv;
5611 ptlv = (MrvlIEtypes_Data_t *)(ptlv->data + tlv_len);
5612 bytes_left_for_tlv -=
5613 (tlv_len + sizeof(MrvlIEtypesHeader_t));
5614 } else
5615 break;
5616
5617 /* Process variable TLV */
5618 while (bytes_left_for_tlv >= sizeof(MrvlIEtypesHeader_t) &&
5619 wlan_le16_to_cpu(ptlv->header.type) !=
5620 TLV_TYPE_BSS_SCAN_RSP) {
5621 tlv_type = wlan_le16_to_cpu(ptlv->header.type);
5622 tlv_len = wlan_le16_to_cpu(ptlv->header.len);
5623 if (bytes_left_for_tlv <
5624 sizeof(MrvlIEtypesHeader_t) + tlv_len) {
5625 PRINTM(MERROR,
5626 "EXT_SCAN: Error in processing TLV, "
5627 "bytes left < TLV length\n");
5628 pscan_rsp_tlv = MNULL;
5629 bytes_left_for_tlv = 0;
5630 continue;
5631 }
5632 switch (tlv_type) {
5633 case TLV_TYPE_BSS_SCAN_INFO:
5634 pscan_info_tlv =
5635 (MrvlIEtypes_Bss_Scan_Info_t *)ptlv;
5636 if (tlv_len !=
5637 sizeof(MrvlIEtypes_Bss_Scan_Info_t) -
5638 sizeof(MrvlIEtypesHeader_t)) {
5639 bytes_left_for_tlv = 0;
5640 continue;
5641 }
5642 break;
5643 default:
5644 break;
5645 }
5646 ptlv = (MrvlIEtypes_Data_t *)(ptlv->data + tlv_len);
5647 bytes_left -= (tlv_len + sizeof(MrvlIEtypesHeader_t));
5648 bytes_left_for_tlv -=
5649 (tlv_len + sizeof(MrvlIEtypesHeader_t));
5650 }
5651 /* No BSS response TLV */
5652 if (pscan_rsp_tlv == MNULL)
5653 break;
5654
5655 /*
5656 * Advance pointer to the beacon buffer length and
5657 * update the bytes count so that the function
5658 * wlan_interpret_bss_desc_with_ie() can handle the
5659 * scan buffer withut any change
5660 */
5661 pbss_info += sizeof(t_u16);
5662 bytes_left -= sizeof(t_u16);
5663
5664 /* Zero out the bss_new_entry we are about to store info in */
5665 memset(pmadapter, bss_new_entry, 0x00, sizeof(BSSDescriptor_t));
5666
5667 /* Process the data fields and IEs returned for this BSS */
5668 if (wlan_interpret_bss_desc_with_ie(
5669 pmadapter, bss_new_entry, &pbss_info, &bytes_left,
5670 MTRUE) == MLAN_STATUS_SUCCESS) {
5671 PRINTM(MINFO, "EXT_SCAN: BSSID = " MACSTR "\n",
5672 MAC2STR(bss_new_entry->mac_address));
5673
5674 band = BAND_G;
5675 /*
5676 * If the BSS info TLV was appended to the scan results,
5677 * save this entry's TSF value in the networkTSF field.
5678 * The networkTSF is the firmware's TSF value at the
5679 * time the beacon or probe response was received.
5680 */
5681 if (pscan_info_tlv) {
5682 /* RSSI is 2 byte long */
5683 bss_new_entry->rssi = -(t_s32)(
5684 wlan_le16_to_cpu(pscan_info_tlv->rssi));
5685 PRINTM(MINFO, "EXT_SCAN: RSSI=%d\n",
5686 bss_new_entry->rssi);
5687 memcpy_ext(pmpriv->adapter, &tsf_val,
5688 &pscan_info_tlv->tsf,
5689 sizeof(tsf_val), sizeof(tsf_val));
5690 tsf_val = wlan_le64_to_cpu(tsf_val);
5691 memcpy_ext(pmpriv->adapter,
5692 &bss_new_entry->network_tsf,
5693 &tsf_val,
5694 sizeof(bss_new_entry->network_tsf),
5695 sizeof(bss_new_entry->network_tsf));
5696 band = radio_type_to_band(
5697 pscan_info_tlv->bandcfg.chanBand);
5698 if (!bss_new_entry->channel)
5699 bss_new_entry->channel =
5700 pscan_info_tlv->channel;
5701 }
5702 /* Save the band designation for this entry for use in
5703 * join */
5704 bss_new_entry->bss_band = band;
5705 bss_new_entry->age_in_secs = pmadapter->age_in_secs;
5706
5707 cfp = wlan_find_cfp_by_band_and_channel(
5708 pmadapter, bss_new_entry->bss_band,
5709 (t_u16)bss_new_entry->channel);
5710 if (cfp)
5711 bss_new_entry->freq = cfp->freq;
5712 else
5713 bss_new_entry->freq = 0;
5714
5715 /* Skip entry if on blacklisted channel */
5716 if (cfp && cfp->dynamic.blacklist) {
5717 PRINTM(MINFO,
5718 "EXT_SCAN: dropping entry on blacklist channel.\n");
5719 continue;
5720 }
5721 if (IS_FW_SUPPORT_MULTIBSSID(pmadapter)) {
5722 if (bss_new_entry->multi_bssid_ap ==
5723 MULTI_BSSID_AP)
5724 wlan_parse_multi_bssid_ap(
5725 pmpriv, bss_new_entry,
5726 &num_in_table);
5727 }
5728 wlan_add_new_entry_to_scan_table(pmpriv, bss_new_entry,
5729 &num_in_table);
5730
5731 } else {
5732 /* Error parsing/interpreting the scan response, skipped
5733 */
5734 PRINTM(MERROR,
5735 "EXT_SCAN: wlan_interpret_bss_desc_with_ie returned error\n");
5736 }
5737 }
5738
5739 PRINTM(MCMND, "EXT_SCAN: Scanned %2d APs, %d valid, %d total\n",
5740 number_of_sets, num_in_table - pmadapter->num_in_scan_table,
5741 num_in_table);
5742
5743 /* Update the total number of BSSIDs in the scan table */
5744 pmadapter->num_in_scan_table = num_in_table;
5745 /* Update the age_in_second */
5746 pmadapter->callbacks.moal_get_system_time(
5747 pmadapter->pmoal_handle, &pmadapter->age_in_secs, &age_ts_usec);
5748
5749 done:
5750 if (bss_new_entry)
5751 pcb->moal_mfree(pmadapter->pmoal_handle, (t_u8 *)bss_new_entry);
5752
5753 LEAVE();
5754 return ret;
5755 }
5756
5757 /**
5758 * @brief This function handles the event extended scan report
5759 *
5760 * @param pmpriv A pointer to mlan_private structure
5761 * @param pmbuf A pointer to mlan_buffer
5762 *
5763 * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
5764 */
wlan_handle_event_ext_scan_report(mlan_private * pmpriv,mlan_buffer * pmbuf)5765 mlan_status wlan_handle_event_ext_scan_report(mlan_private *pmpriv,
5766 mlan_buffer *pmbuf)
5767 {
5768 mlan_adapter *pmadapter = pmpriv->adapter;
5769 mlan_callbacks *pcb = &pmadapter->callbacks;
5770 mlan_ioctl_req *pioctl_req = MNULL;
5771 cmd_ctrl_node *pcmd_node = MNULL;
5772 mlan_status ret = MLAN_STATUS_SUCCESS;
5773
5774 mlan_event_scan_result *pevent_scan =
5775 (pmlan_event_scan_result)(pmbuf->pbuf + pmbuf->data_offset);
5776 t_u8 *ptlv = (pmbuf->pbuf + pmbuf->data_offset +
5777 sizeof(mlan_event_scan_result));
5778 t_u16 tlv_buf_left = wlan_le16_to_cpu(pevent_scan->buf_size);
5779
5780 DBG_HEXDUMP(MCMD_D, "EVENT EXT_SCAN", pmbuf->pbuf + pmbuf->data_offset,
5781 pmbuf->data_len);
5782
5783 if (!pevent_scan->more_event)
5784 pmadapter->scan_state |= SCAN_STATE_EXT_SCAN_RESULT |
5785 SCAN_STATE_LAST_EXT_SCAN_RESULT;
5786 else
5787 pmadapter->scan_state |= SCAN_STATE_EXT_SCAN_RESULT;
5788
5789 wlan_parse_ext_scan_result(pmpriv, pevent_scan->num_of_set, ptlv,
5790 tlv_buf_left);
5791 if (!pevent_scan->more_event &&
5792 (pmadapter->ext_scan_type != EXT_SCAN_ENHANCE)) {
5793 wlan_request_cmd_lock(pmadapter);
5794 if (!util_peek_list(pmadapter->pmoal_handle,
5795 &pmadapter->scan_pending_q, MNULL, MNULL)) {
5796 wlan_release_cmd_lock(pmadapter);
5797 if (pmadapter->pscan_ioctl_req) {
5798 if (((mlan_ds_scan *)
5799 pmadapter->pscan_ioctl_req->pbuf)
5800 ->sub_command ==
5801 MLAN_OID_SCAN_SPECIFIC_SSID ||
5802 ((mlan_ds_scan *)
5803 pmadapter->pscan_ioctl_req->pbuf)
5804 ->sub_command ==
5805 MLAN_OID_SCAN_USER_CONFIG) {
5806 if (wlan_active_scan_req_for_passive_chan(
5807 pmpriv,
5808 pmadapter->pscan_ioctl_req)) {
5809 LEAVE();
5810 return ret;
5811 }
5812 }
5813 }
5814 /*
5815 * Process the resulting scan table:
5816 * - Remove any bad ssids
5817 * - Update our current BSS information from scan data
5818 */
5819 wlan_scan_process_results(pmpriv);
5820 wlan_request_cmd_lock(pmadapter);
5821 pmadapter->scan_processing = MFALSE;
5822 pmadapter->scan_state |= SCAN_STATE_SCAN_COMPLETE;
5823 pioctl_req = pmadapter->pscan_ioctl_req;
5824 pmadapter->pscan_ioctl_req = MNULL;
5825 /* Need to indicate IOCTL complete */
5826 if (pioctl_req != MNULL) {
5827 pioctl_req->status_code = MLAN_ERROR_NO_ERROR;
5828 /* Indicate ioctl complete */
5829 pcb->moal_ioctl_complete(
5830 pmadapter->pmoal_handle,
5831 (pmlan_ioctl_req)pioctl_req,
5832 MLAN_STATUS_SUCCESS);
5833 }
5834 wlan_release_cmd_lock(pmadapter);
5835
5836 pmadapter->bgscan_reported = MFALSE;
5837 wlan_recv_event(pmpriv, MLAN_EVENT_ID_DRV_SCAN_REPORT,
5838 MNULL);
5839 } else {
5840 /* If firmware not ready, do not issue any more scan
5841 * commands */
5842 if (pmadapter->hw_status != WlanHardwareStatusReady) {
5843 wlan_release_cmd_lock(pmadapter);
5844 /* Flush all pending scan commands */
5845 wlan_flush_scan_queue(pmadapter);
5846 wlan_request_cmd_lock(pmadapter);
5847 pmadapter->scan_processing = MFALSE;
5848 pmadapter->scan_state |=
5849 SCAN_STATE_SCAN_COMPLETE;
5850
5851 pioctl_req = pmadapter->pscan_ioctl_req;
5852 pmadapter->pscan_ioctl_req = MNULL;
5853 /* Indicate IOCTL complete */
5854 if (pioctl_req != MNULL) {
5855 pioctl_req->status_code =
5856 MLAN_ERROR_FW_NOT_READY;
5857
5858 /* Indicate ioctl complete */
5859 pcb->moal_ioctl_complete(
5860 pmadapter->pmoal_handle,
5861 (pmlan_ioctl_req)pioctl_req,
5862 MLAN_STATUS_FAILURE);
5863 }
5864 wlan_release_cmd_lock(pmadapter);
5865 } else {
5866 /* Get scan command from scan_pending_q and put
5867 * to cmd_pending_q */
5868 pcmd_node = (cmd_ctrl_node *)util_dequeue_list(
5869 pmadapter->pmoal_handle,
5870 &pmadapter->scan_pending_q, MNULL,
5871 MNULL);
5872 wlan_insert_cmd_to_pending_q(pmadapter,
5873 pcmd_node, MTRUE);
5874 wlan_release_cmd_lock(pmadapter);
5875 }
5876 }
5877 }
5878 LEAVE();
5879 return ret;
5880 }
5881
5882 /**
5883 * @brief This function handles the event extended scan status
5884 *
5885 * @param pmpriv A pointer to mlan_private structure
5886 * @param pmbuf A pointer to mlan_buffer
5887 *
5888 * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
5889 */
wlan_handle_event_ext_scan_status(mlan_private * pmpriv,mlan_buffer * pmbuf)5890 mlan_status wlan_handle_event_ext_scan_status(mlan_private *pmpriv,
5891 mlan_buffer *pmbuf)
5892 {
5893 mlan_adapter *pmadapter = pmpriv->adapter;
5894 mlan_status ret = MLAN_STATUS_SUCCESS;
5895 mlan_event_scan_status *scan_event;
5896 mlan_ioctl_req *pioctl_req;
5897 mlan_callbacks *pcb = (mlan_callbacks *)&pmadapter->callbacks;
5898 t_u16 tlv_buf_left, tlv_len, tlv_type;
5899 MrvlIEtypesHeader_t *tlv;
5900 MrvlIEtypes_ChannelStats_t *tlv_chan_stats;
5901 t_u8 status;
5902 cmd_ctrl_node *pcmd_node = MNULL;
5903
5904 ENTER();
5905
5906 if (pmbuf->data_len < sizeof(mlan_event_scan_status)) {
5907 PRINTM(MERROR, "Wrong ext scan status event data length\n");
5908 ret = MLAN_STATUS_FAILURE;
5909 goto done;
5910 }
5911 pmadapter->scan_state |= SCAN_STATE_EXT_SCAN_STATUS;
5912
5913 scan_event =
5914 (pmlan_event_scan_status)(pmbuf->pbuf + pmbuf->data_offset);
5915 DBG_HEXDUMP(MCMD_D, "EVENT: Ext_Scan_Status", scan_event,
5916 pmbuf->data_len);
5917 status = scan_event->scan_status;
5918 PRINTM(MEVENT, "ext_scan_status: status %d (scan %s), buf_len %d\n",
5919 status, status ? "cancelled" : "success", scan_event->buf_len);
5920
5921 tlv = (MrvlIEtypesHeader_t *)scan_event->event_buf;
5922 tlv_buf_left = pmbuf->data_len - sizeof(mlan_event_scan_status);
5923 while (tlv_buf_left >= sizeof(MrvlIEtypesHeader_t)) {
5924 tlv_type = wlan_le16_to_cpu(tlv->type);
5925 tlv_len = wlan_le16_to_cpu(tlv->len);
5926 if (tlv_buf_left < (tlv_len + sizeof(MrvlIEtypesHeader_t))) {
5927 PRINTM(MERROR,
5928 "Error process scan gap tlv: length %d type 0x%x\n",
5929 tlv_len, tlv_type);
5930 ret = MLAN_STATUS_FAILURE;
5931 goto done;
5932 }
5933 switch (tlv_type) {
5934 case TLV_TYPE_CHANNEL_STATS:
5935 tlv_chan_stats = (MrvlIEtypes_ChannelStats_t *)tlv;
5936 wlan_update_chan_statistics(pmpriv, tlv_chan_stats);
5937 break;
5938 default:
5939 break;
5940 }
5941 tlv_buf_left -= tlv_len + sizeof(MrvlIEtypesHeader_t);
5942 tlv = (MrvlIEtypesHeader_t *)((t_u8 *)tlv + tlv_len +
5943 sizeof(MrvlIEtypesHeader_t));
5944 }
5945
5946 done:
5947 wlan_request_cmd_lock(pmadapter);
5948 if (util_peek_list(pmadapter->pmoal_handle, &pmadapter->scan_pending_q,
5949 MNULL, MNULL)) {
5950 /* If firmware not ready, do not issue any more scan
5951 * commands */
5952 if (pmadapter->hw_status != WlanHardwareStatusReady) {
5953 wlan_release_cmd_lock(pmadapter);
5954 /* Flush all pending scan commands */
5955 wlan_flush_scan_queue(pmadapter);
5956 wlan_request_cmd_lock(pmadapter);
5957 pmadapter->scan_processing = MFALSE;
5958 pmadapter->scan_state |= SCAN_STATE_SCAN_COMPLETE;
5959 pioctl_req = pmadapter->pscan_ioctl_req;
5960 pmadapter->pscan_ioctl_req = MNULL;
5961 /* Indicate IOCTL complete */
5962 if (pioctl_req != MNULL) {
5963 pioctl_req->status_code =
5964 MLAN_ERROR_FW_NOT_READY;
5965
5966 /* Indicate ioctl complete */
5967 pcb->moal_ioctl_complete(
5968 pmadapter->pmoal_handle,
5969 (pmlan_ioctl_req)pioctl_req,
5970 MLAN_STATUS_FAILURE);
5971 }
5972 wlan_release_cmd_lock(pmadapter);
5973 } else {
5974 /* Get scan command from scan_pending_q and put
5975 * to cmd_pending_q */
5976 pcmd_node = (cmd_ctrl_node *)util_dequeue_list(
5977 pmadapter->pmoal_handle,
5978 &pmadapter->scan_pending_q, MNULL, MNULL);
5979 wlan_insert_cmd_to_pending_q(pmadapter, pcmd_node,
5980 MTRUE);
5981 wlan_release_cmd_lock(pmadapter);
5982 }
5983 LEAVE();
5984 return ret;
5985 }
5986 wlan_release_cmd_lock(pmadapter);
5987
5988 /* Now we got response from FW, cancel the command timer */
5989 if (!pmadapter->curr_cmd && pmadapter->cmd_timer_is_set) {
5990 /* Cancel command timeout timer */
5991 pcb->moal_stop_timer(pmadapter->pmoal_handle,
5992 pmadapter->pmlan_cmd_timer);
5993 /* Cancel command timeout timer */
5994 pmadapter->cmd_timer_is_set = MFALSE;
5995 }
5996 if (pmadapter->pscan_ioctl_req) {
5997 if (((mlan_ds_scan *)pmadapter->pscan_ioctl_req->pbuf)
5998 ->sub_command ==
5999 MLAN_OID_SCAN_SPECIFIC_SSID ||
6000 ((mlan_ds_scan *)pmadapter->pscan_ioctl_req->pbuf)
6001 ->sub_command ==
6002 MLAN_OID_SCAN_USER_CONFIG) {
6003 if (wlan_active_scan_req_for_passive_chan(
6004 pmpriv, pmadapter->pscan_ioctl_req)) {
6005 LEAVE();
6006 return ret;
6007 }
6008 }
6009 }
6010 /*
6011 * Process the resulting scan table:
6012 * - Remove any bad ssids
6013 * - Update our current BSS information from scan data
6014 */
6015 wlan_scan_process_results(pmpriv);
6016 /** Complete scan ioctl */
6017 wlan_request_cmd_lock(pmadapter);
6018 pmadapter->scan_processing = MFALSE;
6019 pmadapter->scan_state |= SCAN_STATE_SCAN_COMPLETE;
6020 pioctl_req = pmadapter->pscan_ioctl_req;
6021 pmadapter->pscan_ioctl_req = MNULL;
6022 /* Need to indicate IOCTL complete */
6023 if (pioctl_req != MNULL) {
6024 pioctl_req->status_code = MLAN_ERROR_NO_ERROR;
6025 /* Indicate ioctl complete */
6026 pcb->moal_ioctl_complete(pmadapter->pmoal_handle, pioctl_req,
6027 MLAN_STATUS_SUCCESS);
6028 }
6029 wlan_release_cmd_lock(pmadapter);
6030 wlan_move_cmd_to_cmd_pending_q(pmadapter);
6031 pmadapter->bgscan_reported = MFALSE;
6032 wlan_recv_event(pmpriv, MLAN_EVENT_ID_DRV_SCAN_REPORT, MNULL);
6033 LEAVE();
6034 return ret;
6035 }
6036
6037 /**
6038 * @brief This function prepares command of bg_scan_query.
6039 *
6040 * @param pmpriv A pointer to mlan_private structure
6041 * @param pcmd A pointer to HostCmd_DS_COMMAND structure
6042 * @param pdata_buf Void pointer cast of a wlan_scan_cmd_config struct used
6043 * to set the fields/TLVs for the command sent to firmware
6044 *
6045 * @return MLAN_STATUS_SUCCESS
6046 */
wlan_cmd_802_11_bg_scan_query(mlan_private * pmpriv,HostCmd_DS_COMMAND * pcmd,t_void * pdata_buf)6047 mlan_status wlan_cmd_802_11_bg_scan_query(mlan_private *pmpriv,
6048 HostCmd_DS_COMMAND *pcmd,
6049 t_void *pdata_buf)
6050 {
6051 HostCmd_DS_802_11_BG_SCAN_QUERY *bg_query = &pcmd->params.bg_scan_query;
6052
6053 ENTER();
6054
6055 pcmd->command = wlan_cpu_to_le16(HostCmd_CMD_802_11_BG_SCAN_QUERY);
6056 pcmd->size = wlan_cpu_to_le16(sizeof(HostCmd_DS_802_11_BG_SCAN_QUERY) +
6057 S_DS_GEN);
6058
6059 bg_query->flush = MTRUE;
6060
6061 LEAVE();
6062 return MLAN_STATUS_SUCCESS;
6063 }
6064
6065 /**
6066 * @brief Create a channel list for the driver to scan based on region info
6067 *
6068 * Use the driver region/band information to construct a comprehensive list
6069 * of channels to scan. This routine is used for any scan that is not
6070 * provided a specific channel list to scan.
6071 *
6072 * @param pmpriv A pointer to mlan_private structure
6073 * @param pbg_scan_in pointer to scan configuration parameters
6074 * @param tlv_chan_list A pointer to structure
6075 * MrvlIEtypes_ChanListParamSet_t
6076 *
6077 * @return channel number
6078 */
6079 static t_u8
wlan_bgscan_create_channel_list(mlan_private * pmpriv,const wlan_bgscan_cfg * pbg_scan_in,MrvlIEtypes_ChanListParamSet_t * tlv_chan_list)6080 wlan_bgscan_create_channel_list(mlan_private *pmpriv,
6081 const wlan_bgscan_cfg *pbg_scan_in,
6082 MrvlIEtypes_ChanListParamSet_t *tlv_chan_list)
6083 {
6084 mlan_adapter *pmadapter = pmpriv->adapter;
6085 region_chan_t *pscan_region;
6086 chan_freq_power_t *cfp;
6087 t_u32 region_idx;
6088 t_u32 chan_idx = 0;
6089 t_u32 next_chan;
6090 t_u8 scan_type;
6091 t_u8 radio_type;
6092 t_u16 band;
6093
6094 ENTER();
6095
6096 for (region_idx = 0; region_idx < NELEMENTS(pmadapter->region_channel);
6097 region_idx++) {
6098 if (wlan_11d_is_enabled(pmpriv) &&
6099 pmpriv->media_connected != MTRUE) {
6100 /* Scan all the supported chan for the first scan */
6101 if (!pmadapter->universal_channel[region_idx].valid)
6102 continue;
6103 pscan_region =
6104 &pmadapter->universal_channel[region_idx];
6105 } else {
6106 if (!pmadapter->region_channel[region_idx].valid)
6107 continue;
6108 pscan_region = &pmadapter->region_channel[region_idx];
6109 }
6110
6111 if (pbg_scan_in && !pbg_scan_in->chan_list[0].chan_number &&
6112 pbg_scan_in->chan_list[0].radio_type & BAND_SPECIFIED) {
6113 radio_type = pbg_scan_in->chan_list[0].radio_type &
6114 ~BAND_SPECIFIED;
6115 if (!radio_type && (pscan_region->band != BAND_B) &&
6116 (pscan_region->band != BAND_G))
6117 continue;
6118 if (radio_type && (pscan_region->band != BAND_A))
6119 continue;
6120 }
6121 if ((pbg_scan_in &&
6122 (pbg_scan_in->bss_type == MLAN_SCAN_MODE_IBSS)) ||
6123 pmpriv->bss_mode == MLAN_BSS_MODE_IBSS)
6124 band = pmadapter->adhoc_start_band;
6125 else
6126 band = pmpriv->config_bands;
6127 if (!wlan_is_band_compatible(band, pscan_region->band))
6128 continue;
6129 for (next_chan = 0; next_chan < pscan_region->num_cfp;
6130 next_chan++, chan_idx++) {
6131 if (chan_idx >= WLAN_BG_SCAN_CHAN_MAX)
6132 break;
6133 /*
6134 * Set the default scan type to ACTIVE SCAN type, will
6135 * later be changed to passive on a per channel basis
6136 * if restricted by regulatory requirements (11d or 11h)
6137 */
6138 scan_type = MLAN_SCAN_TYPE_ACTIVE;
6139 cfp = pscan_region->pcfp + next_chan;
6140
6141 switch (pscan_region->band) {
6142 case BAND_A:
6143 tlv_chan_list->chan_scan_param[chan_idx]
6144 .bandcfg.chanBand = BAND_5GHZ;
6145 /* Passive scan on DFS channels */
6146 if (wlan_11h_radar_detect_required(
6147 pmpriv, (t_u8)cfp->channel))
6148 scan_type = MLAN_SCAN_TYPE_PASSIVE;
6149 break;
6150 case BAND_B:
6151 case BAND_G:
6152 if (wlan_bg_scan_type_is_passive(
6153 pmpriv, (t_u8)cfp->channel))
6154 scan_type = MLAN_SCAN_TYPE_PASSIVE;
6155 tlv_chan_list->chan_scan_param[chan_idx]
6156 .bandcfg.chanBand = BAND_2GHZ;
6157 break;
6158 default:
6159 tlv_chan_list->chan_scan_param[chan_idx]
6160 .bandcfg.chanBand = BAND_2GHZ;
6161 break;
6162 }
6163
6164 if (pbg_scan_in &&
6165 pbg_scan_in->chan_list[0].scan_time) {
6166 tlv_chan_list->chan_scan_param[chan_idx]
6167 .max_scan_time = wlan_cpu_to_le16(
6168 (t_u16)pbg_scan_in->chan_list[0]
6169 .scan_time);
6170 tlv_chan_list->chan_scan_param[chan_idx]
6171 .min_scan_time = wlan_cpu_to_le16(
6172 (t_u16)pbg_scan_in->chan_list[0]
6173 .scan_time);
6174 } else if (scan_type == MLAN_SCAN_TYPE_PASSIVE) {
6175 tlv_chan_list->chan_scan_param[chan_idx]
6176 .max_scan_time = wlan_cpu_to_le16(
6177 pmadapter->passive_scan_time);
6178 tlv_chan_list->chan_scan_param[chan_idx]
6179 .min_scan_time = wlan_cpu_to_le16(
6180 pmadapter->passive_scan_time);
6181 } else {
6182 tlv_chan_list->chan_scan_param[chan_idx]
6183 .max_scan_time = wlan_cpu_to_le16(
6184 pmadapter->specific_scan_time);
6185 tlv_chan_list->chan_scan_param[chan_idx]
6186 .min_scan_time = wlan_cpu_to_le16(
6187 pmadapter->specific_scan_time);
6188 }
6189
6190 if (scan_type == MLAN_SCAN_TYPE_PASSIVE) {
6191 tlv_chan_list->chan_scan_param[chan_idx]
6192 .chan_scan_mode.passive_scan = MTRUE;
6193 } else {
6194 tlv_chan_list->chan_scan_param[chan_idx]
6195 .chan_scan_mode.passive_scan = MFALSE;
6196 }
6197
6198 tlv_chan_list->chan_scan_param[chan_idx].chan_number =
6199 (t_u8)cfp->channel;
6200 }
6201 }
6202
6203 LEAVE();
6204 return chan_idx;
6205 }
6206
6207 /**
6208 * @brief This function prepares command of bg_scan_config
6209 *
6210 * @param pmpriv A pointer to mlan_private structure
6211 * @param pcmd A pointer to HostCmd_DS_COMMAND structure
6212 * @param pdata_buf Void pointer cast of a wlan_scan_cmd_config struct used
6213 * to set the fields/TLVs for the command sent to firmware
6214 *
6215 * @return MLAN_STATUS_SUCCESS
6216 */
wlan_cmd_bgscan_config(mlan_private * pmpriv,HostCmd_DS_COMMAND * pcmd,t_void * pdata_buf)6217 mlan_status wlan_cmd_bgscan_config(mlan_private *pmpriv,
6218 HostCmd_DS_COMMAND *pcmd, t_void *pdata_buf)
6219 {
6220 mlan_adapter *pmadapter = pmpriv->adapter;
6221 HostCmd_DS_802_11_BG_SCAN_CONFIG *bg_scan =
6222 &pcmd->params.bg_scan_config;
6223 wlan_bgscan_cfg *bg_scan_in = (wlan_bgscan_cfg *)pdata_buf;
6224 t_u16 cmd_size = 0;
6225 MrvlIEtypes_NumProbes_t *pnum_probes_tlv = MNULL;
6226 MrvlIEtypes_BeaconLowRssiThreshold_t *rssi_tlv = MNULL;
6227 MrvlIEtypes_BeaconLowSnrThreshold_t *snr_tlv = MNULL;
6228 MrvlIEtypes_WildCardSsIdParamSet_t *pwildcard_ssid_tlv = MNULL;
6229 MrvlIEtypes_ChanListParamSet_t *tlv_chan_list = MNULL;
6230 MrvlIEtypes_StartLater_t *tlv_start_later = MNULL;
6231 MrvlIEtypes_RepeatCount_t *tlv_repeat = MNULL;
6232 MrvlIEtypes_EESParamSet_t *tlv_ees_cfg = MNULL;
6233 MrvlIEtype_EESNetworkCfg_t *tlv_ees_net_cfg = MNULL;
6234 MrvlIEtypes_Cipher_t *tlv_ees_cipher = MNULL;
6235 MrvlIEtypes_SsIdParamSet_t *tlv_ssid = MNULL;
6236 MrvlIETypes_HTCap_t *pht_cap = MNULL;
6237 MrvlIETypes_VHTCap_t *pvht_cap = MNULL;
6238 MrvlIEtypes_Extension_t *phe_cap = MNULL;
6239 t_u16 len = 0;
6240
6241 t_u8 index;
6242 t_u8 *tlv = MNULL;
6243 t_u16 num_probes = 0;
6244 t_u32 ssid_idx;
6245 t_u32 ssid_len = 0;
6246 t_u32 chan_idx;
6247 t_u32 chan_num;
6248 t_u8 radio_type;
6249 t_u16 scan_dur;
6250 t_u8 scan_type;
6251 t_u16 band;
6252 const t_u8 zero_mac[6] = {0, 0, 0, 0, 0, 0};
6253
6254 ENTER();
6255
6256 pcmd->command = wlan_cpu_to_le16(HostCmd_CMD_802_11_BG_SCAN_CONFIG);
6257 bg_scan->action = wlan_cpu_to_le16(bg_scan_in->action);
6258 bg_scan->enable = bg_scan_in->enable;
6259 bg_scan->bss_type = bg_scan_in->bss_type;
6260 cmd_size = sizeof(HostCmd_DS_802_11_BG_SCAN_CONFIG) + S_DS_GEN;
6261 if (bg_scan_in->scan_interval)
6262 bg_scan->scan_interval =
6263 wlan_cpu_to_le32(bg_scan_in->scan_interval);
6264 else
6265 bg_scan->scan_interval =
6266 wlan_cpu_to_le32(DEFAULT_BGSCAN_INTERVAL);
6267 bg_scan->report_condition =
6268 wlan_cpu_to_le32(bg_scan_in->report_condition);
6269
6270 if ((bg_scan_in->action == BG_SCAN_ACT_GET) ||
6271 (bg_scan_in->action == BG_SCAN_ACT_GET_PPS_UAPSD) ||
6272 (!bg_scan->enable))
6273 goto done;
6274
6275 tlv = (t_u8 *)bg_scan + sizeof(HostCmd_DS_802_11_BG_SCAN_CONFIG);
6276 num_probes = (bg_scan_in->num_probes ? bg_scan_in->num_probes :
6277 pmadapter->scan_probes);
6278 if (num_probes) {
6279 pnum_probes_tlv = (MrvlIEtypes_NumProbes_t *)tlv;
6280 pnum_probes_tlv->header.type =
6281 wlan_cpu_to_le16(TLV_TYPE_NUMPROBES);
6282 pnum_probes_tlv->header.len =
6283 wlan_cpu_to_le16(sizeof(pnum_probes_tlv->num_probes));
6284 pnum_probes_tlv->num_probes =
6285 wlan_cpu_to_le16((t_u16)num_probes);
6286 tlv += sizeof(MrvlIEtypes_NumProbes_t);
6287 cmd_size += sizeof(MrvlIEtypes_NumProbes_t);
6288 }
6289 if (bg_scan_in->rssi_threshold) {
6290 rssi_tlv = (MrvlIEtypes_BeaconLowRssiThreshold_t *)tlv;
6291 rssi_tlv->header.type = wlan_cpu_to_le16(TLV_TYPE_RSSI_LOW);
6292 rssi_tlv->header.len = wlan_cpu_to_le16(
6293 sizeof(MrvlIEtypes_BeaconLowRssiThreshold_t) -
6294 sizeof(MrvlIEtypesHeader_t));
6295 rssi_tlv->value = bg_scan_in->rssi_threshold;
6296 rssi_tlv->frequency = 0;
6297 tlv += sizeof(MrvlIEtypes_BeaconLowRssiThreshold_t);
6298 cmd_size += sizeof(MrvlIEtypes_BeaconLowRssiThreshold_t);
6299 }
6300 if (bg_scan_in->snr_threshold) {
6301 snr_tlv = (MrvlIEtypes_BeaconLowSnrThreshold_t *)tlv;
6302 snr_tlv->header.type = wlan_cpu_to_le16(TLV_TYPE_SNR_LOW);
6303 snr_tlv->header.len = wlan_cpu_to_le16(
6304 sizeof(MrvlIEtypes_BeaconLowSnrThreshold_t) -
6305 sizeof(MrvlIEtypesHeader_t));
6306 snr_tlv->value = bg_scan_in->snr_threshold;
6307 snr_tlv->frequency = 0;
6308 tlv += sizeof(MrvlIEtypes_BeaconLowRssiThreshold_t);
6309 cmd_size += sizeof(MrvlIEtypes_BeaconLowRssiThreshold_t);
6310 }
6311 if (bg_scan_in->repeat_count) {
6312 tlv_repeat = (MrvlIEtypes_RepeatCount_t *)tlv;
6313 tlv_repeat->header.type =
6314 wlan_cpu_to_le16(TLV_TYPE_REPEAT_COUNT);
6315 tlv_repeat->header.len =
6316 wlan_cpu_to_le16(sizeof(MrvlIEtypes_RepeatCount_t) -
6317 sizeof(MrvlIEtypesHeader_t));
6318 tlv_repeat->repeat_count =
6319 wlan_cpu_to_le16(bg_scan_in->repeat_count);
6320 tlv += sizeof(MrvlIEtypes_RepeatCount_t);
6321 cmd_size += sizeof(MrvlIEtypes_RepeatCount_t);
6322 }
6323 for (ssid_idx = 0; ((ssid_idx < NELEMENTS(bg_scan_in->ssid_list)) &&
6324 (*bg_scan_in->ssid_list[ssid_idx].ssid ||
6325 bg_scan_in->ssid_list[ssid_idx].max_len));
6326 ssid_idx++) {
6327 ssid_len = wlan_strlen(
6328 (char *)bg_scan_in->ssid_list[ssid_idx].ssid);
6329 pwildcard_ssid_tlv = (MrvlIEtypes_WildCardSsIdParamSet_t *)tlv;
6330 pwildcard_ssid_tlv->header.type =
6331 wlan_cpu_to_le16(TLV_TYPE_WILDCARDSSID);
6332 pwildcard_ssid_tlv->header.len = (t_u16)(
6333 ssid_len + sizeof(pwildcard_ssid_tlv->max_ssid_length));
6334 pwildcard_ssid_tlv->max_ssid_length =
6335 bg_scan_in->ssid_list[ssid_idx].max_len;
6336 memcpy_ext(pmadapter, pwildcard_ssid_tlv->ssid,
6337 bg_scan_in->ssid_list[ssid_idx].ssid, ssid_len,
6338 MLAN_MAX_SSID_LENGTH);
6339 tlv += sizeof(pwildcard_ssid_tlv->header) +
6340 pwildcard_ssid_tlv->header.len;
6341 cmd_size += sizeof(pwildcard_ssid_tlv->header) +
6342 pwildcard_ssid_tlv->header.len;
6343 pwildcard_ssid_tlv->header.len =
6344 wlan_cpu_to_le16(pwildcard_ssid_tlv->header.len);
6345 PRINTM(MINFO, "Scan: ssid_list[%d]: %s, %d\n", ssid_idx,
6346 pwildcard_ssid_tlv->ssid,
6347 pwildcard_ssid_tlv->max_ssid_length);
6348 }
6349 if (bg_scan_in->chan_list[0].chan_number) {
6350 tlv_chan_list = (MrvlIEtypes_ChanListParamSet_t *)tlv;
6351 PRINTM(MINFO, "Scan: Using supplied channel list\n");
6352 chan_num = 0;
6353 for (chan_idx = 0; chan_idx < WLAN_BG_SCAN_CHAN_MAX &&
6354 bg_scan_in->chan_list[chan_idx].chan_number;
6355 chan_idx++) {
6356 radio_type = bg_scan_in->chan_list[chan_idx].radio_type;
6357 if (bg_scan_in->bss_type == MLAN_SCAN_MODE_IBSS ||
6358 pmpriv->bss_mode == MLAN_BSS_MODE_IBSS)
6359 band = pmadapter->adhoc_start_band;
6360 else
6361 band = pmpriv->config_bands;
6362 if (!wlan_is_band_compatible(
6363 band, radio_type_to_band(radio_type)))
6364 continue;
6365 scan_type = bg_scan_in->chan_list[chan_idx].scan_type;
6366 /* Prevent active scanning on a radar controlled channel
6367 */
6368 if (radio_type == BAND_5GHZ) {
6369 if (wlan_11h_radar_detect_required(
6370 pmpriv,
6371 bg_scan_in->chan_list[chan_idx]
6372 .chan_number)) {
6373 scan_type = MLAN_SCAN_TYPE_PASSIVE;
6374 }
6375 }
6376 if (radio_type == BAND_2GHZ) {
6377 if (wlan_bg_scan_type_is_passive(
6378 pmpriv,
6379 bg_scan_in->chan_list[chan_idx]
6380 .chan_number)) {
6381 scan_type = MLAN_SCAN_TYPE_PASSIVE;
6382 }
6383 }
6384 tlv_chan_list->chan_scan_param[chan_num].chan_number =
6385 bg_scan_in->chan_list[chan_idx].chan_number;
6386 tlv_chan_list->chan_scan_param[chan_num]
6387 .bandcfg.chanBand =
6388 bg_scan_in->chan_list[chan_idx].radio_type;
6389
6390 if (scan_type == MLAN_SCAN_TYPE_PASSIVE) {
6391 tlv_chan_list->chan_scan_param[chan_num]
6392 .chan_scan_mode.passive_scan = MTRUE;
6393 } else {
6394 tlv_chan_list->chan_scan_param[chan_num]
6395 .chan_scan_mode.passive_scan = MFALSE;
6396 }
6397 if (bg_scan_in->chan_list[chan_idx].scan_time) {
6398 scan_dur =
6399 (t_u16)bg_scan_in->chan_list[chan_idx]
6400 .scan_time;
6401 } else {
6402 if (scan_type == MLAN_SCAN_TYPE_PASSIVE) {
6403 scan_dur = pmadapter->passive_scan_time;
6404 } else {
6405 scan_dur =
6406 pmadapter->specific_scan_time;
6407 }
6408 }
6409 tlv_chan_list->chan_scan_param[chan_num].min_scan_time =
6410 wlan_cpu_to_le16(scan_dur);
6411 tlv_chan_list->chan_scan_param[chan_num].max_scan_time =
6412 wlan_cpu_to_le16(scan_dur);
6413 chan_num++;
6414 }
6415 tlv_chan_list->header.type =
6416 wlan_cpu_to_le16(TLV_TYPE_CHANLIST);
6417 tlv_chan_list->header.len =
6418 wlan_cpu_to_le16(sizeof(ChanScanParamSet_t) * chan_num);
6419 tlv += sizeof(MrvlIEtypesHeader_t) +
6420 sizeof(ChanScanParamSet_t) * chan_num;
6421 cmd_size += sizeof(MrvlIEtypesHeader_t) +
6422 sizeof(ChanScanParamSet_t) * chan_num;
6423 } else {
6424 tlv_chan_list = (MrvlIEtypes_ChanListParamSet_t *)tlv;
6425 chan_num = wlan_bgscan_create_channel_list(pmpriv, bg_scan_in,
6426 tlv_chan_list);
6427 tlv_chan_list->header.type =
6428 wlan_cpu_to_le16(TLV_TYPE_CHANLIST);
6429 tlv_chan_list->header.len =
6430 wlan_cpu_to_le16(sizeof(ChanScanParamSet_t) * chan_num);
6431 tlv += sizeof(MrvlIEtypesHeader_t) +
6432 sizeof(ChanScanParamSet_t) * chan_num;
6433 cmd_size += sizeof(MrvlIEtypesHeader_t) +
6434 sizeof(ChanScanParamSet_t) * chan_num;
6435 }
6436 if (bg_scan_in->chan_per_scan) {
6437 bg_scan->chan_per_scan = bg_scan_in->chan_per_scan;
6438 } else {
6439 if (bg_scan_in->report_condition & BG_SCAN_WAIT_ALL_CHAN_DONE)
6440 bg_scan->chan_per_scan = chan_num;
6441 else
6442 bg_scan->chan_per_scan =
6443 MRVDRV_MAX_CHANNELS_PER_SPECIFIC_SCAN;
6444 }
6445 if (ISSUPP_11NENABLED(pmpriv->adapter->fw_cap_info) &&
6446 (pmpriv->config_bands & BAND_GN ||
6447 pmpriv->config_bands & BAND_AN)) {
6448 pht_cap = (MrvlIETypes_HTCap_t *)tlv;
6449 memset(pmadapter, pht_cap, 0, sizeof(MrvlIETypes_HTCap_t));
6450 pht_cap->header.type = wlan_cpu_to_le16(HT_CAPABILITY);
6451 pht_cap->header.len = sizeof(HTCap_t);
6452 wlan_fill_ht_cap_tlv(pmpriv, pht_cap, pmpriv->config_bands,
6453 MTRUE);
6454 DBG_HEXDUMP(MCMD_D, "BGSCAN: HT_CAPABILITIES IE",
6455 (t_u8 *)pht_cap, sizeof(MrvlIETypes_HTCap_t));
6456 tlv += sizeof(MrvlIETypes_HTCap_t);
6457 cmd_size += sizeof(MrvlIETypes_HTCap_t);
6458 pht_cap->header.len = wlan_cpu_to_le16(pht_cap->header.len);
6459 }
6460 if (ISSUPP_11ACENABLED(pmpriv->adapter->fw_cap_info) &&
6461 (pmpriv->config_bands & BAND_AAC)) {
6462 pvht_cap = (MrvlIETypes_VHTCap_t *)tlv;
6463 memset(pmadapter, pvht_cap, 0, sizeof(MrvlIETypes_VHTCap_t));
6464 pvht_cap->header.type = wlan_cpu_to_le16(VHT_CAPABILITY);
6465 pvht_cap->header.len = sizeof(VHT_capa_t);
6466 wlan_fill_vht_cap_tlv(pmpriv, pvht_cap, pmpriv->config_bands,
6467 MFALSE, MFALSE);
6468 DBG_HEXDUMP(MCMD_D, "BGSCAN: VHT_CAPABILITIES IE",
6469 (t_u8 *)pvht_cap, sizeof(MrvlIETypes_VHTCap_t));
6470 tlv += sizeof(MrvlIETypes_VHTCap_t);
6471 cmd_size += sizeof(MrvlIETypes_VHTCap_t);
6472 pvht_cap->header.len = wlan_cpu_to_le16(pvht_cap->header.len);
6473 }
6474
6475 if (IS_FW_SUPPORT_11AX(pmadapter) &&
6476 ((pmpriv->config_bands & BAND_GAX) ||
6477 (pmpriv->config_bands & BAND_AAX))) {
6478 phe_cap = (MrvlIEtypes_Extension_t *)tlv;
6479 len = wlan_fill_he_cap_tlv(pmpriv, pmpriv->config_bands,
6480 phe_cap, MFALSE);
6481 DBG_HEXDUMP(MCMD_D, "BGSCAN: HE_CAPABILITIES IE",
6482 (t_u8 *)phe_cap, len);
6483 tlv += len;
6484 cmd_size += len;
6485 }
6486 if (wlan_is_ext_capa_support(pmpriv)) {
6487 wlan_add_ext_capa_info_ie(pmpriv, MNULL, &tlv);
6488 cmd_size += sizeof(MrvlIETypes_ExtCap_t);
6489 }
6490 if (pmpriv->adapter->ecsa_enable) {
6491 t_u8 bandwidth = BW_20MHZ;
6492 t_u8 oper_class = 1;
6493 t_u32 usr_dot_11n_dev_cap;
6494 if (pmpriv->media_connected) {
6495 if (pmpriv->config_bands & BAND_A)
6496 usr_dot_11n_dev_cap =
6497 pmpriv->usr_dot_11n_dev_cap_a;
6498 else
6499 usr_dot_11n_dev_cap =
6500 pmpriv->usr_dot_11n_dev_cap_bg;
6501 if (usr_dot_11n_dev_cap & MBIT(17)) {
6502 bandwidth = BW_40MHZ;
6503 if (ISSUPP_11ACENABLED(
6504 pmadapter->fw_cap_info) &&
6505 (pmpriv->config_bands & BAND_AAC))
6506 bandwidth = BW_80MHZ;
6507 }
6508 wlan_get_curr_oper_class(
6509 pmpriv,
6510 pmpriv->curr_bss_params.bss_descriptor.channel,
6511 bandwidth, &oper_class);
6512 }
6513 len = wlan_add_supported_oper_class_ie(pmpriv, &tlv,
6514 oper_class);
6515 cmd_size += len;
6516 }
6517
6518 tlv_start_later = (MrvlIEtypes_StartLater_t *)tlv;
6519 tlv_start_later->header.type =
6520 wlan_cpu_to_le16(TLV_TYPE_STARTBGSCANLATER);
6521 tlv_start_later->header.len = wlan_cpu_to_le16(
6522 sizeof(MrvlIEtypes_StartLater_t) - sizeof(MrvlIEtypesHeader_t));
6523 tlv_start_later->value = wlan_cpu_to_le16(bg_scan_in->start_later);
6524 tlv += sizeof(MrvlIEtypes_StartLater_t);
6525 cmd_size += sizeof(MrvlIEtypes_StartLater_t);
6526
6527 if (bg_scan_in->config_ees) {
6528 /* Fill EES configuration */
6529 tlv_ees_cfg = (MrvlIEtypes_EESParamSet_t *)tlv;
6530 tlv_ees_cfg->header.type = wlan_cpu_to_le16(TLV_TYPE_EES_CFG);
6531 tlv_ees_cfg->header.len =
6532 wlan_cpu_to_le16(sizeof(MrvlIEtypes_EESParamSet_t) -
6533 sizeof(MrvlIEtypesHeader_t));
6534 tlv_ees_cfg->ees_mode = wlan_cpu_to_le16(bg_scan_in->ees_mode);
6535 tlv_ees_cfg->report_cond =
6536 wlan_cpu_to_le16(bg_scan_in->report_cond);
6537 tlv_ees_cfg->high_period =
6538 wlan_cpu_to_le16(bg_scan_in->high_period);
6539 tlv_ees_cfg->high_period_count =
6540 wlan_cpu_to_le16(bg_scan_in->high_period_count);
6541 tlv_ees_cfg->mid_period =
6542 wlan_cpu_to_le16(bg_scan_in->mid_period);
6543 tlv_ees_cfg->mid_period_count =
6544 wlan_cpu_to_le16(bg_scan_in->mid_period_count);
6545 tlv_ees_cfg->low_period =
6546 wlan_cpu_to_le16(bg_scan_in->low_period);
6547 tlv_ees_cfg->low_period_count =
6548 wlan_cpu_to_le16(bg_scan_in->low_period_count);
6549 tlv += sizeof(MrvlIEtypes_EESParamSet_t);
6550 cmd_size += sizeof(MrvlIEtypes_EESParamSet_t);
6551
6552 if (bg_scan_in->network_count) {
6553 /* Fill EES network configuration */
6554 tlv_ees_net_cfg = (MrvlIEtype_EESNetworkCfg_t *)tlv;
6555 tlv_ees_net_cfg->header.type =
6556 wlan_cpu_to_le16(TLV_TYPE_EES_NET_CFG);
6557 tlv_ees_net_cfg->header.len = wlan_cpu_to_le16(
6558 sizeof(MrvlIEtype_EESNetworkCfg_t) -
6559 sizeof(MrvlIEtypesHeader_t));
6560 tlv_ees_net_cfg->network_count =
6561 bg_scan_in->network_count;
6562 tlv_ees_net_cfg->max_conn_count =
6563 bg_scan_in->max_conn_count;
6564 tlv_ees_net_cfg->black_list_exp =
6565 bg_scan_in->black_list_exp;
6566 tlv += sizeof(MrvlIEtype_EESNetworkCfg_t);
6567 cmd_size += sizeof(MrvlIEtype_EESNetworkCfg_t);
6568 for (index = 0; index < bg_scan_in->network_count;
6569 index++) {
6570 if (wlan_strlen((char *)bg_scan_in
6571 ->ees_ssid_cfg[index]
6572 .ssid)) {
6573 /* Fill SSID settings */
6574 tlv_ssid =
6575 (MrvlIEtypes_SsIdParamSet_t *)
6576 tlv;
6577 tlv_ssid->header.type =
6578 wlan_cpu_to_le16(TLV_TYPE_SSID);
6579 tlv_ssid->header.len = wlan_cpu_to_le16(
6580 (t_u16)bg_scan_in
6581 ->ees_ssid_cfg[index]
6582 .max_len);
6583 memcpy_ext(
6584 pmadapter, tlv_ssid->ssid,
6585 bg_scan_in->ees_ssid_cfg[index]
6586 .ssid,
6587 bg_scan_in->ees_ssid_cfg[index]
6588 .max_len,
6589 MLAN_MAX_SSID_LENGTH);
6590 tlv += sizeof(MrvlIEtypesHeader_t) +
6591 tlv_ssid->header.len;
6592 cmd_size +=
6593 sizeof(MrvlIEtypesHeader_t) +
6594 tlv_ssid->header.len;
6595 } else {
6596 /* Fill Wildcard SSID settings */
6597 pwildcard_ssid_tlv =
6598 (MrvlIEtypes_WildCardSsIdParamSet_t
6599 *)tlv;
6600 pwildcard_ssid_tlv->header.type =
6601 wlan_cpu_to_le16(
6602 TLV_TYPE_WILDCARDSSID);
6603 pwildcard_ssid_tlv->header
6604 .len = wlan_cpu_to_le16(
6605 sizeof(MrvlIEtypes_WildCardSsIdParamSet_t) -
6606 sizeof(MrvlIEtypesHeader_t));
6607 pwildcard_ssid_tlv->max_ssid_length =
6608 MLAN_MAX_SSID_LENGTH;
6609 tlv += sizeof(MrvlIEtypesHeader_t) +
6610 sizeof(pwildcard_ssid_tlv
6611 ->max_ssid_length);
6612 cmd_size +=
6613 sizeof(MrvlIEtypesHeader_t) +
6614 sizeof(pwildcard_ssid_tlv
6615 ->max_ssid_length);
6616 }
6617 /* Fill Cipher settings */
6618 tlv_ees_cipher = (MrvlIEtypes_Cipher_t *)tlv;
6619 tlv_ees_cipher->header.type =
6620 wlan_cpu_to_le16(TLV_TYPE_CIPHER);
6621 tlv_ees_cipher->header.len = wlan_cpu_to_le16(
6622 sizeof(MrvlIEtypes_Cipher_t) -
6623 sizeof(MrvlIEtypesHeader_t));
6624 tlv_ees_cipher->pair_cipher =
6625 bg_scan_in->ees_ssid_cfg[index]
6626 .pair_cipher;
6627 tlv_ees_cipher->group_cipher =
6628 bg_scan_in->ees_ssid_cfg[index]
6629 .group_cipher;
6630 tlv += sizeof(MrvlIEtypes_Cipher_t);
6631 cmd_size += sizeof(MrvlIEtypes_Cipher_t);
6632 }
6633 }
6634 }
6635
6636 if (memcmp(pmadapter, bg_scan_in->random_mac, zero_mac,
6637 MLAN_MAC_ADDR_LENGTH)) {
6638 MrvlIEtypes_MacAddr_t *randomMacParam =
6639 (MrvlIEtypes_MacAddr_t *)tlv;
6640 memset(pmadapter, randomMacParam, 0,
6641 sizeof(MrvlIEtypes_MacAddr_t));
6642 randomMacParam->header.type =
6643 wlan_cpu_to_le16(TLV_TYPE_RANDOM_MAC);
6644 randomMacParam->header.len =
6645 wlan_cpu_to_le16(MLAN_MAC_ADDR_LENGTH);
6646 memcpy_ext(pmadapter, randomMacParam->mac,
6647 bg_scan_in->random_mac, MLAN_MAC_ADDR_LENGTH,
6648 MLAN_MAC_ADDR_LENGTH);
6649 tlv += sizeof(MrvlIEtypes_MacAddr_t);
6650 cmd_size += sizeof(MrvlIEtypes_MacAddr_t);
6651 }
6652 done:
6653 pcmd->size = wlan_cpu_to_le16(cmd_size);
6654 LEAVE();
6655 return MLAN_STATUS_SUCCESS;
6656 }
6657
6658 /**
6659 * @brief This function handles the command response of extended scan
6660 *
6661 * @param pmpriv A pointer to mlan_private structure
6662 * @param resp A pointer to HostCmd_DS_COMMAND
6663 * @param pioctl_buf A pointer to mlan_ioctl_req structure
6664 *
6665 * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
6666 */
wlan_ret_bgscan_config(mlan_private * pmpriv,HostCmd_DS_COMMAND * resp,mlan_ioctl_req * pioctl_buf)6667 mlan_status wlan_ret_bgscan_config(mlan_private *pmpriv,
6668 HostCmd_DS_COMMAND *resp,
6669 mlan_ioctl_req *pioctl_buf)
6670 {
6671 mlan_ds_scan *pscan = MNULL;
6672 HostCmd_DS_802_11_BG_SCAN_CONFIG *bg_scan =
6673 &resp->params.bg_scan_config;
6674 wlan_bgscan_cfg *bg_scan_out = MNULL;
6675
6676 ENTER();
6677 if (pioctl_buf) {
6678 pscan = (mlan_ds_scan *)pioctl_buf->pbuf;
6679 bg_scan_out =
6680 (wlan_bgscan_cfg *)pscan->param.user_scan.scan_cfg_buf;
6681 bg_scan_out->action = wlan_le16_to_cpu(bg_scan->action);
6682 if ((bg_scan_out->action == BG_SCAN_ACT_GET) ||
6683 (bg_scan_out->action == BG_SCAN_ACT_GET_PPS_UAPSD)) {
6684 bg_scan_out->enable = bg_scan->enable;
6685 bg_scan_out->bss_type = bg_scan->bss_type;
6686 bg_scan_out->chan_per_scan = bg_scan->chan_per_scan;
6687 bg_scan_out->scan_interval =
6688 wlan_le32_to_cpu(bg_scan->scan_interval);
6689 bg_scan_out->report_condition =
6690 wlan_le32_to_cpu(bg_scan->report_condition);
6691 pioctl_buf->data_read_written =
6692 sizeof(mlan_ds_scan) + MLAN_SUB_COMMAND_SIZE;
6693 }
6694 }
6695 LEAVE();
6696 return MLAN_STATUS_SUCCESS;
6697 }
6698
6699 /**
6700 * @brief This function handles the command response of bgscan_query
6701 * @param pmpriv A pointer to mlan_private structure
6702 * @param resp A pointer to HostCmd_DS_COMMAND
6703 * @param pioctl_buf A pointer to mlan_ioctl_req structure
6704 *
6705 * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
6706 */
wlan_ret_802_11_bgscan_query(mlan_private * pmpriv,HostCmd_DS_COMMAND * resp,mlan_ioctl_req * pioctl_buf)6707 mlan_status wlan_ret_802_11_bgscan_query(mlan_private *pmpriv,
6708 HostCmd_DS_COMMAND *resp,
6709 mlan_ioctl_req *pioctl_buf)
6710 {
6711 mlan_ds_scan *pscan = MNULL;
6712 mlan_adapter *pmadapter = pmpriv->adapter;
6713 t_u8 i;
6714 ENTER();
6715 for (i = 0; i < pmadapter->num_in_chan_stats; i++)
6716 pmadapter->pchan_stats[i].cca_scan_duration = 0;
6717 pmadapter->idx_chan_stats = 0;
6718
6719 wlan_ret_802_11_scan(pmpriv, resp, MNULL);
6720 if (pioctl_buf) {
6721 pscan = (mlan_ds_scan *)pioctl_buf->pbuf;
6722 pscan->param.scan_resp.pscan_table =
6723 (t_u8 *)pmadapter->pscan_table;
6724 pscan->param.scan_resp.num_in_scan_table =
6725 pmadapter->num_in_scan_table;
6726 pscan->param.scan_resp.age_in_secs = pmadapter->age_in_secs;
6727 pscan->param.scan_resp.pchan_stats =
6728 (t_u8 *)pmadapter->pchan_stats;
6729 pscan->param.scan_resp.num_in_chan_stats =
6730 pmadapter->num_in_chan_stats;
6731
6732 pioctl_buf->data_read_written =
6733 sizeof(mlan_scan_resp) + MLAN_SUB_COMMAND_SIZE;
6734 }
6735 LEAVE();
6736 return MLAN_STATUS_SUCCESS;
6737 }
6738
6739 /**
6740 * @brief This function finds ssid in ssid list.
6741 *
6742 * @param pmpriv A pointer to mlan_private structure
6743 * @param ssid SSID to find in the list
6744 * @param bssid BSSID to qualify the SSID selection (if provided)
6745 * @param mode Network mode: Infrastructure or IBSS
6746 *
6747 * @return index in BSSID list or < 0 if error
6748 */
wlan_find_ssid_in_list(mlan_private * pmpriv,mlan_802_11_ssid * ssid,t_u8 * bssid,t_u32 mode)6749 t_s32 wlan_find_ssid_in_list(mlan_private *pmpriv, mlan_802_11_ssid *ssid,
6750 t_u8 *bssid, t_u32 mode)
6751 {
6752 mlan_adapter *pmadapter = pmpriv->adapter;
6753 t_s32 net = -1, j;
6754 t_u8 best_rssi = 0;
6755 t_u32 i;
6756
6757 ENTER();
6758 PRINTM(MINFO, "Num of entries in scan table = %d\n",
6759 pmadapter->num_in_scan_table);
6760
6761 /*
6762 * Loop through the table until the maximum is reached or until a match
6763 * is found based on the bssid field comparison
6764 */
6765 for (i = 0;
6766 i < pmadapter->num_in_scan_table && (!bssid || (bssid && net < 0));
6767 i++) {
6768 if (!wlan_ssid_cmp(pmadapter, &pmadapter->pscan_table[i].ssid,
6769 ssid) &&
6770 (!bssid ||
6771 !memcmp(pmadapter, pmadapter->pscan_table[i].mac_address,
6772 bssid, MLAN_MAC_ADDR_LENGTH))) {
6773 if ((mode == MLAN_BSS_MODE_INFRA) &&
6774 !wlan_is_band_compatible(
6775 pmpriv->config_bands,
6776 pmadapter->pscan_table[i].bss_band))
6777 continue;
6778
6779 switch (mode) {
6780 case MLAN_BSS_MODE_INFRA:
6781 case MLAN_BSS_MODE_IBSS:
6782 j = wlan_is_network_compatible(pmpriv, i, mode);
6783
6784 if (j >= 0) {
6785 if (SCAN_RSSI(pmadapter->pscan_table[i]
6786 .rssi) >
6787 best_rssi) {
6788 best_rssi = SCAN_RSSI(
6789 pmadapter
6790 ->pscan_table[i]
6791 .rssi);
6792 net = i;
6793 }
6794 } else {
6795 if (net == -1)
6796 net = j;
6797 }
6798 break;
6799 case MLAN_BSS_MODE_AUTO:
6800 default:
6801 /*
6802 * Do not check compatibility if the mode
6803 * requested is Auto/Unknown. Allows generic
6804 * find to work without verifying against the
6805 * Adapter security settings
6806 */
6807 if (SCAN_RSSI(pmadapter->pscan_table[i].rssi) >
6808 best_rssi) {
6809 best_rssi = SCAN_RSSI(
6810 pmadapter->pscan_table[i].rssi);
6811 net = i;
6812 }
6813 break;
6814 }
6815 }
6816 }
6817
6818 LEAVE();
6819 return net;
6820 }
6821
6822 /**
6823 * @brief This function finds a specific compatible BSSID in the scan list
6824 *
6825 * @param pmpriv A pointer to mlan_private structure
6826 * @param bssid BSSID to find in the scan list
6827 * @param mode Network mode: Infrastructure or IBSS
6828 *
6829 * @return index in BSSID list or < 0 if error
6830 */
wlan_find_bssid_in_list(mlan_private * pmpriv,t_u8 * bssid,t_u32 mode)6831 t_s32 wlan_find_bssid_in_list(mlan_private *pmpriv, t_u8 *bssid, t_u32 mode)
6832 {
6833 mlan_adapter *pmadapter = pmpriv->adapter;
6834 t_s32 net = -1;
6835 t_u32 i;
6836
6837 ENTER();
6838
6839 if (!bssid) {
6840 LEAVE();
6841 return -1;
6842 }
6843
6844 PRINTM(MINFO, "FindBSSID: Num of BSSIDs = %d\n",
6845 pmadapter->num_in_scan_table);
6846
6847 /*
6848 * Look through the scan table for a compatible match. The ret return
6849 * variable will be equal to the index in the scan table (greater
6850 * than zero) if the network is compatible. The loop will continue
6851 * past a matched bssid that is not compatible in case there is an
6852 * AP with multiple SSIDs assigned to the same BSSID
6853 */
6854 for (i = 0; net < 0 && i < pmadapter->num_in_scan_table; i++) {
6855 if (!memcmp(pmadapter, pmadapter->pscan_table[i].mac_address,
6856 bssid, MLAN_MAC_ADDR_LENGTH)) {
6857 if ((mode == MLAN_BSS_MODE_INFRA) &&
6858 !wlan_is_band_compatible(
6859 pmpriv->config_bands,
6860 pmadapter->pscan_table[i].bss_band))
6861 continue;
6862 switch (mode) {
6863 case MLAN_BSS_MODE_INFRA:
6864 case MLAN_BSS_MODE_IBSS:
6865 net = wlan_is_network_compatible(pmpriv, i,
6866 mode);
6867 break;
6868 default:
6869 net = i;
6870 break;
6871 }
6872 }
6873 }
6874
6875 LEAVE();
6876 return net;
6877 }
6878
6879 /**
6880 * @brief Compare two SSIDs
6881 *
6882 * @param pmadapter A pointer to mlan_adapter structure
6883 * @param ssid1 A pointer to ssid to compare
6884 * @param ssid2 A pointer to ssid to compare
6885 *
6886 * @return 0--ssid is same, otherwise is different
6887 */
wlan_ssid_cmp(pmlan_adapter pmadapter,mlan_802_11_ssid * ssid1,mlan_802_11_ssid * ssid2)6888 t_s32 wlan_ssid_cmp(pmlan_adapter pmadapter, mlan_802_11_ssid *ssid1,
6889 mlan_802_11_ssid *ssid2)
6890 {
6891 ENTER();
6892
6893 if (!ssid1 || !ssid2) {
6894 LEAVE();
6895 return -1;
6896 }
6897
6898 if (ssid1->ssid_len != ssid2->ssid_len) {
6899 LEAVE();
6900 return -1;
6901 }
6902
6903 LEAVE();
6904 return memcmp(pmadapter, ssid1->ssid, ssid2->ssid, ssid1->ssid_len);
6905 }
6906
6907 /**
6908 * @brief Find the AP with specific ssid in the scan list
6909 *
6910 * @param pmpriv A pointer to mlan_private structure
6911 * @param preq_ssid_bssid A pointer to AP's ssid returned
6912 *
6913 * @return MLAN_STATUS_SUCCESS--success, otherwise--fail
6914 */
wlan_find_best_network(mlan_private * pmpriv,mlan_ssid_bssid * preq_ssid_bssid)6915 mlan_status wlan_find_best_network(mlan_private *pmpriv,
6916 mlan_ssid_bssid *preq_ssid_bssid)
6917 {
6918 mlan_adapter *pmadapter = pmpriv->adapter;
6919 mlan_status ret = MLAN_STATUS_SUCCESS;
6920 BSSDescriptor_t *preq_bss;
6921 t_s32 i;
6922
6923 ENTER();
6924
6925 memset(pmadapter, preq_ssid_bssid, 0, sizeof(mlan_ssid_bssid));
6926
6927 i = wlan_find_best_network_in_list(pmpriv);
6928
6929 if (i >= 0) {
6930 preq_bss = &pmadapter->pscan_table[i];
6931 memcpy_ext(pmadapter, &preq_ssid_bssid->ssid, &preq_bss->ssid,
6932 sizeof(mlan_802_11_ssid),
6933 sizeof(preq_ssid_bssid->ssid));
6934 memcpy_ext(pmadapter, (t_u8 *)&preq_ssid_bssid->bssid,
6935 (t_u8 *)&preq_bss->mac_address, MLAN_MAC_ADDR_LENGTH,
6936 MLAN_MAC_ADDR_LENGTH);
6937
6938 /* Make sure we are in the right mode */
6939 if (pmpriv->bss_mode == MLAN_BSS_MODE_AUTO)
6940 pmpriv->bss_mode = preq_bss->bss_mode;
6941 preq_ssid_bssid->channel = (t_u16)preq_bss->channel;
6942 if (preq_bss->pmd_ie &&
6943 wlan_ft_akm_is_used(pmpriv, (t_u8 *)preq_bss->prsn_ie)) {
6944 preq_ssid_bssid->ft_md = preq_bss->pmd_ie->mdid;
6945 preq_ssid_bssid->ft_cap = preq_bss->pmd_ie->ft_cap;
6946 }
6947 preq_ssid_bssid->bss_band = preq_bss->bss_band;
6948 preq_ssid_bssid->idx = i + 1;
6949 }
6950
6951 if (!preq_ssid_bssid->ssid.ssid_len) {
6952 ret = MLAN_STATUS_FAILURE;
6953 goto done;
6954 }
6955
6956 PRINTM(MINFO,
6957 "Best network found = [%s], "
6958 "[" MACSTR "]\n",
6959 preq_ssid_bssid->ssid.ssid, MAC2STR(preq_ssid_bssid->bssid));
6960
6961 done:
6962 LEAVE();
6963 return ret;
6964 }
6965
6966 /**
6967 * @brief Send a scan command for all available channels filtered on a spec
6968 *
6969 * @param pmpriv A pointer to mlan_private structure
6970 * @param pioctl_buf A pointer to MLAN IOCTL Request buffer
6971 * @param preq_ssid A pointer to AP's ssid returned
6972 *
6973 * @return MLAN_STATUS_SUCCESS--success, otherwise--fail
6974 */
wlan_scan_specific_ssid(mlan_private * pmpriv,t_void * pioctl_buf,mlan_802_11_ssid * preq_ssid)6975 mlan_status wlan_scan_specific_ssid(mlan_private *pmpriv, t_void *pioctl_buf,
6976 mlan_802_11_ssid *preq_ssid)
6977 {
6978 mlan_status ret = MLAN_STATUS_SUCCESS;
6979 mlan_callbacks *pcb = (mlan_callbacks *)&pmpriv->adapter->callbacks;
6980 wlan_user_scan_cfg *pscan_cfg;
6981 pmlan_ioctl_req pioctl_req = (mlan_ioctl_req *)pioctl_buf;
6982
6983 ENTER();
6984
6985 if (!preq_ssid) {
6986 if (pioctl_req)
6987 pioctl_req->status_code = MLAN_ERROR_CMD_SCAN_FAIL;
6988 ret = MLAN_STATUS_FAILURE;
6989 goto done;
6990 }
6991 wlan_scan_delete_ssid_table_entry(pmpriv, preq_ssid);
6992
6993 ret = pcb->moal_malloc(pmpriv->adapter->pmoal_handle,
6994 sizeof(wlan_user_scan_cfg),
6995 MLAN_MEM_DEF | MLAN_MEM_FLAG_ATOMIC,
6996 (t_u8 **)&pscan_cfg);
6997
6998 if (ret != MLAN_STATUS_SUCCESS || !pscan_cfg) {
6999 PRINTM(MERROR, "Memory allocation for pscan_cfg failed!\n");
7000 if (pioctl_req)
7001 pioctl_req->status_code = MLAN_ERROR_NO_MEM;
7002 ret = MLAN_STATUS_FAILURE;
7003 goto done;
7004 }
7005
7006 memset(pmpriv->adapter, pscan_cfg, 0x00, sizeof(wlan_user_scan_cfg));
7007
7008 memcpy_ext(pmpriv->adapter, pscan_cfg->ssid_list[0].ssid,
7009 preq_ssid->ssid, preq_ssid->ssid_len, MLAN_MAX_SSID_LENGTH);
7010 pscan_cfg->keep_previous_scan = MFALSE;
7011
7012 ret = wlan_scan_networks(pmpriv, pioctl_buf, pscan_cfg);
7013
7014 if (pscan_cfg)
7015 pcb->moal_mfree(pmpriv->adapter->pmoal_handle,
7016 (t_u8 *)pscan_cfg);
7017
7018 done:
7019 LEAVE();
7020 return ret;
7021 }
7022
7023 /**
7024 * @brief Save a beacon buffer of the current bss descriptor
7025 * Save the current beacon buffer to restore in the following cases that
7026 * makes the bcn_buf not to contain the current ssid's beacon buffer.
7027 * - the current ssid was not found somehow in the last scan.
7028 * - the current ssid was the last entry of the scan table and overloaded.
7029 *
7030 * @param pmpriv A pointer to mlan_private structure
7031 *
7032 * @return N/A
7033 */
wlan_save_curr_bcn(mlan_private * pmpriv)7034 t_void wlan_save_curr_bcn(mlan_private *pmpriv)
7035 {
7036 mlan_adapter *pmadapter = pmpriv->adapter;
7037 mlan_callbacks *pcb = (pmlan_callbacks)&pmadapter->callbacks;
7038 BSSDescriptor_t *pcurr_bss = &pmpriv->curr_bss_params.bss_descriptor;
7039 mlan_status ret = MLAN_STATUS_SUCCESS;
7040
7041 ENTER();
7042 pcb->moal_spin_lock(pmadapter->pmoal_handle, pmpriv->curr_bcn_buf_lock);
7043 /* save the beacon buffer if it is not saved or updated */
7044 if ((pmpriv->pcurr_bcn_buf == MNULL) ||
7045 (pmpriv->curr_bcn_size != pcurr_bss->beacon_buf_size) ||
7046 (memcmp(pmpriv->adapter, pmpriv->pcurr_bcn_buf,
7047 pcurr_bss->pbeacon_buf, pcurr_bss->beacon_buf_size))) {
7048 if (pmpriv->pcurr_bcn_buf) {
7049 pcb->moal_mfree(pmadapter->pmoal_handle,
7050 pmpriv->pcurr_bcn_buf);
7051 pmpriv->pcurr_bcn_buf = MNULL;
7052 }
7053 pmpriv->curr_bcn_size = pcurr_bss->beacon_buf_size;
7054
7055 if (pmpriv->curr_bcn_size) {
7056 ret = pcb->moal_malloc(pmadapter->pmoal_handle,
7057 pcurr_bss->beacon_buf_size,
7058 MLAN_MEM_DEF |
7059 MLAN_MEM_FLAG_ATOMIC,
7060 &pmpriv->pcurr_bcn_buf);
7061
7062 if ((ret == MLAN_STATUS_SUCCESS) &&
7063 pmpriv->pcurr_bcn_buf) {
7064 memcpy_ext(pmpriv->adapter,
7065 pmpriv->pcurr_bcn_buf,
7066 pcurr_bss->pbeacon_buf,
7067 pcurr_bss->beacon_buf_size,
7068 pcurr_bss->beacon_buf_size);
7069 PRINTM(MINFO, "current beacon saved %d\n",
7070 pmpriv->curr_bcn_size);
7071 } else {
7072 PRINTM(MERROR,
7073 "Fail to allocate curr_bcn_buf\n");
7074 }
7075 }
7076 }
7077 wlan_update_curr_bcn(pmpriv);
7078 pcb->moal_spin_unlock(pmadapter->pmoal_handle,
7079 pmpriv->curr_bcn_buf_lock);
7080
7081 LEAVE();
7082 }
7083
7084 /**
7085 * @brief Free a beacon buffer of the current bss descriptor
7086 *
7087 * @param pmpriv A pointer to mlan_private structure
7088 *
7089 * @return N/A
7090 */
wlan_free_curr_bcn(mlan_private * pmpriv)7091 t_void wlan_free_curr_bcn(mlan_private *pmpriv)
7092 {
7093 mlan_adapter *pmadapter = pmpriv->adapter;
7094 mlan_callbacks *pcb = (pmlan_callbacks)&pmadapter->callbacks;
7095
7096 ENTER();
7097 if (pmpriv->pcurr_bcn_buf) {
7098 pcb->moal_mfree(pmadapter->pmoal_handle, pmpriv->pcurr_bcn_buf);
7099 pmpriv->pcurr_bcn_buf = MNULL;
7100 }
7101 LEAVE();
7102 }
7103