223 lines · c
1// SPDX-License-Identifier: GPL-2.0-or-later2/*3 4 Broadcom B43legacy wireless driver5 6 SYSFS support routines7 8 Copyright (c) 2006 Michael Buesch <m@bues.ch>9 10 11*/12 13#include "sysfs.h"14#include "b43legacy.h"15#include "main.h"16#include "phy.h"17#include "radio.h"18 19#include <linux/capability.h>20 21 22#define GENERIC_FILESIZE 6423 24 25static int get_integer(const char *buf, size_t count)26{27 char tmp[10 + 1] = { 0 };28 int ret = -EINVAL, res;29 30 if (count == 0)31 goto out;32 count = min_t(size_t, count, 10);33 memcpy(tmp, buf, count);34 ret = kstrtoint(tmp, 10, &res);35 if (!ret)36 return res;37out:38 return ret;39}40 41static int get_boolean(const char *buf, size_t count)42{43 if (count != 0) {44 if (buf[0] == '1')45 return 1;46 if (buf[0] == '0')47 return 0;48 if (count >= 4 && memcmp(buf, "true", 4) == 0)49 return 1;50 if (count >= 5 && memcmp(buf, "false", 5) == 0)51 return 0;52 if (count >= 3 && memcmp(buf, "yes", 3) == 0)53 return 1;54 if (count >= 2 && memcmp(buf, "no", 2) == 0)55 return 0;56 if (count >= 2 && memcmp(buf, "on", 2) == 0)57 return 1;58 if (count >= 3 && memcmp(buf, "off", 3) == 0)59 return 0;60 }61 return -EINVAL;62}63 64static ssize_t b43legacy_attr_interfmode_show(struct device *dev,65 struct device_attribute *attr,66 char *buf)67{68 struct b43legacy_wldev *wldev = dev_to_b43legacy_wldev(dev);69 ssize_t count = 0;70 71 if (!capable(CAP_NET_ADMIN))72 return -EPERM;73 74 mutex_lock(&wldev->wl->mutex);75 76 switch (wldev->phy.interfmode) {77 case B43legacy_INTERFMODE_NONE:78 count = sysfs_emit(buf, "0 (No Interference Mitigation)\n");79 break;80 case B43legacy_INTERFMODE_NONWLAN:81 count = sysfs_emit(buf,82 "1 (Non-WLAN Interference Mitigation)\n");83 break;84 case B43legacy_INTERFMODE_MANUALWLAN:85 count = sysfs_emit(buf, "2 (WLAN Interference Mitigation)\n");86 break;87 default:88 B43legacy_WARN_ON(1);89 }90 91 mutex_unlock(&wldev->wl->mutex);92 93 return count;94}95 96static ssize_t b43legacy_attr_interfmode_store(struct device *dev,97 struct device_attribute *attr,98 const char *buf, size_t count)99{100 struct b43legacy_wldev *wldev = dev_to_b43legacy_wldev(dev);101 unsigned long flags;102 int err;103 int mode;104 105 if (!capable(CAP_NET_ADMIN))106 return -EPERM;107 108 mode = get_integer(buf, count);109 switch (mode) {110 case 0:111 mode = B43legacy_INTERFMODE_NONE;112 break;113 case 1:114 mode = B43legacy_INTERFMODE_NONWLAN;115 break;116 case 2:117 mode = B43legacy_INTERFMODE_MANUALWLAN;118 break;119 case 3:120 mode = B43legacy_INTERFMODE_AUTOWLAN;121 break;122 default:123 return -EINVAL;124 }125 126 mutex_lock(&wldev->wl->mutex);127 spin_lock_irqsave(&wldev->wl->irq_lock, flags);128 129 err = b43legacy_radio_set_interference_mitigation(wldev, mode);130 if (err)131 b43legacyerr(wldev->wl, "Interference Mitigation not "132 "supported by device\n");133 spin_unlock_irqrestore(&wldev->wl->irq_lock, flags);134 mutex_unlock(&wldev->wl->mutex);135 136 return err ? err : count;137}138 139static DEVICE_ATTR(interference, 0644,140 b43legacy_attr_interfmode_show,141 b43legacy_attr_interfmode_store);142 143static ssize_t b43legacy_attr_preamble_show(struct device *dev,144 struct device_attribute *attr,145 char *buf)146{147 struct b43legacy_wldev *wldev = dev_to_b43legacy_wldev(dev);148 ssize_t count;149 150 if (!capable(CAP_NET_ADMIN))151 return -EPERM;152 153 mutex_lock(&wldev->wl->mutex);154 155 if (wldev->short_preamble)156 count = sysfs_emit(buf, "1 (Short Preamble enabled)\n");157 else158 count = sysfs_emit(buf, "0 (Short Preamble disabled)\n");159 160 mutex_unlock(&wldev->wl->mutex);161 162 return count;163}164 165static ssize_t b43legacy_attr_preamble_store(struct device *dev,166 struct device_attribute *attr,167 const char *buf, size_t count)168{169 struct b43legacy_wldev *wldev = dev_to_b43legacy_wldev(dev);170 unsigned long flags;171 int value;172 173 if (!capable(CAP_NET_ADMIN))174 return -EPERM;175 176 value = get_boolean(buf, count);177 if (value < 0)178 return value;179 mutex_lock(&wldev->wl->mutex);180 spin_lock_irqsave(&wldev->wl->irq_lock, flags);181 182 wldev->short_preamble = !!value;183 184 spin_unlock_irqrestore(&wldev->wl->irq_lock, flags);185 mutex_unlock(&wldev->wl->mutex);186 187 return count;188}189 190static DEVICE_ATTR(shortpreamble, 0644,191 b43legacy_attr_preamble_show,192 b43legacy_attr_preamble_store);193 194int b43legacy_sysfs_register(struct b43legacy_wldev *wldev)195{196 struct device *dev = wldev->dev->dev;197 int err;198 199 B43legacy_WARN_ON(b43legacy_status(wldev) !=200 B43legacy_STAT_INITIALIZED);201 202 err = device_create_file(dev, &dev_attr_interference);203 if (err)204 goto out;205 err = device_create_file(dev, &dev_attr_shortpreamble);206 if (err)207 goto err_remove_interfmode;208 209out:210 return err;211err_remove_interfmode:212 device_remove_file(dev, &dev_attr_interference);213 goto out;214}215 216void b43legacy_sysfs_unregister(struct b43legacy_wldev *wldev)217{218 struct device *dev = wldev->dev->dev;219 220 device_remove_file(dev, &dev_attr_shortpreamble);221 device_remove_file(dev, &dev_attr_interference);222}223