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
50 /* FIXME: the next line is a guess as to what the maximum value of RX power
52 #define RX_POWER_MAX -10
55 static int bcm43xx_wx_get_name(struct net_device *net_dev,
56 struct iw_request_info *info,
57 union iwreq_data *data,
60 struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
62 struct bcm43xx_phyinfo *phy;
63 char suffix[7] = { 0 };
64 int have_a = 0, have_b = 0, have_g = 0;
66 mutex_lock(&bcm->mutex);
67 for (i = 0; i < bcm->nr_80211_available; i++) {
68 phy = &(bcm->core_80211_ext[i].phy);
70 case BCM43xx_PHYTYPE_A:
73 case BCM43xx_PHYTYPE_G:
75 case BCM43xx_PHYTYPE_B:
82 mutex_unlock(&bcm->mutex);
100 snprintf(data->name, IFNAMSIZ, "IEEE 802.11%s", suffix);
105 static int bcm43xx_wx_set_channelfreq(struct net_device *net_dev,
106 struct iw_request_info *info,
107 union iwreq_data *data,
110 struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
116 mutex_lock(&bcm->mutex);
117 spin_lock_irqsave(&bcm->irq_lock, flags);
119 if ((data->freq.m >= 0) && (data->freq.m <= 1000)) {
120 channel = data->freq.m;
121 freq = bcm43xx_channel_to_freq(bcm, channel);
123 channel = bcm43xx_freq_to_channel(bcm, data->freq.m);
126 if (!ieee80211_is_valid_channel(bcm->ieee, channel))
128 if (bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED) {
129 //ieee80211softmac_disassoc(softmac, $REASON);
130 bcm43xx_mac_suspend(bcm);
131 err = bcm43xx_radio_selectchannel(bcm, channel, 0);
132 bcm43xx_mac_enable(bcm);
134 bcm43xx_current_radio(bcm)->initial_channel = channel;
138 spin_unlock_irqrestore(&bcm->irq_lock, flags);
139 mutex_unlock(&bcm->mutex);
144 static int bcm43xx_wx_get_channelfreq(struct net_device *net_dev,
145 struct iw_request_info *info,
146 union iwreq_data *data,
149 struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
150 struct bcm43xx_radioinfo *radio;
154 mutex_lock(&bcm->mutex);
155 radio = bcm43xx_current_radio(bcm);
156 channel = radio->channel;
157 if (channel == 0xFF) {
158 channel = radio->initial_channel;
162 assert(channel > 0 && channel <= 1000);
164 data->freq.m = bcm43xx_channel_to_freq(bcm, channel) * 100000;
165 data->freq.flags = 1;
169 mutex_unlock(&bcm->mutex);
174 static int bcm43xx_wx_set_mode(struct net_device *net_dev,
175 struct iw_request_info *info,
176 union iwreq_data *data,
179 struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
184 if (mode == IW_MODE_AUTO)
185 mode = BCM43xx_INITIAL_IWMODE;
187 mutex_lock(&bcm->mutex);
188 spin_lock_irqsave(&bcm->irq_lock, flags);
189 if (bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED) {
190 if (bcm->ieee->iw_mode != mode)
191 bcm43xx_set_iwmode(bcm, mode);
193 bcm->ieee->iw_mode = mode;
194 spin_unlock_irqrestore(&bcm->irq_lock, flags);
195 mutex_unlock(&bcm->mutex);
200 static int bcm43xx_wx_get_mode(struct net_device *net_dev,
201 struct iw_request_info *info,
202 union iwreq_data *data,
205 struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
207 mutex_lock(&bcm->mutex);
208 data->mode = bcm->ieee->iw_mode;
209 mutex_unlock(&bcm->mutex);
214 static int bcm43xx_wx_get_rangeparams(struct net_device *net_dev,
215 struct iw_request_info *info,
216 union iwreq_data *data,
219 struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
220 struct iw_range *range = (struct iw_range *)extra;
221 const struct ieee80211_geo *geo;
223 struct bcm43xx_phyinfo *phy;
225 data->data.length = sizeof(*range);
226 memset(range, 0, sizeof(*range));
228 //TODO: What about 802.11b?
229 /* 54Mb/s == ~27Mb/s payload throughput (802.11g) */
230 range->throughput = 27 * 1000 * 1000;
232 range->max_qual.qual = 100;
233 /* TODO: Real max RSSI */
234 range->max_qual.level = 0;
235 range->max_qual.noise = 0;
236 range->max_qual.updated = IW_QUAL_ALL_UPDATED;
238 range->avg_qual.qual = 50;
239 range->avg_qual.level = 0;
240 range->avg_qual.noise = 0;
241 range->avg_qual.updated = IW_QUAL_ALL_UPDATED;
243 range->min_rts = BCM43xx_MIN_RTS_THRESHOLD;
244 range->max_rts = BCM43xx_MAX_RTS_THRESHOLD;
245 range->min_frag = MIN_FRAG_THRESHOLD;
246 range->max_frag = MAX_FRAG_THRESHOLD;
248 range->encoding_size[0] = 5;
249 range->encoding_size[1] = 13;
250 range->num_encoding_sizes = 2;
251 range->max_encoding_tokens = WEP_KEYS;
253 range->we_version_compiled = WIRELESS_EXT;
254 range->we_version_source = BCM43xx_WX_VERSION;
256 range->enc_capa = IW_ENC_CAPA_WPA |
258 IW_ENC_CAPA_CIPHER_TKIP |
259 IW_ENC_CAPA_CIPHER_CCMP;
261 mutex_lock(&bcm->mutex);
262 phy = bcm43xx_current_phy(bcm);
264 range->num_bitrates = 0;
266 if (phy->type == BCM43xx_PHYTYPE_A ||
267 phy->type == BCM43xx_PHYTYPE_G) {
268 range->num_bitrates = 8;
269 range->bitrate[i++] = IEEE80211_OFDM_RATE_6MB;
270 range->bitrate[i++] = IEEE80211_OFDM_RATE_9MB;
271 range->bitrate[i++] = IEEE80211_OFDM_RATE_12MB;
272 range->bitrate[i++] = IEEE80211_OFDM_RATE_18MB;
273 range->bitrate[i++] = IEEE80211_OFDM_RATE_24MB;
274 range->bitrate[i++] = IEEE80211_OFDM_RATE_36MB;
275 range->bitrate[i++] = IEEE80211_OFDM_RATE_48MB;
276 range->bitrate[i++] = IEEE80211_OFDM_RATE_54MB;
278 if (phy->type == BCM43xx_PHYTYPE_B ||
279 phy->type == BCM43xx_PHYTYPE_G) {
280 range->num_bitrates += 4;
281 range->bitrate[i++] = IEEE80211_CCK_RATE_1MB;
282 range->bitrate[i++] = IEEE80211_CCK_RATE_2MB;
283 range->bitrate[i++] = IEEE80211_CCK_RATE_5MB;
284 range->bitrate[i++] = IEEE80211_CCK_RATE_11MB;
287 geo = ieee80211_get_geo(bcm->ieee);
288 range->num_channels = geo->a_channels + geo->bg_channels;
290 for (i = 0; i < geo->a_channels; i++) {
291 if (j == IW_MAX_FREQUENCIES)
293 range->freq[j].i = j + 1;
294 range->freq[j].m = geo->a[i].freq;//FIXME?
295 range->freq[j].e = 1;
298 for (i = 0; i < geo->bg_channels; i++) {
299 if (j == IW_MAX_FREQUENCIES)
301 range->freq[j].i = j + 1;
302 range->freq[j].m = geo->bg[i].freq;//FIXME?
303 range->freq[j].e = 1;
306 range->num_frequency = j;
308 mutex_unlock(&bcm->mutex);
313 static int bcm43xx_wx_set_nick(struct net_device *net_dev,
314 struct iw_request_info *info,
315 union iwreq_data *data,
318 struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
321 mutex_lock(&bcm->mutex);
322 len = min((size_t)data->data.length, (size_t)IW_ESSID_MAX_SIZE);
323 memcpy(bcm->nick, extra, len);
324 bcm->nick[len] = '\0';
325 mutex_unlock(&bcm->mutex);
330 static int bcm43xx_wx_get_nick(struct net_device *net_dev,
331 struct iw_request_info *info,
332 union iwreq_data *data,
335 struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
338 mutex_lock(&bcm->mutex);
339 len = strlen(bcm->nick) + 1;
340 memcpy(extra, bcm->nick, len);
341 data->data.length = (__u16)len;
342 data->data.flags = 1;
343 mutex_unlock(&bcm->mutex);
348 static int bcm43xx_wx_set_rts(struct net_device *net_dev,
349 struct iw_request_info *info,
350 union iwreq_data *data,
353 struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
357 mutex_lock(&bcm->mutex);
358 spin_lock_irqsave(&bcm->irq_lock, flags);
359 if (data->rts.disabled) {
360 bcm->rts_threshold = BCM43xx_MAX_RTS_THRESHOLD;
363 if (data->rts.value >= BCM43xx_MIN_RTS_THRESHOLD &&
364 data->rts.value <= BCM43xx_MAX_RTS_THRESHOLD) {
365 bcm->rts_threshold = data->rts.value;
369 spin_unlock_irqrestore(&bcm->irq_lock, flags);
370 mutex_unlock(&bcm->mutex);
375 static int bcm43xx_wx_get_rts(struct net_device *net_dev,
376 struct iw_request_info *info,
377 union iwreq_data *data,
380 struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
382 mutex_lock(&bcm->mutex);
383 data->rts.value = bcm->rts_threshold;
385 data->rts.disabled = (bcm->rts_threshold == BCM43xx_MAX_RTS_THRESHOLD);
386 mutex_unlock(&bcm->mutex);
391 static int bcm43xx_wx_set_frag(struct net_device *net_dev,
392 struct iw_request_info *info,
393 union iwreq_data *data,
396 struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
400 mutex_lock(&bcm->mutex);
401 spin_lock_irqsave(&bcm->irq_lock, flags);
402 if (data->frag.disabled) {
403 bcm->ieee->fts = MAX_FRAG_THRESHOLD;
406 if (data->frag.value >= MIN_FRAG_THRESHOLD &&
407 data->frag.value <= MAX_FRAG_THRESHOLD) {
408 bcm->ieee->fts = data->frag.value & ~0x1;
412 spin_unlock_irqrestore(&bcm->irq_lock, flags);
413 mutex_unlock(&bcm->mutex);
418 static int bcm43xx_wx_get_frag(struct net_device *net_dev,
419 struct iw_request_info *info,
420 union iwreq_data *data,
423 struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
425 mutex_lock(&bcm->mutex);
426 data->frag.value = bcm->ieee->fts;
427 data->frag.fixed = 0;
428 data->frag.disabled = (bcm->ieee->fts == MAX_FRAG_THRESHOLD);
429 mutex_unlock(&bcm->mutex);
434 static int bcm43xx_wx_set_xmitpower(struct net_device *net_dev,
435 struct iw_request_info *info,
436 union iwreq_data *data,
439 struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
440 struct bcm43xx_radioinfo *radio;
441 struct bcm43xx_phyinfo *phy;
446 if ((data->txpower.flags & IW_TXPOW_TYPE) != IW_TXPOW_DBM) {
447 printk(PFX KERN_ERR "TX power not in dBm.\n");
451 mutex_lock(&bcm->mutex);
452 spin_lock_irqsave(&bcm->irq_lock, flags);
453 if (bcm43xx_status(bcm) != BCM43xx_STAT_INITIALIZED)
455 radio = bcm43xx_current_radio(bcm);
456 phy = bcm43xx_current_phy(bcm);
457 if (data->txpower.disabled != (!(radio->enabled))) {
458 if (data->txpower.disabled)
459 bcm43xx_radio_turn_off(bcm);
461 bcm43xx_radio_turn_on(bcm);
463 if (data->txpower.value > 0) {
464 /* desired and maxpower dBm values are in Q5.2 */
465 if (phy->type == BCM43xx_PHYTYPE_A)
466 maxpower = bcm->sprom.maxpower_aphy;
468 maxpower = bcm->sprom.maxpower_bgphy;
469 radio->txpower_desired = limit_value(data->txpower.value << 2,
471 bcm43xx_phy_xmitpower(bcm);
476 spin_unlock_irqrestore(&bcm->irq_lock, flags);
477 mutex_unlock(&bcm->mutex);
482 static int bcm43xx_wx_get_xmitpower(struct net_device *net_dev,
483 struct iw_request_info *info,
484 union iwreq_data *data,
487 struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
488 struct bcm43xx_radioinfo *radio;
491 mutex_lock(&bcm->mutex);
492 if (bcm43xx_status(bcm) != BCM43xx_STAT_INITIALIZED)
494 radio = bcm43xx_current_radio(bcm);
495 /* desired dBm value is in Q5.2 */
496 data->txpower.value = radio->txpower_desired >> 2;
497 data->txpower.fixed = 1;
498 data->txpower.flags = IW_TXPOW_DBM;
499 data->txpower.disabled = !(radio->enabled);
503 mutex_unlock(&bcm->mutex);
508 static int bcm43xx_wx_set_encoding(struct net_device *net_dev,
509 struct iw_request_info *info,
510 union iwreq_data *data,
513 struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
516 err = ieee80211_wx_set_encode(bcm->ieee, info, data, extra);
521 static int bcm43xx_wx_set_encodingext(struct net_device *net_dev,
522 struct iw_request_info *info,
523 union iwreq_data *data,
526 struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
529 err = ieee80211_wx_set_encodeext(bcm->ieee, info, data, extra);
534 static int bcm43xx_wx_get_encoding(struct net_device *net_dev,
535 struct iw_request_info *info,
536 union iwreq_data *data,
539 struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
542 err = ieee80211_wx_get_encode(bcm->ieee, info, data, extra);
547 static int bcm43xx_wx_get_encodingext(struct net_device *net_dev,
548 struct iw_request_info *info,
549 union iwreq_data *data,
552 struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
555 err = ieee80211_wx_get_encodeext(bcm->ieee, info, data, extra);
560 static int bcm43xx_wx_set_interfmode(struct net_device *net_dev,
561 struct iw_request_info *info,
562 union iwreq_data *data,
565 struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
569 mode = *((int *)extra);
572 mode = BCM43xx_RADIO_INTERFMODE_NONE;
575 mode = BCM43xx_RADIO_INTERFMODE_NONWLAN;
578 mode = BCM43xx_RADIO_INTERFMODE_MANUALWLAN;
581 mode = BCM43xx_RADIO_INTERFMODE_AUTOWLAN;
584 printk(KERN_ERR PFX "set_interfmode allowed parameters are: "
585 "0 => None, 1 => Non-WLAN, 2 => WLAN, "
590 mutex_lock(&bcm->mutex);
591 spin_lock_irqsave(&bcm->irq_lock, flags);
592 if (bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED) {
593 err = bcm43xx_radio_set_interference_mitigation(bcm, mode);
595 printk(KERN_ERR PFX "Interference Mitigation not "
596 "supported by device\n");
599 if (mode == BCM43xx_RADIO_INTERFMODE_AUTOWLAN) {
600 printk(KERN_ERR PFX "Interference Mitigation mode Auto-WLAN "
601 "not supported while the interface is down.\n");
604 bcm43xx_current_radio(bcm)->interfmode = mode;
606 spin_unlock_irqrestore(&bcm->irq_lock, flags);
607 mutex_unlock(&bcm->mutex);
612 static int bcm43xx_wx_get_interfmode(struct net_device *net_dev,
613 struct iw_request_info *info,
614 union iwreq_data *data,
617 struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
620 mutex_lock(&bcm->mutex);
621 mode = bcm43xx_current_radio(bcm)->interfmode;
622 mutex_unlock(&bcm->mutex);
625 case BCM43xx_RADIO_INTERFMODE_NONE:
626 strncpy(extra, "0 (No Interference Mitigation)", MAX_WX_STRING);
628 case BCM43xx_RADIO_INTERFMODE_NONWLAN:
629 strncpy(extra, "1 (Non-WLAN Interference Mitigation)", MAX_WX_STRING);
631 case BCM43xx_RADIO_INTERFMODE_MANUALWLAN:
632 strncpy(extra, "2 (WLAN Interference Mitigation)", MAX_WX_STRING);
637 data->data.length = strlen(extra) + 1;
642 static int bcm43xx_wx_set_shortpreamble(struct net_device *net_dev,
643 struct iw_request_info *info,
644 union iwreq_data *data,
647 struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
651 on = *((int *)extra);
652 mutex_lock(&bcm->mutex);
653 spin_lock_irqsave(&bcm->irq_lock, flags);
654 bcm->short_preamble = !!on;
655 spin_unlock_irqrestore(&bcm->irq_lock, flags);
656 mutex_unlock(&bcm->mutex);
661 static int bcm43xx_wx_get_shortpreamble(struct net_device *net_dev,
662 struct iw_request_info *info,
663 union iwreq_data *data,
666 struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
669 mutex_lock(&bcm->mutex);
670 on = bcm->short_preamble;
671 mutex_unlock(&bcm->mutex);
674 strncpy(extra, "1 (Short Preamble enabled)", MAX_WX_STRING);
676 strncpy(extra, "0 (Short Preamble disabled)", MAX_WX_STRING);
677 data->data.length = strlen(extra) + 1;
682 static int bcm43xx_wx_set_swencryption(struct net_device *net_dev,
683 struct iw_request_info *info,
684 union iwreq_data *data,
687 struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
691 on = *((int *)extra);
693 mutex_lock(&bcm->mutex);
694 spin_lock_irqsave(&bcm->irq_lock, flags);
695 bcm->ieee->host_encrypt = !!on;
696 bcm->ieee->host_decrypt = !!on;
697 bcm->ieee->host_build_iv = !on;
698 spin_unlock_irqrestore(&bcm->irq_lock, flags);
699 mutex_unlock(&bcm->mutex);
704 static int bcm43xx_wx_get_swencryption(struct net_device *net_dev,
705 struct iw_request_info *info,
706 union iwreq_data *data,
709 struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
712 mutex_lock(&bcm->mutex);
713 on = bcm->ieee->host_encrypt;
714 mutex_unlock(&bcm->mutex);
717 strncpy(extra, "1 (SW encryption enabled) ", MAX_WX_STRING);
719 strncpy(extra, "0 (SW encryption disabled) ", MAX_WX_STRING);
720 data->data.length = strlen(extra + 1);
725 /* Enough buffer to hold a hexdump of the sprom data. */
726 #define SPROM_BUFFERSIZE 512
728 static int sprom2hex(const u16 *sprom, char *dump)
732 for (i = 0; i < BCM43xx_SPROM_SIZE; i++) {
733 pos += snprintf(dump + pos, SPROM_BUFFERSIZE - pos - 1,
734 "%04X", swab16(sprom[i]) & 0xFFFF);
740 static int hex2sprom(u16 *sprom, const char *dump, unsigned int len)
744 unsigned long parsed;
746 if (len < BCM43xx_SPROM_SIZE * sizeof(u16) * 2)
748 while (cnt < BCM43xx_SPROM_SIZE) {
749 memcpy(tmp, dump, 4);
751 parsed = simple_strtoul(tmp, NULL, 16);
752 sprom[cnt++] = swab16((u16)parsed);
758 static int bcm43xx_wx_sprom_read(struct net_device *net_dev,
759 struct iw_request_info *info,
760 union iwreq_data *data,
763 struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
768 if (!capable(CAP_SYS_RAWIO))
772 sprom = kmalloc(BCM43xx_SPROM_SIZE * sizeof(*sprom),
777 mutex_lock(&bcm->mutex);
778 spin_lock_irqsave(&bcm->irq_lock, flags);
780 if (bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED)
781 err = bcm43xx_sprom_read(bcm, sprom);
782 spin_unlock_irqrestore(&bcm->irq_lock, flags);
783 mutex_unlock(&bcm->mutex);
785 data->data.length = sprom2hex(sprom, extra);
791 static int bcm43xx_wx_sprom_write(struct net_device *net_dev,
792 struct iw_request_info *info,
793 union iwreq_data *data,
796 struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
803 if (!capable(CAP_SYS_RAWIO))
807 sprom = kmalloc(BCM43xx_SPROM_SIZE * sizeof(*sprom),
812 len = data->data.length;
813 extra[len - 1] = '\0';
814 input = strchr(extra, ':');
817 len -= input - extra;
820 err = hex2sprom(sprom, input, len);
824 mutex_lock(&bcm->mutex);
825 spin_lock_irqsave(&bcm->irq_lock, flags);
826 spin_lock(&bcm->leds_lock);
828 if (bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED)
829 err = bcm43xx_sprom_write(bcm, sprom);
830 spin_unlock(&bcm->leds_lock);
831 spin_unlock_irqrestore(&bcm->irq_lock, flags);
832 mutex_unlock(&bcm->mutex);
839 /* Get wireless statistics. Called by /proc/net/wireless and by SIOCGIWSTATS */
841 static struct iw_statistics *bcm43xx_get_wireless_stats(struct net_device *net_dev)
843 struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
844 struct ieee80211softmac_device *mac = ieee80211_priv(net_dev);
845 struct iw_statistics *wstats;
846 struct ieee80211_network *network = NULL;
847 static int tmp_level = 0;
850 wstats = &bcm->stats.wstats;
851 if (!mac->associated) {
852 wstats->miss.beacon = 0;
853 // bcm->ieee->ieee_stats.tx_retry_limit_exceeded = 0; // FIXME: should this be cleared here?
854 wstats->discard.retries = 0;
855 // bcm->ieee->ieee_stats.tx_discards_wrong_sa = 0; // FIXME: same question
856 wstats->discard.nwid = 0;
857 // bcm->ieee->ieee_stats.rx_discards_undecryptable = 0; // FIXME: ditto
858 wstats->discard.code = 0;
859 // bcm->ieee->ieee_stats.rx_fragments = 0; // FIXME: same here
860 wstats->discard.fragment = 0;
861 wstats->discard.misc = 0;
862 wstats->qual.qual = 0;
863 wstats->qual.level = 0;
864 wstats->qual.noise = 0;
865 wstats->qual.updated = 7;
866 wstats->qual.updated |= IW_QUAL_ALL_UPDATED;
869 /* fill in the real statistics when iface associated */
870 spin_lock_irqsave(&mac->ieee->lock, flags);
871 list_for_each_entry(network, &mac->ieee->network_list, list) {
872 if (!memcmp(mac->associnfo.bssid, network->bssid, ETH_ALEN)) {
873 if (!tmp_level) /* get initial value */
874 tmp_level = network->stats.rssi;
875 else /* smooth results */
876 tmp_level = (7 * tmp_level + network->stats.rssi)/8;
880 spin_unlock_irqrestore(&mac->ieee->lock, flags);
881 wstats->qual.level = tmp_level;
882 wstats->qual.qual = 100 + tmp_level - RX_POWER_MAX; // TODO: get the real signal quality
883 wstats->qual.noise = bcm->stats.noise;
884 wstats->qual.updated = IW_QUAL_ALL_UPDATED;
885 wstats->discard.code = bcm->ieee->ieee_stats.rx_discards_undecryptable;
886 wstats->discard.retries = bcm->ieee->ieee_stats.tx_retry_limit_exceeded;
887 wstats->discard.nwid = bcm->ieee->ieee_stats.tx_discards_wrong_sa;
888 wstats->discard.fragment = bcm->ieee->ieee_stats.rx_fragments;
889 wstats->discard.misc = 0; // FIXME
890 wstats->miss.beacon = 0; // FIXME
898 #define WX(ioctl) [(ioctl) - SIOCSIWCOMMIT]
899 static const iw_handler bcm43xx_wx_handlers[] = {
900 /* Wireless Identification */
901 WX(SIOCGIWNAME) = bcm43xx_wx_get_name,
902 /* Basic operations */
903 WX(SIOCSIWFREQ) = bcm43xx_wx_set_channelfreq,
904 WX(SIOCGIWFREQ) = bcm43xx_wx_get_channelfreq,
905 WX(SIOCSIWMODE) = bcm43xx_wx_set_mode,
906 WX(SIOCGIWMODE) = bcm43xx_wx_get_mode,
907 /* Informative stuff */
908 WX(SIOCGIWRANGE) = bcm43xx_wx_get_rangeparams,
909 /* Access Point manipulation */
910 WX(SIOCSIWAP) = ieee80211softmac_wx_set_wap,
911 WX(SIOCGIWAP) = ieee80211softmac_wx_get_wap,
912 WX(SIOCSIWSCAN) = ieee80211softmac_wx_trigger_scan,
913 WX(SIOCGIWSCAN) = ieee80211softmac_wx_get_scan_results,
914 /* 802.11 specific support */
915 WX(SIOCSIWESSID) = ieee80211softmac_wx_set_essid,
916 WX(SIOCGIWESSID) = ieee80211softmac_wx_get_essid,
917 WX(SIOCSIWNICKN) = bcm43xx_wx_set_nick,
918 WX(SIOCGIWNICKN) = bcm43xx_wx_get_nick,
919 /* Other parameters */
920 WX(SIOCSIWRATE) = ieee80211softmac_wx_set_rate,
921 WX(SIOCGIWRATE) = ieee80211softmac_wx_get_rate,
922 WX(SIOCSIWRTS) = bcm43xx_wx_set_rts,
923 WX(SIOCGIWRTS) = bcm43xx_wx_get_rts,
924 WX(SIOCSIWFRAG) = bcm43xx_wx_set_frag,
925 WX(SIOCGIWFRAG) = bcm43xx_wx_get_frag,
926 WX(SIOCSIWTXPOW) = bcm43xx_wx_set_xmitpower,
927 WX(SIOCGIWTXPOW) = bcm43xx_wx_get_xmitpower,
928 //TODO WX(SIOCSIWRETRY) = bcm43xx_wx_set_retry,
929 //TODO WX(SIOCGIWRETRY) = bcm43xx_wx_get_retry,
931 WX(SIOCSIWENCODE) = bcm43xx_wx_set_encoding,
932 WX(SIOCGIWENCODE) = bcm43xx_wx_get_encoding,
933 WX(SIOCSIWENCODEEXT) = bcm43xx_wx_set_encodingext,
934 WX(SIOCGIWENCODEEXT) = bcm43xx_wx_get_encodingext,
936 //TODO WX(SIOCSIWPOWER) = bcm43xx_wx_set_power,
937 //TODO WX(SIOCGIWPOWER) = bcm43xx_wx_get_power,
938 WX(SIOCSIWGENIE) = ieee80211softmac_wx_set_genie,
939 WX(SIOCGIWGENIE) = ieee80211softmac_wx_get_genie,
940 WX(SIOCSIWAUTH) = ieee80211_wx_set_auth,
941 WX(SIOCGIWAUTH) = ieee80211_wx_get_auth,
945 static const iw_handler bcm43xx_priv_wx_handlers[] = {
946 /* Set Interference Mitigation Mode. */
947 bcm43xx_wx_set_interfmode,
948 /* Get Interference Mitigation Mode. */
949 bcm43xx_wx_get_interfmode,
950 /* Enable/Disable Short Preamble mode. */
951 bcm43xx_wx_set_shortpreamble,
952 /* Get Short Preamble mode. */
953 bcm43xx_wx_get_shortpreamble,
954 /* Enable/Disable Software Encryption mode */
955 bcm43xx_wx_set_swencryption,
956 /* Get Software Encryption mode */
957 bcm43xx_wx_get_swencryption,
958 /* Write SRPROM data. */
959 bcm43xx_wx_sprom_write,
960 /* Read SPROM data. */
961 bcm43xx_wx_sprom_read,
964 #define PRIV_WX_SET_INTERFMODE (SIOCIWFIRSTPRIV + 0)
965 #define PRIV_WX_GET_INTERFMODE (SIOCIWFIRSTPRIV + 1)
966 #define PRIV_WX_SET_SHORTPREAMBLE (SIOCIWFIRSTPRIV + 2)
967 #define PRIV_WX_GET_SHORTPREAMBLE (SIOCIWFIRSTPRIV + 3)
968 #define PRIV_WX_SET_SWENCRYPTION (SIOCIWFIRSTPRIV + 4)
969 #define PRIV_WX_GET_SWENCRYPTION (SIOCIWFIRSTPRIV + 5)
970 #define PRIV_WX_SPROM_WRITE (SIOCIWFIRSTPRIV + 6)
971 #define PRIV_WX_SPROM_READ (SIOCIWFIRSTPRIV + 7)
973 #define PRIV_WX_DUMMY(ioctl) \
979 static const struct iw_priv_args bcm43xx_priv_wx_args[] = {
981 .cmd = PRIV_WX_SET_INTERFMODE,
982 .set_args = IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
983 .name = "set_interfmode",
986 .cmd = PRIV_WX_GET_INTERFMODE,
987 .get_args = IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | MAX_WX_STRING,
988 .name = "get_interfmode",
991 .cmd = PRIV_WX_SET_SHORTPREAMBLE,
992 .set_args = IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
993 .name = "set_shortpreamb",
996 .cmd = PRIV_WX_GET_SHORTPREAMBLE,
997 .get_args = IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | MAX_WX_STRING,
998 .name = "get_shortpreamb",
1001 .cmd = PRIV_WX_SET_SWENCRYPTION,
1002 .set_args = IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
1003 .name = "set_swencrypt",
1006 .cmd = PRIV_WX_GET_SWENCRYPTION,
1007 .get_args = IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | MAX_WX_STRING,
1008 .name = "get_swencrypt",
1011 .cmd = PRIV_WX_SPROM_WRITE,
1012 .set_args = IW_PRIV_TYPE_CHAR | SPROM_BUFFERSIZE,
1013 .name = "write_sprom",
1016 .cmd = PRIV_WX_SPROM_READ,
1017 .get_args = IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | SPROM_BUFFERSIZE,
1018 .name = "read_sprom",
1022 const struct iw_handler_def bcm43xx_wx_handlers_def = {
1023 .standard = bcm43xx_wx_handlers,
1024 .num_standard = ARRAY_SIZE(bcm43xx_wx_handlers),
1025 .num_private = ARRAY_SIZE(bcm43xx_priv_wx_handlers),
1026 .num_private_args = ARRAY_SIZE(bcm43xx_priv_wx_args),
1027 .private = bcm43xx_priv_wx_handlers,
1028 .private_args = bcm43xx_priv_wx_args,
1029 .get_wireless_stats = bcm43xx_get_wireless_stats,