[third_party/bcmdhd] Expose logic for wstats.
Expose more constants, macros, and some logic for the proper handling of
the firmware iovar wstats_counters (per-antenna histograms).
Also there are two type fixes in bcmwifi_channels.h, where uint8 and
uint16 were accidentally used (instead of uint8_t and uint16_t).
Bug: 29698
Change-Id: I07ad8fd29d884e25afe943a039b64b7961196b71
Reviewed-on: https://fuchsia-review.googlesource.com/c/third_party/bcmdhd/+/404954
Reviewed-by: Joshua Conner <joshconner@google.com>
diff --git a/crossdriver/BUILD.gn b/crossdriver/BUILD.gn
index a5cdf93..15714e0 100644
--- a/crossdriver/BUILD.gn
+++ b/crossdriver/BUILD.gn
@@ -1,11 +1,19 @@
# Crossdriver (bcmdhd/brcmfmac) symbols extracted from bcmdhd.
-static_library("bcmdhd_crossdriver") {
+source_set("bcmdhd_crossdriver") {
public = [
+ "bcmwifi_channels.cc",
"bcmwifi_channels.h",
+ "dhd.cc",
"dhd.h",
+ "wl_cfg80211.cc",
+ "wl_cfg80211.h",
]
sources = [
+ "bcmwifi_channels.cc",
"bcmwifi_channels.h",
+ "dhd.cc",
"dhd.h",
+ "wl_cfg80211.cc",
+ "wl_cfg80211.h",
]
}
diff --git a/crossdriver/bcmwifi_channels.cc b/crossdriver/bcmwifi_channels.cc
new file mode 100644
index 0000000..e85883e
--- /dev/null
+++ b/crossdriver/bcmwifi_channels.cc
@@ -0,0 +1,79 @@
+/* Crossdriver (bcmdhd/brcmfmac) logic extracted from bcmdhd bcmwifi_channels.c.
+ *
+ * Copyright 1999-2016, Broadcom Corporation
+ * All rights reserved,
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * This software is provided by the copyright holder "as is" and any express or
+ * implied warranties, including, but not limited to, the implied warranties of
+ * merchantability and fitness for a particular purpose are disclaimed. In no event
+ * shall copyright holder be liable for any direct, indirect, incidental, special,
+ * exemplary, or consequential damages (including, but not limited to, procurement
+ * of substitute goods or services; loss of use, data, or profits; or business
+ * interruption) however caused and on any theory of liability, whether in
+ * contract, strict liability, or tort (including negligence or otherwise) arising
+ * in any way out of the use of this software, even if advised of the possibility
+ * of such damage
+ */
+
+#include "bcmwifi_channels.h"
+
+bool chspec_malformed(chanspec_t chanspec) {
+ uint16_t chspec_bw = CHSPEC_BW(chanspec);
+ uint16_t chspec_ch = CHSPEC_CHANNEL(chanspec);
+
+ /* must be 2G or 5G band */
+ if (CHSPEC_IS2G(chanspec)) {
+ /* must be valid bandwidth */
+ if (!BW_LE40(chspec_bw)) {
+ return true;
+ }
+ } else if (CHSPEC_IS5G(chanspec)) {
+ if (chspec_bw == WL_CHANSPEC_BW_8080) {
+ uint16_t 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_5G_80M_CHANS || ch2_id >= WF_NUM_5G_80M_CHANS)
+ return true;
+
+ } else if (BW_LE160(chspec_bw)) {
+ if (chspec_ch > MAXCHANNEL) {
+ return true;
+ }
+ } else {
+ /* invalid bandwidth */
+ return true;
+ }
+ } else {
+ /* must be 2G or 5G band */
+ return true;
+ }
+
+ /* side band needs to be consistent with bandwidth */
+ if (BW_LE20(chspec_bw)) {
+ if (CHSPEC_CTL_SB(chanspec) != WL_CHANSPEC_CTL_SB_LLL)
+ return true;
+ } else if (chspec_bw == WL_CHANSPEC_BW_40) {
+ if (CHSPEC_CTL_SB(chanspec) > WL_CHANSPEC_CTL_SB_LLU)
+ return true;
+ } else if (chspec_bw == WL_CHANSPEC_BW_80 || chspec_bw == WL_CHANSPEC_BW_8080) {
+ if (CHSPEC_CTL_SB(chanspec) > WL_CHANSPEC_CTL_SB_LUU)
+ return true;
+ } else if (chspec_bw == WL_CHANSPEC_BW_160) {
+ // This condition was originally an assertion, which is inverted here.
+ // Assertion was: ASSERT(CHSPEC_CTL_SB(chanspec) <= WL_CHANSPEC_CTL_SB_UUU);
+ if (CHSPEC_CTL_SB(chanspec) > WL_CHANSPEC_CTL_SB_UUU) {
+ return true;
+ }
+ }
+ return false;
+}
diff --git a/crossdriver/bcmwifi_channels.h b/crossdriver/bcmwifi_channels.h
index d46382c..cde38ce 100644
--- a/crossdriver/bcmwifi_channels.h
+++ b/crossdriver/bcmwifi_channels.h
@@ -28,21 +28,19 @@
#include <stdint.h>
-// clang-format off
-
/* A chanspec holds the channel number, band, bandwidth and control sideband */
using chanspec_t = uint16_t;
/* channel defines */
-#define CH_UPPER_SB 0x01
-#define CH_LOWER_SB 0x02
-#define CH_EWA_VALID 0x04
-#define CH_80MHZ_APART 16
-#define CH_40MHZ_APART 8
-#define CH_20MHZ_APART 4
-#define CH_10MHZ_APART 2
-#define CH_5MHZ_APART 1 /* 2G band channels are 5 Mhz apart */
-#define CH_MAX_2G_CHANNEL 14 /* Max channel in 2G band */
+#define CH_UPPER_SB 0x01
+#define CH_LOWER_SB 0x02
+#define CH_EWA_VALID 0x04
+#define CH_80MHZ_APART 16
+#define CH_40MHZ_APART 8
+#define CH_20MHZ_APART 4
+#define CH_10MHZ_APART 2
+#define CH_5MHZ_APART 1 /* 2G band channels are 5 Mhz apart */
+#define CH_MAX_2G_CHANNEL 14 /* Max channel in 2G band */
/*
* max # supported channels. The max channel no is 216, this is that + 1
@@ -51,142 +49,191 @@
*/
#define MAXCHANNEL 224
-#define MAXCHANNEL_NUM (MAXCHANNEL - 1) /* max channel number */
+#define MAXCHANNEL_NUM (MAXCHANNEL - 1) /* max channel number */
-#define WL_CHANSPEC_CHAN_MASK 0x00ff
-#define WL_CHANSPEC_CHAN_SHIFT 0
-#define WL_CHANSPEC_CHAN1_MASK 0x000f
-#define WL_CHANSPEC_CHAN1_SHIFT 0
-#define WL_CHANSPEC_CHAN2_MASK 0x00f0
-#define WL_CHANSPEC_CHAN2_SHIFT 4
+#define WL_CHANSPEC_CHAN_MASK 0x00ff
+#define WL_CHANSPEC_CHAN_SHIFT 0
+#define WL_CHANSPEC_CHAN1_MASK 0x000f
+#define WL_CHANSPEC_CHAN1_SHIFT 0
+#define WL_CHANSPEC_CHAN2_MASK 0x00f0
+#define WL_CHANSPEC_CHAN2_SHIFT 4
-#define WL_CHANSPEC_CTL_SB_MASK 0x0700
-#define WL_CHANSPEC_CTL_SB_SHIFT 8
-#define WL_CHANSPEC_CTL_SB_LLL 0x0000
-#define WL_CHANSPEC_CTL_SB_LLU 0x0100
-#define WL_CHANSPEC_CTL_SB_LUL 0x0200
-#define WL_CHANSPEC_CTL_SB_LUU 0x0300
-#define WL_CHANSPEC_CTL_SB_ULL 0x0400
-#define WL_CHANSPEC_CTL_SB_ULU 0x0500
-#define WL_CHANSPEC_CTL_SB_UUL 0x0600
-#define WL_CHANSPEC_CTL_SB_UUU 0x0700
-#define WL_CHANSPEC_CTL_SB_LL WL_CHANSPEC_CTL_SB_LLL
-#define WL_CHANSPEC_CTL_SB_LU WL_CHANSPEC_CTL_SB_LLU
-#define WL_CHANSPEC_CTL_SB_UL WL_CHANSPEC_CTL_SB_LUL
-#define WL_CHANSPEC_CTL_SB_UU WL_CHANSPEC_CTL_SB_LUU
-#define WL_CHANSPEC_CTL_SB_L WL_CHANSPEC_CTL_SB_LLL
-#define WL_CHANSPEC_CTL_SB_U WL_CHANSPEC_CTL_SB_LLU
-#define WL_CHANSPEC_CTL_SB_LOWER WL_CHANSPEC_CTL_SB_LLL
-#define WL_CHANSPEC_CTL_SB_UPPER WL_CHANSPEC_CTL_SB_LLU
-#define WL_CHANSPEC_CTL_SB_NONE WL_CHANSPEC_CTL_SB_LLL
+#define WL_CHANSPEC_CTL_SB_MASK 0x0700
+#define WL_CHANSPEC_CTL_SB_SHIFT 8
+#define WL_CHANSPEC_CTL_SB_LLL 0x0000
+#define WL_CHANSPEC_CTL_SB_LLU 0x0100
+#define WL_CHANSPEC_CTL_SB_LUL 0x0200
+#define WL_CHANSPEC_CTL_SB_LUU 0x0300
+#define WL_CHANSPEC_CTL_SB_ULL 0x0400
+#define WL_CHANSPEC_CTL_SB_ULU 0x0500
+#define WL_CHANSPEC_CTL_SB_UUL 0x0600
+#define WL_CHANSPEC_CTL_SB_UUU 0x0700
+#define WL_CHANSPEC_CTL_SB_LL WL_CHANSPEC_CTL_SB_LLL
+#define WL_CHANSPEC_CTL_SB_LU WL_CHANSPEC_CTL_SB_LLU
+#define WL_CHANSPEC_CTL_SB_UL WL_CHANSPEC_CTL_SB_LUL
+#define WL_CHANSPEC_CTL_SB_UU WL_CHANSPEC_CTL_SB_LUU
+#define WL_CHANSPEC_CTL_SB_L WL_CHANSPEC_CTL_SB_LLL
+#define WL_CHANSPEC_CTL_SB_U WL_CHANSPEC_CTL_SB_LLU
+#define WL_CHANSPEC_CTL_SB_LOWER WL_CHANSPEC_CTL_SB_LLL
+#define WL_CHANSPEC_CTL_SB_UPPER WL_CHANSPEC_CTL_SB_LLU
+#define WL_CHANSPEC_CTL_SB_NONE WL_CHANSPEC_CTL_SB_LLL
-#define WL_CHANSPEC_BW_MASK 0x3800
-#define WL_CHANSPEC_BW_SHIFT 11
-#define WL_CHANSPEC_BW_5 0x0000
-#define WL_CHANSPEC_BW_10 0x0800
-#define WL_CHANSPEC_BW_20 0x1000
-#define WL_CHANSPEC_BW_40 0x1800
-#define WL_CHANSPEC_BW_80 0x2000
-#define WL_CHANSPEC_BW_160 0x2800
-#define WL_CHANSPEC_BW_8080 0x3000
-#define WL_CHANSPEC_BW_2P5 0x3800
-#define WL_CHANSPEC_BAND_MASK 0xc000
-#define WL_CHANSPEC_BAND_SHIFT 14
-#define WL_CHANSPEC_BAND_2G 0x0000
-#define WL_CHANSPEC_BAND_3G 0x4000
-#define WL_CHANSPEC_BAND_4G 0x8000
-#define WL_CHANSPEC_BAND_5G 0xc000
-#define INVCHANSPEC 255
-#define MAX_CHANSPEC 0xFFFF
+#define WL_CHANSPEC_BW_MASK 0x3800
+#define WL_CHANSPEC_BW_SHIFT 11
+#define WL_CHANSPEC_BW_5 0x0000
+#define WL_CHANSPEC_BW_10 0x0800
+#define WL_CHANSPEC_BW_20 0x1000
+#define WL_CHANSPEC_BW_40 0x1800
+#define WL_CHANSPEC_BW_80 0x2000
+#define WL_CHANSPEC_BW_160 0x2800
+#define WL_CHANSPEC_BW_8080 0x3000
+#define WL_CHANSPEC_BW_2P5 0x3800
+#define WL_CHANSPEC_BAND_MASK 0xc000
+#define WL_CHANSPEC_BAND_SHIFT 14
+#define WL_CHANSPEC_BAND_2G 0x0000
+#define WL_CHANSPEC_BAND_3G 0x4000
+#define WL_CHANSPEC_BAND_4G 0x8000
+#define WL_CHANSPEC_BAND_5G 0xc000
+#define INVCHANSPEC 255
+#define MAX_CHANSPEC 0xFFFF
/* channel defines */
-#define LOWER_20_SB(channel) (((channel) > CH_10MHZ_APART) ? \
- ((channel) - CH_10MHZ_APART) : 0)
-#define UPPER_20_SB(channel) (((channel) < (MAXCHANNEL - CH_10MHZ_APART)) ? \
- ((channel) + CH_10MHZ_APART) : 0)
+#define LOWER_20_SB(channel) (((channel) > CH_10MHZ_APART) ? ((channel)-CH_10MHZ_APART) : 0)
+#define UPPER_20_SB(channel) \
+ (((channel) < (MAXCHANNEL - CH_10MHZ_APART)) ? ((channel) + CH_10MHZ_APART) : 0)
-#define LL_20_SB(channel) (((channel) > 3 * CH_10MHZ_APART) ? ((channel) - 3 * CH_10MHZ_APART) : 0)
-#define UU_20_SB(channel) (((channel) < (MAXCHANNEL - 3 * CH_10MHZ_APART)) ? \
- ((channel) + 3 * CH_10MHZ_APART) : 0)
+#define LL_20_SB(channel) (((channel) > 3 * CH_10MHZ_APART) ? ((channel)-3 * CH_10MHZ_APART) : 0)
+#define UU_20_SB(channel) \
+ (((channel) < (MAXCHANNEL - 3 * CH_10MHZ_APART)) ? ((channel) + 3 * CH_10MHZ_APART) : 0)
#define LU_20_SB(channel) LOWER_20_SB(channel)
#define UL_20_SB(channel) UPPER_20_SB(channel)
-#define LOWER_40_SB(channel) ((channel) - CH_20MHZ_APART)
-#define UPPER_40_SB(channel) ((channel) + CH_20MHZ_APART)
-#define CHSPEC_WLCBANDUNIT(chspec) (CHSPEC_IS5G(chspec) ? BAND_5G_INDEX : BAND_2G_INDEX)
-#define CH20MHZ_CHSPEC(channel) (chanspec_t)((chanspec_t)(channel) | WL_CHANSPEC_BW_20 | \
- (((channel) <= CH_MAX_2G_CHANNEL) ? \
- WL_CHANSPEC_BAND_2G : WL_CHANSPEC_BAND_5G))
-#define CH2P5MHZ_CHSPEC(channel) (chanspec_t)((chanspec_t)(channel) | WL_CHANSPEC_BW_2P5 | \
- (((channel) <= CH_MAX_2G_CHANNEL) ? \
- WL_CHANSPEC_BAND_2G : WL_CHANSPEC_BAND_5G))
-#define CH5MHZ_CHSPEC(channel) (chanspec_t)((chanspec_t)(channel) | WL_CHANSPEC_BW_5 | \
- (((channel) <= CH_MAX_2G_CHANNEL) ? \
- WL_CHANSPEC_BAND_2G : WL_CHANSPEC_BAND_5G))
-#define CH10MHZ_CHSPEC(channel) (chanspec_t)((chanspec_t)(channel) | WL_CHANSPEC_BW_10 | \
- (((channel) <= CH_MAX_2G_CHANNEL) ? \
- WL_CHANSPEC_BAND_2G : WL_CHANSPEC_BAND_5G))
-#define NEXT_20MHZ_CHAN(channel) (((channel) < (MAXCHANNEL - CH_20MHZ_APART)) ? \
- ((channel) + CH_20MHZ_APART) : 0)
-#define CH40MHZ_CHSPEC(channel, ctlsb) (chanspec_t) \
- ((channel) | (ctlsb) | WL_CHANSPEC_BW_40 | \
- ((channel) <= CH_MAX_2G_CHANNEL ? WL_CHANSPEC_BAND_2G : \
- WL_CHANSPEC_BAND_5G))
-#define CH80MHZ_CHSPEC(channel, ctlsb) (chanspec_t) \
- ((channel) | (ctlsb) | \
- WL_CHANSPEC_BW_80 | WL_CHANSPEC_BAND_5G)
-#define CH160MHZ_CHSPEC(channel, ctlsb) (chanspec_t) \
- ((channel) | (ctlsb) | \
- WL_CHANSPEC_BW_160 | WL_CHANSPEC_BAND_5G)
-#define CHBW_CHSPEC(bw, channel) (chanspec_t)((chanspec_t)(channel) | (bw) | \
- (((channel) <= CH_MAX_2G_CHANNEL) ? \
- WL_CHANSPEC_BAND_2G : WL_CHANSPEC_BAND_5G))
+#define LOWER_40_SB(channel) ((channel)-CH_20MHZ_APART)
+#define UPPER_40_SB(channel) ((channel) + CH_20MHZ_APART)
+#define CHSPEC_WLCBANDUNIT(chspec) (CHSPEC_IS5G(chspec) ? BAND_5G_INDEX : BAND_2G_INDEX)
+#define CH20MHZ_CHSPEC(channel) \
+ (chanspec_t)((chanspec_t)(channel) | WL_CHANSPEC_BW_20 | \
+ (((channel) <= CH_MAX_2G_CHANNEL) ? WL_CHANSPEC_BAND_2G : WL_CHANSPEC_BAND_5G))
+#define CH2P5MHZ_CHSPEC(channel) \
+ (chanspec_t)((chanspec_t)(channel) | WL_CHANSPEC_BW_2P5 | \
+ (((channel) <= CH_MAX_2G_CHANNEL) ? WL_CHANSPEC_BAND_2G : WL_CHANSPEC_BAND_5G))
+#define CH5MHZ_CHSPEC(channel) \
+ (chanspec_t)((chanspec_t)(channel) | WL_CHANSPEC_BW_5 | \
+ (((channel) <= CH_MAX_2G_CHANNEL) ? WL_CHANSPEC_BAND_2G : WL_CHANSPEC_BAND_5G))
+#define CH10MHZ_CHSPEC(channel) \
+ (chanspec_t)((chanspec_t)(channel) | WL_CHANSPEC_BW_10 | \
+ (((channel) <= CH_MAX_2G_CHANNEL) ? WL_CHANSPEC_BAND_2G : WL_CHANSPEC_BAND_5G))
+#define NEXT_20MHZ_CHAN(channel) \
+ (((channel) < (MAXCHANNEL - CH_20MHZ_APART)) ? ((channel) + CH_20MHZ_APART) : 0)
+#define CH40MHZ_CHSPEC(channel, ctlsb) \
+ (chanspec_t)((channel) | (ctlsb) | WL_CHANSPEC_BW_40 | \
+ ((channel) <= CH_MAX_2G_CHANNEL ? WL_CHANSPEC_BAND_2G : WL_CHANSPEC_BAND_5G))
+#define CH80MHZ_CHSPEC(channel, ctlsb) \
+ (chanspec_t)((channel) | (ctlsb) | WL_CHANSPEC_BW_80 | WL_CHANSPEC_BAND_5G)
+#define CH160MHZ_CHSPEC(channel, ctlsb) \
+ (chanspec_t)((channel) | (ctlsb) | WL_CHANSPEC_BW_160 | WL_CHANSPEC_BAND_5G)
+#define CHBW_CHSPEC(bw, channel) \
+ (chanspec_t)((chanspec_t)(channel) | (bw) | \
+ (((channel) <= CH_MAX_2G_CHANNEL) ? WL_CHANSPEC_BAND_2G : WL_CHANSPEC_BAND_5G))
+
+/* simple MACROs to get different fields of chanspec */
+// TODO(karlward) What about WL11AC_80P80 version of CHSPEC_CHANNEL?
+#define CHSPEC_CHANNEL(chspec) ((uint8_t)((chspec)&WL_CHANSPEC_CHAN_MASK))
+#define CHSPEC_CHAN1(chspec) ((chspec)&WL_CHANSPEC_CHAN1_MASK) >> WL_CHANSPEC_CHAN1_SHIFT
+#define CHSPEC_CHAN2(chspec) ((chspec)&WL_CHANSPEC_CHAN2_MASK) >> WL_CHANSPEC_CHAN2_SHIFT
+#define CHSPEC_BAND(chspec) ((chspec)&WL_CHANSPEC_BAND_MASK)
+#define CHSPEC_CTL_SB(chspec) ((chspec)&WL_CHANSPEC_CTL_SB_MASK)
+#define CHSPEC_BW(chspec) ((chspec)&WL_CHANSPEC_BW_MASK)
+
+// TODO(karlward) What about WL11N_20MHZONLY version of these?
+#define CHSPEC_IS2P5(chspec) (((chspec)&WL_CHANSPEC_BW_MASK) == WL_CHANSPEC_BW_2P5)
+#define CHSPEC_IS5(chspec) (((chspec)&WL_CHANSPEC_BW_MASK) == WL_CHANSPEC_BW_5)
+#define CHSPEC_IS10(chspec) (((chspec)&WL_CHANSPEC_BW_MASK) == WL_CHANSPEC_BW_10)
+#define CHSPEC_IS20(chspec) (((chspec)&WL_CHANSPEC_BW_MASK) == WL_CHANSPEC_BW_20)
+#define CHSPEC_IS40(chspec) (((chspec)&WL_CHANSPEC_BW_MASK) == WL_CHANSPEC_BW_40)
+#define CHSPEC_IS80(chspec) (((chspec)&WL_CHANSPEC_BW_MASK) == WL_CHANSPEC_BW_80)
+#define CHSPEC_IS160(chspec) (((chspec)&WL_CHANSPEC_BW_MASK) == WL_CHANSPEC_BW_160)
+#define CHSPEC_IS8080(chspec) (((chspec)&WL_CHANSPEC_BW_MASK) == WL_CHANSPEC_BW_8080)
+
+// TODO(karlward) What about WL11N_20MHZONLY and WL11ULB versions of this?
+/* This MACRO is strictly to avoid abandons in existing code with ULB feature and is in no way
+ * optimial to use. Should be replaced with CHSPEC_BW_LE() instead
+ */
+#define BW_LE20(bw) \
+ (((bw) == WL_CHANSPEC_BW_2P5) || ((bw) == WL_CHANSPEC_BW_5) || ((bw) == WL_CHANSPEC_BW_10) || \
+ ((bw) == WL_CHANSPEC_BW_20))
+
+#define BW_LE40(bw) (BW_LE20(bw) || ((bw) == WL_CHANSPEC_BW_40))
+#define BW_LE80(bw) (BW_LE40(bw) || ((bw) == WL_CHANSPEC_BW_80))
+#define BW_LE160(bw) (BW_LE80(bw) || ((bw) == WL_CHANSPEC_BW_160))
+
+#define CHSPEC_IS5G(chspec) (((chspec)&WL_CHANSPEC_BAND_MASK) == WL_CHANSPEC_BAND_5G)
+#define CHSPEC_IS2G(chspec) (((chspec)&WL_CHANSPEC_BAND_MASK) == WL_CHANSPEC_BAND_2G)
+#define CHSPEC_SB_UPPER(chspec) \
+ ((((chspec)&WL_CHANSPEC_CTL_SB_MASK) == WL_CHANSPEC_CTL_SB_UPPER) && \
+ (((chspec)&WL_CHANSPEC_BW_MASK) == WL_CHANSPEC_BW_40))
+#define CHSPEC_SB_LOWER(chspec) \
+ ((((chspec)&WL_CHANSPEC_CTL_SB_MASK) == WL_CHANSPEC_CTL_SB_LOWER) && \
+ (((chspec)&WL_CHANSPEC_BW_MASK) == WL_CHANSPEC_BW_40))
/* Legacy Chanspec defines
* These are the defines for the previous format of the chanspec_t
*/
-#define WL_LCHANSPEC_CHAN_MASK 0x00ff
-#define WL_LCHANSPEC_CHAN_SHIFT 0
+#define WL_LCHANSPEC_CHAN_MASK 0x00ff
+#define WL_LCHANSPEC_CHAN_SHIFT 0
-#define WL_LCHANSPEC_CTL_SB_MASK 0x0300
-#define WL_LCHANSPEC_CTL_SB_SHIFT 8
-#define WL_LCHANSPEC_CTL_SB_LOWER 0x0100
-#define WL_LCHANSPEC_CTL_SB_UPPER 0x0200
-#define WL_LCHANSPEC_CTL_SB_NONE 0x0300
+#define WL_LCHANSPEC_CTL_SB_MASK 0x0300
+#define WL_LCHANSPEC_CTL_SB_SHIFT 8
+#define WL_LCHANSPEC_CTL_SB_LOWER 0x0100
+#define WL_LCHANSPEC_CTL_SB_UPPER 0x0200
+#define WL_LCHANSPEC_CTL_SB_NONE 0x0300
-#define WL_LCHANSPEC_BW_MASK 0x0C00
-#define WL_LCHANSPEC_BW_SHIFT 10
-#define WL_LCHANSPEC_BW_10 0x0400
-#define WL_LCHANSPEC_BW_20 0x0800
-#define WL_LCHANSPEC_BW_40 0x0C00
+#define WL_LCHANSPEC_BW_MASK 0x0C00
+#define WL_LCHANSPEC_BW_SHIFT 10
+#define WL_LCHANSPEC_BW_10 0x0400
+#define WL_LCHANSPEC_BW_20 0x0800
+#define WL_LCHANSPEC_BW_40 0x0C00
-#define WL_LCHANSPEC_BAND_MASK 0xf000
-#define WL_LCHANSPEC_BAND_SHIFT 12
-#define WL_LCHANSPEC_BAND_5G 0x1000
-#define WL_LCHANSPEC_BAND_2G 0x2000
+#define WL_LCHANSPEC_BAND_MASK 0xf000
+#define WL_LCHANSPEC_BAND_SHIFT 12
+#define WL_LCHANSPEC_BAND_5G 0x1000
+#define WL_LCHANSPEC_BAND_2G 0x2000
-#define LCHSPEC_CHANNEL(chspec) ((uint8)((chspec) & WL_LCHANSPEC_CHAN_MASK))
-#define LCHSPEC_BAND(chspec) ((chspec) & WL_LCHANSPEC_BAND_MASK)
-#define LCHSPEC_CTL_SB(chspec) ((chspec) & WL_LCHANSPEC_CTL_SB_MASK)
-#define LCHSPEC_BW(chspec) ((chspec) & WL_LCHANSPEC_BW_MASK)
-#define LCHSPEC_IS10(chspec) (((chspec) & WL_LCHANSPEC_BW_MASK) == WL_LCHANSPEC_BW_10)
-#define LCHSPEC_IS20(chspec) (((chspec) & WL_LCHANSPEC_BW_MASK) == WL_LCHANSPEC_BW_20)
-#define LCHSPEC_IS40(chspec) (((chspec) & WL_LCHANSPEC_BW_MASK) == WL_LCHANSPEC_BW_40)
-#define LCHSPEC_IS5G(chspec) (((chspec) & WL_LCHANSPEC_BAND_MASK) == WL_LCHANSPEC_BAND_5G)
-#define LCHSPEC_IS2G(chspec) (((chspec) & WL_LCHANSPEC_BAND_MASK) == WL_LCHANSPEC_BAND_2G)
+#define LCHSPEC_CHANNEL(chspec) ((uint8_t)((chspec)&WL_LCHANSPEC_CHAN_MASK))
+#define LCHSPEC_BAND(chspec) ((chspec)&WL_LCHANSPEC_BAND_MASK)
+#define LCHSPEC_CTL_SB(chspec) ((chspec)&WL_LCHANSPEC_CTL_SB_MASK)
+#define LCHSPEC_BW(chspec) ((chspec)&WL_LCHANSPEC_BW_MASK)
+#define LCHSPEC_IS10(chspec) (((chspec)&WL_LCHANSPEC_BW_MASK) == WL_LCHANSPEC_BW_10)
+#define LCHSPEC_IS20(chspec) (((chspec)&WL_LCHANSPEC_BW_MASK) == WL_LCHANSPEC_BW_20)
+#define LCHSPEC_IS40(chspec) (((chspec)&WL_LCHANSPEC_BW_MASK) == WL_LCHANSPEC_BW_40)
+#define LCHSPEC_IS5G(chspec) (((chspec)&WL_LCHANSPEC_BAND_MASK) == WL_LCHANSPEC_BAND_5G)
+#define LCHSPEC_IS2G(chspec) (((chspec)&WL_LCHANSPEC_BAND_MASK) == WL_LCHANSPEC_BAND_2G)
-#define LCHSPEC_SB_UPPER(chspec) \
- ((((chspec) & WL_LCHANSPEC_CTL_SB_MASK) == WL_LCHANSPEC_CTL_SB_UPPER) && \
- (((chspec) & WL_LCHANSPEC_BW_MASK) == WL_LCHANSPEC_BW_40))
-#define LCHSPEC_SB_LOWER(chspec) \
- ((((chspec) & WL_LCHANSPEC_CTL_SB_MASK) == WL_LCHANSPEC_CTL_SB_LOWER) && \
- (((chspec) & WL_LCHANSPEC_BW_MASK) == WL_LCHANSPEC_BW_40))
+#define LCHSPEC_SB_UPPER(chspec) \
+ ((((chspec)&WL_LCHANSPEC_CTL_SB_MASK) == WL_LCHANSPEC_CTL_SB_UPPER) && \
+ (((chspec)&WL_LCHANSPEC_BW_MASK) == WL_LCHANSPEC_BW_40))
+#define LCHSPEC_SB_LOWER(chspec) \
+ ((((chspec)&WL_LCHANSPEC_CTL_SB_MASK) == WL_LCHANSPEC_CTL_SB_LOWER) && \
+ (((chspec)&WL_LCHANSPEC_BW_MASK) == WL_LCHANSPEC_BW_40))
-#define LCHSPEC_CREATE(chan, band, bw, sb) ((uint16)((chan) | (sb) | (bw) | (band)))
+#define LCHSPEC_CREATE(chan, band, bw, sb) ((uint16_t)((chan) | (sb) | (bw) | (band)))
-#define CH20MHZ_LCHSPEC(channel) \
- (chanspec_t)((chanspec_t)(channel) | WL_LCHANSPEC_BW_20 | \
- WL_LCHANSPEC_CTL_SB_NONE | (((channel) <= CH_MAX_2G_CHANNEL) ? \
- WL_LCHANSPEC_BAND_2G : WL_LCHANSPEC_BAND_5G))
+#define CH20MHZ_LCHSPEC(channel) \
+ (chanspec_t)((chanspec_t)(channel) | WL_LCHANSPEC_BW_20 | WL_LCHANSPEC_CTL_SB_NONE | \
+ (((channel) <= CH_MAX_2G_CHANNEL) ? WL_LCHANSPEC_BAND_2G : WL_LCHANSPEC_BAND_5G))
+
+/* 80MHz channels in 5GHz band */
+static const uint8_t wf_5g_80m_chans[] = {42, 58, 106, 122, 138, 155};
+#define WF_NUM_5G_80M_CHANS (sizeof(wf_5g_80m_chans) / sizeof(uint8_t))
+
+/*
+ * 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
+ * combination could be legal given any set of circumstances.
+ * Returns true if chanspec is malformed, false if it looks good.
+ *
+ * Ported from wf_chspec_malformed.
+ */
+bool chspec_malformed(chanspec_t chanspec);
#endif // THIRD_PARTY_BCMDHD_CROSSDRIVER_BCMWIFI_CHANNELS_H_
diff --git a/crossdriver/dhd.cc b/crossdriver/dhd.cc
new file mode 100644
index 0000000..a7980b4
--- /dev/null
+++ b/crossdriver/dhd.cc
@@ -0,0 +1,59 @@
+/* Crossdriver (bcmdhd/brcmfmac) logic extracted from bcmdhd dhd.h externs.
+ *
+ * Copyright 1999-2016, Broadcom Corporation
+ * All rights reserved,
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * This software is provided by the copyright holder "as is" and any express or
+ * implied warranties, including, but not limited to, the implied warranties of
+ * merchantability and fitness for a particular purpose are disclaimed. In no event
+ * shall copyright holder be liable for any direct, indirect, incidental, special,
+ * exemplary, or consequential damages (including, but not limited to, procurement
+ * of substitute goods or services; loss of use, data, or profits; or business
+ * interruption) however caused and on any theory of liability, whether in
+ * contract, strict liability, or tort (including negligence or otherwise) arising
+ * in any way out of the use of this software, even if advised of the possibility
+ * of such damage
+ */
+
+#include "dhd.h"
+
+#include <memory>
+
+#include "wl_cfg80211.h"
+
+bool get_histograms(wl_wstats_cnt_t wl_stats_cnt, chanspec_t chanspec, uint32_t version,
+ uint32_t rxchain, histograms_report_t* out_report) {
+ if (wl_stats_cnt.version > WSTATS_CNT_T_VERSION) {
+ // Unexpected wl_stats_cnt version.
+ return false;
+ }
+
+ const chanspec_t real_chanspec = interpret_chanspec(chanspec, version);
+ if (real_chanspec == INVCHANSPEC) {
+ return false;
+ }
+
+ int band = chanspec & WL_CHANSPEC_BAND_MASK;
+ AntennaId antenna_id;
+ antenna_id.freq = (band == WL_CHANSPEC_BAND_5G) ? ANTENNA_5G : ANTENNA_2G;
+ antenna_id.idx = (rxchain == 1) ? 0 : 1;
+
+ std::memset(out_report, 0, sizeof(histograms_report_t));
+ std::memcpy(out_report->rxsnr, wl_stats_cnt.rxsnr, sizeof(out_report->rxsnr));
+ std::memcpy(out_report->rxnoiseflr, wl_stats_cnt.rxnoiseflr, sizeof(out_report->rxnoiseflr));
+ std::memcpy(out_report->rxrssi, wl_stats_cnt.rxrssi, sizeof(out_report->rxrssi));
+ std::memcpy(out_report->rx11b, wl_stats_cnt.rx11b, sizeof(out_report->rx11b));
+ std::memcpy(out_report->rx11g, wl_stats_cnt.rx11g, sizeof(out_report->rx11g));
+ std::memcpy(out_report->rx11n, wl_stats_cnt.rx11n, sizeof(out_report->rx11n));
+ std::memcpy(out_report->rx11ac, wl_stats_cnt.rx11ac, sizeof(out_report->rx11ac));
+ std::memcpy(&out_report->antennaid, &antenna_id, sizeof(out_report->antennaid));
+ return true;
+}
diff --git a/crossdriver/dhd.h b/crossdriver/dhd.h
index 057dae3..0ad38f9 100644
--- a/crossdriver/dhd.h
+++ b/crossdriver/dhd.h
@@ -26,79 +26,80 @@
#ifndef THIRD_PARTY_BCMDHD_CROSSDRIVER_DHD_H_
#define THIRD_PARTY_BCMDHD_CROSSDRIVER_DHD_H_
-// clang-format off
-
#include <stdint.h>
-#define WSTATS_CNT_T_VERSION 1
-#define WSTATS_RATE_RANGE_11B 4
-#define WSTATS_RATE_RANGE_11G 8
-#define WSTATS_SGI_RANGE 2
-#define WSTATS_BW_RANGE_11N 2
-#define WSTATS_MCS_RANGE_11N 16
-#define WSTATS_BW_RANGE_11AC 3
-#define WSTATS_NSS_RANGE 2
-#define WSTATS_MCS_RANGE_11AC 10
-#define WSTATS_SNR_RANGE 256
-#define WSTATS_NOISE_FLR_RANGE 256
-#define WSTATS_RSSI_RANGE 256
+#include "bcmwifi_channels.h"
+
+#define WSTATS_CNT_T_VERSION 1
+#define WSTATS_RATE_RANGE_11B 4
+#define WSTATS_RATE_RANGE_11G 8
+#define WSTATS_SGI_RANGE 2
+#define WSTATS_BW_RANGE_11N 2
+#define WSTATS_MCS_RANGE_11N 16
+#define WSTATS_BW_RANGE_11AC 3
+#define WSTATS_NSS_RANGE 2
+#define WSTATS_MCS_RANGE_11AC 10
+#define WSTATS_SNR_RANGE 256
+#define WSTATS_NOISE_FLR_RANGE 256
+#define WSTATS_RSSI_RANGE 256
struct wl_wstats_cnt {
- uint16_t version;
- uint16_t length;
+ uint16_t version;
+ uint16_t length;
- /* pkt counters per snr */
- uint32_t rxsnr[WSTATS_SNR_RANGE];
- /* pkt counters per noise floor */
- uint32_t rxnoiseflr[WSTATS_NOISE_FLR_RANGE];
- /* pkt counters per signal level */
- uint32_t rxrssi[WSTATS_RSSI_RANGE];
- /* [RATE 1,2,55,11] */
- uint32_t rx11b[WSTATS_RATE_RANGE_11B];
- /* [RATE 6,9,12,18,24,36,48,54] */
- uint32_t rx11g[WSTATS_RATE_RANGE_11G];
- /* [SGI off/on][BW 20/40][MCS 0-15] */
- uint32_t rx11n[WSTATS_SGI_RANGE]
- [WSTATS_BW_RANGE_11N][WSTATS_MCS_RANGE_11N];
- /* [NSS 1/2][SGI off/on][BW 20/40/80][MCS 0-9] */
- uint32_t rx11ac[WSTATS_NSS_RANGE][WSTATS_SGI_RANGE]
- [WSTATS_BW_RANGE_11AC][WSTATS_MCS_RANGE_11AC];
+ /* pkt counters per snr */
+ uint32_t rxsnr[WSTATS_SNR_RANGE];
+ /* pkt counters per noise floor */
+ uint32_t rxnoiseflr[WSTATS_NOISE_FLR_RANGE];
+ /* pkt counters per signal level */
+ uint32_t rxrssi[WSTATS_RSSI_RANGE];
+ /* [RATE 1,2,55,11] */
+ uint32_t rx11b[WSTATS_RATE_RANGE_11B];
+ /* [RATE 6,9,12,18,24,36,48,54] */
+ uint32_t rx11g[WSTATS_RATE_RANGE_11G];
+ /* [SGI off/on][BW 20/40][MCS 0-15] */
+ uint32_t rx11n[WSTATS_SGI_RANGE][WSTATS_BW_RANGE_11N][WSTATS_MCS_RANGE_11N];
+ /* [NSS 1/2][SGI off/on][BW 20/40/80][MCS 0-9] */
+ uint32_t rx11ac[WSTATS_NSS_RANGE][WSTATS_SGI_RANGE][WSTATS_BW_RANGE_11AC][WSTATS_MCS_RANGE_11AC];
};
using wl_wstats_cnt_t = wl_wstats_cnt;
enum AntennaFreq {
- ANTENNA_2G,
- ANTENNA_5G,
- NUM_ANTENNA_FREQ,
+ ANTENNA_2G,
+ ANTENNA_5G,
+ NUM_ANTENNA_FREQ,
};
struct AntennaId {
- int freq;
- int idx;
+ int freq;
+ int idx;
};
struct histograms_report {
- struct AntennaId antennaid;
+ struct AntennaId antennaid;
- /* pkt counters per snr */
- uint32_t rxsnr[WSTATS_SNR_RANGE];
- /* pkt counters per noise floor */
- uint32_t rxnoiseflr[WSTATS_NOISE_FLR_RANGE];
- /* pkt counters per signal level */
- uint32_t rxrssi[WSTATS_RSSI_RANGE];
- /* [RATE 1,2,55,11]: 0-3 */
- uint32_t rx11b[WSTATS_RATE_RANGE_11B];
- /* [RATE 6,9,12,18,24,36,48,54]: 4-11 */
- uint32_t rx11g[WSTATS_RATE_RANGE_11G];
- /* [SGI off/on][BW 20/40][MCS 0-15]: 12-75 */
- uint32_t rx11n[WSTATS_SGI_RANGE]
- [WSTATS_BW_RANGE_11N][WSTATS_MCS_RANGE_11N];
- /* [NSS 1/2][SGI off/on][BW 20/40/80][MCS 0-9]: */
- uint32_t rx11ac[WSTATS_NSS_RANGE][WSTATS_SGI_RANGE]
- [WSTATS_BW_RANGE_11AC][WSTATS_MCS_RANGE_11AC];
+ /* pkt counters per snr */
+ uint32_t rxsnr[WSTATS_SNR_RANGE];
+ /* pkt counters per noise floor */
+ uint32_t rxnoiseflr[WSTATS_NOISE_FLR_RANGE];
+ /* pkt counters per signal level */
+ uint32_t rxrssi[WSTATS_RSSI_RANGE];
+ /* [RATE 1,2,55,11]: 0-3 */
+ uint32_t rx11b[WSTATS_RATE_RANGE_11B];
+ /* [RATE 6,9,12,18,24,36,48,54]: 4-11 */
+ uint32_t rx11g[WSTATS_RATE_RANGE_11G];
+ /* [SGI off/on][BW 20/40][MCS 0-15]: 12-75 */
+ uint32_t rx11n[WSTATS_SGI_RANGE][WSTATS_BW_RANGE_11N][WSTATS_MCS_RANGE_11N];
+ /* [NSS 1/2][SGI off/on][BW 20/40/80][MCS 0-9]: */
+ uint32_t rx11ac[WSTATS_NSS_RANGE][WSTATS_SGI_RANGE][WSTATS_BW_RANGE_11AC][WSTATS_MCS_RANGE_11AC];
};
using histograms_report_t = histograms_report;
+// Construct a histograms_report_t from the given arguments.
+// Ported from dhd_dev_get_histograms in dhd_linux.c.
+bool get_histograms(wl_wstats_cnt_t wl_stats_cnt, chanspec_t chanspec, uint32_t version,
+ uint32_t rxchain, histograms_report_t* out_report);
+
#endif // THIRD_PARTY_BCMDHD_CROSSDRIVER_DHD_H_
diff --git a/crossdriver/wl_cfg80211.cc b/crossdriver/wl_cfg80211.cc
new file mode 100644
index 0000000..08f2c93
--- /dev/null
+++ b/crossdriver/wl_cfg80211.cc
@@ -0,0 +1,65 @@
+/* Crossdriver (bcmdhd/brcmfmac) logic extracted from bcmdhd wl_cfg80211.c.
+ *
+ * Copyright 1999-2016, Broadcom Corporation
+ * All rights reserved,
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * This software is provided by the copyright holder "as is" and any express or
+ * implied warranties, including, but not limited to, the implied warranties of
+ * merchantability and fitness for a particular purpose are disclaimed. In no event
+ * shall copyright holder be liable for any direct, indirect, incidental, special,
+ * exemplary, or consequential damages (including, but not limited to, procurement
+ * of substitute goods or services; loss of use, data, or profits; or business
+ * interruption) however caused and on any theory of liability, whether in
+ * contract, strict liability, or tort (including negligence or otherwise) arising
+ * in any way out of the use of this software, even if advised of the possibility
+ * of such damage
+ */
+
+#include "wl_cfg80211.h"
+
+#include "bcmwifi_channels.h"
+
+chanspec_t chspec_from_legacy(chanspec_t legacy_chspec) {
+ chanspec_t chspec;
+ /* get the channel number */
+ chspec = LCHSPEC_CHANNEL(legacy_chspec);
+
+ /* convert the band */
+ if (LCHSPEC_IS2G(legacy_chspec)) {
+ chspec |= WL_CHANSPEC_BAND_2G;
+ } else {
+ chspec |= WL_CHANSPEC_BAND_5G;
+ }
+
+ /* convert the bw and sideband */
+ if (LCHSPEC_IS20(legacy_chspec)) {
+ chspec |= WL_CHANSPEC_BW_20;
+ } else {
+ chspec |= WL_CHANSPEC_BW_40;
+ if (LCHSPEC_CTL_SB(legacy_chspec) == WL_LCHANSPEC_CTL_SB_LOWER) {
+ chspec |= WL_CHANSPEC_CTL_SB_L;
+ } else {
+ chspec |= WL_CHANSPEC_CTL_SB_U;
+ }
+ }
+
+ if (chspec_malformed(chspec)) {
+ return INVCHANSPEC;
+ }
+ return chspec;
+}
+
+chanspec_t interpret_chanspec(chanspec_t chanspec, uint32_t version) {
+ if (version == 1) {
+ return chspec_from_legacy(chanspec);
+ }
+ return chanspec;
+}
diff --git a/crossdriver/wl_cfg80211.h b/crossdriver/wl_cfg80211.h
new file mode 100644
index 0000000..c14c1bf
--- /dev/null
+++ b/crossdriver/wl_cfg80211.h
@@ -0,0 +1,39 @@
+/* Crossdriver (bcmdhd/brcmfmac) symbols extracted from bcmdhd wl_cfg80211.h.
+ *
+ * Copyright 1999-2016, Broadcom Corporation
+ * All rights reserved,
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * This software is provided by the copyright holder "as is" and any express or
+ * implied warranties, including, but not limited to, the implied warranties of
+ * merchantability and fitness for a particular purpose are disclaimed. In no event
+ * shall copyright holder be liable for any direct, indirect, incidental, special,
+ * exemplary, or consequential damages (including, but not limited to, procurement
+ * of substitute goods or services; loss of use, data, or profits; or business
+ * interruption) however caused and on any theory of liability, whether in
+ * contract, strict liability, or tort (including negligence or otherwise) arising
+ * in any way out of the use of this software, even if advised of the possibility
+ * of such damage
+ */
+
+#ifndef THIRD_PARTY_BCMDHD_CROSSDRIVER_WL_CFG80211_H_
+#define THIRD_PARTY_BCMDHD_CROSSDRIVER_WL_CFG80211_H_
+
+#include "bcmwifi_channels.h"
+
+// Return a new chanspec given a legacy chanspec.
+// Ported from wl_chspec_from_legacy.
+chanspec_t chspec_from_legacy(chanspec_t legacy_chspec);
+
+// Convert firmware chanspec from legacy chanspec if necessary.
+// Ported from wl_chspec_driver_to_host.
+chanspec_t interpret_chanspec(chanspec_t chanspec, uint32_t version);
+
+#endif // THIRD_PARTY_BCMDHD_CROSSDRIVER_WL_CFG80211_H_