예제 #1
0
void
ieee80211_scan_dump_channels(const struct ieee80211_scan_state *ss)
{
	struct ieee80211com *ic = ss->ss_ic;
	const char *sep;
	int i;

	sep = "";
	for (i = ss->ss_next; i < ss->ss_last; i++) {
		const struct ieee80211_channel *c = ss->ss_chans[i];

		printf("%s%u%c", sep, ieee80211_chan2ieee(ic, c),
		    ieee80211_channel_type_char(c));
		sep = ", ";
	}
}
예제 #2
0
/*
 * Process a beacon or probe response frame.
 */
static void
ieee80211_swscan_add_scan(struct ieee80211vap *vap,
	struct ieee80211_channel *curchan,
	const struct ieee80211_scanparams *sp,
	const struct ieee80211_frame *wh,
	int subtype, int rssi, int noise)
{
	struct ieee80211com *ic = vap->iv_ic;
	struct ieee80211_scan_state *ss = ic->ic_scan;

	/* XXX locking */
	/*
	 * Frames received during startup are discarded to avoid
	 * using scan state setup on the initial entry to the timer
	 * callback.  This can occur because the device may enable
	 * rx prior to our doing the initial channel change in the
	 * timer routine.
	 */
	if (SCAN_PRIVATE(ss)->ss_iflags & ISCAN_DISCARD)
		return;
#ifdef IEEE80211_DEBUG
	if (ieee80211_msg_scan(vap) && (ic->ic_flags & IEEE80211_F_SCAN))
		ieee80211_scan_dump_probe_beacon(subtype, 1, wh->i_addr2, sp, rssi);
#endif
	if (ss->ss_ops != NULL &&
	    ss->ss_ops->scan_add(ss, curchan, sp, wh, subtype, rssi, noise)) {
		/*
		 * If we've reached the min dwell time terminate
		 * the timer so we'll switch to the next channel.
		 */
		if ((SCAN_PRIVATE(ss)->ss_iflags & ISCAN_MINDWELL) == 0 &&
		    ieee80211_time_after_eq(ticks, SCAN_PRIVATE(ss)->ss_chanmindwell)) {
			IEEE80211_DPRINTF(vap, IEEE80211_MSG_SCAN,
			    "%s: chan %3d%c min dwell met (%u > %lu)\n",
			    __func__,
			    ieee80211_chan2ieee(ic, ic->ic_curchan),
			    ieee80211_channel_type_char(ic->ic_curchan),
			    ticks, SCAN_PRIVATE(ss)->ss_chanmindwell);
			SCAN_PRIVATE(ss)->ss_iflags |= ISCAN_MINDWELL;
			/*
			 * NB: trigger at next clock tick or wait for the
			 * hardware.
			 */
			ic->ic_scan_mindwell(ss);
		}
	}
}
예제 #3
0
static void
scan_curchan_task(void *arg, int pending)
{
	struct ieee80211_scan_state *ss = arg;
	struct scan_state *ss_priv = SCAN_PRIVATE(ss);
	struct ieee80211com *ic = ss->ss_ic;
	struct ieee80211_channel *chan;
	unsigned long maxdwell;
	int scandone;

	IEEE80211_LOCK(ic);
end:
	scandone = (ss->ss_next >= ss->ss_last) ||
	    (ss_priv->ss_iflags & ISCAN_CANCEL) != 0;

	IEEE80211_DPRINTF(ss->ss_vap, IEEE80211_MSG_SCAN,
	    "%s: loop start; scandone=%d\n",
	    __func__,
	    scandone);

	if (scandone || (ss->ss_flags & IEEE80211_SCAN_GOTPICK) ||
	    (ss_priv->ss_iflags & ISCAN_ABORT) ||
	     ieee80211_time_after(ticks + ss->ss_mindwell, ss_priv->ss_scanend)) {
		ss_priv->ss_iflags &= ~ISCAN_RUNNING;
		scan_end(ss, scandone);
		return;
	} else
		ss_priv->ss_iflags |= ISCAN_RUNNING;

	chan = ss->ss_chans[ss->ss_next++];

	/*
	 * Watch for truncation due to the scan end time.
	 */
	if (ieee80211_time_after(ticks + ss->ss_maxdwell, ss_priv->ss_scanend))
		maxdwell = ss_priv->ss_scanend - ticks;
	else
		maxdwell = ss->ss_maxdwell;

	IEEE80211_DPRINTF(ss->ss_vap, IEEE80211_MSG_SCAN,
	    "%s: chan %3d%c -> %3d%c [%s, dwell min %lums max %lums]\n",
	    __func__,
	    ieee80211_chan2ieee(ic, ic->ic_curchan),
	    ieee80211_channel_type_char(ic->ic_curchan),
	    ieee80211_chan2ieee(ic, chan),
	    ieee80211_channel_type_char(chan),
	    (ss->ss_flags & IEEE80211_SCAN_ACTIVE) &&
		(chan->ic_flags & IEEE80211_CHAN_PASSIVE) == 0 ?
		"active" : "passive",
	    ticks_to_msecs(ss->ss_mindwell), ticks_to_msecs(maxdwell));

	/*
	 * Potentially change channel and phy mode.
	 */
	ic->ic_curchan = chan;
	ic->ic_rt = ieee80211_get_ratetable(chan);
	IEEE80211_UNLOCK(ic);
	/*
	 * Perform the channel change and scan unlocked so the driver
	 * may sleep. Once set_channel returns the hardware has
	 * completed the channel change.
	 */
	ic->ic_set_channel(ic);
	ieee80211_radiotap_chan_change(ic);

	/*
	 * Scan curchan.  Drivers for "intelligent hardware"
	 * override ic_scan_curchan to tell the device to do
	 * the work.  Otherwise we manage the work ourselves;
	 * sending a probe request (as needed), and arming the
	 * timeout to switch channels after maxdwell ticks.
	 *
	 * scan_curchan should only pause for the time required to
	 * prepare/initiate the hardware for the scan (if at all).
	 */
	ic->ic_scan_curchan(ss, maxdwell);
	IEEE80211_LOCK(ic);

	/* XXX scan state can change! Re-validate scan state! */

	ss_priv->ss_chanmindwell = ticks + ss->ss_mindwell;
	/* clear mindwell lock and initial channel change flush */
	ss_priv->ss_iflags &= ~ISCAN_REP;

	if (ss_priv->ss_iflags & (ISCAN_CANCEL|ISCAN_ABORT)) {
		taskqueue_cancel_timeout(ic->ic_tq, &ss_priv->ss_scan_curchan,
		    NULL);
		goto end;
	}

	IEEE80211_DPRINTF(ss->ss_vap, IEEE80211_MSG_SCAN, "%s: waiting\n",
	    __func__);
	IEEE80211_UNLOCK(ic);
}