Ejemplo n.º 1
0
static uint8
spec_to_chan(chanspec_t chspec)
{
	uint8 center_ch, edge, primary, sb;

	center_ch = CHSPEC_CHANNEL(chspec);

	if (CHSPEC_IS20(chspec)) {
		return center_ch;
	} else {
		/* the lower edge of the wide channel is half the bw from
		 * the center channel.
		 */
		if (CHSPEC_IS40(chspec)) {
			edge = center_ch - CH_20MHZ_APART;
		} else {
			/* must be 80MHz (until we support more) */
			ASSERT(CHSPEC_IS80(chspec));
			edge = center_ch - CH_40MHZ_APART;
		}

		/* find the channel number of the lowest 20MHz primary channel */
		primary = edge + CH_10MHZ_APART;

		/* select the actual subband */
		sb = (chspec & WL_CHANSPEC_CTL_SB_MASK) >> WL_CHANSPEC_CTL_SB_SHIFT;
		primary = primary + sb * CH_20MHZ_APART;

		return primary;
	}
}
Ejemplo n.º 2
0
/*
 * Verify the chanspec is using a legal set of parameters, i.e. that the
 * chanspec specified a band, bw, ctl_sb and channel and that the
 * combination could be legal given any set of circumstances.
 * RETURNS: true is the chanspec is malformed, false if it looks good.
 */
static bool brcms_c_chspec_malformed(u16 chanspec)
{
	/* must be 2G or 5G band */
	if (!CHSPEC_IS5G(chanspec) && !CHSPEC_IS2G(chanspec))
		return true;
	/* must be 20 or 40 bandwidth */
	if (!CHSPEC_IS40(chanspec) && !CHSPEC_IS20(chanspec))
		return true;

	/* 20MHZ b/w must have no ctl sb, 40 must have a ctl sb */
	if (CHSPEC_IS20(chanspec)) {
		if (!CHSPEC_SB_NONE(chanspec))
			return true;
	} else if (!CHSPEC_SB_UPPER(chanspec) && !CHSPEC_SB_LOWER(chanspec)) {
		return true;
	}

	return false;
}
/*
 * Verify the chanspec is using a legal set of parameters, i.e. that the
 * chanspec specified a band, bw, ctl_sb and channel and that the
 * combination could be legal given any set of circumstances.
 * RETURNS: TRUE is the chanspec is malformed, false if it looks good.
 */
bool
wf_chspec_malformed(chanspec_t chanspec)
{
	/* must be 2G or 5G band */
	if (!CHSPEC_IS5G(chanspec) && !CHSPEC_IS2G(chanspec))
		return TRUE;
	/* must be 20 or 40 bandwidth */
	if (!CHSPEC_IS40(chanspec) && !CHSPEC_IS20(chanspec))
		return TRUE;

	/* 20MHZ b/w must have no ctl sb, 40 must have a ctl sb */
	if (CHSPEC_IS20(chanspec)) {
		if (!CHSPEC_SB_NONE(chanspec))
			return TRUE;
	} else {
		if (!CHSPEC_SB_UPPER(chanspec) && !CHSPEC_SB_LOWER(chanspec))
		return TRUE;
	}

	return FALSE;
}
bool
wf_chspec_malformed(chanspec_t chanspec)
{
	
	if (!CHSPEC_IS5G(chanspec) && !CHSPEC_IS2G(chanspec))
		return TRUE;
	
	if (!CHSPEC_IS40(chanspec) && !CHSPEC_IS20(chanspec))
		return TRUE;

	
	if (CHSPEC_IS20(chanspec)) {
		if (!CHSPEC_SB_NONE(chanspec))
			return TRUE;
	} else {
		if (!CHSPEC_SB_UPPER(chanspec) && !CHSPEC_SB_LOWER(chanspec))
		return TRUE;
	}

	return FALSE;
}
Ejemplo n.º 5
0
/* given a chanspec and a string buffer, format the chanspec as a
 * string, and return the original pointer a.
 * Min buffer length must be CHANSPEC_STR_LEN.
 * On error return NULL
 */
char *
wf_chspec_ntoa(chanspec_t chspec, char *buf)
{
    const char *band;
    uint ctl_chan;

    if (wf_chspec_malformed(chspec))
        return NULL;

    band = "";

    /* check for non-default band spec */
    if ((CHSPEC_IS2G(chspec) && CHSPEC_CHANNEL(chspec) > CH_MAX_2G_CHANNEL) ||
            (CHSPEC_IS5G(chspec) && CHSPEC_CHANNEL(chspec) <= CH_MAX_2G_CHANNEL))
        band = (CHSPEC_IS2G(chspec)) ? "2g" : "5g";

    /* ctl channel */
    ctl_chan = wf_chspec_ctlchan(chspec);

    /* bandwidth and ctl sideband */
    if (CHSPEC_IS20(chspec)) {
        snprintf(buf, CHANSPEC_STR_LEN, "%s%d", band, ctl_chan);
    } else if (!CHSPEC_IS8080(chspec)) {
        const char *bw;
        const char *sb = "";

        bw = wf_chspec_bw_str[(chspec & WL_CHANSPEC_BW_MASK) >> WL_CHANSPEC_BW_SHIFT];

#ifdef CHANSPEC_NEW_40MHZ_FORMAT
        /* ctl sideband string if needed for 2g 40MHz */
        if (CHSPEC_IS40(chspec) && CHSPEC_IS2G(chspec)) {
            sb = CHSPEC_SB_UPPER(chspec) ? "u" : "l";
        }

        snprintf(buf, CHANSPEC_STR_LEN, "%s%d/%s%s", band, ctl_chan, bw, sb);
#else
        /* ctl sideband string instead of BW for 40MHz */
        if (CHSPEC_IS40(chspec)) {
            sb = CHSPEC_SB_UPPER(chspec) ? "u" : "l";
            snprintf(buf, CHANSPEC_STR_LEN, "%s%d%s", band, ctl_chan, sb);
        } else {
            snprintf(buf, CHANSPEC_STR_LEN, "%s%d/%s", band, ctl_chan, bw);
        }
#endif /* CHANSPEC_NEW_40MHZ_FORMAT */

    } else {
char *
wf_chspec_ntoa(chanspec_t chspec, char *buf)
{
	const char *band;
	uint ctl_chan;

	if (wf_chspec_malformed(chspec))
		return NULL;

	band = "";

	
	if ((CHSPEC_IS2G(chspec) && CHSPEC_CHANNEL(chspec) > CH_MAX_2G_CHANNEL) ||
	    (CHSPEC_IS5G(chspec) && CHSPEC_CHANNEL(chspec) <= CH_MAX_2G_CHANNEL))
		band = (CHSPEC_IS2G(chspec)) ? "2g" : "5g";

	
	ctl_chan = wf_chspec_ctlchan(chspec);

	
	if (CHSPEC_IS20(chspec)) {
		snprintf(buf, CHANSPEC_STR_LEN, "%s%d", band, ctl_chan);
	} else if (!CHSPEC_IS8080(chspec)) {
		const char *bw;
		const char *sb = "";

		bw = wf_chspec_bw_str[(chspec & WL_CHANSPEC_BW_MASK) >> WL_CHANSPEC_BW_SHIFT];

#ifdef CHANSPEC_NEW_40MHZ_FORMAT
		
		if (CHSPEC_IS40(chspec) && CHSPEC_IS2G(chspec)) {
			sb = CHSPEC_SB_UPPER(chspec) ? "u" : "l";
		}

		snprintf(buf, CHANSPEC_STR_LEN, "%s%d/%s%s", band, ctl_chan, bw, sb);
#else
		
		if (CHSPEC_IS40(chspec)) {
			sb = CHSPEC_SB_UPPER(chspec) ? "u" : "l";
			snprintf(buf, CHANSPEC_STR_LEN, "%s%d%s", band, ctl_chan, sb);
		} else {
			snprintf(buf, CHANSPEC_STR_LEN, "%s%d/%s", band, ctl_chan, bw);
		}
#endif 

	} else {
Ejemplo n.º 7
0
bool
wf_chspec_malformed(chanspec_t chanspec)
{
	
	DHD_MYTRACE(("%s-%s\n", __FILE__, __FUNCTION__));

	if (!CHSPEC_IS5G(chanspec) && !CHSPEC_IS2G(chanspec))
		return TRUE;
	
	if (!CHSPEC_IS40(chanspec) && !CHSPEC_IS20(chanspec))
		return TRUE;

	
	if (CHSPEC_IS20_UNCOND(chanspec)) {
		if (!CHSPEC_SB_NONE(chanspec))
			return TRUE;
	} else {
		if (!CHSPEC_SB_UPPER(chanspec) && !CHSPEC_SB_LOWER(chanspec))
		return TRUE;
	}

	return FALSE;
}
Ejemplo n.º 8
0
/*
 * Validate the chanspec for this locale, for 40MHZ we need to also check that the sidebands
 * are valid 20MZH channels in this locale and they are also a legal HT combination
 */
static bool
wlc_valid_chanspec_ext(wlc_cm_info_t *wlc_cm, chanspec_t chspec, bool dualband)
{
	struct wlc_info *wlc = wlc_cm->wlc;
	u8 channel = CHSPEC_CHANNEL(chspec);

	/* check the chanspec */
	if (wf_chspec_malformed(chspec)) {
		WL_ERROR("wl%d: malformed chanspec 0x%x\n",
			 wlc->pub->unit, chspec);
		ASSERT(0);
		return false;
	}

	if (CHANNEL_BANDUNIT(wlc_cm->wlc, channel) !=
	    CHSPEC_WLCBANDUNIT(chspec))
		return false;

	/* Check a 20Mhz channel */
	if (CHSPEC_IS20(chspec)) {
		if (dualband)
			return VALID_CHANNEL20_DB(wlc_cm->wlc, channel);
		else
			return VALID_CHANNEL20(wlc_cm->wlc, channel);
	}
#ifdef SUPPORT_40MHZ
	/* We know we are now checking a 40MHZ channel, so we should only be here
	 * for NPHYS
	 */
	if (WLCISNPHY(wlc->band) || WLCISSSLPNPHY(wlc->band)) {
		u8 upper_sideband = 0, idx;
		u8 num_ch20_entries =
		    sizeof(chan20_info) / sizeof(struct chan20_info);

		if (!VALID_40CHANSPEC_IN_BAND(wlc, CHSPEC_WLCBANDUNIT(chspec)))
			return false;

		if (dualband) {
			if (!VALID_CHANNEL20_DB(wlc, LOWER_20_SB(channel)) ||
			    !VALID_CHANNEL20_DB(wlc, UPPER_20_SB(channel)))
				return false;
		} else {
			if (!VALID_CHANNEL20(wlc, LOWER_20_SB(channel)) ||
			    !VALID_CHANNEL20(wlc, UPPER_20_SB(channel)))
				return false;
		}

		/* find the lower sideband info in the sideband array */
		for (idx = 0; idx < num_ch20_entries; idx++) {
			if (chan20_info[idx].sb == LOWER_20_SB(channel))
				upper_sideband = chan20_info[idx].adj_sbs;
		}
		/* check that the lower sideband allows an upper sideband */
		if ((upper_sideband & (CH_UPPER_SB | CH_EWA_VALID)) ==
		    (CH_UPPER_SB | CH_EWA_VALID))
			return true;
		return false;
	}
#endif				/* 40 MHZ */

	return false;
}
Ejemplo n.º 9
0
/*
 * Validate the chanspec for this locale, for 40MHZ we need to also
 * check that the sidebands are valid 20MZH channels in this locale
 * and they are also a legal HT combination
 */
static bool
brcms_c_valid_chanspec_ext(struct brcms_cm_info *wlc_cm, u16 chspec,
			   bool dualband)
{
	struct brcms_c_info *wlc = wlc_cm->wlc;
	u8 channel = CHSPEC_CHANNEL(chspec);

	/* check the chanspec */
	if (brcms_c_chspec_malformed(chspec)) {
		wiphy_err(wlc->wiphy, "wl%d: malformed chanspec 0x%x\n",
			wlc->pub->unit, chspec);
		return false;
	}

	if (CHANNEL_BANDUNIT(wlc_cm->wlc, channel) !=
	    chspec_bandunit(chspec))
		return false;

	/* Check a 20Mhz channel */
	if (CHSPEC_IS20(chspec)) {
		if (dualband)
			return brcms_c_valid_channel20_db(wlc_cm->wlc->cmi,
							  channel);
		else
			return brcms_c_valid_channel20(wlc_cm->wlc->cmi,
						       channel);
	}
#ifdef SUPPORT_40MHZ
	/*
	 * We know we are now checking a 40MHZ channel, so we should
	 * only be here for NPHYS
	 */
	if (BRCMS_ISNPHY(wlc->band) || BRCMS_ISSSLPNPHY(wlc->band)) {
		u8 upper_sideband = 0, idx;
		u8 num_ch20_entries =
		    sizeof(chan20_info) / sizeof(struct chan20_info);

		if (!VALID_40CHANSPEC_IN_BAND(wlc, chspec_bandunit(chspec)))
			return false;

		if (dualband) {
			if (!brcms_c_valid_channel20_db(wlc->cmi,
							lower_20_sb(channel)) ||
			    !brcms_c_valid_channel20_db(wlc->cmi,
							upper_20_sb(channel)))
				return false;
		} else {
			if (!brcms_c_valid_channel20(wlc->cmi,
						     lower_20_sb(channel)) ||
			    !brcms_c_valid_channel20(wlc->cmi,
						     upper_20_sb(channel)))
				return false;
		}

		/* find the lower sideband info in the sideband array */
		for (idx = 0; idx < num_ch20_entries; idx++) {
			if (chan20_info[idx].sb == lower_20_sb(channel))
				upper_sideband = chan20_info[idx].adj_sbs;
		}
		/* check that the lower sideband allows an upper sideband */
		if ((upper_sideband & (CH_UPPER_SB | CH_EWA_VALID)) ==
		    (CH_UPPER_SB | CH_EWA_VALID))
			return true;
		return false;
	}
#endif				/* 40 MHZ */

	return false;
}