int orinoco_wiphy_register(struct wiphy *wiphy) { struct orinoco_private *priv = wiphy_priv(wiphy); int i, channels = 0; if (priv->firmware_type == FIRMWARE_TYPE_AGERE) wiphy->max_scan_ssids = 1; else wiphy->max_scan_ssids = 0; wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION); if (priv->has_ibss) wiphy->interface_modes |= BIT(NL80211_IFTYPE_ADHOC); if (!priv->broken_monitor || force_monitor) wiphy->interface_modes |= BIT(NL80211_IFTYPE_MONITOR); priv->band.bitrates = orinoco_rates; priv->band.n_bitrates = ARRAY_SIZE(orinoco_rates); for (i = 0; i < NUM_CHANNELS; i++) { if (priv->channel_mask & (1 << i)) { priv->channels[i].center_freq = ieee80211_dsss_chan_to_freq(i + 1); channels++; } } priv->band.channels = priv->channels; priv->band.n_channels = channels; wiphy->bands[IEEE80211_BAND_2GHZ] = &priv->band; wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM; i = 0; if (priv->has_wep) { priv->cipher_suites[i] = WLAN_CIPHER_SUITE_WEP40; i++; if (priv->has_big_wep) { priv->cipher_suites[i] = WLAN_CIPHER_SUITE_WEP104; i++; } } if (priv->has_wpa) { priv->cipher_suites[i] = WLAN_CIPHER_SUITE_TKIP; i++; } wiphy->cipher_suites = priv->cipher_suites; wiphy->n_cipher_suites = i; wiphy->rts_threshold = priv->rts_thresh; if (!priv->has_mwo) wiphy->frag_threshold = priv->frag_thresh + 1; wiphy->retry_short = priv->short_retry_limit; wiphy->retry_long = priv->long_retry_limit; return wiphy_register(wiphy); }
void orinoco_add_extscan_result(struct orinoco_private *priv, struct agere_ext_scan_info *bss, size_t len) { struct wiphy *wiphy = priv_to_wiphy(priv); struct ieee80211_channel *channel; struct cfg80211_bss *cbss; const u8 *ie; u64 timestamp; s32 signal; u16 capability; u16 beacon_interval; size_t ie_len; int chan, freq; ie_len = len - sizeof(*bss); ie = cfg80211_find_ie(WLAN_EID_DS_PARAMS, bss->data, ie_len); chan = ie ? ie[2] : 0; freq = ieee80211_dsss_chan_to_freq(chan); channel = ieee80211_get_channel(wiphy, freq); timestamp = le64_to_cpu(bss->timestamp); capability = le16_to_cpu(bss->capabilities); beacon_interval = le16_to_cpu(bss->beacon_interval); ie = bss->data; signal = SIGNAL_TO_MBM(bss->level); cbss = cfg80211_inform_bss(wiphy, channel, bss->bssid, timestamp, capability, beacon_interval, ie, ie_len, signal, GFP_KERNEL); cfg80211_put_bss(cbss); }
static void orinoco_add_hostscan_result(struct orinoco_private *priv, const union hermes_scan_info *bss) { struct wiphy *wiphy = priv_to_wiphy(priv); struct ieee80211_channel *channel; struct cfg80211_bss *cbss; u8 *ie; u8 ie_buf[46]; u64 timestamp; s32 signal; u16 capability; u16 beacon_interval; int ie_len; int freq; int len; len = le16_to_cpu(bss->a.essid_len); /* Reconstruct SSID and bitrate IEs to pass up */ ie_buf[0] = WLAN_EID_SSID; ie_buf[1] = len; memcpy(&ie_buf[2], bss->a.essid, len); ie = ie_buf + len + 2; ie_len = ie_buf[1] + 2; switch (priv->firmware_type) { case FIRMWARE_TYPE_SYMBOL: ie_len += symbol_build_supp_rates(ie, bss->s.rates); break; case FIRMWARE_TYPE_INTERSIL: ie_len += prism_build_supp_rates(ie, bss->p.rates); break; case FIRMWARE_TYPE_AGERE: default: break; } freq = ieee80211_dsss_chan_to_freq(le16_to_cpu(bss->a.channel)); channel = ieee80211_get_channel(wiphy, freq); if (!channel) { printk(KERN_DEBUG "Invalid channel designation %04X(%04X)", bss->a.channel, freq); return; /* Then ignore it for now */ } timestamp = 0; capability = le16_to_cpu(bss->a.capabilities); beacon_interval = le16_to_cpu(bss->a.beacon_interv); signal = SIGNAL_TO_MBM(le16_to_cpu(bss->a.level)); cbss = cfg80211_inform_bss(wiphy, channel, bss->a.bssid, timestamp, capability, beacon_interval, ie_buf, ie_len, signal, GFP_KERNEL); cfg80211_put_bss(cbss); }
int orinoco_hw_get_freq(struct orinoco_private *priv) { hermes_t *hw = &priv->hw; int err = 0; u16 channel; int freq = 0; unsigned long flags; if (orinoco_lock(priv, &flags) != 0) return -EBUSY; err = hermes_read_wordrec(hw, USER_BAP, HERMES_RID_CURRENTCHANNEL, &channel); if (err) goto out; /* Intersil firmware 1.3.5 returns 0 when the interface is down */ if (channel == 0) { err = -EBUSY; goto out; } if ((channel < 1) || (channel > NUM_CHANNELS)) { printk(KERN_WARNING "%s: Channel out of range (%d)!\n", priv->ndev->name, channel); err = -EBUSY; goto out; } freq = ieee80211_dsss_chan_to_freq(channel); out: orinoco_unlock(priv, &flags); if (err > 0) err = -EBUSY; return err ? err : freq; }
int prism2_scan(struct wiphy *wiphy, struct net_device *dev, struct cfg80211_scan_request *request) { struct prism2_wiphy_private *priv = wiphy_priv(wiphy); wlandevice_t *wlandev = dev->ml_priv; struct p80211msg_dot11req_scan msg1; struct p80211msg_dot11req_scan_results msg2; int result; int err = 0; int numbss = 0; int i = 0; u8 ie_buf[46]; int ie_len; if (!request) return -EINVAL; if (priv->scan_request && priv->scan_request != request) return -EBUSY; if (wlandev->macmode == WLAN_MACMODE_ESS_AP) { printk(KERN_ERR "Can't scan in AP mode\n"); return -EOPNOTSUPP; } priv->scan_request = request; memset(&msg1, 0x00, sizeof(struct p80211msg_dot11req_scan)); msg1.msgcode = DIDmsg_dot11req_scan; msg1.bsstype.data = P80211ENUM_bsstype_any; memset(&(msg1.bssid.data), 0xFF, sizeof(p80211item_pstr6_t)); msg1.bssid.data.len = 6; if (request->n_ssids > 0) { msg1.scantype.data = P80211ENUM_scantype_active; msg1.ssid.data.len = request->ssids->ssid_len; memcpy(msg1.ssid.data.data, request->ssids->ssid, request->ssids->ssid_len); } else { msg1.scantype.data = 0; } msg1.probedelay.data = 0; for (i = 0; (i < request->n_channels) && i < ARRAY_SIZE(prism2_channels); i++) msg1.channellist.data.data[i] = ieee80211_frequency_to_channel(request->channels[i]->center_freq); msg1.channellist.data.len = request->n_channels; msg1.maxchanneltime.data = 250; msg1.minchanneltime.data = 200; result = p80211req_dorequest(wlandev, (u8 *) &msg1); if (result) { err = prism2_result2err(msg1.resultcode.data); goto exit; } /* Now retrieve scan results */ numbss = msg1.numbss.data; for (i = 0; i < numbss; i++) { memset(&msg2, 0, sizeof(msg2)); msg2.msgcode = DIDmsg_dot11req_scan_results; msg2.bssindex.data = i; result = p80211req_dorequest(wlandev, (u8 *) &msg2); if ((result != 0) || (msg2.resultcode.data != P80211ENUM_resultcode_success)) { break; } ie_buf[0] = WLAN_EID_SSID; ie_buf[1] = msg2.ssid.data.len; ie_len = ie_buf[1] + 2; memcpy(&ie_buf[2], &(msg2.ssid.data.data), msg2.ssid.data.len); cfg80211_inform_bss(wiphy, ieee80211_get_channel(wiphy, ieee80211_dsss_chan_to_freq(msg2.dschannel.data)), (const u8 *) &(msg2.bssid.data.data), msg2.timestamp.data, msg2.capinfo.data, msg2.beaconperiod.data, ie_buf, ie_len, (msg2.signal.data - 65536) * 100, /* Conversion to signed type */ GFP_KERNEL ); } if (result) err = prism2_result2err(msg2.resultcode.data); exit: cfg80211_scan_done(request, err ? 1 : 0); priv->scan_request = NULL; return err; }