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