/*
 * Copyright (c) 2018, 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 <net/netlink.h>
#include <linux/firmware.h>
#include <net/cfg80211.h>
#include "wcn36xx.h"

#include "testmode.h"
#include "testmode_i.h"
#include "hal.h"
#include "smd.h"

static const struct nla_policy wcn36xx_tm_policy[WCN36XX_TM_ATTR_MAX + 1] = {
	[WCN36XX_TM_ATTR_CMD] = { .type = NLA_U16 },
	[WCN36XX_TM_ATTR_DATA] = { .type = NLA_BINARY,
	.len = WCN36XX_TM_DATA_MAX_LEN },
};

struct build_release_number {
	u16 drv_major;
	u16 drv_minor;
	u16 drv_patch;
	u16 drv_build;
	u16 ptt_max;
	u16 ptt_min;
	u16 fw_ver;
} __packed;

static int wcn36xx_tm_cmd_ptt(struct wcn36xx *wcn, struct ieee80211_vif *vif,
			      struct nlattr *tb[])
{
	int ret = 0, buf_len;
	void *buf;
	struct ftm_rsp_msg *msg, *rsp = NULL;
	struct sk_buff *skb;

	if (!tb[WCN36XX_TM_ATTR_DATA])
		return -EINVAL;

	buf = nla_data(tb[WCN36XX_TM_ATTR_DATA]);
	buf_len = nla_len(tb[WCN36XX_TM_ATTR_DATA]);
	msg = buf;

	wcn36xx_dbg(WCN36XX_DBG_TESTMODE,
		    "testmode cmd wmi msg_id 0x%04X msg_len %d buf %pK buf_len %d\n",
		   msg->msg_id, msg->msg_body_length,
		   buf, buf_len);

	wcn36xx_dbg_dump(WCN36XX_DBG_TESTMODE_DUMP, "REQ ", buf, buf_len);

	if (msg->msg_id == MSG_GET_BUILD_RELEASE_NUMBER) {
		struct build_release_number *body =
				(struct build_release_number *)
				msg->msg_response;

		body->drv_major = wcn->fw_major;
		body->drv_minor = wcn->fw_minor;
		body->drv_patch = wcn->fw_version;
		body->drv_build = wcn->fw_revision;
		body->ptt_max = 10;
		body->ptt_min = 0;

		rsp = msg;
		rsp->resp_status = 0;
	} else {
		wcn36xx_dbg(WCN36XX_DBG_TESTMODE,
			    "PPT Request >> HAL size %d\n",
				msg->msg_body_length);

		msg->resp_status = wcn36xx_smd_process_ptt_msg(wcn, vif, msg,
							       msg->msg_body_length, (void *)(&rsp));

		wcn36xx_dbg(WCN36XX_DBG_TESTMODE,
			    "Response status = %d\n",
				msg->resp_status);
		if (rsp)
			wcn36xx_dbg(WCN36XX_DBG_TESTMODE,
				    "PPT Response << HAL size %d\n",
					rsp->msg_body_length);
	}

	if (!rsp) {
		rsp = msg;
		wcn36xx_warn("No response! Echoing request with response status %d\n",
			     rsp->resp_status);
	}
	wcn36xx_dbg_dump(WCN36XX_DBG_TESTMODE_DUMP, "RSP ",
			 rsp, rsp->msg_body_length);

	skb = cfg80211_testmode_alloc_reply_skb(wcn->hw->wiphy,
						nla_total_size(msg->msg_body_length));
	if (!skb) {
		ret = -ENOMEM;
		goto out;
	}

	ret = nla_put(skb, WCN36XX_TM_ATTR_DATA, rsp->msg_body_length, rsp);
	if (ret) {
		kfree_skb(skb);
		goto out;
	}

	ret = cfg80211_testmode_reply(skb);

out:
	if (rsp != msg)
		kfree(rsp);

	return ret;
}

int wcn36xx_tm_cmd(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
		   void *data, int len)
{
	struct wcn36xx *wcn = hw->priv;
	struct nlattr *tb[WCN36XX_TM_ATTR_MAX + 1];
	int ret = 0;
	unsigned short attr;

	wcn36xx_dbg_dump(WCN36XX_DBG_TESTMODE_DUMP, "Data:", data, len);
	ret = nla_parse_deprecated(tb, WCN36XX_TM_ATTR_MAX, data, len,
				   wcn36xx_tm_policy, NULL);
	if (ret)
		return ret;

	if (!tb[WCN36XX_TM_ATTR_CMD])
		return -EINVAL;

	attr = nla_get_u16(tb[WCN36XX_TM_ATTR_CMD]);

	if (attr != WCN36XX_TM_CMD_PTT)
		return -EOPNOTSUPP;

	return wcn36xx_tm_cmd_ptt(wcn, vif, tb);
}
