Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 1 Jan 2007 23:42:42 GMT
From:      Kip Macy <kmacy@FreeBSD.org>
To:        Perforce Change Reviews <perforce@freebsd.org>
Subject:   PERFORCE change 112405 for review
Message-ID:  <200701012342.l01Nggu3031208@repoman.freebsd.org>

next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=112405

Change 112405 by kmacy@kmacy_serendipity:sam_wifi on 2007/01/01 23:42:28

	- add in basic scanning hooks so that we don't blow up
	  if wlan_scan_sta is loaded
	- add ioctl's to bypass net80211 to fetch the scanning 
	  results for ifconfig - scanning now appears to work

Affected files ...

.. //depot/projects/wifi/sys/dev/wi/if_wi.c#24 edit

Differences ...

==== //depot/projects/wifi/sys/dev/wi/if_wi.c#24 (text+ko) ====

@@ -118,7 +118,7 @@
 		struct mbuf *m0);
 static int  wi_raw_xmit(struct ieee80211_node *, struct mbuf *,
 		const struct ieee80211_bpf_params *);
-static int  wi_reset(struct wi_softc *);
+static int  wi_reset(struct ifnet *);
 static void wi_watchdog(void *);
 static int  wi_ioctl(struct ifnet *, u_long, caddr_t);
 static int  wi_media_change(struct ifnet *);
@@ -164,6 +164,14 @@
 		const void *, int);
 static int wi_symbol_set_hcr(struct wi_softc *, int);
 
+static void wi_scan_start(struct ieee80211com *);
+static void wi_scan_end(struct ieee80211com *);
+static void wi_set_channel(struct ieee80211com *);
+static void wi_update_slot(struct ifnet *);
+static struct ieee80211_node *wi_node_alloc(struct ieee80211_node_table *);
+static int wi_ioctl_get(struct ifnet *ifp, u_long command, caddr_t data);
+static int wi_ioctl_set(struct ifnet *ifp, u_long command, caddr_t data);
+	
 static __inline int
 wi_write_val(struct wi_softc *sc, int rid, u_int16_t val)
 {
@@ -253,6 +261,7 @@
 	int error;
 
 	ifp = sc->sc_ifp = if_alloc(IFT_ETHER);
+	ifp->if_softc = sc;
 	if (ifp == NULL) {
 		device_printf(dev, "can not if_alloc\n");
 		wi_free(dev);
@@ -279,7 +288,7 @@
 	sc->sc_firmware_type = WI_NOTYPE;
 	sc->wi_cmd_count = 500;
 	/* Reset the NIC. */
-	if (wi_reset(sc) != 0)
+	if (wi_reset(ifp) != 0)
 		return ENXIO;		/* XXX */
 
 	/*
@@ -308,7 +317,6 @@
 	/* Read NIC identification */
 	wi_read_nicid(sc);
 
-	ifp->if_softc = sc;
 	if_initname(ifp, device_get_name(dev), device_get_unit(dev));
 	ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
 	ifp->if_ioctl = wi_ioctl;
@@ -494,6 +502,14 @@
 	ic->ic_crypto.cs_key_alloc = wi_key_alloc;
 	ic->ic_newstate = wi_newstate;
 	ic->ic_raw_xmit = wi_raw_xmit;
+
+	ic->ic_scan_start = wi_scan_start;
+	ic->ic_scan_end = wi_scan_end;
+	ic->ic_set_channel = wi_set_channel;
+	ic->ic_node_alloc = wi_node_alloc;
+	ic->ic_updateslot = wi_update_slot;
+	ic->ic_reset = wi_reset;
+
 	ieee80211_media_init(ic, wi_media_change, wi_media_status);
 
 #if NBPFILTER > 0
@@ -665,7 +681,7 @@
 
 	if ((wasenabled = sc->sc_enabled))
 		wi_stop(ifp, 1);
-	wi_reset(sc);
+	wi_reset(ifp);
 
 	/* common 802.11 configuration */
 	ic->ic_flags &= ~IEEE80211_F_IBSSON;
@@ -1137,9 +1153,9 @@
 }
 
 static int
-wi_reset(struct wi_softc *sc)
+wi_reset(struct ifnet *ifp)
 {
-	struct ifnet *ifp = sc->sc_ifp;
+	struct wi_softc *sc = ifp->if_softc;
 #define WI_INIT_TRIES 3
 	int i;
 	int error = 0;
@@ -1212,8 +1228,6 @@
 	struct wi_softc *sc = ifp->if_softc;
 	struct ieee80211com *ic = &sc->sc_ic;
 	struct ifreq *ifr = (struct ifreq *)data;
-	struct ieee80211req *ireq;
-	u_int8_t nodename[IEEE80211_NWID_LEN];
 	int error = 0;
 	struct thread *td = curthread;
 	struct wi_req wreq;
@@ -1294,47 +1308,147 @@
 		WI_UNLOCK(sc);
 		break;
 	case SIOCG80211:
-		ireq = (struct ieee80211req *) data;
-		if (ireq->i_type == IEEE80211_IOC_STATIONNAME) {
-			ireq->i_len = sc->sc_nodelen + 1;
-			error = copyout(sc->sc_nodename, ireq->i_data,
-					ireq->i_len);
+		error = wi_ioctl_get(ifp, cmd, data);
+		break;
+	case SIOCS80211:
+		error = priv_check(td, PRIV_NET80211_MANAGE);
+		if (error)
+			break;
+		error = wi_ioctl_set(ifp, cmd, data);
+
+
+			break;
+	default:
+		error = ieee80211_ioctl(ic, cmd, data);
+		WI_LOCK(sc);
+		if (error == ENETRESET) {
+			if (sc->sc_enabled)
+				wi_init(sc);	/* XXX no error return */
+			error = 0;
+		}
+		WI_UNLOCK(sc);
+		break;
+	}
+	return (error);
+}
+
+static int
+wi_ioctl_get(struct ifnet *ifp, u_long cmd, caddr_t data)
+{
+	int                 error, i, len;
+	struct wi_softc     *sc;
+	struct ieee80211req *ireq;
+	struct ieee80211com *ic;
+	struct wi_apinfo    *ap;
+	struct ieee80211req_scan_result	*sr, *bsr;
+	char                *cp;
+	uint16_t            *bssid;
+	sc = ifp->if_softc;
+	ic = &sc->sc_ic;
+	ireq = (struct ieee80211req *) data;
+
+	switch (ireq->i_type) {
+	case IEEE80211_IOC_SCAN_RESULTS:
+		sr = bsr = malloc(ireq->i_len, M_DEVBUF, M_NOWAIT | M_ZERO);
+		if (sr == NULL) {
+			error = ENOMEM;
 			break;
 		}
-		goto ioctl_common;
-	case SIOCS80211:
-		ireq = (struct ieee80211req *) data;
-		if (ireq->i_type == IEEE80211_IOC_STATIONNAME) {
-			error = priv_check(td, PRIV_NET80211_MANAGE);
-			if (error)
+		len = 0;
+		for (i = 0; i < sc->sc_naps; i++) {
+			ap = &sc->sc_aps[i];
+			if (len + sizeof(*sr) + ap->namelen >  ireq->i_len)
 				break;
-			if (ireq->i_val != 0 ||
-			    ireq->i_len > IEEE80211_NWID_LEN) {
-				error = EINVAL;
+			bssid = (uint16_t *)&ap->bssid;
+			/* Lucent firmware will return empty records */
+			if (bssid[0] == 0 && bssid[1] == 0 && bssid[2] == 0) 
 				break;
-			}
-			memset(nodename, 0, IEEE80211_NWID_LEN);
-			error = copyin(ireq->i_data, nodename, ireq->i_len);
-			if (error)
-				break;
-			WI_LOCK(sc);
-			if (sc->sc_enabled) {
-				error = wi_write_ssid(sc, WI_RID_NODENAME,
-					nodename, ireq->i_len);
-			}
-			if (error == 0) {
-				memcpy(sc->sc_nodename, nodename,
-					IEEE80211_NWID_LEN);
-				sc->sc_nodelen = ireq->i_len;
-			}
-			WI_UNLOCK(sc);
+
+			sr->isr_rssi = ap->signal;
+			sr->isr_freq = ieee80211_ieee2mhz(ap->channel, 
+							  IEEE80211_CHAN_B);
+			sr->isr_intval = ap->interval;
+			sr->isr_rates[0] = ap->rate;
+			sr->isr_nrates = 1;
+			sr->isr_ssid_len = ap->namelen;
+			sr->isr_ie_len = 0;
+			sr->isr_capinfo = ap->capinfo; /* XXX */
+			sr->isr_noise = ap->noise;  /* XXX */
+			bcopy(ap->bssid, sr->isr_bssid, sizeof(sr->isr_bssid));
+			cp = (char *)sr + sizeof(*sr);
+			bcopy(ap->name, cp, sr->isr_ssid_len);
+			cp += sr->isr_ssid_len;
+			sr->isr_len = roundup(sizeof(*sr) + sr->isr_ssid_len,
+					      sizeof(uint32_t));
+			len += sr->isr_len;
+		}
+		ireq->i_len = len;
+		error = copyout(bsr, ireq->i_data, len);
+		free(bsr, M_DEVBUF);
+		break;
+	case IEEE80211_IOC_STATIONNAME:
+		ireq->i_len = sc->sc_nodelen + 1;
+		error = copyout(sc->sc_nodename, ireq->i_data,
+				ireq->i_len);
+		break;
+	default:
+		error = ieee80211_ioctl(ic, cmd, data);
+		WI_LOCK(sc);
+		if (error == ENETRESET) {
+			if (sc->sc_enabled)
+				wi_init(sc);	/* XXX no error return */
+			error = 0;
+		}
+		WI_UNLOCK(sc);
+
+		break;
+	}
+	
+	return (error);
+}
+
+static int
+wi_ioctl_set(struct ifnet *ifp, u_long cmd, caddr_t data)
+{
+	int                 error;
+	struct wi_softc     *sc;
+	struct ieee80211req *ireq;
+	u_int8_t nodename[IEEE80211_NWID_LEN];
+		
+	sc = ifp->if_softc;
+	ireq = (struct ieee80211req *) data;
+	switch (ireq->i_type) {
+	case IEEE80211_IOC_SCAN_REQ:
+		WI_LOCK(sc);
+		error = wi_scan_ap(sc, 0x3fff, 0x000f);
+		WI_UNLOCK(sc);
+		break;
+	case IEEE80211_IOC_STATIONNAME:
+		if (ireq->i_val != 0 ||
+		    ireq->i_len > IEEE80211_NWID_LEN) {
+			error = EINVAL;
 			break;
 		}
-		goto ioctl_common;
+		memset(nodename, 0, IEEE80211_NWID_LEN);
+		error = copyin(ireq->i_data, nodename, ireq->i_len);
+		if (error)
+			break;
+		WI_LOCK(sc);
+		if (sc->sc_enabled) {
+			error = wi_write_ssid(sc, WI_RID_NODENAME,
+					      nodename, ireq->i_len);
+		}
+		if (error == 0) {
+			memcpy(sc->sc_nodename, nodename,
+			       IEEE80211_NWID_LEN);
+			sc->sc_nodelen = ireq->i_len;
+		}
+		WI_UNLOCK(sc);
+		
+		break;
 	default:
-	ioctl_common:
+		error = ieee80211_ioctl(&sc->sc_ic, cmd, data);
 		WI_LOCK(sc);
-		error = ieee80211_ioctl(ic, cmd, data);
 		if (error == ENETRESET) {
 			if (sc->sc_enabled)
 				wi_init(sc);	/* XXX no error return */
@@ -1343,9 +1457,21 @@
 		WI_UNLOCK(sc);
 		break;
 	}
+
 	return (error);
 }
 
+static struct ieee80211_node *
+wi_node_alloc(struct ieee80211_node_table *nt)
+{
+	struct wi_node *rn;
+
+	rn = malloc(sizeof (struct wi_node), M_80211_NODE,
+	    M_NOWAIT | M_ZERO);
+
+	return (rn != NULL) ? &rn->ni : NULL;
+}
+
 static int
 wi_media_change(struct ifnet *ifp)
 {
@@ -3376,3 +3502,37 @@
 	tsleep(sc, PWAIT, "wiinit", 1);
 	return 0;
 }
+
+/*
+ * This function can be called by ieee80211_set_shortslottime(). Refer to
+ * IEEE Std 802.11-1999 pp. 85 to know how these values are computed.
+ */
+static void
+wi_update_slot(struct ifnet *ifp)
+{
+	DPRINTF(("wi update slot unimplemented\n"));
+}
+
+static void
+wi_set_channel(struct ieee80211com *ic)
+{
+	return;
+}
+
+static void
+wi_scan_start(struct ieee80211com *ic)
+{
+	struct ifnet *ifp = ic->ic_ifp;
+	struct wi_softc *sc = ifp->if_softc;
+
+	WI_LOCK(sc);
+	wi_scan_ap(sc, 0x3fff, 0x000f);
+	WI_UNLOCK(sc);
+
+}
+
+static void
+wi_scan_end(struct ieee80211com *ic)
+{
+	return;
+}



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200701012342.l01Nggu3031208>