Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 /*
0003 
0004   Broadcom B43legacy wireless driver
0005 
0006   SYSFS support routines
0007 
0008   Copyright (c) 2006 Michael Buesch <m@bues.ch>
0009 
0010 
0011 */
0012 
0013 #include "sysfs.h"
0014 #include "b43legacy.h"
0015 #include "main.h"
0016 #include "phy.h"
0017 #include "radio.h"
0018 
0019 #include <linux/capability.h>
0020 
0021 
0022 #define GENERIC_FILESIZE    64
0023 
0024 
0025 static int get_integer(const char *buf, size_t count)
0026 {
0027     char tmp[10 + 1] = { 0 };
0028     int ret = -EINVAL, res;
0029 
0030     if (count == 0)
0031         goto out;
0032     count = min_t(size_t, count, 10);
0033     memcpy(tmp, buf, count);
0034     ret = kstrtoint(tmp, 10, &res);
0035     if (!ret)
0036         return res;
0037 out:
0038     return ret;
0039 }
0040 
0041 static int get_boolean(const char *buf, size_t count)
0042 {
0043     if (count != 0) {
0044         if (buf[0] == '1')
0045             return 1;
0046         if (buf[0] == '0')
0047             return 0;
0048         if (count >= 4 && memcmp(buf, "true", 4) == 0)
0049             return 1;
0050         if (count >= 5 && memcmp(buf, "false", 5) == 0)
0051             return 0;
0052         if (count >= 3 && memcmp(buf, "yes", 3) == 0)
0053             return 1;
0054         if (count >= 2 && memcmp(buf, "no", 2) == 0)
0055             return 0;
0056         if (count >= 2 && memcmp(buf, "on", 2) == 0)
0057             return 1;
0058         if (count >= 3 && memcmp(buf, "off", 3) == 0)
0059             return 0;
0060     }
0061     return -EINVAL;
0062 }
0063 
0064 static ssize_t b43legacy_attr_interfmode_show(struct device *dev,
0065                           struct device_attribute *attr,
0066                           char *buf)
0067 {
0068     struct b43legacy_wldev *wldev = dev_to_b43legacy_wldev(dev);
0069     ssize_t count = 0;
0070 
0071     if (!capable(CAP_NET_ADMIN))
0072         return -EPERM;
0073 
0074     mutex_lock(&wldev->wl->mutex);
0075 
0076     switch (wldev->phy.interfmode) {
0077     case B43legacy_INTERFMODE_NONE:
0078         count = snprintf(buf, PAGE_SIZE, "0 (No Interference"
0079                  " Mitigation)\n");
0080         break;
0081     case B43legacy_INTERFMODE_NONWLAN:
0082         count = snprintf(buf, PAGE_SIZE, "1 (Non-WLAN Interference"
0083                  " Mitigation)\n");
0084         break;
0085     case B43legacy_INTERFMODE_MANUALWLAN:
0086         count = snprintf(buf, PAGE_SIZE, "2 (WLAN Interference"
0087                  " Mitigation)\n");
0088         break;
0089     default:
0090         B43legacy_WARN_ON(1);
0091     }
0092 
0093     mutex_unlock(&wldev->wl->mutex);
0094 
0095     return count;
0096 }
0097 
0098 static ssize_t b43legacy_attr_interfmode_store(struct device *dev,
0099                            struct device_attribute *attr,
0100                            const char *buf, size_t count)
0101 {
0102     struct b43legacy_wldev *wldev = dev_to_b43legacy_wldev(dev);
0103     unsigned long flags;
0104     int err;
0105     int mode;
0106 
0107     if (!capable(CAP_NET_ADMIN))
0108         return -EPERM;
0109 
0110     mode = get_integer(buf, count);
0111     switch (mode) {
0112     case 0:
0113         mode = B43legacy_INTERFMODE_NONE;
0114         break;
0115     case 1:
0116         mode = B43legacy_INTERFMODE_NONWLAN;
0117         break;
0118     case 2:
0119         mode = B43legacy_INTERFMODE_MANUALWLAN;
0120         break;
0121     case 3:
0122         mode = B43legacy_INTERFMODE_AUTOWLAN;
0123         break;
0124     default:
0125         return -EINVAL;
0126     }
0127 
0128     mutex_lock(&wldev->wl->mutex);
0129     spin_lock_irqsave(&wldev->wl->irq_lock, flags);
0130 
0131     err = b43legacy_radio_set_interference_mitigation(wldev, mode);
0132     if (err)
0133         b43legacyerr(wldev->wl, "Interference Mitigation not "
0134                "supported by device\n");
0135     spin_unlock_irqrestore(&wldev->wl->irq_lock, flags);
0136     mutex_unlock(&wldev->wl->mutex);
0137 
0138     return err ? err : count;
0139 }
0140 
0141 static DEVICE_ATTR(interference, 0644,
0142            b43legacy_attr_interfmode_show,
0143            b43legacy_attr_interfmode_store);
0144 
0145 static ssize_t b43legacy_attr_preamble_show(struct device *dev,
0146                         struct device_attribute *attr,
0147                         char *buf)
0148 {
0149     struct b43legacy_wldev *wldev = dev_to_b43legacy_wldev(dev);
0150     ssize_t count;
0151 
0152     if (!capable(CAP_NET_ADMIN))
0153         return -EPERM;
0154 
0155     mutex_lock(&wldev->wl->mutex);
0156 
0157     if (wldev->short_preamble)
0158         count = snprintf(buf, PAGE_SIZE, "1 (Short Preamble"
0159                  " enabled)\n");
0160     else
0161         count = snprintf(buf, PAGE_SIZE, "0 (Short Preamble"
0162                  " disabled)\n");
0163 
0164     mutex_unlock(&wldev->wl->mutex);
0165 
0166     return count;
0167 }
0168 
0169 static ssize_t b43legacy_attr_preamble_store(struct device *dev,
0170                          struct device_attribute *attr,
0171                          const char *buf, size_t count)
0172 {
0173     struct b43legacy_wldev *wldev = dev_to_b43legacy_wldev(dev);
0174     unsigned long flags;
0175     int value;
0176 
0177     if (!capable(CAP_NET_ADMIN))
0178         return -EPERM;
0179 
0180     value = get_boolean(buf, count);
0181     if (value < 0)
0182         return value;
0183     mutex_lock(&wldev->wl->mutex);
0184     spin_lock_irqsave(&wldev->wl->irq_lock, flags);
0185 
0186     wldev->short_preamble = !!value;
0187 
0188     spin_unlock_irqrestore(&wldev->wl->irq_lock, flags);
0189     mutex_unlock(&wldev->wl->mutex);
0190 
0191     return count;
0192 }
0193 
0194 static DEVICE_ATTR(shortpreamble, 0644,
0195            b43legacy_attr_preamble_show,
0196            b43legacy_attr_preamble_store);
0197 
0198 int b43legacy_sysfs_register(struct b43legacy_wldev *wldev)
0199 {
0200     struct device *dev = wldev->dev->dev;
0201     int err;
0202 
0203     B43legacy_WARN_ON(b43legacy_status(wldev) !=
0204               B43legacy_STAT_INITIALIZED);
0205 
0206     err = device_create_file(dev, &dev_attr_interference);
0207     if (err)
0208         goto out;
0209     err = device_create_file(dev, &dev_attr_shortpreamble);
0210     if (err)
0211         goto err_remove_interfmode;
0212 
0213 out:
0214     return err;
0215 err_remove_interfmode:
0216     device_remove_file(dev, &dev_attr_interference);
0217     goto out;
0218 }
0219 
0220 void b43legacy_sysfs_unregister(struct b43legacy_wldev *wldev)
0221 {
0222     struct device *dev = wldev->dev->dev;
0223 
0224     device_remove_file(dev, &dev_attr_shortpreamble);
0225     device_remove_file(dev, &dev_attr_interference);
0226 }