📄 wext.c
字号:
Infra B(4) G(12) Adhoc B(4) B(4) *//** * @brief Get Range Info * * @param dev A pointer to net_device structure * @param info A pointer to iw_request_info structure * @param vwrq A pointer to iw_param structure * @param extra A pointer to extra data buf * @return 0 --success, otherwise fail */static int wlan_get_range(struct net_device *dev, struct iw_request_info *info, struct iw_point *dwrq, char *extra){ int i, j; wlan_private *priv = dev->priv; wlan_adapter *adapter = priv->adapter; struct iw_range *range = (struct iw_range *)extra; struct chan_freq_power *cfp; u8 rates[MAX_RATES + 1]; u8 flag = 0; lbs_deb_enter(LBS_DEB_WEXT); dwrq->length = sizeof(struct iw_range); memset(range, 0, sizeof(struct iw_range)); range->min_nwid = 0; range->max_nwid = 0; memset(rates, 0, sizeof(rates)); copy_active_data_rates(adapter, rates); range->num_bitrates = strnlen(rates, IW_MAX_BITRATES); for (i = 0; i < range->num_bitrates; i++) range->bitrate[i] = rates[i] * 500000; range->num_bitrates = i; lbs_deb_wext("IW_MAX_BITRATES %d, num_bitrates %d\n", IW_MAX_BITRATES, range->num_bitrates); range->num_frequency = 0; if (priv->adapter->enable11d && adapter->connect_status == LIBERTAS_CONNECTED) { u8 chan_no; u8 band; struct parsed_region_chan_11d *parsed_region_chan = &adapter->parsed_region_chan; if (parsed_region_chan == NULL) { lbs_deb_wext("11d: parsed_region_chan is NULL\n"); goto out; } band = parsed_region_chan->band; lbs_deb_wext("band %d, nr_char %d\n", band, parsed_region_chan->nr_chan); for (i = 0; (range->num_frequency < IW_MAX_FREQUENCIES) && (i < parsed_region_chan->nr_chan); i++) { chan_no = parsed_region_chan->chanpwr[i].chan; lbs_deb_wext("chan_no %d\n", chan_no); range->freq[range->num_frequency].i = (long)chan_no; range->freq[range->num_frequency].m = (long)libertas_chan_2_freq(chan_no, band) * 100000; range->freq[range->num_frequency].e = 1; range->num_frequency++; } flag = 1; } if (!flag) { for (j = 0; (range->num_frequency < IW_MAX_FREQUENCIES) && (j < sizeof(adapter->region_channel) / sizeof(adapter->region_channel[0])); j++) { cfp = adapter->region_channel[j].CFP; for (i = 0; (range->num_frequency < IW_MAX_FREQUENCIES) && adapter->region_channel[j].valid && cfp && (i < adapter->region_channel[j].nrcfp); i++) { range->freq[range->num_frequency].i = (long)cfp->channel; range->freq[range->num_frequency].m = (long)cfp->freq * 100000; range->freq[range->num_frequency].e = 1; cfp++; range->num_frequency++; } } } lbs_deb_wext("IW_MAX_FREQUENCIES %d, num_frequency %d\n", IW_MAX_FREQUENCIES, range->num_frequency); range->num_channels = range->num_frequency; sort_channels(&range->freq[0], range->num_frequency); /* * Set an indication of the max TCP throughput in bit/s that we can * expect using this interface */ if (i > 2) range->throughput = 5000 * 1000; else range->throughput = 1500 * 1000; range->min_rts = MRVDRV_RTS_MIN_VALUE; range->max_rts = MRVDRV_RTS_MAX_VALUE; range->min_frag = MRVDRV_FRAG_MIN_VALUE; range->max_frag = MRVDRV_FRAG_MAX_VALUE; range->encoding_size[0] = 5; range->encoding_size[1] = 13; range->num_encoding_sizes = 2; range->max_encoding_tokens = 4; range->min_pmp = 1000000; range->max_pmp = 120000000; range->min_pmt = 1000; range->max_pmt = 1000000; range->pmp_flags = IW_POWER_PERIOD; range->pmt_flags = IW_POWER_TIMEOUT; range->pm_capa = IW_POWER_PERIOD | IW_POWER_TIMEOUT | IW_POWER_ALL_R; /* * Minimum version we recommend */ range->we_version_source = 15; /* * Version we are compiled with */ range->we_version_compiled = WIRELESS_EXT; range->retry_capa = IW_RETRY_LIMIT; range->retry_flags = IW_RETRY_LIMIT | IW_RETRY_MAX; range->min_retry = TX_RETRY_MIN; range->max_retry = TX_RETRY_MAX; /* * Set the qual, level and noise range values */ range->max_qual.qual = 100; range->max_qual.level = 0; range->max_qual.noise = 0; range->max_qual.updated = IW_QUAL_ALL_UPDATED | IW_QUAL_DBM; range->avg_qual.qual = 70; /* TODO: Find real 'good' to 'bad' threshold value for RSSI */ range->avg_qual.level = 0; range->avg_qual.noise = 0; range->avg_qual.updated = IW_QUAL_ALL_UPDATED | IW_QUAL_DBM; range->sensitivity = 0; /* * Setup the supported power level ranges */ memset(range->txpower, 0, sizeof(range->txpower)); range->txpower[0] = 5; range->txpower[1] = 7; range->txpower[2] = 9; range->txpower[3] = 11; range->txpower[4] = 13; range->txpower[5] = 15; range->txpower[6] = 17; range->txpower[7] = 19; range->num_txpower = 8; range->txpower_capa = IW_TXPOW_DBM; range->txpower_capa |= IW_TXPOW_RANGE; range->event_capa[0] = (IW_EVENT_CAPA_K_0 | IW_EVENT_CAPA_MASK(SIOCGIWAP) | IW_EVENT_CAPA_MASK(SIOCGIWSCAN)); range->event_capa[1] = IW_EVENT_CAPA_K_1; if (adapter->fwcapinfo & FW_CAPINFO_WPA) { range->enc_capa = IW_ENC_CAPA_WPA | IW_ENC_CAPA_WPA2 | IW_ENC_CAPA_CIPHER_TKIP | IW_ENC_CAPA_CIPHER_CCMP; }out: lbs_deb_leave(LBS_DEB_WEXT); return 0;}static int wlan_set_power(struct net_device *dev, struct iw_request_info *info, struct iw_param *vwrq, char *extra){ wlan_private *priv = dev->priv; wlan_adapter *adapter = priv->adapter; lbs_deb_enter(LBS_DEB_WEXT); /* PS is currently supported only in Infrastructure mode * Remove this check if it is to be supported in IBSS mode also */ if (vwrq->disabled) { adapter->psmode = WLAN802_11POWERMODECAM; if (adapter->psstate != PS_STATE_FULL_POWER) { libertas_ps_wakeup(priv, CMD_OPTION_WAITFORRSP); } return 0; } if ((vwrq->flags & IW_POWER_TYPE) == IW_POWER_TIMEOUT) { lbs_deb_wext( "setting power timeout is not supported\n"); return -EINVAL; } else if ((vwrq->flags & IW_POWER_TYPE) == IW_POWER_PERIOD) { lbs_deb_wext("setting power period not supported\n"); return -EINVAL; } if (adapter->psmode != WLAN802_11POWERMODECAM) { return 0; } adapter->psmode = WLAN802_11POWERMODEMAX_PSP; if (adapter->connect_status == LIBERTAS_CONNECTED) { libertas_ps_sleep(priv, CMD_OPTION_WAITFORRSP); } lbs_deb_leave(LBS_DEB_WEXT); return 0;}static int wlan_get_power(struct net_device *dev, struct iw_request_info *info, struct iw_param *vwrq, char *extra){ wlan_private *priv = dev->priv; wlan_adapter *adapter = priv->adapter; int mode; lbs_deb_enter(LBS_DEB_WEXT); mode = adapter->psmode; if ((vwrq->disabled = (mode == WLAN802_11POWERMODECAM)) || adapter->connect_status == LIBERTAS_DISCONNECTED) { goto out; } vwrq->value = 0;out: lbs_deb_leave(LBS_DEB_WEXT); return 0;}static struct iw_statistics *wlan_get_wireless_stats(struct net_device *dev){ enum { POOR = 30, FAIR = 60, GOOD = 80, VERY_GOOD = 90, EXCELLENT = 95, PERFECT = 100 }; wlan_private *priv = dev->priv; wlan_adapter *adapter = priv->adapter; u32 rssi_qual; u32 tx_qual; u32 quality = 0; int stats_valid = 0; u8 rssi; u32 tx_retries; lbs_deb_enter(LBS_DEB_WEXT); priv->wstats.status = adapter->mode; /* If we're not associated, all quality values are meaningless */ if (adapter->connect_status != LIBERTAS_CONNECTED) goto out; /* Quality by RSSI */ priv->wstats.qual.level = CAL_RSSI(adapter->SNR[TYPE_BEACON][TYPE_NOAVG], adapter->NF[TYPE_BEACON][TYPE_NOAVG]); if (adapter->NF[TYPE_BEACON][TYPE_NOAVG] == 0) { priv->wstats.qual.noise = MRVDRV_NF_DEFAULT_SCAN_VALUE; } else { priv->wstats.qual.noise = CAL_NF(adapter->NF[TYPE_BEACON][TYPE_NOAVG]); } lbs_deb_wext("signal level %#x\n", priv->wstats.qual.level); lbs_deb_wext("noise %#x\n", priv->wstats.qual.noise); rssi = priv->wstats.qual.level - priv->wstats.qual.noise; if (rssi < 15) rssi_qual = rssi * POOR / 10; else if (rssi < 20) rssi_qual = (rssi - 15) * (FAIR - POOR) / 5 + POOR; else if (rssi < 30) rssi_qual = (rssi - 20) * (GOOD - FAIR) / 5 + FAIR; else if (rssi < 40) rssi_qual = (rssi - 30) * (VERY_GOOD - GOOD) / 10 + GOOD; else rssi_qual = (rssi - 40) * (PERFECT - VERY_GOOD) / 10 + VERY_GOOD; quality = rssi_qual; /* Quality by TX errors */ priv->wstats.discard.retries = priv->stats.tx_errors; tx_retries = le32_to_cpu(adapter->logmsg.retry); if (tx_retries > 75) tx_qual = (90 - tx_retries) * POOR / 15; else if (tx_retries > 70) tx_qual = (75 - tx_retries) * (FAIR - POOR) / 5 + POOR; else if (tx_retries > 65) tx_qual = (70 - tx_retries) * (GOOD - FAIR) / 5 + FAIR; else if (tx_retries > 50) tx_qual = (65 - tx_retries) * (VERY_GOOD - GOOD) / 15 + GOOD; else tx_qual = (50 - tx_retries) * (PERFECT - VERY_GOOD) / 50 + VERY_GOOD; quality = min(quality, tx_qual); priv->wstats.discard.code = le32_to_cpu(adapter->logmsg.wepundecryptable); priv->wstats.discard.fragment = le32_to_cpu(adapter->logmsg.rxfrag); priv->wstats.discard.retries = tx_retries; priv->wstats.discard.misc = le32_to_cpu(adapter->logmsg.ackfailure); /* Calculate quality */ priv->wstats.qual.qual = min_t(u8, quality, 100); priv->wstats.qual.updated = IW_QUAL_ALL_UPDATED | IW_QUAL_DBM; stats_valid = 1; /* update stats asynchronously for future calls */ libertas_prepare_and_send_command(priv, CMD_802_11_RSSI, 0, 0, 0, NULL); libertas_prepare_and_send_command(priv, CMD_802_11_GET_LOG, 0, 0, 0, NULL);out: if (!stats_valid) { priv->wstats.miss.beacon = 0; priv->wstats.discard.retries = 0; priv->wstats.qual.qual = 0; priv->wstats.qual.level = 0; priv->wstats.qual.noise = 0; priv->wstats.qual.updated = IW_QUAL_ALL_UPDATED; priv->wstats.qual.updated |= IW_QUAL_NOISE_INVALID | IW_QUAL_QUAL_INVALID | IW_QUAL_LEVEL_INVALID; } lbs_deb_leave(LBS_DEB_WEXT); return &priv->wstats;}static int wlan_set_freq(struct net_device *dev, struct iw_request_info *info, struct iw_freq *fwrq, char *extra){ int ret = -EINVAL; wlan_private *priv = dev->priv; wlan_adapter *adapter = priv->adapter; struct chan_freq_power *cfp; struct assoc_request * assoc_req; lbs_deb_enter(LBS_DEB_WEXT); mutex_lock(&adapter->lock); assoc_req = wlan_get_association_request(adapter); if (!assoc_req) { ret = -ENOMEM; goto out; } /* If setting by frequency, convert to a channel */ if (fwrq->e == 1) { long f = fwrq->m / 100000; cfp = find_cfp_by_band_and_freq(adapter, 0, f); if (!cfp) { lbs_deb_wext("invalid freq %ld\n", f); goto out; } fwrq->e = 0; fwrq->m = (int) cfp->channel; } /* Setting by channel number */ if (fwrq->m > 1000 || fwrq->e > 0) { goto out; } cfp = libertas_find_cfp_by_band_and_channel(adapter, 0, fwrq->m); if (!cfp) { goto out; } assoc_req->channel = fwrq->m; ret = 0;out: if (ret == 0) { set_bit(ASSOC_FLAG_CHANNEL, &assoc_req->flags); wlan_postpone_association_work(priv); } else { wlan_cancel_association_work(priv); } mutex_unlock(&adapter->lock); lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret); return ret;}static int wlan_set_rate(struct net_device *dev, struct iw_request_info *info, struct iw_param *vwrq, char *extra){ wlan_private *priv = dev->priv; wlan_adapter *adapter = priv->adapter; u32 new_rate; u16 action; int ret = -EINVAL; u8 rates[MAX_RATES + 1]; lbs_deb_enter(LBS_DEB_WEXT); lbs_deb_wext("vwrq->value %d\n", vwrq->value); /* Auto rate? */ if (vwrq->value == -1) { action = CMD_ACT_SET_TX_AUTO; adapter->auto_rate = 1; adapter->cur_rate = 0; } else { if (vwrq->value % 100000) goto out; memset(rates, 0, sizeof(rates)); copy_active_data_rates(adapter, rates); new_rate = vwrq->value / 500000; if (!memchr(rates, new_rate, sizeof(rates))) { lbs_pr_alert("fixed data rate 0x%X out of range\n", new_rate); goto out; } adapter->cur_rate = new_rate; action = CMD_ACT_SET_TX_FIX_RATE; adapter->auto_rate = 0; } ret = libertas_prepare_and_send_command(priv, CMD_802_11_DATA_RATE, action, CMD_OPTION_WAITFORRSP, 0, NULL);out: lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret); return ret;}static int wlan_get_rate(struct net_device *dev, struct iw_request_info *info, struct iw_param *vwrq, char *extra){ wlan_private *priv = dev->priv; wlan_adapter *adapter = priv->adapter; lbs_deb_enter(LBS_DEB_WEXT); if (adapter->connect_status == LIBERTAS_CONNECTED) { vwrq->value = adapter->cur_rate * 500000; if (adapter->auto_rate) vwrq->fixed = 0; else vwrq->fixed = 1; } else { vwrq->fixed = 0; vwrq->value = 0; } lbs_deb_leave(LBS_DEB_WEXT); return 0;}static int wlan_set_mode(struct net_device *dev, struct iw_request_info *info, u32 * uwrq, char *extra){ int ret = 0; wlan_private *priv = dev->priv; wlan_adapter *adapter = priv->adapter; struct assoc_request * assoc_req; lbs_deb_enter(LBS_DEB_WEXT); if ( (*uwrq != IW_MODE_ADHOC) && (*uwrq != IW_MODE_INFRA) && (*uwrq != IW_MODE_AUTO)) { lbs_deb_wext("Invalid mode: 0x%x\n", *uwrq); ret = -EINVAL; goto out; } mutex_lock(&adapter->lock); assoc_req = wlan_get_association_request(adapter); if (!assoc_req) { ret = -ENOMEM; wlan_cancel_association_work(priv); } else { assoc_req->mode = *uwrq; set_bit(ASSOC_FLAG_MODE, &assoc_req->flags); wlan_postpone_association_work(priv); lbs_deb_wext("Switching to mode: 0x%x\n", *uwrq); } mutex_unlock(&adapter->lock);out: lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret); return ret;}/** * @brief Get Encryption key * * @param dev A pointer to net_device structure * @param info A pointer to iw_request_info structure
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -