|
@@ -1583,519 +1583,6 @@ static int orinoco_ioctl_getrid(struct net_device *dev,
|
|
return err;
|
|
return err;
|
|
}
|
|
}
|
|
|
|
|
|
-/* Trigger a scan (look for other cells in the vicinity) */
|
|
|
|
-static int orinoco_ioctl_setscan(struct net_device *dev,
|
|
|
|
- struct iw_request_info *info,
|
|
|
|
- struct iw_point *srq,
|
|
|
|
- char *extra)
|
|
|
|
-{
|
|
|
|
- struct orinoco_private *priv = ndev_priv(dev);
|
|
|
|
- hermes_t *hw = &priv->hw;
|
|
|
|
- struct iw_scan_req *si = (struct iw_scan_req *) extra;
|
|
|
|
- int err = 0;
|
|
|
|
- unsigned long flags;
|
|
|
|
-
|
|
|
|
- /* Note : you may have realised that, as this is a SET operation,
|
|
|
|
- * this is privileged and therefore a normal user can't
|
|
|
|
- * perform scanning.
|
|
|
|
- * This is not an error, while the device perform scanning,
|
|
|
|
- * traffic doesn't flow, so it's a perfect DoS...
|
|
|
|
- * Jean II */
|
|
|
|
-
|
|
|
|
- if (orinoco_lock(priv, &flags) != 0)
|
|
|
|
- return -EBUSY;
|
|
|
|
-
|
|
|
|
- /* Scanning with port 0 disabled would fail */
|
|
|
|
- if (!netif_running(dev)) {
|
|
|
|
- err = -ENETDOWN;
|
|
|
|
- goto out;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- /* In monitor mode, the scan results are always empty.
|
|
|
|
- * Probe responses are passed to the driver as received
|
|
|
|
- * frames and could be processed in software. */
|
|
|
|
- if (priv->iw_mode == NL80211_IFTYPE_MONITOR) {
|
|
|
|
- err = -EOPNOTSUPP;
|
|
|
|
- goto out;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- /* Note : because we don't lock out the irq handler, the way
|
|
|
|
- * we access scan variables in priv is critical.
|
|
|
|
- * o scan_inprogress : not touched by irq handler
|
|
|
|
- * o scan_mode : not touched by irq handler
|
|
|
|
- * Before modifying anything on those variables, please think hard !
|
|
|
|
- * Jean II */
|
|
|
|
-
|
|
|
|
- /* Save flags */
|
|
|
|
- priv->scan_mode = srq->flags;
|
|
|
|
-
|
|
|
|
- /* Always trigger scanning, even if it's in progress.
|
|
|
|
- * This way, if the info frame get lost, we will recover somewhat
|
|
|
|
- * gracefully - Jean II */
|
|
|
|
-
|
|
|
|
- if (priv->has_hostscan) {
|
|
|
|
- switch (priv->firmware_type) {
|
|
|
|
- case FIRMWARE_TYPE_SYMBOL:
|
|
|
|
- err = hermes_write_wordrec(hw, USER_BAP,
|
|
|
|
- HERMES_RID_CNFHOSTSCAN_SYMBOL,
|
|
|
|
- HERMES_HOSTSCAN_SYMBOL_ONCE |
|
|
|
|
- HERMES_HOSTSCAN_SYMBOL_BCAST);
|
|
|
|
- break;
|
|
|
|
- case FIRMWARE_TYPE_INTERSIL: {
|
|
|
|
- __le16 req[3];
|
|
|
|
-
|
|
|
|
- req[0] = cpu_to_le16(0x3fff); /* All channels */
|
|
|
|
- req[1] = cpu_to_le16(0x0001); /* rate 1 Mbps */
|
|
|
|
- req[2] = 0; /* Any ESSID */
|
|
|
|
- err = HERMES_WRITE_RECORD(hw, USER_BAP,
|
|
|
|
- HERMES_RID_CNFHOSTSCAN, &req);
|
|
|
|
- }
|
|
|
|
- break;
|
|
|
|
- case FIRMWARE_TYPE_AGERE:
|
|
|
|
- if (priv->scan_mode & IW_SCAN_THIS_ESSID) {
|
|
|
|
- struct hermes_idstring idbuf;
|
|
|
|
- size_t len = min(sizeof(idbuf.val),
|
|
|
|
- (size_t) si->essid_len);
|
|
|
|
- idbuf.len = cpu_to_le16(len);
|
|
|
|
- memcpy(idbuf.val, si->essid, len);
|
|
|
|
-
|
|
|
|
- err = hermes_write_ltv(hw, USER_BAP,
|
|
|
|
- HERMES_RID_CNFSCANSSID_AGERE,
|
|
|
|
- HERMES_BYTES_TO_RECLEN(len + 2),
|
|
|
|
- &idbuf);
|
|
|
|
- } else
|
|
|
|
- err = hermes_write_wordrec(hw, USER_BAP,
|
|
|
|
- HERMES_RID_CNFSCANSSID_AGERE,
|
|
|
|
- 0); /* Any ESSID */
|
|
|
|
- if (err)
|
|
|
|
- break;
|
|
|
|
-
|
|
|
|
- if (priv->has_ext_scan) {
|
|
|
|
- /* Clear scan results at the start of
|
|
|
|
- * an extended scan */
|
|
|
|
- orinoco_clear_scan_results(priv,
|
|
|
|
- msecs_to_jiffies(15000));
|
|
|
|
-
|
|
|
|
- /* TODO: Is this available on older firmware?
|
|
|
|
- * Can we use it to scan specific channels
|
|
|
|
- * for IW_SCAN_THIS_FREQ? */
|
|
|
|
- err = hermes_write_wordrec(hw, USER_BAP,
|
|
|
|
- HERMES_RID_CNFSCANCHANNELS2GHZ,
|
|
|
|
- 0x7FFF);
|
|
|
|
- if (err)
|
|
|
|
- goto out;
|
|
|
|
-
|
|
|
|
- err = hermes_inquire(hw,
|
|
|
|
- HERMES_INQ_CHANNELINFO);
|
|
|
|
- } else
|
|
|
|
- err = hermes_inquire(hw, HERMES_INQ_SCAN);
|
|
|
|
- break;
|
|
|
|
- }
|
|
|
|
- } else
|
|
|
|
- err = hermes_inquire(hw, HERMES_INQ_SCAN);
|
|
|
|
-
|
|
|
|
- /* One more client */
|
|
|
|
- if (!err)
|
|
|
|
- priv->scan_inprogress = 1;
|
|
|
|
-
|
|
|
|
- out:
|
|
|
|
- orinoco_unlock(priv, &flags);
|
|
|
|
- return err;
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-#define MAX_CUSTOM_LEN 64
|
|
|
|
-
|
|
|
|
-/* Translate scan data returned from the card to a card independant
|
|
|
|
- * format that the Wireless Tools will understand - Jean II */
|
|
|
|
-static inline char *orinoco_translate_scan(struct net_device *dev,
|
|
|
|
- struct iw_request_info *info,
|
|
|
|
- char *current_ev,
|
|
|
|
- char *end_buf,
|
|
|
|
- union hermes_scan_info *bss,
|
|
|
|
- unsigned long last_scanned)
|
|
|
|
-{
|
|
|
|
- struct orinoco_private *priv = ndev_priv(dev);
|
|
|
|
- u16 capabilities;
|
|
|
|
- u16 channel;
|
|
|
|
- struct iw_event iwe; /* Temporary buffer */
|
|
|
|
- char custom[MAX_CUSTOM_LEN];
|
|
|
|
-
|
|
|
|
- memset(&iwe, 0, sizeof(iwe));
|
|
|
|
-
|
|
|
|
- /* First entry *MUST* be the AP MAC address */
|
|
|
|
- iwe.cmd = SIOCGIWAP;
|
|
|
|
- iwe.u.ap_addr.sa_family = ARPHRD_ETHER;
|
|
|
|
- memcpy(iwe.u.ap_addr.sa_data, bss->a.bssid, ETH_ALEN);
|
|
|
|
- current_ev = iwe_stream_add_event(info, current_ev, end_buf,
|
|
|
|
- &iwe, IW_EV_ADDR_LEN);
|
|
|
|
-
|
|
|
|
- /* Other entries will be displayed in the order we give them */
|
|
|
|
-
|
|
|
|
- /* Add the ESSID */
|
|
|
|
- iwe.u.data.length = le16_to_cpu(bss->a.essid_len);
|
|
|
|
- if (iwe.u.data.length > 32)
|
|
|
|
- iwe.u.data.length = 32;
|
|
|
|
- iwe.cmd = SIOCGIWESSID;
|
|
|
|
- iwe.u.data.flags = 1;
|
|
|
|
- current_ev = iwe_stream_add_point(info, current_ev, end_buf,
|
|
|
|
- &iwe, bss->a.essid);
|
|
|
|
-
|
|
|
|
- /* Add mode */
|
|
|
|
- iwe.cmd = SIOCGIWMODE;
|
|
|
|
- capabilities = le16_to_cpu(bss->a.capabilities);
|
|
|
|
- if (capabilities & (WLAN_CAPABILITY_ESS | WLAN_CAPABILITY_IBSS)) {
|
|
|
|
- if (capabilities & WLAN_CAPABILITY_ESS)
|
|
|
|
- iwe.u.mode = IW_MODE_MASTER;
|
|
|
|
- else
|
|
|
|
- iwe.u.mode = IW_MODE_ADHOC;
|
|
|
|
- current_ev = iwe_stream_add_event(info, current_ev, end_buf,
|
|
|
|
- &iwe, IW_EV_UINT_LEN);
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- channel = bss->s.channel;
|
|
|
|
- if ((channel >= 1) && (channel <= NUM_CHANNELS)) {
|
|
|
|
- /* Add channel and frequency */
|
|
|
|
- iwe.cmd = SIOCGIWFREQ;
|
|
|
|
- iwe.u.freq.m = channel;
|
|
|
|
- iwe.u.freq.e = 0;
|
|
|
|
- current_ev = iwe_stream_add_event(info, current_ev, end_buf,
|
|
|
|
- &iwe, IW_EV_FREQ_LEN);
|
|
|
|
-
|
|
|
|
- iwe.u.freq.m = ieee80211_dsss_chan_to_freq(channel) * 100000;
|
|
|
|
- iwe.u.freq.e = 1;
|
|
|
|
- current_ev = iwe_stream_add_event(info, current_ev, end_buf,
|
|
|
|
- &iwe, IW_EV_FREQ_LEN);
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- /* Add quality statistics. level and noise in dB. No link quality */
|
|
|
|
- iwe.cmd = IWEVQUAL;
|
|
|
|
- iwe.u.qual.updated = IW_QUAL_DBM | IW_QUAL_QUAL_INVALID;
|
|
|
|
- iwe.u.qual.level = (__u8) le16_to_cpu(bss->a.level) - 0x95;
|
|
|
|
- iwe.u.qual.noise = (__u8) le16_to_cpu(bss->a.noise) - 0x95;
|
|
|
|
- /* Wireless tools prior to 27.pre22 will show link quality
|
|
|
|
- * anyway, so we provide a reasonable value. */
|
|
|
|
- if (iwe.u.qual.level > iwe.u.qual.noise)
|
|
|
|
- iwe.u.qual.qual = iwe.u.qual.level - iwe.u.qual.noise;
|
|
|
|
- else
|
|
|
|
- iwe.u.qual.qual = 0;
|
|
|
|
- current_ev = iwe_stream_add_event(info, current_ev, end_buf,
|
|
|
|
- &iwe, IW_EV_QUAL_LEN);
|
|
|
|
-
|
|
|
|
- /* Add encryption capability */
|
|
|
|
- iwe.cmd = SIOCGIWENCODE;
|
|
|
|
- if (capabilities & WLAN_CAPABILITY_PRIVACY)
|
|
|
|
- iwe.u.data.flags = IW_ENCODE_ENABLED | IW_ENCODE_NOKEY;
|
|
|
|
- else
|
|
|
|
- iwe.u.data.flags = IW_ENCODE_DISABLED;
|
|
|
|
- iwe.u.data.length = 0;
|
|
|
|
- current_ev = iwe_stream_add_point(info, current_ev, end_buf,
|
|
|
|
- &iwe, NULL);
|
|
|
|
-
|
|
|
|
- /* Bit rate is not available in Lucent/Agere firmwares */
|
|
|
|
- if (priv->firmware_type != FIRMWARE_TYPE_AGERE) {
|
|
|
|
- char *current_val = current_ev + iwe_stream_lcp_len(info);
|
|
|
|
- int i;
|
|
|
|
- int step;
|
|
|
|
-
|
|
|
|
- if (priv->firmware_type == FIRMWARE_TYPE_SYMBOL)
|
|
|
|
- step = 2;
|
|
|
|
- else
|
|
|
|
- step = 1;
|
|
|
|
-
|
|
|
|
- iwe.cmd = SIOCGIWRATE;
|
|
|
|
- /* Those two flags are ignored... */
|
|
|
|
- iwe.u.bitrate.fixed = iwe.u.bitrate.disabled = 0;
|
|
|
|
- /* Max 10 values */
|
|
|
|
- for (i = 0; i < 10; i += step) {
|
|
|
|
- /* NULL terminated */
|
|
|
|
- if (bss->p.rates[i] == 0x0)
|
|
|
|
- break;
|
|
|
|
- /* Bit rate given in 500 kb/s units (+ 0x80) */
|
|
|
|
- iwe.u.bitrate.value =
|
|
|
|
- ((bss->p.rates[i] & 0x7f) * 500000);
|
|
|
|
- current_val = iwe_stream_add_value(info, current_ev,
|
|
|
|
- current_val,
|
|
|
|
- end_buf, &iwe,
|
|
|
|
- IW_EV_PARAM_LEN);
|
|
|
|
- }
|
|
|
|
- /* Check if we added any event */
|
|
|
|
- if ((current_val - current_ev) > iwe_stream_lcp_len(info))
|
|
|
|
- current_ev = current_val;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- /* Beacon interval */
|
|
|
|
- iwe.cmd = IWEVCUSTOM;
|
|
|
|
- iwe.u.data.length = snprintf(custom, MAX_CUSTOM_LEN,
|
|
|
|
- "bcn_int=%d",
|
|
|
|
- le16_to_cpu(bss->a.beacon_interv));
|
|
|
|
- if (iwe.u.data.length)
|
|
|
|
- current_ev = iwe_stream_add_point(info, current_ev, end_buf,
|
|
|
|
- &iwe, custom);
|
|
|
|
-
|
|
|
|
- /* Capabilites */
|
|
|
|
- iwe.cmd = IWEVCUSTOM;
|
|
|
|
- iwe.u.data.length = snprintf(custom, MAX_CUSTOM_LEN,
|
|
|
|
- "capab=0x%04x",
|
|
|
|
- capabilities);
|
|
|
|
- if (iwe.u.data.length)
|
|
|
|
- current_ev = iwe_stream_add_point(info, current_ev, end_buf,
|
|
|
|
- &iwe, custom);
|
|
|
|
-
|
|
|
|
- /* Add EXTRA: Age to display seconds since last beacon/probe response
|
|
|
|
- * for given network. */
|
|
|
|
- iwe.cmd = IWEVCUSTOM;
|
|
|
|
- iwe.u.data.length = snprintf(custom, MAX_CUSTOM_LEN,
|
|
|
|
- " Last beacon: %dms ago",
|
|
|
|
- jiffies_to_msecs(jiffies - last_scanned));
|
|
|
|
- if (iwe.u.data.length)
|
|
|
|
- current_ev = iwe_stream_add_point(info, current_ev, end_buf,
|
|
|
|
- &iwe, custom);
|
|
|
|
-
|
|
|
|
- return current_ev;
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-static inline char *orinoco_translate_ext_scan(struct net_device *dev,
|
|
|
|
- struct iw_request_info *info,
|
|
|
|
- char *current_ev,
|
|
|
|
- char *end_buf,
|
|
|
|
- struct agere_ext_scan_info *bss,
|
|
|
|
- unsigned long last_scanned)
|
|
|
|
-{
|
|
|
|
- u16 capabilities;
|
|
|
|
- u16 channel;
|
|
|
|
- struct iw_event iwe; /* Temporary buffer */
|
|
|
|
- char custom[MAX_CUSTOM_LEN];
|
|
|
|
- u8 *ie;
|
|
|
|
-
|
|
|
|
- memset(&iwe, 0, sizeof(iwe));
|
|
|
|
-
|
|
|
|
- /* First entry *MUST* be the AP MAC address */
|
|
|
|
- iwe.cmd = SIOCGIWAP;
|
|
|
|
- iwe.u.ap_addr.sa_family = ARPHRD_ETHER;
|
|
|
|
- memcpy(iwe.u.ap_addr.sa_data, bss->bssid, ETH_ALEN);
|
|
|
|
- current_ev = iwe_stream_add_event(info, current_ev, end_buf,
|
|
|
|
- &iwe, IW_EV_ADDR_LEN);
|
|
|
|
-
|
|
|
|
- /* Other entries will be displayed in the order we give them */
|
|
|
|
-
|
|
|
|
- /* Add the ESSID */
|
|
|
|
- ie = bss->data;
|
|
|
|
- iwe.u.data.length = ie[1];
|
|
|
|
- if (iwe.u.data.length) {
|
|
|
|
- if (iwe.u.data.length > 32)
|
|
|
|
- iwe.u.data.length = 32;
|
|
|
|
- iwe.cmd = SIOCGIWESSID;
|
|
|
|
- iwe.u.data.flags = 1;
|
|
|
|
- current_ev = iwe_stream_add_point(info, current_ev, end_buf,
|
|
|
|
- &iwe, &ie[2]);
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- /* Add mode */
|
|
|
|
- capabilities = le16_to_cpu(bss->capabilities);
|
|
|
|
- if (capabilities & (WLAN_CAPABILITY_ESS | WLAN_CAPABILITY_IBSS)) {
|
|
|
|
- iwe.cmd = SIOCGIWMODE;
|
|
|
|
- if (capabilities & WLAN_CAPABILITY_ESS)
|
|
|
|
- iwe.u.mode = IW_MODE_MASTER;
|
|
|
|
- else
|
|
|
|
- iwe.u.mode = IW_MODE_ADHOC;
|
|
|
|
- current_ev = iwe_stream_add_event(info, current_ev, end_buf,
|
|
|
|
- &iwe, IW_EV_UINT_LEN);
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- ie = orinoco_get_ie(bss->data, sizeof(bss->data), WLAN_EID_DS_PARAMS);
|
|
|
|
- channel = ie ? ie[2] : 0;
|
|
|
|
- if ((channel >= 1) && (channel <= NUM_CHANNELS)) {
|
|
|
|
- /* Add channel and frequency */
|
|
|
|
- iwe.cmd = SIOCGIWFREQ;
|
|
|
|
- iwe.u.freq.m = channel;
|
|
|
|
- iwe.u.freq.e = 0;
|
|
|
|
- current_ev = iwe_stream_add_event(info, current_ev, end_buf,
|
|
|
|
- &iwe, IW_EV_FREQ_LEN);
|
|
|
|
-
|
|
|
|
- iwe.u.freq.m = ieee80211_dsss_chan_to_freq(channel) * 100000;
|
|
|
|
- iwe.u.freq.e = 1;
|
|
|
|
- current_ev = iwe_stream_add_event(info, current_ev, end_buf,
|
|
|
|
- &iwe, IW_EV_FREQ_LEN);
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- /* Add quality statistics. level and noise in dB. No link quality */
|
|
|
|
- iwe.cmd = IWEVQUAL;
|
|
|
|
- iwe.u.qual.updated = IW_QUAL_DBM | IW_QUAL_QUAL_INVALID;
|
|
|
|
- iwe.u.qual.level = bss->level - 0x95;
|
|
|
|
- iwe.u.qual.noise = bss->noise - 0x95;
|
|
|
|
- /* Wireless tools prior to 27.pre22 will show link quality
|
|
|
|
- * anyway, so we provide a reasonable value. */
|
|
|
|
- if (iwe.u.qual.level > iwe.u.qual.noise)
|
|
|
|
- iwe.u.qual.qual = iwe.u.qual.level - iwe.u.qual.noise;
|
|
|
|
- else
|
|
|
|
- iwe.u.qual.qual = 0;
|
|
|
|
- current_ev = iwe_stream_add_event(info, current_ev, end_buf,
|
|
|
|
- &iwe, IW_EV_QUAL_LEN);
|
|
|
|
-
|
|
|
|
- /* Add encryption capability */
|
|
|
|
- iwe.cmd = SIOCGIWENCODE;
|
|
|
|
- if (capabilities & WLAN_CAPABILITY_PRIVACY)
|
|
|
|
- iwe.u.data.flags = IW_ENCODE_ENABLED | IW_ENCODE_NOKEY;
|
|
|
|
- else
|
|
|
|
- iwe.u.data.flags = IW_ENCODE_DISABLED;
|
|
|
|
- iwe.u.data.length = 0;
|
|
|
|
- current_ev = iwe_stream_add_point(info, current_ev, end_buf,
|
|
|
|
- &iwe, NULL);
|
|
|
|
-
|
|
|
|
- /* WPA IE */
|
|
|
|
- ie = orinoco_get_wpa_ie(bss->data, sizeof(bss->data));
|
|
|
|
- if (ie) {
|
|
|
|
- iwe.cmd = IWEVGENIE;
|
|
|
|
- iwe.u.data.length = ie[1] + 2;
|
|
|
|
- current_ev = iwe_stream_add_point(info, current_ev, end_buf,
|
|
|
|
- &iwe, ie);
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- /* RSN IE */
|
|
|
|
- ie = orinoco_get_ie(bss->data, sizeof(bss->data), WLAN_EID_RSN);
|
|
|
|
- if (ie) {
|
|
|
|
- iwe.cmd = IWEVGENIE;
|
|
|
|
- iwe.u.data.length = ie[1] + 2;
|
|
|
|
- current_ev = iwe_stream_add_point(info, current_ev, end_buf,
|
|
|
|
- &iwe, ie);
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- ie = orinoco_get_ie(bss->data, sizeof(bss->data), WLAN_EID_SUPP_RATES);
|
|
|
|
- if (ie) {
|
|
|
|
- char *p = current_ev + iwe_stream_lcp_len(info);
|
|
|
|
- int i;
|
|
|
|
-
|
|
|
|
- iwe.cmd = SIOCGIWRATE;
|
|
|
|
- /* Those two flags are ignored... */
|
|
|
|
- iwe.u.bitrate.fixed = iwe.u.bitrate.disabled = 0;
|
|
|
|
-
|
|
|
|
- for (i = 2; i < (ie[1] + 2); i++) {
|
|
|
|
- iwe.u.bitrate.value = ((ie[i] & 0x7F) * 500000);
|
|
|
|
- p = iwe_stream_add_value(info, current_ev, p, end_buf,
|
|
|
|
- &iwe, IW_EV_PARAM_LEN);
|
|
|
|
- }
|
|
|
|
- /* Check if we added any event */
|
|
|
|
- if (p > (current_ev + iwe_stream_lcp_len(info)))
|
|
|
|
- current_ev = p;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- /* Timestamp */
|
|
|
|
- iwe.cmd = IWEVCUSTOM;
|
|
|
|
- iwe.u.data.length =
|
|
|
|
- snprintf(custom, MAX_CUSTOM_LEN, "tsf=%016llx",
|
|
|
|
- (unsigned long long) le64_to_cpu(bss->timestamp));
|
|
|
|
- if (iwe.u.data.length)
|
|
|
|
- current_ev = iwe_stream_add_point(info, current_ev, end_buf,
|
|
|
|
- &iwe, custom);
|
|
|
|
-
|
|
|
|
- /* Beacon interval */
|
|
|
|
- iwe.cmd = IWEVCUSTOM;
|
|
|
|
- iwe.u.data.length = snprintf(custom, MAX_CUSTOM_LEN,
|
|
|
|
- "bcn_int=%d",
|
|
|
|
- le16_to_cpu(bss->beacon_interval));
|
|
|
|
- if (iwe.u.data.length)
|
|
|
|
- current_ev = iwe_stream_add_point(info, current_ev, end_buf,
|
|
|
|
- &iwe, custom);
|
|
|
|
-
|
|
|
|
- /* Capabilites */
|
|
|
|
- iwe.cmd = IWEVCUSTOM;
|
|
|
|
- iwe.u.data.length = snprintf(custom, MAX_CUSTOM_LEN,
|
|
|
|
- "capab=0x%04x",
|
|
|
|
- capabilities);
|
|
|
|
- if (iwe.u.data.length)
|
|
|
|
- current_ev = iwe_stream_add_point(info, current_ev, end_buf,
|
|
|
|
- &iwe, custom);
|
|
|
|
-
|
|
|
|
- /* Add EXTRA: Age to display seconds since last beacon/probe response
|
|
|
|
- * for given network. */
|
|
|
|
- iwe.cmd = IWEVCUSTOM;
|
|
|
|
- iwe.u.data.length = snprintf(custom, MAX_CUSTOM_LEN,
|
|
|
|
- " Last beacon: %dms ago",
|
|
|
|
- jiffies_to_msecs(jiffies - last_scanned));
|
|
|
|
- if (iwe.u.data.length)
|
|
|
|
- current_ev = iwe_stream_add_point(info, current_ev, end_buf,
|
|
|
|
- &iwe, custom);
|
|
|
|
-
|
|
|
|
- return current_ev;
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-/* Return results of a scan */
|
|
|
|
-static int orinoco_ioctl_getscan(struct net_device *dev,
|
|
|
|
- struct iw_request_info *info,
|
|
|
|
- struct iw_point *srq,
|
|
|
|
- char *extra)
|
|
|
|
-{
|
|
|
|
- struct orinoco_private *priv = ndev_priv(dev);
|
|
|
|
- int err = 0;
|
|
|
|
- unsigned long flags;
|
|
|
|
- char *current_ev = extra;
|
|
|
|
-
|
|
|
|
- if (orinoco_lock(priv, &flags) != 0)
|
|
|
|
- return -EBUSY;
|
|
|
|
-
|
|
|
|
- if (priv->scan_inprogress) {
|
|
|
|
- /* Important note : we don't want to block the caller
|
|
|
|
- * until results are ready for various reasons.
|
|
|
|
- * First, managing wait queues is complex and racy.
|
|
|
|
- * Second, we grab some rtnetlink lock before comming
|
|
|
|
- * here (in dev_ioctl()).
|
|
|
|
- * Third, we generate an Wireless Event, so the
|
|
|
|
- * caller can wait itself on that - Jean II */
|
|
|
|
- err = -EAGAIN;
|
|
|
|
- goto out;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- if (priv->has_ext_scan) {
|
|
|
|
- struct xbss_element *bss;
|
|
|
|
-
|
|
|
|
- list_for_each_entry(bss, &priv->bss_list, list) {
|
|
|
|
- /* Translate this entry to WE format */
|
|
|
|
- current_ev =
|
|
|
|
- orinoco_translate_ext_scan(dev, info,
|
|
|
|
- current_ev,
|
|
|
|
- extra + srq->length,
|
|
|
|
- &bss->bss,
|
|
|
|
- bss->last_scanned);
|
|
|
|
-
|
|
|
|
- /* Check if there is space for one more entry */
|
|
|
|
- if ((extra + srq->length - current_ev)
|
|
|
|
- <= IW_EV_ADDR_LEN) {
|
|
|
|
- /* Ask user space to try again with a
|
|
|
|
- * bigger buffer */
|
|
|
|
- err = -E2BIG;
|
|
|
|
- goto out;
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- } else {
|
|
|
|
- struct bss_element *bss;
|
|
|
|
-
|
|
|
|
- list_for_each_entry(bss, &priv->bss_list, list) {
|
|
|
|
- /* Translate this entry to WE format */
|
|
|
|
- current_ev = orinoco_translate_scan(dev, info,
|
|
|
|
- current_ev,
|
|
|
|
- extra + srq->length,
|
|
|
|
- &bss->bss,
|
|
|
|
- bss->last_scanned);
|
|
|
|
-
|
|
|
|
- /* Check if there is space for one more entry */
|
|
|
|
- if ((extra + srq->length - current_ev)
|
|
|
|
- <= IW_EV_ADDR_LEN) {
|
|
|
|
- /* Ask user space to try again with a
|
|
|
|
- * bigger buffer */
|
|
|
|
- err = -E2BIG;
|
|
|
|
- goto out;
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- srq->length = (current_ev - extra);
|
|
|
|
- srq->flags = (__u16) priv->scan_mode;
|
|
|
|
-
|
|
|
|
-out:
|
|
|
|
- orinoco_unlock(priv, &flags);
|
|
|
|
- return err;
|
|
|
|
-}
|
|
|
|
|
|
|
|
/* Commit handler, called after set operations */
|
|
/* Commit handler, called after set operations */
|
|
static int orinoco_ioctl_commit(struct net_device *dev,
|
|
static int orinoco_ioctl_commit(struct net_device *dev,
|
|
@@ -2161,8 +1648,8 @@ static const iw_handler orinoco_handler[] = {
|
|
STD_IW_HANDLER(SIOCGIWTHRSPY, iw_handler_get_thrspy),
|
|
STD_IW_HANDLER(SIOCGIWTHRSPY, iw_handler_get_thrspy),
|
|
STD_IW_HANDLER(SIOCSIWAP, orinoco_ioctl_setwap),
|
|
STD_IW_HANDLER(SIOCSIWAP, orinoco_ioctl_setwap),
|
|
STD_IW_HANDLER(SIOCGIWAP, orinoco_ioctl_getwap),
|
|
STD_IW_HANDLER(SIOCGIWAP, orinoco_ioctl_getwap),
|
|
- STD_IW_HANDLER(SIOCSIWSCAN, orinoco_ioctl_setscan),
|
|
|
|
- STD_IW_HANDLER(SIOCGIWSCAN, orinoco_ioctl_getscan),
|
|
|
|
|
|
+ STD_IW_HANDLER(SIOCSIWSCAN, cfg80211_wext_siwscan),
|
|
|
|
+ STD_IW_HANDLER(SIOCGIWSCAN, cfg80211_wext_giwscan),
|
|
STD_IW_HANDLER(SIOCSIWESSID, orinoco_ioctl_setessid),
|
|
STD_IW_HANDLER(SIOCSIWESSID, orinoco_ioctl_setessid),
|
|
STD_IW_HANDLER(SIOCGIWESSID, orinoco_ioctl_getessid),
|
|
STD_IW_HANDLER(SIOCGIWESSID, orinoco_ioctl_getessid),
|
|
STD_IW_HANDLER(SIOCSIWNICKN, orinoco_ioctl_setnick),
|
|
STD_IW_HANDLER(SIOCSIWNICKN, orinoco_ioctl_setnick),
|