prism2wext.c

来自「Linux的无线局域网方案是一个Linux设备驱动程序和子系统 一揽子方案的用」· C语言 代码 · 共 363 行

C
363
字号
/* prism2wext.c -*- linux-c -*- *     _     _   ___   _   _  _____  _   _   ___   __   _ *    | | _ | | / _ \ | | | || ____|| |_| | / _ \ |  \ | | *    | || || || /_\ || | | || ___| | ___ || /_\ ||   \| | *    | || || || ___ | \ | / | |___ | | | || ___ || |\   | * www.\_/ \_/ |_| |_|  \_/  |_____||_| |_||_| |_||_| \__|.de  * * Wireless Tools 10+ compatibility for linux-wlan-ng based on code * of wlancfg and orinoco_cs * * author:  Reyk Floeter <reyk@synack.de> * home:    https://www.wavehan.de/projekte/prism2/ * date:    10/04/2001 * version: 0.0.4 * * 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.  *//*================================================================*//* System Includes */#define __NO_VERSION__#define WAVEHAN 23#define WLAN_DBVAR prism2_debug#include <prism2/prism2wext.h>/* compatibility to wireless extensions */#if defined(__LINUX_WLAN__) && defined (__KERNEL__)#if WIRELESS_EXT > 10/* taken from orinoco.c ;-) */const long prism2wext_channel_freq[] = {	2412, 2417, 2422, 2427, 2432, 2437, 2442,	2447, 2452, 2457, 2462, 2467, 2472, 2484};#define NUM_CHANNELS (sizeof(prism2wext_channel_freq) / sizeof(prism2wext_channel_freq[0])) /** function declarations =============== *//* called by p80211wstats_get_wireless_stats for /proc/net/wireless */ iw_stats* prism2wext_get_wireless_stats(struct net_device *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;	iw_stats* 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 (iw_stats*) 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);		/* 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?! */		DBFEXIT;		return &wlandev->wstats;}/* wireless extensions' ioctls */ int prism2wext_support_ioctl(struct net_device *dev, struct iwreq *iwr, int cmd){	wlandevice_t *wlandev = (wlandevice_t*)dev->priv;	prism2sta_priv_t *priv = (prism2sta_priv_t*)wlandev->priv;	hfa384x_t *hw = priv->hw;	UINT8 bytebuf[HFA384x_BAP_DATALEN_MAX];	UINT16 *reqbuf = (UINT16*)bytebuf;	int err = 0, intval = -1;	DBFENTER; 	WLAN_LOG_DEBUG1(1, "received wireless extension- compatible ioctl #%d.\n", cmd);		switch (cmd) {	case SIOCSIWNAME: /* unused */		err = (-EOPNOTSUPP);		break;			case SIOCGIWNAME: /* get name == wireless protocol */		strcpy(iwr->u.name, "IEEE 802.11-b");/* IEEE							802.11-DS as							in orinoco.c?						     */         		break;			case SIOCSIWNWID:	case SIOCGIWNWID:		err = (-EOPNOTSUPP);		break;			case SIOCSIWFREQ: /* set channel */		intval = prism2wext_get_channel(&(iwr->u.freq)); 		/* check for valid channels */ 		if ((!intval) || (intval > NUM_CHANNELS))			return (-EFAULT);                 /* Where's the difference between cnfOwnChannel and 		 * CurrentChannel? 		 */      		err = hfa384x_drvr_setconfig(hw, HFA384x_RID_CNFOWNCHANNEL, &intval, HFA384x_RID_CNFOWNCHANNEL_LEN); 				break;	case SIOCGIWFREQ: /* get channel */		err = hfa384x_drvr_getconfig(hw, HFA384x_RID_CNFOWNCHANNEL, reqbuf, HFA384x_RID_CNFOWNCHANNEL_LEN); 		/* check for valid channels */ 		if ((!*reqbuf) || (*reqbuf > NUM_CHANNELS))			return (-EFAULT); 		/* return the correct frequency instead of a channel */		iwr->u.freq.e = 1;				iwr->u.freq.m = prism2wext_channel_freq[(*reqbuf)-1] * 100000;				break;	case SIOCSIWMODE: /* set operation mode */		err = (-EOPNOTSUPP);		break;			case SIOCGIWMODE: /* get operation mode */		err = priv->ap ? 0 : hfa384x_drvr_getconfig(hw, HFA384x_RID_CNFPORTTYPE, reqbuf, HFA384x_RID_CNFPORTTYPE_LEN);				/* Access Point, infrastructure or ADHOC? */		iwr->u.mode = priv->ap ? IW_MODE_MASTER : 			(*reqbuf ? IW_MODE_INFRA : IW_MODE_ADHOC); 				break;	case SIOCSIWSENS:	case SIOCGIWSENS:	case SIOCSIWRANGE:	case SIOCSIWPRIV:		case SIOCSIWSPY:	case SIOCGIWSPY:	case SIOCSIWAP: /* set access point MAC addresses (BSSID) */			err = (-EOPNOTSUPP);		break;	case SIOCGIWAP:	/* get access point MAC addresses (BSSID) */		err = hfa384x_drvr_getconfig(hw,					     HFA384x_RID_CURRENTBSSID,					     &(iwr->u.ap_addr.sa_data), HFA384x_RID_CURRENTBSSID_LEN);				/* it's an ARP- address */		iwr->u.ap_addr.sa_family = ARPHRD_ETHER;		break;	case SIOCGIWAPLIST:		case SIOCSIWESSID: /* set ESSID (network name) */		err = (-EOPNOTSUPP);		break;	case SIOCGIWESSID: /* get ESSID */		if (!priv->ap) {			err = prism2wext_get_string(hw, &(iwr->u.essid), HFA384x_RID_CURRENTSSID, HFA384x_RID_CURRENTSSID_LEN);		} else {			err = prism2wext_get_string(hw, &(iwr->u.essid), HFA384x_RID_CNFOWNSSID, HFA384x_RID_CNFOWNSSID_LEN);		}		break;	case SIOCSIWNICKN: /* set node name/nickname */			err = (-EOPNOTSUPP);		break;	case SIOCGIWNICKN: /* get node name/nickname */		err = prism2wext_get_string(hw, &(iwr->u.data), HFA384x_RID_CNFOWNNAME, HFA384x_RID_CNFOWNNAME_LEN);		break;	case SIOCSIWRATE: /* set default bit rate (bps) */		case SIOCGIWRATE: /* get default bit rate (bps) */		case SIOCSIWRTS:		case SIOCGIWRTS:		case SIOCSIWFRAG:		case SIOCGIWFRAG:		case SIOCSIWTXPOW:		case SIOCGIWTXPOW:		case SIOCSIWRETRY:		case SIOCGIWRETRY:		case SIOCSIWENCODE: /* set encoding token & mode */		case SIOCGIWENCODE: /* get encoding token & mode */		err = (-EOPNOTSUPP);		break;			case SIOCSIWPOWER:		case SIOCGIWPOWER:		err = (-EOPNOTSUPP);		break;	case SIOCGIWRANGE:		/* Static meta data about the other ioctls */		if(iwr->u.data.pointer != NULL) {			struct iw_range range;			iwr->u.data.length = sizeof(range);			memset(&range, 0, sizeof(range));#if WIRELESS_EXT > 10			range.we_version_compiled = WIRELESS_EXT;			range.we_version_source = 9;#endif /* WIRELESS_EXT > 10 */			/* Max of /proc/net/wireless */			range.max_qual.qual = 100;	/* ??? */#ifdef WEXT_IN_DB			range.max_qual.level = 0x100 - 108;	/* -108 dBm */			range.max_qual.noise = 0x100 - 108;	/* -108 dBm */#else	/* WEXT_IN_DB */			range.max_qual.level = 100;	/* ??? */			range.max_qual.noise = 100;	/* ??? */#endif	/* WEXT_IN_DB */			/* There are lots of other goodies that should go			 * in there, it will come in its own time - Jean II */			/* Push that up to the caller */			if (copy_to_user(iwr->u.data.pointer, &range, sizeof(range)))				err = -EFAULT;		}		break;	case SIOCGIWPRIV: /* get private ioctls for iwpriv. This is			     not necessary and not implemented but			     i'll return a useless dummy for			     demonstration. */ 		WLAN_LOG_DEBUG1(1, "%s: SIOCGIWPRIV\n", dev->name);		if (iwr->u.data.pointer) {			struct iw_priv_args privtab[] = {				{ SIOCGIWPRIV, 0, 0, "DUMMY;-)" }, /* no action */			};						err = verify_area(VERIFY_WRITE, iwr->u.data.pointer, sizeof(privtab));			if (err)				break;						iwr->u.data.length = sizeof(privtab) / sizeof(privtab[0]);			if (copy_to_user(iwr->u.data.pointer, privtab, sizeof(privtab)))				err = -EFAULT;		}		break;	default:		err = (-EOPNOTSUPP);		break;	}	DBFEXIT;	return (err);}/* determine a channel */int prism2wext_get_channel(struct iw_freq *iwf) {	int mult = 1, chan = -1, i;	DBFENTER;		if ( (iwf->e == 0) && (iwf->m <= 1000) ) {		/* input is a channel number */				chan = iwf->m;	} else {		/* input is a frequency - search the table */		for (i = 0; i < (6 - iwf->e); i++)			mult *= 10;				for (i = 0; i < NUM_CHANNELS; i++)			if (iwf->m == (prism2wext_channel_freq[i] * mult))				chan = i+1;	}	DBFEXIT;		return chan;}	/* return a string value to user space */int prism2wext_get_string(hfa384x_t *hw, struct iw_point *erq, UINT16 rid, UINT16 len) {	UINT8 bytebuf[len];	UINT8 pstrbuf[len];	hfa384x_bytestr_t *bytestr = (hfa384x_bytestr_t*)bytebuf;	p80211pstrd_t *pstr = (p80211pstrd_t*)pstrbuf;	int err = 0;	DBFENTER;		err = hfa384x_drvr_getconfig(hw, rid, bytebuf, len); 	if (err)		return (err);		prism2mgmt_bytestr2pstr(bytestr, pstr); /* convert string to						   host format */		erq->flags = 1;	erq->length = pstr->len;		WLAN_LOG_DEBUG1(1, "returning bytestr of %d bytes\n", pstr->len);		if(erq->pointer) {		if(copy_to_user(erq->pointer, (char*)pstr->data, erq->length))			return (-EFAULT);	}		DBFEXIT;	return (err);}#endif#endif /* compatibility to wireless extensions */

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?