0001
0002
0003
0004
0005
0006
0007
0008
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 }