* Common code to set the current channel. If the device * is up and running this may result in an immediate channel * change or a kick of the state machine. */
| 1980 | * change or a kick of the state machine. |
| 1981 | */ |
| 1982 | static int |
| 1983 | setcurchan(struct ieee80211vap *vap, struct ieee80211_channel *c) |
| 1984 | { |
| 1985 | struct ieee80211com *ic = vap->iv_ic; |
| 1986 | int error; |
| 1987 | |
| 1988 | if (c != IEEE80211_CHAN_ANYC) { |
| 1989 | if (IEEE80211_IS_CHAN_RADAR(c)) |
| 1990 | return EBUSY; /* XXX better code? */ |
| 1991 | if (vap->iv_opmode == IEEE80211_M_HOSTAP) { |
| 1992 | if (IEEE80211_IS_CHAN_NOHOSTAP(c)) |
| 1993 | return EINVAL; |
| 1994 | if (!check_mode_consistency(c, vap->iv_des_mode)) |
| 1995 | return EINVAL; |
| 1996 | } else if (vap->iv_opmode == IEEE80211_M_IBSS) { |
| 1997 | if (IEEE80211_IS_CHAN_NOADHOC(c)) |
| 1998 | return EINVAL; |
| 1999 | } |
| 2000 | if ((vap->iv_state == IEEE80211_S_RUN || vap->iv_state == IEEE80211_S_SLEEP) && |
| 2001 | vap->iv_bss->ni_chan == c) |
| 2002 | return 0; /* NB: nothing to do */ |
| 2003 | } |
| 2004 | vap->iv_des_chan = c; |
| 2005 | |
| 2006 | error = 0; |
| 2007 | if (vap->iv_opmode == IEEE80211_M_MONITOR && |
| 2008 | vap->iv_des_chan != IEEE80211_CHAN_ANYC) { |
| 2009 | /* |
| 2010 | * Monitor mode can switch directly. |
| 2011 | */ |
| 2012 | if (IFNET_IS_UP_RUNNING(vap->iv_ifp)) { |
| 2013 | /* XXX need state machine for other vap's to follow */ |
| 2014 | ieee80211_setcurchan(ic, vap->iv_des_chan); |
| 2015 | vap->iv_bss->ni_chan = ic->ic_curchan; |
| 2016 | } else { |
| 2017 | ic->ic_curchan = vap->iv_des_chan; |
| 2018 | ic->ic_rt = ieee80211_get_ratetable(ic->ic_curchan); |
| 2019 | } |
| 2020 | } else { |
| 2021 | /* |
| 2022 | * Need to go through the state machine in case we |
| 2023 | * need to reassociate or the like. The state machine |
| 2024 | * will pickup the desired channel and avoid scanning. |
| 2025 | */ |
| 2026 | if (IS_UP_AUTO(vap)) |
| 2027 | ieee80211_new_state(vap, IEEE80211_S_SCAN, 0); |
| 2028 | else if (vap->iv_des_chan != IEEE80211_CHAN_ANYC) { |
| 2029 | /* |
| 2030 | * When not up+running and a real channel has |
| 2031 | * been specified fix the current channel so |
| 2032 | * there is immediate feedback; e.g. via ifconfig. |
| 2033 | */ |
| 2034 | ic->ic_curchan = vap->iv_des_chan; |
| 2035 | ic->ic_rt = ieee80211_get_ratetable(ic->ic_curchan); |
| 2036 | } |
| 2037 | } |
| 2038 | return error; |
| 2039 | } |
no test coverage detected