766 lines
23 KiB
Diff
766 lines
23 KiB
Diff
From 67be9ce68d84e2800b481123a0c140e5ad912619 Mon Sep 17 00:00:00 2001
|
|
From: Carter Chen <carter.chen@infineon.com>
|
|
Date: Wed, 14 Dec 2022 01:34:23 -0600
|
|
Subject: [PATCH 49/60] non-upstream: MBO: wpa_cli mbo command by IFX vendorID
|
|
|
|
Signed-off-by: Carter Chen <carter.chen@infineon.com>
|
|
Signed-off-by: Shelley Yang <shelley.yang@infineon.com>
|
|
---
|
|
src/common/ifx_vendor.h | 52 ++++++++
|
|
src/drivers/driver.h | 46 +++++++
|
|
src/drivers/driver_nl80211.c | 141 ++++++++++++++++++++++
|
|
src/drivers/driver_nl80211.h | 1 +
|
|
src/drivers/driver_nl80211_capa.c | 3 +
|
|
wpa_supplicant/ctrl_iface.c | 193 ++++++++++++++++++++++++++++++
|
|
wpa_supplicant/driver_i.h | 8 ++
|
|
wpa_supplicant/mbo.c | 119 ++++++++++++++++++
|
|
wpa_supplicant/wpa_cli.c | 15 +++
|
|
wpa_supplicant/wpa_supplicant_i.h | 9 ++
|
|
10 files changed, 587 insertions(+)
|
|
|
|
diff --git a/src/common/ifx_vendor.h b/src/common/ifx_vendor.h
|
|
index aa8e83bc7..6cd3b874c 100644
|
|
--- a/src/common/ifx_vendor.h
|
|
+++ b/src/common/ifx_vendor.h
|
|
@@ -56,6 +56,8 @@
|
|
*
|
|
* @IFX_VENDOR_SCMD_TWT: Vendor subcommand to configure TWT
|
|
* Uses attributes defined in enum ifx_vendor_attr_twt.
|
|
+ * @IFX_VENDOR_SCMD_MBO: Vendor subcommand to configure MBO
|
|
+ * Uses attribute IFX_VENDOR_ATTR_MBO to configure.
|
|
*
|
|
* @IFX_VENDOR_SCMD_MAX: This acts as a the tail of cmds list.
|
|
* Make sure it located at the end of the list.
|
|
@@ -74,6 +76,8 @@ enum ifx_nl80211_vendor_subcmds {
|
|
IFX_VENDOR_SCMD_LDPC_CAP = 12,
|
|
IFX_VENDOR_SCMD_AMSDU = 13,
|
|
IFX_VENDOR_SCMD_TWT = 14,
|
|
+ /* Reserved 15-17 */
|
|
+ IFX_VENDOR_SCMD_MBO = 18,
|
|
IFX_VENDOR_SCMD_MAX
|
|
};
|
|
|
|
@@ -96,6 +100,13 @@ enum ifx_vendor_attr {
|
|
IFX_VENDOR_ATTR_MAX = 11
|
|
};
|
|
|
|
+enum ifx_vendor_attr_mbo {
|
|
+ IFX_VENDOR_ATTR_MBO_UNSPEC,
|
|
+ IFX_VENDOR_ATTR_MBO_CMD,
|
|
+ IFX_VENDOR_ATTR_MBO_PARAMS,
|
|
+ IFX_VENDOR_ATTR_MBO_MAX
|
|
+};
|
|
+
|
|
/*
|
|
* enum ifx_vendor_attr_twt - Attributes for the TWT vendor command
|
|
*
|
|
@@ -260,4 +271,45 @@ enum ifx_twt_oper_setup_cmd_type {
|
|
IFX_TWT_OPER_SETUP_CMD_TYPE_MAX = 8
|
|
};
|
|
|
|
+enum ifx_mbo_config_cmd_type {
|
|
+ IFX_MBO_CONFIG_CMD_TYPE_INVALID = -1,
|
|
+ //align internal definition
|
|
+ IFX_MBO_CONFIG_CMD_ADD_CHAN_PREF = 1,
|
|
+ IFX_MBO_CONFIG_CMD_DEL_CHAN_PREF = 2,
|
|
+ IFX_MBO_CONFIG_CMD_LIST_CHAN_PREF = 3,
|
|
+ IFX_MBO_CONFIG_CMD_CELLULAR_DATA_CAP = 4,
|
|
+ IFX_MBO_CONFIG_CMD_DUMP_COUNTER = 5,
|
|
+ IFX_MBO_CONFIG_CMD_CLEAR_COUNTER = 6,
|
|
+ IFX_MBO_CONFIG_CMD_FORCE_ASSOC = 7,
|
|
+ IFX_MBO_CONFIG_CMD_BSSTRANS_REJ = 8,
|
|
+ IFX_MBO_CONFIG_CMD_SEND_NOTIF = 9,
|
|
+ IFX_MBO_CONFIG_CMD_CLR_CHAN_PREF = 10,
|
|
+ IFX_MBO_CONFIG_CMD_NBR_INFO_CACHE = 11,
|
|
+ IFX_MBO_CONFIG_CMD_ANQPO_SUPPORT = 12,
|
|
+ IFX_MBO_CONFIG_CMD_DBG_EVENT_CHECK = 13,
|
|
+ IFX_MBO_CONFIG_CMD_EVENT_MASK = 14,
|
|
+ IFX_MBO_CONFIG_CMD_ASSOC_DISALLOWED = 15,
|
|
+ IFX_MBO_CONFIG_CMD_CELLULAR_DATA_PREF = 16,
|
|
+ IFX_MBO_CONFIG_CMD_TYPE_MAX = 17
|
|
+};
|
|
+
|
|
+enum ifx_vendor_attr_mbo_param {
|
|
+ IFX_VENDOR_ATTR_MBO_PARAM_UNSPEC,
|
|
+ IFX_VENDOR_ATTR_MBO_PARAM_OPCLASS,
|
|
+ IFX_VENDOR_ATTR_MBO_PARAM_CHAN,
|
|
+ IFX_VENDOR_ATTR_MBO_PARAM_PREFERENCE,
|
|
+ IFX_VENDOR_ATTR_MBO_PARAM_REASON_CODE,
|
|
+ IFX_VENDOR_ATTR_MBO_PARAM_CELL_DATA_CAP,
|
|
+ IFX_VENDOR_ATTR_MBO_PARAM_COUNTERS,
|
|
+ IFX_VENDOR_ATTR_MBO_PARAM_ENABLE,
|
|
+ IFX_VENDOR_ATTR_MBO_PARAM_SUB_ELEM_TYPE,
|
|
+ IFX_VENDOR_ATTR_MBO_PARAM_BTQ_TRIG_START_OFFSET,
|
|
+ IFX_VENDOR_ATTR_MBO_PARAM_BTQ_TRIG_RSSI_DELTA,
|
|
+ IFX_VENDOR_ATTR_MBO_PARAM_ANQP_CELL_SUPP,
|
|
+ IFX_VENDOR_ATTR_MBO_PARAM_BIT_MASK,
|
|
+ IFX_VENDOR_ATTR_MBO_PARAM_ASSOC_DISALLOWED,
|
|
+ IFX_VENDOR_ATTR_MBO_PARAM_CELLULAR_DATA_PREF,
|
|
+ IFX_VENDOR_ATTR_MBO_PARAM_MAX
|
|
+};
|
|
+
|
|
#endif /* IFX_VENDOR_H */
|
|
diff --git a/src/drivers/driver.h b/src/drivers/driver.h
|
|
index 23f599bef..996614ee5 100644
|
|
--- a/src/drivers/driver.h
|
|
+++ b/src/drivers/driver.h
|
|
@@ -2553,6 +2553,51 @@ struct drv_teardown_twt_params {
|
|
u8 teardown_all_twt;
|
|
};
|
|
#endif /* CONFIG_TWT_OFFLOAD_IFX */
|
|
+
|
|
+struct drv_config_mbo_params {
|
|
+ u8 cmd;
|
|
+ union {
|
|
+ struct {
|
|
+ u8 op_class;
|
|
+ u8 chan;
|
|
+ u8 pref_val;
|
|
+ u8 reason;
|
|
+ } add_chan_pref;
|
|
+ struct {
|
|
+ u8 op_class;
|
|
+ u8 chan;
|
|
+ } del_chan_pref;
|
|
+ struct {
|
|
+ u8 cap;
|
|
+ } cell_data_cap;
|
|
+ struct {
|
|
+ u8 enable;
|
|
+ } force_assoc;
|
|
+ struct {
|
|
+ u8 enable;
|
|
+ u8 reason;
|
|
+ } bsstrans_reject;
|
|
+ struct {
|
|
+ u8 type;
|
|
+ } send_notif;
|
|
+ struct {
|
|
+ u8 enable;
|
|
+ u8 t_offset;
|
|
+ u8 trig_delta;
|
|
+ } nbr_info_cache;
|
|
+ struct {
|
|
+ u8 enable;
|
|
+ u8 value;
|
|
+ } anqpo_support;
|
|
+ struct {
|
|
+ u8 disallow;
|
|
+ u8 reason;
|
|
+ } assoc_disallow;
|
|
+ struct {
|
|
+ u8 pref_value;
|
|
+ } cellular_pref;
|
|
+ } u;
|
|
+};
|
|
#endif /* CONFIG_DRIVER_NL80211_IFX */
|
|
|
|
struct wpa_bss_trans_info {
|
|
@@ -4681,6 +4726,7 @@ struct wpa_driver_ops {
|
|
*/
|
|
int (*teardown_twt)(void *priv, struct drv_teardown_twt_params *params);
|
|
#endif /* CONFIG_TWT_OFFLOAD_IFX */
|
|
+ int (*config_mbo)(void *priv, struct drv_config_mbo_params *params);
|
|
#endif /* CONFIG_DRIVER_NL80211_IFX */
|
|
|
|
};
|
|
diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c
|
|
index 3d98e5943..506b1e406 100644
|
|
--- a/src/drivers/driver_nl80211.c
|
|
+++ b/src/drivers/driver_nl80211.c
|
|
@@ -12473,6 +12473,146 @@ fail:
|
|
return ret;
|
|
}
|
|
#endif /* CONFIG_TWT_OFFLOAD_IFX */
|
|
+
|
|
+static int wpa_driver_nl80211_config_mbo(void *priv, struct drv_config_mbo_params *params)
|
|
+{
|
|
+ struct i802_bss *bss = priv;
|
|
+ struct wpa_driver_nl80211_data *drv = bss->drv;
|
|
+ struct nl_msg *msg = NULL;
|
|
+ struct nlattr *data, *mbo_param_attrs;
|
|
+ int ret = -1;
|
|
+
|
|
+ if (!drv->ifx_mbo_offload)
|
|
+ goto fail;
|
|
+
|
|
+ if (!(msg = nl80211_drv_msg(drv, 0, NL80211_CMD_VENDOR)) ||
|
|
+ nla_put_u32(msg, NL80211_ATTR_VENDOR_ID, OUI_IFX) ||
|
|
+ nla_put_u32(msg, NL80211_ATTR_VENDOR_SUBCMD, IFX_VENDOR_SCMD_MBO))
|
|
+ goto fail;
|
|
+
|
|
+ data = nla_nest_start(msg, NL80211_ATTR_VENDOR_DATA);
|
|
+ if (!data)
|
|
+ goto fail;
|
|
+
|
|
+ if (nla_put_u8(msg, IFX_VENDOR_ATTR_MBO_CMD, params->cmd))
|
|
+ goto fail;
|
|
+
|
|
+ switch (params->cmd) {
|
|
+ case IFX_MBO_CONFIG_CMD_ADD_CHAN_PREF:
|
|
+ mbo_param_attrs = nla_nest_start(msg, IFX_VENDOR_ATTR_MBO_PARAMS);
|
|
+ if (!mbo_param_attrs)
|
|
+ goto fail;
|
|
+
|
|
+ if (nla_put_u8(msg, IFX_VENDOR_ATTR_MBO_PARAM_OPCLASS,
|
|
+ params->u.add_chan_pref.op_class) ||
|
|
+ nla_put_u8(msg, IFX_VENDOR_ATTR_MBO_PARAM_CHAN,
|
|
+ params->u.add_chan_pref.chan) ||
|
|
+ nla_put_u8(msg, IFX_VENDOR_ATTR_MBO_PARAM_PREFERENCE,
|
|
+ params->u.add_chan_pref.pref_val) ||
|
|
+ nla_put_u8(msg, IFX_VENDOR_ATTR_MBO_PARAM_REASON_CODE,
|
|
+ params->u.add_chan_pref.reason)) {
|
|
+ wpa_printf(MSG_ERROR,
|
|
+ "nl80211: MBO config: build IFX_MBO_CONFIG_CMD_ADD_CHAN_PREF msg failed");
|
|
+ goto fail;
|
|
+ }
|
|
+ nla_nest_end(msg, mbo_param_attrs);
|
|
+ break;
|
|
+ case IFX_MBO_CONFIG_CMD_DEL_CHAN_PREF:
|
|
+ mbo_param_attrs = nla_nest_start(msg, IFX_VENDOR_ATTR_MBO_PARAMS);
|
|
+ if (!mbo_param_attrs)
|
|
+ goto fail;
|
|
+
|
|
+ if (nla_put_u8(msg, IFX_VENDOR_ATTR_MBO_PARAM_OPCLASS,
|
|
+ params->u.del_chan_pref.op_class) ||
|
|
+ nla_put_u8(msg, IFX_VENDOR_ATTR_MBO_PARAM_CHAN,
|
|
+ params->u.del_chan_pref.chan)) {
|
|
+ wpa_printf(MSG_ERROR,
|
|
+ "nl80211: MBO config: build IFX_MBO_CONFIG_CMD_DEL_CHAN_PREF msg failed");
|
|
+ goto fail;
|
|
+ }
|
|
+ nla_nest_end(msg, mbo_param_attrs);
|
|
+ break;
|
|
+ case IFX_MBO_CONFIG_CMD_CELLULAR_DATA_CAP:
|
|
+ mbo_param_attrs = nla_nest_start(msg, IFX_VENDOR_ATTR_MBO_PARAMS);
|
|
+ if (!mbo_param_attrs)
|
|
+ goto fail;
|
|
+
|
|
+ if (nla_put_u8(msg, IFX_VENDOR_ATTR_MBO_PARAM_CELL_DATA_CAP,
|
|
+ params->u.cell_data_cap.cap)) {
|
|
+ wpa_printf(MSG_ERROR,
|
|
+ "nl80211: MBO config: build IFX_MBO_CONFIG_CMD_CELLULAR_DATA_CAP msg failed");
|
|
+ goto fail;
|
|
+ }
|
|
+ nla_nest_end(msg, mbo_param_attrs);
|
|
+ break;
|
|
+ case IFX_MBO_CONFIG_CMD_FORCE_ASSOC:
|
|
+ mbo_param_attrs = nla_nest_start(msg, IFX_VENDOR_ATTR_MBO_PARAMS);
|
|
+ if (!mbo_param_attrs)
|
|
+ goto fail;
|
|
+
|
|
+ if (nla_put_u8(msg, IFX_VENDOR_ATTR_MBO_PARAM_ENABLE,
|
|
+ params->u.force_assoc.enable)) {
|
|
+ wpa_printf(MSG_ERROR,
|
|
+ "nl80211: MBO config: build IFX_MBO_CONFIG_CMD_FORCE_ASSOC msg failed");
|
|
+ goto fail;
|
|
+ }
|
|
+ nla_nest_end(msg, mbo_param_attrs);
|
|
+ break;
|
|
+ case IFX_MBO_CONFIG_CMD_BSSTRANS_REJ:
|
|
+ mbo_param_attrs = nla_nest_start(msg, IFX_VENDOR_ATTR_MBO_PARAMS);
|
|
+ if (!mbo_param_attrs)
|
|
+ goto fail;
|
|
+
|
|
+ if (nla_put_u8(msg, IFX_VENDOR_ATTR_MBO_PARAM_ENABLE,
|
|
+ params->u.bsstrans_reject.enable) ||
|
|
+ nla_put_u8(msg, IFX_VENDOR_ATTR_MBO_PARAM_REASON_CODE,
|
|
+ params->u.bsstrans_reject.reason)) {
|
|
+ wpa_printf(MSG_ERROR,
|
|
+ "nl80211: MBO config: build IFX_MBO_CONFIG_CMD_DEL_CHAN_PREF msg failed");
|
|
+ goto fail;
|
|
+ }
|
|
+ nla_nest_end(msg, mbo_param_attrs);
|
|
+ break;
|
|
+ case IFX_MBO_CONFIG_CMD_SEND_NOTIF:
|
|
+ mbo_param_attrs = nla_nest_start(msg, IFX_VENDOR_ATTR_MBO_PARAMS);
|
|
+ if (!mbo_param_attrs)
|
|
+ goto fail;
|
|
+
|
|
+ if (nla_put_u8(msg, IFX_VENDOR_ATTR_MBO_PARAM_SUB_ELEM_TYPE,
|
|
+ params->u.send_notif.type)) {
|
|
+ wpa_printf(MSG_ERROR,
|
|
+ "nl80211: MBO config: build IFX_MBO_CONFIG_CMD_FORCE_ASSOC msg failed");
|
|
+ goto fail;
|
|
+ }
|
|
+ nla_nest_end(msg, mbo_param_attrs);
|
|
+ break;
|
|
+ case IFX_MBO_CONFIG_CMD_LIST_CHAN_PREF:
|
|
+ case IFX_MBO_CONFIG_CMD_DUMP_COUNTER:
|
|
+ case IFX_MBO_CONFIG_CMD_CLEAR_COUNTER:
|
|
+ wpa_printf(MSG_DEBUG,
|
|
+ "MBO config: cmd %d doesn't need extra attribute",
|
|
+ params->cmd);
|
|
+ break;
|
|
+ default:
|
|
+ break;
|
|
+ }
|
|
+
|
|
+ nla_nest_end(msg, data);
|
|
+
|
|
+ ret = send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL);
|
|
+ if (ret) {
|
|
+ wpa_printf(MSG_ERROR,
|
|
+ "nl80211: MBO config: Failed to invoke driver "
|
|
+ "MBO config function: %s",
|
|
+ strerror(-ret));
|
|
+ }
|
|
+
|
|
+ return ret;
|
|
+fail:
|
|
+ nl80211_nlmsg_clear(msg);
|
|
+ nlmsg_free(msg);
|
|
+ return ret;
|
|
+}
|
|
#endif /* CONFIG_DRIVER_NL80211_IFX */
|
|
|
|
const struct wpa_driver_ops wpa_driver_nl80211_ops = {
|
|
@@ -12624,5 +12764,6 @@ const struct wpa_driver_ops wpa_driver_nl80211_ops = {
|
|
.setup_twt = wpa_driver_nl80211_setup_twt,
|
|
.teardown_twt = wpa_driver_nl80211_teardown_twt,
|
|
#endif /* CONFIG_TWT_OFFLOAD_IFX */
|
|
+ .config_mbo = wpa_driver_nl80211_config_mbo,
|
|
#endif /* CONFIG_DRIVER_NL80211_IFX */
|
|
};
|
|
diff --git a/src/drivers/driver_nl80211.h b/src/drivers/driver_nl80211.h
|
|
index f681afb41..6d2c09477 100644
|
|
--- a/src/drivers/driver_nl80211.h
|
|
+++ b/src/drivers/driver_nl80211.h
|
|
@@ -182,6 +182,7 @@ struct wpa_driver_nl80211_data {
|
|
unsigned int brcm_do_acs:1;
|
|
#ifdef CONFIG_DRIVER_NL80211_IFX
|
|
unsigned int ifx_twt_offload:1;
|
|
+ unsigned int ifx_mbo_offload:1;
|
|
#endif /* CONFIG_DRIVER_NL80211_IFX */
|
|
|
|
u64 vendor_scan_cookie;
|
|
diff --git a/src/drivers/driver_nl80211_capa.c b/src/drivers/driver_nl80211_capa.c
|
|
index 19d1569bf..b0807a7fc 100644
|
|
--- a/src/drivers/driver_nl80211_capa.c
|
|
+++ b/src/drivers/driver_nl80211_capa.c
|
|
@@ -1059,6 +1059,9 @@ static int wiphy_info_handler(struct nl_msg *msg, void *arg)
|
|
case IFX_VENDOR_SCMD_TWT:
|
|
drv->ifx_twt_offload = 1;
|
|
break;
|
|
+ case IFX_VENDOR_SCMD_MBO:
|
|
+ drv->ifx_mbo_offload = 1;
|
|
+ break;
|
|
}
|
|
#endif /* CONFIG_DRIVER_NL80211_IFX */
|
|
}
|
|
diff --git a/wpa_supplicant/ctrl_iface.c b/wpa_supplicant/ctrl_iface.c
|
|
index 90cc4861c..9f0149a20 100644
|
|
--- a/wpa_supplicant/ctrl_iface.c
|
|
+++ b/wpa_supplicant/ctrl_iface.c
|
|
@@ -10150,6 +10150,194 @@ static int wpas_ctrl_iface_send_twt_teardown(struct wpa_supplicant *wpa_s,
|
|
}
|
|
|
|
|
|
+#ifdef CONFIG_DRIVER_NL80211_IFX
|
|
+int wpas_config_offload_send_mbo_config(struct wpa_supplicant *wpa_s, u8 cmd_id,
|
|
+ u8 oper_class, u8 chan, u8 pref_val,
|
|
+ u8 reason_code, u8 enable, u8 notif_type,
|
|
+ u8 time_offset, u8 rssi_trig_delta,
|
|
+ bool enable_anqpo, bool enable_cell_pref,
|
|
+ u8 cell_pref_val, u8 cell_cap)
|
|
+{
|
|
+ struct drv_config_mbo_params params;
|
|
+ int ret = 0;
|
|
+
|
|
+ memset(¶ms, 0, sizeof(struct drv_config_mbo_params));
|
|
+
|
|
+ switch (cmd_id) {
|
|
+ case IFX_MBO_CONFIG_CMD_ADD_CHAN_PREF:
|
|
+ if (!oper_class || !chan ||
|
|
+ (pref_val != 0 && pref_val != 1 && pref_val != 255) ||
|
|
+ reason_code > 3) {
|
|
+ wpa_printf(MSG_ERROR,
|
|
+ "MBO: incorrect parameter for add_chan_pref oper_class: %d "
|
|
+ "chan:%d pref_val:%d reason_code:%d",
|
|
+ oper_class, chan, pref_val, reason_code);
|
|
+ ret = -EOPNOTSUPP;
|
|
+ goto fail;
|
|
+ }
|
|
+ params.cmd = cmd_id;
|
|
+ params.u.add_chan_pref.op_class = oper_class;
|
|
+ params.u.add_chan_pref.chan = chan;
|
|
+ params.u.add_chan_pref.pref_val = pref_val;
|
|
+ params.u.add_chan_pref.reason = reason_code;
|
|
+ break;
|
|
+ case IFX_MBO_CONFIG_CMD_DEL_CHAN_PREF:
|
|
+ if (!oper_class || !chan) {
|
|
+ wpa_printf(MSG_ERROR,
|
|
+ "MBO: incorrect parameter for del_chan_pref "
|
|
+ "oper_class: %d chan:%d",
|
|
+ oper_class, chan);
|
|
+ ret = -EOPNOTSUPP;
|
|
+ goto fail;
|
|
+ }
|
|
+ params.cmd = cmd_id;
|
|
+ params.u.del_chan_pref.op_class = oper_class;
|
|
+ params.u.del_chan_pref.chan = chan;
|
|
+ break;
|
|
+ case IFX_MBO_CONFIG_CMD_LIST_CHAN_PREF:
|
|
+ case IFX_MBO_CONFIG_CMD_DUMP_COUNTER:
|
|
+ case IFX_MBO_CONFIG_CMD_CLEAR_COUNTER:
|
|
+ params.cmd = cmd_id;
|
|
+ break;
|
|
+ case IFX_MBO_CONFIG_CMD_CELLULAR_DATA_CAP:
|
|
+ if (!cell_cap || cell_cap > 3) {
|
|
+ wpa_printf(MSG_ERROR,
|
|
+ "MBO: incorrect parameter for cellular_data_cap:%d",
|
|
+ cell_cap);
|
|
+ ret = -EOPNOTSUPP;
|
|
+ goto fail;
|
|
+ }
|
|
+ params.cmd = cmd_id;
|
|
+ params.u.cell_data_cap.cap = cell_cap;
|
|
+ break;
|
|
+ case IFX_MBO_CONFIG_CMD_FORCE_ASSOC:
|
|
+ if (enable > 1) {
|
|
+ wpa_printf(MSG_ERROR,
|
|
+ "MBO: incorrect parameter for force_assoc:%d",
|
|
+ enable);
|
|
+ ret = -EOPNOTSUPP;
|
|
+ goto fail;
|
|
+ }
|
|
+ params.cmd = cmd_id;
|
|
+ params.u.force_assoc.enable = enable;
|
|
+ break;
|
|
+ case IFX_MBO_CONFIG_CMD_BSSTRANS_REJ:
|
|
+ if (enable > 1 || reason_code > 6) {
|
|
+ wpa_printf(MSG_ERROR,
|
|
+ "MBO: incorrect parameter for bsstrans reject, enable:%d, reason:%d",
|
|
+ enable, reason_code);
|
|
+ ret = -EOPNOTSUPP;
|
|
+ goto fail;
|
|
+ }
|
|
+ params.cmd = cmd_id;
|
|
+ params.u.bsstrans_reject.enable = enable;
|
|
+ params.u.bsstrans_reject.reason = reason_code;
|
|
+ break;
|
|
+ case IFX_MBO_CONFIG_CMD_SEND_NOTIF:
|
|
+ if (notif_type != 2 && notif_type != 3) {
|
|
+ wpa_printf(MSG_ERROR,
|
|
+ "MBO: incorrect parameter for send notifty:%d",
|
|
+ notif_type);
|
|
+ ret = -EOPNOTSUPP;
|
|
+ goto fail;
|
|
+ }
|
|
+ params.cmd = cmd_id;
|
|
+ params.u.send_notif.type = notif_type;
|
|
+ break;
|
|
+ case IFX_MBO_CONFIG_CMD_NBR_INFO_CACHE:
|
|
+ case IFX_MBO_CONFIG_CMD_ANQPO_SUPPORT:
|
|
+ case IFX_MBO_CONFIG_CMD_CELLULAR_DATA_PREF:
|
|
+ default:
|
|
+ wpa_printf(MSG_DEBUG, "MBO: Unsupported cmd_id %d",
|
|
+ cmd_id);
|
|
+ ret = -EOPNOTSUPP;
|
|
+ goto fail;
|
|
+ }
|
|
+
|
|
+ ret = wpa_drv_config_mbo(wpa_s, ¶ms);
|
|
+
|
|
+fail:
|
|
+ return ret;
|
|
+}
|
|
+
|
|
+static int wpas_ctrl_iface_send_mbo_config(struct wpa_supplicant *wpa_s,
|
|
+ const char *cmd)
|
|
+{
|
|
+ u8 oper_class = 0;
|
|
+ u8 chan = 0;
|
|
+ u8 pref_val = 0;
|
|
+ u8 reason_code = 0;
|
|
+ u8 cmd_id = 0;
|
|
+ u8 enable = 0;
|
|
+ u8 notif_type = 0;
|
|
+ u8 time_offset = 0;
|
|
+ u8 rssi_trig_delta = 0;
|
|
+ bool enable_anqpo = false;
|
|
+ bool enable_cell_pref = false;
|
|
+ u8 cell_pref_val = 0;
|
|
+ u8 cell_cap = 0;
|
|
+ const char *tok_s;
|
|
+
|
|
+ tok_s = os_strstr(cmd, " cmd_id=");
|
|
+ if (tok_s)
|
|
+ cmd_id = strtol(tok_s + os_strlen(" cmd_id="), NULL, 10);
|
|
+
|
|
+ tok_s = os_strstr(cmd, " oper_class=");
|
|
+ if (tok_s)
|
|
+ oper_class = strtol(tok_s + os_strlen(" oper_class="), NULL, 10);
|
|
+
|
|
+ tok_s = os_strstr(cmd, " pref_val=");
|
|
+ if (tok_s)
|
|
+ pref_val = strtol(tok_s + os_strlen(" pref_val="), NULL, 10);
|
|
+
|
|
+ tok_s = os_strstr(cmd, " reason_code=");
|
|
+ if (tok_s)
|
|
+ reason_code = strtol(tok_s + os_strlen(" reason_code="), NULL, 10);
|
|
+
|
|
+ tok_s = os_strstr(cmd, " chan=");
|
|
+ if (tok_s)
|
|
+ chan = strtol(tok_s + os_strlen(" chan="), NULL, 10);
|
|
+
|
|
+ tok_s = os_strstr(cmd, " cell_cap=");
|
|
+ if (tok_s)
|
|
+ cell_cap = strtol(tok_s + os_strlen(" cell_cap="), NULL, 10);
|
|
+
|
|
+ tok_s = os_strstr(cmd, " enable=");
|
|
+ if (tok_s)
|
|
+ enable = strtol(tok_s + os_strlen(" enable="), NULL, 10);
|
|
+
|
|
+ tok_s = os_strstr(cmd, " notif_type=");
|
|
+ if (tok_s)
|
|
+ notif_type = strtol(tok_s + os_strlen(" notif_type="), NULL, 10);
|
|
+
|
|
+ tok_s = os_strstr(cmd, " time_offset=");
|
|
+ if (tok_s)
|
|
+ time_offset = strtol(tok_s + os_strlen(" time_offset="), NULL, 10);
|
|
+
|
|
+ tok_s = os_strstr(cmd, " rssi_trig_delta=");
|
|
+ if (tok_s)
|
|
+ rssi_trig_delta = strtol(tok_s + os_strlen(" rssi_trig_delta="), NULL, 10);
|
|
+
|
|
+ tok_s = os_strstr(cmd, " enable_anqpo=");
|
|
+ if (tok_s)
|
|
+ enable_anqpo = strtol(tok_s + os_strlen(" enable_anqpo="), NULL, 10);
|
|
+
|
|
+ tok_s = os_strstr(cmd, " enable_cell_pref=");
|
|
+ if (tok_s)
|
|
+ enable_cell_pref = strtol(tok_s + os_strlen(" enable_cell_pref="), NULL, 10);
|
|
+
|
|
+ tok_s = os_strstr(cmd, " cell_pref_val=");
|
|
+ if (tok_s)
|
|
+ cell_pref_val = strtol(tok_s + os_strlen(" cell_pref_val="), NULL, 10);
|
|
+
|
|
+ return wpas_config_offload_send_mbo_config(wpa_s, cmd_id, oper_class,
|
|
+ chan, pref_val, reason_code,
|
|
+ enable, notif_type, time_offset,
|
|
+ rssi_trig_delta, enable_anqpo,
|
|
+ enable_cell_pref, cell_pref_val,
|
|
+ cell_cap);
|
|
+}
|
|
+#endif /* CONFIG_DRIVER_NL80211_IFX */
|
|
|
|
static int wpas_ctrl_vendor_elem_add(struct wpa_supplicant *wpa_s, char *cmd)
|
|
{
|
|
@@ -12271,6 +12459,11 @@ char * wpa_supplicant_ctrl_iface_process(struct wpa_supplicant *wpa_s,
|
|
} else if (os_strcmp(buf, "TWT_SETUP") == 0) {
|
|
if (wpas_ctrl_iface_send_twt_setup(wpa_s, ""))
|
|
reply_len = -1;
|
|
+#ifdef CONFIG_DRIVER_NL80211_IFX
|
|
+ } else if (os_strncmp(buf, "MBO ", 4) == 0) {
|
|
+ if (wpas_ctrl_iface_send_mbo_config(wpa_s, buf + 3))
|
|
+ reply_len = -1;
|
|
+#endif /* CONFIG_DRIVER_NL80211_IFX */
|
|
} else if (os_strncmp(buf, "TWT_TEARDOWN ", 13) == 0) {
|
|
if (wpas_ctrl_iface_send_twt_teardown(wpa_s, buf + 12))
|
|
reply_len = -1;
|
|
diff --git a/wpa_supplicant/driver_i.h b/wpa_supplicant/driver_i.h
|
|
index 9a7975a6a..2fcfa44a6 100644
|
|
--- a/wpa_supplicant/driver_i.h
|
|
+++ b/wpa_supplicant/driver_i.h
|
|
@@ -1145,6 +1145,14 @@ static inline int wpa_drv_teardown_twt(struct wpa_supplicant *wpa_s,
|
|
return wpa_s->driver->teardown_twt(wpa_s->drv_priv, params);
|
|
}
|
|
#endif /* CONFIG_TWT_OFFLOAD_IFX */
|
|
+
|
|
+static inline int wpa_drv_config_mbo(struct wpa_supplicant *wpa_s,
|
|
+ struct drv_config_mbo_params *params)
|
|
+{
|
|
+ if (!wpa_s->driver->config_mbo)
|
|
+ return -1;
|
|
+ return wpa_s->driver->config_mbo(wpa_s->drv_priv, params);
|
|
+}
|
|
#endif /* CONFIG_DRIVER_NL80211_IFX */
|
|
|
|
#endif /* DRIVER_I_H */
|
|
diff --git a/wpa_supplicant/mbo.c b/wpa_supplicant/mbo.c
|
|
index 3df86ef07..714f9ef6f 100644
|
|
--- a/wpa_supplicant/mbo.c
|
|
+++ b/wpa_supplicant/mbo.c
|
|
@@ -663,3 +663,122 @@ void mbo_parse_rx_anqp_resp(struct wpa_supplicant *wpa_s,
|
|
break;
|
|
}
|
|
}
|
|
+
|
|
+#ifdef CONFIG_DRIVER_NL80211_IFX
|
|
+int wpas_config_offload_send_mbo_config(struct wpa_supplicant *wpa_s, u8 cmd_id,
|
|
+ u8 oper_class, u8 chan, u8 pref_val,
|
|
+ u8 reason_code, u8 enable, u8 notif_type,
|
|
+ u8 time_offset, u8 rssi_trig_delta,
|
|
+ bool enable_anqpo, bool enable_cell_pref,
|
|
+ u8 cell_pref_val, u8 cell_cap)
|
|
+{
|
|
+ struct drv_config_mbo_params params;
|
|
+ int ret = 0;
|
|
+
|
|
+ memset(¶ms, 0, sizeof(struct drv_config_mbo_params));
|
|
+
|
|
+ switch (cmd_id) {
|
|
+ case IFX_MBO_CONFIG_CMD_ADD_CHAN_PREF:
|
|
+ if (!oper_class || !chan ||
|
|
+ (pref_val != 0 && pref_val != 1 && pref_val != 255) ||
|
|
+ reason_code > 3) {
|
|
+ wpa_printf(MSG_ERROR,
|
|
+ "MBO: incorrect parameter for add_chan_pref oper_class: %d "
|
|
+ "chan:%d pref_val:%d reason_code:%d",
|
|
+ oper_class, chan, pref_val, reason_code);
|
|
+ ret = -EOPNOTSUPP;
|
|
+ goto fail;
|
|
+ }
|
|
+ params.cmd = cmd_id;
|
|
+ params.u.add_chan_pref.op_class = oper_class;
|
|
+ params.u.add_chan_pref.chan = chan;
|
|
+ params.u.add_chan_pref.pref_val = pref_val;
|
|
+ params.u.add_chan_pref.reason = reason;
|
|
+ break;
|
|
+ case IFX_MBO_CONFIG_CMD_DEL_CHAN_PREF:
|
|
+ if (!oper_class || !chan) {
|
|
+ wpa_printf(MSG_ERROR,
|
|
+ "MBO: incorrect parameter for del_chan_pref "
|
|
+ "oper_class: %d chan:%d",
|
|
+ oper_class, chan);
|
|
+ ret = -EOPNOTSUPP;
|
|
+ goto fail;
|
|
+ }
|
|
+ params.cmd = cmd_id;
|
|
+ params.u.del_chan_pref.op_class = oper_class;
|
|
+ params.u.del_chan_pref.chan = chan;
|
|
+ break;
|
|
+ case IFX_MBO_CONFIG_CMD_LIST_CHAN_PREF:
|
|
+ params.cmd = cmd_id;
|
|
+ break;
|
|
+ case IFX_MBO_CONFIG_CMD_CELLULAR_DATA_CAP:
|
|
+ if (!cell_cap || cell_cap > 3) {
|
|
+ wpa_printf(MSG_ERROR,
|
|
+ "MBO: incorrect parameter for cellular_data_cap:%d",
|
|
+ cell_cap);
|
|
+ ret = -EOPNOTSUPP;
|
|
+ goto fail;
|
|
+ }
|
|
+ params.cmd = cmd_id;
|
|
+ params.u.cell_data_cap.cap = cell_cap;
|
|
+ break;
|
|
+ case IFX_MBO_CONFIG_CMD_DUMP_COUNTER:
|
|
+ params.cmd = cmd_id;
|
|
+ break;
|
|
+ case IFX_MBO_CONFIG_CMD_CLEAR_COUNTER:
|
|
+ params.cmd = cmd_id;
|
|
+ break;
|
|
+ case IFX_MBO_CONFIG_CMD_FORCE_ASSOC:
|
|
+ if (enable > 1) {
|
|
+ wpa_printf(MSG_ERROR,
|
|
+ "MBO: incorrect parameter for force_assoc:%d",
|
|
+ enable);
|
|
+ ret = -EOPNOTSUPP;
|
|
+ goto fail;
|
|
+ }
|
|
+ params.cmd = cmd_id;
|
|
+ params.u.force_assoc.enable = enable;
|
|
+ break;
|
|
+ case IFX_MBO_CONFIG_CMD_BSSTRANS_REJ:
|
|
+ if (enable > 1 || reason_code > 6) {
|
|
+ wpa_printf(MSG_ERROR,
|
|
+ "MBO: incorrect parameter for bsstrans reject, enable:%d, reason:%d",
|
|
+ enable, reason_code);
|
|
+ ret = -EOPNOTSUPP;
|
|
+ goto fail;
|
|
+ }
|
|
+ params.cmd = cmd_id;
|
|
+ params.u.bsstrans_reject.enable = enable;
|
|
+ params.u.bsstrans_reject.reason = reason_code;
|
|
+ break;
|
|
+ case IFX_MBO_CONFIG_CMD_SEND_NOTIF:
|
|
+ if (notif_type != 2 && notif_type != 3) {
|
|
+ wpa_printf(MSG_ERROR,
|
|
+ "MBO: incorrect parameter for send notifty:%d",
|
|
+ notif_type);
|
|
+ ret = -EOPNOTSUPP;
|
|
+ goto fail;
|
|
+ }
|
|
+ params.cmd = cmd_id;
|
|
+ params.u.send_notif.type = notif_type;
|
|
+ break;
|
|
+ case IFX_MBO_CONFIG_CMD_NBR_INFO_CACHE:
|
|
+ break;
|
|
+ case IFX_MBO_CONFIG_CMD_ANQPO_SUPPORT:
|
|
+ break;
|
|
+ case IFX_MBO_CONFIG_CMD_CELLULAR_DATA_PREF:
|
|
+ break;
|
|
+ default:
|
|
+ wpa_printf(MSG_DEBUG, "MBO: Unsupported cmd_id %d",
|
|
+ cmd_id);
|
|
+ ret = -EOPNOTSUPP;
|
|
+ goto fail;
|
|
+ }
|
|
+
|
|
+ ret = wpa_drv_config_mbo(wpa_s, params);
|
|
+
|
|
+fail:
|
|
+ return ret;
|
|
+}
|
|
+#endif /* CONFIG_DRIVER_NL80211_IFX */
|
|
+
|
|
diff --git a/wpa_supplicant/wpa_cli.c b/wpa_supplicant/wpa_cli.c
|
|
index 07160b5da..3055417fe 100644
|
|
--- a/wpa_supplicant/wpa_cli.c
|
|
+++ b/wpa_supplicant/wpa_cli.c
|
|
@@ -2957,6 +2957,15 @@ static int wpa_cli_cmd_twt_teardown(struct wpa_ctrl *ctrl, int argc,
|
|
}
|
|
|
|
|
|
+#ifdef CONFIG_DRIVER_NL80211_IFX
|
|
+static int wpa_cli_cmd_mbo_config(struct wpa_ctrl *ctrl, int argc,
|
|
+ char *argv[])
|
|
+{
|
|
+ return wpa_cli_cmd(ctrl, "MBO", 0, argc, argv);
|
|
+}
|
|
+#endif /* CONFIG_DRIVER_NL80211_IFX */
|
|
+
|
|
+
|
|
static int wpa_cli_cmd_erp_flush(struct wpa_ctrl *ctrl, int argc, char *argv[])
|
|
{
|
|
return wpa_ctrl_command(ctrl, "ERP_FLUSH");
|
|
@@ -3880,8 +3889,14 @@ static const struct wpa_cli_cmd wpa_cli_commands[] = {
|
|
},
|
|
{ "twt_teardown",
|
|
wpa_cli_cmd_twt_teardown, NULL, cli_cmd_flag_none,
|
|
+ "[cmd_id=<value>] [oper_class=0|1|255] [pref_val=0|1|255] [reason_code=<reason-u8>] [chan=<channel id>] [cell_cap=1|2] [enable=0|1] [notif_type=2|3] = Send MBO Setup frame"
|
|
+ },
|
|
+#ifdef CONFIG_DRIVER_NL80211_IFX
|
|
+ { "mbo",
|
|
+ wpa_cli_cmd_mbo_config, NULL, cli_cmd_flag_none,
|
|
"[flags=<value>] = Send TWT Teardown frame"
|
|
},
|
|
+#endif/* CONFIG_DRIVER_NL80211_IFX */
|
|
{ "erp_flush", wpa_cli_cmd_erp_flush, NULL, cli_cmd_flag_none,
|
|
"= flush ERP keys" },
|
|
{ "mac_rand_scan",
|
|
diff --git a/wpa_supplicant/wpa_supplicant_i.h b/wpa_supplicant/wpa_supplicant_i.h
|
|
index 28eff55ed..553d27d2c 100644
|
|
--- a/wpa_supplicant/wpa_supplicant_i.h
|
|
+++ b/wpa_supplicant/wpa_supplicant_i.h
|
|
@@ -1712,6 +1712,15 @@ void mbo_parse_rx_anqp_resp(struct wpa_supplicant *wpa_s,
|
|
const u8 *data, size_t slen);
|
|
void wpas_update_mbo_connect_params(struct wpa_supplicant *wpa_s);
|
|
|
|
+#ifdef CONFIG_DRIVER_NL80211_IFX
|
|
+int wpas_config_offload_send_mbo_config(struct wpa_supplicant *wpa_s, u8 cmd_id,
|
|
+ u8 oper_class, u8 chan, u8 pref_val,
|
|
+ u8 reason_code, u8 enable, u8 notif_type,
|
|
+ u8 time_offset, u8 rssi_trig_delta,
|
|
+ bool enable_anqpo, bool enable_cell_pref,
|
|
+ u8 cell_pref_val, u8 cell_cap);
|
|
+#endif /* CONFIG_DRIVER_NL80211_IFX */
|
|
+
|
|
/* op_classes.c */
|
|
enum chan_allowed {
|
|
NOT_ALLOWED, NO_IR, RADAR, ALLOWED
|
|
--
|
|
2.17.1
|
|
|