📄 wext.c
字号:
/** * This file contains ioctl functions */#include <linux/ctype.h>#include <linux/delay.h>#include <linux/if.h>#include <linux/if_arp.h>#include <linux/wireless.h>#include <linux/bitops.h>#include <net/ieee80211.h>#include <net/iw_handler.h>#include "host.h"#include "radiotap.h"#include "decl.h"#include "defs.h"#include "dev.h"#include "join.h"#include "wext.h"#include "assoc.h"/** * @brief Find the channel frequency power info with specific channel * * @param adapter A pointer to wlan_adapter structure * @param band it can be BAND_A, BAND_G or BAND_B * @param channel the channel for looking * @return A pointer to struct chan_freq_power structure or NULL if not find. */struct chan_freq_power *libertas_find_cfp_by_band_and_channel(wlan_adapter * adapter, u8 band, u16 channel){ struct chan_freq_power *cfp = NULL; struct region_channel *rc; int count = sizeof(adapter->region_channel) / sizeof(adapter->region_channel[0]); int i, j; for (j = 0; !cfp && (j < count); j++) { rc = &adapter->region_channel[j]; if (adapter->enable11d) rc = &adapter->universal_channel[j]; if (!rc->valid || !rc->CFP) continue; if (rc->band != band) continue; for (i = 0; i < rc->nrcfp; i++) { if (rc->CFP[i].channel == channel) { cfp = &rc->CFP[i]; break; } } } if (!cfp && channel) lbs_deb_wext("libertas_find_cfp_by_band_and_channel: can't find " "cfp by band %d / channel %d\n", band, channel); return cfp;}/** * @brief Find the channel frequency power info with specific frequency * * @param adapter A pointer to wlan_adapter structure * @param band it can be BAND_A, BAND_G or BAND_B * @param freq the frequency for looking * @return A pointer to struct chan_freq_power structure or NULL if not find. */static struct chan_freq_power *find_cfp_by_band_and_freq(wlan_adapter * adapter, u8 band, u32 freq){ struct chan_freq_power *cfp = NULL; struct region_channel *rc; int count = sizeof(adapter->region_channel) / sizeof(adapter->region_channel[0]); int i, j; for (j = 0; !cfp && (j < count); j++) { rc = &adapter->region_channel[j]; if (adapter->enable11d) rc = &adapter->universal_channel[j]; if (!rc->valid || !rc->CFP) continue; if (rc->band != band) continue; for (i = 0; i < rc->nrcfp; i++) { if (rc->CFP[i].freq == freq) { cfp = &rc->CFP[i]; break; } } } if (!cfp && freq) lbs_deb_wext("find_cfp_by_band_and_freql: can't find cfp by " "band %d / freq %d\n", band, freq); return cfp;}/** * @brief Set Radio On/OFF * * @param priv A pointer to wlan_private structure * @option Radio Option * @return 0 --success, otherwise fail */static int wlan_radio_ioctl(wlan_private * priv, u8 option){ int ret = 0; wlan_adapter *adapter = priv->adapter; lbs_deb_enter(LBS_DEB_WEXT); if (adapter->radioon != option) { lbs_deb_wext("switching radio %s\n", option ? "on" : "off"); adapter->radioon = option; ret = libertas_prepare_and_send_command(priv, CMD_802_11_RADIO_CONTROL, CMD_ACT_SET, CMD_OPTION_WAITFORRSP, 0, NULL); } lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret); return ret;}/** * @brief Copy active data rates based on adapter mode and status * * @param adapter A pointer to wlan_adapter structure * @param rate The buf to return the active rates */static void copy_active_data_rates(wlan_adapter * adapter, u8 * rates){ lbs_deb_enter(LBS_DEB_WEXT); if (adapter->connect_status != LIBERTAS_CONNECTED) memcpy(rates, libertas_bg_rates, MAX_RATES); else memcpy(rates, adapter->curbssparams.rates, MAX_RATES); lbs_deb_leave(LBS_DEB_WEXT);}static int wlan_get_name(struct net_device *dev, struct iw_request_info *info, char *cwrq, char *extra){ lbs_deb_enter(LBS_DEB_WEXT); /* We could add support for 802.11n here as needed. Jean II */ snprintf(cwrq, IFNAMSIZ, "IEEE 802.11b/g"); lbs_deb_leave(LBS_DEB_WEXT); return 0;}static int wlan_get_freq(struct net_device *dev, struct iw_request_info *info, struct iw_freq *fwrq, char *extra){ wlan_private *priv = dev->priv; wlan_adapter *adapter = priv->adapter; struct chan_freq_power *cfp; lbs_deb_enter(LBS_DEB_WEXT); cfp = libertas_find_cfp_by_band_and_channel(adapter, 0, adapter->curbssparams.channel); if (!cfp) { if (adapter->curbssparams.channel) lbs_deb_wext("invalid channel %d\n", adapter->curbssparams.channel); return -EINVAL; } fwrq->m = (long)cfp->freq * 100000; fwrq->e = 1; lbs_deb_wext("freq %u\n", fwrq->m); lbs_deb_leave(LBS_DEB_WEXT); return 0;}static int wlan_get_wap(struct net_device *dev, struct iw_request_info *info, struct sockaddr *awrq, char *extra){ wlan_private *priv = dev->priv; wlan_adapter *adapter = priv->adapter; lbs_deb_enter(LBS_DEB_WEXT); if (adapter->connect_status == LIBERTAS_CONNECTED) { memcpy(awrq->sa_data, adapter->curbssparams.bssid, ETH_ALEN); } else { memset(awrq->sa_data, 0, ETH_ALEN); } awrq->sa_family = ARPHRD_ETHER; lbs_deb_leave(LBS_DEB_WEXT); return 0;}static int wlan_set_nick(struct net_device *dev, struct iw_request_info *info, struct iw_point *dwrq, char *extra){ wlan_private *priv = dev->priv; wlan_adapter *adapter = priv->adapter; lbs_deb_enter(LBS_DEB_WEXT); /* * Check the size of the string */ if (dwrq->length > 16) { return -E2BIG; } mutex_lock(&adapter->lock); memset(adapter->nodename, 0, sizeof(adapter->nodename)); memcpy(adapter->nodename, extra, dwrq->length); mutex_unlock(&adapter->lock); lbs_deb_leave(LBS_DEB_WEXT); return 0;}static int wlan_get_nick(struct net_device *dev, struct iw_request_info *info, struct iw_point *dwrq, char *extra){ wlan_private *priv = dev->priv; wlan_adapter *adapter = priv->adapter; lbs_deb_enter(LBS_DEB_WEXT); dwrq->length = strlen(adapter->nodename); memcpy(extra, adapter->nodename, dwrq->length); extra[dwrq->length] = '\0'; dwrq->flags = 1; /* active */ lbs_deb_leave(LBS_DEB_WEXT); return 0;}static int mesh_get_nick(struct net_device *dev, struct iw_request_info *info, struct iw_point *dwrq, char *extra){ wlan_private *priv = dev->priv; wlan_adapter *adapter = priv->adapter; lbs_deb_enter(LBS_DEB_WEXT); /* Use nickname to indicate that mesh is on */ if (adapter->connect_status == LIBERTAS_CONNECTED) { strncpy(extra, "Mesh", 12); extra[12] = '\0'; dwrq->length = strlen(extra); } else { extra[0] = '\0'; dwrq->length = 0; } lbs_deb_leave(LBS_DEB_WEXT); return 0;}static int wlan_set_rts(struct net_device *dev, struct iw_request_info *info, struct iw_param *vwrq, char *extra){ int ret = 0; wlan_private *priv = dev->priv; wlan_adapter *adapter = priv->adapter; u32 rthr = vwrq->value; lbs_deb_enter(LBS_DEB_WEXT); if (vwrq->disabled) { adapter->rtsthsd = rthr = MRVDRV_RTS_MAX_VALUE; } else { if (rthr < MRVDRV_RTS_MIN_VALUE || rthr > MRVDRV_RTS_MAX_VALUE) return -EINVAL; adapter->rtsthsd = rthr; } ret = libertas_prepare_and_send_command(priv, CMD_802_11_SNMP_MIB, CMD_ACT_SET, CMD_OPTION_WAITFORRSP, OID_802_11_RTS_THRESHOLD, &rthr); lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret); return ret;}static int wlan_get_rts(struct net_device *dev, struct iw_request_info *info, struct iw_param *vwrq, char *extra){ int ret = 0; wlan_private *priv = dev->priv; wlan_adapter *adapter = priv->adapter; lbs_deb_enter(LBS_DEB_WEXT); adapter->rtsthsd = 0; ret = libertas_prepare_and_send_command(priv, CMD_802_11_SNMP_MIB, CMD_ACT_GET, CMD_OPTION_WAITFORRSP, OID_802_11_RTS_THRESHOLD, NULL); if (ret) goto out; vwrq->value = adapter->rtsthsd; vwrq->disabled = ((vwrq->value < MRVDRV_RTS_MIN_VALUE) || (vwrq->value > MRVDRV_RTS_MAX_VALUE)); vwrq->fixed = 1;out: lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret); return ret;}static int wlan_set_frag(struct net_device *dev, struct iw_request_info *info, struct iw_param *vwrq, char *extra){ int ret = 0; u32 fthr = vwrq->value; wlan_private *priv = dev->priv; wlan_adapter *adapter = priv->adapter; lbs_deb_enter(LBS_DEB_WEXT); if (vwrq->disabled) { adapter->fragthsd = fthr = MRVDRV_FRAG_MAX_VALUE; } else { if (fthr < MRVDRV_FRAG_MIN_VALUE || fthr > MRVDRV_FRAG_MAX_VALUE) return -EINVAL; adapter->fragthsd = fthr; } ret = libertas_prepare_and_send_command(priv, CMD_802_11_SNMP_MIB, CMD_ACT_SET, CMD_OPTION_WAITFORRSP, OID_802_11_FRAGMENTATION_THRESHOLD, &fthr); lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret); return ret;}static int wlan_get_frag(struct net_device *dev, struct iw_request_info *info, struct iw_param *vwrq, char *extra){ int ret = 0; wlan_private *priv = dev->priv; wlan_adapter *adapter = priv->adapter; lbs_deb_enter(LBS_DEB_WEXT); adapter->fragthsd = 0; ret = libertas_prepare_and_send_command(priv, CMD_802_11_SNMP_MIB, CMD_ACT_GET, CMD_OPTION_WAITFORRSP, OID_802_11_FRAGMENTATION_THRESHOLD, NULL); if (ret) goto out; vwrq->value = adapter->fragthsd; vwrq->disabled = ((vwrq->value < MRVDRV_FRAG_MIN_VALUE) || (vwrq->value > MRVDRV_FRAG_MAX_VALUE)); vwrq->fixed = 1;out: lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret); return ret;}static int wlan_get_mode(struct net_device *dev, struct iw_request_info *info, u32 * uwrq, char *extra){ wlan_private *priv = dev->priv; wlan_adapter *adapter = priv->adapter; lbs_deb_enter(LBS_DEB_WEXT); *uwrq = adapter->mode; lbs_deb_leave(LBS_DEB_WEXT); return 0;}static int mesh_wlan_get_mode(struct net_device *dev, struct iw_request_info *info, u32 * uwrq, char *extra){ lbs_deb_enter(LBS_DEB_WEXT); *uwrq = IW_MODE_REPEAT ; lbs_deb_leave(LBS_DEB_WEXT); return 0;}static int wlan_get_txpow(struct net_device *dev, struct iw_request_info *info, struct iw_param *vwrq, char *extra){ int ret = 0; wlan_private *priv = dev->priv; wlan_adapter *adapter = priv->adapter; lbs_deb_enter(LBS_DEB_WEXT); ret = libertas_prepare_and_send_command(priv, CMD_802_11_RF_TX_POWER, CMD_ACT_TX_POWER_OPT_GET, CMD_OPTION_WAITFORRSP, 0, NULL); if (ret) goto out; lbs_deb_wext("tx power level %d dbm\n", adapter->txpowerlevel); vwrq->value = adapter->txpowerlevel; vwrq->fixed = 1; if (adapter->radioon) { vwrq->disabled = 0; vwrq->flags = IW_TXPOW_DBM; } else { vwrq->disabled = 1; }out: lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret); return ret;}static int wlan_set_retry(struct net_device *dev, struct iw_request_info *info, struct iw_param *vwrq, char *extra){ int ret = 0; wlan_private *priv = dev->priv; wlan_adapter *adapter = priv->adapter; lbs_deb_enter(LBS_DEB_WEXT); if (vwrq->flags == IW_RETRY_LIMIT) { /* The MAC has a 4-bit Total_Tx_Count register Total_Tx_Count = 1 + Tx_Retry_Count */#define TX_RETRY_MIN 0#define TX_RETRY_MAX 14 if (vwrq->value < TX_RETRY_MIN || vwrq->value > TX_RETRY_MAX) return -EINVAL; /* Adding 1 to convert retry count to try count */ adapter->txretrycount = vwrq->value + 1; ret = libertas_prepare_and_send_command(priv, CMD_802_11_SNMP_MIB, CMD_ACT_SET, CMD_OPTION_WAITFORRSP, OID_802_11_TX_RETRYCOUNT, NULL); if (ret) goto out; } else { return -EOPNOTSUPP; }out: lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret); return ret;}static int wlan_get_retry(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 ret = 0; lbs_deb_enter(LBS_DEB_WEXT); adapter->txretrycount = 0; ret = libertas_prepare_and_send_command(priv, CMD_802_11_SNMP_MIB, CMD_ACT_GET, CMD_OPTION_WAITFORRSP, OID_802_11_TX_RETRYCOUNT, NULL); if (ret) goto out; vwrq->disabled = 0; if (!vwrq->flags) { vwrq->flags = IW_RETRY_LIMIT; /* Subtract 1 to convert try count to retry count */ vwrq->value = adapter->txretrycount - 1; }out: lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret); return ret;}static inline void sort_channels(struct iw_freq *freq, int num){ int i, j; struct iw_freq temp; for (i = 0; i < num; i++) for (j = i + 1; j < num; j++) if (freq[i].i > freq[j].i) { temp.i = freq[i].i; temp.m = freq[i].m; freq[i].i = freq[j].i; freq[i].m = freq[j].m; freq[j].i = temp.i; freq[j].m = temp.m; }}/* data rate listing MULTI_BANDS: abg a b b/g Infra G(12) A(8) B(4) G(12) Adhoc A+B(12) A(8) B(4) B(4) non-MULTI_BANDS: b b/g
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -