]> git.ipfire.org Git - thirdparty/hostap.git/commitdiff
nl80211: Add ACS support for Broadcom device
authorXinrui Sun <xinrui.sun@broadcom.com>
Fri, 12 Jun 2020 12:49:07 +0000 (20:49 +0800)
committerJouni Malinen <j@w1.fi>
Sat, 27 Feb 2021 10:14:09 +0000 (12:14 +0200)
BRCM vendor command used to trigger ACS scan. After ACS finished,
DHD driver will send results by event BRCM_VENDOR_EVENT_ACS.

Signed-off-by: Xinrui Sun <xinrui.sun@broadcom.com>
hostapd/android.config
src/common/brcm_vendor.h [new file with mode: 0644]
src/drivers/driver_nl80211.c
src/drivers/driver_nl80211_capa.c
src/drivers/driver_nl80211_event.c
src/drivers/drivers.mak
src/drivers/drivers.mk

index 7bd792efe9a9dccd5b30368d65dc7ed14b82c1ea..c8b3afabef8ddb8fce6c794a49acaddfa1512398 100644 (file)
@@ -28,6 +28,9 @@ CONFIG_LIBNL20=y
 # QCA vendor extensions to nl80211
 CONFIG_DRIVER_NL80211_QCA=y
 
+# Broadcom vendor extensions to nl80211
+#CONFIG_DRIVER_NL80211_BRCM=y
+
 # Driver interface for FreeBSD net80211 layer (e.g., Atheros driver)
 #CONFIG_DRIVER_BSD=y
 #CFLAGS += -I/usr/local/include
diff --git a/src/common/brcm_vendor.h b/src/common/brcm_vendor.h
new file mode 100644 (file)
index 0000000..f163dea
--- /dev/null
@@ -0,0 +1,156 @@
+/*
+ * Broadcom Corporation OUI and vendor specific assignments
+ * Copyright (c) 2020, Broadcom Corporation.
+ *
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
+ */
+
+#ifndef BRCM_VENDOR_H
+#define BRCM_VENDOR_H
+
+/*
+ * This file is a registry of identifier assignments from the Broadcom
+ * OUI 00:10:18 for purposes other than MAC address assignment. New identifiers
+ * can be assigned through normal review process for changes to the upstream
+ * hostap.git repository.
+ */
+
+#define OUI_BRCM    0x001018
+
+/**
+ * enum brcm_nl80211_vendor_subcmds - BRCM nl80211 vendor command identifiers
+ *
+ * @BRCM_VENDOR_SCMD_UNSPEC: Reserved value 0
+ *
+ * @BRCM_VENDOR_SCMD_PRIV_STR: Provide vendor private cmds to send to FW.
+ *
+ * @BRCM_VENDOR_SCMD_BCM_STR:  Provide vendor cmds to BCMDHD driver.
+ *
+ * @BRCM_VENDOR_SCMD_BCM_PSK: Used to set SAE password.
+ *
+ * @BRCM_VENDOR_SCMD_SET_PMK: Command to check driver support
+ *     for DFS offloading.
+ *
+ * @BRCM_VENDOR_SCMD_GET_FEATURES: Command to get the features
+ *      supported by the driver.
+ *
+ * @BRCM_VENDOR_SCMD_SET_MAC: Set random mac address for P2P interface.
+ *
+ * @BRCM_VENDOR_SCMD_SET_CONNECT_PARAMS: Set some connect parameters.
+ *      Used for the case that FW handle SAE.
+ *
+ * @BRCM_VENDOR_SCMD_SET_START_AP_PARAMS: Set SoftAP paramters.
+ *      Used for the case that FW handle SAE.
+ *
+ * @BRCM_VENDOR_SCMD_ACS: ACS command/event which is used to
+ *     invoke the ACS function in device and pass selected channels to
+ *     hostapd. Uses enum qca_wlan_vendor_attr_acs_offload attributes.
+ *
+ * @BRCM_VENDOR_SCMD_MAX: This acts as a the tail of cmds list.
+ *      Make sure it located at the end of the list.
+ *
+ */
+enum brcm_nl80211_vendor_subcmds {
+       BRCM_VENDOR_SCMD_UNSPEC                 = 0,
+       BRCM_VENDOR_SCMD_PRIV_STR               = 1,
+       BRCM_VENDOR_SCMD_BCM_STR                = 2,
+       BRCM_VENDOR_SCMD_BCM_PSK                = 3,
+       BRCM_VENDOR_SCMD_SET_PMK                = 4,
+       BRCM_VENDOR_SCMD_GET_FEATURES           = 5,
+       BRCM_VENDOR_SCMD_SET_MAC                = 6,
+       BRCM_VENDOR_SCMD_SET_CONNECT_PARAMS     = 7,
+       BRCM_VENDOR_SCMD_SET_START_AP_PARAMS    = 8,
+       BRCM_VENDOR_SCMD_ACS                    = 9,
+       BRCM_VENDOR_SCMD_MAX                    = 10
+};
+
+/**
+ * enum brcm_nl80211_vendor_events - BRCM nl80211 asynchoronous event identifiers
+ *
+ * @BRCM_VENDOR_EVENT_UNSPEC: Reserved value 0
+ *
+ * @BRCM_VENDOR_EVENT_PRIV_STR: String command/event
+ */
+enum brcm_nl80211_vendor_events {
+       BRCM_VENDOR_EVENT_UNSPEC                = 0,
+       BRCM_VENDOR_EVENT_PRIV_STR              = 1,
+       GOOGLE_GSCAN_SIGNIFICANT_EVENT          = 2,
+       GOOGLE_GSCAN_GEOFENCE_FOUND_EVENT       = 3,
+       GOOGLE_GSCAN_BATCH_SCAN_EVENT           = 4,
+       GOOGLE_SCAN_FULL_RESULTS_EVENT          = 5,
+       GOOGLE_RTT_COMPLETE_EVENT               = 6,
+       GOOGLE_SCAN_COMPLETE_EVENT              = 7,
+       GOOGLE_GSCAN_GEOFENCE_LOST_EVENT        = 8,
+       GOOGLE_SCAN_EPNO_EVENT                  = 9,
+       GOOGLE_DEBUG_RING_EVENT                 = 10,
+       GOOGLE_FW_DUMP_EVENT                    = 11,
+       GOOGLE_PNO_HOTSPOT_FOUND_EVENT          = 12,
+       GOOGLE_RSSI_MONITOR_EVENT               = 13,
+       GOOGLE_MKEEP_ALIVE_EVENT                = 14,
+
+       /*
+        * BRCM specific events should be placed after
+        * the Generic events so that enums don't mismatch
+        * between the DHD and HAL
+        */
+       GOOGLE_NAN_EVENT_ENABLED                = 15,
+       GOOGLE_NAN_EVENT_DISABLED               = 16,
+       GOOGLE_NAN_EVENT_SUBSCRIBE_MATCH        = 17,
+       GOOGLE_NAN_EVENT_REPLIED                = 18,
+       GOOGLE_NAN_EVENT_PUBLISH_TERMINATED     = 19,
+       GOOGLE_NAN_EVENT_SUBSCRIBE_TERMINATED   = 20,
+       GOOGLE_NAN_EVENT_DE_EVENT               = 21,
+       GOOGLE_NAN_EVENT_FOLLOWUP               = 22,
+       GOOGLE_NAN_EVENT_TRANSMIT_FOLLOWUP_IND  = 23,
+       GOOGLE_NAN_EVENT_DATA_REQUEST           = 24,
+       GOOGLE_NAN_EVENT_DATA_CONFIRMATION      = 25,
+       GOOGLE_NAN_EVENT_DATA_END               = 26,
+       GOOGLE_NAN_EVENT_BEACON                 = 27,
+       GOOGLE_NAN_EVENT_SDF                    = 28,
+       GOOGLE_NAN_EVENT_TCA                    = 29,
+       GOOGLE_NAN_EVENT_SUBSCRIBE_UNMATCH      = 30,
+       GOOGLE_NAN_EVENT_UNKNOWN                = 31,
+       GOOGLE_ROAM_EVENT_START                 = 32,
+       BRCM_VENDOR_EVENT_HANGED                = 33,
+       BRCM_VENDOR_EVENT_SAE_KEY               = 34,
+       BRCM_VENDOR_EVENT_BEACON_RECV           = 35,
+       BRCM_VENDOR_EVENT_PORT_AUTHORIZED       = 36,
+       GOOGLE_FILE_DUMP_EVENT                  = 37,
+       BRCM_VENDOR_EVENT_CU                    = 38,
+       BRCM_VENDOR_EVENT_WIPS                  = 39,
+       NAN_ASYNC_RESPONSE_DISABLED             = 40,
+       BRCM_VENDOR_EVENT_RCC_INFO              = 41,
+       BRCM_VENDOR_EVENT_ACS                   = 42,
+       BRCM_VENDOR_EVENT_LAST
+
+};
+
+#ifdef CONFIG_BRCM_SAE
+enum wifi_sae_key_attr {
+       BRCM_SAE_KEY_ATTR_BSSID,
+       BRCM_SAE_KEY_ATTR_PMK,
+       BRCM_SAE_KEY_ATTR_PMKID
+};
+#endif /* CONFIG_BRCM_SAE */
+
+enum wl_vendor_attr_acs_offload {
+       BRCM_VENDOR_ATTR_ACS_CHANNEL_INVALID = 0,
+       BRCM_VENDOR_ATTR_ACS_PRIMARY_FREQ,
+       BRCM_VENDOR_ATTR_ACS_SECONDARY_FREQ,
+       BRCM_VENDOR_ATTR_ACS_VHT_SEG0_CENTER_CHANNEL,
+       BRCM_VENDOR_ATTR_ACS_VHT_SEG1_CENTER_CHANNEL,
+
+       BRCM_VENDOR_ATTR_ACS_HW_MODE,
+       BRCM_VENDOR_ATTR_ACS_HT_ENABLED,
+       BRCM_VENDOR_ATTR_ACS_HT40_ENABLED,
+       BRCM_VENDOR_ATTR_ACS_VHT_ENABLED,
+       BRCM_VENDOR_ATTR_ACS_CHWIDTH,
+       BRCM_VENDOR_ATTR_ACS_CH_LIST,
+       BRCM_VENDOR_ATTR_ACS_FREQ_LIST,
+
+       BRCM_VENDOR_ATTR_ACS_LAST
+};
+
+
+#endif /* BRCM_VENDOR_H */
index 8342eb8a9ad0a759649510344bef92d8c656c5b5..59052a94e95be3842d6a13910bd3ad153417d237 100644 (file)
@@ -27,6 +27,7 @@
 #include "eloop.h"
 #include "common/qca-vendor.h"
 #include "common/qca-vendor-attr.h"
+#include "common/brcm_vendor.h"
 #include "common/ieee802_11_defs.h"
 #include "common/ieee802_11_common.h"
 #include "common/wpa_common.h"
@@ -11605,6 +11606,60 @@ fail:
 #endif /* CONFIG_DRIVER_NL80211_QCA */
 
 
+#ifdef CONFIG_DRIVER_NL80211_BRCM
+static int wpa_driver_do_broadcom_acs(void *priv, struct drv_acs_params *params)
+{
+       struct i802_bss *bss = priv;
+       struct wpa_driver_nl80211_data *drv = bss->drv;
+       struct nl_msg *msg;
+       struct nlattr *data;
+       int freq_list_len;
+       int ret = -1;
+
+       freq_list_len = int_array_len(params->freq_list);
+       wpa_printf(MSG_DEBUG, "%s: freq_list_len=%d",
+                  __func__, freq_list_len);
+
+       msg = nl80211_drv_msg(drv, 0, NL80211_CMD_VENDOR);
+       if (!msg ||
+           nla_put_u32(msg, NL80211_ATTR_VENDOR_ID, OUI_BRCM) ||
+           nla_put_u32(msg, NL80211_ATTR_VENDOR_SUBCMD,
+                       BRCM_VENDOR_SCMD_ACS) ||
+           !(data = nla_nest_start(msg, NL80211_ATTR_VENDOR_DATA)) ||
+           nla_put_u8(msg, BRCM_VENDOR_ATTR_ACS_HW_MODE, params->hw_mode) ||
+           nla_put_u8(msg, BRCM_VENDOR_ATTR_ACS_HT_ENABLED,
+                      params->ht_enabled) ||
+           nla_put_u8(msg, BRCM_VENDOR_ATTR_ACS_HT40_ENABLED,
+                      params->ht40_enabled) ||
+           nla_put_u8(msg, BRCM_VENDOR_ATTR_ACS_VHT_ENABLED,
+                      params->vht_enabled) ||
+           nla_put_u16(msg, BRCM_VENDOR_ATTR_ACS_CHWIDTH, params->ch_width) ||
+           (freq_list_len > 0 &&
+            nla_put(msg, BRCM_VENDOR_ATTR_ACS_FREQ_LIST,
+                    sizeof(int) * freq_list_len, params->freq_list)))
+               goto fail;
+       nla_nest_end(msg, data);
+
+       wpa_printf(MSG_DEBUG,
+                  "nl80211: ACS Params: HW_MODE: %d HT: %d HT40: %d VHT: %d BW: %d",
+                  params->hw_mode, params->ht_enabled, params->ht40_enabled,
+                  params->vht_enabled, params->ch_width);
+
+       ret = send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL);
+       if (ret) {
+               wpa_printf(MSG_ERROR,
+                          "nl80211: BRCM Failed to invoke driver ACS function: %s",
+                          strerror(errno));
+       }
+
+       msg = NULL;
+fail:
+       nlmsg_free(msg);
+       return ret;
+}
+#endif /* CONFIG_DRIVER_NL80211_BRCM */
+
+
 static int nl80211_write_to_file(const char *name, unsigned int val)
 {
        int fd, len;
@@ -12050,6 +12105,9 @@ const struct wpa_driver_ops wpa_driver_nl80211_ops = {
        .set_bssid_tmp_disallow = nl80211_set_bssid_tmp_disallow,
        .add_sta_node = nl80211_add_sta_node,
 #endif /* CONFIG_DRIVER_NL80211_QCA */
+#ifdef CONFIG_DRIVER_NL80211_BRCM
+       .do_acs = wpa_driver_do_broadcom_acs,
+#endif /* CONFIG_DRIVER_NL80211_BRCM */
        .configure_data_frame_filters = nl80211_configure_data_frame_filters,
        .get_ext_capab = nl80211_get_ext_capab,
        .update_connect_params = nl80211_update_connection_params,
index 1b57c0e88b69ce6f080f07cc52ac911ec0036757..7dac62b4e990273ab2d9ab57000ffc2224d1d0d7 100644 (file)
@@ -16,6 +16,7 @@
 #include "common/wpa_common.h"
 #include "common/qca-vendor.h"
 #include "common/qca-vendor-attr.h"
+#include "common/brcm_vendor.h"
 #include "driver_nl80211.h"
 
 
@@ -1019,6 +1020,16 @@ static int wiphy_info_handler(struct nl_msg *msg, void *arg)
                                        break;
 #endif /* CONFIG_DRIVER_NL80211_QCA */
                                }
+#ifdef CONFIG_DRIVER_NL80211_BRCM
+                       } else if (vinfo->vendor_id == OUI_BRCM) {
+                               switch (vinfo->subcmd) {
+                               case BRCM_VENDOR_SCMD_ACS:
+                                       drv->capa.flags |=
+                                               WPA_DRIVER_FLAGS_ACS_OFFLOAD;
+                                       wpa_printf(MSG_DEBUG,
+                                                  "Enabled BRCM ACS");
+                               }
+#endif /* CONFIG_DRIVER_NL80211_BRCM */
                        }
 
                        wpa_printf(MSG_DEBUG, "nl80211: Supported vendor command: vendor_id=0x%x subcmd=%u",
index c971001ae0b93d6e9cd8de32ea8221102e1caf57..c6f3e0ef6b8aeeaeb7ad0465aff03bcc458bedc9 100644 (file)
@@ -15,6 +15,7 @@
 #include "utils/eloop.h"
 #include "common/qca-vendor.h"
 #include "common/qca-vendor-attr.h"
+#include "common/brcm_vendor.h"
 #include "common/ieee802_11_defs.h"
 #include "common/ieee802_11_common.h"
 #include "driver_nl80211.h"
@@ -2381,6 +2382,87 @@ static void nl80211_vendor_event_qca(struct wpa_driver_nl80211_data *drv,
 }
 
 
+#ifdef CONFIG_DRIVER_NL80211_BRCM
+
+static void brcm_nl80211_acs_select_ch(struct wpa_driver_nl80211_data *drv,
+                                      const u8 *data, size_t len)
+{
+       struct nlattr *tb[BRCM_VENDOR_ATTR_ACS_LAST + 1];
+       union wpa_event_data event;
+
+       wpa_printf(MSG_DEBUG,
+                  "nl80211: BRCM ACS channel selection vendor event received");
+
+       if (nla_parse(tb, BRCM_VENDOR_ATTR_ACS_LAST, (struct nlattr *) data,
+                     len, NULL) ||
+           !tb[BRCM_VENDOR_ATTR_ACS_PRIMARY_FREQ] ||
+           !tb[BRCM_VENDOR_ATTR_ACS_SECONDARY_FREQ])
+               return;
+
+       os_memset(&event, 0, sizeof(event));
+       if (tb[BRCM_VENDOR_ATTR_ACS_PRIMARY_FREQ])
+               event.acs_selected_channels.pri_freq =
+                       nla_get_u32(tb[BRCM_VENDOR_ATTR_ACS_PRIMARY_FREQ]);
+       if (tb[BRCM_VENDOR_ATTR_ACS_SECONDARY_FREQ])
+               event.acs_selected_channels.sec_freq =
+                       nla_get_u32(tb[BRCM_VENDOR_ATTR_ACS_SECONDARY_FREQ]);
+       if (tb[BRCM_VENDOR_ATTR_ACS_VHT_SEG0_CENTER_CHANNEL])
+               event.acs_selected_channels.vht_seg0_center_ch =
+                       nla_get_u8(tb[BRCM_VENDOR_ATTR_ACS_VHT_SEG0_CENTER_CHANNEL]);
+       if (tb[BRCM_VENDOR_ATTR_ACS_VHT_SEG0_CENTER_CHANNEL])
+               event.acs_selected_channels.vht_seg1_center_ch =
+                       nla_get_u8(tb[BRCM_VENDOR_ATTR_ACS_VHT_SEG1_CENTER_CHANNEL]);
+       if (tb[BRCM_VENDOR_ATTR_ACS_CHWIDTH])
+               event.acs_selected_channels.ch_width =
+                       nla_get_u16(tb[BRCM_VENDOR_ATTR_ACS_CHWIDTH]);
+       if (tb[BRCM_VENDOR_ATTR_ACS_HW_MODE]) {
+               event.acs_selected_channels.hw_mode = nla_get_u8(tb[BRCM_VENDOR_ATTR_ACS_HW_MODE]);
+               if (event.acs_selected_channels.hw_mode == NUM_HOSTAPD_MODES ||
+                   event.acs_selected_channels.hw_mode ==
+                   HOSTAPD_MODE_IEEE80211ANY) {
+                       wpa_printf(MSG_DEBUG,
+                                  "nl80211: Invalid hw_mode %d in ACS selection event",
+                                  event.acs_selected_channels.hw_mode);
+                       return;
+               }
+       }
+
+       wpa_printf(MSG_DEBUG,
+                  "nl80211: ACS Results: PCH: %d SCH: %d BW: %d VHT0: %d VHT1: %d HW_MODE: %d",
+                  event.acs_selected_channels.pri_freq,
+                  event.acs_selected_channels.sec_freq,
+                  event.acs_selected_channels.ch_width,
+                  event.acs_selected_channels.vht_seg0_center_ch,
+                  event.acs_selected_channels.vht_seg1_center_ch,
+                  event.acs_selected_channels.hw_mode);
+       wpa_supplicant_event(drv->ctx, EVENT_ACS_CHANNEL_SELECTED, &event);
+}
+
+
+static void nl80211_vendor_event_brcm(struct wpa_driver_nl80211_data *drv,
+                                     u32 subcmd, u8 *data, size_t len)
+{
+       wpa_printf(MSG_DEBUG, "nl80211: Got BRCM vendor event %u", subcmd);
+       switch (subcmd) {
+       case BRCM_VENDOR_EVENT_PRIV_STR:
+       case BRCM_VENDOR_EVENT_HANGED:
+               /* Dump the event on to the console */
+               wpa_msg(NULL, MSG_INFO, "%s", data);
+               break;
+       case BRCM_VENDOR_EVENT_ACS:
+               brcm_nl80211_acs_select_ch(drv, data, len);
+               break;
+       default:
+               wpa_printf(MSG_DEBUG,
+                          "%s: Ignore unsupported BRCM vendor event %u",
+                          __func__, subcmd);
+               break;
+       }
+}
+
+#endif /* CONFIG_DRIVER_NL80211_BRCM */
+
+
 static void nl80211_vendor_event(struct wpa_driver_nl80211_data *drv,
                                 struct nlattr **tb)
 {
@@ -2425,6 +2507,11 @@ static void nl80211_vendor_event(struct wpa_driver_nl80211_data *drv,
        case OUI_QCA:
                nl80211_vendor_event_qca(drv, subcmd, data, len);
                break;
+#ifdef CONFIG_DRIVER_NL80211_BRCM
+       case OUI_BRCM:
+               nl80211_vendor_event_brcm(drv, subcmd, data, len);
+               break;
+#endif /* CONFIG_DRIVER_NL80211_BRCM */
        default:
                wpa_printf(MSG_DEBUG, "nl80211: Ignore unsupported vendor event");
                break;
index 55a98ef86d0df4a306cd1075e31b919fd2c9f9d4..a03d4a0345119dc3a834611a1c792a0ef3047fa1 100644 (file)
@@ -26,6 +26,10 @@ NEED_LIBNL=y
 CONFIG_LIBNL3_ROUTE=y
 endif
 
+ifdef CONFIG_DRIVER_NL80211_BRCM
+DRV_CFLAGS += -DCONFIG_DRIVER_NL80211_BRCM
+endif
+
 ifdef CONFIG_DRIVER_MACSEC_QCA
 DRV_CFLAGS += -DCONFIG_DRIVER_MACSEC_QCA
 DRV_OBJS += ../src/drivers/driver_macsec_qca.o
index 5a32a24228ced98c114f161518ad0a0ec54411e1..10eab6a92e17762727ea53e3326b6b7e9a36c26a 100644 (file)
@@ -41,6 +41,9 @@ DRV_OBJS += src/drivers/driver_nl80211_scan.c
 ifdef CONFIG_DRIVER_NL80211_QCA
 DRV_CFLAGS += -DCONFIG_DRIVER_NL80211_QCA
 endif
+ifdef CONFIG_DRIVER_NL80211_BRCM
+DRV_CFLAGS += -DCONFIG_DRIVER_NL80211_BRCM
+endif
 NEED_SME=y
 NEED_AP_MLME=y
 NEED_NETLINK=y