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