📄 wlan_cmd.c
字号:
#endif /*TLV_SCAN*/
/*
* Function: Mac Control
*/
static inline int wlan_cmd_mac_control(wlan_private * priv,
HostCmd_DS_COMMAND * cmd)
{
HostCmd_DS_MAC_CONTROL *mac = &cmd->params.macctrl;
ENTER();
cmd->Command = wlan_cpu_to_le16(HostCmd_CMD_MAC_CONTROL);
cmd->Size = wlan_cpu_to_le16(sizeof(HostCmd_DS_MAC_CONTROL) + S_DS_GEN);
mac->Action = wlan_cpu_to_le16(priv->adapter->CurrentPacketFilter);
PRINTK("cmd_mac_control() Action=0x%X Size=%d\n",
mac->Action,cmd->Size);
LEAVE();
return 0;
}
void CleanupAndInsertCmd(wlan_private * priv, CmdCtrlNode * pTempCmd)
{
u32 flags;
wlan_adapter *Adapter = priv->adapter;
ENTER();
if (!pTempCmd)
return;
spin_lock_irqsave(&Adapter->QueueSpinLock, flags);
CleanUpCmdCtrlNode(pTempCmd);
list_add_tail((struct list_head *)pTempCmd, &Adapter->CmdFreeQ);
spin_unlock_irqrestore(&Adapter->QueueSpinLock, flags);
LEAVE();
}
int SetRadioControl(wlan_private *priv)
{
int ret = 0;
ENTER();
ret = PrepareAndSendCommand(priv, HostCmd_CMD_802_11_RADIO_CONTROL,
HostCmd_ACT_GEN_SET, HostCmd_OPTION_USE_INT,
0, HostCmd_PENDING_ON_GET_OID, NULL);
mdelay(200);
PRINTK1("Radio = 0x%X, Preamble = 0x%X\n",
priv->adapter->RadioOn, priv->adapter->Preamble);
LEAVE();
return ret;
}
/* This function will verify the provided rates with the card
* supported rates, and fills only the common rates between them
* in to the destination address
* NOTE: Setting the MSB of the basic rates need to be taken
* care, either before or after calling this function */
inline int get_common_rates(wlan_adapter *Adapter, u8 *dest, int size1,
u8 *card_rates, int size2)
{
int i;
u8 tmp[30], *ptr = dest;
memset(&tmp, 0, sizeof(tmp));
memcpy(&tmp, dest, MIN(size1,sizeof(tmp)));
memset(dest, 0, size1);
/* Mask the top bit of the original values */
for (i = 0; tmp[i] && i < sizeof(tmp); i++)
tmp[i] &= 0x7F;
for (i = 0; card_rates[i] && i < size2; i++) {
/* Check for Card Rate in tmp, excluding the top bit */
if (strchr(tmp, card_rates[i] & 0x7F)) {
/* Values match, so copy the Card Rate to dest */
*dest++ = card_rates[i];
}
}
HEXDUMP("AP Rates", tmp, sizeof(tmp));
HEXDUMP("Card Rates", card_rates, size2);
HEXDUMP("Common Rates", ptr, size1);
PRINTK1("Data Rate = 0x%X\n", Adapter->DataRate);
if (!Adapter->Is_DataRate_Auto) {
while (*ptr) {
if ((*ptr & 0x7f) == Adapter->DataRate)
return 0; // fixed rate match
ptr++;
}
printk(KERN_ALERT "Previously set fixed data rate %#x isn't "
"compatible with the network.\n",Adapter->DataRate);
return -1; // no fixed rate match
}
return 0; // auto rate
}
#ifdef TLV_ASSOCIATION
static inline int wlan_cmd_802_11_associate(wlan_private * priv,
CmdCtrlNode * pTempCmd,
void *InfoBuf)
{
int ret = 0;
int i;
wlan_adapter *Adapter = priv->adapter;
HostCmd_DS_COMMAND *cmd = (HostCmd_DS_COMMAND *)
pTempCmd->BufVirtualAddr;
HostCmd_DS_802_11_ASSOCIATE *pAsso = &cmd->params.associate;
u8 *pReqBSSID = NULL;
WLAN_802_11_BSSID *pBSSIDList;
u8 *card_rates;
int card_rates_size;
#ifdef MULTI_BANDS
HostCmd_DS_802_11_BAND_CONFIG bc;
#endif /* MULTI BANDS*/
u16 TmpCap;
u8 *pos = (u8 *)pAsso;
MrvlIEtypes_SsIdParamSet_t *ssid;
MrvlIEtypes_PhyParamSet_t *phy;
MrvlIEtypes_SsParamSet_t *ss;
MrvlIEtypes_RatesParamSet_t *rates;
#ifdef WPA
MrvlIEtypes_RsnParamSet_t *rsn;
#endif
#ifdef WMM
MrvlIEtypes_WmmParamSet_t *wmm;
#endif
ENTER();
if (!Adapter)
return -ENODEV;
cmd->Command = wlan_cpu_to_le16(HostCmd_CMD_802_11_ASSOCIATE);
if (Adapter->RequestViaBSSID)
pReqBSSID = Adapter->RequestedBSSID;
/*
* find out the BSSID that matches
* the SSID given in InformationBuffer
*/
PRINTK1("NumOfBSSIDs = %u\n", Adapter->ulNumOfBSSIDs);
PRINTK1("Wanted SSID = %s\n", ((WLAN_802_11_SSID *)InfoBuf)->Ssid);
#ifdef DEBUG
for (i = 0; i < Adapter->ulNumOfBSSIDs; i++) {
ssid = &Adapter->BSSIDList[i].Ssid;
PRINTK1("Listed SSID = %s\n", ssid->Ssid);
}
#endif
i = FindSSIDInList(Adapter, InfoBuf, pReqBSSID,
Wlan802_11Infrastructure);
if (i >= 0) {
memmove(pAsso->PeerStaAddr, &(Adapter->BSSIDList[i].MacAddress),
ETH_ALEN);
} else {
PRINTK1("HWAC - SSID is not in the list\n");
return -1;
}
pos += sizeof(pAsso->PeerStaAddr);
/* Set the temporary BSSID Index */
Adapter->ulAttemptedBSSIDIndex = i;
pBSSIDList = &Adapter->BSSIDList[i];
// set preamble to firmware
if (Adapter->capInfo.ShortPreamble && pBSSIDList->Cap.ShortPreamble) {
Adapter->Preamble = HostCmd_TYPE_SHORT_PREAMBLE;
} else {
Adapter->Preamble = HostCmd_TYPE_LONG_PREAMBLE;
}
SetRadioControl(priv);
/* set the Capability info */
memcpy(&TmpCap, &pBSSIDList->Cap, sizeof(pAsso->CapInfo));
TmpCap &= CAPINFO_MASK;
PRINTK("TmpCap=%4X CAPINFO_MASK=%4X\n", TmpCap, CAPINFO_MASK );
TmpCap = wlan_cpu_to_le16(TmpCap);
memcpy(&pAsso->CapInfo, &TmpCap, sizeof(pAsso->CapInfo));
pos += sizeof(pAsso->CapInfo);
/* set the listen interval */
pAsso->ListenInterval = Adapter->ListenInterval;
pos += sizeof(pAsso->ListenInterval);
pos += sizeof(pAsso->BcnPeriod);
pos += sizeof(pAsso->DtimPeriod);
ssid = (MrvlIEtypes_SsIdParamSet_t *)pos;
ssid->Header.Type = wlan_cpu_to_le16(TLV_TYPE_SSID);
ssid->Header.Len = pBSSIDList->Ssid.SsidLength;
memcpy(ssid->SsId, pBSSIDList->Ssid.Ssid, ssid->Header.Len);
pos += sizeof(ssid->Header) + ssid->Header.Len;
phy = (MrvlIEtypes_PhyParamSet_t *)pos;
phy->Header.Type = wlan_cpu_to_le16(TLV_TYPE_PHY_DS);
phy->Header.Len = sizeof(phy->fh_ds.DsParamSet);
memcpy(&phy->fh_ds.DsParamSet, &pBSSIDList->PhyParamSet.DsParamSet.CurrentChan,
sizeof(phy->fh_ds.DsParamSet));
pos += sizeof(phy->Header) + phy->Header.Len;
ss = (MrvlIEtypes_SsParamSet_t *)pos;
ss->Header.Type = wlan_cpu_to_le16(TLV_TYPE_CF);
ss->Header.Len = sizeof(ss->cf_ibss.CfParamSet);
pos += sizeof(ss->Header) + ss->Header.Len;
rates = (MrvlIEtypes_RatesParamSet_t *)pos;
rates->Header.Type = wlan_cpu_to_le16(TLV_TYPE_RATES);
memcpy(&rates->Rates,&pBSSIDList->SupportedRates, WLAN_SUPPORTED_RATES);
#ifdef MULTI_BANDS
if (pBSSIDList->bss_band == BAND_A) {
card_rates = SupportedRates_A;
card_rates_size = sizeof(SupportedRates_A);
}
else if (pBSSIDList->bss_band == BAND_B) {
card_rates = SupportedRates_B;
card_rates_size = sizeof(SupportedRates_B);
}
else if (pBSSIDList->bss_band == BAND_G) {
card_rates = SupportedRates_G;
card_rates_size = sizeof(SupportedRates_G);
}
else {
return -EINVAL;
}
#else
card_rates = SupportedRates;
card_rates_size = sizeof(SupportedRates);
#endif /* MULTI_BANDS*/
if (get_common_rates(Adapter, rates->Rates, WLAN_SUPPORTED_RATES,
card_rates, card_rates_size)) {
return -EINVAL;
}
//strlen() here may not right !!!
rates->Header.Len = MIN(strlen(rates->Rates), WLAN_SUPPORTED_RATES);
Adapter->CurBssParams.NumOfRates = rates->Header.Len;
pos += sizeof(rates->Header) + rates->Header.Len;
#ifdef WPA
if (Adapter->SecInfo.WPAEnabled
#ifdef WPA2
|| Adapter->SecInfo.WPA2Enabled
#endif //WPA2
) {
rsn = (MrvlIEtypes_RsnParamSet_t *)pos;
rsn->Header.Type = (u16)Adapter->Wpa_ie[0]; /* WPA_IE or WPA2_IE */
rsn->Header.Type = wlan_cpu_to_le16(rsn->Header.Type);
rsn->Header.Len = (u16)Adapter->Wpa_ie[1];
memcpy(rsn->RsnIE, &Adapter->Wpa_ie[2], rsn->Header.Len);
HEXDUMP("RSN IE", (u8*)rsn, sizeof(rsn->Header) + rsn->Header.Len);
pos += sizeof(rsn->Header) + rsn->Header.Len;
}
#endif //WPA
#ifdef WMM
if (Adapter->wmm.required && pBSSIDList->Wmm_IE[0] == WMM_IE) {
Adapter->CurrentPacketFilter |= HostCmd_ACT_MAC_WMM_ENABLE;
SetMacPacketFilter(priv);
wmm = (MrvlIEtypes_WmmParamSet_t *)pos;
wmm->Header.Type = (u16)wmm_ie[0];
wmm->Header.Type = wlan_cpu_to_le16(wmm->Header.Type);
wmm->Header.Len = (u16)wmm_ie[1];
memcpy(wmm->WmmIE, &wmm_ie[2], wmm->Header.Len);
#ifdef WMM_UAPSD
if((pBSSIDList->Wmm_IE[WMM_QOS_INFO_OFFSET] & WMM_QOS_INFO_UAPSD_BIT) && ((Adapter->wmm.qosinfo & 0x0f) != 0))
{
memcpy((u8 *)wmm->WmmIE + wmm->Header.Len - 1, &Adapter->wmm.qosinfo, 1);
}
#endif
HEXDUMP("WMM IE", (u8*)wmm, sizeof(wmm->Header) + wmm->Header.Len);
pos += sizeof(wmm->Header) + wmm->Header.Len;
}
else {
Adapter->CurrentPacketFilter &= ~HostCmd_ACT_MAC_WMM_ENABLE;
SetMacPacketFilter(priv);
}
#endif /* WMM */
#ifdef REASSOC_CMD_SUPPORT
wlan_cmd_append_reassoc_tlv(priv, &pos);
#endif
#ifdef IWGENIE_SUPPORT
wlan_cmd_append_generic_ie(priv, &pos);
#endif
#ifdef CCX
#ifdef ENABLE_802_11H_TPC
wlan_ccx_process_association_req(&pos, &pBSSIDList->ccx_bss_info,
!pBSSIDList->Sensed11H);
#else
wlan_ccx_process_association_req(&pos, &pBSSIDList->ccx_bss_info, TRUE);
#endif
#endif
cmd->Size = wlan_cpu_to_le16((u16)(pos - (u8 *)pAsso) + S_DS_GEN);
/* update CurBssParams */
Adapter->CurBssParams.channel = (pBSSIDList
->PhyParamSet.DsParamSet.CurrentChan);
#ifdef MULTI_BANDS
Adapter->CurBssParams.band = pBSSIDList->bss_band;
#endif /* MULTI_BANDS*/
/* Copy the infra. association rates into Current BSS state structure */
memcpy(&Adapter->CurBssParams.DataRates, &rates->Rates,
MIN(sizeof(Adapter->CurBssParams.DataRates), rates->Header.Len));
PRINTK1("rates->Header.Len = %d\n", rates->Header.Len);
/* set IBSS field */
if (pBSSIDList->InfrastructureMode == Wlan802_11Infrastructure)
{
pAsso->CapInfo.Ess = 1; /* HostCmd_CAPINFO_ESS */
#ifdef ENABLE_802_11D
ret = wlan_parse_dnld_countryinfo_11d( priv );
if ( ret )
{
LEAVE();
return ret;
}
#endif
#ifdef ENABLE_802_11H_TPC
/*infra, before Assoc, send power constraint to FW first. */
{
PWLAN_802_11_BSSID bssid =
&(Adapter->BSSIDList[Adapter->ulAttemptedBSSIDIndex]);
if (Adapter->State11HTPC.Enable11HTPC==TRUE &&
bssid->Sensed11H )
pAsso->CapInfo.SpectrumMgmt = 1;
PRINTK2( "11HTPC: Cap = 0x%x\n", *(unsigned int *)&(pAsso->CapInfo));
PRINTK2("11HTPC:Enable11H=%s Sensed11H=%s\n",
(Adapter->State11HTPC.Enable11HTPC == TRUE)?"TRUE":"FALSE",
(bssid->Sensed11H)?"TRUE":"FALSE"
);
if (Adapter->State11HTPC.Enable11HTPC==TRUE &&
bssid->Sensed11H ) {
Adapter->State11HTPC.InfoTpc.Chan =
Adapter->CurBssParams.channel;
Adapter->State11HTPC.InfoTpc.PowerConstraint =
bssid->PowerConstraint.LocalPowerConstraint;
/*Enabel 11H and Dnld TPC Info to FW*/
wlan_802_11h_tpc_enable( priv, TRUE );
ret = PrepareAndSendCommand(priv,
HostCmd_CMD_802_11H_TPC_INFO,
HostCmd_ACT_SET, HostCmd_OPTION_USE_INT,
0, HostCmd_PENDING_ON_NONE, NULL);
if (ret) {
PRINTK2("11HTPC:Err: Send TPC_INFO CMD: %d\n", ret);
LEAVE();
return ret;
}
}
else {
wlan_802_11h_tpc_enable( priv, FALSE ); /* Disable 11H*/
}
}
#endif
}
Adapter->bIsAssociationInProgress = TRUE;
/* need to report disconnect event if currently associated */
if (Adapter->CurBssParams.ssid.SsidLength != 0) {
MacEventDisconnected(priv);
}
#ifdef MULTI_BANDS
if (Adapter->is_multiband) {
bc.BandSelection = Adapter->CurBssParams.band;
bc.Channel = Adapter->CurBssParams.channel;
ret = PrepareAndSendCommand(priv,
HostCmd_CMD_802_11_BAND_CONFIG,
HostCmd_ACT_SET,
(HostCmd_OPTION_USE_INT
| HostCmd_OPTION_WAITFORRSP),
0, HostCmd_PENDING_ON_NONE, &bc);
if (ret) {
LEAVE();
return ret;
}
}
#endif /* MULTI_BANDS */
LEAVE();
return ret;
}
#else /* !TLV_ASSOCIATION */
static inline int wlan_cmd_802_11_associate(wlan_private * priv,
CmdCtrlNode * pTempCmd,
void *InfoBuf)
{
int ret = 0;
int i;
wlan_adapter *Adapter = priv->adapter;
HostCmd_DS_COMMAND *cmd = (HostCmd_DS_COMMAND *)
pTempCmd->BufVirtualAddr;
HostCmd_DS_802_11_ASSOCIATE *pAsso = &cmd->params.associate;
u8 *pReqBSSID = NULL;
u8 *card_rates;
int card_rates_size;
#ifdef MULTI_BANDS
HostCmd_DS_802_11_BAND_CONFIG bc;
#endif /* MULTI BANDS*/
#ifdef DEBUG
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -