From f3128e46315c9d6ed5d8a27106ec7bde7da873de Mon Sep 17 00:00:00 2001 From: Marek Puzyniak <marek.puzyniak@iopsys.eu> Date: Mon, 25 Jan 2021 09:47:30 +0000 Subject: [PATCH] libwifi: brcm: fix wrong oper stds for 5G If there is no DS information element then function eveluating operating standards should fail. In that case falback function will be used which will use iovar commands. Signed-off-by: Marek Puzyniak <marek.puzyniak@iopsys.eu> --- libwifi/modules/broadcom/wlctrl.c | 110 +++++++++++++++++++++++++++++- libwifi/modules/broadcom/wlctrl.h | 1 + libwifi/util.c | 2 + 3 files changed, 112 insertions(+), 1 deletion(-) diff --git a/libwifi/modules/broadcom/wlctrl.c b/libwifi/modules/broadcom/wlctrl.c index 04610d8f..036c3e0f 100644 --- a/libwifi/modules/broadcom/wlctrl.c +++ b/libwifi/modules/broadcom/wlctrl.c @@ -697,7 +697,9 @@ int bcmwl_iface_ap_info(const char *name, struct wifi_ap *ap) ies_len = beacon_len - ((uint8_t *)&bf->cap_info - beacon + 2); beacon_ies = bf->var; - WARN_ON(wifi_oper_stds_set_from_ie(beacon_ies, ies_len, &ap->bss.oper_std)); + ret = wifi_oper_stds_set_from_ie(beacon_ies, ies_len, &ap->bss.oper_std); + if (ret) + WARN_ON(bcmwl_get_oper_stds(name, &ap->bss.oper_std)); WARN_ON(wifi_ssid_advertised_set_from_ie(beacon_ies, ies_len, &ap->ssid_advertised)); WARN_ON(wifi_get_bss_security_from_ies(&ap->bss, beacon_ies, ies_len)); WARN_ON(wifi_apload_set_from_ie(beacon_ies, ies_len, &ap->bss.load)); @@ -775,9 +777,115 @@ int bcmwl_ap_get_oper_stds(const char *name, uint8_t *std) ret = wifi_oper_stds_set_from_ie(beacon_ies, ies_len, std); + if (ret == 0) { + return 0; + } + + ret = bcmwl_get_oper_stds(name, std); + if (WARN_ON(ret)) { return ret; } return 0; } + +int bcmwl_get_oper_band(const char *name, enum wifi_band *band) +{ + uint32_t val, b; + int ret; + struct wl_arg arg = { + .ifname = name, + .cmd = WLC_GET_BAND, + .buf = &val, + .buflen = sizeof(val) + }; + + libwifi_dbg("[%s] %s called (vendor)\n", name, __func__); + + ret = wl_vendor(&arg); + + if (ret) { + libwifi_dbg("[%s] %s fallback to ioctl\n", name, __func__); + ret = wl_ioctl(&arg); + } + + if (ret) { + *band = BAND_UNKNOWN; + return ret; + } + + b = wl_swap_32(name, val); + + switch (b) { + case 1: + *band = BAND_5; + break; + case 2: + *band = BAND_2; + break; + case 0: + *band = BAND_DUAL; + break; + default: + *band = BAND_UNKNOWN; + break; + } + + return ret; +} + +int bcmwl_get_oper_stds(const char *name, uint8_t *std) +{ + int ret; + enum wifi_band band; + uint32_t nmode = 0; + uint32_t vhtmode = 0; + uint32_t he = 0; + + libwifi_dbg("[%s] %s called\n", name, __func__); + + if (!std) + return -EINVAL; + + *std = 0; + + WARN_ON(ret = bcmwl_get_oper_band(name, &band)); + if (ret) + goto exit; + + WARN_ON(ret = wl_iovar_get(name, "nmode", NULL, 0, &nmode, sizeof(nmode))); + if (ret) + goto exit; + + WARN_ON(ret = wl_iovar_get(name, "vhtmode", NULL, 0, &vhtmode, sizeof(vhtmode))); + if (ret) + goto exit;; + + WARN_ON(ret = wl_iovar_get(name, "he", NULL, 0, &he, sizeof(he))); + if (ret) + goto exit; + + if (he) { + *std |= WIFI_AX; + } + + if (vhtmode) { + *std |= WIFI_AC; + } + + if (nmode) { + *std |= WIFI_N; + } + + if (band == BAND_5) { + *std |= WIFI_A; + } + + if (band == BAND_2) { + *std |= WIFI_G; + } + +exit: + return ret; +} diff --git a/libwifi/modules/broadcom/wlctrl.h b/libwifi/modules/broadcom/wlctrl.h index 3ec7754f..7f540758 100644 --- a/libwifi/modules/broadcom/wlctrl.h +++ b/libwifi/modules/broadcom/wlctrl.h @@ -10,5 +10,6 @@ int bcmwl_get_bss_supported_security(const char *name, uint32_t *sec); int bcmwl_iface_get_beacon_ies(const char *name, uint8_t *ies, int *len); int bcmwl_iface_ap_info(const char *name, struct wifi_ap *ap); int bcmwl_ap_get_oper_stds(const char *name, uint8_t *std); +int bcmwl_get_oper_stds(const char *name, uint8_t *std); #endif /* WLCTRL_H */ diff --git a/libwifi/util.c b/libwifi/util.c index e433c67c..5c7fc86b 100644 --- a/libwifi/util.c +++ b/libwifi/util.c @@ -788,6 +788,8 @@ int wifi_oper_stds_set_from_ie(uint8_t *ies, size_t ies_len, uint8_t *std) if (ds && ds[1] == 1) { channel = ds[2]; + } else { + return -1; } *std = 0; -- GitLab