[third_party/bcmdhd] Include additional channel code.
Bug: 59186
Including functions that are related
to determining control channel of a given chanspec.
Change-Id: I7e1b787c41376c9ac6bb9d642f4a5bef8506ba64
Reviewed-on: https://fuchsia-review.googlesource.com/c/third_party/bcmdhd/+/427094
Reviewed-by: Karl Ward <karlward@google.com>
diff --git a/README.fuchsia b/README.fuchsia
index e9c120c..ccf2cbd 100644
--- a/README.fuchsia
+++ b/README.fuchsia
@@ -14,6 +14,8 @@
* Extracted cross-driver (bcmdhd/brcmfmac) symbols into crossdriver/dhd.h
* Extracted cross-driver (bcmdhd/brcmfmac) symbols into crossdriver/bcmwifi_channels.h
* Added crossdriver/BUILD.gn
+* fxr/427094
+ * Extracted additional cross-driver (bcmdhd/brcmfmac) symbols into crossdriver/bcmwifi_channels.cc
Description:
diff --git a/crossdriver/bcmwifi_channels.cc b/crossdriver/bcmwifi_channels.cc
index e85883e..742d629 100644
--- a/crossdriver/bcmwifi_channels.cc
+++ b/crossdriver/bcmwifi_channels.cc
@@ -25,6 +25,13 @@
#include "bcmwifi_channels.h"
+#include <zircon/errors.h>
+#include <zircon/status.h>
+
+static const uint8_t chspec_bw_mhz[] = {5, 10, 20, 40, 80, 160, 160};
+
+#define WF_NUM_BW (sizeof(chspec_bw_mhz) / sizeof(uint8_t))
+
bool chspec_malformed(chanspec_t chanspec) {
uint16_t chspec_bw = CHSPEC_BW(chanspec);
uint16_t chspec_ch = CHSPEC_CHANNEL(chanspec);
@@ -77,3 +84,63 @@
}
return false;
}
+
+// bw in MHz, return the channel count from the center channel to the the channel at the edge of the
+// band
+static uint8_t center_chan_to_edge(uint32_t bw) {
+ // edge channels separated by BW - 10MHz on each side delta from cf to edge is half of that, MHz
+ // to channel num conversion is 5MHz/channel
+ return (uint8_t)(((bw - 20) / 2) / 5);
+}
+
+// return channel number of the low edge of the band given the center channel and BW
+static uint8_t channel_low_edge(uint32_t center_ch, uint32_t bw) {
+ return (uint8_t)(center_ch - center_chan_to_edge(bw));
+}
+
+// return control channel given center channel and side band
+static uint8_t channel_to_ctl_chan(uint32_t center_ch, uint32_t bw, uint32_t sb) {
+ return (uint8_t)(channel_low_edge(center_ch, bw) + sb * 4);
+}
+
+// convert bandwidth from chanspec to MHz
+static uint32_t bw_chspec_to_mhz(chanspec_t chspec) {
+ uint32_t bw;
+
+ bw = (chspec & WL_CHANSPEC_BW_MASK) >> WL_CHANSPEC_BW_SHIFT;
+ return (bw >= WF_NUM_BW ? 0 : chspec_bw_mhz[bw]);
+}
+
+// Return the control channel of the given chanspec.
+zx_status_t chspec_ctlchan(chanspec_t chspec, uint8_t* ctrl_chan) {
+ uint32_t center_chan;
+ uint32_t bw_mhz;
+ uint32_t sb;
+
+ if (chspec_malformed(chspec) || ctrl_chan == nullptr)
+ return ZX_ERR_INVALID_ARGS;
+
+ // Is there a sideband ?
+ if (CHSPEC_BW_LE20(chspec)) {
+ *ctrl_chan = CHSPEC_CHANNEL(chspec);
+ } else {
+ sb = CHSPEC_CTL_SB(chspec) >> WL_CHANSPEC_CTL_SB_SHIFT;
+
+ if (CHSPEC_IS8080(chspec)) {
+ // For an 80+80 MHz channel, the sideband 'sb' field is an 80 MHz sideband (LL, LU, UL, LU)
+ // for the 80 MHz frequency segment 0.
+ uint32_t chan_id = CHSPEC_CHAN1(chspec);
+
+ bw_mhz = 80;
+
+ // convert from channel index to channel number
+ center_chan = wf_5g_80m_chans[chan_id];
+ } else {
+ bw_mhz = bw_chspec_to_mhz(chspec);
+ center_chan = CHSPEC_CHANNEL(chspec) >> WL_CHANSPEC_CHAN_SHIFT;
+ }
+
+ *ctrl_chan = channel_to_ctl_chan(center_chan, bw_mhz, sb);
+ }
+ return ZX_OK;
+}
diff --git a/crossdriver/bcmwifi_channels.h b/crossdriver/bcmwifi_channels.h
index cde38ce..21f0e2a 100644
--- a/crossdriver/bcmwifi_channels.h
+++ b/crossdriver/bcmwifi_channels.h
@@ -27,6 +27,7 @@
#define THIRD_PARTY_BCMDHD_CROSSDRIVER_BCMWIFI_CHANNELS_H_
#include <stdint.h>
+#include <zircon/status.h>
/* A chanspec holds the channel number, band, bandwidth and control sideband */
using chanspec_t = uint16_t;
@@ -166,6 +167,7 @@
#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_BW_LE20(chspec) (BW_LE20(CHSPEC_BW(chspec)))
#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)
@@ -236,4 +238,9 @@
*/
bool chspec_malformed(chanspec_t chanspec);
+// 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. Ported from wf_chspec_ctlchan().
+zx_status_t chspec_ctlchan(chanspec_t chspec, uint8_t* ctrl_chan);
+
#endif // THIRD_PARTY_BCMDHD_CROSSDRIVER_BCMWIFI_CHANNELS_H_