⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ieee80211_scan.c.svn-base

📁 最新之atheros芯片driver source code, 基于linux操作系统,內含atheros芯片HAL全部代码
💻 SVN-BASE
📖 第 1 页 / 共 3 页
字号:
	int scanning;	scan = ieee80211_scanner_get(vap->iv_opmode, 0);	if (scan == NULL) {		IEEE80211_DPRINTF(vap, IEEE80211_MSG_SCAN,			"%s: no scanner support for mode %u\n",			__func__, vap->iv_opmode);		/* XXX stat */		return 0;	}	IEEE80211_LOCK_IRQ(ic);	if ((ic->ic_flags & IEEE80211_F_SCAN) == 0) {		IEEE80211_DPRINTF(vap, IEEE80211_MSG_SCAN,			"%s: %s scan, duration %lu, desired mode %s, %s%s%s%s\n",			__func__,			flags & IEEE80211_SCAN_ACTIVE ? "active" : "passive",		 	duration,			ieee80211_phymode_name[vap->iv_des_mode],			flags & IEEE80211_SCAN_FLUSH ? "flush" : "append",			flags & IEEE80211_SCAN_NOPICK ? ", nopick" : "",			flags & IEEE80211_SCAN_PICK1ST ? ", pick1st" : "",			flags & IEEE80211_SCAN_ONCE ? ", once" : "");		ss->ss_vap = vap;		if (ss->ss_ops != scan) {			/* switch scanners; detach old, attach new */			if (ss->ss_ops != NULL)				ss->ss_ops->scan_detach(ss);			if (!scan->scan_attach(ss)) {				/* XXX attach failure */				/* XXX stat+msg */				ss->ss_ops = NULL;			} else				ss->ss_ops = scan;		}		if (ss->ss_ops != NULL) {			if ((flags & IEEE80211_SCAN_NOSSID) == 0)				copy_ssid(vap, ss, nssid, ssids);			/* NB: top 4 bits for internal use */			ss->ss_flags = flags & 0xfff;			if (ss->ss_flags & IEEE80211_SCAN_ACTIVE)				vap->iv_stats.is_scan_active++;			else				vap->iv_stats.is_scan_passive++;			if (flags & IEEE80211_SCAN_FLUSH)				ss->ss_ops->scan_flush(ss);			/* NB: flush frames rx'd before 1st channel change */			SCAN_PRIVATE(ss)->ss_iflags |= ISCAN_DISCARD;			ss->ss_ops->scan_start(ss, vap);			if (scan_restart(SCAN_PRIVATE(ss), duration))				ic->ic_flags |= IEEE80211_F_SCAN;		}	} else {		IEEE80211_DPRINTF(vap, IEEE80211_MSG_SCAN,			"%s: %s scan already in progress\n", __func__,			ss->ss_flags & IEEE80211_SCAN_ACTIVE ? "active" : "passive");		/* If the running scanning has the flag SCAN_NOPICK set, but		 * the requested scan has not, then we update the running scan		 * flag. This is needed when wpa_supplicant is used with		 * ap_scan=1. Without it, the driver will never associate. */		if (((flags & IEEE80211_SCAN_NOPICK) == 0) &&		    (ss->ss_flags & IEEE80211_SCAN_NOPICK)) {			IEEE80211_DPRINTF(vap, IEEE80211_MSG_SCAN,					  "%s: clearing SCAN_NOPICK flag\n",					  __func__);			ss->ss_flags &= ~IEEE80211_SCAN_NOPICK;		}	}		scanning = (ic->ic_flags & IEEE80211_F_SCAN);	IEEE80211_UNLOCK_IRQ(ic);	return scanning;}EXPORT_SYMBOL(ieee80211_start_scan);/* * Check the scan cache for an ap/channel to use; if that * fails then kick off a new scan. */intieee80211_check_scan(struct ieee80211vap *vap, int flags, u_int duration,	u_int nssid, const struct ieee80211_scan_ssid ssids[],	int (*action)(struct ieee80211vap *, const struct ieee80211_scan_entry *)){	struct ieee80211com *ic = vap->iv_ic;	struct ieee80211_scan_state *ss = ic->ic_scan;	int checkscanlist = 0;	/*	 * Check if there's a list of scan candidates already.	 * XXX want more than the ap we're currently associated with	 */	IEEE80211_LOCK_IRQ(ic);	IEEE80211_DPRINTF(vap, IEEE80211_MSG_SCAN,		"%s: %s scan, duration %lu, desired mode %s, %s%s%s%s\n",		__func__,		flags & IEEE80211_SCAN_ACTIVE ? "active" : "passive",		duration,		ieee80211_phymode_name[vap->iv_des_mode],		flags & IEEE80211_SCAN_FLUSH ? "flush" : "append",		flags & IEEE80211_SCAN_NOPICK ? ", nopick" : "",		flags & IEEE80211_SCAN_PICK1ST ? ", pick1st" : "",		flags & IEEE80211_SCAN_ONCE ? ", once" : "",		flags & IEEE80211_SCAN_USECACHE ? ", usecache" : "");	if (ss->ss_ops != NULL) {		/* XXX verify ss_ops matches vap->iv_opmode */		if ((flags & IEEE80211_SCAN_NOSSID) == 0) {			/*			 * Update the ssid list and mark flags so if			 * we call start_scan it doesn't duplicate work.			 */			copy_ssid(vap, ss, nssid, ssids);			flags |= IEEE80211_SCAN_NOSSID;		}		if ((ic->ic_flags & IEEE80211_F_SCAN) == 0 &&		     time_before(jiffies, ic->ic_lastscan + vap->iv_scanvalid)) {			/*			 * We're not currently scanning and the cache is			 * deemed hot enough to consult.  Lock out others			 * by marking IEEE80211_F_SCAN while we decide if			 * something is already in the scan cache we can			 * use.  Also discard any frames that might come			 * in while temporarily marked as scanning.			 */			SCAN_PRIVATE(ss)->ss_iflags |= ISCAN_DISCARD;			ic->ic_flags |= IEEE80211_F_SCAN;			checkscanlist = 1;		}	}	IEEE80211_UNLOCK_IRQ(ic);	if (checkscanlist) {		/*		 * ss must be filled out so scan may be restarted "outside"		 * of the current callstack.		 */		ss->ss_flags = flags;		ss->ss_duration = duration;		if (ss->ss_ops->scan_end(ss, ss->ss_vap, action, flags & IEEE80211_SCAN_KEEPMODE)) {			/* found an ap, just clear the flag */			ic->ic_flags &= ~IEEE80211_F_SCAN;			return 1;		}		/* no ap, clear the flag before starting a scan */		ic->ic_flags &= ~IEEE80211_F_SCAN;	}	if ((flags & IEEE80211_SCAN_USECACHE) == 0)		return ieee80211_start_scan(vap, flags, duration, nssid, ssids);	else {		/* If we *must* use the cache and no ap was found, return failure */		return 0;	}}/* * Restart a previous scan.  If the previous scan completed * then we start again using the existing channel list. */intieee80211_bg_scan(struct ieee80211vap *vap){	struct ieee80211com *ic = vap->iv_ic;	struct ieee80211_scan_state *ss = ic->ic_scan;	int scanning;	IEEE80211_LOCK_IRQ(ic);	if ((ic->ic_flags & IEEE80211_F_SCAN) == 0) {		u_int duration;		/*		 * Go off-channel for a fixed interval that is large		 * enough to catch most APs but short enough that		 * we can return on-channel before our listen interval		 * expires.		 */		duration = IEEE80211_SCAN_OFFCHANNEL;		IEEE80211_DPRINTF(vap, IEEE80211_MSG_SCAN,			"%s: %s scan, jiffies %lu duration %lu\n", __func__,			ss->ss_flags & IEEE80211_SCAN_ACTIVE ? "active" : "passive",			jiffies, duration);		if (ss->ss_ops != NULL) {			ss->ss_vap = vap;			/*			 * A background scan does not select a new STA; it			 * just refreshes the scan cache.  Also, indicate			 * the scan logic should follow the beacon schedule:			 * we go off-channel and scan for a while, then			 * return to the bss channel to receive a beacon,			 * then go off-channel again.  All during this time			 * we notify the ap we're in power save mode.  When			 * the scan is complete, we leave power save mode.			 * If any beacon indicates there are frames pending			 * for us then we drop out of power save mode			 * (and background scan) automatically by way of the			 * usual STA power save logic.			 */			ss->ss_flags |= IEEE80211_SCAN_NOPICK |				IEEE80211_SCAN_BGSCAN;			/* If previous scan completed, restart */			if (ss->ss_next >= ss->ss_last) {				ss->ss_next = 0;				if (ss->ss_flags & IEEE80211_SCAN_ACTIVE)					vap->iv_stats.is_scan_active++;				else					vap->iv_stats.is_scan_passive++;				ss->ss_ops->scan_restart(ss, vap);			}			/* NB: Flush frames RX'd before 1st channel change */			SCAN_PRIVATE(ss)->ss_iflags |= ISCAN_DISCARD;			ss->ss_mindwell = duration;			if (scan_restart(SCAN_PRIVATE(ss), duration)) {				ic->ic_flags |= IEEE80211_F_SCAN;				ic->ic_flags_ext |= IEEE80211_FEXT_BGSCAN;			}		} else {			/* XXX msg+stat */		}	} else {		IEEE80211_DPRINTF(vap, IEEE80211_MSG_SCAN,			"%s: %s scan already in progress\n", __func__,			ss->ss_flags & IEEE80211_SCAN_ACTIVE ? "active" : "passive");	}		scanning = (ic->ic_flags & IEEE80211_F_SCAN);	IEEE80211_UNLOCK_IRQ(ic);	return scanning;}EXPORT_SYMBOL(ieee80211_bg_scan);EXPORT_SYMBOL(ieee80211_cancel_scan);/* * Cancel any scan currently going on. */voidieee80211_cancel_scan(struct ieee80211vap *vap){	struct ieee80211com *ic = vap->iv_ic;	struct ieee80211_scan_state *ss = ic->ic_scan;	IEEE80211_LOCK_IRQ(ic);	if (ic->ic_flags & IEEE80211_F_SCAN) {		IEEE80211_DPRINTF(vap, IEEE80211_MSG_SCAN,			"%s: cancel %s scan\n", __func__,			ss->ss_flags & IEEE80211_SCAN_ACTIVE ? "active" : "passive");		/* clear bg scan NOPICK and mark cancel request */		ss->ss_flags &= ~IEEE80211_SCAN_NOPICK;		SCAN_PRIVATE(ss)->ss_iflags |= ISCAN_CANCEL;		ss->ss_ops->scan_cancel(ss, vap);		/* force it to fire asap */		mod_timer(&SCAN_PRIVATE(ss)->ss_scan_timer, jiffies);	}	IEEE80211_UNLOCK_IRQ(ic);}/* * Switch to the next channel marked for scanning. */static voidscan_next(unsigned long arg){#define	ISCAN_REP	(ISCAN_MINDWELL | ISCAN_START | ISCAN_DISCARD)	struct ieee80211_scan_state *ss = (struct ieee80211_scan_state *)arg;	struct ieee80211vap *vap = ss->ss_vap;	struct ieee80211com *ic = vap->iv_ic;	struct ieee80211_channel *chan;	unsigned long maxdwell, scanend;	int scanning, scandone, i;	IEEE80211_LOCK_IRQ(ic);	scanning = (ic->ic_flags & IEEE80211_F_SCAN) != 0;	IEEE80211_UNLOCK_IRQ(ic);	if (!scanning)			/* canceled */		return;again:	scandone = (ss->ss_next >= ss->ss_last) ||		((SCAN_PRIVATE(ss)->ss_iflags & ISCAN_CANCEL) != 0);	scanend = SCAN_PRIVATE(ss)->ss_scanend;	if (!scandone &&	    (ss->ss_flags & IEEE80211_SCAN_GOTPICK) == 0 &&	    ((SCAN_PRIVATE(ss)->ss_iflags & ISCAN_START) ||	     time_before(jiffies + ss->ss_mindwell, scanend))) {		chan = ss->ss_chans[ss->ss_next++];		/*		 * Watch for truncation due to the scan end time.		 */		if (time_after(jiffies + ss->ss_maxdwell, scanend))			maxdwell = scanend - jiffies;		else			maxdwell = ss->ss_maxdwell;		IEEE80211_DPRINTF(vap, IEEE80211_MSG_SCAN,			"%s: chan %3d%c -> %3d%c [%s, dwell min %lu max %lu]\n",			__func__,			ieee80211_chan2ieee(ic, ic->ic_curchan),		        	channel_type(ic->ic_curchan),			ieee80211_chan2ieee(ic, chan), channel_type(chan),			(ss->ss_flags & IEEE80211_SCAN_ACTIVE) &&				(chan->ic_flags & IEEE80211_CHAN_PASSIVE) == 0 ?				"active" : "passive",			ss->ss_mindwell, maxdwell);		/*		 * Potentially change channel and phy mode.		 */		change_channel(ic, chan);		/*		 * If doing an active scan and the channel is not		 * marked passive-only then send a probe request.		 * Otherwise just listen for traffic on the channel.		 */		if ((ss->ss_flags & IEEE80211_SCAN_ACTIVE) &&		    (chan->ic_flags & IEEE80211_CHAN_PASSIVE) == 0) {			struct net_device *dev = vap->iv_dev;			/*			 * Send a broadcast probe request followed by			 * any specified directed probe requests.			 * XXX suppress broadcast probe req?			 * XXX remove dependence on vap/vap->iv_bss			 * XXX move to policy code?			 */			ieee80211_send_probereq(vap->iv_bss,				vap->iv_myaddr, dev->broadcast,				dev->broadcast,				"", 0,				vap->iv_opt_ie, vap->iv_opt_ie_len);			for (i = 0; i < ss->ss_nssid; i++)				ieee80211_send_probereq(vap->iv_bss,					vap->iv_myaddr, dev->broadcast,					dev->broadcast,					ss->ss_ssid[i].ssid,					ss->ss_ssid[i].len,					vap->iv_opt_ie, vap->iv_opt_ie_len);		}		SCAN_PRIVATE(ss)->ss_chanmindwell = jiffies + ss->ss_mindwell;		mod_timer(&SCAN_PRIVATE(ss)->ss_scan_timer, jiffies + maxdwell);		/* clear mindwell lock and initial channel change flush */		SCAN_PRIVATE(ss)->ss_iflags &= ~ISCAN_REP;	} else {		ic->ic_scan_end(ic);		/* notify driver */		/*		 * Record scan complete time.  Note that we also do		 * this when canceled so any background scan will		 * not be restarted for a while.		 */		if (scandone)			ic->ic_lastscan = jiffies;		/* return to the bss channel */		if ((ic->ic_bsschan != IEEE80211_CHAN_ANYC) &&		    (ic->ic_curchan != ic->ic_bsschan))			change_channel(ic, ic->ic_bsschan);		/* clear internal flags and any indication of a pick */		SCAN_PRIVATE(ss)->ss_iflags &= ~ISCAN_REP;		ss->ss_flags &= ~IEEE80211_SCAN_GOTPICK;		/*		 * If not canceled and scan completed, do post-processing.		 * If the callback function returns 0, then it wants to		 * continue/restart scanning.  Unfortunately we needed to		 * notify the driver to end the scan above to avoid having		 * rx frames alter the scan candidate list.

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -