10 #include <proto/ethernet.h>
12 #include <linux/if_arp.h>
13 #include <asm/uaccess.h>
16 #include <wl_android.h>
19 #include <dhd_config.h>
22 #define ESCAN_ERROR_LEVEL 0x0001
23 #define ESCAN_SCAN_LEVEL 0x0002
24 #define ESCAN_TRACE_LEVEL 0x0004
26 #define ESCAN_ERROR(x) \
28 if (iw_msg_level & ESCAN_ERROR_LEVEL) { \
29 printf(KERN_ERR "ESCAN-ERROR) "); \
33 #define ESCAN_SCAN(x) \
35 if (iw_msg_level & ESCAN_SCAN_LEVEL) { \
36 printf(KERN_ERR "ESCAN-SCAN) "); \
40 #define ESCAN_TRACE(x) \
42 if (iw_msg_level & ESCAN_TRACE_LEVEL) { \
43 printf(KERN_ERR "ESCAN-TRACE) "); \
48 /* IOCTL swapping mode for Big Endian host with Little Endian dongle. Default to off */
53 #define htodchanspec(i) (i)
54 #define dtohchanspec(i) (i)
56 #define wl_escan_get_buf(a) ((wl_scan_results_t *) (a)->escan_buf)
58 #define for_each_bss(list, bss, __i) \
59 for (__i = 0; __i < list->count && __i < IW_MAX_AP; __i++, bss = next_bss(list, bss))
61 #define wl_escan_set_sync_id(a) ((a) = htod16(0x1234))
63 #ifdef ESCAN_BUF_OVERFLOW_MGMT
64 #define BUF_OVERFLOW_MGMT_COUNT 3
68 struct ether_addr BSSID;
70 #endif /* ESCAN_BUF_OVERFLOW_MGMT */
72 struct wl_escan_info *g_escan = NULL;
75 static wl_rssi_cache_ctrl_t g_rssi_cache_ctrl;
76 static wl_rssi_cache_ctrl_t g_connected_rssi_cache_ctrl;
79 static wl_bss_cache_ctrl_t g_bss_cache_ctrl;
82 /* Return a new chanspec given a legacy chanspec
83 * Returns INVCHANSPEC on error
86 wl_chspec_from_legacy(chanspec_t legacy_chspec)
90 /* get the channel number */
91 chspec = LCHSPEC_CHANNEL(legacy_chspec);
93 /* convert the band */
94 if (LCHSPEC_IS2G(legacy_chspec)) {
95 chspec |= WL_CHANSPEC_BAND_2G;
97 chspec |= WL_CHANSPEC_BAND_5G;
100 /* convert the bw and sideband */
101 if (LCHSPEC_IS20(legacy_chspec)) {
102 chspec |= WL_CHANSPEC_BW_20;
104 chspec |= WL_CHANSPEC_BW_40;
105 if (LCHSPEC_CTL_SB(legacy_chspec) == WL_LCHANSPEC_CTL_SB_LOWER) {
106 chspec |= WL_CHANSPEC_CTL_SB_L;
108 chspec |= WL_CHANSPEC_CTL_SB_U;
112 if (wf_chspec_malformed(chspec)) {
113 ESCAN_ERROR(("wl_chspec_from_legacy: output chanspec (0x%04X) malformed\n",
121 /* Return a legacy chanspec given a new chanspec
122 * Returns INVCHANSPEC on error
125 wl_chspec_to_legacy(chanspec_t chspec)
129 if (wf_chspec_malformed(chspec)) {
130 ESCAN_ERROR(("wl_chspec_to_legacy: input chanspec (0x%04X) malformed\n",
135 /* get the channel number */
136 lchspec = CHSPEC_CHANNEL(chspec);
138 /* convert the band */
139 if (CHSPEC_IS2G(chspec)) {
140 lchspec |= WL_LCHANSPEC_BAND_2G;
142 lchspec |= WL_LCHANSPEC_BAND_5G;
145 /* convert the bw and sideband */
146 if (CHSPEC_IS20(chspec)) {
147 lchspec |= WL_LCHANSPEC_BW_20;
148 lchspec |= WL_LCHANSPEC_CTL_SB_NONE;
149 } else if (CHSPEC_IS40(chspec)) {
150 lchspec |= WL_LCHANSPEC_BW_40;
151 if (CHSPEC_CTL_SB(chspec) == WL_CHANSPEC_CTL_SB_L) {
152 lchspec |= WL_LCHANSPEC_CTL_SB_LOWER;
154 lchspec |= WL_LCHANSPEC_CTL_SB_UPPER;
157 /* cannot express the bandwidth */
158 char chanbuf[CHANSPEC_STR_LEN];
160 "wl_chspec_to_legacy: unable to convert chanspec %s (0x%04X) "
161 "to pre-11ac format\n",
162 wf_chspec_ntoa(chspec, chanbuf), chspec));
169 /* given a chanspec value from the driver, do the endian and chanspec version conversion to
171 * Returns INVCHANSPEC on error
174 wl_chspec_driver_to_host(int ioctl_ver, chanspec_t chanspec)
176 chanspec = dtohchanspec(chanspec);
177 if (ioctl_ver == 1) {
178 chanspec = wl_chspec_from_legacy(chanspec);
184 /* given a chanspec value, do the endian and chanspec version conversion to
186 * Returns INVCHANSPEC on error
189 wl_chspec_host_to_driver(chanspec_t chanspec)
192 chanspec = wl_chspec_to_legacy(chanspec);
193 if (chanspec == INVCHANSPEC) {
197 chanspec = htodchanspec(chanspec);
202 /* given a channel value, do the endian and chanspec version conversion to
204 * Returns INVCHANSPEC on error
207 wl_ch_host_to_driver(s32 bssidx, u16 channel)
211 chanspec = channel & WL_CHANSPEC_CHAN_MASK;
213 if (channel <= CH_MAX_2G_CHANNEL)
214 chanspec |= WL_CHANSPEC_BAND_2G;
216 chanspec |= WL_CHANSPEC_BAND_5G;
218 chanspec |= WL_CHANSPEC_BW_20;
220 chanspec |= WL_CHANSPEC_CTL_SB_NONE;
222 return wl_chspec_host_to_driver(chanspec);
225 static inline struct wl_bss_info *next_bss(struct wl_scan_results *list, struct wl_bss_info *bss)
228 (struct wl_bss_info *)((uintptr) bss + dtoh32(bss->length)) : list->bss_info;
231 #define MAC2STR(a) (a)[0], (a)[1], (a)[2], (a)[3], (a)[4], (a)[5]
234 rssi_to_qual(int rssi)
236 if (rssi <= WL_IW_RSSI_NO_SIGNAL)
238 else if (rssi <= WL_IW_RSSI_VERY_LOW)
240 else if (rssi <= WL_IW_RSSI_LOW)
242 else if (rssi <= WL_IW_RSSI_GOOD)
244 else if (rssi <= WL_IW_RSSI_VERY_GOOD)
250 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == \
251 4 && __GNUC_MINOR__ >= 6))
252 #define BCM_SET_LIST_FIRST_ENTRY(entry, ptr, type, member) \
253 _Pragma("GCC diagnostic push") \
254 _Pragma("GCC diagnostic ignored \"-Wcast-qual\"") \
255 (entry) = list_first_entry((ptr), type, member); \
256 _Pragma("GCC diagnostic pop") \
258 #define BCM_SET_CONTAINER_OF(entry, ptr, type, member) \
259 _Pragma("GCC diagnostic push") \
260 _Pragma("GCC diagnostic ignored \"-Wcast-qual\"") \
261 entry = container_of((ptr), type, member); \
262 _Pragma("GCC diagnostic pop") \
265 #define BCM_SET_LIST_FIRST_ENTRY(entry, ptr, type, member) \
266 (entry) = list_first_entry((ptr), type, member); \
268 #define BCM_SET_CONTAINER_OF(entry, ptr, type, member) \
269 entry = container_of((ptr), type, member); \
271 #endif /* STRICT_GCC_WARNINGS */
273 static unsigned long wl_lock_eq(struct wl_escan_info *escan)
277 spin_lock_irqsave(&escan->eq_lock, flags);
281 static void wl_unlock_eq(struct wl_escan_info *escan, unsigned long flags)
283 spin_unlock_irqrestore(&escan->eq_lock, flags);
286 static void wl_init_eq(struct wl_escan_info *escan)
288 spin_lock_init(&escan->eq_lock);
289 INIT_LIST_HEAD(&escan->eq_list);
292 static void wl_flush_eq(struct wl_escan_info *escan)
294 struct escan_event_q *e;
297 flags = wl_lock_eq(escan);
298 while (!list_empty_careful(&escan->eq_list)) {
299 BCM_SET_LIST_FIRST_ENTRY(e, &escan->eq_list, struct escan_event_q, eq_list);
300 list_del(&e->eq_list);
303 wl_unlock_eq(escan, flags);
306 static struct escan_event_q *wl_deq_event(struct wl_escan_info *escan)
308 struct escan_event_q *e = NULL;
311 flags = wl_lock_eq(escan);
312 if (likely(!list_empty(&escan->eq_list))) {
313 BCM_SET_LIST_FIRST_ENTRY(e, &escan->eq_list, struct escan_event_q, eq_list);
314 list_del(&e->eq_list);
316 wl_unlock_eq(escan, flags);
322 * push event to tail of the queue
326 wl_enq_event(struct wl_escan_info *escan, struct net_device *ndev, u32 event,
327 const wl_event_msg_t *msg, void *data)
329 struct escan_event_q *e;
338 data_len = ntoh32(msg->datalen);
339 evtq_size = sizeof(struct escan_event_q) + data_len;
340 aflags = (in_atomic()) ? GFP_ATOMIC : GFP_KERNEL;
341 e = kzalloc(evtq_size, aflags);
343 ESCAN_ERROR(("event alloc failed\n"));
347 memcpy(&e->emsg, msg, sizeof(wl_event_msg_t));
349 memcpy(e->edata, data, data_len);
350 flags = wl_lock_eq(escan);
351 list_add_tail(&e->eq_list, &escan->eq_list);
352 wl_unlock_eq(escan, flags);
357 static void wl_put_event(struct escan_event_q *e)
362 static void wl_wakeup_event(struct wl_escan_info *escan)
364 dhd_pub_t *dhd = (dhd_pub_t *)(escan->pub);
366 if (dhd->up && (escan->event_tsk.thr_pid >= 0)) {
367 up(&escan->event_tsk.sema);
371 static s32 wl_escan_event_handler(void *data)
373 struct wl_escan_info *escan = NULL;
374 struct escan_event_q *e;
375 tsk_ctl_t *tsk = (tsk_ctl_t *)data;
377 escan = (struct wl_escan_info *)tsk->parent;
379 printf("tsk Enter, tsk = 0x%p\n", tsk);
381 while (down_interruptible (&tsk->sema) == 0) {
382 SMP_RD_BARRIER_DEPENDS();
383 if (tsk->terminated) {
386 while (escan && (e = wl_deq_event(escan))) {
387 ESCAN_TRACE(("dev=%p, event type (%d), ifidx: %d bssidx: %d \n",
388 escan->dev, e->etype, e->emsg.ifidx, e->emsg.bsscfgidx));
390 if (e->emsg.ifidx > WL_MAX_IFS) {
391 ESCAN_ERROR(("Event ifidx not in range. val:%d \n", e->emsg.ifidx));
395 if (escan->dev && escan->evt_handler[e->etype]) {
396 dhd_pub_t *dhd = (struct dhd_pub *)(escan->pub);
397 if (dhd->busstate == DHD_BUS_DOWN) {
398 ESCAN_ERROR((": BUS is DOWN.\n"));
400 escan->evt_handler[e->etype](escan, &e->emsg, e->edata);
403 ESCAN_TRACE(("Unknown Event (%d): ignoring\n", e->etype));
407 DHD_EVENT_WAKE_UNLOCK(escan->pub);
410 printf("%s: was terminated\n", __FUNCTION__);
411 complete_and_exit(&tsk->completed, 0);
416 wl_escan_event(struct net_device *ndev, const wl_event_msg_t * e, void *data)
418 u32 event_type = ntoh32(e->event_type);
419 struct wl_escan_info *escan = g_escan;
421 if (!escan || !escan->dev) {
425 if (escan->event_tsk.thr_pid == -1) {
426 ESCAN_ERROR(("Event handler is not created\n"));
431 ESCAN_ERROR(("Stale event ignored\n"));
435 if (event_type == WLC_E_PFN_NET_FOUND) {
436 ESCAN_TRACE(("PNOEVENT: PNO_NET_FOUND\n"));
438 else if (event_type == WLC_E_PFN_NET_LOST) {
439 ESCAN_TRACE(("PNOEVENT: PNO_NET_LOST\n"));
442 DHD_EVENT_WAKE_LOCK(escan->pub);
443 if (likely(!wl_enq_event(escan, ndev, event_type, e, data))) {
444 wl_wakeup_event(escan);
446 DHD_EVENT_WAKE_UNLOCK(escan->pub);
450 static s32 wl_escan_inform_bss(struct wl_escan_info *escan)
452 struct wl_scan_results *bss_list;
458 bss_list = escan->bss_list;
460 /* Delete disconnected cache */
461 #if defined(BSSCACHE)
462 wl_delete_disconnected_bss_cache(&g_bss_cache_ctrl, (u8*)&escan->disconnected_bssid);
464 wl_delete_disconnected_rssi_cache(&g_rssi_cache_ctrl, (u8*)&escan->disconnected_bssid);
470 wl_update_rssi_cache(&g_rssi_cache_ctrl, bss_list);
472 wl_update_connected_rssi_cache(escan->dev, &g_rssi_cache_ctrl, &rssi);
474 #if defined(BSSCACHE)
475 wl_update_bss_cache(&g_bss_cache_ctrl,
482 /* delete dirty cache */
484 wl_delete_dirty_rssi_cache(&g_rssi_cache_ctrl);
485 wl_reset_rssi_cache(&g_rssi_cache_ctrl);
487 #if defined(BSSCACHE)
488 wl_delete_dirty_bss_cache(&g_bss_cache_ctrl);
489 wl_reset_bss_cache(&g_bss_cache_ctrl);
492 ESCAN_TRACE(("scanned AP count (%d)\n", bss_list->count));
497 static wl_scan_params_t *
498 wl_escan_alloc_params(int channel, int nprobes, int *out_params_size)
500 wl_scan_params_t *params;
505 *out_params_size = 0;
507 /* Our scan params only need space for 1 channel and 0 ssids */
508 params_size = WL_SCAN_PARAMS_FIXED_SIZE + 1 * sizeof(uint16);
509 params = (wl_scan_params_t*) kzalloc(params_size, GFP_KERNEL);
510 if (params == NULL) {
511 ESCAN_ERROR(("mem alloc failed (%d bytes)\n", params_size));
514 memset(params, 0, params_size);
515 params->nprobes = nprobes;
517 num_chans = (channel == 0) ? 0 : 1;
519 memcpy(¶ms->bssid, ðer_bcast, ETHER_ADDR_LEN);
520 params->bss_type = DOT11_BSSTYPE_ANY;
521 params->scan_type = DOT11_SCANTYPE_ACTIVE;
522 params->nprobes = htod32(1);
523 params->active_time = htod32(-1);
524 params->passive_time = htod32(-1);
525 params->home_time = htod32(10);
527 params->channel_list[0] = htodchanspec(channel);
529 params->channel_list[0] = wl_ch_host_to_driver(bssidx, channel);
531 /* Our scan params have 1 channel and 0 ssids */
532 params->channel_num = htod32((0 << WL_SCAN_PARAMS_NSSID_SHIFT) |
533 (num_chans & WL_SCAN_PARAMS_COUNT_MASK));
535 *out_params_size = params_size; /* rtn size to the caller */
539 static void wl_escan_abort(struct wl_escan_info *escan)
541 wl_scan_params_t *params = NULL;
545 /* Our scan params only need space for 1 channel and 0 ssids */
546 params = wl_escan_alloc_params(-1, 0, ¶ms_size);
547 if (params == NULL) {
548 ESCAN_ERROR(("scan params allocation failed \n"));
551 /* Do a scan abort to stop the driver's scan engine */
552 err = wldev_ioctl(escan->dev, WLC_SCAN, params, params_size, true);
554 ESCAN_ERROR(("scan abort failed \n"));
561 static s32 wl_notify_escan_complete(struct wl_escan_info *escan, bool fw_abort)
565 #if WIRELESS_EXT > 13
566 union iwreq_data wrqu;
567 char extra[IW_CUSTOM_MAX + 1];
569 memset(extra, 0, sizeof(extra));
572 ESCAN_TRACE(("Enter\n"));
574 if (!escan || !escan->dev) {
575 ESCAN_ERROR(("escan or dev is null\n"));
579 if (fw_abort && !in_atomic())
580 wl_escan_abort(escan);
582 if (timer_pending(&escan->scan_timeout))
583 del_timer_sync(&escan->scan_timeout);
584 #if defined(ESCAN_RESULT_PATCH)
585 escan->bss_list = wl_escan_get_buf(escan);
586 wl_escan_inform_bss(escan);
587 #endif /* ESCAN_RESULT_PATCH */
589 #if WIRELESS_EXT > 13
590 #if WIRELESS_EXT > 14
593 ESCAN_TRACE(("event WLC_E_SCAN_COMPLETE\n"));
594 // terence 20150224: fix "wlan0: (WE) : Wireless Event too big (65306)"
595 memset(&wrqu, 0, sizeof(wrqu));
597 if (cmd == SIOCGIWSCAN) {
598 wireless_send_event(escan->dev, cmd, &wrqu, NULL);
600 wireless_send_event(escan->dev, cmd, &wrqu, extra);
608 #ifdef ESCAN_BUF_OVERFLOW_MGMT
610 wl_cfg80211_find_removal_candidate(wl_bss_info_t *bss, removal_element_t *candidate)
613 for (idx = 0; idx < BUF_OVERFLOW_MGMT_COUNT; idx++) {
614 int len = BUF_OVERFLOW_MGMT_COUNT - idx - 1;
615 if (bss->RSSI < candidate[idx].RSSI) {
617 memcpy(&candidate[idx + 1], &candidate[idx],
618 sizeof(removal_element_t) * len);
619 candidate[idx].RSSI = bss->RSSI;
620 candidate[idx].length = bss->length;
621 memcpy(&candidate[idx].BSSID, &bss->BSSID, ETHER_ADDR_LEN);
628 wl_cfg80211_remove_lowRSSI_info(wl_scan_results_t *list, removal_element_t *candidate,
632 int total_delete_len = 0;
633 for (idx1 = 0; idx1 < BUF_OVERFLOW_MGMT_COUNT; idx1++) {
634 int cur_len = WL_SCAN_RESULTS_FIXED_SIZE;
635 wl_bss_info_t *bss = NULL;
636 if (candidate[idx1].RSSI >= bi->RSSI)
638 for (idx2 = 0; idx2 < list->count; idx2++) {
639 bss = bss ? (wl_bss_info_t *)((uintptr)bss + dtoh32(bss->length)) :
641 if (!bcmp(&candidate[idx1].BSSID, &bss->BSSID, ETHER_ADDR_LEN) &&
642 candidate[idx1].RSSI == bss->RSSI &&
643 candidate[idx1].length == dtoh32(bss->length)) {
644 u32 delete_len = dtoh32(bss->length);
645 ESCAN_TRACE(("delete scan info of " MACDBG " to add new AP\n",
646 MAC2STRDBG(bss->BSSID.octet)));
647 if (idx2 < list->count -1) {
648 memmove((u8 *)bss, (u8 *)bss + delete_len,
649 list->buflen - cur_len - delete_len);
651 list->buflen -= delete_len;
653 total_delete_len += delete_len;
654 /* if delete_len is greater than or equal to result length */
655 if (total_delete_len >= bi->length) {
660 cur_len += dtoh32(bss->length);
664 #endif /* ESCAN_BUF_OVERFLOW_MGMT */
666 static s32 wl_escan_handler(struct wl_escan_info *escan,
667 const wl_event_msg_t *e, void *data)
670 s32 status = ntoh32(e->status);
672 wl_escan_result_t *escan_result;
673 wl_bss_info_t *bss = NULL;
674 wl_scan_results_t *list;
679 ESCAN_TRACE(("enter event type : %d, status : %d \n",
680 ntoh32(e->event_type), ntoh32(e->status)));
682 mutex_lock(&escan->usr_sync);
683 escan_result = (wl_escan_result_t *)data;
685 if (escan->escan_state != ESCAN_STATE_SCANING) {
686 ESCAN_TRACE(("Not my scan\n"));
690 if (status == WLC_E_STATUS_PARTIAL) {
691 ESCAN_TRACE(("WLC_E_STATUS_PARTIAL \n"));
693 ESCAN_ERROR(("Invalid escan result (NULL pointer)\n"));
696 if (dtoh16(escan_result->bss_count) != 1) {
697 ESCAN_ERROR(("Invalid bss_count %d: ignoring\n", escan_result->bss_count));
700 bi = escan_result->bss_info;
702 ESCAN_ERROR(("Invalid escan bss info (NULL pointer)\n"));
705 bi_length = dtoh32(bi->length);
706 if (bi_length != (dtoh32(escan_result->buflen) - WL_ESCAN_RESULTS_FIXED_SIZE)) {
707 ESCAN_ERROR(("Invalid bss_info length %d: ignoring\n", bi_length));
711 /* +++++ terence 20130524: skip invalid bss */
713 bi->ctl_ch ? bi->ctl_ch : CHSPEC_CHANNEL(wl_chspec_driver_to_host(escan->ioctl_ver, bi->chanspec));
714 if (!dhd_conf_match_channel(escan->pub, channel))
716 /* ----- terence 20130524: skip invalid bss */
719 int cur_len = WL_SCAN_RESULTS_FIXED_SIZE;
720 #ifdef ESCAN_BUF_OVERFLOW_MGMT
721 removal_element_t candidate[BUF_OVERFLOW_MGMT_COUNT];
722 int remove_lower_rssi = FALSE;
724 bzero(candidate, sizeof(removal_element_t)*BUF_OVERFLOW_MGMT_COUNT);
725 #endif /* ESCAN_BUF_OVERFLOW_MGMT */
727 list = wl_escan_get_buf(escan);
728 #ifdef ESCAN_BUF_OVERFLOW_MGMT
729 if (bi_length > ESCAN_BUF_SIZE - list->buflen)
730 remove_lower_rssi = TRUE;
731 #endif /* ESCAN_BUF_OVERFLOW_MGMT */
733 ESCAN_TRACE(("%s("MACDBG") RSSI %d flags 0x%x length %d\n", bi->SSID,
734 MAC2STRDBG(bi->BSSID.octet), bi->RSSI, bi->flags, bi->length));
735 for (i = 0; i < list->count; i++) {
736 bss = bss ? (wl_bss_info_t *)((uintptr)bss + dtoh32(bss->length))
738 #ifdef ESCAN_BUF_OVERFLOW_MGMT
739 ESCAN_TRACE(("%s("MACDBG"), i=%d bss: RSSI %d list->count %d\n",
740 bss->SSID, MAC2STRDBG(bss->BSSID.octet),
741 i, bss->RSSI, list->count));
743 if (remove_lower_rssi)
744 wl_cfg80211_find_removal_candidate(bss, candidate);
745 #endif /* ESCAN_BUF_OVERFLOW_MGMT */
746 if (!bcmp(&bi->BSSID, &bss->BSSID, ETHER_ADDR_LEN) &&
747 (CHSPEC_BAND(wl_chspec_driver_to_host(escan->ioctl_ver, bi->chanspec))
748 == CHSPEC_BAND(wl_chspec_driver_to_host(escan->ioctl_ver, bss->chanspec))) &&
749 bi->SSID_len == bss->SSID_len &&
750 !bcmp(bi->SSID, bss->SSID, bi->SSID_len)) {
752 /* do not allow beacon data to update
753 *the data recd from a probe response
755 if (!(bss->flags & WL_BSS_FLAGS_FROM_BEACON) &&
756 (bi->flags & WL_BSS_FLAGS_FROM_BEACON))
759 ESCAN_TRACE(("%s("MACDBG"), i=%d prev: RSSI %d"
760 " flags 0x%x, new: RSSI %d flags 0x%x\n",
761 bss->SSID, MAC2STRDBG(bi->BSSID.octet), i,
762 bss->RSSI, bss->flags, bi->RSSI, bi->flags));
764 if ((bss->flags & WL_BSS_FLAGS_RSSI_ONCHANNEL) ==
765 (bi->flags & WL_BSS_FLAGS_RSSI_ONCHANNEL)) {
766 /* preserve max RSSI if the measurements are
767 * both on-channel or both off-channel
769 ESCAN_TRACE(("%s("MACDBG"), same onchan"
770 ", RSSI: prev %d new %d\n",
771 bss->SSID, MAC2STRDBG(bi->BSSID.octet),
772 bss->RSSI, bi->RSSI));
773 bi->RSSI = MAX(bss->RSSI, bi->RSSI);
774 } else if ((bss->flags & WL_BSS_FLAGS_RSSI_ONCHANNEL) &&
775 (bi->flags & WL_BSS_FLAGS_RSSI_ONCHANNEL) == 0) {
776 /* preserve the on-channel rssi measurement
777 * if the new measurement is off channel
779 ESCAN_TRACE(("%s("MACDBG"), prev onchan"
780 ", RSSI: prev %d new %d\n",
781 bss->SSID, MAC2STRDBG(bi->BSSID.octet),
782 bss->RSSI, bi->RSSI));
783 bi->RSSI = bss->RSSI;
784 bi->flags |= WL_BSS_FLAGS_RSSI_ONCHANNEL;
786 if (dtoh32(bss->length) != bi_length) {
787 u32 prev_len = dtoh32(bss->length);
789 ESCAN_TRACE(("bss info replacement"
790 " is occured(bcast:%d->probresp%d)\n",
791 bss->ie_length, bi->ie_length));
792 ESCAN_TRACE(("%s("MACDBG"), replacement!(%d -> %d)\n",
793 bss->SSID, MAC2STRDBG(bi->BSSID.octet),
794 prev_len, bi_length));
796 if (list->buflen - prev_len + bi_length
798 ESCAN_ERROR(("Buffer is too small: keep the"
799 " previous result of this AP\n"));
800 /* Only update RSSI */
801 bss->RSSI = bi->RSSI;
802 bss->flags |= (bi->flags
803 & WL_BSS_FLAGS_RSSI_ONCHANNEL);
807 if (i < list->count - 1) {
808 /* memory copy required by this case only */
809 memmove((u8 *)bss + bi_length,
810 (u8 *)bss + prev_len,
811 list->buflen - cur_len - prev_len);
813 list->buflen -= prev_len;
814 list->buflen += bi_length;
816 list->version = dtoh32(bi->version);
817 memcpy((u8 *)bss, (u8 *)bi, bi_length);
820 cur_len += dtoh32(bss->length);
822 if (bi_length > ESCAN_BUF_SIZE - list->buflen) {
823 #ifdef ESCAN_BUF_OVERFLOW_MGMT
824 wl_cfg80211_remove_lowRSSI_info(list, candidate, bi);
825 if (bi_length > ESCAN_BUF_SIZE - list->buflen) {
826 ESCAN_TRACE(("RSSI(" MACDBG ") is too low(%d) to add Buffer\n",
827 MAC2STRDBG(bi->BSSID.octet), bi->RSSI));
831 ESCAN_ERROR(("Buffer is too small: ignoring\n"));
833 #endif /* ESCAN_BUF_OVERFLOW_MGMT */
836 if (strlen(bi->SSID) == 0) { // terence: fix for hidden SSID
837 ESCAN_SCAN(("Skip hidden SSID %pM\n", &bi->BSSID));
841 memcpy(&(((char *)list)[list->buflen]), bi, bi_length);
842 list->version = dtoh32(bi->version);
843 list->buflen += bi_length;
847 else if (status == WLC_E_STATUS_SUCCESS) {
848 escan->escan_state = ESCAN_STATE_IDLE;
850 ESCAN_TRACE(("ESCAN COMPLETED\n"));
851 escan->bss_list = wl_escan_get_buf(escan);
852 ESCAN_TRACE(("SCAN COMPLETED: scanned AP count=%d\n",
853 escan->bss_list->count));
854 wl_escan_inform_bss(escan);
855 wl_notify_escan_complete(escan, false);
857 } else if ((status == WLC_E_STATUS_ABORT) || (status == WLC_E_STATUS_NEWSCAN) ||
858 (status == WLC_E_STATUS_11HQUIET) || (status == WLC_E_STATUS_CS_ABORT) ||
859 (status == WLC_E_STATUS_NEWASSOC)) {
860 /* Handle all cases of scan abort */
861 escan->escan_state = ESCAN_STATE_IDLE;
862 ESCAN_TRACE(("ESCAN ABORT reason: %d\n", status));
863 wl_escan_inform_bss(escan);
864 wl_notify_escan_complete(escan, false);
865 } else if (status == WLC_E_STATUS_TIMEOUT) {
866 ESCAN_ERROR(("WLC_E_STATUS_TIMEOUT\n"));
867 ESCAN_ERROR(("reason[0x%x]\n", e->reason));
868 if (e->reason == 0xFFFFFFFF) {
869 wl_notify_escan_complete(escan, true);
872 ESCAN_ERROR(("unexpected Escan Event %d : abort\n", status));
873 escan->escan_state = ESCAN_STATE_IDLE;
874 escan->bss_list = wl_escan_get_buf(escan);
875 ESCAN_TRACE(("SCAN ABORTED(UNEXPECTED): scanned AP count=%d\n",
876 escan->bss_list->count));
877 wl_escan_inform_bss(escan);
878 wl_notify_escan_complete(escan, false);
881 mutex_unlock(&escan->usr_sync);
886 wl_escan_prep(struct wl_escan_info *escan, wl_uint32_list_t *list,
887 wl_scan_params_t *params, wlc_ssid_t *ssid)
890 wl_scan_results_t *results;
899 results = wl_escan_get_buf(escan);
900 results->version = 0;
902 results->buflen = WL_SCAN_RESULTS_FIXED_SIZE;
903 escan->escan_state = ESCAN_STATE_SCANING;
905 /* Arm scan timeout timer */
906 mod_timer(&escan->scan_timeout, jiffies + msecs_to_jiffies(WL_ESCAN_TIMER_INTERVAL_MS));
908 memcpy(¶ms->bssid, ðer_bcast, ETHER_ADDR_LEN);
909 params->bss_type = DOT11_BSSTYPE_ANY;
910 params->scan_type = 0;
911 params->nprobes = -1;
912 params->active_time = -1;
913 params->passive_time = -1;
914 params->home_time = -1;
915 params->channel_num = 0;
917 params->nprobes = htod32(params->nprobes);
918 params->active_time = htod32(params->active_time);
919 params->passive_time = htod32(params->passive_time);
920 params->home_time = htod32(params->home_time);
922 n_channels = dtoh32(list->count);
923 /* Copy channel array if applicable */
924 ESCAN_SCAN(("### List of channelspecs to scan ###\n"));
925 if (n_channels > 0) {
926 for (i = 0; i < n_channels; i++) {
927 channel = dtoh32(list->element[i]);
928 if (!dhd_conf_match_channel(escan->pub, channel))
930 chanspec = WL_CHANSPEC_BW_20;
931 if (chanspec == INVCHANSPEC) {
932 ESCAN_ERROR(("Invalid chanspec! Skipping channel\n"));
935 if (channel <= CH_MAX_2G_CHANNEL) {
936 chanspec |= WL_CHANSPEC_BAND_2G;
938 chanspec |= WL_CHANSPEC_BAND_5G;
940 params->channel_list[j] = channel;
941 params->channel_list[j] &= WL_CHANSPEC_CHAN_MASK;
942 params->channel_list[j] |= chanspec;
943 ESCAN_SCAN(("Chan : %d, Channel spec: %x \n",
944 channel, params->channel_list[j]));
945 params->channel_list[j] = wl_chspec_host_to_driver(params->channel_list[j]);
949 ESCAN_SCAN(("Scanning all channels\n"));
952 if (ssid && ssid->SSID_len) {
953 /* Copy ssid array if applicable */
954 ESCAN_SCAN(("### List of SSIDs to scan ###\n"));
955 offset = offsetof(wl_scan_params_t, channel_list) + n_channels * sizeof(u16);
956 offset = roundup(offset, sizeof(u32));
957 ptr = (char*)params + offset;
959 ESCAN_SCAN(("0: Broadcast scan\n"));
960 memset(&ssid_tmp, 0, sizeof(wlc_ssid_t));
961 ssid_tmp.SSID_len = 0;
962 memcpy(ptr, &ssid_tmp, sizeof(wlc_ssid_t));
963 ptr += sizeof(wlc_ssid_t);
965 memset(&ssid_tmp, 0, sizeof(wlc_ssid_t));
966 ssid_tmp.SSID_len = ssid->SSID_len;
967 memcpy(ssid_tmp.SSID, ssid->SSID, ssid->SSID_len);
968 memcpy(ptr, &ssid_tmp, sizeof(wlc_ssid_t));
969 ptr += sizeof(wlc_ssid_t);
970 ESCAN_SCAN(("1: scan for %s size=%d\n", ssid_tmp.SSID, ssid_tmp.SSID_len));
971 /* Adding mask to channel numbers */
972 params->channel_num =
973 htod32((2 << WL_SCAN_PARAMS_NSSID_SHIFT) |
974 (n_channels & WL_SCAN_PARAMS_COUNT_MASK));
977 ESCAN_SCAN(("Broadcast scan\n"));
983 static int wl_escan_reset(void) {
984 struct wl_escan_info *escan = g_escan;
986 if (timer_pending(&escan->scan_timeout))
987 del_timer_sync(&escan->scan_timeout);
988 escan->escan_state = ESCAN_STATE_IDLE;
993 static void wl_escan_timeout(unsigned long data)
996 struct wl_escan_info *escan = (struct wl_escan_info *)data;
997 struct wl_scan_results *bss_list;
998 struct wl_bss_info *bi = NULL;
1002 bss_list = wl_escan_get_buf(escan);
1004 ESCAN_ERROR(("bss_list is null. Didn't receive any partial scan results\n"));
1006 ESCAN_ERROR(("%s: scanned AP count (%d)\n", __FUNCTION__, bss_list->count));
1007 bi = next_bss(bss_list, bi);
1008 for_each_bss(bss_list, bi, i) {
1009 channel = wf_chspec_ctlchan(wl_chspec_driver_to_host(escan->ioctl_ver, bi->chanspec));
1010 ESCAN_ERROR(("SSID :%s Channel :%d\n", bi->SSID, channel));
1015 ESCAN_ERROR(("No dev present\n"));
1019 bzero(&msg, sizeof(wl_event_msg_t));
1020 ESCAN_ERROR(("timer expired\n"));
1022 msg.event_type = hton32(WLC_E_ESCAN_RESULT);
1023 msg.status = hton32(WLC_E_STATUS_TIMEOUT);
1024 msg.reason = 0xFFFFFFFF;
1025 wl_escan_event(escan->dev, &msg, NULL);
1027 // terence 20130729: workaround to fix out of memory in firmware
1028 // if (dhd_conf_get_chip(dhd_get_pub(dev)) == BCM43362_CHIP_ID) {
1029 // ESCAN_ERROR(("Send hang event\n"));
1030 // net_os_send_hang_message(dev);
1036 struct net_device *dev,
1037 struct iw_request_info *info,
1038 union iwreq_data *wrqu,
1043 s32 params_size = (WL_SCAN_PARAMS_FIXED_SIZE + OFFSETOF(wl_escan_params_t, params));
1044 wl_escan_params_t *params = NULL;
1047 struct wl_escan_info *escan = NULL;
1050 wl_uint32_list_t *list;
1051 u8 valid_chan_list[sizeof(u32)*(WL_NUMCHANNELS + 1)];
1054 ESCAN_TRACE(("Enter \n"));
1058 ESCAN_ERROR(("device is not ready\n")); \
1061 mutex_lock(&escan->usr_sync);
1063 if (!escan->ioctl_ver) {
1065 if ((err = wldev_ioctl(dev, WLC_GET_VERSION, &val, sizeof(int), false) < 0)) {
1066 ANDROID_ERROR(("WLC_GET_VERSION failed, err=%d\n", err));
1070 if (val != WLC_IOCTL_VERSION && val != 1) {
1071 ANDROID_ERROR(("Version mismatch, please upgrade. Got %d, expected %d or 1\n",
1072 val, WLC_IOCTL_VERSION));
1075 escan->ioctl_ver = val;
1076 printf("%s: ioctl_ver=%d\n", __FUNCTION__, val);
1079 /* default Broadcast scan */
1080 memset(&ssid, 0, sizeof(ssid));
1082 #if WIRELESS_EXT > 17
1083 /* check for given essid */
1084 if (wrqu->data.length == sizeof(struct iw_scan_req)) {
1085 if (wrqu->data.flags & IW_SCAN_THIS_ESSID) {
1086 struct iw_scan_req *req = (struct iw_scan_req *)extra;
1087 ssid.SSID_len = MIN(sizeof(ssid.SSID), req->essid_len);
1088 memcpy(ssid.SSID, req->essid, ssid.SSID_len);
1089 ssid.SSID_len = htod32(ssid.SSID_len);
1093 if (escan->escan_state == ESCAN_STATE_SCANING) {
1094 ESCAN_ERROR(("Scanning already\n"));
1098 /* if scan request is not empty parse scan request paramters */
1099 memset(valid_chan_list, 0, sizeof(valid_chan_list));
1100 list = (wl_uint32_list_t *)(void *) valid_chan_list;
1101 list->count = htod32(WL_NUMCHANNELS);
1102 err = wldev_ioctl(escan->dev, WLC_GET_VALID_CHANNELS, valid_chan_list, sizeof(valid_chan_list), false);
1104 ESCAN_ERROR(("%s: get channels failed with %d\n", __FUNCTION__, err));
1107 n_channels = dtoh32(list->count);
1108 /* Allocate space for populating ssids in wl_escan_params_t struct */
1109 if (dtoh32(list->count) % 2)
1110 /* If n_channels is odd, add a padd of u16 */
1111 params_size += sizeof(u16) * (n_channels + 1);
1113 params_size += sizeof(u16) * n_channels;
1114 if (ssid.SSID_len) {
1115 params_size += sizeof(struct wlc_ssid) * 2;
1118 params = (wl_escan_params_t *) kzalloc(params_size, GFP_KERNEL);
1119 if (params == NULL) {
1123 wl_escan_prep(escan, list, ¶ms->params, &ssid);
1125 params->version = htod32(ESCAN_REQ_VERSION);
1126 params->action = htod16(WL_SCAN_ACTION_START);
1127 wl_escan_set_sync_id(params->sync_id);
1128 if (params_size + sizeof("escan") >= WLC_IOCTL_MEDLEN) {
1129 ESCAN_ERROR(("ioctl buffer length not sufficient\n"));
1134 params->params.scan_type = DOT11_SCANTYPE_ACTIVE;
1135 ESCAN_TRACE(("Passive scan_type %d\n", params->params.scan_type));
1137 err = wldev_iovar_setbuf(dev, "escan", params, params_size,
1138 escan->escan_ioctl_buf, WLC_IOCTL_MEDLEN, NULL);
1139 if (unlikely(err)) {
1140 if (err == BCME_EPERM)
1141 /* Scan Not permitted at this point of time */
1142 ESCAN_TRACE(("Escan not permitted at this time (%d)\n", err));
1144 ESCAN_ERROR(("Escan set error (%d)\n", err));
1150 if (unlikely(err)) {
1151 /* Don't print Error incase of Scan suppress */
1152 if ((err == BCME_EPERM))
1153 ESCAN_TRACE(("Escan failed: Scan Suppressed \n"));
1156 ESCAN_ERROR(("error (%d), cnt=%d\n", err, cnt));
1157 // terence 20140111: send disassoc to firmware
1159 memset(&scbval, 0, sizeof(scb_val_t));
1160 wldev_ioctl(dev, WLC_DISASSOC, &scbval, sizeof(scb_val_t), true);
1161 ESCAN_ERROR(("Send disassoc to break the busy dev=%p\n", dev));
1168 mutex_unlock(&escan->usr_sync);
1174 struct net_device *dev,
1175 struct iw_request_info *info,
1176 struct iw_point *dwrq,
1181 struct iw_event iwe;
1183 char *event = extra, *end = extra + dwrq->length, *value;
1186 wl_bss_info_t *bi = NULL;
1187 struct wl_escan_info *escan = g_escan;
1188 struct wl_scan_results *bss_list;
1189 #if defined(BSSCACHE)
1190 wl_bss_cache_t *node;
1193 ESCAN_TRACE(("%s: %s SIOCGIWSCAN, len=%d\n", __FUNCTION__, dev->name, dwrq->length));
1198 mutex_lock(&escan->usr_sync);
1200 /* Check for scan in progress */
1201 if (escan->escan_state == ESCAN_STATE_SCANING) {
1202 ESCAN_TRACE(("%s: SIOCGIWSCAN GET still scanning\n", dev->name));
1207 #if defined(BSSCACHE)
1208 bss_list = &g_bss_cache_ctrl.m_cache_head->results;
1209 node = g_bss_cache_ctrl.m_cache_head;
1210 for (i=0; node && i<IW_MAX_AP; i++)
1212 bss_list = escan->bss_list;
1213 bi = next_bss(bss_list, bi);
1214 for_each_bss(bss_list, bi, i)
1217 #if defined(BSSCACHE)
1218 bi = node->results.bss_info;
1220 /* overflow check cover fields before wpa IEs */
1221 if (event + ETHER_ADDR_LEN + bi->SSID_len + IW_EV_UINT_LEN + IW_EV_FREQ_LEN +
1222 IW_EV_QUAL_LEN >= end) {
1227 #if defined(RSSIAVG)
1228 rssi = wl_get_avg_rssi(&g_rssi_cache_ctrl, &bi->BSSID);
1229 if (rssi == RSSI_MINVAL)
1230 rssi = MIN(dtoh16(bi->RSSI), RSSI_MAXVAL);
1232 // terence 20150419: limit the max. rssi to -2 or the bss will be filtered out in android OS
1233 rssi = MIN(dtoh16(bi->RSSI), RSSI_MAXVAL);
1235 channel = wf_chspec_ctlchan(wl_chspec_driver_to_host(escan->ioctl_ver, bi->chanspec));
1236 ESCAN_SCAN(("%s: BSSID="MACSTR", channel=%d, RSSI=%d, SSID=\"%s\"\n",
1237 __FUNCTION__, MAC2STR(bi->BSSID.octet), channel, rssi, bi->SSID));
1239 /* First entry must be the BSSID */
1240 iwe.cmd = SIOCGIWAP;
1241 iwe.u.ap_addr.sa_family = ARPHRD_ETHER;
1242 memcpy(iwe.u.ap_addr.sa_data, &bi->BSSID, ETHER_ADDR_LEN);
1243 event = IWE_STREAM_ADD_EVENT(info, event, end, &iwe, IW_EV_ADDR_LEN);
1246 iwe.u.data.length = dtoh32(bi->SSID_len);
1247 iwe.cmd = SIOCGIWESSID;
1248 iwe.u.data.flags = 1;
1249 event = IWE_STREAM_ADD_POINT(info, event, end, &iwe, bi->SSID);
1252 if (dtoh16(bi->capability) & (DOT11_CAP_ESS | DOT11_CAP_IBSS)) {
1253 iwe.cmd = SIOCGIWMODE;
1254 if (dtoh16(bi->capability) & DOT11_CAP_ESS)
1255 iwe.u.mode = IW_MODE_INFRA;
1257 iwe.u.mode = IW_MODE_ADHOC;
1258 event = IWE_STREAM_ADD_EVENT(info, event, end, &iwe, IW_EV_UINT_LEN);
1262 iwe.cmd = SIOCGIWFREQ;
1264 iwe.u.freq.m = wf_channel2mhz(channel, channel <= CH_MAX_2G_CHANNEL ?
1265 WF_CHAN_FACTOR_2_4_G : WF_CHAN_FACTOR_5_G);
1267 iwe.u.freq.m = wf_channel2mhz(bi->n_cap ?
1268 bi->ctl_ch : CHSPEC_CHANNEL(bi->chanspec),
1269 CHSPEC_CHANNEL(bi->chanspec) <= CH_MAX_2G_CHANNEL ?
1270 WF_CHAN_FACTOR_2_4_G : WF_CHAN_FACTOR_5_G);
1273 event = IWE_STREAM_ADD_EVENT(info, event, end, &iwe, IW_EV_FREQ_LEN);
1275 /* Channel quality */
1277 iwe.u.qual.qual = rssi_to_qual(rssi);
1278 iwe.u.qual.level = 0x100 + rssi;
1279 iwe.u.qual.noise = 0x100 + bi->phy_noise;
1280 event = IWE_STREAM_ADD_EVENT(info, event, end, &iwe, IW_EV_QUAL_LEN);
1282 wl_iw_handle_scanresults_ies(&event, end, info, bi);
1285 iwe.cmd = SIOCGIWENCODE;
1286 if (dtoh16(bi->capability) & DOT11_CAP_PRIVACY)
1287 iwe.u.data.flags = IW_ENCODE_ENABLED | IW_ENCODE_NOKEY;
1289 iwe.u.data.flags = IW_ENCODE_DISABLED;
1290 iwe.u.data.length = 0;
1291 event = IWE_STREAM_ADD_POINT(info, event, end, &iwe, (char *)event);
1294 if (bi->rateset.count <= sizeof(bi->rateset.rates)) {
1295 if (event + IW_MAX_BITRATES*IW_EV_PARAM_LEN >= end) {
1299 value = event + IW_EV_LCP_LEN;
1300 iwe.cmd = SIOCGIWRATE;
1301 /* Those two flags are ignored... */
1302 iwe.u.bitrate.fixed = iwe.u.bitrate.disabled = 0;
1303 for (j = 0; j < bi->rateset.count && j < IW_MAX_BITRATES; j++) {
1304 iwe.u.bitrate.value = (bi->rateset.rates[j] & 0x7f) * 500000;
1305 value = IWE_STREAM_ADD_VALUE(info, event, value, end, &iwe,
1310 #if defined(BSSCACHE)
1315 dwrq->length = event - extra;
1316 dwrq->flags = 0; /* todo */
1317 ESCAN_SCAN(("scanned AP count (%d)\n", i));
1319 mutex_unlock(&escan->usr_sync);
1323 static s32 wl_create_event_handler(struct wl_escan_info *escan)
1326 ESCAN_TRACE(("Enter \n"));
1328 /* Do not use DHD in cfg driver */
1329 escan->event_tsk.thr_pid = -1;
1331 PROC_START(wl_escan_event_handler, escan, &escan->event_tsk, 0, "wl_escan_handler");
1332 if (escan->event_tsk.thr_pid < 0)
1337 static void wl_destroy_event_handler(struct wl_escan_info *escan)
1339 if (escan->event_tsk.thr_pid >= 0)
1340 PROC_STOP(&escan->event_tsk);
1343 static void wl_escan_deinit(void)
1345 struct wl_escan_info *escan = g_escan;
1347 printf("%s: Enter\n", __FUNCTION__);
1349 ESCAN_ERROR(("device is not ready\n")); \
1352 wl_destroy_event_handler(escan);
1354 del_timer_sync(&escan->scan_timeout);
1356 #if defined(RSSIAVG)
1357 wl_free_rssi_cache(&g_rssi_cache_ctrl);
1359 #if defined(BSSCACHE)
1360 wl_free_bss_cache(&g_bss_cache_ctrl);
1364 static s32 wl_escan_init(void)
1366 struct wl_escan_info *escan = g_escan;
1369 printf("%s: Enter\n", __FUNCTION__);
1371 ESCAN_ERROR(("device is not ready\n")); \
1375 /* Init scan_timeout timer */
1376 init_timer(&escan->scan_timeout);
1377 escan->scan_timeout.data = (unsigned long) escan;
1378 escan->scan_timeout.function = wl_escan_timeout;
1380 if (wl_create_event_handler(escan)) {
1384 memset(escan->evt_handler, 0, sizeof(escan->evt_handler));
1386 escan->evt_handler[WLC_E_ESCAN_RESULT] = wl_escan_handler;
1387 escan->escan_state = ESCAN_STATE_IDLE;
1389 mutex_init(&escan->usr_sync);
1397 void wl_escan_detach(void)
1399 struct wl_escan_info *escan = g_escan;
1401 printf("%s: Enter\n", __FUNCTION__);
1404 ESCAN_ERROR(("device is not ready\n")); \
1410 if (escan->escan_ioctl_buf) {
1411 kfree(escan->escan_ioctl_buf);
1412 escan->escan_ioctl_buf = NULL;
1420 wl_escan_attach(struct net_device *dev, void * dhdp)
1422 struct wl_escan_info *escan = NULL;
1424 printf("%s: Enter\n", __FUNCTION__);
1429 escan = kmalloc(sizeof(struct wl_escan_info), GFP_KERNEL);
1432 memset(escan, 0, sizeof(struct wl_escan_info));
1434 /* we only care about main interface so save a global here */
1438 escan->escan_state = ESCAN_STATE_IDLE;
1440 escan->escan_ioctl_buf = (void *)kzalloc(WLC_IOCTL_MAXLEN, GFP_KERNEL);
1441 if (unlikely(!escan->escan_ioctl_buf)) {
1442 ESCAN_ERROR(("Ioctl buf alloc failed\n"));
1456 #endif /* WL_ESCAN */