📄 isl_ioctl.c
字号:
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); u8 wpa_ie[MAX_WPA_IE_LEN]; size_t wpa_ie_len; /* 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 = bss->channel; iwe.u.freq.e = 6; 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); /* Add WPA/RSN Information Element, if any */ wpa_ie_len = prism54_wpa_bss_ie_get(priv, bss->address, wpa_ie); if (wpa_ie_len > 0) { iwe.cmd = IWEVGENIE; iwe.u.data.length = min(wpa_ie_len, (size_t)MAX_WPA_IE_LEN); current_ev = iwe_stream_add_point(current_ev, end_buf, &iwe, wpa_ie); } /* Do the bitrates */ { char * current_val = current_ev + IW_EV_LCP_LEN; int i; int mask; iwe.cmd = SIOCGIWRATE; /* Those two flags are ignored... */ iwe.u.bitrate.fixed = iwe.u.bitrate.disabled = 0; /* Parse the bitmask */ mask = 0x1; for(i = 0; i < sizeof(scan_rate_list); i++) { if(bss->rates & mask) { iwe.u.bitrate.value = (scan_rate_list[i] * 500000); current_val = iwe_stream_add_value(current_ev, current_val, end_buf, &iwe, IW_EV_PARAM_LEN); } mask <<= 1; } /* Check if we added any event */ if ((current_val - current_ev) > IW_EV_LCP_LEN) current_ev = current_val; } return current_ev;}static 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. * The old API, using SIOCGIWAPLIST, had a hard limit of IW_MAX_AP=64. * The new API, using SIOCGIWSCAN, is only limited by the buffer size. * WE-14->WE-16, the buffer is limited to IW_SCAN_MAX_DATA bytes. * Starting with WE-17, the buffer can be as big as needed. * 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 < (int) bsslist->nr; i++) { current_ev = prism54_translate_bss(ndev, current_ev, extra + dwrq->length, &(bsslist->bsslist[i]), noise); /* Check if there is space for one more entry */ if((extra + dwrq->length - current_ev) <= IW_EV_ADDR_LEN) { /* Ask user space to try again with a bigger buffer */ rvalue = -E2BIG; break; } } 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 > 32) return -E2BIG; essid.length = dwrq->length; 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 too big, trunk it */ dwrq->length = min((u8)IW_ESSID_MAX_SIZE, essid->length); } 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); 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){ islpci_private *priv = netdev_priv(ndev); return mgt_set_request(priv, DOT11_OID_RTSTHRESH, 0, &vwrq->value);}static intprism54_get_rts(struct net_device *ndev, struct iw_request_info *info, struct iw_param *vwrq, char *extra){ islpci_private *priv = netdev_priv(ndev); union oid_res_t r; int rvalue; /* get the rts threshold */ rvalue = mgt_get_request(priv, DOT11_OID_RTSTHRESH, 0, NULL, &r); vwrq->value = r.u; return rvalue;}static intprism54_set_frag(struct net_device *ndev, struct iw_request_info *info, struct iw_param *vwrq, char *extra){ islpci_private *priv = netdev_priv(ndev); return mgt_set_request(priv, DOT11_OID_FRAGTHRESH, 0, &vwrq->value);}static intprism54_get_frag(struct net_device *ndev, struct iw_request_info *info, struct iw_param *vwrq, char *extra){ islpci_private *priv = netdev_priv(ndev); union oid_res_t r; int rvalue; rvalue = mgt_get_request(priv, DOT11_OID_FRAGTHRESH, 0, NULL, &r); vwrq->value = r.u; return rvalue;}/* Here we have (min,max) = max retries for (small frames, big frames). Where * big frame <=> bigger than the rts threshold * small frame <=> smaller than the rts threshold * This is not really the behavior expected by the wireless tool but it seems * to be a common behavior in other drivers. */static intprism54_set_retry(struct net_device *ndev, struct iw_request_info *info, struct iw_param *vwrq, char *extra){ islpci_private *priv = netdev_priv(ndev); u32 slimit = 0, llimit = 0; /* short and long limit */ u32 lifetime = 0; int rvalue = 0; if (vwrq->disabled) /* we cannot disable this feature */ return -EINVAL; if (vwrq->flags & IW_RETRY_LIMIT) { if (vwrq->flags & IW_RETRY_SHORT) slimit = vwrq->value; else if (vwrq->flags & IW_RETRY_LONG) llimit = vwrq->value; else { /* we are asked to set both */ slimit = vwrq->value; llimit = vwrq->value; } } if (vwrq->flags & IW_RETRY_LIFETIME) /* Wireless tools use us unit while the device uses 1024 us unit */ lifetime = vwrq->value / 1024; /* now set what is requested */ if (slimit) rvalue = mgt_set_request(priv, DOT11_OID_SHORTRETRIES, 0, &slimit); if (llimit) rvalue |= mgt_set_request(priv, DOT11_OID_LONGRETRIES, 0, &llimit); if (lifetime) rvalue |= mgt_set_request(priv, DOT11_OID_MAXTXLIFETIME, 0, &lifetime); return rvalue;}static intprism54_get_retry(struct net_device *ndev, struct iw_request_info *info, struct iw_param *vwrq, char *extra){ islpci_private *priv = netdev_priv(ndev); union oid_res_t r; int rvalue = 0; vwrq->disabled = 0; /* It cannot be disabled */ if ((vwrq->flags & IW_RETRY_TYPE) == IW_RETRY_LIFETIME) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -