/*
 * Linux WiMAX
 * RF-kill framework integration
 *
 *
 * Copyright (C) 2008 Intel Corporation <linux-wimax@intel.com>
 * Inaky Perez-Gonzalez <inaky.perez-gonzalez@intel.com>
 *
 * 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.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
 * 02110-1301, USA.
 *
 *
 * This integrates into the Linux Kernel rfkill susbystem so that the
 * drivers just have to do the bare minimal work, which is providing a
 * method to set the software RF-Kill switch and to report changes in
 * the software and hardware switch status.
 *
 * A non-polled generic rfkill device is embedded into the WiMAX
 * subsystem's representation of a device.
 *
 * FIXME: Need polled support? use a timer or add the implementation
 *     to the stack.
 *
 * All device drivers have to do is after wimax_dev_init(), call
 * wimax_report_rfkill_hw() and wimax_report_rfkill_sw() to update
 * initial state and then every time it changes. See wimax.h:struct
 * wimax_dev for more information.
 *
 * ROADMAP
 *
 * wimax_gnl_doit_rfkill()      User space calling wimax_rfkill()
 *   wimax_rfkill()             Kernel calling wimax_rfkill()
 *     __wimax_rf_toggle_radio()
 *
 * wimax_rfkill_toggle_radio()  RF-Kill subsytem calling
 *   __wimax_rf_toggle_radio()
 *
 * __wimax_rf_toggle_radio()
 *   wimax_dev->op_rfkill_sw_toggle() Driver backend
 *   __wimax_state_change()
 *
 * wimax_report_rfkill_sw()     Driver reports state change
 *   __wimax_state_change()
 *
 * wimax_report_rfkill_hw()     Driver reports state change
 *   __wimax_state_change()
 *
 * wimax_rfkill_add()           Initialize/shutdown rfkill support
 * wimax_rfkill_rm()            [called by wimax_dev_add/rm()]
 */

#include <net/wimax.h>
#include <net/genetlink.h>
#include <linux/wimax.h>
#include <linux/security.h>
#include <linux/rfkill.h>
#include <linux/input.h>
#include "wimax-internal.h"

#define D_SUBMODULE op_rfkill
#include "debug-levels.h"

#if defined(CONFIG_RFKILL) || defined(CONFIG_RFKILL_MODULE)


/**
 * wimax_report_rfkill_hw - Reports changes in the hardware RF switch
 *
 * @wimax_dev: WiMAX device descriptor
 *
 * @state: New state of the RF Kill switch. %WIMAX_RF_ON radio on,
 *     %WIMAX_RF_OFF radio off.
 *
 * When the device detects a change in the state of thehardware RF
 * switch, it must call this function to let the WiMAX kernel stack
 * know that the state has changed so it can be properly propagated.
 *
 * The WiMAX stack caches the state (the driver doesn't need to). As
 * well, as the change is propagated it will come back as a request to
 * change the software state to mirror the hardware state.
 *
 * If the device doesn't have a hardware kill switch, just report
 * it on initialization as always on (%WIMAX_RF_ON, radio on).
 */
void wimax_report_rfkill_hw(struct wimax_dev *wimax_dev,
			    enum wimax_rf_state state)
{
	int result;
	struct device *dev = wimax_dev_to_dev(wimax_dev);
	enum wimax_st wimax_state;
	enum rfkill_state rfkill_state;

	d_fnstart(3, dev, "(wimax_dev %p state %u)\n", wimax_dev, state);
	BUG_ON(state == WIMAX_RF_QUERY);
	BUG_ON(state != WIMAX_RF_ON && state != WIMAX_RF_OFF);

	mutex_lock(&wimax_dev->mutex);
	result = wimax_dev_is_ready(wimax_dev);
	if (result < 0)
		goto error_not_ready;

	if (state != wimax_dev->rf_hw) {
		wimax_dev->rf_hw = state;
		rfkill_state = state == WIMAX_RF_ON ?
			RFKILL_STATE_OFF : RFKILL_STATE_ON;
		if (wimax_dev->rf_hw == WIMAX_RF_ON
		    && wimax_dev->rf_sw == WIMAX_RF_ON)
			wimax_state = WIMAX_ST_READY;
		else
			wimax_state = WIMAX_ST_RADIO_OFF;
		__wimax_state_change(wimax_dev, wimax_state);
		input_report_key(wimax_dev->rfkill_input, KEY_WIMAX,
				 rfkill_state);
	}
error_not_ready:
	mutex_unlock(&wimax_dev->mutex);
	d_fnend(3, dev, "(wimax_dev %p state %u) = void [%d]\n",
		wimax_dev, state, result);
}
EXPORT_SYMBOL_GPL(wimax_report_rfkill_hw);


/**
 * wimax_report_rfkill_sw - Reports changes in the software RF switch
 *
 * @wimax_dev: WiMAX device descriptor
 *
 * @state: New state of the RF kill switch. %WIMAX_RF_ON radio on,
 *     %WIMAX_RF_OFF radio off.
 *
 * Reports changes in the software RF switch state to the the WiMAX
 * stack.
 *
 * The main use is during initialization, so the driver can query the
 * device for its current software radio kill switch state and feed it
 * to the system.
 *
 * On the side, the device does not change the software state by
 * itself. In practice, this can happen, as the device might decide to
 * switch (in software) the radio off for different reasons.
 */
void wimax_report_rfkill_sw(struct wimax_dev *wimax_dev,
			    enum wimax_rf_state state)
{
	int result;
	struct device *dev = wimax_dev_to_dev(wimax_dev);
	enum wimax_st wimax_state;

	d_fnstart(3, dev, "(wimax_dev %p state %u)\n", wimax_dev, state);
	BUG_ON(state == WIMAX_RF_QUERY);
	BUG_ON(state != WIMAX_RF_ON && state != WIMAX_RF_OFF);

	mutex_lock(&wimax_dev->mutex);
	result = wimax_dev_is_ready(wimax_dev);
	if (result < 0)
		goto error_not_ready;

	if (state != wimax_dev->rf_sw) {
		wimax_dev->rf_sw = state;
		if (wimax_dev->rf_hw == WIMAX_RF_ON
		    && wimax_dev->rf_sw == WIMAX_RF_ON)
			wimax_state = WIMAX_ST_READY;
		else
			wimax_state = WIMAX_ST_RADIO_OFF;
		__wimax_state_change(wimax_dev, wimax_state);
	}
error_not_ready:
	mutex_unlock(&wimax_dev->mutex);
	d_fnend(3, dev, "(wimax_dev %p state %u) = void [%d]\n",
		wimax_dev, state, result);
}
EXPORT_SYMBOL_GPL(wimax_report_rfkill_sw);


/*
 * Callback for the RF Kill toggle operation
 *
 * This function is called by:
 *
 * - The rfkill subsystem when the RF-Kill key is pressed in the
 *   hardware and the driver notifies through
 *   wimax_report_rfkill_hw(). The rfkill subsystem ends up calling back
 *   here so the software RF Kill switch state is changed to reflect
 *   the hardware switch state.
 *
 * - When the user sets the state through sysfs' rfkill/state file
 *
 * - When the user calls wimax_rfkill().
 *
 * This call blocks!
 *
 * WARNING! When we call rfkill_unregister(), this will be called with
 * state 0!
 *
 * WARNING: wimax_dev must be locked
 */
static
int __wimax_rf_toggle_radio(struct wimax_dev *wimax_dev,
			    enum wimax_rf_state state)
{
	int result = 0;
	struct device *dev = wimax_dev_to_dev(wimax_dev);
	enum wimax_st wimax_state;

	might_sleep();
	d_fnstart(3, dev, "(wimax_dev %p state %u)\n", wimax_dev, state);
	if (wimax_dev->rf_sw == state)
		goto out_no_change;
	if (wimax_dev->op_rfkill_sw_toggle != NULL)
		result = wimax_dev->op_rfkill_sw_toggle(wimax_dev, state);
	else if (state == WIMAX_RF_OFF)	/* No op? can't turn off */
		result = -ENXIO;
	else				/* No op? can turn on */
		result = 0;		/* should never happen tho */
	if (result >= 0) {
		result = 0;
		wimax_dev->rf_sw = state;
		wimax_state = state == WIMAX_RF_ON ?
			WIMAX_ST_READY : WIMAX_ST_RADIO_OFF;
		__wimax_state_change(wimax_dev, wimax_state);
	}
out_no_change:
	d_fnend(3, dev, "(wimax_dev %p state %u) = %d\n",
		wimax_dev, state, result);
	return result;
}


/*
 * Translate from rfkill state to wimax state
 *
 * NOTE: Special state handling rules here
 *
 *     Just pretend the call didn't happen if we are in a state where
 *     we know for sure it cannot be handled (WIMAX_ST_DOWN or
 *     __WIMAX_ST_QUIESCING). rfkill() needs it to register and
 *     unregister, as it will run this path.
 *
 * NOTE: This call will block until the operation is completed.
 */
static
int wimax_rfkill_toggle_radio(void *data, enum rfkill_state state)
{
	int result;
	struct wimax_dev *wimax_dev = data;
	struct device *dev = wimax_dev_to_dev(wimax_dev);
	enum wimax_rf_state rf_state;

	d_fnstart(3, dev, "(wimax_dev %p state %u)\n", wimax_dev, state);
	switch (state) {
	case RFKILL_STATE_ON:
		rf_state = WIMAX_RF_OFF;
		break;
	case RFKILL_STATE_OFF:
		rf_state = WIMAX_RF_ON;
		break;
	default:
		BUG();
	}
	mutex_lock(&wimax_dev->mutex);
	if (wimax_dev->state <= __WIMAX_ST_QUIESCING)
		result = 0;	/* just pretend it didn't happen */
	else
		result = __wimax_rf_toggle_radio(wimax_dev, rf_state);
	mutex_unlock(&wimax_dev->mutex);
	d_fnend(3, dev, "(wimax_dev %p state %u) = %d\n",
		wimax_dev, state, result);
	return result;
}


/**
 * wimax_rfkill - Set the software RF switch state for a WiMAX device
 *
 * @wimax_dev: WiMAX device descriptor
 *
 * @state: New RF state.
 *
 * Returns:
 *
 * >= 0 toggle state if ok, < 0 errno code on error. The toggle state
 * is returned as a bitmap, bit 0 being the hardware RF state, bit 1
 * the software RF state.
 *
 * 0 means disabled (%WIMAX_RF_ON, radio on), 1 means enabled radio
 * off (%WIMAX_RF_OFF).
 *
 * Description:
 *
 * Called by the user when he wants to request the WiMAX radio to be
 * switched on (%WIMAX_RF_ON) or off (%WIMAX_RF_OFF). With
 * %WIMAX_RF_QUERY, just the current state is returned.
 *
 * NOTE:
 *
 * This call will block until the operation is complete.
 */
int wimax_rfkill(struct wimax_dev *wimax_dev, enum wimax_rf_state state)
{
	int result;
	struct device *dev = wimax_dev_to_dev(wimax_dev);

	d_fnstart(3, dev, "(wimax_dev %p state %u)\n", wimax_dev, state);
	mutex_lock(&wimax_dev->mutex);
	result = wimax_dev_is_ready(wimax_dev);
	if (result < 0)
		goto error_not_ready;
	switch (state) {
	case WIMAX_RF_ON:
	case WIMAX_RF_OFF:
		result = __wimax_rf_toggle_radio(wimax_dev, state);
		if (result < 0)
			goto error;
		break;
	case WIMAX_RF_QUERY:
		break;
	default:
		result = -EINVAL;
		goto error;
	}
	result = wimax_dev->rf_sw << 1 | wimax_dev->rf_hw;
error:
error_not_ready:
	mutex_unlock(&wimax_dev->mutex);
	d_fnend(3, dev, "(wimax_dev %p state %u) = %d\n",
		wimax_dev, state, result);
	return result;
}
EXPORT_SYMBOL(wimax_rfkill);


/*
 * Register a new WiMAX device's RF Kill support
 *
 * WARNING: wimax_dev->mutex must be unlocked
 */
int wimax_rfkill_add(struct wimax_dev *wimax_dev)
{
	int result;
	struct rfkill *rfkill;
	struct input_dev *input_dev;
	struct device *dev = wimax_dev_to_dev(wimax_dev);

	d_fnstart(3, dev, "(wimax_dev %p)\n", wimax_dev);
	/* Initialize RF Kill */
	result = -ENOMEM;
	rfkill = rfkill_allocate(dev, RFKILL_TYPE_WIMAX);
	if (rfkill == NULL)
		goto error_rfkill_allocate;
	wimax_dev->rfkill = rfkill;

	rfkill->name = wimax_dev->name;
	rfkill->state = RFKILL_STATE_OFF;
	rfkill->data = wimax_dev;
	rfkill->toggle_radio = wimax_rfkill_toggle_radio;
	rfkill->user_claim_unsupported = 1;

	/* Initialize the input device for the hw key */
	input_dev = input_allocate_device();
	if (input_dev == NULL)
		goto error_input_allocate;
	wimax_dev->rfkill_input = input_dev;
	d_printf(1, dev, "rfkill %p input %p\n", rfkill, input_dev);

	input_dev->name = wimax_dev->name;
	/* FIXME: get a real device bus ID and stuff? do we care? */
	input_dev->id.bustype = BUS_HOST;
	input_dev->id.vendor = 0xffff;
	input_dev->evbit[0] = BIT(EV_KEY);
	set_bit(KEY_WIMAX, input_dev->keybit);

	/* Register both */
	result = input_register_device(wimax_dev->rfkill_input);
	if (result < 0)
		goto error_input_register;
	result = rfkill_register(wimax_dev->rfkill);
	if (result < 0)
		goto error_rfkill_register;

	/* If there is no SW toggle op, SW RFKill is always on */
	if (wimax_dev->op_rfkill_sw_toggle == NULL)
		wimax_dev->rf_sw = WIMAX_RF_ON;

	d_fnend(3, dev, "(wimax_dev %p) = 0\n", wimax_dev);
	return 0;

	/* if rfkill_register() suceeds, can't use rfkill_free() any
	 * more, only rfkill_unregister() [it owns the refcount]; with
	 * the input device we have the same issue--hence the if. */
error_rfkill_register:
	input_unregister_device(wimax_dev->rfkill_input);
	wimax_dev->rfkill_input = NULL;
error_input_register:
	if (wimax_dev->rfkill_input)
		input_free_device(wimax_dev->rfkill_input);
error_input_allocate:
	rfkill_free(wimax_dev->rfkill);
error_rfkill_allocate:
	d_fnend(3, dev, "(wimax_dev %p) = %d\n", wimax_dev, result);
	return result;
}


/*
 * Deregister a WiMAX device's RF Kill support
 *
 * Ick, we can't call rfkill_free() after rfkill_unregister()...oh
 * well.
 *
 * WARNING: wimax_dev->mutex must be unlocked
 */
void wimax_rfkill_rm(struct wimax_dev *wimax_dev)
{
	struct device *dev = wimax_dev_to_dev(wimax_dev);
	d_fnstart(3, dev, "(wimax_dev %p)\n", wimax_dev);
	rfkill_unregister(wimax_dev->rfkill);	/* frees */
	input_unregister_device(wimax_dev->rfkill_input);
	d_fnend(3, dev, "(wimax_dev %p)\n", wimax_dev);
}


#else /* #ifdef CONFIG_RFKILL */

void wimax_report_rfkill_hw(struct wimax_dev *wimax_dev,
			    enum wimax_rf_state state)
{
}
EXPORT_SYMBOL_GPL(wimax_report_rfkill_hw);

void wimax_report_rfkill_sw(struct wimax_dev *wimax_dev,
			    enum wimax_rf_state state)
{
}
EXPORT_SYMBOL_GPL(wimax_report_rfkill_sw);

int wimax_rfkill(struct wimax_dev *wimax_dev,
		 enum wimax_rf_state state)
{
	return WIMAX_RF_ON << 1 | WIMAX_RF_ON;
}
EXPORT_SYMBOL_GPL(wimax_rfkill);

int wimax_rfkill_add(struct wimax_dev *wimax_dev)
{
	return 0;
}

void wimax_rfkill_rm(struct wimax_dev *wimax_dev)
{
}

#endif /* #ifdef CONFIG_RFKILL */


/*
 * Exporting to user space over generic netlink
 *
 * Parse the rfkill command from user space, return a combination
 * value that describe the states of the different toggles.
 *
 * Only one attribute: the new state requested (on, off or no change,
 * just query).
 */

static const
struct nla_policy wimax_gnl_rfkill_policy[WIMAX_GNL_ATTR_MAX + 1] = {
	[WIMAX_GNL_RFKILL_IFIDX] = {
		.type = NLA_U32,
	},
	[WIMAX_GNL_RFKILL_STATE] = {
		.type = NLA_U32		/* enum wimax_rf_state */
	},
};


static
int wimax_gnl_doit_rfkill(struct sk_buff *skb, struct genl_info *info)
{
	int result, ifindex;
	struct wimax_dev *wimax_dev;
	struct device *dev;
	enum wimax_rf_state new_state;

	d_fnstart(3, NULL, "(skb %p info %p)\n", skb, info);
	result = -ENODEV;
	if (info->attrs[WIMAX_GNL_RFKILL_IFIDX] == NULL) {
		printk(KERN_ERR "WIMAX_GNL_OP_RFKILL: can't find IFIDX "
			"attribute\n");
		goto error_no_wimax_dev;
	}
	ifindex = nla_get_u32(info->attrs[WIMAX_GNL_RFKILL_IFIDX]);
	wimax_dev = wimax_dev_get_by_genl_info(info, ifindex);
	if (wimax_dev == NULL)
		goto error_no_wimax_dev;
	dev = wimax_dev_to_dev(wimax_dev);
	result = -EINVAL;
	if (info->attrs[WIMAX_GNL_RFKILL_STATE] == NULL) {
		dev_err(dev, "WIMAX_GNL_RFKILL: can't find RFKILL_STATE "
			"attribute\n");
		goto error_no_pid;
	}
	new_state = nla_get_u32(info->attrs[WIMAX_GNL_RFKILL_STATE]);

	/* Execute the operation and send the result back to user space */
	result = wimax_rfkill(wimax_dev, new_state);
error_no_pid:
	dev_put(wimax_dev->net_dev);
error_no_wimax_dev:
	d_fnend(3, NULL, "(skb %p info %p) = %d\n", skb, info, result);
	return result;
}


struct genl_ops wimax_gnl_rfkill = {
	.cmd = WIMAX_GNL_OP_RFKILL,
	.flags = GENL_ADMIN_PERM,
	.policy = wimax_gnl_rfkill_policy,
	.doit = wimax_gnl_doit_rfkill,
	.dumpit = NULL,
};

