|
@@ -0,0 +1,314 @@
|
|
|
+/*
|
|
|
+ * Copyright (c) 2022 Qualcomm Innovation Center, Inc. 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.
|
|
|
+ */
|
|
|
+
|
|
|
+/**
|
|
|
+ * DOC: contains CoAP target if functions
|
|
|
+ */
|
|
|
+#include <wlan_coap_main.h>
|
|
|
+#include <target_if_coap.h>
|
|
|
+#include <wmi_unified_coap_api.h>
|
|
|
+
|
|
|
+/**
|
|
|
+ * target_if_wow_coap_buf_info_event_handler() - function to handle CoAP
|
|
|
+ * buf info event from firmware.
|
|
|
+ * @scn: scn handle
|
|
|
+ * @data: data buffer for event
|
|
|
+ * @datalen: data length
|
|
|
+ *
|
|
|
+ * Return: status of operation.
|
|
|
+ */
|
|
|
+static int
|
|
|
+target_if_wow_coap_buf_info_event_handler(ol_scn_t scn, uint8_t *data,
|
|
|
+ uint32_t datalen)
|
|
|
+{
|
|
|
+ QDF_STATUS status;
|
|
|
+ struct wlan_objmgr_psoc *psoc;
|
|
|
+ struct wmi_unified *wmi_handle;
|
|
|
+ struct wlan_objmgr_vdev *vdev = NULL;
|
|
|
+ struct wlan_coap_comp_priv *coap_priv;
|
|
|
+ struct coap_buf_info info = {0};
|
|
|
+ struct coap_buf_node *cur, *next;
|
|
|
+
|
|
|
+ if (!scn || !data) {
|
|
|
+ coap_err("scn: 0x%pK, data: 0x%pK", scn, data);
|
|
|
+ return -EINVAL;
|
|
|
+ }
|
|
|
+
|
|
|
+ psoc = target_if_get_psoc_from_scn_hdl(scn);
|
|
|
+ if (!psoc) {
|
|
|
+ coap_err("null psoc");
|
|
|
+ return -EINVAL;
|
|
|
+ }
|
|
|
+
|
|
|
+ wmi_handle = get_wmi_unified_hdl_from_psoc(psoc);
|
|
|
+ if (!wmi_handle) {
|
|
|
+ coap_err("wmi_handle is null");
|
|
|
+ return -EINVAL;
|
|
|
+ }
|
|
|
+
|
|
|
+ qdf_list_create(&info.info_list, 0);
|
|
|
+ status = wmi_unified_coap_extract_buf_info(wmi_handle, data,
|
|
|
+ &info);
|
|
|
+ if (QDF_IS_STATUS_ERROR(status))
|
|
|
+ goto out;
|
|
|
+
|
|
|
+ vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc, info.vdev_id,
|
|
|
+ WLAN_COAP_ID);
|
|
|
+ if (!vdev) {
|
|
|
+ coap_err("vdev is NULL, vdev_id: %d", info.vdev_id);
|
|
|
+ status = QDF_STATUS_E_INVAL;
|
|
|
+ goto out;
|
|
|
+ }
|
|
|
+
|
|
|
+ coap_priv = wlan_get_vdev_coap_obj(vdev);
|
|
|
+ if (!coap_priv->cache_get_cbk || !coap_priv->cache_get_context) {
|
|
|
+ coap_err("req id %d: callback or context is NULL",
|
|
|
+ coap_priv->req_id);
|
|
|
+ status = QDF_STATUS_E_INVAL;
|
|
|
+ goto out;
|
|
|
+ }
|
|
|
+
|
|
|
+ coap_priv->cache_get_cbk(coap_priv->cache_get_context, &info);
|
|
|
+out:
|
|
|
+ qdf_list_for_each_del(&info.info_list, cur, next, node) {
|
|
|
+ qdf_list_remove_node(&info.info_list, &cur->node);
|
|
|
+ qdf_mem_free(cur->payload);
|
|
|
+ qdf_mem_free(cur);
|
|
|
+ }
|
|
|
+
|
|
|
+ if (vdev)
|
|
|
+ wlan_objmgr_vdev_release_ref(vdev, WLAN_COAP_ID);
|
|
|
+ return qdf_status_to_os_return(status);
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * target_if_coap_register_event_handler() - Register CoAP related wmi events
|
|
|
+ * @psoc: psoc handle
|
|
|
+ *
|
|
|
+ * Register CoAP related WMI events
|
|
|
+ *
|
|
|
+ * return: QDF_STATUS
|
|
|
+ */
|
|
|
+static QDF_STATUS
|
|
|
+target_if_coap_register_event_handler(struct wlan_objmgr_psoc *psoc)
|
|
|
+{
|
|
|
+ QDF_STATUS ret_val;
|
|
|
+ struct wmi_unified *wmi_handle;
|
|
|
+
|
|
|
+ if (!psoc) {
|
|
|
+ coap_err("PSOC is NULL!");
|
|
|
+ return QDF_STATUS_E_NULL_VALUE;
|
|
|
+ }
|
|
|
+
|
|
|
+ wmi_handle = get_wmi_unified_hdl_from_psoc(psoc);
|
|
|
+ if (!wmi_handle) {
|
|
|
+ coap_err("wmi_handle is null");
|
|
|
+ return QDF_STATUS_E_INVAL;
|
|
|
+ }
|
|
|
+
|
|
|
+ ret_val = wmi_unified_register_event_handler(wmi_handle,
|
|
|
+ wmi_wow_coap_buf_info_eventid,
|
|
|
+ target_if_wow_coap_buf_info_event_handler,
|
|
|
+ WMI_RX_WORK_CTX);
|
|
|
+ if (QDF_IS_STATUS_ERROR(ret_val))
|
|
|
+ coap_err("Failed to register coap buf info event cb");
|
|
|
+
|
|
|
+ return ret_val;
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * target_if_coap_unregister_event_handler() - Unregister CoAP related wmi
|
|
|
+ * events
|
|
|
+ * @psoc: psoc handle
|
|
|
+ *
|
|
|
+ * Register CoAP related WMI events
|
|
|
+ *
|
|
|
+ * return: QDF_STATUS
|
|
|
+ */
|
|
|
+static QDF_STATUS
|
|
|
+target_if_coap_unregister_event_handler(struct wlan_objmgr_psoc *psoc)
|
|
|
+{
|
|
|
+ struct wmi_unified *wmi_handle;
|
|
|
+
|
|
|
+ if (!psoc) {
|
|
|
+ coap_err("PSOC is NULL!");
|
|
|
+ return QDF_STATUS_E_INVAL;
|
|
|
+ }
|
|
|
+
|
|
|
+ wmi_handle = get_wmi_unified_hdl_from_psoc(psoc);
|
|
|
+ if (!wmi_handle) {
|
|
|
+ coap_err("wmi_handle is null");
|
|
|
+ return QDF_STATUS_E_INVAL;
|
|
|
+ }
|
|
|
+ wmi_unified_unregister_event_handler(wmi_handle,
|
|
|
+ wmi_wow_coap_buf_info_eventid);
|
|
|
+
|
|
|
+ return QDF_STATUS_SUCCESS;
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * target_if_coap_offload_reply_enable() - enable CoAP offload reply
|
|
|
+ * @vdev: pointer to vdev object
|
|
|
+ * @param: parameters for CoAP offload reply
|
|
|
+ *
|
|
|
+ * Return: status of operation
|
|
|
+ */
|
|
|
+static QDF_STATUS
|
|
|
+target_if_coap_offload_reply_enable(struct wlan_objmgr_vdev *vdev,
|
|
|
+ struct coap_offload_reply_param *param)
|
|
|
+{
|
|
|
+ wmi_unified_t wmi_handle;
|
|
|
+ struct wlan_objmgr_pdev *pdev;
|
|
|
+
|
|
|
+ pdev = wlan_vdev_get_pdev(vdev);
|
|
|
+ wmi_handle = GET_WMI_HDL_FROM_PDEV(pdev);
|
|
|
+ if (!wmi_handle) {
|
|
|
+ coap_err("Invalid PDEV WMI handle");
|
|
|
+ return QDF_STATUS_E_FAILURE;
|
|
|
+ }
|
|
|
+
|
|
|
+ return wmi_unified_coap_add_pattern_cmd(wmi_handle, param);
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * target_if_coap_offload_reply_disable() - disable CoAP offload reply
|
|
|
+ * @vdev: pointer to vdev object
|
|
|
+ * @req_id: request id
|
|
|
+ *
|
|
|
+ * Return: status of operation
|
|
|
+ */
|
|
|
+static QDF_STATUS
|
|
|
+target_if_coap_offload_reply_disable(struct wlan_objmgr_vdev *vdev,
|
|
|
+ uint32_t req_id)
|
|
|
+{
|
|
|
+ wmi_unified_t wmi_handle;
|
|
|
+ struct wlan_objmgr_pdev *pdev;
|
|
|
+
|
|
|
+ pdev = wlan_vdev_get_pdev(vdev);
|
|
|
+ wmi_handle = GET_WMI_HDL_FROM_PDEV(pdev);
|
|
|
+ if (!wmi_handle) {
|
|
|
+ coap_err("Invalid PDEV WMI handle");
|
|
|
+ return QDF_STATUS_E_FAILURE;
|
|
|
+ }
|
|
|
+
|
|
|
+ return wmi_unified_coap_del_pattern_cmd(wmi_handle,
|
|
|
+ wlan_vdev_get_id(vdev),
|
|
|
+ req_id);
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * target_if_coap_offload_periodic_tx_enable() - enable CoAP offload
|
|
|
+ * periodic transmitting
|
|
|
+ * @vdev: pointer to vdev object
|
|
|
+ * @param: parameters for CoAP periodic transmitting
|
|
|
+ *
|
|
|
+ * Return: status of operation
|
|
|
+ */
|
|
|
+static QDF_STATUS
|
|
|
+target_if_coap_offload_periodic_tx_enable(struct wlan_objmgr_vdev *vdev,
|
|
|
+ struct coap_offload_periodic_tx_param *param)
|
|
|
+{
|
|
|
+ wmi_unified_t wmi_handle;
|
|
|
+ struct wlan_objmgr_pdev *pdev;
|
|
|
+
|
|
|
+ pdev = wlan_vdev_get_pdev(vdev);
|
|
|
+ wmi_handle = GET_WMI_HDL_FROM_PDEV(pdev);
|
|
|
+ if (!wmi_handle) {
|
|
|
+ coap_err("Invalid PDEV WMI handle");
|
|
|
+ return QDF_STATUS_E_FAILURE;
|
|
|
+ }
|
|
|
+
|
|
|
+ return wmi_unified_coap_add_keepalive_pattern_cmd(wmi_handle, param);
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * target_if_coap_offload_periodic_tx_disable() - disable CoAP offload
|
|
|
+ * periodic transmitting
|
|
|
+ * @vdev: pointer to vdev object
|
|
|
+ * @req_id: request id
|
|
|
+ *
|
|
|
+ * Return: status of operation
|
|
|
+ */
|
|
|
+static QDF_STATUS
|
|
|
+target_if_coap_offload_periodic_tx_disable(struct wlan_objmgr_vdev *vdev,
|
|
|
+ uint32_t req_id)
|
|
|
+{
|
|
|
+ wmi_unified_t wmi_handle;
|
|
|
+ struct wlan_objmgr_pdev *pdev;
|
|
|
+ uint8_t vdev_id;
|
|
|
+
|
|
|
+ pdev = wlan_vdev_get_pdev(vdev);
|
|
|
+ wmi_handle = GET_WMI_HDL_FROM_PDEV(pdev);
|
|
|
+ if (!wmi_handle) {
|
|
|
+ coap_err("Invalid PDEV WMI handle");
|
|
|
+ return QDF_STATUS_E_FAILURE;
|
|
|
+ }
|
|
|
+
|
|
|
+ vdev_id = wlan_vdev_get_id(vdev);
|
|
|
+ return wmi_unified_coap_del_keepalive_pattern_cmd(wmi_handle,
|
|
|
+ vdev_id, req_id);
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * target_if_coap_offload_cache_get() - get cached CoAP messages
|
|
|
+ * @vdev: pointer to vdev object
|
|
|
+ * @req_id: request id
|
|
|
+ *
|
|
|
+ * Return: status of operation
|
|
|
+ */
|
|
|
+static QDF_STATUS
|
|
|
+target_if_coap_offload_cache_get(struct wlan_objmgr_vdev *vdev,
|
|
|
+ uint32_t req_id)
|
|
|
+{
|
|
|
+ wmi_unified_t wmi_handle;
|
|
|
+ struct wlan_objmgr_pdev *pdev;
|
|
|
+
|
|
|
+ pdev = wlan_vdev_get_pdev(vdev);
|
|
|
+ wmi_handle = GET_WMI_HDL_FROM_PDEV(pdev);
|
|
|
+ if (!wmi_handle) {
|
|
|
+ coap_err("Invalid PDEV WMI handle");
|
|
|
+ return QDF_STATUS_E_FAILURE;
|
|
|
+ }
|
|
|
+
|
|
|
+ return wmi_unified_coap_cache_get(wmi_handle, wlan_vdev_get_id(vdev),
|
|
|
+ req_id);
|
|
|
+}
|
|
|
+
|
|
|
+QDF_STATUS
|
|
|
+target_if_coap_register_tx_ops(struct wlan_lmac_if_tx_ops *tx_ops)
|
|
|
+{
|
|
|
+ struct wlan_lmac_if_coap_tx_ops *coap_ops;
|
|
|
+
|
|
|
+ if (!tx_ops) {
|
|
|
+ coap_err("target if tx ops is NULL!");
|
|
|
+ return QDF_STATUS_E_INVAL;
|
|
|
+ }
|
|
|
+
|
|
|
+ coap_ops = &tx_ops->coap_ops;
|
|
|
+ coap_ops->attach = target_if_coap_register_event_handler;
|
|
|
+ coap_ops->detach = target_if_coap_unregister_event_handler;
|
|
|
+ coap_ops->offload_reply_enable =
|
|
|
+ target_if_coap_offload_reply_enable;
|
|
|
+ coap_ops->offload_reply_disable =
|
|
|
+ target_if_coap_offload_reply_disable;
|
|
|
+ coap_ops->offload_periodic_tx_enable =
|
|
|
+ target_if_coap_offload_periodic_tx_enable;
|
|
|
+ coap_ops->offload_periodic_tx_disable =
|
|
|
+ target_if_coap_offload_periodic_tx_disable;
|
|
|
+ coap_ops->offload_cache_get = target_if_coap_offload_cache_get;
|
|
|
+
|
|
|
+ return QDF_STATUS_SUCCESS;
|
|
|
+}
|