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 2007, Broadcom Corporation 7 * All Rights Reserved. 8 * 9 * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Broadcom Corporation; 10 * the contents of this file may not be disclosed to third parties, copied 11 * or duplicated in any form, in whole or in part, without the prior 12 * written permission of Broadcom Corporation. 13 * $Id: bcmwifi.c,v 1.1.1.1 2008/10/15 03:31:34 james26_jang Exp $ 14 */ 15 16#include <typedefs.h> 17 18#ifdef BCMDRIVER 19#include <osl.h> 20#include <bcmutils.h> 21#define strtoul(nptr, endptr, base) bcm_strtoul((nptr), (endptr), (base)) 22#define tolower(c) (bcm_isupper((c)) ? ((c) + 'a' - 'A') : (c)) 23#else 24#include <stdio.h> 25#include <stdlib.h> 26#include <ctype.h> 27#endif /* BCMDRIVER */ 28#include <bcmwifi.h> 29 30/* Chanspec ASCII representation: 31 * <channel><band><bandwidth><ctl-sideband> 32 * digit [AB] N [UL] 33 * 34 * <channel>: channel number of the 10MHz or 20MHz channel, 35 * or control sideband channel of 40MHz channel. 36 * <band>: A for 5GHz, B for 2.4GHz 37 * <bandwidth>: N for 10MHz, nothing for 20MHz or 40MHz 38 * (ctl-sideband spec implies 40MHz) 39 * <ctl-sideband>: U for upper, L for lower 40 * 41 * <band> may be omitted on input, and will be assumed to be 42 * 2.4GHz if channel number <= 14. 43 * 44 * Examples: ... 45 */ 46/* given a chanspec and a string buffer, format the chanspec as a 47 * string, and return the original pointer a. On error, return's NULL 48 */ 49char * 50wf_chspec_ntoa(chanspec_t chspec, char *buf) 51{ 52 const char *band, *bw, *sb; 53 uint channel; 54 55 bw = ""; 56 sb = ""; 57 channel = CHSPEC_CHANNEL(chspec); 58 band = (CHSPEC_IS2G(chspec)) ? "b" : "a"; 59 if (CHSPEC_IS40(chspec)) { 60 if (CHSPEC_SB_UPPER(chspec)) { 61 sb = "u"; 62 channel += CH_10MHZ_APART; 63 } else { 64 sb = "l"; 65 channel -= CH_10MHZ_APART; 66 } 67 } else if (CHSPEC_IS10(chspec)) { 68 bw = "n"; 69 } 70 71 sprintf(buf, "%d%s%s%s", channel, band, bw, sb); 72 return (buf); 73} 74 75/* given a chanspec string, convert to a chanspec. 76 * On error, return 0 77 */ 78 79chanspec_t 80wf_chspec_aton(char *a) 81{ 82 char *endp; 83 uint channel, band, bw, ctl_sb; 84 bool band_set = FALSE, bw_set = FALSE, ctl_sb_set = FALSE; 85 int error = 0; 86 87 channel = strtoul(a, &endp, 10); 88 if (endp == a) 89 return 0; 90 91 if (channel > MAXCHANNEL) 92 return 0; 93 94 band = ((channel <= WLC_MAX_2G_CHANNEL) ? WL_CHANSPEC_BAND_2G : WL_CHANSPEC_BAND_5G); 95 bw = WL_CHANSPEC_BW_20; 96 ctl_sb = WL_CHANSPEC_CTL_SB_NONE; 97 98 a = endp; 99 while (*a != 0 && error != -1) { 100 switch (tolower((int)*a)) { 101 case 'a': 102 case 'b': 103 if (!band_set) { 104 band = (tolower((int)*a) == 'a') ? 105 WL_CHANSPEC_BAND_5G : WL_CHANSPEC_BAND_2G; 106 band_set = TRUE; 107 } else { 108 error = -1; 109 } 110 break; 111 case 'n': 112 if (!bw_set) { 113 bw = WL_CHANSPEC_BW_10; 114 bw_set = TRUE; 115 } else { 116 error = -1; 117 } 118 break; 119 case 'l': 120 case 'u': 121 if (!ctl_sb_set && !bw_set) { 122 ctl_sb = (tolower((int)*a) == 'l') ? 123 WL_CHANSPEC_CTL_SB_LOWER : WL_CHANSPEC_CTL_SB_UPPER; 124 ctl_sb_set = TRUE; 125 if (ctl_sb == WL_CHANSPEC_CTL_SB_LOWER) 126 channel = UPPER_20_SB(channel); 127 else 128 channel = LOWER_20_SB(channel); 129 bw = WL_CHANSPEC_BW_40; 130 bw_set = TRUE; 131 } else if (bw_set) { 132 error = -1; 133 } else { 134 error = -1; 135 } 136 break; 137 default: 138 error = -1; 139 break; 140 } 141 a++; 142 } 143 144 if (bw_set && (bw == WL_CHANSPEC_BW_40) && !ctl_sb_set) 145 error = -1; 146 147 if (ctl_sb_set && !bw_set) 148 error = -1; 149 150 if (!error) 151 return ((channel | band | bw | ctl_sb)); 152 153 return 0; 154} 155 156#ifdef CONFIG_NET_RADIO 157/* channel info structure */ 158typedef struct { 159 uint chan; /* channel number */ 160 uint freq; /* in Mhz */ 161} chan_info_t; 162 163static chan_info_t chan_info[] = { 164 /* B channels */ 165 { 1, 2412}, 166 { 2, 2417}, 167 { 3, 2422}, 168 { 4, 2427}, 169 { 5, 2432}, 170 { 6, 2437}, 171 { 7, 2442}, 172 { 8, 2447}, 173 { 9, 2452}, 174 { 10, 2457}, 175 { 11, 2462}, 176 { 12, 2467}, 177 { 13, 2472}, 178 { 14, 2484}, 179 180 /* A channels */ 181 /* 11a usa low */ 182 { 36, 5180}, 183 { 40, 5200}, 184 { 44, 5220}, 185 { 48, 5240}, 186 { 52, 5260}, 187 { 56, 5280}, 188 { 60, 5300}, 189 { 64, 5320}, 190 191 /* 11a Europe */ 192 { 100, 5500}, 193 { 104, 5520}, 194 { 108, 5540}, 195 { 112, 5560}, 196 { 116, 5580}, 197 { 120, 5600}, 198 { 124, 5620}, 199 { 128, 5640}, 200 { 132, 5660}, 201 { 136, 5680}, 202 { 140, 5700}, 203 204 /* 11a usa high */ 205 { 149, 5745}, 206 { 153, 5765}, 207 { 157, 5785}, 208 { 161, 5805}, 209 210 /* 11a japan */ 211 { 184, 4920}, 212 { 188, 4940}, 213 { 192, 4960}, 214 { 196, 4980}, 215 { 200, 5000}, 216 { 204, 5020}, 217 { 208, 5040}, 218 { 212, 5060}, 219 { 216, 5080} 220}; 221 222 223uint 224freq2channel(uint freq) 225{ 226 int i; 227 228 for (i = 0; i < (int)ARRAYSIZE(chan_info); i++) { 229 if (chan_info[i].freq == freq) 230 return (chan_info[i].chan); 231 } 232 return (0); 233} 234 235uint 236channel2freq(uint channel) 237{ 238 uint i; 239 240 for (i = 0; i < ARRAYSIZE(chan_info); i++) 241 if (chan_info[i].chan == channel) 242 return (chan_info[i].freq); 243 return (0); 244} 245#endif /* CONFIG_NET_RADIO */ 246