5783 lines
178 KiB
C
5783 lines
178 KiB
C
/*
|
|
* Copyright (c) 2007-2008 Atheros Communications Inc.
|
|
*
|
|
* Permission to use, copy, modify, and/or distribute this software for any
|
|
* purpose with or without fee is hereby granted, provided that the above
|
|
* copyright notice and this permission notice appear in all copies.
|
|
*
|
|
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
|
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
|
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
|
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
|
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
|
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
|
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
|
*/
|
|
|
|
#include "cprecomp.h"
|
|
#include "ratectrl.h"
|
|
#include "../hal/hpreg.h"
|
|
|
|
/* TODO : change global variable to constant */
|
|
u8_t zgWpaRadiusOui[] = { 0x00, 0x50, 0xf2, 0x01 };
|
|
u8_t zgWpaAesOui[] = { 0x00, 0x50, 0xf2, 0x04 };
|
|
u8_t zgWpa2RadiusOui[] = { 0x00, 0x0f, 0xac, 0x01 };
|
|
u8_t zgWpa2AesOui[] = { 0x00, 0x0f, 0xac, 0x04 };
|
|
|
|
const u16_t zcCwTlb[16] = { 0, 1, 3, 7, 15, 31, 63, 127,
|
|
255, 511, 1023, 2047, 4095, 4095, 4095, 4095};
|
|
|
|
void zfStaStartConnectCb(zdev_t* dev);
|
|
|
|
/************************************************************************/
|
|
/* */
|
|
/* FUNCTION DESCRIPTION zfStaPutApIntoBlockingList */
|
|
/* Put AP into blocking AP list. */
|
|
/* */
|
|
/* INPUTS */
|
|
/* dev : device pointer */
|
|
/* bssid : AP's BSSID */
|
|
/* weight : weight of AP */
|
|
/* */
|
|
/* OUTPUTS */
|
|
/* none */
|
|
/* */
|
|
/* AUTHOR */
|
|
/* Stephen Chen Atheros Communications, INC. 2006.12 */
|
|
/* */
|
|
/************************************************************************/
|
|
void zfStaPutApIntoBlockingList(zdev_t* dev, u8_t* bssid, u8_t weight)
|
|
{
|
|
u16_t i, j;
|
|
zmw_get_wlan_dev(dev);
|
|
zmw_declare_for_critical_section();
|
|
|
|
if (weight > 0)
|
|
{
|
|
zmw_enter_critical_section(dev);
|
|
/*Find same bssid entry first*/
|
|
for (i=0; i<ZM_MAX_BLOCKING_AP_LIST_SIZE; i++)
|
|
{
|
|
for (j=0; j<6; j++)
|
|
{
|
|
if(wd->sta.blockingApList[i].addr[j]!= bssid[j])
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
|
|
if(j==6)
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
/*This bssid doesn't have old record.Find an empty entry*/
|
|
if (i == ZM_MAX_BLOCKING_AP_LIST_SIZE)
|
|
{
|
|
for (i=0; i<ZM_MAX_BLOCKING_AP_LIST_SIZE; i++)
|
|
{
|
|
if (wd->sta.blockingApList[i].weight == 0)
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
/* If the list is full, pick one entry for replacement */
|
|
if (i == ZM_MAX_BLOCKING_AP_LIST_SIZE)
|
|
{
|
|
i = bssid[5] & (ZM_MAX_BLOCKING_AP_LIST_SIZE-1);
|
|
}
|
|
|
|
/* Update AP address and weight */
|
|
for (j=0; j<6; j++)
|
|
{
|
|
wd->sta.blockingApList[i].addr[j] = bssid[j];
|
|
}
|
|
|
|
wd->sta.blockingApList[i].weight = weight;
|
|
zmw_leave_critical_section(dev);
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
/************************************************************************/
|
|
/* */
|
|
/* FUNCTION DESCRIPTION zfStaIsApInBlockingList */
|
|
/* Is AP in blocking list. */
|
|
/* */
|
|
/* INPUTS */
|
|
/* dev : device pointer */
|
|
/* bssid : AP's BSSID */
|
|
/* */
|
|
/* OUTPUTS */
|
|
/* TRUE : AP in blocking list */
|
|
/* FALSE : AP not in blocking list */
|
|
/* */
|
|
/* AUTHOR */
|
|
/* Stephen Chen Atheros Communications, INC. 2006.12 */
|
|
/* */
|
|
/************************************************************************/
|
|
u16_t zfStaIsApInBlockingList(zdev_t* dev, u8_t* bssid)
|
|
{
|
|
u16_t i, j;
|
|
zmw_get_wlan_dev(dev);
|
|
//zmw_declare_for_critical_section();
|
|
|
|
//zmw_enter_critical_section(dev);
|
|
for (i=0; i<ZM_MAX_BLOCKING_AP_LIST_SIZE; i++)
|
|
{
|
|
if (wd->sta.blockingApList[i].weight != 0)
|
|
{
|
|
for (j=0; j<6; j++)
|
|
{
|
|
if (wd->sta.blockingApList[i].addr[j] != bssid[j])
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
if (j == 6)
|
|
{
|
|
//zmw_leave_critical_section(dev);
|
|
return TRUE;
|
|
}
|
|
}
|
|
}
|
|
//zmw_leave_critical_section(dev);
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
/************************************************************************/
|
|
/* */
|
|
/* FUNCTION DESCRIPTION zfStaRefreshBlockList */
|
|
/* Is AP in blocking list. */
|
|
/* */
|
|
/* INPUTS */
|
|
/* dev : device pointer */
|
|
/* flushFlag : flush whole blocking list */
|
|
/* */
|
|
/* OUTPUTS */
|
|
/* none */
|
|
/* */
|
|
/* AUTHOR */
|
|
/* Stephen Chen Atheros Communications, INC. 2006.12 */
|
|
/* */
|
|
/************************************************************************/
|
|
void zfStaRefreshBlockList(zdev_t* dev, u16_t flushFlag)
|
|
{
|
|
u16_t i;
|
|
zmw_get_wlan_dev(dev);
|
|
zmw_declare_for_critical_section();
|
|
|
|
zmw_enter_critical_section(dev);
|
|
for (i=0; i<ZM_MAX_BLOCKING_AP_LIST_SIZE; i++)
|
|
{
|
|
if (wd->sta.blockingApList[i].weight != 0)
|
|
{
|
|
if (flushFlag != 0)
|
|
{
|
|
wd->sta.blockingApList[i].weight = 0;
|
|
}
|
|
else
|
|
{
|
|
wd->sta.blockingApList[i].weight--;
|
|
}
|
|
}
|
|
}
|
|
zmw_leave_critical_section(dev);
|
|
return;
|
|
}
|
|
|
|
|
|
/************************************************************************/
|
|
/* */
|
|
/* FUNCTION DESCRIPTION zfStaConnectFail */
|
|
/* Handle Connect failure. */
|
|
/* */
|
|
/* INPUTS */
|
|
/* dev : device pointer */
|
|
/* bssid : BSSID */
|
|
/* reason : reason of failure */
|
|
/* */
|
|
/* OUTPUTS */
|
|
/* none */
|
|
/* */
|
|
/* AUTHOR */
|
|
/* Stephen Chen Atheros Communications, INC. 2006.12 */
|
|
/* */
|
|
/************************************************************************/
|
|
void zfStaConnectFail(zdev_t* dev, u16_t reason, u16_t* bssid, u8_t weight)
|
|
{
|
|
zmw_get_wlan_dev(dev);
|
|
|
|
/* Change internal state */
|
|
zfChangeAdapterState(dev, ZM_STA_STATE_DISCONNECT);
|
|
|
|
/* Improve WEP/TKIP performace with HT AP, detail information please look bug#32495 */
|
|
//zfHpSetTTSIFSTime(dev, 0x8);
|
|
|
|
/* Notify wrapper of connection status changes */
|
|
if (wd->zfcbConnectNotify != NULL)
|
|
{
|
|
wd->zfcbConnectNotify(dev, reason, bssid);
|
|
}
|
|
|
|
/* Put AP into internal blocking list */
|
|
zfStaPutApIntoBlockingList(dev, (u8_t *)bssid, weight);
|
|
|
|
/* Issue another SCAN */
|
|
if ( wd->sta.bAutoReconnect )
|
|
{
|
|
zm_debug_msg0("Start internal scan...");
|
|
zfScanMgrScanStop(dev, ZM_SCAN_MGR_SCAN_INTERNAL);
|
|
zfScanMgrScanStart(dev, ZM_SCAN_MGR_SCAN_INTERNAL);
|
|
}
|
|
}
|
|
|
|
u8_t zfiWlanIBSSGetPeerStationsCount(zdev_t* dev)
|
|
{
|
|
zmw_get_wlan_dev(dev);
|
|
|
|
return wd->sta.oppositeCount;
|
|
}
|
|
|
|
u8_t zfiWlanIBSSIteratePeerStations(zdev_t* dev, u8_t numToIterate, zfpIBSSIteratePeerStationCb callback, void *ctx)
|
|
{
|
|
u8_t oppositeCount;
|
|
u8_t i;
|
|
u8_t index = 0;
|
|
|
|
zmw_get_wlan_dev(dev);
|
|
|
|
zmw_declare_for_critical_section();
|
|
|
|
zmw_enter_critical_section(dev);
|
|
|
|
oppositeCount = wd->sta.oppositeCount;
|
|
if ( oppositeCount > numToIterate )
|
|
{
|
|
oppositeCount = numToIterate;
|
|
}
|
|
|
|
for(i=0; i < ZM_MAX_OPPOSITE_COUNT; i++)
|
|
{
|
|
if ( oppositeCount == 0 )
|
|
{
|
|
break;
|
|
}
|
|
|
|
if ( wd->sta.oppositeInfo[i].valid == 0 )
|
|
{
|
|
continue;
|
|
}
|
|
|
|
callback(dev, &wd->sta.oppositeInfo[i], ctx, index++);
|
|
oppositeCount--;
|
|
|
|
}
|
|
|
|
zmw_leave_critical_section(dev);
|
|
|
|
return index;
|
|
}
|
|
|
|
|
|
s8_t zfStaFindFreeOpposite(zdev_t* dev, u16_t *sa, int *pFoundIdx)
|
|
{
|
|
int oppositeCount;
|
|
int i;
|
|
|
|
zmw_get_wlan_dev(dev);
|
|
|
|
oppositeCount = wd->sta.oppositeCount;
|
|
|
|
for(i=0; i < ZM_MAX_OPPOSITE_COUNT; i++)
|
|
{
|
|
if ( oppositeCount == 0 )
|
|
{
|
|
break;
|
|
}
|
|
|
|
if ( wd->sta.oppositeInfo[i].valid == 0 )
|
|
{
|
|
continue;
|
|
}
|
|
|
|
oppositeCount--;
|
|
if ( zfMemoryIsEqual((u8_t*) sa, wd->sta.oppositeInfo[i].macAddr, 6) )
|
|
{
|
|
//wd->sta.oppositeInfo[i].aliveCounter++;
|
|
wd->sta.oppositeInfo[i].aliveCounter = ZM_IBSS_PEER_ALIVE_COUNTER;
|
|
|
|
/* it is already stored */
|
|
return 1;
|
|
}
|
|
}
|
|
|
|
// Check if there's still space for new comer
|
|
if ( wd->sta.oppositeCount == ZM_MAX_OPPOSITE_COUNT )
|
|
{
|
|
return -1;
|
|
}
|
|
|
|
// Find an unused slot for new peer station
|
|
for(i=0; i < ZM_MAX_OPPOSITE_COUNT; i++)
|
|
{
|
|
if ( wd->sta.oppositeInfo[i].valid == 0 )
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
|
|
*pFoundIdx = i;
|
|
return 0;
|
|
}
|
|
|
|
s8_t zfStaFindOppositeByMACAddr(zdev_t* dev, u16_t *sa, u8_t *pFoundIdx)
|
|
{
|
|
u32_t oppositeCount;
|
|
u32_t i;
|
|
|
|
zmw_get_wlan_dev(dev);
|
|
|
|
oppositeCount = wd->sta.oppositeCount;
|
|
|
|
for(i=0; i < ZM_MAX_OPPOSITE_COUNT; i++)
|
|
{
|
|
if ( oppositeCount == 0 )
|
|
{
|
|
break;
|
|
}
|
|
|
|
if ( wd->sta.oppositeInfo[i].valid == 0 )
|
|
{
|
|
continue;
|
|
}
|
|
|
|
oppositeCount--;
|
|
if ( zfMemoryIsEqual((u8_t*) sa, wd->sta.oppositeInfo[i].macAddr, 6) )
|
|
{
|
|
*pFoundIdx = (u8_t)i;
|
|
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
*pFoundIdx = 0;
|
|
return 1;
|
|
}
|
|
|
|
static void zfStaInitCommonOppositeInfo(zdev_t* dev, int i)
|
|
{
|
|
zmw_get_wlan_dev(dev);
|
|
|
|
/* set the default rate to the highest rate */
|
|
wd->sta.oppositeInfo[i].valid = 1;
|
|
wd->sta.oppositeInfo[i].aliveCounter = ZM_IBSS_PEER_ALIVE_COUNTER;
|
|
wd->sta.oppositeCount++;
|
|
|
|
#ifdef ZM_ENABLE_IBSS_WPA2PSK
|
|
/* Set parameters for new opposite peer station !!! */
|
|
wd->sta.oppositeInfo[i].camIdx = 0xff; // Not set key in this location
|
|
wd->sta.oppositeInfo[i].pkInstalled = 0;
|
|
wd->sta.oppositeInfo[i].wpaState = ZM_STA_WPA_STATE_INIT ; // No encryption
|
|
#endif
|
|
}
|
|
|
|
int zfStaSetOppositeInfoFromBSSInfo(zdev_t* dev, struct zsBssInfo* pBssInfo)
|
|
{
|
|
int i;
|
|
u8_t* dst;
|
|
u16_t sa[3];
|
|
int res;
|
|
u32_t oneTxStreamCap;
|
|
|
|
zmw_get_wlan_dev(dev);
|
|
|
|
zfMemoryCopy((u8_t*) sa, pBssInfo->macaddr, 6);
|
|
|
|
res = zfStaFindFreeOpposite(dev, sa, &i);
|
|
if ( res != 0 )
|
|
{
|
|
goto zlReturn;
|
|
}
|
|
|
|
dst = wd->sta.oppositeInfo[i].macAddr;
|
|
zfMemoryCopy(dst, (u8_t *)sa, 6);
|
|
|
|
oneTxStreamCap = (zfHpCapability(dev) & ZM_HP_CAP_11N_ONE_TX_STREAM);
|
|
|
|
if (pBssInfo->extSupportedRates[1] != 0)
|
|
{
|
|
/* TODO : Handle 11n */
|
|
if (pBssInfo->frequency < 3000)
|
|
{
|
|
/* 2.4GHz */
|
|
if (pBssInfo->EnableHT == 1)
|
|
zfRateCtrlInitCell(dev, &wd->sta.oppositeInfo[i].rcCell, (oneTxStreamCap!=0)?3:2, 1, pBssInfo->SG40);
|
|
else
|
|
zfRateCtrlInitCell(dev, &wd->sta.oppositeInfo[i].rcCell, 1, 1, pBssInfo->SG40);
|
|
}
|
|
else
|
|
{
|
|
/* 5GHz */
|
|
if (pBssInfo->EnableHT == 1)
|
|
zfRateCtrlInitCell(dev, &wd->sta.oppositeInfo[i].rcCell, (oneTxStreamCap!=0)?3:2, 0, pBssInfo->SG40);
|
|
else
|
|
zfRateCtrlInitCell(dev, &wd->sta.oppositeInfo[i].rcCell, 1, 0, pBssInfo->SG40);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
/* TODO : Handle 11n */
|
|
if (pBssInfo->frequency < 3000)
|
|
{
|
|
/* 2.4GHz */
|
|
if (pBssInfo->EnableHT == 1)
|
|
zfRateCtrlInitCell(dev, &wd->sta.oppositeInfo[i].rcCell, (oneTxStreamCap!=0)?3:2, 1, pBssInfo->SG40);
|
|
else
|
|
zfRateCtrlInitCell(dev, &wd->sta.oppositeInfo[i].rcCell, 0, 1, pBssInfo->SG40);
|
|
}
|
|
else
|
|
{
|
|
/* 5GHz */
|
|
if (pBssInfo->EnableHT == 1)
|
|
zfRateCtrlInitCell(dev, &wd->sta.oppositeInfo[i].rcCell, (oneTxStreamCap!=0)?3:2, 0, pBssInfo->SG40);
|
|
else
|
|
zfRateCtrlInitCell(dev, &wd->sta.oppositeInfo[i].rcCell, 1, 0, pBssInfo->SG40);
|
|
}
|
|
}
|
|
|
|
|
|
zfStaInitCommonOppositeInfo(dev, i);
|
|
zlReturn:
|
|
return 0;
|
|
}
|
|
|
|
int zfStaSetOppositeInfoFromRxBuf(zdev_t* dev, zbuf_t* buf)
|
|
{
|
|
int i;
|
|
u8_t* dst;
|
|
u16_t sa[3];
|
|
int res = 0;
|
|
u16_t offset;
|
|
u8_t bSupportExtRate;
|
|
u32_t rtsctsRate = 0xffffffff; /* CTS:OFDM 6M, RTS:OFDM 6M */
|
|
u32_t oneTxStreamCap;
|
|
|
|
zmw_get_wlan_dev(dev);
|
|
zmw_declare_for_critical_section();
|
|
|
|
sa[0] = zmw_rx_buf_readh(dev, buf, ZM_WLAN_HEADER_A2_OFFSET);
|
|
sa[1] = zmw_rx_buf_readh(dev, buf, ZM_WLAN_HEADER_A2_OFFSET+2);
|
|
sa[2] = zmw_rx_buf_readh(dev, buf, ZM_WLAN_HEADER_A2_OFFSET+4);
|
|
|
|
zmw_enter_critical_section(dev);
|
|
|
|
res = zfStaFindFreeOpposite(dev, sa, &i);
|
|
if ( res != 0 )
|
|
{
|
|
goto zlReturn;
|
|
}
|
|
|
|
dst = wd->sta.oppositeInfo[i].macAddr;
|
|
zfCopyFromRxBuffer(dev, buf, dst, ZM_WLAN_HEADER_A2_OFFSET, 6);
|
|
|
|
if ( (wd->sta.currentFrequency < 3000) && !(wd->supportMode & (ZM_WIRELESS_MODE_24_54|ZM_WIRELESS_MODE_24_N)) )
|
|
{
|
|
bSupportExtRate = 0;
|
|
} else {
|
|
bSupportExtRate = 1;
|
|
}
|
|
|
|
if ( (bSupportExtRate == 1)
|
|
&& (wd->sta.currentFrequency < 3000)
|
|
&& (wd->wlanMode == ZM_MODE_IBSS)
|
|
&& (wd->wfc.bIbssGMode == 0) )
|
|
{
|
|
bSupportExtRate = 0;
|
|
}
|
|
|
|
wd->sta.connection_11b = 0;
|
|
oneTxStreamCap = (zfHpCapability(dev) & ZM_HP_CAP_11N_ONE_TX_STREAM);
|
|
|
|
if ( ((offset = zfFindElement(dev, buf, ZM_WLAN_EID_EXTENDED_RATE)) != 0xffff)
|
|
&& (bSupportExtRate == 1) )
|
|
{
|
|
/* TODO : Handle 11n */
|
|
if (wd->sta.currentFrequency < 3000)
|
|
{
|
|
/* 2.4GHz */
|
|
if (wd->sta.EnableHT == 1)
|
|
{
|
|
//11ng
|
|
zfRateCtrlInitCell(dev, &wd->sta.oppositeInfo[i].rcCell, (oneTxStreamCap!=0)?3:2, 1, wd->sta.SG40);
|
|
}
|
|
else
|
|
{
|
|
//11g
|
|
zfRateCtrlInitCell(dev, &wd->sta.oppositeInfo[i].rcCell, 1, 1, wd->sta.SG40);
|
|
}
|
|
rtsctsRate = 0x00001bb; /* CTS:CCK 1M, RTS:OFDM 6M */
|
|
}
|
|
else
|
|
{
|
|
/* 5GHz */
|
|
if (wd->sta.EnableHT == 1)
|
|
{
|
|
//11na
|
|
zfRateCtrlInitCell(dev, &wd->sta.oppositeInfo[i].rcCell, (oneTxStreamCap!=0)?3:2, 0, wd->sta.SG40);
|
|
}
|
|
else
|
|
{
|
|
//11a
|
|
zfRateCtrlInitCell(dev, &wd->sta.oppositeInfo[i].rcCell, 1, 0, wd->sta.SG40);
|
|
}
|
|
rtsctsRate = 0x10b01bb; /* CTS:OFDM 6M, RTS:OFDM 6M */
|
|
}
|
|
}
|
|
else
|
|
{
|
|
/* TODO : Handle 11n */
|
|
if (wd->sta.currentFrequency < 3000)
|
|
{
|
|
/* 2.4GHz */
|
|
if (wd->sta.EnableHT == 1)
|
|
{
|
|
//11ng
|
|
zfRateCtrlInitCell(dev, &wd->sta.oppositeInfo[i].rcCell, (oneTxStreamCap!=0)?3:2, 1, wd->sta.SG40);
|
|
rtsctsRate = 0x00001bb; /* CTS:CCK 1M, RTS:OFDM 6M */
|
|
}
|
|
else
|
|
{
|
|
//11b
|
|
zfRateCtrlInitCell(dev, &wd->sta.oppositeInfo[i].rcCell, 0, 1, wd->sta.SG40);
|
|
rtsctsRate = 0x0; /* CTS:CCK 1M, RTS:CCK 1M */
|
|
wd->sta.connection_11b = 1;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
/* 5GHz */
|
|
if (wd->sta.EnableHT == 1)
|
|
{
|
|
//11na
|
|
zfRateCtrlInitCell(dev, &wd->sta.oppositeInfo[i].rcCell, (oneTxStreamCap!=0)?3:2, 0, wd->sta.SG40);
|
|
}
|
|
else
|
|
{
|
|
//11a
|
|
zfRateCtrlInitCell(dev, &wd->sta.oppositeInfo[i].rcCell, 1, 0, wd->sta.SG40);
|
|
}
|
|
rtsctsRate = 0x10b01bb; /* CTS:OFDM 6M, RTS:OFDM 6M */
|
|
}
|
|
}
|
|
|
|
zfStaInitCommonOppositeInfo(dev, i);
|
|
|
|
zlReturn:
|
|
zmw_leave_critical_section(dev);
|
|
|
|
if (rtsctsRate != 0xffffffff)
|
|
{
|
|
zfHpSetRTSCTSRate(dev, rtsctsRate);
|
|
}
|
|
return res;
|
|
}
|
|
|
|
void zfStaProtErpMonitor(zdev_t* dev, zbuf_t* buf)
|
|
{
|
|
u16_t offset;
|
|
u8_t erp;
|
|
u8_t bssid[6];
|
|
|
|
zmw_get_wlan_dev(dev);
|
|
|
|
if ( (wd->wlanMode == ZM_MODE_INFRASTRUCTURE)&&(zfStaIsConnected(dev)) )
|
|
{
|
|
ZM_MAC_WORD_TO_BYTE(wd->sta.bssid, bssid);
|
|
|
|
if (zfRxBufferEqualToStr(dev, buf, bssid, ZM_WLAN_HEADER_A2_OFFSET, 6))
|
|
{
|
|
if ( (offset=zfFindElement(dev, buf, ZM_WLAN_EID_ERP)) != 0xffff )
|
|
{
|
|
erp = zmw_rx_buf_readb(dev, buf, offset+2);
|
|
|
|
if ( erp & ZM_BIT_1 )
|
|
{
|
|
//zm_debug_msg0("protection mode on");
|
|
if (wd->sta.bProtectionMode == FALSE)
|
|
{
|
|
wd->sta.bProtectionMode = TRUE;
|
|
zfHpSetSlotTime(dev, 0);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//zm_debug_msg0("protection mode off");
|
|
if (wd->sta.bProtectionMode == TRUE)
|
|
{
|
|
wd->sta.bProtectionMode = FALSE;
|
|
zfHpSetSlotTime(dev, 1);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
//Check the existence of Non-N AP
|
|
//Follow the check the "pBssInfo->EnableHT"
|
|
if ((offset = zfFindElement(dev, buf, ZM_WLAN_EID_HT_CAPABILITY)) != 0xffff)
|
|
{}
|
|
else if ((offset = zfFindElement(dev, buf, ZM_WLAN_PREN2_EID_HTCAPABILITY)) != 0xffff)
|
|
{}
|
|
else
|
|
{wd->sta.NonNAPcount++;}
|
|
}
|
|
}
|
|
|
|
void zfStaUpdateWmeParameter(zdev_t* dev, zbuf_t* buf)
|
|
{
|
|
u16_t tmp;
|
|
u16_t aifs[5];
|
|
u16_t cwmin[5];
|
|
u16_t cwmax[5];
|
|
u16_t txop[5];
|
|
u8_t acm;
|
|
u8_t ac;
|
|
u16_t len;
|
|
u16_t i;
|
|
u16_t offset;
|
|
u8_t rxWmeParameterSetCount;
|
|
|
|
zmw_get_wlan_dev(dev);
|
|
|
|
/* Update if WME parameter set count is changed */
|
|
/* If connect to WME AP */
|
|
if (wd->sta.wmeConnected != 0)
|
|
{
|
|
/* Find WME parameter element */
|
|
if ((offset = zfFindWifiElement(dev, buf, 2, 1)) != 0xffff)
|
|
{
|
|
if ((len = zmw_rx_buf_readb(dev, buf, offset+1)) >= 7)
|
|
{
|
|
rxWmeParameterSetCount=zmw_rx_buf_readb(dev, buf, offset+8);
|
|
if (rxWmeParameterSetCount != wd->sta.wmeParameterSetCount)
|
|
{
|
|
zm_msg0_mm(ZM_LV_0, "wmeParameterSetCount changed!");
|
|
wd->sta.wmeParameterSetCount = rxWmeParameterSetCount;
|
|
/* retrieve WME parameter and update TxQ parameters */
|
|
acm = 0xf;
|
|
for (i=0; i<4; i++)
|
|
{
|
|
if (len >= (8+(i*4)+4))
|
|
{
|
|
tmp=zmw_rx_buf_readb(dev, buf, offset+10+i*4);
|
|
ac = (tmp >> 5) & 0x3;
|
|
if ((tmp & 0x10) == 0)
|
|
{
|
|
acm &= (~(1<<ac));
|
|
}
|
|
aifs[ac] = ((tmp & 0xf) * 9) + 10;
|
|
tmp=zmw_rx_buf_readb(dev, buf, offset+11+i*4);
|
|
/* Convert to 2^n */
|
|
cwmin[ac] = zcCwTlb[(tmp & 0xf)];
|
|
cwmax[ac] = zcCwTlb[(tmp >> 4)];
|
|
txop[ac]=zmw_rx_buf_readh(dev, buf,
|
|
offset+12+i*4);
|
|
}
|
|
}
|
|
|
|
if ((acm & 0x4) != 0)
|
|
{
|
|
cwmin[2] = cwmin[0];
|
|
cwmax[2] = cwmax[0];
|
|
aifs[2] = aifs[0];
|
|
txop[2] = txop[0];
|
|
}
|
|
if ((acm & 0x8) != 0)
|
|
{
|
|
cwmin[3] = cwmin[2];
|
|
cwmax[3] = cwmax[2];
|
|
aifs[3] = aifs[2];
|
|
txop[3] = txop[2];
|
|
}
|
|
cwmin[4] = 3;
|
|
cwmax[4] = 7;
|
|
aifs[4] = 28;
|
|
|
|
if ((cwmin[2]+aifs[2]) > ((cwmin[0]+aifs[0])+1))
|
|
{
|
|
wd->sta.ac0PriorityHigherThanAc2 = 1;
|
|
}
|
|
else
|
|
{
|
|
wd->sta.ac0PriorityHigherThanAc2 = 0;
|
|
}
|
|
zfHpUpdateQosParameter(dev, cwmin, cwmax, aifs, txop);
|
|
}
|
|
}
|
|
}
|
|
} //if (wd->sta.wmeConnected != 0)
|
|
}
|
|
/* process 802.11h Dynamic Frequency Selection */
|
|
void zfStaUpdateDot11HDFS(zdev_t* dev, zbuf_t* buf)
|
|
{
|
|
zmw_get_wlan_dev(dev);
|
|
|
|
/*
|
|
Channel Switch Announcement Element Format
|
|
+------+----------+------+-------------------+------------------+--------------------+
|
|
|Format|Element ID|Length|Channel Switch Mode|New Channel Number|Channel Switch Count|
|
|
+------+----------+------+-------------------+------------------+--------------------+
|
|
|Bytes | 1 | 1 | 1 | 1 | 1 |
|
|
+------+----------+------+-------------------+------------------+--------------------+
|
|
|Value | 37 | 3 | 0 or 1 |unsigned integer |unsigned integer |
|
|
+------+----------+------+-------------------+------------------+--------------------+
|
|
*/
|
|
//u8_t length, channel, is5G;
|
|
u16_t offset;
|
|
|
|
/* get EID(Channel Switch Announcement) */
|
|
if ( (offset = zfFindElement(dev, buf, ZM_WLAN_EID_CHANNEL_SWITCH_ANNOUNCE)) == 0xffff )
|
|
{
|
|
//zm_debug_msg0("EID(Channel Switch Announcement) not found");
|
|
return;
|
|
}
|
|
else if ( zmw_rx_buf_readb(dev, buf, offset+1) == 0x3 )
|
|
{
|
|
zm_debug_msg0("EID(Channel Switch Announcement) found");
|
|
|
|
//length = zmw_rx_buf_readb(dev, buf, offset+1);
|
|
//zfCopyFromRxBuffer(dev, buf, pBssInfo->supportedRates, offset, length+2);
|
|
|
|
//Chanell Switch Mode set to 1, driver should disable transmit immediate
|
|
//we do this by poll CCA high
|
|
if (zmw_rx_buf_readb(dev, buf, offset+2) == 0x1 )
|
|
{
|
|
//use ZM_OID_INTERNAL_WRITE,ZM_CMD_RESET to notice firmware flush quene and stop dma,
|
|
//then restart rx dma but not tx dma
|
|
if (wd->sta.DFSDisableTx != TRUE)
|
|
{
|
|
/* TODO : zfHpResetTxRx would cause Rx hang */
|
|
//zfHpResetTxRx(dev);
|
|
wd->sta.DFSDisableTx = TRUE;
|
|
/* Trgger Rx DMA */
|
|
zfHpStartRecv(dev);
|
|
}
|
|
//Adapter->ZD80211HSetting.DisableTxBy80211H=TRUE;
|
|
//AcquireCtrOfPhyReg(Adapter);
|
|
//ZD1205_WRITE_REGISTER(Adapter,CR24, 0x0);
|
|
//ReleaseDoNotSleep(Adapter);
|
|
}
|
|
|
|
if (zmw_rx_buf_readb(dev, buf, offset+4) <= 0x2 )
|
|
{
|
|
//Channel Switch
|
|
//if Channel Switch Count = 0 , STA should change channel immediately.
|
|
//if Channel Switch Count > 0 , STA should change channel after TBTT*count
|
|
//But it won't be accurate to let driver calculate TBTT*count, and the value of
|
|
//Channel Switch Count will decrease by one each when continue receving beacon
|
|
//So we change channel here when we receive count <=2.
|
|
|
|
zfHpDeleteAllowChannel(dev, wd->sta.currentFrequency);
|
|
wd->frequency = zfChNumToFreq(dev, zmw_rx_buf_readb(dev, buf, offset+3), 0);
|
|
//zfHpAddAllowChannel(dev, wd->frequency);
|
|
zm_debug_msg1("CWY - jump to frequency = ", wd->frequency);
|
|
zfCoreSetFrequency(dev, wd->frequency);
|
|
wd->sta.DFSDisableTx = FALSE;
|
|
/* Increase rxBeaconCount to prevent beacon lost */
|
|
if (zfStaIsConnected(dev))
|
|
{
|
|
wd->sta.rxBeaconCount = 1 << 6; // 2 times of check would pass
|
|
}
|
|
//start tx dma to transmit packet
|
|
|
|
//if (zmw_rx_buf_readb(dev, buf, offset+3) != wd->frequency)
|
|
//{
|
|
// //ZDDbgPrint(("Radar Detect by AP\n"));
|
|
// zfCoreSetFrequency();
|
|
// ProcessRadarDetectEvent(Adapter);
|
|
// Set_RF_Channel(Adapter, SwRfd->Rfd->RxBuffer[index+3], (UCHAR)Adapter->RF_Mode, 1);
|
|
// Adapter->CardSetting.Channel = SwRfd->Rfd->RxBuffer[index+3];
|
|
// Adapter->SaveChannel = Adapter->CardSetting.Channel;
|
|
// Adapter->UtilityChannel = Adapter->CardSetting.Channel;
|
|
//}
|
|
}
|
|
}
|
|
|
|
}
|
|
/* TODO : process 802.11h Transmission Power Control */
|
|
void zfStaUpdateDot11HTPC(zdev_t* dev, zbuf_t* buf)
|
|
{
|
|
}
|
|
|
|
/* IBSS power-saving mode */
|
|
void zfStaIbssPSCheckState(zdev_t* dev, zbuf_t* buf)
|
|
{
|
|
u8_t i, frameCtrl;
|
|
|
|
zmw_get_wlan_dev(dev);
|
|
|
|
if ( !zfStaIsConnected(dev) )
|
|
{
|
|
return;
|
|
}
|
|
|
|
if ( wd->wlanMode != ZM_MODE_IBSS )
|
|
{
|
|
return ;
|
|
}
|
|
|
|
/* check BSSID */
|
|
if ( !zfRxBufferEqualToStr(dev, buf, (u8_t*) wd->sta.bssid,
|
|
ZM_WLAN_HEADER_A3_OFFSET, 6) )
|
|
{
|
|
return;
|
|
}
|
|
|
|
frameCtrl = zmw_rx_buf_readb(dev, buf, 1);
|
|
|
|
/* check power management bit */
|
|
if ( frameCtrl & ZM_BIT_4 )
|
|
{
|
|
for(i=1; i<ZM_MAX_PS_STA; i++)
|
|
{
|
|
if ( !wd->sta.staPSList.entity[i].bUsed )
|
|
{
|
|
continue;
|
|
}
|
|
|
|
/* check source address */
|
|
if ( zfRxBufferEqualToStr(dev, buf,
|
|
wd->sta.staPSList.entity[i].macAddr,
|
|
ZM_WLAN_HEADER_A2_OFFSET, 6) )
|
|
{
|
|
return;
|
|
}
|
|
}
|
|
|
|
for(i=1; i<ZM_MAX_PS_STA; i++)
|
|
{
|
|
if ( !wd->sta.staPSList.entity[i].bUsed )
|
|
{
|
|
wd->sta.staPSList.entity[i].bUsed = TRUE;
|
|
wd->sta.staPSList.entity[i].bDataQueued = FALSE;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if ( i == ZM_MAX_PS_STA )
|
|
{
|
|
/* STA list is full */
|
|
return;
|
|
}
|
|
|
|
zfCopyFromRxBuffer(dev, buf, wd->sta.staPSList.entity[i].macAddr,
|
|
ZM_WLAN_HEADER_A2_OFFSET, 6);
|
|
|
|
if ( wd->sta.staPSList.count == 0 )
|
|
{
|
|
// enable ATIM window
|
|
//zfEnableAtimWindow(dev);
|
|
}
|
|
|
|
wd->sta.staPSList.count++;
|
|
}
|
|
else if ( wd->sta.staPSList.count )
|
|
{
|
|
for(i=1; i<ZM_MAX_PS_STA; i++)
|
|
{
|
|
if ( wd->sta.staPSList.entity[i].bUsed )
|
|
{
|
|
if ( zfRxBufferEqualToStr(dev, buf,
|
|
wd->sta.staPSList.entity[i].macAddr,
|
|
ZM_WLAN_HEADER_A2_OFFSET, 6) )
|
|
{
|
|
wd->sta.staPSList.entity[i].bUsed = FALSE;
|
|
wd->sta.staPSList.count--;
|
|
|
|
if ( wd->sta.staPSList.entity[i].bDataQueued )
|
|
{
|
|
/* send queued data */
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if ( wd->sta.staPSList.count == 0 )
|
|
{
|
|
/* disable ATIM window */
|
|
//zfDisableAtimWindow(dev);
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
/* IBSS power-saving mode */
|
|
u8_t zfStaIbssPSQueueData(zdev_t* dev, zbuf_t* buf)
|
|
{
|
|
u8_t i;
|
|
u16_t da[3];
|
|
|
|
zmw_get_wlan_dev(dev);
|
|
|
|
if ( !zfStaIsConnected(dev) )
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
if ( wd->wlanMode != ZM_MODE_IBSS )
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
if ( wd->sta.staPSList.count == 0 && wd->sta.powerSaveMode <= ZM_STA_PS_NONE )
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
/* DA */
|
|
#ifdef ZM_ENABLE_NATIVE_WIFI
|
|
da[0] = zmw_tx_buf_readh(dev, buf, ZM_WLAN_HEADER_A1_OFFSET);
|
|
da[1] = zmw_tx_buf_readh(dev, buf, ZM_WLAN_HEADER_A1_OFFSET + 2);
|
|
da[2] = zmw_tx_buf_readh(dev, buf, ZM_WLAN_HEADER_A1_OFFSET + 4);
|
|
#else
|
|
da[0] = zmw_tx_buf_readh(dev, buf, 0);
|
|
da[1] = zmw_tx_buf_readh(dev, buf, 2);
|
|
da[2] = zmw_tx_buf_readh(dev, buf, 4);
|
|
#endif
|
|
|
|
if ( ZM_IS_MULTICAST_OR_BROADCAST(da) )
|
|
{
|
|
wd->sta.staPSList.entity[0].bDataQueued = TRUE;
|
|
wd->sta.ibssPSDataQueue[wd->sta.ibssPSDataCount++] = buf;
|
|
return 1;
|
|
}
|
|
|
|
// Unicast packet...
|
|
|
|
for(i=1; i<ZM_MAX_PS_STA; i++)
|
|
{
|
|
if ( zfMemoryIsEqual(wd->sta.staPSList.entity[i].macAddr,
|
|
(u8_t*) da, 6) )
|
|
{
|
|
wd->sta.staPSList.entity[i].bDataQueued = TRUE;
|
|
wd->sta.ibssPSDataQueue[wd->sta.ibssPSDataCount++] = buf;
|
|
|
|
return 1;
|
|
}
|
|
}
|
|
|
|
#if 0
|
|
if ( wd->sta.powerSaveMode > ZM_STA_PS_NONE )
|
|
{
|
|
wd->sta.staPSDataQueue[wd->sta.staPSDataCount++] = buf;
|
|
|
|
return 1;
|
|
}
|
|
#endif
|
|
|
|
return 0;
|
|
}
|
|
|
|
/* IBSS power-saving mode */
|
|
void zfStaIbssPSSend(zdev_t* dev)
|
|
{
|
|
u8_t i;
|
|
u16_t bcastAddr[3] = {0xffff, 0xffff, 0xffff};
|
|
|
|
zmw_get_wlan_dev(dev);
|
|
|
|
if ( !zfStaIsConnected(dev) )
|
|
{
|
|
return ;
|
|
}
|
|
|
|
if ( wd->wlanMode != ZM_MODE_IBSS )
|
|
{
|
|
return ;
|
|
}
|
|
|
|
for(i=0; i<ZM_MAX_PS_STA; i++)
|
|
{
|
|
if ( wd->sta.staPSList.entity[i].bDataQueued )
|
|
{
|
|
if ( i == 0 )
|
|
{
|
|
zfSendMmFrame(dev, ZM_WLAN_FRAME_TYPE_ATIM,
|
|
bcastAddr,
|
|
0, 0, 0);
|
|
}
|
|
else if ( wd->sta.staPSList.entity[i].bUsed )
|
|
{
|
|
// Send ATIM to prevent the peer to go to sleep
|
|
zfSendMmFrame(dev, ZM_WLAN_FRAME_TYPE_ATIM,
|
|
(u16_t*) wd->sta.staPSList.entity[i].macAddr,
|
|
0, 0, 0);
|
|
}
|
|
|
|
wd->sta.staPSList.entity[i].bDataQueued = FALSE;
|
|
}
|
|
}
|
|
|
|
for(i=0; i<wd->sta.ibssPSDataCount; i++)
|
|
{
|
|
zfTxSendEth(dev, wd->sta.ibssPSDataQueue[i], 0,
|
|
ZM_EXTERNAL_ALLOC_BUF, 0);
|
|
}
|
|
|
|
wd->sta.ibssPrevPSDataCount = wd->sta.ibssPSDataCount;
|
|
wd->sta.ibssPSDataCount = 0;
|
|
}
|
|
|
|
|
|
void zfStaReconnect(zdev_t* dev)
|
|
{
|
|
zmw_get_wlan_dev(dev);
|
|
zmw_declare_for_critical_section();
|
|
|
|
if ( wd->wlanMode != ZM_MODE_INFRASTRUCTURE &&
|
|
wd->wlanMode != ZM_MODE_IBSS )
|
|
{
|
|
return;
|
|
}
|
|
|
|
if ( (zfStaIsConnected(dev))||(zfStaIsConnecting(dev)) )
|
|
{
|
|
return;
|
|
}
|
|
|
|
if ( wd->sta.bChannelScan )
|
|
{
|
|
return;
|
|
}
|
|
|
|
/* Recover zero SSID length */
|
|
if ( (wd->wlanMode == ZM_MODE_INFRASTRUCTURE) && (wd->ws.ssidLen == 0))
|
|
{
|
|
zm_debug_msg0("zfStaReconnect: NOT Support!! Set SSID to any BSS");
|
|
/* ANY BSS */
|
|
zmw_enter_critical_section(dev);
|
|
wd->sta.ssid[0] = 0;
|
|
wd->sta.ssidLen = 0;
|
|
zmw_leave_critical_section(dev);
|
|
}
|
|
|
|
// RAY: To ensure no TX pending before re-connecting
|
|
zfFlushVtxq(dev);
|
|
zfWlanEnable(dev);
|
|
zfScanMgrScanAck(dev);
|
|
}
|
|
|
|
void zfStaTimer100ms(zdev_t* dev)
|
|
{
|
|
zmw_get_wlan_dev(dev);
|
|
|
|
if ( (wd->tick % 10) == 0 )
|
|
{
|
|
zfPushVtxq(dev);
|
|
// zfPowerSavingMgrMain(dev);
|
|
}
|
|
}
|
|
|
|
|
|
void zfStaCheckRxBeacon(zdev_t* dev)
|
|
{
|
|
zmw_get_wlan_dev(dev);
|
|
|
|
if (( wd->wlanMode == ZM_MODE_INFRASTRUCTURE ) && (zfStaIsConnected(dev)))
|
|
{
|
|
if (wd->beaconInterval == 0)
|
|
{
|
|
wd->beaconInterval = 100;
|
|
}
|
|
if ( (wd->tick % ((wd->beaconInterval * 10) / ZM_MS_PER_TICK)) == 0 )
|
|
{
|
|
/* Check rxBeaconCount */
|
|
if (wd->sta.rxBeaconCount == 0)
|
|
{
|
|
if (wd->sta.beaconMissState == 1)
|
|
{
|
|
/*notify AP that we left*/
|
|
zfSendMmFrame(dev, ZM_WLAN_FRAME_TYPE_DEAUTH, wd->sta.bssid, 3, 0, 0);
|
|
/* Beacon Lost */
|
|
zfStaConnectFail(dev, ZM_STATUS_MEDIA_DISCONNECT_BEACON_MISS,
|
|
wd->sta.bssid, 0);
|
|
}
|
|
else
|
|
{
|
|
wd->sta.beaconMissState = 1;
|
|
/* Reset channel */
|
|
zfCoreSetFrequencyExV2(dev, wd->frequency, wd->BandWidth40,
|
|
wd->ExtOffset, NULL, 1);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
wd->sta.beaconMissState = 0;
|
|
}
|
|
wd->sta.rxBeaconCount = 0;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
void zfStaCheckConnectTimeout(zdev_t* dev)
|
|
{
|
|
zmw_get_wlan_dev(dev);
|
|
zmw_declare_for_critical_section();
|
|
|
|
if ( wd->wlanMode != ZM_MODE_INFRASTRUCTURE )
|
|
{
|
|
return;
|
|
}
|
|
|
|
if ( !zfStaIsConnecting(dev) )
|
|
{
|
|
return;
|
|
}
|
|
|
|
zmw_enter_critical_section(dev);
|
|
if ( (wd->sta.connectState == ZM_STA_CONN_STATE_AUTH_OPEN)||
|
|
(wd->sta.connectState == ZM_STA_CONN_STATE_AUTH_SHARE_1)||
|
|
(wd->sta.connectState == ZM_STA_CONN_STATE_AUTH_SHARE_2)||
|
|
(wd->sta.connectState == ZM_STA_CONN_STATE_ASSOCIATE) )
|
|
{
|
|
if ( (wd->tick - wd->sta.connectTimer) > ZM_INTERVAL_CONNECT_TIMEOUT )
|
|
{
|
|
if ( wd->sta.connectByReasso )
|
|
{
|
|
wd->sta.failCntOfReasso++;
|
|
if ( wd->sta.failCntOfReasso > 2 )
|
|
{
|
|
wd->sta.connectByReasso = FALSE;
|
|
}
|
|
}
|
|
|
|
wd->sta.connectState = ZM_STA_CONN_STATE_NONE;
|
|
zm_debug_msg1("connect timeout, state = ", wd->sta.connectState);
|
|
//zfiWlanDisable(dev);
|
|
goto failed;
|
|
}
|
|
}
|
|
|
|
zmw_leave_critical_section(dev);
|
|
return;
|
|
|
|
failed:
|
|
zmw_leave_critical_section(dev);
|
|
if(wd->sta.authMode == ZM_AUTH_MODE_AUTO)
|
|
{ // Fix some AP not send authentication failed message to sta and lead to connect timeout !
|
|
wd->sta.connectTimeoutCount++;
|
|
}
|
|
zfStaConnectFail(dev, ZM_STATUS_MEDIA_DISCONNECT_TIMEOUT, wd->sta.bssid, 2);
|
|
return;
|
|
}
|
|
|
|
void zfMmStaTimeTick(zdev_t* dev)
|
|
{
|
|
zmw_get_wlan_dev(dev);
|
|
|
|
/* airopeek */
|
|
if (wd->wlanMode != ZM_MODE_AP && !wd->swSniffer)
|
|
{
|
|
if ( wd->tick & 1 )
|
|
{
|
|
zfTimerCheckAndHandle(dev);
|
|
}
|
|
|
|
zfStaCheckRxBeacon(dev);
|
|
zfStaTimer100ms(dev);
|
|
zfStaCheckConnectTimeout(dev);
|
|
zfPowerSavingMgrMain(dev);
|
|
}
|
|
|
|
#ifdef ZM_ENABLE_AGGREGATION
|
|
/*
|
|
* add by honda
|
|
*/
|
|
zfAggScanAndClear(dev, wd->tick);
|
|
#endif
|
|
}
|
|
|
|
void zfStaSendBeacon(zdev_t* dev)
|
|
{
|
|
zbuf_t* buf;
|
|
u16_t offset, seq;
|
|
|
|
zmw_get_wlan_dev(dev);
|
|
|
|
zmw_declare_for_critical_section();
|
|
|
|
//zm_debug_msg0("\n");
|
|
|
|
/* TBD : Maximum size of beacon */
|
|
if ((buf = zfwBufAllocate(dev, 1024)) == NULL)
|
|
{
|
|
zm_debug_msg0("Allocate beacon buffer failed");
|
|
return;
|
|
}
|
|
|
|
offset = 0;
|
|
/* wlan header */
|
|
/* Frame control */
|
|
zmw_tx_buf_writeh(dev, buf, offset, 0x0080);
|
|
offset+=2;
|
|
/* Duration */
|
|
zmw_tx_buf_writeh(dev, buf, offset, 0x0000);
|
|
offset+=2;
|
|
/* Address 1 */
|
|
zmw_tx_buf_writeh(dev, buf, offset, 0xffff);
|
|
offset+=2;
|
|
zmw_tx_buf_writeh(dev, buf, offset, 0xffff);
|
|
offset+=2;
|
|
zmw_tx_buf_writeh(dev, buf, offset, 0xffff);
|
|
offset+=2;
|
|
/* Address 2 */
|
|
zmw_tx_buf_writeh(dev, buf, offset, wd->macAddr[0]);
|
|
offset+=2;
|
|
zmw_tx_buf_writeh(dev, buf, offset, wd->macAddr[1]);
|
|
offset+=2;
|
|
zmw_tx_buf_writeh(dev, buf, offset, wd->macAddr[2]);
|
|
offset+=2;
|
|
/* Address 3 */
|
|
zmw_tx_buf_writeh(dev, buf, offset, wd->sta.bssid[0]);
|
|
offset+=2;
|
|
zmw_tx_buf_writeh(dev, buf, offset, wd->sta.bssid[1]);
|
|
offset+=2;
|
|
zmw_tx_buf_writeh(dev, buf, offset, wd->sta.bssid[2]);
|
|
offset+=2;
|
|
|
|
/* Sequence number */
|
|
zmw_enter_critical_section(dev);
|
|
seq = ((wd->mmseq++)<<4);
|
|
zmw_leave_critical_section(dev);
|
|
zmw_tx_buf_writeh(dev, buf, offset, seq);
|
|
offset+=2;
|
|
|
|
/* 24-31 Time Stamp : hardware will fill this field */
|
|
offset+=8;
|
|
|
|
/* Beacon Interval */
|
|
zmw_tx_buf_writeh(dev, buf, offset, wd->beaconInterval);
|
|
offset+=2;
|
|
|
|
/* Capability */
|
|
zmw_tx_buf_writeb(dev, buf, offset++, wd->sta.capability[0]);
|
|
zmw_tx_buf_writeb(dev, buf, offset++, wd->sta.capability[1]);
|
|
|
|
/* SSID */
|
|
offset = zfStaAddIeSsid(dev, buf, offset);
|
|
|
|
if(wd->frequency <= ZM_CH_G_14) // 2.4 GHz b+g
|
|
{
|
|
|
|
/* Support Rate */
|
|
offset = zfMmAddIeSupportRate(dev, buf, offset,
|
|
ZM_WLAN_EID_SUPPORT_RATE, ZM_RATE_SET_CCK);
|
|
|
|
/* DS parameter set */
|
|
offset = zfMmAddIeDs(dev, buf, offset);
|
|
|
|
offset = zfStaAddIeIbss(dev, buf, offset);
|
|
|
|
if( wd->wfc.bIbssGMode
|
|
&& (wd->supportMode & (ZM_WIRELESS_MODE_24_54|ZM_WIRELESS_MODE_24_N)) ) // Only accompany with enabling a mode .
|
|
{
|
|
/* ERP Information */
|
|
wd->erpElement = 0;
|
|
offset = zfMmAddIeErp(dev, buf, offset);
|
|
}
|
|
|
|
/* TODO : country information */
|
|
/* RSN */
|
|
if ( wd->sta.authMode == ZM_AUTH_MODE_WPA2PSK )
|
|
{
|
|
offset = zfwStaAddIeWpaRsn(dev, buf, offset, ZM_WLAN_FRAME_TYPE_AUTH);
|
|
}
|
|
|
|
if( wd->wfc.bIbssGMode
|
|
&& (wd->supportMode & (ZM_WIRELESS_MODE_24_54|ZM_WIRELESS_MODE_24_N)) ) // Only accompany with enabling a mode .
|
|
{
|
|
/* Enable G Mode */
|
|
/* Extended Supported Rates */
|
|
offset = zfMmAddIeSupportRate(dev, buf, offset,
|
|
ZM_WLAN_EID_EXTENDED_RATE, ZM_RATE_SET_OFDM);
|
|
}
|
|
}
|
|
else // 5GHz a
|
|
{
|
|
/* Support Rate a Mode */
|
|
offset = zfMmAddIeSupportRate(dev, buf, offset,
|
|
ZM_WLAN_EID_SUPPORT_RATE, ZM_RATE_SET_OFDM);
|
|
|
|
/* DS parameter set */
|
|
offset = zfMmAddIeDs(dev, buf, offset);
|
|
|
|
offset = zfStaAddIeIbss(dev, buf, offset);
|
|
|
|
/* TODO : country information */
|
|
/* RSN */
|
|
if ( wd->sta.authMode == ZM_AUTH_MODE_WPA2PSK )
|
|
{
|
|
offset = zfwStaAddIeWpaRsn(dev, buf, offset, ZM_WLAN_FRAME_TYPE_AUTH);
|
|
}
|
|
}
|
|
|
|
if ( wd->wlanMode != ZM_MODE_IBSS )
|
|
{
|
|
/* TODO : Need to check if it is ok */
|
|
/* HT Capabilities Info */
|
|
offset = zfMmAddHTCapability(dev, buf, offset);
|
|
|
|
/* Extended HT Capabilities Info */
|
|
offset = zfMmAddExtendedHTCapability(dev, buf, offset);
|
|
}
|
|
|
|
if ( wd->sta.ibssAdditionalIESize )
|
|
offset = zfStaAddIbssAdditionalIE(dev, buf, offset);
|
|
|
|
/* 1212 : write to beacon fifo */
|
|
/* 1221 : write to share memory */
|
|
zfHpSendBeacon(dev, buf, offset);
|
|
|
|
/* Free beacon buffer */
|
|
//zfwBufFree(dev, buf, 0);
|
|
}
|
|
|
|
void zfStaSignalStatistic(zdev_t* dev, u8_t SignalStrength, u8_t SignalQuality) //CWYang(+)
|
|
{
|
|
zmw_get_wlan_dev(dev);
|
|
|
|
/* Add Your Code to Do Works Like Moving Average Here */
|
|
wd->SignalStrength = (wd->SignalStrength * 7 + SignalStrength * 3)/10;
|
|
wd->SignalQuality = (wd->SignalQuality * 7 + SignalQuality * 3)/10;
|
|
|
|
}
|
|
|
|
struct zsBssInfo* zfStaFindBssInfo(zdev_t* dev, zbuf_t* buf, struct zsWlanProbeRspFrameHeader *pProbeRspHeader)
|
|
{
|
|
u8_t i;
|
|
u8_t j;
|
|
u8_t k;
|
|
u8_t isMatched, length, channel;
|
|
u16_t offset, frequency;
|
|
struct zsBssInfo* pBssInfo;
|
|
|
|
zmw_get_wlan_dev(dev);
|
|
|
|
if ((pBssInfo = wd->sta.bssList.head) == NULL)
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
for( i=0; i<wd->sta.bssList.bssCount; i++ )
|
|
{
|
|
//zm_debug_msg2("check pBssInfo = ", pBssInfo);
|
|
|
|
/* Check BSSID */
|
|
for( j=0; j<6; j++ )
|
|
{
|
|
if ( pBssInfo->bssid[j] != pProbeRspHeader->bssid[j] )
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
|
|
/* Check SSID */
|
|
if (j == 6)
|
|
{
|
|
if (pProbeRspHeader->ssid[1] <= 32)
|
|
{
|
|
/* compare length and ssid */
|
|
isMatched = 1;
|
|
if((pProbeRspHeader->ssid[1] != 0) && (pBssInfo->ssid[1] != 0))
|
|
{
|
|
for( k=1; k<pProbeRspHeader->ssid[1] + 1; k++ )
|
|
{
|
|
if ( pBssInfo->ssid[k] != pProbeRspHeader->ssid[k] )
|
|
{
|
|
isMatched = 0;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
isMatched = 0;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
isMatched = 0;
|
|
}
|
|
|
|
/* Check channel */
|
|
/* Add check channel to solve the bug #31222 */
|
|
if (isMatched) {
|
|
if ((offset = zfFindElement(dev, buf, ZM_WLAN_EID_DS)) != 0xffff) {
|
|
if ((length = zmw_rx_buf_readb(dev, buf, offset+1)) == 1) {
|
|
channel = zmw_rx_buf_readb(dev, buf, offset+2);
|
|
if (zfHpIsAllowedChannel(dev, zfChNumToFreq(dev, channel, 0)) == 0) {
|
|
frequency = 0;
|
|
} else {
|
|
frequency = zfChNumToFreq(dev, channel, 0);;
|
|
}
|
|
} else {
|
|
frequency = 0;
|
|
}
|
|
} else {
|
|
frequency = wd->sta.currentFrequency;
|
|
}
|
|
|
|
if (frequency != 0) {
|
|
if ( ((frequency > 3000) && (pBssInfo->frequency > 3000))
|
|
|| ((frequency < 3000) && (pBssInfo->frequency < 3000)) ) {
|
|
/* redundant */
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
pBssInfo = pBssInfo->next;
|
|
}
|
|
|
|
if ( i == wd->sta.bssList.bssCount )
|
|
{
|
|
pBssInfo = NULL;
|
|
}
|
|
|
|
return pBssInfo;
|
|
}
|
|
|
|
u8_t zfStaInitBssInfo(zdev_t* dev, zbuf_t* buf,
|
|
struct zsWlanProbeRspFrameHeader *pProbeRspHeader,
|
|
struct zsBssInfo* pBssInfo, struct zsAdditionInfo* AddInfo, u8_t type)
|
|
{
|
|
u8_t length, channel, is5G;
|
|
u16_t i, offset;
|
|
u8_t apQosInfo;
|
|
u16_t eachIElength = 0;
|
|
u16_t accumulateLen = 0;
|
|
|
|
zmw_get_wlan_dev(dev);
|
|
|
|
if ((type == 1) && ((pBssInfo->flag & ZM_BSS_INFO_VALID_BIT) != 0))
|
|
{
|
|
goto zlUpdateRssi;
|
|
}
|
|
|
|
/* get SSID */
|
|
if ( (offset = zfFindElement(dev, buf, ZM_WLAN_EID_SSID)) == 0xffff )
|
|
{
|
|
zm_debug_msg0("EID(SSID) not found");
|
|
goto zlError;
|
|
}
|
|
|
|
length = zmw_rx_buf_readb(dev, buf, offset+1);
|
|
|
|
{
|
|
u8_t Show_Flag = 0;
|
|
zfwGetShowZeroLengthSSID(dev, &Show_Flag);
|
|
|
|
if(Show_Flag)
|
|
{
|
|
if (length > ZM_MAX_SSID_LENGTH )
|
|
{
|
|
zm_debug_msg0("EID(SSID) is invalid");
|
|
goto zlError;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if ( length == 0 || length > ZM_MAX_SSID_LENGTH )
|
|
{
|
|
zm_debug_msg0("EID(SSID) is invalid");
|
|
goto zlError;
|
|
}
|
|
|
|
}
|
|
}
|
|
zfCopyFromRxBuffer(dev, buf, pBssInfo->ssid, offset, length+2);
|
|
|
|
/* get DS parameter */
|
|
if ( (offset = zfFindElement(dev, buf, ZM_WLAN_EID_DS)) != 0xffff )
|
|
{
|
|
length = zmw_rx_buf_readb(dev, buf, offset+1);
|
|
if ( length != 1 )
|
|
{
|
|
zm_msg0_mm(ZM_LV_0, "Abnormal DS Param Set IE");
|
|
goto zlError;
|
|
}
|
|
channel = zmw_rx_buf_readb(dev, buf, offset+2);
|
|
|
|
if (zfHpIsAllowedChannel(dev, zfChNumToFreq(dev, channel, 0)) == 0)
|
|
{
|
|
goto zlError2;
|
|
}
|
|
|
|
pBssInfo->frequency = zfChNumToFreq(dev, channel, 0); // auto check
|
|
pBssInfo->channel = channel;
|
|
|
|
|
|
}
|
|
else
|
|
{
|
|
/* DS parameter not found */
|
|
pBssInfo->frequency = wd->sta.currentFrequency;
|
|
pBssInfo->channel = zfChFreqToNum(wd->sta.currentFrequency, &is5G);
|
|
}
|
|
|
|
/* initialize security type */
|
|
pBssInfo->securityType = ZM_SECURITY_TYPE_NONE;
|
|
|
|
/* get macaddr */
|
|
for( i=0; i<6; i++ )
|
|
{
|
|
pBssInfo->macaddr[i] = pProbeRspHeader->sa[i];
|
|
}
|
|
|
|
/* get bssid */
|
|
for( i=0; i<6; i++ )
|
|
{
|
|
pBssInfo->bssid[i] = pProbeRspHeader->bssid[i];
|
|
}
|
|
|
|
/* get timestamp */
|
|
for( i=0; i<8; i++ )
|
|
{
|
|
pBssInfo->timeStamp[i] = pProbeRspHeader->timeStamp[i];
|
|
}
|
|
|
|
/* get beacon interval */
|
|
pBssInfo->beaconInterval[0] = pProbeRspHeader->beaconInterval[0];
|
|
pBssInfo->beaconInterval[1] = pProbeRspHeader->beaconInterval[1];
|
|
|
|
/* get capability */
|
|
pBssInfo->capability[0] = pProbeRspHeader->capability[0];
|
|
pBssInfo->capability[1] = pProbeRspHeader->capability[1];
|
|
|
|
/* Copy frame body */
|
|
offset = 36; // Copy from the start of variable IE
|
|
pBssInfo->frameBodysize = zfwBufGetSize(dev, buf)-offset;
|
|
if (pBssInfo->frameBodysize > (ZM_MAX_PROBE_FRAME_BODY_SIZE-1))
|
|
{
|
|
pBssInfo->frameBodysize = ZM_MAX_PROBE_FRAME_BODY_SIZE-1;
|
|
}
|
|
accumulateLen = 0;
|
|
do
|
|
{
|
|
eachIElength = zmw_rx_buf_readb(dev, buf, offset + accumulateLen+1) + 2; //Len+(EID+Data)
|
|
|
|
if ( (eachIElength >= 2)
|
|
&& ((accumulateLen + eachIElength) <= pBssInfo->frameBodysize) )
|
|
{
|
|
zfCopyFromRxBuffer(dev, buf, pBssInfo->frameBody+accumulateLen, offset+accumulateLen, eachIElength);
|
|
accumulateLen+=(u16_t)eachIElength;
|
|
}
|
|
else
|
|
{
|
|
zm_msg0_mm(ZM_LV_1, "probersp frameBodysize abnormal");
|
|
break;
|
|
}
|
|
}
|
|
while(accumulateLen < pBssInfo->frameBodysize);
|
|
pBssInfo->frameBodysize = accumulateLen;
|
|
|
|
/* get supported rates */
|
|
if ( (offset = zfFindElement(dev, buf, ZM_WLAN_EID_SUPPORT_RATE)) == 0xffff )
|
|
{
|
|
zm_debug_msg0("EID(supported rates) not found");
|
|
goto zlError;
|
|
}
|
|
|
|
length = zmw_rx_buf_readb(dev, buf, offset+1);
|
|
if ( length == 0 || length > ZM_MAX_SUPP_RATES_IE_SIZE)
|
|
{
|
|
zm_msg0_mm(ZM_LV_0, "Supported rates IE length abnormal");
|
|
goto zlError;
|
|
}
|
|
zfCopyFromRxBuffer(dev, buf, pBssInfo->supportedRates, offset, length+2);
|
|
|
|
|
|
|
|
/* get Country information */
|
|
if ( (offset = zfFindElement(dev, buf, ZM_WLAN_EID_COUNTRY)) != 0xffff )
|
|
{
|
|
length = zmw_rx_buf_readb(dev, buf, offset+1);
|
|
if (length > ZM_MAX_COUNTRY_INFO_SIZE)
|
|
{
|
|
length = ZM_MAX_COUNTRY_INFO_SIZE;
|
|
}
|
|
zfCopyFromRxBuffer(dev, buf, pBssInfo->countryInfo, offset, length+2);
|
|
/* check 802.11d support data */
|
|
if (wd->sta.b802_11D)
|
|
{
|
|
zfHpGetRegulationTablefromISO(dev, (u8_t *)&pBssInfo->countryInfo, 3);
|
|
/* only set regulatory one time */
|
|
wd->sta.b802_11D = 0;
|
|
}
|
|
}
|
|
|
|
/* get ERP information */
|
|
if ( (offset = zfFindElement(dev, buf, ZM_WLAN_EID_ERP)) != 0xffff )
|
|
{
|
|
pBssInfo->erp = zmw_rx_buf_readb(dev, buf, offset+2);
|
|
}
|
|
|
|
/* get extended supported rates */
|
|
if ( (offset = zfFindElement(dev, buf, ZM_WLAN_EID_EXTENDED_RATE)) != 0xffff )
|
|
{
|
|
length = zmw_rx_buf_readb(dev, buf, offset+1);
|
|
if (length > ZM_MAX_SUPP_RATES_IE_SIZE)
|
|
{
|
|
zm_msg0_mm(ZM_LV_0, "Extended rates IE length abnormal");
|
|
goto zlError;
|
|
}
|
|
zfCopyFromRxBuffer(dev, buf, pBssInfo->extSupportedRates, offset, length+2);
|
|
}
|
|
else
|
|
{
|
|
pBssInfo->extSupportedRates[0] = 0;
|
|
pBssInfo->extSupportedRates[1] = 0;
|
|
}
|
|
|
|
/* get WPA IE */
|
|
if ( (offset = zfFindElement(dev, buf, ZM_WLAN_EID_WPA_IE)) != 0xffff )
|
|
{
|
|
length = zmw_rx_buf_readb(dev, buf, offset+1);
|
|
if (length > ZM_MAX_IE_SIZE)
|
|
{
|
|
length = ZM_MAX_IE_SIZE;
|
|
}
|
|
zfCopyFromRxBuffer(dev, buf, pBssInfo->wpaIe, offset, length+2);
|
|
pBssInfo->securityType = ZM_SECURITY_TYPE_WPA;
|
|
}
|
|
else
|
|
{
|
|
pBssInfo->wpaIe[1] = 0;
|
|
}
|
|
|
|
/* get WPS IE */
|
|
if ((offset = zfFindWifiElement(dev, buf, 4, 0xff)) != 0xffff)
|
|
{
|
|
length = zmw_rx_buf_readb(dev, buf, offset+1);
|
|
if (length > ZM_MAX_WPS_IE_SIZE )
|
|
{
|
|
length = ZM_MAX_WPS_IE_SIZE;
|
|
}
|
|
zfCopyFromRxBuffer(dev, buf, pBssInfo->wscIe, offset, length+2);
|
|
}
|
|
else
|
|
{
|
|
pBssInfo->wscIe[1] = 0;
|
|
}
|
|
|
|
/* get SuperG IE */
|
|
if ((offset = zfFindSuperGElement(dev, buf, ZM_WLAN_EID_VENDOR_PRIVATE)) != 0xffff)
|
|
{
|
|
pBssInfo->apCap |= ZM_SuperG_AP;
|
|
}
|
|
|
|
/* get XR IE */
|
|
if ((offset = zfFindXRElement(dev, buf, ZM_WLAN_EID_VENDOR_PRIVATE)) != 0xffff)
|
|
{
|
|
pBssInfo->apCap |= ZM_XR_AP;
|
|
}
|
|
|
|
/* get RSN IE */
|
|
if ( (offset = zfFindElement(dev, buf, ZM_WLAN_EID_RSN_IE)) != 0xffff )
|
|
{
|
|
length = zmw_rx_buf_readb(dev, buf, offset+1);
|
|
if (length > ZM_MAX_IE_SIZE)
|
|
{
|
|
length = ZM_MAX_IE_SIZE;
|
|
}
|
|
zfCopyFromRxBuffer(dev, buf, pBssInfo->rsnIe, offset, length+2);
|
|
pBssInfo->securityType = ZM_SECURITY_TYPE_WPA;
|
|
}
|
|
else
|
|
{
|
|
pBssInfo->rsnIe[1] = 0;
|
|
}
|
|
#ifdef ZM_ENABLE_CENC
|
|
/* get CENC IE */
|
|
if ( (offset = zfFindElement(dev, buf, ZM_WLAN_EID_CENC_IE)) != 0xffff )
|
|
{
|
|
length = zmw_rx_buf_readb(dev, buf, offset+1);
|
|
if (length > ZM_MAX_IE_SIZE )
|
|
{
|
|
length = ZM_MAX_IE_SIZE;
|
|
}
|
|
zfCopyFromRxBuffer(dev, buf, pBssInfo->cencIe, offset, length+2);
|
|
pBssInfo->securityType = ZM_SECURITY_TYPE_CENC;
|
|
pBssInfo->capability[0] &= 0xffef;
|
|
}
|
|
else
|
|
{
|
|
pBssInfo->cencIe[1] = 0;
|
|
}
|
|
#endif //ZM_ENABLE_CENC
|
|
/* get WME Parameter IE, probe rsp may contain WME parameter element */
|
|
//if ( wd->bQoSEnable )
|
|
{
|
|
if ((offset = zfFindWifiElement(dev, buf, 2, 1)) != 0xffff)
|
|
{
|
|
apQosInfo = zmw_rx_buf_readb(dev, buf, offset+8) & 0x80;
|
|
pBssInfo->wmeSupport = 1 | apQosInfo;
|
|
}
|
|
else if ((offset = zfFindWifiElement(dev, buf, 2, 0)) != 0xffff)
|
|
{
|
|
apQosInfo = zmw_rx_buf_readb(dev, buf, offset+8) & 0x80;
|
|
pBssInfo->wmeSupport = 1 | apQosInfo;
|
|
}
|
|
else
|
|
{
|
|
pBssInfo->wmeSupport = 0;
|
|
}
|
|
}
|
|
//CWYang(+)
|
|
if ((offset = zfFindElement(dev, buf, ZM_WLAN_EID_HT_CAPABILITY)) != 0xffff)
|
|
{
|
|
/* 11n AP */
|
|
pBssInfo->EnableHT = 1;
|
|
if (zmw_rx_buf_readb(dev, buf, offset+1) & 0x02)
|
|
{
|
|
pBssInfo->enableHT40 = 1;
|
|
}
|
|
else
|
|
{
|
|
pBssInfo->enableHT40 = 0;
|
|
}
|
|
|
|
if (zmw_rx_buf_readb(dev, buf, offset+1) & 0x40)
|
|
{
|
|
pBssInfo->SG40 = 1;
|
|
}
|
|
else
|
|
{
|
|
pBssInfo->SG40 = 0;
|
|
}
|
|
}
|
|
else if ((offset = zfFindElement(dev, buf, ZM_WLAN_PREN2_EID_HTCAPABILITY)) != 0xffff)
|
|
{
|
|
/* 11n AP */
|
|
pBssInfo->EnableHT = 1;
|
|
pBssInfo->apCap |= ZM_All11N_AP;
|
|
if (zmw_rx_buf_readb(dev, buf, offset+2) & 0x02)
|
|
{
|
|
pBssInfo->enableHT40 = 1;
|
|
}
|
|
else
|
|
{
|
|
pBssInfo->enableHT40 = 0;
|
|
}
|
|
|
|
if (zmw_rx_buf_readb(dev, buf, offset+2) & 0x40)
|
|
{
|
|
pBssInfo->SG40 = 1;
|
|
}
|
|
else
|
|
{
|
|
pBssInfo->SG40 = 0;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
pBssInfo->EnableHT = 0;
|
|
}
|
|
/* HT information */
|
|
if ((offset = zfFindElement(dev, buf, ZM_WLAN_EID_EXTENDED_HT_CAPABILITY)) != 0xffff)
|
|
{
|
|
/* atheros pre n */
|
|
pBssInfo->extChOffset = zmw_rx_buf_readb(dev, buf, offset+2) & 0x03;
|
|
}
|
|
else if ((offset = zfFindElement(dev, buf, ZM_WLAN_PREN2_EID_HTINFORMATION)) != 0xffff)
|
|
{
|
|
/* pre n 2.0 standard */
|
|
pBssInfo->extChOffset = zmw_rx_buf_readb(dev, buf, offset+3) & 0x03;
|
|
}
|
|
else
|
|
{
|
|
pBssInfo->extChOffset = 0;
|
|
}
|
|
|
|
if ( (pBssInfo->enableHT40 == 1)
|
|
&& ((pBssInfo->extChOffset != 1) && (pBssInfo->extChOffset != 3)) )
|
|
{
|
|
pBssInfo->enableHT40 = 0;
|
|
}
|
|
|
|
if (pBssInfo->enableHT40 == 1)
|
|
{
|
|
if (zfHpIsAllowedChannel(dev, pBssInfo->frequency+((pBssInfo->extChOffset==1)?20:-20)) == 0)
|
|
{
|
|
/* if extension channel is not an allowed channel, treat AP as non-HT mode */
|
|
pBssInfo->EnableHT = 0;
|
|
pBssInfo->enableHT40 = 0;
|
|
pBssInfo->extChOffset = 0;
|
|
}
|
|
}
|
|
|
|
/* get ATH Extended Capability */
|
|
if ( ((offset = zfFindElement(dev, buf, ZM_WLAN_EID_EXTENDED_HT_CAPABILITY)) != 0xffff)&&
|
|
((offset = zfFindBrdcmMrvlRlnkExtCap(dev, buf)) == 0xffff))
|
|
|
|
{
|
|
pBssInfo->athOwlAp = 1;
|
|
}
|
|
else
|
|
{
|
|
pBssInfo->athOwlAp = 0;
|
|
}
|
|
|
|
/* get Broadcom Extended Capability */
|
|
if ( (pBssInfo->EnableHT == 1) //((offset = zfFindElement(dev, buf, ZM_WLAN_EID_EXTENDED_HT_CAPABILITY)) != 0xffff)
|
|
&& ((offset = zfFindBroadcomExtCap(dev, buf)) != 0xffff) )
|
|
{
|
|
pBssInfo->broadcomHTAp = 1;
|
|
}
|
|
else
|
|
{
|
|
pBssInfo->broadcomHTAp = 0;
|
|
}
|
|
|
|
/* get Marvel Extended Capability */
|
|
if ((offset = zfFindMarvelExtCap(dev, buf)) != 0xffff)
|
|
{
|
|
pBssInfo->marvelAp = 1;
|
|
}
|
|
else
|
|
{
|
|
pBssInfo->marvelAp = 0;
|
|
}
|
|
|
|
/* get ATIM window */
|
|
if ( (offset = zfFindElement(dev, buf, ZM_WLAN_EID_IBSS)) != 0xffff )
|
|
{
|
|
pBssInfo->atimWindow = zmw_rx_buf_readh(dev, buf,offset+2);
|
|
}
|
|
|
|
/* Fit for support mode */
|
|
if (pBssInfo->frequency > 3000) {
|
|
if (wd->supportMode & ZM_WIRELESS_MODE_5_N) {
|
|
#if 0
|
|
if (wd->supportMode & ZM_WIRELESS_MODE_5_54) {
|
|
/* support mode: a, n */
|
|
/* do nothing */
|
|
} else {
|
|
/* support mode: n */
|
|
/* reject non-n bss info */
|
|
if (!pBssInfo->EnableHT) {
|
|
goto zlError2;
|
|
}
|
|
}
|
|
#endif
|
|
} else {
|
|
if (wd->supportMode & ZM_WIRELESS_MODE_5_54) {
|
|
/* support mode: a */
|
|
/* delete n mode information */
|
|
pBssInfo->EnableHT = 0;
|
|
pBssInfo->enableHT40 = 0;
|
|
pBssInfo->apCap &= (~ZM_All11N_AP);
|
|
pBssInfo->extChOffset = 0;
|
|
pBssInfo->frameBodysize = zfRemoveElement(dev, pBssInfo->frameBody,
|
|
pBssInfo->frameBodysize, ZM_WLAN_EID_HT_CAPABILITY);
|
|
pBssInfo->frameBodysize = zfRemoveElement(dev, pBssInfo->frameBody,
|
|
pBssInfo->frameBodysize, ZM_WLAN_PREN2_EID_HTCAPABILITY);
|
|
pBssInfo->frameBodysize = zfRemoveElement(dev, pBssInfo->frameBody,
|
|
pBssInfo->frameBodysize, ZM_WLAN_EID_EXTENDED_HT_CAPABILITY);
|
|
pBssInfo->frameBodysize = zfRemoveElement(dev, pBssInfo->frameBody,
|
|
pBssInfo->frameBodysize, ZM_WLAN_PREN2_EID_HTINFORMATION);
|
|
} else {
|
|
/* support mode: none */
|
|
goto zlError2;
|
|
}
|
|
}
|
|
} else {
|
|
if (wd->supportMode & ZM_WIRELESS_MODE_24_N) {
|
|
#if 0
|
|
if (wd->supportMode & ZM_WIRELESS_MODE_24_54) {
|
|
if (wd->supportMode & ZM_WIRELESS_MODE_24_11) {
|
|
/* support mode: b, g, n */
|
|
/* do nothing */
|
|
} else {
|
|
/* support mode: g, n */
|
|
/* reject b-only bss info */
|
|
if ( (!pBssInfo->EnableHT)
|
|
&& (pBssInfo->extSupportedRates[1] == 0) ) {
|
|
goto zlError2;
|
|
}
|
|
}
|
|
} else {
|
|
if (wd->supportMode & ZM_WIRELESS_MODE_24_11) {
|
|
/* support mode: b, n */
|
|
/* 1. reject g-only bss info
|
|
* 2. if non g-only, delete g mode information
|
|
*/
|
|
if ( !pBssInfo->EnableHT ) {
|
|
if ( zfIsGOnlyMode(dev, pBssInfo->frequency, pBssInfo->supportedRates)
|
|
|| zfIsGOnlyMode(dev, pBssInfo->frequency, pBssInfo->extSupportedRates) ) {
|
|
goto zlError2;
|
|
} else {
|
|
zfGatherBMode(dev, pBssInfo->supportedRates,
|
|
pBssInfo->extSupportedRates);
|
|
pBssInfo->erp = 0;
|
|
|
|
pBssInfo->frameBodysize = zfRemoveElement(dev,
|
|
pBssInfo->frameBody, pBssInfo->frameBodysize,
|
|
ZM_WLAN_EID_ERP);
|
|
pBssInfo->frameBodysize = zfRemoveElement(dev,
|
|
pBssInfo->frameBody, pBssInfo->frameBodysize,
|
|
ZM_WLAN_EID_EXTENDED_RATE);
|
|
|
|
pBssInfo->frameBodysize = zfUpdateElement(dev,
|
|
pBssInfo->frameBody, pBssInfo->frameBodysize,
|
|
pBssInfo->supportedRates);
|
|
}
|
|
}
|
|
} else {
|
|
/* support mode: n */
|
|
/* reject non-n bss info */
|
|
if (!pBssInfo->EnableHT) {
|
|
goto zlError2;
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
} else {
|
|
/* delete n mode information */
|
|
pBssInfo->EnableHT = 0;
|
|
pBssInfo->enableHT40 = 0;
|
|
pBssInfo->apCap &= (~ZM_All11N_AP);
|
|
pBssInfo->extChOffset = 0;
|
|
pBssInfo->frameBodysize = zfRemoveElement(dev, pBssInfo->frameBody,
|
|
pBssInfo->frameBodysize, ZM_WLAN_EID_HT_CAPABILITY);
|
|
pBssInfo->frameBodysize = zfRemoveElement(dev, pBssInfo->frameBody,
|
|
pBssInfo->frameBodysize, ZM_WLAN_PREN2_EID_HTCAPABILITY);
|
|
pBssInfo->frameBodysize = zfRemoveElement(dev, pBssInfo->frameBody,
|
|
pBssInfo->frameBodysize, ZM_WLAN_EID_EXTENDED_HT_CAPABILITY);
|
|
pBssInfo->frameBodysize = zfRemoveElement(dev, pBssInfo->frameBody,
|
|
pBssInfo->frameBodysize, ZM_WLAN_PREN2_EID_HTINFORMATION);
|
|
|
|
if (wd->supportMode & ZM_WIRELESS_MODE_24_54) {
|
|
#if 0
|
|
if (wd->supportMode & ZM_WIRELESS_MODE_24_11) {
|
|
/* support mode: b, g */
|
|
/* delete n mode information */
|
|
} else {
|
|
/* support mode: g */
|
|
/* delete n mode information */
|
|
/* reject b-only bss info */
|
|
if (pBssInfo->extSupportedRates[1] == 0) {
|
|
goto zlError2;
|
|
}
|
|
}
|
|
#endif
|
|
} else {
|
|
if (wd->supportMode & ZM_WIRELESS_MODE_24_11) {
|
|
/* support mode: b */
|
|
/* delete n mode information */
|
|
if ( zfIsGOnlyMode(dev, pBssInfo->frequency, pBssInfo->supportedRates)
|
|
|| zfIsGOnlyMode(dev, pBssInfo->frequency, pBssInfo->extSupportedRates) ) {
|
|
goto zlError2;
|
|
} else {
|
|
zfGatherBMode(dev, pBssInfo->supportedRates,
|
|
pBssInfo->extSupportedRates);
|
|
pBssInfo->erp = 0;
|
|
|
|
pBssInfo->frameBodysize = zfRemoveElement(dev,
|
|
pBssInfo->frameBody, pBssInfo->frameBodysize,
|
|
ZM_WLAN_EID_ERP);
|
|
pBssInfo->frameBodysize = zfRemoveElement(dev,
|
|
pBssInfo->frameBody, pBssInfo->frameBodysize,
|
|
ZM_WLAN_EID_EXTENDED_RATE);
|
|
|
|
pBssInfo->frameBodysize = zfUpdateElement(dev,
|
|
pBssInfo->frameBody, pBssInfo->frameBodysize,
|
|
pBssInfo->supportedRates);
|
|
}
|
|
} else {
|
|
/* support mode: none */
|
|
goto zlError2;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
pBssInfo->flag |= ZM_BSS_INFO_VALID_BIT;
|
|
|
|
zlUpdateRssi:
|
|
/* Update Timer information */
|
|
pBssInfo->tick = wd->tick;
|
|
|
|
/* Update ERP information */
|
|
if ( (offset = zfFindElement(dev, buf, ZM_WLAN_EID_ERP)) != 0xffff )
|
|
{
|
|
pBssInfo->erp = zmw_rx_buf_readb(dev, buf, offset+2);
|
|
}
|
|
|
|
if( (s8_t)pBssInfo->signalStrength < (s8_t)AddInfo->Tail.Data.SignalStrength1 )
|
|
{
|
|
/* Update signal strength */
|
|
pBssInfo->signalStrength = (u8_t)AddInfo->Tail.Data.SignalStrength1;
|
|
/* Update signal quality */
|
|
pBssInfo->signalQuality = (u8_t)(AddInfo->Tail.Data.SignalStrength1 * 2);
|
|
|
|
/* Update the sorting value */
|
|
pBssInfo->sortValue = zfComputeBssInfoWeightValue(dev,
|
|
(pBssInfo->supportedRates[6] + pBssInfo->extSupportedRates[0]),
|
|
pBssInfo->EnableHT,
|
|
pBssInfo->enableHT40,
|
|
pBssInfo->signalStrength);
|
|
}
|
|
|
|
return 0;
|
|
|
|
zlError:
|
|
|
|
return 1;
|
|
|
|
zlError2:
|
|
|
|
return 2;
|
|
}
|
|
|
|
void zfStaProcessBeacon(zdev_t* dev, zbuf_t* buf, struct zsAdditionInfo* AddInfo) //CWYang(m)
|
|
{
|
|
/* Parse TIM and send PS-POLL in power saving mode */
|
|
struct zsWlanBeaconFrameHeader* pBeaconHeader;
|
|
struct zsBssInfo* pBssInfo;
|
|
u8_t pBuf[sizeof(struct zsWlanBeaconFrameHeader)];
|
|
u8_t bssid[6];
|
|
int res;
|
|
|
|
zmw_get_wlan_dev(dev);
|
|
|
|
zmw_declare_for_critical_section();
|
|
|
|
/* sta routine jobs */
|
|
zfStaProtErpMonitor(dev, buf); /* check protection mode */
|
|
|
|
if (zfStaIsConnected(dev))
|
|
{
|
|
ZM_MAC_WORD_TO_BYTE(wd->sta.bssid, bssid);
|
|
|
|
if ( wd->wlanMode == ZM_MODE_INFRASTRUCTURE )
|
|
{
|
|
if ( zfRxBufferEqualToStr(dev, buf, bssid, ZM_WLAN_HEADER_A2_OFFSET, 6) )
|
|
{
|
|
zfPowerSavingMgrProcessBeacon(dev, buf);
|
|
zfStaUpdateWmeParameter(dev, buf);
|
|
if (wd->sta.DFSEnable)
|
|
zfStaUpdateDot11HDFS(dev, buf);
|
|
if (wd->sta.TPCEnable)
|
|
zfStaUpdateDot11HTPC(dev, buf);
|
|
/* update signal strength and signal quality */
|
|
zfStaSignalStatistic(dev, AddInfo->Tail.Data.SignalStrength1,
|
|
AddInfo->Tail.Data.SignalQuality); //CWYang(+)
|
|
wd->sta.rxBeaconCount++;
|
|
}
|
|
}
|
|
else if ( wd->wlanMode == ZM_MODE_IBSS )
|
|
{
|
|
if ( zfRxBufferEqualToStr(dev, buf, bssid, ZM_WLAN_HEADER_A3_OFFSET, 6) )
|
|
{
|
|
int res;
|
|
struct zsPartnerNotifyEvent event;
|
|
|
|
zm_debug_msg0("20070916 Receive opposite Beacon!");
|
|
zmw_enter_critical_section(dev);
|
|
wd->sta.ibssReceiveBeaconCount++;
|
|
zmw_leave_critical_section(dev);
|
|
|
|
res = zfStaSetOppositeInfoFromRxBuf(dev, buf);
|
|
if ( res == 0 )
|
|
{
|
|
// New peer station found. Notify the wrapper now
|
|
zfInitPartnerNotifyEvent(dev, buf, &event);
|
|
if (wd->zfcbIbssPartnerNotify != NULL)
|
|
{
|
|
wd->zfcbIbssPartnerNotify(dev, 1, &event);
|
|
}
|
|
}
|
|
/* update signal strength and signal quality */
|
|
zfStaSignalStatistic(dev, AddInfo->Tail.Data.SignalStrength1,
|
|
AddInfo->Tail.Data.SignalQuality); //CWYang(+)
|
|
}
|
|
//else if ( wd->sta.ibssPartnerStatus == ZM_IBSS_PARTNER_LOST )
|
|
// Why does this happen in IBSS?? The impact of Vista since
|
|
// we need to tell it the BSSID
|
|
#if 0
|
|
else if ( wd->sta.oppositeCount == 0 )
|
|
{ /* IBSS merge if SSID matched */
|
|
if ( (offset = zfFindElement(dev, buf, ZM_WLAN_EID_SSID)) != 0xffff )
|
|
{
|
|
if ( (wd->sta.ssidLen == zmw_buf_readb(dev, buf, offset+1))&&
|
|
(zfRxBufferEqualToStr(dev, buf, wd->sta.ssid,
|
|
offset+2, wd->sta.ssidLen)) )
|
|
{
|
|
capabilityInfo = zmw_buf_readh(dev, buf, 34);
|
|
|
|
if ( capabilityInfo & ZM_BIT_1 )
|
|
{
|
|
if ( (wd->sta.capability[0] & ZM_BIT_4) ==
|
|
(capabilityInfo & ZM_BIT_4) )
|
|
{
|
|
zm_debug_msg0("IBSS merge");
|
|
zfCopyFromRxBuffer(dev, buf, bssid,
|
|
ZM_WLAN_HEADER_A3_OFFSET, 6);
|
|
zfUpdateBssid(dev, bssid);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
}
|
|
}
|
|
|
|
/* return if not channel scan */
|
|
if ( !wd->sta.bChannelScan )
|
|
{
|
|
goto zlReturn;
|
|
}
|
|
|
|
zfCopyFromRxBuffer(dev, buf, pBuf, 0, sizeof(struct zsWlanBeaconFrameHeader));
|
|
pBeaconHeader = (struct zsWlanBeaconFrameHeader*) pBuf;
|
|
|
|
zmw_enter_critical_section(dev);
|
|
|
|
//zm_debug_msg1("bss count = ", wd->sta.bssList.bssCount);
|
|
|
|
pBssInfo = zfStaFindBssInfo(dev, buf, pBeaconHeader);
|
|
|
|
if ( pBssInfo == NULL )
|
|
{
|
|
/* Allocate a new entry if BSS not in the scan list */
|
|
pBssInfo = zfBssInfoAllocate(dev);
|
|
if (pBssInfo != NULL)
|
|
{
|
|
res = zfStaInitBssInfo(dev, buf, pBeaconHeader, pBssInfo, AddInfo, 0);
|
|
//zfDumpSSID(pBssInfo->ssid[1], &(pBssInfo->ssid[2]));
|
|
if ( res != 0 )
|
|
{
|
|
zfBssInfoFree(dev, pBssInfo);
|
|
}
|
|
else
|
|
{
|
|
zfBssInfoInsertToList(dev, pBssInfo);
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
res = zfStaInitBssInfo(dev, buf, pBeaconHeader, pBssInfo, AddInfo, 1);
|
|
if (res == 2)
|
|
{
|
|
zfBssInfoRemoveFromList(dev, pBssInfo);
|
|
zfBssInfoFree(dev, pBssInfo);
|
|
}
|
|
else if ( wd->wlanMode == ZM_MODE_IBSS )
|
|
{
|
|
int idx;
|
|
|
|
// It would reset the alive counter if the peer station is found!
|
|
zfStaFindFreeOpposite(dev, (u16_t *)pBssInfo->macaddr, &idx);
|
|
}
|
|
}
|
|
|
|
zmw_leave_critical_section(dev);
|
|
|
|
zlReturn:
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
void zfAuthFreqCompleteCb(zdev_t* dev)
|
|
{
|
|
zmw_get_wlan_dev(dev);
|
|
zmw_declare_for_critical_section();
|
|
|
|
zmw_enter_critical_section(dev);
|
|
|
|
if (wd->sta.connectState == ZM_STA_CONN_STATE_AUTH_COMPLETED)
|
|
{
|
|
zm_debug_msg0("ZM_STA_CONN_STATE_ASSOCIATE");
|
|
wd->sta.connectTimer = wd->tick;
|
|
wd->sta.connectState = ZM_STA_CONN_STATE_ASSOCIATE;
|
|
}
|
|
|
|
zmw_leave_critical_section(dev);
|
|
return;
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* */
|
|
/* FUNCTION DESCRIPTION zfProcessAuth */
|
|
/* Process authenticate management frame. */
|
|
/* */
|
|
/* INPUTS */
|
|
/* dev : device pointer */
|
|
/* buf : auth frame buffer */
|
|
/* */
|
|
/* OUTPUTS */
|
|
/* none */
|
|
/* */
|
|
/* AUTHOR */
|
|
/* Stephen Chen ZyDAS Technology Corporation 2005.10 */
|
|
/* */
|
|
/************************************************************************/
|
|
/* Note : AP allows one authenticating STA at a time, does not */
|
|
/* support multiple authentication process. Make sure */
|
|
/* authentication state machine will not be blocked due */
|
|
/* to incompleted authentication handshake. */
|
|
void zfStaProcessAuth(zdev_t* dev, zbuf_t* buf, u16_t* src, u16_t apId)
|
|
{
|
|
struct zsWlanAuthFrameHeader* pAuthFrame;
|
|
u8_t pBuf[sizeof(struct zsWlanAuthFrameHeader)];
|
|
u32_t p1, p2;
|
|
|
|
zmw_get_wlan_dev(dev);
|
|
zmw_declare_for_critical_section();
|
|
|
|
if ( !zfStaIsConnecting(dev) )
|
|
{
|
|
return;
|
|
}
|
|
|
|
pAuthFrame = (struct zsWlanAuthFrameHeader*) pBuf;
|
|
zfCopyFromRxBuffer(dev, buf, pBuf, 0, sizeof(struct zsWlanAuthFrameHeader));
|
|
|
|
if ( wd->sta.connectState == ZM_STA_CONN_STATE_AUTH_OPEN )
|
|
{
|
|
if ( (zmw_le16_to_cpu(pAuthFrame->seq) == 2)&&
|
|
(zmw_le16_to_cpu(pAuthFrame->algo) == 0)&&
|
|
(zmw_le16_to_cpu(pAuthFrame->status) == 0) )
|
|
{
|
|
|
|
zmw_enter_critical_section(dev);
|
|
wd->sta.connectTimer = wd->tick;
|
|
zm_debug_msg0("ZM_STA_CONN_STATE_AUTH_COMPLETED");
|
|
wd->sta.connectState = ZM_STA_CONN_STATE_AUTH_COMPLETED;
|
|
zmw_leave_critical_section(dev);
|
|
|
|
//Set channel according to AP's configuration
|
|
//Move to here because of Cisco 11n AP feature
|
|
zfCoreSetFrequencyEx(dev, wd->frequency, wd->BandWidth40,
|
|
wd->ExtOffset, zfAuthFreqCompleteCb);
|
|
|
|
/* send association frame */
|
|
if ( wd->sta.connectByReasso )
|
|
{
|
|
zfSendMmFrame(dev, ZM_WLAN_FRAME_TYPE_REASOCREQ,
|
|
wd->sta.bssid, 0, 0, 0);
|
|
}
|
|
else
|
|
{
|
|
zfSendMmFrame(dev, ZM_WLAN_FRAME_TYPE_ASOCREQ,
|
|
wd->sta.bssid, 0, 0, 0);
|
|
}
|
|
|
|
|
|
}
|
|
else
|
|
{
|
|
zm_debug_msg1("authentication failed, status = ",
|
|
pAuthFrame->status);
|
|
|
|
if (wd->sta.authMode == ZM_AUTH_MODE_AUTO)
|
|
{
|
|
wd->sta.bIsSharedKey = 1;
|
|
zfStaStartConnect(dev, wd->sta.bIsSharedKey);
|
|
}
|
|
else
|
|
{
|
|
zm_debug_msg0("ZM_STA_STATE_DISCONNECT");
|
|
zfStaConnectFail(dev, ZM_STATUS_MEDIA_DISCONNECT_AUTH_FAILED, wd->sta.bssid, 3);
|
|
}
|
|
}
|
|
}
|
|
else if ( wd->sta.connectState == ZM_STA_CONN_STATE_AUTH_SHARE_1 )
|
|
{
|
|
if ( (zmw_le16_to_cpu(pAuthFrame->algo) == 1) &&
|
|
(zmw_le16_to_cpu(pAuthFrame->seq) == 2) &&
|
|
(zmw_le16_to_cpu(pAuthFrame->status) == 0))
|
|
//&& (pAuthFrame->challengeText[1] <= 255) )
|
|
{
|
|
zfMemoryCopy(wd->sta.challengeText, pAuthFrame->challengeText,
|
|
pAuthFrame->challengeText[1]+2);
|
|
|
|
/* send the 3rd authentication frame */
|
|
p1 = 0x30001;
|
|
p2 = 0;
|
|
zfSendMmFrame(dev, ZM_WLAN_FRAME_TYPE_AUTH,
|
|
wd->sta.bssid, p1, p2, 0);
|
|
|
|
zmw_enter_critical_section(dev);
|
|
wd->sta.connectTimer = wd->tick;
|
|
|
|
zm_debug_msg0("ZM_STA_SUB_STATE_AUTH_SHARE_2");
|
|
wd->sta.connectState = ZM_STA_CONN_STATE_AUTH_SHARE_2;
|
|
zmw_leave_critical_section(dev);
|
|
}
|
|
else
|
|
{
|
|
zm_debug_msg1("authentication failed, status = ",
|
|
pAuthFrame->status);
|
|
|
|
zm_debug_msg0("ZM_STA_STATE_DISCONNECT");
|
|
zfStaConnectFail(dev, ZM_STATUS_MEDIA_DISCONNECT_AUTH_FAILED, wd->sta.bssid, 3);
|
|
}
|
|
}
|
|
else if ( wd->sta.connectState == ZM_STA_CONN_STATE_AUTH_SHARE_2 )
|
|
{
|
|
if ( (zmw_le16_to_cpu(pAuthFrame->algo) == 1)&&
|
|
(zmw_le16_to_cpu(pAuthFrame->seq) == 4)&&
|
|
(zmw_le16_to_cpu(pAuthFrame->status) == 0) )
|
|
{
|
|
//Set channel according to AP's configuration
|
|
//Move to here because of Cisco 11n AP feature
|
|
zfCoreSetFrequencyEx(dev, wd->frequency, wd->BandWidth40,
|
|
wd->ExtOffset, NULL);
|
|
|
|
/* send association frame */
|
|
zfSendMmFrame(dev, ZM_WLAN_FRAME_TYPE_ASOCREQ,
|
|
wd->sta.bssid, 0, 0, 0);
|
|
|
|
zmw_enter_critical_section(dev);
|
|
wd->sta.connectTimer = wd->tick;
|
|
|
|
zm_debug_msg0("ZM_STA_SUB_STATE_ASSOCIATE");
|
|
wd->sta.connectState = ZM_STA_CONN_STATE_ASSOCIATE;
|
|
zmw_leave_critical_section(dev);
|
|
}
|
|
else
|
|
{
|
|
zm_debug_msg1("authentication failed, status = ",
|
|
pAuthFrame->status);
|
|
|
|
zm_debug_msg0("ZM_STA_STATE_DISCONNECT");
|
|
zfStaConnectFail(dev, ZM_STATUS_MEDIA_DISCONNECT_AUTH_FAILED, wd->sta.bssid, 3);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
zm_debug_msg0("unknown case");
|
|
}
|
|
}
|
|
|
|
void zfStaProcessAsocReq(zdev_t* dev, zbuf_t* buf, u16_t* src, u16_t apId)
|
|
{
|
|
|
|
return;
|
|
}
|
|
|
|
void zfStaProcessAsocRsp(zdev_t* dev, zbuf_t* buf)
|
|
{
|
|
struct zsWlanAssoFrameHeader* pAssoFrame;
|
|
u8_t pBuf[sizeof(struct zsWlanAssoFrameHeader)];
|
|
u16_t offset;
|
|
u32_t i;
|
|
u32_t oneTxStreamCap;
|
|
|
|
zmw_get_wlan_dev(dev);
|
|
|
|
if ( !zfStaIsConnecting(dev) )
|
|
{
|
|
return;
|
|
}
|
|
|
|
pAssoFrame = (struct zsWlanAssoFrameHeader*) pBuf;
|
|
zfCopyFromRxBuffer(dev, buf, pBuf, 0, sizeof(struct zsWlanAssoFrameHeader));
|
|
|
|
if ( wd->sta.connectState == ZM_STA_CONN_STATE_ASSOCIATE )
|
|
{
|
|
if ( pAssoFrame->status == 0 )
|
|
{
|
|
zm_debug_msg0("ZM_STA_STATE_CONNECTED");
|
|
|
|
if (wd->sta.EnableHT == 1)
|
|
{
|
|
wd->sta.wmeConnected = 1;
|
|
}
|
|
if ((wd->sta.wmeEnabled & ZM_STA_WME_ENABLE_BIT) != 0) //WME enabled
|
|
{
|
|
/* Asoc rsp may contain WME parameter element */
|
|
if ((offset = zfFindWifiElement(dev, buf, 2, 1)) != 0xffff)
|
|
{
|
|
zm_debug_msg0("WME enable");
|
|
wd->sta.wmeConnected = 1;
|
|
if ((wd->sta.wmeEnabled & ZM_STA_UAPSD_ENABLE_BIT) != 0)
|
|
{
|
|
if ((zmw_rx_buf_readb(dev, buf, offset+8) & 0x80) != 0)
|
|
{
|
|
zm_debug_msg0("UAPSD enable");
|
|
wd->sta.qosInfo = wd->sta.wmeQosInfo;
|
|
}
|
|
}
|
|
|
|
zfStaUpdateWmeParameter(dev, buf);
|
|
}
|
|
}
|
|
|
|
|
|
//Store asoc response frame body, for VISTA only
|
|
wd->sta.asocRspFrameBodySize = zfwBufGetSize(dev, buf)-24;
|
|
if (wd->sta.asocRspFrameBodySize > ZM_CACHED_FRAMEBODY_SIZE)
|
|
{
|
|
wd->sta.asocRspFrameBodySize = ZM_CACHED_FRAMEBODY_SIZE;
|
|
}
|
|
for (i=0; i<wd->sta.asocRspFrameBodySize; i++)
|
|
{
|
|
wd->sta.asocRspFrameBody[i] = zmw_rx_buf_readb(dev, buf, i+24);
|
|
}
|
|
|
|
zfStaStoreAsocRspIe(dev, buf);
|
|
if (wd->sta.EnableHT &&
|
|
((wd->sta.ie.HtCap.HtCapInfo & HTCAP_SupChannelWidthSet) != 0) &&
|
|
(wd->ExtOffset != 0))
|
|
{
|
|
wd->sta.htCtrlBandwidth = 1;
|
|
}
|
|
else
|
|
{
|
|
wd->sta.htCtrlBandwidth = 0;
|
|
}
|
|
|
|
//Set channel according to AP's configuration
|
|
//zfCoreSetFrequencyEx(dev, wd->frequency, wd->BandWidth40,
|
|
// wd->ExtOffset, NULL);
|
|
|
|
if (wd->sta.EnableHT == 1)
|
|
{
|
|
wd->addbaComplete = 0;
|
|
|
|
if ((wd->sta.SWEncryptEnable & ZM_SW_TKIP_ENCRY_EN) == 0 &&
|
|
(wd->sta.SWEncryptEnable & ZM_SW_WEP_ENCRY_EN) == 0)
|
|
{
|
|
wd->addbaCount = 1;
|
|
zfAggSendAddbaRequest(dev, wd->sta.bssid, 0, 0);
|
|
zfTimerSchedule(dev, ZM_EVENT_TIMEOUT_ADDBA, 100);
|
|
}
|
|
}
|
|
|
|
/* set RIFS support */
|
|
if(wd->sta.ie.HtInfo.ChannelInfo & ExtHtCap_RIFSMode)
|
|
{
|
|
wd->sta.HT2040 = 1;
|
|
// zfHpSetRifs(dev, wd->sta.EnableHT, 1, (wd->sta.currentFrequency < 3000)? 1:0);
|
|
}
|
|
|
|
wd->sta.aid = pAssoFrame->aid & 0x3fff;
|
|
wd->sta.oppositeCount = 0; /* reset opposite count */
|
|
zfStaSetOppositeInfoFromRxBuf(dev, buf);
|
|
|
|
wd->sta.rxBeaconCount = 16;
|
|
|
|
zfChangeAdapterState(dev, ZM_STA_STATE_CONNECTED);
|
|
wd->sta.connPowerInHalfDbm = zfHpGetTransmitPower(dev);
|
|
if (wd->zfcbConnectNotify != NULL)
|
|
{
|
|
if (wd->sta.EnableHT != 0) /* 11n */
|
|
{
|
|
oneTxStreamCap = (zfHpCapability(dev) & ZM_HP_CAP_11N_ONE_TX_STREAM);
|
|
if (wd->sta.htCtrlBandwidth == 1) /* HT40*/
|
|
{
|
|
if(oneTxStreamCap) /* one Tx stream */
|
|
{
|
|
if (wd->sta.SG40)
|
|
{
|
|
wd->CurrentTxRateKbps = 150000;
|
|
wd->CurrentRxRateKbps = 300000;
|
|
}
|
|
else
|
|
{
|
|
wd->CurrentTxRateKbps = 135000;
|
|
wd->CurrentRxRateKbps = 270000;
|
|
}
|
|
}
|
|
else /* Two Tx streams */
|
|
{
|
|
if (wd->sta.SG40)
|
|
{
|
|
wd->CurrentTxRateKbps = 300000;
|
|
wd->CurrentRxRateKbps = 300000;
|
|
}
|
|
else
|
|
{
|
|
wd->CurrentTxRateKbps = 270000;
|
|
wd->CurrentRxRateKbps = 270000;
|
|
}
|
|
}
|
|
}
|
|
else /* HT20 */
|
|
{
|
|
if(oneTxStreamCap) /* one Tx stream */
|
|
{
|
|
wd->CurrentTxRateKbps = 650000;
|
|
wd->CurrentRxRateKbps = 130000;
|
|
}
|
|
else /* Two Tx streams */
|
|
{
|
|
wd->CurrentTxRateKbps = 130000;
|
|
wd->CurrentRxRateKbps = 130000;
|
|
}
|
|
}
|
|
}
|
|
else /* 11abg */
|
|
{
|
|
if (wd->sta.connection_11b != 0)
|
|
{
|
|
wd->CurrentTxRateKbps = 11000;
|
|
wd->CurrentRxRateKbps = 11000;
|
|
}
|
|
else
|
|
{
|
|
wd->CurrentTxRateKbps = 54000;
|
|
wd->CurrentRxRateKbps = 54000;
|
|
}
|
|
}
|
|
|
|
|
|
wd->zfcbConnectNotify(dev, ZM_STATUS_MEDIA_CONNECT, wd->sta.bssid);
|
|
}
|
|
wd->sta.connectByReasso = TRUE;
|
|
wd->sta.failCntOfReasso = 0;
|
|
|
|
zfPowerSavingMgrConnectNotify(dev);
|
|
|
|
/* Disable here because fixed rate is only for test, TBD. */
|
|
//if (wd->sta.EnableHT)
|
|
//{
|
|
// wd->txMCS = 7; //Rate = 65Mbps
|
|
// wd->txMT = 2; // Ht rate
|
|
// wd->enableAggregation = 2; // Enable Aggregation
|
|
//}
|
|
}
|
|
else
|
|
{
|
|
zm_debug_msg1("association failed, status = ",
|
|
pAssoFrame->status);
|
|
|
|
zm_debug_msg0("ZM_STA_STATE_DISCONNECT");
|
|
wd->sta.connectByReasso = FALSE;
|
|
zfStaConnectFail(dev, ZM_STATUS_MEDIA_DISCONNECT_ASOC_FAILED, wd->sta.bssid, 3);
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
void zfStaStoreAsocRspIe(zdev_t* dev, zbuf_t* buf)
|
|
{
|
|
u16_t offset;
|
|
u32_t i;
|
|
u16_t length;
|
|
u8_t *htcap;
|
|
u8_t asocBw40 = 0;
|
|
u8_t asocExtOffset = 0;
|
|
|
|
zmw_get_wlan_dev(dev);
|
|
|
|
for (i=0; i<wd->sta.asocRspFrameBodySize; i++)
|
|
{
|
|
wd->sta.asocRspFrameBody[i] = zmw_rx_buf_readb(dev, buf, i+24);
|
|
}
|
|
|
|
/* HT capabilities: 28 octets */
|
|
if ( ((wd->sta.currentFrequency > 3000) && !(wd->supportMode & ZM_WIRELESS_MODE_5_N))
|
|
|| ((wd->sta.currentFrequency < 3000) && !(wd->supportMode & ZM_WIRELESS_MODE_24_N)) )
|
|
{
|
|
/* not 11n AP */
|
|
htcap = (u8_t *)&wd->sta.ie.HtCap;
|
|
for (i=0; i<28; i++)
|
|
{
|
|
htcap[i] = 0;
|
|
}
|
|
wd->BandWidth40 = 0;
|
|
wd->ExtOffset = 0;
|
|
return;
|
|
}
|
|
|
|
if ((offset = zfFindElement(dev, buf, ZM_WLAN_EID_HT_CAPABILITY)) != 0xffff)
|
|
{
|
|
/* atheros pre n */
|
|
zm_debug_msg0("atheros pre n");
|
|
htcap = (u8_t *)&wd->sta.ie.HtCap;
|
|
htcap[0] = zmw_rx_buf_readb(dev, buf, offset);
|
|
htcap[1] = 26;
|
|
for (i=1; i<=26; i++)
|
|
{
|
|
htcap[i+1] = zmw_rx_buf_readb(dev, buf, offset + i);
|
|
zm_msg2_mm(ZM_LV_1, "ASOC: HT Capabilities, htcap=", htcap[i+1]);
|
|
}
|
|
}
|
|
else if ((offset = zfFindElement(dev, buf, ZM_WLAN_PREN2_EID_HTCAPABILITY)) != 0xffff)
|
|
{
|
|
/* pre n 2.0 standard */
|
|
zm_debug_msg0("pre n 2.0 standard");
|
|
htcap = (u8_t *)&wd->sta.ie.HtCap;
|
|
for (i=0; i<28; i++)
|
|
{
|
|
htcap[i] = zmw_rx_buf_readb(dev, buf, offset + i);
|
|
zm_msg2_mm(ZM_LV_1, "ASOC: HT Capabilities, htcap=", htcap[i]);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
/* not 11n AP */
|
|
htcap = (u8_t *)&wd->sta.ie.HtCap;
|
|
for (i=0; i<28; i++)
|
|
{
|
|
htcap[i] = 0;
|
|
}
|
|
wd->BandWidth40 = 0;
|
|
wd->ExtOffset = 0;
|
|
return;
|
|
}
|
|
|
|
asocBw40 = (u8_t)((wd->sta.ie.HtCap.HtCapInfo & HTCAP_SupChannelWidthSet) >> 1);
|
|
|
|
/* HT information */
|
|
if ((offset = zfFindElement(dev, buf, ZM_WLAN_EID_EXTENDED_HT_CAPABILITY)) != 0xffff)
|
|
{
|
|
/* atheros pre n */
|
|
zm_debug_msg0("atheros pre n HTINFO");
|
|
length = 22;
|
|
htcap = (u8_t *)&wd->sta.ie.HtInfo;
|
|
htcap[0] = zmw_rx_buf_readb(dev, buf, offset);
|
|
htcap[1] = 22;
|
|
for (i=1; i<=22; i++)
|
|
{
|
|
htcap[i+1] = zmw_rx_buf_readb(dev, buf, offset + i);
|
|
zm_msg2_mm(ZM_LV_1, "ASOC: HT Info, htinfo=", htcap[i+1]);
|
|
}
|
|
}
|
|
else if ((offset = zfFindElement(dev, buf, ZM_WLAN_PREN2_EID_HTINFORMATION)) != 0xffff)
|
|
{
|
|
/* pre n 2.0 standard */
|
|
zm_debug_msg0("pre n 2.0 standard HTINFO");
|
|
length = zmw_rx_buf_readb(dev, buf, offset + 1);
|
|
htcap = (u8_t *)&wd->sta.ie.HtInfo;
|
|
for (i=0; i<24; i++)
|
|
{
|
|
htcap[i] = zmw_rx_buf_readb(dev, buf, offset + i);
|
|
zm_msg2_mm(ZM_LV_1, "ASOC: HT Info, htinfo=", htcap[i]);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
zm_debug_msg0("no HTINFO");
|
|
htcap = (u8_t *)&wd->sta.ie.HtInfo;
|
|
for (i=0; i<24; i++)
|
|
{
|
|
htcap[i] = 0;
|
|
}
|
|
}
|
|
asocExtOffset = wd->sta.ie.HtInfo.ChannelInfo & ExtHtCap_ExtChannelOffsetBelow;
|
|
|
|
if ((wd->sta.EnableHT == 1) && (asocBw40 == 1) && ((asocExtOffset == 1) || (asocExtOffset == 3)))
|
|
{
|
|
wd->BandWidth40 = asocBw40;
|
|
wd->ExtOffset = asocExtOffset;
|
|
}
|
|
else
|
|
{
|
|
wd->BandWidth40 = 0;
|
|
wd->ExtOffset = 0;
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
void zfStaProcessDeauth(zdev_t* dev, zbuf_t* buf)
|
|
{
|
|
u16_t apMacAddr[3];
|
|
|
|
zmw_get_wlan_dev(dev);
|
|
zmw_declare_for_critical_section();
|
|
|
|
/* STA : if SA=connected AP then disconnect with AP */
|
|
if ( wd->wlanMode == ZM_MODE_INFRASTRUCTURE )
|
|
{
|
|
apMacAddr[0] = zmw_rx_buf_readh(dev, buf, ZM_WLAN_HEADER_A3_OFFSET);
|
|
apMacAddr[1] = zmw_rx_buf_readh(dev, buf, ZM_WLAN_HEADER_A3_OFFSET+2);
|
|
apMacAddr[2] = zmw_rx_buf_readh(dev, buf, ZM_WLAN_HEADER_A3_OFFSET+4);
|
|
if ((apMacAddr[0] == wd->sta.bssid[0]) && (apMacAddr[1] == wd->sta.bssid[1]) && (apMacAddr[2] == wd->sta.bssid[2]))
|
|
{
|
|
if (zfwBufGetSize(dev, buf) >= 24+2) //not a malformed frame
|
|
{
|
|
if ( zfStaIsConnected(dev) )
|
|
{
|
|
zfStaConnectFail(dev, ZM_STATUS_MEDIA_DISCONNECT_DEAUTH, wd->sta.bssid, 2);
|
|
}
|
|
else if (zfStaIsConnecting(dev))
|
|
{
|
|
zfStaConnectFail(dev, ZM_STATUS_MEDIA_DISCONNECT_AUTH_FAILED, wd->sta.bssid, 3);
|
|
}
|
|
else
|
|
{
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else if ( wd->wlanMode == ZM_MODE_IBSS )
|
|
{
|
|
u16_t peerMacAddr[3];
|
|
u8_t peerIdx;
|
|
s8_t res;
|
|
|
|
if ( zfStaIsConnected(dev) )
|
|
{
|
|
peerMacAddr[0] = zmw_rx_buf_readh(dev, buf, ZM_WLAN_HEADER_A2_OFFSET);
|
|
peerMacAddr[1] = zmw_rx_buf_readh(dev, buf, ZM_WLAN_HEADER_A2_OFFSET+2);
|
|
peerMacAddr[2] = zmw_rx_buf_readh(dev, buf, ZM_WLAN_HEADER_A2_OFFSET+4);
|
|
|
|
zmw_enter_critical_section(dev);
|
|
res = zfStaFindOppositeByMACAddr(dev, peerMacAddr, &peerIdx);
|
|
if ( res == 0 )
|
|
{
|
|
wd->sta.oppositeInfo[peerIdx].aliveCounter = 0;
|
|
}
|
|
zmw_leave_critical_section(dev);
|
|
}
|
|
}
|
|
}
|
|
|
|
void zfStaProcessDisasoc(zdev_t* dev, zbuf_t* buf)
|
|
{
|
|
u16_t apMacAddr[3];
|
|
|
|
zmw_get_wlan_dev(dev);
|
|
|
|
/* STA : if SA=connected AP then disconnect with AP */
|
|
if ( wd->wlanMode == ZM_MODE_INFRASTRUCTURE )
|
|
{
|
|
apMacAddr[0] = zmw_rx_buf_readh(dev, buf, ZM_WLAN_HEADER_A3_OFFSET);
|
|
apMacAddr[1] = zmw_rx_buf_readh(dev, buf, ZM_WLAN_HEADER_A3_OFFSET+2);
|
|
apMacAddr[2] = zmw_rx_buf_readh(dev, buf, ZM_WLAN_HEADER_A3_OFFSET+4);
|
|
|
|
if ((apMacAddr[0] == wd->sta.bssid[0]) && (apMacAddr[1] == wd->sta.bssid[1]) && (apMacAddr[2] == wd->sta.bssid[2]))
|
|
{
|
|
if (zfwBufGetSize(dev, buf) >= 24+2) //not a malformed frame
|
|
{
|
|
if ( zfStaIsConnected(dev) )
|
|
{
|
|
zfStaConnectFail(dev, ZM_STATUS_MEDIA_DISCONNECT_DISASOC, wd->sta.bssid, 2);
|
|
}
|
|
else
|
|
{
|
|
zfStaConnectFail(dev, ZM_STATUS_MEDIA_DISCONNECT_ASOC_FAILED, wd->sta.bssid, 3);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/************************************************************************/
|
|
/* */
|
|
/* FUNCTION DESCRIPTION zfProcessProbeReq */
|
|
/* Process probe request management frame. */
|
|
/* */
|
|
/* INPUTS */
|
|
/* dev : device pointer */
|
|
/* buf : auth frame buffer */
|
|
/* */
|
|
/* OUTPUTS */
|
|
/* none */
|
|
/* */
|
|
/* AUTHOR */
|
|
/* Stephen Chen ZyDAS Technology Corporation 2005.10 */
|
|
/* */
|
|
/************************************************************************/
|
|
void zfStaProcessProbeReq(zdev_t* dev, zbuf_t* buf, u16_t* src)
|
|
{
|
|
u16_t offset;
|
|
u8_t len;
|
|
u16_t i, j;
|
|
u16_t sendFlag;
|
|
|
|
zmw_get_wlan_dev(dev);
|
|
|
|
/* check mode : AP/IBSS */
|
|
if ((wd->wlanMode != ZM_MODE_AP) || (wd->wlanMode != ZM_MODE_IBSS))
|
|
{
|
|
zm_msg0_mm(ZM_LV_3, "Ignore probe req");
|
|
return;
|
|
}
|
|
|
|
/* check SSID */
|
|
if ((offset = zfFindElement(dev, buf, ZM_WLAN_EID_SSID)) == 0xffff)
|
|
{
|
|
zm_msg0_mm(ZM_LV_3, "probe req SSID not found");
|
|
return;
|
|
}
|
|
|
|
len = zmw_rx_buf_readb(dev, buf, offset+1);
|
|
|
|
for (i=0; i<ZM_MAX_AP_SUPPORT; i++)
|
|
{
|
|
if ((wd->ap.apBitmap & (i<<i)) != 0)
|
|
{
|
|
sendFlag = 0;
|
|
/* boardcast SSID */
|
|
if ((len == 0) && (wd->ap.hideSsid[i] == 0))
|
|
{
|
|
sendFlag = 1;
|
|
}
|
|
/* Not broadcast SSID */
|
|
else if (wd->ap.ssidLen[i] == len)
|
|
{
|
|
for (j=0; j<len; j++)
|
|
{
|
|
if (zmw_rx_buf_readb(dev, buf, offset+1+j)
|
|
!= wd->ap.ssid[i][j])
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
if (j == len)
|
|
{
|
|
sendFlag = 1;
|
|
}
|
|
}
|
|
if (sendFlag == 1)
|
|
{
|
|
/* Send probe response */
|
|
zfSendMmFrame(dev, ZM_WLAN_FRAME_TYPE_PROBERSP, src, i, 0, 0);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void zfStaProcessProbeRsp(zdev_t* dev, zbuf_t* buf, struct zsAdditionInfo* AddInfo)
|
|
{
|
|
/* return if not channel scan */
|
|
// Probe response is sent with unicast. Is this required?
|
|
// IBSS would send probe request and the code below would prevent
|
|
// the probe response from handling.
|
|
#if 0
|
|
zmw_get_wlan_dev(dev);
|
|
|
|
if ( !wd->sta.bChannelScan )
|
|
{
|
|
return;
|
|
}
|
|
#endif
|
|
|
|
zfProcessProbeRsp(dev, buf, AddInfo);
|
|
}
|
|
|
|
void zfIBSSSetupBssDesc(zdev_t *dev)
|
|
{
|
|
#ifdef ZM_ENABLE_IBSS_WPA2PSK
|
|
u8_t i;
|
|
#endif
|
|
struct zsBssInfo *pBssInfo;
|
|
u16_t offset = 0;
|
|
|
|
zmw_get_wlan_dev(dev);
|
|
|
|
pBssInfo = &wd->sta.ibssBssDesc;
|
|
zfZeroMemory((u8_t *)pBssInfo, sizeof(struct zsBssInfo));
|
|
|
|
pBssInfo->signalStrength = 100;
|
|
|
|
zfMemoryCopy((u8_t *)pBssInfo->macaddr, (u8_t *)wd->macAddr,6);
|
|
zfMemoryCopy((u8_t *)pBssInfo->bssid, (u8_t *)wd->sta.bssid, 6);
|
|
|
|
pBssInfo->beaconInterval[0] = (u8_t)(wd->beaconInterval) ;
|
|
pBssInfo->beaconInterval[1] = (u8_t)((wd->beaconInterval) >> 8) ;
|
|
|
|
pBssInfo->capability[0] = wd->sta.capability[0];
|
|
pBssInfo->capability[1] = wd->sta.capability[1];
|
|
|
|
pBssInfo->ssid[0] = ZM_WLAN_EID_SSID;
|
|
pBssInfo->ssid[1] = wd->sta.ssidLen;
|
|
zfMemoryCopy((u8_t *)&pBssInfo->ssid[2], (u8_t *)wd->sta.ssid, wd->sta.ssidLen);
|
|
zfMemoryCopy((u8_t *)&pBssInfo->frameBody[offset], (u8_t *)pBssInfo->ssid,
|
|
wd->sta.ssidLen + 2);
|
|
offset += wd->sta.ssidLen + 2;
|
|
|
|
/* support rate */
|
|
|
|
/* DS parameter set */
|
|
pBssInfo->channel = zfChFreqToNum(wd->frequency, NULL);
|
|
pBssInfo->frequency = wd->frequency;
|
|
pBssInfo->atimWindow = wd->sta.atimWindow;
|
|
|
|
#ifdef ZM_ENABLE_IBSS_WPA2PSK
|
|
if ( wd->sta.authMode == ZM_AUTH_MODE_WPA2PSK )
|
|
{
|
|
u8_t rsn[64]=
|
|
{
|
|
/* Element ID */
|
|
0x30,
|
|
/* Length */
|
|
0x14,
|
|
/* Version */
|
|
0x01, 0x00,
|
|
/* Group Cipher Suite, default=TKIP */
|
|
0x00, 0x0f, 0xac, 0x04,
|
|
/* Pairwise Cipher Suite Count */
|
|
0x01, 0x00,
|
|
/* Pairwise Cipher Suite, default=TKIP */
|
|
0x00, 0x0f, 0xac, 0x02,
|
|
/* Authentication and Key Management Suite Count */
|
|
0x01, 0x00,
|
|
/* Authentication type, default=PSK */
|
|
0x00, 0x0f, 0xac, 0x02,
|
|
/* RSN capability */
|
|
0x00, 0x00
|
|
};
|
|
|
|
/* Overwrite Group Cipher Suite by AP's setting */
|
|
zfMemoryCopy(rsn+4, zgWpa2AesOui, 4);
|
|
|
|
if ( wd->sta.wepStatus == ZM_ENCRYPTION_AES )
|
|
{
|
|
/* Overwrite Pairwise Cipher Suite by AES */
|
|
zfMemoryCopy(rsn+10, zgWpa2AesOui, 4);
|
|
}
|
|
|
|
// RSN element id
|
|
pBssInfo->frameBody[offset++] = ZM_WLAN_EID_RSN_IE ;
|
|
|
|
// RSN length
|
|
pBssInfo->frameBody[offset++] = rsn[1] ;
|
|
|
|
// RSN information
|
|
for(i=0; i<rsn[1]; i++)
|
|
{
|
|
pBssInfo->frameBody[offset++] = rsn[i+2] ;
|
|
}
|
|
|
|
zfMemoryCopy(pBssInfo->rsnIe, rsn, rsn[1]+2);
|
|
}
|
|
#endif
|
|
}
|
|
|
|
void zfIbssConnectNetwork(zdev_t* dev)
|
|
{
|
|
struct zsBssInfo* pBssInfo;
|
|
struct zsBssInfo tmpBssInfo;
|
|
u8_t macAddr[6], bssid[6], bssNotFound = TRUE;
|
|
u16_t i, j=100;
|
|
u16_t k;
|
|
struct zsPartnerNotifyEvent event;
|
|
u32_t channelFlags;
|
|
u16_t oppositeWepStatus;
|
|
|
|
zmw_get_wlan_dev(dev);
|
|
|
|
zmw_declare_for_critical_section();
|
|
|
|
/* change state to CONNECTING and stop the channel scanning */
|
|
zfChangeAdapterState(dev, ZM_STA_STATE_CONNECTING);
|
|
zfPowerSavingMgrWakeup(dev);
|
|
|
|
/* Set TxQs CWMIN, CWMAX, AIFS and TXO to WME STA default. */
|
|
zfUpdateDefaultQosParameter(dev, 0);
|
|
|
|
wd->sta.bProtectionMode = FALSE;
|
|
zfHpSetSlotTime(dev, 1);
|
|
|
|
/* ESS bit off */
|
|
wd->sta.capability[0] &= ~ZM_BIT_0;
|
|
/* IBSS bit on */
|
|
wd->sta.capability[0] |= ZM_BIT_1;
|
|
/* not not use short slot time */
|
|
wd->sta.capability[1] &= ~ZM_BIT_2;
|
|
|
|
wd->sta.wmeConnected = 0;
|
|
wd->sta.psMgr.tempWakeUp = 0;
|
|
wd->sta.qosInfo = 0;
|
|
wd->sta.EnableHT = 0;
|
|
wd->BandWidth40 = 0;
|
|
wd->ExtOffset = 0;
|
|
|
|
if ( wd->sta.bssList.bssCount )
|
|
{
|
|
//Reorder BssList by RSSI--CWYang(+)
|
|
zfBssInfoReorderList(dev);
|
|
|
|
zmw_enter_critical_section(dev);
|
|
|
|
pBssInfo = wd->sta.bssList.head;
|
|
|
|
for(i=0; i<wd->sta.bssList.bssCount; i++)
|
|
{
|
|
// 20070806 #1 Privacy bit
|
|
if ( pBssInfo->capability[0] & ZM_BIT_4 )
|
|
{ // Privacy Ibss network
|
|
// zm_debug_msg0("Privacy bit on");
|
|
oppositeWepStatus = ZM_ENCRYPTION_WEP_ENABLED;
|
|
|
|
if ( pBssInfo->rsnIe[1] != 0 )
|
|
{
|
|
if ( (pBssInfo->rsnIe[7] == 0x01) || (pBssInfo->rsnIe[7] == 0x05) )
|
|
{ // WEP-40 & WEP-104
|
|
// zm_debug_msg0("WEP40 or WEP104");
|
|
oppositeWepStatus = ZM_ENCRYPTION_WEP_ENABLED;
|
|
}
|
|
else if ( pBssInfo->rsnIe[7] == 0x02 )
|
|
{ // TKIP
|
|
// zm_debug_msg0("TKIP");
|
|
oppositeWepStatus = ZM_ENCRYPTION_TKIP;
|
|
}
|
|
else if ( pBssInfo->rsnIe[7] == 0x04 )
|
|
{ // AES
|
|
// zm_debug_msg0("CCMP-AES");
|
|
oppositeWepStatus = ZM_ENCRYPTION_AES;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// zm_debug_msg0("Privacy bit off");
|
|
oppositeWepStatus = ZM_ENCRYPTION_WEP_DISABLED;
|
|
}
|
|
|
|
if ( (zfMemoryIsEqual(&(pBssInfo->ssid[2]), wd->sta.ssid,
|
|
wd->sta.ssidLen))&&
|
|
(wd->sta.ssidLen == pBssInfo->ssid[1])&&
|
|
(oppositeWepStatus == wd->sta.wepStatus) )
|
|
{
|
|
/* Check support mode */
|
|
if (pBssInfo->frequency > 3000) {
|
|
if ( (pBssInfo->EnableHT == 1)
|
|
|| (pBssInfo->apCap & ZM_All11N_AP) ) //11n AP
|
|
{
|
|
channelFlags = CHANNEL_A_HT;
|
|
if (pBssInfo->enableHT40 == 1) {
|
|
channelFlags |= CHANNEL_HT40;
|
|
}
|
|
} else {
|
|
channelFlags = CHANNEL_A;
|
|
}
|
|
} else {
|
|
if ( (pBssInfo->EnableHT == 1)
|
|
|| (pBssInfo->apCap & ZM_All11N_AP) ) //11n AP
|
|
{
|
|
channelFlags = CHANNEL_G_HT;
|
|
if(pBssInfo->enableHT40 == 1) {
|
|
channelFlags |= CHANNEL_HT40;
|
|
}
|
|
} else {
|
|
if (pBssInfo->extSupportedRates[1] == 0) {
|
|
channelFlags = CHANNEL_B;
|
|
} else {
|
|
channelFlags = CHANNEL_G;
|
|
}
|
|
}
|
|
}
|
|
|
|
if ( ((channelFlags == CHANNEL_B) && (wd->connectMode & ZM_BIT_0))
|
|
|| ((channelFlags == CHANNEL_G) && (wd->connectMode & ZM_BIT_1))
|
|
|| ((channelFlags == CHANNEL_A) && (wd->connectMode & ZM_BIT_2))
|
|
|| ((channelFlags & CHANNEL_HT20) && (wd->connectMode & ZM_BIT_3)) )
|
|
{
|
|
pBssInfo = pBssInfo->next;
|
|
continue;
|
|
}
|
|
|
|
/* Bypass DFS channel */
|
|
if (zfHpIsDfsChannelNCS(dev, pBssInfo->frequency))
|
|
{
|
|
zm_debug_msg0("Bypass DFS channel");
|
|
continue;
|
|
}
|
|
|
|
/* check IBSS bit */
|
|
if ( pBssInfo->capability[0] & ZM_BIT_1 )
|
|
{
|
|
/* may check timestamp here */
|
|
j = i;
|
|
break;
|
|
}
|
|
}
|
|
|
|
pBssInfo = pBssInfo->next;
|
|
}
|
|
|
|
if ((j < wd->sta.bssList.bssCount) && (pBssInfo != NULL))
|
|
{
|
|
zfwMemoryCopy((u8_t*)&tmpBssInfo, (u8_t*)(pBssInfo), sizeof(struct zsBssInfo));
|
|
pBssInfo = &tmpBssInfo;
|
|
}
|
|
else
|
|
{
|
|
pBssInfo = NULL;
|
|
}
|
|
|
|
zmw_leave_critical_section(dev);
|
|
|
|
//if ( j < wd->sta.bssList.bssCount )
|
|
if (pBssInfo != NULL)
|
|
{
|
|
int res;
|
|
|
|
zm_debug_msg0("IBSS found");
|
|
|
|
/* Found IBSS, reset bssNotFoundCount */
|
|
zmw_enter_critical_section(dev);
|
|
wd->sta.bssNotFoundCount = 0;
|
|
zmw_leave_critical_section(dev);
|
|
|
|
bssNotFound = FALSE;
|
|
wd->sta.atimWindow = pBssInfo->atimWindow;
|
|
wd->frequency = pBssInfo->frequency;
|
|
//wd->sta.flagFreqChanging = 1;
|
|
zfCoreSetFrequency(dev, wd->frequency);
|
|
zfUpdateBssid(dev, pBssInfo->bssid);
|
|
zfResetSupportRate(dev, ZM_DEFAULT_SUPPORT_RATE_ZERO);
|
|
zfUpdateSupportRate(dev, pBssInfo->supportedRates);
|
|
zfUpdateSupportRate(dev, pBssInfo->extSupportedRates);
|
|
wd->beaconInterval = pBssInfo->beaconInterval[0] +
|
|
(((u16_t) pBssInfo->beaconInterval[1]) << 8);
|
|
|
|
if (wd->beaconInterval == 0)
|
|
{
|
|
wd->beaconInterval = 100;
|
|
}
|
|
|
|
/* rsn information element */
|
|
if ( pBssInfo->rsnIe[1] != 0 )
|
|
{
|
|
zfMemoryCopy(wd->sta.rsnIe, pBssInfo->rsnIe,
|
|
pBssInfo->rsnIe[1]+2);
|
|
|
|
#ifdef ZM_ENABLE_IBSS_WPA2PSK
|
|
/* If not use RSNA , run traditional */
|
|
zmw_enter_critical_section(dev);
|
|
wd->sta.ibssWpa2Psk = 1;
|
|
zmw_leave_critical_section(dev);
|
|
#endif
|
|
}
|
|
else
|
|
{
|
|
wd->sta.rsnIe[1] = 0;
|
|
}
|
|
|
|
/* privacy bit */
|
|
if ( pBssInfo->capability[0] & ZM_BIT_4 )
|
|
{
|
|
wd->sta.capability[0] |= ZM_BIT_4;
|
|
}
|
|
else
|
|
{
|
|
wd->sta.capability[0] &= ~ZM_BIT_4;
|
|
}
|
|
|
|
/* preamble type */
|
|
wd->preambleTypeInUsed = wd->preambleType;
|
|
if ( wd->preambleTypeInUsed == ZM_PREAMBLE_TYPE_AUTO )
|
|
{
|
|
if (pBssInfo->capability[0] & ZM_BIT_5)
|
|
{
|
|
wd->preambleTypeInUsed = ZM_PREAMBLE_TYPE_SHORT;
|
|
}
|
|
else
|
|
{
|
|
wd->preambleTypeInUsed = ZM_PREAMBLE_TYPE_LONG;
|
|
}
|
|
}
|
|
|
|
if (wd->preambleTypeInUsed == ZM_PREAMBLE_TYPE_LONG)
|
|
{
|
|
wd->sta.capability[0] &= ~ZM_BIT_5;
|
|
}
|
|
else
|
|
{
|
|
wd->sta.capability[0] |= ZM_BIT_5;
|
|
}
|
|
|
|
wd->sta.beaconFrameBodySize = pBssInfo->frameBodysize + 12;
|
|
|
|
if (wd->sta.beaconFrameBodySize > ZM_CACHED_FRAMEBODY_SIZE)
|
|
{
|
|
wd->sta.beaconFrameBodySize = ZM_CACHED_FRAMEBODY_SIZE;
|
|
}
|
|
|
|
for (k=0; k<8; k++)
|
|
{
|
|
wd->sta.beaconFrameBody[k] = pBssInfo->timeStamp[k];
|
|
}
|
|
wd->sta.beaconFrameBody[8] = pBssInfo->beaconInterval[0];
|
|
wd->sta.beaconFrameBody[9] = pBssInfo->beaconInterval[1];
|
|
wd->sta.beaconFrameBody[10] = pBssInfo->capability[0];
|
|
wd->sta.beaconFrameBody[11] = pBssInfo->capability[1];
|
|
//for (k=12; k<wd->sta.beaconFrameBodySize; k++)
|
|
for (k=0; k<pBssInfo->frameBodysize; k++)
|
|
{
|
|
wd->sta.beaconFrameBody[k+12] = pBssInfo->frameBody[k];
|
|
}
|
|
|
|
zmw_enter_critical_section(dev);
|
|
res = zfStaSetOppositeInfoFromBSSInfo(dev, pBssInfo);
|
|
if ( res == 0 )
|
|
{
|
|
zfMemoryCopy(event.bssid, (u8_t *)(pBssInfo->bssid), 6);
|
|
zfMemoryCopy(event.peerMacAddr, (u8_t *)(pBssInfo->macaddr), 6);
|
|
}
|
|
zmw_leave_critical_section(dev);
|
|
|
|
//zfwIbssPartnerNotify(dev, 1, &event);
|
|
goto connect_done;
|
|
}
|
|
}
|
|
|
|
/* IBSS not found */
|
|
if ( bssNotFound )
|
|
{
|
|
#ifdef ZM_ENABLE_IBSS_WPA2PSK
|
|
u16_t offset ;
|
|
#endif
|
|
if ( wd->sta.ibssJoinOnly )
|
|
{
|
|
zm_debug_msg0("IBSS join only...retry...");
|
|
goto retry_ibss;
|
|
}
|
|
|
|
if(wd->sta.bssNotFoundCount<2)
|
|
{
|
|
zmw_enter_critical_section(dev);
|
|
zm_debug_msg1("IBSS not found, do sitesurvey!! bssNotFoundCount=", wd->sta.bssNotFoundCount);
|
|
wd->sta.bssNotFoundCount++;
|
|
zmw_leave_critical_section(dev);
|
|
goto retry_ibss;
|
|
}
|
|
else
|
|
{
|
|
zmw_enter_critical_section(dev);
|
|
/* Fail IBSS found, TODO create IBSS */
|
|
wd->sta.bssNotFoundCount = 0;
|
|
zmw_leave_critical_section(dev);
|
|
}
|
|
|
|
|
|
if (zfHpIsDfsChannel(dev, wd->frequency))
|
|
{
|
|
wd->frequency = zfHpFindFirstNonDfsChannel(dev, wd->frequency > 3000);
|
|
}
|
|
|
|
if( wd->ws.autoSetFrequency == 0 )
|
|
{ /* Auto set frequency */
|
|
zm_debug_msg1("Create Ad Hoc Network Band ", wd->ws.adhocMode);
|
|
wd->frequency = zfFindCleanFrequency(dev, wd->ws.adhocMode);
|
|
wd->ws.autoSetFrequency = 0xff;
|
|
}
|
|
zm_debug_msg1("IBSS not found, created one in channel ", wd->frequency);
|
|
|
|
wd->sta.ibssBssIsCreator = 1;
|
|
|
|
//wd->sta.flagFreqChanging = 1;
|
|
zfCoreSetFrequency(dev, wd->frequency);
|
|
if (wd->sta.bDesiredBssid == TRUE)
|
|
{
|
|
for (k=0; k<6; k++)
|
|
{
|
|
bssid[k] = wd->sta.desiredBssid[k];
|
|
}
|
|
}
|
|
else
|
|
{
|
|
#if 1
|
|
macAddr[0] = (wd->macAddr[0] & 0xff);
|
|
macAddr[1] = (wd->macAddr[0] >> 8);
|
|
macAddr[2] = (wd->macAddr[1] & 0xff);
|
|
macAddr[3] = (wd->macAddr[1] >> 8);
|
|
macAddr[4] = (wd->macAddr[2] & 0xff);
|
|
macAddr[5] = (wd->macAddr[2] >> 8);
|
|
zfGenerateRandomBSSID(dev, (u8_t *)wd->macAddr, (u8_t *)bssid);
|
|
#else
|
|
for (k=0; k<6; k++)
|
|
{
|
|
bssid[k] = (u8_t) zfGetRandomNumber(dev, 0);
|
|
}
|
|
bssid[0] &= ~ZM_BIT_0;
|
|
bssid[0] |= ZM_BIT_1;
|
|
#endif
|
|
}
|
|
|
|
zfUpdateBssid(dev, bssid);
|
|
//wd->sta.atimWindow = 0x0a;
|
|
|
|
/* rate information */
|
|
if(wd->frequency <= ZM_CH_G_14) // 2.4 GHz b+g
|
|
{
|
|
if ( wd->wfc.bIbssGMode
|
|
&& (wd->supportMode & (ZM_WIRELESS_MODE_24_54|ZM_WIRELESS_MODE_24_N)) )
|
|
{
|
|
zfResetSupportRate(dev, ZM_DEFAULT_SUPPORT_RATE_IBSS_AG);
|
|
}
|
|
else
|
|
{
|
|
zfResetSupportRate(dev, ZM_DEFAULT_SUPPORT_RATE_IBSS_B);
|
|
}
|
|
} else {
|
|
zfResetSupportRate(dev, ZM_DEFAULT_SUPPORT_RATE_IBSS_AG);
|
|
}
|
|
|
|
if ( wd->sta.wepStatus == ZM_ENCRYPTION_WEP_DISABLED )
|
|
{
|
|
wd->sta.capability[0] &= ~ZM_BIT_4;
|
|
}
|
|
else
|
|
{
|
|
wd->sta.capability[0] |= ZM_BIT_4;
|
|
}
|
|
|
|
wd->preambleTypeInUsed = wd->preambleType;
|
|
if (wd->preambleTypeInUsed == ZM_PREAMBLE_TYPE_LONG)
|
|
{
|
|
wd->sta.capability[0] &= ~ZM_BIT_5;
|
|
}
|
|
else
|
|
{
|
|
wd->preambleTypeInUsed = ZM_PREAMBLE_TYPE_SHORT;
|
|
wd->sta.capability[0] |= ZM_BIT_5;
|
|
}
|
|
|
|
zfIBSSSetupBssDesc(dev);
|
|
|
|
#ifdef ZM_ENABLE_IBSS_WPA2PSK
|
|
|
|
// 20070411 Add WPA2PSK information to its IBSS network !!!
|
|
offset = 0 ;
|
|
|
|
/* timestamp */
|
|
offset += 8 ;
|
|
|
|
/* beacon interval */
|
|
wd->sta.beaconFrameBody[offset++] = (u8_t)(wd->beaconInterval) ;
|
|
wd->sta.beaconFrameBody[offset++] = (u8_t)((wd->beaconInterval) >> 8) ;
|
|
|
|
/* capability information */
|
|
wd->sta.beaconFrameBody[offset++] = wd->sta.capability[0] ;
|
|
wd->sta.beaconFrameBody[offset++] = wd->sta.capability[1] ;
|
|
#if 0
|
|
/* ssid */
|
|
// ssid element id
|
|
wd->sta.beaconFrameBody[offset++] = ZM_WLAN_EID_SSID ;
|
|
// ssid length
|
|
wd->sta.beaconFrameBody[offset++] = wd->sta.ssidLen ;
|
|
// ssid information
|
|
for(i=0; i<wd->sta.ssidLen; i++)
|
|
{
|
|
wd->sta.beaconFrameBody[offset++] = wd->sta.ssid[i] ;
|
|
}
|
|
|
|
/* support rate */
|
|
rateSet = ZM_RATE_SET_CCK ;
|
|
if ( (rateSet == ZM_RATE_SET_OFDM)&&((wd->gRate & 0xff) == 0) )
|
|
{
|
|
offset += 0 ;
|
|
}
|
|
else
|
|
{
|
|
// support rate element id
|
|
wd->sta.beaconFrameBody[offset++] = ZM_WLAN_EID_SUPPORT_RATE ;
|
|
|
|
// support rate length
|
|
lenOffset = offset++;
|
|
|
|
// support rate information
|
|
for (i=0; i<4; i++)
|
|
{
|
|
if ((wd->bRate & (0x1<<i)) == (0x1<<i))
|
|
{
|
|
wd->sta.beaconFrameBody[offset++] =
|
|
zg11bRateTbl[i]+((wd->bRateBasic & (0x1<<i))<<(7-i)) ;
|
|
len++;
|
|
}
|
|
}
|
|
|
|
// support rate length
|
|
wd->sta.beaconFrameBody[lenOffset] = len ;
|
|
}
|
|
|
|
/* DS parameter set */
|
|
// DS parameter set elemet id
|
|
wd->sta.beaconFrameBody[offset++] = ZM_WLAN_EID_DS ;
|
|
|
|
// DS parameter set length
|
|
wd->sta.beaconFrameBody[offset++] = 1 ;
|
|
|
|
// DS parameter set information
|
|
wd->sta.beaconFrameBody[offset++] =
|
|
zfChFreqToNum(wd->frequency, NULL) ;
|
|
|
|
/* IBSS parameter set */
|
|
// IBSS parameter set element id
|
|
wd->sta.beaconFrameBody[offset++] = ZM_WLAN_EID_IBSS ;
|
|
|
|
// IBSS parameter set length
|
|
wd->sta.beaconFrameBody[offset++] = 2 ;
|
|
|
|
// IBSS parameter set information
|
|
wd->sta.beaconFrameBody[offset] = wd->sta.atimWindow ;
|
|
offset += 2 ;
|
|
|
|
/* ERP Information and Extended Supported Rates */
|
|
if ( wd->wfc.bIbssGMode
|
|
&& (wd->supportMode & (ZM_WIRELESS_MODE_24_54|ZM_WIRELESS_MODE_24_N)) )
|
|
{
|
|
/* ERP Information */
|
|
wd->erpElement = 0;
|
|
// ERP element id
|
|
wd->sta.beaconFrameBody[offset++] = ZM_WLAN_EID_ERP ;
|
|
|
|
// ERP length
|
|
wd->sta.beaconFrameBody[offset++] = 1 ;
|
|
|
|
// ERP information
|
|
wd->sta.beaconFrameBody[offset++] = wd->erpElement ;
|
|
|
|
/* Extended Supported Rates */
|
|
if ( (rateSet == ZM_RATE_SET_OFDM)&&((wd->gRate & 0xff) == 0) )
|
|
{
|
|
offset += 0 ;
|
|
}
|
|
else
|
|
{
|
|
len = 0 ;
|
|
|
|
// Extended Supported Rates element id
|
|
wd->sta.beaconFrameBody[offset++] = ZM_WLAN_EID_EXTENDED_RATE ;
|
|
|
|
// Extended Supported Rates length
|
|
lenOffset = offset++ ;
|
|
|
|
// Extended Supported Rates information
|
|
for (i=0; i<8; i++)
|
|
{
|
|
if ((wd->gRate & (0x1<<i)) == (0x1<<i))
|
|
{
|
|
wd->sta.beaconFrameBody[offset++] =
|
|
zg11gRateTbl[i]+((wd->gRateBasic & (0x1<<i))<<(7-i));
|
|
len++;
|
|
}
|
|
}
|
|
|
|
// extended support rate length
|
|
wd->sta.beaconFrameBody[lenOffset] = len ;
|
|
}
|
|
}
|
|
#endif
|
|
|
|
/* RSN : important information influence the result of creating an IBSS network */
|
|
if ( wd->sta.authMode == ZM_AUTH_MODE_WPA2PSK )
|
|
{
|
|
u8_t frameType = ZM_WLAN_FRAME_TYPE_AUTH ;
|
|
u8_t rsn[64]=
|
|
{
|
|
/* Element ID */
|
|
0x30,
|
|
/* Length */
|
|
0x14,
|
|
/* Version */
|
|
0x01, 0x00,
|
|
/* Group Cipher Suite, default=TKIP */
|
|
0x00, 0x0f, 0xac, 0x04,
|
|
/* Pairwise Cipher Suite Count */
|
|
0x01, 0x00,
|
|
/* Pairwise Cipher Suite, default=TKIP */
|
|
0x00, 0x0f, 0xac, 0x02,
|
|
/* Authentication and Key Management Suite Count */
|
|
0x01, 0x00,
|
|
/* Authentication type, default=PSK */
|
|
0x00, 0x0f, 0xac, 0x02,
|
|
/* RSN capability */
|
|
0x00, 0x00
|
|
};
|
|
|
|
/* Overwrite Group Cipher Suite by AP's setting */
|
|
zfMemoryCopy(rsn+4, zgWpa2AesOui, 4);
|
|
|
|
if ( wd->sta.wepStatus == ZM_ENCRYPTION_AES )
|
|
{
|
|
/* Overwrite Pairwise Cipher Suite by AES */
|
|
zfMemoryCopy(rsn+10, zgWpa2AesOui, 4);
|
|
}
|
|
|
|
// RSN element id
|
|
wd->sta.beaconFrameBody[offset++] = ZM_WLAN_EID_RSN_IE ;
|
|
|
|
// RSN length
|
|
wd->sta.beaconFrameBody[offset++] = rsn[1] ;
|
|
|
|
// RSN information
|
|
for(i=0; i<rsn[1]; i++)
|
|
wd->sta.beaconFrameBody[offset++] = rsn[i+2] ;
|
|
|
|
zfMemoryCopy(wd->sta.rsnIe, rsn, rsn[1]+2);
|
|
|
|
#ifdef ZM_ENABLE_IBSS_WPA2PSK
|
|
/* If not use RSNA , run traditional */
|
|
zmw_enter_critical_section(dev);
|
|
wd->sta.ibssWpa2Psk = 1;
|
|
zmw_leave_critical_section(dev);
|
|
#endif
|
|
}
|
|
|
|
#if 0
|
|
/* HT Capabilities Info */
|
|
{
|
|
u8_t OUI[3] = { 0x0 , 0x90 , 0x4C } ;
|
|
|
|
wd->sta.beaconFrameBody[offset++] = ZM_WLAN_EID_WPA_IE ;
|
|
|
|
wd->sta.beaconFrameBody[offset++] = wd->sta.HTCap.Data.Length + 4 ;
|
|
|
|
for (i = 0; i < 3; i++)
|
|
{
|
|
wd->sta.beaconFrameBody[offset++] = OUI[i] ;
|
|
}
|
|
|
|
wd->sta.beaconFrameBody[offset++] = wd->sta.HTCap.Data.ElementID ;
|
|
|
|
for (i = 0; i < 26; i++)
|
|
{
|
|
wd->sta.beaconFrameBody[offset++] = wd->sta.HTCap.Byte[i+2] ;
|
|
}
|
|
}
|
|
|
|
/* Extended HT Capabilities Info */
|
|
{
|
|
u8_t OUI[3] = { 0x0 , 0x90 , 0x4C } ;
|
|
|
|
wd->sta.beaconFrameBody[offset++] = ZM_WLAN_EID_WPA_IE ;
|
|
|
|
wd->sta.beaconFrameBody[offset++] = wd->sta.ExtHTCap.Data.Length + 4 ;
|
|
|
|
for (i = 0; i < 3; i++)
|
|
{
|
|
wd->sta.beaconFrameBody[offset++] = OUI[i] ;
|
|
}
|
|
|
|
wd->sta.beaconFrameBody[offset++] = wd->sta.ExtHTCap.Data.ElementID ;
|
|
|
|
for (i = 0; i < 22; i++)
|
|
{
|
|
wd->sta.beaconFrameBody[offset++] = wd->sta.ExtHTCap.Byte[i+2] ;
|
|
}
|
|
}
|
|
#endif
|
|
|
|
wd->sta.beaconFrameBodySize = offset ;
|
|
|
|
if (wd->sta.beaconFrameBodySize > ZM_CACHED_FRAMEBODY_SIZE)
|
|
{
|
|
wd->sta.beaconFrameBodySize = ZM_CACHED_FRAMEBODY_SIZE;
|
|
}
|
|
|
|
// 20070416 Let Create IBSS network could enter the zfwIbssPartnerNotify function
|
|
// bssNotFound = FALSE ;
|
|
|
|
printk("The capability info 1 = %02x\n", wd->sta.capability[0]) ;
|
|
printk("The capability info 2 = %02x\n", wd->sta.capability[1]) ;
|
|
for(k=0; k<wd->sta.beaconFrameBodySize; k++)
|
|
{
|
|
printk("%02x ", wd->sta.beaconFrameBody[k]) ;
|
|
}
|
|
#if 0
|
|
zmw_enter_critical_section(dev);
|
|
zfMemoryCopy(event.bssid, (u8_t *)bssid, 6);
|
|
zfMemoryCopy(event.peerMacAddr, (u8_t *)wd->macAddr, 6);
|
|
zmw_leave_critical_section(dev);
|
|
#endif
|
|
#endif
|
|
|
|
//zmw_enter_critical_section(dev);
|
|
//wd->sta.ibssPartnerStatus = ZM_IBSS_PARTNER_LOST;
|
|
//zmw_leave_critical_section(dev);
|
|
}
|
|
else
|
|
{
|
|
wd->sta.ibssBssIsCreator = 0;
|
|
}
|
|
|
|
connect_done:
|
|
zfHpEnableBeacon(dev, ZM_MODE_IBSS, wd->beaconInterval, wd->dtim, (u8_t)wd->sta.atimWindow);
|
|
zfStaSendBeacon(dev); // Refresh Beacon content for ZD1211B HalPlus
|
|
zfHpSetAtimWindow(dev, wd->sta.atimWindow);
|
|
|
|
// Start the IBSS timer to monitor for new stations
|
|
zmw_enter_critical_section(dev);
|
|
zfTimerSchedule(dev, ZM_EVENT_IBSS_MONITOR, ZM_TICK_IBSS_MONITOR);
|
|
zmw_leave_critical_section(dev);
|
|
|
|
|
|
if (wd->zfcbConnectNotify != NULL)
|
|
{
|
|
wd->zfcbConnectNotify(dev, ZM_STATUS_MEDIA_CONNECT, wd->sta.bssid);
|
|
}
|
|
zfChangeAdapterState(dev, ZM_STA_STATE_CONNECTED);
|
|
wd->sta.connPowerInHalfDbm = zfHpGetTransmitPower(dev);
|
|
|
|
#ifdef ZM_ENABLE_IBSS_DELAYED_JOIN_INDICATION
|
|
if ( !bssNotFound )
|
|
{
|
|
wd->sta.ibssDelayedInd = 1;
|
|
zfMemoryCopy((u8_t *)&wd->sta.ibssDelayedIndEvent, (u8_t *)&event, sizeof(struct zsPartnerNotifyEvent));
|
|
}
|
|
#else
|
|
if ( !bssNotFound )
|
|
{
|
|
if (wd->zfcbIbssPartnerNotify != NULL)
|
|
{
|
|
wd->zfcbIbssPartnerNotify(dev, 1, &event);
|
|
}
|
|
}
|
|
#endif
|
|
|
|
return;
|
|
|
|
retry_ibss:
|
|
zfChangeAdapterState(dev, ZM_STA_STATE_CONNECTING);
|
|
zfStaConnectFail(dev, ZM_STATUS_MEDIA_DISCONNECT_NOT_FOUND, wd->sta.bssid, 0);
|
|
return;
|
|
}
|
|
|
|
void zfStaProcessAtim(zdev_t* dev, zbuf_t* buf)
|
|
{
|
|
zmw_get_wlan_dev(dev);
|
|
|
|
zm_debug_msg0("Receiving Atim window notification");
|
|
|
|
wd->sta.recvAtim = 1;
|
|
}
|
|
|
|
static struct zsBssInfo* zfInfraFindAPToConnect(zdev_t* dev,
|
|
struct zsBssInfo* candidateBss)
|
|
{
|
|
struct zsBssInfo* pBssInfo;
|
|
struct zsBssInfo* pNowBssInfo=NULL;
|
|
u16_t i;
|
|
u16_t ret, apWepStatus;
|
|
u32_t k;
|
|
u32_t channelFlags;
|
|
|
|
zmw_get_wlan_dev(dev);
|
|
zmw_declare_for_critical_section();
|
|
|
|
zmw_enter_critical_section(dev);
|
|
|
|
pBssInfo = wd->sta.bssList.head;
|
|
|
|
for(i=0; i<wd->sta.bssList.bssCount; i++)
|
|
{
|
|
if ( pBssInfo->capability[0] & ZM_BIT_4 )
|
|
{
|
|
apWepStatus = ZM_ENCRYPTION_WEP_ENABLED;
|
|
}
|
|
else
|
|
{
|
|
apWepStatus = ZM_ENCRYPTION_WEP_DISABLED;
|
|
}
|
|
|
|
if ( ((zfMemoryIsEqual(&(pBssInfo->ssid[2]), wd->sta.ssid,
|
|
wd->sta.ssidLen))&&
|
|
(wd->sta.ssidLen == pBssInfo->ssid[1]))||
|
|
((wd->sta.ssidLen == 0)&&
|
|
/* connect to any BSS: AP's ans STA's WEP status must match */
|
|
(wd->sta.wepStatus == apWepStatus )&&
|
|
(pBssInfo->securityType != ZM_SECURITY_TYPE_WPA) ))
|
|
{
|
|
if ( wd->sta.ssidLen == 0 )
|
|
{
|
|
zm_debug_msg0("ANY BSS found");
|
|
}
|
|
|
|
if ( ((wd->sta.wepStatus == ZM_ENCRYPTION_WEP_DISABLED && apWepStatus == ZM_ENCRYPTION_WEP_ENABLED) ||
|
|
(wd->sta.wepStatus == ZM_ENCRYPTION_WEP_ENABLED &&
|
|
(apWepStatus == ZM_ENCRYPTION_WEP_DISABLED && wd->sta.dropUnencryptedPkts == 1))) &&
|
|
(wd->sta.authMode >= ZM_AUTH_MODE_OPEN && wd->sta.authMode <= ZM_AUTH_MODE_AUTO) )
|
|
{
|
|
zm_debug_msg0("Privacy policy is inconsistent");
|
|
pBssInfo = pBssInfo->next;
|
|
continue;
|
|
}
|
|
|
|
/* for WPA negative test */
|
|
if ( !zfCheckAuthentication(dev, pBssInfo) )
|
|
{
|
|
pBssInfo = pBssInfo->next;
|
|
continue;
|
|
}
|
|
|
|
/* Check bssid */
|
|
if (wd->sta.bDesiredBssid == TRUE)
|
|
{
|
|
for (k=0; k<6; k++)
|
|
{
|
|
if (wd->sta.desiredBssid[k] != pBssInfo->bssid[k])
|
|
{
|
|
zm_msg0_mm(ZM_LV_1, "desired bssid not matched 1");
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (k != 6)
|
|
{
|
|
zm_msg0_mm(ZM_LV_1, "desired bssid not matched 2");
|
|
pBssInfo = pBssInfo->next;
|
|
continue;
|
|
}
|
|
}
|
|
|
|
/* Check support mode */
|
|
if (pBssInfo->frequency > 3000) {
|
|
if ( (pBssInfo->EnableHT == 1)
|
|
|| (pBssInfo->apCap & ZM_All11N_AP) ) //11n AP
|
|
{
|
|
channelFlags = CHANNEL_A_HT;
|
|
if (pBssInfo->enableHT40 == 1) {
|
|
channelFlags |= CHANNEL_HT40;
|
|
}
|
|
} else {
|
|
channelFlags = CHANNEL_A;
|
|
}
|
|
} else {
|
|
if ( (pBssInfo->EnableHT == 1)
|
|
|| (pBssInfo->apCap & ZM_All11N_AP) ) //11n AP
|
|
{
|
|
channelFlags = CHANNEL_G_HT;
|
|
if(pBssInfo->enableHT40 == 1) {
|
|
channelFlags |= CHANNEL_HT40;
|
|
}
|
|
} else {
|
|
if (pBssInfo->extSupportedRates[1] == 0) {
|
|
channelFlags = CHANNEL_B;
|
|
} else {
|
|
channelFlags = CHANNEL_G;
|
|
}
|
|
}
|
|
}
|
|
|
|
if ( ((channelFlags == CHANNEL_B) && (wd->connectMode & ZM_BIT_0))
|
|
|| ((channelFlags == CHANNEL_G) && (wd->connectMode & ZM_BIT_1))
|
|
|| ((channelFlags == CHANNEL_A) && (wd->connectMode & ZM_BIT_2))
|
|
|| ((channelFlags & CHANNEL_HT20) && (wd->connectMode & ZM_BIT_3)) )
|
|
{
|
|
pBssInfo = pBssInfo->next;
|
|
continue;
|
|
}
|
|
|
|
/* Skip if AP in blocking list */
|
|
if ((ret = zfStaIsApInBlockingList(dev, pBssInfo->bssid)) == TRUE)
|
|
{
|
|
zm_msg0_mm(ZM_LV_0, "Candidate AP in blocking List, skip if there's stilla choice!");
|
|
pNowBssInfo = pBssInfo;
|
|
pBssInfo = pBssInfo->next;
|
|
continue;
|
|
}
|
|
|
|
if ( pBssInfo->capability[0] & ZM_BIT_0 ) // check if infra-BSS
|
|
{
|
|
pNowBssInfo = pBssInfo;
|
|
wd->sta.apWmeCapability = pBssInfo->wmeSupport;
|
|
|
|
|
|
goto done;
|
|
}
|
|
}
|
|
|
|
pBssInfo = pBssInfo->next;
|
|
}
|
|
|
|
done:
|
|
if (pNowBssInfo != NULL)
|
|
{
|
|
zfwMemoryCopy((void*)candidateBss, (void*)pNowBssInfo, sizeof(struct zsBssInfo));
|
|
pNowBssInfo = candidateBss;
|
|
}
|
|
|
|
zmw_leave_critical_section(dev);
|
|
|
|
return pNowBssInfo;
|
|
}
|
|
|
|
|
|
void zfInfraConnectNetwork(zdev_t* dev)
|
|
{
|
|
struct zsBssInfo* pBssInfo;
|
|
struct zsBssInfo* pNowBssInfo=NULL;
|
|
struct zsBssInfo candidateBss;
|
|
//u16_t i, j=100, quality=10000;
|
|
//u8_t ret=FALSE, apWepStatus;
|
|
u8_t ret=FALSE;
|
|
u16_t k;
|
|
u8_t density = ZM_MPDU_DENSITY_NONE;
|
|
|
|
zmw_get_wlan_dev(dev);
|
|
zmw_declare_for_critical_section();
|
|
|
|
/* Reset bssNotFoundCount for Ad-Hoc:IBSS */
|
|
/* Need review : IbssConn -> InfraConn -> IbssConn etc, flag/counter reset? */
|
|
zmw_enter_critical_section(dev);
|
|
wd->sta.bssNotFoundCount = 0;
|
|
zmw_leave_critical_section(dev);
|
|
|
|
/* Set TxQs CWMIN, CWMAX, AIFS and TXO to WME STA default. */
|
|
zfUpdateDefaultQosParameter(dev, 0);
|
|
|
|
zfStaRefreshBlockList(dev, 0);
|
|
|
|
/* change state to CONNECTING and stop the channel scanning */
|
|
zfChangeAdapterState(dev, ZM_STA_STATE_CONNECTING);
|
|
zfPowerSavingMgrWakeup(dev);
|
|
|
|
wd->sta.wmeConnected = 0;
|
|
wd->sta.psMgr.tempWakeUp = 0;
|
|
wd->sta.qosInfo = 0;
|
|
zfQueueFlush(dev, wd->sta.uapsdQ);
|
|
|
|
wd->sta.connectState = ZM_STA_CONN_STATE_NONE;
|
|
|
|
//Reorder BssList by RSSI--CWYang(+)
|
|
zfBssInfoReorderList(dev);
|
|
|
|
pNowBssInfo = zfInfraFindAPToConnect(dev, &candidateBss);
|
|
|
|
if (wd->sta.SWEncryptEnable != 0)
|
|
{
|
|
if (wd->sta.bSafeMode == 0)
|
|
{
|
|
zfStaDisableSWEncryption(dev);//Quickly reboot
|
|
}
|
|
}
|
|
if ( pNowBssInfo != NULL )
|
|
{
|
|
//zm_assert(pNowBssInfo != NULL);
|
|
|
|
pBssInfo = pNowBssInfo;
|
|
wd->sta.ssidLen = pBssInfo->ssid[1];
|
|
zfMemoryCopy(wd->sta.ssid, &(pBssInfo->ssid[2]), pBssInfo->ssid[1]);
|
|
wd->frequency = pBssInfo->frequency;
|
|
//wd->sta.flagFreqChanging = 1;
|
|
|
|
//zfCoreSetFrequency(dev, wd->frequency);
|
|
zfUpdateBssid(dev, pBssInfo->bssid);
|
|
zfResetSupportRate(dev, ZM_DEFAULT_SUPPORT_RATE_ZERO);
|
|
zfUpdateSupportRate(dev, pBssInfo->supportedRates);
|
|
zfUpdateSupportRate(dev, pBssInfo->extSupportedRates);
|
|
|
|
wd->beaconInterval = pBssInfo->beaconInterval[0] +
|
|
(((u16_t) pBssInfo->beaconInterval[1]) << 8);
|
|
if (wd->beaconInterval == 0)
|
|
{
|
|
wd->beaconInterval = 100;
|
|
}
|
|
|
|
/* ESS bit on */
|
|
wd->sta.capability[0] |= ZM_BIT_0;
|
|
/* IBSS bit off */
|
|
wd->sta.capability[0] &= ~ZM_BIT_1;
|
|
|
|
/* 11n AP flag */
|
|
wd->sta.EnableHT = pBssInfo->EnableHT;
|
|
wd->sta.SG40 = pBssInfo->SG40;
|
|
#ifdef ZM_ENABLE_CENC
|
|
if ( pBssInfo->securityType == ZM_SECURITY_TYPE_CENC )
|
|
{
|
|
wd->sta.wmeEnabled = 0; //Disable WMM in CENC
|
|
cencInit(dev);
|
|
cencSetCENCMode(dev, NdisCENC_PSK);
|
|
wd->sta.wpaState = ZM_STA_WPA_STATE_INIT;
|
|
/* CENC */
|
|
if ( pBssInfo->cencIe[1] != 0 )
|
|
{
|
|
//wd->sta.wepStatus = ZM_ENCRYPTION_CENC;
|
|
//wd->sta.encryMode = ZM_CENC;
|
|
zfwCencHandleBeaconProbrespon(dev, (u8_t *)&pBssInfo->cencIe,
|
|
(u8_t *)&pBssInfo->ssid, (u8_t *)&pBssInfo->macaddr);
|
|
zfMemoryCopy(wd->sta.cencIe, pBssInfo->cencIe,
|
|
pBssInfo->cencIe[1]+2);
|
|
}
|
|
else
|
|
{
|
|
wd->sta.cencIe[1] = 0;
|
|
}
|
|
}
|
|
#endif //ZM_ENABLE_CENC
|
|
if ( pBssInfo->securityType == ZM_SECURITY_TYPE_WPA )
|
|
{
|
|
wd->sta.wpaState = ZM_STA_WPA_STATE_INIT;
|
|
|
|
if ( wd->sta.wepStatus == ZM_ENCRYPTION_TKIP )
|
|
{
|
|
wd->sta.encryMode = ZM_TKIP;
|
|
|
|
/* Turn on software encryption/decryption for TKIP */
|
|
if (wd->sta.EnableHT == 1)
|
|
{
|
|
zfStaEnableSWEncryption(dev, (ZM_SW_TKIP_ENCRY_EN|ZM_SW_TKIP_DECRY_EN));
|
|
}
|
|
|
|
/* Do not support TKIP in 11n mode */
|
|
//wd->sta.EnableHT = 0;
|
|
//pBssInfo->enableHT40 = 0;
|
|
}
|
|
else if ( wd->sta.wepStatus == ZM_ENCRYPTION_AES )
|
|
{
|
|
wd->sta.encryMode = ZM_AES;
|
|
|
|
/* If AP supports HT mode */
|
|
if (wd->sta.EnableHT)
|
|
{
|
|
/* Set MPDU density to 8 us*/
|
|
density = ZM_MPDU_DENSITY_8US;
|
|
}
|
|
}
|
|
|
|
if ( pBssInfo->wpaIe[1] != 0 )
|
|
{
|
|
zfMemoryCopy(wd->sta.wpaIe, pBssInfo->wpaIe,
|
|
pBssInfo->wpaIe[1]+2);
|
|
}
|
|
else
|
|
{
|
|
wd->sta.wpaIe[1] = 0;
|
|
}
|
|
|
|
if ( pBssInfo->rsnIe[1] != 0 )
|
|
{
|
|
zfMemoryCopy(wd->sta.rsnIe, pBssInfo->rsnIe,
|
|
pBssInfo->rsnIe[1]+2);
|
|
}
|
|
else
|
|
{
|
|
wd->sta.rsnIe[1] = 0;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/* check preamble bit */
|
|
wd->preambleTypeInUsed = wd->preambleType;
|
|
if ( wd->preambleTypeInUsed == ZM_PREAMBLE_TYPE_AUTO )
|
|
{
|
|
if (pBssInfo->capability[0] & ZM_BIT_5)
|
|
{
|
|
wd->preambleTypeInUsed = ZM_PREAMBLE_TYPE_SHORT;
|
|
}
|
|
else
|
|
{
|
|
wd->preambleTypeInUsed = ZM_PREAMBLE_TYPE_LONG;
|
|
}
|
|
}
|
|
|
|
if (wd->preambleTypeInUsed == ZM_PREAMBLE_TYPE_LONG)
|
|
{
|
|
wd->sta.capability[0] &= ~ZM_BIT_5;
|
|
}
|
|
else
|
|
{
|
|
wd->sta.capability[0] |= ZM_BIT_5;
|
|
}
|
|
|
|
/* check 802.11n 40MHz Setting */
|
|
if ((pBssInfo->enableHT40 == 1) &&
|
|
((pBssInfo->extChOffset == 1) || (pBssInfo->extChOffset == 3)))
|
|
{
|
|
wd->BandWidth40 = pBssInfo->enableHT40;
|
|
wd->ExtOffset = pBssInfo->extChOffset;
|
|
}
|
|
else
|
|
{
|
|
wd->BandWidth40 = 0;
|
|
wd->ExtOffset = 0;
|
|
}
|
|
|
|
/* check 802.11H support bit */
|
|
|
|
/* check Owl Ap */
|
|
if ( pBssInfo->athOwlAp & ZM_BIT_0 )
|
|
{
|
|
/* In this function, FW retry will be enable, ZM_MAC_REG_RETRY_MAX
|
|
will be set to 0.
|
|
*/
|
|
zfHpDisableHwRetry(dev);
|
|
wd->sta.athOwlAp = 1;
|
|
/* Set MPDU density to 8 us*/
|
|
density = ZM_MPDU_DENSITY_8US;
|
|
}
|
|
else
|
|
{
|
|
/* In this function, FW retry will be disable, ZM_MAC_REG_RETRY_MAX
|
|
will be set to 3.
|
|
*/
|
|
zfHpEnableHwRetry(dev);
|
|
wd->sta.athOwlAp = 0;
|
|
}
|
|
wd->reorder = 1;
|
|
|
|
/* Set MPDU density */
|
|
zfHpSetMPDUDensity(dev, density);
|
|
|
|
/* check short slot time bit */
|
|
if ( pBssInfo->capability[1] & ZM_BIT_2 )
|
|
{
|
|
wd->sta.capability[1] |= ZM_BIT_2;
|
|
}
|
|
|
|
if ( pBssInfo->erp & ZM_BIT_1 )
|
|
{
|
|
//zm_debug_msg0("protection mode on");
|
|
wd->sta.bProtectionMode = TRUE;
|
|
zfHpSetSlotTime(dev, 0);
|
|
}
|
|
else
|
|
{
|
|
//zm_debug_msg0("protection mode off");
|
|
wd->sta.bProtectionMode = FALSE;
|
|
zfHpSetSlotTime(dev, 1);
|
|
}
|
|
|
|
if (pBssInfo->marvelAp == 1)
|
|
{
|
|
wd->sta.enableDrvBA = 0;
|
|
/*
|
|
* 8701 : NetGear 3500 (MARVELL)
|
|
* Downlink issue : set slottime to 20.
|
|
*/
|
|
zfHpSetSlotTimeRegister(dev, 0);
|
|
}
|
|
else
|
|
{
|
|
wd->sta.enableDrvBA = 1;
|
|
|
|
/*
|
|
* This is not good for here do reset slot time.
|
|
* I think it should reset when leave MARVELL ap
|
|
* or enter disconnect state etc.
|
|
*/
|
|
zfHpSetSlotTimeRegister(dev, 1);
|
|
}
|
|
|
|
//Store probe response frame body, for VISTA only
|
|
wd->sta.beaconFrameBodySize = pBssInfo->frameBodysize + 12;
|
|
if (wd->sta.beaconFrameBodySize > ZM_CACHED_FRAMEBODY_SIZE)
|
|
{
|
|
wd->sta.beaconFrameBodySize = ZM_CACHED_FRAMEBODY_SIZE;
|
|
}
|
|
for (k=0; k<8; k++)
|
|
{
|
|
wd->sta.beaconFrameBody[k] = pBssInfo->timeStamp[k];
|
|
}
|
|
wd->sta.beaconFrameBody[8] = pBssInfo->beaconInterval[0];
|
|
wd->sta.beaconFrameBody[9] = pBssInfo->beaconInterval[1];
|
|
wd->sta.beaconFrameBody[10] = pBssInfo->capability[0];
|
|
wd->sta.beaconFrameBody[11] = pBssInfo->capability[1];
|
|
for (k=0; k<(wd->sta.beaconFrameBodySize - 12); k++)
|
|
{
|
|
wd->sta.beaconFrameBody[k+12] = pBssInfo->frameBody[k];
|
|
}
|
|
|
|
if ( ( pBssInfo->capability[0] & ZM_BIT_4 )&&
|
|
(( wd->sta.authMode == ZM_AUTH_MODE_OPEN )||
|
|
( wd->sta.authMode == ZM_AUTH_MODE_SHARED_KEY)||
|
|
(wd->sta.authMode == ZM_AUTH_MODE_AUTO)) )
|
|
{ /* privacy enabled */
|
|
|
|
if ( wd->sta.wepStatus == ZM_ENCRYPTION_WEP_DISABLED )
|
|
{
|
|
zm_debug_msg0("Adapter is no WEP, try to connect to WEP AP");
|
|
ret = FALSE;
|
|
}
|
|
|
|
/* Do not support WEP in 11n mode */
|
|
if ( wd->sta.wepStatus == ZM_ENCRYPTION_WEP_ENABLED )
|
|
{
|
|
/* Turn on software encryption/decryption for WEP */
|
|
if (wd->sta.EnableHT == 1)
|
|
{
|
|
zfStaEnableSWEncryption(dev, (ZM_SW_WEP_ENCRY_EN|ZM_SW_WEP_DECRY_EN));
|
|
}
|
|
|
|
//wd->sta.EnableHT = 0;
|
|
//wd->BandWidth40 = 0;
|
|
//wd->ExtOffset = 0;
|
|
}
|
|
|
|
wd->sta.capability[0] |= ZM_BIT_4;
|
|
|
|
if ( wd->sta.authMode == ZM_AUTH_MODE_AUTO )
|
|
{ /* Try to use open and shared-key authehtication alternatively */
|
|
if ( (wd->sta.connectTimeoutCount % 2) == 0 )
|
|
wd->sta.bIsSharedKey = 0;
|
|
else
|
|
wd->sta.bIsSharedKey = 1;
|
|
}
|
|
else if ( wd->sta.authMode != ZM_AUTH_MODE_SHARED_KEY )
|
|
{ /* open or auto */
|
|
//zfStaStartConnect(dev, 0);
|
|
wd->sta.bIsSharedKey = 0;
|
|
}
|
|
else if ( wd->sta.authMode != ZM_AUTH_MODE_OPEN )
|
|
{ /* shared key */
|
|
//zfStaStartConnect(dev, 1) ;
|
|
wd->sta.bIsSharedKey = 1;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if ( (pBssInfo->securityType == ZM_SECURITY_TYPE_WPA)||
|
|
(pBssInfo->capability[0] & ZM_BIT_4) )
|
|
{
|
|
wd->sta.capability[0] |= ZM_BIT_4;
|
|
/* initialize WPA related parameters */
|
|
}
|
|
else
|
|
{
|
|
wd->sta.capability[0] &= (~ZM_BIT_4);
|
|
}
|
|
|
|
/* authentication with open system */
|
|
//zfStaStartConnect(dev, 0);
|
|
wd->sta.bIsSharedKey = 0;
|
|
}
|
|
|
|
/* Improve WEP/TKIP performace with HT AP, detail information please look bug#32495 */
|
|
/*
|
|
if ( (pBssInfo->broadcomHTAp == 1)
|
|
&& (wd->sta.SWEncryptEnable != 0) )
|
|
{
|
|
zfHpSetTTSIFSTime(dev, 0xa);
|
|
}
|
|
else
|
|
{
|
|
zfHpSetTTSIFSTime(dev, 0x8);
|
|
}
|
|
*/
|
|
}
|
|
else
|
|
{
|
|
zm_debug_msg0("Desired SSID not found");
|
|
goto zlConnectFailed;
|
|
}
|
|
|
|
|
|
zfCoreSetFrequencyV2(dev, wd->frequency, zfStaStartConnectCb);
|
|
return;
|
|
|
|
zlConnectFailed:
|
|
zfStaConnectFail(dev, ZM_STATUS_MEDIA_DISCONNECT_NOT_FOUND, wd->sta.bssid, 0);
|
|
return;
|
|
}
|
|
|
|
u8_t zfCheckWPAAuth(zdev_t* dev, struct zsBssInfo* pBssInfo)
|
|
{
|
|
u8_t ret=TRUE;
|
|
u8_t pmkCount;
|
|
u8_t i;
|
|
u16_t encAlgoType = 0;
|
|
|
|
zmw_get_wlan_dev(dev);
|
|
|
|
if ( wd->sta.wepStatus == ZM_ENCRYPTION_TKIP )
|
|
{
|
|
encAlgoType = ZM_TKIP;
|
|
}
|
|
else if ( wd->sta.wepStatus == ZM_ENCRYPTION_AES )
|
|
{
|
|
encAlgoType = ZM_AES;
|
|
}
|
|
|
|
switch(wd->sta.authMode)
|
|
{
|
|
case ZM_AUTH_MODE_WPA:
|
|
case ZM_AUTH_MODE_WPAPSK:
|
|
if ( pBssInfo->wpaIe[1] == 0 )
|
|
{
|
|
ret = FALSE;
|
|
break;
|
|
}
|
|
|
|
pmkCount = pBssInfo->wpaIe[12];
|
|
for(i=0; i < pmkCount; i++)
|
|
{
|
|
if ( pBssInfo->wpaIe[17 + 4*i] == encAlgoType )
|
|
{
|
|
ret = TRUE;
|
|
goto done;
|
|
}
|
|
}
|
|
|
|
ret = FALSE;
|
|
break;
|
|
|
|
case ZM_AUTH_MODE_WPA2:
|
|
case ZM_AUTH_MODE_WPA2PSK:
|
|
if ( pBssInfo->rsnIe[1] == 0 )
|
|
{
|
|
ret = FALSE;
|
|
break;
|
|
}
|
|
|
|
pmkCount = pBssInfo->rsnIe[8];
|
|
for(i=0; i < pmkCount; i++)
|
|
{
|
|
if ( pBssInfo->rsnIe[13 + 4*i] == encAlgoType )
|
|
{
|
|
ret = TRUE;
|
|
goto done;
|
|
}
|
|
}
|
|
|
|
ret = FALSE;
|
|
break;
|
|
}
|
|
|
|
done:
|
|
return ret;
|
|
}
|
|
|
|
u8_t zfCheckAuthentication(zdev_t* dev, struct zsBssInfo* pBssInfo)
|
|
{
|
|
u8_t ret=TRUE;
|
|
u16_t encAlgoType;
|
|
u16_t UnicastCipherNum;
|
|
|
|
zmw_get_wlan_dev(dev);
|
|
|
|
/* Connecting to ANY has been checked */
|
|
if ( wd->sta.ssidLen == 0 )
|
|
{
|
|
return ret;
|
|
}
|
|
|
|
|
|
switch(wd->sta.authMode)
|
|
//switch(wd->ws.authMode)//Quickly reboot
|
|
{
|
|
case ZM_AUTH_MODE_WPA_AUTO:
|
|
case ZM_AUTH_MODE_WPAPSK_AUTO:
|
|
encAlgoType = 0;
|
|
if(pBssInfo->rsnIe[1] != 0)
|
|
{
|
|
UnicastCipherNum = (pBssInfo->rsnIe[8]) +
|
|
(pBssInfo->rsnIe[9] << 8);
|
|
|
|
/* If there is only one unicast cipher */
|
|
if (UnicastCipherNum == 1)
|
|
{
|
|
encAlgoType = pBssInfo->rsnIe[13];
|
|
//encAlgoType = pBssInfo->rsnIe[7];
|
|
}
|
|
else
|
|
{
|
|
u16_t ii;
|
|
u16_t desiredCipher = 0;
|
|
u16_t IEOffSet = 13;
|
|
|
|
/* Enumerate all the supported unicast cipher */
|
|
for (ii = 0; ii < UnicastCipherNum; ii++)
|
|
{
|
|
if (pBssInfo->rsnIe[IEOffSet+ii*4] > desiredCipher)
|
|
{
|
|
desiredCipher = pBssInfo->rsnIe[IEOffSet+ii*4];
|
|
}
|
|
}
|
|
|
|
encAlgoType = desiredCipher;
|
|
}
|
|
|
|
if ( encAlgoType == 0x02 )
|
|
{
|
|
wd->sta.wepStatus = ZM_ENCRYPTION_TKIP;
|
|
|
|
if ( wd->sta.authMode == ZM_AUTH_MODE_WPA_AUTO )
|
|
{
|
|
wd->sta.currentAuthMode = ZM_AUTH_MODE_WPA2;
|
|
}
|
|
else //ZM_AUTH_MODE_WPAPSK_AUTO
|
|
{
|
|
wd->sta.currentAuthMode = ZM_AUTH_MODE_WPA2PSK;
|
|
}
|
|
}
|
|
else if ( encAlgoType == 0x04 )
|
|
{
|
|
wd->sta.wepStatus = ZM_ENCRYPTION_AES;
|
|
|
|
if ( wd->sta.authMode == ZM_AUTH_MODE_WPA_AUTO )
|
|
{
|
|
wd->sta.currentAuthMode = ZM_AUTH_MODE_WPA2;
|
|
}
|
|
else //ZM_AUTH_MODE_WPAPSK_AUTO
|
|
{
|
|
wd->sta.currentAuthMode = ZM_AUTH_MODE_WPA2PSK;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
ret = FALSE;
|
|
}
|
|
}
|
|
else if(pBssInfo->wpaIe[1] != 0)
|
|
{
|
|
UnicastCipherNum = (pBssInfo->wpaIe[12]) +
|
|
(pBssInfo->wpaIe[13] << 8);
|
|
|
|
/* If there is only one unicast cipher */
|
|
if (UnicastCipherNum == 1)
|
|
{
|
|
encAlgoType = pBssInfo->wpaIe[17];
|
|
//encAlgoType = pBssInfo->wpaIe[11];
|
|
}
|
|
else
|
|
{
|
|
u16_t ii;
|
|
u16_t desiredCipher = 0;
|
|
u16_t IEOffSet = 17;
|
|
|
|
/* Enumerate all the supported unicast cipher */
|
|
for (ii = 0; ii < UnicastCipherNum; ii++)
|
|
{
|
|
if (pBssInfo->wpaIe[IEOffSet+ii*4] > desiredCipher)
|
|
{
|
|
desiredCipher = pBssInfo->wpaIe[IEOffSet+ii*4];
|
|
}
|
|
}
|
|
|
|
encAlgoType = desiredCipher;
|
|
}
|
|
|
|
if ( encAlgoType == 0x02 )
|
|
{
|
|
wd->sta.wepStatus = ZM_ENCRYPTION_TKIP;
|
|
|
|
if ( wd->sta.authMode == ZM_AUTH_MODE_WPA_AUTO )
|
|
{
|
|
wd->sta.currentAuthMode = ZM_AUTH_MODE_WPA;
|
|
}
|
|
else //ZM_AUTH_MODE_WPAPSK_AUTO
|
|
{
|
|
wd->sta.currentAuthMode = ZM_AUTH_MODE_WPAPSK;
|
|
}
|
|
}
|
|
else if ( encAlgoType == 0x04 )
|
|
{
|
|
wd->sta.wepStatus = ZM_ENCRYPTION_AES;
|
|
|
|
if ( wd->sta.authMode == ZM_AUTH_MODE_WPA_AUTO )
|
|
{
|
|
wd->sta.currentAuthMode = ZM_AUTH_MODE_WPA;
|
|
}
|
|
else //ZM_AUTH_MODE_WPAPSK_AUTO
|
|
{
|
|
wd->sta.currentAuthMode = ZM_AUTH_MODE_WPAPSK;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
ret = FALSE;
|
|
}
|
|
|
|
|
|
}
|
|
else
|
|
{
|
|
ret = FALSE;
|
|
}
|
|
|
|
break;
|
|
|
|
case ZM_AUTH_MODE_WPA:
|
|
case ZM_AUTH_MODE_WPAPSK:
|
|
case ZM_AUTH_MODE_WPA_NONE:
|
|
case ZM_AUTH_MODE_WPA2:
|
|
case ZM_AUTH_MODE_WPA2PSK:
|
|
{
|
|
if ( pBssInfo->securityType != ZM_SECURITY_TYPE_WPA )
|
|
{
|
|
ret = FALSE;
|
|
}
|
|
|
|
ret = zfCheckWPAAuth(dev, pBssInfo);
|
|
}
|
|
break;
|
|
|
|
case ZM_AUTH_MODE_OPEN:
|
|
case ZM_AUTH_MODE_SHARED_KEY:
|
|
case ZM_AUTH_MODE_AUTO:
|
|
{
|
|
if ( pBssInfo->wscIe[1] )
|
|
{
|
|
// If the AP is a Jumpstart AP, it's ok!! Ray
|
|
break;
|
|
}
|
|
else if ( pBssInfo->securityType == ZM_SECURITY_TYPE_WPA )
|
|
{
|
|
ret = FALSE;
|
|
}
|
|
}
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
u8_t zfStaIsConnected(zdev_t* dev)
|
|
{
|
|
zmw_get_wlan_dev(dev);
|
|
|
|
if ( wd->sta.adapterState == ZM_STA_STATE_CONNECTED )
|
|
{
|
|
return TRUE;
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
u8_t zfStaIsConnecting(zdev_t* dev)
|
|
{
|
|
zmw_get_wlan_dev(dev);
|
|
|
|
if ( wd->sta.adapterState == ZM_STA_STATE_CONNECTING )
|
|
{
|
|
return TRUE;
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
u8_t zfStaIsDisconnect(zdev_t* dev)
|
|
{
|
|
zmw_get_wlan_dev(dev);
|
|
|
|
if ( wd->sta.adapterState == ZM_STA_STATE_DISCONNECT )
|
|
{
|
|
return TRUE;
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
u8_t zfChangeAdapterState(zdev_t* dev, u8_t newState)
|
|
{
|
|
u8_t ret = TRUE;
|
|
|
|
zmw_get_wlan_dev(dev);
|
|
|
|
zmw_declare_for_critical_section();
|
|
|
|
//if ( newState == wd->sta.adapterState )
|
|
//{
|
|
// return FALSE;
|
|
//}
|
|
|
|
switch(newState)
|
|
{
|
|
case ZM_STA_STATE_DISCONNECT:
|
|
zfResetSupportRate(dev, ZM_DEFAULT_SUPPORT_RATE_DISCONNECT);
|
|
|
|
#if 1
|
|
zfScanMgrScanStop(dev, ZM_SCAN_MGR_SCAN_INTERNAL);
|
|
#else
|
|
if ( wd->sta.bChannelScan )
|
|
{
|
|
/* stop the action of channel scanning */
|
|
wd->sta.bChannelScan = FALSE;
|
|
ret = TRUE;
|
|
break;
|
|
}
|
|
#endif
|
|
|
|
break;
|
|
case ZM_STA_STATE_CONNECTING:
|
|
#if 1
|
|
zfScanMgrScanStop(dev, ZM_SCAN_MGR_SCAN_INTERNAL);
|
|
#else
|
|
if ( wd->sta.bChannelScan )
|
|
{
|
|
/* stop the action of channel scanning */
|
|
wd->sta.bChannelScan = FALSE;
|
|
ret = TRUE;
|
|
break;
|
|
}
|
|
#endif
|
|
|
|
break;
|
|
case ZM_STA_STATE_CONNECTED:
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
//if ( ret )
|
|
//{
|
|
zmw_enter_critical_section(dev);
|
|
wd->sta.adapterState = newState;
|
|
zmw_leave_critical_section(dev);
|
|
|
|
zm_debug_msg1("change adapter state = ", newState);
|
|
//}
|
|
|
|
return ret;
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* */
|
|
/* FUNCTION DESCRIPTION zfStaMmAddIeSsid */
|
|
/* Add information element SSID to buffer. */
|
|
/* */
|
|
/* INPUTS */
|
|
/* dev : device pointer */
|
|
/* buf : buffer to add information element */
|
|
/* offset : add information element from this offset */
|
|
/* */
|
|
/* OUTPUTS */
|
|
/* buffer offset after adding information element */
|
|
/* */
|
|
/* AUTHOR */
|
|
/* Ji-Huang Lee ZyDAS Technology Corporation 2005.11 */
|
|
/* */
|
|
/************************************************************************/
|
|
u16_t zfStaAddIeSsid(zdev_t* dev, zbuf_t* buf, u16_t offset)
|
|
{
|
|
u16_t i;
|
|
|
|
zmw_get_wlan_dev(dev);
|
|
|
|
/* Element ID */
|
|
zmw_tx_buf_writeb(dev, buf, offset++, ZM_WLAN_EID_SSID);
|
|
|
|
/* Element Length */
|
|
zmw_tx_buf_writeb(dev, buf, offset++, wd->sta.ssidLen);
|
|
|
|
/* Information : SSID */
|
|
for (i=0; i<wd->sta.ssidLen; i++)
|
|
{
|
|
zmw_tx_buf_writeb(dev, buf, offset++, wd->sta.ssid[i]);
|
|
}
|
|
|
|
return offset;
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* */
|
|
/* FUNCTION DESCRIPTION zfStaMmAddIeWpa */
|
|
/* Add information element SSID to buffer. */
|
|
/* */
|
|
/* INPUTS */
|
|
/* dev : device pointer */
|
|
/* buf : buffer to add information element */
|
|
/* offset : add information element from this offset */
|
|
/* */
|
|
/* OUTPUTS */
|
|
/* buffer offset after adding information element */
|
|
/* */
|
|
/* AUTHOR */
|
|
/* Ji-Huang Lee ZyDAS Technology Corporation 2006.01 */
|
|
/* */
|
|
/************************************************************************/
|
|
u16_t zfStaAddIeWpaRsn(zdev_t* dev, zbuf_t* buf, u16_t offset, u8_t frameType)
|
|
{
|
|
u32_t i;
|
|
u8_t ssn[64]={
|
|
/* Element ID */
|
|
0xdd,
|
|
/* Length */
|
|
0x18,
|
|
/* OUI type */
|
|
0x00, 0x50, 0xf2, 0x01,
|
|
/* Version */
|
|
0x01, 0x00,
|
|
/* Group Cipher Suite, default=TKIP */
|
|
0x00, 0x50, 0xf2, 0x02,
|
|
/* Pairwise Cipher Suite Count */
|
|
0x01, 0x00,
|
|
/* Pairwise Cipher Suite, default=TKIP */
|
|
0x00, 0x50, 0xf2, 0x02,
|
|
/* Authentication and Key Management Suite Count */
|
|
0x01, 0x00,
|
|
/* Authentication type, default=PSK */
|
|
0x00, 0x50, 0xf2, 0x02,
|
|
/* WPA capability */
|
|
0x00, 0x00
|
|
};
|
|
|
|
u8_t rsn[64]={
|
|
/* Element ID */
|
|
0x30,
|
|
/* Length */
|
|
0x14,
|
|
/* Version */
|
|
0x01, 0x00,
|
|
/* Group Cipher Suite, default=TKIP */
|
|
0x00, 0x0f, 0xac, 0x02,
|
|
/* Pairwise Cipher Suite Count */
|
|
0x01, 0x00,
|
|
/* Pairwise Cipher Suite, default=TKIP */
|
|
0x00, 0x0f, 0xac, 0x02,
|
|
/* Authentication and Key Management Suite Count */
|
|
0x01, 0x00,
|
|
/* Authentication type, default=PSK */
|
|
0x00, 0x0f, 0xac, 0x02,
|
|
/* RSN capability */
|
|
0x00, 0x00
|
|
};
|
|
|
|
zmw_get_wlan_dev(dev);
|
|
|
|
if ( wd->sta.currentAuthMode == ZM_AUTH_MODE_WPAPSK )
|
|
{
|
|
/* Overwrite Group Cipher Suite by AP's setting */
|
|
zfMemoryCopy(ssn+8, wd->sta.wpaIe+8, 4);
|
|
|
|
if ( wd->sta.wepStatus == ZM_ENCRYPTION_AES )
|
|
{
|
|
/* Overwrite Pairwise Cipher Suite by AES */
|
|
zfMemoryCopy(ssn+14, zgWpaAesOui, 4);
|
|
}
|
|
|
|
zfCopyToIntTxBuffer(dev, buf, ssn, offset, ssn[1]+2);
|
|
zfMemoryCopy(wd->sta.wpaIe, ssn, ssn[1]+2);
|
|
offset += (ssn[1]+2);
|
|
}
|
|
else if ( wd->sta.currentAuthMode == ZM_AUTH_MODE_WPA )
|
|
{
|
|
/* Overwrite Group Cipher Suite by AP's setting */
|
|
zfMemoryCopy(ssn+8, wd->sta.wpaIe+8, 4);
|
|
/* Overwrite Key Management Suite by WPA-Radius */
|
|
zfMemoryCopy(ssn+20, zgWpaRadiusOui, 4);
|
|
|
|
if ( wd->sta.wepStatus == ZM_ENCRYPTION_AES )
|
|
{
|
|
/* Overwrite Pairwise Cipher Suite by AES */
|
|
zfMemoryCopy(ssn+14, zgWpaAesOui, 4);
|
|
}
|
|
|
|
zfCopyToIntTxBuffer(dev, buf, ssn, offset, ssn[1]+2);
|
|
zfMemoryCopy(wd->sta.wpaIe, ssn, ssn[1]+2);
|
|
offset += (ssn[1]+2);
|
|
}
|
|
else if ( wd->sta.currentAuthMode == ZM_AUTH_MODE_WPA2PSK )
|
|
{
|
|
/* Overwrite Group Cipher Suite by AP's setting */
|
|
zfMemoryCopy(rsn+4, wd->sta.rsnIe+4, 4);
|
|
|
|
if ( wd->sta.wepStatus == ZM_ENCRYPTION_AES )
|
|
{
|
|
/* Overwrite Pairwise Cipher Suite by AES */
|
|
zfMemoryCopy(rsn+10, zgWpa2AesOui, 4);
|
|
}
|
|
|
|
if ( frameType == ZM_WLAN_FRAME_TYPE_REASOCREQ )
|
|
{
|
|
for(i=0; i<wd->sta.pmkidInfo.bssidCount; i++)
|
|
{
|
|
if ( zfMemoryIsEqual((u8_t*) wd->sta.pmkidInfo.bssidInfo[i].bssid,
|
|
(u8_t*) wd->sta.bssid, 6) )
|
|
{
|
|
/* matched */
|
|
break;
|
|
}
|
|
|
|
if ( i < wd->sta.pmkidInfo.bssidCount )
|
|
{
|
|
// Fill PMKID Count in RSN information element
|
|
rsn[22] = 0x01;
|
|
rsn[23] = 0x00;
|
|
|
|
// Fill PMKID in RSN information element
|
|
zfMemoryCopy(rsn+24,
|
|
wd->sta.pmkidInfo.bssidInfo[i].pmkid, 16);
|
|
rsn[1] += 18;
|
|
}
|
|
}
|
|
}
|
|
|
|
zfCopyToIntTxBuffer(dev, buf, rsn, offset, rsn[1]+2);
|
|
zfMemoryCopy(wd->sta.rsnIe, rsn, rsn[1]+2);
|
|
offset += (rsn[1]+2);
|
|
}
|
|
else if ( wd->sta.currentAuthMode == ZM_AUTH_MODE_WPA2 )
|
|
{
|
|
/* Overwrite Group Cipher Suite by AP's setting */
|
|
zfMemoryCopy(rsn+4, wd->sta.rsnIe+4, 4);
|
|
/* Overwrite Key Management Suite by WPA2-Radius */
|
|
zfMemoryCopy(rsn+16, zgWpa2RadiusOui, 4);
|
|
|
|
if ( wd->sta.wepStatus == ZM_ENCRYPTION_AES )
|
|
{
|
|
/* Overwrite Pairwise Cipher Suite by AES */
|
|
zfMemoryCopy(rsn+10, zgWpa2AesOui, 4);
|
|
}
|
|
|
|
if (( frameType == ZM_WLAN_FRAME_TYPE_REASOCREQ || ( frameType == ZM_WLAN_FRAME_TYPE_ASOCREQ )))
|
|
{
|
|
|
|
if (wd->sta.pmkidInfo.bssidCount != 0) {
|
|
// Fill PMKID Count in RSN information element
|
|
rsn[22] = 1;
|
|
rsn[23] = 0;
|
|
/*
|
|
* The caller is respnsible to give us the relevant PMKID.
|
|
* We'll only accept 1 PMKID for now.
|
|
*/
|
|
for(i=0; i<wd->sta.pmkidInfo.bssidCount; i++)
|
|
{
|
|
if ( zfMemoryIsEqual((u8_t*) wd->sta.pmkidInfo.bssidInfo[i].bssid, (u8_t*) wd->sta.bssid, 6) )
|
|
{
|
|
zfMemoryCopy(rsn+24, wd->sta.pmkidInfo.bssidInfo[i].pmkid, 16);
|
|
break;
|
|
}
|
|
}
|
|
rsn[1] += 18;
|
|
}
|
|
|
|
}
|
|
|
|
zfCopyToIntTxBuffer(dev, buf, rsn, offset, rsn[1]+2);
|
|
zfMemoryCopy(wd->sta.rsnIe, rsn, rsn[1]+2);
|
|
offset += (rsn[1]+2);
|
|
}
|
|
|
|
return offset;
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* */
|
|
/* FUNCTION DESCRIPTION zfStaAddIeIbss */
|
|
/* Add information element IBSS parameter to buffer. */
|
|
/* */
|
|
/* INPUTS */
|
|
/* dev : device pointer */
|
|
/* buf : buffer to add information element */
|
|
/* offset : add information element from this offset */
|
|
/* */
|
|
/* OUTPUTS */
|
|
/* buffer offset after adding information element */
|
|
/* */
|
|
/* AUTHOR */
|
|
/* Ji-Huang Lee ZyDAS Technology Corporation 2005.12 */
|
|
/* */
|
|
/************************************************************************/
|
|
u16_t zfStaAddIeIbss(zdev_t* dev, zbuf_t* buf, u16_t offset)
|
|
{
|
|
zmw_get_wlan_dev(dev);
|
|
|
|
/* Element ID */
|
|
zmw_tx_buf_writeb(dev, buf, offset++, ZM_WLAN_EID_IBSS);
|
|
|
|
/* Element Length */
|
|
zmw_tx_buf_writeb(dev, buf, offset++, 2);
|
|
|
|
/* ATIM window */
|
|
zmw_tx_buf_writeh(dev, buf, offset, wd->sta.atimWindow);
|
|
offset += 2;
|
|
|
|
return offset;
|
|
}
|
|
|
|
|
|
|
|
/************************************************************************/
|
|
/* */
|
|
/* FUNCTION DESCRIPTION zfStaAddIeWmeInfo */
|
|
/* Add WME Information Element to buffer. */
|
|
/* */
|
|
/* INPUTS */
|
|
/* dev : device pointer */
|
|
/* buf : buffer to add information element */
|
|
/* offset : add information element from this offset */
|
|
/* */
|
|
/* OUTPUTS */
|
|
/* buffer offset after adding information element */
|
|
/* */
|
|
/* AUTHOR */
|
|
/* Stephen Chen ZyDAS Technology Corporation 2006.6 */
|
|
/* */
|
|
/************************************************************************/
|
|
u16_t zfStaAddIeWmeInfo(zdev_t* dev, zbuf_t* buf, u16_t offset, u8_t qosInfo)
|
|
{
|
|
/* Element ID */
|
|
zmw_tx_buf_writeb(dev, buf, offset++, ZM_WLAN_EID_WIFI_IE);
|
|
|
|
/* Element Length */
|
|
zmw_tx_buf_writeb(dev, buf, offset++, 7);
|
|
|
|
/* OUI */
|
|
zmw_tx_buf_writeb(dev, buf, offset++, 0x00);
|
|
zmw_tx_buf_writeb(dev, buf, offset++, 0x50);
|
|
zmw_tx_buf_writeb(dev, buf, offset++, 0xF2);
|
|
zmw_tx_buf_writeb(dev, buf, offset++, 0x02);
|
|
zmw_tx_buf_writeb(dev, buf, offset++, 0x00);
|
|
zmw_tx_buf_writeb(dev, buf, offset++, 0x01);
|
|
|
|
/* QoS Info */
|
|
zmw_tx_buf_writeb(dev, buf, offset++, qosInfo);
|
|
|
|
return offset;
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* */
|
|
/* FUNCTION DESCRIPTION zfStaAddIePowerCap */
|
|
/* Add information element Power capability to buffer. */
|
|
/* */
|
|
/* INPUTS */
|
|
/* dev : device pointer */
|
|
/* buf : buffer to add information element */
|
|
/* offset : add information element from this offset */
|
|
/* */
|
|
/* OUTPUTS */
|
|
/* buffer offset after adding information element */
|
|
/* */
|
|
/* AUTHOR */
|
|
/* Sharon 2007.12 */
|
|
/* */
|
|
/************************************************************************/
|
|
u16_t zfStaAddIePowerCap(zdev_t* dev, zbuf_t* buf, u16_t offset)
|
|
{
|
|
u8_t MaxTxPower;
|
|
u8_t MinTxPower;
|
|
|
|
zmw_get_wlan_dev(dev);
|
|
|
|
/* Element ID */
|
|
zmw_tx_buf_writeb(dev, buf, offset++, ZM_WLAN_EID_POWER_CAPABILITY);
|
|
|
|
/* Element Length */
|
|
zmw_tx_buf_writeb(dev, buf, offset++, 2);
|
|
|
|
MinTxPower = (u8_t)(zfHpGetMinTxPower(dev)/2);
|
|
MaxTxPower = (u8_t)(zfHpGetMaxTxPower(dev)/2);
|
|
|
|
/* Min Transmit Power Cap */
|
|
zmw_tx_buf_writeh(dev, buf, offset++, MinTxPower);
|
|
|
|
/* Max Transmit Power Cap */
|
|
zmw_tx_buf_writeh(dev, buf, offset++, MaxTxPower);
|
|
|
|
return offset;
|
|
}
|
|
/************************************************************************/
|
|
/* */
|
|
/* FUNCTION DESCRIPTION zfStaAddIeSupportCh */
|
|
/* Add information element supported channels to buffer. */
|
|
/* */
|
|
/* INPUTS */
|
|
/* dev : device pointer */
|
|
/* buf : buffer to add information element */
|
|
/* offset : add information element from this offset */
|
|
/* */
|
|
/* OUTPUTS */
|
|
/* buffer offset after adding information element */
|
|
/* */
|
|
/* AUTHOR */
|
|
/* Sharon 2007.12 */
|
|
/* */
|
|
/************************************************************************/
|
|
u16_t zfStaAddIeSupportCh(zdev_t* dev, zbuf_t* buf, u16_t offset)
|
|
{
|
|
|
|
u8_t i;
|
|
u16_t count_24G = 0;
|
|
u16_t count_5G = 0;
|
|
u16_t channelNum;
|
|
u8_t length;
|
|
|
|
zmw_get_wlan_dev(dev);
|
|
|
|
zmw_declare_for_critical_section();
|
|
zmw_enter_critical_section(dev);
|
|
|
|
for (i = 0; i < wd->regulationTable.allowChannelCnt; i++)
|
|
{
|
|
if (wd->regulationTable.allowChannel[i].channel < 3000)
|
|
{ // 2.4Hz
|
|
count_24G++;
|
|
}
|
|
else
|
|
{ // 5GHz
|
|
count_5G++;
|
|
}
|
|
}
|
|
|
|
length = (u8_t)(count_5G * 2 + 2); //5G fill by pair, 2,4G (continuous channels) fill 2 bytes
|
|
|
|
/* Element ID */
|
|
zmw_tx_buf_writeb(dev, buf, offset++, ZM_WLAN_EID_SUPPORTED_CHANNELS );
|
|
|
|
/* Element Length */
|
|
zmw_tx_buf_writeb(dev, buf, offset++, length);
|
|
|
|
// 2.4GHz (continuous channels)
|
|
/* First channel number */
|
|
zmw_tx_buf_writeh(dev, buf, offset++, 1); //Start from channle 1
|
|
/* Number of channels */
|
|
zmw_tx_buf_writeh(dev, buf, offset++, count_24G);
|
|
|
|
for (i = 0; i < wd->regulationTable.allowChannelCnt ; i++)
|
|
{
|
|
if (wd->regulationTable.allowChannel[i].channel > 4000 && wd->regulationTable.allowChannel[i].channel < 5000)
|
|
{ // 5GHz 4000 -5000Mhz
|
|
channelNum = (wd->regulationTable.allowChannel[i].channel-4000)/5;
|
|
/* First channel number */
|
|
zmw_tx_buf_writeh(dev, buf, offset++, channelNum);
|
|
/* Number of channels */
|
|
zmw_tx_buf_writeh(dev, buf, offset++, 1);
|
|
}
|
|
else if (wd->regulationTable.allowChannel[i].channel >= 5000)
|
|
{ // 5GHz >5000Mhz
|
|
channelNum = (wd->regulationTable.allowChannel[i].channel-5000)/5;
|
|
/* First channel number */
|
|
zmw_tx_buf_writeh(dev, buf, offset++, channelNum);
|
|
/* Number of channels */
|
|
zmw_tx_buf_writeh(dev, buf, offset++, 1);
|
|
}
|
|
}
|
|
zmw_leave_critical_section(dev);
|
|
|
|
return offset;
|
|
}
|
|
|
|
void zfStaStartConnectCb(zdev_t* dev)
|
|
{
|
|
zmw_get_wlan_dev(dev);
|
|
|
|
zfStaStartConnect(dev, wd->sta.bIsSharedKey);
|
|
}
|
|
|
|
void zfStaStartConnect(zdev_t* dev, u8_t bIsSharedKey)
|
|
{
|
|
u32_t p1, p2;
|
|
u8_t newConnState;
|
|
|
|
zmw_get_wlan_dev(dev);
|
|
zmw_declare_for_critical_section();
|
|
|
|
/* p1_low = algorithm number, p1_high = transaction sequence number */
|
|
if ( bIsSharedKey )
|
|
{
|
|
//wd->sta.connectState = ZM_STA_CONN_STATE_AUTH_SHARE_1;
|
|
newConnState = ZM_STA_CONN_STATE_AUTH_SHARE_1;
|
|
zm_debug_msg0("ZM_STA_CONN_STATE_AUTH_SHARE_1");
|
|
p1 = ZM_AUTH_ALGO_SHARED_KEY;
|
|
}
|
|
else
|
|
{
|
|
//wd->sta.connectState = ZM_STA_CONN_STATE_AUTH_OPEN;
|
|
newConnState = ZM_STA_CONN_STATE_AUTH_OPEN;
|
|
zm_debug_msg0("ZM_STA_CONN_STATE_AUTH_OPEN");
|
|
if( wd->sta.leapEnabled )
|
|
p1 = ZM_AUTH_ALGO_LEAP;
|
|
else
|
|
p1 = ZM_AUTH_ALGO_OPEN_SYSTEM;
|
|
}
|
|
|
|
/* status code */
|
|
p2 = 0x0;
|
|
|
|
zmw_enter_critical_section(dev);
|
|
wd->sta.connectTimer = wd->tick;
|
|
wd->sta.connectState = newConnState;
|
|
zmw_leave_critical_section(dev);
|
|
|
|
/* send the 1st authentication frame */
|
|
zfSendMmFrame(dev, ZM_WLAN_FRAME_TYPE_AUTH, wd->sta.bssid, p1, p2, 0);
|
|
|
|
return;
|
|
}
|
|
|
|
void zfSendNullData(zdev_t* dev, u8_t type)
|
|
{
|
|
zbuf_t* buf;
|
|
//u16_t addrTblSize;
|
|
//struct zsAddrTbl addrTbl;
|
|
u16_t err;
|
|
u16_t hlen;
|
|
u16_t header[(34+8+1)/2];
|
|
u16_t bcastAddr[3] = {0xffff,0xffff,0xffff};
|
|
u16_t *dstAddr;
|
|
|
|
zmw_get_wlan_dev(dev);
|
|
|
|
if ((buf = zfwBufAllocate(dev, 1024)) == NULL)
|
|
{
|
|
zm_msg0_mm(ZM_LV_0, "Alloc mm buf Fail!");
|
|
return;
|
|
}
|
|
|
|
zfwBufSetSize(dev, buf, 0);
|
|
|
|
//zm_msg2_mm(ZM_LV_2, "buf->len=", buf->len);
|
|
|
|
if ( wd->wlanMode == ZM_MODE_IBSS)
|
|
{
|
|
dstAddr = bcastAddr;
|
|
}
|
|
else
|
|
{
|
|
dstAddr = wd->sta.bssid;
|
|
}
|
|
|
|
if (wd->sta.wmeConnected != 0)
|
|
{
|
|
/* If connect to a WMM AP, Send QoS Null data */
|
|
hlen = zfTxGenMmHeader(dev, ZM_WLAN_FRAME_TYPE_QOS_NULL, dstAddr, header, 0, buf, 0, 0);
|
|
}
|
|
else
|
|
{
|
|
hlen = zfTxGenMmHeader(dev, ZM_WLAN_FRAME_TYPE_NULL, dstAddr, header, 0, buf, 0, 0);
|
|
}
|
|
|
|
if (wd->wlanMode == ZM_MODE_INFRASTRUCTURE)
|
|
{
|
|
header[4] |= 0x0100; //TODS bit
|
|
}
|
|
|
|
if ( type == 1 )
|
|
{
|
|
header[4] |= 0x1000;
|
|
}
|
|
|
|
/* Get buffer DMA address */
|
|
//if ((addrTblSize = zfwBufMapDma(dev, buf, &addrTbl)) == 0)
|
|
//if ((addrTblSize = zfwMapTxDma(dev, buf, &addrTbl)) == 0)
|
|
//{
|
|
// goto zlError;
|
|
//}
|
|
|
|
/*increase unicast frame counter*/
|
|
wd->commTally.txUnicastFrm++;
|
|
|
|
if ((err = zfHpSend(dev, header, hlen, NULL, 0, NULL, 0, buf, 0,
|
|
ZM_INTERNAL_ALLOC_BUF, 0, 0xff)) != ZM_SUCCESS)
|
|
{
|
|
goto zlError;
|
|
}
|
|
|
|
|
|
return;
|
|
|
|
zlError:
|
|
|
|
zfwBufFree(dev, buf, 0);
|
|
return;
|
|
|
|
}
|
|
|
|
void zfSendPSPoll(zdev_t* dev)
|
|
{
|
|
zbuf_t* buf;
|
|
//u16_t addrTblSize;
|
|
//struct zsAddrTbl addrTbl;
|
|
u16_t err;
|
|
u16_t hlen;
|
|
u16_t header[(8+24+1)/2];
|
|
|
|
zmw_get_wlan_dev(dev);
|
|
|
|
if ((buf = zfwBufAllocate(dev, 1024)) == NULL)
|
|
{
|
|
zm_msg0_mm(ZM_LV_0, "Alloc mm buf Fail!");
|
|
return;
|
|
}
|
|
|
|
zfwBufSetSize(dev, buf, 0);
|
|
|
|
//zm_msg2_mm(ZM_LV_2, "buf->len=", buf->len);
|
|
|
|
zfTxGenMmHeader(dev, ZM_WLAN_FRAME_TYPE_PSPOLL, wd->sta.bssid, header, 0, buf, 0, 0);
|
|
|
|
header[0] = 20;
|
|
header[4] |= 0x1000;
|
|
header[5] = wd->sta.aid | 0xc000; //Both bit-14 and bit-15 are 1
|
|
hlen = 16 + 8;
|
|
|
|
/* Get buffer DMA address */
|
|
//if ((addrTblSize = zfwBufMapDma(dev, buf, &addrTbl)) == 0)
|
|
//if ((addrTblSize = zfwMapTxDma(dev, buf, &addrTbl)) == 0)
|
|
//{
|
|
// goto zlError;
|
|
//}
|
|
|
|
if ((err = zfHpSend(dev, header, hlen, NULL, 0, NULL, 0, buf, 0,
|
|
ZM_INTERNAL_ALLOC_BUF, 0, 0xff)) != ZM_SUCCESS)
|
|
{
|
|
goto zlError;
|
|
}
|
|
|
|
return;
|
|
|
|
zlError:
|
|
|
|
zfwBufFree(dev, buf, 0);
|
|
return;
|
|
|
|
}
|
|
|
|
void zfSendBA(zdev_t* dev, u16_t start_seq, u8_t *bitmap)
|
|
{
|
|
zbuf_t* buf;
|
|
//u16_t addrTblSize;
|
|
//struct zsAddrTbl addrTbl;
|
|
u16_t err;
|
|
u16_t hlen;
|
|
u16_t header[(8+24+1)/2];
|
|
u16_t i, offset = 0;
|
|
|
|
zmw_get_wlan_dev(dev);
|
|
|
|
if ((buf = zfwBufAllocate(dev, 1024)) == NULL)
|
|
{
|
|
zm_msg0_mm(ZM_LV_0, "Alloc mm buf Fail!");
|
|
return;
|
|
}
|
|
|
|
zfwBufSetSize(dev, buf, 12); // 28 = FC 2 + DU 2 + RA 6 + TA 6 + BAC 2 + SEQ 2 + BitMap 8
|
|
// 12 = BAC 2 + SEQ 2 + BitMap 8
|
|
|
|
//zm_msg2_mm(ZM_LV_2, "buf->len=", buf->len);
|
|
|
|
zfTxGenMmHeader(dev, ZM_WLAN_FRAME_TYPE_BA, wd->sta.bssid, header, 0, buf, 0, 0);
|
|
|
|
header[0] = 32; /* MAC header 16 + BA control 2 + BA info 10 + FCS 4*/
|
|
header[1] = 0x4; /* No ACK */
|
|
|
|
/* send by OFDM 6M */
|
|
header[2] = (u16_t)(zcRateToPhyCtrl[4] & 0xffff);
|
|
header[3] = (u16_t)(zcRateToPhyCtrl[4]>>16) & 0xffff;
|
|
|
|
hlen = 16 + 8; /* MAC header 16 + control 8*/
|
|
offset = 0;
|
|
zmw_tx_buf_writeh(dev, buf, offset, 0x05); /*compressed bitmap on*/
|
|
offset+=2;
|
|
zmw_tx_buf_writeh(dev, buf, offset, start_seq);
|
|
offset+=2;
|
|
|
|
for (i=0; i<8; i++) {
|
|
zmw_tx_buf_writeb(dev, buf, offset, bitmap[i]);
|
|
offset++;
|
|
}
|
|
|
|
if ((err = zfHpSend(dev, header, hlen, NULL, 0, NULL, 0, buf, 0,
|
|
ZM_INTERNAL_ALLOC_BUF, 0, 0xff)) != ZM_SUCCESS)
|
|
{
|
|
goto zlError;
|
|
}
|
|
|
|
return;
|
|
|
|
zlError:
|
|
|
|
zfwBufFree(dev, buf, 0);
|
|
return;
|
|
|
|
}
|
|
|
|
void zfStaGetTxRate(zdev_t* dev, u16_t* macAddr, u32_t* phyCtrl,
|
|
u16_t* rcProbingFlag)
|
|
{
|
|
u8_t addr[6], i;
|
|
u8_t rate;
|
|
zmw_get_wlan_dev(dev);
|
|
zmw_declare_for_critical_section();
|
|
|
|
ZM_MAC_WORD_TO_BYTE(macAddr, addr);
|
|
*phyCtrl = 0;
|
|
|
|
if ( wd->wlanMode == ZM_MODE_INFRASTRUCTURE )
|
|
{
|
|
zmw_enter_critical_section(dev);
|
|
rate = (u8_t)zfRateCtrlGetTxRate(dev, &wd->sta.oppositeInfo[0].rcCell, rcProbingFlag);
|
|
//#ifdef ZM_FB50
|
|
//rate = 27;
|
|
//#endif
|
|
*phyCtrl = zcRateToPhyCtrl[rate];
|
|
zmw_leave_critical_section(dev);
|
|
}
|
|
else
|
|
{
|
|
zmw_enter_critical_section(dev);
|
|
for(i=0; i<wd->sta.oppositeCount; i++)
|
|
{
|
|
if ( addr[0] && 0x01 == 1 ) // The default beacon transmitted rate is CCK and 1 Mbps , but the a mode should use
|
|
// OFDM modulation and 6Mbps to transmit beacon.
|
|
{
|
|
//rate = (u8_t)zfRateCtrlGetTxRate(dev, &wd->sta.oppositeInfo[i].rcCell, rcProbingFlag);
|
|
rate = wd->sta.oppositeInfo[i].rcCell.operationRateSet[0];
|
|
*phyCtrl = zcRateToPhyCtrl[rate];
|
|
break;
|
|
}
|
|
else if ( zfMemoryIsEqual(addr, wd->sta.oppositeInfo[i].macAddr, 6) )
|
|
{
|
|
rate = (u8_t)zfRateCtrlGetTxRate(dev, &wd->sta.oppositeInfo[i].rcCell, rcProbingFlag);
|
|
*phyCtrl = zcRateToPhyCtrl[rate];
|
|
break;
|
|
}
|
|
}
|
|
zmw_leave_critical_section(dev);
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
struct zsMicVar* zfStaGetRxMicKey(zdev_t* dev, zbuf_t* buf)
|
|
{
|
|
u8_t keyIndex;
|
|
u8_t da0;
|
|
|
|
zmw_get_wlan_dev(dev);
|
|
|
|
/* if need not check MIC, return NULL */
|
|
if ( ((wd->sta.encryMode != ZM_TKIP)&&(wd->sta.encryMode != ZM_AES))||
|
|
(wd->sta.wpaState < ZM_STA_WPA_STATE_PK_OK) )
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
da0 = zmw_rx_buf_readb(dev, buf, ZM_WLAN_HEADER_A1_OFFSET);
|
|
|
|
if ((zmw_rx_buf_readb(dev, buf, 0) & 0x80) == 0x80)
|
|
keyIndex = zmw_rx_buf_readb(dev, buf, ZM_WLAN_HEADER_IV_OFFSET+5); /* Qos Packet*/
|
|
else
|
|
keyIndex = zmw_rx_buf_readb(dev, buf, ZM_WLAN_HEADER_IV_OFFSET+3); /* normal Packet*/
|
|
keyIndex = (keyIndex & 0xc0) >> 6;
|
|
|
|
return (&wd->sta.rxMicKey[keyIndex]);
|
|
}
|
|
|
|
struct zsMicVar* zfStaGetTxMicKey(zdev_t* dev, zbuf_t* buf)
|
|
{
|
|
zmw_get_wlan_dev(dev);
|
|
|
|
/* if need not check MIC, return NULL */
|
|
//if ( ((wd->sta.encryMode != ZM_TKIP)&&(wd->sta.encryMode != ZM_AES))||
|
|
// (wd->sta.wpaState < ZM_STA_WPA_STATE_PK_OK) )
|
|
if ( (wd->sta.encryMode != ZM_TKIP) || (wd->sta.wpaState < ZM_STA_WPA_STATE_PK_OK) )
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
return (&wd->sta.txMicKey);
|
|
}
|
|
|
|
u16_t zfStaRxValidateFrame(zdev_t* dev, zbuf_t* buf)
|
|
{
|
|
u8_t frameType, frameCtrl;
|
|
u8_t da0;
|
|
//u16_t sa[3];
|
|
u16_t ret;
|
|
u16_t i;
|
|
//u8_t sa0;
|
|
|
|
zmw_get_wlan_dev(dev);
|
|
|
|
frameType = zmw_rx_buf_readb(dev, buf, 0);
|
|
da0 = zmw_rx_buf_readb(dev, buf, ZM_WLAN_HEADER_A1_OFFSET);
|
|
//sa0 = zmw_rx_buf_readb(dev, buf, ZM_WLAN_HEADER_A2_OFFSET);
|
|
|
|
if ( (!zfStaIsConnected(dev))&&((frameType & 0xf) == ZM_WLAN_DATA_FRAME) )
|
|
{
|
|
return ZM_ERR_DATA_BEFORE_CONNECTED;
|
|
}
|
|
|
|
|
|
if ( (zfStaIsConnected(dev))&&((frameType & 0xf) == ZM_WLAN_DATA_FRAME) )
|
|
{
|
|
/* check BSSID */
|
|
if ( wd->wlanMode == ZM_MODE_INFRASTRUCTURE )
|
|
{
|
|
/* Big Endian and Little Endian Compatibility */
|
|
u16_t mac[3];
|
|
mac[0] = zmw_cpu_to_le16(wd->sta.bssid[0]);
|
|
mac[1] = zmw_cpu_to_le16(wd->sta.bssid[1]);
|
|
mac[2] = zmw_cpu_to_le16(wd->sta.bssid[2]);
|
|
if ( !zfRxBufferEqualToStr(dev, buf, (u8_t *)mac,
|
|
ZM_WLAN_HEADER_A2_OFFSET, 6) )
|
|
{
|
|
/*We will get lots of garbage data, especially in AES mode.*/
|
|
/*To avoid sending too many deauthentication frames in STA mode, mark it.*/
|
|
#if 0
|
|
/* If unicast frame, send deauth to the transmitter */
|
|
if (( da0 & 0x01 ) == 0)
|
|
{
|
|
for (i=0; i<3; i++)
|
|
{
|
|
sa[i] = zmw_rx_buf_readh(dev, buf, ZM_WLAN_HEADER_A2_OFFSET+(i*2));
|
|
}
|
|
/* If mutilcast address, don't send deauthentication*/
|
|
if (( sa0 & 0x01 ) == 0)
|
|
zfSendMmFrame(dev, ZM_WLAN_FRAME_TYPE_DEAUTH, sa, 7, 0, 0);
|
|
}
|
|
#endif
|
|
return ZM_ERR_DATA_BSSID_NOT_MATCHED;
|
|
}
|
|
}
|
|
else if ( wd->wlanMode == ZM_MODE_IBSS )
|
|
{
|
|
/* Big Endian and Little Endian Compatibility */
|
|
u16_t mac[3];
|
|
mac[0] = zmw_cpu_to_le16(wd->sta.bssid[0]);
|
|
mac[1] = zmw_cpu_to_le16(wd->sta.bssid[1]);
|
|
mac[2] = zmw_cpu_to_le16(wd->sta.bssid[2]);
|
|
if ( !zfRxBufferEqualToStr(dev, buf, (u8_t *)mac,
|
|
ZM_WLAN_HEADER_A3_OFFSET, 6) )
|
|
{
|
|
return ZM_ERR_DATA_BSSID_NOT_MATCHED;
|
|
}
|
|
}
|
|
|
|
frameCtrl = zmw_rx_buf_readb(dev, buf, 1);
|
|
|
|
/* check security bit */
|
|
if ( wd->sta.dropUnencryptedPkts &&
|
|
(wd->sta.wepStatus != ZM_ENCRYPTION_WEP_DISABLED )&&
|
|
( !(frameCtrl & ZM_BIT_6) ) )
|
|
{ /* security on, but got data without encryption */
|
|
|
|
#if 1
|
|
ret = ZM_ERR_DATA_NOT_ENCRYPTED;
|
|
if ( wd->sta.pStaRxSecurityCheckCb != NULL )
|
|
{
|
|
ret = wd->sta.pStaRxSecurityCheckCb(dev, buf);
|
|
}
|
|
else
|
|
{
|
|
ret = ZM_ERR_DATA_NOT_ENCRYPTED;
|
|
}
|
|
if (ret == ZM_ERR_DATA_NOT_ENCRYPTED)
|
|
{
|
|
wd->commTally.swRxDropUnencryptedCount++;
|
|
}
|
|
return ret;
|
|
#else
|
|
if ( (wd->sta.wepStatus != ZM_ENCRYPTION_TKIP)&&
|
|
(wd->sta.wepStatus != ZM_ENCRYPTION_AES) )
|
|
{
|
|
return ZM_ERR_DATA_NOT_ENCRYPTED;
|
|
}
|
|
#endif
|
|
}
|
|
}
|
|
|
|
return ZM_SUCCESS;
|
|
}
|
|
|
|
void zfStaMicFailureHandling(zdev_t* dev, zbuf_t* buf)
|
|
{
|
|
u8_t da0;
|
|
u8_t micNotify = 1;
|
|
|
|
zmw_get_wlan_dev(dev);
|
|
|
|
zmw_declare_for_critical_section();
|
|
|
|
if ( wd->sta.wpaState < ZM_STA_WPA_STATE_PK_OK )
|
|
{
|
|
return;
|
|
}
|
|
|
|
zmw_enter_critical_section(dev);
|
|
|
|
wd->sta.cmMicFailureCount++;
|
|
|
|
if ( wd->sta.cmMicFailureCount == 1 )
|
|
{
|
|
zm_debug_msg0("get the first MIC failure");
|
|
//zfTimerSchedule(dev, ZM_EVENT_CM_TIMER, ZM_TICK_CM_TIMEOUT);
|
|
|
|
/* Timer Resolution on WinXP is 15/16 ms */
|
|
/* Decrease Time offset for <XP> Counter Measure */
|
|
zfTimerSchedule(dev, ZM_EVENT_CM_TIMER, ZM_TICK_CM_TIMEOUT - ZM_TICK_CM_TIMEOUT_OFFSET);
|
|
}
|
|
else if ( wd->sta.cmMicFailureCount == 2 )
|
|
{
|
|
zm_debug_msg0("get the second MIC failure");
|
|
/* reserve 2 second for OS to send MIC failure report to AP */
|
|
wd->sta.cmDisallowSsidLength = wd->sta.ssidLen;
|
|
zfMemoryCopy(wd->sta.cmDisallowSsid, wd->sta.ssid, wd->sta.ssidLen);
|
|
//wd->sta.cmMicFailureCount = 0;
|
|
zfTimerCancel(dev, ZM_EVENT_CM_TIMER);
|
|
//zfTimerSchedule(dev, ZM_EVENT_CM_DISCONNECT, ZM_TICK_CM_DISCONNECT);
|
|
|
|
/* Timer Resolution on WinXP is 15/16 ms */
|
|
/* Decrease Time offset for <XP> Counter Measure */
|
|
zfTimerSchedule(dev, ZM_EVENT_CM_DISCONNECT, ZM_TICK_CM_DISCONNECT - ZM_TICK_CM_DISCONNECT_OFFSET);
|
|
}
|
|
else
|
|
{
|
|
micNotify = 0;
|
|
}
|
|
|
|
zmw_leave_critical_section(dev);
|
|
|
|
if (micNotify == 1)
|
|
{
|
|
da0 = zmw_rx_buf_readb(dev, buf, ZM_WLAN_HEADER_A1_OFFSET);
|
|
if ( da0 & 0x01 )
|
|
{
|
|
if (wd->zfcbMicFailureNotify != NULL)
|
|
{
|
|
wd->zfcbMicFailureNotify(dev, wd->sta.bssid, ZM_MIC_GROUP_ERROR);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (wd->zfcbMicFailureNotify != NULL)
|
|
{
|
|
wd->zfcbMicFailureNotify(dev, wd->sta.bssid, ZM_MIC_PAIRWISE_ERROR);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
u8_t zfStaBlockWlanScan(zdev_t* dev)
|
|
{
|
|
u8_t ret=FALSE;
|
|
|
|
zmw_get_wlan_dev(dev);
|
|
|
|
if ( wd->sta.bChannelScan )
|
|
{
|
|
return TRUE;
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
void zfStaResetStatus(zdev_t* dev, u8_t bInit)
|
|
{
|
|
u8_t i;
|
|
|
|
zmw_get_wlan_dev(dev);
|
|
|
|
zfHpDisableBeacon(dev);
|
|
|
|
wd->dtim = 1;
|
|
wd->sta.capability[0] = 0x01;
|
|
wd->sta.capability[1] = 0x00;
|
|
/* 802.11h */
|
|
if (wd->sta.DFSEnable || wd->sta.TPCEnable)
|
|
wd->sta.capability[1] |= ZM_BIT_0;
|
|
|
|
/* release queued packets */
|
|
for(i=0; i<wd->sta.ibssPSDataCount; i++)
|
|
{
|
|
zfwBufFree(dev, wd->sta.ibssPSDataQueue[i], 0);
|
|
}
|
|
|
|
for(i=0; i<wd->sta.staPSDataCount; i++)
|
|
{
|
|
zfwBufFree(dev, wd->sta.staPSDataQueue[i], 0);
|
|
}
|
|
|
|
wd->sta.ibssPSDataCount = 0;
|
|
wd->sta.staPSDataCount = 0;
|
|
zfZeroMemory((u8_t*) &wd->sta.staPSList, sizeof(struct zsStaPSList));
|
|
|
|
wd->sta.wmeConnected = 0;
|
|
wd->sta.psMgr.tempWakeUp = 0;
|
|
wd->sta.qosInfo = 0;
|
|
zfQueueFlush(dev, wd->sta.uapsdQ);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
void zfStaIbssMonitoring(zdev_t* dev, u8_t reset)
|
|
{
|
|
u16_t i;
|
|
u16_t oppositeCount;
|
|
struct zsPartnerNotifyEvent event;
|
|
|
|
zmw_get_wlan_dev(dev);
|
|
|
|
zmw_declare_for_critical_section();
|
|
|
|
//zm_debug_msg1("zfStaIbssMonitoring %d", wd->sta.oppositeCount);
|
|
|
|
zmw_enter_critical_section(dev);
|
|
|
|
if ( wd->sta.oppositeCount == 0 )
|
|
{
|
|
goto done;
|
|
}
|
|
|
|
if ( wd->sta.bChannelScan )
|
|
{
|
|
goto done;
|
|
}
|
|
|
|
oppositeCount = wd->sta.oppositeCount;
|
|
|
|
for(i=0; i < ZM_MAX_OPPOSITE_COUNT; i++)
|
|
{
|
|
if ( oppositeCount == 0 )
|
|
{
|
|
break;
|
|
}
|
|
|
|
if ( reset )
|
|
{
|
|
wd->sta.oppositeInfo[i].valid = 0;
|
|
}
|
|
|
|
if ( wd->sta.oppositeInfo[i].valid == 0 )
|
|
{
|
|
continue;
|
|
}
|
|
|
|
oppositeCount--;
|
|
|
|
if ( wd->sta.oppositeInfo[i].aliveCounter )
|
|
{
|
|
zm_debug_msg1("Setting alive to ", wd->sta.oppositeInfo[i].aliveCounter);
|
|
|
|
zmw_leave_critical_section(dev);
|
|
|
|
if ( wd->sta.oppositeInfo[i].aliveCounter != ZM_IBSS_PEER_ALIVE_COUNTER )
|
|
{
|
|
zfSendMmFrame(dev, ZM_WLAN_FRAME_TYPE_PROBEREQ,
|
|
(u16_t*)wd->sta.oppositeInfo[i].macAddr, 1, 0, 0);
|
|
}
|
|
|
|
zmw_enter_critical_section(dev);
|
|
wd->sta.oppositeInfo[i].aliveCounter--;
|
|
}
|
|
else
|
|
{
|
|
zm_debug_msg0("zfStaIbssMonitoring remove the peer station");
|
|
zfMemoryCopy(event.bssid, (u8_t *)(wd->sta.bssid), 6);
|
|
zfMemoryCopy(event.peerMacAddr, wd->sta.oppositeInfo[i].macAddr, 6);
|
|
|
|
wd->sta.oppositeInfo[i].valid = 0;
|
|
wd->sta.oppositeCount--;
|
|
if (wd->zfcbIbssPartnerNotify != NULL)
|
|
{
|
|
zmw_leave_critical_section(dev);
|
|
wd->zfcbIbssPartnerNotify(dev, 0, &event);
|
|
zmw_enter_critical_section(dev);
|
|
}
|
|
}
|
|
}
|
|
|
|
done:
|
|
if ( reset == 0 )
|
|
{
|
|
zfTimerSchedule(dev, ZM_EVENT_IBSS_MONITOR, ZM_TICK_IBSS_MONITOR);
|
|
}
|
|
|
|
zmw_leave_critical_section(dev);
|
|
}
|
|
|
|
void zfInitPartnerNotifyEvent(zdev_t* dev, zbuf_t* buf, struct zsPartnerNotifyEvent *event)
|
|
{
|
|
u16_t *peerMacAddr;
|
|
|
|
zmw_get_wlan_dev(dev);
|
|
|
|
peerMacAddr = (u16_t *)event->peerMacAddr;
|
|
|
|
zfMemoryCopy(event->bssid, (u8_t *)(wd->sta.bssid), 6);
|
|
peerMacAddr[0] = zmw_rx_buf_readh(dev, buf, ZM_WLAN_HEADER_A2_OFFSET);
|
|
peerMacAddr[1] = zmw_rx_buf_readh(dev, buf, ZM_WLAN_HEADER_A2_OFFSET + 2);
|
|
peerMacAddr[2] = zmw_rx_buf_readh(dev, buf, ZM_WLAN_HEADER_A2_OFFSET + 4);
|
|
}
|
|
|
|
void zfStaInitOppositeInfo(zdev_t* dev)
|
|
{
|
|
int i;
|
|
|
|
zmw_get_wlan_dev(dev);
|
|
|
|
for(i=0; i<ZM_MAX_OPPOSITE_COUNT; i++)
|
|
{
|
|
wd->sta.oppositeInfo[i].valid = 0;
|
|
wd->sta.oppositeInfo[i].aliveCounter = ZM_IBSS_PEER_ALIVE_COUNTER;
|
|
}
|
|
}
|
|
#ifdef ZM_ENABLE_CENC
|
|
u16_t zfStaAddIeCenc(zdev_t* dev, zbuf_t* buf, u16_t offset)
|
|
{
|
|
zmw_get_wlan_dev(dev);
|
|
|
|
if (wd->sta.cencIe[1] != 0)
|
|
{
|
|
zfCopyToIntTxBuffer(dev, buf, wd->sta.cencIe, offset, wd->sta.cencIe[1]+2);
|
|
offset += (wd->sta.cencIe[1]+2);
|
|
}
|
|
return offset;
|
|
}
|
|
#endif //ZM_ENABLE_CENC
|
|
u16_t zfStaProcessAction(zdev_t* dev, zbuf_t* buf)
|
|
{
|
|
u8_t category, actionDetails;
|
|
zmw_get_wlan_dev(dev);
|
|
|
|
category = zmw_rx_buf_readb(dev, buf, 24);
|
|
actionDetails = zmw_rx_buf_readb(dev, buf, 25);
|
|
switch (category)
|
|
{
|
|
case 0: //Spectrum Management
|
|
switch(actionDetails)
|
|
{
|
|
case 0: //Measurement Request
|
|
break;
|
|
case 1: //Measurement Report
|
|
//ProcessActionSpectrumFrame_MeasurementReport(Adapter,pActionBody+3);
|
|
break;
|
|
case 2: //TPC request
|
|
//if (wd->sta.TPCEnable)
|
|
// zfStaUpdateDot11HTPC(dev, buf);
|
|
break;
|
|
case 3: //TPC report
|
|
//if (wd->sta.TPCEnable)
|
|
// zfStaUpdateDot11HTPC(dev, buf);
|
|
break;
|
|
case 4: //Channel Switch Announcement
|
|
if (wd->sta.DFSEnable)
|
|
zfStaUpdateDot11HDFS(dev, buf);
|
|
break;
|
|
default:
|
|
zm_debug_msg1("Action Frame contain not support action field ", actionDetails);
|
|
break;
|
|
}
|
|
break;
|
|
case ZM_WLAN_BLOCK_ACK_ACTION_FRAME:
|
|
zfAggBlockAckActionFrame(dev, buf);
|
|
break;
|
|
case 17: //Qos Management
|
|
break;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
/* Determine the time not send beacon , if more than some value ,
|
|
re-write the beacon start address */
|
|
void zfReWriteBeaconStartAddress(zdev_t* dev)
|
|
{
|
|
zmw_get_wlan_dev(dev);
|
|
|
|
zmw_declare_for_critical_section();
|
|
|
|
zmw_enter_critical_section(dev);
|
|
wd->tickIbssSendBeacon++; // Increase 1 per 10ms .
|
|
zmw_leave_critical_section(dev);
|
|
|
|
if ( wd->tickIbssSendBeacon == 40 )
|
|
{
|
|
// DbgPrint("20070727");
|
|
zfHpEnableBeacon(dev, ZM_MODE_IBSS, wd->beaconInterval, wd->dtim, (u8_t)wd->sta.atimWindow);
|
|
zmw_enter_critical_section(dev);
|
|
wd->tickIbssSendBeacon = 0;
|
|
zmw_leave_critical_section(dev);
|
|
}
|
|
}
|
|
|
|
struct zsTkipSeed* zfStaGetRxSeed(zdev_t* dev, zbuf_t* buf)
|
|
{
|
|
u8_t keyIndex;
|
|
u8_t da0;
|
|
|
|
zmw_get_wlan_dev(dev);
|
|
|
|
/* if need not check MIC, return NULL */
|
|
if ( ((wd->sta.encryMode != ZM_TKIP)&&(wd->sta.encryMode != ZM_AES))||
|
|
(wd->sta.wpaState < ZM_STA_WPA_STATE_PK_OK) )
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
da0 = zmw_rx_buf_readb(dev, buf, ZM_WLAN_HEADER_A1_OFFSET);
|
|
|
|
if ((zmw_rx_buf_readb(dev, buf, 0) & 0x80) == 0x80)
|
|
keyIndex = zmw_rx_buf_readb(dev, buf, ZM_WLAN_HEADER_IV_OFFSET+5); /* Qos Packet*/
|
|
else
|
|
keyIndex = zmw_rx_buf_readb(dev, buf, ZM_WLAN_HEADER_IV_OFFSET+3); /* normal Packet*/
|
|
keyIndex = (keyIndex & 0xc0) >> 6;
|
|
|
|
return (&wd->sta.rxSeed[keyIndex]);
|
|
}
|
|
|
|
void zfStaEnableSWEncryption(zdev_t *dev, u8_t value)
|
|
{
|
|
zmw_get_wlan_dev(dev);
|
|
|
|
wd->sta.SWEncryptEnable = value;
|
|
zfHpSWDecrypt(dev, 1);
|
|
zfHpSWEncrypt(dev, 1);
|
|
}
|
|
|
|
void zfStaDisableSWEncryption(zdev_t *dev)
|
|
{
|
|
zmw_get_wlan_dev(dev);
|
|
|
|
wd->sta.SWEncryptEnable = 0;
|
|
zfHpSWDecrypt(dev, 0);
|
|
zfHpSWEncrypt(dev, 0);
|
|
}
|
|
|
|
u16_t zfComputeBssInfoWeightValue(zdev_t *dev, u8_t isBMode, u8_t isHT, u8_t isHT40, u8_t signalStrength)
|
|
{
|
|
u8_t weightOfB = 0;
|
|
u8_t weightOfAGBelowThr = 0;
|
|
u8_t weightOfAGUpThr = 15;
|
|
u8_t weightOfN20BelowThr = 15;
|
|
u8_t weightOfN20UpThr = 30;
|
|
u8_t weightOfN40BelowThr = 16;
|
|
u8_t weightOfN40UpThr = 32;
|
|
|
|
zmw_get_wlan_dev(dev);
|
|
|
|
if( isBMode == 0 )
|
|
return (signalStrength + weightOfB); // pure b mode , do not add the weight value for this AP !
|
|
else
|
|
{
|
|
if( isHT == 0 && isHT40 == 0 )
|
|
{ // a , g , b/g mode ! add the weight value 15 for this AP if it's signal strength is more than some value !
|
|
if( signalStrength < 18 ) // -77 dBm
|
|
return signalStrength + weightOfAGBelowThr;
|
|
else
|
|
return (signalStrength + weightOfAGUpThr);
|
|
}
|
|
else if( isHT == 1 && isHT40 == 0 )
|
|
{ // 80211n mode use 20MHz
|
|
if( signalStrength < 23 ) // -72 dBm
|
|
return (signalStrength + weightOfN20BelowThr);
|
|
else
|
|
return (signalStrength + weightOfN20UpThr);
|
|
}
|
|
else // isHT == 1 && isHT40 == 1
|
|
{ // 80211n mode use 40MHz
|
|
if( signalStrength < 16 ) // -79 dBm
|
|
return (signalStrength + weightOfN40BelowThr);
|
|
else
|
|
return (signalStrength + weightOfN40UpThr);
|
|
}
|
|
}
|
|
}
|
|
|
|
u16_t zfStaAddIbssAdditionalIE(zdev_t* dev, zbuf_t* buf, u16_t offset)
|
|
{
|
|
u16_t i;
|
|
|
|
zmw_get_wlan_dev(dev);
|
|
|
|
for (i=0; i<wd->sta.ibssAdditionalIESize; i++)
|
|
{
|
|
zmw_tx_buf_writeb(dev, buf, offset++, wd->sta.ibssAdditionalIE[i]);
|
|
}
|
|
|
|
return offset;
|
|
}
|