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) 2010, Broadcom Corporation. All Rights Reserved.
8 * Permission to use, copy, modify, and/or distribute this software for any
9 * purpose with or without fee is hereby granted, provided that the above
10 * copyright notice and this permission notice appear in all copies.
12 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
13 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
14 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
15 * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
16 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
17 * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
18 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
19 * $Id: bcm_app_utils.c,v 1.5 2009-12-03 23:24:26 Exp $
27 #define strtoul(nptr, endptr, base) bcm_strtoul((nptr), (endptr), (base))
28 #define tolower(c) (bcm_isupper((c)) ? ((c) + 'a' - 'A') : (c))
36 #endif /* BCMDRIVER */
39 #if defined(WIN32) && (defined(BCMDLL) || defined(WLMDLL))
40 #include <bcmstdlib.h> /* For wl/exe/GNUmakefile.brcm_wlu and GNUmakefile.wlm_dll */
46 cca_congest_channel_req_t
*
47 cca_per_chan_summary(cca_congest_channel_req_t
*input
, cca_congest_channel_req_t
*avg
,
51 cca_analyze(cca_congest_channel_req_t
*input
[], int num_chans
, uint flags
, chanspec_t
*answer
);
53 /* Take an array of measurments representing a single channel over time and return
54 a summary. Currently implemented as a simple average but could easily evolve
55 into more cpomplex alogrithms.
57 cca_congest_channel_req_t
*
58 cca_per_chan_summary(cca_congest_channel_req_t
*input
, cca_congest_channel_req_t
*avg
, bool percent
)
64 totals
.congest_ibss
= 0;
65 totals
.congest_obss
= 0;
66 totals
.interference
= 0;
69 for (sec
= 0; sec
< input
->num_secs
; sec
++) {
70 if (input
->secs
[sec
].duration
) {
71 totals
.duration
+= input
->secs
[sec
].duration
;
72 totals
.congest_ibss
+= input
->secs
[sec
].congest_ibss
;
73 totals
.congest_obss
+= input
->secs
[sec
].congest_obss
;
74 totals
.interference
+= input
->secs
[sec
].interference
;
78 avg
->chanspec
= input
->chanspec
;
80 if (!avg
->num_secs
|| !totals
.duration
)
84 avg
->secs
[0].duration
= totals
.duration
/ avg
->num_secs
;
85 avg
->secs
[0].congest_ibss
= totals
.congest_ibss
* 100/totals
.duration
;
86 avg
->secs
[0].congest_obss
= totals
.congest_obss
* 100/totals
.duration
;
87 avg
->secs
[0].interference
= totals
.interference
* 100/totals
.duration
;
89 avg
->secs
[0].duration
= totals
.duration
/ avg
->num_secs
;
90 avg
->secs
[0].congest_ibss
= totals
.congest_ibss
/ avg
->num_secs
;
91 avg
->secs
[0].congest_obss
= totals
.congest_obss
/ avg
->num_secs
;
92 avg
->secs
[0].interference
= totals
.interference
/ avg
->num_secs
;
99 cca_info(uint8
*bitmap
, int num_bits
, int *left
, int *bit_pos
)
102 for (*left
= 0, i
= 0; i
< num_bits
; i
++) {
103 if (isset(bitmap
, i
)) {
111 spec_to_chan(chanspec_t chspec
)
113 switch (CHSPEC_CTL_SB(chspec
)) {
114 case WL_CHANSPEC_CTL_SB_NONE
:
115 return CHSPEC_CHANNEL(chspec
);
116 case WL_CHANSPEC_CTL_SB_UPPER
:
117 return UPPER_20_SB(CHSPEC_CHANNEL(chspec
));
118 case WL_CHANSPEC_CTL_SB_LOWER
:
119 return LOWER_20_SB(CHSPEC_CHANNEL(chspec
));
125 #define CCA_THRESH_MILLI 14
126 #define CCA_THRESH_INTERFERE 6
129 Take an array of measumrements representing summaries of different channels.
130 Return a recomended channel.
131 Interference is evil, get rid of that first.
132 Then hunt for lowest Other bss traffic.
133 Don't forget that channels with low duration times may not have accurate readings.
134 For the moment, do not overwrite input array.
137 cca_analyze(cca_congest_channel_req_t
*input
[], int num_chans
, uint flags
, chanspec_t
*answer
)
139 uint8 bitmap
[CEIL(MAX_CCA_CHANNELS
, NBBY
)]; /* 38 Max channels needs 5 bytes = 40 */
141 uint32 min_obss
= 1 << 30;
143 ASSERT(num_chans
< MAX_CCA_CHANNELS
);
144 for (i
= 0; i
< (int)sizeof(bitmap
); i
++)
147 /* Initially, all channels are up for consideration */
148 for (i
= 0; i
< num_chans
; i
++) {
149 if (input
[i
]->chanspec
)
152 cca_info(bitmap
, num_chans
, &left
, &i
);
154 return CCA_ERRNO_TOO_FEW
;
156 /* Filter for 2.4 GHz Band */
157 if (flags
& CCA_FLAG_2G_ONLY
) {
158 for (i
= 0; i
< num_chans
; i
++) {
159 if (!CHSPEC_IS2G(input
[i
]->chanspec
))
163 cca_info(bitmap
, num_chans
, &left
, &i
);
165 return CCA_ERRNO_BAND
;
167 /* Filter for 5 GHz Band */
168 if (flags
& CCA_FLAG_5G_ONLY
) {
169 for (i
= 0; i
< num_chans
; i
++) {
170 if (!CHSPEC_IS5G(input
[i
]->chanspec
))
174 cca_info(bitmap
, num_chans
, &left
, &i
);
176 return CCA_ERRNO_BAND
;
178 /* Filter for Duration */
179 if (!(flags
& CCA_FLAG_IGNORE_DURATION
)) {
180 for (i
= 0; i
< num_chans
; i
++) {
181 if (input
[i
]->secs
[0].duration
< CCA_THRESH_MILLI
)
185 cca_info(bitmap
, num_chans
, &left
, &i
);
187 return CCA_ERRNO_DURATION
;
189 /* Filter for 1 6 11 on 2.4 Band */
190 if (flags
& CCA_FLAGS_PREFER_1_6_11
) {
191 int tmp_channel
= spec_to_chan(input
[i
]->chanspec
);
192 int is2g
= CHSPEC_IS2G(input
[i
]->chanspec
);
193 for (i
= 0; i
< num_chans
; i
++) {
194 if (is2g
&& tmp_channel
!= 1 && tmp_channel
!= 6 && tmp_channel
!= 11)
198 cca_info(bitmap
, num_chans
, &left
, &i
);
200 return CCA_ERRNO_PREF_CHAN
;
202 /* Toss high interference interference */
203 if (!(flags
& CCA_FLAG_IGNORE_INTERFER
)) {
204 for (i
= 0; i
< num_chans
; i
++) {
205 if (input
[i
]->secs
[0].interference
> CCA_THRESH_INTERFERE
)
208 cca_info(bitmap
, num_chans
, &left
, &i
);
210 return CCA_ERRNO_INTERFER
;
213 /* Now find lowest obss */
215 for (i
= 0; i
< num_chans
; i
++) {
216 if (isset(bitmap
, i
) && input
[i
]->secs
[0].congest_obss
< min_obss
) {
218 min_obss
= input
[i
]->secs
[0].congest_obss
;
221 *answer
= input
[winner
]->chanspec
;