Hi, This is the patch to add ACS support for Broadcom device. May I submit it by this mail list? Or could you help to share the steps to submit it? Patch was created based on published source code. The details are: From b9efc86587a14c0165dfda8ded5070703decc75b Mon Sep 17 00:00:00 2001 From: Xinrui Sun <xinrui.sun@xxxxxxxxxxxx> 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@xxxxxxxxxxxx> --- 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 Thanks, Xinrui.
Attachment:
0001-Add-ACS-support-for-Broadcom-device.patch
Description: Binary data
_______________________________________________ Hostap mailing list Hostap@xxxxxxxxxxxxxxxxxxx http://lists.infradead.org/mailman/listinfo/hostap