/*

  Broadcom B43legacy wireless driver

  SYSFS support routines

  Copyright (c) 2006 Michael Buesch <m@bues.ch>

  This program is free software; you can redistribute it and/or modify
  it under the terms of the GNU General Public License as published by
  the Free Software Foundation; either version 2 of the License, or
  (at your option) any later version.

  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; see the file COPYING.  If not, write to
  the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor,
  Boston, MA 02110-1301, USA.

*/

#include "sysfs.h"
#include "b43legacy.h"
#include "main.h"
#include "phy.h"
#include "radio.h"

#include <linux/capability.h>


#define GENERIC_FILESIZE	64


static int get_integer(const char *buf, size_t count)
{
	char tmp[10 + 1] = { 0 };
	int ret = -EINVAL;

	if (count == 0)
		goto out;
	count = min(count, (size_t)10);
	memcpy(tmp, buf, count);
	ret = simple_strtol(tmp, NULL, 10);
out:
	return ret;
}

static int get_boolean(const char *buf, size_t count)
{
	if (count != 0) {
		if (buf[0] == '1')
			return 1;
		if (buf[0] == '0')
			return 0;
		if (count >= 4 && memcmp(buf, "true", 4) == 0)
			return 1;
		if (count >= 5 && memcmp(buf, "false", 5) == 0)
			return 0;
		if (count >= 3 && memcmp(buf, "yes", 3) == 0)
			return 1;
		if (count >= 2 && memcmp(buf, "no", 2) == 0)
			return 0;
		if (count >= 2 && memcmp(buf, "on", 2) == 0)
			return 1;
		if (count >= 3 && memcmp(buf, "off", 3) == 0)
			return 0;
	}
	return -EINVAL;
}

static ssize_t b43legacy_attr_interfmode_show(struct device *dev,
					      struct device_attribute *attr,
					      char *buf)
{
	struct b43legacy_wldev *wldev = dev_to_b43legacy_wldev(dev);
	ssize_t count = 0;

	if (!capable(CAP_NET_ADMIN))
		return -EPERM;

	mutex_lock(&wldev->wl->mutex);

	switch (wldev->phy.interfmode) {
	case B43legacy_INTERFMODE_NONE:
		count = snprintf(buf, PAGE_SIZE, "0 (No Interference"
				 " Mitigation)\n");
		break;
	case B43legacy_INTERFMODE_NONWLAN:
		count = snprintf(buf, PAGE_SIZE, "1 (Non-WLAN Interference"
				 " Mitigation)\n");
		break;
	case B43legacy_INTERFMODE_MANUALWLAN:
		count = snprintf(buf, PAGE_SIZE, "2 (WLAN Interference"
				 " Mitigation)\n");
		break;
	default:
		B43legacy_WARN_ON(1);
	}

	mutex_unlock(&wldev->wl->mutex);

	return count;
}

static ssize_t b43legacy_attr_interfmode_store(struct device *dev,
					       struct device_attribute *attr,
					       const char *buf, size_t count)
{
	struct b43legacy_wldev *wldev = dev_to_b43legacy_wldev(dev);
	unsigned long flags;
	int err;
	int mode;

	if (!capable(CAP_NET_ADMIN))
		return -EPERM;

	mode = get_integer(buf, count);
	switch (mode) {
	case 0:
		mode = B43legacy_INTERFMODE_NONE;
		break;
	case 1:
		mode = B43legacy_INTERFMODE_NONWLAN;
		break;
	case 2:
		mode = B43legacy_INTERFMODE_MANUALWLAN;
		break;
	case 3:
		mode = B43legacy_INTERFMODE_AUTOWLAN;
		break;
	default:
		return -EINVAL;
	}

	mutex_lock(&wldev->wl->mutex);
	spin_lock_irqsave(&wldev->wl->irq_lock, flags);

	err = b43legacy_radio_set_interference_mitigation(wldev, mode);
	if (err)
		b43legacyerr(wldev->wl, "Interference Mitigation not "
		       "supported by device\n");
	mmiowb();
	spin_unlock_irqrestore(&wldev->wl->irq_lock, flags);
	mutex_unlock(&wldev->wl->mutex);

	return err ? err : count;
}

static DEVICE_ATTR(interference, 0644,
		   b43legacy_attr_interfmode_show,
		   b43legacy_attr_interfmode_store);

static ssize_t b43legacy_attr_preamble_show(struct device *dev,
					    struct device_attribute *attr,
					    char *buf)
{
	struct b43legacy_wldev *wldev = dev_to_b43legacy_wldev(dev);
	ssize_t count;

	if (!capable(CAP_NET_ADMIN))
		return -EPERM;

	mutex_lock(&wldev->wl->mutex);

	if (wldev->short_preamble)
		count = snprintf(buf, PAGE_SIZE, "1 (Short Preamble"
				 " enabled)\n");
	else
		count = snprintf(buf, PAGE_SIZE, "0 (Short Preamble"
				 " disabled)\n");

	mutex_unlock(&wldev->wl->mutex);

	return count;
}

static ssize_t b43legacy_attr_preamble_store(struct device *dev,
					     struct device_attribute *attr,
					     const char *buf, size_t count)
{
	struct b43legacy_wldev *wldev = dev_to_b43legacy_wldev(dev);
	unsigned long flags;
	int value;

	if (!capable(CAP_NET_ADMIN))
		return -EPERM;

	value = get_boolean(buf, count);
	if (value < 0)
		return value;
	mutex_lock(&wldev->wl->mutex);
	spin_lock_irqsave(&wldev->wl->irq_lock, flags);

	wldev->short_preamble = !!value;

	spin_unlock_irqrestore(&wldev->wl->irq_lock, flags);
	mutex_unlock(&wldev->wl->mutex);

	return count;
}

static DEVICE_ATTR(shortpreamble, 0644,
		   b43legacy_attr_preamble_show,
		   b43legacy_attr_preamble_store);

int b43legacy_sysfs_register(struct b43legacy_wldev *wldev)
{
	struct device *dev = wldev->dev->dev;
	int err;

	B43legacy_WARN_ON(b43legacy_status(wldev) !=
			  B43legacy_STAT_INITIALIZED);

	err = device_create_file(dev, &dev_attr_interference);
	if (err)
		goto out;
	err = device_create_file(dev, &dev_attr_shortpreamble);
	if (err)
		goto err_remove_interfmode;

out:
	return err;
err_remove_interfmode:
	device_remove_file(dev, &dev_attr_interference);
	goto out;
}

void b43legacy_sysfs_unregister(struct b43legacy_wldev *wldev)
{
	struct device *dev = wldev->dev->dev;

	device_remove_file(dev, &dev_attr_shortpreamble);
	device_remove_file(dev, &dev_attr_interference);
}
