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