4 #include <linux/if_arp.h>
5 #include <asm/uaccess.h>
6 #include <wl_android.h>
8 #include <dhd_config.h>
10 #define ESCAN_ERROR(name, arg1, args...) \
12 if (android_msg_level & ANDROID_ERROR_LEVEL) { \
13 printk(KERN_ERR "[dhd-%s] ESCAN-ERROR) %s : " arg1, name, __func__, ## args); \
16 #define ESCAN_TRACE(name, arg1, args...) \
18 if (android_msg_level & ANDROID_TRACE_LEVEL) { \
19 printk(KERN_INFO "[dhd-%s] ESCAN-TRACE) %s : " arg1, name, __func__, ## args); \
22 #define ESCAN_SCAN(name, arg1, args...) \
24 if (android_msg_level & ANDROID_SCAN_LEVEL) { \
25 printk(KERN_INFO "[dhd-%s] ESCAN-SCAN) %s : " arg1, name, __func__, ## args); \
28 #define ESCAN_DBG(name, arg1, args...) \
30 if (android_msg_level & ANDROID_DBG_LEVEL) { \
31 printk(KERN_INFO "[dhd-%s] ESCAN-DBG) %s : " arg1, name, __func__, ## args); \
35 /* IOCTL swapping mode for Big Endian host with Little Endian dongle. Default to off */
40 #define htodchanspec(i) (i)
41 #define dtohchanspec(i) (i)
42 #define WL_EXTRA_BUF_MAX 2048
44 #define wl_escan_get_buf(a) ((wl_scan_results_t *) (a)->escan_buf)
46 #define for_each_bss(list, bss, __i) \
47 for (__i = 0; __i < list->count && __i < IW_MAX_AP; __i++, bss = next_bss(list, bss))
49 #define wl_escan_set_sync_id(a) ((a) = htod16(0x1234))
51 #ifdef ESCAN_BUF_OVERFLOW_MGMT
52 #define BUF_OVERFLOW_MGMT_COUNT 3
56 struct ether_addr BSSID
;
58 #endif /* ESCAN_BUF_OVERFLOW_MGMT */
60 /* Return a new chanspec given a legacy chanspec
61 * Returns INVCHANSPEC on error
64 wl_chspec_from_legacy(chanspec_t legacy_chspec
)
68 /* get the channel number */
69 chspec
= LCHSPEC_CHANNEL(legacy_chspec
);
71 /* convert the band */
72 if (LCHSPEC_IS2G(legacy_chspec
)) {
73 chspec
|= WL_CHANSPEC_BAND_2G
;
75 chspec
|= WL_CHANSPEC_BAND_5G
;
78 /* convert the bw and sideband */
79 if (LCHSPEC_IS20(legacy_chspec
)) {
80 chspec
|= WL_CHANSPEC_BW_20
;
82 chspec
|= WL_CHANSPEC_BW_40
;
83 if (LCHSPEC_CTL_SB(legacy_chspec
) == WL_LCHANSPEC_CTL_SB_LOWER
) {
84 chspec
|= WL_CHANSPEC_CTL_SB_L
;
86 chspec
|= WL_CHANSPEC_CTL_SB_U
;
90 if (wf_chspec_malformed(chspec
)) {
91 ESCAN_ERROR("wlan", "wl_chspec_from_legacy: output chanspec (0x%04X) malformed\n",
99 /* Return a legacy chanspec given a new chanspec
100 * Returns INVCHANSPEC on error
103 wl_chspec_to_legacy(chanspec_t chspec
)
107 if (wf_chspec_malformed(chspec
)) {
108 ESCAN_ERROR("wlan", "wl_chspec_to_legacy: input chanspec (0x%04X) malformed\n",
113 /* get the channel number */
114 lchspec
= CHSPEC_CHANNEL(chspec
);
116 /* convert the band */
117 if (CHSPEC_IS2G(chspec
)) {
118 lchspec
|= WL_LCHANSPEC_BAND_2G
;
120 lchspec
|= WL_LCHANSPEC_BAND_5G
;
123 /* convert the bw and sideband */
124 if (CHSPEC_IS20(chspec
)) {
125 lchspec
|= WL_LCHANSPEC_BW_20
;
126 lchspec
|= WL_LCHANSPEC_CTL_SB_NONE
;
127 } else if (CHSPEC_IS40(chspec
)) {
128 lchspec
|= WL_LCHANSPEC_BW_40
;
129 if (CHSPEC_CTL_SB(chspec
) == WL_CHANSPEC_CTL_SB_L
) {
130 lchspec
|= WL_LCHANSPEC_CTL_SB_LOWER
;
132 lchspec
|= WL_LCHANSPEC_CTL_SB_UPPER
;
135 /* cannot express the bandwidth */
136 char chanbuf
[CHANSPEC_STR_LEN
];
137 ESCAN_ERROR("wlan", "wl_chspec_to_legacy: unable to convert chanspec %s "
138 "(0x%04X) to pre-11ac format\n",
139 wf_chspec_ntoa(chspec
, chanbuf
), chspec
);
146 /* given a chanspec value from the driver, do the endian and chanspec version conversion to
148 * Returns INVCHANSPEC on error
151 wl_chspec_driver_to_host(int ioctl_ver
, chanspec_t chanspec
)
153 chanspec
= dtohchanspec(chanspec
);
154 if (ioctl_ver
== 1) {
155 chanspec
= wl_chspec_from_legacy(chanspec
);
161 /* given a chanspec value, do the endian and chanspec version conversion to
163 * Returns INVCHANSPEC on error
166 wl_chspec_host_to_driver(int ioctl_ver
, chanspec_t chanspec
)
168 if (ioctl_ver
== 1) {
169 chanspec
= wl_chspec_to_legacy(chanspec
);
170 if (chanspec
== INVCHANSPEC
) {
174 chanspec
= htodchanspec(chanspec
);
179 /* given a channel value, do the endian and chanspec version conversion to
181 * Returns INVCHANSPEC on error
184 wl_ch_host_to_driver(int ioctl_ver
, u16 channel
)
188 chanspec
= channel
& WL_CHANSPEC_CHAN_MASK
;
190 if (channel
<= CH_MAX_2G_CHANNEL
)
191 chanspec
|= WL_CHANSPEC_BAND_2G
;
193 chanspec
|= WL_CHANSPEC_BAND_5G
;
195 chanspec
|= WL_CHANSPEC_BW_20
;
197 chanspec
|= WL_CHANSPEC_CTL_SB_NONE
;
199 return wl_chspec_host_to_driver(ioctl_ver
, chanspec
);
202 static inline struct wl_bss_info
*next_bss(struct wl_scan_results
*list
,
203 struct wl_bss_info
*bss
)
206 (struct wl_bss_info
*)((uintptr
) bss
+ dtoh32(bss
->length
)) : list
->bss_info
;
209 #if defined(ESCAN_RESULT_PATCH)
211 wl_escan_inform_bss(struct net_device
*dev
, struct wl_escan_info
*escan
)
213 struct wl_scan_results
*bss_list
;
219 bss_list
= escan
->bss_list
;
221 ESCAN_SCAN(dev
->name
, "scanned AP count (%d)\n", bss_list
->count
);
223 /* Delete disconnected cache */
224 #if defined(BSSCACHE)
225 wl_delete_disconnected_bss_cache(&escan
->g_bss_cache_ctrl
,
226 (u8
*)&escan
->disconnected_bssid
);
228 wl_delete_disconnected_rssi_cache(&escan
->g_rssi_cache_ctrl
,
229 (u8
*)&escan
->disconnected_bssid
);
235 wl_update_rssi_cache(&escan
->g_rssi_cache_ctrl
, bss_list
);
237 wl_update_connected_rssi_cache(dev
, &escan
->g_rssi_cache_ctrl
, &rssi
);
239 #if defined(BSSCACHE)
240 wl_update_bss_cache(&escan
->g_bss_cache_ctrl
,
242 &escan
->g_rssi_cache_ctrl
,
247 /* delete dirty cache */
249 wl_delete_dirty_rssi_cache(&escan
->g_rssi_cache_ctrl
);
250 wl_reset_rssi_cache(&escan
->g_rssi_cache_ctrl
);
252 #if defined(BSSCACHE)
253 wl_delete_dirty_bss_cache(&escan
->g_bss_cache_ctrl
);
254 wl_reset_bss_cache(&escan
->g_bss_cache_ctrl
);
255 if (escan
->autochannel
)
256 wl_ext_get_best_channel(dev
, &escan
->g_bss_cache_ctrl
,
257 escan
->ioctl_ver
, &escan
->best_2g_ch
, &escan
->best_5g_ch
);
259 if (escan
->autochannel
)
260 wl_ext_get_best_channel(dev
, bss_list
, escan
->ioctl_ver
,
261 &escan
->best_2g_ch
, &escan
->best_5g_ch
);
266 #endif /* ESCAN_RESULT_PATCH */
268 static wl_scan_params_t
*
269 wl_escan_alloc_params(struct net_device
*dev
, struct wl_escan_info
*escan
,
270 int channel
, int nprobes
, int *out_params_size
)
272 wl_scan_params_t
*params
;
276 *out_params_size
= 0;
278 /* Our scan params only need space for 1 channel and 0 ssids */
279 params_size
= WL_SCAN_PARAMS_FIXED_SIZE
+ 1 * sizeof(uint16
);
280 params
= (wl_scan_params_t
*) kzalloc(params_size
, GFP_KERNEL
);
281 if (params
== NULL
) {
282 ESCAN_ERROR(dev
->name
, "mem alloc failed (%d bytes)\n", params_size
);
285 memset(params
, 0, params_size
);
286 params
->nprobes
= nprobes
;
288 num_chans
= (channel
== 0) ? 0 : 1;
290 memcpy(¶ms
->bssid
, ðer_bcast
, ETHER_ADDR_LEN
);
291 params
->bss_type
= DOT11_BSSTYPE_ANY
;
292 params
->scan_type
= DOT11_SCANTYPE_ACTIVE
;
293 params
->nprobes
= htod32(1);
294 params
->active_time
= htod32(-1);
295 params
->passive_time
= htod32(-1);
296 params
->home_time
= htod32(10);
298 params
->channel_list
[0] = htodchanspec(channel
);
300 params
->channel_list
[0] = wl_ch_host_to_driver(escan
->ioctl_ver
, channel
);
302 /* Our scan params have 1 channel and 0 ssids */
303 params
->channel_num
= htod32((0 << WL_SCAN_PARAMS_NSSID_SHIFT
) |
304 (num_chans
& WL_SCAN_PARAMS_COUNT_MASK
));
306 *out_params_size
= params_size
; /* rtn size to the caller */
311 wl_escan_abort(struct net_device
*dev
, struct wl_escan_info
*escan
)
313 wl_scan_params_t
*params
= NULL
;
317 /* Our scan params only need space for 1 channel and 0 ssids */
318 params
= wl_escan_alloc_params(dev
, escan
, -1, 0, ¶ms_size
);
319 if (params
== NULL
) {
320 ESCAN_ERROR(dev
->name
, "scan params allocation failed \n");
323 /* Do a scan abort to stop the driver's scan engine */
324 err
= wldev_ioctl(dev
, WLC_SCAN
, params
, params_size
, true);
326 ESCAN_ERROR(dev
->name
, "scan abort failed \n");
334 wl_escan_notify_complete(struct net_device
*dev
,
335 struct wl_escan_info
*escan
, bool fw_abort
)
338 #if defined(WL_WIRELESS_EXT)
340 #if WIRELESS_EXT > 13
341 union iwreq_data wrqu
;
342 char extra
[IW_CUSTOM_MAX
+ 1];
345 struct dhd_pub
*dhd
= dhd_get_pub(dev
);
347 ESCAN_TRACE(dev
->name
, "Enter\n");
349 if (fw_abort
&& !in_atomic())
350 wl_escan_abort(dev
, escan
);
352 if (timer_pending(&escan
->scan_timeout
))
353 del_timer_sync(&escan
->scan_timeout
);
355 #if defined(ESCAN_RESULT_PATCH)
356 escan
->bss_list
= wl_escan_get_buf(escan
);
357 wl_escan_inform_bss(dev
, escan
);
358 #endif /* ESCAN_RESULT_PATCH */
360 escan
->escan_state
= ESCAN_STATE_IDLE
;
361 wake_up_interruptible(&dhd
->conf
->event_complete
);
363 #if defined(WL_WIRELESS_EXT)
364 #if WIRELESS_EXT > 13
365 #if WIRELESS_EXT > 14
368 // terence 20150224: fix "wlan0: (WE) : Wireless Event too big (65306)"
369 memset(&wrqu
, 0, sizeof(wrqu
));
370 memset(extra
, 0, sizeof(extra
));
372 if (cmd
== SIOCGIWSCAN
) {
373 wireless_send_event(dev
, cmd
, &wrqu
, NULL
);
375 wireless_send_event(dev
, cmd
, &wrqu
, extra
);
383 #ifdef ESCAN_BUF_OVERFLOW_MGMT
385 wl_escan_find_removal_candidate(struct wl_escan_info
*escan
,
386 wl_bss_info_t
*bss
, removal_element_t
*candidate
)
389 for (idx
= 0; idx
< BUF_OVERFLOW_MGMT_COUNT
; idx
++) {
390 int len
= BUF_OVERFLOW_MGMT_COUNT
- idx
- 1;
391 if (bss
->RSSI
< candidate
[idx
].RSSI
) {
393 memcpy(&candidate
[idx
+ 1], &candidate
[idx
],
394 sizeof(removal_element_t
) * len
);
395 candidate
[idx
].RSSI
= bss
->RSSI
;
396 candidate
[idx
].length
= bss
->length
;
397 memcpy(&candidate
[idx
].BSSID
, &bss
->BSSID
, ETHER_ADDR_LEN
);
404 wl_escan_remove_lowRSSI_info(struct net_device
*dev
, struct wl_escan_info
*escan
,
405 wl_scan_results_t
*list
, removal_element_t
*candidate
, wl_bss_info_t
*bi
)
408 int total_delete_len
= 0;
409 for (idx1
= 0; idx1
< BUF_OVERFLOW_MGMT_COUNT
; idx1
++) {
410 int cur_len
= WL_SCAN_RESULTS_FIXED_SIZE
;
411 wl_bss_info_t
*bss
= NULL
;
412 if (candidate
[idx1
].RSSI
>= bi
->RSSI
)
414 for (idx2
= 0; idx2
< list
->count
; idx2
++) {
415 bss
= bss
? (wl_bss_info_t
*)((uintptr
)bss
+ dtoh32(bss
->length
)) :
417 if (!bcmp(&candidate
[idx1
].BSSID
, &bss
->BSSID
, ETHER_ADDR_LEN
) &&
418 candidate
[idx1
].RSSI
== bss
->RSSI
&&
419 candidate
[idx1
].length
== dtoh32(bss
->length
)) {
420 u32 delete_len
= dtoh32(bss
->length
);
422 "delete scan info of %pM to add new AP\n", &bss
->BSSID
);
423 if (idx2
< list
->count
-1) {
424 memmove((u8
*)bss
, (u8
*)bss
+ delete_len
,
425 list
->buflen
- cur_len
- delete_len
);
427 list
->buflen
-= delete_len
;
429 total_delete_len
+= delete_len
;
430 /* if delete_len is greater than or equal to result length */
431 if (total_delete_len
>= bi
->length
) {
436 cur_len
+= dtoh32(bss
->length
);
440 #endif /* ESCAN_BUF_OVERFLOW_MGMT */
443 wl_escan_handler(struct net_device
*dev
, struct wl_escan_info
*escan
,
444 const wl_event_msg_t
*e
, void *data
)
447 s32 status
= ntoh32(e
->status
);
449 wl_escan_result_t
*escan_result
;
450 wl_bss_info_t
*bss
= NULL
;
451 wl_scan_results_t
*list
;
456 mutex_lock(&escan
->usr_sync
);
457 escan_result
= (wl_escan_result_t
*)data
;
459 if (escan
->escan_state
!= ESCAN_STATE_SCANING
) {
460 ESCAN_DBG(dev
->name
, "Not my scan\n");
464 ESCAN_DBG(dev
->name
, "enter event type : %d, status : %d \n",
465 ntoh32(e
->event_type
), ntoh32(e
->status
));
467 if (status
== WLC_E_STATUS_PARTIAL
) {
468 ESCAN_DBG(dev
->name
, "WLC_E_STATUS_PARTIAL \n");
470 ESCAN_ERROR(dev
->name
, "Invalid escan result (NULL pointer)\n");
473 if (dtoh16(escan_result
->bss_count
) != 1) {
474 ESCAN_ERROR(dev
->name
, "Invalid bss_count %d: ignoring\n",
475 escan_result
->bss_count
);
478 bi
= escan_result
->bss_info
;
480 ESCAN_ERROR(dev
->name
, "Invalid escan bss info (NULL pointer)\n");
483 bi_length
= dtoh32(bi
->length
);
484 if (bi_length
!= (dtoh32(escan_result
->buflen
) - WL_ESCAN_RESULTS_FIXED_SIZE
)) {
485 ESCAN_ERROR(dev
->name
, "Invalid bss_info length %d: ignoring\n",
490 /* +++++ terence 20130524: skip invalid bss */
492 bi
->ctl_ch
? bi
->ctl_ch
:
493 CHSPEC_CHANNEL(wl_chspec_driver_to_host(escan
->ioctl_ver
, bi
->chanspec
));
494 if (!dhd_conf_match_channel(escan
->pub
, channel
))
496 /* ----- terence 20130524: skip invalid bss */
499 int cur_len
= WL_SCAN_RESULTS_FIXED_SIZE
;
500 #ifdef ESCAN_BUF_OVERFLOW_MGMT
501 removal_element_t candidate
[BUF_OVERFLOW_MGMT_COUNT
];
502 int remove_lower_rssi
= FALSE
;
504 bzero(candidate
, sizeof(removal_element_t
)*BUF_OVERFLOW_MGMT_COUNT
);
505 #endif /* ESCAN_BUF_OVERFLOW_MGMT */
507 list
= wl_escan_get_buf(escan
);
508 #ifdef ESCAN_BUF_OVERFLOW_MGMT
509 if (bi_length
> ESCAN_BUF_SIZE
- list
->buflen
)
510 remove_lower_rssi
= TRUE
;
511 #endif /* ESCAN_BUF_OVERFLOW_MGMT */
513 ESCAN_DBG(dev
->name
, "%s(%pM) RSSI %d flags 0x%x length %d\n",
514 bi
->SSID
, &bi
->BSSID
, bi
->RSSI
, bi
->flags
, bi
->length
);
515 for (i
= 0; i
< list
->count
; i
++) {
516 bss
= bss
? (wl_bss_info_t
*)((uintptr
)bss
+ dtoh32(bss
->length
))
518 #ifdef ESCAN_BUF_OVERFLOW_MGMT
520 "%s(%pM), i=%d bss: RSSI %d list->count %d\n",
521 bss
->SSID
, &bss
->BSSID
, i
, bss
->RSSI
, list
->count
);
523 if (remove_lower_rssi
)
524 wl_escan_find_removal_candidate(escan
, bss
, candidate
);
525 #endif /* ESCAN_BUF_OVERFLOW_MGMT */
526 if (!bcmp(&bi
->BSSID
, &bss
->BSSID
, ETHER_ADDR_LEN
) &&
527 (CHSPEC_BAND(wl_chspec_driver_to_host(escan
->ioctl_ver
, bi
->chanspec
))
528 == CHSPEC_BAND(wl_chspec_driver_to_host(escan
->ioctl_ver
, bss
->chanspec
))) &&
529 bi
->SSID_len
== bss
->SSID_len
&&
530 !bcmp(bi
->SSID
, bss
->SSID
, bi
->SSID_len
)) {
532 /* do not allow beacon data to update
533 *the data recd from a probe response
535 if (!(bss
->flags
& WL_BSS_FLAGS_FROM_BEACON
) &&
536 (bi
->flags
& WL_BSS_FLAGS_FROM_BEACON
))
540 "%s(%pM), i=%d prev: RSSI %d flags 0x%x, "
541 "new: RSSI %d flags 0x%x\n",
542 bss
->SSID
, &bi
->BSSID
, i
, bss
->RSSI
, bss
->flags
,
543 bi
->RSSI
, bi
->flags
);
545 if ((bss
->flags
& WL_BSS_FLAGS_RSSI_ONCHANNEL
) ==
546 (bi
->flags
& WL_BSS_FLAGS_RSSI_ONCHANNEL
)) {
547 /* preserve max RSSI if the measurements are
548 * both on-channel or both off-channel
551 "%s(%pM), same onchan, RSSI: prev %d new %d\n",
552 bss
->SSID
, &bi
->BSSID
, bss
->RSSI
, bi
->RSSI
);
553 bi
->RSSI
= MAX(bss
->RSSI
, bi
->RSSI
);
554 } else if ((bss
->flags
& WL_BSS_FLAGS_RSSI_ONCHANNEL
) &&
555 (bi
->flags
& WL_BSS_FLAGS_RSSI_ONCHANNEL
) == 0) {
556 /* preserve the on-channel rssi measurement
557 * if the new measurement is off channel
560 "%s(%pM), prev onchan, RSSI: prev %d new %d\n",
561 bss
->SSID
, &bi
->BSSID
, bss
->RSSI
, bi
->RSSI
);
562 bi
->RSSI
= bss
->RSSI
;
563 bi
->flags
|= WL_BSS_FLAGS_RSSI_ONCHANNEL
;
565 if (dtoh32(bss
->length
) != bi_length
) {
566 u32 prev_len
= dtoh32(bss
->length
);
569 "bss info replacement occured(bcast:%d->probresp%d)\n",
570 bss
->ie_length
, bi
->ie_length
);
572 "%s(%pM), replacement!(%d -> %d)\n",
573 bss
->SSID
, &bi
->BSSID
, prev_len
, bi_length
);
575 if (list
->buflen
- prev_len
+ bi_length
> ESCAN_BUF_SIZE
) {
576 ESCAN_ERROR(dev
->name
,
577 "Buffer is too small: keep the previous result "
579 /* Only update RSSI */
580 bss
->RSSI
= bi
->RSSI
;
581 bss
->flags
|= (bi
->flags
582 & WL_BSS_FLAGS_RSSI_ONCHANNEL
);
586 if (i
< list
->count
- 1) {
587 /* memory copy required by this case only */
588 memmove((u8
*)bss
+ bi_length
,
589 (u8
*)bss
+ prev_len
,
590 list
->buflen
- cur_len
- prev_len
);
592 list
->buflen
-= prev_len
;
593 list
->buflen
+= bi_length
;
595 list
->version
= dtoh32(bi
->version
);
596 memcpy((u8
*)bss
, (u8
*)bi
, bi_length
);
599 cur_len
+= dtoh32(bss
->length
);
601 if (bi_length
> ESCAN_BUF_SIZE
- list
->buflen
) {
602 #ifdef ESCAN_BUF_OVERFLOW_MGMT
603 wl_escan_remove_lowRSSI_info(dev
, escan
, list
, candidate
, bi
);
604 if (bi_length
> ESCAN_BUF_SIZE
- list
->buflen
) {
606 "RSSI(%pM) is too low(%d) to add Buffer\n",
607 &bi
->BSSID
, bi
->RSSI
);
611 ESCAN_ERROR(dev
->name
, "Buffer is too small: ignoring\n");
613 #endif /* ESCAN_BUF_OVERFLOW_MGMT */
616 memcpy(&(((char *)list
)[list
->buflen
]), bi
, bi_length
);
617 list
->version
= dtoh32(bi
->version
);
618 list
->buflen
+= bi_length
;
622 else if (status
== WLC_E_STATUS_SUCCESS
) {
623 ESCAN_DBG(dev
->name
, "ESCAN COMPLETED\n");
624 escan
->bss_list
= wl_escan_get_buf(escan
);
625 ESCAN_DBG(dev
->name
, "SCAN COMPLETED: scanned AP count=%d\n",
626 escan
->bss_list
->count
);
627 wl_escan_notify_complete(dev
, escan
, false);
628 } else if ((status
== WLC_E_STATUS_ABORT
) || (status
== WLC_E_STATUS_NEWSCAN
) ||
629 (status
== WLC_E_STATUS_11HQUIET
) || (status
== WLC_E_STATUS_CS_ABORT
) ||
630 (status
== WLC_E_STATUS_NEWASSOC
)) {
631 /* Handle all cases of scan abort */
632 ESCAN_DBG(dev
->name
, "ESCAN ABORT reason: %d\n", status
);
633 escan
->bss_list
= wl_escan_get_buf(escan
);
634 ESCAN_DBG(dev
->name
, "SCAN ABORT: scanned AP count=%d\n",
635 escan
->bss_list
->count
);
636 wl_escan_notify_complete(dev
, escan
, false);
637 } else if (status
== WLC_E_STATUS_TIMEOUT
) {
638 ESCAN_ERROR(dev
->name
, "WLC_E_STATUS_TIMEOUT\n");
639 ESCAN_ERROR(dev
->name
, "reason[0x%x]\n", e
->reason
);
640 if (e
->reason
== 0xFFFFFFFF) {
641 wl_escan_notify_complete(dev
, escan
, true);
644 ESCAN_ERROR(dev
->name
, "unexpected Escan Event %d : abort\n", status
);
645 escan
->bss_list
= wl_escan_get_buf(escan
);
646 ESCAN_DBG(dev
->name
, "SCAN ABORTED(UNEXPECTED): scanned AP count=%d\n",
647 escan
->bss_list
->count
);
648 wl_escan_notify_complete(dev
, escan
, false);
651 mutex_unlock(&escan
->usr_sync
);
656 wl_escan_prep(struct net_device
*dev
, struct wl_escan_info
*escan
,
657 wl_uint32_list_t
*list
, wl_scan_params_t
*params
, wlc_ssid_t
*ssid
, bool bcast
)
660 wl_scan_results_t
*results
;
670 results
= wl_escan_get_buf(escan
);
671 results
->version
= 0;
673 results
->buflen
= WL_SCAN_RESULTS_FIXED_SIZE
;
674 escan
->escan_state
= ESCAN_STATE_SCANING
;
676 /* Arm scan timeout timer */
677 mod_timer(&escan
->scan_timeout
, jiffies
+ msecs_to_jiffies(WL_ESCAN_TIMER_INTERVAL_MS
));
679 memcpy(¶ms
->bssid
, ðer_bcast
, ETHER_ADDR_LEN
);
680 params
->bss_type
= DOT11_BSSTYPE_ANY
;
681 params
->scan_type
= 0;
682 params
->nprobes
= -1;
683 params
->active_time
= -1;
684 params
->passive_time
= -1;
685 params
->home_time
= -1;
686 params
->channel_num
= 0;
688 params
->nprobes
= htod32(params
->nprobes
);
689 params
->active_time
= htod32(params
->active_time
);
690 params
->passive_time
= htod32(params
->passive_time
);
691 params
->home_time
= htod32(params
->home_time
);
693 n_channels
= dtoh32(list
->count
);
694 /* Copy channel array if applicable */
695 ESCAN_SCAN(dev
->name
, "### List of channelspecs to scan ###\n");
696 if (n_channels
> 0) {
697 for (i
= 0; i
< n_channels
; i
++) {
698 channel
= dtoh32(list
->element
[i
]);
699 if (!dhd_conf_match_channel(escan
->pub
, channel
))
701 chanspec
= WL_CHANSPEC_BW_20
;
702 if (chanspec
== INVCHANSPEC
) {
703 ESCAN_ERROR(dev
->name
, "Invalid chanspec! Skipping channel\n");
706 if (channel
<= CH_MAX_2G_CHANNEL
) {
707 chanspec
|= WL_CHANSPEC_BAND_2G
;
709 chanspec
|= WL_CHANSPEC_BAND_5G
;
711 params
->channel_list
[j
] = channel
;
712 params
->channel_list
[j
] &= WL_CHANSPEC_CHAN_MASK
;
713 params
->channel_list
[j
] |= chanspec
;
714 ESCAN_SCAN(dev
->name
, "Chan : %d, Channel spec: %x\n",
715 channel
, params
->channel_list
[j
]);
716 params
->channel_list
[j
] = wl_chspec_host_to_driver(escan
->ioctl_ver
,
717 params
->channel_list
[j
]);
721 ESCAN_SCAN(dev
->name
, "Scanning all channels\n");
724 if (ssid
&& ssid
->SSID_len
) {
725 /* Copy ssid array if applicable */
726 ESCAN_SCAN(dev
->name
, "### List of SSIDs to scan ###\n");
727 offset
= offsetof(wl_scan_params_t
, channel_list
) + n_channels
* sizeof(u16
);
728 offset
= roundup(offset
, sizeof(u32
));
729 ptr
= (char*)params
+ offset
;
733 ESCAN_SCAN(dev
->name
, "0: Broadcast scan\n");
734 memset(&ssid_tmp
, 0, sizeof(wlc_ssid_t
));
735 ssid_tmp
.SSID_len
= 0;
736 memcpy(ptr
, &ssid_tmp
, sizeof(wlc_ssid_t
));
737 ptr
+= sizeof(wlc_ssid_t
);
742 memset(&ssid_tmp
, 0, sizeof(wlc_ssid_t
));
743 ssid_tmp
.SSID_len
= ssid
->SSID_len
;
744 memcpy(ssid_tmp
.SSID
, ssid
->SSID
, ssid
->SSID_len
);
745 memcpy(ptr
, &ssid_tmp
, sizeof(wlc_ssid_t
));
746 ptr
+= sizeof(wlc_ssid_t
);
747 ESCAN_SCAN(dev
->name
, "1: scan for %s size=%d\n",
748 ssid_tmp
.SSID
, ssid_tmp
.SSID_len
);
749 /* Adding mask to channel numbers */
750 params
->channel_num
=
751 htod32((n_ssids
<< WL_SCAN_PARAMS_NSSID_SHIFT
) |
752 (n_channels
& WL_SCAN_PARAMS_COUNT_MASK
));
755 ESCAN_SCAN(dev
->name
, "Broadcast scan\n");
762 wl_escan_reset(struct wl_escan_info
*escan
)
764 if (timer_pending(&escan
->scan_timeout
))
765 del_timer_sync(&escan
->scan_timeout
);
766 escan
->escan_state
= ESCAN_STATE_IDLE
;
772 wl_escan_timeout(unsigned long data
)
775 struct wl_escan_info
*escan
= (struct wl_escan_info
*)data
;
776 struct wl_scan_results
*bss_list
;
777 struct wl_bss_info
*bi
= NULL
;
782 ESCAN_ERROR("wlan", "No dev present\n");
786 bss_list
= wl_escan_get_buf(escan
);
788 ESCAN_ERROR(escan
->dev
->name
,
789 "bss_list is null. Didn't receive any partial scan results\n");
791 ESCAN_ERROR(escan
->dev
->name
, "scanned AP count (%d)\n", bss_list
->count
);
792 bi
= next_bss(bss_list
, bi
);
793 for_each_bss(bss_list
, bi
, i
) {
794 channel
= wf_chspec_ctlchan(wl_chspec_driver_to_host(escan
->ioctl_ver
,
796 ESCAN_ERROR(escan
->dev
->name
, "SSID :%s Channel :%d\n", bi
->SSID
, channel
);
800 bzero(&msg
, sizeof(wl_event_msg_t
));
801 ESCAN_ERROR(escan
->dev
->name
, "timer expired\n");
803 msg
.ifidx
= dhd_net2idx(escan
->pub
->info
, escan
->dev
);
804 msg
.event_type
= hton32(WLC_E_ESCAN_RESULT
);
805 msg
.status
= hton32(WLC_E_STATUS_TIMEOUT
);
806 msg
.reason
= 0xFFFFFFFF;
807 wl_ext_event_send(escan
->pub
->event_params
, &msg
, NULL
);
811 wl_escan_set_scan(struct net_device
*dev
, dhd_pub_t
*dhdp
,
812 wlc_ssid_t
*ssid
, uint16 channel
, bool bcast
)
814 struct wl_escan_info
*escan
= dhdp
->escan
;
816 s32 params_size
= (WL_SCAN_PARAMS_FIXED_SIZE
+ OFFSETOF(wl_escan_params_t
, params
));
817 wl_escan_params_t
*params
= NULL
;
821 wl_uint32_list_t
*list
;
822 u8 valid_chan_list
[sizeof(u32
)*(WL_NUMCHANNELS
+ 1)];
824 mutex_lock(&escan
->usr_sync
);
825 if (escan
->escan_state
== ESCAN_STATE_DOWN
) {
826 ESCAN_ERROR(dev
->name
, "STATE is down\n");
831 if (wl_ext_check_scan(dev
, dhdp
)) {
836 ESCAN_TRACE(dev
->name
, "Enter \n");
838 /* if scan request is not empty parse scan request paramters */
839 memset(valid_chan_list
, 0, sizeof(valid_chan_list
));
840 list
= (wl_uint32_list_t
*)(void *) valid_chan_list
;
843 list
->count
= htod32(1);
844 list
->element
[0] = htod32(channel
);
846 list
->count
= htod32(WL_NUMCHANNELS
);
847 err
= wldev_ioctl(dev
, WLC_GET_VALID_CHANNELS
, valid_chan_list
,
848 sizeof(valid_chan_list
), false);
850 ESCAN_ERROR(dev
->name
, "get channels failed with %d\n", err
);
855 n_channels
= dtoh32(list
->count
);
856 /* Allocate space for populating ssids in wl_escan_params_t struct */
857 if (dtoh32(list
->count
) % 2)
858 /* If n_channels is odd, add a padd of u16 */
859 params_size
+= sizeof(u16
) * (n_channels
+ 1);
861 params_size
+= sizeof(u16
) * n_channels
;
862 if (ssid
&& ssid
->SSID_len
) {
863 params_size
+= sizeof(struct wlc_ssid
) * 2;
866 params
= (wl_escan_params_t
*) kzalloc(params_size
, GFP_KERNEL
);
867 if (params
== NULL
) {
871 wl_escan_prep(dev
, escan
, list
, ¶ms
->params
, ssid
, bcast
);
873 params
->version
= htod32(ESCAN_REQ_VERSION
);
874 params
->action
= htod16(WL_SCAN_ACTION_START
);
875 wl_escan_set_sync_id(params
->sync_id
);
876 if (params_size
+ sizeof("escan") >= WLC_IOCTL_MEDLEN
) {
877 ESCAN_ERROR(dev
->name
, "ioctl buffer length not sufficient\n");
882 params
->params
.scan_type
= DOT11_SCANTYPE_ACTIVE
;
883 ESCAN_SCAN(dev
->name
, "Passive scan_type %d\n", params
->params
.scan_type
);
885 WL_MSG(dev
->name
, "LEGACY_SCAN\n");
886 err
= wldev_iovar_setbuf(dev
, "escan", params
, params_size
,
887 escan
->escan_ioctl_buf
, WLC_IOCTL_MEDLEN
, NULL
);
889 if (err
== BCME_EPERM
)
890 /* Scan Not permitted at this point of time */
891 ESCAN_TRACE(dev
->name
, "Escan not permitted at this time (%d)\n", err
);
893 ESCAN_ERROR(dev
->name
, "Escan set error (%d)\n", err
);
898 /* Don't print Error incase of Scan suppress */
899 if (err
== BCME_EPERM
)
900 ESCAN_TRACE(dev
->name
, "Escan failed: Scan Suppressed\n");
903 ESCAN_ERROR(dev
->name
, "error (%d), cnt=%d\n", err
, cnt
);
904 // terence 20140111: send disassoc to firmware
906 memset(&scbval
, 0, sizeof(scb_val_t
));
907 wldev_ioctl(dev
, WLC_DISASSOC
, &scbval
, sizeof(scb_val_t
), true);
908 ESCAN_ERROR(dev
->name
, "Send disassoc to break the busy\n");
918 wl_escan_reset(escan
);
921 mutex_unlock(&escan
->usr_sync
);
925 #if defined(WL_WIRELESS_EXT)
927 rssi_to_qual(int rssi
)
929 if (rssi
<= WL_IW_RSSI_NO_SIGNAL
)
931 else if (rssi
<= WL_IW_RSSI_VERY_LOW
)
933 else if (rssi
<= WL_IW_RSSI_LOW
)
935 else if (rssi
<= WL_IW_RSSI_GOOD
)
937 else if (rssi
<= WL_IW_RSSI_VERY_GOOD
)
944 wl_escan_merge_scan_results(struct net_device
*dev
, struct wl_escan_info
*escan
,
945 struct iw_request_info
*info
, char *extra
, wl_bss_info_t
*bi
, int *len
, int max_size
)
950 char *event
= extra
, *end
= extra
+ max_size
- WE_ADD_EVENT_FIX
, *value
;
955 /* overflow check cover fields before wpa IEs */
956 if (event
+ ETHER_ADDR_LEN
+ bi
->SSID_len
+ IW_EV_UINT_LEN
+ IW_EV_FREQ_LEN
+
957 IW_EV_QUAL_LEN
>= end
) {
963 rssi
= wl_get_avg_rssi(&escan
->g_rssi_cache_ctrl
, &bi
->BSSID
);
964 if (rssi
== RSSI_MINVAL
)
965 rssi
= MIN(dtoh16(bi
->RSSI
), RSSI_MAXVAL
);
967 // terence 20150419: limit the max. rssi to -2 or the bss will be filtered out in android OS
968 rssi
= MIN(dtoh16(bi
->RSSI
), RSSI_MAXVAL
);
970 chanspec
= wl_chspec_driver_to_host(escan
->ioctl_ver
, bi
->chanspec
);
971 channel
= wf_chspec_ctlchan(chanspec
);
972 ESCAN_SCAN(dev
->name
, "BSSID %pM, channel %3d(%3d %sMHz), rssi %3d, SSID \"%s\"\n",
973 &bi
->BSSID
, channel
, CHSPEC_CHANNEL(chanspec
),
974 CHSPEC_IS20(chanspec
)?"20":
975 CHSPEC_IS40(chanspec
)?"40":
976 CHSPEC_IS80(chanspec
)?"80":"160",
979 /* First entry must be the BSSID */
981 iwe
.u
.ap_addr
.sa_family
= ARPHRD_ETHER
;
982 memcpy(iwe
.u
.ap_addr
.sa_data
, &bi
->BSSID
, ETHER_ADDR_LEN
);
983 event
= IWE_STREAM_ADD_EVENT(info
, event
, end
, &iwe
, IW_EV_ADDR_LEN
);
986 iwe
.u
.data
.length
= dtoh32(bi
->SSID_len
);
987 iwe
.cmd
= SIOCGIWESSID
;
988 iwe
.u
.data
.flags
= 1;
989 event
= IWE_STREAM_ADD_POINT(info
, event
, end
, &iwe
, bi
->SSID
);
992 if (dtoh16(bi
->capability
) & (DOT11_CAP_ESS
| DOT11_CAP_IBSS
)) {
993 iwe
.cmd
= SIOCGIWMODE
;
994 if (dtoh16(bi
->capability
) & DOT11_CAP_ESS
)
995 iwe
.u
.mode
= IW_MODE_INFRA
;
997 iwe
.u
.mode
= IW_MODE_ADHOC
;
998 event
= IWE_STREAM_ADD_EVENT(info
, event
, end
, &iwe
, IW_EV_UINT_LEN
);
1002 iwe
.cmd
= SIOCGIWFREQ
;
1004 iwe
.u
.freq
.m
= wf_channel2mhz(channel
, channel
<= CH_MAX_2G_CHANNEL
?
1005 WF_CHAN_FACTOR_2_4_G
: WF_CHAN_FACTOR_5_G
);
1007 iwe
.u
.freq
.m
= wf_channel2mhz(bi
->n_cap
?
1008 bi
->ctl_ch
: CHSPEC_CHANNEL(bi
->chanspec
),
1009 CHSPEC_CHANNEL(bi
->chanspec
) <= CH_MAX_2G_CHANNEL
?
1010 WF_CHAN_FACTOR_2_4_G
: WF_CHAN_FACTOR_5_G
);
1013 event
= IWE_STREAM_ADD_EVENT(info
, event
, end
, &iwe
, IW_EV_FREQ_LEN
);
1015 /* Channel quality */
1017 iwe
.u
.qual
.qual
= rssi_to_qual(rssi
);
1018 iwe
.u
.qual
.level
= 0x100 + rssi
;
1019 iwe
.u
.qual
.noise
= 0x100 + bi
->phy_noise
;
1020 event
= IWE_STREAM_ADD_EVENT(info
, event
, end
, &iwe
, IW_EV_QUAL_LEN
);
1022 wl_iw_handle_scanresults_ies(&event
, end
, info
, bi
);
1025 iwe
.cmd
= SIOCGIWENCODE
;
1026 if (dtoh16(bi
->capability
) & DOT11_CAP_PRIVACY
)
1027 iwe
.u
.data
.flags
= IW_ENCODE_ENABLED
| IW_ENCODE_NOKEY
;
1029 iwe
.u
.data
.flags
= IW_ENCODE_DISABLED
;
1030 iwe
.u
.data
.length
= 0;
1031 event
= IWE_STREAM_ADD_POINT(info
, event
, end
, &iwe
, (char *)event
);
1034 if (bi
->rateset
.count
<= sizeof(bi
->rateset
.rates
)) {
1035 if (event
+ IW_MAX_BITRATES
*IW_EV_PARAM_LEN
>= end
) {
1039 value
= event
+ IW_EV_LCP_LEN
;
1040 iwe
.cmd
= SIOCGIWRATE
;
1041 /* Those two flags are ignored... */
1042 iwe
.u
.bitrate
.fixed
= iwe
.u
.bitrate
.disabled
= 0;
1043 for (j
= 0; j
< bi
->rateset
.count
&& j
< IW_MAX_BITRATES
; j
++) {
1044 iwe
.u
.bitrate
.value
= (bi
->rateset
.rates
[j
] & 0x7f) * 500000;
1045 value
= IWE_STREAM_ADD_VALUE(info
, event
, value
, end
, &iwe
,
1050 *len
= event
- extra
;
1052 ESCAN_ERROR(dev
->name
, "==> Wrong size\n");
1059 wl_escan_get_scan(struct net_device
*dev
, dhd_pub_t
*dhdp
,
1060 struct iw_request_info
*info
, struct iw_point
*dwrq
, char *extra
)
1062 struct wl_escan_info
*escan
= dhdp
->escan
;
1065 int len_prep
= 0, len_ret
= 0;
1066 wl_bss_info_t
*bi
= NULL
;
1067 struct wl_scan_results
*bss_list
;
1068 __u16 buflen_from_user
= dwrq
->length
;
1069 #if defined(BSSCACHE)
1070 wl_bss_cache_t
*node
;
1073 struct ether_addr cur_bssid
;
1074 u8 ioctl_buf
[WLC_IOCTL_SMLEN
];
1077 ESCAN_TRACE(dev
->name
, "extra is null\n");
1081 mutex_lock(&escan
->usr_sync
);
1083 /* Check for scan in progress */
1084 if (escan
->escan_state
== ESCAN_STATE_SCANING
) {
1085 ESCAN_DBG(dev
->name
, "SIOCGIWSCAN GET still scanning\n");
1089 if (!escan
->bss_list
) {
1090 ESCAN_ERROR(dev
->name
, "scan not ready\n");
1094 if (dev
!= escan
->dev
) {
1095 ESCAN_ERROR(dev
->name
, "not my scan from %s\n", escan
->dev
->name
);
1100 ESCAN_SCAN(dev
->name
, "SIOCGIWSCAN, len=%d\n", dwrq
->length
);
1102 wldev_iovar_getbuf(dev
, "cur_etheraddr", NULL
, 0, ioctl_buf
, WLC_IOCTL_SMLEN
, NULL
);
1103 err
= wldev_ioctl(dev
, WLC_GET_BSSID
, &cur_bssid
, sizeof(cur_bssid
), false);
1104 if (err
!= BCME_NOTASSOCIATED
&&
1105 memcmp(ðer_null
, &cur_bssid
, ETHER_ADDR_LEN
) &&
1106 memcmp(ioctl_buf
, &cur_bssid
, ETHER_ADDR_LEN
)) {
1107 // merge current connected bss
1108 buf
= kzalloc(WL_EXTRA_BUF_MAX
, GFP_ATOMIC
);
1110 ESCAN_ERROR(dev
->name
, "buffer alloc failed.\n");
1114 *(u32
*)buf
= htod32(WL_EXTRA_BUF_MAX
);
1115 err
= wldev_ioctl(dev
, WLC_GET_BSS_INFO
, buf
, WL_EXTRA_BUF_MAX
, false);
1116 if (unlikely(err
)) {
1117 ESCAN_ERROR(dev
->name
, "Could not get bss info %d\n", err
);
1120 bi
= (struct wl_bss_info
*)(buf
+ 4);
1122 err
= wl_escan_merge_scan_results(dev
, escan
, info
, extra
+len_ret
, bi
,
1123 &len_prep
, buflen_from_user
-len_ret
);
1124 len_ret
+= len_prep
;
1130 #if defined(BSSCACHE)
1131 bss_list
= &escan
->g_bss_cache_ctrl
.m_cache_head
->results
;
1132 node
= escan
->g_bss_cache_ctrl
.m_cache_head
;
1133 for (i
=0; node
&& i
<IW_MAX_AP
; i
++)
1135 bss_list
= escan
->bss_list
;
1136 bi
= next_bss(bss_list
, bi
);
1137 for_each_bss(bss_list
, bi
, i
)
1140 #if defined(BSSCACHE)
1141 bi
= node
->results
.bss_info
;
1143 if (!memcmp(&bi
->BSSID
, &cur_bssid
, ETHER_ADDR_LEN
)) {
1144 ESCAN_SCAN(dev
->name
, "skip connected AP %pM\n", &cur_bssid
);
1145 #if defined(BSSCACHE)
1151 err
= wl_escan_merge_scan_results(dev
, escan
, info
, extra
+len_ret
, bi
,
1152 &len_prep
, buflen_from_user
-len_ret
);
1153 len_ret
+= len_prep
;
1156 #if defined(BSSCACHE)
1161 if ((len_ret
+ WE_ADD_EVENT_FIX
) < dwrq
->length
)
1162 dwrq
->length
= len_ret
;
1164 dwrq
->flags
= 0; /* todo */
1165 ESCAN_SCAN(dev
->name
, "scanned AP count (%d)\n", i
);
1168 dwrq
->length
= len_ret
;
1169 mutex_unlock(&escan
->usr_sync
);
1172 #endif /* WL_WIRELESS_EXT */
1176 wl_escan_meshid_ie(u8
*parse
, u32 len
, wlc_ssid_t
*mesh_id
)
1180 if((ie
= bcm_parse_tlvs(parse
, (int)len
, DOT11_MNG_MESH_ID
)) != NULL
) {
1181 mesh_id
->SSID_len
= ie
->len
;
1183 strncpy(mesh_id
->SSID
, ie
->data
, ie
->len
);
1191 wl_escan_rsn_ie(u8
*parse
, u32 len
)
1193 if (bcm_parse_tlvs(parse
, (u32
)len
, DOT11_MNG_RSN_ID
)) {
1200 wl_escan_mesh_info_ie(struct net_device
*dev
, u8
*parse
, u32 len
,
1201 struct wl_mesh_params
*mesh_info
)
1204 uchar mesh_oui
[]={0x00, 0x22, 0xf4};
1210 memset(mesh_info
, 0, sizeof(struct wl_mesh_params
));
1211 if((ie
= bcm_parse_tlvs(parse
, (int)len
, DOT11_MNG_VS_ID
)) != NULL
) {
1213 if (!memcmp(ie
->data
, &mesh_oui
, sizeof(mesh_oui
))) {
1214 pie
= ie
->data
+ sizeof(mesh_oui
);
1215 ie
= (bcm_tlv_t
*)pie
;
1216 totl_len
-= sizeof(mesh_oui
);
1217 while (totl_len
> 2 && ie
->len
) {
1218 if (ie
->id
== MESH_INFO_MASTER_BSSID
&& ie
->len
== ETHER_ADDR_LEN
) {
1219 memcpy(&mesh_info
->master_bssid
, ie
->data
, ETHER_ADDR_LEN
);
1220 } else if (ie
->id
== MESH_INFO_MASTER_CHANNEL
) {
1221 mesh_info
->master_channel
= ie
->data
[0];
1223 } else if (ie
->id
== MESH_INFO_HOP_CNT
) {
1224 mesh_info
->hop_cnt
= ie
->data
[0];
1225 } else if (ie
->id
== MESH_INFO_PEER_BSSID
) {
1226 max_len
= min(MAX_HOP_LIST
*ETHER_ADDR_LEN
, (int)ie
->len
);
1227 memcpy(mesh_info
->peer_bssid
, ie
->data
, max_len
);
1229 totl_len
-= (ie
->len
+ 2);
1230 pie
= ie
->data
+ ie
->len
;
1231 ie
= (bcm_tlv_t
*)pie
;
1240 wl_escan_mesh_info(struct net_device
*dev
, struct wl_escan_info
*escan
,
1241 struct ether_addr
*peer_bssid
, struct wl_mesh_params
*mesh_info
)
1244 wl_bss_info_t
*bi
= NULL
;
1245 struct wl_scan_results
*bss_list
;
1246 int16 bi_rssi
, bi_chan
;
1247 wlc_ssid_t bi_meshid
;
1248 bool is_mesh_peer
= FALSE
, found
= FALSE
;
1249 struct wl_mesh_params peer_mesh_info
;
1251 mutex_lock(&escan
->usr_sync
);
1253 /* Check for scan in progress */
1254 if (escan
->escan_state
== ESCAN_STATE_SCANING
) {
1255 ESCAN_ERROR(dev
->name
, "SIOCGIWSCAN GET still scanning\n");
1258 if (!escan
->bss_list
) {
1259 ESCAN_ERROR(dev
->name
, "scan not ready\n");
1262 if (dev
!= escan
->dev
) {
1263 ESCAN_ERROR(dev
->name
, "not my scan from %s\n", escan
->dev
->name
);
1267 bss_list
= escan
->bss_list
;
1268 bi
= next_bss(bss_list
, bi
);
1269 ESCAN_SCAN(dev
->name
, "scanned AP/Mesh count (%d)\n", bss_list
->count
);
1270 for_each_bss(bss_list
, bi
, i
)
1272 memset(&bi_meshid
, 0, sizeof(bi_meshid
));
1273 is_mesh_peer
= FALSE
;
1274 bi_chan
= wf_chspec_ctlchan(
1275 wl_chspec_driver_to_host(escan
->ioctl_ver
, bi
->chanspec
));
1276 bi_rssi
= MIN(dtoh16(bi
->RSSI
), RSSI_MAXVAL
);
1277 is_mesh_peer
= wl_escan_meshid_ie(((u8
*)bi
)+bi
->ie_offset
,
1278 bi
->ie_length
, &bi_meshid
);
1279 if (!(bi
->capability
& (DOT11_CAP_ESS
|DOT11_CAP_IBSS
)) && is_mesh_peer
) {
1280 bool bi_sae
= FALSE
, bss_found
= FALSE
, prefer
= FALSE
;
1281 if (!memcmp(peer_bssid
, &bi
->BSSID
, ETHER_ADDR_LEN
)) {
1282 bi_sae
= wl_escan_rsn_ie(((u8
*)bi
)+bi
->ie_offset
, bi
->ie_length
);
1283 bss_found
= wl_escan_mesh_info_ie(dev
, ((u8
*)bi
)+bi
->ie_offset
,
1284 bi
->ie_length
, &peer_mesh_info
);
1286 memcpy(&mesh_info
->master_bssid
, &peer_mesh_info
.master_bssid
,
1288 mesh_info
->master_channel
= peer_mesh_info
.master_channel
;
1289 mesh_info
->hop_cnt
= peer_mesh_info
.hop_cnt
;
1290 memcpy(mesh_info
->peer_bssid
, peer_mesh_info
.peer_bssid
,
1291 sizeof(peer_mesh_info
.peer_bssid
));
1296 ESCAN_SCAN(dev
->name
,
1297 "%s[Mesh] BSSID=%pM, channel=%d, RSSI=%d, sec=%s, "
1298 "mbssid=%pM, mchannel=%d, hop=%d, pbssid=%pM, MeshID=\"%s\"\n",
1299 prefer
?"*":" ", &bi
->BSSID
, bi_chan
, bi_rssi
, bi_sae
?"SAE":"OPEN",
1300 &peer_mesh_info
.master_bssid
, peer_mesh_info
.master_channel
,
1301 peer_mesh_info
.hop_cnt
, &peer_mesh_info
.peer_bssid
, bi_meshid
.SSID
);
1306 mutex_unlock(&escan
->usr_sync
);
1311 wl_escan_mesh_peer(struct net_device
*dev
, struct wl_escan_info
*escan
,
1312 wlc_ssid_t
*cur_ssid
, uint16 cur_chan
, bool sae
,
1313 struct wl_mesh_params
*mesh_info
)
1316 wl_bss_info_t
*bi
= NULL
;
1317 struct wl_scan_results
*bss_list
;
1318 int16 bi_rssi
, bi_chan
, max_rssi
= -100;
1319 uint min_hop_cnt
= 255;
1320 wlc_ssid_t bi_meshid
;
1321 bool is_mesh_peer
= FALSE
, chan_matched
= FALSE
, found
= FALSE
;
1322 struct wl_mesh_params peer_mesh_info
;
1324 mutex_lock(&escan
->usr_sync
);
1326 /* Check for scan in progress */
1327 if (escan
->escan_state
== ESCAN_STATE_SCANING
) {
1328 ESCAN_ERROR(dev
->name
, "SIOCGIWSCAN GET still scanning\n");
1331 if (!escan
->bss_list
) {
1332 ESCAN_ERROR(dev
->name
, "scan not ready\n");
1335 if (dev
!= escan
->dev
) {
1336 ESCAN_ERROR(dev
->name
, "not my scan from %s\n", escan
->dev
->name
);
1340 bss_list
= escan
->bss_list
;
1341 bi
= next_bss(bss_list
, bi
);
1342 ESCAN_SCAN(dev
->name
, "scanned AP/Mesh count (%d)\n", bss_list
->count
);
1343 for_each_bss(bss_list
, bi
, i
)
1345 memset(&bi_meshid
, 0, sizeof(bi_meshid
));
1346 is_mesh_peer
= FALSE
;
1347 bi_chan
= wf_chspec_ctlchan(
1348 wl_chspec_driver_to_host(escan
->ioctl_ver
, bi
->chanspec
));
1349 bi_rssi
= MIN(dtoh16(bi
->RSSI
), RSSI_MAXVAL
);
1350 is_mesh_peer
= wl_escan_meshid_ie(((u8
*)bi
)+bi
->ie_offset
,
1351 bi
->ie_length
, &bi_meshid
);
1352 if (!(bi
->capability
& (DOT11_CAP_ESS
|DOT11_CAP_IBSS
)) && is_mesh_peer
) {
1353 bool meshid_matched
= FALSE
, sec_matched
= FALSE
, bi_sae
= FALSE
,
1354 bss_found
= FALSE
, prefer
= FALSE
;
1356 if (cur_ssid
->SSID_len
&& cur_ssid
->SSID_len
== bi_meshid
.SSID_len
&&
1357 !memcmp(cur_ssid
->SSID
, bi_meshid
.SSID
, bi_meshid
.SSID_len
))
1358 meshid_matched
= TRUE
;
1360 bi_sae
= wl_escan_rsn_ie(((u8
*)bi
)+bi
->ie_offset
, bi
->ie_length
);
1364 bss_found
= wl_escan_mesh_info_ie(dev
, ((u8
*)bi
)+bi
->ie_offset
, bi
->ie_length
,
1366 if (meshid_matched
&& sec_matched
&& bss_found
&&
1367 (cur_chan
== bi_chan
)) {
1368 if (peer_mesh_info
.hop_cnt
< min_hop_cnt
) {
1369 memcpy(&mesh_info
->master_bssid
, &peer_mesh_info
.master_bssid
,
1371 mesh_info
->master_channel
= peer_mesh_info
.master_channel
;
1372 mesh_info
->hop_cnt
= peer_mesh_info
.hop_cnt
;
1373 memcpy(mesh_info
->peer_bssid
, peer_mesh_info
.peer_bssid
,
1374 sizeof(peer_mesh_info
.peer_bssid
));
1375 min_hop_cnt
= peer_mesh_info
.hop_cnt
;
1377 chan_matched
= TRUE
;
1381 else if (meshid_matched
&& sec_matched
&& bss_found
&&
1382 (cur_chan
!= bi_chan
) && !chan_matched
) {
1383 if (bi_rssi
> max_rssi
) {
1384 memcpy(&mesh_info
->master_bssid
, &peer_mesh_info
.master_bssid
,
1386 mesh_info
->master_channel
= peer_mesh_info
.master_channel
;
1387 mesh_info
->hop_cnt
= peer_mesh_info
.hop_cnt
;
1388 memcpy(mesh_info
->peer_bssid
, peer_mesh_info
.peer_bssid
,
1389 sizeof(peer_mesh_info
.peer_bssid
));
1396 ESCAN_SCAN(dev
->name
,
1397 "%s[Mesh] BSSID=%pM, channel=%d, RSSI=%d, sec=%s, "
1398 "mbssid=%pM, mchannel=%d, hop=%d, pbssid=%pM, MeshID=\"%s\"\n",
1399 prefer
?"*":" ", &bi
->BSSID
, bi_chan
, bi_rssi
, bi_sae
?"SAE":"OPEN",
1400 &peer_mesh_info
.master_bssid
, peer_mesh_info
.master_channel
,
1401 peer_mesh_info
.hop_cnt
, &peer_mesh_info
.peer_bssid
, bi_meshid
.SSID
);
1403 ESCAN_SCAN(dev
->name
,
1404 "[AP] BSSID=%pM, channel=%d, RSSI=%d, SSID=\"%s\"\n",
1405 &bi
->BSSID
, bi_chan
, bi_rssi
, bi
->SSID
);
1410 mutex_unlock(&escan
->usr_sync
);
1416 wl_escan_deinit(struct net_device
*dev
, struct wl_escan_info
*escan
)
1418 ESCAN_TRACE(dev
->name
, "Enter\n");
1420 del_timer_sync(&escan
->scan_timeout
);
1421 escan
->escan_state
= ESCAN_STATE_DOWN
;
1423 #if defined(RSSIAVG)
1424 wl_free_rssi_cache(&escan
->g_rssi_cache_ctrl
);
1426 #if defined(BSSCACHE)
1427 wl_free_bss_cache(&escan
->g_bss_cache_ctrl
);
1432 wl_escan_init(struct net_device
*dev
, struct wl_escan_info
*escan
)
1434 ESCAN_TRACE(dev
->name
, "Enter\n");
1436 /* Init scan_timeout timer */
1437 init_timer_compat(&escan
->scan_timeout
, wl_escan_timeout
, escan
);
1438 escan
->escan_state
= ESCAN_STATE_IDLE
;
1444 wl_escan_down(struct net_device
*dev
, dhd_pub_t
*dhdp
)
1446 struct wl_escan_info
*escan
= dhdp
->escan
;
1448 ESCAN_TRACE(dev
->name
, "Enter\n");
1450 ESCAN_ERROR(dev
->name
, "escan is NULL\n");
1454 wl_escan_deinit(dev
, escan
);
1458 wl_escan_up(struct net_device
*dev
, dhd_pub_t
*dhdp
)
1460 struct wl_escan_info
*escan
= dhdp
->escan
;
1464 ESCAN_TRACE(dev
->name
, "Enter\n");
1466 ESCAN_ERROR(dev
->name
, "escan is NULL\n");
1470 ret
= wl_escan_init(dev
, escan
);
1472 ESCAN_ERROR(dev
->name
, "wl_escan_init ret %d\n", ret
);
1476 if (!escan
->ioctl_ver
) {
1478 if ((ret
= wldev_ioctl(dev
, WLC_GET_VERSION
, &val
, sizeof(int), false) < 0)) {
1479 ESCAN_ERROR(dev
->name
, "WLC_GET_VERSION failed, ret=%d\n", ret
);
1483 if (val
!= WLC_IOCTL_VERSION
&& val
!= 1) {
1484 ESCAN_ERROR(dev
->name
,
1485 "Version mismatch, please upgrade. Got %d, expected %d or 1\n",
1486 val
, WLC_IOCTL_VERSION
);
1489 escan
->ioctl_ver
= val
;
1496 wl_escan_event_dettach(struct net_device
*dev
, dhd_pub_t
*dhdp
)
1498 struct wl_escan_info
*escan
= dhdp
->escan
;
1502 ESCAN_ERROR(dev
->name
, "escan is NULL\n");
1506 wl_ext_event_deregister(dev
, dhdp
, WLC_E_ESCAN_RESULT
, wl_escan_handler
);
1512 wl_escan_event_attach(struct net_device
*dev
, dhd_pub_t
*dhdp
)
1514 struct wl_escan_info
*escan
= dhdp
->escan
;
1518 ESCAN_ERROR(dev
->name
, "escan is NULL\n");
1522 ret
= wl_ext_event_register(dev
, dhdp
, WLC_E_ESCAN_RESULT
, wl_escan_handler
,
1523 escan
, PRIO_EVENT_ESCAN
);
1525 ESCAN_ERROR(dev
->name
, "wl_ext_event_register err %d\n", ret
);
1532 wl_escan_detach(struct net_device
*dev
, dhd_pub_t
*dhdp
)
1534 struct wl_escan_info
*escan
= dhdp
->escan
;
1536 ESCAN_TRACE(dev
->name
, "Enter\n");
1541 wl_escan_deinit(dev
, escan
);
1542 if (escan
->escan_ioctl_buf
) {
1543 kfree(escan
->escan_ioctl_buf
);
1544 escan
->escan_ioctl_buf
= NULL
;
1546 wl_ext_event_deregister(dev
, dhdp
, WLC_E_ESCAN_RESULT
, wl_escan_handler
);
1548 DHD_OS_PREFREE(dhdp
, escan
, sizeof(struct wl_escan_info
));
1553 wl_escan_attach(struct net_device
*dev
, dhd_pub_t
*dhdp
)
1555 struct wl_escan_info
*escan
= NULL
;
1558 ESCAN_TRACE(dev
->name
, "Enter\n");
1560 escan
= (struct wl_escan_info
*)DHD_OS_PREALLOC(dhdp
,
1561 DHD_PREALLOC_WL_ESCAN
, sizeof(struct wl_escan_info
));
1564 memset(escan
, 0, sizeof(struct wl_escan_info
));
1566 dhdp
->escan
= escan
;
1568 /* we only care about main interface so save a global here */
1570 escan
->escan_state
= ESCAN_STATE_DOWN
;
1572 escan
->escan_ioctl_buf
= (void *)kzalloc(WLC_IOCTL_MAXLEN
, GFP_KERNEL
);
1573 if (unlikely(!escan
->escan_ioctl_buf
)) {
1574 ESCAN_ERROR(dev
->name
, "Ioctl buf alloc failed\n");
1578 ret
= wl_escan_init(dev
, escan
);
1580 ESCAN_ERROR(dev
->name
, "wl_escan_init err %d\n", ret
);
1583 mutex_init(&escan
->usr_sync
);
1588 wl_escan_detach(dev
, dhdp
);
1592 #endif /* WL_ESCAN */