PERFORCE change 113263 for review

Sam Leffler sam at FreeBSD.org
Sun Jan 21 19:51:57 UTC 2007


http://perforce.freebsd.org/chv.cgi?CH=113263

Change 113263 by sam at sam_ebb on 2007/01/21 19:51:42

	Cleanup channel manipulation ioctls a bit:
	o change IEEE80211_IOC_CHANINFO to return the complete
	  channel list the kernel uses, don't suppress/combine
	  duplicates
	o add IEEE80211_IOC_CURCHAN ioctl to replace IEEE80211_IOC_CHANNEL
	  for getting and setting the current channel; this allows us to
	  unambiguously specify a channel when a single frequency can
	  be operated in multiple ways (e.g. different channel width)

Affected files ...

.. //depot/projects/wifi/sys/net80211/ieee80211_ioctl.c#64 edit
.. //depot/projects/wifi/sys/net80211/ieee80211_ioctl.h#36 edit

Differences ...

==== //depot/projects/wifi/sys/net80211/ieee80211_ioctl.c#64 (text+ko) ====

@@ -158,29 +158,14 @@
 static int
 ieee80211_ioctl_getchaninfo(struct ieee80211com *ic, struct ieee80211req *ireq)
 {
-	struct ieee80211req_chaninfo chans;	/* XXX off stack? */
-	u_int8_t reported[IEEE80211_CHAN_BYTES];	/* XXX stack usage */
-	int i, space;
-
-	memset(&chans, 0, sizeof(chans));
-	memset(&reported, 0, sizeof(reported));
-	for (i = 0; i < ic->ic_nchans; i++) {
-		const struct ieee80211_channel *c = &ic->ic_channels[i];
+	int space;
 
-		/* discard if previously reported (e.g. b/g) */
-		if (isclr(reported, c->ic_ieee)) {
-			setbit(reported, c->ic_ieee);
-			chans.ic_chans[chans.ic_nchans].ic_freq = c->ic_freq;
-			chans.ic_chans[chans.ic_nchans].ic_flags = c->ic_flags;
-			if (++chans.ic_nchans >= IEEE80211_CHAN_MAX)
-				break;
-		}
-	}
 	space = __offsetof(struct ieee80211req_chaninfo,
-			ic_chans[chans.ic_nchans]);
+			ic_chans[ic->ic_nchans]);
 	if (space > ireq->i_len)
 		space = ireq->i_len;
-	return copyout(&chans, ireq->i_data, space);
+	/* XXX assumes compatible layout */
+	return copyout(&ic->ic_nchans, ireq->i_data, space);
 }
 
 static int
@@ -804,6 +789,14 @@
 		return (ic->ic_flags & cap) != 0;
 }
 
+static int
+ieee80211_ioctl_getcurchan(struct ieee80211com *ic, struct ieee80211req *ireq)
+{
+	if (ireq->i_len != sizeof(struct ieee80211_channel))
+		return EINVAL;
+	return copyout(ic->ic_curchan, ireq->i_data, sizeof(*ic->ic_curchan));
+}
+
 /*
  * When building the kernel with -O2 on the i386 architecture, gcc
  * seems to want to inline this function into ieee80211_ioctl()
@@ -1098,6 +1091,9 @@
 	case IEEE80211_IOC_BMISSTHRESHOLD:
 		ireq->i_val = ic->ic_bmissthreshold;
 		break;
+	case IEEE80211_IOC_CURCHAN:
+		error = ieee80211_ioctl_getcurchan(ic, ireq);
+		break;
 	default:
 		error = EINVAL;
 		break;
@@ -1767,6 +1763,65 @@
 }
 
 static int
+ieee80211_ioctl_setcurchan(struct ieee80211com *ic,
+	const struct ieee80211req *ireq)
+{
+	struct ieee80211_channel chan;
+	int error;
+
+	if (ireq->i_len != sizeof(chan))
+		return EINVAL;
+	error = copyin(ireq->i_data, &chan, sizeof(chan));
+	if (error != 0)
+		return error;
+	/* XXX 0xffff overflows 16-bit signed */
+	if (chan.ic_freq == 0 || chan.ic_freq == IEEE80211_CHAN_ANY) {
+		ic->ic_des_chan = IEEE80211_CHAN_ANYC;
+	} else {
+		struct ieee80211_channel *c;
+
+		c = ieee80211_find_channel(ic, chan.ic_freq, chan.ic_flags);
+		if (c == NULL)
+			return EINVAL;
+		/* XXX? */
+		if (ic->ic_opmode == IEEE80211_M_HOSTAP &&
+		    !check_mode_consistency(c, ic->ic_des_mode))
+			return EINVAL;
+		if (ic->ic_state == IEEE80211_S_RUN && c == ic->ic_bsschan)
+			return 0;	/* NB: nothing to do */
+		ic->ic_des_chan = c;
+	}
+	error = 0;
+	if ((ic->ic_opmode == IEEE80211_M_MONITOR ||
+	    ic->ic_opmode == IEEE80211_M_WDS) &&
+	    ic->ic_des_chan != IEEE80211_CHAN_ANYC) {
+		/*
+		 * Monitor and wds modes can switch directly.
+		 */
+		ic->ic_curchan = ic->ic_des_chan;
+		if (ic->ic_state == IEEE80211_S_RUN)
+			ic->ic_set_channel(ic);
+	} else {
+		/*
+		 * Need to go through the state machine in case we
+		 * need to reassociate or the like.  The state machine
+		 * will pickup the desired channel and avoid scanning.
+		 */
+		if (IS_UP_AUTO(ic))
+			error = ieee80211_init(ic, RESCAN);
+		else if (ic->ic_des_chan != IEEE80211_CHAN_ANYC) {
+			/*
+			 * When not up+running and a real channel has
+			 * been specified fix the current channel so
+			 * there is immediate feedback; e.g. via ifconfig.
+			 */
+			ic->ic_curchan = ic->ic_des_chan;
+		}
+	}
+	return error;
+}
+
+static int
 ieee80211_ioctl_set80211(struct ieee80211com *ic, u_long cmd, struct ieee80211req *ireq)
 {
 	static const u_int8_t zerobssid[IEEE80211_ADDR_LEN];
@@ -2265,6 +2320,9 @@
 		ic->ic_bmissthreshold = ireq->i_val;
 		error = IS_UP(ic) ? ic->ic_reset(ic->ic_ifp) : 0;
 		break;
+	case IEEE80211_IOC_CURCHAN:
+		error = ieee80211_ioctl_setcurchan(ic, ireq);
+		break;
 	default:
 		error = EINVAL;
 		break;

==== //depot/projects/wifi/sys/net80211/ieee80211_ioctl.h#36 (text+ko) ====

@@ -471,6 +471,7 @@
 #define	IEEE80211_IOC_BMISSTHRESHOLD	77	/* beacon miss threshold */
 #define	IEEE80211_IOC_STA_INFO		78	/* station/neighbor info */
 #define	IEEE80211_IOC_WPAIE2		79	/* WPA+RSN info elements */
+#define	IEEE80211_IOC_CURCHAN		80	/* current channel */
 
 /*
  * Scan result data returned for IEEE80211_IOC_SCAN_RESULTS.


More information about the p4-projects mailing list