/*
 * Misc utility routines used by kernel or app-level.
 * Contents are wifi-specific, used by any kernel or app-level
 * software that might want wifi things as it grows.
 *
 * $Copyright Open Broadcom Corporation$
 * $Id: bcm_app_utils.c 315295 2012-02-16 06:55:23Z $
 */

#include <typedefs.h>

#ifdef BCMDRIVER
#include <osl.h>
#include <bcmutils.h>
#define strtoul(nptr, endptr, base) bcm_strtoul((nptr), (endptr), (base))
#define tolower(c) (bcm_isupper((c)) ? ((c) + 'a' - 'A') : (c))
#else /* BCMDRIVER */
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#ifndef ASSERT
#define ASSERT(exp)
#endif
#endif /* BCMDRIVER */
#include <bcmwifi_channels.h>

#if defined(WIN32) && (defined(BCMDLL) || defined(WLMDLL))
#include <bcmstdlib.h> 	/* For wl/exe/GNUmakefile.brcm_wlu and GNUmakefile.wlm_dll */
#endif

#include <bcmutils.h>
#include <wlioctl.h>

cca_congest_channel_req_t *
cca_per_chan_summary(cca_congest_channel_req_t *input, cca_congest_channel_req_t *avg,
	bool percent);

int
cca_analyze(cca_congest_channel_req_t *input[], int num_chans, uint flags, chanspec_t *answer);

/* 	Take an array of measurments representing a single channel over time and return
	a summary. Currently implemented as a simple average but could easily evolve
	into more cpomplex alogrithms.
*/
cca_congest_channel_req_t *
cca_per_chan_summary(cca_congest_channel_req_t *input, cca_congest_channel_req_t *avg, bool percent)
{
	int sec;
	cca_congest_t totals;

	totals.duration  = 0;
	totals.congest_ibss  = 0;
	totals.congest_obss  = 0;
	totals.interference  = 0;
	avg->num_secs = 0;

	for (sec = 0; sec < input->num_secs; sec++) {
		if (input->secs[sec].duration) {
			totals.duration += input->secs[sec].duration;
			totals.congest_ibss += input->secs[sec].congest_ibss;
			totals.congest_obss += input->secs[sec].congest_obss;
			totals.interference += input->secs[sec].interference;
			avg->num_secs++;
		}
	}
	avg->chanspec = input->chanspec;

	if (!avg->num_secs || !totals.duration)
		return (avg);

	if (percent) {
		avg->secs[0].duration = totals.duration / avg->num_secs;
		avg->secs[0].congest_ibss = totals.congest_ibss * 100/totals.duration;
		avg->secs[0].congest_obss = totals.congest_obss * 100/totals.duration;
		avg->secs[0].interference = totals.interference * 100/totals.duration;
	} else {
		avg->secs[0].duration = totals.duration / avg->num_secs;
		avg->secs[0].congest_ibss = totals.congest_ibss / avg->num_secs;
		avg->secs[0].congest_obss = totals.congest_obss / avg->num_secs;
		avg->secs[0].interference = totals.interference / avg->num_secs;
	}

	return (avg);
}

static void
cca_info(uint8 *bitmap, int num_bits, int *left, int *bit_pos)
{
	int i;
	for (*left = 0, i = 0; i < num_bits; i++) {
		if (isset(bitmap, i)) {
			(*left)++;
			*bit_pos = i;
		}
	}
}

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;
	}
}

#define CCA_THRESH_MILLI	14
#define CCA_THRESH_INTERFERE	6

/*
	Take an array of measumrements representing summaries of different channels.
	Return a recomended channel.
	Interference is evil, get rid of that first.
	Then hunt for lowest Other bss traffic.
	Don't forget that channels with low duration times may not have accurate readings.
	For the moment, do not overwrite input array.
*/
int
cca_analyze(cca_congest_channel_req_t *input[], int num_chans, uint flags, chanspec_t *answer)
{
	uint8 bitmap[CEIL(MAX_CCA_CHANNELS, NBBY)];	/* 38 Max channels needs 5 bytes  = 40 */
	int i, left, winner;
	uint32 min_obss = 1 << 30;

	ASSERT(num_chans < MAX_CCA_CHANNELS);
	for (i = 0; i < (int)sizeof(bitmap); i++)
		bitmap[i] = 0;

	/* Initially, all channels are up for consideration */
	for (i = 0; i < num_chans; i++) {
		if (input[i]->chanspec)
			setbit(bitmap, i);
	}
	cca_info(bitmap, num_chans, &left, &i);
	if (!left)
		return CCA_ERRNO_TOO_FEW;

	/* Filter for 2.4 GHz Band */
	if (flags & CCA_FLAG_2G_ONLY) {
		for (i = 0; i < num_chans; i++) {
			if (!CHSPEC_IS2G(input[i]->chanspec))
				clrbit(bitmap, i);
		}
	}
	cca_info(bitmap, num_chans, &left, &i);
	if (!left)
		return CCA_ERRNO_BAND;

	/* Filter for 5 GHz Band */
	if (flags & CCA_FLAG_5G_ONLY) {
		for (i = 0; i < num_chans; i++) {
			if (!CHSPEC_IS5G(input[i]->chanspec))
				clrbit(bitmap, i);
		}
	}
	cca_info(bitmap, num_chans, &left, &i);
	if (!left)
		return CCA_ERRNO_BAND;

	/* Filter for Duration */
	if (!(flags & CCA_FLAG_IGNORE_DURATION)) {
		for (i = 0; i < num_chans; i++) {
			if (input[i]->secs[0].duration < CCA_THRESH_MILLI)
				clrbit(bitmap, i);
		}
	}
	cca_info(bitmap, num_chans, &left, &i);
	if (!left)
		return CCA_ERRNO_DURATION;

	/* Filter for 1 6 11 on 2.4 Band */
	if (flags &  CCA_FLAGS_PREFER_1_6_11) {
		int tmp_channel = spec_to_chan(input[i]->chanspec);
		int is2g = CHSPEC_IS2G(input[i]->chanspec);
		for (i = 0; i < num_chans; i++) {
			if (is2g && tmp_channel != 1 && tmp_channel != 6 && tmp_channel != 11)
				clrbit(bitmap, i);
		}
	}
	cca_info(bitmap, num_chans, &left, &i);
	if (!left)
		return CCA_ERRNO_PREF_CHAN;

	/* Toss high interference interference */
	if (!(flags & CCA_FLAG_IGNORE_INTERFER)) {
		for (i = 0; i < num_chans; i++) {
			if (input[i]->secs[0].interference > CCA_THRESH_INTERFERE)
				clrbit(bitmap, i);
		}
		cca_info(bitmap, num_chans, &left, &i);
		if (!left)
			return CCA_ERRNO_INTERFER;
	}

	/* Now find lowest obss */
	winner = 0;
	for (i = 0; i < num_chans; i++) {
		if (isset(bitmap, i) && input[i]->secs[0].congest_obss < min_obss) {
			winner = i;
			min_obss = input[i]->secs[0].congest_obss;
		}
	}
	*answer = input[winner]->chanspec;

	return 0;
}
