[PATCH] hostapd: Add ACS support for broadcom device (Xinrui Sun)

Xinrui Sun xinrui.sun at broadcom.com
Mon Jul 13 23:41:03 EDT 2020


Hi,

Modified issue of BRCM_VENDOR_ATTR_ACS_VHT_SEG1_CENTER_CHANNEL, and add
support for HW_MODE_ANY

Update new patch.

>From b1391e12be13fa29c19b625602ba39cd81f2226e Mon Sep 17 00:00:00 2001
From: Xinrui Sun <xinrui.sun at broadcom.com>
Date: Fri, 12 Jun 2020 20:49:07 +0800
Subject: [PATCH] Add ACS support for Broadcom device

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 at broadcom.com>
---
 hostapd/android.config             |   5 +-
 src/ap/hw_features.c               |   8 ++
 src/common/brcm_vendor.h           | 156 +++++++++++++++++++++++++++++
 src/drivers/driver_nl80211.c       | 104 +++++++++++++++++++
 src/drivers/driver_nl80211_capa.c  |  12 +++
 src/drivers/driver_nl80211_event.c |  93 +++++++++++++++++
 src/drivers/drivers.mak            |   4 +
 src/drivers/drivers.mk             |   3 +
 8 files changed, 384 insertions(+), 1 deletion(-)
 create mode 100644 src/common/brcm_vendor.h

diff --git a/hostapd/android.config b/hostapd/android.config
index 94a9bb47b..34b42d389 100644
--- a/hostapd/android.config
+++ b/hostapd/android.config
@@ -26,7 +26,10 @@
 CONFIG_LIBNL20=y

 # QCA vendor extensions to nl80211
-CONFIG_DRIVER_NL80211_QCA=y
+#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
diff --git a/src/ap/hw_features.c b/src/ap/hw_features.c
index f6e69030d..e94f557af 100644
--- a/src/ap/hw_features.c
+++ b/src/ap/hw_features.c
@@ -972,6 +972,14 @@ int hostapd_acs_completed(struct hostapd_iface
*iface, int err)
 		wpa_msg(iface->bss[0]->msg_ctx, MSG_INFO,
 			ACS_EVENT_COMPLETED "freq=%d channel=%d",
 			iface->freq, iface->conf->channel);
+#ifdef CONFIG_DRIVER_NL80211_BRCM
+		/* Driver already do the scan for different band width,
+		 * And send final results directly.
+		 * don't need to check ht cap and do scan for bw40 again.
+		 */
+		ret = 0;
+		goto out;
+#endif
 		break;
 	case HOSTAPD_CHAN_ACS:
 		wpa_printf(MSG_ERROR, "ACS error - reported complete, but
no result available");
diff --git a/src/common/brcm_vendor.h b/src/common/brcm_vendor.h
new file mode 100644
index 000000000..f163dea73
--- /dev/null
+++ b/src/common/brcm_vendor.h
@@ -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 */
diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c
index 72189da24..de9b4651f 100644
--- a/src/drivers/driver_nl80211.c
+++ b/src/drivers/driver_nl80211.c
@@ -38,6 +38,10 @@
 #include "rfkill.h"
 #include "driver_nl80211.h"

+#ifdef CONFIG_DRIVER_NL80211_BRCM
+#include "common/brcm_vendor.h"
+#endif /* CONFIG_DRIVER_NL80211_BRCM */
+

 #ifndef NETLINK_CAP_ACK
 #define NETLINK_CAP_ACK 10
@@ -11212,6 +11216,103 @@ 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 = 0;
+
+	do {
+		freq_list_len = int_array_len(params->freq_list);
+		wpa_printf(MSG_DEBUG, "%s: freq_list_len=%d",
+			__FUNCTION__, freq_list_len);
+
+		msg = nl80211_drv_msg(drv, 0, NL80211_CMD_VENDOR);
+		if (!msg) {
+			wpa_printf(MSG_ERROR, "%s: *errof, no memory for
msg",
+				__FUNCTION__);
+			return ret;
+		}
+		if ((nla_put_u32(msg, NL80211_ATTR_VENDOR_ID, OUI_BRCM)))
{
+			wpa_printf(MSG_ERROR, "%s: *errof,
NL80211_ATTR_VENDOR_ID",
+				__FUNCTION__);
+			nlmsg_free(msg);
+			return ret;
+		}
+		if ((nla_put_u32(msg, NL80211_ATTR_VENDOR_SUBCMD,
BRCM_VENDOR_SCMD_ACS))) {
+			wpa_printf(MSG_ERROR, "%s: *errof,
NL80211_ATTR_VENDOR_SUBCMD",
+				__FUNCTION__);
+			nlmsg_free(msg);
+			return ret;
+		}
+		if (!(data = nla_nest_start(msg,
NL80211_ATTR_VENDOR_DATA))) {
+			wpa_printf(MSG_ERROR, "%s: *errof,
NL80211_ATTR_VENDOR_DATA",
+				__FUNCTION__);
+			nlmsg_free(msg);
+			return ret;
+		}
+		if ((nla_put_u8(msg, BRCM_VENDOR_ATTR_ACS_HW_MODE,
params->hw_mode))) {
+			wpa_printf(MSG_ERROR, "%s: *errof,
BRCM_VENDOR_ATTR_ACS_HW_MODE",
+				__FUNCTION__);
+			nlmsg_free(msg);
+			return ret;
+		}
+		if ((nla_put_u8(msg, BRCM_VENDOR_ATTR_ACS_HT_ENABLED,
params->ht_enabled))) {
+			wpa_printf(MSG_ERROR, "%s: *errof,
BRCM_VENDOR_ATTR_ACS_HT_ENABLED",
+				__FUNCTION__);
+			nlmsg_free(msg);
+			return ret;
+		}
+		if ((nla_put_u8(msg, BRCM_VENDOR_ATTR_ACS_HT40_ENABLED,
params->ht40_enabled))) {
+			wpa_printf(MSG_ERROR, "%s: *errof,
BRCM_VENDOR_ATTR_ACS_HT40_ENABLED",
+				__FUNCTION__);
+			nlmsg_free(msg);
+			return ret;
+		}
+		if ((nla_put_u8(msg, BRCM_VENDOR_ATTR_ACS_VHT_ENABLED,
params->vht_enabled))) {
+			wpa_printf(MSG_ERROR, "%s: *errof,
BRCM_VENDOR_ATTR_ACS_VHT_ENABLED",
+				__FUNCTION__);
+			nlmsg_free(msg);
+			return ret;
+		}
+		if ((nla_put_u16(msg, BRCM_VENDOR_ATTR_ACS_CHWIDTH,
params->ch_width))) {
+			wpa_printf(MSG_ERROR, "%s: *errof,
BRCM_VENDOR_ATTR_ACS_CHWIDTH",
+				__FUNCTION__);
+			nlmsg_free(msg);
+			return ret;
+		}
+		wpa_printf(MSG_DEBUG, "%s: ht40=%d, ch_width=%d\n",
__FUNCTION__,
+			params->ht40_enabled, params->ch_width);
+		if ((freq_list_len > 0)
+			&& (nla_put(msg, BRCM_VENDOR_ATTR_ACS_FREQ_LIST,
sizeof(int) * freq_list_len,
+					params->freq_list))) {
+			wpa_printf(MSG_ERROR, "%s: *errof,
BRCM_VENDOR_ATTR_ACS_FREQ_LIST, list_len=%d",
+				__FUNCTION__, freq_list_len);
+			nlmsg_free(msg);
+			return ret;
+		}
+
+		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);
+		if (ret) {
+			wpa_printf(MSG_ERROR,
+				"nl80211: BRCM Failed to invoke driver ACS
function: %s",
+				strerror(errno));
+		}
+	} while (0);
+
+	return ret;
+}
+#endif /* CONFIG_DRIVER_NL80211_BRCM */

 static int nl80211_write_to_file(const char *name, unsigned int val)
 {
@@ -11649,6 +11750,9 @@ const struct wpa_driver_ops wpa_driver_nl80211_ops
= {
 	.set_bssid_blacklist = nl80211_set_bssid_blacklist,
 	.add_sta_node = nl80211_add_sta_node,
 #endif /* CONFIG_DRIVER_NL80211_QCA */
+#if defined(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,
diff --git a/src/drivers/driver_nl80211_capa.c
b/src/drivers/driver_nl80211_capa.c
index b9eb6e220..9d6e461f0 100644
--- a/src/drivers/driver_nl80211_capa.c
+++ b/src/drivers/driver_nl80211_capa.c
@@ -18,6 +18,9 @@
 #include "common/qca-vendor-attr.h"
 #include "driver_nl80211.h"

+#ifdef CONFIG_DRIVER_NL80211_BRCM
+#include "common/brcm_vendor.h"
+#endif

 static int protocol_feature_handler(struct nl_msg *msg, void *arg)
 {
@@ -991,6 +994,15 @@ 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;
+					drv->capa.flags |=
WPA_DRIVER_FLAGS_SUPPORT_HW_MODE_ANY;
+					wpa_printf(MSG_DEBUG, "Enabled
BRCM ACS\n");
+				}
+#endif /*CONFIG_DRIVER_NL80211_BRCM */
 			}

 			wpa_printf(MSG_DEBUG, "nl80211: Supported vendor
command: vendor_id=0x%x subcmd=%u",
diff --git a/src/drivers/driver_nl80211_event.c
b/src/drivers/driver_nl80211_event.c
index 6a2de1f3c..9ec2622f3 100644
--- a/src/drivers/driver_nl80211_event.c
+++ b/src/drivers/driver_nl80211_event.c
@@ -19,6 +19,9 @@
 #include "common/ieee802_11_common.h"
 #include "driver_nl80211.h"

+#ifdef CONFIG_DRIVER_NL80211_BRCM
+#include "common/brcm_vendor.h"
+#endif /* CONFIG_DRIVER_NL80211_BRCM */

 static const char * nl80211_command_to_string(enum nl80211_commands cmd)
 {
@@ -2228,6 +2231,90 @@ 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]);
+	}
+	wpa_printf(MSG_DEBUG, "got pri_freq=%d\n",
event.acs_selected_channels.pri_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]);
+	}
+	wpa_printf(MSG_DEBUG, "got sec_freq=%d\n",
event.acs_selected_channels.sec_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_SEG1_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_INFO,
+	          "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)
+{
+	union wpa_event_data event;
+
+	wpa_printf(MSG_DEBUG, "got vendor event %d", subcmd);
+	memset(&event, 0, sizeof(event));
+	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:
+		wpa_msg(NULL, MSG_INFO, "%s", data);
+		brcm_nl80211_acs_select_ch(drv, data, len);
+		break;
+
+	default:
+		wpa_printf(MSG_ERROR, "%s-%d: Ignore unsupported BRCM
vendor event %u",
+		           __FUNCTION__, __LINE__, subcmd);
+		break;
+	}
+}
+
+#endif /* CONFIG_DRIVER_NL80211_BRCM */

 static void nl80211_vendor_event(struct wpa_driver_nl80211_data *drv,
 				 struct nlattr **tb)
@@ -2267,6 +2354,12 @@ 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:
+		wpa_printf(MSG_DEBUG, "BRCM event");
+		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;
diff --git a/src/drivers/drivers.mak b/src/drivers/drivers.mak
index 55a98ef86..a03d4a034 100644
--- a/src/drivers/drivers.mak
+++ b/src/drivers/drivers.mak
@@ -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
diff --git a/src/drivers/drivers.mk b/src/drivers/drivers.mk
index 5a32a2422..10eab6a92 100644
--- a/src/drivers/drivers.mk
+++ b/src/drivers/drivers.mk
@@ -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
-- 
2.17.2

-----Original Message-----
From: Hostap [mailto:hostap-bounces at lists.infradead.org] On Behalf Of
hostap-request at lists.infradead.org
Sent: Sunday, June 14, 2020 3:00 AM
To: hostap at lists.infradead.org
Subject: Hostap Digest, Vol 57, Issue 21

Send Hostap mailing list submissions to
	hostap at lists.infradead.org

To subscribe or unsubscribe via the World Wide Web, visit
	http://lists.infradead.org/mailman/listinfo/hostap
or, via email, send a message with subject or body 'help' to
	hostap-request at lists.infradead.org

You can reach the person managing the list at
	hostap-owner at lists.infradead.org

When replying, please edit your Subject line so it is more specific
than "Re: Contents of Hostap digest..."


Today's Topics:

   1. [PATCH] hostapd: Add ACS support for broadcom device (Xinrui Sun)


----------------------------------------------------------------------

Message: 1
Date: Sat, 13 Jun 2020 09:03:03 +0800
From: Xinrui Sun <xinrui.sun at broadcom.com>
To: hostap at lists.infradead.org
Subject: [PATCH] hostapd: Add ACS support for broadcom device
Message-ID: <59ffe473aef1756a2ed567e046a3f2ad at mail.gmail.com>
Content-Type: text/plain; charset="UTF-8"

>From b9efc86587a14c0165dfda8ded5070703decc75b Mon Sep 17 00:00:00 2001
From: Xinrui Sun <xinrui.sun at broadcom.com>
Date: Fri, 12 Jun 2020 20:49:07 +0800
Subject: [PATCH] Add ACS support for Broadcom device

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 at broadcom.com>
---
 hostapd/android.config             |   5 +-
 src/common/brcm_vendor.h           | 156 +++++++++++++++++++++++++++++
 src/drivers/driver_nl80211.c       | 104 +++++++++++++++++++
 src/drivers/driver_nl80211_capa.c  |  11 ++
 src/drivers/driver_nl80211_event.c |  93 +++++++++++++++++
 src/drivers/drivers.mak            |   4 +
 src/drivers/drivers.mk             |   3 +
 7 files changed, 375 insertions(+), 1 deletion(-)
 create mode 100644 src/common/brcm_vendor.h

diff --git a/hostapd/android.config b/hostapd/android.config
index 94a9bb47b..34b42d389 100644
--- a/hostapd/android.config
+++ b/hostapd/android.config
@@ -26,7 +26,10 @@
 CONFIG_LIBNL20=y

 # QCA vendor extensions to nl80211
-CONFIG_DRIVER_NL80211_QCA=y
+#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
diff --git a/src/common/brcm_vendor.h b/src/common/brcm_vendor.h
new file mode 100644
index 000000000..f163dea73
--- /dev/null
+++ b/src/common/brcm_vendor.h
@@ -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 */
diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c
index 72189da24..de9b4651f 100644
--- a/src/drivers/driver_nl80211.c
+++ b/src/drivers/driver_nl80211.c
@@ -38,6 +38,10 @@
 #include "rfkill.h"
 #include "driver_nl80211.h"

+#ifdef CONFIG_DRIVER_NL80211_BRCM
+#include "common/brcm_vendor.h"
+#endif /* CONFIG_DRIVER_NL80211_BRCM */
+

 #ifndef NETLINK_CAP_ACK
 #define NETLINK_CAP_ACK 10
@@ -11212,6 +11216,103 @@ 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 = 0;
+
+	do {
+		freq_list_len = int_array_len(params->freq_list);
+		wpa_printf(MSG_DEBUG, "%s: freq_list_len=%d",
+			__FUNCTION__, freq_list_len);
+
+		msg = nl80211_drv_msg(drv, 0, NL80211_CMD_VENDOR);
+		if (!msg) {
+			wpa_printf(MSG_ERROR, "%s: *errof, no memory for
msg",
+				__FUNCTION__);
+			return ret;
+		}
+		if ((nla_put_u32(msg, NL80211_ATTR_VENDOR_ID, OUI_BRCM)))
{
+			wpa_printf(MSG_ERROR, "%s: *errof,
NL80211_ATTR_VENDOR_ID",
+				__FUNCTION__);
+			nlmsg_free(msg);
+			return ret;
+		}
+		if ((nla_put_u32(msg, NL80211_ATTR_VENDOR_SUBCMD,
BRCM_VENDOR_SCMD_ACS))) {
+			wpa_printf(MSG_ERROR, "%s: *errof,
NL80211_ATTR_VENDOR_SUBCMD",
+				__FUNCTION__);
+			nlmsg_free(msg);
+			return ret;
+		}
+		if (!(data = nla_nest_start(msg,
NL80211_ATTR_VENDOR_DATA))) {
+			wpa_printf(MSG_ERROR, "%s: *errof,
NL80211_ATTR_VENDOR_DATA",
+				__FUNCTION__);
+			nlmsg_free(msg);
+			return ret;
+		}
+		if ((nla_put_u8(msg, BRCM_VENDOR_ATTR_ACS_HW_MODE,
params->hw_mode))) {
+			wpa_printf(MSG_ERROR, "%s: *errof,
BRCM_VENDOR_ATTR_ACS_HW_MODE",
+				__FUNCTION__);
+			nlmsg_free(msg);
+			return ret;
+		}
+		if ((nla_put_u8(msg, BRCM_VENDOR_ATTR_ACS_HT_ENABLED,
params->ht_enabled))) {
+			wpa_printf(MSG_ERROR, "%s: *errof,
BRCM_VENDOR_ATTR_ACS_HT_ENABLED",
+				__FUNCTION__);
+			nlmsg_free(msg);
+			return ret;
+		}
+		if ((nla_put_u8(msg, BRCM_VENDOR_ATTR_ACS_HT40_ENABLED,
params->ht40_enabled))) {
+			wpa_printf(MSG_ERROR, "%s: *errof,
BRCM_VENDOR_ATTR_ACS_HT40_ENABLED",
+				__FUNCTION__);
+			nlmsg_free(msg);
+			return ret;
+		}
+		if ((nla_put_u8(msg, BRCM_VENDOR_ATTR_ACS_VHT_ENABLED,
params->vht_enabled))) {
+			wpa_printf(MSG_ERROR, "%s: *errof,
BRCM_VENDOR_ATTR_ACS_VHT_ENABLED",
+				__FUNCTION__);
+			nlmsg_free(msg);
+			return ret;
+		}
+		if ((nla_put_u16(msg, BRCM_VENDOR_ATTR_ACS_CHWIDTH,
params->ch_width))) {
+			wpa_printf(MSG_ERROR, "%s: *errof,
BRCM_VENDOR_ATTR_ACS_CHWIDTH",
+				__FUNCTION__);
+			nlmsg_free(msg);
+			return ret;
+		}
+		wpa_printf(MSG_DEBUG, "%s: ht40=%d, ch_width=%d\n",
__FUNCTION__,
+			params->ht40_enabled, params->ch_width);
+		if ((freq_list_len > 0)
+			&& (nla_put(msg, BRCM_VENDOR_ATTR_ACS_FREQ_LIST,
sizeof(int) * freq_list_len,
+					params->freq_list))) {
+			wpa_printf(MSG_ERROR, "%s: *errof,
BRCM_VENDOR_ATTR_ACS_FREQ_LIST, list_len=%d",
+				__FUNCTION__, freq_list_len);
+			nlmsg_free(msg);
+			return ret;
+		}
+
+		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);
+		if (ret) {
+			wpa_printf(MSG_ERROR,
+				"nl80211: BRCM Failed to invoke driver ACS
function: %s",
+				strerror(errno));
+		}
+	} while (0);
+
+	return ret;
+}
+#endif /* CONFIG_DRIVER_NL80211_BRCM */

 static int nl80211_write_to_file(const char *name, unsigned int val)
 {
@@ -11649,6 +11750,9 @@ const struct wpa_driver_ops wpa_driver_nl80211_ops
= {
 	.set_bssid_blacklist = nl80211_set_bssid_blacklist,
 	.add_sta_node = nl80211_add_sta_node,
 #endif /* CONFIG_DRIVER_NL80211_QCA */
+#if defined(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,
diff --git a/src/drivers/driver_nl80211_capa.c
b/src/drivers/driver_nl80211_capa.c
index b9eb6e220..067bf96f0 100644
--- a/src/drivers/driver_nl80211_capa.c
+++ b/src/drivers/driver_nl80211_capa.c
@@ -18,6 +18,9 @@
 #include "common/qca-vendor-attr.h"
 #include "driver_nl80211.h"

+#ifdef CONFIG_DRIVER_NL80211_BRCM
+#include "common/brcm_vendor.h"
+#endif

 static int protocol_feature_handler(struct nl_msg *msg, void *arg)
 {
@@ -991,6 +994,14 @@ 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\n");
+				}
+#endif /*CONFIG_DRIVER_NL80211_BRCM */
 			}

 			wpa_printf(MSG_DEBUG, "nl80211: Supported vendor
command: vendor_id=0x%x subcmd=%u",
diff --git a/src/drivers/driver_nl80211_event.c
b/src/drivers/driver_nl80211_event.c
index 6a2de1f3c..93ae11321 100644
--- a/src/drivers/driver_nl80211_event.c
+++ b/src/drivers/driver_nl80211_event.c
@@ -19,6 +19,9 @@
 #include "common/ieee802_11_common.h"
 #include "driver_nl80211.h"

+#ifdef CONFIG_DRIVER_NL80211_BRCM
+#include "common/brcm_vendor.h"
+#endif /* CONFIG_DRIVER_NL80211_BRCM */

 static const char * nl80211_command_to_string(enum nl80211_commands cmd)
 {
@@ -2228,6 +2231,90 @@ 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]);
+	}
+	wpa_printf(MSG_DEBUG, "got pri_freq=%d\n",
event.acs_selected_channels.pri_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]);
+	}
+	wpa_printf(MSG_DEBUG, "got sec_freq=%d\n",
event.acs_selected_channels.sec_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_INFO,
+	          "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)
+{
+	union wpa_event_data event;
+
+	wpa_printf(MSG_DEBUG, "got vendor event %d", subcmd);
+	memset(&event, 0, sizeof(event));
+	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:
+		wpa_msg(NULL, MSG_INFO, "%s", data);
+		brcm_nl80211_acs_select_ch(drv, data, len);
+		break;
+
+	default:
+		wpa_printf(MSG_ERROR, "%s-%d: Ignore unsupported BRCM
vendor event %u",
+		           __FUNCTION__, __LINE__, subcmd);
+		break;
+	}
+}
+
+#endif /* CONFIG_DRIVER_NL80211_BRCM */

 static void nl80211_vendor_event(struct wpa_driver_nl80211_data *drv,
 				 struct nlattr **tb)
@@ -2267,6 +2354,12 @@ 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:
+		wpa_printf(MSG_DEBUG, "BRCM event");
+		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;
diff --git a/src/drivers/drivers.mak b/src/drivers/drivers.mak
index 55a98ef86..a03d4a034 100644
--- a/src/drivers/drivers.mak
+++ b/src/drivers/drivers.mak
@@ -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
diff --git a/src/drivers/drivers.mk b/src/drivers/drivers.mk
index 5a32a2422..10eab6a92 100644
--- a/src/drivers/drivers.mk
+++ b/src/drivers/drivers.mk
@@ -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
-- 
2.17.2



------------------------------

Subject: Digest Footer

_______________________________________________
Hostap mailing list
Hostap at lists.infradead.org
http://lists.infradead.org/mailman/listinfo/hostap


------------------------------

End of Hostap Digest, Vol 57, Issue 21
**************************************



More information about the Hostap mailing list