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 + -
显示快捷键?