Home | History | Annotate | Download | only in shared
      1 /*
      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.
      5  *
      6  * Copyright (C) 1999-2009, Broadcom Corporation
      7  *
      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:
     13  *
     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.
     21  *
     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: bcmwifi.c,v 1.18.24.2.4.1 2009/09/25 00:32:01 Exp $
     26  */
     27 
     28 
     29 #include <typedefs.h>
     30 
     31 #ifdef BCMDRIVER
     32 #include <osl.h>
     33 #include <bcmutils.h>
     34 #define strtoul(nptr, endptr, base) bcm_strtoul((nptr), (endptr), (base))
     35 #define tolower(c) (bcm_isupper((c)) ? ((c) + 'a' - 'A') : (c))
     36 #else
     37 #include <stdio.h>
     38 #include <stdlib.h>
     39 #include <ctype.h>
     40 #endif
     41 #include <bcmwifi.h>
     42 
     43 #if defined(WIN32) && (defined(BCMDLL) || defined(WLMDLL))
     44 #include <bcmstdlib.h>
     45 #endif
     46 
     47 
     48 
     49 
     50 
     51 char *
     52 wf_chspec_ntoa(chanspec_t chspec, char *buf)
     53 {
     54 	const char *band, *bw, *sb;
     55 	uint channel;
     56 
     57 	band = "";
     58 	bw = "";
     59 	sb = "";
     60 	channel = CHSPEC_CHANNEL(chspec);
     61 
     62 	if ((CHSPEC_IS2G(chspec) && channel > CH_MAX_2G_CHANNEL) ||
     63 	    (CHSPEC_IS5G(chspec) && channel <= CH_MAX_2G_CHANNEL))
     64 		band = (CHSPEC_IS2G(chspec)) ? "b" : "a";
     65 	if (CHSPEC_IS40(chspec)) {
     66 		if (CHSPEC_SB_UPPER(chspec)) {
     67 			sb = "u";
     68 			channel += CH_10MHZ_APART;
     69 		} else {
     70 			sb = "l";
     71 			channel -= CH_10MHZ_APART;
     72 		}
     73 	} else if (CHSPEC_IS10(chspec)) {
     74 		bw = "n";
     75 	}
     76 
     77 
     78 	snprintf(buf, 6, "%d%s%s%s", channel, band, bw, sb);
     79 	return (buf);
     80 }
     81 
     82 
     83 chanspec_t
     84 wf_chspec_aton(char *a)
     85 {
     86 	char *endp = NULL;
     87 	uint channel, band, bw, ctl_sb;
     88 	char c;
     89 
     90 	channel = strtoul(a, &endp, 10);
     91 
     92 
     93 	if (endp == a)
     94 		return 0;
     95 
     96 	if (channel > MAXCHANNEL)
     97 		return 0;
     98 
     99 	band = ((channel <= CH_MAX_2G_CHANNEL) ? WL_CHANSPEC_BAND_2G : WL_CHANSPEC_BAND_5G);
    100 	bw = WL_CHANSPEC_BW_20;
    101 	ctl_sb = WL_CHANSPEC_CTL_SB_NONE;
    102 
    103 	a = endp;
    104 
    105 	c = tolower(a[0]);
    106 	if (c == '\0')
    107 		goto done;
    108 
    109 
    110 	if (c == 'a' || c == 'b') {
    111 		band = (c == 'a') ? WL_CHANSPEC_BAND_5G : WL_CHANSPEC_BAND_2G;
    112 		a++;
    113 		c = tolower(a[0]);
    114 		if (c == '\0')
    115 			goto done;
    116 	}
    117 
    118 
    119 	if (c == 'n') {
    120 		bw = WL_CHANSPEC_BW_10;
    121 	} else if (c == 'l') {
    122 		bw = WL_CHANSPEC_BW_40;
    123 		ctl_sb = WL_CHANSPEC_CTL_SB_LOWER;
    124 
    125 		if (channel <= (MAXCHANNEL - CH_20MHZ_APART))
    126 			channel += CH_10MHZ_APART;
    127 		else
    128 			return 0;
    129 	} else if (c == 'u') {
    130 		bw = WL_CHANSPEC_BW_40;
    131 		ctl_sb = WL_CHANSPEC_CTL_SB_UPPER;
    132 
    133 		if (channel > CH_20MHZ_APART)
    134 			channel -= CH_10MHZ_APART;
    135 		else
    136 			return 0;
    137 	} else {
    138 		return 0;
    139 	}
    140 
    141 done:
    142 	return (channel | band | bw | ctl_sb);
    143 }
    144 
    145 
    146 int
    147 wf_mhz2channel(uint freq, uint start_factor)
    148 {
    149 	int ch = -1;
    150 	uint base;
    151 	int offset;
    152 
    153 
    154 	if (start_factor == 0) {
    155 		if (freq >= 2400 && freq <= 2500)
    156 			start_factor = WF_CHAN_FACTOR_2_4_G;
    157 		else if (freq >= 5000 && freq <= 6000)
    158 			start_factor = WF_CHAN_FACTOR_5_G;
    159 	}
    160 
    161 	if (freq == 2484 && start_factor == WF_CHAN_FACTOR_2_4_G)
    162 		return 14;
    163 
    164 	base = start_factor / 2;
    165 
    166 
    167 	if ((freq < base) || (freq > base + 1000))
    168 		return -1;
    169 
    170 	offset = freq - base;
    171 	ch = offset / 5;
    172 
    173 
    174 	if (offset != (ch * 5))
    175 		return -1;
    176 
    177 
    178 	if (start_factor == WF_CHAN_FACTOR_2_4_G && (ch < 1 || ch > 13))
    179 		return -1;
    180 
    181 	return ch;
    182 }
    183 
    184 
    185 int
    186 wf_channel2mhz(uint ch, uint start_factor)
    187 {
    188 	int freq;
    189 
    190 	if ((start_factor == WF_CHAN_FACTOR_2_4_G && (ch < 1 || ch > 14)) ||
    191 	    (ch <= 200))
    192 		freq = -1;
    193 	if ((start_factor == WF_CHAN_FACTOR_2_4_G) && (ch == 14))
    194 		freq = 2484;
    195 	else
    196 		freq = ch * 5 + start_factor / 2;
    197 
    198 	return freq;
    199 }
    200