-/* $OpenBSD: bwfm.c,v 1.29 2018/01/08 23:30:11 patrick Exp $ */
+/* $OpenBSD: bwfm.c,v 1.30 2018/01/11 19:33:34 patrick Exp $ */
/*
* Copyright (c) 2010-2016 Broadcom Corporation
* Copyright (c) 2016,2017 Patrick Wildt <patrick@blueri.se>
int bwfm_fwvar_var_get_int(struct bwfm_softc *, char *, uint32_t *);
int bwfm_fwvar_var_set_int(struct bwfm_softc *, char *, uint32_t);
+uint32_t bwfm_spec2chan(struct bwfm_softc *, uint32_t);
+uint32_t bwfm_spec2chan_d11n(struct bwfm_softc *, uint32_t);
+uint32_t bwfm_spec2chan_d11ac(struct bwfm_softc *, uint32_t);
+
void bwfm_connect(struct bwfm_softc *);
#ifndef IEEE80211_STA_ONLY
void bwfm_hostap(struct bwfm_softc *);
return bwfm_fwvar_var_set_data(sc, name, &data, sizeof(data));
}
+/* Channel parameters */
+uint32_t
+bwfm_spec2chan(struct bwfm_softc *sc, uint32_t chanspec)
+{
+ if (sc->sc_io_type == BWFM_IO_TYPE_D11N)
+ return bwfm_spec2chan_d11n(sc, chanspec);
+ else
+ return bwfm_spec2chan_d11ac(sc, chanspec);
+}
+
+uint32_t
+bwfm_spec2chan_d11n(struct bwfm_softc *sc, uint32_t chanspec)
+{
+ uint32_t chanidx;
+
+ chanidx = chanspec & BWFM_CHANSPEC_CHAN_MASK;
+
+ switch (chanspec & BWFM_CHANSPEC_D11N_BW_MASK) {
+ case BWFM_CHANSPEC_D11N_BW_40:
+ switch (chanspec & BWFM_CHANSPEC_D11N_SB_MASK) {
+ case BWFM_CHANSPEC_D11N_SB_L:
+ chanidx -= 2;
+ break;
+ case BWFM_CHANSPEC_D11N_SB_U:
+ chanidx += 2;
+ break;
+ default:
+ break;
+ }
+ break;
+ default:
+ break;
+ }
+
+ return chanidx;
+}
+
+uint32_t
+bwfm_spec2chan_d11ac(struct bwfm_softc *sc, uint32_t chanspec)
+{
+ uint32_t chanidx;
+
+ chanidx = chanspec & BWFM_CHANSPEC_CHAN_MASK;
+
+ switch (chanspec & BWFM_CHANSPEC_D11AC_BW_MASK) {
+ case BWFM_CHANSPEC_D11AC_BW_40:
+ switch (chanspec & BWFM_CHANSPEC_D11AC_SB_MASK) {
+ case BWFM_CHANSPEC_D11AC_SB_LLL:
+ chanidx -= 2;
+ break;
+ case BWFM_CHANSPEC_D11AC_SB_LLU:
+ chanidx += 2;
+ break;
+ default:
+ break;
+ }
+ break;
+ case BWFM_CHANSPEC_D11AC_BW_80:
+ switch (chanspec & BWFM_CHANSPEC_D11AC_SB_MASK) {
+ case BWFM_CHANSPEC_D11AC_SB_LLL:
+ chanidx -= 6;
+ break;
+ case BWFM_CHANSPEC_D11AC_SB_LLU:
+ chanidx -= 2;
+ break;
+ case BWFM_CHANSPEC_D11AC_SB_LUL:
+ chanidx += 2;
+ break;
+ case BWFM_CHANSPEC_D11AC_SB_LUU:
+ chanidx += 6;
+ break;
+ default:
+ break;
+ }
+ break;
+ default:
+ break;
+ }
+
+ return chanidx;
+}
+
/* 802.11 code */
void
bwfm_connect(struct bwfm_softc *sc)
{
struct ieee80211com *ic = &sc->sc_ic;
struct ifnet *ifp = &ic->ic_if;
- struct ieee80211_rxinfo rxi;
struct ieee80211_frame *wh;
struct ieee80211_node *ni;
+ struct ieee80211_rxinfo rxi;
+ struct ieee80211_channel *bss_chan;
struct mbuf *m;
uint32_t pktlen, ieslen;
uint16_t iesoff;
+ int chanidx;
iesoff = letoh16(bss->ie_offset);
ieslen = letoh32(bss->ie_length);
/* Finalize mbuf. */
m->m_pkthdr.len = m->m_len = pktlen;
ni = ieee80211_find_rxnode(ic, wh);
+ /*
+ * We may switch ic_bss's channel during scans.
+ * Record the current channel so we can restore it later.
+ */
+ bss_chan = NULL;
+ if (ni == ic->ic_bss)
+ bss_chan = ni->ni_chan;
+ /* Channel mask equals IEEE80211_CHAN_MAX */
+ chanidx = bwfm_spec2chan(sc, letoh32(bss->chanspec));
+ ni->ni_chan = &ic->ic_channels[chanidx];
+ /* Supply RSSI */
rxi.rxi_flags = 0;
rxi.rxi_rssi = letoh32(bss->rssi);
rxi.rxi_tstamp = 0;
ieee80211_input(ifp, m, ni, &rxi);
+ /* Restore channel */
+ if (bss_chan)
+ ni->ni_chan = bss_chan;
/* Node is no longer needed. */
ieee80211_release_node(ic, ni);
}
-/* $OpenBSD: bwfmreg.h,v 1.13 2018/01/08 23:30:11 patrick Exp $ */
+/* $OpenBSD: bwfmreg.h,v 1.14 2018/01/11 19:33:34 patrick Exp $ */
/*
* Copyright (c) 2010-2016 Broadcom Corporation
* Copyright (c) 2016,2017 Patrick Wildt <patrick@blueri.se>
/* Channel Parameters */
#define BWFM_CHANSPEC_CHAN_MASK 0xff
#define BWFM_CHANSPEC_CHAN_SHIFT 0
+#define BWFM_CHANSPEC_D11N_SB_L (0x1 << 8) /* control lower */
+#define BWFM_CHANSPEC_D11N_SB_U (0x2 << 8) /* control lower */
+#define BWFM_CHANSPEC_D11N_SB_N (0x3 << 8) /* none */
+#define BWFM_CHANSPEC_D11N_SB_MASK (0x3 << 8)
+#define BWFM_CHANSPEC_D11N_SB_SHIFT 8
+#define BWFM_CHANSPEC_D11N_BW_10 (0x1 << 10)
+#define BWFM_CHANSPEC_D11N_BW_20 (0x2 << 10)
+#define BWFM_CHANSPEC_D11N_BW_40 (0x3 << 10)
+#define BWFM_CHANSPEC_D11N_BW_MASK (0x3 << 10)
+#define BWFM_CHANSPEC_D11N_BW_SHIFT 10
+#define BWFM_CHANSPEC_D11N_BND_5G (0x1 << 12)
+#define BWFM_CHANSPEC_D11N_BND_2G (0x2 << 12)
+#define BWFM_CHANSPEC_D11N_BND_MASK (0x3 << 12)
+#define BWFM_CHANSPEC_D11N_BND_SHIFT 12
+#define BWFM_CHANSPEC_D11AC_SB_LLL (0x0 << 8)
+#define BWFM_CHANSPEC_D11AC_SB_LLU (0x1 << 8)
+#define BWFM_CHANSPEC_D11AC_SB_LUL (0x2 << 8)
+#define BWFM_CHANSPEC_D11AC_SB_LUU (0x3 << 8)
+#define BWFM_CHANSPEC_D11AC_SB_ULL (0x4 << 8)
+#define BWFM_CHANSPEC_D11AC_SB_ULU (0x5 << 8)
+#define BWFM_CHANSPEC_D11AC_SB_UUL (0x6 << 8)
+#define BWFM_CHANSPEC_D11AC_SB_UUU (0x7 << 8)
+#define BWFM_CHANSPEC_D11AC_SB_MASK (0x7 << 8)
+#define BWFM_CHANSPEC_D11AC_SB_SHIFT 8
+#define BWFM_CHANSPEC_D11AC_BW_5 (0x0 << 11)
+#define BWFM_CHANSPEC_D11AC_BW_10 (0x1 << 11)
+#define BWFM_CHANSPEC_D11AC_BW_20 (0x2 << 11)
+#define BWFM_CHANSPEC_D11AC_BW_40 (0x3 << 11)
+#define BWFM_CHANSPEC_D11AC_BW_80 (0x4 << 11)
+#define BWFM_CHANSPEC_D11AC_BW_160 (0x5 << 11)
+#define BWFM_CHANSPEC_D11AC_BW_8080 (0x6 << 11)
+#define BWFM_CHANSPEC_D11AC_BW_MASK (0x7 << 11)
+#define BWFM_CHANSPEC_D11AC_BW_SHIFT 11
+#define BWFM_CHANSPEC_D11AC_BND_2G (0x0 << 14)
+#define BWFM_CHANSPEC_D11AC_BND_3G (0x1 << 14)
+#define BWFM_CHANSPEC_D11AC_BND_4G (0x2 << 14)
+#define BWFM_CHANSPEC_D11AC_BND_5G (0x3 << 14)
+#define BWFM_CHANSPEC_D11AC_BND_MASK (0x3 << 14)
+#define BWFM_CHANSPEC_D11AC_BND_SHIFT 14
+
#define BWFM_BAND_AUTO 0
#define BWFM_BAND_5G 1
#define BWFM_BAND_2G 2