blob: 5c36e29efff7e1082af46c193bd9b2255479da7e [file] [log] [blame]
John W. Linvillef2223132006-01-23 16:59:58 -05001/*
2
3 Broadcom BCM43xx wireless driver
4
5 Copyright (c) 2005 Martin Langer <martin-langer@gmx.de>,
6 Stefano Brivio <st3@riseup.net>
7 Michael Buesch <mbuesch@freenet.de>
8 Danny van Dyk <kugelfang@gentoo.org>
9 Andreas Jaggi <andreas.jaggi@waterwave.ch>
10
11 Some parts of the code in this file are derived from the ipw2200
12 driver Copyright(c) 2003 - 2004 Intel Corporation.
13
14 This program is free software; you can redistribute it and/or modify
15 it under the terms of the GNU General Public License as published by
16 the Free Software Foundation; either version 2 of the License, or
17 (at your option) any later version.
18
19 This program is distributed in the hope that it will be useful,
20 but WITHOUT ANY WARRANTY; without even the implied warranty of
21 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 GNU General Public License for more details.
23
24 You should have received a copy of the GNU General Public License
25 along with this program; see the file COPYING. If not, write to
26 the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor,
27 Boston, MA 02110-1301, USA.
28
29*/
30
31#include <linux/wireless.h>
32#include <net/iw_handler.h>
33#include <net/ieee80211softmac.h>
34#include <net/ieee80211softmac_wx.h>
35#include <linux/capability.h>
36#include <linux/sched.h> /* for capable() */
37#include <linux/delay.h>
38
39#include "bcm43xx.h"
40#include "bcm43xx_wx.h"
41#include "bcm43xx_main.h"
42#include "bcm43xx_radio.h"
Michael Bueschb5488be2006-02-08 18:00:30 +010043#include "bcm43xx_phy.h"
John W. Linvillef2223132006-01-23 16:59:58 -050044
Michael Buesch8fa252d2006-02-02 19:49:15 +010045
46/* The WIRELESS_EXT version, which is implemented by this driver. */
47#define BCM43xx_WX_VERSION 18
48
John W. Linvillef2223132006-01-23 16:59:58 -050049#define MAX_WX_STRING 80
50
51
52static int bcm43xx_wx_get_name(struct net_device *net_dev,
53 struct iw_request_info *info,
54 union iwreq_data *data,
55 char *extra)
56{
57 struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
Michael Buesche9357c02006-03-13 19:27:34 +010058 int i;
Michael Buesch78ff56a2006-06-05 20:24:10 +020059 unsigned long flags;
John W. Linvillef2223132006-01-23 16:59:58 -050060 struct bcm43xx_phyinfo *phy;
61 char suffix[7] = { 0 };
62 int have_a = 0, have_b = 0, have_g = 0;
63
Michael Buesch78ff56a2006-06-05 20:24:10 +020064 bcm43xx_lock_irqsafe(bcm, flags);
Michael Buesche9357c02006-03-13 19:27:34 +010065 for (i = 0; i < bcm->nr_80211_available; i++) {
66 phy = &(bcm->core_80211_ext[i].phy);
John W. Linvillef2223132006-01-23 16:59:58 -050067 switch (phy->type) {
68 case BCM43xx_PHYTYPE_A:
69 have_a = 1;
70 break;
71 case BCM43xx_PHYTYPE_G:
72 have_g = 1;
73 case BCM43xx_PHYTYPE_B:
74 have_b = 1;
75 break;
76 default:
77 assert(0);
78 }
79 }
Michael Buesch78ff56a2006-06-05 20:24:10 +020080 bcm43xx_unlock_irqsafe(bcm, flags);
John W. Linvillef2223132006-01-23 16:59:58 -050081
82 i = 0;
83 if (have_a) {
84 suffix[i++] = 'a';
85 suffix[i++] = '/';
86 }
87 if (have_b) {
88 suffix[i++] = 'b';
89 suffix[i++] = '/';
90 }
91 if (have_g) {
92 suffix[i++] = 'g';
93 suffix[i++] = '/';
94 }
95 if (i != 0)
96 suffix[i - 1] = '\0';
97
98 snprintf(data->name, IFNAMSIZ, "IEEE 802.11%s", suffix);
99
100 return 0;
101}
102
103static int bcm43xx_wx_set_channelfreq(struct net_device *net_dev,
104 struct iw_request_info *info,
105 union iwreq_data *data,
106 char *extra)
107{
108 struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
John W. Linvillef2223132006-01-23 16:59:58 -0500109 unsigned long flags;
110 u8 channel;
111 int freq;
Michael Buesch10d8dd82006-02-19 22:08:48 +0100112 int err = -EINVAL;
John W. Linvillef2223132006-01-23 16:59:58 -0500113
Michael Buesch78ff56a2006-06-05 20:24:10 +0200114 bcm43xx_lock_irqsafe(bcm, flags);
John W. Linvillef2223132006-01-23 16:59:58 -0500115 if ((data->freq.m >= 0) && (data->freq.m <= 1000)) {
116 channel = data->freq.m;
117 freq = bcm43xx_channel_to_freq(bcm, channel);
118 } else {
119 channel = bcm43xx_freq_to_channel(bcm, data->freq.m);
120 freq = data->freq.m;
121 }
Larry Fingerfc8fd342006-06-25 21:32:21 -0500122 if (!ieee80211_is_valid_channel(bcm->ieee, channel))
Michael Buesch10d8dd82006-02-19 22:08:48 +0100123 goto out_unlock;
Michael Buesch78ff56a2006-06-05 20:24:10 +0200124 if (bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED) {
John W. Linvillef2223132006-01-23 16:59:58 -0500125 //ieee80211softmac_disassoc(softmac, $REASON);
126 bcm43xx_mac_suspend(bcm);
127 err = bcm43xx_radio_selectchannel(bcm, channel, 0);
128 bcm43xx_mac_enable(bcm);
Michael Buesch10d8dd82006-02-19 22:08:48 +0100129 } else {
Michael Buesche9357c02006-03-13 19:27:34 +0100130 bcm43xx_current_radio(bcm)->initial_channel = channel;
Michael Buesch10d8dd82006-02-19 22:08:48 +0100131 err = 0;
132 }
133out_unlock:
Michael Buesch78ff56a2006-06-05 20:24:10 +0200134 bcm43xx_unlock_irqsafe(bcm, flags);
John W. Linvillef2223132006-01-23 16:59:58 -0500135
136 return err;
137}
138
139static int bcm43xx_wx_get_channelfreq(struct net_device *net_dev,
140 struct iw_request_info *info,
141 union iwreq_data *data,
142 char *extra)
143{
144 struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
Michael Buesche9357c02006-03-13 19:27:34 +0100145 struct bcm43xx_radioinfo *radio;
John W. Linvillef2223132006-01-23 16:59:58 -0500146 unsigned long flags;
147 int err = -ENODEV;
148 u16 channel;
149
Michael Buesch78ff56a2006-06-05 20:24:10 +0200150 bcm43xx_lock_irqsafe(bcm, flags);
Michael Buesche9357c02006-03-13 19:27:34 +0100151 radio = bcm43xx_current_radio(bcm);
152 channel = radio->channel;
John W. Linvillef2223132006-01-23 16:59:58 -0500153 if (channel == 0xFF) {
Michael Buesche9357c02006-03-13 19:27:34 +0100154 channel = radio->initial_channel;
John W. Linvillef2223132006-01-23 16:59:58 -0500155 if (channel == 0xFF)
156 goto out_unlock;
157 }
158 assert(channel > 0 && channel <= 1000);
159 data->freq.e = 1;
160 data->freq.m = bcm43xx_channel_to_freq(bcm, channel) * 100000;
161 data->freq.flags = 1;
162
163 err = 0;
164out_unlock:
Michael Buesch78ff56a2006-06-05 20:24:10 +0200165 bcm43xx_unlock_irqsafe(bcm, flags);
John W. Linvillef2223132006-01-23 16:59:58 -0500166
167 return err;
168}
169
170static int bcm43xx_wx_set_mode(struct net_device *net_dev,
171 struct iw_request_info *info,
172 union iwreq_data *data,
173 char *extra)
174{
175 struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
176 unsigned long flags;
177 int mode;
178
John W. Linvillef2223132006-01-23 16:59:58 -0500179 mode = data->mode;
180 if (mode == IW_MODE_AUTO)
181 mode = BCM43xx_INITIAL_IWMODE;
182
Michael Buesch78ff56a2006-06-05 20:24:10 +0200183 bcm43xx_lock_irqsafe(bcm, flags);
184 if (bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED) {
Michael Buesch5b4b9772006-05-01 22:43:00 +0200185 if (bcm->ieee->iw_mode != mode)
186 bcm43xx_set_iwmode(bcm, mode);
187 } else
188 bcm->ieee->iw_mode = mode;
Michael Buesch78ff56a2006-06-05 20:24:10 +0200189 bcm43xx_unlock_irqsafe(bcm, flags);
John W. Linvillef2223132006-01-23 16:59:58 -0500190
191 return 0;
192}
193
194static int bcm43xx_wx_get_mode(struct net_device *net_dev,
195 struct iw_request_info *info,
196 union iwreq_data *data,
197 char *extra)
198{
199 struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
200 unsigned long flags;
201
Michael Buesch78ff56a2006-06-05 20:24:10 +0200202 bcm43xx_lock_irqsafe(bcm, flags);
John W. Linvillef2223132006-01-23 16:59:58 -0500203 data->mode = bcm->ieee->iw_mode;
Michael Buesch78ff56a2006-06-05 20:24:10 +0200204 bcm43xx_unlock_irqsafe(bcm, flags);
John W. Linvillef2223132006-01-23 16:59:58 -0500205
206 return 0;
207}
208
John W. Linvillef2223132006-01-23 16:59:58 -0500209static int bcm43xx_wx_get_rangeparams(struct net_device *net_dev,
210 struct iw_request_info *info,
211 union iwreq_data *data,
212 char *extra)
213{
214 struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
215 struct iw_range *range = (struct iw_range *)extra;
216 const struct ieee80211_geo *geo;
217 unsigned long flags;
218 int i, j;
Michael Buesche9357c02006-03-13 19:27:34 +0100219 struct bcm43xx_phyinfo *phy;
John W. Linvillef2223132006-01-23 16:59:58 -0500220
John W. Linvillef2223132006-01-23 16:59:58 -0500221 data->data.length = sizeof(*range);
222 memset(range, 0, sizeof(*range));
223
224 //TODO: What about 802.11b?
225 /* 54Mb/s == ~27Mb/s payload throughput (802.11g) */
226 range->throughput = 27 * 1000 * 1000;
227
228 range->max_qual.qual = 100;
229 /* TODO: Real max RSSI */
Michael Buesch72fb8512006-03-22 18:10:19 +0100230 range->max_qual.level = 3;
231 range->max_qual.noise = 100;
John W. Linvillef2223132006-01-23 16:59:58 -0500232 range->max_qual.updated = 7;
233
234 range->avg_qual.qual = 70;
Michael Buesch72fb8512006-03-22 18:10:19 +0100235 range->avg_qual.level = 2;
236 range->avg_qual.noise = 40;
John W. Linvillef2223132006-01-23 16:59:58 -0500237 range->avg_qual.updated = 7;
238
239 range->min_rts = BCM43xx_MIN_RTS_THRESHOLD;
240 range->max_rts = BCM43xx_MAX_RTS_THRESHOLD;
241 range->min_frag = MIN_FRAG_THRESHOLD;
242 range->max_frag = MAX_FRAG_THRESHOLD;
243
244 range->encoding_size[0] = 5;
245 range->encoding_size[1] = 13;
246 range->num_encoding_sizes = 2;
247 range->max_encoding_tokens = WEP_KEYS;
248
249 range->we_version_compiled = WIRELESS_EXT;
Michael Buesch8fa252d2006-02-02 19:49:15 +0100250 range->we_version_source = BCM43xx_WX_VERSION;
251
252 range->enc_capa = IW_ENC_CAPA_WPA |
253 IW_ENC_CAPA_WPA2 |
254 IW_ENC_CAPA_CIPHER_TKIP |
255 IW_ENC_CAPA_CIPHER_CCMP;
John W. Linvillef2223132006-01-23 16:59:58 -0500256
Michael Buesch78ff56a2006-06-05 20:24:10 +0200257 bcm43xx_lock_irqsafe(bcm, flags);
Michael Buesche9357c02006-03-13 19:27:34 +0100258 phy = bcm43xx_current_phy(bcm);
John W. Linvillef2223132006-01-23 16:59:58 -0500259
260 range->num_bitrates = 0;
261 i = 0;
Michael Buesche9357c02006-03-13 19:27:34 +0100262 if (phy->type == BCM43xx_PHYTYPE_A ||
263 phy->type == BCM43xx_PHYTYPE_G) {
John W. Linvillef2223132006-01-23 16:59:58 -0500264 range->num_bitrates = 8;
265 range->bitrate[i++] = IEEE80211_OFDM_RATE_6MB;
266 range->bitrate[i++] = IEEE80211_OFDM_RATE_9MB;
267 range->bitrate[i++] = IEEE80211_OFDM_RATE_12MB;
268 range->bitrate[i++] = IEEE80211_OFDM_RATE_18MB;
269 range->bitrate[i++] = IEEE80211_OFDM_RATE_24MB;
270 range->bitrate[i++] = IEEE80211_OFDM_RATE_36MB;
271 range->bitrate[i++] = IEEE80211_OFDM_RATE_48MB;
272 range->bitrate[i++] = IEEE80211_OFDM_RATE_54MB;
273 }
Michael Buesche9357c02006-03-13 19:27:34 +0100274 if (phy->type == BCM43xx_PHYTYPE_B ||
275 phy->type == BCM43xx_PHYTYPE_G) {
John W. Linvillef2223132006-01-23 16:59:58 -0500276 range->num_bitrates += 4;
277 range->bitrate[i++] = IEEE80211_CCK_RATE_1MB;
278 range->bitrate[i++] = IEEE80211_CCK_RATE_2MB;
279 range->bitrate[i++] = IEEE80211_CCK_RATE_5MB;
280 range->bitrate[i++] = IEEE80211_CCK_RATE_11MB;
281 }
282
283 geo = ieee80211_get_geo(bcm->ieee);
284 range->num_channels = geo->a_channels + geo->bg_channels;
285 j = 0;
286 for (i = 0; i < geo->a_channels; i++) {
287 if (j == IW_MAX_FREQUENCIES)
288 break;
289 range->freq[j].i = j + 1;
290 range->freq[j].m = geo->a[i].freq;//FIXME?
291 range->freq[j].e = 1;
292 j++;
293 }
294 for (i = 0; i < geo->bg_channels; i++) {
295 if (j == IW_MAX_FREQUENCIES)
296 break;
297 range->freq[j].i = j + 1;
298 range->freq[j].m = geo->bg[i].freq;//FIXME?
299 range->freq[j].e = 1;
300 j++;
301 }
302 range->num_frequency = j;
303
Michael Buesch78ff56a2006-06-05 20:24:10 +0200304 bcm43xx_unlock_irqsafe(bcm, flags);
John W. Linvillef2223132006-01-23 16:59:58 -0500305
306 return 0;
307}
308
309static int bcm43xx_wx_set_nick(struct net_device *net_dev,
310 struct iw_request_info *info,
311 union iwreq_data *data,
312 char *extra)
313{
314 struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
John W. Linvillef2223132006-01-23 16:59:58 -0500315 size_t len;
316
Michael Buesch78ff56a2006-06-05 20:24:10 +0200317 bcm43xx_lock_noirq(bcm);
John W. Linvillef2223132006-01-23 16:59:58 -0500318 len = min((size_t)data->data.length, (size_t)IW_ESSID_MAX_SIZE);
319 memcpy(bcm->nick, extra, len);
320 bcm->nick[len] = '\0';
Michael Buesch78ff56a2006-06-05 20:24:10 +0200321 bcm43xx_unlock_noirq(bcm);
John W. Linvillef2223132006-01-23 16:59:58 -0500322
323 return 0;
324}
325
326static int bcm43xx_wx_get_nick(struct net_device *net_dev,
327 struct iw_request_info *info,
328 union iwreq_data *data,
329 char *extra)
330{
331 struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
John W. Linvillef2223132006-01-23 16:59:58 -0500332 size_t len;
333
Michael Buesch78ff56a2006-06-05 20:24:10 +0200334 bcm43xx_lock_noirq(bcm);
John W. Linvillef2223132006-01-23 16:59:58 -0500335 len = strlen(bcm->nick) + 1;
336 memcpy(extra, bcm->nick, len);
337 data->data.length = (__u16)len;
338 data->data.flags = 1;
Michael Buesch78ff56a2006-06-05 20:24:10 +0200339 bcm43xx_unlock_noirq(bcm);
John W. Linvillef2223132006-01-23 16:59:58 -0500340
341 return 0;
342}
343
344static int bcm43xx_wx_set_rts(struct net_device *net_dev,
345 struct iw_request_info *info,
346 union iwreq_data *data,
347 char *extra)
348{
349 struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
350 unsigned long flags;
351 int err = -EINVAL;
352
Michael Buesch78ff56a2006-06-05 20:24:10 +0200353 bcm43xx_lock_irqsafe(bcm, flags);
John W. Linvillef2223132006-01-23 16:59:58 -0500354 if (data->rts.disabled) {
355 bcm->rts_threshold = BCM43xx_MAX_RTS_THRESHOLD;
356 err = 0;
357 } else {
358 if (data->rts.value >= BCM43xx_MIN_RTS_THRESHOLD &&
359 data->rts.value <= BCM43xx_MAX_RTS_THRESHOLD) {
360 bcm->rts_threshold = data->rts.value;
361 err = 0;
362 }
363 }
Michael Buesch78ff56a2006-06-05 20:24:10 +0200364 bcm43xx_unlock_irqsafe(bcm, flags);
John W. Linvillef2223132006-01-23 16:59:58 -0500365
366 return err;
367}
368
369static int bcm43xx_wx_get_rts(struct net_device *net_dev,
370 struct iw_request_info *info,
371 union iwreq_data *data,
372 char *extra)
373{
374 struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
375 unsigned long flags;
376
Michael Buesch78ff56a2006-06-05 20:24:10 +0200377 bcm43xx_lock_irqsafe(bcm, flags);
John W. Linvillef2223132006-01-23 16:59:58 -0500378 data->rts.value = bcm->rts_threshold;
379 data->rts.fixed = 0;
380 data->rts.disabled = (bcm->rts_threshold == BCM43xx_MAX_RTS_THRESHOLD);
Michael Buesch78ff56a2006-06-05 20:24:10 +0200381 bcm43xx_unlock_irqsafe(bcm, flags);
John W. Linvillef2223132006-01-23 16:59:58 -0500382
383 return 0;
384}
385
386static int bcm43xx_wx_set_frag(struct net_device *net_dev,
387 struct iw_request_info *info,
388 union iwreq_data *data,
389 char *extra)
390{
391 struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
392 unsigned long flags;
393 int err = -EINVAL;
394
Michael Buesch78ff56a2006-06-05 20:24:10 +0200395 bcm43xx_lock_irqsafe(bcm, flags);
John W. Linvillef2223132006-01-23 16:59:58 -0500396 if (data->frag.disabled) {
397 bcm->ieee->fts = MAX_FRAG_THRESHOLD;
398 err = 0;
399 } else {
400 if (data->frag.value >= MIN_FRAG_THRESHOLD &&
401 data->frag.value <= MAX_FRAG_THRESHOLD) {
402 bcm->ieee->fts = data->frag.value & ~0x1;
403 err = 0;
404 }
405 }
Michael Buesch78ff56a2006-06-05 20:24:10 +0200406 bcm43xx_unlock_irqsafe(bcm, flags);
John W. Linvillef2223132006-01-23 16:59:58 -0500407
408 return err;
409}
410
411static int bcm43xx_wx_get_frag(struct net_device *net_dev,
412 struct iw_request_info *info,
413 union iwreq_data *data,
414 char *extra)
415{
416 struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
417 unsigned long flags;
418
Michael Buesch78ff56a2006-06-05 20:24:10 +0200419 bcm43xx_lock_irqsafe(bcm, flags);
John W. Linvillef2223132006-01-23 16:59:58 -0500420 data->frag.value = bcm->ieee->fts;
421 data->frag.fixed = 0;
422 data->frag.disabled = (bcm->ieee->fts == MAX_FRAG_THRESHOLD);
Michael Buesch78ff56a2006-06-05 20:24:10 +0200423 bcm43xx_unlock_irqsafe(bcm, flags);
John W. Linvillef2223132006-01-23 16:59:58 -0500424
425 return 0;
426}
427
428static int bcm43xx_wx_set_xmitpower(struct net_device *net_dev,
429 struct iw_request_info *info,
430 union iwreq_data *data,
431 char *extra)
432{
433 struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
Michael Buesch393344f2006-02-05 15:28:20 +0100434 struct bcm43xx_radioinfo *radio;
435 struct bcm43xx_phyinfo *phy;
John W. Linvillef2223132006-01-23 16:59:58 -0500436 unsigned long flags;
437 int err = -ENODEV;
Michael Buesch393344f2006-02-05 15:28:20 +0100438 u16 maxpower;
John W. Linvillef2223132006-01-23 16:59:58 -0500439
Michael Buesch393344f2006-02-05 15:28:20 +0100440 if ((data->txpower.flags & IW_TXPOW_TYPE) != IW_TXPOW_DBM) {
441 printk(PFX KERN_ERR "TX power not in dBm.\n");
442 return -EOPNOTSUPP;
443 }
444
Michael Buesch78ff56a2006-06-05 20:24:10 +0200445 bcm43xx_lock_irqsafe(bcm, flags);
446 if (bcm43xx_status(bcm) != BCM43xx_STAT_INITIALIZED)
John W. Linvillef2223132006-01-23 16:59:58 -0500447 goto out_unlock;
Michael Buesche9357c02006-03-13 19:27:34 +0100448 radio = bcm43xx_current_radio(bcm);
449 phy = bcm43xx_current_phy(bcm);
Michael Buesch393344f2006-02-05 15:28:20 +0100450 if (data->txpower.disabled != (!(radio->enabled))) {
451 if (data->txpower.disabled)
John W. Linvillef2223132006-01-23 16:59:58 -0500452 bcm43xx_radio_turn_off(bcm);
453 else
454 bcm43xx_radio_turn_on(bcm);
455 }
Michael Buesch393344f2006-02-05 15:28:20 +0100456 if (data->txpower.value > 0) {
457 /* desired and maxpower dBm values are in Q5.2 */
458 if (phy->type == BCM43xx_PHYTYPE_A)
459 maxpower = bcm->sprom.maxpower_aphy;
460 else
461 maxpower = bcm->sprom.maxpower_bgphy;
462 radio->txpower_desired = limit_value(data->txpower.value << 2,
463 0, maxpower);
464 bcm43xx_phy_xmitpower(bcm);
465 }
John W. Linvillef2223132006-01-23 16:59:58 -0500466 err = 0;
467
468out_unlock:
Michael Buesch78ff56a2006-06-05 20:24:10 +0200469 bcm43xx_unlock_irqsafe(bcm, flags);
John W. Linvillef2223132006-01-23 16:59:58 -0500470
471 return err;
472}
473
474static int bcm43xx_wx_get_xmitpower(struct net_device *net_dev,
475 struct iw_request_info *info,
476 union iwreq_data *data,
477 char *extra)
478{
479 struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
Michael Buesch393344f2006-02-05 15:28:20 +0100480 struct bcm43xx_radioinfo *radio;
John W. Linvillef2223132006-01-23 16:59:58 -0500481 unsigned long flags;
Michael Buesch393344f2006-02-05 15:28:20 +0100482 int err = -ENODEV;
John W. Linvillef2223132006-01-23 16:59:58 -0500483
Michael Buesch78ff56a2006-06-05 20:24:10 +0200484 bcm43xx_lock_irqsafe(bcm, flags);
485 if (bcm43xx_status(bcm) != BCM43xx_STAT_INITIALIZED)
Michael Buesch393344f2006-02-05 15:28:20 +0100486 goto out_unlock;
Michael Buesche9357c02006-03-13 19:27:34 +0100487 radio = bcm43xx_current_radio(bcm);
Michael Buesch393344f2006-02-05 15:28:20 +0100488 /* desired dBm value is in Q5.2 */
489 data->txpower.value = radio->txpower_desired >> 2;
490 data->txpower.fixed = 1;
491 data->txpower.flags = IW_TXPOW_DBM;
492 data->txpower.disabled = !(radio->enabled);
493
494 err = 0;
495out_unlock:
Michael Buesch78ff56a2006-06-05 20:24:10 +0200496 bcm43xx_unlock_irqsafe(bcm, flags);
John W. Linvillef2223132006-01-23 16:59:58 -0500497
Michael Buesch393344f2006-02-05 15:28:20 +0100498 return err;
John W. Linvillef2223132006-01-23 16:59:58 -0500499}
500
John W. Linvillef2223132006-01-23 16:59:58 -0500501static int bcm43xx_wx_set_encoding(struct net_device *net_dev,
502 struct iw_request_info *info,
503 union iwreq_data *data,
504 char *extra)
505{
506 struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
507 int err;
508
John W. Linvillef2223132006-01-23 16:59:58 -0500509 err = ieee80211_wx_set_encode(bcm->ieee, info, data, extra);
510
511 return err;
512}
513
514static int bcm43xx_wx_set_encodingext(struct net_device *net_dev,
515 struct iw_request_info *info,
516 union iwreq_data *data,
517 char *extra)
518{
519 struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
520 int err;
521
John W. Linvillef2223132006-01-23 16:59:58 -0500522 err = ieee80211_wx_set_encodeext(bcm->ieee, info, data, extra);
523
524 return err;
525}
526
527static int bcm43xx_wx_get_encoding(struct net_device *net_dev,
528 struct iw_request_info *info,
529 union iwreq_data *data,
530 char *extra)
531{
532 struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
533 int err;
534
John W. Linvillef2223132006-01-23 16:59:58 -0500535 err = ieee80211_wx_get_encode(bcm->ieee, info, data, extra);
536
537 return err;
538}
539
540static int bcm43xx_wx_get_encodingext(struct net_device *net_dev,
541 struct iw_request_info *info,
542 union iwreq_data *data,
543 char *extra)
544{
545 struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
546 int err;
547
John W. Linvillef2223132006-01-23 16:59:58 -0500548 err = ieee80211_wx_get_encodeext(bcm->ieee, info, data, extra);
549
550 return err;
551}
552
John W. Linvillef2223132006-01-23 16:59:58 -0500553static int bcm43xx_wx_set_interfmode(struct net_device *net_dev,
554 struct iw_request_info *info,
555 union iwreq_data *data,
556 char *extra)
557{
558 struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
559 unsigned long flags;
560 int mode, err = 0;
561
John W. Linvillef2223132006-01-23 16:59:58 -0500562 mode = *((int *)extra);
563 switch (mode) {
564 case 0:
565 mode = BCM43xx_RADIO_INTERFMODE_NONE;
566 break;
567 case 1:
568 mode = BCM43xx_RADIO_INTERFMODE_NONWLAN;
569 break;
570 case 2:
571 mode = BCM43xx_RADIO_INTERFMODE_MANUALWLAN;
572 break;
573 case 3:
574 mode = BCM43xx_RADIO_INTERFMODE_AUTOWLAN;
575 break;
576 default:
577 printk(KERN_ERR PFX "set_interfmode allowed parameters are: "
578 "0 => None, 1 => Non-WLAN, 2 => WLAN, "
579 "3 => Auto-WLAN\n");
580 return -EINVAL;
581 }
582
Michael Buesch78ff56a2006-06-05 20:24:10 +0200583 bcm43xx_lock_irqsafe(bcm, flags);
584 if (bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED) {
John W. Linvillef2223132006-01-23 16:59:58 -0500585 err = bcm43xx_radio_set_interference_mitigation(bcm, mode);
586 if (err) {
587 printk(KERN_ERR PFX "Interference Mitigation not "
588 "supported by device\n");
589 }
590 } else {
591 if (mode == BCM43xx_RADIO_INTERFMODE_AUTOWLAN) {
592 printk(KERN_ERR PFX "Interference Mitigation mode Auto-WLAN "
593 "not supported while the interface is down.\n");
594 err = -ENODEV;
595 } else
Michael Buesche9357c02006-03-13 19:27:34 +0100596 bcm43xx_current_radio(bcm)->interfmode = mode;
John W. Linvillef2223132006-01-23 16:59:58 -0500597 }
Michael Buesch78ff56a2006-06-05 20:24:10 +0200598 bcm43xx_unlock_irqsafe(bcm, flags);
John W. Linvillef2223132006-01-23 16:59:58 -0500599
600 return err;
601}
602
603static int bcm43xx_wx_get_interfmode(struct net_device *net_dev,
604 struct iw_request_info *info,
605 union iwreq_data *data,
606 char *extra)
607{
608 struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
609 unsigned long flags;
610 int mode;
611
Michael Buesch78ff56a2006-06-05 20:24:10 +0200612 bcm43xx_lock_irqsafe(bcm, flags);
Michael Buesche9357c02006-03-13 19:27:34 +0100613 mode = bcm43xx_current_radio(bcm)->interfmode;
Michael Buesch78ff56a2006-06-05 20:24:10 +0200614 bcm43xx_unlock_irqsafe(bcm, flags);
John W. Linvillef2223132006-01-23 16:59:58 -0500615
616 switch (mode) {
617 case BCM43xx_RADIO_INTERFMODE_NONE:
618 strncpy(extra, "0 (No Interference Mitigation)", MAX_WX_STRING);
619 break;
620 case BCM43xx_RADIO_INTERFMODE_NONWLAN:
621 strncpy(extra, "1 (Non-WLAN Interference Mitigation)", MAX_WX_STRING);
622 break;
623 case BCM43xx_RADIO_INTERFMODE_MANUALWLAN:
624 strncpy(extra, "2 (WLAN Interference Mitigation)", MAX_WX_STRING);
625 break;
626 default:
627 assert(0);
628 }
629 data->data.length = strlen(extra) + 1;
630
631 return 0;
632}
633
634static int bcm43xx_wx_set_shortpreamble(struct net_device *net_dev,
635 struct iw_request_info *info,
636 union iwreq_data *data,
637 char *extra)
638{
639 struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
640 unsigned long flags;
641 int on;
642
John W. Linvillef2223132006-01-23 16:59:58 -0500643 on = *((int *)extra);
Michael Buesch78ff56a2006-06-05 20:24:10 +0200644 bcm43xx_lock_irqsafe(bcm, flags);
John W. Linvillef2223132006-01-23 16:59:58 -0500645 bcm->short_preamble = !!on;
Michael Buesch78ff56a2006-06-05 20:24:10 +0200646 bcm43xx_unlock_irqsafe(bcm, flags);
John W. Linvillef2223132006-01-23 16:59:58 -0500647
648 return 0;
649}
650
651static int bcm43xx_wx_get_shortpreamble(struct net_device *net_dev,
652 struct iw_request_info *info,
653 union iwreq_data *data,
654 char *extra)
655{
656 struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
657 unsigned long flags;
658 int on;
659
Michael Buesch78ff56a2006-06-05 20:24:10 +0200660 bcm43xx_lock_irqsafe(bcm, flags);
John W. Linvillef2223132006-01-23 16:59:58 -0500661 on = bcm->short_preamble;
Michael Buesch78ff56a2006-06-05 20:24:10 +0200662 bcm43xx_unlock_irqsafe(bcm, flags);
John W. Linvillef2223132006-01-23 16:59:58 -0500663
664 if (on)
665 strncpy(extra, "1 (Short Preamble enabled)", MAX_WX_STRING);
666 else
667 strncpy(extra, "0 (Short Preamble disabled)", MAX_WX_STRING);
668 data->data.length = strlen(extra) + 1;
669
670 return 0;
671}
672
673static int bcm43xx_wx_set_swencryption(struct net_device *net_dev,
674 struct iw_request_info *info,
675 union iwreq_data *data,
676 char *extra)
677{
678 struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
679 unsigned long flags;
680 int on;
681
John W. Linvillef2223132006-01-23 16:59:58 -0500682 on = *((int *)extra);
Michael Bueschefccb642006-03-11 13:39:14 +0100683
Michael Buesch78ff56a2006-06-05 20:24:10 +0200684 bcm43xx_lock_irqsafe(bcm, flags);
John W. Linvillef2223132006-01-23 16:59:58 -0500685 bcm->ieee->host_encrypt = !!on;
686 bcm->ieee->host_decrypt = !!on;
687 bcm->ieee->host_build_iv = !on;
Michael Buesch78ff56a2006-06-05 20:24:10 +0200688 bcm43xx_unlock_irqsafe(bcm, flags);
Michael Bueschefccb642006-03-11 13:39:14 +0100689
John W. Linvillef2223132006-01-23 16:59:58 -0500690 return 0;
691}
692
693static int bcm43xx_wx_get_swencryption(struct net_device *net_dev,
694 struct iw_request_info *info,
695 union iwreq_data *data,
696 char *extra)
697{
698 struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
699 unsigned long flags;
700 int on;
Michael Bueschefccb642006-03-11 13:39:14 +0100701
Michael Buesch78ff56a2006-06-05 20:24:10 +0200702 bcm43xx_lock_irqsafe(bcm, flags);
John W. Linvillef2223132006-01-23 16:59:58 -0500703 on = bcm->ieee->host_encrypt;
Michael Buesch78ff56a2006-06-05 20:24:10 +0200704 bcm43xx_unlock_irqsafe(bcm, flags);
Michael Bueschefccb642006-03-11 13:39:14 +0100705
John W. Linvillef2223132006-01-23 16:59:58 -0500706 if (on)
707 strncpy(extra, "1 (SW encryption enabled) ", MAX_WX_STRING);
708 else
709 strncpy(extra, "0 (SW encryption disabled) ", MAX_WX_STRING);
710 data->data.length = strlen(extra + 1);
Michael Bueschefccb642006-03-11 13:39:14 +0100711
John W. Linvillef2223132006-01-23 16:59:58 -0500712 return 0;
713}
714
715/* Enough buffer to hold a hexdump of the sprom data. */
716#define SPROM_BUFFERSIZE 512
717
718static int sprom2hex(const u16 *sprom, char *dump)
719{
720 int i, pos = 0;
721
722 for (i = 0; i < BCM43xx_SPROM_SIZE; i++) {
723 pos += snprintf(dump + pos, SPROM_BUFFERSIZE - pos - 1,
724 "%04X", swab16(sprom[i]) & 0xFFFF);
725 }
726
727 return pos + 1;
728}
729
730static int hex2sprom(u16 *sprom, const char *dump, unsigned int len)
731{
732 char tmp[5] = { 0 };
733 int cnt = 0;
734 unsigned long parsed;
John W. Linvillef2223132006-01-23 16:59:58 -0500735
736 if (len < BCM43xx_SPROM_SIZE * sizeof(u16) * 2)
737 return -EINVAL;
738 while (cnt < BCM43xx_SPROM_SIZE) {
739 memcpy(tmp, dump, 4);
740 dump += 4;
741 parsed = simple_strtoul(tmp, NULL, 16);
742 sprom[cnt++] = swab16((u16)parsed);
743 }
744
John W. Linvillef2223132006-01-23 16:59:58 -0500745 return 0;
746}
747
748static int bcm43xx_wx_sprom_read(struct net_device *net_dev,
749 struct iw_request_info *info,
750 union iwreq_data *data,
751 char *extra)
752{
753 struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
Michael Bueschea0922b2006-02-19 14:09:20 +0100754 int err = -EPERM;
John W. Linvillef2223132006-01-23 16:59:58 -0500755 u16 *sprom;
756 unsigned long flags;
757
758 if (!capable(CAP_SYS_RAWIO))
759 goto out;
760
761 err = -ENOMEM;
762 sprom = kmalloc(BCM43xx_SPROM_SIZE * sizeof(*sprom),
763 GFP_KERNEL);
764 if (!sprom)
765 goto out;
766
Michael Buesch78ff56a2006-06-05 20:24:10 +0200767 bcm43xx_lock_irqsafe(bcm, flags);
John W. Linvillef2223132006-01-23 16:59:58 -0500768 err = -ENODEV;
Michael Buesch78ff56a2006-06-05 20:24:10 +0200769 if (bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED)
Michael Bueschefccb642006-03-11 13:39:14 +0100770 err = bcm43xx_sprom_read(bcm, sprom);
Michael Buesch78ff56a2006-06-05 20:24:10 +0200771 bcm43xx_unlock_irqsafe(bcm, flags);
Michael Bueschea0922b2006-02-19 14:09:20 +0100772 if (!err)
773 data->data.length = sprom2hex(sprom, extra);
John W. Linvillef2223132006-01-23 16:59:58 -0500774 kfree(sprom);
775out:
776 return err;
777}
778
779static int bcm43xx_wx_sprom_write(struct net_device *net_dev,
780 struct iw_request_info *info,
781 union iwreq_data *data,
782 char *extra)
783{
784 struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
785 int err = -EPERM;
786 u16 *sprom;
787 unsigned long flags;
788 char *input;
789 unsigned int len;
John W. Linvillef2223132006-01-23 16:59:58 -0500790
791 if (!capable(CAP_SYS_RAWIO))
792 goto out;
793
794 err = -ENOMEM;
795 sprom = kmalloc(BCM43xx_SPROM_SIZE * sizeof(*sprom),
796 GFP_KERNEL);
797 if (!sprom)
798 goto out;
799
800 len = data->data.length;
801 extra[len - 1] = '\0';
802 input = strchr(extra, ':');
803 if (input) {
804 input++;
805 len -= input - extra;
806 } else
807 input = extra;
808 err = hex2sprom(sprom, input, len);
809 if (err)
810 goto out_kfree;
811
Michael Buesch78ff56a2006-06-05 20:24:10 +0200812 bcm43xx_lock_irqsafe(bcm, flags);
John W. Linvillef2223132006-01-23 16:59:58 -0500813 err = -ENODEV;
Michael Buesch78ff56a2006-06-05 20:24:10 +0200814 if (bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED)
Michael Bueschefccb642006-03-11 13:39:14 +0100815 err = bcm43xx_sprom_write(bcm, sprom);
Michael Buesch78ff56a2006-06-05 20:24:10 +0200816 bcm43xx_unlock_irqsafe(bcm, flags);
John W. Linvillef2223132006-01-23 16:59:58 -0500817out_kfree:
818 kfree(sprom);
819out:
820 return err;
821}
822
Michael Buesch72fb8512006-03-22 18:10:19 +0100823/* Get wireless statistics. Called by /proc/net/wireless and by SIOCGIWSTATS */
824
825static struct iw_statistics *bcm43xx_get_wireless_stats(struct net_device *net_dev)
826{
827 struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
828 struct ieee80211softmac_device *mac = ieee80211_priv(net_dev);
829 struct iw_statistics *wstats;
830
831 wstats = &bcm->stats.wstats;
832 if (!mac->associated) {
833 wstats->miss.beacon = 0;
834// bcm->ieee->ieee_stats.tx_retry_limit_exceeded = 0; // FIXME: should this be cleared here?
835 wstats->discard.retries = 0;
836// bcm->ieee->ieee_stats.tx_discards_wrong_sa = 0; // FIXME: same question
837 wstats->discard.nwid = 0;
838// bcm->ieee->ieee_stats.rx_discards_undecryptable = 0; // FIXME: ditto
839 wstats->discard.code = 0;
840// bcm->ieee->ieee_stats.rx_fragments = 0; // FIXME: same here
841 wstats->discard.fragment = 0;
842 wstats->discard.misc = 0;
843 wstats->qual.qual = 0;
844 wstats->qual.level = 0;
845 wstats->qual.noise = 0;
846 wstats->qual.updated = 7;
847 wstats->qual.updated |= IW_QUAL_NOISE_INVALID |
848 IW_QUAL_QUAL_INVALID | IW_QUAL_LEVEL_INVALID;
849 return wstats;
850 }
851 /* fill in the real statistics when iface associated */
852 wstats->qual.qual = 100; // TODO: get the real signal quality
853 wstats->qual.level = 3 - bcm->stats.link_quality;
854 wstats->qual.noise = bcm->stats.noise;
855 wstats->qual.updated = IW_QUAL_QUAL_UPDATED | IW_QUAL_LEVEL_UPDATED |
856 IW_QUAL_NOISE_UPDATED;
857 wstats->discard.code = bcm->ieee->ieee_stats.rx_discards_undecryptable;
858 wstats->discard.retries = bcm->ieee->ieee_stats.tx_retry_limit_exceeded;
859 wstats->discard.nwid = bcm->ieee->ieee_stats.tx_discards_wrong_sa;
860 wstats->discard.fragment = bcm->ieee->ieee_stats.rx_fragments;
861 wstats->discard.misc = 0; // FIXME
862 wstats->miss.beacon = 0; // FIXME
863 return wstats;
864}
865
John W. Linvillef2223132006-01-23 16:59:58 -0500866
867#ifdef WX
868# undef WX
869#endif
870#define WX(ioctl) [(ioctl) - SIOCSIWCOMMIT]
871static const iw_handler bcm43xx_wx_handlers[] = {
872 /* Wireless Identification */
873 WX(SIOCGIWNAME) = bcm43xx_wx_get_name,
874 /* Basic operations */
875 WX(SIOCSIWFREQ) = bcm43xx_wx_set_channelfreq,
876 WX(SIOCGIWFREQ) = bcm43xx_wx_get_channelfreq,
877 WX(SIOCSIWMODE) = bcm43xx_wx_set_mode,
878 WX(SIOCGIWMODE) = bcm43xx_wx_get_mode,
879 /* Informative stuff */
880 WX(SIOCGIWRANGE) = bcm43xx_wx_get_rangeparams,
881 /* Access Point manipulation */
882 WX(SIOCSIWAP) = ieee80211softmac_wx_set_wap,
883 WX(SIOCGIWAP) = ieee80211softmac_wx_get_wap,
884 WX(SIOCSIWSCAN) = ieee80211softmac_wx_trigger_scan,
885 WX(SIOCGIWSCAN) = ieee80211softmac_wx_get_scan_results,
886 /* 802.11 specific support */
887 WX(SIOCSIWESSID) = ieee80211softmac_wx_set_essid,
888 WX(SIOCGIWESSID) = ieee80211softmac_wx_get_essid,
889 WX(SIOCSIWNICKN) = bcm43xx_wx_set_nick,
890 WX(SIOCGIWNICKN) = bcm43xx_wx_get_nick,
891 /* Other parameters */
892 WX(SIOCSIWRATE) = ieee80211softmac_wx_set_rate,
893 WX(SIOCGIWRATE) = ieee80211softmac_wx_get_rate,
894 WX(SIOCSIWRTS) = bcm43xx_wx_set_rts,
895 WX(SIOCGIWRTS) = bcm43xx_wx_get_rts,
896 WX(SIOCSIWFRAG) = bcm43xx_wx_set_frag,
897 WX(SIOCGIWFRAG) = bcm43xx_wx_get_frag,
898 WX(SIOCSIWTXPOW) = bcm43xx_wx_set_xmitpower,
899 WX(SIOCGIWTXPOW) = bcm43xx_wx_get_xmitpower,
900//TODO WX(SIOCSIWRETRY) = bcm43xx_wx_set_retry,
901//TODO WX(SIOCGIWRETRY) = bcm43xx_wx_get_retry,
902 /* Encoding */
903 WX(SIOCSIWENCODE) = bcm43xx_wx_set_encoding,
904 WX(SIOCGIWENCODE) = bcm43xx_wx_get_encoding,
905 WX(SIOCSIWENCODEEXT) = bcm43xx_wx_set_encodingext,
906 WX(SIOCGIWENCODEEXT) = bcm43xx_wx_get_encodingext,
907 /* Power saving */
908//TODO WX(SIOCSIWPOWER) = bcm43xx_wx_set_power,
909//TODO WX(SIOCGIWPOWER) = bcm43xx_wx_get_power,
910 WX(SIOCSIWGENIE) = ieee80211softmac_wx_set_genie,
911 WX(SIOCGIWGENIE) = ieee80211softmac_wx_get_genie,
912 WX(SIOCSIWAUTH) = ieee80211_wx_set_auth,
913 WX(SIOCGIWAUTH) = ieee80211_wx_get_auth,
914};
915#undef WX
916
917static const iw_handler bcm43xx_priv_wx_handlers[] = {
918 /* Set Interference Mitigation Mode. */
919 bcm43xx_wx_set_interfmode,
920 /* Get Interference Mitigation Mode. */
921 bcm43xx_wx_get_interfmode,
922 /* Enable/Disable Short Preamble mode. */
923 bcm43xx_wx_set_shortpreamble,
924 /* Get Short Preamble mode. */
925 bcm43xx_wx_get_shortpreamble,
926 /* Enable/Disable Software Encryption mode */
927 bcm43xx_wx_set_swencryption,
928 /* Get Software Encryption mode */
929 bcm43xx_wx_get_swencryption,
930 /* Write SRPROM data. */
931 bcm43xx_wx_sprom_write,
932 /* Read SPROM data. */
933 bcm43xx_wx_sprom_read,
934};
935
936#define PRIV_WX_SET_INTERFMODE (SIOCIWFIRSTPRIV + 0)
937#define PRIV_WX_GET_INTERFMODE (SIOCIWFIRSTPRIV + 1)
938#define PRIV_WX_SET_SHORTPREAMBLE (SIOCIWFIRSTPRIV + 2)
939#define PRIV_WX_GET_SHORTPREAMBLE (SIOCIWFIRSTPRIV + 3)
940#define PRIV_WX_SET_SWENCRYPTION (SIOCIWFIRSTPRIV + 4)
941#define PRIV_WX_GET_SWENCRYPTION (SIOCIWFIRSTPRIV + 5)
942#define PRIV_WX_SPROM_WRITE (SIOCIWFIRSTPRIV + 6)
943#define PRIV_WX_SPROM_READ (SIOCIWFIRSTPRIV + 7)
944
945#define PRIV_WX_DUMMY(ioctl) \
946 { \
947 .cmd = (ioctl), \
948 .name = "__unused" \
949 }
950
951static const struct iw_priv_args bcm43xx_priv_wx_args[] = {
952 {
953 .cmd = PRIV_WX_SET_INTERFMODE,
954 .set_args = IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
955 .name = "set_interfmode",
956 },
957 {
958 .cmd = PRIV_WX_GET_INTERFMODE,
959 .get_args = IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | MAX_WX_STRING,
960 .name = "get_interfmode",
961 },
962 {
963 .cmd = PRIV_WX_SET_SHORTPREAMBLE,
964 .set_args = IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
Erik Mouwa3921492006-04-13 15:02:27 +0200965 .name = "set_shortpreamb",
John W. Linvillef2223132006-01-23 16:59:58 -0500966 },
967 {
968 .cmd = PRIV_WX_GET_SHORTPREAMBLE,
969 .get_args = IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | MAX_WX_STRING,
Erik Mouwa3921492006-04-13 15:02:27 +0200970 .name = "get_shortpreamb",
John W. Linvillef2223132006-01-23 16:59:58 -0500971 },
972 {
973 .cmd = PRIV_WX_SET_SWENCRYPTION,
974 .set_args = IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
Erik Mouwa3921492006-04-13 15:02:27 +0200975 .name = "set_swencrypt",
John W. Linvillef2223132006-01-23 16:59:58 -0500976 },
977 {
978 .cmd = PRIV_WX_GET_SWENCRYPTION,
979 .get_args = IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | MAX_WX_STRING,
Erik Mouwa3921492006-04-13 15:02:27 +0200980 .name = "get_swencrypt",
John W. Linvillef2223132006-01-23 16:59:58 -0500981 },
982 {
983 .cmd = PRIV_WX_SPROM_WRITE,
984 .set_args = IW_PRIV_TYPE_CHAR | SPROM_BUFFERSIZE,
985 .name = "write_sprom",
986 },
987 {
988 .cmd = PRIV_WX_SPROM_READ,
989 .get_args = IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | SPROM_BUFFERSIZE,
990 .name = "read_sprom",
991 },
992};
993
994const struct iw_handler_def bcm43xx_wx_handlers_def = {
995 .standard = bcm43xx_wx_handlers,
996 .num_standard = ARRAY_SIZE(bcm43xx_wx_handlers),
997 .num_private = ARRAY_SIZE(bcm43xx_priv_wx_handlers),
998 .num_private_args = ARRAY_SIZE(bcm43xx_priv_wx_args),
999 .private = bcm43xx_priv_wx_handlers,
1000 .private_args = bcm43xx_priv_wx_args,
Michael Buesch72fb8512006-03-22 18:10:19 +01001001 .get_wireless_stats = bcm43xx_get_wireless_stats,
John W. Linvillef2223132006-01-23 16:59:58 -05001002};