3 Broadcom BCM43xx wireless driver
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>
11 Some parts of the code in this file are derived from the ipw2200
12 driver Copyright(c) 2003 - 2004 Intel Corporation.
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.
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.
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.
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>
40 #include "bcm43xx_wx.h"
41 #include "bcm43xx_main.h"
42 #include "bcm43xx_radio.h"
43 #include "bcm43xx_phy.h"
46 /* The WIRELESS_EXT version, which is implemented by this driver. */
47 #define BCM43xx_WX_VERSION 18
49 #define MAX_WX_STRING 80
52 static int bcm43xx_wx_get_name(struct net_device *net_dev,
53 struct iw_request_info *info,
54 union iwreq_data *data,
57 struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
59 struct bcm43xx_phyinfo *phy;
60 char suffix[7] = { 0 };
61 int have_a = 0, have_b = 0, have_g = 0;
63 mutex_lock(&bcm->mutex);
64 for (i = 0; i < bcm->nr_80211_available; i++) {
65 phy = &(bcm->core_80211_ext[i].phy);
67 case BCM43xx_PHYTYPE_A:
70 case BCM43xx_PHYTYPE_G:
72 case BCM43xx_PHYTYPE_B:
79 mutex_unlock(&bcm->mutex);
97 snprintf(data->name, IFNAMSIZ, "IEEE 802.11%s", suffix);
102 static int bcm43xx_wx_set_channelfreq(struct net_device *net_dev,
103 struct iw_request_info *info,
104 union iwreq_data *data,
107 struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
113 mutex_lock(&bcm->mutex);
114 spin_lock_irqsave(&bcm->irq_lock, flags);
116 if ((data->freq.m >= 0) && (data->freq.m <= 1000)) {
117 channel = data->freq.m;
118 freq = bcm43xx_channel_to_freq(bcm, channel);
120 channel = bcm43xx_freq_to_channel(bcm, data->freq.m);
123 if (!ieee80211_is_valid_channel(bcm->ieee, channel))
125 if (bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED) {
126 //ieee80211softmac_disassoc(softmac, $REASON);
127 bcm43xx_mac_suspend(bcm);
128 err = bcm43xx_radio_selectchannel(bcm, channel, 0);
129 bcm43xx_mac_enable(bcm);
131 bcm43xx_current_radio(bcm)->initial_channel = channel;
135 spin_unlock_irqrestore(&bcm->irq_lock, flags);
136 mutex_unlock(&bcm->mutex);
141 static int bcm43xx_wx_get_channelfreq(struct net_device *net_dev,
142 struct iw_request_info *info,
143 union iwreq_data *data,
146 struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
147 struct bcm43xx_radioinfo *radio;
151 mutex_lock(&bcm->mutex);
152 radio = bcm43xx_current_radio(bcm);
153 channel = radio->channel;
154 if (channel == 0xFF) {
155 channel = radio->initial_channel;
159 assert(channel > 0 && channel <= 1000);
161 data->freq.m = bcm43xx_channel_to_freq(bcm, channel) * 100000;
162 data->freq.flags = 1;
166 mutex_unlock(&bcm->mutex);
171 static int bcm43xx_wx_set_mode(struct net_device *net_dev,
172 struct iw_request_info *info,
173 union iwreq_data *data,
176 struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
181 if (mode == IW_MODE_AUTO)
182 mode = BCM43xx_INITIAL_IWMODE;
184 mutex_lock(&bcm->mutex);
185 spin_lock_irqsave(&bcm->irq_lock, flags);
186 if (bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED) {
187 if (bcm->ieee->iw_mode != mode)
188 bcm43xx_set_iwmode(bcm, mode);
190 bcm->ieee->iw_mode = mode;
191 spin_unlock_irqrestore(&bcm->irq_lock, flags);
192 mutex_unlock(&bcm->mutex);
197 static int bcm43xx_wx_get_mode(struct net_device *net_dev,
198 struct iw_request_info *info,
199 union iwreq_data *data,
202 struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
204 mutex_lock(&bcm->mutex);
205 data->mode = bcm->ieee->iw_mode;
206 mutex_unlock(&bcm->mutex);
211 static int bcm43xx_wx_get_rangeparams(struct net_device *net_dev,
212 struct iw_request_info *info,
213 union iwreq_data *data,
216 struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
217 struct iw_range *range = (struct iw_range *)extra;
218 const struct ieee80211_geo *geo;
220 struct bcm43xx_phyinfo *phy;
222 data->data.length = sizeof(*range);
223 memset(range, 0, sizeof(*range));
225 //TODO: What about 802.11b?
226 /* 54Mb/s == ~27Mb/s payload throughput (802.11g) */
227 range->throughput = 27 * 1000 * 1000;
229 range->max_qual.qual = 100;
230 /* TODO: Real max RSSI */
231 range->max_qual.level = 3;
232 range->max_qual.noise = 100;
233 range->max_qual.updated = 7;
235 range->avg_qual.qual = 70;
236 range->avg_qual.level = 2;
237 range->avg_qual.noise = 40;
238 range->avg_qual.updated = 7;
240 range->min_rts = BCM43xx_MIN_RTS_THRESHOLD;
241 range->max_rts = BCM43xx_MAX_RTS_THRESHOLD;
242 range->min_frag = MIN_FRAG_THRESHOLD;
243 range->max_frag = MAX_FRAG_THRESHOLD;
245 range->encoding_size[0] = 5;
246 range->encoding_size[1] = 13;
247 range->num_encoding_sizes = 2;
248 range->max_encoding_tokens = WEP_KEYS;
250 range->we_version_compiled = WIRELESS_EXT;
251 range->we_version_source = BCM43xx_WX_VERSION;
253 range->enc_capa = IW_ENC_CAPA_WPA |
255 IW_ENC_CAPA_CIPHER_TKIP |
256 IW_ENC_CAPA_CIPHER_CCMP;
258 mutex_lock(&bcm->mutex);
259 phy = bcm43xx_current_phy(bcm);
261 range->num_bitrates = 0;
263 if (phy->type == BCM43xx_PHYTYPE_A ||
264 phy->type == BCM43xx_PHYTYPE_G) {
265 range->num_bitrates = 8;
266 range->bitrate[i++] = IEEE80211_OFDM_RATE_6MB;
267 range->bitrate[i++] = IEEE80211_OFDM_RATE_9MB;
268 range->bitrate[i++] = IEEE80211_OFDM_RATE_12MB;
269 range->bitrate[i++] = IEEE80211_OFDM_RATE_18MB;
270 range->bitrate[i++] = IEEE80211_OFDM_RATE_24MB;
271 range->bitrate[i++] = IEEE80211_OFDM_RATE_36MB;
272 range->bitrate[i++] = IEEE80211_OFDM_RATE_48MB;
273 range->bitrate[i++] = IEEE80211_OFDM_RATE_54MB;
275 if (phy->type == BCM43xx_PHYTYPE_B ||
276 phy->type == BCM43xx_PHYTYPE_G) {
277 range->num_bitrates += 4;
278 range->bitrate[i++] = IEEE80211_CCK_RATE_1MB;
279 range->bitrate[i++] = IEEE80211_CCK_RATE_2MB;
280 range->bitrate[i++] = IEEE80211_CCK_RATE_5MB;
281 range->bitrate[i++] = IEEE80211_CCK_RATE_11MB;
284 geo = ieee80211_get_geo(bcm->ieee);
285 range->num_channels = geo->a_channels + geo->bg_channels;
287 for (i = 0; i < geo->a_channels; i++) {
288 if (j == IW_MAX_FREQUENCIES)
290 range->freq[j].i = j + 1;
291 range->freq[j].m = geo->a[i].freq;//FIXME?
292 range->freq[j].e = 1;
295 for (i = 0; i < geo->bg_channels; i++) {
296 if (j == IW_MAX_FREQUENCIES)
298 range->freq[j].i = j + 1;
299 range->freq[j].m = geo->bg[i].freq;//FIXME?
300 range->freq[j].e = 1;
303 range->num_frequency = j;
305 mutex_unlock(&bcm->mutex);
310 static int bcm43xx_wx_set_nick(struct net_device *net_dev,
311 struct iw_request_info *info,
312 union iwreq_data *data,
315 struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
318 mutex_lock(&bcm->mutex);
319 len = min((size_t)data->data.length, (size_t)IW_ESSID_MAX_SIZE);
320 memcpy(bcm->nick, extra, len);
321 bcm->nick[len] = '\0';
322 mutex_unlock(&bcm->mutex);
327 static int bcm43xx_wx_get_nick(struct net_device *net_dev,
328 struct iw_request_info *info,
329 union iwreq_data *data,
332 struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
335 mutex_lock(&bcm->mutex);
336 len = strlen(bcm->nick) + 1;
337 memcpy(extra, bcm->nick, len);
338 data->data.length = (__u16)len;
339 data->data.flags = 1;
340 mutex_unlock(&bcm->mutex);
345 static int bcm43xx_wx_set_rts(struct net_device *net_dev,
346 struct iw_request_info *info,
347 union iwreq_data *data,
350 struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
354 mutex_lock(&bcm->mutex);
355 spin_lock_irqsave(&bcm->irq_lock, flags);
356 if (data->rts.disabled) {
357 bcm->rts_threshold = BCM43xx_MAX_RTS_THRESHOLD;
360 if (data->rts.value >= BCM43xx_MIN_RTS_THRESHOLD &&
361 data->rts.value <= BCM43xx_MAX_RTS_THRESHOLD) {
362 bcm->rts_threshold = data->rts.value;
366 spin_unlock_irqrestore(&bcm->irq_lock, flags);
367 mutex_unlock(&bcm->mutex);
372 static int bcm43xx_wx_get_rts(struct net_device *net_dev,
373 struct iw_request_info *info,
374 union iwreq_data *data,
377 struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
379 mutex_lock(&bcm->mutex);
380 data->rts.value = bcm->rts_threshold;
382 data->rts.disabled = (bcm->rts_threshold == BCM43xx_MAX_RTS_THRESHOLD);
383 mutex_unlock(&bcm->mutex);
388 static int bcm43xx_wx_set_frag(struct net_device *net_dev,
389 struct iw_request_info *info,
390 union iwreq_data *data,
393 struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
397 mutex_lock(&bcm->mutex);
398 spin_lock_irqsave(&bcm->irq_lock, flags);
399 if (data->frag.disabled) {
400 bcm->ieee->fts = MAX_FRAG_THRESHOLD;
403 if (data->frag.value >= MIN_FRAG_THRESHOLD &&
404 data->frag.value <= MAX_FRAG_THRESHOLD) {
405 bcm->ieee->fts = data->frag.value & ~0x1;
409 spin_unlock_irqrestore(&bcm->irq_lock, flags);
410 mutex_unlock(&bcm->mutex);
415 static int bcm43xx_wx_get_frag(struct net_device *net_dev,
416 struct iw_request_info *info,
417 union iwreq_data *data,
420 struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
422 mutex_lock(&bcm->mutex);
423 data->frag.value = bcm->ieee->fts;
424 data->frag.fixed = 0;
425 data->frag.disabled = (bcm->ieee->fts == MAX_FRAG_THRESHOLD);
426 mutex_unlock(&bcm->mutex);
431 static int bcm43xx_wx_set_xmitpower(struct net_device *net_dev,
432 struct iw_request_info *info,
433 union iwreq_data *data,
436 struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
437 struct bcm43xx_radioinfo *radio;
438 struct bcm43xx_phyinfo *phy;
443 if ((data->txpower.flags & IW_TXPOW_TYPE) != IW_TXPOW_DBM) {
444 printk(PFX KERN_ERR "TX power not in dBm.\n");
448 mutex_lock(&bcm->mutex);
449 spin_lock_irqsave(&bcm->irq_lock, flags);
450 if (bcm43xx_status(bcm) != BCM43xx_STAT_INITIALIZED)
452 radio = bcm43xx_current_radio(bcm);
453 phy = bcm43xx_current_phy(bcm);
454 if (data->txpower.disabled != (!(radio->enabled))) {
455 if (data->txpower.disabled)
456 bcm43xx_radio_turn_off(bcm);
458 bcm43xx_radio_turn_on(bcm);
460 if (data->txpower.value > 0) {
461 /* desired and maxpower dBm values are in Q5.2 */
462 if (phy->type == BCM43xx_PHYTYPE_A)
463 maxpower = bcm->sprom.maxpower_aphy;
465 maxpower = bcm->sprom.maxpower_bgphy;
466 radio->txpower_desired = limit_value(data->txpower.value << 2,
468 bcm43xx_phy_xmitpower(bcm);
473 spin_unlock_irqrestore(&bcm->irq_lock, flags);
474 mutex_unlock(&bcm->mutex);
479 static int bcm43xx_wx_get_xmitpower(struct net_device *net_dev,
480 struct iw_request_info *info,
481 union iwreq_data *data,
484 struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
485 struct bcm43xx_radioinfo *radio;
488 mutex_lock(&bcm->mutex);
489 if (bcm43xx_status(bcm) != BCM43xx_STAT_INITIALIZED)
491 radio = bcm43xx_current_radio(bcm);
492 /* desired dBm value is in Q5.2 */
493 data->txpower.value = radio->txpower_desired >> 2;
494 data->txpower.fixed = 1;
495 data->txpower.flags = IW_TXPOW_DBM;
496 data->txpower.disabled = !(radio->enabled);
500 mutex_unlock(&bcm->mutex);
505 static int bcm43xx_wx_set_encoding(struct net_device *net_dev,
506 struct iw_request_info *info,
507 union iwreq_data *data,
510 struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
513 err = ieee80211_wx_set_encode(bcm->ieee, info, data, extra);
518 static int bcm43xx_wx_set_encodingext(struct net_device *net_dev,
519 struct iw_request_info *info,
520 union iwreq_data *data,
523 struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
526 err = ieee80211_wx_set_encodeext(bcm->ieee, info, data, extra);
531 static int bcm43xx_wx_get_encoding(struct net_device *net_dev,
532 struct iw_request_info *info,
533 union iwreq_data *data,
536 struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
539 err = ieee80211_wx_get_encode(bcm->ieee, info, data, extra);
544 static int bcm43xx_wx_get_encodingext(struct net_device *net_dev,
545 struct iw_request_info *info,
546 union iwreq_data *data,
549 struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
552 err = ieee80211_wx_get_encodeext(bcm->ieee, info, data, extra);
557 static int bcm43xx_wx_set_interfmode(struct net_device *net_dev,
558 struct iw_request_info *info,
559 union iwreq_data *data,
562 struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
566 mode = *((int *)extra);
569 mode = BCM43xx_RADIO_INTERFMODE_NONE;
572 mode = BCM43xx_RADIO_INTERFMODE_NONWLAN;
575 mode = BCM43xx_RADIO_INTERFMODE_MANUALWLAN;
578 mode = BCM43xx_RADIO_INTERFMODE_AUTOWLAN;
581 printk(KERN_ERR PFX "set_interfmode allowed parameters are: "
582 "0 => None, 1 => Non-WLAN, 2 => WLAN, "
587 mutex_lock(&bcm->mutex);
588 spin_lock_irqsave(&bcm->irq_lock, flags);
589 if (bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED) {
590 err = bcm43xx_radio_set_interference_mitigation(bcm, mode);
592 printk(KERN_ERR PFX "Interference Mitigation not "
593 "supported by device\n");
596 if (mode == BCM43xx_RADIO_INTERFMODE_AUTOWLAN) {
597 printk(KERN_ERR PFX "Interference Mitigation mode Auto-WLAN "
598 "not supported while the interface is down.\n");
601 bcm43xx_current_radio(bcm)->interfmode = mode;
603 spin_unlock_irqrestore(&bcm->irq_lock, flags);
604 mutex_unlock(&bcm->mutex);
609 static int bcm43xx_wx_get_interfmode(struct net_device *net_dev,
610 struct iw_request_info *info,
611 union iwreq_data *data,
614 struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
617 mutex_lock(&bcm->mutex);
618 mode = bcm43xx_current_radio(bcm)->interfmode;
619 mutex_unlock(&bcm->mutex);
622 case BCM43xx_RADIO_INTERFMODE_NONE:
623 strncpy(extra, "0 (No Interference Mitigation)", MAX_WX_STRING);
625 case BCM43xx_RADIO_INTERFMODE_NONWLAN:
626 strncpy(extra, "1 (Non-WLAN Interference Mitigation)", MAX_WX_STRING);
628 case BCM43xx_RADIO_INTERFMODE_MANUALWLAN:
629 strncpy(extra, "2 (WLAN Interference Mitigation)", MAX_WX_STRING);
634 data->data.length = strlen(extra) + 1;
639 static int bcm43xx_wx_set_shortpreamble(struct net_device *net_dev,
640 struct iw_request_info *info,
641 union iwreq_data *data,
644 struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
648 on = *((int *)extra);
649 mutex_lock(&bcm->mutex);
650 spin_lock_irqsave(&bcm->irq_lock, flags);
651 bcm->short_preamble = !!on;
652 spin_unlock_irqrestore(&bcm->irq_lock, flags);
653 mutex_unlock(&bcm->mutex);
658 static int bcm43xx_wx_get_shortpreamble(struct net_device *net_dev,
659 struct iw_request_info *info,
660 union iwreq_data *data,
663 struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
666 mutex_lock(&bcm->mutex);
667 on = bcm->short_preamble;
668 mutex_unlock(&bcm->mutex);
671 strncpy(extra, "1 (Short Preamble enabled)", MAX_WX_STRING);
673 strncpy(extra, "0 (Short Preamble disabled)", MAX_WX_STRING);
674 data->data.length = strlen(extra) + 1;
679 static int bcm43xx_wx_set_swencryption(struct net_device *net_dev,
680 struct iw_request_info *info,
681 union iwreq_data *data,
684 struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
688 on = *((int *)extra);
690 mutex_lock(&bcm->mutex);
691 spin_lock_irqsave(&bcm->irq_lock, flags);
692 bcm->ieee->host_encrypt = !!on;
693 bcm->ieee->host_decrypt = !!on;
694 bcm->ieee->host_build_iv = !on;
695 spin_unlock_irqrestore(&bcm->irq_lock, flags);
696 mutex_unlock(&bcm->mutex);
701 static int bcm43xx_wx_get_swencryption(struct net_device *net_dev,
702 struct iw_request_info *info,
703 union iwreq_data *data,
706 struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
709 mutex_lock(&bcm->mutex);
710 on = bcm->ieee->host_encrypt;
711 mutex_unlock(&bcm->mutex);
714 strncpy(extra, "1 (SW encryption enabled) ", MAX_WX_STRING);
716 strncpy(extra, "0 (SW encryption disabled) ", MAX_WX_STRING);
717 data->data.length = strlen(extra + 1);
722 /* Enough buffer to hold a hexdump of the sprom data. */
723 #define SPROM_BUFFERSIZE 512
725 static int sprom2hex(const u16 *sprom, char *dump)
729 for (i = 0; i < BCM43xx_SPROM_SIZE; i++) {
730 pos += snprintf(dump + pos, SPROM_BUFFERSIZE - pos - 1,
731 "%04X", swab16(sprom[i]) & 0xFFFF);
737 static int hex2sprom(u16 *sprom, const char *dump, unsigned int len)
741 unsigned long parsed;
743 if (len < BCM43xx_SPROM_SIZE * sizeof(u16) * 2)
745 while (cnt < BCM43xx_SPROM_SIZE) {
746 memcpy(tmp, dump, 4);
748 parsed = simple_strtoul(tmp, NULL, 16);
749 sprom[cnt++] = swab16((u16)parsed);
755 static int bcm43xx_wx_sprom_read(struct net_device *net_dev,
756 struct iw_request_info *info,
757 union iwreq_data *data,
760 struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
765 if (!capable(CAP_SYS_RAWIO))
769 sprom = kmalloc(BCM43xx_SPROM_SIZE * sizeof(*sprom),
774 mutex_lock(&bcm->mutex);
775 spin_lock_irqsave(&bcm->irq_lock, flags);
777 if (bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED)
778 err = bcm43xx_sprom_read(bcm, sprom);
779 spin_unlock_irqrestore(&bcm->irq_lock, flags);
780 mutex_unlock(&bcm->mutex);
782 data->data.length = sprom2hex(sprom, extra);
788 static int bcm43xx_wx_sprom_write(struct net_device *net_dev,
789 struct iw_request_info *info,
790 union iwreq_data *data,
793 struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
800 if (!capable(CAP_SYS_RAWIO))
804 sprom = kmalloc(BCM43xx_SPROM_SIZE * sizeof(*sprom),
809 len = data->data.length;
810 extra[len - 1] = '\0';
811 input = strchr(extra, ':');
814 len -= input - extra;
817 err = hex2sprom(sprom, input, len);
821 mutex_lock(&bcm->mutex);
822 spin_lock_irqsave(&bcm->irq_lock, flags);
823 spin_lock(&bcm->leds_lock);
825 if (bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED)
826 err = bcm43xx_sprom_write(bcm, sprom);
827 spin_unlock(&bcm->leds_lock);
828 spin_unlock_irqrestore(&bcm->irq_lock, flags);
829 mutex_unlock(&bcm->mutex);
836 /* Get wireless statistics. Called by /proc/net/wireless and by SIOCGIWSTATS */
838 static struct iw_statistics *bcm43xx_get_wireless_stats(struct net_device *net_dev)
840 struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
841 struct ieee80211softmac_device *mac = ieee80211_priv(net_dev);
842 struct iw_statistics *wstats;
844 wstats = &bcm->stats.wstats;
845 if (!mac->associated) {
846 wstats->miss.beacon = 0;
847 // bcm->ieee->ieee_stats.tx_retry_limit_exceeded = 0; // FIXME: should this be cleared here?
848 wstats->discard.retries = 0;
849 // bcm->ieee->ieee_stats.tx_discards_wrong_sa = 0; // FIXME: same question
850 wstats->discard.nwid = 0;
851 // bcm->ieee->ieee_stats.rx_discards_undecryptable = 0; // FIXME: ditto
852 wstats->discard.code = 0;
853 // bcm->ieee->ieee_stats.rx_fragments = 0; // FIXME: same here
854 wstats->discard.fragment = 0;
855 wstats->discard.misc = 0;
856 wstats->qual.qual = 0;
857 wstats->qual.level = 0;
858 wstats->qual.noise = 0;
859 wstats->qual.updated = 7;
860 wstats->qual.updated |= IW_QUAL_NOISE_INVALID |
861 IW_QUAL_QUAL_INVALID | IW_QUAL_LEVEL_INVALID;
864 /* fill in the real statistics when iface associated */
865 wstats->qual.qual = 100; // TODO: get the real signal quality
866 wstats->qual.level = 3 - bcm->stats.link_quality;
867 wstats->qual.noise = bcm->stats.noise;
868 wstats->qual.updated = IW_QUAL_QUAL_UPDATED | IW_QUAL_LEVEL_UPDATED |
869 IW_QUAL_NOISE_UPDATED;
870 wstats->discard.code = bcm->ieee->ieee_stats.rx_discards_undecryptable;
871 wstats->discard.retries = bcm->ieee->ieee_stats.tx_retry_limit_exceeded;
872 wstats->discard.nwid = bcm->ieee->ieee_stats.tx_discards_wrong_sa;
873 wstats->discard.fragment = bcm->ieee->ieee_stats.rx_fragments;
874 wstats->discard.misc = 0; // FIXME
875 wstats->miss.beacon = 0; // FIXME
883 #define WX(ioctl) [(ioctl) - SIOCSIWCOMMIT]
884 static const iw_handler bcm43xx_wx_handlers[] = {
885 /* Wireless Identification */
886 WX(SIOCGIWNAME) = bcm43xx_wx_get_name,
887 /* Basic operations */
888 WX(SIOCSIWFREQ) = bcm43xx_wx_set_channelfreq,
889 WX(SIOCGIWFREQ) = bcm43xx_wx_get_channelfreq,
890 WX(SIOCSIWMODE) = bcm43xx_wx_set_mode,
891 WX(SIOCGIWMODE) = bcm43xx_wx_get_mode,
892 /* Informative stuff */
893 WX(SIOCGIWRANGE) = bcm43xx_wx_get_rangeparams,
894 /* Access Point manipulation */
895 WX(SIOCSIWAP) = ieee80211softmac_wx_set_wap,
896 WX(SIOCGIWAP) = ieee80211softmac_wx_get_wap,
897 WX(SIOCSIWSCAN) = ieee80211softmac_wx_trigger_scan,
898 WX(SIOCGIWSCAN) = ieee80211softmac_wx_get_scan_results,
899 /* 802.11 specific support */
900 WX(SIOCSIWESSID) = ieee80211softmac_wx_set_essid,
901 WX(SIOCGIWESSID) = ieee80211softmac_wx_get_essid,
902 WX(SIOCSIWNICKN) = bcm43xx_wx_set_nick,
903 WX(SIOCGIWNICKN) = bcm43xx_wx_get_nick,
904 /* Other parameters */
905 WX(SIOCSIWRATE) = ieee80211softmac_wx_set_rate,
906 WX(SIOCGIWRATE) = ieee80211softmac_wx_get_rate,
907 WX(SIOCSIWRTS) = bcm43xx_wx_set_rts,
908 WX(SIOCGIWRTS) = bcm43xx_wx_get_rts,
909 WX(SIOCSIWFRAG) = bcm43xx_wx_set_frag,
910 WX(SIOCGIWFRAG) = bcm43xx_wx_get_frag,
911 WX(SIOCSIWTXPOW) = bcm43xx_wx_set_xmitpower,
912 WX(SIOCGIWTXPOW) = bcm43xx_wx_get_xmitpower,
913 //TODO WX(SIOCSIWRETRY) = bcm43xx_wx_set_retry,
914 //TODO WX(SIOCGIWRETRY) = bcm43xx_wx_get_retry,
916 WX(SIOCSIWENCODE) = bcm43xx_wx_set_encoding,
917 WX(SIOCGIWENCODE) = bcm43xx_wx_get_encoding,
918 WX(SIOCSIWENCODEEXT) = bcm43xx_wx_set_encodingext,
919 WX(SIOCGIWENCODEEXT) = bcm43xx_wx_get_encodingext,
921 //TODO WX(SIOCSIWPOWER) = bcm43xx_wx_set_power,
922 //TODO WX(SIOCGIWPOWER) = bcm43xx_wx_get_power,
923 WX(SIOCSIWGENIE) = ieee80211softmac_wx_set_genie,
924 WX(SIOCGIWGENIE) = ieee80211softmac_wx_get_genie,
925 WX(SIOCSIWAUTH) = ieee80211_wx_set_auth,
926 WX(SIOCGIWAUTH) = ieee80211_wx_get_auth,
930 static const iw_handler bcm43xx_priv_wx_handlers[] = {
931 /* Set Interference Mitigation Mode. */
932 bcm43xx_wx_set_interfmode,
933 /* Get Interference Mitigation Mode. */
934 bcm43xx_wx_get_interfmode,
935 /* Enable/Disable Short Preamble mode. */
936 bcm43xx_wx_set_shortpreamble,
937 /* Get Short Preamble mode. */
938 bcm43xx_wx_get_shortpreamble,
939 /* Enable/Disable Software Encryption mode */
940 bcm43xx_wx_set_swencryption,
941 /* Get Software Encryption mode */
942 bcm43xx_wx_get_swencryption,
943 /* Write SRPROM data. */
944 bcm43xx_wx_sprom_write,
945 /* Read SPROM data. */
946 bcm43xx_wx_sprom_read,
949 #define PRIV_WX_SET_INTERFMODE (SIOCIWFIRSTPRIV + 0)
950 #define PRIV_WX_GET_INTERFMODE (SIOCIWFIRSTPRIV + 1)
951 #define PRIV_WX_SET_SHORTPREAMBLE (SIOCIWFIRSTPRIV + 2)
952 #define PRIV_WX_GET_SHORTPREAMBLE (SIOCIWFIRSTPRIV + 3)
953 #define PRIV_WX_SET_SWENCRYPTION (SIOCIWFIRSTPRIV + 4)
954 #define PRIV_WX_GET_SWENCRYPTION (SIOCIWFIRSTPRIV + 5)
955 #define PRIV_WX_SPROM_WRITE (SIOCIWFIRSTPRIV + 6)
956 #define PRIV_WX_SPROM_READ (SIOCIWFIRSTPRIV + 7)
958 #define PRIV_WX_DUMMY(ioctl) \
964 static const struct iw_priv_args bcm43xx_priv_wx_args[] = {
966 .cmd = PRIV_WX_SET_INTERFMODE,
967 .set_args = IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
968 .name = "set_interfmode",
971 .cmd = PRIV_WX_GET_INTERFMODE,
972 .get_args = IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | MAX_WX_STRING,
973 .name = "get_interfmode",
976 .cmd = PRIV_WX_SET_SHORTPREAMBLE,
977 .set_args = IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
978 .name = "set_shortpreamb",
981 .cmd = PRIV_WX_GET_SHORTPREAMBLE,
982 .get_args = IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | MAX_WX_STRING,
983 .name = "get_shortpreamb",
986 .cmd = PRIV_WX_SET_SWENCRYPTION,
987 .set_args = IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
988 .name = "set_swencrypt",
991 .cmd = PRIV_WX_GET_SWENCRYPTION,
992 .get_args = IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | MAX_WX_STRING,
993 .name = "get_swencrypt",
996 .cmd = PRIV_WX_SPROM_WRITE,
997 .set_args = IW_PRIV_TYPE_CHAR | SPROM_BUFFERSIZE,
998 .name = "write_sprom",
1001 .cmd = PRIV_WX_SPROM_READ,
1002 .get_args = IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | SPROM_BUFFERSIZE,
1003 .name = "read_sprom",
1007 const struct iw_handler_def bcm43xx_wx_handlers_def = {
1008 .standard = bcm43xx_wx_handlers,
1009 .num_standard = ARRAY_SIZE(bcm43xx_wx_handlers),
1010 .num_private = ARRAY_SIZE(bcm43xx_priv_wx_handlers),
1011 .num_private_args = ARRAY_SIZE(bcm43xx_priv_wx_args),
1012 .private = bcm43xx_priv_wx_handlers,
1013 .private_args = bcm43xx_priv_wx_args,
1014 .get_wireless_stats = bcm43xx_get_wireless_stats,