diff --git a/iot_sim/Kbuild b/iot_sim/Kbuild index 7e98265df2..6a8bf0f8f1 100644 --- a/iot_sim/Kbuild +++ b/iot_sim/Kbuild @@ -100,7 +100,7 @@ INCS += -I$(obj)/$(DEPTH)/include -I$(obj)/$(DEPTH)/umac/include \ -I$(obj)/$(DEPTH)/cmn_dev/umac/mlme/pdev_mgr/dispatcher/inc \ -I$(obj)/$(DEPTH)/direct_attach/hal/linux \ -#INCS += -I$(obj)/$(DEPTH)/cmn_dev/target_if/iot_sim +INCS += -I$(obj)/$(DEPTH)/cmn_dev/target_if/iot_sim INCS += -I$(obj)/$(DEPTH)/cmn_dev/wmi/inc #end of offload related defines @@ -122,15 +122,13 @@ ifeq ($(strip ${QCA_PARTNER_MAKE_F_SUPPORT}),1) MOD_CFLAGS = -D"KBUILD_STR(s)=\#s" -D"KBUILD_BASENAME=KBUILD_STR(qca_iot_sim.mod)" -D"KBUILD_MODNAME=KBUILD_STR(qca_iot_sim)" endif -IOT_SIM_TIF_OBJS += - IOT_SIM_CMN_OBJS += core/iot_sim_common.o \ dispatcher/src/wlan_iot_sim_utils_api.o \ dispatcher/src/wlan_iot_sim_tgt_api.o \ - core/iot_sim_module.o + core/iot_sim_utils.o \ + core/iot_sim_module.o -qca_iot_sim-objs += ${IOT_SIM_CMN_OBJS} \ - ${IOT_SIM_TIF_OBJS} +qca_iot_sim-objs += ${IOT_SIM_CMN_OBJS} ifeq ($(strip ${QCA_PARTNER_MAKE_F_SUPPORT}),1) all: qca_iot_sim.ko diff --git a/iot_sim/core/iot_sim_cmn_api_i.h b/iot_sim/core/iot_sim_cmn_api_i.h index f8fb1670fb..3c0e2b77aa 100644 --- a/iot_sim/core/iot_sim_cmn_api_i.h +++ b/iot_sim/core/iot_sim_cmn_api_i.h @@ -64,6 +64,19 @@ QDF_STATUS wlan_iot_sim_pdev_obj_create_handler(struct wlan_objmgr_pdev *pdev, QDF_STATUS wlan_iot_sim_pdev_obj_destroy_handler(struct wlan_objmgr_pdev *pdev, void *arg); +/** + * iot_sim_frame_update() - Management frame update + * @pdev: reference to global pdev object + * @nbuf: frame buffer + * + * This function updates the outgoing management frame with + * the content stored in iot_sim_context. + * + * Return: QDF_STATUS_SUCCESS on success + * QDF_STATUS_E_FAILURE on failure + */ +QDF_STATUS iot_sim_frame_update(struct wlan_objmgr_pdev *pdev, qdf_nbuf_t nbuf); + /* * iot_sim_get_ctx_from_pdev() - API to get iot_sim context object * from pdev diff --git a/iot_sim/core/iot_sim_utils.c b/iot_sim/core/iot_sim_utils.c new file mode 100644 index 0000000000..d385e4e62d --- /dev/null +++ b/iot_sim/core/iot_sim_utils.c @@ -0,0 +1,121 @@ +/* + * Copyright (c) 2020, The Linux Foundation. All rights reserved. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +#include +#include "../../core/iot_sim_cmn_api_i.h" +#include +#include + +#define IEEE80211_FRAME_BODY_OFFSET 0x18 + +QDF_STATUS iot_sim_frame_update(struct wlan_objmgr_pdev *pdev, qdf_nbuf_t nbuf) +{ + u8 type, subtype, seq = 0; + struct iot_sim_context *isc; + u8 *buf = qdf_nbuf_data(nbuf); + int fixed_param_length = 0; + + type = (buf[0] & IEEE80211_FC0_TYPE_MASK) >> IEEE80211_FC0_TYPE_SHIFT; + subtype = (buf[0] & IEEE80211_FC0_SUBTYPE_MASK); + subtype >>= IEEE80211_FC0_SUBTYPE_SHIFT; + isc = wlan_objmgr_pdev_get_comp_private_obj(pdev, WLAN_IOT_SIM_COMP); + if (!isc) { + iot_sim_err("pdev IOT_SIM object is NULL!"); + return QDF_STATUS_SUCCESS; + } + + if (type == 0x00 && subtype == 0x0b) { + /* Authentication frame */ + int auth_seq_index = IEEE80211_FRAME_BODY_OFFSET + 2; + + seq = le16toh(*(u_int16_t *)(buf + auth_seq_index)); + } else if (type == 0x00 && subtype == 0x05) + /* Probe response frame */ + fixed_param_length = 12; + else if (type == 0x00 && (subtype == 0x01 || subtype == 0x03)) + /* Assoc/Reassoc response frame */ + fixed_param_length = 6; + + /* Only broadcast peer is getting handled right now. + * Need to add support for peer based content modification + */ + if ((isc->bcast_peer.rule_per_seq[seq]) && + (isc->bcast_peer.rule_per_seq[seq]->rule_per_type[type][subtype])) { + if (isc->bcast_peer.rule_per_seq[seq]-> + rule_per_type[type][subtype]) { + struct iot_sim_rule *piot_sim_rule = + isc->bcast_peer.rule_per_seq[seq]-> + rule_per_type[type][subtype]; + qdf_size_t buf_len = qdf_nbuf_len(nbuf); + + if (piot_sim_rule->frm_content && piot_sim_rule->len) { + int offset; + + if (piot_sim_rule->offset == + IEEE80211_FRAME_BODY_OFFSET) { + offset = IEEE80211_FRAME_BODY_OFFSET; + } else if (piot_sim_rule->offset == 0) { + offset = 0; + } else if (buf[piot_sim_rule->offset] == + piot_sim_rule->frm_content[0]) { + offset = piot_sim_rule->offset; + } else { + offset = IEEE80211_FRAME_BODY_OFFSET + + fixed_param_length; + while (((offset + 1) < buf_len) && + (buf[offset] < + piot_sim_rule-> + frm_content[0])) { + offset += buf[offset + 1] + 2; + } + } + + if (offset <= buf_len) { + buf += offset; + qdf_mem_copy(buf, + piot_sim_rule->frm_content, + piot_sim_rule->len); + qdf_nbuf_set_pktlen(nbuf, + offset + + piot_sim_rule->len); + iot_sim_err("Content updated for peer"); + iot_sim_err("frame type:%d, subtype:%d", + type, subtype); + iot_sim_err("seq:%d", seq); + } else { + iot_sim_err("Failed to modify content"); + iot_sim_err("type:%d, subtype:%d", + type, subtype); + iot_sim_err("seq:%d", seq); + } + } else { + iot_sim_err("Content update rule not set"); + iot_sim_err("frame type:%d, subtype:%d, seq:%d", + type, subtype, seq); + } + } else { + iot_sim_err("Content update rule not set"); + iot_sim_err("frame type:%d, subtype:%d, seq:%d", + type, subtype, seq); + } + } else { + iot_sim_err("Content update rule not set for peer frame"); + iot_sim_err("type:%d, subtype:%d, seq:%d", type, subtype, seq); + } + + return QDF_STATUS_SUCCESS; +} diff --git a/iot_sim/dispatcher/inc/wlan_iot_sim_tgt_api.h b/iot_sim/dispatcher/inc/wlan_iot_sim_tgt_api.h index 05f4398e5e..a1197f6e4b 100644 --- a/iot_sim/dispatcher/inc/wlan_iot_sim_tgt_api.h +++ b/iot_sim/dispatcher/inc/wlan_iot_sim_tgt_api.h @@ -21,4 +21,7 @@ #include #include "../../core/iot_sim_cmn_api_i.h" +QDF_STATUS tgt_send_simulation_cmd(struct wlan_objmgr_pdev *pdev, + struct simulation_test_params *param); + #endif /* _WLAN_IOT_SIM_TGT_API_H_ */ diff --git a/iot_sim/dispatcher/inc/wlan_iot_sim_utils_api.h b/iot_sim/dispatcher/inc/wlan_iot_sim_utils_api.h index 14f3bfe0d2..308ad5db90 100644 --- a/iot_sim/dispatcher/inc/wlan_iot_sim_utils_api.h +++ b/iot_sim/dispatcher/inc/wlan_iot_sim_utils_api.h @@ -19,6 +19,7 @@ #include #include +#include /* Forward Declarations */ struct wmi_iot_sim_cmd_ops; diff --git a/iot_sim/dispatcher/src/wlan_iot_sim_tgt_api.c b/iot_sim/dispatcher/src/wlan_iot_sim_tgt_api.c index cd9036873f..c2179bcd95 100644 --- a/iot_sim/dispatcher/src/wlan_iot_sim_tgt_api.c +++ b/iot_sim/dispatcher/src/wlan_iot_sim_tgt_api.c @@ -34,3 +34,12 @@ tgt_get_target_handle(struct wlan_objmgr_pdev *pdev) } return isc->p_iot_sim_target_handle; } + +QDF_STATUS tgt_send_simulation_cmd(struct wlan_objmgr_pdev *pdev, + struct simulation_test_params *param) +{ + struct wlan_objmgr_psoc *psoc = NULL; + + psoc = wlan_pdev_get_psoc(pdev); + return psoc->soc_cb.tx_ops.iot_sim_tx_ops.iot_sim_send_cmd(pdev, param); +} diff --git a/iot_sim/dispatcher/src/wlan_iot_sim_utils_api.c b/iot_sim/dispatcher/src/wlan_iot_sim_utils_api.c index 54ff8c4c02..d846638811 100644 --- a/iot_sim/dispatcher/src/wlan_iot_sim_utils_api.c +++ b/iot_sim/dispatcher/src/wlan_iot_sim_utils_api.c @@ -26,94 +26,8 @@ QDF_STATUS iot_sim_cmd_handler(struct wlan_objmgr_vdev *vdev, qdf_nbuf_t nbuf) { struct wlan_objmgr_pdev *pdev = vdev->vdev_objmgr.wlan_pdev; - u8 type, subtype, seq = 0; - struct iot_sim_context *isc; - u8 *buf = qdf_nbuf_data(nbuf); - type = (buf[0] & IEEE80211_FC0_TYPE_MASK) >> IEEE80211_FC0_TYPE_SHIFT; - subtype = (buf[0] & IEEE80211_FC0_SUBTYPE_MASK); - subtype >>= IEEE80211_FC0_SUBTYPE_SHIFT; - isc = wlan_objmgr_pdev_get_comp_private_obj(pdev, WLAN_IOT_SIM_COMP); - - if (!isc) { - iot_sim_err("pdev IOT_SIM object is NULL!"); - return QDF_STATUS_SUCCESS; - } - - if (type == 0x00 && subtype == 0xb0) { - /* Authentication frame */ - int auth_seq_index = IEEE80211_FRAME_BODY_OFFSET + 2; - - seq = le16toh(*(u_int16_t *)(buf + auth_seq_index)); - } - - /* Only broadcast peer is getting handled right now. - * Need to add support for peer based content modification - */ - if ((isc->bcast_peer.rule_per_seq[seq]) && - (isc->bcast_peer.rule_per_seq[seq]->rule_per_type[type][subtype])) { - if (isc->bcast_peer.rule_per_seq[seq]-> - rule_per_type[type][subtype]) { - struct iot_sim_rule *piot_sim_rule = - isc->bcast_peer.rule_per_seq[seq]-> - rule_per_type[type][subtype]; - qdf_size_t buf_len = qdf_nbuf_len(nbuf); - - if (piot_sim_rule->frm_content && piot_sim_rule->len) { - int offset; - - if (piot_sim_rule->offset == - IEEE80211_FRAME_BODY_OFFSET) { - offset = IEEE80211_FRAME_BODY_OFFSET; - } else if (buf[piot_sim_rule->offset] == - piot_sim_rule->frm_content[0]) { - offset = piot_sim_rule->offset; - } else if (piot_sim_rule->offset == 0) { - offset = 0; - } else { - offset = IEEE80211_FRAME_BODY_OFFSET; - while (((offset + 1) < buf_len) && - (buf[offset] < - piot_sim_rule->frm_content[0])) { - offset += buf[offset + 1] + 2; - } - } - - if (offset <= buf_len) { - buf += offset; - qdf_mem_copy(buf, - piot_sim_rule-> - frm_content, - piot_sim_rule->len); - qdf_nbuf_set_pktlen(nbuf, - offset + - piot_sim_rule->len); - iot_sim_err("Content updated for peer"); - iot_sim_err("frame type:%d, subtype:%d", - type, subtype); - iot_sim_err("seq:%d", seq); - } else { - iot_sim_err("Failed to modify content"); - iot_sim_err("type:%d, subtype:%d", - type, subtype); - iot_sim_err("seq:%d", seq); - } - } else { - iot_sim_err("Content update rule not set"); - iot_sim_err("frame type:%d, subtype:%d, seq:%d", - type, subtype, seq); - } - } else { - iot_sim_err("Content update rule not set"); - iot_sim_err("frame type:%d, subtype:%d, seq:%d", - type, subtype, seq); - } - } else { - iot_sim_err("Content update rule not set for peer frame"); - iot_sim_err("type:%d, subtype:%d, seq:%d", type, subtype, seq); - } - - return QDF_STATUS_SUCCESS; + return iot_sim_frame_update(pdev, nbuf); } QDF_STATUS diff --git a/target_if/core/src/target_if_main.c b/target_if/core/src/target_if_main.c index 7dbd25c7d6..ffe980bdda 100644 --- a/target_if/core/src/target_if_main.c +++ b/target_if/core/src/target_if_main.c @@ -35,6 +35,10 @@ #ifdef WLAN_CONV_SPECTRAL_ENABLE #include "target_if_spectral.h" #endif + +#ifdef WLAN_IOT_SIM_SUPPORT +#include +#endif #include #include #include @@ -308,6 +312,19 @@ static void target_if_sptrl_tx_ops_register( } #endif /* WLAN_CONV_SPECTRAL_ENABLE */ +#ifdef WLAN_IOT_SIM_SUPPORT +static void target_if_iot_sim_tx_ops_register( + struct wlan_lmac_if_tx_ops *tx_ops) +{ + target_if_iot_sim_register_tx_ops(tx_ops); +} +#else +static void target_if_iot_sim_tx_ops_register( + struct wlan_lmac_if_tx_ops *tx_ops) +{ +} +#endif + #ifdef DIRECT_BUF_RX_ENABLE static void target_if_direct_buf_rx_tx_ops_register( struct wlan_lmac_if_tx_ops *tx_ops) @@ -497,6 +514,8 @@ QDF_STATUS target_if_register_tx_ops(struct wlan_lmac_if_tx_ops *tx_ops) /* Components parallel to UMAC to register their TX-ops here */ target_if_sptrl_tx_ops_register(tx_ops); + target_if_iot_sim_tx_ops_register(tx_ops); + /* Register direct buffer rx component tx ops here */ target_if_direct_buf_rx_tx_ops_register(tx_ops); diff --git a/target_if/iot_sim/target_if_iot_sim.c b/target_if/iot_sim/target_if_iot_sim.c new file mode 100644 index 0000000000..044665a4e1 --- /dev/null +++ b/target_if/iot_sim/target_if_iot_sim.c @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2020, The Linux Foundation. All rights reserved. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +#include +#include +#include +#include + +QDF_STATUS +target_if_iot_sim_send_cmd(struct wlan_objmgr_pdev *pdev, + struct simulation_test_params *param) +{ + if (pdev && pdev->tgt_if_handle) { + struct wmi_unified *wmi_hdl; + + wmi_hdl = pdev->tgt_if_handle->wmi_handle; + return wmi_unified_simulation_test_cmd_send(wmi_hdl, param); + } else + return QDF_STATUS_E_FAILURE; +} + +void target_if_iot_sim_register_tx_ops(struct wlan_lmac_if_tx_ops *tx_ops) +{ + tx_ops->iot_sim_tx_ops.iot_sim_send_cmd = + target_if_iot_sim_send_cmd; +} + +qdf_export_symbol(target_if_iot_sim_register_tx_ops); + diff --git a/target_if/iot_sim/target_if_iot_sim.h b/target_if/iot_sim/target_if_iot_sim.h new file mode 100644 index 0000000000..4b8311b760 --- /dev/null +++ b/target_if/iot_sim/target_if_iot_sim.h @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2020, The Linux Foundation. All rights reserved. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _TARGET_IF_IOT_SIM_H_ +#define _TARGET_IOT_SIM_H_ + +#include +#include + +#ifdef WLAN_IOT_SIM_SUPPORT +#include + +/** + * target_if_iot_sim_register_tx_ops() - Register IOT Sim target_if Tx Ops + * @tx_ops: Tx Ops + * + * Return: void + */ +void target_if_iot_sim_register_tx_ops(struct wlan_lmac_if_tx_ops *tx_ops); + +QDF_STATUS +target_if_iot_sim_send_cmd(struct wlan_objmgr_pdev *pdev, + struct simulation_test_params *param); + +#endif +#endif diff --git a/umac/global_umac_dispatcher/lmac_if/inc/wlan_lmac_if_def.h b/umac/global_umac_dispatcher/lmac_if/inc/wlan_lmac_if_def.h index 960968c145..30750a3480 100644 --- a/umac/global_umac_dispatcher/lmac_if/inc/wlan_lmac_if_def.h +++ b/umac/global_umac_dispatcher/lmac_if/inc/wlan_lmac_if_def.h @@ -663,6 +663,13 @@ struct wlan_lmac_if_sptrl_tx_ops { }; #endif /* WLAN_CONV_SPECTRAL_ENABLE */ +struct simulation_test_params; + +struct wlan_lmac_if_iot_sim_tx_ops { + QDF_STATUS (*iot_sim_send_cmd)(struct wlan_objmgr_pdev *pdev, + struct simulation_test_params *param); +}; + #ifdef WIFI_POS_CONVERGED /* * struct wlan_lmac_if_wifi_pos_tx_ops - structure of firmware tx function @@ -1008,6 +1015,7 @@ struct wlan_lmac_if_tx_ops { #ifdef CONVERGED_P2P_ENABLE struct wlan_lmac_if_p2p_tx_ops p2p; #endif + struct wlan_lmac_if_iot_sim_tx_ops iot_sim_tx_ops; #ifdef QCA_SUPPORT_SON struct wlan_lmac_if_son_tx_ops son_tx_ops; #endif @@ -1382,12 +1390,10 @@ struct wlan_lmac_if_sptrl_rx_ops { }; #endif /* WLAN_CONV_SPECTRAL_ENABLE */ -#ifdef WLAN_IOT_SIM_SUPPORT struct wlan_lmac_if_iot_sim_rx_ops { QDF_STATUS (*iot_sim_cmd_handler)(struct wlan_objmgr_vdev *vdev, qdf_nbuf_t n_buf); }; -#endif #ifdef WIFI_POS_CONVERGED /** @@ -1732,10 +1738,7 @@ struct wlan_lmac_if_rx_ops { #ifdef CONVERGED_P2P_ENABLE struct wlan_lmac_if_p2p_rx_ops p2p; #endif - -#ifdef WLAN_IOT_SIM_SUPPORT struct wlan_lmac_if_iot_sim_rx_ops iot_sim_rx_ops; -#endif #ifdef WLAN_ATF_ENABLE struct wlan_lmac_if_atf_rx_ops atf_rx_ops; diff --git a/wmi/inc/wmi_unified_api.h b/wmi/inc/wmi_unified_api.h index 182603b598..c234a2790a 100644 --- a/wmi/inc/wmi_unified_api.h +++ b/wmi/inc/wmi_unified_api.h @@ -1991,6 +1991,18 @@ QDF_STATUS wmi_unified_smart_ant_enable_tx_feedback_cmd_send( wmi_unified_t wmi_handle, struct smart_ant_enable_tx_feedback_params *param); +/** + * wmi_unified_simulation_test_cmd_send() - + * WMI simulation test command + * @wmi_handle: handle to WMI. + * @param: pointer to hold simulation test param + * + * Return: QDF_STATUS_SUCCESS on success and QDF_STATUS_E_FAILURE for failure + */ +QDF_STATUS wmi_unified_simulation_test_cmd_send(wmi_unified_t wmi_handle, + struct simulation_test_params + *param); + /** * wmi_unified_vdev_spectral_configure_cmd_send() - * WMI set spectral config function diff --git a/wmi/inc/wmi_unified_param.h b/wmi/inc/wmi_unified_param.h index fcc15bd9c8..f7be144d00 100644 --- a/wmi/inc/wmi_unified_param.h +++ b/wmi/inc/wmi_unified_param.h @@ -2903,6 +2903,37 @@ struct smart_ant_enable_tx_feedback_params { int enable; }; +/** + * struct simulation_test_params + * pdev_id: pdev id + * vdev_id: vdev id + * peer_macaddr: peer MAC address + * test_cmd_type: test command type + * test_subcmd_type: test command sub type + * frame_type: frame type + * frame_subtype: frame subtype + * seq: sequence number + * offset: Frame content offset + * frame_length: Frame content length + * buf_len: Buffer length + * bufp: buffer + */ +struct simulation_test_params { + u32 pdev_id; + u32 vdev_id; + u8 peer_mac[QDF_MAC_ADDR_SIZE]; + u32 test_cmd_type; + u32 test_subcmd_type; + u8 frame_type; + u8 frame_subtype; + u8 seq; + u8 reserved; + u16 offset; + u16 frame_length; + u32 buf_len; + u8 *bufp; +}; + /** * struct vdev_spectral_configure_params - SPectral config params * @vdev_id: VDEV id diff --git a/wmi/inc/wmi_unified_priv.h b/wmi/inc/wmi_unified_priv.h index b63f7b1f6b..c562b3b250 100644 --- a/wmi/inc/wmi_unified_priv.h +++ b/wmi/inc/wmi_unified_priv.h @@ -1201,6 +1201,9 @@ QDF_STATUS (*send_smart_ant_set_node_config_cmd)(wmi_unified_t wmi_handle, struct smart_ant_node_config_params *param); #endif +QDF_STATUS (*send_simulation_test_cmd)(wmi_unified_t wmi_handle, + struct simulation_test_params *param); + QDF_STATUS (*send_smart_ant_enable_tx_feedback_cmd)(wmi_unified_t wmi_handle, struct smart_ant_enable_tx_feedback_params *param); diff --git a/wmi/src/wmi_unified_api.c b/wmi/src/wmi_unified_api.c index d7dc144e67..771a1d9f76 100644 --- a/wmi/src/wmi_unified_api.c +++ b/wmi/src/wmi_unified_api.c @@ -1296,6 +1296,19 @@ wmi_unified_smart_ant_enable_tx_feedback_cmd_send( } qdf_export_symbol(wmi_unified_smart_ant_enable_tx_feedback_cmd_send); +QDF_STATUS +wmi_unified_simulation_test_cmd_send( + wmi_unified_t wmi_handle, + struct simulation_test_params *param) +{ + if (wmi_handle->ops->send_simulation_test_cmd) + return wmi_handle->ops->send_simulation_test_cmd( + wmi_handle, param); + + return QDF_STATUS_E_FAILURE; +} +qdf_export_symbol(wmi_unified_simulation_test_cmd_send); + QDF_STATUS wmi_unified_vdev_spectral_configure_cmd_send( wmi_unified_t wmi_handle, diff --git a/wmi/src/wmi_unified_tlv.c b/wmi/src/wmi_unified_tlv.c index 5c49dade8c..9e15a1d0dd 100644 --- a/wmi/src/wmi_unified_tlv.c +++ b/wmi/src/wmi_unified_tlv.c @@ -6399,6 +6399,72 @@ send_periodic_chan_stats_config_cmd_tlv(wmi_unified_t wmi_handle, return ret; } +/** + * send_simulation_test_cmd_tlv() - send simulation test command to fw + * + * @wmi_handle: wmi handle + * @param: pointer to hold simulation test parameter + * + * Return: 0 for success or error code + */ +static QDF_STATUS send_simulation_test_cmd_tlv(wmi_unified_t wmi_handle, + struct simulation_test_params + *param) +{ + wmi_simulation_test_cmd_fixed_param *cmd; + u32 wmi_buf_len; + wmi_buf_t buf; + u8 *buf_ptr; + u32 aligned_len = 0; + + wmi_buf_len = sizeof(*cmd); + if (param->buf_len) { + aligned_len = roundup(param->buf_len, sizeof(A_UINT32)); + wmi_buf_len += WMI_TLV_HDR_SIZE + aligned_len; + } + + buf = wmi_buf_alloc(wmi_handle, wmi_buf_len); + if (!buf) { + WMI_LOGP("%s: wmi_buf_alloc failed", __func__); + return QDF_STATUS_E_NOMEM; + } + + buf_ptr = wmi_buf_data(buf); + cmd = (wmi_simulation_test_cmd_fixed_param *)buf_ptr; + WMITLV_SET_HDR(&cmd->tlv_header, + WMITLV_TAG_STRUC_wmi_simulation_test_cmd_fixed_param, + WMITLV_GET_STRUCT_TLVLEN( + wmi_simulation_test_cmd_fixed_param)); + cmd->pdev_id = param->pdev_id; + cmd->vdev_id = param->vdev_id; + WMI_CHAR_ARRAY_TO_MAC_ADDR(param->peer_mac, &cmd->peer_macaddr); + cmd->test_cmd_type = param->test_cmd_type; + cmd->test_subcmd_type = param->test_subcmd_type; + WMI_SIM_FRAME_TYPE_SET(cmd->frame_type_subtype_seq, param->frame_type); + WMI_SIM_FRAME_SUBTYPE_SET(cmd->frame_type_subtype_seq, + param->frame_subtype); + WMI_SIM_FRAME_SEQ_SET(cmd->frame_type_subtype_seq, param->seq); + WMI_SIM_FRAME_OFFSET_SET(cmd->frame_offset_length, param->offset); + WMI_SIM_FRAME_LENGTH_SET(cmd->frame_offset_length, param->frame_length); + cmd->buf_len = param->buf_len; + + if (param->buf_len) { + buf_ptr += sizeof(*cmd); + WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_BYTE, aligned_len); + buf_ptr += WMI_TLV_HDR_SIZE; + qdf_mem_copy(buf_ptr, param->bufp, param->buf_len); + } + + if (wmi_unified_cmd_send(wmi_handle, buf, wmi_buf_len, + WMI_SIMULATION_TEST_CMDID)) { + WMI_LOGE("%s: Failed to send test simulation cmd", __func__); + wmi_buf_free(buf); + return QDF_STATUS_E_FAILURE; + } + + return QDF_STATUS_SUCCESS; +} + /** * send_vdev_spectral_configure_cmd_tlv() - send VDEV spectral configure * command to fw @@ -13740,6 +13806,7 @@ struct wmi_ops tlv_ops = { .send_phyerr_enable_cmd = send_phyerr_enable_cmd_tlv, .send_periodic_chan_stats_config_cmd = send_periodic_chan_stats_config_cmd_tlv, + .send_simulation_test_cmd = send_simulation_test_cmd_tlv, .send_vdev_spectral_configure_cmd = send_vdev_spectral_configure_cmd_tlv, .send_vdev_spectral_enable_cmd =