isl_ioctl.c

来自「优龙2410linux2.6.8内核源代码」· C语言 代码 · 共 2,269 行 · 第 1/5 页

C
2,269
字号
	/* 128(104) bits WEP */	range->encoding_size[1] = 13;	/* 256 bits for WPA-PSK */	range->encoding_size[2] = 32;	/* 4 keys are allowed */	range->max_encoding_tokens = 4;	/* we don't know the quality range... */	range->max_qual.level = 0;	range->max_qual.noise = 0;	range->max_qual.qual = 0;	/* these value describe an average quality. Needs more tweaking... */	range->avg_qual.level = -80;	/* -80 dBm */	range->avg_qual.noise = 0;	/* don't know what to put here */	range->avg_qual.qual = 0;	range->sensitivity = 200;	/* retry limit capabilities */	range->retry_capa = IW_RETRY_LIMIT | IW_RETRY_LIFETIME;	range->retry_flags = IW_RETRY_LIMIT;	range->r_time_flags = IW_RETRY_LIFETIME;	/* I don't know the range. Put stupid things here */	range->min_retry = 1;	range->max_retry = 65535;	range->min_r_time = 1024;	range->max_r_time = 65535 * 1024;	/* txpower is supported in dBm's */	range->txpower_capa = IW_TXPOW_DBM;	if (islpci_get_state(priv) < PRV_STATE_INIT)		return 0;	/* Request the device for the supported frequencies	 * not really relevant since some devices will report the 5 GHz band	 * frequencies even if they don't support them.	 */	rvalue =	    mgt_get_request(priv, DOT11_OID_SUPPORTEDFREQUENCIES, 0, NULL, &r);	freq = r.ptr;	range->num_channels = freq->nr;	range->num_frequency = freq->nr;	m = min(IW_MAX_FREQUENCIES, (int) freq->nr);	for (i = 0; i < m; i++) {		range->freq[i].m = freq->mhz[i];		range->freq[i].e = 6;		range->freq[i].i = channel_of_freq(freq->mhz[i]);	}	kfree(freq);	rvalue |= mgt_get_request(priv, DOT11_OID_SUPPORTEDRATES, 0, NULL, &r);	data = r.ptr;	/* We got an array of char. It is NULL terminated. */	i = 0;	while ((i < IW_MAX_BITRATES) && (*data != 0)) {		/*       the result must be in bps. The card gives us 500Kbps */		range->bitrate[i] = *data * 500000;		i++;		data++;	}	range->num_bitrates = i;	kfree(r.ptr);	return rvalue;}/* Set AP address*/static intprism54_set_wap(struct net_device *ndev, struct iw_request_info *info,		struct sockaddr *awrq, char *extra){	islpci_private *priv = netdev_priv(ndev);	char bssid[6];	int rvalue;	if (awrq->sa_family != ARPHRD_ETHER)		return -EINVAL;	/* prepare the structure for the set object */	memcpy(&bssid[0], awrq->sa_data, 6);	/* set the bssid -- does this make sense when in AP mode? */	rvalue = mgt_set_request(priv, DOT11_OID_BSSID, 0, &bssid);	return (rvalue ? rvalue : -EINPROGRESS);	/* Call commit handler */}/* get AP address*/static intprism54_get_wap(struct net_device *ndev, struct iw_request_info *info,		struct sockaddr *awrq, char *extra){	islpci_private *priv = netdev_priv(ndev);	union oid_res_t r;	int rvalue;	rvalue = mgt_get_request(priv, DOT11_OID_BSSID, 0, NULL, &r);	memcpy(awrq->sa_data, r.ptr, 6);	awrq->sa_family = ARPHRD_ETHER;	kfree(r.ptr);	return rvalue;}static intprism54_set_scan(struct net_device *dev, struct iw_request_info *info,		 struct iw_param *vwrq, char *extra){	/* hehe the device does this automagicaly */	return 0;}/* a little helper that will translate our data into a card independent * format that the Wireless Tools will understand. This was inspired by * the "Aironet driver for 4500 and 4800 series cards" (GPL) */static char *prism54_translate_bss(struct net_device *ndev, char *current_ev,		      char *end_buf, struct obj_bss *bss, char noise){	struct iw_event iwe;	/* Temporary buffer */	short cap;	islpci_private *priv = netdev_priv(ndev);	/* The first entry must be the MAC address */	memcpy(iwe.u.ap_addr.sa_data, bss->address, 6);	iwe.u.ap_addr.sa_family = ARPHRD_ETHER;	iwe.cmd = SIOCGIWAP;	current_ev =	    iwe_stream_add_event(current_ev, end_buf, &iwe, IW_EV_ADDR_LEN);	/* The following entries will be displayed in the same order we give them */	/* The ESSID. */	iwe.u.data.length = bss->ssid.length;	iwe.u.data.flags = 1;	iwe.cmd = SIOCGIWESSID;	current_ev = iwe_stream_add_point(current_ev, end_buf,					  &iwe, bss->ssid.octets);	/* Capabilities */#define CAP_ESS 0x01#define CAP_IBSS 0x02#define CAP_CRYPT 0x10	/* Mode */	cap = bss->capinfo;	iwe.u.mode = 0;	if (cap & CAP_ESS)		iwe.u.mode = IW_MODE_MASTER;	else if (cap & CAP_IBSS)		iwe.u.mode = IW_MODE_ADHOC;	iwe.cmd = SIOCGIWMODE;	if (iwe.u.mode)		current_ev =		    iwe_stream_add_event(current_ev, end_buf, &iwe,					 IW_EV_UINT_LEN);	/* Encryption capability */	if (cap & CAP_CRYPT)		iwe.u.data.flags = IW_ENCODE_ENABLED | IW_ENCODE_NOKEY;	else		iwe.u.data.flags = IW_ENCODE_DISABLED;	iwe.u.data.length = 0;	iwe.cmd = SIOCGIWENCODE;	current_ev = iwe_stream_add_point(current_ev, end_buf, &iwe, NULL);	/* Add frequency. (short) bss->channel is the frequency in MHz */	iwe.u.freq.m = channel_of_freq(bss->channel);	iwe.u.freq.e = 0;	iwe.cmd = SIOCGIWFREQ;	current_ev =	    iwe_stream_add_event(current_ev, end_buf, &iwe, IW_EV_FREQ_LEN);	/* Add quality statistics */	iwe.u.qual.level = bss->rssi;	iwe.u.qual.noise = noise;	/* do a simple SNR for quality */	iwe.u.qual.qual = bss->rssi - noise;	iwe.cmd = IWEVQUAL;	current_ev =	    iwe_stream_add_event(current_ev, end_buf, &iwe, IW_EV_QUAL_LEN);	if (priv->wpa) {		u8 wpa_ie[MAX_WPA_IE_LEN];		char *buf, *p;		size_t wpa_ie_len;		int i;		wpa_ie_len = prism54_wpa_ie_get(priv, bss->address, wpa_ie);		if (wpa_ie_len > 0 &&		    (buf = kmalloc(wpa_ie_len * 2 + 10, GFP_ATOMIC))) {			p = buf;			p += sprintf(p, "wpa_ie=");			for (i = 0; i < wpa_ie_len; i++) {				p += sprintf(p, "%02x", wpa_ie[i]);			}			memset(&iwe, 0, sizeof (iwe));			iwe.cmd = IWEVCUSTOM;			iwe.u.data.length = strlen(buf);			current_ev = iwe_stream_add_point(current_ev, end_buf,							  &iwe, buf);			kfree(buf);		}	}	return current_ev;}intprism54_get_scan(struct net_device *ndev, struct iw_request_info *info,		 struct iw_point *dwrq, char *extra){	islpci_private *priv = netdev_priv(ndev);	int i, rvalue;	struct obj_bsslist *bsslist;	u32 noise = 0;	char *current_ev = extra;	union oid_res_t r;	if (islpci_get_state(priv) < PRV_STATE_INIT) {		/* device is not ready, fail gently */		dwrq->length = 0;		return 0;	}	/* first get the noise value. We will use it to report the link quality */	rvalue = mgt_get_request(priv, DOT11_OID_NOISEFLOOR, 0, NULL, &r);	noise = r.u;	/* Ask the device for a list of known bss. We can report at most	 * IW_MAX_AP=64 to the range struct. But the device won't repport anything	 * if you change the value of IWMAX_BSS=24.	 */	rvalue |= mgt_get_request(priv, DOT11_OID_BSSLIST, 0, NULL, &r);	bsslist = r.ptr;	/* ok now, scan the list and translate its info */	for (i = 0; i < min(IW_MAX_AP, (int) bsslist->nr); i++)		current_ev = prism54_translate_bss(ndev, current_ev,						   extra + IW_SCAN_MAX_DATA,						   &(bsslist->bsslist[i]),						   noise);	kfree(bsslist);	dwrq->length = (current_ev - extra);	dwrq->flags = 0;	/* todo */	return rvalue;}static intprism54_set_essid(struct net_device *ndev, struct iw_request_info *info,		  struct iw_point *dwrq, char *extra){	islpci_private *priv = netdev_priv(ndev);	struct obj_ssid essid;	memset(essid.octets, 0, 33);	/* Check if we were asked for `any' */	if (dwrq->flags && dwrq->length) {		if (dwrq->length > min(33, IW_ESSID_MAX_SIZE + 1))			return -E2BIG;		essid.length = dwrq->length - 1;		memcpy(essid.octets, extra, dwrq->length);	} else		essid.length = 0;	if (priv->iw_mode != IW_MODE_MONITOR)		return mgt_set_request(priv, DOT11_OID_SSID, 0, &essid);	/* If in monitor mode, just save to mib */	mgt_set(priv, DOT11_OID_SSID, &essid);	return 0;}static intprism54_get_essid(struct net_device *ndev, struct iw_request_info *info,		  struct iw_point *dwrq, char *extra){	islpci_private *priv = netdev_priv(ndev);	struct obj_ssid *essid;	union oid_res_t r;	int rvalue;	rvalue = mgt_get_request(priv, DOT11_OID_SSID, 0, NULL, &r);	essid = r.ptr;	if (essid->length) {		dwrq->flags = 1;	/* set ESSID to ON for Wireless Extensions */		/* if it is to big, trunk it */		dwrq->length = min(IW_ESSID_MAX_SIZE, essid->length + 1);	} else {		dwrq->flags = 0;		dwrq->length = 0;	}	essid->octets[essid->length] = '\0';	memcpy(extra, essid->octets, dwrq->length);	kfree(essid);	return rvalue;}/* Provides no functionality, just completes the ioctl. In essence this is a  * just a cosmetic ioctl. */static intprism54_set_nick(struct net_device *ndev, struct iw_request_info *info,		 struct iw_point *dwrq, char *extra){	islpci_private *priv = netdev_priv(ndev);	if (dwrq->length > IW_ESSID_MAX_SIZE)		return -E2BIG;	down_write(&priv->mib_sem);	memset(priv->nickname, 0, sizeof (priv->nickname));	memcpy(priv->nickname, extra, dwrq->length);	up_write(&priv->mib_sem);	return 0;}static intprism54_get_nick(struct net_device *ndev, struct iw_request_info *info,		 struct iw_point *dwrq, char *extra){	islpci_private *priv = netdev_priv(ndev);	dwrq->length = 0;	down_read(&priv->mib_sem);	dwrq->length = strlen(priv->nickname) + 1;	memcpy(extra, priv->nickname, dwrq->length);	up_read(&priv->mib_sem);	return 0;}/* Set the allowed Bitrates */static intprism54_set_rate(struct net_device *ndev,		 struct iw_request_info *info,		 struct iw_param *vwrq, char *extra){	islpci_private *priv = netdev_priv(ndev);	u32 rate, profile;	char *data;	int ret, i;	union oid_res_t r;	if (vwrq->value == -1) {		/* auto mode. No limit. */		profile = 1;		return mgt_set_request(priv, DOT11_OID_PROFILES, 0, &profile);	}	ret = mgt_get_request(priv, DOT11_OID_SUPPORTEDRATES, 0, NULL, &r);	if (ret) {		kfree(r.ptr);		return ret;	}	rate = (u32) (vwrq->value / 500000);	data = r.ptr;	i = 0;	while (data[i]) {		if (rate && (data[i] == rate)) {			break;		}		if (vwrq->value == i) {			break;		}		data[i] |= 0x80;		i++;	}	if (!data[i]) {		kfree(r.ptr);		return -EINVAL;	}	data[i] |= 0x80;	data[i + 1] = 0;	/* Now, check if we want a fixed or auto value */	if (vwrq->fixed) {		data[0] = data[i];		data[1] = 0;	}/*	i = 0;	printk("prism54 rate: ");	while(data[i]) {		printk("%u ", data[i]);		i++;	}	printk("0\n");*/	profile = -1;	ret = mgt_set_request(priv, DOT11_OID_PROFILES, 0, &profile);	ret |= mgt_set_request(priv, DOT11_OID_EXTENDEDRATES, 0, data);	ret |= mgt_set_request(priv, DOT11_OID_RATES, 0, data);	kfree(r.ptr);	return ret;}/* Get the current bit rate */static intprism54_get_rate(struct net_device *ndev,		 struct iw_request_info *info,		 struct iw_param *vwrq, char *extra){	islpci_private *priv = netdev_priv(ndev);	int rvalue;	char *data;	union oid_res_t r;	/* Get the current bit rate */	if ((rvalue = mgt_get_request(priv, GEN_OID_LINKSTATE, 0, NULL, &r)))		return rvalue;	vwrq->value = r.u * 500000;	/* request the device for the enabled rates */	rvalue = mgt_get_request(priv, DOT11_OID_RATES, 0, NULL, &r);	if (rvalue) {		kfree(r.ptr);		return rvalue;	}	data = r.ptr;	vwrq->fixed = (data[0] != 0) && (data[1] == 0);	kfree(r.ptr);	return 0;}static intprism54_set_rts(struct net_device *ndev, struct iw_request_info *info,		struct iw_param *vwrq, char *extra){

⌨️ 快捷键说明

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