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 int ret = 0;
1215 u8 element_id;
1216 struct ieee_types_fh_param_set *fh_param_set;
1217 struct ieee_types_ds_param_set *ds_param_set;
1218 struct ieee_types_cf_param_set *cf_param_set;
1219 struct ieee_types_ibss_param_set *ibss_param_set;
1220 u8 *current_ptr;
1221 u8 *rate;
1222 u8 element_len;
1223 u16 total_ie_len;
1224 u8 bytes_to_copy;
1225 u8 rate_size;
1226 u8 found_data_rate_ie;
1227 u32 bytes_left;
1228 struct ieee_types_vendor_specific *vendor_ie;
1229 const u8 wpa_oui[4] = { 0x00, 0x50, 0xf2, 0x01 };
1230 const u8 wmm_oui[4] = { 0x00, 0x50, 0xf2, 0x02 };
1231
1232 found_data_rate_ie = false;
1233 rate_size = 0;
1234 current_ptr = bss_entry->beacon_buf;
1235 bytes_left = bss_entry->beacon_buf_size;
1236
1237
1238 while (bytes_left >= 2) {
1239 element_id = *current_ptr;
1240 element_len = *(current_ptr + 1);
1241 total_ie_len = element_len + sizeof(struct ieee_types_header);
1242
1243 if (bytes_left < total_ie_len) {
1244 mwifiex_dbg(adapter, ERROR,
1245 "err: InterpretIE: in processing\t"
1246 "IE, bytes left < IE length\n");
1247 return -EINVAL;
1248 }
1249 switch (element_id) {
1250 case WLAN_EID_SSID:
1251 if (element_len > IEEE80211_MAX_SSID_LEN)
1252 return -EINVAL;
1253 bss_entry->ssid.ssid_len = element_len;
1254 memcpy(bss_entry->ssid.ssid, (current_ptr + 2),
1255 element_len);
1256 mwifiex_dbg(adapter, INFO,
1257 "info: InterpretIE: ssid: %-32s\n",
1258 bss_entry->ssid.ssid);
1259 break;
1260
1261 case WLAN_EID_SUPP_RATES:
1262 if (element_len > MWIFIEX_SUPPORTED_RATES)
1263 return -EINVAL;
1264 memcpy(bss_entry->data_rates, current_ptr + 2,
1265 element_len);
1266 memcpy(bss_entry->supported_rates, current_ptr + 2,
1267 element_len);
1268 rate_size = element_len;
1269 found_data_rate_ie = true;
1270 break;
1271
1272 case WLAN_EID_FH_PARAMS:
1273 if (element_len + 2 < sizeof(*fh_param_set))
1274 return -EINVAL;
1275 fh_param_set =
1276 (struct ieee_types_fh_param_set *) current_ptr;
1277 memcpy(&bss_entry->phy_param_set.fh_param_set,
1278 fh_param_set,
1279 sizeof(struct ieee_types_fh_param_set));
1280 break;
1281
1282 case WLAN_EID_DS_PARAMS:
1283 if (element_len + 2 < sizeof(*ds_param_set))
1284 return -EINVAL;
1285 ds_param_set =
1286 (struct ieee_types_ds_param_set *) current_ptr;
1287
1288 bss_entry->channel = ds_param_set->current_chan;
1289
1290 memcpy(&bss_entry->phy_param_set.ds_param_set,
1291 ds_param_set,
1292 sizeof(struct ieee_types_ds_param_set));
1293 break;
1294
1295 case WLAN_EID_CF_PARAMS:
1296 if (element_len + 2 < sizeof(*cf_param_set))
1297 return -EINVAL;
1298 cf_param_set =
1299 (struct ieee_types_cf_param_set *) current_ptr;
1300 memcpy(&bss_entry->ss_param_set.cf_param_set,
1301 cf_param_set,
1302 sizeof(struct ieee_types_cf_param_set));
1303 break;
1304
1305 case WLAN_EID_IBSS_PARAMS:
1306 if (element_len + 2 < sizeof(*ibss_param_set))
1307 return -EINVAL;
1308 ibss_param_set =
1309 (struct ieee_types_ibss_param_set *)
1310 current_ptr;
1311 memcpy(&bss_entry->ss_param_set.ibss_param_set,
1312 ibss_param_set,
1313 sizeof(struct ieee_types_ibss_param_set));
1314 break;
1315
1316 case WLAN_EID_ERP_INFO:
1317 if (!element_len)
1318 return -EINVAL;
1319 bss_entry->erp_flags = *(current_ptr + 2);
1320 break;
1321
1322 case WLAN_EID_PWR_CONSTRAINT:
1323 if (!element_len)
1324 return -EINVAL;
1325 bss_entry->local_constraint = *(current_ptr + 2);
1326 bss_entry->sensed_11h = true;
1327 break;
1328
1329 case WLAN_EID_CHANNEL_SWITCH:
1330 bss_entry->chan_sw_ie_present = true;
1331
1332 case WLAN_EID_PWR_CAPABILITY:
1333 case WLAN_EID_TPC_REPORT:
1334 case WLAN_EID_QUIET:
1335 bss_entry->sensed_11h = true;
1336 break;
1337
1338 case WLAN_EID_EXT_SUPP_RATES:
1339
1340
1341
1342
1343
1344
1345 if (found_data_rate_ie) {
1346 if ((element_len + rate_size) >
1347 MWIFIEX_SUPPORTED_RATES)
1348 bytes_to_copy =
1349 (MWIFIEX_SUPPORTED_RATES -
1350 rate_size);
1351 else
1352 bytes_to_copy = element_len;
1353
1354 rate = (u8 *) bss_entry->data_rates;
1355 rate += rate_size;
1356 memcpy(rate, current_ptr + 2, bytes_to_copy);
1357
1358 rate = (u8 *) bss_entry->supported_rates;
1359 rate += rate_size;
1360 memcpy(rate, current_ptr + 2, bytes_to_copy);
1361 }
1362 break;
1363
1364 case WLAN_EID_VENDOR_SPECIFIC:
1365 vendor_ie = (struct ieee_types_vendor_specific *)
1366 current_ptr;
1367
1368
1369 if (element_len < sizeof(vendor_ie->vend_hdr.oui.oui))
1370 return -EINVAL;
1371
1372
1373 if (element_len < sizeof(wpa_oui))
1374 break;
1375
1376 if (!memcmp(&vendor_ie->vend_hdr.oui, wpa_oui,
1377 sizeof(wpa_oui))) {
1378 bss_entry->bcn_wpa_ie =
1379 (struct ieee_types_vendor_specific *)
1380 current_ptr;
1381 bss_entry->wpa_offset = (u16)
1382 (current_ptr - bss_entry->beacon_buf);
1383 } else if (!memcmp(&vendor_ie->vend_hdr.oui, wmm_oui,
1384 sizeof(wmm_oui))) {
1385 if (total_ie_len ==
1386 sizeof(struct ieee_types_wmm_parameter) ||
1387 total_ie_len ==
1388 sizeof(struct ieee_types_wmm_info))
1389
1390
1391
1392
1393
1394 memcpy((u8 *) &bss_entry->wmm_ie,
1395 current_ptr, total_ie_len);
1396 }
1397 break;
1398 case WLAN_EID_RSN:
1399 bss_entry->bcn_rsn_ie =
1400 (struct ieee_types_generic *) current_ptr;
1401 bss_entry->rsn_offset = (u16) (current_ptr -
1402 bss_entry->beacon_buf);
1403 break;
1404 case WLAN_EID_BSS_AC_ACCESS_DELAY:
1405 bss_entry->bcn_wapi_ie =
1406 (struct ieee_types_generic *) current_ptr;
1407 bss_entry->wapi_offset = (u16) (current_ptr -
1408 bss_entry->beacon_buf);
1409 break;
1410 case WLAN_EID_HT_CAPABILITY:
1411 bss_entry->bcn_ht_cap = (struct ieee80211_ht_cap *)
1412 (current_ptr +
1413 sizeof(struct ieee_types_header));
1414 bss_entry->ht_cap_offset = (u16) (current_ptr +
1415 sizeof(struct ieee_types_header) -
1416 bss_entry->beacon_buf);
1417 break;
1418 case WLAN_EID_HT_OPERATION:
1419 bss_entry->bcn_ht_oper =
1420 (struct ieee80211_ht_operation *)(current_ptr +
1421 sizeof(struct ieee_types_header));
1422 bss_entry->ht_info_offset = (u16) (current_ptr +
1423 sizeof(struct ieee_types_header) -
1424 bss_entry->beacon_buf);
1425 break;
1426 case WLAN_EID_VHT_CAPABILITY:
1427 bss_entry->disable_11ac = false;
1428 bss_entry->bcn_vht_cap =
1429 (void *)(current_ptr +
1430 sizeof(struct ieee_types_header));
1431 bss_entry->vht_cap_offset =
1432 (u16)((u8 *)bss_entry->bcn_vht_cap -
1433 bss_entry->beacon_buf);
1434 break;
1435 case WLAN_EID_VHT_OPERATION:
1436 bss_entry->bcn_vht_oper =
1437 (void *)(current_ptr +
1438 sizeof(struct ieee_types_header));
1439 bss_entry->vht_info_offset =
1440 (u16)((u8 *)bss_entry->bcn_vht_oper -
1441 bss_entry->beacon_buf);
1442 break;
1443 case WLAN_EID_BSS_COEX_2040:
1444 bss_entry->bcn_bss_co_2040 = current_ptr;
1445 bss_entry->bss_co_2040_offset =
1446 (u16) (current_ptr - bss_entry->beacon_buf);
1447 break;
1448 case WLAN_EID_EXT_CAPABILITY:
1449 bss_entry->bcn_ext_cap = current_ptr;
1450 bss_entry->ext_cap_offset =
1451 (u16) (current_ptr - bss_entry->beacon_buf);
1452 break;
1453 case WLAN_EID_OPMODE_NOTIF:
1454 bss_entry->oper_mode = (void *)current_ptr;
1455 bss_entry->oper_mode_offset =
1456 (u16)((u8 *)bss_entry->oper_mode -
1457 bss_entry->beacon_buf);
1458 break;
1459 default:
1460 break;
1461 }
1462
1463 current_ptr += element_len + 2;
1464
1465
1466 bytes_left -= (element_len + 2);
1467
1468 }
1469 return ret;
1470}
1471
1472
1473
1474
1475
1476static u8
1477mwifiex_radio_type_to_band(u8 radio_type)
1478{
1479 switch (radio_type) {
1480 case HostCmd_SCAN_RADIO_TYPE_A:
1481 return BAND_A;
1482 case HostCmd_SCAN_RADIO_TYPE_BG:
1483 default:
1484 return BAND_G;
1485 }
1486}
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496int mwifiex_scan_networks(struct mwifiex_private *priv,
1497 const struct mwifiex_user_scan_cfg *user_scan_in)
1498{
1499 int ret;
1500 struct mwifiex_adapter *adapter = priv->adapter;
1501 struct cmd_ctrl_node *cmd_node;
1502 union mwifiex_scan_cmd_config_tlv *scan_cfg_out;
1503 struct mwifiex_ie_types_chan_list_param_set *chan_list_out;
1504 struct mwifiex_chan_scan_param_set *scan_chan_list;
1505 u8 filtered_scan;
1506 u8 scan_current_chan_only;
1507 u8 max_chan_per_scan;
1508
1509 if (adapter->scan_processing) {
1510 mwifiex_dbg(adapter, WARN,
1511 "cmd: Scan already in process...\n");
1512 return -EBUSY;
1513 }
1514
1515 if (priv->scan_block) {
1516 mwifiex_dbg(adapter, WARN,
1517 "cmd: Scan is blocked during association...\n");
1518 return -EBUSY;
1519 }
1520
1521 if (test_bit(MWIFIEX_SURPRISE_REMOVED, &adapter->work_flags) ||
1522 test_bit(MWIFIEX_IS_CMD_TIMEDOUT, &adapter->work_flags)) {
1523 mwifiex_dbg(adapter, ERROR,
1524 "Ignore scan. Card removed or firmware in bad state\n");
1525 return -EFAULT;
1526 }
1527
1528 spin_lock_bh(&adapter->mwifiex_cmd_lock);
1529 adapter->scan_processing = true;
1530 spin_unlock_bh(&adapter->mwifiex_cmd_lock);
1531
1532 scan_cfg_out = kzalloc(sizeof(union mwifiex_scan_cmd_config_tlv),
1533 GFP_KERNEL);
1534 if (!scan_cfg_out) {
1535 ret = -ENOMEM;
1536 goto done;
1537 }
1538
1539 scan_chan_list = kcalloc(MWIFIEX_USER_SCAN_CHAN_MAX,
1540 sizeof(struct mwifiex_chan_scan_param_set),
1541 GFP_KERNEL);
1542 if (!scan_chan_list) {
1543 kfree(scan_cfg_out);
1544 ret = -ENOMEM;
1545 goto done;
1546 }
1547
1548 mwifiex_config_scan(priv, user_scan_in, &scan_cfg_out->config,
1549 &chan_list_out, scan_chan_list, &max_chan_per_scan,
1550 &filtered_scan, &scan_current_chan_only);
1551
1552 ret = mwifiex_scan_channel_list(priv, max_chan_per_scan, filtered_scan,
1553 &scan_cfg_out->config, chan_list_out,
1554 scan_chan_list);
1555
1556
1557 if (!ret) {
1558 spin_lock_bh(&adapter->scan_pending_q_lock);
1559 if (!list_empty(&adapter->scan_pending_q)) {
1560 cmd_node = list_first_entry(&adapter->scan_pending_q,
1561 struct cmd_ctrl_node, list);
1562 list_del(&cmd_node->list);
1563 spin_unlock_bh(&adapter->scan_pending_q_lock);
1564 mwifiex_insert_cmd_to_pending_q(adapter, cmd_node);
1565 queue_work(adapter->workqueue, &adapter->main_work);
1566
1567
1568 if (!priv->scan_request) {
1569 mwifiex_dbg(adapter, INFO,
1570 "wait internal scan\n");
1571 mwifiex_wait_queue_complete(adapter, cmd_node);
1572 }
1573 } else {
1574 spin_unlock_bh(&adapter->scan_pending_q_lock);
1575 }
1576 }
1577
1578 kfree(scan_cfg_out);
1579 kfree(scan_chan_list);
1580done:
1581 if (ret) {
1582 spin_lock_bh(&adapter->mwifiex_cmd_lock);
1583 adapter->scan_processing = false;
1584 spin_unlock_bh(&adapter->mwifiex_cmd_lock);
1585 }
1586 return ret;
1587}
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603int mwifiex_cmd_802_11_scan(struct host_cmd_ds_command *cmd,
1604 struct mwifiex_scan_cmd_config *scan_cfg)
1605{
1606 struct host_cmd_ds_802_11_scan *scan_cmd = &cmd->params.scan;
1607
1608
1609 scan_cmd->bss_mode = scan_cfg->bss_mode;
1610 memcpy(scan_cmd->bssid, scan_cfg->specific_bssid,
1611 sizeof(scan_cmd->bssid));
1612 memcpy(scan_cmd->tlv_buffer, scan_cfg->tlv_buf, scan_cfg->tlv_buf_len);
1613
1614 cmd->command = cpu_to_le16(HostCmd_CMD_802_11_SCAN);
1615
1616
1617 cmd->size = cpu_to_le16((u16) (sizeof(scan_cmd->bss_mode)
1618 + sizeof(scan_cmd->bssid)
1619 + scan_cfg->tlv_buf_len + S_DS_GEN));
1620
1621 return 0;
1622}
1623
1624
1625
1626
1627
1628int mwifiex_check_network_compatibility(struct mwifiex_private *priv,
1629 struct mwifiex_bssdescriptor *bss_desc)
1630{
1631 int ret = -1;
1632
1633 if (!bss_desc)
1634 return -1;
1635
1636 if ((mwifiex_get_cfp(priv, (u8) bss_desc->bss_band,
1637 (u16) bss_desc->channel, 0))) {
1638 switch (priv->bss_mode) {
1639 case NL80211_IFTYPE_STATION:
1640 case NL80211_IFTYPE_ADHOC:
1641 ret = mwifiex_is_network_compatible(priv, bss_desc,
1642 priv->bss_mode);
1643 if (ret)
1644 mwifiex_dbg(priv->adapter, ERROR,
1645 "Incompatible network settings\n");
1646 break;
1647 default:
1648 ret = 0;
1649 }
1650 }
1651
1652 return ret;
1653}
1654
1655
1656static bool mwifiex_is_hidden_ssid(struct cfg80211_ssid *ssid)
1657{
1658 int idx;
1659
1660 for (idx = 0; idx < ssid->ssid_len; idx++) {
1661 if (ssid->ssid[idx])
1662 return false;
1663 }
1664
1665 return true;
1666}
1667
1668
1669
1670
1671static int mwifiex_save_hidden_ssid_channels(struct mwifiex_private *priv,
1672 struct cfg80211_bss *bss)
1673{
1674 struct mwifiex_bssdescriptor *bss_desc;
1675 int ret;
1676 int chid;
1677
1678
1679 bss_desc = kzalloc(sizeof(*bss_desc), GFP_KERNEL);
1680 if (!bss_desc)
1681 return -ENOMEM;
1682
1683 ret = mwifiex_fill_new_bss_desc(priv, bss, bss_desc);
1684 if (ret)
1685 goto done;
1686
1687 if (mwifiex_is_hidden_ssid(&bss_desc->ssid)) {
1688 mwifiex_dbg(priv->adapter, INFO, "found hidden SSID\n");
1689 for (chid = 0 ; chid < MWIFIEX_USER_SCAN_CHAN_MAX; chid++) {
1690 if (priv->hidden_chan[chid].chan_number ==
1691 bss->channel->hw_value)
1692 break;
1693
1694 if (!priv->hidden_chan[chid].chan_number) {
1695 priv->hidden_chan[chid].chan_number =
1696 bss->channel->hw_value;
1697 priv->hidden_chan[chid].radio_type =
1698 bss->channel->band;
1699 priv->hidden_chan[chid].scan_type =
1700 MWIFIEX_SCAN_TYPE_ACTIVE;
1701 break;
1702 }
1703 }
1704 }
1705
1706done:
1707
1708
1709
1710 kfree(bss_desc->beacon_buf);
1711 kfree(bss_desc);
1712 return 0;
1713}
1714
1715static int mwifiex_update_curr_bss_params(struct mwifiex_private *priv,
1716 struct cfg80211_bss *bss)
1717{
1718 struct mwifiex_bssdescriptor *bss_desc;
1719 int ret;
1720
1721
1722 bss_desc = kzalloc(sizeof(struct mwifiex_bssdescriptor), GFP_KERNEL);
1723 if (!bss_desc)
1724 return -ENOMEM;
1725
1726 ret = mwifiex_fill_new_bss_desc(priv, bss, bss_desc);
1727 if (ret)
1728 goto done;
1729
1730 ret = mwifiex_check_network_compatibility(priv, bss_desc);
1731 if (ret)
1732 goto done;
1733
1734 spin_lock_bh(&priv->curr_bcn_buf_lock);
1735
1736 memcpy(&priv->curr_bss_params.bss_descriptor, bss_desc,
1737 sizeof(priv->curr_bss_params.bss_descriptor));
1738
1739
1740
1741
1742 mwifiex_save_curr_bcn(priv);
1743 spin_unlock_bh(&priv->curr_bcn_buf_lock);
1744
1745done:
1746
1747
1748
1749 kfree(bss_desc->beacon_buf);
1750 kfree(bss_desc);
1751 return 0;
1752}
1753
1754static int
1755mwifiex_parse_single_response_buf(struct mwifiex_private *priv, u8 **bss_info,
1756 u32 *bytes_left, u64 fw_tsf, u8 *radio_type,
1757 bool ext_scan, s32 rssi_val)
1758{
1759 struct mwifiex_adapter *adapter = priv->adapter;
1760 struct mwifiex_chan_freq_power *cfp;
1761 struct cfg80211_bss *bss;
1762 u8 bssid[ETH_ALEN];
1763 s32 rssi;
1764 const u8 *ie_buf;
1765 size_t ie_len;
1766 u16 channel = 0;
1767 u16 beacon_size = 0;
1768 u32 curr_bcn_bytes;
1769 u32 freq;
1770 u16 beacon_period;
1771 u16 cap_info_bitmap;
1772 u8 *current_ptr;
1773 u64 timestamp;
1774 struct mwifiex_fixed_bcn_param *bcn_param;
1775 struct mwifiex_bss_priv *bss_priv;
1776
1777 if (*bytes_left >= sizeof(beacon_size)) {
1778
1779 beacon_size = get_unaligned_le16((*bss_info));
1780 *bytes_left -= sizeof(beacon_size);
1781 *bss_info += sizeof(beacon_size);
1782 }
1783
1784 if (!beacon_size || beacon_size > *bytes_left) {
1785 *bss_info += *bytes_left;
1786 *bytes_left = 0;
1787 return -EFAULT;
1788 }
1789
1790
1791
1792
1793 current_ptr = *bss_info;
1794
1795
1796 *bss_info += beacon_size;
1797 *bytes_left -= beacon_size;
1798
1799 curr_bcn_bytes = beacon_size;
1800
1801
1802
1803
1804 if (curr_bcn_bytes < ETH_ALEN + sizeof(u8) +
1805 sizeof(struct mwifiex_fixed_bcn_param)) {
1806 mwifiex_dbg(adapter, ERROR,
1807 "InterpretIE: not enough bytes left\n");
1808 return -EFAULT;
1809 }
1810
1811 memcpy(bssid, current_ptr, ETH_ALEN);
1812 current_ptr += ETH_ALEN;
1813 curr_bcn_bytes -= ETH_ALEN;
1814
1815 if (!ext_scan) {
1816 rssi = (s32) *current_ptr;
1817 rssi = (-rssi) * 100;
1818 current_ptr += sizeof(u8);
1819 curr_bcn_bytes -= sizeof(u8);
1820 mwifiex_dbg(adapter, INFO,
1821 "info: InterpretIE: RSSI=%d\n", rssi);
1822 } else {
1823 rssi = rssi_val;
1824 }
1825
1826 bcn_param = (struct mwifiex_fixed_bcn_param *)current_ptr;
1827 current_ptr += sizeof(*bcn_param);
1828 curr_bcn_bytes -= sizeof(*bcn_param);
1829
1830 timestamp = le64_to_cpu(bcn_param->timestamp);
1831 beacon_period = le16_to_cpu(bcn_param->beacon_period);
1832
1833 cap_info_bitmap = le16_to_cpu(bcn_param->cap_info_bitmap);
1834 mwifiex_dbg(adapter, INFO,
1835 "info: InterpretIE: capabilities=0x%X\n",
1836 cap_info_bitmap);
1837
1838
1839 ie_buf = current_ptr;
1840 ie_len = curr_bcn_bytes;
1841 mwifiex_dbg(adapter, INFO,
1842 "info: InterpretIE: IELength for this AP = %d\n",
1843 curr_bcn_bytes);
1844
1845 while (curr_bcn_bytes >= sizeof(struct ieee_types_header)) {
1846 u8 element_id, element_len;
1847
1848 element_id = *current_ptr;
1849 element_len = *(current_ptr + 1);
1850 if (curr_bcn_bytes < element_len +
1851 sizeof(struct ieee_types_header)) {
1852 mwifiex_dbg(adapter, ERROR,
1853 "%s: bytes left < IE length\n", __func__);
1854 return -EFAULT;
1855 }
1856 if (element_id == WLAN_EID_DS_PARAMS) {
1857 channel = *(current_ptr +
1858 sizeof(struct ieee_types_header));
1859 break;
1860 }
1861
1862 current_ptr += element_len + sizeof(struct ieee_types_header);
1863 curr_bcn_bytes -= element_len +
1864 sizeof(struct ieee_types_header);
1865 }
1866
1867 if (channel) {
1868 struct ieee80211_channel *chan;
1869 u8 band;
1870
1871
1872 if (channel == priv->csa_chan) {
1873 mwifiex_dbg(adapter, WARN,
1874 "Dropping entry on csa closed channel\n");
1875 return 0;
1876 }
1877
1878 band = BAND_G;
1879 if (radio_type)
1880 band = mwifiex_radio_type_to_band(*radio_type &
1881 (BIT(0) | BIT(1)));
1882
1883 cfp = mwifiex_get_cfp(priv, band, channel, 0);
1884
1885 freq = cfp ? cfp->freq : 0;
1886
1887 chan = ieee80211_get_channel(priv->wdev.wiphy, freq);
1888
1889 if (chan && !(chan->flags & IEEE80211_CHAN_DISABLED)) {
1890 bss = cfg80211_inform_bss(priv->wdev.wiphy,
1891 chan, CFG80211_BSS_FTYPE_UNKNOWN,
1892 bssid, timestamp,
1893 cap_info_bitmap, beacon_period,
1894 ie_buf, ie_len, rssi, GFP_KERNEL);
1895 if (bss) {
1896 bss_priv = (struct mwifiex_bss_priv *)bss->priv;
1897 bss_priv->band = band;
1898 bss_priv->fw_tsf = fw_tsf;
1899 if (priv->media_connected &&
1900 !memcmp(bssid, priv->curr_bss_params.
1901 bss_descriptor.mac_address,
1902 ETH_ALEN))
1903 mwifiex_update_curr_bss_params(priv,
1904 bss);
1905
1906 if ((chan->flags & IEEE80211_CHAN_RADAR) ||
1907 (chan->flags & IEEE80211_CHAN_NO_IR)) {
1908 mwifiex_dbg(adapter, INFO,
1909 "radar or passive channel %d\n",
1910 channel);
1911 mwifiex_save_hidden_ssid_channels(priv,
1912 bss);
1913 }
1914
1915 cfg80211_put_bss(priv->wdev.wiphy, bss);
1916 }
1917 }
1918 } else {
1919 mwifiex_dbg(adapter, WARN, "missing BSS channel IE\n");
1920 }
1921
1922 return 0;
1923}
1924
1925static void mwifiex_complete_scan(struct mwifiex_private *priv)
1926{
1927 struct mwifiex_adapter *adapter = priv->adapter;
1928
1929 adapter->survey_idx = 0;
1930 if (adapter->curr_cmd->wait_q_enabled) {
1931 adapter->cmd_wait_q.status = 0;
1932 if (!priv->scan_request) {
1933 mwifiex_dbg(adapter, INFO,
1934 "complete internal scan\n");
1935 mwifiex_complete_cmd(adapter, adapter->curr_cmd);
1936 }
1937 }
1938}
1939
1940
1941
1942
1943static int
1944mwifiex_active_scan_req_for_passive_chan(struct mwifiex_private *priv)
1945{
1946 int ret;
1947 struct mwifiex_adapter *adapter = priv->adapter;
1948 u8 id = 0;
1949 struct mwifiex_user_scan_cfg *user_scan_cfg;
1950
1951 if (adapter->active_scan_triggered || !priv->scan_request ||
1952 priv->scan_aborting) {
1953 adapter->active_scan_triggered = false;
1954 return 0;
1955 }
1956
1957 if (!priv->hidden_chan[0].chan_number) {
1958 mwifiex_dbg(adapter, INFO, "No BSS with hidden SSID found on DFS channels\n");
1959 return 0;
1960 }
1961 user_scan_cfg = kzalloc(sizeof(*user_scan_cfg), GFP_KERNEL);
1962
1963 if (!user_scan_cfg)
1964 return -ENOMEM;
1965
1966 for (id = 0; id < MWIFIEX_USER_SCAN_CHAN_MAX; id++) {
1967 if (!priv->hidden_chan[id].chan_number)
1968 break;
1969 memcpy(&user_scan_cfg->chan_list[id],
1970 &priv->hidden_chan[id],
1971 sizeof(struct mwifiex_user_scan_chan));
1972 }
1973
1974 adapter->active_scan_triggered = true;
1975 if (priv->scan_request->flags & NL80211_SCAN_FLAG_RANDOM_ADDR)
1976 ether_addr_copy(user_scan_cfg->random_mac,
1977 priv->scan_request->mac_addr);
1978 user_scan_cfg->num_ssids = priv->scan_request->n_ssids;
1979 user_scan_cfg->ssid_list = priv->scan_request->ssids;
1980
1981 ret = mwifiex_scan_networks(priv, user_scan_cfg);
1982 kfree(user_scan_cfg);
1983
1984 memset(&priv->hidden_chan, 0, sizeof(priv->hidden_chan));
1985
1986 if (ret) {
1987 dev_err(priv->adapter->dev, "scan failed: %d\n", ret);
1988 return ret;
1989 }
1990
1991 return 0;
1992}
1993static void mwifiex_check_next_scan_command(struct mwifiex_private *priv)
1994{
1995 struct mwifiex_adapter *adapter = priv->adapter;
1996 struct cmd_ctrl_node *cmd_node;
1997
1998 spin_lock_bh(&adapter->scan_pending_q_lock);
1999 if (list_empty(&adapter->scan_pending_q)) {
2000 spin_unlock_bh(&adapter->scan_pending_q_lock);
2001
2002 spin_lock_bh(&adapter->mwifiex_cmd_lock);
2003 adapter->scan_processing = false;
2004 spin_unlock_bh(&adapter->mwifiex_cmd_lock);
2005
2006 mwifiex_active_scan_req_for_passive_chan(priv);
2007
2008 if (!adapter->ext_scan)
2009 mwifiex_complete_scan(priv);
2010
2011 if (priv->scan_request) {
2012 struct cfg80211_scan_info info = {
2013 .aborted = false,
2014 };
2015
2016 mwifiex_dbg(adapter, INFO,
2017 "info: notifying scan done\n");
2018 cfg80211_scan_done(priv->scan_request, &info);
2019 priv->scan_request = NULL;
2020 priv->scan_aborting = false;
2021 } else {
2022 priv->scan_aborting = false;
2023 mwifiex_dbg(adapter, INFO,
2024 "info: scan already aborted\n");
2025 }
2026 } else if ((priv->scan_aborting && !priv->scan_request) ||
2027 priv->scan_block) {
2028 spin_unlock_bh(&adapter->scan_pending_q_lock);
2029
2030 mwifiex_cancel_pending_scan_cmd(adapter);
2031
2032 spin_lock_bh(&adapter->mwifiex_cmd_lock);
2033 adapter->scan_processing = false;
2034 spin_unlock_bh(&adapter->mwifiex_cmd_lock);
2035
2036 if (!adapter->active_scan_triggered) {
2037 if (priv->scan_request) {
2038 struct cfg80211_scan_info info = {
2039 .aborted = true,
2040 };
2041
2042 mwifiex_dbg(adapter, INFO,
2043 "info: aborting scan\n");
2044 cfg80211_scan_done(priv->scan_request, &info);
2045 priv->scan_request = NULL;
2046 priv->scan_aborting = false;
2047 } else {
2048 priv->scan_aborting = false;
2049 mwifiex_dbg(adapter, INFO,
2050 "info: scan already aborted\n");
2051 }
2052 }
2053 } else {
2054
2055
2056
2057 cmd_node = list_first_entry(&adapter->scan_pending_q,
2058 struct cmd_ctrl_node, list);
2059 list_del(&cmd_node->list);
2060 spin_unlock_bh(&adapter->scan_pending_q_lock);
2061 mwifiex_insert_cmd_to_pending_q(adapter, cmd_node);
2062 }
2063
2064 return;
2065}
2066
2067void mwifiex_cancel_scan(struct mwifiex_adapter *adapter)
2068{
2069 struct mwifiex_private *priv;
2070 int i;
2071
2072 mwifiex_cancel_pending_scan_cmd(adapter);
2073
2074 if (adapter->scan_processing) {
2075 spin_lock_bh(&adapter->mwifiex_cmd_lock);
2076 adapter->scan_processing = false;
2077 spin_unlock_bh(&adapter->mwifiex_cmd_lock);
2078 for (i = 0; i < adapter->priv_num; i++) {
2079 priv = adapter->priv[i];
2080 if (!priv)
2081 continue;
2082 if (priv->scan_request) {
2083 struct cfg80211_scan_info info = {
2084 .aborted = true,
2085 };
2086
2087 mwifiex_dbg(adapter, INFO,
2088 "info: aborting scan\n");
2089 cfg80211_scan_done(priv->scan_request, &info);
2090 priv->scan_request = NULL;
2091 priv->scan_aborting = false;
2092 }
2093 }
2094 }
2095}
2096
2097
2098
2099
2100
2101
2102
2103
2104
2105
2106
2107
2108
2109
2110
2111
2112
2113
2114
2115
2116int mwifiex_ret_802_11_scan(struct mwifiex_private *priv,
2117 struct host_cmd_ds_command *resp)
2118{
2119 int ret = 0;
2120 struct mwifiex_adapter *adapter = priv->adapter;
2121 struct host_cmd_ds_802_11_scan_rsp *scan_rsp;
2122 struct mwifiex_ie_types_data *tlv_data;
2123 struct mwifiex_ie_types_tsf_timestamp *tsf_tlv;
2124 u8 *bss_info;
2125 u32 scan_resp_size;
2126 u32 bytes_left;
2127 u32 idx;
2128 u32 tlv_buf_size;
2129 struct mwifiex_ie_types_chan_band_list_param_set *chan_band_tlv;
2130 struct chan_band_param_set *chan_band;
2131 u8 is_bgscan_resp;
2132 __le64 fw_tsf = 0;
2133 u8 *radio_type;
2134 struct cfg80211_wowlan_nd_match *pmatch;
2135 struct cfg80211_sched_scan_request *nd_config = NULL;
2136
2137 is_bgscan_resp = (le16_to_cpu(resp->command)
2138 == HostCmd_CMD_802_11_BG_SCAN_QUERY);
2139 if (is_bgscan_resp)
2140 scan_rsp = &resp->params.bg_scan_query_resp.scan_resp;
2141 else
2142 scan_rsp = &resp->params.scan_resp;
2143
2144
2145 if (scan_rsp->number_of_sets > MWIFIEX_MAX_AP) {
2146 mwifiex_dbg(adapter, ERROR,
2147 "SCAN_RESP: too many AP returned (%d)\n",
2148 scan_rsp->number_of_sets);
2149 ret = -1;
2150 goto check_next_scan;
2151 }
2152
2153
2154 mwifiex_11h_get_csa_closed_channel(priv);
2155
2156 bytes_left = le16_to_cpu(scan_rsp->bss_descript_size);
2157 mwifiex_dbg(adapter, INFO,
2158 "info: SCAN_RESP: bss_descript_size %d\n",
2159 bytes_left);
2160
2161 scan_resp_size = le16_to_cpu(resp->size);
2162
2163 mwifiex_dbg(adapter, INFO,
2164 "info: SCAN_RESP: returned %d APs before parsing\n",
2165 scan_rsp->number_of_sets);
2166
2167 bss_info = scan_rsp->bss_desc_and_tlv_buffer;
2168
2169
2170
2171
2172
2173
2174
2175 tlv_buf_size = scan_resp_size - (bytes_left
2176 + sizeof(scan_rsp->bss_descript_size)
2177 + sizeof(scan_rsp->number_of_sets)
2178 + S_DS_GEN);
2179
2180 tlv_data = (struct mwifiex_ie_types_data *) (scan_rsp->
2181 bss_desc_and_tlv_buffer +
2182 bytes_left);
2183
2184
2185
2186 mwifiex_ret_802_11_scan_get_tlv_ptrs(adapter, tlv_data, tlv_buf_size,
2187 TLV_TYPE_TSFTIMESTAMP,
2188 (struct mwifiex_ie_types_data **)
2189 &tsf_tlv);
2190
2191
2192
2193 mwifiex_ret_802_11_scan_get_tlv_ptrs(adapter, tlv_data, tlv_buf_size,
2194 TLV_TYPE_CHANNELBANDLIST,
2195 (struct mwifiex_ie_types_data **)
2196 &chan_band_tlv);
2197
2198#ifdef CONFIG_PM
2199 if (priv->wdev.wiphy->wowlan_config)
2200 nd_config = priv->wdev.wiphy->wowlan_config->nd_config;
2201#endif
2202
2203 if (nd_config) {
2204 adapter->nd_info =
2205 kzalloc(sizeof(struct cfg80211_wowlan_nd_match) +
2206 sizeof(struct cfg80211_wowlan_nd_match *) *
2207 scan_rsp->number_of_sets, GFP_ATOMIC);
2208
2209 if (adapter->nd_info)
2210 adapter->nd_info->n_matches = scan_rsp->number_of_sets;
2211 }
2212
2213 for (idx = 0; idx < scan_rsp->number_of_sets && bytes_left; idx++) {
2214
2215
2216
2217
2218
2219
2220 if (tsf_tlv)
2221 memcpy(&fw_tsf, &tsf_tlv->tsf_data[idx * TSF_DATA_SIZE],
2222 sizeof(fw_tsf));
2223
2224 if (chan_band_tlv) {
2225 chan_band = &chan_band_tlv->chan_band_param[idx];
2226 radio_type = &chan_band->radio_type;
2227 } else {
2228 radio_type = NULL;
2229 }
2230
2231 if (chan_band_tlv && adapter->nd_info) {
2232 adapter->nd_info->matches[idx] =
2233 kzalloc(sizeof(*pmatch) + sizeof(u32),
2234 GFP_ATOMIC);
2235
2236 pmatch = adapter->nd_info->matches[idx];
2237
2238 if (pmatch) {
2239 pmatch->n_channels = 1;
2240 pmatch->channels[0] = chan_band->chan_number;
2241 }
2242 }
2243
2244 ret = mwifiex_parse_single_response_buf(priv, &bss_info,
2245 &bytes_left,
2246 le64_to_cpu(fw_tsf),
2247 radio_type, false, 0);
2248 if (ret)
2249 goto check_next_scan;
2250 }
2251
2252check_next_scan:
2253 mwifiex_check_next_scan_command(priv);
2254 return ret;
2255}
2256
2257
2258
2259
2260
2261
2262
2263
2264int mwifiex_cmd_802_11_scan_ext(struct mwifiex_private *priv,
2265 struct host_cmd_ds_command *cmd,
2266 void *data_buf)
2267{
2268 struct host_cmd_ds_802_11_scan_ext *ext_scan = &cmd->params.ext_scan;
2269 struct mwifiex_scan_cmd_config *scan_cfg = data_buf;
2270
2271 memcpy(ext_scan->tlv_buffer, scan_cfg->tlv_buf, scan_cfg->tlv_buf_len);
2272
2273 cmd->command = cpu_to_le16(HostCmd_CMD_802_11_SCAN_EXT);
2274
2275
2276 cmd->size = cpu_to_le16((u16)(sizeof(ext_scan->reserved)
2277 + scan_cfg->tlv_buf_len + S_DS_GEN));
2278
2279 return 0;
2280}
2281
2282
2283
2284
2285int mwifiex_cmd_802_11_bg_scan_config(struct mwifiex_private *priv,
2286 struct host_cmd_ds_command *cmd,
2287 void *data_buf)
2288{
2289 struct host_cmd_ds_802_11_bg_scan_config *bgscan_config =
2290 &cmd->params.bg_scan_config;
2291 struct mwifiex_bg_scan_cfg *bgscan_cfg_in = data_buf;
2292 u8 *tlv_pos = bgscan_config->tlv;
2293 u8 num_probes;
2294 u32 ssid_len, chan_idx, scan_type, scan_dur, chan_num;
2295 int i;
2296 struct mwifiex_ie_types_num_probes *num_probes_tlv;
2297 struct mwifiex_ie_types_repeat_count *repeat_count_tlv;
2298 struct mwifiex_ie_types_min_rssi_threshold *rssi_threshold_tlv;
2299 struct mwifiex_ie_types_bgscan_start_later *start_later_tlv;
2300 struct mwifiex_ie_types_wildcard_ssid_params *wildcard_ssid_tlv;
2301 struct mwifiex_ie_types_chan_list_param_set *chan_list_tlv;
2302 struct mwifiex_chan_scan_param_set *temp_chan;
2303
2304 cmd->command = cpu_to_le16(HostCmd_CMD_802_11_BG_SCAN_CONFIG);
2305 cmd->size = cpu_to_le16(sizeof(*bgscan_config) + S_DS_GEN);
2306
2307 bgscan_config->action = cpu_to_le16(bgscan_cfg_in->action);
2308 bgscan_config->enable = bgscan_cfg_in->enable;
2309 bgscan_config->bss_type = bgscan_cfg_in->bss_type;
2310 bgscan_config->scan_interval =
2311 cpu_to_le32(bgscan_cfg_in->scan_interval);
2312 bgscan_config->report_condition =
2313 cpu_to_le32(bgscan_cfg_in->report_condition);
2314
2315
2316 if (!bgscan_config->enable)
2317 return 0;
2318
2319 bgscan_config->chan_per_scan = bgscan_cfg_in->chan_per_scan;
2320
2321 num_probes = (bgscan_cfg_in->num_probes ? bgscan_cfg_in->
2322 num_probes : priv->adapter->scan_probes);
2323
2324 if (num_probes) {
2325 num_probes_tlv = (struct mwifiex_ie_types_num_probes *)tlv_pos;
2326 num_probes_tlv->header.type = cpu_to_le16(TLV_TYPE_NUMPROBES);
2327 num_probes_tlv->header.len =
2328 cpu_to_le16(sizeof(num_probes_tlv->num_probes));
2329 num_probes_tlv->num_probes = cpu_to_le16((u16)num_probes);
2330
2331 tlv_pos += sizeof(num_probes_tlv->header) +
2332 le16_to_cpu(num_probes_tlv->header.len);
2333 }
2334
2335 if (bgscan_cfg_in->repeat_count) {
2336 repeat_count_tlv =
2337 (struct mwifiex_ie_types_repeat_count *)tlv_pos;
2338 repeat_count_tlv->header.type =
2339 cpu_to_le16(TLV_TYPE_REPEAT_COUNT);
2340 repeat_count_tlv->header.len =
2341 cpu_to_le16(sizeof(repeat_count_tlv->repeat_count));
2342 repeat_count_tlv->repeat_count =
2343 cpu_to_le16(bgscan_cfg_in->repeat_count);
2344
2345 tlv_pos += sizeof(repeat_count_tlv->header) +
2346 le16_to_cpu(repeat_count_tlv->header.len);
2347 }
2348
2349 if (bgscan_cfg_in->rssi_threshold) {
2350 rssi_threshold_tlv =
2351 (struct mwifiex_ie_types_min_rssi_threshold *)tlv_pos;
2352 rssi_threshold_tlv->header.type =
2353 cpu_to_le16(TLV_TYPE_RSSI_LOW);
2354 rssi_threshold_tlv->header.len =
2355 cpu_to_le16(sizeof(rssi_threshold_tlv->rssi_threshold));
2356 rssi_threshold_tlv->rssi_threshold =
2357 cpu_to_le16(bgscan_cfg_in->rssi_threshold);
2358
2359 tlv_pos += sizeof(rssi_threshold_tlv->header) +
2360 le16_to_cpu(rssi_threshold_tlv->header.len);
2361 }
2362
2363 for (i = 0; i < bgscan_cfg_in->num_ssids; i++) {
2364 ssid_len = bgscan_cfg_in->ssid_list[i].ssid.ssid_len;
2365
2366 wildcard_ssid_tlv =
2367 (struct mwifiex_ie_types_wildcard_ssid_params *)tlv_pos;
2368 wildcard_ssid_tlv->header.type =
2369 cpu_to_le16(TLV_TYPE_WILDCARDSSID);
2370 wildcard_ssid_tlv->header.len = cpu_to_le16(
2371 (u16)(ssid_len + sizeof(wildcard_ssid_tlv->
2372 max_ssid_length)));
2373
2374
2375
2376
2377
2378
2379 if (ssid_len)
2380 wildcard_ssid_tlv->max_ssid_length = 0;
2381 else
2382 wildcard_ssid_tlv->max_ssid_length =
2383 IEEE80211_MAX_SSID_LEN;
2384
2385 memcpy(wildcard_ssid_tlv->ssid,
2386 bgscan_cfg_in->ssid_list[i].ssid.ssid, ssid_len);
2387
2388 tlv_pos += (sizeof(wildcard_ssid_tlv->header)
2389 + le16_to_cpu(wildcard_ssid_tlv->header.len));
2390 }
2391
2392 chan_list_tlv = (struct mwifiex_ie_types_chan_list_param_set *)tlv_pos;
2393
2394 if (bgscan_cfg_in->chan_list[0].chan_number) {
2395 dev_dbg(priv->adapter->dev, "info: bgscan: Using supplied channel list\n");
2396
2397 chan_list_tlv->header.type = cpu_to_le16(TLV_TYPE_CHANLIST);
2398
2399 for (chan_idx = 0;
2400 chan_idx < MWIFIEX_BG_SCAN_CHAN_MAX &&
2401 bgscan_cfg_in->chan_list[chan_idx].chan_number;
2402 chan_idx++) {
2403 temp_chan = chan_list_tlv->chan_scan_param + chan_idx;
2404
2405
2406 le16_unaligned_add_cpu(&chan_list_tlv->header.len,
2407 sizeof(
2408 chan_list_tlv->chan_scan_param));
2409
2410 temp_chan->chan_number =
2411 bgscan_cfg_in->chan_list[chan_idx].chan_number;
2412 temp_chan->radio_type =
2413 bgscan_cfg_in->chan_list[chan_idx].radio_type;
2414
2415 scan_type =
2416 bgscan_cfg_in->chan_list[chan_idx].scan_type;
2417
2418 if (scan_type == MWIFIEX_SCAN_TYPE_PASSIVE)
2419 temp_chan->chan_scan_mode_bitmap
2420 |= MWIFIEX_PASSIVE_SCAN;
2421 else
2422 temp_chan->chan_scan_mode_bitmap
2423 &= ~MWIFIEX_PASSIVE_SCAN;
2424
2425 if (bgscan_cfg_in->chan_list[chan_idx].scan_time) {
2426 scan_dur = (u16)bgscan_cfg_in->
2427 chan_list[chan_idx].scan_time;
2428 } else {
2429 scan_dur = (scan_type ==
2430 MWIFIEX_SCAN_TYPE_PASSIVE) ?
2431 priv->adapter->passive_scan_time :
2432 priv->adapter->specific_scan_time;
2433 }
2434
2435 temp_chan->min_scan_time = cpu_to_le16(scan_dur);
2436 temp_chan->max_scan_time = cpu_to_le16(scan_dur);
2437 }
2438 } else {
2439 dev_dbg(priv->adapter->dev,
2440 "info: bgscan: Creating full region channel list\n");
2441 chan_num =
2442 mwifiex_bgscan_create_channel_list(priv, bgscan_cfg_in,
2443 chan_list_tlv->
2444 chan_scan_param);
2445 le16_unaligned_add_cpu(&chan_list_tlv->header.len,
2446 chan_num *
2447 sizeof(chan_list_tlv->chan_scan_param[0]));
2448 }
2449
2450 tlv_pos += (sizeof(chan_list_tlv->header)
2451 + le16_to_cpu(chan_list_tlv->header.len));
2452
2453 if (bgscan_cfg_in->start_later) {
2454 start_later_tlv =
2455 (struct mwifiex_ie_types_bgscan_start_later *)tlv_pos;
2456 start_later_tlv->header.type =
2457 cpu_to_le16(TLV_TYPE_BGSCAN_START_LATER);
2458 start_later_tlv->header.len =
2459 cpu_to_le16(sizeof(start_later_tlv->start_later));
2460 start_later_tlv->start_later =
2461 cpu_to_le16(bgscan_cfg_in->start_later);
2462
2463 tlv_pos += sizeof(start_later_tlv->header) +
2464 le16_to_cpu(start_later_tlv->header.len);
2465 }
2466
2467
2468 mwifiex_cmd_append_vsie_tlv(priv, MWIFIEX_VSIE_MASK_BGSCAN, &tlv_pos);
2469
2470 le16_unaligned_add_cpu(&cmd->size, tlv_pos - bgscan_config->tlv);
2471
2472 return 0;
2473}
2474
2475int mwifiex_stop_bg_scan(struct mwifiex_private *priv)
2476{
2477 struct mwifiex_bg_scan_cfg *bgscan_cfg;
2478
2479 if (!priv->sched_scanning) {
2480 dev_dbg(priv->adapter->dev, "bgscan already stopped!\n");
2481 return 0;
2482 }
2483
2484 bgscan_cfg = kzalloc(sizeof(*bgscan_cfg), GFP_KERNEL);
2485 if (!bgscan_cfg)
2486 return -ENOMEM;
2487
2488 bgscan_cfg->bss_type = MWIFIEX_BSS_MODE_INFRA;
2489 bgscan_cfg->action = MWIFIEX_BGSCAN_ACT_SET;
2490 bgscan_cfg->enable = false;
2491
2492 if (mwifiex_send_cmd(priv, HostCmd_CMD_802_11_BG_SCAN_CONFIG,
2493 HostCmd_ACT_GEN_SET, 0, bgscan_cfg, true)) {
2494 kfree(bgscan_cfg);
2495 return -EFAULT;
2496 }
2497
2498 kfree(bgscan_cfg);
2499 priv->sched_scanning = false;
2500
2501 return 0;
2502}
2503
2504static void
2505mwifiex_update_chan_statistics(struct mwifiex_private *priv,
2506 struct mwifiex_ietypes_chanstats *tlv_stat)
2507{
2508 struct mwifiex_adapter *adapter = priv->adapter;
2509 u8 i, num_chan;
2510 struct mwifiex_fw_chan_stats *fw_chan_stats;
2511 struct mwifiex_chan_stats chan_stats;
2512
2513 fw_chan_stats = (void *)((u8 *)tlv_stat +
2514 sizeof(struct mwifiex_ie_types_header));
2515 num_chan = le16_to_cpu(tlv_stat->header.len) /
2516 sizeof(struct mwifiex_chan_stats);
2517
2518 for (i = 0 ; i < num_chan; i++) {
2519 if (adapter->survey_idx >= adapter->num_in_chan_stats) {
2520 mwifiex_dbg(adapter, WARN,
2521 "FW reported too many channel results (max %d)\n",
2522 adapter->num_in_chan_stats);
2523 return;
2524 }
2525 chan_stats.chan_num = fw_chan_stats->chan_num;
2526 chan_stats.bandcfg = fw_chan_stats->bandcfg;
2527 chan_stats.flags = fw_chan_stats->flags;
2528 chan_stats.noise = fw_chan_stats->noise;
2529 chan_stats.total_bss = le16_to_cpu(fw_chan_stats->total_bss);
2530 chan_stats.cca_scan_dur =
2531 le16_to_cpu(fw_chan_stats->cca_scan_dur);
2532 chan_stats.cca_busy_dur =
2533 le16_to_cpu(fw_chan_stats->cca_busy_dur);
2534 mwifiex_dbg(adapter, INFO,
2535 "chan=%d, noise=%d, total_network=%d scan_duration=%d, busy_duration=%d\n",
2536 chan_stats.chan_num,
2537 chan_stats.noise,
2538 chan_stats.total_bss,
2539 chan_stats.cca_scan_dur,
2540 chan_stats.cca_busy_dur);
2541 memcpy(&adapter->chan_stats[adapter->survey_idx++], &chan_stats,
2542 sizeof(struct mwifiex_chan_stats));
2543 fw_chan_stats++;
2544 }
2545}
2546
2547
2548int mwifiex_ret_802_11_scan_ext(struct mwifiex_private *priv,
2549 struct host_cmd_ds_command *resp)
2550{
2551 struct mwifiex_adapter *adapter = priv->adapter;
2552 struct host_cmd_ds_802_11_scan_ext *ext_scan_resp;
2553 struct mwifiex_ie_types_header *tlv;
2554 struct mwifiex_ietypes_chanstats *tlv_stat;
2555 u16 buf_left, type, len;
2556
2557 struct host_cmd_ds_command *cmd_ptr;
2558 struct cmd_ctrl_node *cmd_node;
2559 bool complete_scan = false;
2560
2561 mwifiex_dbg(adapter, INFO, "info: EXT scan returns successfully\n");
2562
2563 ext_scan_resp = &resp->params.ext_scan;
2564
2565 tlv = (void *)ext_scan_resp->tlv_buffer;
2566 buf_left = le16_to_cpu(resp->size) - (sizeof(*ext_scan_resp) + S_DS_GEN
2567 - 1);
2568
2569 while (buf_left >= sizeof(struct mwifiex_ie_types_header)) {
2570 type = le16_to_cpu(tlv->type);
2571 len = le16_to_cpu(tlv->len);
2572
2573 if (buf_left < (sizeof(struct mwifiex_ie_types_header) + len)) {
2574 mwifiex_dbg(adapter, ERROR,
2575 "error processing scan response TLVs");
2576 break;
2577 }
2578
2579 switch (type) {
2580 case TLV_TYPE_CHANNEL_STATS:
2581 tlv_stat = (void *)tlv;
2582 mwifiex_update_chan_statistics(priv, tlv_stat);
2583 break;
2584 default:
2585 break;
2586 }
2587
2588 buf_left -= len + sizeof(struct mwifiex_ie_types_header);
2589 tlv = (void *)((u8 *)tlv + len +
2590 sizeof(struct mwifiex_ie_types_header));
2591 }
2592
2593 spin_lock_bh(&adapter->cmd_pending_q_lock);
2594 spin_lock_bh(&adapter->scan_pending_q_lock);
2595 if (list_empty(&adapter->scan_pending_q)) {
2596 complete_scan = true;
2597 list_for_each_entry(cmd_node, &adapter->cmd_pending_q, list) {
2598 cmd_ptr = (void *)cmd_node->cmd_skb->data;
2599 if (le16_to_cpu(cmd_ptr->command) ==
2600 HostCmd_CMD_802_11_SCAN_EXT) {
2601 mwifiex_dbg(adapter, INFO,
2602 "Scan pending in command pending list");
2603 complete_scan = false;
2604 break;
2605 }
2606 }
2607 }
2608 spin_unlock_bh(&adapter->scan_pending_q_lock);
2609 spin_unlock_bh(&adapter->cmd_pending_q_lock);
2610
2611 if (complete_scan)
2612 mwifiex_complete_scan(priv);
2613
2614 return 0;
2615}
2616
2617
2618
2619
2620int mwifiex_handle_event_ext_scan_report(struct mwifiex_private *priv,
2621 void *buf)
2622{
2623 int ret = 0;
2624 struct mwifiex_adapter *adapter = priv->adapter;
2625 u8 *bss_info;
2626 u32 bytes_left, bytes_left_for_tlv, idx;
2627 u16 type, len;
2628 struct mwifiex_ie_types_data *tlv;
2629 struct mwifiex_ie_types_bss_scan_rsp *scan_rsp_tlv;
2630 struct mwifiex_ie_types_bss_scan_info *scan_info_tlv;
2631 u8 *radio_type;
2632 u64 fw_tsf = 0;
2633 s32 rssi = 0;
2634 struct mwifiex_event_scan_result *event_scan = buf;
2635 u8 num_of_set = event_scan->num_of_set;
2636 u8 *scan_resp = buf + sizeof(struct mwifiex_event_scan_result);
2637 u16 scan_resp_size = le16_to_cpu(event_scan->buf_size);
2638
2639 if (num_of_set > MWIFIEX_MAX_AP) {
2640 mwifiex_dbg(adapter, ERROR,
2641 "EXT_SCAN: Invalid number of AP returned (%d)!!\n",
2642 num_of_set);
2643 ret = -1;
2644 goto check_next_scan;
2645 }
2646
2647 bytes_left = scan_resp_size;
2648 mwifiex_dbg(adapter, INFO,
2649 "EXT_SCAN: size %d, returned %d APs...",
2650 scan_resp_size, num_of_set);
2651 mwifiex_dbg_dump(adapter, CMD_D, "EXT_SCAN buffer:", buf,
2652 scan_resp_size +
2653 sizeof(struct mwifiex_event_scan_result));
2654
2655 tlv = (struct mwifiex_ie_types_data *)scan_resp;
2656
2657 for (idx = 0; idx < num_of_set && bytes_left; idx++) {
2658 type = le16_to_cpu(tlv->header.type);
2659 len = le16_to_cpu(tlv->header.len);
2660 if (bytes_left < sizeof(struct mwifiex_ie_types_header) + len) {
2661 mwifiex_dbg(adapter, ERROR,
2662 "EXT_SCAN: Error bytes left < TLV length\n");
2663 break;
2664 }
2665 scan_rsp_tlv = NULL;
2666 scan_info_tlv = NULL;
2667 bytes_left_for_tlv = bytes_left;
2668
2669
2670
2671
2672 if (type != TLV_TYPE_BSS_SCAN_RSP)
2673 break;
2674
2675 bss_info = (u8 *)tlv;
2676 scan_rsp_tlv = (struct mwifiex_ie_types_bss_scan_rsp *)tlv;
2677 tlv = (struct mwifiex_ie_types_data *)(tlv->data + len);
2678 bytes_left_for_tlv -=
2679 (len + sizeof(struct mwifiex_ie_types_header));
2680
2681 while (bytes_left_for_tlv >=
2682 sizeof(struct mwifiex_ie_types_header) &&
2683 le16_to_cpu(tlv->header.type) != TLV_TYPE_BSS_SCAN_RSP) {
2684 type = le16_to_cpu(tlv->header.type);
2685 len = le16_to_cpu(tlv->header.len);
2686 if (bytes_left_for_tlv <
2687 sizeof(struct mwifiex_ie_types_header) + len) {
2688 mwifiex_dbg(adapter, ERROR,
2689 "EXT_SCAN: Error in processing TLV,\t"
2690 "bytes left < TLV length\n");
2691 scan_rsp_tlv = NULL;
2692 bytes_left_for_tlv = 0;
2693 continue;
2694 }
2695 switch (type) {
2696 case TLV_TYPE_BSS_SCAN_INFO:
2697 scan_info_tlv =
2698 (struct mwifiex_ie_types_bss_scan_info *)tlv;
2699 if (len !=
2700 sizeof(struct mwifiex_ie_types_bss_scan_info) -
2701 sizeof(struct mwifiex_ie_types_header)) {
2702 bytes_left_for_tlv = 0;
2703 continue;
2704 }
2705 break;
2706 default:
2707 break;
2708 }
2709 tlv = (struct mwifiex_ie_types_data *)(tlv->data + len);
2710 bytes_left -=
2711 (len + sizeof(struct mwifiex_ie_types_header));
2712 bytes_left_for_tlv -=
2713 (len + sizeof(struct mwifiex_ie_types_header));
2714 }
2715
2716 if (!scan_rsp_tlv)
2717 break;
2718
2719
2720
2721
2722
2723
2724 bss_info += sizeof(u16);
2725 bytes_left -= sizeof(u16);
2726
2727 if (scan_info_tlv) {
2728 rssi = (s32)(s16)(le16_to_cpu(scan_info_tlv->rssi));
2729 rssi *= 100;
2730 mwifiex_dbg(adapter, INFO,
2731 "info: InterpretIE: RSSI=%d\n", rssi);
2732 fw_tsf = le64_to_cpu(scan_info_tlv->tsf);
2733 radio_type = &scan_info_tlv->radio_type;
2734 } else {
2735 radio_type = NULL;
2736 }
2737 ret = mwifiex_parse_single_response_buf(priv, &bss_info,
2738 &bytes_left, fw_tsf,
2739 radio_type, true, rssi);
2740 if (ret)
2741 goto check_next_scan;
2742 }
2743
2744check_next_scan:
2745 if (!event_scan->more_event)
2746 mwifiex_check_next_scan_command(priv);
2747
2748 return ret;
2749}
2750
2751
2752
2753
2754
2755
2756
2757
2758
2759int mwifiex_cmd_802_11_bg_scan_query(struct host_cmd_ds_command *cmd)
2760{
2761 struct host_cmd_ds_802_11_bg_scan_query *bg_query =
2762 &cmd->params.bg_scan_query;
2763
2764 cmd->command = cpu_to_le16(HostCmd_CMD_802_11_BG_SCAN_QUERY);
2765 cmd->size = cpu_to_le16(sizeof(struct host_cmd_ds_802_11_bg_scan_query)
2766 + S_DS_GEN);
2767
2768 bg_query->flush = 1;
2769
2770 return 0;
2771}
2772
2773
2774
2775
2776void
2777mwifiex_queue_scan_cmd(struct mwifiex_private *priv,
2778 struct cmd_ctrl_node *cmd_node)
2779{
2780 struct mwifiex_adapter *adapter = priv->adapter;
2781
2782 cmd_node->wait_q_enabled = true;
2783 cmd_node->condition = &adapter->scan_wait_q_woken;
2784 spin_lock_bh(&adapter->scan_pending_q_lock);
2785 list_add_tail(&cmd_node->list, &adapter->scan_pending_q);
2786 spin_unlock_bh(&adapter->scan_pending_q_lock);
2787}
2788
2789
2790
2791
2792
2793static int mwifiex_scan_specific_ssid(struct mwifiex_private *priv,
2794 struct cfg80211_ssid *req_ssid)
2795{
2796 struct mwifiex_adapter *adapter = priv->adapter;
2797 int ret;
2798 struct mwifiex_user_scan_cfg *scan_cfg;
2799
2800 if (adapter->scan_processing) {
2801 mwifiex_dbg(adapter, WARN,
2802 "cmd: Scan already in process...\n");
2803 return -EBUSY;
2804 }
2805
2806 if (priv->scan_block) {
2807 mwifiex_dbg(adapter, WARN,
2808 "cmd: Scan is blocked during association...\n");
2809 return -EBUSY;
2810 }
2811
2812 scan_cfg = kzalloc(sizeof(struct mwifiex_user_scan_cfg), GFP_KERNEL);
2813 if (!scan_cfg)
2814 return -ENOMEM;
2815
2816 scan_cfg->ssid_list = req_ssid;
2817 scan_cfg->num_ssids = 1;
2818
2819 ret = mwifiex_scan_networks(priv, scan_cfg);
2820
2821 kfree(scan_cfg);
2822 return ret;
2823}
2824
2825
2826
2827
2828
2829
2830
2831
2832
2833
2834int mwifiex_request_scan(struct mwifiex_private *priv,
2835 struct cfg80211_ssid *req_ssid)
2836{
2837 int ret;
2838
2839 if (mutex_lock_interruptible(&priv->async_mutex)) {
2840 mwifiex_dbg(priv->adapter, ERROR,
2841 "%s: acquire semaphore fail\n",
2842 __func__);
2843 return -1;
2844 }
2845
2846 priv->adapter->scan_wait_q_woken = false;
2847
2848 if (req_ssid && req_ssid->ssid_len != 0)
2849
2850 ret = mwifiex_scan_specific_ssid(priv, req_ssid);
2851 else
2852
2853 ret = mwifiex_scan_networks(priv, NULL);
2854
2855 mutex_unlock(&priv->async_mutex);
2856
2857 return ret;
2858}
2859
2860
2861
2862
2863int
2864mwifiex_cmd_append_vsie_tlv(struct mwifiex_private *priv,
2865 u16 vsie_mask, u8 **buffer)
2866{
2867 int id, ret_len = 0;
2868 struct mwifiex_ie_types_vendor_param_set *vs_param_set;
2869
2870 if (!buffer)
2871 return 0;
2872 if (!(*buffer))
2873 return 0;
2874
2875
2876
2877
2878
2879 for (id = 0; id < MWIFIEX_MAX_VSIE_NUM; id++) {
2880 if (priv->vs_ie[id].mask & vsie_mask) {
2881 vs_param_set =
2882 (struct mwifiex_ie_types_vendor_param_set *)
2883 *buffer;
2884 vs_param_set->header.type =
2885 cpu_to_le16(TLV_TYPE_PASSTHROUGH);
2886 vs_param_set->header.len =
2887 cpu_to_le16((((u16) priv->vs_ie[id].ie[1])
2888 & 0x00FF) + 2);
2889 memcpy(vs_param_set->ie, priv->vs_ie[id].ie,
2890 le16_to_cpu(vs_param_set->header.len));
2891 *buffer += le16_to_cpu(vs_param_set->header.len) +
2892 sizeof(struct mwifiex_ie_types_header);
2893 ret_len += le16_to_cpu(vs_param_set->header.len) +
2894 sizeof(struct mwifiex_ie_types_header);
2895 }
2896 }
2897 return ret_len;
2898}
2899
2900
2901
2902
2903
2904
2905
2906
2907
2908
2909void
2910mwifiex_save_curr_bcn(struct mwifiex_private *priv)
2911{
2912 struct mwifiex_bssdescriptor *curr_bss =
2913 &priv->curr_bss_params.bss_descriptor;
2914
2915 if (!curr_bss->beacon_buf_size)
2916 return;
2917
2918
2919 if (!priv->curr_bcn_buf ||
2920 priv->curr_bcn_size != curr_bss->beacon_buf_size) {
2921 priv->curr_bcn_size = curr_bss->beacon_buf_size;
2922
2923 kfree(priv->curr_bcn_buf);
2924 priv->curr_bcn_buf = kmalloc(curr_bss->beacon_buf_size,
2925 GFP_ATOMIC);
2926 if (!priv->curr_bcn_buf)
2927 return;
2928 }
2929
2930 memcpy(priv->curr_bcn_buf, curr_bss->beacon_buf,
2931 curr_bss->beacon_buf_size);
2932 mwifiex_dbg(priv->adapter, INFO,
2933 "info: current beacon saved %d\n",
2934 priv->curr_bcn_size);
2935
2936 curr_bss->beacon_buf = priv->curr_bcn_buf;
2937
2938
2939 if (curr_bss->bcn_wpa_ie)
2940 curr_bss->bcn_wpa_ie =
2941 (struct ieee_types_vendor_specific *)
2942 (curr_bss->beacon_buf +
2943 curr_bss->wpa_offset);
2944
2945 if (curr_bss->bcn_rsn_ie)
2946 curr_bss->bcn_rsn_ie = (struct ieee_types_generic *)
2947 (curr_bss->beacon_buf +
2948 curr_bss->rsn_offset);
2949
2950 if (curr_bss->bcn_ht_cap)
2951 curr_bss->bcn_ht_cap = (struct ieee80211_ht_cap *)
2952 (curr_bss->beacon_buf +
2953 curr_bss->ht_cap_offset);
2954
2955 if (curr_bss->bcn_ht_oper)
2956 curr_bss->bcn_ht_oper = (struct ieee80211_ht_operation *)
2957 (curr_bss->beacon_buf +
2958 curr_bss->ht_info_offset);
2959
2960 if (curr_bss->bcn_vht_cap)
2961 curr_bss->bcn_vht_cap = (void *)(curr_bss->beacon_buf +
2962 curr_bss->vht_cap_offset);
2963
2964 if (curr_bss->bcn_vht_oper)
2965 curr_bss->bcn_vht_oper = (void *)(curr_bss->beacon_buf +
2966 curr_bss->vht_info_offset);
2967
2968 if (curr_bss->bcn_bss_co_2040)
2969 curr_bss->bcn_bss_co_2040 =
2970 (curr_bss->beacon_buf + curr_bss->bss_co_2040_offset);
2971
2972 if (curr_bss->bcn_ext_cap)
2973 curr_bss->bcn_ext_cap = curr_bss->beacon_buf +
2974 curr_bss->ext_cap_offset;
2975
2976 if (curr_bss->oper_mode)
2977 curr_bss->oper_mode = (void *)(curr_bss->beacon_buf +
2978 curr_bss->oper_mode_offset);
2979}
2980
2981
2982
2983
2984void
2985mwifiex_free_curr_bcn(struct mwifiex_private *priv)
2986{
2987 kfree(priv->curr_bcn_buf);
2988 priv->curr_bcn_buf = NULL;
2989}
2990