linux/drivers/net/wireless/broadcom/b43legacy/sysfs.c
<<
>>
Prefs
   1/*
   2
   3  Broadcom B43legacy wireless driver
   4
   5  SYSFS support routines
   6
   7  Copyright (c) 2006 Michael Buesch <m@bues.ch>
   8
   9  This program is free software; you can redistribute it and/or modify
  10  it under the terms of the GNU General Public License as published by
  11  the Free Software Foundation; either version 2 of the License, or
  12  (at your option) any later version.
  13
  14  This program is distributed in the hope that it will be useful,
  15  but WITHOUT ANY WARRANTY; without even the implied warranty of
  16  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  17  GNU General Public License for more details.
  18
  19  You should have received a copy of the GNU General Public License
  20  along with this program; see the file COPYING.  If not, write to
  21  the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor,
  22  Boston, MA 02110-1301, USA.
  23
  24*/
  25
  26#include "sysfs.h"
  27#include "b43legacy.h"
  28#include "main.h"
  29#include "phy.h"
  30#include "radio.h"
  31
  32#include <linux/capability.h>
  33
  34
  35#define GENERIC_FILESIZE        64
  36
  37
  38static int get_integer(const char *buf, size_t count)
  39{
  40        char tmp[10 + 1] = { 0 };
  41        int ret = -EINVAL;
  42
  43        if (count == 0)
  44                goto out;
  45        count = min_t(size_t, count, 10);
  46        memcpy(tmp, buf, count);
  47        ret = simple_strtol(tmp, NULL, 10);
  48out:
  49        return ret;
  50}
  51
  52static int get_boolean(const char *buf, size_t count)
  53{
  54        if (count != 0) {
  55                if (buf[0] == '1')
  56                        return 1;
  57                if (buf[0] == '0')
  58                        return 0;
  59                if (count >= 4 && memcmp(buf, "true", 4) == 0)
  60                        return 1;
  61                if (count >= 5 && memcmp(buf, "false", 5) == 0)
  62                        return 0;
  63                if (count >= 3 && memcmp(buf, "yes", 3) == 0)
  64                        return 1;
  65                if (count >= 2 && memcmp(buf, "no", 2) == 0)
  66                        return 0;
  67                if (count >= 2 && memcmp(buf, "on", 2) == 0)
  68                        return 1;
  69                if (count >= 3 && memcmp(buf, "off", 3) == 0)
  70                        return 0;
  71        }
  72        return -EINVAL;
  73}
  74
  75static ssize_t b43legacy_attr_interfmode_show(struct device *dev,
  76                                              struct device_attribute *attr,
  77                                              char *buf)
  78{
  79        struct b43legacy_wldev *wldev = dev_to_b43legacy_wldev(dev);
  80        ssize_t count = 0;
  81
  82        if (!capable(CAP_NET_ADMIN))
  83                return -EPERM;
  84
  85        mutex_lock(&wldev->wl->mutex);
  86
  87        switch (wldev->phy.interfmode) {
  88        case B43legacy_INTERFMODE_NONE:
  89                count = snprintf(buf, PAGE_SIZE, "0 (No Interference"
  90                                 " Mitigation)\n");
  91                break;
  92        case B43legacy_INTERFMODE_NONWLAN:
  93                count = snprintf(buf, PAGE_SIZE, "1 (Non-WLAN Interference"
  94                                 " Mitigation)\n");
  95                break;
  96        case B43legacy_INTERFMODE_MANUALWLAN:
  97                count = snprintf(buf, PAGE_SIZE, "2 (WLAN Interference"
  98                                 " Mitigation)\n");
  99                break;
 100        default:
 101                B43legacy_WARN_ON(1);
 102        }
 103
 104        mutex_unlock(&wldev->wl->mutex);
 105
 106        return count;
 107}
 108
 109static ssize_t b43legacy_attr_interfmode_store(struct device *dev,
 110                                               struct device_attribute *attr,
 111                                               const char *buf, size_t count)
 112{
 113        struct b43legacy_wldev *wldev = dev_to_b43legacy_wldev(dev);
 114        unsigned long flags;
 115        int err;
 116        int mode;
 117
 118        if (!capable(CAP_NET_ADMIN))
 119                return -EPERM;
 120
 121        mode = get_integer(buf, count);
 122        switch (mode) {
 123        case 0:
 124                mode = B43legacy_INTERFMODE_NONE;
 125                break;
 126        case 1:
 127                mode = B43legacy_INTERFMODE_NONWLAN;
 128                break;
 129        case 2:
 130                mode = B43legacy_INTERFMODE_MANUALWLAN;
 131                break;
 132        case 3:
 133                mode = B43legacy_INTERFMODE_AUTOWLAN;
 134                break;
 135        default:
 136                return -EINVAL;
 137        }
 138
 139        mutex_lock(&wldev->wl->mutex);
 140        spin_lock_irqsave(&wldev->wl->irq_lock, flags);
 141
 142        err = b43legacy_radio_set_interference_mitigation(wldev, mode);
 143        if (err)
 144                b43legacyerr(wldev->wl, "Interference Mitigation not "
 145                       "supported by device\n");
 146        mmiowb();
 147        spin_unlock_irqrestore(&wldev->wl->irq_lock, flags);
 148        mutex_unlock(&wldev->wl->mutex);
 149
 150        return err ? err : count;
 151}
 152
 153static DEVICE_ATTR(interference, 0644,
 154                   b43legacy_attr_interfmode_show,
 155                   b43legacy_attr_interfmode_store);
 156
 157static ssize_t b43legacy_attr_preamble_show(struct device *dev,
 158                                            struct device_attribute *attr,
 159                                            char *buf)
 160{
 161        struct b43legacy_wldev *wldev = dev_to_b43legacy_wldev(dev);
 162        ssize_t count;
 163
 164        if (!capable(CAP_NET_ADMIN))
 165                return -EPERM;
 166
 167        mutex_lock(&wldev->wl->mutex);
 168
 169        if (wldev->short_preamble)
 170                count = snprintf(buf, PAGE_SIZE, "1 (Short Preamble"
 171                                 " enabled)\n");
 172        else
 173                count = snprintf(buf, PAGE_SIZE, "0 (Short Preamble"
 174                                 " disabled)\n");
 175
 176        mutex_unlock(&wldev->wl->mutex);
 177
 178        return count;
 179}
 180
 181static ssize_t b43legacy_attr_preamble_store(struct device *dev,
 182                                             struct device_attribute *attr,
 183                                             const char *buf, size_t count)
 184{
 185        struct b43legacy_wldev *wldev = dev_to_b43legacy_wldev(dev);
 186        unsigned long flags;
 187        int value;
 188
 189        if (!capable(CAP_NET_ADMIN))
 190                return -EPERM;
 191
 192        value = get_boolean(buf, count);
 193        if (value < 0)
 194                return value;
 195        mutex_lock(&wldev->wl->mutex);
 196        spin_lock_irqsave(&wldev->wl->irq_lock, flags);
 197
 198        wldev->short_preamble = !!value;
 199
 200        spin_unlock_irqrestore(&wldev->wl->irq_lock, flags);
 201        mutex_unlock(&wldev->wl->mutex);
 202
 203        return count;
 204}
 205
 206static DEVICE_ATTR(shortpreamble, 0644,
 207                   b43legacy_attr_preamble_show,
 208                   b43legacy_attr_preamble_store);
 209
 210int b43legacy_sysfs_register(struct b43legacy_wldev *wldev)
 211{
 212        struct device *dev = wldev->dev->dev;
 213        int err;
 214
 215        B43legacy_WARN_ON(b43legacy_status(wldev) !=
 216                          B43legacy_STAT_INITIALIZED);
 217
 218        err = device_create_file(dev, &dev_attr_interference);
 219        if (err)
 220                goto out;
 221        err = device_create_file(dev, &dev_attr_shortpreamble);
 222        if (err)
 223                goto err_remove_interfmode;
 224
 225out:
 226        return err;
 227err_remove_interfmode:
 228        device_remove_file(dev, &dev_attr_interference);
 229        goto out;
 230}
 231
 232void b43legacy_sysfs_unregister(struct b43legacy_wldev *wldev)
 233{
 234        struct device *dev = wldev->dev->dev;
 235
 236        device_remove_file(dev, &dev_attr_shortpreamble);
 237        device_remove_file(dev, &dev_attr_interference);
 238}
 239