2 * Misc utility routines used by kernel or app-level.
3 * Contents are wifi-specific, used by any kernel or app-level
4 * software that might want wifi things as it grows.
6 * Copyright (C) 1999-2011, Broadcom Corporation
8 * Unless you and Broadcom execute a separate written software license
9 * agreement governing use of this software, this software is licensed to you
10 * under the terms of the GNU General Public License version 2 (the "GPL"),
11 * available at http://www.broadcom.com/licenses/GPLv2.php, with the
12 * following added to such license:
14 * As a special exception, the copyright holders of this software give you
15 * permission to link this software with independent modules, and to copy and
16 * distribute the resulting executable under terms of your choice, provided that
17 * you also meet, for each linked independent module, the terms and conditions of
18 * the license of that module. An independent module is a module which is not
19 * derived from this software. The special exception does not apply to any
20 * modifications of the software.
22 * Notwithstanding the above, under no circumstances may you combine this
23 * software in any way with any other Broadcom software provided under a license
24 * other than the GPL, without Broadcom's express prior written consent.
25 * $Id: bcm_app_utils.c,v 1.5 2009-12-03 23:24:26 $
33 #define strtoul(nptr, endptr, base) bcm_strtoul((nptr), (endptr), (base))
34 #define tolower(c) (bcm_isupper((c)) ? ((c) + 'a' - 'A') : (c))
42 #endif /* BCMDRIVER */
45 #if defined(WIN32) && (defined(BCMDLL) || defined(WLMDLL))
46 #include <bcmstdlib.h> /* For wl/exe/GNUmakefile.brcm_wlu and GNUmakefile.wlm_dll */
52 cca_congest_channel_req_t *
53 cca_per_chan_summary(cca_congest_channel_req_t *input, cca_congest_channel_req_t *avg,
57 cca_analyze(cca_congest_channel_req_t *input[], int num_chans, uint flags, chanspec_t *answer);
59 /* Take an array of measurments representing a single channel over time and return
60 a summary. Currently implemented as a simple average but could easily evolve
61 into more cpomplex alogrithms.
63 cca_congest_channel_req_t *
64 cca_per_chan_summary(cca_congest_channel_req_t *input, cca_congest_channel_req_t *avg, bool percent)
70 totals.congest_ibss = 0;
71 totals.congest_obss = 0;
72 totals.interference = 0;
75 for (sec = 0; sec < input->num_secs; sec++) {
76 if (input->secs[sec].duration) {
77 totals.duration += input->secs[sec].duration;
78 totals.congest_ibss += input->secs[sec].congest_ibss;
79 totals.congest_obss += input->secs[sec].congest_obss;
80 totals.interference += input->secs[sec].interference;
84 avg->chanspec = input->chanspec;
86 if (!avg->num_secs || !totals.duration)
90 avg->secs[0].duration = totals.duration / avg->num_secs;
91 avg->secs[0].congest_ibss = totals.congest_ibss * 100/totals.duration;
92 avg->secs[0].congest_obss = totals.congest_obss * 100/totals.duration;
93 avg->secs[0].interference = totals.interference * 100/totals.duration;
95 avg->secs[0].duration = totals.duration / avg->num_secs;
96 avg->secs[0].congest_ibss = totals.congest_ibss / avg->num_secs;
97 avg->secs[0].congest_obss = totals.congest_obss / avg->num_secs;
98 avg->secs[0].interference = totals.interference / avg->num_secs;
105 cca_info(uint8 *bitmap, int num_bits, int *left, int *bit_pos)
108 for (*left = 0, i = 0; i < num_bits; i++) {
109 if (isset(bitmap, i)) {
117 spec_to_chan(chanspec_t chspec)
119 switch (CHSPEC_CTL_SB(chspec)) {
120 case WL_CHANSPEC_CTL_SB_NONE:
121 return CHSPEC_CHANNEL(chspec);
122 case WL_CHANSPEC_CTL_SB_UPPER:
123 return UPPER_20_SB(CHSPEC_CHANNEL(chspec));
124 case WL_CHANSPEC_CTL_SB_LOWER:
125 return LOWER_20_SB(CHSPEC_CHANNEL(chspec));
131 #define CCA_THRESH_MILLI 14
132 #define CCA_THRESH_INTERFERE 6
135 Take an array of measumrements representing summaries of different channels.
136 Return a recomended channel.
137 Interference is evil, get rid of that first.
138 Then hunt for lowest Other bss traffic.
139 Don't forget that channels with low duration times may not have accurate readings.
140 For the moment, do not overwrite input array.
143 cca_analyze(cca_congest_channel_req_t *input[], int num_chans, uint flags, chanspec_t *answer)
145 uint8 bitmap[CEIL(MAX_CCA_CHANNELS, NBBY)]; /* 38 Max channels needs 5 bytes = 40 */
147 uint32 min_obss = 1 << 30;
149 ASSERT(num_chans < MAX_CCA_CHANNELS);
150 for (i = 0; i < (int)sizeof(bitmap); i++)
153 /* Initially, all channels are up for consideration */
154 for (i = 0; i < num_chans; i++) {
155 if (input[i]->chanspec)
158 cca_info(bitmap, num_chans, &left, &i);
160 return CCA_ERRNO_TOO_FEW;
162 /* Filter for 2.4 GHz Band */
163 if (flags & CCA_FLAG_2G_ONLY) {
164 for (i = 0; i < num_chans; i++) {
165 if (!CHSPEC_IS2G(input[i]->chanspec))
169 cca_info(bitmap, num_chans, &left, &i);
171 return CCA_ERRNO_BAND;
173 /* Filter for 5 GHz Band */
174 if (flags & CCA_FLAG_5G_ONLY) {
175 for (i = 0; i < num_chans; i++) {
176 if (!CHSPEC_IS5G(input[i]->chanspec))
180 cca_info(bitmap, num_chans, &left, &i);
182 return CCA_ERRNO_BAND;
184 /* Filter for Duration */
185 if (!(flags & CCA_FLAG_IGNORE_DURATION)) {
186 for (i = 0; i < num_chans; i++) {
187 if (input[i]->secs[0].duration < CCA_THRESH_MILLI)
191 cca_info(bitmap, num_chans, &left, &i);
193 return CCA_ERRNO_DURATION;
195 /* Filter for 1 6 11 on 2.4 Band */
196 if (flags & CCA_FLAGS_PREFER_1_6_11) {
197 int tmp_channel = spec_to_chan(input[i]->chanspec);
198 int is2g = CHSPEC_IS2G(input[i]->chanspec);
199 for (i = 0; i < num_chans; i++) {
200 if (is2g && tmp_channel != 1 && tmp_channel != 6 && tmp_channel != 11)
204 cca_info(bitmap, num_chans, &left, &i);
206 return CCA_ERRNO_PREF_CHAN;
208 /* Toss high interference interference */
209 if (!(flags & CCA_FLAG_IGNORE_INTERFER)) {
210 for (i = 0; i < num_chans; i++) {
211 if (input[i]->secs[0].interference > CCA_THRESH_INTERFERE)
214 cca_info(bitmap, num_chans, &left, &i);
216 return CCA_ERRNO_INTERFER;
219 /* Now find lowest obss */
221 for (i = 0; i < num_chans; i++) {
222 if (isset(bitmap, i) && input[i]->secs[0].congest_obss < min_obss) {
224 min_obss = input[i]->secs[0].congest_obss;
227 *answer = input[winner]->chanspec;