/* TBD factor with ieee80211_media_change */ int an_media_change(struct ifnet *ifp) { struct an_softc *sc = ifp->if_softc; struct ieee80211com *ic = &sc->sc_ic; struct ifmedia_entry *ime; enum ieee80211_opmode newmode; int i, rate, error = 0; ime = ic->ic_media.ifm_cur; if (IFM_SUBTYPE(ime->ifm_media) == IFM_AUTO) { i = -1; } else { struct ieee80211_rateset *rs = &ic->ic_sup_rates[IEEE80211_MODE_11B]; rate = ieee80211_media2rate(ime->ifm_media); if (rate == 0) return EINVAL; for (i = 0; i < rs->rs_nrates; i++) { if ((rs->rs_rates[i] & IEEE80211_RATE_VAL) == rate) break; } if (i == rs->rs_nrates) return EINVAL; } if (ic->ic_fixed_rate != i) { ic->ic_fixed_rate = i; error = ENETRESET; } #ifndef IEEE80211_STA_ONLY if (ime->ifm_media & IFM_IEEE80211_ADHOC) newmode = IEEE80211_M_IBSS; else if (ime->ifm_media & IFM_IEEE80211_HOSTAP) newmode = IEEE80211_M_HOSTAP; else #endif if (ime->ifm_media & IFM_IEEE80211_MONITOR) newmode = IEEE80211_M_MONITOR; else newmode = IEEE80211_M_STA; if (ic->ic_opmode != newmode) { ic->ic_opmode = newmode; error = ENETRESET; } if (error == ENETRESET) { if (sc->sc_enabled) error = an_init(ifp); else error = 0; } ifp->if_baudrate = ifmedia_baudrate(ic->ic_media.ifm_cur->ifm_media); return error; }
/* * Handle a media change request. */ int ieee80211_media_change(struct ifnet *ifp) { struct ieee80211com *ic; struct ifmedia_entry *ime; enum ieee80211_opmode newopmode; enum ieee80211_phymode newphymode; int i, j, newrate, error = 0; ic = ieee80211_find_instance(ifp); if (!ic) { if_printf(ifp, "%s: no 802.11 instance!\n", __func__); return EINVAL; } ime = ic->ic_media.ifm_cur; /* * First, identify the phy mode. */ switch (IFM_MODE(ime->ifm_media)) { case IFM_IEEE80211_11A: newphymode = IEEE80211_MODE_11A; break; case IFM_IEEE80211_11B: newphymode = IEEE80211_MODE_11B; break; case IFM_IEEE80211_11G: newphymode = IEEE80211_MODE_11G; break; case IFM_IEEE80211_FH: newphymode = IEEE80211_MODE_FH; break; case IFM_AUTO: newphymode = IEEE80211_MODE_AUTO; break; default: return EINVAL; } /* * Turbo mode is an ``option''. * XXX does not apply to AUTO */ if (ime->ifm_media & IFM_IEEE80211_TURBO) { if (newphymode == IEEE80211_MODE_11A) newphymode = IEEE80211_MODE_TURBO_A; else if (newphymode == IEEE80211_MODE_11G) newphymode = IEEE80211_MODE_TURBO_G; else return EINVAL; } /* * Validate requested mode is available. */ if ((ic->ic_modecaps & (1<<newphymode)) == 0) return EINVAL; /* * Next, the fixed/variable rate. */ i = -1; if (IFM_SUBTYPE(ime->ifm_media) != IFM_AUTO) { /* * Convert media subtype to rate. */ newrate = ieee80211_media2rate(ime->ifm_media); if (newrate == 0) return EINVAL; /* * Check the rate table for the specified/current phy. */ if (newphymode == IEEE80211_MODE_AUTO) { /* * In autoselect mode search for the rate. */ for (j = IEEE80211_MODE_11A; j < IEEE80211_MODE_MAX; j++) { if ((ic->ic_modecaps & (1<<j)) == 0) continue; i = findrate(ic, j, newrate); if (i != -1) { /* lock mode too */ newphymode = j; break; } } } else { i = findrate(ic, newphymode, newrate); } if (i == -1) /* mode/rate mismatch */ return EINVAL; } /* NB: defer rate setting to later */ /* * Deduce new operating mode but don't install it just yet. */ if ((ime->ifm_media & (IFM_IEEE80211_ADHOC|IFM_FLAG0)) == (IFM_IEEE80211_ADHOC|IFM_FLAG0)) newopmode = IEEE80211_M_AHDEMO; else if (ime->ifm_media & IFM_IEEE80211_HOSTAP) newopmode = IEEE80211_M_HOSTAP; else if (ime->ifm_media & IFM_IEEE80211_ADHOC) newopmode = IEEE80211_M_IBSS; else if (ime->ifm_media & IFM_IEEE80211_MONITOR) newopmode = IEEE80211_M_MONITOR; else newopmode = IEEE80211_M_STA; #ifndef IEEE80211_NO_HOSTAP /* * Autoselect doesn't make sense when operating as an AP. * If no phy mode has been selected, pick one and lock it * down so rate tables can be used in forming beacon frames * and the like. */ if (newopmode == IEEE80211_M_HOSTAP && newphymode == IEEE80211_MODE_AUTO) { for (j = IEEE80211_MODE_11A; j < IEEE80211_MODE_MAX; j++) if (ic->ic_modecaps & (1<<j)) { newphymode = j; break; } } #endif /* !IEEE80211_NO_HOSTAP */ /* * Handle phy mode change. */ if (ic->ic_curmode != newphymode) { /* change phy mode */ error = ieee80211_setmode(ic, newphymode); if (error != 0) return error; error = ENETRESET; } /* * Committed to changes, install the rate setting. */ if (ic->ic_fixed_rate != i) { ic->ic_fixed_rate = i; /* set fixed tx rate */ error = ENETRESET; } /* * Handle operating mode change. */ if (ic->ic_opmode != newopmode) { ic->ic_opmode = newopmode; switch (newopmode) { case IEEE80211_M_AHDEMO: case IEEE80211_M_HOSTAP: case IEEE80211_M_STA: case IEEE80211_M_MONITOR: ic->ic_flags &= ~IEEE80211_F_IBSSON; break; case IEEE80211_M_IBSS: ic->ic_flags |= IEEE80211_F_IBSSON; break; } /* * Yech, slot time may change depending on the * operating mode so reset it to be sure everything * is setup appropriately. */ ieee80211_reset_erp(ic); ieee80211_wme_initparams(ic); /* after opmode change */ error = ENETRESET; } #ifdef notdef if (error == 0) ifp->if_baudrate = ifmedia_baudrate(ime->ifm_media); #endif return error; }
/* * Handle a media change request. */ int ieee80211_media_change(struct ifnet *ifp) { struct ieee80211com *ic = (void *)ifp; struct ifmedia_entry *ime; enum ieee80211_opmode newopmode; enum ieee80211_phymode newphymode; int i, j, newrate, error = 0; ime = ic->ic_media.ifm_cur; /* * First, identify the phy mode. */ switch (IFM_MODE(ime->ifm_media)) { case IFM_IEEE80211_11A: newphymode = IEEE80211_MODE_11A; break; case IFM_IEEE80211_11B: newphymode = IEEE80211_MODE_11B; break; case IFM_IEEE80211_11G: newphymode = IEEE80211_MODE_11G; break; case IFM_IEEE80211_FH: newphymode = IEEE80211_MODE_FH; break; case IFM_AUTO: newphymode = IEEE80211_MODE_AUTO; break; default: return EINVAL; } /* * Turbo mode is an ``option''. Eventually it * needs to be applied to 11g too. */ if (ime->ifm_media & IFM_IEEE80211_TURBO) { if (newphymode != IEEE80211_MODE_11A) return EINVAL; newphymode = IEEE80211_MODE_TURBO; } /* * Validate requested mode is available. */ if ((ic->ic_modecaps & (1<<newphymode)) == 0) return EINVAL; /* * Next, the fixed/variable rate. */ i = -1; if (IFM_SUBTYPE(ime->ifm_media) != IFM_AUTO) { /* * Convert media subtype to rate. */ newrate = ieee80211_media2rate(ime->ifm_media); if (newrate == 0) return EINVAL; /* * Check the rate table for the specified/current phy. */ if (newphymode == IEEE80211_MODE_AUTO) { /* * In autoselect mode search for the rate. */ for (j = IEEE80211_MODE_11A; j < IEEE80211_MODE_MAX; j++) { if ((ic->ic_modecaps & (1<<j)) == 0) continue; i = findrate(ic, j, newrate); if (i != -1) { /* lock mode too */ newphymode = j; break; } } } else { i = findrate(ic, newphymode, newrate); } if (i == -1) /* mode/rate mismatch */ return EINVAL; } /* NB: defer rate setting to later */ /* * Deduce new operating mode but don't install it just yet. */ if ((ime->ifm_media & (IFM_IEEE80211_ADHOC|IFM_FLAG0)) == (IFM_IEEE80211_ADHOC|IFM_FLAG0)) newopmode = IEEE80211_M_AHDEMO; else if (ime->ifm_media & IFM_IEEE80211_HOSTAP) newopmode = IEEE80211_M_HOSTAP; else if (ime->ifm_media & IFM_IEEE80211_ADHOC) newopmode = IEEE80211_M_IBSS; else if (ime->ifm_media & IFM_IEEE80211_MONITOR) newopmode = IEEE80211_M_MONITOR; else newopmode = IEEE80211_M_STA; /* * Autoselect doesn't make sense when operating as an AP. * If no phy mode has been selected, pick one and lock it * down so rate tables can be used in forming beacon frames * and the like. */ if (newopmode == IEEE80211_M_HOSTAP && newphymode == IEEE80211_MODE_AUTO) { for (j = IEEE80211_MODE_11A; j < IEEE80211_MODE_MAX; j++) if (ic->ic_modecaps & (1<<j)) { newphymode = j; break; } } /* * Handle phy mode change. */ if (ic->ic_curmode != newphymode) { /* change phy mode */ error = ieee80211_setmode(ic, newphymode); if (error != 0) return error; error = ENETRESET; } /* * Committed to changes, install the rate setting. */ if (ic->ic_fixed_rate != i) { ic->ic_fixed_rate = i; /* set fixed tx rate */ error = ENETRESET; } /* * Handle operating mode change. */ if (ic->ic_opmode != newopmode) { ic->ic_opmode = newopmode; switch (newopmode) { case IEEE80211_M_AHDEMO: case IEEE80211_M_HOSTAP: case IEEE80211_M_STA: case IEEE80211_M_MONITOR: ic->ic_flags &= ~IEEE80211_F_IBSSON; break; case IEEE80211_M_IBSS: ic->ic_flags |= IEEE80211_F_IBSSON; break; } error = ENETRESET; } #ifdef notdef if (error == 0) ifp->if_baudrate = ifmedia_baudrate(ime->ifm_media); #endif return error; }