/*
 * This file is part of wlcore
 *
 * Copyright (C) 2014 Texas Instruments. All rights reserved.
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * version 2 as published by the Free Software Foundation.
 */

#include <linux/pm_runtime.h>

#include <net/mac80211.h>
#include <net/netlink.h>

#include "wlcore.h"
#include "debug.h"
#include "hw_ops.h"
#include "vendor_cmd.h"

static const
struct nla_policy wlcore_vendor_attr_policy[NUM_WLCORE_VENDOR_ATTR] = {
	[WLCORE_VENDOR_ATTR_FREQ]		= { .type = NLA_U32 },
	[WLCORE_VENDOR_ATTR_GROUP_ID]		= { .type = NLA_U32 },
	[WLCORE_VENDOR_ATTR_GROUP_KEY]		= { .type = NLA_BINARY,
						    .len = WLAN_MAX_KEY_LEN },
};

static int
wlcore_vendor_cmd_smart_config_start(struct wiphy *wiphy,
				     struct wireless_dev *wdev,
				     const void *data, int data_len)
{
	struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy);
	struct wl1271 *wl = hw->priv;
	struct nlattr *tb[NUM_WLCORE_VENDOR_ATTR];
	int ret;

	wl1271_debug(DEBUG_CMD, "vendor cmd smart config start");

	if (!data)
		return -EINVAL;

	ret = nla_parse(tb, MAX_WLCORE_VENDOR_ATTR, data, data_len,
			wlcore_vendor_attr_policy, NULL);
	if (ret)
		return ret;

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

	mutex_lock(&wl->mutex);

	if (unlikely(wl->state != WLCORE_STATE_ON)) {
		ret = -EINVAL;
		goto out;
	}

	ret = pm_runtime_get_sync(wl->dev);
	if (ret < 0) {
		pm_runtime_put_noidle(wl->dev);
		goto out;
	}

	ret = wlcore_smart_config_start(wl,
			nla_get_u32(tb[WLCORE_VENDOR_ATTR_GROUP_ID]));

	pm_runtime_mark_last_busy(wl->dev);
	pm_runtime_put_autosuspend(wl->dev);
out:
	mutex_unlock(&wl->mutex);

	return ret;
}

static int
wlcore_vendor_cmd_smart_config_stop(struct wiphy *wiphy,
				    struct wireless_dev *wdev,
				    const void *data, int data_len)
{
	struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy);
	struct wl1271 *wl = hw->priv;
	int ret;

	wl1271_debug(DEBUG_CMD, "testmode cmd smart config stop");

	mutex_lock(&wl->mutex);

	if (unlikely(wl->state != WLCORE_STATE_ON)) {
		ret = -EINVAL;
		goto out;
	}

	ret = pm_runtime_get_sync(wl->dev);
	if (ret < 0) {
		pm_runtime_put_noidle(wl->dev);
		goto out;
	}

	ret = wlcore_smart_config_stop(wl);

	pm_runtime_mark_last_busy(wl->dev);
	pm_runtime_put_autosuspend(wl->dev);
out:
	mutex_unlock(&wl->mutex);

	return ret;
}

static int
wlcore_vendor_cmd_smart_config_set_group_key(struct wiphy *wiphy,
					     struct wireless_dev *wdev,
					     const void *data, int data_len)
{
	struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy);
	struct wl1271 *wl = hw->priv;
	struct nlattr *tb[NUM_WLCORE_VENDOR_ATTR];
	int ret;

	wl1271_debug(DEBUG_CMD, "testmode cmd smart config set group key");

	if (!data)
		return -EINVAL;

	ret = nla_parse(tb, MAX_WLCORE_VENDOR_ATTR, data, data_len,
			wlcore_vendor_attr_policy, NULL);
	if (ret)
		return ret;

	if (!tb[WLCORE_VENDOR_ATTR_GROUP_ID] ||
	    !tb[WLCORE_VENDOR_ATTR_GROUP_KEY])
		return -EINVAL;

	mutex_lock(&wl->mutex);

	if (unlikely(wl->state != WLCORE_STATE_ON)) {
		ret = -EINVAL;
		goto out;
	}

	ret = pm_runtime_get_sync(wl->dev);
	if (ret < 0) {
		pm_runtime_put_noidle(wl->dev);
		goto out;
	}

	ret = wlcore_smart_config_set_group_key(wl,
			nla_get_u32(tb[WLCORE_VENDOR_ATTR_GROUP_ID]),
			nla_len(tb[WLCORE_VENDOR_ATTR_GROUP_KEY]),
			nla_data(tb[WLCORE_VENDOR_ATTR_GROUP_KEY]));

	pm_runtime_mark_last_busy(wl->dev);
	pm_runtime_put_autosuspend(wl->dev);
out:
	mutex_unlock(&wl->mutex);

	return ret;
}

static const struct wiphy_vendor_command wlcore_vendor_commands[] = {
	{
		.info = {
			.vendor_id = TI_OUI,
			.subcmd = WLCORE_VENDOR_CMD_SMART_CONFIG_START,
		},
		.flags = WIPHY_VENDOR_CMD_NEED_NETDEV |
			 WIPHY_VENDOR_CMD_NEED_RUNNING,
		.doit = wlcore_vendor_cmd_smart_config_start,
	},
	{
		.info = {
			.vendor_id = TI_OUI,
			.subcmd = WLCORE_VENDOR_CMD_SMART_CONFIG_STOP,
		},
		.flags = WIPHY_VENDOR_CMD_NEED_NETDEV |
			 WIPHY_VENDOR_CMD_NEED_RUNNING,
		.doit = wlcore_vendor_cmd_smart_config_stop,
	},
	{
		.info = {
			.vendor_id = TI_OUI,
			.subcmd = WLCORE_VENDOR_CMD_SMART_CONFIG_SET_GROUP_KEY,
		},
		.flags = WIPHY_VENDOR_CMD_NEED_NETDEV |
			 WIPHY_VENDOR_CMD_NEED_RUNNING,
		.doit = wlcore_vendor_cmd_smart_config_set_group_key,
	},
};

static const struct nl80211_vendor_cmd_info wlcore_vendor_events[] = {
	{
		.vendor_id = TI_OUI,
		.subcmd = WLCORE_VENDOR_EVENT_SC_SYNC,
	},
	{
		.vendor_id = TI_OUI,
		.subcmd = WLCORE_VENDOR_EVENT_SC_DECODE,
	},
};

void wlcore_set_vendor_commands(struct wiphy *wiphy)
{
	wiphy->vendor_commands = wlcore_vendor_commands;
	wiphy->n_vendor_commands = ARRAY_SIZE(wlcore_vendor_commands);
	wiphy->vendor_events = wlcore_vendor_events;
	wiphy->n_vendor_events = ARRAY_SIZE(wlcore_vendor_events);
}
