first commit
This commit is contained in:
236
external/cache/sources/wl/shared/bcm_app_utils.c
vendored
Normal file
236
external/cache/sources/wl/shared/bcm_app_utils.c
vendored
Normal file
@@ -0,0 +1,236 @@
|
||||
/*
|
||||
* 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 401759 2013-05-13 16:08:08Z sudhirbs $
|
||||
*/
|
||||
|
||||
#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))
|
||||
#elif defined(__IOPOS__)
|
||||
#include <bcmutils.h>
|
||||
#define strtoul(nptr, endptr, base) bcm_strtoul((nptr), (endptr), (base))
|
||||
#define tolower(c) (bcm_tolower((c)))
|
||||
#ifndef ASSERT
|
||||
#define ASSERT(exp)
|
||||
#endif
|
||||
#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;
|
||||
}
|
||||
Reference in New Issue
Block a user