1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20#include "decl.h"
21#include "ioctl.h"
22#include "util.h"
23#include "fw.h"
24#include "main.h"
25#include "11n.h"
26#include "cfg80211.h"
27
28
29#define MWIFIEX_MAX_CHANNELS_PER_SPECIFIC_SCAN 14
30
31#define MWIFIEX_DEF_CHANNELS_PER_SCAN_CMD 4
32
33
34#define CHAN_TLV_MAX_SIZE (sizeof(struct mwifiex_ie_types_header) \
35 + (MWIFIEX_MAX_CHANNELS_PER_SPECIFIC_SCAN \
36 *sizeof(struct mwifiex_chan_scan_param_set)))
37
38
39#define RATE_TLV_MAX_SIZE (sizeof(struct mwifiex_ie_types_rates_param_set) \
40 + HOSTCMD_SUPPORTED_RATES)
41
42
43
44#define WILDCARD_SSID_TLV_MAX_SIZE \
45 (MWIFIEX_MAX_SSID_LIST_LENGTH * \
46 (sizeof(struct mwifiex_ie_types_wildcard_ssid_params) \
47 + IEEE80211_MAX_SSID_LEN))
48
49
50#define MAX_SCAN_CFG_ALLOC (sizeof(struct mwifiex_scan_cmd_config) \
51 + sizeof(struct mwifiex_ie_types_num_probes) \
52 + sizeof(struct mwifiex_ie_types_htcap) \
53 + CHAN_TLV_MAX_SIZE \
54 + RATE_TLV_MAX_SIZE \
55 + WILDCARD_SSID_TLV_MAX_SIZE)
56
57
58union mwifiex_scan_cmd_config_tlv {
59
60 struct mwifiex_scan_cmd_config config;
61
62 u8 config_alloc_buf[MAX_SCAN_CFG_ALLOC];
63};
64
65enum cipher_suite {
66 CIPHER_SUITE_TKIP,
67 CIPHER_SUITE_CCMP,
68 CIPHER_SUITE_MAX
69};
70static u8 mwifiex_wpa_oui[CIPHER_SUITE_MAX][4] = {
71 { 0x00, 0x50, 0xf2, 0x02 },
72 { 0x00, 0x50, 0xf2, 0x04 },
73};
74static u8 mwifiex_rsn_oui[CIPHER_SUITE_MAX][4] = {
75 { 0x00, 0x0f, 0xac, 0x02 },
76 { 0x00, 0x0f, 0xac, 0x04 },
77};
78
79static void
80_dbg_security_flags(int log_level, const char *func, const char *desc,
81 struct mwifiex_private *priv,
82 struct mwifiex_bssdescriptor *bss_desc)
83{
84 _mwifiex_dbg(priv->adapter, log_level,
85 "info: %s: %s:\twpa_ie=%#x wpa2_ie=%#x WEP=%s WPA=%s WPA2=%s\tEncMode=%#x privacy=%#x\n",
86 func, desc,
87 bss_desc->bcn_wpa_ie ?
88 bss_desc->bcn_wpa_ie->vend_hdr.element_id : 0,
89 bss_desc->bcn_rsn_ie ?
90 bss_desc->bcn_rsn_ie->ieee_hdr.element_id : 0,
91 priv->sec_info.wep_enabled ? "e" : "d",
92 priv->sec_info.wpa_enabled ? "e" : "d",
93 priv->sec_info.wpa2_enabled ? "e" : "d",
94 priv->sec_info.encryption_mode,
95 bss_desc->privacy);
96}
97#define dbg_security_flags(mask, desc, priv, bss_desc) \
98 _dbg_security_flags(MWIFIEX_DBG_##mask, desc, __func__, priv, bss_desc)
99
100static bool
101has_ieee_hdr(struct ieee_types_generic *ie, u8 key)
102{
103 return (ie && ie->ieee_hdr.element_id == key);
104}
105
106static bool
107has_vendor_hdr(struct ieee_types_vendor_specific *ie, u8 key)
108{
109 return (ie && ie->vend_hdr.element_id == key);
110}
111
112
113
114
115
116
117
118static u8
119mwifiex_search_oui_in_ie(struct ie_body *iebody, u8 *oui)
120{
121 u8 count;
122
123 count = iebody->ptk_cnt[0];
124
125
126
127
128
129 while (count) {
130 if (!memcmp(iebody->ptk_body, oui, sizeof(iebody->ptk_body)))
131 return MWIFIEX_OUI_PRESENT;
132
133 --count;
134 if (count)
135 iebody = (struct ie_body *) ((u8 *) iebody +
136 sizeof(iebody->ptk_body));
137 }
138
139 pr_debug("info: %s: OUI is not found in PTK\n", __func__);
140 return MWIFIEX_OUI_NOT_PRESENT;
141}
142
143
144
145
146
147
148
149
150static u8
151mwifiex_is_rsn_oui_present(struct mwifiex_bssdescriptor *bss_desc, u32 cipher)
152{
153 u8 *oui;
154 struct ie_body *iebody;
155 u8 ret = MWIFIEX_OUI_NOT_PRESENT;
156
157 if (has_ieee_hdr(bss_desc->bcn_rsn_ie, WLAN_EID_RSN)) {
158 iebody = (struct ie_body *)
159 (((u8 *) bss_desc->bcn_rsn_ie->data) +
160 RSN_GTK_OUI_OFFSET);
161 oui = &mwifiex_rsn_oui[cipher][0];
162 ret = mwifiex_search_oui_in_ie(iebody, oui);
163 if (ret)
164 return ret;
165 }
166 return ret;
167}
168
169
170
171
172
173
174
175
176static u8
177mwifiex_is_wpa_oui_present(struct mwifiex_bssdescriptor *bss_desc, u32 cipher)
178{
179 u8 *oui;
180 struct ie_body *iebody;
181 u8 ret = MWIFIEX_OUI_NOT_PRESENT;
182
183 if (has_vendor_hdr(bss_desc->bcn_wpa_ie, WLAN_EID_VENDOR_SPECIFIC)) {
184 iebody = (struct ie_body *) bss_desc->bcn_wpa_ie->data;
185 oui = &mwifiex_wpa_oui[cipher][0];
186 ret = mwifiex_search_oui_in_ie(iebody, oui);
187 if (ret)
188 return ret;
189 }
190 return ret;
191}
192
193
194
195
196s32
197mwifiex_ssid_cmp(struct cfg80211_ssid *ssid1, struct cfg80211_ssid *ssid2)
198{
199 if (!ssid1 || !ssid2 || (ssid1->ssid_len != ssid2->ssid_len))
200 return -1;
201 return memcmp(ssid1->ssid, ssid2->ssid, ssid1->ssid_len);
202}
203
204
205
206
207
208static bool
209mwifiex_is_bss_wapi(struct mwifiex_private *priv,
210 struct mwifiex_bssdescriptor *bss_desc)
211{
212 if (priv->sec_info.wapi_enabled &&
213 has_ieee_hdr(bss_desc->bcn_wapi_ie, WLAN_EID_BSS_AC_ACCESS_DELAY))
214 return true;
215 return false;
216}
217
218
219
220
221
222static bool
223mwifiex_is_bss_no_sec(struct mwifiex_private *priv,
224 struct mwifiex_bssdescriptor *bss_desc)
225{
226 if (!priv->sec_info.wep_enabled && !priv->sec_info.wpa_enabled &&
227 !priv->sec_info.wpa2_enabled &&
228 !has_vendor_hdr(bss_desc->bcn_wpa_ie, WLAN_EID_VENDOR_SPECIFIC) &&
229 !has_ieee_hdr(bss_desc->bcn_rsn_ie, WLAN_EID_RSN) &&
230 !priv->sec_info.encryption_mode && !bss_desc->privacy) {
231 return true;
232 }
233 return false;
234}
235
236
237
238
239
240static bool
241mwifiex_is_bss_static_wep(struct mwifiex_private *priv,
242 struct mwifiex_bssdescriptor *bss_desc)
243{
244 if (priv->sec_info.wep_enabled && !priv->sec_info.wpa_enabled &&
245 !priv->sec_info.wpa2_enabled && bss_desc->privacy) {
246 return true;
247 }
248 return false;
249}
250
251
252
253
254
255static bool
256mwifiex_is_bss_wpa(struct mwifiex_private *priv,
257 struct mwifiex_bssdescriptor *bss_desc)
258{
259 if (!priv->sec_info.wep_enabled && priv->sec_info.wpa_enabled &&
260 !priv->sec_info.wpa2_enabled &&
261 has_vendor_hdr(bss_desc->bcn_wpa_ie, WLAN_EID_VENDOR_SPECIFIC)
262
263
264
265
266 ) {
267 dbg_security_flags(INFO, "WPA", priv, bss_desc);
268 return true;
269 }
270 return false;
271}
272
273
274
275
276
277static bool
278mwifiex_is_bss_wpa2(struct mwifiex_private *priv,
279 struct mwifiex_bssdescriptor *bss_desc)
280{
281 if (!priv->sec_info.wep_enabled && !priv->sec_info.wpa_enabled &&
282 priv->sec_info.wpa2_enabled &&
283 has_ieee_hdr(bss_desc->bcn_rsn_ie, WLAN_EID_RSN)) {
284
285
286
287
288 dbg_security_flags(INFO, "WAP2", priv, bss_desc);
289 return true;
290 }
291 return false;
292}
293
294
295
296
297
298static bool
299mwifiex_is_bss_adhoc_aes(struct mwifiex_private *priv,
300 struct mwifiex_bssdescriptor *bss_desc)
301{
302 if (!priv->sec_info.wep_enabled && !priv->sec_info.wpa_enabled &&
303 !priv->sec_info.wpa2_enabled &&
304 !has_vendor_hdr(bss_desc->bcn_wpa_ie, WLAN_EID_VENDOR_SPECIFIC) &&
305 !has_ieee_hdr(bss_desc->bcn_rsn_ie, WLAN_EID_RSN) &&
306 !priv->sec_info.encryption_mode && bss_desc->privacy) {
307 return true;
308 }
309 return false;
310}
311
312
313
314
315
316static bool
317mwifiex_is_bss_dynamic_wep(struct mwifiex_private *priv,
318 struct mwifiex_bssdescriptor *bss_desc)
319{
320 if (!priv->sec_info.wep_enabled && !priv->sec_info.wpa_enabled &&
321 !priv->sec_info.wpa2_enabled &&
322 !has_vendor_hdr(bss_desc->bcn_wpa_ie, WLAN_EID_VENDOR_SPECIFIC) &&
323 !has_ieee_hdr(bss_desc->bcn_rsn_ie, WLAN_EID_RSN) &&
324 priv->sec_info.encryption_mode && bss_desc->privacy) {
325 dbg_security_flags(INFO, "dynamic", priv, bss_desc);
326 return true;
327 }
328 return false;
329}
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349static s32
350mwifiex_is_network_compatible(struct mwifiex_private *priv,
351 struct mwifiex_bssdescriptor *bss_desc, u32 mode)
352{
353 struct mwifiex_adapter *adapter = priv->adapter;
354
355 bss_desc->disable_11n = false;
356
357
358 if (priv->media_connected &&
359 (priv->bss_mode == NL80211_IFTYPE_STATION) &&
360 (bss_desc->bss_mode == NL80211_IFTYPE_STATION))
361 return 0;
362
363 if (priv->wps.session_enable) {
364 mwifiex_dbg(adapter, IOCTL,
365 "info: return success directly in WPS period\n");
366 return 0;
367 }
368
369 if (bss_desc->chan_sw_ie_present) {
370 mwifiex_dbg(adapter, INFO,
371 "Don't connect to AP with WLAN_EID_CHANNEL_SWITCH\n");
372 return -1;
373 }
374
375 if (mwifiex_is_bss_wapi(priv, bss_desc)) {
376 mwifiex_dbg(adapter, INFO,
377 "info: return success for WAPI AP\n");
378 return 0;
379 }
380
381 if (bss_desc->bss_mode == mode) {
382 if (mwifiex_is_bss_no_sec(priv, bss_desc)) {
383
384 return 0;
385 } else if (mwifiex_is_bss_static_wep(priv, bss_desc)) {
386
387 mwifiex_dbg(adapter, INFO,
388 "info: Disable 11n in WEP mode.\n");
389 bss_desc->disable_11n = true;
390 return 0;
391 } else if (mwifiex_is_bss_wpa(priv, bss_desc)) {
392
393 if (((priv->adapter->config_bands & BAND_GN ||
394 priv->adapter->config_bands & BAND_AN) &&
395 bss_desc->bcn_ht_cap) &&
396 !mwifiex_is_wpa_oui_present(bss_desc,
397 CIPHER_SUITE_CCMP)) {
398
399 if (mwifiex_is_wpa_oui_present
400 (bss_desc, CIPHER_SUITE_TKIP)) {
401 mwifiex_dbg(adapter, INFO,
402 "info: Disable 11n if AES\t"
403 "is not supported by AP\n");
404 bss_desc->disable_11n = true;
405 } else {
406 return -1;
407 }
408 }
409 return 0;
410 } else if (mwifiex_is_bss_wpa2(priv, bss_desc)) {
411
412 if (((priv->adapter->config_bands & BAND_GN ||
413 priv->adapter->config_bands & BAND_AN) &&
414 bss_desc->bcn_ht_cap) &&
415 !mwifiex_is_rsn_oui_present(bss_desc,
416 CIPHER_SUITE_CCMP)) {
417
418 if (mwifiex_is_rsn_oui_present
419 (bss_desc, CIPHER_SUITE_TKIP)) {
420 mwifiex_dbg(adapter, INFO,
421 "info: Disable 11n if AES\t"
422 "is not supported by AP\n");
423 bss_desc->disable_11n = true;
424 } else {
425 return -1;
426 }
427 }
428 return 0;
429 } else if (mwifiex_is_bss_adhoc_aes(priv, bss_desc)) {
430
431 return 0;
432 } else if (mwifiex_is_bss_dynamic_wep(priv, bss_desc)) {
433
434 return 0;
435 }
436
437
438 dbg_security_flags(ERROR, "failed", priv, bss_desc);
439 return -1;
440 }
441
442
443 return -1;
444}
445
446
447
448
449
450
451
452
453static int
454mwifiex_scan_create_channel_list(struct mwifiex_private *priv,
455 const struct mwifiex_user_scan_cfg
456 *user_scan_in,
457 struct mwifiex_chan_scan_param_set
458 *scan_chan_list,
459 u8 filtered_scan)
460{
461 enum nl80211_band band;
462 struct ieee80211_supported_band *sband;
463 struct ieee80211_channel *ch;
464 struct mwifiex_adapter *adapter = priv->adapter;
465 int chan_idx = 0, i;
466
467 for (band = 0; (band < NUM_NL80211_BANDS) ; band++) {
468
469 if (!priv->wdev.wiphy->bands[band])
470 continue;
471
472 sband = priv->wdev.wiphy->bands[band];
473
474 for (i = 0; (i < sband->n_channels) ; i++) {
475 ch = &sband->channels[i];
476 if (ch->flags & IEEE80211_CHAN_DISABLED)
477 continue;
478 scan_chan_list[chan_idx].radio_type = band;
479
480 if (user_scan_in &&
481 user_scan_in->chan_list[0].scan_time)
482 scan_chan_list[chan_idx].max_scan_time =
483 cpu_to_le16((u16) user_scan_in->
484 chan_list[0].scan_time);
485 else if ((ch->flags & IEEE80211_CHAN_NO_IR) ||
486 (ch->flags & IEEE80211_CHAN_RADAR))
487 scan_chan_list[chan_idx].max_scan_time =
488 cpu_to_le16(adapter->passive_scan_time);
489 else
490 scan_chan_list[chan_idx].max_scan_time =
491 cpu_to_le16(adapter->active_scan_time);
492
493 if (ch->flags & IEEE80211_CHAN_NO_IR)
494 scan_chan_list[chan_idx].chan_scan_mode_bitmap
495 |= (MWIFIEX_PASSIVE_SCAN |
496 MWIFIEX_HIDDEN_SSID_REPORT);
497 else
498 scan_chan_list[chan_idx].chan_scan_mode_bitmap
499 &= ~MWIFIEX_PASSIVE_SCAN;
500 scan_chan_list[chan_idx].chan_number =
501 (u32) ch->hw_value;
502
503 scan_chan_list[chan_idx].chan_scan_mode_bitmap
504 |= MWIFIEX_DISABLE_CHAN_FILT;
505
506 if (filtered_scan &&
507 !((ch->flags & IEEE80211_CHAN_NO_IR) ||
508 (ch->flags & IEEE80211_CHAN_RADAR)))
509 scan_chan_list[chan_idx].max_scan_time =
510 cpu_to_le16(adapter->specific_scan_time);
511
512 chan_idx++;
513 }
514
515 }
516 return chan_idx;
517}
518
519
520
521
522static int
523mwifiex_bgscan_create_channel_list(struct mwifiex_private *priv,
524 const struct mwifiex_bg_scan_cfg
525 *bgscan_cfg_in,
526 struct mwifiex_chan_scan_param_set
527 *scan_chan_list)
528{
529 enum nl80211_band band;
530 struct ieee80211_supported_band *sband;
531 struct ieee80211_channel *ch;
532 struct mwifiex_adapter *adapter = priv->adapter;
533 int chan_idx = 0, i;
534
535 for (band = 0; (band < NUM_NL80211_BANDS); band++) {
536 if (!priv->wdev.wiphy->bands[band])
537 continue;
538
539 sband = priv->wdev.wiphy->bands[band];
540
541 for (i = 0; (i < sband->n_channels) ; i++) {
542 ch = &sband->channels[i];
543 if (ch->flags & IEEE80211_CHAN_DISABLED)
544 continue;
545 scan_chan_list[chan_idx].radio_type = band;
546
547 if (bgscan_cfg_in->chan_list[0].scan_time)
548 scan_chan_list[chan_idx].max_scan_time =
549 cpu_to_le16((u16)bgscan_cfg_in->
550 chan_list[0].scan_time);
551 else if (ch->flags & IEEE80211_CHAN_NO_IR)
552 scan_chan_list[chan_idx].max_scan_time =
553 cpu_to_le16(adapter->passive_scan_time);
554 else
555 scan_chan_list[chan_idx].max_scan_time =
556 cpu_to_le16(adapter->
557 specific_scan_time);
558
559 if (ch->flags & IEEE80211_CHAN_NO_IR)
560 scan_chan_list[chan_idx].chan_scan_mode_bitmap
561 |= MWIFIEX_PASSIVE_SCAN;
562 else
563 scan_chan_list[chan_idx].chan_scan_mode_bitmap
564 &= ~MWIFIEX_PASSIVE_SCAN;
565
566 scan_chan_list[chan_idx].chan_number =
567 (u32)ch->hw_value;
568 chan_idx++;
569 }
570 }
571 return chan_idx;
572}
573
574
575static int
576mwifiex_append_rate_tlv(struct mwifiex_private *priv,
577 struct mwifiex_scan_cmd_config *scan_cfg_out,
578 u8 radio)
579{
580 struct mwifiex_ie_types_rates_param_set *rates_tlv;
581 u8 rates[MWIFIEX_SUPPORTED_RATES], *tlv_pos;
582 u32 rates_size;
583
584 memset(rates, 0, sizeof(rates));
585
586 tlv_pos = (u8 *)scan_cfg_out->tlv_buf + scan_cfg_out->tlv_buf_len;
587
588 if (priv->scan_request)
589 rates_size = mwifiex_get_rates_from_cfg80211(priv, rates,
590 radio);
591 else
592 rates_size = mwifiex_get_supported_rates(priv, rates);
593
594 mwifiex_dbg(priv->adapter, CMD,
595 "info: SCAN_CMD: Rates size = %d\n",
596 rates_size);
597 rates_tlv = (struct mwifiex_ie_types_rates_param_set *)tlv_pos;
598 rates_tlv->header.type = cpu_to_le16(WLAN_EID_SUPP_RATES);
599 rates_tlv->header.len = cpu_to_le16((u16) rates_size);
600 memcpy(rates_tlv->rates, rates, rates_size);
601 scan_cfg_out->tlv_buf_len += sizeof(rates_tlv->header) + rates_size;
602
603 return rates_size;
604}
605
606
607
608
609
610
611
612
613
614
615static int
616mwifiex_scan_channel_list(struct mwifiex_private *priv,
617 u32 max_chan_per_scan, u8 filtered_scan,
618 struct mwifiex_scan_cmd_config *scan_cfg_out,
619 struct mwifiex_ie_types_chan_list_param_set
620 *chan_tlv_out,
621 struct mwifiex_chan_scan_param_set *scan_chan_list)
622{
623 struct mwifiex_adapter *adapter = priv->adapter;
624 int ret = 0;
625 struct mwifiex_chan_scan_param_set *tmp_chan_list;
626 struct mwifiex_chan_scan_param_set *start_chan;
627 u32 tlv_idx, rates_size, cmd_no;
628 u32 total_scan_time;
629 u32 done_early;
630 u8 radio_type;
631
632 if (!scan_cfg_out || !chan_tlv_out || !scan_chan_list) {
633 mwifiex_dbg(priv->adapter, ERROR,
634 "info: Scan: Null detect: %p, %p, %p\n",
635 scan_cfg_out, chan_tlv_out, scan_chan_list);
636 return -1;
637 }
638
639
640 mwifiex_11h_get_csa_closed_channel(priv);
641
642 chan_tlv_out->header.type = cpu_to_le16(TLV_TYPE_CHANLIST);
643
644
645
646 tmp_chan_list = scan_chan_list;
647
648
649
650
651 while (tmp_chan_list->chan_number) {
652
653 tlv_idx = 0;
654 total_scan_time = 0;
655 radio_type = 0;
656 chan_tlv_out->header.len = 0;
657 start_chan = tmp_chan_list;
658 done_early = false;
659
660
661
662
663
664
665
666
667
668
669 while (tlv_idx < max_chan_per_scan &&
670 tmp_chan_list->chan_number && !done_early) {
671
672 if (tmp_chan_list->chan_number == priv->csa_chan) {
673 tmp_chan_list++;
674 continue;
675 }
676
677 radio_type = tmp_chan_list->radio_type;
678 mwifiex_dbg(priv->adapter, INFO,
679 "info: Scan: Chan(%3d), Radio(%d),\t"
680 "Mode(%d, %d), Dur(%d)\n",
681 tmp_chan_list->chan_number,
682 tmp_chan_list->radio_type,
683 tmp_chan_list->chan_scan_mode_bitmap
684 & MWIFIEX_PASSIVE_SCAN,
685 (tmp_chan_list->chan_scan_mode_bitmap
686 & MWIFIEX_DISABLE_CHAN_FILT) >> 1,
687 le16_to_cpu(tmp_chan_list->max_scan_time));
688
689
690
691 memcpy(chan_tlv_out->chan_scan_param + tlv_idx,
692 tmp_chan_list,
693 sizeof(chan_tlv_out->chan_scan_param));
694
695
696
697 le16_unaligned_add_cpu(&chan_tlv_out->header.len,
698 sizeof(
699 chan_tlv_out->chan_scan_param));
700
701
702
703
704
705
706
707 scan_cfg_out->tlv_buf_len = (u32) ((u8 *) chan_tlv_out -
708 scan_cfg_out->tlv_buf);
709
710
711
712 scan_cfg_out->tlv_buf_len +=
713 (sizeof(chan_tlv_out->header)
714 + le16_to_cpu(chan_tlv_out->header.len));
715
716
717
718 tlv_idx++;
719
720
721 total_scan_time +=
722 le16_to_cpu(tmp_chan_list->max_scan_time);
723
724 done_early = false;
725
726
727
728
729 if (!filtered_scan &&
730 (tmp_chan_list->chan_number == 1 ||
731 tmp_chan_list->chan_number == 6 ||
732 tmp_chan_list->chan_number == 11))
733 done_early = true;
734
735
736
737 tmp_chan_list++;
738
739
740
741
742 if (!filtered_scan &&
743 (tmp_chan_list->chan_number == 1 ||
744 tmp_chan_list->chan_number == 6 ||
745 tmp_chan_list->chan_number == 11))
746 done_early = true;
747 }
748
749
750
751 if (total_scan_time > MWIFIEX_MAX_TOTAL_SCAN_TIME) {
752 mwifiex_dbg(priv->adapter, ERROR,
753 "total scan time %dms\t"
754 "is over limit (%dms), scan skipped\n",
755 total_scan_time,
756 MWIFIEX_MAX_TOTAL_SCAN_TIME);
757 ret = -1;
758 break;
759 }
760
761 rates_size = mwifiex_append_rate_tlv(priv, scan_cfg_out,
762 radio_type);
763
764 priv->adapter->scan_channels = start_chan;
765
766
767
768 if (priv->adapter->ext_scan)
769 cmd_no = HostCmd_CMD_802_11_SCAN_EXT;
770 else
771 cmd_no = HostCmd_CMD_802_11_SCAN;
772
773 ret = mwifiex_send_cmd(priv, cmd_no, HostCmd_ACT_GEN_SET,
774 0, scan_cfg_out, false);
775
776
777
778
779
780 scan_cfg_out->tlv_buf_len -=
781 sizeof(struct mwifiex_ie_types_header) + rates_size;
782
783 if (ret) {
784 mwifiex_cancel_pending_scan_cmd(adapter);
785 break;
786 }
787 }
788
789 if (ret)
790 return -1;
791
792 return 0;
793}
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815static void
816mwifiex_config_scan(struct mwifiex_private *priv,
817 const struct mwifiex_user_scan_cfg *user_scan_in,
818 struct mwifiex_scan_cmd_config *scan_cfg_out,
819 struct mwifiex_ie_types_chan_list_param_set **chan_list_out,
820 struct mwifiex_chan_scan_param_set *scan_chan_list,
821 u8 *max_chan_per_scan, u8 *filtered_scan,
822 u8 *scan_current_only)
823{
824 struct mwifiex_adapter *adapter = priv->adapter;
825 struct mwifiex_ie_types_num_probes *num_probes_tlv;
826 struct mwifiex_ie_types_scan_chan_gap *chan_gap_tlv;
827 struct mwifiex_ie_types_random_mac *random_mac_tlv;
828 struct mwifiex_ie_types_wildcard_ssid_params *wildcard_ssid_tlv;
829 struct mwifiex_ie_types_bssid_list *bssid_tlv;
830 u8 *tlv_pos;
831 u32 num_probes;
832 u32 ssid_len;
833 u32 chan_idx;
834 u32 scan_type;
835 u16 scan_dur;
836 u8 channel;
837 u8 radio_type;
838 int i;
839 u8 ssid_filter;
840 struct mwifiex_ie_types_htcap *ht_cap;
841 struct mwifiex_ie_types_bss_mode *bss_mode;
842 const u8 zero_mac[6] = {0, 0, 0, 0, 0, 0};
843
844
845
846
847
848
849 scan_cfg_out->tlv_buf_len = 0;
850
851
852
853
854 tlv_pos = scan_cfg_out->tlv_buf;
855
856
857
858 *filtered_scan = false;
859
860
861
862
863 *scan_current_only = false;
864
865 if (user_scan_in) {
866 u8 tmpaddr[ETH_ALEN];
867
868
869
870
871 ssid_filter = true;
872
873
874
875 scan_cfg_out->bss_mode =
876 (u8)(user_scan_in->bss_mode ?: adapter->scan_mode);
877
878
879
880 num_probes = user_scan_in->num_probes ?: adapter->scan_probes;
881
882
883
884
885
886
887 memcpy(scan_cfg_out->specific_bssid,
888 user_scan_in->specific_bssid,
889 sizeof(scan_cfg_out->specific_bssid));
890
891 memcpy(tmpaddr, scan_cfg_out->specific_bssid, ETH_ALEN);
892
893 if (adapter->ext_scan &&
894 !is_zero_ether_addr(tmpaddr)) {
895 bssid_tlv =
896 (struct mwifiex_ie_types_bssid_list *)tlv_pos;
897 bssid_tlv->header.type = cpu_to_le16(TLV_TYPE_BSSID);
898 bssid_tlv->header.len = cpu_to_le16(ETH_ALEN);
899 memcpy(bssid_tlv->bssid, user_scan_in->specific_bssid,
900 ETH_ALEN);
901 tlv_pos += sizeof(struct mwifiex_ie_types_bssid_list);
902 }
903
904 for (i = 0; i < user_scan_in->num_ssids; i++) {
905 ssid_len = user_scan_in->ssid_list[i].ssid_len;
906
907 wildcard_ssid_tlv =
908 (struct mwifiex_ie_types_wildcard_ssid_params *)
909 tlv_pos;
910 wildcard_ssid_tlv->header.type =
911 cpu_to_le16(TLV_TYPE_WILDCARDSSID);
912 wildcard_ssid_tlv->header.len = cpu_to_le16(
913 (u16) (ssid_len + sizeof(wildcard_ssid_tlv->
914 max_ssid_length)));
915
916
917
918
919
920
921
922 if (ssid_len)
923 wildcard_ssid_tlv->max_ssid_length = 0;
924 else
925 wildcard_ssid_tlv->max_ssid_length =
926 IEEE80211_MAX_SSID_LEN;
927
928 if (!memcmp(user_scan_in->ssid_list[i].ssid,
929 "DIRECT-", 7))
930 wildcard_ssid_tlv->max_ssid_length = 0xfe;
931
932 memcpy(wildcard_ssid_tlv->ssid,
933 user_scan_in->ssid_list[i].ssid, ssid_len);
934
935 tlv_pos += (sizeof(wildcard_ssid_tlv->header)
936 + le16_to_cpu(wildcard_ssid_tlv->header.len));
937
938 mwifiex_dbg(adapter, INFO,
939 "info: scan: ssid[%d]: %s, %d\n",
940 i, wildcard_ssid_tlv->ssid,
941 wildcard_ssid_tlv->max_ssid_length);
942
943
944
945
946
947 if (!ssid_len && wildcard_ssid_tlv->max_ssid_length)
948 ssid_filter = false;
949 }
950
951
952
953
954
955
956
957 memcpy(tmpaddr, scan_cfg_out->specific_bssid, ETH_ALEN);
958 if ((i && ssid_filter) ||
959 !is_zero_ether_addr(tmpaddr))
960 *filtered_scan = true;
961
962 if (user_scan_in->scan_chan_gap) {
963 mwifiex_dbg(adapter, INFO,
964 "info: scan: channel gap = %d\n",
965 user_scan_in->scan_chan_gap);
966 *max_chan_per_scan =
967 MWIFIEX_MAX_CHANNELS_PER_SPECIFIC_SCAN;
968
969 chan_gap_tlv = (void *)tlv_pos;
970 chan_gap_tlv->header.type =
971 cpu_to_le16(TLV_TYPE_SCAN_CHANNEL_GAP);
972 chan_gap_tlv->header.len =
973 cpu_to_le16(sizeof(chan_gap_tlv->chan_gap));
974 chan_gap_tlv->chan_gap =
975 cpu_to_le16((user_scan_in->scan_chan_gap));
976 tlv_pos +=
977 sizeof(struct mwifiex_ie_types_scan_chan_gap);
978 }
979
980 if (!ether_addr_equal(user_scan_in->random_mac, zero_mac)) {
981 random_mac_tlv = (void *)tlv_pos;
982 random_mac_tlv->header.type =
983 cpu_to_le16(TLV_TYPE_RANDOM_MAC);
984 random_mac_tlv->header.len =
985 cpu_to_le16(sizeof(random_mac_tlv->mac));
986 ether_addr_copy(random_mac_tlv->mac,
987 user_scan_in->random_mac);
988 tlv_pos +=
989 sizeof(struct mwifiex_ie_types_random_mac);
990 }
991 } else {
992 scan_cfg_out->bss_mode = (u8) adapter->scan_mode;
993 num_probes = adapter->scan_probes;
994 }
995
996
997
998
999
1000 if (*filtered_scan) {
1001 *max_chan_per_scan = MWIFIEX_MAX_CHANNELS_PER_SPECIFIC_SCAN;
1002 } else {
1003 if (!priv->media_connected)
1004 *max_chan_per_scan = MWIFIEX_DEF_CHANNELS_PER_SCAN_CMD;
1005 else
1006 *max_chan_per_scan =
1007 MWIFIEX_DEF_CHANNELS_PER_SCAN_CMD / 2;
1008 }
1009
1010 if (adapter->ext_scan) {
1011 bss_mode = (struct mwifiex_ie_types_bss_mode *)tlv_pos;
1012 bss_mode->header.type = cpu_to_le16(TLV_TYPE_BSS_MODE);
1013 bss_mode->header.len = cpu_to_le16(sizeof(bss_mode->bss_mode));
1014 bss_mode->bss_mode = scan_cfg_out->bss_mode;
1015 tlv_pos += sizeof(bss_mode->header) +
1016 le16_to_cpu(bss_mode->header.len);
1017 }
1018
1019
1020
1021 if (num_probes) {
1022
1023 mwifiex_dbg(adapter, INFO,
1024 "info: scan: num_probes = %d\n",
1025 num_probes);
1026
1027 num_probes_tlv = (struct mwifiex_ie_types_num_probes *) tlv_pos;
1028 num_probes_tlv->header.type = cpu_to_le16(TLV_TYPE_NUMPROBES);
1029 num_probes_tlv->header.len =
1030 cpu_to_le16(sizeof(num_probes_tlv->num_probes));
1031 num_probes_tlv->num_probes = cpu_to_le16((u16) num_probes);
1032
1033 tlv_pos += sizeof(num_probes_tlv->header) +
1034 le16_to_cpu(num_probes_tlv->header.len);
1035
1036 }
1037
1038 if (ISSUPP_11NENABLED(priv->adapter->fw_cap_info) &&
1039 (priv->adapter->config_bands & BAND_GN ||
1040 priv->adapter->config_bands & BAND_AN)) {
1041 ht_cap = (struct mwifiex_ie_types_htcap *) tlv_pos;
1042 memset(ht_cap, 0, sizeof(struct mwifiex_ie_types_htcap));
1043 ht_cap->header.type = cpu_to_le16(WLAN_EID_HT_CAPABILITY);
1044 ht_cap->header.len =
1045 cpu_to_le16(sizeof(struct ieee80211_ht_cap));
1046 radio_type =
1047 mwifiex_band_to_radio_type(priv->adapter->config_bands);
1048 mwifiex_fill_cap_info(priv, radio_type, &ht_cap->ht_cap);
1049 tlv_pos += sizeof(struct mwifiex_ie_types_htcap);
1050 }
1051
1052
1053 mwifiex_cmd_append_vsie_tlv(priv, MWIFIEX_VSIE_MASK_SCAN, &tlv_pos);
1054
1055
1056
1057
1058
1059
1060
1061 *chan_list_out =
1062 (struct mwifiex_ie_types_chan_list_param_set *) tlv_pos;
1063
1064 if (user_scan_in && user_scan_in->chan_list[0].chan_number) {
1065
1066 mwifiex_dbg(adapter, INFO,
1067 "info: Scan: Using supplied channel list\n");
1068
1069 for (chan_idx = 0;
1070 chan_idx < MWIFIEX_USER_SCAN_CHAN_MAX &&
1071 user_scan_in->chan_list[chan_idx].chan_number;
1072 chan_idx++) {
1073
1074 channel = user_scan_in->chan_list[chan_idx].chan_number;
1075 scan_chan_list[chan_idx].chan_number = channel;
1076
1077 radio_type =
1078 user_scan_in->chan_list[chan_idx].radio_type;
1079 scan_chan_list[chan_idx].radio_type = radio_type;
1080
1081 scan_type = user_scan_in->chan_list[chan_idx].scan_type;
1082
1083 if (scan_type == MWIFIEX_SCAN_TYPE_PASSIVE)
1084 scan_chan_list[chan_idx].chan_scan_mode_bitmap
1085 |= (MWIFIEX_PASSIVE_SCAN |
1086 MWIFIEX_HIDDEN_SSID_REPORT);
1087 else
1088 scan_chan_list[chan_idx].chan_scan_mode_bitmap
1089 &= ~MWIFIEX_PASSIVE_SCAN;
1090
1091 scan_chan_list[chan_idx].chan_scan_mode_bitmap
1092 |= MWIFIEX_DISABLE_CHAN_FILT;
1093
1094 if (user_scan_in->chan_list[chan_idx].scan_time) {
1095 scan_dur = (u16) user_scan_in->
1096 chan_list[chan_idx].scan_time;
1097 } else {
1098 if (scan_type == MWIFIEX_SCAN_TYPE_PASSIVE)
1099 scan_dur = adapter->passive_scan_time;
1100 else if (*filtered_scan)
1101 scan_dur = adapter->specific_scan_time;
1102 else
1103 scan_dur = adapter->active_scan_time;
1104 }
1105
1106 scan_chan_list[chan_idx].min_scan_time =
1107 cpu_to_le16(scan_dur);
1108 scan_chan_list[chan_idx].max_scan_time =
1109 cpu_to_le16(scan_dur);
1110 }
1111
1112
1113 if ((chan_idx == 1) &&
1114 (user_scan_in->chan_list[0].chan_number ==
1115 priv->curr_bss_params.bss_descriptor.channel)) {
1116 *scan_current_only = true;
1117 mwifiex_dbg(adapter, INFO,
1118 "info: Scan: Scanning current channel only\n");
1119 }
1120 } else {
1121 mwifiex_dbg(adapter, INFO,
1122 "info: Scan: Creating full region channel list\n");
1123 mwifiex_scan_create_channel_list(priv, user_scan_in,
1124 scan_chan_list,
1125 *filtered_scan);
1126 }
1127
1128}
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139static void
1140mwifiex_ret_802_11_scan_get_tlv_ptrs(struct mwifiex_adapter *adapter,
1141 struct mwifiex_ie_types_data *tlv,
1142 u32 tlv_buf_size, u32 req_tlv_type,
1143 struct mwifiex_ie_types_data **tlv_data)
1144{
1145 struct mwifiex_ie_types_data *current_tlv;
1146 u32 tlv_buf_left;
1147 u32 tlv_type;
1148 u32 tlv_len;
1149
1150 current_tlv = tlv;
1151 tlv_buf_left = tlv_buf_size;
1152 *tlv_data = NULL;
1153
1154 mwifiex_dbg(adapter, INFO,
1155 "info: SCAN_RESP: tlv_buf_size = %d\n",
1156 tlv_buf_size);
1157
1158 while (tlv_buf_left >= sizeof(struct mwifiex_ie_types_header)) {
1159
1160 tlv_type = le16_to_cpu(current_tlv->header.type);
1161 tlv_len = le16_to_cpu(current_tlv->header.len);
1162
1163 if (sizeof(tlv->header) + tlv_len > tlv_buf_left) {
1164 mwifiex_dbg(adapter, ERROR,
1165 "SCAN_RESP: TLV buffer corrupt\n");
1166 break;
1167 }
1168
1169 if (req_tlv_type == tlv_type) {
1170 switch (tlv_type) {
1171 case TLV_TYPE_TSFTIMESTAMP:
1172 mwifiex_dbg(adapter, INFO,
1173 "info: SCAN_RESP: TSF\t"
1174 "timestamp TLV, len = %d\n",
1175 tlv_len);
1176 *tlv_data = current_tlv;
1177 break;
1178 case TLV_TYPE_CHANNELBANDLIST:
1179 mwifiex_dbg(adapter, INFO,
1180 "info: SCAN_RESP: channel\t"
1181 "band list TLV, len = %d\n",
1182 tlv_len);
1183 *tlv_data = current_tlv;
1184 break;
1185 default:
1186 mwifiex_dbg(adapter, ERROR,
1187 "SCAN_RESP: unhandled TLV = %d\n",
1188 tlv_type);
1189
1190 return;
1191 }
1192 }
1193
1194 if (*tlv_data)
1195 break;
1196
1197
1198 tlv_buf_left -= (sizeof(tlv->header) + tlv_len);
1199 current_tlv =
1200 (struct mwifiex_ie_types_data *) (current_tlv->data +
1201 tlv_len);
1202
1203 }
1204}
1205
1206
1207
1208
1209
1210int mwifiex_update_bss_desc_with_ie(struct mwifiex_adapter *adapter,
1211 struct mwifiex_bssdescriptor *bss_entry)
1212{
1213 int ret = 0;
1214 u8 element_id;
1215 struct ieee_types_fh_param_set *fh_param_set;
1216 struct ieee_types_ds_param_set *ds_param_set;
1217 struct ieee_types_cf_param_set *cf_param_set;
1218 struct ieee_types_ibss_param_set *ibss_param_set;
1219 u8 *current_ptr;
1220 u8 *rate;
1221 u8 element_len;
1222 u16 total_ie_len;
1223 u8 bytes_to_copy;
1224 u8 rate_size;
1225 u8 found_data_rate_ie;
1226 u32 bytes_left;
1227 struct ieee_types_vendor_specific *vendor_ie;
1228 const u8 wpa_oui[4] = { 0x00, 0x50, 0xf2, 0x01 };
1229 const u8 wmm_oui[4] = { 0x00, 0x50, 0xf2, 0x02 };
1230
1231 found_data_rate_ie = false;
1232 rate_size = 0;
1233 current_ptr = bss_entry->beacon_buf;
1234 bytes_left = bss_entry->beacon_buf_size;
1235
1236
1237 while (bytes_left >= 2) {
1238 element_id = *current_ptr;
1239 element_len = *(current_ptr + 1);
1240 total_ie_len = element_len + sizeof(struct ieee_types_header);
1241
1242 if (bytes_left < total_ie_len) {
1243 mwifiex_dbg(adapter, ERROR,
1244 "err: InterpretIE: in processing\t"
1245 "IE, bytes left < IE length\n");
1246 return -1;
1247 }
1248 switch (element_id) {
1249 case WLAN_EID_SSID:
1250 bss_entry->ssid.ssid_len = element_len;
1251 memcpy(bss_entry->ssid.ssid, (current_ptr + 2),
1252 element_len);
1253 mwifiex_dbg(adapter, INFO,
1254 "info: InterpretIE: ssid: %-32s\n",
1255 bss_entry->ssid.ssid);
1256 break;
1257
1258 case WLAN_EID_SUPP_RATES:
1259 memcpy(bss_entry->data_rates, current_ptr + 2,
1260 element_len);
1261 memcpy(bss_entry->supported_rates, current_ptr + 2,
1262 element_len);
1263 rate_size = element_len;
1264 found_data_rate_ie = true;
1265 break;
1266
1267 case WLAN_EID_FH_PARAMS:
1268 fh_param_set =
1269 (struct ieee_types_fh_param_set *) current_ptr;
1270 memcpy(&bss_entry->phy_param_set.fh_param_set,
1271 fh_param_set,
1272 sizeof(struct ieee_types_fh_param_set));
1273 break;
1274
1275 case WLAN_EID_DS_PARAMS:
1276 ds_param_set =
1277 (struct ieee_types_ds_param_set *) current_ptr;
1278
1279 bss_entry->channel = ds_param_set->current_chan;
1280
1281 memcpy(&bss_entry->phy_param_set.ds_param_set,
1282 ds_param_set,
1283 sizeof(struct ieee_types_ds_param_set));
1284 break;
1285
1286 case WLAN_EID_CF_PARAMS:
1287 cf_param_set =
1288 (struct ieee_types_cf_param_set *) current_ptr;
1289 memcpy(&bss_entry->ss_param_set.cf_param_set,
1290 cf_param_set,
1291 sizeof(struct ieee_types_cf_param_set));
1292 break;
1293
1294 case WLAN_EID_IBSS_PARAMS:
1295 ibss_param_set =
1296 (struct ieee_types_ibss_param_set *)
1297 current_ptr;
1298 memcpy(&bss_entry->ss_param_set.ibss_param_set,
1299 ibss_param_set,
1300 sizeof(struct ieee_types_ibss_param_set));
1301 break;
1302
1303 case WLAN_EID_ERP_INFO:
1304 bss_entry->erp_flags = *(current_ptr + 2);
1305 break;
1306
1307 case WLAN_EID_PWR_CONSTRAINT:
1308 bss_entry->local_constraint = *(current_ptr + 2);
1309 bss_entry->sensed_11h = true;
1310 break;
1311
1312 case WLAN_EID_CHANNEL_SWITCH:
1313 bss_entry->chan_sw_ie_present = true;
1314
1315 case WLAN_EID_PWR_CAPABILITY:
1316 case WLAN_EID_TPC_REPORT:
1317 case WLAN_EID_QUIET:
1318 bss_entry->sensed_11h = true;
1319 break;
1320
1321 case WLAN_EID_EXT_SUPP_RATES:
1322
1323
1324
1325
1326
1327
1328 if (found_data_rate_ie) {
1329 if ((element_len + rate_size) >
1330 MWIFIEX_SUPPORTED_RATES)
1331 bytes_to_copy =
1332 (MWIFIEX_SUPPORTED_RATES -
1333 rate_size);
1334 else
1335 bytes_to_copy = element_len;
1336
1337 rate = (u8 *) bss_entry->data_rates;
1338 rate += rate_size;
1339 memcpy(rate, current_ptr + 2, bytes_to_copy);
1340
1341 rate = (u8 *) bss_entry->supported_rates;
1342 rate += rate_size;
1343 memcpy(rate, current_ptr + 2, bytes_to_copy);
1344 }
1345 break;
1346
1347 case WLAN_EID_VENDOR_SPECIFIC:
1348 vendor_ie = (struct ieee_types_vendor_specific *)
1349 current_ptr;
1350
1351 if (!memcmp
1352 (vendor_ie->vend_hdr.oui, wpa_oui,
1353 sizeof(wpa_oui))) {
1354 bss_entry->bcn_wpa_ie =
1355 (struct ieee_types_vendor_specific *)
1356 current_ptr;
1357 bss_entry->wpa_offset = (u16)
1358 (current_ptr - bss_entry->beacon_buf);
1359 } else if (!memcmp(vendor_ie->vend_hdr.oui, wmm_oui,
1360 sizeof(wmm_oui))) {
1361 if (total_ie_len ==
1362 sizeof(struct ieee_types_wmm_parameter) ||
1363 total_ie_len ==
1364 sizeof(struct ieee_types_wmm_info))
1365
1366
1367
1368
1369
1370 memcpy((u8 *) &bss_entry->wmm_ie,
1371 current_ptr, total_ie_len);
1372 }
1373 break;
1374 case WLAN_EID_RSN:
1375 bss_entry->bcn_rsn_ie =
1376 (struct ieee_types_generic *) current_ptr;
1377 bss_entry->rsn_offset = (u16) (current_ptr -
1378 bss_entry->beacon_buf);
1379 break;
1380 case WLAN_EID_BSS_AC_ACCESS_DELAY:
1381 bss_entry->bcn_wapi_ie =
1382 (struct ieee_types_generic *) current_ptr;
1383 bss_entry->wapi_offset = (u16) (current_ptr -
1384 bss_entry->beacon_buf);
1385 break;
1386 case WLAN_EID_HT_CAPABILITY:
1387 bss_entry->bcn_ht_cap = (struct ieee80211_ht_cap *)
1388 (current_ptr +
1389 sizeof(struct ieee_types_header));
1390 bss_entry->ht_cap_offset = (u16) (current_ptr +
1391 sizeof(struct ieee_types_header) -
1392 bss_entry->beacon_buf);
1393 break;
1394 case WLAN_EID_HT_OPERATION:
1395 bss_entry->bcn_ht_oper =
1396 (struct ieee80211_ht_operation *)(current_ptr +
1397 sizeof(struct ieee_types_header));
1398 bss_entry->ht_info_offset = (u16) (current_ptr +
1399 sizeof(struct ieee_types_header) -
1400 bss_entry->beacon_buf);
1401 break;
1402 case WLAN_EID_VHT_CAPABILITY:
1403 bss_entry->disable_11ac = false;
1404 bss_entry->bcn_vht_cap =
1405 (void *)(current_ptr +
1406 sizeof(struct ieee_types_header));
1407 bss_entry->vht_cap_offset =
1408 (u16)((u8 *)bss_entry->bcn_vht_cap -
1409 bss_entry->beacon_buf);
1410 break;
1411 case WLAN_EID_VHT_OPERATION:
1412 bss_entry->bcn_vht_oper =
1413 (void *)(current_ptr +
1414 sizeof(struct ieee_types_header));
1415 bss_entry->vht_info_offset =
1416 (u16)((u8 *)bss_entry->bcn_vht_oper -
1417 bss_entry->beacon_buf);
1418 break;
1419 case WLAN_EID_BSS_COEX_2040:
1420 bss_entry->bcn_bss_co_2040 = current_ptr;
1421 bss_entry->bss_co_2040_offset =
1422 (u16) (current_ptr - bss_entry->beacon_buf);
1423 break;
1424 case WLAN_EID_EXT_CAPABILITY:
1425 bss_entry->bcn_ext_cap = current_ptr;
1426 bss_entry->ext_cap_offset =
1427 (u16) (current_ptr - bss_entry->beacon_buf);
1428 break;
1429 case WLAN_EID_OPMODE_NOTIF:
1430 bss_entry->oper_mode = (void *)current_ptr;
1431 bss_entry->oper_mode_offset =
1432 (u16)((u8 *)bss_entry->oper_mode -
1433 bss_entry->beacon_buf);
1434 break;
1435 default:
1436 break;
1437 }
1438
1439 current_ptr += element_len + 2;
1440
1441
1442 bytes_left -= (element_len + 2);
1443
1444 }
1445 return ret;
1446}
1447
1448
1449
1450
1451
1452static u8
1453mwifiex_radio_type_to_band(u8 radio_type)
1454{
1455 switch (radio_type) {
1456 case HostCmd_SCAN_RADIO_TYPE_A:
1457 return BAND_A;
1458 case HostCmd_SCAN_RADIO_TYPE_BG:
1459 default:
1460 return BAND_G;
1461 }
1462}
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472int mwifiex_scan_networks(struct mwifiex_private *priv,
1473 const struct mwifiex_user_scan_cfg *user_scan_in)
1474{
1475 int ret;
1476 struct mwifiex_adapter *adapter = priv->adapter;
1477 struct cmd_ctrl_node *cmd_node;
1478 union mwifiex_scan_cmd_config_tlv *scan_cfg_out;
1479 struct mwifiex_ie_types_chan_list_param_set *chan_list_out;
1480 struct mwifiex_chan_scan_param_set *scan_chan_list;
1481 u8 filtered_scan;
1482 u8 scan_current_chan_only;
1483 u8 max_chan_per_scan;
1484 unsigned long flags;
1485
1486 if (adapter->scan_processing) {
1487 mwifiex_dbg(adapter, WARN,
1488 "cmd: Scan already in process...\n");
1489 return -EBUSY;
1490 }
1491
1492 if (priv->scan_block) {
1493 mwifiex_dbg(adapter, WARN,
1494 "cmd: Scan is blocked during association...\n");
1495 return -EBUSY;
1496 }
1497
1498 if (test_bit(MWIFIEX_SURPRISE_REMOVED, &adapter->work_flags) ||
1499 test_bit(MWIFIEX_IS_CMD_TIMEDOUT, &adapter->work_flags)) {
1500 mwifiex_dbg(adapter, ERROR,
1501 "Ignore scan. Card removed or firmware in bad state\n");
1502 return -EFAULT;
1503 }
1504
1505 spin_lock_irqsave(&adapter->mwifiex_cmd_lock, flags);
1506 adapter->scan_processing = true;
1507 spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, flags);
1508
1509 scan_cfg_out = kzalloc(sizeof(union mwifiex_scan_cmd_config_tlv),
1510 GFP_KERNEL);
1511 if (!scan_cfg_out) {
1512 ret = -ENOMEM;
1513 goto done;
1514 }
1515
1516 scan_chan_list = kcalloc(MWIFIEX_USER_SCAN_CHAN_MAX,
1517 sizeof(struct mwifiex_chan_scan_param_set),
1518 GFP_KERNEL);
1519 if (!scan_chan_list) {
1520 kfree(scan_cfg_out);
1521 ret = -ENOMEM;
1522 goto done;
1523 }
1524
1525 mwifiex_config_scan(priv, user_scan_in, &scan_cfg_out->config,
1526 &chan_list_out, scan_chan_list, &max_chan_per_scan,
1527 &filtered_scan, &scan_current_chan_only);
1528
1529 ret = mwifiex_scan_channel_list(priv, max_chan_per_scan, filtered_scan,
1530 &scan_cfg_out->config, chan_list_out,
1531 scan_chan_list);
1532
1533
1534 if (!ret) {
1535 spin_lock_irqsave(&adapter->scan_pending_q_lock, flags);
1536 if (!list_empty(&adapter->scan_pending_q)) {
1537 cmd_node = list_first_entry(&adapter->scan_pending_q,
1538 struct cmd_ctrl_node, list);
1539 list_del(&cmd_node->list);
1540 spin_unlock_irqrestore(&adapter->scan_pending_q_lock,
1541 flags);
1542 mwifiex_insert_cmd_to_pending_q(adapter, cmd_node);
1543 queue_work(adapter->workqueue, &adapter->main_work);
1544
1545
1546 if (!priv->scan_request) {
1547 mwifiex_dbg(adapter, INFO,
1548 "wait internal scan\n");
1549 mwifiex_wait_queue_complete(adapter, cmd_node);
1550 }
1551 } else {
1552 spin_unlock_irqrestore(&adapter->scan_pending_q_lock,
1553 flags);
1554 }
1555 }
1556
1557 kfree(scan_cfg_out);
1558 kfree(scan_chan_list);
1559done:
1560 if (ret) {
1561 spin_lock_irqsave(&adapter->mwifiex_cmd_lock, flags);
1562 adapter->scan_processing = false;
1563 spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, flags);
1564 }
1565 return ret;
1566}
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582int mwifiex_cmd_802_11_scan(struct host_cmd_ds_command *cmd,
1583 struct mwifiex_scan_cmd_config *scan_cfg)
1584{
1585 struct host_cmd_ds_802_11_scan *scan_cmd = &cmd->params.scan;
1586
1587
1588 scan_cmd->bss_mode = scan_cfg->bss_mode;
1589 memcpy(scan_cmd->bssid, scan_cfg->specific_bssid,
1590 sizeof(scan_cmd->bssid));
1591 memcpy(scan_cmd->tlv_buffer, scan_cfg->tlv_buf, scan_cfg->tlv_buf_len);
1592
1593 cmd->command = cpu_to_le16(HostCmd_CMD_802_11_SCAN);
1594
1595
1596 cmd->size = cpu_to_le16((u16) (sizeof(scan_cmd->bss_mode)
1597 + sizeof(scan_cmd->bssid)
1598 + scan_cfg->tlv_buf_len + S_DS_GEN));
1599
1600 return 0;
1601}
1602
1603
1604
1605
1606
1607int mwifiex_check_network_compatibility(struct mwifiex_private *priv,
1608 struct mwifiex_bssdescriptor *bss_desc)
1609{
1610 int ret = -1;
1611
1612 if (!bss_desc)
1613 return -1;
1614
1615 if ((mwifiex_get_cfp(priv, (u8) bss_desc->bss_band,
1616 (u16) bss_desc->channel, 0))) {
1617 switch (priv->bss_mode) {
1618 case NL80211_IFTYPE_STATION:
1619 case NL80211_IFTYPE_ADHOC:
1620 ret = mwifiex_is_network_compatible(priv, bss_desc,
1621 priv->bss_mode);
1622 if (ret)
1623 mwifiex_dbg(priv->adapter, ERROR,
1624 "Incompatible network settings\n");
1625 break;
1626 default:
1627 ret = 0;
1628 }
1629 }
1630
1631 return ret;
1632}
1633
1634
1635static bool mwifiex_is_hidden_ssid(struct cfg80211_ssid *ssid)
1636{
1637 int idx;
1638
1639 for (idx = 0; idx < ssid->ssid_len; idx++) {
1640 if (ssid->ssid[idx])
1641 return false;
1642 }
1643
1644 return true;
1645}
1646
1647
1648
1649
1650static int mwifiex_save_hidden_ssid_channels(struct mwifiex_private *priv,
1651 struct cfg80211_bss *bss)
1652{
1653 struct mwifiex_bssdescriptor *bss_desc;
1654 int ret;
1655 int chid;
1656
1657
1658 bss_desc = kzalloc(sizeof(*bss_desc), GFP_KERNEL);
1659 if (!bss_desc)
1660 return -ENOMEM;
1661
1662 ret = mwifiex_fill_new_bss_desc(priv, bss, bss_desc);
1663 if (ret)
1664 goto done;
1665
1666 if (mwifiex_is_hidden_ssid(&bss_desc->ssid)) {
1667 mwifiex_dbg(priv->adapter, INFO, "found hidden SSID\n");
1668 for (chid = 0 ; chid < MWIFIEX_USER_SCAN_CHAN_MAX; chid++) {
1669 if (priv->hidden_chan[chid].chan_number ==
1670 bss->channel->hw_value)
1671 break;
1672
1673 if (!priv->hidden_chan[chid].chan_number) {
1674 priv->hidden_chan[chid].chan_number =
1675 bss->channel->hw_value;
1676 priv->hidden_chan[chid].radio_type =
1677 bss->channel->band;
1678 priv->hidden_chan[chid].scan_type =
1679 MWIFIEX_SCAN_TYPE_ACTIVE;
1680 break;
1681 }
1682 }
1683 }
1684
1685done:
1686
1687
1688
1689 kfree(bss_desc->beacon_buf);
1690 kfree(bss_desc);
1691 return 0;
1692}
1693
1694static int mwifiex_update_curr_bss_params(struct mwifiex_private *priv,
1695 struct cfg80211_bss *bss)
1696{
1697 struct mwifiex_bssdescriptor *bss_desc;
1698 int ret;
1699 unsigned long flags;
1700
1701
1702 bss_desc = kzalloc(sizeof(struct mwifiex_bssdescriptor), GFP_KERNEL);
1703 if (!bss_desc)
1704 return -ENOMEM;
1705
1706 ret = mwifiex_fill_new_bss_desc(priv, bss, bss_desc);
1707 if (ret)
1708 goto done;
1709
1710 ret = mwifiex_check_network_compatibility(priv, bss_desc);
1711 if (ret)
1712 goto done;
1713
1714 spin_lock_irqsave(&priv->curr_bcn_buf_lock, flags);
1715
1716 memcpy(&priv->curr_bss_params.bss_descriptor, bss_desc,
1717 sizeof(priv->curr_bss_params.bss_descriptor));
1718
1719
1720
1721
1722 mwifiex_save_curr_bcn(priv);
1723 spin_unlock_irqrestore(&priv->curr_bcn_buf_lock, flags);
1724
1725done:
1726
1727
1728
1729 kfree(bss_desc->beacon_buf);
1730 kfree(bss_desc);
1731 return 0;
1732}
1733
1734static int
1735mwifiex_parse_single_response_buf(struct mwifiex_private *priv, u8 **bss_info,
1736 u32 *bytes_left, u64 fw_tsf, u8 *radio_type,
1737 bool ext_scan, s32 rssi_val)
1738{
1739 struct mwifiex_adapter *adapter = priv->adapter;
1740 struct mwifiex_chan_freq_power *cfp;
1741 struct cfg80211_bss *bss;
1742 u8 bssid[ETH_ALEN];
1743 s32 rssi;
1744 const u8 *ie_buf;
1745 size_t ie_len;
1746 u16 channel = 0;
1747 u16 beacon_size = 0;
1748 u32 curr_bcn_bytes;
1749 u32 freq;
1750 u16 beacon_period;
1751 u16 cap_info_bitmap;
1752 u8 *current_ptr;
1753 u64 timestamp;
1754 struct mwifiex_fixed_bcn_param *bcn_param;
1755 struct mwifiex_bss_priv *bss_priv;
1756
1757 if (*bytes_left >= sizeof(beacon_size)) {
1758
1759 beacon_size = get_unaligned_le16((*bss_info));
1760 *bytes_left -= sizeof(beacon_size);
1761 *bss_info += sizeof(beacon_size);
1762 }
1763
1764 if (!beacon_size || beacon_size > *bytes_left) {
1765 *bss_info += *bytes_left;
1766 *bytes_left = 0;
1767 return -EFAULT;
1768 }
1769
1770
1771
1772
1773 current_ptr = *bss_info;
1774
1775
1776 *bss_info += beacon_size;
1777 *bytes_left -= beacon_size;
1778
1779 curr_bcn_bytes = beacon_size;
1780
1781
1782
1783
1784 if (curr_bcn_bytes < ETH_ALEN + sizeof(u8) +
1785 sizeof(struct mwifiex_fixed_bcn_param)) {
1786 mwifiex_dbg(adapter, ERROR,
1787 "InterpretIE: not enough bytes left\n");
1788 return -EFAULT;
1789 }
1790
1791 memcpy(bssid, current_ptr, ETH_ALEN);
1792 current_ptr += ETH_ALEN;
1793 curr_bcn_bytes -= ETH_ALEN;
1794
1795 if (!ext_scan) {
1796 rssi = (s32) *current_ptr;
1797 rssi = (-rssi) * 100;
1798 current_ptr += sizeof(u8);
1799 curr_bcn_bytes -= sizeof(u8);
1800 mwifiex_dbg(adapter, INFO,
1801 "info: InterpretIE: RSSI=%d\n", rssi);
1802 } else {
1803 rssi = rssi_val;
1804 }
1805
1806 bcn_param = (struct mwifiex_fixed_bcn_param *)current_ptr;
1807 current_ptr += sizeof(*bcn_param);
1808 curr_bcn_bytes -= sizeof(*bcn_param);
1809
1810 timestamp = le64_to_cpu(bcn_param->timestamp);
1811 beacon_period = le16_to_cpu(bcn_param->beacon_period);
1812
1813 cap_info_bitmap = le16_to_cpu(bcn_param->cap_info_bitmap);
1814 mwifiex_dbg(adapter, INFO,
1815 "info: InterpretIE: capabilities=0x%X\n",
1816 cap_info_bitmap);
1817
1818
1819 ie_buf = current_ptr;
1820 ie_len = curr_bcn_bytes;
1821 mwifiex_dbg(adapter, INFO,
1822 "info: InterpretIE: IELength for this AP = %d\n",
1823 curr_bcn_bytes);
1824
1825 while (curr_bcn_bytes >= sizeof(struct ieee_types_header)) {
1826 u8 element_id, element_len;
1827
1828 element_id = *current_ptr;
1829 element_len = *(current_ptr + 1);
1830 if (curr_bcn_bytes < element_len +
1831 sizeof(struct ieee_types_header)) {
1832 mwifiex_dbg(adapter, ERROR,
1833 "%s: bytes left < IE length\n", __func__);
1834 return -EFAULT;
1835 }
1836 if (element_id == WLAN_EID_DS_PARAMS) {
1837 channel = *(current_ptr +
1838 sizeof(struct ieee_types_header));
1839 break;
1840 }
1841
1842 current_ptr += element_len + sizeof(struct ieee_types_header);
1843 curr_bcn_bytes -= element_len +
1844 sizeof(struct ieee_types_header);
1845 }
1846
1847 if (channel) {
1848 struct ieee80211_channel *chan;
1849 u8 band;
1850
1851
1852 if (channel == priv->csa_chan) {
1853 mwifiex_dbg(adapter, WARN,
1854 "Dropping entry on csa closed channel\n");
1855 return 0;
1856 }
1857
1858 band = BAND_G;
1859 if (radio_type)
1860 band = mwifiex_radio_type_to_band(*radio_type &
1861 (BIT(0) | BIT(1)));
1862
1863 cfp = mwifiex_get_cfp(priv, band, channel, 0);
1864
1865 freq = cfp ? cfp->freq : 0;
1866
1867 chan = ieee80211_get_channel(priv->wdev.wiphy, freq);
1868
1869 if (chan && !(chan->flags & IEEE80211_CHAN_DISABLED)) {
1870 bss = cfg80211_inform_bss(priv->wdev.wiphy,
1871 chan, CFG80211_BSS_FTYPE_UNKNOWN,
1872 bssid, timestamp,
1873 cap_info_bitmap, beacon_period,
1874 ie_buf, ie_len, rssi, GFP_KERNEL);
1875 if (bss) {
1876 bss_priv = (struct mwifiex_bss_priv *)bss->priv;
1877 bss_priv->band = band;
1878 bss_priv->fw_tsf = fw_tsf;
1879 if (priv->media_connected &&
1880 !memcmp(bssid, priv->curr_bss_params.
1881 bss_descriptor.mac_address,
1882 ETH_ALEN))
1883 mwifiex_update_curr_bss_params(priv,
1884 bss);
1885
1886 if ((chan->flags & IEEE80211_CHAN_RADAR) ||
1887 (chan->flags & IEEE80211_CHAN_NO_IR)) {
1888 mwifiex_dbg(adapter, INFO,
1889 "radar or passive channel %d\n",
1890 channel);
1891 mwifiex_save_hidden_ssid_channels(priv,
1892 bss);
1893 }
1894
1895 cfg80211_put_bss(priv->wdev.wiphy, bss);
1896 }
1897 }
1898 } else {
1899 mwifiex_dbg(adapter, WARN, "missing BSS channel IE\n");
1900 }
1901
1902 return 0;
1903}
1904
1905static void mwifiex_complete_scan(struct mwifiex_private *priv)
1906{
1907 struct mwifiex_adapter *adapter = priv->adapter;
1908
1909 adapter->survey_idx = 0;
1910 if (adapter->curr_cmd->wait_q_enabled) {
1911 adapter->cmd_wait_q.status = 0;
1912 if (!priv->scan_request) {
1913 mwifiex_dbg(adapter, INFO,
1914 "complete internal scan\n");
1915 mwifiex_complete_cmd(adapter, adapter->curr_cmd);
1916 }
1917 }
1918}
1919
1920
1921
1922
1923static int
1924mwifiex_active_scan_req_for_passive_chan(struct mwifiex_private *priv)
1925{
1926 int ret;
1927 struct mwifiex_adapter *adapter = priv->adapter;
1928 u8 id = 0;
1929 struct mwifiex_user_scan_cfg *user_scan_cfg;
1930
1931 if (adapter->active_scan_triggered || !priv->scan_request ||
1932 priv->scan_aborting) {
1933 adapter->active_scan_triggered = false;
1934 return 0;
1935 }
1936
1937 if (!priv->hidden_chan[0].chan_number) {
1938 mwifiex_dbg(adapter, INFO, "No BSS with hidden SSID found on DFS channels\n");
1939 return 0;
1940 }
1941 user_scan_cfg = kzalloc(sizeof(*user_scan_cfg), GFP_KERNEL);
1942
1943 if (!user_scan_cfg)
1944 return -ENOMEM;
1945
1946 for (id = 0; id < MWIFIEX_USER_SCAN_CHAN_MAX; id++) {
1947 if (!priv->hidden_chan[id].chan_number)
1948 break;
1949 memcpy(&user_scan_cfg->chan_list[id],
1950 &priv->hidden_chan[id],
1951 sizeof(struct mwifiex_user_scan_chan));
1952 }
1953
1954 adapter->active_scan_triggered = true;
1955 if (priv->scan_request->flags & NL80211_SCAN_FLAG_RANDOM_ADDR)
1956 ether_addr_copy(user_scan_cfg->random_mac,
1957 priv->scan_request->mac_addr);
1958 user_scan_cfg->num_ssids = priv->scan_request->n_ssids;
1959 user_scan_cfg->ssid_list = priv->scan_request->ssids;
1960
1961 ret = mwifiex_scan_networks(priv, user_scan_cfg);
1962 kfree(user_scan_cfg);
1963
1964 memset(&priv->hidden_chan, 0, sizeof(priv->hidden_chan));
1965
1966 if (ret) {
1967 dev_err(priv->adapter->dev, "scan failed: %d\n", ret);
1968 return ret;
1969 }
1970
1971 return 0;
1972}
1973static void mwifiex_check_next_scan_command(struct mwifiex_private *priv)
1974{
1975 struct mwifiex_adapter *adapter = priv->adapter;
1976 struct cmd_ctrl_node *cmd_node;
1977 unsigned long flags;
1978
1979 spin_lock_irqsave(&adapter->scan_pending_q_lock, flags);
1980 if (list_empty(&adapter->scan_pending_q)) {
1981 spin_unlock_irqrestore(&adapter->scan_pending_q_lock, flags);
1982
1983 spin_lock_irqsave(&adapter->mwifiex_cmd_lock, flags);
1984 adapter->scan_processing = false;
1985 spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, flags);
1986
1987 mwifiex_active_scan_req_for_passive_chan(priv);
1988
1989 if (!adapter->ext_scan)
1990 mwifiex_complete_scan(priv);
1991
1992 if (priv->scan_request) {
1993 struct cfg80211_scan_info info = {
1994 .aborted = false,
1995 };
1996
1997 mwifiex_dbg(adapter, INFO,
1998 "info: notifying scan done\n");
1999 cfg80211_scan_done(priv->scan_request, &info);
2000 priv->scan_request = NULL;
2001 priv->scan_aborting = false;
2002 } else {
2003 priv->scan_aborting = false;
2004 mwifiex_dbg(adapter, INFO,
2005 "info: scan already aborted\n");
2006 }
2007 } else if ((priv->scan_aborting && !priv->scan_request) ||
2008 priv->scan_block) {
2009 spin_unlock_irqrestore(&adapter->scan_pending_q_lock, flags);
2010
2011 mwifiex_cancel_pending_scan_cmd(adapter);
2012
2013 spin_lock_irqsave(&adapter->mwifiex_cmd_lock, flags);
2014 adapter->scan_processing = false;
2015 spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, flags);
2016
2017 if (!adapter->active_scan_triggered) {
2018 if (priv->scan_request) {
2019 struct cfg80211_scan_info info = {
2020 .aborted = true,
2021 };
2022
2023 mwifiex_dbg(adapter, INFO,
2024 "info: aborting scan\n");
2025 cfg80211_scan_done(priv->scan_request, &info);
2026 priv->scan_request = NULL;
2027 priv->scan_aborting = false;
2028 } else {
2029 priv->scan_aborting = false;
2030 mwifiex_dbg(adapter, INFO,
2031 "info: scan already aborted\n");
2032 }
2033 }
2034 } else {
2035
2036
2037
2038 cmd_node = list_first_entry(&adapter->scan_pending_q,
2039 struct cmd_ctrl_node, list);
2040 list_del(&cmd_node->list);
2041 spin_unlock_irqrestore(&adapter->scan_pending_q_lock, flags);
2042 mwifiex_insert_cmd_to_pending_q(adapter, cmd_node);
2043 }
2044
2045 return;
2046}
2047
2048void mwifiex_cancel_scan(struct mwifiex_adapter *adapter)
2049{
2050 struct mwifiex_private *priv;
2051 unsigned long cmd_flags;
2052 int i;
2053
2054 mwifiex_cancel_pending_scan_cmd(adapter);
2055
2056 if (adapter->scan_processing) {
2057 spin_lock_irqsave(&adapter->mwifiex_cmd_lock, cmd_flags);
2058 adapter->scan_processing = false;
2059 spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, cmd_flags);
2060 for (i = 0; i < adapter->priv_num; i++) {
2061 priv = adapter->priv[i];
2062 if (!priv)
2063 continue;
2064 if (priv->scan_request) {
2065 struct cfg80211_scan_info info = {
2066 .aborted = true,
2067 };
2068
2069 mwifiex_dbg(adapter, INFO,
2070 "info: aborting scan\n");
2071 cfg80211_scan_done(priv->scan_request, &info);
2072 priv->scan_request = NULL;
2073 priv->scan_aborting = false;
2074 }
2075 }
2076 }
2077}
2078
2079
2080
2081
2082
2083
2084
2085
2086
2087
2088
2089
2090
2091
2092
2093
2094
2095
2096
2097
2098int mwifiex_ret_802_11_scan(struct mwifiex_private *priv,
2099 struct host_cmd_ds_command *resp)
2100{
2101 int ret = 0;
2102 struct mwifiex_adapter *adapter = priv->adapter;
2103 struct host_cmd_ds_802_11_scan_rsp *scan_rsp;
2104 struct mwifiex_ie_types_data *tlv_data;
2105 struct mwifiex_ie_types_tsf_timestamp *tsf_tlv;
2106 u8 *bss_info;
2107 u32 scan_resp_size;
2108 u32 bytes_left;
2109 u32 idx;
2110 u32 tlv_buf_size;
2111 struct mwifiex_ie_types_chan_band_list_param_set *chan_band_tlv;
2112 struct chan_band_param_set *chan_band;
2113 u8 is_bgscan_resp;
2114 __le64 fw_tsf = 0;
2115 u8 *radio_type;
2116 struct cfg80211_wowlan_nd_match *pmatch;
2117 struct cfg80211_sched_scan_request *nd_config = NULL;
2118
2119 is_bgscan_resp = (le16_to_cpu(resp->command)
2120 == HostCmd_CMD_802_11_BG_SCAN_QUERY);
2121 if (is_bgscan_resp)
2122 scan_rsp = &resp->params.bg_scan_query_resp.scan_resp;
2123 else
2124 scan_rsp = &resp->params.scan_resp;
2125
2126
2127 if (scan_rsp->number_of_sets > MWIFIEX_MAX_AP) {
2128 mwifiex_dbg(adapter, ERROR,
2129 "SCAN_RESP: too many AP returned (%d)\n",
2130 scan_rsp->number_of_sets);
2131 ret = -1;
2132 goto check_next_scan;
2133 }
2134
2135
2136 mwifiex_11h_get_csa_closed_channel(priv);
2137
2138 bytes_left = le16_to_cpu(scan_rsp->bss_descript_size);
2139 mwifiex_dbg(adapter, INFO,
2140 "info: SCAN_RESP: bss_descript_size %d\n",
2141 bytes_left);
2142
2143 scan_resp_size = le16_to_cpu(resp->size);
2144
2145 mwifiex_dbg(adapter, INFO,
2146 "info: SCAN_RESP: returned %d APs before parsing\n",
2147 scan_rsp->number_of_sets);
2148
2149 bss_info = scan_rsp->bss_desc_and_tlv_buffer;
2150
2151
2152
2153
2154
2155
2156
2157 tlv_buf_size = scan_resp_size - (bytes_left
2158 + sizeof(scan_rsp->bss_descript_size)
2159 + sizeof(scan_rsp->number_of_sets)
2160 + S_DS_GEN);
2161
2162 tlv_data = (struct mwifiex_ie_types_data *) (scan_rsp->
2163 bss_desc_and_tlv_buffer +
2164 bytes_left);
2165
2166
2167
2168 mwifiex_ret_802_11_scan_get_tlv_ptrs(adapter, tlv_data, tlv_buf_size,
2169 TLV_TYPE_TSFTIMESTAMP,
2170 (struct mwifiex_ie_types_data **)
2171 &tsf_tlv);
2172
2173
2174
2175 mwifiex_ret_802_11_scan_get_tlv_ptrs(adapter, tlv_data, tlv_buf_size,
2176 TLV_TYPE_CHANNELBANDLIST,
2177 (struct mwifiex_ie_types_data **)
2178 &chan_band_tlv);
2179
2180#ifdef CONFIG_PM
2181 if (priv->wdev.wiphy->wowlan_config)
2182 nd_config = priv->wdev.wiphy->wowlan_config->nd_config;
2183#endif
2184
2185 if (nd_config) {
2186 adapter->nd_info =
2187 kzalloc(sizeof(struct cfg80211_wowlan_nd_match) +
2188 sizeof(struct cfg80211_wowlan_nd_match *) *
2189 scan_rsp->number_of_sets, GFP_ATOMIC);
2190
2191 if (adapter->nd_info)
2192 adapter->nd_info->n_matches = scan_rsp->number_of_sets;
2193 }
2194
2195 for (idx = 0; idx < scan_rsp->number_of_sets && bytes_left; idx++) {
2196
2197
2198
2199
2200
2201
2202 if (tsf_tlv)
2203 memcpy(&fw_tsf, &tsf_tlv->tsf_data[idx * TSF_DATA_SIZE],
2204 sizeof(fw_tsf));
2205
2206 if (chan_band_tlv) {
2207 chan_band = &chan_band_tlv->chan_band_param[idx];
2208 radio_type = &chan_band->radio_type;
2209 } else {
2210 radio_type = NULL;
2211 }
2212
2213 if (chan_band_tlv && adapter->nd_info) {
2214 adapter->nd_info->matches[idx] =
2215 kzalloc(sizeof(*pmatch) + sizeof(u32),
2216 GFP_ATOMIC);
2217
2218 pmatch = adapter->nd_info->matches[idx];
2219
2220 if (pmatch) {
2221 pmatch->n_channels = 1;
2222 pmatch->channels[0] = chan_band->chan_number;
2223 }
2224 }
2225
2226 ret = mwifiex_parse_single_response_buf(priv, &bss_info,
2227 &bytes_left,
2228 le64_to_cpu(fw_tsf),
2229 radio_type, false, 0);
2230 if (ret)
2231 goto check_next_scan;
2232 }
2233
2234check_next_scan:
2235 mwifiex_check_next_scan_command(priv);
2236 return ret;
2237}
2238
2239
2240
2241
2242
2243
2244
2245
2246int mwifiex_cmd_802_11_scan_ext(struct mwifiex_private *priv,
2247 struct host_cmd_ds_command *cmd,
2248 void *data_buf)
2249{
2250 struct host_cmd_ds_802_11_scan_ext *ext_scan = &cmd->params.ext_scan;
2251 struct mwifiex_scan_cmd_config *scan_cfg = data_buf;
2252
2253 memcpy(ext_scan->tlv_buffer, scan_cfg->tlv_buf, scan_cfg->tlv_buf_len);
2254
2255 cmd->command = cpu_to_le16(HostCmd_CMD_802_11_SCAN_EXT);
2256
2257
2258 cmd->size = cpu_to_le16((u16)(sizeof(ext_scan->reserved)
2259 + scan_cfg->tlv_buf_len + S_DS_GEN));
2260
2261 return 0;
2262}
2263
2264
2265
2266
2267int mwifiex_cmd_802_11_bg_scan_config(struct mwifiex_private *priv,
2268 struct host_cmd_ds_command *cmd,
2269 void *data_buf)
2270{
2271 struct host_cmd_ds_802_11_bg_scan_config *bgscan_config =
2272 &cmd->params.bg_scan_config;
2273 struct mwifiex_bg_scan_cfg *bgscan_cfg_in = data_buf;
2274 u8 *tlv_pos = bgscan_config->tlv;
2275 u8 num_probes;
2276 u32 ssid_len, chan_idx, scan_type, scan_dur, chan_num;
2277 int i;
2278 struct mwifiex_ie_types_num_probes *num_probes_tlv;
2279 struct mwifiex_ie_types_repeat_count *repeat_count_tlv;
2280 struct mwifiex_ie_types_min_rssi_threshold *rssi_threshold_tlv;
2281 struct mwifiex_ie_types_bgscan_start_later *start_later_tlv;
2282 struct mwifiex_ie_types_wildcard_ssid_params *wildcard_ssid_tlv;
2283 struct mwifiex_ie_types_chan_list_param_set *chan_list_tlv;
2284 struct mwifiex_chan_scan_param_set *temp_chan;
2285
2286 cmd->command = cpu_to_le16(HostCmd_CMD_802_11_BG_SCAN_CONFIG);
2287 cmd->size = cpu_to_le16(sizeof(*bgscan_config) + S_DS_GEN);
2288
2289 bgscan_config->action = cpu_to_le16(bgscan_cfg_in->action);
2290 bgscan_config->enable = bgscan_cfg_in->enable;
2291 bgscan_config->bss_type = bgscan_cfg_in->bss_type;
2292 bgscan_config->scan_interval =
2293 cpu_to_le32(bgscan_cfg_in->scan_interval);
2294 bgscan_config->report_condition =
2295 cpu_to_le32(bgscan_cfg_in->report_condition);
2296
2297
2298 if (!bgscan_config->enable)
2299 return 0;
2300
2301 bgscan_config->chan_per_scan = bgscan_cfg_in->chan_per_scan;
2302
2303 num_probes = (bgscan_cfg_in->num_probes ? bgscan_cfg_in->
2304 num_probes : priv->adapter->scan_probes);
2305
2306 if (num_probes) {
2307 num_probes_tlv = (struct mwifiex_ie_types_num_probes *)tlv_pos;
2308 num_probes_tlv->header.type = cpu_to_le16(TLV_TYPE_NUMPROBES);
2309 num_probes_tlv->header.len =
2310 cpu_to_le16(sizeof(num_probes_tlv->num_probes));
2311 num_probes_tlv->num_probes = cpu_to_le16((u16)num_probes);
2312
2313 tlv_pos += sizeof(num_probes_tlv->header) +
2314 le16_to_cpu(num_probes_tlv->header.len);
2315 }
2316
2317 if (bgscan_cfg_in->repeat_count) {
2318 repeat_count_tlv =
2319 (struct mwifiex_ie_types_repeat_count *)tlv_pos;
2320 repeat_count_tlv->header.type =
2321 cpu_to_le16(TLV_TYPE_REPEAT_COUNT);
2322 repeat_count_tlv->header.len =
2323 cpu_to_le16(sizeof(repeat_count_tlv->repeat_count));
2324 repeat_count_tlv->repeat_count =
2325 cpu_to_le16(bgscan_cfg_in->repeat_count);
2326
2327 tlv_pos += sizeof(repeat_count_tlv->header) +
2328 le16_to_cpu(repeat_count_tlv->header.len);
2329 }
2330
2331 if (bgscan_cfg_in->rssi_threshold) {
2332 rssi_threshold_tlv =
2333 (struct mwifiex_ie_types_min_rssi_threshold *)tlv_pos;
2334 rssi_threshold_tlv->header.type =
2335 cpu_to_le16(TLV_TYPE_RSSI_LOW);
2336 rssi_threshold_tlv->header.len =
2337 cpu_to_le16(sizeof(rssi_threshold_tlv->rssi_threshold));
2338 rssi_threshold_tlv->rssi_threshold =
2339 cpu_to_le16(bgscan_cfg_in->rssi_threshold);
2340
2341 tlv_pos += sizeof(rssi_threshold_tlv->header) +
2342 le16_to_cpu(rssi_threshold_tlv->header.len);
2343 }
2344
2345 for (i = 0; i < bgscan_cfg_in->num_ssids; i++) {
2346 ssid_len = bgscan_cfg_in->ssid_list[i].ssid.ssid_len;
2347
2348 wildcard_ssid_tlv =
2349 (struct mwifiex_ie_types_wildcard_ssid_params *)tlv_pos;
2350 wildcard_ssid_tlv->header.type =
2351 cpu_to_le16(TLV_TYPE_WILDCARDSSID);
2352 wildcard_ssid_tlv->header.len = cpu_to_le16(
2353 (u16)(ssid_len + sizeof(wildcard_ssid_tlv->
2354 max_ssid_length)));
2355
2356
2357
2358
2359
2360
2361 if (ssid_len)
2362 wildcard_ssid_tlv->max_ssid_length = 0;
2363 else
2364 wildcard_ssid_tlv->max_ssid_length =
2365 IEEE80211_MAX_SSID_LEN;
2366
2367 memcpy(wildcard_ssid_tlv->ssid,
2368 bgscan_cfg_in->ssid_list[i].ssid.ssid, ssid_len);
2369
2370 tlv_pos += (sizeof(wildcard_ssid_tlv->header)
2371 + le16_to_cpu(wildcard_ssid_tlv->header.len));
2372 }
2373
2374 chan_list_tlv = (struct mwifiex_ie_types_chan_list_param_set *)tlv_pos;
2375
2376 if (bgscan_cfg_in->chan_list[0].chan_number) {
2377 dev_dbg(priv->adapter->dev, "info: bgscan: Using supplied channel list\n");
2378
2379 chan_list_tlv->header.type = cpu_to_le16(TLV_TYPE_CHANLIST);
2380
2381 for (chan_idx = 0;
2382 chan_idx < MWIFIEX_BG_SCAN_CHAN_MAX &&
2383 bgscan_cfg_in->chan_list[chan_idx].chan_number;
2384 chan_idx++) {
2385 temp_chan = chan_list_tlv->chan_scan_param + chan_idx;
2386
2387
2388 le16_unaligned_add_cpu(&chan_list_tlv->header.len,
2389 sizeof(
2390 chan_list_tlv->chan_scan_param));
2391
2392 temp_chan->chan_number =
2393 bgscan_cfg_in->chan_list[chan_idx].chan_number;
2394 temp_chan->radio_type =
2395 bgscan_cfg_in->chan_list[chan_idx].radio_type;
2396
2397 scan_type =
2398 bgscan_cfg_in->chan_list[chan_idx].scan_type;
2399
2400 if (scan_type == MWIFIEX_SCAN_TYPE_PASSIVE)
2401 temp_chan->chan_scan_mode_bitmap
2402 |= MWIFIEX_PASSIVE_SCAN;
2403 else
2404 temp_chan->chan_scan_mode_bitmap
2405 &= ~MWIFIEX_PASSIVE_SCAN;
2406
2407 if (bgscan_cfg_in->chan_list[chan_idx].scan_time) {
2408 scan_dur = (u16)bgscan_cfg_in->
2409 chan_list[chan_idx].scan_time;
2410 } else {
2411 scan_dur = (scan_type ==
2412 MWIFIEX_SCAN_TYPE_PASSIVE) ?
2413 priv->adapter->passive_scan_time :
2414 priv->adapter->specific_scan_time;
2415 }
2416
2417 temp_chan->min_scan_time = cpu_to_le16(scan_dur);
2418 temp_chan->max_scan_time = cpu_to_le16(scan_dur);
2419 }
2420 } else {
2421 dev_dbg(priv->adapter->dev,
2422 "info: bgscan: Creating full region channel list\n");
2423 chan_num =
2424 mwifiex_bgscan_create_channel_list(priv, bgscan_cfg_in,
2425 chan_list_tlv->
2426 chan_scan_param);
2427 le16_unaligned_add_cpu(&chan_list_tlv->header.len,
2428 chan_num *
2429 sizeof(chan_list_tlv->chan_scan_param[0]));
2430 }
2431
2432 tlv_pos += (sizeof(chan_list_tlv->header)
2433 + le16_to_cpu(chan_list_tlv->header.len));
2434
2435 if (bgscan_cfg_in->start_later) {
2436 start_later_tlv =
2437 (struct mwifiex_ie_types_bgscan_start_later *)tlv_pos;
2438 start_later_tlv->header.type =
2439 cpu_to_le16(TLV_TYPE_BGSCAN_START_LATER);
2440 start_later_tlv->header.len =
2441 cpu_to_le16(sizeof(start_later_tlv->start_later));
2442 start_later_tlv->start_later =
2443 cpu_to_le16(bgscan_cfg_in->start_later);
2444
2445 tlv_pos += sizeof(start_later_tlv->header) +
2446 le16_to_cpu(start_later_tlv->header.len);
2447 }
2448
2449
2450 mwifiex_cmd_append_vsie_tlv(priv, MWIFIEX_VSIE_MASK_BGSCAN, &tlv_pos);
2451
2452 le16_unaligned_add_cpu(&cmd->size, tlv_pos - bgscan_config->tlv);
2453
2454 return 0;
2455}
2456
2457int mwifiex_stop_bg_scan(struct mwifiex_private *priv)
2458{
2459 struct mwifiex_bg_scan_cfg *bgscan_cfg;
2460
2461 if (!priv->sched_scanning) {
2462 dev_dbg(priv->adapter->dev, "bgscan already stopped!\n");
2463 return 0;
2464 }
2465
2466 bgscan_cfg = kzalloc(sizeof(*bgscan_cfg), GFP_KERNEL);
2467 if (!bgscan_cfg)
2468 return -ENOMEM;
2469
2470 bgscan_cfg->bss_type = MWIFIEX_BSS_MODE_INFRA;
2471 bgscan_cfg->action = MWIFIEX_BGSCAN_ACT_SET;
2472 bgscan_cfg->enable = false;
2473
2474 if (mwifiex_send_cmd(priv, HostCmd_CMD_802_11_BG_SCAN_CONFIG,
2475 HostCmd_ACT_GEN_SET, 0, bgscan_cfg, true)) {
2476 kfree(bgscan_cfg);
2477 return -EFAULT;
2478 }
2479
2480 kfree(bgscan_cfg);
2481 priv->sched_scanning = false;
2482
2483 return 0;
2484}
2485
2486static void
2487mwifiex_update_chan_statistics(struct mwifiex_private *priv,
2488 struct mwifiex_ietypes_chanstats *tlv_stat)
2489{
2490 struct mwifiex_adapter *adapter = priv->adapter;
2491 u8 i, num_chan;
2492 struct mwifiex_fw_chan_stats *fw_chan_stats;
2493 struct mwifiex_chan_stats chan_stats;
2494
2495 fw_chan_stats = (void *)((u8 *)tlv_stat +
2496 sizeof(struct mwifiex_ie_types_header));
2497 num_chan = le16_to_cpu(tlv_stat->header.len) /
2498 sizeof(struct mwifiex_chan_stats);
2499
2500 for (i = 0 ; i < num_chan; i++) {
2501 if (adapter->survey_idx >= adapter->num_in_chan_stats) {
2502 mwifiex_dbg(adapter, WARN,
2503 "FW reported too many channel results (max %d)\n",
2504 adapter->num_in_chan_stats);
2505 return;
2506 }
2507 chan_stats.chan_num = fw_chan_stats->chan_num;
2508 chan_stats.bandcfg = fw_chan_stats->bandcfg;
2509 chan_stats.flags = fw_chan_stats->flags;
2510 chan_stats.noise = fw_chan_stats->noise;
2511 chan_stats.total_bss = le16_to_cpu(fw_chan_stats->total_bss);
2512 chan_stats.cca_scan_dur =
2513 le16_to_cpu(fw_chan_stats->cca_scan_dur);
2514 chan_stats.cca_busy_dur =
2515 le16_to_cpu(fw_chan_stats->cca_busy_dur);
2516 mwifiex_dbg(adapter, INFO,
2517 "chan=%d, noise=%d, total_network=%d scan_duration=%d, busy_duration=%d\n",
2518 chan_stats.chan_num,
2519 chan_stats.noise,
2520 chan_stats.total_bss,
2521 chan_stats.cca_scan_dur,
2522 chan_stats.cca_busy_dur);
2523 memcpy(&adapter->chan_stats[adapter->survey_idx++], &chan_stats,
2524 sizeof(struct mwifiex_chan_stats));
2525 fw_chan_stats++;
2526 }
2527}
2528
2529
2530int mwifiex_ret_802_11_scan_ext(struct mwifiex_private *priv,
2531 struct host_cmd_ds_command *resp)
2532{
2533 struct mwifiex_adapter *adapter = priv->adapter;
2534 struct host_cmd_ds_802_11_scan_ext *ext_scan_resp;
2535 struct mwifiex_ie_types_header *tlv;
2536 struct mwifiex_ietypes_chanstats *tlv_stat;
2537 u16 buf_left, type, len;
2538
2539 struct host_cmd_ds_command *cmd_ptr;
2540 struct cmd_ctrl_node *cmd_node;
2541 unsigned long cmd_flags, scan_flags;
2542 bool complete_scan = false;
2543
2544 mwifiex_dbg(adapter, INFO, "info: EXT scan returns successfully\n");
2545
2546 ext_scan_resp = &resp->params.ext_scan;
2547
2548 tlv = (void *)ext_scan_resp->tlv_buffer;
2549 buf_left = le16_to_cpu(resp->size) - (sizeof(*ext_scan_resp) + S_DS_GEN
2550 - 1);
2551
2552 while (buf_left >= sizeof(struct mwifiex_ie_types_header)) {
2553 type = le16_to_cpu(tlv->type);
2554 len = le16_to_cpu(tlv->len);
2555
2556 if (buf_left < (sizeof(struct mwifiex_ie_types_header) + len)) {
2557 mwifiex_dbg(adapter, ERROR,
2558 "error processing scan response TLVs");
2559 break;
2560 }
2561
2562 switch (type) {
2563 case TLV_TYPE_CHANNEL_STATS:
2564 tlv_stat = (void *)tlv;
2565 mwifiex_update_chan_statistics(priv, tlv_stat);
2566 break;
2567 default:
2568 break;
2569 }
2570
2571 buf_left -= len + sizeof(struct mwifiex_ie_types_header);
2572 tlv = (void *)((u8 *)tlv + len +
2573 sizeof(struct mwifiex_ie_types_header));
2574 }
2575
2576 spin_lock_irqsave(&adapter->cmd_pending_q_lock, cmd_flags);
2577 spin_lock_irqsave(&adapter->scan_pending_q_lock, scan_flags);
2578 if (list_empty(&adapter->scan_pending_q)) {
2579 complete_scan = true;
2580 list_for_each_entry(cmd_node, &adapter->cmd_pending_q, list) {
2581 cmd_ptr = (void *)cmd_node->cmd_skb->data;
2582 if (le16_to_cpu(cmd_ptr->command) ==
2583 HostCmd_CMD_802_11_SCAN_EXT) {
2584 mwifiex_dbg(adapter, INFO,
2585 "Scan pending in command pending list");
2586 complete_scan = false;
2587 break;
2588 }
2589 }
2590 }
2591 spin_unlock_irqrestore(&adapter->scan_pending_q_lock, scan_flags);
2592 spin_unlock_irqrestore(&adapter->cmd_pending_q_lock, cmd_flags);
2593
2594 if (complete_scan)
2595 mwifiex_complete_scan(priv);
2596
2597 return 0;
2598}
2599
2600
2601
2602
2603int mwifiex_handle_event_ext_scan_report(struct mwifiex_private *priv,
2604 void *buf)
2605{
2606 int ret = 0;
2607 struct mwifiex_adapter *adapter = priv->adapter;
2608 u8 *bss_info;
2609 u32 bytes_left, bytes_left_for_tlv, idx;
2610 u16 type, len;
2611 struct mwifiex_ie_types_data *tlv;
2612 struct mwifiex_ie_types_bss_scan_rsp *scan_rsp_tlv;
2613 struct mwifiex_ie_types_bss_scan_info *scan_info_tlv;
2614 u8 *radio_type;
2615 u64 fw_tsf = 0;
2616 s32 rssi = 0;
2617 struct mwifiex_event_scan_result *event_scan = buf;
2618 u8 num_of_set = event_scan->num_of_set;
2619 u8 *scan_resp = buf + sizeof(struct mwifiex_event_scan_result);
2620 u16 scan_resp_size = le16_to_cpu(event_scan->buf_size);
2621
2622 if (num_of_set > MWIFIEX_MAX_AP) {
2623 mwifiex_dbg(adapter, ERROR,
2624 "EXT_SCAN: Invalid number of AP returned (%d)!!\n",
2625 num_of_set);
2626 ret = -1;
2627 goto check_next_scan;
2628 }
2629
2630 bytes_left = scan_resp_size;
2631 mwifiex_dbg(adapter, INFO,
2632 "EXT_SCAN: size %d, returned %d APs...",
2633 scan_resp_size, num_of_set);
2634 mwifiex_dbg_dump(adapter, CMD_D, "EXT_SCAN buffer:", buf,
2635 scan_resp_size +
2636 sizeof(struct mwifiex_event_scan_result));
2637
2638 tlv = (struct mwifiex_ie_types_data *)scan_resp;
2639
2640 for (idx = 0; idx < num_of_set && bytes_left; idx++) {
2641 type = le16_to_cpu(tlv->header.type);
2642 len = le16_to_cpu(tlv->header.len);
2643 if (bytes_left < sizeof(struct mwifiex_ie_types_header) + len) {
2644 mwifiex_dbg(adapter, ERROR,
2645 "EXT_SCAN: Error bytes left < TLV length\n");
2646 break;
2647 }
2648 scan_rsp_tlv = NULL;
2649 scan_info_tlv = NULL;
2650 bytes_left_for_tlv = bytes_left;
2651
2652
2653
2654
2655 if (type != TLV_TYPE_BSS_SCAN_RSP)
2656 break;
2657
2658 bss_info = (u8 *)tlv;
2659 scan_rsp_tlv = (struct mwifiex_ie_types_bss_scan_rsp *)tlv;
2660 tlv = (struct mwifiex_ie_types_data *)(tlv->data + len);
2661 bytes_left_for_tlv -=
2662 (len + sizeof(struct mwifiex_ie_types_header));
2663
2664 while (bytes_left_for_tlv >=
2665 sizeof(struct mwifiex_ie_types_header) &&
2666 le16_to_cpu(tlv->header.type) != TLV_TYPE_BSS_SCAN_RSP) {
2667 type = le16_to_cpu(tlv->header.type);
2668 len = le16_to_cpu(tlv->header.len);
2669 if (bytes_left_for_tlv <
2670 sizeof(struct mwifiex_ie_types_header) + len) {
2671 mwifiex_dbg(adapter, ERROR,
2672 "EXT_SCAN: Error in processing TLV,\t"
2673 "bytes left < TLV length\n");
2674 scan_rsp_tlv = NULL;
2675 bytes_left_for_tlv = 0;
2676 continue;
2677 }
2678 switch (type) {
2679 case TLV_TYPE_BSS_SCAN_INFO:
2680 scan_info_tlv =
2681 (struct mwifiex_ie_types_bss_scan_info *)tlv;
2682 if (len !=
2683 sizeof(struct mwifiex_ie_types_bss_scan_info) -
2684 sizeof(struct mwifiex_ie_types_header)) {
2685 bytes_left_for_tlv = 0;
2686 continue;
2687 }
2688 break;
2689 default:
2690 break;
2691 }
2692 tlv = (struct mwifiex_ie_types_data *)(tlv->data + len);
2693 bytes_left -=
2694 (len + sizeof(struct mwifiex_ie_types_header));
2695 bytes_left_for_tlv -=
2696 (len + sizeof(struct mwifiex_ie_types_header));
2697 }
2698
2699 if (!scan_rsp_tlv)
2700 break;
2701
2702
2703
2704
2705
2706
2707 bss_info += sizeof(u16);
2708 bytes_left -= sizeof(u16);
2709
2710 if (scan_info_tlv) {
2711 rssi = (s32)(s16)(le16_to_cpu(scan_info_tlv->rssi));
2712 rssi *= 100;
2713 mwifiex_dbg(adapter, INFO,
2714 "info: InterpretIE: RSSI=%d\n", rssi);
2715 fw_tsf = le64_to_cpu(scan_info_tlv->tsf);
2716 radio_type = &scan_info_tlv->radio_type;
2717 } else {
2718 radio_type = NULL;
2719 }
2720 ret = mwifiex_parse_single_response_buf(priv, &bss_info,
2721 &bytes_left, fw_tsf,
2722 radio_type, true, rssi);
2723 if (ret)
2724 goto check_next_scan;
2725 }
2726
2727check_next_scan:
2728 if (!event_scan->more_event)
2729 mwifiex_check_next_scan_command(priv);
2730
2731 return ret;
2732}
2733
2734
2735
2736
2737
2738
2739
2740
2741
2742int mwifiex_cmd_802_11_bg_scan_query(struct host_cmd_ds_command *cmd)
2743{
2744 struct host_cmd_ds_802_11_bg_scan_query *bg_query =
2745 &cmd->params.bg_scan_query;
2746
2747 cmd->command = cpu_to_le16(HostCmd_CMD_802_11_BG_SCAN_QUERY);
2748 cmd->size = cpu_to_le16(sizeof(struct host_cmd_ds_802_11_bg_scan_query)
2749 + S_DS_GEN);
2750
2751 bg_query->flush = 1;
2752
2753 return 0;
2754}
2755
2756
2757
2758
2759void
2760mwifiex_queue_scan_cmd(struct mwifiex_private *priv,
2761 struct cmd_ctrl_node *cmd_node)
2762{
2763 struct mwifiex_adapter *adapter = priv->adapter;
2764 unsigned long flags;
2765
2766 cmd_node->wait_q_enabled = true;
2767 cmd_node->condition = &adapter->scan_wait_q_woken;
2768 spin_lock_irqsave(&adapter->scan_pending_q_lock, flags);
2769 list_add_tail(&cmd_node->list, &adapter->scan_pending_q);
2770 spin_unlock_irqrestore(&adapter->scan_pending_q_lock, flags);
2771}
2772
2773
2774
2775
2776
2777static int mwifiex_scan_specific_ssid(struct mwifiex_private *priv,
2778 struct cfg80211_ssid *req_ssid)
2779{
2780 struct mwifiex_adapter *adapter = priv->adapter;
2781 int ret;
2782 struct mwifiex_user_scan_cfg *scan_cfg;
2783
2784 if (adapter->scan_processing) {
2785 mwifiex_dbg(adapter, WARN,
2786 "cmd: Scan already in process...\n");
2787 return -EBUSY;
2788 }
2789
2790 if (priv->scan_block) {
2791 mwifiex_dbg(adapter, WARN,
2792 "cmd: Scan is blocked during association...\n");
2793 return -EBUSY;
2794 }
2795
2796 scan_cfg = kzalloc(sizeof(struct mwifiex_user_scan_cfg), GFP_KERNEL);
2797 if (!scan_cfg)
2798 return -ENOMEM;
2799
2800 scan_cfg->ssid_list = req_ssid;
2801 scan_cfg->num_ssids = 1;
2802
2803 ret = mwifiex_scan_networks(priv, scan_cfg);
2804
2805 kfree(scan_cfg);
2806 return ret;
2807}
2808
2809
2810
2811
2812
2813
2814
2815
2816
2817
2818int mwifiex_request_scan(struct mwifiex_private *priv,
2819 struct cfg80211_ssid *req_ssid)
2820{
2821 int ret;
2822
2823 if (mutex_lock_interruptible(&priv->async_mutex)) {
2824 mwifiex_dbg(priv->adapter, ERROR,
2825 "%s: acquire semaphore fail\n",
2826 __func__);
2827 return -1;
2828 }
2829
2830 priv->adapter->scan_wait_q_woken = false;
2831
2832 if (req_ssid && req_ssid->ssid_len != 0)
2833
2834 ret = mwifiex_scan_specific_ssid(priv, req_ssid);
2835 else
2836
2837 ret = mwifiex_scan_networks(priv, NULL);
2838
2839 mutex_unlock(&priv->async_mutex);
2840
2841 return ret;
2842}
2843
2844
2845
2846
2847int
2848mwifiex_cmd_append_vsie_tlv(struct mwifiex_private *priv,
2849 u16 vsie_mask, u8 **buffer)
2850{
2851 int id, ret_len = 0;
2852 struct mwifiex_ie_types_vendor_param_set *vs_param_set;
2853
2854 if (!buffer)
2855 return 0;
2856 if (!(*buffer))
2857 return 0;
2858
2859
2860
2861
2862
2863 for (id = 0; id < MWIFIEX_MAX_VSIE_NUM; id++) {
2864 if (priv->vs_ie[id].mask & vsie_mask) {
2865 vs_param_set =
2866 (struct mwifiex_ie_types_vendor_param_set *)
2867 *buffer;
2868 vs_param_set->header.type =
2869 cpu_to_le16(TLV_TYPE_PASSTHROUGH);
2870 vs_param_set->header.len =
2871 cpu_to_le16((((u16) priv->vs_ie[id].ie[1])
2872 & 0x00FF) + 2);
2873 memcpy(vs_param_set->ie, priv->vs_ie[id].ie,
2874 le16_to_cpu(vs_param_set->header.len));
2875 *buffer += le16_to_cpu(vs_param_set->header.len) +
2876 sizeof(struct mwifiex_ie_types_header);
2877 ret_len += le16_to_cpu(vs_param_set->header.len) +
2878 sizeof(struct mwifiex_ie_types_header);
2879 }
2880 }
2881 return ret_len;
2882}
2883
2884
2885
2886
2887
2888
2889
2890
2891
2892
2893void
2894mwifiex_save_curr_bcn(struct mwifiex_private *priv)
2895{
2896 struct mwifiex_bssdescriptor *curr_bss =
2897 &priv->curr_bss_params.bss_descriptor;
2898
2899 if (!curr_bss->beacon_buf_size)
2900 return;
2901
2902
2903 if (!priv->curr_bcn_buf ||
2904 priv->curr_bcn_size != curr_bss->beacon_buf_size) {
2905 priv->curr_bcn_size = curr_bss->beacon_buf_size;
2906
2907 kfree(priv->curr_bcn_buf);
2908 priv->curr_bcn_buf = kmalloc(curr_bss->beacon_buf_size,
2909 GFP_ATOMIC);
2910 if (!priv->curr_bcn_buf)
2911 return;
2912 }
2913
2914 memcpy(priv->curr_bcn_buf, curr_bss->beacon_buf,
2915 curr_bss->beacon_buf_size);
2916 mwifiex_dbg(priv->adapter, INFO,
2917 "info: current beacon saved %d\n",
2918 priv->curr_bcn_size);
2919
2920 curr_bss->beacon_buf = priv->curr_bcn_buf;
2921
2922
2923 if (curr_bss->bcn_wpa_ie)
2924 curr_bss->bcn_wpa_ie =
2925 (struct ieee_types_vendor_specific *)
2926 (curr_bss->beacon_buf +
2927 curr_bss->wpa_offset);
2928
2929 if (curr_bss->bcn_rsn_ie)
2930 curr_bss->bcn_rsn_ie = (struct ieee_types_generic *)
2931 (curr_bss->beacon_buf +
2932 curr_bss->rsn_offset);
2933
2934 if (curr_bss->bcn_ht_cap)
2935 curr_bss->bcn_ht_cap = (struct ieee80211_ht_cap *)
2936 (curr_bss->beacon_buf +
2937 curr_bss->ht_cap_offset);
2938
2939 if (curr_bss->bcn_ht_oper)
2940 curr_bss->bcn_ht_oper = (struct ieee80211_ht_operation *)
2941 (curr_bss->beacon_buf +
2942 curr_bss->ht_info_offset);
2943
2944 if (curr_bss->bcn_vht_cap)
2945 curr_bss->bcn_vht_cap = (void *)(curr_bss->beacon_buf +
2946 curr_bss->vht_cap_offset);
2947
2948 if (curr_bss->bcn_vht_oper)
2949 curr_bss->bcn_vht_oper = (void *)(curr_bss->beacon_buf +
2950 curr_bss->vht_info_offset);
2951
2952 if (curr_bss->bcn_bss_co_2040)
2953 curr_bss->bcn_bss_co_2040 =
2954 (curr_bss->beacon_buf + curr_bss->bss_co_2040_offset);
2955
2956 if (curr_bss->bcn_ext_cap)
2957 curr_bss->bcn_ext_cap = curr_bss->beacon_buf +
2958 curr_bss->ext_cap_offset;
2959
2960 if (curr_bss->oper_mode)
2961 curr_bss->oper_mode = (void *)(curr_bss->beacon_buf +
2962 curr_bss->oper_mode_offset);
2963}
2964
2965
2966
2967
2968void
2969mwifiex_free_curr_bcn(struct mwifiex_private *priv)
2970{
2971 kfree(priv->curr_bcn_buf);
2972 priv->curr_bcn_buf = NULL;
2973}
2974