@@ -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
new file mode 100644
@@ -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 */
@@ -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,
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",
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;
@@ -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
@@ -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