From 297b60346df8beafee954a0fd7c2d64f33f3b9bc Mon Sep 17 00:00:00 2001
From: hc <hc@nodka.com>
Date: Sat, 11 May 2024 01:44:05 +0000
Subject: [PATCH] rtl8211F_led_control
---
kernel/drivers/net/wireless/rockchip_wlan/cywdhd/bcmdhd/bcmwifi_channels.c | 733 ++++++++++++++++++++++++++++++++++++++------------------
1 files changed, 498 insertions(+), 235 deletions(-)
diff --git a/kernel/drivers/net/wireless/rockchip_wlan/cywdhd/bcmdhd/bcmwifi_channels.c b/kernel/drivers/net/wireless/rockchip_wlan/cywdhd/bcmdhd/bcmwifi_channels.c
index 3a138ed..18747aa 100644
--- a/kernel/drivers/net/wireless/rockchip_wlan/cywdhd/bcmdhd/bcmwifi_channels.c
+++ b/kernel/drivers/net/wireless/rockchip_wlan/cywdhd/bcmdhd/bcmwifi_channels.c
@@ -1,17 +1,18 @@
-/* SPDX-License-Identifier: GPL-2.0 */
/*
* 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 (C) 1999-2019, Broadcom Corporation
- *
+ * Portions of this code are copyright (c) 2022 Cypress Semiconductor Corporation
+ *
+ * Copyright (C) 1999-2017, Broadcom Corporation
+ *
* Unless you and Broadcom execute a separate written software license
* agreement governing use of this software, this software is licensed to you
* under the terms of the GNU General Public License version 2 (the "GPL"),
* available at http://www.broadcom.com/licenses/GPLv2.php, with the
* following added to such license:
- *
+ *
* As a special exception, the copyright holders of this software give you
* permission to link this software with independent modules, and to copy and
* distribute the resulting executable under terms of your choice, provided that
@@ -19,7 +20,7 @@
* the license of that module. An independent module is a module which is not
* derived from this software. The special exception does not apply to any
* modifications of the software.
- *
+ *
* Notwithstanding the above, under no circumstances may you combine this
* software in any way with any other Broadcom software provided under a license
* other than the GPL, without Broadcom's express prior written consent.
@@ -27,7 +28,7 @@
*
* <<Broadcom-WL-IPTag/Open:>>
*
- * $Id: bcmwifi_channels.c 309193 2012-01-19 00:03:57Z $
+ * $Id: bcmwifi_channels.c 695288 2017-04-19 17:20:39Z $
*/
#include <bcm_cfg.h>
@@ -44,19 +45,21 @@
#include <ctype.h>
#ifndef ASSERT
#define ASSERT(exp)
-#endif
+#endif // 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
+#endif // endif
-/* Definitions for D11AC capable Chanspec type */
+#include <802.11.h>
-/* Chanspec ASCII representation with 802.11ac capability:
- * [<band> 'g'] <channel> ['/'<bandwidth> [<ctl-sideband>]['/'<1st80channel>'-'<2nd80channel>]]
+/* Definitions for D11AC capable (80MHz+) Chanspec type */
+
+/* Chanspec ASCII representation:
+ * [<band> 'g'] <channel> ['/'<bandwidth> [<primary-sideband>]['/'<1st80channel>'-'<2nd80channel>]]
*
* <band>:
* (optional) 2, 3, 4, 5 for 2.4GHz, 3GHz, 4GHz, and 5GHz respectively.
@@ -82,18 +85,18 @@
* <1st80Channel>:
* <2nd80Channel>:
* Required for 80+80, otherwise not allowed.
- * Specifies the center channel of the first and second 80MHz band.
+ * Specifies the center channel of the primary and secondary 80MHz band.
*
* In its simplest form, it is a 20MHz channel number, with the implied band
* of 2.4GHz if channel number <= 14, and 5GHz otherwise.
*
* To allow for backward compatibility with scripts, the old form for
- * 40MHz channels is also allowed: <channel><ctl-sideband>
+ * 40MHz channels is also allowed: <channel><primary-sideband>
*
* <channel>:
* primary channel of 40MHz, channel <= 14 is 2GHz, otherwise 5GHz
- * <ctl-sideband>:
- * "U" for upper, "L" for lower (or lower case "u" "l")
+ * <primary-sideband>:
+ * "U" for upper, "L" for lower (or lower case "u" "l")
*
* 5 GHz Examples:
* Chanspec BW Center Ch Channel Range Primary Ch
@@ -130,11 +133,7 @@
"80",
"160",
"80+80",
-#ifdef WL11ULB
- "2.5"
-#else /* WL11ULB */
"na"
-#endif /* WL11ULB */
};
static const uint8 wf_chspec_bw_mhz[] =
@@ -145,13 +144,13 @@
/* 40MHz channels in 5GHz band */
static const uint8 wf_5g_40m_chans[] =
-{38, 46, 54, 62, 102, 110, 118, 126, 134, 142, 151, 159};
+{38, 46, 54, 62, 102, 110, 118, 126, 134, 142, 151, 159, 167, 175};
#define WF_NUM_5G_40M_CHANS \
(sizeof(wf_5g_40m_chans)/sizeof(uint8))
/* 80MHz channels in 5GHz band */
static const uint8 wf_5g_80m_chans[] =
-{42, 58, 106, 122, 138, 155};
+{42, 58, 106, 122, 138, 155, 171};
#define WF_NUM_5G_80M_CHANS \
(sizeof(wf_5g_80m_chans)/sizeof(uint8))
@@ -161,10 +160,82 @@
#define WF_NUM_5G_160M_CHANS \
(sizeof(wf_5g_160m_chans)/sizeof(uint8))
+/* Based on IEEE 802.11ax D6.1 */
+/* 40MHz channels in 6GHz band */
+static const uint8 wf_6g_40m_chans[] =
+{3, 11, 19, 27, 35, 43, 51, 59, 67, 75, 83, 91, 99,
+107, 115, 123, 131, 139, 147, 155, 163, 171, 179,
+187, 195, 203, 211, 219, 227};
+#define WF_NUM_6G_40M_CHANS \
+ (sizeof(wf_6g_40m_chans)/sizeof(uint8))
-/* convert bandwidth from chanspec to MHz */
-static uint
-bw_chspec_to_mhz(chanspec_t chspec)
+/* 80MHz channels in 6GHz band */
+static const uint8 wf_6g_80m_chans[] =
+{7, 23, 39, 55, 71, 87, 103, 119, 135, 151, 167, 183,
+199, 215};
+#define WF_NUM_6G_80M_CHANS \
+ (sizeof(wf_6g_80m_chans)/sizeof(uint8))
+
+/* 160MHz channels in 6GHz band */
+static const uint8 wf_6g_160m_chans[] =
+{15, 47, 79, 111, 143, 175, 207};
+#define WF_NUM_6G_160M_CHANS \
+ (sizeof(wf_6g_160m_chans)/sizeof(uint8))
+
+/* 6GHz PSC channels */
+uint8 wf_6g_psc_chans[] =
+{5, 21, 37, 53, 69, 85, 101, 117, 133, 149, 165, 181,
+197, 213, 229};
+#define WF_NUM_6G_PSC_CHANS \
+ (sizeof(wf_6g_psc_chans)/sizeof(uint8))
+
+/* opclass and channel information for US. Table E-1 */
+static const uint16 opclass_data[] = {
+ (WL_CHANSPEC_BAND_5G |((WL_CHANSPEC_BW_20)&WL_CHANSPEC_BW_MASK)),
+ (WL_CHANSPEC_BAND_5G |((WL_CHANSPEC_BW_20)&WL_CHANSPEC_BW_MASK)),
+ (WL_CHANSPEC_BAND_5G |((WL_CHANSPEC_BW_20)&WL_CHANSPEC_BW_MASK)),
+ (WL_CHANSPEC_BAND_5G |((WL_CHANSPEC_BW_20)&WL_CHANSPEC_BW_MASK)),
+ (WL_CHANSPEC_BAND_5G |((WL_CHANSPEC_BW_20)&WL_CHANSPEC_BW_MASK)),
+ (WL_CHANSPEC_BAND_5G |((WL_CHANSPEC_BW_5)&WL_CHANSPEC_BW_MASK)),
+ (WL_CHANSPEC_BAND_5G |((WL_CHANSPEC_BW_5)&WL_CHANSPEC_BW_MASK)),
+ (WL_CHANSPEC_BAND_5G |((WL_CHANSPEC_BW_10)&WL_CHANSPEC_BW_MASK)),
+ (WL_CHANSPEC_BAND_5G |((WL_CHANSPEC_BW_10)&WL_CHANSPEC_BW_MASK)),
+ (WL_CHANSPEC_BAND_5G |((WL_CHANSPEC_BW_20)&WL_CHANSPEC_BW_MASK)),
+ (WL_CHANSPEC_BAND_5G |((WL_CHANSPEC_BW_20)&WL_CHANSPEC_BW_MASK)),
+ (WL_CHANSPEC_BAND_2G |((WL_CHANSPEC_BW_20)&WL_CHANSPEC_BW_MASK)),
+ (WL_CHANSPEC_BAND_3G |((WL_CHANSPEC_BW_20)&WL_CHANSPEC_BW_MASK)),
+ (WL_CHANSPEC_BAND_3G |((WL_CHANSPEC_BW_10)&WL_CHANSPEC_BW_MASK)),
+ (WL_CHANSPEC_BAND_3G |((WL_CHANSPEC_BW_5)&WL_CHANSPEC_BW_MASK)),
+ (WL_CHANSPEC_BAND_5G |((WL_CHANSPEC_BW_5)&WL_CHANSPEC_BW_MASK)),
+ (WL_CHANSPEC_BAND_5G |((WL_CHANSPEC_BW_10)&WL_CHANSPEC_BW_MASK)),
+ (WL_CHANSPEC_BAND_5G |((WL_CHANSPEC_BW_20)&WL_CHANSPEC_BW_MASK)),
+ 0,
+ 0,
+ 0,
+ (WL_CHANSPEC_BAND_5G |((WL_CHANSPEC_BW_40)&WL_CHANSPEC_BW_MASK)|WL_CHANSPEC_CTL_SB_LOWER),
+ (WL_CHANSPEC_BAND_5G |((WL_CHANSPEC_BW_40)&WL_CHANSPEC_BW_MASK)|WL_CHANSPEC_CTL_SB_LOWER),
+ (WL_CHANSPEC_BAND_5G |((WL_CHANSPEC_BW_40)&WL_CHANSPEC_BW_MASK)|WL_CHANSPEC_CTL_SB_LOWER),
+ (WL_CHANSPEC_BAND_5G |((WL_CHANSPEC_BW_40)&WL_CHANSPEC_BW_MASK)|WL_CHANSPEC_CTL_SB_LOWER),
+ (WL_CHANSPEC_BAND_5G |((WL_CHANSPEC_BW_40)&WL_CHANSPEC_BW_MASK)|WL_CHANSPEC_CTL_SB_LOWER),
+ (WL_CHANSPEC_BAND_5G |((WL_CHANSPEC_BW_40)&WL_CHANSPEC_BW_MASK)|WL_CHANSPEC_CTL_SB_UPPER),
+ (WL_CHANSPEC_BAND_5G |((WL_CHANSPEC_BW_40)&WL_CHANSPEC_BW_MASK)|WL_CHANSPEC_CTL_SB_UPPER),
+ (WL_CHANSPEC_BAND_5G |((WL_CHANSPEC_BW_40)&WL_CHANSPEC_BW_MASK)|WL_CHANSPEC_CTL_SB_UPPER),
+ (WL_CHANSPEC_BAND_5G |((WL_CHANSPEC_BW_40)&WL_CHANSPEC_BW_MASK)|WL_CHANSPEC_CTL_SB_UPPER),
+ (WL_CHANSPEC_BAND_5G |((WL_CHANSPEC_BW_40)&WL_CHANSPEC_BW_MASK)|WL_CHANSPEC_CTL_SB_UPPER),
+ (WL_CHANSPEC_BAND_2G |((WL_CHANSPEC_BW_40)&WL_CHANSPEC_BW_MASK)|WL_CHANSPEC_CTL_SB_LOWER),
+ (WL_CHANSPEC_BAND_2G |((WL_CHANSPEC_BW_40)&WL_CHANSPEC_BW_MASK)|WL_CHANSPEC_CTL_SB_UPPER),
+};
+
+/**
+ * Return the chanspec bandwidth in MHz
+ * Bandwidth of 160 MHz will be returned for 80+80MHz chanspecs.
+ *
+ * @param chspec chanspec_t
+ *
+ * @return bandwidth of chspec in MHz units
+ */
+uint
+wf_bw_chspec_to_mhz(chanspec_t chspec)
{
uint bw;
@@ -194,34 +265,34 @@
return (uint8)(center_ch - center_chan_to_edge(bw));
}
-/* return side band number given center channel and control channel
+/* return side band number given center channel and primary20 channel
* return -1 on error
*/
static int
-channel_to_sb(uint center_ch, uint ctl_ch, uint bw)
+channel_to_sb(uint center_ch, uint primary_ch, uint bw)
{
uint lowest = channel_low_edge(center_ch, bw);
uint sb;
- if ((ctl_ch - lowest) % 4) {
- /* bad ctl channel, not mult 4 */
+ if ((primary_ch - lowest) % 4) {
+ /* bad primary channel, not mult 4 */
return -1;
}
- sb = ((ctl_ch - lowest) / 4);
+ sb = ((primary_ch - lowest) / 4);
/* sb must be a index to a 20MHz channel in range */
if (sb >= (bw / 20)) {
- /* ctl_ch must have been too high for the center_ch */
+ /* primary_ch must have been too high for the center_ch */
return -1;
}
- return sb;
+ return (int)sb;
}
-/* return control channel given center channel and side band */
+/* return primary20 channel given center channel and side band */
static uint8
-channel_to_ctl_chan(uint center_ch, uint bw, uint sb)
+channel_to_primary20_chan(uint center_ch, uint bw, uint sb)
{
return (uint8)(channel_low_edge(center_ch, bw) + sb * 4);
}
@@ -235,7 +306,7 @@
uint i;
for (i = 0; i < WF_NUM_5G_80M_CHANS; i ++) {
if (ch == wf_5g_80m_chans[i])
- return i;
+ return (int)i;
}
return -1;
@@ -262,7 +333,7 @@
wf_chspec_ntoa(chanspec_t chspec, char *buf)
{
const char *band;
- uint ctl_chan;
+ uint pri_chan;
if (wf_chspec_malformed(chspec))
return NULL;
@@ -274,32 +345,32 @@
(CHSPEC_IS5G(chspec) && CHSPEC_CHANNEL(chspec) <= CH_MAX_2G_CHANNEL))
band = (CHSPEC_IS2G(chspec)) ? "2g" : "5g";
- /* ctl channel */
- ctl_chan = wf_chspec_ctlchan(chspec);
+ /* primary20 channel */
+ pri_chan = wf_chspec_primary20_chan(chspec);
- /* bandwidth and ctl sideband */
+ /* bandwidth and primary20 sideband */
if (CHSPEC_IS20(chspec)) {
- snprintf(buf, CHANSPEC_STR_LEN, "%s%d", band, ctl_chan);
+ snprintf(buf, CHANSPEC_STR_LEN, "%s%d", band, pri_chan);
} else if (!CHSPEC_IS8080(chspec)) {
const char *bw;
const char *sb = "";
- bw = wf_chspec_bw_str[(chspec & WL_CHANSPEC_BW_MASK) >> WL_CHANSPEC_BW_SHIFT];
+ bw = wf_chspec_to_bw_str(chspec);
#ifdef CHANSPEC_NEW_40MHZ_FORMAT
- /* ctl sideband string if needed for 2g 40MHz */
+ /* primary20 sideband string if needed for 2g 40MHz */
if (CHSPEC_IS40(chspec) && CHSPEC_IS2G(chspec)) {
sb = CHSPEC_SB_UPPER(chspec) ? "u" : "l";
}
- snprintf(buf, CHANSPEC_STR_LEN, "%s%d/%s%s", band, ctl_chan, bw, sb);
+ snprintf(buf, CHANSPEC_STR_LEN, "%s%d/%s%s", band, pri_chan, bw, sb);
#else
- /* ctl sideband string instead of BW for 40MHz */
+ /* primary20 sideband string instead of BW for 40MHz */
if (CHSPEC_IS40(chspec)) {
sb = CHSPEC_SB_UPPER(chspec) ? "u" : "l";
- snprintf(buf, CHANSPEC_STR_LEN, "%s%d%s", band, ctl_chan, sb);
+ snprintf(buf, CHANSPEC_STR_LEN, "%s%d%s", band, pri_chan, sb);
} else {
- snprintf(buf, CHANSPEC_STR_LEN, "%s%d/%s", band, ctl_chan, bw);
+ snprintf(buf, CHANSPEC_STR_LEN, "%s%d/%s", band, pri_chan, bw);
}
#endif /* CHANSPEC_NEW_40MHZ_FORMAT */
@@ -313,7 +384,7 @@
chan2 = (chan2 < WF_NUM_5G_80M_CHANS) ? wf_5g_80m_chans[chan2] : 0;
/* Outputs a max of CHANSPEC_STR_LEN chars including '\0' */
- snprintf(buf, CHANSPEC_STR_LEN, "%d/80+80/%d-%d", ctl_chan, chan1, chan2);
+ snprintf(buf, CHANSPEC_STR_LEN, "%d/80+80/%d-%d", pri_chan, chan1, chan2);
}
return (buf);
@@ -339,14 +410,15 @@
}
/* given a chanspec string, convert to a chanspec.
+ * if bandwidth not specified in chanspec input string, then use default_bw as bandwidth.
* On error return 0
*/
chanspec_t
-wf_chspec_aton(const char *a)
+wf_chspec_aton_ex(const char *a, const uint default_bw)
{
chanspec_t chspec;
uint chspec_ch, chspec_band, bw, chspec_bw, chspec_sb;
- uint num, ctl_ch;
+ uint num, pri_ch;
uint ch1, ch2;
char c, sb_ul = '\0';
int i;
@@ -359,7 +431,7 @@
if (!read_uint(&a, &num))
return 0;
/* if we are looking at a 'g', then the first number was a band */
- c = tolower((int)a[0]);
+ c = tolower(a[0]);
if (c == 'g') {
a++; /* consume the char */
@@ -372,21 +444,22 @@
return 0;
/* read the channel number */
- if (!read_uint(&a, &ctl_ch))
+ if (!read_uint(&a, &pri_ch))
return 0;
- c = tolower((int)a[0]);
+ c = tolower(a[0]);
}
else {
/* first number is channel, use default for band */
- ctl_ch = num;
- chspec_band = ((ctl_ch <= CH_MAX_2G_CHANNEL) ?
+ pri_ch = num;
+ chspec_band = ((pri_ch <= CH_MAX_2G_CHANNEL) ?
WL_CHANSPEC_BAND_2G : WL_CHANSPEC_BAND_5G);
}
if (c == '\0') {
- /* default BW of 20MHz */
- chspec_bw = WL_CHANSPEC_BW_20;
+ /* bandwidth not specified in chanspec input string, so use default_bw bandwidth */
+ chspec_bw = default_bw;
+ bw = wf_bw_chspec_to_mhz(default_bw);
goto done_read;
}
@@ -408,9 +481,7 @@
return 0;
/* convert to chspec value */
- if (bw == 2) {
- chspec_bw = WL_CHANSPEC_BW_2P5;
- } else if (bw == 5) {
+ if (bw == 5) {
chspec_bw = WL_CHANSPEC_BW_5;
} else if (bw == 10) {
chspec_bw = WL_CHANSPEC_BW_10;
@@ -428,11 +499,10 @@
/* So far we have <band>g<chan>/<bw>
* Can now be followed by u/l if bw = 40,
- * or '+80' if bw = 80, to make '80+80' bw,
- * or '.5' if bw = 2.5 to make '2.5' bw .
+ * or '+80' if bw = 80, to make '80+80' bw.
*/
- c = tolower((int)a[0]);
+ c = (char)tolower((int)a[0]);
/* if we have a 2g/40 channel, we should have a l/u spec now */
if (chspec_band == WL_CHANSPEC_BAND_2G && bw == 40) {
@@ -474,19 +544,6 @@
/* read secondary 80MHz channel */
if (!read_uint(&a, &ch2))
return 0;
- } else if (c == '.') {
- /* 2.5 */
- /* must be looking at '.5'
- * check and consume this string.
- */
- chspec_bw = WL_CHANSPEC_BW_2P5;
-
- a ++; /* consume the char '.' */
-
- /* consume the '5' string */
- if (*a++ != '5') {
- return 0;
- }
}
done_read:
@@ -500,9 +557,9 @@
return 0;
/* Now have all the chanspec string parts read;
- * chspec_band, ctl_ch, chspec_bw, sb_ul, ch1, ch2.
+ * chspec_band, pri_ch, chspec_bw, sb_ul, ch1, ch2.
* chspec_band and chspec_bw are chanspec values.
- * Need to convert ctl_ch, sb_ul, and ch1,ch2 into
+ * Need to convert pri_ch, sb_ul, and ch1,ch2 into
* a center channel (or two) and sideband.
*/
@@ -511,23 +568,23 @@
*/
if (sb_ul != '\0') {
if (sb_ul == 'l') {
- chspec_ch = UPPER_20_SB(ctl_ch);
+ chspec_ch = UPPER_20_SB(pri_ch);
chspec_sb = WL_CHANSPEC_CTL_SB_LLL;
} else if (sb_ul == 'u') {
- chspec_ch = LOWER_20_SB(ctl_ch);
+ chspec_ch = LOWER_20_SB(pri_ch);
chspec_sb = WL_CHANSPEC_CTL_SB_LLU;
}
}
/* if the bw is 20, center and sideband are trivial */
- else if (BW_LE20(chspec_bw)) {
- chspec_ch = ctl_ch;
+ else if (chspec_bw == WL_CHANSPEC_BW_20) {
+ chspec_ch = pri_ch;
chspec_sb = WL_CHANSPEC_CTL_SB_NONE;
}
/* if the bw is 40/80/160, not 80+80, a single method
* can be used to to find the center and sideband
*/
else if (chspec_bw != WL_CHANSPEC_BW_8080) {
- /* figure out ctl sideband based on ctl channel and bandwidth */
+ /* figure out primary20 sideband based on primary20 channel and bandwidth */
const uint8 *center_ch = NULL;
int num_ch = 0;
int sb = -1;
@@ -546,10 +603,10 @@
}
for (i = 0; i < num_ch; i ++) {
- sb = channel_to_sb(center_ch[i], ctl_ch, bw);
+ sb = channel_to_sb(center_ch[i], pri_ch, bw);
if (sb >= 0) {
chspec_ch = center_ch[i];
- chspec_sb = sb << WL_CHANSPEC_CTL_SB_SHIFT;
+ chspec_sb = (uint)(sb << WL_CHANSPEC_CTL_SB_SHIFT);
break;
}
}
@@ -579,16 +636,16 @@
/* figure out primary 20 MHz sideband */
/* is the primary channel contained in the 1st 80MHz channel? */
- sb = channel_to_sb(ch1, ctl_ch, bw);
+ sb = channel_to_sb(ch1, pri_ch, bw);
if (sb < 0) {
- /* no match for primary channel 'ctl_ch' in segment0 80MHz channel */
+ /* no match for primary channel 'pri_ch' in segment0 80MHz channel */
return 0;
}
- chspec_sb = sb << WL_CHANSPEC_CTL_SB_SHIFT;
+ chspec_sb = (uint)(sb << WL_CHANSPEC_CTL_SB_SHIFT);
}
- chspec = (chspec_ch | chspec_band | chspec_bw | chspec_sb);
+ chspec = (chanspec_t)(chspec_ch | chspec_band | chspec_bw | chspec_sb);
if (wf_chspec_malformed(chspec))
return 0;
@@ -596,9 +653,18 @@
return chspec;
}
+/* given a chanspec string, convert to a chanspec.
+ * On error return 0
+ */
+chanspec_t
+wf_chspec_aton(const char *a)
+{
+ return wf_chspec_aton_ex(a, WL_CHANSPEC_BW_20);
+}
+
/*
* Verify the chanspec is using a legal set of parameters, i.e. that the
- * chanspec specified a band, bw, ctl_sb and channel and that the
+ * chanspec specified a band, bw, pri_sb and channel and that the
* combination could be legal given any set of circumstances.
* RETURNS: TRUE is the chanspec is malformed, false if it looks good.
*/
@@ -608,10 +674,9 @@
uint chspec_bw = CHSPEC_BW(chanspec);
uint chspec_ch = CHSPEC_CHANNEL(chanspec);
- /* must be 2G or 5G band */
if (CHSPEC_IS2G(chanspec)) {
- /* must be valid bandwidth */
- if (!BW_LE40(chspec_bw)) {
+ /* must be valid bandwidth and channel */
+ if (!BW_LE40(chspec_bw) || (chspec_ch > CH_MAX_2G_CHANNEL)) {
return TRUE;
}
} else if (CHSPEC_IS5G(chanspec)) {
@@ -624,7 +689,29 @@
if (ch1_id >= WF_NUM_5G_80M_CHANS || ch2_id >= WF_NUM_5G_80M_CHANS)
return TRUE;
- } else if (BW_LE160(chspec_bw)) {
+ } else if (chspec_bw == WL_CHANSPEC_BW_20 || chspec_bw == WL_CHANSPEC_BW_40 ||
+ chspec_bw == WL_CHANSPEC_BW_80 || chspec_bw == WL_CHANSPEC_BW_160) {
+
+ if (chspec_ch > MAXCHANNEL) {
+ return TRUE;
+ }
+ } else {
+ /* invalid bandwidth */
+ return TRUE;
+ }
+ } else if (CHSPEC_IS6G(chanspec)) {
+ if (chspec_bw == WL_CHANSPEC_BW_8080) {
+ uint ch1_id, ch2_id;
+
+ /* channel IDs in 80+80 must be in range */
+ ch1_id = CHSPEC_CHAN1(chanspec);
+ ch2_id = CHSPEC_CHAN2(chanspec);
+ if (ch1_id >= WF_NUM_6G_80M_CHANS || ch2_id >= WF_NUM_6G_80M_CHANS)
+ return TRUE;
+
+ } else if (chspec_bw == WL_CHANSPEC_BW_20 || chspec_bw == WL_CHANSPEC_BW_40 ||
+ chspec_bw == WL_CHANSPEC_BW_80 || chspec_bw == WL_CHANSPEC_BW_160) {
+
if (chspec_ch > MAXCHANNEL) {
return TRUE;
}
@@ -633,12 +720,13 @@
return TRUE;
}
} else {
- /* must be 2G or 5G band */
+
+ /* must be 2G, 5G or 6G band */
return TRUE;
}
/* side band needs to be consistent with bandwidth */
- if (BW_LE20(chspec_bw)) {
+ if (chspec_bw == WL_CHANSPEC_BW_20) {
if (CHSPEC_CTL_SB(chanspec) != WL_CHANSPEC_CTL_SB_LLL)
return TRUE;
} else if (chspec_bw == WL_CHANSPEC_BW_40) {
@@ -646,6 +734,9 @@
return TRUE;
} else if (chspec_bw == WL_CHANSPEC_BW_80 ||
chspec_bw == WL_CHANSPEC_BW_8080) {
+ /* both 80MHz and 80+80MHz use 80MHz side bands.
+ * 80+80 SB info is relative to the primary 80MHz sub-band.
+ */
if (CHSPEC_CTL_SB(chanspec) > WL_CHANSPEC_CTL_SB_LUU)
return TRUE;
}
@@ -670,7 +761,7 @@
if (CHSPEC_IS2G(chanspec)) {
/* must be valid bandwidth and channel range */
- if (BW_LE20(chspec_bw)) {
+ if (chspec_bw == WL_CHANSPEC_BW_20) {
if (chspec_ch >= 1 && chspec_ch <= 14)
return TRUE;
} else if (chspec_bw == WL_CHANSPEC_BW_40) {
@@ -692,7 +783,7 @@
const uint8 *center_ch;
uint num_ch, i;
- if (BW_LE40(chspec_bw)) {
+ if (chspec_bw == WL_CHANSPEC_BW_20 || chspec_bw == WL_CHANSPEC_BW_40) {
center_ch = wf_5g_40m_chans;
num_ch = WF_NUM_5G_40M_CHANS;
} else if (chspec_bw == WL_CHANSPEC_BW_80) {
@@ -707,7 +798,7 @@
}
/* check for a valid center channel */
- if (BW_LE20(chspec_bw)) {
+ if (chspec_bw == WL_CHANSPEC_BW_20) {
/* We don't have an array of legal 20MHz 5G channels, but they are
* each side of the legal 40MHz channels. Check the chanspec
* channel against either side of the 40MHz channels.
@@ -749,12 +840,66 @@
}
/*
- * This function returns the channel number that control traffic is being sent on, for 20MHz
- * channels this is just the channel number, for 40MHZ, 80MHz, 160MHz channels it is the 20MHZ
- * sideband depending on the chanspec selected
+ * This function returns TRUE if both the chanspec can co-exist in PHY.
+ * Addition to primary20 channel, the function checks for side band for 2g 40 channels
+ */
+bool
+wf_chspec_coexist(chanspec_t chspec1, chanspec_t chspec2)
+{
+ bool same_primary;
+
+ same_primary = (wf_chspec_primary20_chan(chspec1) == wf_chspec_primary20_chan(chspec2));
+
+ if (same_primary && CHSPEC_IS2G(chspec1)) {
+ if (CHSPEC_IS40(chspec1) && CHSPEC_IS40(chspec2)) {
+ return (CHSPEC_CTL_SB(chspec1) == CHSPEC_CTL_SB(chspec2));
+ }
+ }
+ return same_primary;
+}
+
+/**
+ * Create a 20MHz chanspec for the given band.
+ *
+ * This function returns a 20MHz chanspec in the given band.
+ *
+ * @param channel 20MHz channel number
+ * @param band a chanspec band (e.g. WL_CHANSPEC_BAND_2G)
+ *
+ * @return Returns a 20MHz chanspec, or IVNCHANSPEC in case of error.
+ */
+chanspec_t
+wf_create_20MHz_chspec(uint channel, chanspec_band_t band)
+{
+ chanspec_t chspec;
+
+ if (channel <= WL_CHANSPEC_CHAN_MASK &&
+ (band == WL_CHANSPEC_BAND_2G ||
+ band == WL_CHANSPEC_BAND_5G)) {
+ chspec = band | WL_CHANSPEC_BW_20 | WL_CHANSPEC_CTL_SB_NONE | channel;
+ if (!wf_chspec_valid(chspec)) {
+ chspec = INVCHANSPEC;
+ }
+ } else {
+ chspec = INVCHANSPEC;
+ }
+
+ return chspec;
+}
+
+/**
+ * Return the primary 20MHz channel.
+ *
+ * This function returns the channel number of the primary 20MHz channel. For
+ * 20MHz channels this is just the channel number. For 40MHz or wider channels
+ * it is the primary 20MHz channel specified by the chanspec.
+ *
+ * @param chspec input chanspec
+ *
+ * @return Returns the channel number of the primary 20MHz channel
*/
uint8
-wf_chspec_ctlchan(chanspec_t chspec)
+wf_chspec_primary20_chan(chanspec_t chspec)
{
uint center_chan;
uint bw_mhz;
@@ -763,7 +908,7 @@
ASSERT(!wf_chspec_malformed(chspec));
/* Is there a sideband ? */
- if (CHSPEC_BW_LE20(chspec)) {
+ if (CHSPEC_IS20(chspec)) {
return CHSPEC_CHANNEL(chspec);
} else {
sb = CHSPEC_CTL_SB(chspec) >> WL_CHANSPEC_CTL_SB_SHIFT;
@@ -780,46 +925,46 @@
center_chan = wf_5g_80m_chans[chan_id];
}
else {
- bw_mhz = bw_chspec_to_mhz(chspec);
+ bw_mhz = wf_bw_chspec_to_mhz(chspec);
center_chan = CHSPEC_CHANNEL(chspec) >> WL_CHANSPEC_CHAN_SHIFT;
}
- return (channel_to_ctl_chan(center_chan, bw_mhz, sb));
+ return (channel_to_primary20_chan(center_chan, bw_mhz, sb));
}
}
/* given a chanspec, return the bandwidth string */
-char *
-wf_chspec_to_bw_str(chanspec_t chspec)
+const char *
+BCMRAMFN(wf_chspec_to_bw_str)(chanspec_t chspec)
{
- return (char *)wf_chspec_bw_str[(CHSPEC_BW(chspec) >> WL_CHANSPEC_BW_SHIFT)];
+ return wf_chspec_bw_str[(CHSPEC_BW(chspec) >> WL_CHANSPEC_BW_SHIFT)];
}
/*
- * This function returns the chanspec of the control channel of a given chanspec
+ * Return the primary 20MHz chanspec of the given chanspec
*/
chanspec_t
-wf_chspec_ctlchspec(chanspec_t chspec)
+wf_chspec_primary20_chspec(chanspec_t chspec)
{
- chanspec_t ctl_chspec = chspec;
- uint8 ctl_chan;
+ chanspec_t pri_chspec = chspec;
+ uint8 pri_chan;
ASSERT(!wf_chspec_malformed(chspec));
/* Is there a sideband ? */
- if (!CHSPEC_BW_LE20(chspec)) {
- ctl_chan = wf_chspec_ctlchan(chspec);
- ctl_chspec = ctl_chan | WL_CHANSPEC_BW_20;
- ctl_chspec |= CHSPEC_BAND(chspec);
+ if (!CHSPEC_IS20(chspec)) {
+ pri_chan = wf_chspec_primary20_chan(chspec);
+ pri_chspec = pri_chan | WL_CHANSPEC_BW_20;
+ pri_chspec |= CHSPEC_BAND(chspec);
}
- return ctl_chspec;
+ return pri_chspec;
}
-/* return chanspec given control channel and bandwidth
+/* return chanspec given primary 20MHz channel and bandwidth
* return 0 on error
*/
uint16
-wf_channel2chspec(uint ctl_ch, uint bw)
+wf_channel2chspec(uint pri_ch, uint bw)
{
uint16 chspec;
const uint8 *center_ch = NULL;
@@ -827,7 +972,7 @@
int sb = -1;
int i = 0;
- chspec = ((ctl_ch <= CH_MAX_2G_CHANNEL) ? WL_CHANSPEC_BAND_2G : WL_CHANSPEC_BAND_5G);
+ chspec = ((pri_ch <= CH_MAX_2G_CHANNEL) ? WL_CHANSPEC_BAND_2G : WL_CHANSPEC_BAND_5G);
chspec |= bw;
@@ -843,15 +988,15 @@
center_ch = wf_5g_160m_chans;
num_ch = WF_NUM_5G_160M_CHANS;
bw = 160;
- } else if (BW_LE20(bw)) {
- chspec |= ctl_ch;
+ } else if (bw == WL_CHANSPEC_BW_20) {
+ chspec |= pri_ch;
return chspec;
} else {
return 0;
}
for (i = 0; i < num_ch; i ++) {
- sb = channel_to_sb(center_ch[i], ctl_ch, bw);
+ sb = channel_to_sb(center_ch[i], pri_ch, bw);
if (sb >= 0) {
chspec |= center_ch[i];
chspec |= (sb << WL_CHANSPEC_CTL_SB_SHIFT);
@@ -868,9 +1013,9 @@
}
/*
- * This function returns the chanspec for the primary 40MHz of an 80MHz channel.
- * The control sideband specifies the same 20MHz channel that the 80MHz channel is using
- * as the primary 20MHz channel.
+ * This function returns the chanspec for the primary 40MHz of an 80MHz or wider channel.
+ * The primary 20MHz channel of the returned 40MHz chanspec is the same as the primary 20MHz
+ * channel of the input chanspec.
*/
extern chanspec_t wf_chspec_primary40_chspec(chanspec_t chspec)
{
@@ -902,7 +1047,7 @@
}
/* Create primary 40MHz chanspec */
- chspec40 = (WL_CHANSPEC_BAND_5G | WL_CHANSPEC_BW_40 |
+ chspec40 = (chanspec_t)(WL_CHANSPEC_BAND_5G | WL_CHANSPEC_BW_40 |
sb | center_chan);
}
@@ -926,7 +1071,7 @@
* frequency is not a 2.4 GHz channel, or if the frequency is not and even
* multiple of 5 MHz from the base frequency to the base plus 1 GHz.
*
- * Reference 802.11 REVma, section 17.3.8.3, and 802.11B section 18.4.6.2
+ * Reference 802.11-2016, section 17.3.8.3 and section 16.3.6.3
*/
int
wf_mhz2channel(uint freq, uint start_factor)
@@ -952,7 +1097,7 @@
if ((freq < base) || (freq > base + 1000))
return -1;
- offset = freq - base;
+ offset = (int)(freq - base);
ch = offset / 5;
/* check that frequency is a 5MHz multiple from the base */
@@ -980,7 +1125,7 @@
* the answer is rounded down to an integral MHz.
* -1 is returned for an out of range channel.
*
- * Reference 802.11 REVma, section 17.3.8.3, and 802.11B section 18.4.6.2
+ * Reference 802.11-2016, section 17.3.8.3 and section 16.3.6.3
*/
int
wf_channel2mhz(uint ch, uint start_factor)
@@ -993,7 +1138,7 @@
else if ((start_factor == WF_CHAN_FACTOR_2_4_G) && (ch == 14))
freq = 2484;
else
- freq = ch * 5 + start_factor / 2;
+ freq = (int)(ch * 5 + start_factor / 2);
return freq;
}
@@ -1026,7 +1171,7 @@
for (i = 0; i < WF_NUM_SIDEBANDS_80MHZ; i++) {
chanspec_cur = CH80MHZ_CHSPEC(center_channel, sidebands[i]);
- if (primary_channel == wf_chspec_ctlchan(chanspec_cur)) {
+ if (primary_channel == wf_chspec_primary20_chan(chanspec_cur)) {
chanspec = chanspec_cur;
break;
}
@@ -1051,7 +1196,7 @@
*
* Returns INVCHANSPEC in case of error.
*
- * Refer to IEEE802.11ac section 22.3.14 "Channelization".
+ * Refer to 802.11-2016 section 22.3.14 "Channelization".
*/
chanspec_t
wf_chspec_get8080_chspec(uint8 primary_20mhz, uint8 chan0, uint8 chan1)
@@ -1078,7 +1223,7 @@
/* no, so does the primary channel fit with the 2nd 80MHz channel ? */
sb = channel_to_sb(chan1, primary_20mhz, 80);
if (sb < 0) {
- /* no match for ctl_ch to either 80MHz center channel */
+ /* no match for pri_ch to either 80MHz center channel */
return INVCHANSPEC;
}
/* swapped, so chan1 is frequency segment 0, and chan0 is seg 1 */
@@ -1086,7 +1231,7 @@
seg1 = chan0_id;
}
- chanspec = ((seg0 << WL_CHANSPEC_CHAN1_SHIFT) |
+ chanspec = (uint16)((seg0 << WL_CHANSPEC_CHAN1_SHIFT) |
(seg1 << WL_CHANSPEC_CHAN2_SHIFT) |
(sb << WL_CHANSPEC_CTL_SB_SHIFT) |
WL_CHANSPEC_BW_8080 |
@@ -1108,93 +1253,47 @@
}
/*
- * Returns the primary 80 Mhz channel for the provided chanspec
- *
- * chanspec - Input chanspec for which the 80MHz primary channel has to be retrieved
- *
- * returns -1 in case the provided channel is 20/40 Mhz chanspec
+ * Returns the center channel of the primary 80 MHz sub-band of the provided chanspec
*/
-
uint8
wf_chspec_primary80_channel(chanspec_t chanspec)
{
+ chanspec_t primary80_chspec;
uint8 primary80_chan;
- if (CHSPEC_IS80(chanspec)) {
- primary80_chan = CHSPEC_CHANNEL(chanspec);
- }
- else if (CHSPEC_IS8080(chanspec)) {
- /* Channel ID 1 corresponds to frequency segment 0, the primary 80 MHz segment */
- primary80_chan = wf_chspec_get80Mhz_ch(CHSPEC_CHAN1(chanspec));
- }
- else if (CHSPEC_IS160(chanspec)) {
- uint8 center_chan = CHSPEC_CHANNEL(chanspec);
- uint sb = CHSPEC_CTL_SB(chanspec) >> WL_CHANSPEC_CTL_SB_SHIFT;
+ primary80_chspec = wf_chspec_primary80_chspec(chanspec);
- /* based on the sb value primary 80 channel can be retrieved
- * if sb is in range 0 to 3 the lower band is the 80Mhz primary band
- */
- if (sb < 4) {
- primary80_chan = center_chan - CH_40MHZ_APART;
- }
- /* if sb is in range 4 to 7 the upper band is the 80Mhz primary band */
- else
- {
- primary80_chan = center_chan + CH_40MHZ_APART;
- }
+ if (primary80_chspec == INVCHANSPEC) {
+ primary80_chan = INVCHANNEL;
+ } else {
+ primary80_chan = CHSPEC_CHANNEL(primary80_chspec);
}
- else {
- /* for 20 and 40 Mhz */
- primary80_chan = -1;
- }
+
return primary80_chan;
}
/*
- * Returns the secondary 80 Mhz channel for the provided chanspec
- *
- * chanspec - Input chanspec for which the 80MHz secondary channel has to be retrieved
- *
- * returns -1 in case the provided channel is 20/40/80 Mhz chanspec
+ * Returns the center channel of the secondary 80 MHz sub-band of the provided chanspec
*/
uint8
wf_chspec_secondary80_channel(chanspec_t chanspec)
{
+ chanspec_t secondary80_chspec;
uint8 secondary80_chan;
- if (CHSPEC_IS8080(chanspec)) {
- secondary80_chan = wf_chspec_get80Mhz_ch(CHSPEC_CHAN2(chanspec));
- }
- else if (CHSPEC_IS160(chanspec)) {
- uint8 center_chan = CHSPEC_CHANNEL(chanspec);
- uint sb = CHSPEC_CTL_SB(chanspec) >> WL_CHANSPEC_CTL_SB_SHIFT;
+ secondary80_chspec = wf_chspec_secondary80_chspec(chanspec);
- /* based on the sb value secondary 80 channel can be retrieved
- * if sb is in range 0 to 3 upper band is the secondary 80Mhz band
- */
- if (sb < 4) {
- secondary80_chan = center_chan + CH_40MHZ_APART;
- }
- /* if sb is in range 4 to 7 the lower band is the secondary 80Mhz band */
- else
- {
- secondary80_chan = center_chan - CH_40MHZ_APART;
- }
+ if (secondary80_chspec == INVCHANSPEC) {
+ secondary80_chan = INVCHANNEL;
+ } else {
+ secondary80_chan = CHSPEC_CHANNEL(secondary80_chspec);
}
- else {
- /* for 20, 40, and 80 Mhz */
- secondary80_chan = -1;
- }
+
return secondary80_chan;
}
/*
- * This function returns the chanspec for the primary 80MHz of an 160MHz or 80+80 channel.
- *
- * chanspec - Input chanspec for which the primary 80Mhz chanspec has to be retreived
- *
- * returns the input chanspec in case the provided chanspec is an 80 MHz chanspec
- * returns INVCHANSPEC in case the provided channel is 20/40 MHz chanspec
+ * Returns the chanspec for the primary 80MHz sub-band of an 160MHz or 80+80 channel
*/
chanspec_t
wf_chspec_primary80_chspec(chanspec_t chspec)
@@ -1204,18 +1303,18 @@
uint sb;
ASSERT(!wf_chspec_malformed(chspec));
+
if (CHSPEC_IS80(chspec)) {
chspec80 = chspec;
}
else if (CHSPEC_IS8080(chspec)) {
-
- /* Channel ID 1 corresponds to frequency segment 0, the primary 80 MHz segment */
- center_chan = wf_chspec_get80Mhz_ch(CHSPEC_CHAN1(chspec));
-
sb = CHSPEC_CTL_SB(chspec);
+ /* primary sub-band is stored in seg0 */
+ center_chan = wf_chspec_get80Mhz_ch(CHSPEC_CHAN1(chspec));
+
/* Create primary 80MHz chanspec */
- chspec80 = (WL_CHANSPEC_BAND_5G | WL_CHANSPEC_BW_80 | sb | center_chan);
+ chspec80 = (chanspec_t)(WL_CHANSPEC_BAND_5G | WL_CHANSPEC_BW_80 | sb | center_chan);
}
else if (CHSPEC_IS160(chspec)) {
center_chan = CHSPEC_CHANNEL(chspec);
@@ -1230,14 +1329,88 @@
center_chan += CH_40MHZ_APART;
sb -= WL_CHANSPEC_CTL_SB_ULL;
}
+
/* Create primary 80MHz chanspec */
- chspec80 = (WL_CHANSPEC_BAND_5G | WL_CHANSPEC_BW_80 | sb | center_chan);
+ chspec80 = (chanspec_t)(WL_CHANSPEC_BAND_5G | WL_CHANSPEC_BW_80 | sb | center_chan);
}
else {
chspec80 = INVCHANSPEC;
}
return chspec80;
+}
+
+/*
+ * Returns the chanspec for the secondary 80MHz sub-band of an 160MHz or 80+80 channel
+ */
+chanspec_t
+wf_chspec_secondary80_chspec(chanspec_t chspec)
+{
+ chanspec_t chspec80;
+ uint center_chan;
+
+ ASSERT(!wf_chspec_malformed(chspec));
+
+ if (CHSPEC_IS8080(chspec)) {
+ /* secondary sub-band is stored in seg1 */
+ center_chan = wf_chspec_get80Mhz_ch(CHSPEC_CHAN2(chspec));
+
+ /* Create secondary 80MHz chanspec */
+ chspec80 = (chanspec_t)(WL_CHANSPEC_BAND_5G |
+ WL_CHANSPEC_BW_80 |
+ WL_CHANSPEC_CTL_SB_LL |
+ center_chan);
+ }
+ else if (CHSPEC_IS160(chspec)) {
+ center_chan = CHSPEC_CHANNEL(chspec);
+
+ if (CHSPEC_CTL_SB(chspec) < WL_CHANSPEC_CTL_SB_ULL) {
+ /* Primary 80MHz is on lower side */
+ center_chan -= CH_40MHZ_APART;
+ }
+ else {
+ /* Primary 80MHz is on upper side */
+ center_chan += CH_40MHZ_APART;
+ }
+
+ /* Create secondary 80MHz chanspec */
+ chspec80 = (chanspec_t)(WL_CHANSPEC_BAND_5G |
+ WL_CHANSPEC_BW_80 |
+ WL_CHANSPEC_CTL_SB_LL |
+ center_chan);
+ }
+ else {
+ chspec80 = INVCHANSPEC;
+ }
+
+ return chspec80;
+}
+
+/*
+ * For 160MHz or 80P80 chanspec, set ch[0]/ch[1] to be the low/high 80 Mhz channels
+ *
+ * For 20/40/80MHz chanspec, set ch[0] to be the center freq, and chan[1]=-1
+ */
+void
+wf_chspec_get_80p80_channels(chanspec_t chspec, uint8 *ch)
+{
+
+ if (CHSPEC_IS8080(chspec)) {
+ ch[0] = wf_chspec_get80Mhz_ch(CHSPEC_CHAN1(chspec));
+ ch[1] = wf_chspec_get80Mhz_ch(CHSPEC_CHAN2(chspec));
+ }
+ else if (CHSPEC_IS160(chspec)) {
+ uint8 center_chan = CHSPEC_CHANNEL(chspec);
+ ch[0] = center_chan - CH_40MHZ_APART;
+ ch[1] = center_chan + CH_40MHZ_APART;
+ }
+ else {
+ /* for 20, 40, and 80 Mhz */
+ ch[0] = CHSPEC_CHANNEL(chspec);
+ ch[1] = 0xFFu;
+ }
+ return;
+
}
#ifdef WL11AC_80P80
@@ -1253,40 +1426,130 @@
}
#endif /* WL11AC_80P80 */
-#ifdef WL_OLDPPR
-/* given a chanspec and a string buffer, format the chanspec as a
- * string, and return the original pointer a.
- * Min buffer length must be CHANSPEC_STR_LEN.
- * On error return NULL
+/* This routine returns the chanspec for a given operating class and
+ * channel number
*/
-char *
-wf_chspec_ntoa_old(chanspec_t chspec, char *buf)
+chanspec_t
+wf_channel_create_chspec_frm_opclass(uint8 opclass, uint8 channel)
{
- const char *band, *bw, *sb;
- uint channel;
-
- band = "";
- bw = "";
- sb = "";
- channel = CHSPEC_CHANNEL_OLD(chspec);
- /* check for non-default band spec */
- if ((CHSPEC_IS2G_OLD(chspec) && channel > CH_MAX_2G_CHANNEL) ||
- (CHSPEC_IS5G_OLD(chspec) && channel <= CH_MAX_2G_CHANNEL))
- band = (CHSPEC_IS2G_OLD(chspec)) ? "b" : "a";
- if (CHSPEC_IS40_OLD(chspec)) {
- if (CHSPEC_SB_UPPER_OLD(chspec)) {
- sb = "u";
- channel += CH_10MHZ_APART;
- } else {
- sb = "l";
- channel -= CH_10MHZ_APART;
- }
- } else if (CHSPEC_IS10_OLD(chspec)) {
- bw = "n";
+ chanspec_t chanspec = 0;
+ uint16 opclass_info = 0;
+ uint16 lookupindex = 0;
+ switch (opclass) {
+ case 115:
+ lookupindex = 1;
+ break;
+ case 124:
+ lookupindex = 3;
+ break;
+ case 125:
+ lookupindex = 5;
+ break;
+ case 81:
+ lookupindex = 12;
+ break;
+ case 116:
+ lookupindex = 22;
+ break;
+ case 119:
+ lookupindex = 23;
+ break;
+ case 126:
+ lookupindex = 25;
+ break;
+ case 83:
+ lookupindex = 32;
+ break;
+ case 84:
+ lookupindex = 33;
+ break;
+ default:
+ lookupindex = 12;
}
- /* Outputs a max of 6 chars including '\0' */
- snprintf(buf, 6, "%d%s%s%s", channel, band, bw, sb);
- return (buf);
+ if (lookupindex < 33) {
+ opclass_info = opclass_data[lookupindex-1];
+ }
+ else {
+ opclass_info = opclass_data[11];
+ }
+ chanspec = opclass_info | (uint16)channel;
+ return chanspec;
}
-#endif /* WL_OLDPPR */
+
+/* This routine returns the opclass for a given chanspec */
+int
+wf_channel_create_opclass_frm_chspec(chanspec_t chspec)
+{
+ BCM_REFERENCE(chspec);
+ /* TODO: Implement this function ! */
+ return 12; /* opclass 12 for basic 2G channels */
+}
+
+/* Populates array with all 20MHz side bands of a given chanspec_t in the following order:
+ * primary20, secondary20, two secondary40s, four secondary80s.
+ * 'chspec' is the chanspec of interest
+ * 'pext' must point to an uint8 array of long enough to hold all side bands of the given chspec
+ *
+ * Works with 20, 40, 80, 80p80 and 160MHz chspec
+ */
+void
+wf_get_all_ext(chanspec_t chspec, uint8 *pext)
+{
+#ifdef WL11N_20MHZONLY
+ GET_ALL_SB(chspec, pext);
+#else /* !WL11N_20MHZONLY */
+ chanspec_t t = (CHSPEC_IS160(chspec) || CHSPEC_IS8080(chspec)) ? /* if bw > 80MHz */
+ wf_chspec_primary80_chspec(chspec) : (chspec); /* extract primary 80 */
+ /* primary20 channel as first element */
+ uint8 pri_ch = (pext)[0] = wf_chspec_primary20_chan(t);
+ if (CHSPEC_IS20(chspec)) return; /* nothing more to do since 20MHz chspec */
+ /* 20MHz EXT */
+ (pext)[1] = pri_ch + (uint8)(IS_CTL_IN_L20(t) ? CH_20MHZ_APART : -CH_20MHZ_APART);
+ if (CHSPEC_IS40(chspec)) return; /* nothing more to do since 40MHz chspec */
+ /* center 40MHz EXT */
+ t = wf_channel2chspec((uint)(pri_ch + (IS_CTL_IN_L40(chspec) ?
+ CH_40MHZ_APART : -CH_40MHZ_APART)), WL_CHANSPEC_BW_40);
+ GET_ALL_SB(t, &((pext)[2])); /* get the 20MHz side bands in 40MHz EXT */
+ if (CHSPEC_IS80(chspec)) return; /* nothing more to do since 80MHz chspec */
+ t = CH80MHZ_CHSPEC(wf_chspec_secondary80_channel(chspec), WL_CHANSPEC_CTL_SB_LLL);
+ /* get the 20MHz side bands in 80MHz EXT (secondary) */
+ GET_ALL_SB(t, &((pext)[4]));
+#endif /* !WL11N_20MHZONLY */
+}
+
+/*
+ * Given two chanspecs, returns true if they overlap.
+ * (Overlap: At least one 20MHz subband is common between the two chanspecs provided)
+ */
+bool wf_chspec_overlap(chanspec_t chspec0, chanspec_t chspec1)
+{
+ uint8 ch0, ch1;
+
+ FOREACH_20_SB(chspec0, ch0) {
+ FOREACH_20_SB(chspec1, ch1) {
+ if (ABS(ch0 - ch1) < CH_20MHZ_APART) {
+ return TRUE;
+ }
+ }
+ }
+
+ return FALSE;
+}
+
+uint8
+channel_bw_to_width(chanspec_t chspec)
+{
+ uint8 channel_width;
+
+ if (CHSPEC_IS80(chspec))
+ channel_width = VHT_OP_CHAN_WIDTH_80;
+ else if (CHSPEC_IS160(chspec))
+ channel_width = VHT_OP_CHAN_WIDTH_160;
+ else if (CHSPEC_IS8080(chspec))
+ channel_width = VHT_OP_CHAN_WIDTH_80_80;
+ else
+ channel_width = VHT_OP_CHAN_WIDTH_20_40;
+
+ return channel_width;
+}
--
Gitblit v1.6.2