diff --git a/CHANGES b/CHANGES index 63c3da5..5ad285d 100644 --- a/CHANGES +++ b/CHANGES @@ -46,7 +46,7 @@ you to have multiple profiles per network. Not finished yet. - hfa384x.h updates. - additions to the MIB. - - Cleaned up wireless extension stuff a little bit. + - Rewrote part of the existing wireless extension code. - Add the Microsoft MN510 device ID. - Finally fix the 'crash on unload' problem for 2.2.x kernels with PCI. Turns out the kcompat24 code wasn't quite complete. (Matthew Rush) diff --git a/src/include/wlan/p80211netdev.h b/src/include/wlan/p80211netdev.h index 89f8f48..5859ad6 100644 --- a/src/include/wlan/p80211netdev.h +++ b/src/include/wlan/p80211netdev.h @@ -211,7 +211,6 @@ typedef struct wlandevice #ifdef WIRELESS_EXT struct iw_statistics wstats; - struct iw_statistics* (*get_wireless_stats)(netdevice_t *dev); int (*support_ioctl)(netdevice_t *dev, struct iwreq *iwr, int cmd); #endif diff --git a/src/p80211/p80211wext.c b/src/p80211/p80211wext.c index bc5f285..0e5809d 100644 --- a/src/p80211/p80211wext.c +++ b/src/p80211/p80211wext.c @@ -1,22 +1,38 @@ -/* p80211wext.c -*- linux-c -*- - * - * original author: Reyk Floeter - * - * This application is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This application is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU General Public - * License along with this library; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA - * 02111 USA. - */ +/* src/p80211/p80211wext.c +* +* Glue code to make linux-wlan-ng a happy wireless extension camper. +* +* original author: Reyk Floeter +* Completely re-written by Solomon Peachy +* +* Copyright (C) 2002 AbsoluteValue Systems, Inc. All Rights Reserved. +* -------------------------------------------------------------------- +* +* linux-wlan +* +* The contents of this file are subject to the Mozilla Public +* License Version 1.1 (the "License"); you may not use this file +* except in compliance with the License. You may obtain a copy of +* the License at http://www.mozilla.org/MPL/ +* +* Software distributed under the License is distributed on an "AS +* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or +* implied. See the License for the specific language governing +* rights and limitations under the License. +* +* Alternatively, the contents of this file may be used under the +* terms of the GNU Public License version 2 (the "GPL"), in which +* case the provisions of the GPL are applicable instead of the +* above. If you wish to allow the use of your version of this file +* only under the terms of the GPL and not to allow others to use +* your version of this file under the MPL, indicate your decision +* by deleting the provisions above and replace them with the notice +* and other provisions required by the GPL. If you do not delete +* the provisions above, a recipient may use your version of this +* file under either the MPL or the GPL. +* +* -------------------------------------------------------------------- +*/ /*================================================================*/ /* System Includes */ @@ -47,6 +63,8 @@ #include #include #include +#include +#include #include #include #include @@ -59,8 +77,10 @@ /* called by /proc/net/wireless */ struct iw_statistics* p80211wext_get_wireless_stats (netdevice_t *dev) { + p80211msg_lnxreq_commsquality_t quality; wlandevice_t *wlandev = (wlandevice_t*)dev->priv; - struct iw_statistics* wstats = NULL; + struct iw_statistics* wstats = &wlandev->wstats; + int retval; DBFENTER; @@ -71,26 +91,31 @@ struct iw_statistics* p80211wext_get_wireless_stats (netdevice_t *dev) if ( wlandev->msdstate != WLAN_MSD_RUNNING ) return NULL; - /* iface - status - link_qual - link_level - link_noise - disc_nwid - disc_crypt - disc_frag - disc_retry - disc_misc - missed_beacon - */ + /* XXX Only valid in station mode */ + wstats->status = 0; - /* forward the request to a hardware- dependent function. - * FIX: should it be possible to do abstract MIB- requests (ie. for - * getting the link quality) on the p80211- level?! - * ANSWER: [MSM] Yes, it should. It just isn't done yet. - */ - if (wlandev->get_wireless_stats) - wstats = (*(wlandev->get_wireless_stats))(dev); + /* build request message */ + quality.msgcode = DIDmsg_lnxreq_commsquality; + quality.dbm.data = P80211ENUM_truth_false; + quality.dbm.status = P80211ENUM_msgitem_status_data_ok; + + /* send message to nsd */ + if ( wlandev->mlmerequest == NULL ) + return NULL; + + retval = (*(wlandev->mlmerequest))(wlandev, (p80211msg_t*) &quality); + + wstats->qual.qual = quality.link.data; /* overall link quality */ + wstats->qual.level = quality.level.data; /* instant signal level */ + wstats->qual.noise = quality.noise.data; /* instant noise level */ + + wstats->qual.updated = 7; // XXX magic number. don't know. + wstats->discard.code = wlandev->rx.decrypt_err; + wstats->discard.nwid = 0; + wstats->discard.fragment = 0; + wstats->discard.retries = 0; + wstats->discard.misc = 0; + wstats->miss.beacon = 0; DBFEXIT; diff --git a/src/prism2/driver/prism2sta.c b/src/prism2/driver/prism2sta.c index 2734ccc..bfabbe0 100644 --- a/src/prism2/driver/prism2sta.c +++ b/src/prism2/driver/prism2sta.c @@ -958,9 +958,15 @@ int prism2sta_txframe(wlandevice_t *wlandev, struct sk_buff *skb, p80211_hdr_t * ----------------------------------------------------------------*/ int prism2sta_mlmerequest(wlandevice_t *wlandev, p80211msg_t *msg) { + prism2sta_priv_t *priv; + hfa384x_t *hw; + int result = 0; DBFENTER; + priv = (prism2sta_priv_t*)wlandev->priv; + hw = priv->hw; + switch( msg->msgcode ) { case DIDmsg_dot11req_mibget : @@ -1115,6 +1121,36 @@ int prism2sta_mlmerequest(wlandevice_t *wlandev, p80211msg_t *msg) WLAN_LOG_DEBUG0(2,"Received mlme enable request\n"); result = prism2mgmt_enable(wlandev, msg); break; + case DIDmsg_lnxreq_commsquality: { + UINT8 bytebuf[HFA384x_CMD_ALLOC_LEN_MAX]; + p80211msg_lnxreq_commsquality_t *qualmsg; + hfa384x_commsquality_t *qual = (hfa384x_commsquality_t*)bytebuf; + WLAN_LOG_DEBUG0(2,"Received commsquality request\n"); + + qualmsg = (p80211msg_lnxreq_commsquality_t*) msg; + memset(qual, 0, sizeof(hfa384x_commsquality_t)); + + result = hfa384x_drvr_getconfig(hw, + HFA384x_RID_COMMSQUALITY, + qual, + HFA384x_RID_COMMSQUALITY_LEN); + if (result != 0) { + WLAN_LOG_ERROR2("Failed to read %s statistics: error=%d\n", + wlandev->name, result); + break; + } + if (qualmsg->dbm.data == P80211ENUM_truth_true) { + qualmsg->link.data = qual->CQ_currBSS; + qualmsg->level.data = (qual->ASL_currBSS + 0x100 - 100); + qualmsg->noise.data = (qual->ANL_currFC + 0x100 - 100); + } else { + qualmsg->link.data = qual->CQ_currBSS; + qualmsg->level.data = qual->ASL_currBSS; + qualmsg->noise.data = qual->ANL_currFC; + } + + break; + } default: WLAN_LOG_WARNING1("Unknown mgmt request message 0x%08lx", msg->msgcode); break; @@ -4342,7 +4378,6 @@ static wlandevice_t *create_wlan(void) wlandev->mlmerequest = &prism2sta_mlmerequest; wlandev->hwremovedfn = &prism2sta_hwremoved; #if WIRELESS_EXT > 10 - wlandev->get_wireless_stats = &prism2wext_get_wireless_stats; wlandev->support_ioctl = &prism2wext_support_ioctl; #endif diff --git a/src/prism2/driver/prism2wext.c b/src/prism2/driver/prism2wext.c index 54f4eec..d937b33 100644 --- a/src/prism2/driver/prism2wext.c +++ b/src/prism2/driver/prism2wext.c @@ -102,69 +102,6 @@ static int prism2wext_getrate(hfa384x_t* hw, struct iw_param *rrq); static int prism2wext_get_channel(struct iw_freq *iwf); -/* called by p80211wstats_get_wireless_stats for /proc/net/wireless */ -struct iw_statistics* prism2wext_get_wireless_stats(netdevice_t *dev) -{ - wlandevice_t *wlandev = (wlandevice_t*)dev->priv; - prism2sta_priv_t *priv = (prism2sta_priv_t*)wlandev->priv; - hfa384x_t *hw = priv->hw; - hfa384x_CommTallies32_t tallies = priv->tallies; - struct iw_statistics* wstats; - int result = 0; - UINT8 bytebuf[HFA384x_CMD_ALLOC_LEN_MAX]; - hfa384x_commsquality_t *qual = (hfa384x_commsquality_t*)bytebuf; - - DBFENTER; - - if (wlandev == (wlandevice_t*) NULL) - return NULL; - - wstats = &wlandev->wstats; - - memset(&wstats->qual, 0, sizeof(hfa384x_commsquality_t)); - - /* get the qualitity settings from the RID and return them - * into a struct... - */ - result = hfa384x_drvr_getconfig(hw, - HFA384x_RID_COMMSQUALITY, - qual, - HFA384x_RID_COMMSQUALITY_LEN); - if (result != 0) { - printk(KERN_ERR "Failed to read %s statistics: error=%d\n", - dev->name, result); - goto _done; - } - - /* set stats for the wireless- stats struct. - * we can't return any link quality, if we are in ap (accesspoint) - - * mode! - */ - wstats->status = priv->ap; - wstats->qual.qual = priv->ap ? 0L : qual->CQ_currBSS; -#ifdef WEXT_IN_DB - /* Intersil says : dBm = RSSI - 100 - remember that 0x100 == 0x0 */ - /* Important : Wavelan/Orinoco driver do it differently, but I suspect - * that they are broken. Somebody need to check that iwconfig - * report the proper values before we enable that - Jean II */ - wstats->qual.level = priv->ap ? 0L : (qual->ASL_currBSS + 0x100 - 100); - wstats->qual.noise = priv->ap ? 0L : (qual->ANL_currFC + 0x100 - 100); -#else /* WEXT_IN_DB */ - wstats->qual.level = priv->ap ? 0L : qual->ASL_currBSS; - wstats->qual.noise = priv->ap ? 0L : qual->ANL_currFC; -#endif /* WEXT_IN_DB */ - wstats->qual.updated = 7; - wstats->discard.nwid = 0L; /* tallies.txdiscardswrongsa is wrong! */ - wstats->discard.code = tallies.rxdiscardswepundecr; /* am i wrong?! */ - wstats->discard.misc = tallies.txdiscards; /* am i wrong?! */ - - _done: - DBFEXIT; - - return &wlandev->wstats; -} - -/* wireless extensions' ioctls */ int prism2wext_support_ioctl(netdevice_t *dev, struct iwreq *iwr, int cmd) { wlandevice_t *wlandev = (wlandevice_t*)dev->priv; diff --git a/src/shared/p80211metamsg.c b/src/shared/p80211metamsg.c index 21fe727..e7789f2 100644 --- a/src/shared/p80211metamsg.c +++ b/src/shared/p80211metamsg.c @@ -2476,6 +2476,100 @@ p80211meta_t MKREQMETANAME(lnxreq_ifstate)[] = { UINT32 MKREQMETASIZE(lnxreq_ifstate) = sizeof(MKREQMETANAME(lnxreq_ifstate))/sizeof(p80211meta_t); +/*--------------------------------------------------------------------*/ +/* metadata for the commsquality request message arguments */ +extern UINT32 MKREQMETASIZE(lnxreq_commsquality); + +p80211meta_t MKREQMETANAME(lnxreq_commsquality)[] = { +{ + /* name */ (char *)&(MKREQMETASIZE(lnxreq_commsquality)), + /* did */ 0, + /* flags */ 0, + /* min */ 0, + /* max */ 0, + /* maxlen */ 0, + /* minlen */ 0, + /* enumptr */ NULL, + /* collptr */ NULL, + /* totextptr */ NULL, + /* fromtextptr */ NULL, + /* validfunptr */ NULL +}, +{ + /* name */ MKITEMNAME("resultcode"), + /* did */ 0, + /* flags */ P80211ITEM_SETFLAGS(ISREQUIRED, 0UL, ISCONFIRM), + /* min */ 0, + /* max */ 0, + /* maxlen */ 0, + /* minlen */ 0, + /* enumptr */ &MKENUMNAME(resultcode), + /* collptr */ NULL, + /* totextptr */ p80211_totext_enumint, + /* fromtextptr */ p80211_fromtext_enumint, + /* validfunptr */ p80211_isvalid_enumint +}, +{ + /* name */ MKITEMNAME("dbm"), + /* did */ 0, + /* flags */ P80211ITEM_SETFLAGS(ISREQUIRED, 0UL, ISCONFIRM), + /* min */ 0, + /* max */ 0, + /* maxlen */ 0, + /* minlen */ 0, + /* enumptr */ &MKENUMNAME(truth), + /* collptr */ NULL, + /* totextptr */ p80211_totext_enumint, + /* fromtextptr */ p80211_fromtext_enumint, + /* validfunptr */ p80211_isvalid_enumint +}, +{ + /* name */ MKITEMNAME("link"), + /* did */ 0, + /* flags */ P80211ITEM_SETFLAGS(ISREQUIRED, ISREQUEST, 0UL), + /* min */ 0, + /* max */ 0, + /* maxlen */ 0, + /* minlen */ 0, + /* enumptr */ NULL, + /* collptr */ NULL, + /* totextptr */ p80211_totext_boundedint, + /* fromtextptr */ p80211_fromtext_boundedint, + /* validfunptr */ p80211_isvalid_boundedint +}, +{ + /* name */ MKITEMNAME("level"), + /* did */ 0, + /* flags */ P80211ITEM_SETFLAGS(ISREQUIRED, ISREQUEST, 0UL), + /* min */ 0, + /* max */ 0, + /* maxlen */ 0, + /* minlen */ 0, + /* enumptr */ NULL, + /* collptr */ NULL, + /* totextptr */ p80211_totext_boundedint, + /* fromtextptr */ p80211_fromtext_boundedint, + /* validfunptr */ p80211_isvalid_boundedint +}, +{ + /* name */ MKITEMNAME("noise"), + /* did */ 0, + /* flags */ P80211ITEM_SETFLAGS(ISREQUIRED, ISREQUEST, 0UL), + /* min */ 0, + /* max */ 0, + /* maxlen */ 0, + /* minlen */ 0, + /* enumptr */ NULL, + /* collptr */ NULL, + /* totextptr */ p80211_totext_boundedint, + /* fromtextptr */ p80211_fromtext_boundedint, + /* validfunptr */ p80211_isvalid_boundedint +}, +}; /* end of lnxreq_commsquality list */ + +UINT32 MKREQMETASIZE(lnxreq_commsquality) = + sizeof(MKREQMETANAME(lnxreq_commsquality))/sizeof(p80211meta_t); + /*--------------------------------------------------------------------*/ /* metadata for the hostwep request message arguments */ extern UINT32 MKREQMETASIZE(lnxreq_hostwep); @@ -2495,6 +2589,20 @@ p80211meta_t MKREQMETANAME(lnxreq_hostwep)[] = { /* fromtextptr */ NULL, /* validfunptr */ NULL }, +{ + /* name */ MKITEMNAME("resultcode"), + /* did */ 0, + /* flags */ P80211ITEM_SETFLAGS(ISREQUIRED, 0UL, ISCONFIRM), + /* min */ 0, + /* max */ 0, + /* maxlen */ 0, + /* minlen */ 0, + /* enumptr */ &MKENUMNAME(resultcode), + /* collptr */ NULL, + /* totextptr */ p80211_totext_enumint, + /* fromtextptr */ p80211_fromtext_enumint, + /* validfunptr */ p80211_isvalid_enumint +}, { /* name */ MKITEMNAME("decrypt"), /* did */ 0, @@ -4662,6 +4770,10 @@ grplistitem_t MKGRPMETANAME(lnxreq)[] = { "lnxreq_hostwep", MKREQMETANAME(lnxreq_hostwep) }, + { + "lnxreq_commsquality", + MKREQMETANAME(lnxreq_commsquality) + }, { "lnxreq_autojoin", MKREQMETANAME(lnxreq_autojoin)