blob: 5872b479bc6d1ef9125dbcf7c439d281f02bb58d [file] [log] [blame]
From 4c6d148fea7cd1ea380a792d83d2dabe61e9c869 Mon Sep 17 00:00:00 2001
From: Evelyn Tsai <evelyn.tsai@mediatek.com>
Date: Fri, 17 Mar 2023 16:17:14 +0800
Subject: [PATCH 26/29] hostapd: mtk: Add vendor for CAPI certification
commands
---
hostapd/ctrl_iface.c | 95 +++++++++++++++
src/ap/ap_drv_ops.c | 21 ++++
src/ap/ap_drv_ops.h | 3 +
src/common/mtk_vendor.h | 32 +-----
src/drivers/driver.h | 22 ++++
src/drivers/driver_nl80211.c | 185 ++++++++++++++++++++++++++++++
src/drivers/driver_nl80211.h | 1 +
src/drivers/driver_nl80211_capa.c | 3 +
8 files changed, 332 insertions(+), 30 deletions(-)
diff --git a/hostapd/ctrl_iface.c b/hostapd/ctrl_iface.c
index 87448e7..b0323e7 100644
--- a/hostapd/ctrl_iface.c
+++ b/hostapd/ctrl_iface.c
@@ -38,6 +38,7 @@
#endif /* CONFIG_DPP */
#include "common/wpa_ctrl.h"
#include "common/ptksa_cache.h"
+#include "common/mtk_vendor.h"
#include "crypto/tls.h"
#include "drivers/driver.h"
#include "eapol_auth/eapol_auth_sm.h"
@@ -3727,6 +3728,96 @@ hostapd_ctrl_iface_get_aval_color_bmp(struct hostapd_data *hapd, char *buf,
return pos - buf;
}
+static int
+hostapd_ctrl_iface_ap_wireless(struct hostapd_data *hapd, char *cmd,
+ char *buf, size_t buflen)
+{
+ char *pos, *value, *config = cmd;
+ enum mtk_vendor_attr_wireless_ctrl sub_cmd;
+
+ pos = os_strchr(config, '=');
+ if (pos == NULL)
+ return -1;
+ *pos++ = '\0';
+
+ if(pos == NULL)
+ return -1;
+ value = pos;
+
+ if (os_strncmp(config, "fixed_mcs", 9) == 0)
+ sub_cmd = MTK_VENDOR_ATTR_WIRELESS_CTRL_FIXED_MCS;
+ else if (os_strncmp(config, "ofdma", 5) == 0)
+ sub_cmd = MTK_VENDOR_ATTR_WIRELESS_CTRL_FIXED_OFDMA;
+ else if (os_strncmp(config, "ppdu_type", 9) == 0)
+ sub_cmd = MTK_VENDOR_ATTR_WIRELESS_CTRL_PPDU_TX_TYPE;
+ else if (os_strncmp(config, "nusers_ofdma", 12) == 0)
+ sub_cmd = MTK_VENDOR_ATTR_WIRELESS_CTRL_NUSERS_OFDMA;
+ else if (os_strncmp(config, "add_ba_req_bufsize", 18) == 0)
+ sub_cmd = MTK_VENDOR_ATTR_WIRELESS_CTRL_BA_BUFFER_SIZE;
+ else if (os_strncmp(config, "mimo", 4) == 0)
+ sub_cmd = MTK_VENDOR_ATTR_WIRELESS_CTRL_MIMO;
+ else if (os_strncmp(config, "cert", 4) == 0)
+ sub_cmd = MTK_VENDOR_ATTR_WIRELESS_CTRL_CERT ;
+ else {
+ wpa_printf(MSG_ERROR,
+ "Unsupported parameter %s for ap_wireless", config);
+ return -1;
+ }
+
+ if (hostapd_drv_ap_wireless(hapd, (u8) sub_cmd, atoi(value)) != 0)
+ return -1;
+
+ return os_snprintf(buf, buflen, "OK\n");
+}
+
+static int
+hostapd_ctrl_iface_ap_rfeatures(struct hostapd_data *hapd, char *cmd,
+ char *buf, size_t buflen)
+{
+ char *pos, *value, *type, *config = cmd;
+ enum mtk_vendor_attr_rfeature_ctrl sub_cmd;
+
+ pos = os_strchr(config, '=');
+ if (pos == NULL)
+ return -1;
+ *pos++ = '\0';
+
+ if(pos == NULL)
+ return -1;
+ value = pos;
+
+ if (os_strncmp(config, "he_gi", 5) == 0)
+ sub_cmd = MTK_VENDOR_ATTR_RFEATURE_CTRL_HE_GI;
+ else if (os_strncmp(config, "he_ltf", 6) == 0)
+ sub_cmd = MTK_VENDOR_ATTR_RFEATURE_CTRL_HE_LTF;
+ else if (os_strncmp(config, "trig_type", 9) == 0) {
+ pos = os_strchr(value, ',');
+ if (pos == NULL)
+ return -1;
+ *pos++ = '\0';
+ if(pos == NULL)
+ return -1;
+ type = pos;
+ goto trigtype;
+ } else if (os_strcmp(config, "ack_policy") == 0)
+ sub_cmd = MTK_VENDOR_ATTR_RFEATURE_CTRL_ACK_PLCY;
+ else {
+ wpa_printf(MSG_ERROR,
+ "Unsupported parameter %s for ap_rfeatures", config);
+ return -1;
+ }
+
+ if (hostapd_drv_ap_rfeatures(hapd, (u8) sub_cmd, atoi(value)) != 0)
+ return -1;
+ goto exit;
+
+trigtype:
+ if (hostapd_drv_ap_trig_type(hapd, atoi(value), atoi(type)) != 0)
+ return -1;
+
+exit:
+ return os_snprintf(buf, buflen, "OK\n");
+}
static int hostapd_ctrl_iface_receive_process(struct hostapd_data *hapd,
char *buf, char *reply,
@@ -4298,6 +4389,10 @@ static int hostapd_ctrl_iface_receive_process(struct hostapd_data *hapd,
reply_len = hostapd_ctrl_iface_get_bss_color(hapd, reply, reply_size);
} else if (os_strncmp(buf, "AVAL_COLOR_BMP", 14) == 0) {
reply_len = hostapd_ctrl_iface_get_aval_color_bmp(hapd, reply, reply_size);
+ } else if (os_strncmp(buf, "ap_wireless ", 12) == 0) {
+ reply_len = hostapd_ctrl_iface_ap_wireless(hapd, buf + 12, reply, reply_size);
+ } else if (os_strncmp(buf, "ap_rfeatures ", 13) == 0) {
+ reply_len = hostapd_ctrl_iface_ap_rfeatures(hapd, buf + 13, reply, reply_size);
} else {
os_memcpy(reply, "UNKNOWN COMMAND\n", 16);
reply_len = 16;
diff --git a/src/ap/ap_drv_ops.c b/src/ap/ap_drv_ops.c
index 40b9a20..52d0fff 100644
--- a/src/ap/ap_drv_ops.c
+++ b/src/ap/ap_drv_ops.c
@@ -1100,3 +1100,24 @@ int hostapd_drv_get_aval_bss_color_bmp(struct hostapd_data *hapd, u64 *aval_colo
return 0;
return hapd->driver->get_aval_color_bmp(hapd->drv_priv, aval_color_bmp);
}
+
+int hostapd_drv_ap_wireless(struct hostapd_data *hapd, u8 sub_vendor_id, int value)
+{
+ if (!hapd->driver || !hapd->driver->ap_wireless)
+ return 0;
+ return hapd->driver->ap_wireless(hapd->drv_priv, sub_vendor_id, value);
+}
+
+int hostapd_drv_ap_rfeatures(struct hostapd_data *hapd, u8 sub_vendor_id, int value)
+{
+ if (!hapd->driver || !hapd->driver->ap_rfeatures)
+ return 0;
+ return hapd->driver->ap_rfeatures(hapd->drv_priv, sub_vendor_id, value);
+}
+
+int hostapd_drv_ap_trig_type(struct hostapd_data *hapd, u8 enable, u8 type)
+{
+ if (!hapd->driver || !hapd->driver->ap_trigtype)
+ return 0;
+ return hapd->driver->ap_trigtype(hapd->drv_priv, enable, type);
+}
diff --git a/src/ap/ap_drv_ops.h b/src/ap/ap_drv_ops.h
index 136a3ac..659c3f8 100644
--- a/src/ap/ap_drv_ops.h
+++ b/src/ap/ap_drv_ops.h
@@ -151,6 +151,9 @@ int hostapd_drv_amsdu_ctrl(struct hostapd_data *hapd);
int hostapd_drv_amsdu_dump(struct hostapd_data *hapd, u8 *amsdu);
int hostapd_drv_get_aval_bss_color_bmp(struct hostapd_data *hapd,
u64 *aval_color_bmp);
+int hostapd_drv_ap_wireless(struct hostapd_data *hapd, u8 sub_vendor_id, int value);
+int hostapd_drv_ap_rfeatures(struct hostapd_data *hapd, u8 sub_vendor_id, int value);
+int hostapd_drv_ap_trig_type(struct hostapd_data *hapd, u8 enable, u8 type);
#include "drivers/driver.h"
diff --git a/src/common/mtk_vendor.h b/src/common/mtk_vendor.h
index a99e6f2..32438af 100644
--- a/src/common/mtk_vendor.h
+++ b/src/common/mtk_vendor.h
@@ -48,16 +48,6 @@ enum mtk_vendor_attr_edcca_dump {
NUM_MTK_VENDOR_ATTRS_EDCCA_DUMP - 1
};
-
-static struct nla_policy edcca_ctrl_policy[NUM_MTK_VENDOR_ATTRS_EDCCA_CTRL] = {
- [MTK_VENDOR_ATTR_EDCCA_CTRL_MODE] = { .type = NLA_U8 },
- [MTK_VENDOR_ATTR_EDCCA_CTRL_PRI20_VAL] = { .type = NLA_U8 },
- [MTK_VENDOR_ATTR_EDCCA_CTRL_SEC20_VAL] = { .type = NLA_U8 },
- [MTK_VENDOR_ATTR_EDCCA_CTRL_SEC40_VAL] = { .type = NLA_U8 },
- [MTK_VENDOR_ATTR_EDCCA_CTRL_SEC80_VAL] = { .type = NLA_U8 },
- [MTK_VENDOR_ATTR_EDCCA_CTRL_COMPENSATE] = { .type = NLA_U8 },
-};
-
enum mtk_vendor_attr_3wire_ctrl {
MTK_VENDOR_ATTR_3WIRE_CTRL_UNSPEC,
@@ -69,10 +59,6 @@ enum mtk_vendor_attr_3wire_ctrl {
NUM_MTK_VENDOR_ATTRS_3WIRE_CTRL - 1
};
-static struct nla_policy three_wire_ctrl_policy[NUM_MTK_VENDOR_ATTRS_3WIRE_CTRL] = {
- [MTK_VENDOR_ATTR_3WIRE_CTRL_MODE] = {.type = NLA_U8 },
-};
-
enum mtk_vendor_attr_csi_ctrl {
MTK_VENDOR_ATTR_CSI_CTRL_UNSPEC,
@@ -169,7 +155,7 @@ enum mtk_vendor_attr_wireless_ctrl {
MTK_VENDOR_ATTR_WIRELESS_CTRL_BA_BUFFER_SIZE,
MTK_VENDOR_ATTR_WIRELESS_CTRL_MIMO,
MTK_VENDOR_ATTR_WIRELESS_CTRL_AMSDU,
- MTK_VENDOR_ATTR_WIRELESS_CTRL_CERT,
+ MTK_VENDOR_ATTR_WIRELESS_CTRL_CERT = 9,
MTK_VENDOR_ATTR_WIRELESS_CTRL_RTS_SIGTA,
/* keep last */
@@ -189,11 +175,6 @@ enum mtk_vendor_attr_wireless_dump {
NUM_MTK_VENDOR_ATTRS_WIRELESS_DUMP - 1
};
-static const struct nla_policy
-wireless_dump_policy[NUM_MTK_VENDOR_ATTRS_WIRELESS_DUMP] = {
- [MTK_VENDOR_ATTR_WIRELESS_DUMP_AMSDU] = { .type = NLA_U8 },
-};
-
enum mtk_vendor_attr_rfeature_ctrl {
MTK_VENDOR_ATTR_RFEATURE_CTRL_UNSPEC,
@@ -203,6 +184,7 @@ enum mtk_vendor_attr_rfeature_ctrl {
MTK_VENDOR_ATTR_RFEATURE_CTRL_TRIG_TYPE_EN,
MTK_VENDOR_ATTR_RFEATURE_CTRL_TRIG_TYPE,
MTK_VENDOR_ATTR_RFEATURE_CTRL_ACK_PLCY,
+ MTK_VENDOR_ATTR_RFEATURE_CTRL_TRIG_TXBF,
/* keep last */
NUM_MTK_VENDOR_ATTRS_RFEATURE_CTRL,
@@ -244,16 +226,6 @@ enum mtk_vendor_attr_ibf_dump {
NUM_MTK_VENDOR_ATTRS_IBF_DUMP - 1
};
-static struct nla_policy
-ibf_ctrl_policy[NUM_MTK_VENDOR_ATTRS_IBF_CTRL] = {
- [MTK_VENDOR_ATTR_IBF_CTRL_ENABLE] = { .type = NLA_U8 },
-};
-
-static struct nla_policy
-ibf_dump_policy[NUM_MTK_VENDOR_ATTRS_IBF_DUMP] = {
- [MTK_VENDOR_ATTR_IBF_DUMP_ENABLE] = { .type = NLA_U8 },
-};
-
enum mtk_vendor_attr_bss_color_ctrl {
MTK_VENDOR_ATTR_BSS_COLOR_CTRL_UNSPEC,
diff --git a/src/drivers/driver.h b/src/drivers/driver.h
index 1bf0cd6..6a46832 100644
--- a/src/drivers/driver.h
+++ b/src/drivers/driver.h
@@ -4787,6 +4787,28 @@ struct wpa_driver_ops {
*
*/
int (*get_aval_color_bmp)(void *priv, u64 *aval_color_bmp);
+
+ /**
+ * ap_wireless - set wireless command
+ * @priv: Private driver interface data
+ * @value: value
+ */
+ int (*ap_wireless)(void *priv, u8 mode, int value);
+
+ /**
+ * ap_rfeatures - set ap rf features command
+ * @priv: Private driver interface data
+ * @value: value
+ */
+ int (*ap_rfeatures)(void *priv, u8 mode, int value);
+
+ /**
+ * ap_trigtype - set trigger type
+ * @priv: Private driver interface data
+ * @enable: enable or disable
+ * @type: trigger type
+ */
+ int (*ap_trigtype)(void *priv, u8 enable, u8 type);
};
/**
diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c
index 945ce3e..7fae013 100644
--- a/src/drivers/driver_nl80211.c
+++ b/src/drivers/driver_nl80211.c
@@ -74,6 +74,57 @@ enum nlmsgerr_attrs {
#endif /* ANDROID */
+static struct nla_policy
+ibf_ctrl_policy[NUM_MTK_VENDOR_ATTRS_IBF_CTRL] = {
+ [MTK_VENDOR_ATTR_IBF_CTRL_ENABLE] = { .type = NLA_U8 },
+};
+
+static struct nla_policy
+ibf_dump_policy[NUM_MTK_VENDOR_ATTRS_IBF_DUMP] = {
+ [MTK_VENDOR_ATTR_IBF_DUMP_ENABLE] = { .type = NLA_U8 },
+};
+
+static struct nla_policy three_wire_ctrl_policy[NUM_MTK_VENDOR_ATTRS_3WIRE_CTRL] = {
+ [MTK_VENDOR_ATTR_3WIRE_CTRL_MODE] = {.type = NLA_U8 },
+};
+
+static struct nla_policy edcca_ctrl_policy[NUM_MTK_VENDOR_ATTRS_EDCCA_CTRL] = {
+ [MTK_VENDOR_ATTR_EDCCA_CTRL_MODE] = { .type = NLA_U8 },
+ [MTK_VENDOR_ATTR_EDCCA_CTRL_PRI20_VAL] = { .type = NLA_U8 },
+ [MTK_VENDOR_ATTR_EDCCA_CTRL_SEC20_VAL] = { .type = NLA_U8 },
+ [MTK_VENDOR_ATTR_EDCCA_CTRL_SEC40_VAL] = { .type = NLA_U8 },
+ [MTK_VENDOR_ATTR_EDCCA_CTRL_SEC80_VAL] = { .type = NLA_U8 },
+ [MTK_VENDOR_ATTR_EDCCA_CTRL_COMPENSATE] = { .type = NLA_U8 },
+};
+
+static const struct nla_policy
+wireless_dump_policy[NUM_MTK_VENDOR_ATTRS_WIRELESS_DUMP] = {
+ [MTK_VENDOR_ATTR_WIRELESS_DUMP_AMSDU] = { .type = NLA_U8 },
+};
+
+static const struct nla_policy
+rfeature_ctrl_policy[NUM_MTK_VENDOR_ATTRS_RFEATURE_CTRL] = {
+ [MTK_VENDOR_ATTR_RFEATURE_CTRL_HE_GI] = {.type = NLA_U8 },
+ [MTK_VENDOR_ATTR_RFEATURE_CTRL_HE_LTF] = { .type = NLA_U8 },
+ [MTK_VENDOR_ATTR_RFEATURE_CTRL_TRIG_TYPE_CFG] = { .type = NLA_NESTED },
+ [MTK_VENDOR_ATTR_RFEATURE_CTRL_TRIG_TYPE_EN] = { .type = NLA_U8 },
+ [MTK_VENDOR_ATTR_RFEATURE_CTRL_TRIG_TYPE] = { .type = NLA_U8 },
+ [MTK_VENDOR_ATTR_RFEATURE_CTRL_ACK_PLCY] = { .type = NLA_U8 },
+ [MTK_VENDOR_ATTR_RFEATURE_CTRL_TRIG_TXBF] = { .type = NLA_U8 },
+};
+
+static const struct nla_policy
+wireless_ctrl_policy[NUM_MTK_VENDOR_ATTRS_WIRELESS_CTRL] = {
+ [MTK_VENDOR_ATTR_WIRELESS_CTRL_FIXED_MCS] = {.type = NLA_U8 },
+ [MTK_VENDOR_ATTR_WIRELESS_CTRL_FIXED_OFDMA] = {.type = NLA_U8 },
+ [MTK_VENDOR_ATTR_WIRELESS_CTRL_PPDU_TX_TYPE] = {.type = NLA_U8 },
+ [MTK_VENDOR_ATTR_WIRELESS_CTRL_NUSERS_OFDMA] = {.type = NLA_U8 },
+ [MTK_VENDOR_ATTR_WIRELESS_CTRL_MIMO] = {.type = NLA_U8 },
+ [MTK_VENDOR_ATTR_WIRELESS_CTRL_BA_BUFFER_SIZE] = {.type = NLA_U16 },
+ [MTK_VENDOR_ATTR_WIRELESS_CTRL_AMSDU] = {.type = NLA_U8 },
+ [MTK_VENDOR_ATTR_WIRELESS_CTRL_CERT] = {.type = NLA_U8 },
+};
+
static struct nl_sock * nl_create_handle(struct nl_cb *cb, const char *dbg)
{
struct nl_sock *handle;
@@ -13014,6 +13065,137 @@ fail:
return -ENOBUFS;
}
+static int nl80211_ap_wireless(void *priv, u8 sub_vendor_id, int value)
+{
+ struct i802_bss *bss = priv;
+ struct wpa_driver_nl80211_data *drv = bss->drv;
+ struct nl_msg *msg;
+ struct nlattr *data;
+ int ret;
+
+ if (!drv->mtk_wireless_vendor_cmd_avail) {
+ wpa_printf(MSG_INFO,
+ "nl80211: Driver does not support setting ap wireless control");
+ return 0;
+ }
+
+ msg = nl80211_drv_msg(drv, 0, NL80211_CMD_VENDOR);
+ if (!msg)
+ goto fail;
+
+ if (nla_put_u32(msg, NL80211_ATTR_VENDOR_ID, OUI_MTK) ||
+ nla_put_u32(msg, NL80211_ATTR_VENDOR_SUBCMD, MTK_NL80211_VENDOR_SUBCMD_WIRELESS_CTRL))
+ goto fail;
+
+ data = nla_nest_start(msg, NL80211_ATTR_VENDOR_DATA);
+ if (!data)
+ goto fail;
+
+ if (sub_vendor_id == MTK_VENDOR_ATTR_WIRELESS_CTRL_BA_BUFFER_SIZE)
+ nla_put_u16(msg, sub_vendor_id, (u16) value);
+ else
+ nla_put_u8(msg, sub_vendor_id, (u8) value);
+
+ nla_nest_end(msg, data);
+ ret = send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL);
+ if (ret)
+ wpa_printf(MSG_ERROR, "Failed to set ap_wireless. ret=%d (%s)", ret, strerror(-ret));
+
+ return ret;
+
+fail:
+ nlmsg_free(msg);
+ return -ENOBUFS;
+}
+
+static int nl80211_ap_rfeatures(void *priv, u8 sub_vendor_id, int value)
+{
+ struct i802_bss *bss = priv;
+ struct wpa_driver_nl80211_data *drv = bss->drv;
+ struct nl_msg *msg;
+ struct nlattr *data;
+ int ret;
+
+ if (!drv->mtk_rfeatures_vendor_cmd_avail) {
+ wpa_printf(MSG_INFO,
+ "nl80211: Driver does not support setting ap rfeatures control");
+ return 0;
+ }
+
+ msg = nl80211_drv_msg(drv, 0, NL80211_CMD_VENDOR);
+ if (!msg)
+ goto fail;
+
+ if (nla_put_u32(msg, NL80211_ATTR_VENDOR_ID, OUI_MTK) ||
+ nla_put_u32(msg, NL80211_ATTR_VENDOR_SUBCMD, MTK_NL80211_VENDOR_SUBCMD_RFEATURE_CTRL))
+ goto fail;
+
+ data = nla_nest_start(msg, NL80211_ATTR_VENDOR_DATA);
+ if (!data)
+ goto fail;
+
+ nla_put_u8(msg, sub_vendor_id, (u8) value);
+
+ nla_nest_end(msg, data);
+
+ ret = send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL);
+ if (ret)
+ wpa_printf(MSG_ERROR, "Failed to set rf_features. ret=%d (%s)", ret, strerror(-ret));
+
+ return ret;
+
+fail:
+ nlmsg_free(msg);
+ return -ENOBUFS;
+}
+
+static int nl80211_ap_trigtype(void *priv, u8 enable, u8 type)
+{
+ struct i802_bss *bss = priv;
+ struct wpa_driver_nl80211_data *drv = bss->drv;
+ struct nl_msg *msg;
+ struct nlattr *data, *data2;
+ int ret;
+
+ if (!drv->mtk_rfeatures_vendor_cmd_avail) {
+ wpa_printf(MSG_INFO,
+ "nl80211: Driver does not support setting ap rfeatures control");
+ return 0;
+ }
+
+ msg = nl80211_drv_msg(drv, 0, NL80211_CMD_VENDOR);
+ if (!msg)
+ goto fail;
+
+ if (nla_put_u32(msg, NL80211_ATTR_VENDOR_ID, OUI_MTK) ||
+ nla_put_u32(msg, NL80211_ATTR_VENDOR_SUBCMD, MTK_NL80211_VENDOR_SUBCMD_RFEATURE_CTRL))
+ goto fail;
+
+ data = nla_nest_start(msg, NL80211_ATTR_VENDOR_DATA);
+ if (!data)
+ goto fail;
+
+ data2 = nla_nest_start(msg, MTK_VENDOR_ATTR_RFEATURE_CTRL_TRIG_TYPE_CFG);
+ if (!data2)
+ goto fail;
+
+ nla_put_u8(msg, MTK_VENDOR_ATTR_RFEATURE_CTRL_TRIG_TYPE_EN, enable);
+ nla_put_u8(msg, MTK_VENDOR_ATTR_RFEATURE_CTRL_TRIG_TYPE, type);
+
+ nla_nest_end(msg, data2);
+ nla_nest_end(msg, data);
+
+ ret = send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL);
+ if (ret)
+ wpa_printf(MSG_ERROR, "Failed to set trig_type. ret=%d (%s)", ret, strerror(-ret));
+
+ return ret;
+
+fail:
+ nlmsg_free(msg);
+ return -ENOBUFS;
+}
+
const struct wpa_driver_ops wpa_driver_nl80211_ops = {
.name = "nl80211",
.desc = "Linux nl80211/cfg80211",
@@ -13171,4 +13353,7 @@ const struct wpa_driver_ops wpa_driver_nl80211_ops = {
.amsdu_ctrl = nl80211_enable_amsdu,
.amsdu_dump = nl80211_dump_amsdu,
.get_aval_color_bmp = nl80211_get_aval_color_bmp,
+ .ap_wireless = nl80211_ap_wireless,
+ .ap_rfeatures = nl80211_ap_rfeatures,
+ .ap_trigtype = nl80211_ap_trigtype,
};
diff --git a/src/drivers/driver_nl80211.h b/src/drivers/driver_nl80211.h
index 72c7abd..7a03446 100644
--- a/src/drivers/driver_nl80211.h
+++ b/src/drivers/driver_nl80211.h
@@ -187,6 +187,7 @@ struct wpa_driver_nl80211_data {
unsigned int mtk_ibf_vendor_cmd_avail:1;
unsigned int mtk_wireless_vendor_cmd_avail:1;
unsigned int mtk_bss_color_vendor_cmd_avail:1;
+ unsigned int mtk_rfeatures_vendor_cmd_avail:1;
u64 vendor_scan_cookie;
u64 remain_on_chan_cookie;
diff --git a/src/drivers/driver_nl80211_capa.c b/src/drivers/driver_nl80211_capa.c
index e7c6f39..6f4d029 100644
--- a/src/drivers/driver_nl80211_capa.c
+++ b/src/drivers/driver_nl80211_capa.c
@@ -1095,6 +1095,9 @@ static int wiphy_info_handler(struct nl_msg *msg, void *arg)
case MTK_NL80211_VENDOR_SUBCMD_BSS_COLOR_CTRL :
drv->mtk_bss_color_vendor_cmd_avail = 1;
break;
+ case MTK_NL80211_VENDOR_SUBCMD_RFEATURE_CTRL:
+ drv->mtk_rfeatures_vendor_cmd_avail = 1;
+ break;
}
}
--
2.18.0