📄 wlan_wext.c
字号:
/*
* File : wlan_wext.c
*/
#include "include.h"
#define WAIT_FOR_SCAN_RRESULT_MAX_TIME (10 * HZ)
static int get_active_data_rates(wlan_adapter *Adapter, WLAN_802_11_RATES rates);
static inline int wlan_scan_type_ioctl(wlan_private *priv, struct iwreq *wrq);
int ascii2hex(unsigned char *d, char *s, u32 dlen)
{
int i;
unsigned char n;
memset(d, 0x00, dlen);
for (i = 0; i < dlen * 2; i++) {
if ((s[i] >= 48) && (s[i] <= 57))
n = s[i] - 48;
else if ((s[i] >= 65) && (s[i] <= 70))
n = s[i] - 55;
else if ((s[i] >= 97) && (s[i] <= 102))
n = s[i] - 87;
else
break;
if ((i % 2) == 0)
n = n * 16;
d[i / 2] += n;
}
return i;
}
void *wlan_memchr(void *s, int c, int n)
{
const unsigned char *p = s;
while(n-- != 0) {
if((unsigned char)c == *p++) {
return (void *) (p - 1);
}
}
return NULL;
}
#if WIRELESS_EXT > 14
static int mw_to_dbm(int mw)
{
if (mw < 2)
return 0;
else if (mw < 3)
return 3;
else if (mw < 4)
return 5;
else if (mw < 6)
return 7;
else if (mw < 7)
return 8;
else if (mw < 8)
return 9;
else if (mw < 10)
return 10;
else if (mw < 13)
return 11;
else if (mw < 16)
return 12;
else if (mw < 20)
return 13;
else if (mw < 25)
return 14;
else if (mw < 32)
return 15;
else if (mw < 40)
return 16;
else if (mw < 50)
return 17;
else if (mw < 63)
return 18;
else if (mw < 79)
return 19;
else if (mw < 100)
return 20;
else
return 21;
}
#endif
CHANNEL_FREQ_POWER *find_cfp_by_band_and_channel(wlan_adapter *adapter,
u8 band, u16 channel)
{
CHANNEL_FREQ_POWER *cfp = NULL;
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];
#ifdef ENABLE_802_11D
if( adapter->State11D.Enable11D == ENABLE_11D ) {
rc = &adapter->universal_channel[j];
}
#endif
if(!rc->Valid || !rc->CFP)
continue;
#ifdef MULTI_BANDS
switch (rc->Band) {
case BAND_A:
switch (band) {
case BAND_A: // matching BAND_A
break;
default:
continue;
}
break;
case BAND_B:
case BAND_G:
switch (band) {
case BAND_B: //matching BAND_B/G
case BAND_G:
break;
default:
continue;
}
break;
default:
continue;
}
#else
if (rc->Band != band)
continue;
#endif
for (i = 0; i < rc->NrCFP; i++) {
if (rc->CFP[i].Channel == channel) {
cfp = &rc->CFP[i];
break;
}
}
}
if (!cfp && channel)
PRINTK("find_cfp_by_band_and_channel(): cannot find "
"cfp by band %d & channel %d\n",band,channel);
return cfp;
}
CHANNEL_FREQ_POWER *find_cfp_by_band_and_freq(wlan_adapter *adapter,
u8 band, u32 freq)
{
CHANNEL_FREQ_POWER *cfp = NULL;
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];
#ifdef ENABLE_802_11D
if( adapter->State11D.Enable11D == ENABLE_11D ) {
rc = &adapter->universal_channel[j];
}
#endif
if(!rc->Valid || !rc->CFP)
continue;
#ifdef MULTI_BANDS
switch (rc->Band) {
case BAND_A:
switch (band) {
case BAND_A: // matching BAND_A
break;
default:
continue;
}
break;
case BAND_B:
case BAND_G:
switch (band) {
case BAND_B:
case BAND_G:
break;
default:
continue;
}
break;
default:
continue;
}
#else
if (rc->Band != band)
continue;
#endif
for (i = 0; i < rc->NrCFP; i++) {
if (rc->CFP[i].Freq == freq) {
cfp = &rc->CFP[i];
break;
}
}
}
if(!cfp && freq)
PRINTK("find_cfp_by_band_and_freql(): cannot find cfp by "
"band %d & freq %d\n",band,freq);
return cfp;
}
int wlan_associate(wlan_private *priv, WLAN_802_11_SSID *ssid)
{
int ret = 0;
wlan_adapter *Adapter = priv->adapter;
ret = PrepareAndSendCommand(priv, HostCmd_CMD_802_11_AUTHENTICATE,
0, HostCmd_OPTION_USE_INT
| HostCmd_OPTION_WAITFORRSP
, 0, HostCmd_PENDING_ON_NONE, &Adapter->CurrentBSSID);
if (ret) {
LEAVE();
return ret;
}
ret = PrepareAndSendCommand(priv, HostCmd_CMD_802_11_ASSOCIATE,
0, HostCmd_OPTION_USE_INT
| HostCmd_OPTION_WAITFORRSP
, 0, HostCmd_PENDING_ON_SET_OID, ssid);
return ret;
}
#ifdef MANF_CMD_SUPPORT
static int wlan_mfg_command(wlan_private * priv, void *userdata)
{
PkHeader *pkHdr;
int len, ret;
wlan_adapter *Adapter = priv->adapter;
ENTER();
// creating the cmdbuf
if (Adapter->mfg_cmd == NULL) {
PRINTK1("Creating cmdbuf\n");
if (!(Adapter->mfg_cmd = kmalloc(2000, GFP_KERNEL))) {
PRINTK1("kmalloc failed!\n");
return -1;
}
Adapter->mfg_cmd_len = 2000;
}
// get PktHdr from userdata
if (copy_from_user(Adapter->mfg_cmd, userdata, sizeof(PkHeader))) {
PRINTK1("copy from user failed :PktHdr\n");
return -1;
}
// get the size
pkHdr = (PkHeader *) Adapter->mfg_cmd;
len = pkHdr->len;
PRINTK1("cmdlen = %d\n", (u32) len);
while (len >= Adapter->mfg_cmd_len) {
kfree(Adapter->mfg_cmd);
if (!(Adapter->mfg_cmd = kmalloc(len + 256, GFP_KERNEL))) {
PRINTK1("kmalloc failed!\n");
return -1;
}
Adapter->mfg_cmd_len = len + 256;
}
// get the whole command from user
if (copy_from_user(Adapter->mfg_cmd, userdata, len)) {
PRINTK1("copy from user failed :PktHdr\n");
return -1;
}
ret = PrepareAndSendCommand(priv,
HostCmd_CMD_MFG_COMMAND,
0, HostCmd_OPTION_USE_INT
| HostCmd_OPTION_WAITFORRSP
, 0, HostCmd_PENDING_ON_NONE, NULL);
if (ret) {
LEAVE();
return ret;
}
// copy it back to user
if (Adapter->mfg_cmd_resp_len > 0) {
if (copy_to_user(userdata, Adapter->mfg_cmd, len)) {
PRINTK1("copy to user failed \n");
return -1;
}
}
LEAVE();
return ret;
}
#endif
static inline int StopAdhocNetwork(wlan_private *priv,u16 pending_info)
{
return PrepareAndSendCommand(priv, HostCmd_CMD_802_11_AD_HOC_STOP,
0, HostCmd_OPTION_USE_INT | HostCmd_OPTION_WAITFORRSP
, 0, pending_info, NULL);
}
static inline int SendDeauthentication(wlan_private *priv,u16 pending_info)
{
#ifdef REASSOC_CMD_SUPPORT
wlan_adapter *Adapter = priv->adapter;
/* If a reassociation attempt is in progress, do not send the deauth */
if (Adapter->reassocAttempt)
{
return 0;
}
#endif
return PrepareAndSendCommand(priv, HostCmd_CMD_802_11_DEAUTHENTICATE,
0, HostCmd_OPTION_USE_INT | HostCmd_OPTION_WAITFORRSP
, 0, pending_info, NULL);
}
static int ChangeAdhocChannel(wlan_private *priv, int channel)
{
int ret = 0;
wlan_adapter *Adapter = priv->adapter;
u16 new_channel = channel;
ENTER();
PRINTK1("Setting Adhoc Channel to = %d\n", Adapter->AdhocChannel);
//the channel in f/w could be out of sync. in some cases.
//always set the channel number
ret = PrepareAndSendCommand(priv, HostCmd_CMD_802_11_RF_CHANNEL,
RF_SET, HostCmd_OPTION_USE_INT
| HostCmd_OPTION_WAITFORRSP
, 0, HostCmd_PENDING_ON_CMD, &new_channel);
if (ret) {
LEAVE();
return ret;
}
if (Adapter->AdhocChannel == channel) {
LEAVE();
return 0;
}
Adapter->AdhocChannel = channel;
if (Adapter->MediaConnectStatus == WlanMediaStateConnected) {
int i;
WLAN_802_11_SSID curAdhocSsid;
PRINTK1("Channel Changed while in an IBSS\n");
/* Copy the current ssid */
memcpy(&curAdhocSsid, &Adapter->CurBssParams.ssid,
sizeof(WLAN_802_11_SSID));
/* Exit Adhoc mode */
PRINTK1("In ChangeAdhocChannel(): Sending Adhoc Stop\n");
ret = StopAdhocNetwork(priv, HostCmd_PENDING_ON_NONE);
if (ret) {
LEAVE();
return ret;
}
SendSpecificScan(priv, &curAdhocSsid);
// find out the BSSID that matches the current SSID
i = FindSSIDInList(Adapter, &curAdhocSsid, NULL,
Wlan802_11IBSS);
if (i >= 0) {
PRINTK1("SSID found at %d in List,"
"so join\n", i);
JoinAdhocNetwork(priv, &curAdhocSsid, i);
} else {
// else send START command
PRINTK1("SSID not found in list, "
"so creating adhoc with ssid = %s\n",
curAdhocSsid.Ssid);
StartAdhocNetwork(priv, &curAdhocSsid);
} // end of else (START command)
}
LEAVE();
return 0;
}
int wlan_set_freq(struct net_device *dev, struct iw_request_info *info,
struct iw_freq *fwrq, char *extra)
{
int ret = 0;
wlan_private *priv = dev->priv;
wlan_adapter *Adapter = priv->adapter;
int rc = -EINPROGRESS; /* Call commit handler */
CHANNEL_FREQ_POWER *cfp;
ENTER();
#ifdef DEEP_SLEEP
if ((Adapter->IsDeepSleep == TRUE)) {
printk(KERN_CRIT "SIOCSIWFREQ: IOCTLS called when station is "
"in DeepSleep\n");
return -EBUSY;
}
#endif
#ifdef MULTI_BANDS
if (Adapter->is_multiband) {
printk(KERN_CRIT "SIOCSIWFREQ: IOCTLS call not supported in "
"MultiBands mode, use private command "
"'setadhocch' instead.\n");
return -ENOTSUPP;
}
#endif
/*
* If setting by frequency, convert to a channel
*/
if (fwrq->e == 1) {
long f = fwrq->m / 100000;
int c = 0;
cfp = find_cfp_by_band_and_freq(Adapter, 0, f);
if (!cfp) {
PRINTK("Invalid freq=%ld\n", f);
return -EINVAL;
}
c = (int) cfp->Channel;
if (c < 0)
return -EINVAL;
fwrq->e = 0;
fwrq->m = c;
}
/*
* Setting by channel number
*/
if (fwrq->m > 1000 || fwrq->e > 0) {
rc = -EOPNOTSUPP;
} else {
int channel = fwrq->m;
cfp = find_cfp_by_band_and_channel(Adapter, 0, channel);
if (!cfp) {
rc = -EINVAL;
} else {
if (Adapter->InfrastructureMode == Wlan802_11IBSS) {
rc = ChangeAdhocChannel(priv, channel);
/* If station is WEP enabled, send the
* command to set WEP in firmware
*/
if (Adapter->SecInfo.WEPStatus ==
Wlan802_11WEPEnabled) {
PRINTK1("set_freq: WEP Enabled\n");
ret = PrepareAndSendCommand(priv,
HostCmd_CMD_802_11_SET_WEP,
0, HostCmd_OPTION_USE_INT
| HostCmd_OPTION_WAITFORRSP
, OID_802_11_ADD_WEP,
HostCmd_PENDING_ON_CMD,
NULL);
if (ret) {
LEAVE();
return ret;
}
Adapter->CurrentPacketFilter |=
HostCmd_ACT_MAC_WEP_ENABLE;
SetMacPacketFilter(priv);
}
} else {
rc = -EOPNOTSUPP;
}
}
}
LEAVE();
return rc;
}
int SendSpecificScan(wlan_private *priv, WLAN_802_11_SSID *RequestedSSID)
{
wlan_adapter *Adapter = priv->adapter;
ENTER();
if (!Adapter->bIsScanInProgress) {
/* store the SSID info temporarily */
if (RequestedSSID) {
/* Specific BSSID */
memcpy(&(Adapter->AttemptedSSIDBeforeScan),
RequestedSSID, sizeof(WLAN_802_11_SSID));
memcpy(&Adapter->SpecificScanSSID, RequestedSSID,
sizeof(WLAN_802_11_SSID));
}
Adapter->SetSpecificScanSSID = TRUE;
#ifdef PROGRESSIVE_SCAN
Adapter->ChannelsPerScan = MRVDRV_CHANNELS_PER_ACTIVE_SCAN;
#endif
wlan_scan_networks(priv, HostCmd_PENDING_ON_NONE);
Adapter->SetSpecificScanSSID = FALSE;
#ifdef PROGRESSIVE_SCAN
Adapter->ChannelsPerScan = MRVDRV_CHANNELS_PER_SCAN;
#endif
}
if (Adapter->SurpriseRemoved)
return -1;
LEAVE();
return 0;
}
#ifdef DEEP_SLEEP
int SetDeepSleep(wlan_private *priv, BOOLEAN bDeepSleep)
{
int ret = 0;
wlan_adapter *Adapter = priv->adapter;
ENTER();
#ifdef PS_REQUIRED
// check if it is in IEEE PS mode or not
if (Adapter->PSMode != Wlan802_11PowerModeCAM) {
LEAVE();
return 0;
}
#endif
if (bDeepSleep == TRUE) {
if (Adapter->IsDeepSleep != TRUE) {
PRINTK("Deep Sleep : sleep\n");
/* If the state is associated, turn off the
* network device */
if (Adapter->MediaConnectStatus ==
WlanMediaStateConnected) {
/* Flush all the packets upto the OS before stopping */
wlan_send_rxskbQ(priv);
netif_carrier_off(priv->wlan_dev.netdev);
}
// note: the command could be queued and executed later
// if there is command in prigressing.
ret = PrepareAndSendCommand(priv,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -