2142 lines
73 KiB
C
2142 lines
73 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.
|
||
*/
|
||
/* */
|
||
/* Module Name : mm.c */
|
||
/* */
|
||
/* Abstract */
|
||
/* This module contains common functions for handle management */
|
||
/* frame. */
|
||
/* */
|
||
/* NOTES */
|
||
/* None */
|
||
/* */
|
||
/************************************************************************/
|
||
#include "cprecomp.h"
|
||
#include "../hal/hpreg.h"
|
||
|
||
/* TODO : put all constant tables to a file */
|
||
const u8_t zg11bRateTbl[4] = {2, 4, 11, 22};
|
||
const u8_t zg11gRateTbl[8] = {12, 18, 24, 36, 48, 72, 96, 108};
|
||
|
||
/* 0xff => element does not exist */
|
||
const u8_t zgElementOffsetTable[] =
|
||
{
|
||
4, /* 0 : asoc req */
|
||
6, /* 1 : asoc rsp */
|
||
10, /* 2 : reasoc req*/
|
||
6, /* 3 : reasoc rsp */
|
||
0, /* 4 : probe req */
|
||
12, /* 5 : probe rsp */
|
||
0xff, /* 6 : reserved */
|
||
0xff, /* 7 : reserved */
|
||
12, /* 8 : beacon */
|
||
4, /* 9 : ATIM */
|
||
0xff, /* 10 : disasoc */
|
||
6, /* 11 : auth */
|
||
0xff, /* 12 : deauth */
|
||
4, /* 13 : action */
|
||
0xff, /* 14 : reserved */
|
||
0xff, /* 15 : reserved */
|
||
};
|
||
|
||
/************************************************************************/
|
||
/* */
|
||
/* FUNCTION DESCRIPTION zfFindElement */
|
||
/* Find a specific element in management frame */
|
||
/* */
|
||
/* INPUTS */
|
||
/* dev : device pointer */
|
||
/* buf : management frame buffer */
|
||
/* eid : target element id */
|
||
/* */
|
||
/* OUTPUTS */
|
||
/* byte offset of target element */
|
||
/* or 0xffff if not found */
|
||
/* */
|
||
/* AUTHOR */
|
||
/* Stephen Chen ZyDAS Technology Corporation 2005.10 */
|
||
/* */
|
||
/************************************************************************/
|
||
u16_t zfFindElement(zdev_t* dev, zbuf_t* buf, u8_t eid)
|
||
{
|
||
u8_t subType;
|
||
u16_t offset;
|
||
u16_t bufLen;
|
||
u16_t elen;
|
||
u8_t id, HTEid=0;
|
||
u8_t oui[4] = {0x00, 0x50, 0xf2, 0x01};
|
||
u8_t oui11n[3] = {0x00,0x90,0x4C};
|
||
u8_t HTType = 0;
|
||
|
||
/* Get offset of first element */
|
||
subType = (zmw_rx_buf_readb(dev, buf, 0) >> 4);
|
||
if ((offset = zgElementOffsetTable[subType]) == 0xff)
|
||
{
|
||
zm_assert(0);
|
||
}
|
||
|
||
/* Plus wlan header */
|
||
offset += 24;
|
||
|
||
// jhlee HT 0
|
||
|
||
if ((eid == ZM_WLAN_EID_HT_CAPABILITY) ||
|
||
(eid == ZM_WLAN_EID_EXTENDED_HT_CAPABILITY))
|
||
{
|
||
HTEid = eid;
|
||
eid = ZM_WLAN_EID_WPA_IE;
|
||
HTType = 1;
|
||
}
|
||
|
||
|
||
bufLen = zfwBufGetSize(dev, buf);
|
||
/* Search loop */
|
||
while ((offset+2)<bufLen) // including element ID and length (2bytes)
|
||
{
|
||
/* Search target element */
|
||
if ((id = zmw_rx_buf_readb(dev, buf, offset)) == eid)
|
||
{
|
||
/* Bingo */
|
||
if ((elen = zmw_rx_buf_readb(dev, buf, offset+1))>(bufLen - offset))
|
||
{
|
||
/* Element length error */
|
||
return 0xffff;
|
||
}
|
||
|
||
if ( elen == 0 && eid != ZM_WLAN_EID_SSID)
|
||
{
|
||
/* Element length error */
|
||
return 0xffff;
|
||
}
|
||
|
||
if ( eid == ZM_WLAN_EID_WPA_IE )
|
||
{
|
||
/* avoid sta to be thought use 11n when find a WPA_IE */
|
||
if ( (HTType == 0) && zfRxBufferEqualToStr(dev, buf, oui, offset+2, 4) )
|
||
{
|
||
return offset;
|
||
}
|
||
|
||
// jhlee HT 0
|
||
// CWYang(+)
|
||
|
||
if ((HTType == 1) && ( zfRxBufferEqualToStr(dev, buf, oui11n, offset+2, 3) ))
|
||
{
|
||
if ( zmw_rx_buf_readb(dev, buf, offset+5) == HTEid )
|
||
{
|
||
return offset + 5;
|
||
}
|
||
}
|
||
|
||
}
|
||
else
|
||
{
|
||
return offset;
|
||
}
|
||
}
|
||
/* Advance to next element */
|
||
#if 1
|
||
elen = zmw_rx_buf_readb(dev, buf, offset+1);
|
||
#else
|
||
if ((elen = zmw_rx_buf_readb(dev, buf, offset+1)) == 0)
|
||
{
|
||
return 0xffff;
|
||
}
|
||
#endif
|
||
|
||
offset += (elen+2);
|
||
}
|
||
return 0xffff;
|
||
}
|
||
|
||
|
||
/************************************************************************/
|
||
/* */
|
||
/* FUNCTION DESCRIPTION zfFindWifiElement */
|
||
/* Find a specific Wifi element in management frame */
|
||
/* */
|
||
/* INPUTS */
|
||
/* dev : device pointer */
|
||
/* buf : management frame buffer */
|
||
/* type : OUI type */
|
||
/* subType : OUI subtype */
|
||
/* */
|
||
/* OUTPUTS */
|
||
/* byte offset of target element */
|
||
/* or 0xffff if not found */
|
||
/* */
|
||
/* AUTHOR */
|
||
/* Stephen Chen ZyDAS Technology Corporation 2006.1 */
|
||
/* */
|
||
/************************************************************************/
|
||
u16_t zfFindWifiElement(zdev_t* dev, zbuf_t* buf, u8_t type, u8_t subtype)
|
||
{
|
||
u8_t subType;
|
||
u16_t offset;
|
||
u16_t bufLen;
|
||
u16_t elen;
|
||
u8_t id;
|
||
u8_t tmp;
|
||
|
||
/* Get offset of first element */
|
||
subType = (zmw_rx_buf_readb(dev, buf, 0) >> 4);
|
||
|
||
if ((offset = zgElementOffsetTable[subType]) == 0xff)
|
||
{
|
||
zm_assert(0);
|
||
}
|
||
|
||
/* Plus wlan header */
|
||
offset += 24;
|
||
|
||
bufLen = zfwBufGetSize(dev, buf);
|
||
/* Search loop */
|
||
while ((offset+2)<bufLen) // including element ID and length (2bytes)
|
||
{
|
||
/* Search target element */
|
||
if ((id = zmw_rx_buf_readb(dev, buf, offset)) == ZM_WLAN_EID_WIFI_IE)
|
||
{
|
||
/* Bingo */
|
||
if ((elen = zmw_rx_buf_readb(dev, buf, offset+1))>(bufLen - offset))
|
||
{
|
||
/* Element length error */
|
||
return 0xffff;
|
||
}
|
||
|
||
if ( elen == 0 )
|
||
{
|
||
return 0xffff;
|
||
}
|
||
|
||
if (((tmp = zmw_rx_buf_readb(dev, buf, offset+2)) == 0x00)
|
||
&& ((tmp = zmw_rx_buf_readb(dev, buf, offset+3)) == 0x50)
|
||
&& ((tmp = zmw_rx_buf_readb(dev, buf, offset+4)) == 0xF2)
|
||
&& ((tmp = zmw_rx_buf_readb(dev, buf, offset+5)) == type))
|
||
|
||
{
|
||
if ( subtype != 0xff )
|
||
{
|
||
if ( (tmp = zmw_rx_buf_readb(dev, buf, offset+6)) == subtype )
|
||
{
|
||
return offset;
|
||
}
|
||
}
|
||
else
|
||
{
|
||
return offset;
|
||
}
|
||
}
|
||
}
|
||
/* Advance to next element */
|
||
if ((elen = zmw_rx_buf_readb(dev, buf, offset+1)) == 0)
|
||
{
|
||
return 0xffff;
|
||
}
|
||
offset += (elen+2);
|
||
}
|
||
return 0xffff;
|
||
}
|
||
|
||
u16_t zfRemoveElement(zdev_t* dev, u8_t* buf, u16_t size, u8_t eid)
|
||
{
|
||
u16_t offset = 0;
|
||
u16_t elen;
|
||
u8_t HTEid = 0;
|
||
u8_t oui[4] = {0x00, 0x50, 0xf2, 0x01};
|
||
u8_t oui11n[3] = {0x00,0x90,0x4C};
|
||
u8_t HTType = 0;
|
||
|
||
if ((eid == ZM_WLAN_EID_HT_CAPABILITY) ||
|
||
(eid == ZM_WLAN_EID_EXTENDED_HT_CAPABILITY))
|
||
{
|
||
HTEid = eid;
|
||
eid = ZM_WLAN_EID_WPA_IE;
|
||
HTType = 1;
|
||
}
|
||
|
||
while (offset < size)
|
||
{
|
||
elen = *(buf+offset+1);
|
||
|
||
if (*(buf+offset) == eid)
|
||
{
|
||
if ( eid == ZM_WLAN_EID_WPA_IE )
|
||
{
|
||
if ( (HTType == 0)
|
||
&& (*(buf+offset+2) == oui[0])
|
||
&& (*(buf+offset+3) == oui[1])
|
||
&& (*(buf+offset+4) == oui[2])
|
||
&& (*(buf+offset+5) == oui[3]) )
|
||
{
|
||
zfMemoryMove(buf+offset, buf+offset+elen+2, size-offset-elen-2);
|
||
return (size-elen-2);
|
||
}
|
||
|
||
if ( (HTType == 1)
|
||
&& (*(buf+offset+2) == oui11n[0])
|
||
&& (*(buf+offset+3) == oui11n[1])
|
||
&& (*(buf+offset+4) == oui11n[2])
|
||
&& (*(buf+offset+5) == HTEid) )
|
||
{
|
||
zfMemoryMove(buf+offset, buf+offset+elen+2, size-offset-elen-2);
|
||
return (size-elen-2);
|
||
}
|
||
}
|
||
else
|
||
{
|
||
zfMemoryMove(buf+offset, buf+offset+elen+2, size-offset-elen-2);
|
||
return (size-elen-2);
|
||
}
|
||
}
|
||
|
||
offset += (elen+2);
|
||
}
|
||
|
||
return size;
|
||
}
|
||
|
||
u16_t zfUpdateElement(zdev_t* dev, u8_t* buf, u16_t size, u8_t* updateeid)
|
||
{
|
||
u16_t offset = 0;
|
||
u16_t elen;
|
||
|
||
while (offset < size) {
|
||
elen = *(buf+offset+1);
|
||
|
||
if (*(buf+offset) == updateeid[0]) {
|
||
if (updateeid[1] <= elen) {
|
||
zfMemoryMove(buf+offset, updateeid, updateeid[1]+2);
|
||
zfMemoryMove(buf+offset+updateeid[1]+2, buf+offset+elen+2, size-offset-elen-2);
|
||
|
||
return size-(elen-updateeid[1]);
|
||
} else {
|
||
zfMemoryMove(buf+offset+updateeid[1]+2, buf+offset+elen+2, size-offset-elen-2);
|
||
zfMemoryMove(buf+offset, updateeid, updateeid[1]+2);
|
||
|
||
return size+(updateeid[1]-elen);
|
||
}
|
||
}
|
||
|
||
offset += (elen+2);
|
||
}
|
||
|
||
return size;
|
||
}
|
||
|
||
u16_t zfFindSuperGElement(zdev_t* dev, zbuf_t* buf, u8_t type)
|
||
{
|
||
u8_t subType;
|
||
u16_t offset;
|
||
u16_t bufLen;
|
||
u16_t elen;
|
||
u8_t id;
|
||
u8_t super_feature;
|
||
u8_t ouiSuperG[6] = {0x00,0x03,0x7f,0x01, 0x01, 0x00};
|
||
|
||
zmw_get_wlan_dev(dev);
|
||
|
||
/* Get offset of first element */
|
||
subType = (zmw_rx_buf_readb(dev, buf, 0) >> 4);
|
||
if ((offset = zgElementOffsetTable[subType]) == 0xff)
|
||
{
|
||
zm_assert(0);
|
||
}
|
||
|
||
/* Plus wlan header */
|
||
offset += 24;
|
||
|
||
bufLen = zfwBufGetSize(dev, buf);
|
||
/* Search loop */
|
||
while ((offset+2)<bufLen) // including element ID and length (2bytes)
|
||
{
|
||
/* Search target element */
|
||
if ((id = zmw_rx_buf_readb(dev, buf, offset)) == ZM_WLAN_EID_VENDOR_PRIVATE)
|
||
{
|
||
/* Bingo */
|
||
if ((elen = zmw_rx_buf_readb(dev, buf, offset+1))>(bufLen - offset))
|
||
{
|
||
/* Element length error */
|
||
return 0xffff;
|
||
}
|
||
|
||
if ( elen == 0 )
|
||
{
|
||
return 0xffff;
|
||
}
|
||
|
||
if (zfRxBufferEqualToStr(dev, buf, ouiSuperG, offset+2, 6) && ( zmw_rx_buf_readb(dev, buf, offset+1) >= 6))
|
||
{
|
||
/* super_feature 0:useFastFrame, 1:useCompression, 2:useTurboPrime */
|
||
super_feature= zmw_rx_buf_readb(dev, buf, offset+8);
|
||
if ((super_feature & 0x01) || (super_feature & 0x02) || (super_feature & 0x04))
|
||
{
|
||
return offset;
|
||
}
|
||
}
|
||
}
|
||
/* Advance to next element */
|
||
#if 1
|
||
elen = zmw_rx_buf_readb(dev, buf, offset+1);
|
||
#else
|
||
if ((elen = zmw_rx_buf_readb(dev, buf, offset+1)) == 0)
|
||
{
|
||
return 0xffff;
|
||
}
|
||
#endif
|
||
|
||
offset += (elen+2);
|
||
}
|
||
return 0xffff;
|
||
}
|
||
|
||
u16_t zfFindXRElement(zdev_t* dev, zbuf_t* buf, u8_t type)
|
||
{
|
||
u8_t subType;
|
||
u16_t offset;
|
||
u16_t bufLen;
|
||
u16_t elen;
|
||
u8_t id;
|
||
u8_t ouixr[6] = {0x00,0x03,0x7f,0x03, 0x01, 0x00};
|
||
|
||
zmw_get_wlan_dev(dev);
|
||
|
||
/* Get offset of first element */
|
||
subType = (zmw_rx_buf_readb(dev, buf, 0) >> 4);
|
||
if ((offset = zgElementOffsetTable[subType]) == 0xff)
|
||
{
|
||
zm_assert(0);
|
||
}
|
||
|
||
/* Plus wlan header */
|
||
offset += 24;
|
||
|
||
bufLen = zfwBufGetSize(dev, buf);
|
||
/* Search loop */
|
||
while ((offset+2)<bufLen) // including element ID and length (2bytes)
|
||
{
|
||
/* Search target element */
|
||
if ((id = zmw_rx_buf_readb(dev, buf, offset)) == ZM_WLAN_EID_VENDOR_PRIVATE)
|
||
{
|
||
/* Bingo */
|
||
if ((elen = zmw_rx_buf_readb(dev, buf, offset+1))>(bufLen - offset))
|
||
{
|
||
/* Element length error */
|
||
return 0xffff;
|
||
}
|
||
|
||
if ( elen == 0 )
|
||
{
|
||
return 0xffff;
|
||
}
|
||
|
||
if (zfRxBufferEqualToStr(dev, buf, ouixr, offset+2, 6) && ( zmw_rx_buf_readb(dev, buf, offset+1) >= 6))
|
||
{
|
||
return offset;
|
||
}
|
||
}
|
||
/* Advance to next element */
|
||
#if 1
|
||
elen = zmw_rx_buf_readb(dev, buf, offset+1);
|
||
#else
|
||
if ((elen = zmw_rx_buf_readb(dev, buf, offset+1)) == 0)
|
||
{
|
||
return 0xffff;
|
||
}
|
||
#endif
|
||
|
||
offset += (elen+2);
|
||
}
|
||
return 0xffff;
|
||
}
|
||
|
||
/************************************************************************/
|
||
/* */
|
||
/* FUNCTION DESCRIPTION zfMmAddIeSupportRate */
|
||
/* Add information element Support Rate to buffer. */
|
||
/* */
|
||
/* INPUTS */
|
||
/* dev : device pointer */
|
||
/* buf : buffer to add information element */
|
||
/* offset : add information element from this offset */
|
||
/* eid : element ID */
|
||
/* rateSet : CCK or OFDM */
|
||
/* */
|
||
/* OUTPUTS */
|
||
/* buffer offset after adding information element */
|
||
/* */
|
||
/* AUTHOR */
|
||
/* Stephen Chen ZyDAS Technology Corporation 2005.10 */
|
||
/* */
|
||
/************************************************************************/
|
||
u16_t zfMmAddIeSupportRate(zdev_t* dev, zbuf_t* buf, u16_t offset, u8_t eid, u8_t rateSet)
|
||
{
|
||
u8_t len = 0;
|
||
u16_t i;
|
||
|
||
zmw_get_wlan_dev(dev);
|
||
|
||
//if ( (rateSet == ZM_RATE_SET_OFDM)&&((wd->gRate & 0xff) == 0) )
|
||
//{
|
||
// return offset;
|
||
//}
|
||
|
||
/* Information : Support Rate */
|
||
if ( rateSet == ZM_RATE_SET_CCK )
|
||
{
|
||
for (i=0; i<4; i++)
|
||
{
|
||
if ((wd->bRate & (0x1<<i)) == (0x1<<i))
|
||
//if ((0xf & (0x1<<i)) == (0x1<<i))
|
||
{
|
||
zmw_tx_buf_writeb(dev, buf, offset+len+2,
|
||
zg11bRateTbl[i]+((wd->bRateBasic & (0x1<<i))<<(7-i)));
|
||
len++;
|
||
}
|
||
}
|
||
}
|
||
else if ( rateSet == ZM_RATE_SET_OFDM )
|
||
{
|
||
for (i=0; i<8; i++)
|
||
{
|
||
if ((wd->gRate & (0x1<<i)) == (0x1<<i))
|
||
//if ((0xff & (0x1<<i)) == (0x1<<i))
|
||
{
|
||
zmw_tx_buf_writeb(dev, buf, offset+len+2,
|
||
zg11gRateTbl[i]+((wd->gRateBasic & (0x1<<i))<<(7-i)));
|
||
len++;
|
||
}
|
||
}
|
||
}
|
||
|
||
if (len > 0)
|
||
{
|
||
/* Element ID */
|
||
zmw_tx_buf_writeb(dev, buf, offset, eid);
|
||
|
||
/* Element Length */
|
||
zmw_tx_buf_writeb(dev, buf, offset+1, len);
|
||
|
||
/* Return value */
|
||
offset += (2+len);
|
||
}
|
||
|
||
return offset;
|
||
}
|
||
|
||
/************************************************************************/
|
||
/* */
|
||
/* FUNCTION DESCRIPTION zfMmAddIeDs */
|
||
/* Add information element DS 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 2005.10 */
|
||
/* */
|
||
/************************************************************************/
|
||
u16_t zfMmAddIeDs(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_DS);
|
||
|
||
/* Element Length */
|
||
zmw_tx_buf_writeb(dev, buf, offset++, 1);
|
||
|
||
/* Information : DS */
|
||
zmw_tx_buf_writeb(dev, buf, offset++,
|
||
zfChFreqToNum(wd->frequency, NULL));
|
||
|
||
return offset;
|
||
}
|
||
|
||
|
||
/************************************************************************/
|
||
/* */
|
||
/* FUNCTION DESCRIPTION zfMmAddIeErp */
|
||
/* Add information element ERP 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 2005.10 */
|
||
/* */
|
||
/************************************************************************/
|
||
u16_t zfMmAddIeErp(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_ERP);
|
||
|
||
/* Element Length */
|
||
zmw_tx_buf_writeb(dev, buf, offset++, 1);
|
||
|
||
/* Information : ERP */
|
||
zmw_tx_buf_writeb(dev, buf, offset++, wd->erpElement);
|
||
|
||
return offset;
|
||
}
|
||
|
||
|
||
/************************************************************************/
|
||
/* */
|
||
/* FUNCTION DESCRIPTION zfMmAddIeWpa */
|
||
/* Add information element WPA 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 */
|
||
/* Yuan-Gu Wei ZyDAS Technology Corporation 2006.2 */
|
||
/* */
|
||
/************************************************************************/
|
||
u16_t zfMmAddIeWpa(zdev_t* dev, zbuf_t* buf, u16_t offset, u16_t apId)
|
||
{
|
||
//struct zsWlanDev* wd = (struct zsWlanDev*) zmw_wlan_dev(dev);
|
||
int i;
|
||
|
||
zmw_get_wlan_dev(dev);
|
||
|
||
/* Element ID */
|
||
//zmw_inttx_buf_writeb(dev, buf, offset++, ZM_WLAN_EID_WPA_IE);
|
||
|
||
/* Element Length */
|
||
//zmw_inttx_buf_writeb(dev, buf, offset++, wd->ap.wpaLen);
|
||
for(i = 0; i < wd->ap.wpaLen[apId]; i++)
|
||
{
|
||
/* Information : WPA */
|
||
zmw_tx_buf_writeb(dev, buf, offset++, wd->ap.wpaIe[apId][i]);
|
||
}
|
||
|
||
return offset;
|
||
}
|
||
|
||
/************************************************************************/
|
||
/* */
|
||
/* FUNCTION DESCRIPTION zfMmAddHTCapability */
|
||
/* Add HT Capability Infomation 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 */
|
||
/* Chao-Wen Yang ZyDAS Technology Corporation 2006.06 */
|
||
/* */
|
||
/************************************************************************/
|
||
u16_t zfMmAddHTCapability(zdev_t* dev, zbuf_t* buf, u16_t offset)
|
||
{
|
||
u8_t OUI[3] = {0x0,0x90,0x4C};
|
||
u16_t i;
|
||
|
||
zmw_get_wlan_dev(dev);
|
||
|
||
/* Prob ID */
|
||
zmw_buf_writeb(dev, buf, offset++, ZM_WLAN_EID_WPA_IE);
|
||
|
||
if ( wd->wlanMode == ZM_MODE_AP )
|
||
{
|
||
/* Element Length */
|
||
zmw_buf_writeb(dev, buf, offset++, wd->ap.HTCap.Data.Length + 4);
|
||
|
||
/* OUI Data */
|
||
for (i = 0; i < 3; i++)
|
||
{
|
||
zmw_buf_writeb(dev, buf, offset++, OUI[i]);
|
||
}
|
||
|
||
/* Element Type ID */
|
||
zmw_buf_writeb(dev, buf, offset++, wd->ap.HTCap.Data.ElementID);
|
||
|
||
/* HT Capability Data */
|
||
for (i = 0; i < 26; i++)
|
||
{
|
||
zmw_buf_writeb(dev, buf, offset++, wd->ap.HTCap.Byte[i+2]);
|
||
}
|
||
}
|
||
else
|
||
{
|
||
/* Element Length */
|
||
zmw_buf_writeb(dev, buf, offset++, wd->sta.HTCap.Data.Length + 4);
|
||
|
||
/* OUI Data */
|
||
for (i = 0; i < 3; i++)
|
||
{
|
||
zmw_buf_writeb(dev, buf, offset++, OUI[i]);
|
||
}
|
||
|
||
/* Element Type ID */
|
||
zmw_buf_writeb(dev, buf, offset++, wd->sta.HTCap.Data.ElementID);
|
||
|
||
/* HT Capability Data */
|
||
for (i = 0; i < 26; i++)
|
||
{
|
||
zmw_buf_writeb(dev, buf, offset++, wd->sta.HTCap.Byte[i+2]);
|
||
}
|
||
}
|
||
|
||
return offset;
|
||
}
|
||
|
||
|
||
u16_t zfMmAddPreNHTCapability(zdev_t* dev, zbuf_t* buf, u16_t offset)
|
||
{
|
||
//u8_t OUI[3] = {0x0,0x90,0x4C};
|
||
u16_t i;
|
||
|
||
zmw_get_wlan_dev(dev);
|
||
|
||
/* Prob ID */
|
||
zmw_buf_writeb(dev, buf, offset++, ZM_WLAN_PREN2_EID_HTCAPABILITY);
|
||
|
||
if ( wd->wlanMode == ZM_MODE_AP )
|
||
{
|
||
/* Element Length */
|
||
zmw_buf_writeb(dev, buf, offset++, wd->ap.HTCap.Data.Length);
|
||
|
||
/* HT Capability Data */
|
||
for (i = 0; i < 26; i++)
|
||
{
|
||
zmw_buf_writeb(dev, buf, offset++, wd->ap.HTCap.Byte[i+2]);
|
||
}
|
||
}
|
||
else
|
||
{
|
||
/* Element Length */
|
||
zmw_buf_writeb(dev, buf, offset++, wd->sta.HTCap.Data.Length);
|
||
|
||
/* HT Capability Data */
|
||
for (i = 0; i < 26; i++)
|
||
{
|
||
zmw_buf_writeb(dev, buf, offset++, wd->sta.HTCap.Byte[i+2]);
|
||
}
|
||
}
|
||
|
||
return offset;
|
||
}
|
||
|
||
/************************************************************************/
|
||
/* */
|
||
/* FUNCTION DESCRIPTION zfMmAddExtendedHTCapability */
|
||
/* Add Extended HT Capability Infomation 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 */
|
||
/* Chao-Wen Yang ZyDAS Technology Corporation 2006.06 */
|
||
/* */
|
||
/************************************************************************/
|
||
u16_t zfMmAddExtendedHTCapability(zdev_t* dev, zbuf_t* buf, u16_t offset)
|
||
{
|
||
u8_t OUI[3] = {0x0,0x90,0x4C};
|
||
u16_t i;
|
||
|
||
zmw_get_wlan_dev(dev);
|
||
|
||
/* Prob ID */
|
||
zmw_buf_writeb(dev, buf, offset++, ZM_WLAN_EID_WPA_IE);
|
||
|
||
if ( wd->wlanMode == ZM_MODE_AP )
|
||
{
|
||
/* Element Length */
|
||
zmw_buf_writeb(dev, buf, offset++, wd->ap.ExtHTCap.Data.Length + 4);
|
||
|
||
/* OUI Data */
|
||
for (i = 0; i < 3; i++)
|
||
{
|
||
zmw_buf_writeb(dev, buf, offset++, OUI[i]);
|
||
}
|
||
|
||
/* Element Type ID */
|
||
zmw_buf_writeb(dev, buf, offset++, wd->ap.ExtHTCap.Data.ElementID);
|
||
|
||
/* HT Capability Data */
|
||
for (i = 0; i < 22; i++)
|
||
{
|
||
zmw_buf_writeb(dev, buf, offset++, wd->ap.ExtHTCap.Byte[i+2]);
|
||
}
|
||
}
|
||
else
|
||
{
|
||
/* Element Length */
|
||
zmw_buf_writeb(dev, buf, offset++, wd->sta.ExtHTCap.Data.Length + 4);
|
||
|
||
/* OUI Data */
|
||
for (i = 0; i < 3; i++)
|
||
{
|
||
zmw_buf_writeb(dev, buf, offset++, OUI[i]);
|
||
}
|
||
|
||
/* Element Type ID */
|
||
zmw_buf_writeb(dev, buf, offset++, wd->sta.ExtHTCap.Data.ElementID);
|
||
|
||
/* HT Capability Data */
|
||
for (i = 0; i < 22; i++)
|
||
{
|
||
zmw_buf_writeb(dev, buf, offset++, wd->sta.ExtHTCap.Byte[i+2]);
|
||
}
|
||
}
|
||
|
||
return offset;
|
||
}
|
||
|
||
|
||
|
||
/************************************************************************/
|
||
/* */
|
||
/* FUNCTION DESCRIPTION zfSendMmFrame */
|
||
/* Send management frame. */
|
||
/* */
|
||
/* INPUTS */
|
||
/* dev : device pointer */
|
||
/* frameType : management frame type */
|
||
/* dst : destination MAC address */
|
||
/* p1 : parameter 1 */
|
||
/* p2 : parameter 2 */
|
||
/* p3 : parameter 3 */
|
||
/* */
|
||
/* OUTPUTS */
|
||
/* none */
|
||
/* */
|
||
/* AUTHOR */
|
||
/* Stephen Chen ZyDAS Technology Corporation 2005.10 */
|
||
/* */
|
||
/************************************************************************/
|
||
/* probe req : p1=> bWithSSID, p2=>R, p3=>R */
|
||
/* probe rsp : p1=>R, p2=>R, p3=>VAP ID(AP) */
|
||
/* deauth : p1=>Reason Code, p2=>R, p3=>VAP ID(AP) */
|
||
/* Disasoc : p1=>Reason Code, p2=>R, p3=>VAP ID(AP) */
|
||
/* ATIM : p1=>R, p2=>R, p3=>R */
|
||
/* (re)asoc rsp : p1=>Status Code, p2=>AID, p3=>VAP ID(AP) */
|
||
/* asoc req : p1=>R, p2=>R, p3=>R */
|
||
/* reasoc req : p1=>AP MAC[0], p2=>AP MAC[1], p3=>AP MAC[2] */
|
||
/* auth : p1=>low=Algorithm, high=Transaction, p2=>Status, p3=>VAP ID */
|
||
void zfSendMmFrame(zdev_t* dev, u8_t frameType, u16_t* dst,
|
||
u32_t p1, u32_t p2, u32_t p3)
|
||
{
|
||
zbuf_t* buf;
|
||
//u16_t addrTblSize;
|
||
//struct zsAddrTbl addrTbl;
|
||
u16_t offset = 0;
|
||
u16_t hlen = 32;
|
||
u16_t header[(24+25+1)/2];
|
||
u16_t vap = 0;
|
||
u16_t i;
|
||
u8_t encrypt = 0;
|
||
u16_t aid;
|
||
|
||
zmw_get_wlan_dev(dev);
|
||
zmw_declare_for_critical_section();
|
||
|
||
zm_msg2_mm(ZM_LV_2, "Send mm frame, type=", frameType);
|
||
/* TBD : Maximum size of management frame */
|
||
if ((buf = zfwBufAllocate(dev, 1024)) == NULL)
|
||
{
|
||
zm_msg0_mm(ZM_LV_0, "Alloc mm buf Fail!");
|
||
return;
|
||
}
|
||
|
||
//Reserve room for wlan header
|
||
offset = hlen;
|
||
|
||
switch (frameType)
|
||
{
|
||
case ZM_WLAN_FRAME_TYPE_PROBEREQ :
|
||
offset = zfSendProbeReq(dev, buf, offset, (u8_t) p1);
|
||
break;
|
||
|
||
case ZM_WLAN_FRAME_TYPE_PROBERSP :
|
||
zm_msg0_mm(ZM_LV_3, "probe rsp");
|
||
/* 24-31 Time Stamp : hardware WON'T fill this field */
|
||
zmw_tx_buf_writeh(dev, buf, offset, 0);
|
||
zmw_tx_buf_writeh(dev, buf, offset+2, 0);
|
||
zmw_tx_buf_writeh(dev, buf, offset+4, 0);
|
||
zmw_tx_buf_writeh(dev, buf, offset+6, 0);
|
||
offset+=8;
|
||
|
||
/* Beacon Interval */
|
||
zmw_tx_buf_writeh(dev, buf, offset, wd->beaconInterval);
|
||
offset+=2;
|
||
|
||
if (wd->wlanMode == ZM_MODE_AP)
|
||
{
|
||
vap = (u16_t) p3;
|
||
/* Capability */
|
||
zmw_tx_buf_writeh(dev, buf, offset, wd->ap.capab[vap]);
|
||
offset+=2;
|
||
/* SSID */
|
||
offset = zfApAddIeSsid(dev, buf, offset, vap);
|
||
}
|
||
else
|
||
{
|
||
/* 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);
|
||
}
|
||
|
||
/* Support Rate */
|
||
if ( wd->frequency < 3000 )
|
||
{
|
||
offset = zfMmAddIeSupportRate(dev, buf, offset,
|
||
ZM_WLAN_EID_SUPPORT_RATE, ZM_RATE_SET_CCK);
|
||
}
|
||
else
|
||
{
|
||
offset = zfMmAddIeSupportRate(dev, buf, offset,
|
||
ZM_WLAN_EID_SUPPORT_RATE, ZM_RATE_SET_OFDM);
|
||
}
|
||
|
||
/* DS parameter set */
|
||
offset = zfMmAddIeDs(dev, buf, offset);
|
||
|
||
/* TODO <20>G IBSS */
|
||
if ( wd->wlanMode == ZM_MODE_IBSS )
|
||
{
|
||
offset = zfStaAddIeIbss(dev, buf, offset);
|
||
|
||
if (wd->frequency < 3000)
|
||
{
|
||
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);
|
||
|
||
/* Enable G Mode */
|
||
/* Extended Supported Rates */
|
||
offset = zfMmAddIeSupportRate(dev, buf, offset,
|
||
ZM_WLAN_EID_EXTENDED_RATE, ZM_RATE_SET_OFDM);
|
||
}
|
||
}
|
||
}
|
||
|
||
|
||
if ((wd->wlanMode == ZM_MODE_AP)
|
||
&& (wd->ap.wlanType[vap] != ZM_WLAN_TYPE_PURE_B))
|
||
{
|
||
/* ERP Information */
|
||
offset = zfMmAddIeErp(dev, buf, offset);
|
||
|
||
/* Extended Supported Rates */
|
||
if ( wd->frequency < 3000 )
|
||
{
|
||
offset = zfMmAddIeSupportRate(dev, buf, offset,
|
||
ZM_WLAN_EID_EXTENDED_RATE, ZM_RATE_SET_OFDM);
|
||
}
|
||
}
|
||
|
||
/* ERP Information */
|
||
//offset = zfMmAddIeErp(dev, buf, offset);
|
||
|
||
/* Extended Supported Rates */
|
||
//offset = zfMmAddIeSupportRate(dev, buf, offset,
|
||
// ZM_WLAN_EID_EXTENDED_RATE, ZM_RATE_SET_OFDM);
|
||
|
||
/* TODO : RSN */
|
||
if (wd->wlanMode == ZM_MODE_AP && wd->ap.wpaSupport[vap] == 1)
|
||
{
|
||
offset = zfMmAddIeWpa(dev, buf, offset, vap);
|
||
}
|
||
else if ( wd->wlanMode == ZM_MODE_IBSS && wd->sta.authMode == ZM_AUTH_MODE_WPA2PSK)
|
||
{
|
||
offset = zfwStaAddIeWpaRsn(dev, buf, offset, ZM_WLAN_FRAME_TYPE_AUTH);
|
||
}
|
||
|
||
/* WME Parameters */
|
||
if (wd->wlanMode == ZM_MODE_AP)
|
||
{
|
||
if (wd->ap.qosMode == 1)
|
||
{
|
||
offset = zfApAddIeWmePara(dev, buf, offset, vap);
|
||
}
|
||
}
|
||
|
||
if ( wd->wlanMode != ZM_MODE_IBSS )
|
||
{
|
||
// jhlee HT 0
|
||
//CWYang(+)
|
||
/* TODO : Need to check if it is ok */
|
||
/* HT Capabilities Info */
|
||
offset = zfMmAddHTCapability(dev, buf, offset);
|
||
//CWYang(+)
|
||
/* Extended HT Capabilities Info */
|
||
offset = zfMmAddExtendedHTCapability(dev, buf, offset);
|
||
}
|
||
|
||
if ( wd->sta.ibssAdditionalIESize )
|
||
offset = zfStaAddIbssAdditionalIE(dev, buf, offset);
|
||
break;
|
||
|
||
case ZM_WLAN_FRAME_TYPE_AUTH :
|
||
if (p1 == 0x30001)
|
||
{
|
||
hlen += 4;
|
||
offset += 4; // for reserving wep header
|
||
encrypt = 1;
|
||
}
|
||
|
||
/* Algotrithm Number */
|
||
zmw_tx_buf_writeh(dev, buf, offset, (u16_t)(p1&0xffff));
|
||
offset+=2;
|
||
|
||
/* Transaction Number */
|
||
zmw_tx_buf_writeh(dev, buf, offset, (u16_t)(p1>>16));
|
||
offset+=2;
|
||
|
||
/* Status Code */
|
||
zmw_tx_buf_writeh(dev, buf, offset, (u16_t)p2);
|
||
offset+=2;
|
||
|
||
if (wd->wlanMode == ZM_MODE_AP)
|
||
{
|
||
vap = (u16_t) p3;
|
||
}
|
||
|
||
/* Challenge Text => share-2 or share-3 */
|
||
if (p1 == 0x20001)
|
||
{
|
||
if (p2 == 0) //Status == success
|
||
{
|
||
zmw_buf_writeh(dev, buf, offset, 0x8010);
|
||
offset+=2;
|
||
/* share-2 : AP generate challenge text */
|
||
for (i=0; i<128; i++)
|
||
{
|
||
wd->ap.challengeText[i] = (u8_t)zfGetRandomNumber(dev, 0);
|
||
}
|
||
zfCopyToIntTxBuffer(dev, buf, wd->ap.challengeText, offset, 128);
|
||
offset += 128;
|
||
}
|
||
}
|
||
else if (p1 == 0x30001)
|
||
{
|
||
/* share-3 : STA return challenge Text */
|
||
zfCopyToIntTxBuffer(dev, buf, wd->sta.challengeText, offset, wd->sta.challengeText[1]+2);
|
||
offset += (wd->sta.challengeText[1]+2);
|
||
}
|
||
|
||
break;
|
||
|
||
case ZM_WLAN_FRAME_TYPE_ASOCREQ :
|
||
case ZM_WLAN_FRAME_TYPE_REASOCREQ :
|
||
/* Capability */
|
||
zmw_tx_buf_writeb(dev, buf, offset++, wd->sta.capability[0]);
|
||
zmw_tx_buf_writeb(dev, buf, offset++, wd->sta.capability[1]);
|
||
|
||
/* Listen Interval */
|
||
zmw_tx_buf_writeh(dev, buf, offset, 0x0005);
|
||
offset+=2;
|
||
|
||
/* Reassocaited Request : Current AP address */
|
||
if (frameType == ZM_WLAN_FRAME_TYPE_REASOCREQ)
|
||
{
|
||
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;
|
||
}
|
||
|
||
/* SSID */
|
||
offset = zfStaAddIeSsid(dev, buf, offset);
|
||
|
||
|
||
if ( wd->sta.currentFrequency < 3000 )
|
||
{
|
||
/* Support Rate */
|
||
offset = zfMmAddIeSupportRate(dev, buf, offset, ZM_WLAN_EID_SUPPORT_RATE, ZM_RATE_SET_CCK);
|
||
}
|
||
else
|
||
{
|
||
/* Support Rate */
|
||
offset = zfMmAddIeSupportRate(dev, buf, offset, ZM_WLAN_EID_SUPPORT_RATE, ZM_RATE_SET_OFDM);
|
||
}
|
||
|
||
if ((wd->sta.capability[1] & ZM_BIT_0) == 1)
|
||
{ //spectrum management flag enable
|
||
offset = zfStaAddIePowerCap(dev, buf, offset);
|
||
offset = zfStaAddIeSupportCh(dev, buf, offset);
|
||
}
|
||
|
||
if (wd->sta.currentFrequency < 3000)
|
||
{
|
||
/* Extended Supported Rates */
|
||
if (wd->supportMode & (ZM_WIRELESS_MODE_24_54|ZM_WIRELESS_MODE_24_N))
|
||
{
|
||
offset = zfMmAddIeSupportRate(dev, buf, offset, ZM_WLAN_EID_EXTENDED_RATE, ZM_RATE_SET_OFDM);
|
||
}
|
||
}
|
||
|
||
|
||
//offset = zfStaAddIeWpaRsn(dev, buf, offset, frameType);
|
||
//Move to wrapper function, for OS difference--CWYang(m)
|
||
//for windows wrapper, zfwStaAddIeWpaRsn() should be below:
|
||
//u16_t zfwStaAddIeWpaRsn(zdev_t* dev, zbuf_t* buf, u16_t offset, u8_t frameType)
|
||
//{
|
||
// return zfStaAddIeWpaRsn(dev, buf, offset, frameType);
|
||
//}
|
||
offset = zfwStaAddIeWpaRsn(dev, buf, offset, frameType);
|
||
|
||
#ifdef ZM_ENABLE_CENC
|
||
/* CENC */
|
||
//if (wd->sta.encryMode == ZM_CENC)
|
||
offset = zfStaAddIeCenc(dev, buf, offset);
|
||
#endif //ZM_ENABLE_CENC
|
||
if (((wd->sta.wmeEnabled & ZM_STA_WME_ENABLE_BIT) != 0) //WME enabled
|
||
&& ((wd->sta.apWmeCapability & 0x1) != 0)) //WME AP
|
||
{
|
||
if (((wd->sta.apWmeCapability & 0x80) != 0) //UAPSD AP
|
||
&& ((wd->sta.wmeEnabled & ZM_STA_UAPSD_ENABLE_BIT) != 0)) //UAPSD enabled
|
||
{
|
||
offset = zfStaAddIeWmeInfo(dev, buf, offset, wd->sta.wmeQosInfo);
|
||
}
|
||
else
|
||
{
|
||
offset = zfStaAddIeWmeInfo(dev, buf, offset, 0);
|
||
}
|
||
}
|
||
// jhlee HT 0
|
||
//CWYang(+)
|
||
if (wd->sta.EnableHT != 0)
|
||
{
|
||
#ifndef ZM_DISABLE_AMSDU8K_SUPPORT
|
||
//Support 8K A-MSDU
|
||
if (wd->sta.wepStatus == ZM_ENCRYPTION_WEP_DISABLED)
|
||
{
|
||
wd->sta.HTCap.Data.HtCapInfo |= HTCAP_MaxAMSDULength;
|
||
}
|
||
else
|
||
{
|
||
wd->sta.HTCap.Data.HtCapInfo &= (~HTCAP_MaxAMSDULength);
|
||
}
|
||
#else
|
||
//Support 4K A-MSDU
|
||
wd->sta.HTCap.Data.HtCapInfo &= (~HTCAP_MaxAMSDULength);
|
||
#endif
|
||
|
||
/* HT Capabilities Info */
|
||
if (wd->BandWidth40 == 1) {
|
||
wd->sta.HTCap.Data.HtCapInfo |= HTCAP_SupChannelWidthSet;
|
||
}
|
||
else {
|
||
wd->sta.HTCap.Data.HtCapInfo &= ~HTCAP_SupChannelWidthSet;
|
||
//wd->sta.HTCap.Data.HtCapInfo |= HTCAP_SupChannelWidthSet;
|
||
}
|
||
|
||
wd->sta.HTCap.Data.AMPDUParam &= ~HTCAP_MaxRxAMPDU3;
|
||
wd->sta.HTCap.Data.AMPDUParam |= HTCAP_MaxRxAMPDU3;
|
||
wd->sta.HTCap.Data.MCSSet[1] = 0xFF; // MCS 8 ~ 15
|
||
offset = zfMmAddHTCapability(dev, buf, offset);
|
||
offset = zfMmAddPreNHTCapability(dev, buf, offset);
|
||
//CWYang(+)
|
||
/* Extended HT Capabilities Info */
|
||
//offset = zfMmAddExtendedHTCapability(dev, buf, offset);
|
||
}
|
||
|
||
|
||
//Store asoc request frame body, for VISTA only
|
||
wd->sta.asocReqFrameBodySize = ((offset - hlen) >
|
||
ZM_CACHED_FRAMEBODY_SIZE)?
|
||
ZM_CACHED_FRAMEBODY_SIZE:(offset - hlen);
|
||
for (i=0; i<wd->sta.asocReqFrameBodySize; i++)
|
||
{
|
||
wd->sta.asocReqFrameBody[i] = zmw_tx_buf_readb(dev, buf, i + hlen);
|
||
}
|
||
break;
|
||
|
||
case ZM_WLAN_FRAME_TYPE_ASOCRSP :
|
||
case ZM_WLAN_FRAME_TYPE_REASOCRSP :
|
||
vap = (u16_t) p3;
|
||
|
||
/* Capability */
|
||
zmw_tx_buf_writeh(dev, buf, offset, wd->ap.capab[vap]);
|
||
offset+=2;
|
||
|
||
/* Status Code */
|
||
zmw_tx_buf_writeh(dev, buf, offset, (u16_t)p1);
|
||
offset+=2;
|
||
|
||
/* AID */
|
||
zmw_tx_buf_writeh(dev, buf, offset, (u16_t)(p2|0xc000));
|
||
offset+=2;
|
||
|
||
|
||
if ( wd->frequency < 3000 )
|
||
{
|
||
/* Support Rate */
|
||
offset = zfMmAddIeSupportRate(dev, buf, offset, ZM_WLAN_EID_SUPPORT_RATE, ZM_RATE_SET_CCK);
|
||
|
||
/* Extended Supported Rates */
|
||
offset = zfMmAddIeSupportRate(dev, buf, offset, ZM_WLAN_EID_EXTENDED_RATE, ZM_RATE_SET_OFDM);
|
||
}
|
||
else
|
||
{
|
||
/* Support Rate */
|
||
offset = zfMmAddIeSupportRate(dev, buf, offset, ZM_WLAN_EID_SUPPORT_RATE, ZM_RATE_SET_OFDM);
|
||
}
|
||
|
||
|
||
|
||
/* WME Parameters */
|
||
if (wd->wlanMode == ZM_MODE_AP)
|
||
{
|
||
/* TODO : if WME STA then send WME parameter element */
|
||
if (wd->ap.qosMode == 1)
|
||
{
|
||
offset = zfApAddIeWmePara(dev, buf, offset, vap);
|
||
}
|
||
}
|
||
// jhlee HT 0
|
||
//CWYang(+)
|
||
/* HT Capabilities Info */
|
||
offset = zfMmAddHTCapability(dev, buf, offset);
|
||
//CWYang(+)
|
||
/* Extended HT Capabilities Info */
|
||
offset = zfMmAddExtendedHTCapability(dev, buf, offset);
|
||
break;
|
||
|
||
case ZM_WLAN_FRAME_TYPE_ATIM :
|
||
/* NULL frame */
|
||
/* TODO : add two dumb bytes temporarily */
|
||
offset += 2;
|
||
break;
|
||
|
||
case ZM_WLAN_FRAME_TYPE_QOS_NULL :
|
||
zmw_buf_writeh(dev, buf, offset, 0x0010);
|
||
offset += 2;
|
||
break;
|
||
|
||
case ZM_WLAN_DATA_FRAME :
|
||
break;
|
||
|
||
case ZM_WLAN_FRAME_TYPE_DISASOC :
|
||
case ZM_WLAN_FRAME_TYPE_DEAUTH :
|
||
if (wd->wlanMode == ZM_MODE_AP)
|
||
{
|
||
vap = (u16_t) p3;
|
||
|
||
if ((aid = zfApFindSta(dev, dst)) != 0xffff)
|
||
{
|
||
zmw_enter_critical_section(dev);
|
||
/* Clear STA table */
|
||
wd->ap.staTable[aid].valid = 0;
|
||
|
||
zmw_leave_critical_section(dev);
|
||
|
||
if (wd->zfcbDisAsocNotify != NULL)
|
||
{
|
||
wd->zfcbDisAsocNotify(dev, (u8_t*)dst, vap);
|
||
}
|
||
}
|
||
}
|
||
/* Reason Code */
|
||
zmw_tx_buf_writeh(dev, buf, offset, (u16_t)p1);
|
||
offset+=2;
|
||
break;
|
||
}
|
||
|
||
zfwBufSetSize(dev, buf, offset);
|
||
|
||
zm_msg2_mm(ZM_LV_2, "management frame body size=", offset-hlen);
|
||
|
||
//Copy wlan header
|
||
zfTxGenMmHeader(dev, frameType, dst, header, offset-hlen, buf, vap, encrypt);
|
||
for (i=0; i<(hlen>>1); i++)
|
||
{
|
||
zmw_tx_buf_writeh(dev, buf, i*2, header[i]);
|
||
}
|
||
|
||
/* Get buffer DMA address */
|
||
//if ((addrTblSize = zfwBufMapDma(dev, buf, &addrTbl)) == 0)
|
||
//if ((addrTblSize = zfwMapTxDma(dev, buf, &addrTbl)) == 0)
|
||
//{
|
||
// goto zlError;
|
||
//}
|
||
|
||
zm_msg2_mm(ZM_LV_2, "offset=", offset);
|
||
zm_msg2_mm(ZM_LV_2, "hlen=", hlen);
|
||
//zm_msg2_mm(ZM_LV_2, "addrTblSize=", addrTblSize);
|
||
//zm_msg2_mm(ZM_LV_2, "addrTbl.len[0]=", addrTbl.len[0]);
|
||
//zm_msg2_mm(ZM_LV_2, "addrTbl.physAddrl[0]=", addrTbl.physAddrl[0]);
|
||
//zm_msg2_mm(ZM_LV_2, "buf->data=", buf->data);
|
||
|
||
#if 0
|
||
if ((err = zfHpSend(dev, NULL, 0, NULL, 0, NULL, 0, buf, 0,
|
||
ZM_INTERNAL_ALLOC_BUF, 0, 0xff)) != ZM_SUCCESS)
|
||
{
|
||
goto zlError;
|
||
}
|
||
#else
|
||
zfPutVmmq(dev, buf);
|
||
zfPushVtxq(dev);
|
||
#endif
|
||
|
||
return;
|
||
#if 0
|
||
zlError:
|
||
|
||
zfwBufFree(dev, buf, 0);
|
||
return;
|
||
#endif
|
||
}
|
||
|
||
|
||
/************************************************************************/
|
||
/* */
|
||
/* FUNCTION DESCRIPTION zfProcessManagement */
|
||
/* Process received management frame. */
|
||
/* */
|
||
/* INPUTS */
|
||
/* dev : device pointer */
|
||
/* buf : received management frame buffer */
|
||
/* */
|
||
/* OUTPUTS */
|
||
/* none */
|
||
/* */
|
||
/* AUTHOR */
|
||
/* Stephen Chen ZyDAS Technology Corporation 2005.10 */
|
||
/* */
|
||
/************************************************************************/
|
||
void zfProcessManagement(zdev_t* dev, zbuf_t* buf, struct zsAdditionInfo* AddInfo) //CWYang(m)
|
||
{
|
||
u8_t frameType;
|
||
u16_t ta[3];
|
||
u16_t ra[3];
|
||
u16_t vap = 0, index = 0;
|
||
//u16_t i;
|
||
|
||
zmw_get_wlan_dev(dev);
|
||
|
||
ra[0] = zmw_rx_buf_readh(dev, buf, 4);
|
||
ra[1] = zmw_rx_buf_readh(dev, buf, 6);
|
||
ra[2] = zmw_rx_buf_readh(dev, buf, 8);
|
||
|
||
ta[0] = zmw_rx_buf_readh(dev, buf, 10);
|
||
ta[1] = zmw_rx_buf_readh(dev, buf, 12);
|
||
ta[2] = zmw_rx_buf_readh(dev, buf, 14);
|
||
|
||
frameType = zmw_rx_buf_readb(dev, buf, 0);
|
||
|
||
if (wd->wlanMode == ZM_MODE_AP)
|
||
{
|
||
#if 1
|
||
vap = 0;
|
||
if ((ra[0] & 0x1) != 1)
|
||
{
|
||
/* AP : Find virtual AP */
|
||
if ((index = zfApFindSta(dev, ta)) != 0xffff)
|
||
{
|
||
vap = wd->ap.staTable[index].vap;
|
||
}
|
||
}
|
||
zm_msg2_mm(ZM_LV_2, "vap=", vap);
|
||
#endif
|
||
|
||
/* Dispatch by frame type */
|
||
switch (frameType)
|
||
{
|
||
/* Beacon */
|
||
case ZM_WLAN_FRAME_TYPE_BEACON :
|
||
zfApProcessBeacon(dev, buf);
|
||
break;
|
||
/* Authentication */
|
||
case ZM_WLAN_FRAME_TYPE_AUTH :
|
||
zfApProcessAuth(dev, buf, ta, vap);
|
||
break;
|
||
/* Association request */
|
||
case ZM_WLAN_FRAME_TYPE_ASOCREQ :
|
||
/* Reassociation request */
|
||
case ZM_WLAN_FRAME_TYPE_REASOCREQ :
|
||
zfApProcessAsocReq(dev, buf, ta, vap);
|
||
break;
|
||
/* Association response */
|
||
case ZM_WLAN_FRAME_TYPE_ASOCRSP :
|
||
//zfApProcessAsocRsp(dev, buf);
|
||
break;
|
||
/* Deauthentication */
|
||
case ZM_WLAN_FRAME_TYPE_DEAUTH :
|
||
zfApProcessDeauth(dev, buf, ta, vap);
|
||
break;
|
||
/* Disassociation */
|
||
case ZM_WLAN_FRAME_TYPE_DISASOC :
|
||
zfApProcessDisasoc(dev, buf, ta, vap);
|
||
break;
|
||
/* Probe request */
|
||
case ZM_WLAN_FRAME_TYPE_PROBEREQ :
|
||
zfProcessProbeReq(dev, buf, ta);
|
||
break;
|
||
/* Probe response */
|
||
case ZM_WLAN_FRAME_TYPE_PROBERSP :
|
||
zfApProcessProbeRsp(dev, buf, AddInfo);
|
||
break;
|
||
/* Action */
|
||
case ZM_WLAN_FRAME_TYPE_ACTION :
|
||
zfApProcessAction(dev, buf);
|
||
break;
|
||
}
|
||
}
|
||
else //if ((wd->wlanMode == ZM_MODE_INFRASTRUCTURE) || (wd->wlanMode == ZM_MODE_IBSS))
|
||
{
|
||
/* Dispatch by frame type */
|
||
switch (frameType)
|
||
{
|
||
/* Beacon */
|
||
case ZM_WLAN_FRAME_TYPE_BEACON :
|
||
/* if enable 802.11h and current chanel is silent but receive beacon from other AP */
|
||
if (((wd->regulationTable.allowChannel[wd->regulationTable.CurChIndex].channelFlags
|
||
& ZM_REG_FLAG_CHANNEL_CSA) != 0) && wd->sta.DFSEnable)
|
||
{
|
||
wd->regulationTable.allowChannel[wd->regulationTable.CurChIndex].channelFlags
|
||
&= ~(ZM_REG_FLAG_CHANNEL_CSA & ZM_REG_FLAG_CHANNEL_PASSIVE);
|
||
}
|
||
zfStaProcessBeacon(dev, buf, AddInfo); //CWYang(m)
|
||
break;
|
||
/* Authentication */
|
||
case ZM_WLAN_FRAME_TYPE_AUTH :
|
||
/* TODO : vap parameter is useless in STA mode, get rid of it */
|
||
zfStaProcessAuth(dev, buf, ta, 0);
|
||
break;
|
||
/* Association request */
|
||
case ZM_WLAN_FRAME_TYPE_ASOCREQ :
|
||
/* TODO : vap parameter is useless in STA mode, get rid of it */
|
||
zfStaProcessAsocReq(dev, buf, ta, 0);
|
||
break;
|
||
/* Association response */
|
||
case ZM_WLAN_FRAME_TYPE_ASOCRSP :
|
||
/* Reassociation request */
|
||
case ZM_WLAN_FRAME_TYPE_REASOCRSP :
|
||
zfStaProcessAsocRsp(dev, buf);
|
||
break;
|
||
/* Deauthentication */
|
||
case ZM_WLAN_FRAME_TYPE_DEAUTH :
|
||
zm_debug_msg0("Deauthentication received");
|
||
zfStaProcessDeauth(dev, buf);
|
||
break;
|
||
/* Disassociation */
|
||
case ZM_WLAN_FRAME_TYPE_DISASOC :
|
||
zm_debug_msg0("Disassociation received");
|
||
zfStaProcessDisasoc(dev, buf);
|
||
break;
|
||
/* Probe request */
|
||
case ZM_WLAN_FRAME_TYPE_PROBEREQ :
|
||
zfProcessProbeReq(dev, buf, ta);
|
||
break;
|
||
/* Probe response */
|
||
case ZM_WLAN_FRAME_TYPE_PROBERSP :
|
||
/* if enable 802.11h and current chanel is silent but receive probe response from other AP */
|
||
if (((wd->regulationTable.allowChannel[wd->regulationTable.CurChIndex].channelFlags
|
||
& ZM_REG_FLAG_CHANNEL_CSA) != 0) && wd->sta.DFSEnable)
|
||
{
|
||
wd->regulationTable.allowChannel[wd->regulationTable.CurChIndex].channelFlags
|
||
&= ~(ZM_REG_FLAG_CHANNEL_CSA & ZM_REG_FLAG_CHANNEL_PASSIVE);
|
||
}
|
||
zfStaProcessProbeRsp(dev, buf, AddInfo);
|
||
break;
|
||
|
||
case ZM_WLAN_FRAME_TYPE_ATIM:
|
||
zfStaProcessAtim(dev, buf);
|
||
break;
|
||
/* Action */
|
||
case ZM_WLAN_FRAME_TYPE_ACTION :
|
||
zm_msg0_mm(ZM_LV_2, "ProcessActionMgtFrame");
|
||
zfStaProcessAction(dev, buf);
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
|
||
/************************************************************************/
|
||
/* */
|
||
/* 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 zfProcessProbeReq(zdev_t* dev, zbuf_t* buf, u16_t* src)
|
||
{
|
||
u16_t offset;
|
||
u8_t len;
|
||
u16_t i, j;
|
||
u8_t ch;
|
||
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;
|
||
}
|
||
|
||
if ((wd->wlanMode != ZM_MODE_AP) && (wd->sta.adapterState == ZM_STA_STATE_DISCONNECT))
|
||
{
|
||
zm_msg0_mm(ZM_LV_3, "Packets dropped due to disconnect state");
|
||
return;
|
||
}
|
||
|
||
if ( wd->wlanMode == ZM_MODE_IBSS )
|
||
{
|
||
zfSendMmFrame(dev, ZM_WLAN_FRAME_TYPE_PROBERSP, src, 0, 0, 0);
|
||
|
||
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 & (1<<i)) != 0)
|
||
{
|
||
zm_msg1_mm(ZM_LV_3, "len=", len);
|
||
sendFlag = 0;
|
||
/* boardcast SSID */
|
||
if (len == 0)
|
||
{
|
||
if (wd->ap.hideSsid[i] == 0)
|
||
{
|
||
sendFlag = 1;
|
||
}
|
||
}
|
||
/* Not broadcast SSID */
|
||
else if (wd->ap.ssidLen[i] == len)
|
||
{
|
||
for (j=0; j<len; j++)
|
||
{
|
||
if ((ch = zmw_rx_buf_readb(dev, buf, offset+2+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, i);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
/************************************************************************/
|
||
/* */
|
||
/* FUNCTION DESCRIPTION zfProcessProbeRsp */
|
||
/* Process probe response management frame. */
|
||
/* */
|
||
/* INPUTS */
|
||
/* dev : device pointer */
|
||
/* buf : auth frame buffer */
|
||
/* AddInfo : Rx Header and Rx Mac Status */
|
||
/* */
|
||
/* OUTPUTS */
|
||
/* none */
|
||
/* */
|
||
/* AUTHOR */
|
||
/* Aress Yang ZyDAS Technology Corporation 2006.11 */
|
||
/* */
|
||
/************************************************************************/
|
||
void zfProcessProbeRsp(zdev_t* dev, zbuf_t* buf, struct zsAdditionInfo* AddInfo)
|
||
{
|
||
/* Gather scan result */
|
||
/* Parse TIM and send PS-POLL in power saving mode */
|
||
struct zsWlanProbeRspFrameHeader* pProbeRspHeader;
|
||
struct zsBssInfo* pBssInfo;
|
||
u8_t pBuf[sizeof(struct zsWlanProbeRspFrameHeader)];
|
||
int res;
|
||
|
||
zmw_get_wlan_dev(dev);
|
||
|
||
zmw_declare_for_critical_section();
|
||
|
||
zfCopyFromRxBuffer(dev, buf, pBuf, 0,
|
||
sizeof(struct zsWlanProbeRspFrameHeader));
|
||
pProbeRspHeader = (struct zsWlanProbeRspFrameHeader*) pBuf;
|
||
|
||
zmw_enter_critical_section(dev);
|
||
|
||
//zm_debug_msg1("bss count = ", wd->sta.bssList.bssCount);
|
||
|
||
pBssInfo = zfStaFindBssInfo(dev, buf, pProbeRspHeader);
|
||
|
||
//if ( i == wd->sta.bssList.bssCount )
|
||
if ( pBssInfo == NULL )
|
||
{
|
||
/* Allocate a new entry if BSS not in the scan list */
|
||
pBssInfo = zfBssInfoAllocate(dev);
|
||
if (pBssInfo != NULL)
|
||
{
|
||
res = zfStaInitBssInfo(dev, buf, pProbeRspHeader, 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, pProbeRspHeader, 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);
|
||
|
||
return;
|
||
}
|
||
|
||
/************************************************************************/
|
||
/* */
|
||
/* FUNCTION DESCRIPTION zfSendProbeReq */
|
||
/* Send probe request management frame. */
|
||
/* */
|
||
/* INPUTS */
|
||
/* dev : device pointer */
|
||
/* */
|
||
/* */
|
||
/* OUTPUTS */
|
||
/* none */
|
||
/* */
|
||
/* AUTHOR */
|
||
/* Ji-Huang Lee ZyDAS Technology Corporation 2005.11 */
|
||
/* */
|
||
/************************************************************************/
|
||
|
||
u16_t zfSendProbeReq(zdev_t* dev, zbuf_t* buf, u16_t offset, u8_t bWithSSID)
|
||
{
|
||
zmw_get_wlan_dev(dev);
|
||
zmw_declare_for_critical_section();
|
||
|
||
|
||
/* SSID */
|
||
if (bWithSSID == 0) /* broadcast ssid */
|
||
{
|
||
//zmw_leave_critical_section(dev);
|
||
zmw_tx_buf_writeb(dev, buf, offset++, ZM_WLAN_EID_SSID);
|
||
zmw_tx_buf_writeb(dev, buf, offset++, 0); /* length = 0 */
|
||
}
|
||
else
|
||
{
|
||
zmw_enter_critical_section(dev);
|
||
if (wd->ws.probingSsidList[bWithSSID-1].ssidLen == 0)
|
||
{
|
||
zmw_tx_buf_writeb(dev, buf, offset++, ZM_WLAN_EID_SSID);
|
||
zmw_tx_buf_writeb(dev, buf, offset++, 0); /* length = 0 */
|
||
}
|
||
else
|
||
{
|
||
zmw_tx_buf_writeb(dev, buf, offset++, ZM_WLAN_EID_SSID);
|
||
zmw_tx_buf_writeb(dev, buf, offset++,
|
||
wd->ws.probingSsidList[bWithSSID-1].ssidLen);
|
||
zfCopyToIntTxBuffer(dev, buf,
|
||
wd->ws.probingSsidList[bWithSSID-1].ssid,
|
||
offset,
|
||
wd->ws.probingSsidList[bWithSSID-1].ssidLen); /* ssid */
|
||
offset += wd->ws.probingSsidList[bWithSSID-1].ssidLen;
|
||
}
|
||
zmw_leave_critical_section(dev);
|
||
}
|
||
|
||
/* Supported rates */
|
||
if ( wd->sta.currentFrequency < 3000 )
|
||
{ /* 802.11b+g */
|
||
offset = zfMmAddIeSupportRate(dev, buf, offset,
|
||
ZM_WLAN_EID_SUPPORT_RATE, ZM_RATE_SET_CCK);
|
||
|
||
if (wd->supportMode & (ZM_WIRELESS_MODE_24_54|ZM_WIRELESS_MODE_24_N)) {
|
||
if (wd->wlanMode == ZM_MODE_IBSS) {
|
||
if (wd->wfc.bIbssGMode) {
|
||
offset = zfMmAddIeSupportRate(dev, buf, offset,
|
||
ZM_WLAN_EID_EXTENDED_RATE, ZM_RATE_SET_OFDM);
|
||
}
|
||
} else {
|
||
offset = zfMmAddIeSupportRate(dev, buf, offset,
|
||
ZM_WLAN_EID_EXTENDED_RATE, ZM_RATE_SET_OFDM);
|
||
}
|
||
}
|
||
}
|
||
else
|
||
{ /* 802.11a */
|
||
offset = zfMmAddIeSupportRate(dev, buf, offset,
|
||
ZM_WLAN_EID_SUPPORT_RATE, ZM_RATE_SET_OFDM);
|
||
}
|
||
|
||
return offset;
|
||
}
|
||
|
||
|
||
/************************************************************************/
|
||
/* */
|
||
/* FUNCTION DESCRIPTION zfUpdateDefaultQosParameter */
|
||
/* Update TxQs CWMIN, CWMAX, AIFS and TXO to WME default value. */
|
||
/* */
|
||
/* INPUTS */
|
||
/* dev : device pointer */
|
||
/* mode : 0=>STA, 1=>AP */
|
||
/* */
|
||
/* OUTPUTS */
|
||
/* none */
|
||
/* */
|
||
/* AUTHOR */
|
||
/* Stephen ZyDAS Technology Corporation 2006.6 */
|
||
/* */
|
||
/************************************************************************/
|
||
void zfUpdateDefaultQosParameter(zdev_t* dev, u8_t mode)
|
||
{
|
||
u16_t cwmin[5];
|
||
u16_t cwmax[5];
|
||
u16_t aifs[5];
|
||
u16_t txop[5];
|
||
|
||
/* WMM parameter for STA */
|
||
/* Best Effor */
|
||
cwmin[0] = 15;
|
||
cwmax[0] = 1023;
|
||
aifs[0] = 3 * 9 + 10;
|
||
txop[0] = 0;
|
||
/* Back Ground */
|
||
cwmin[1] = 15;
|
||
cwmax[1] = 1023;
|
||
aifs[1] = 7 * 9 + 10;
|
||
txop[1] = 0;
|
||
/* VIDEO */
|
||
cwmin[2] = 7;
|
||
cwmax[2] = 15;
|
||
aifs[2] = 2 * 9 + 10;
|
||
txop[2] = 94;
|
||
/* VOICE */
|
||
cwmin[3] = 3;
|
||
cwmax[3] = 7;
|
||
aifs[3] = 2 * 9 + 10;
|
||
txop[3] = 47;
|
||
/* Special TxQ */
|
||
cwmin[4] = 3;
|
||
cwmax[4] = 7;
|
||
aifs[4] = 2 * 9 + 10;
|
||
txop[4] = 0;
|
||
|
||
/* WMM parameter for AP */
|
||
if (mode == 1)
|
||
{
|
||
cwmax[0] = 63;
|
||
aifs[3] = 1 * 9 + 10;
|
||
aifs[4] = 1 * 9 + 10;
|
||
}
|
||
zfHpUpdateQosParameter(dev, cwmin, cwmax, aifs, txop);
|
||
}
|
||
|
||
u16_t zfFindATHExtCap(zdev_t* dev, zbuf_t* buf, u8_t type, u8_t subtype)
|
||
{
|
||
u8_t subType;
|
||
u16_t offset;
|
||
u16_t bufLen;
|
||
u16_t elen;
|
||
u8_t id;
|
||
u8_t tmp;
|
||
|
||
/* Get offset of first element */
|
||
subType = (zmw_rx_buf_readb(dev, buf, 0) >> 4);
|
||
|
||
if ((offset = zgElementOffsetTable[subType]) == 0xff)
|
||
{
|
||
zm_assert(0);
|
||
}
|
||
|
||
/* Plus wlan header */
|
||
offset += 24;
|
||
|
||
bufLen = zfwBufGetSize(dev, buf);
|
||
|
||
/* Search loop */
|
||
while ((offset+2)<bufLen) // including element ID and length (2bytes)
|
||
{
|
||
/* Search target element */
|
||
if ((id = zmw_rx_buf_readb(dev, buf, offset)) == ZM_WLAN_EID_WIFI_IE)
|
||
{
|
||
/* Bingo */
|
||
if ((elen = zmw_rx_buf_readb(dev, buf, offset+1))>(bufLen - offset))
|
||
{
|
||
/* Element length error */
|
||
return 0xffff;
|
||
}
|
||
|
||
if ( elen == 0 )
|
||
{
|
||
return 0xffff;
|
||
}
|
||
|
||
if (((tmp = zmw_rx_buf_readb(dev, buf, offset+2)) == 0x00)
|
||
&& ((tmp = zmw_rx_buf_readb(dev, buf, offset+3)) == 0x03)
|
||
&& ((tmp = zmw_rx_buf_readb(dev, buf, offset+4)) == 0x7f)
|
||
&& ((tmp = zmw_rx_buf_readb(dev, buf, offset+5)) == type))
|
||
|
||
{
|
||
if ( subtype != 0xff )
|
||
{
|
||
if ( (tmp = zmw_rx_buf_readb(dev, buf, offset+6)) == subtype )
|
||
{
|
||
return offset;
|
||
}
|
||
}
|
||
else
|
||
{
|
||
return offset;
|
||
}
|
||
}
|
||
}
|
||
|
||
/* Advance to next element */
|
||
if ((elen = zmw_rx_buf_readb(dev, buf, offset+1)) == 0)
|
||
{
|
||
return 0xffff;
|
||
}
|
||
offset += (elen+2);
|
||
}
|
||
return 0xffff;
|
||
}
|
||
|
||
u16_t zfFindBrdcmMrvlRlnkExtCap(zdev_t* dev, zbuf_t* buf)
|
||
{
|
||
u8_t subType;
|
||
u16_t offset;
|
||
u16_t bufLen;
|
||
u16_t elen;
|
||
u8_t id;
|
||
u8_t tmp;
|
||
|
||
/* Get offset of first element */
|
||
subType = (zmw_rx_buf_readb(dev, buf, 0) >> 4);
|
||
|
||
if ((offset = zgElementOffsetTable[subType]) == 0xff)
|
||
{
|
||
zm_assert(0);
|
||
}
|
||
|
||
/* Plus wlan header */
|
||
offset += 24;
|
||
|
||
bufLen = zfwBufGetSize(dev, buf);
|
||
|
||
/* Search loop */
|
||
while ((offset+2)<bufLen) // including element ID and length (2bytes)
|
||
{
|
||
/* Search target element */
|
||
if ((id = zmw_rx_buf_readb(dev, buf, offset)) == ZM_WLAN_EID_WIFI_IE)
|
||
{
|
||
/* Bingo */
|
||
if ((elen = zmw_rx_buf_readb(dev, buf, offset+1))>(bufLen - offset))
|
||
{
|
||
/* Element length error */
|
||
return 0xffff;
|
||
}
|
||
|
||
if ( elen == 0 )
|
||
{
|
||
return 0xffff;
|
||
}
|
||
|
||
if (((tmp = zmw_rx_buf_readb(dev, buf, offset+2)) == 0x00)
|
||
&& ((tmp = zmw_rx_buf_readb(dev, buf, offset+3)) == 0x10)
|
||
&& ((tmp = zmw_rx_buf_readb(dev, buf, offset+4)) == 0x18))
|
||
|
||
{
|
||
return offset;
|
||
}
|
||
else if (((tmp = zmw_rx_buf_readb(dev, buf, offset+2)) == 0x00)
|
||
&& ((tmp = zmw_rx_buf_readb(dev, buf, offset+3)) == 0x50)
|
||
&& ((tmp = zmw_rx_buf_readb(dev, buf, offset+4)) == 0x43))
|
||
|
||
{
|
||
return offset;
|
||
}
|
||
}
|
||
else if ((id = zmw_rx_buf_readb(dev, buf, offset)) == 0x7F)
|
||
{
|
||
/* Bingo */
|
||
if ((elen = zmw_rx_buf_readb(dev, buf, offset+1))>(bufLen - offset))
|
||
{
|
||
/* Element length error */
|
||
return 0xffff;
|
||
}
|
||
|
||
if ( elen == 0 )
|
||
{
|
||
return 0xffff;
|
||
}
|
||
|
||
if ((tmp = zmw_rx_buf_readb(dev, buf, offset+2)) == 0x01)
|
||
|
||
{
|
||
return offset;
|
||
}
|
||
}
|
||
|
||
/* Advance to next element */
|
||
if ((elen = zmw_rx_buf_readb(dev, buf, offset+1)) == 0)
|
||
{
|
||
return 0xffff;
|
||
}
|
||
offset += (elen+2);
|
||
}
|
||
return 0xffff;
|
||
}
|
||
|
||
u16_t zfFindMarvelExtCap(zdev_t* dev, zbuf_t* buf)
|
||
{
|
||
u8_t subType;
|
||
u16_t offset;
|
||
u16_t bufLen;
|
||
u16_t elen;
|
||
u8_t id;
|
||
u8_t tmp;
|
||
|
||
/* Get offset of first element */
|
||
subType = (zmw_rx_buf_readb(dev, buf, 0) >> 4);
|
||
|
||
if ((offset = zgElementOffsetTable[subType]) == 0xff)
|
||
{
|
||
zm_assert(0);
|
||
}
|
||
|
||
/* Plus wlan header */
|
||
offset += 24;
|
||
|
||
bufLen = zfwBufGetSize(dev, buf);
|
||
|
||
/* Search loop */
|
||
while ((offset+2)<bufLen) // including element ID and length (2bytes)
|
||
{
|
||
/* Search target element */
|
||
if ((id = zmw_rx_buf_readb(dev, buf, offset)) == ZM_WLAN_EID_WIFI_IE)
|
||
{
|
||
/* Bingo */
|
||
if ((elen = zmw_rx_buf_readb(dev, buf, offset+1))>(bufLen - offset))
|
||
{
|
||
/* Element length error */
|
||
return 0xffff;
|
||
}
|
||
|
||
if ( elen == 0 )
|
||
{
|
||
return 0xffff;
|
||
}
|
||
|
||
if (((tmp = zmw_rx_buf_readb(dev, buf, offset+2)) == 0x00)
|
||
&& ((tmp = zmw_rx_buf_readb(dev, buf, offset+3)) == 0x50)
|
||
&& ((tmp = zmw_rx_buf_readb(dev, buf, offset+4)) == 0x43))
|
||
|
||
{
|
||
return offset;
|
||
}
|
||
}
|
||
|
||
/* Advance to next element */
|
||
if ((elen = zmw_rx_buf_readb(dev, buf, offset+1)) == 0)
|
||
{
|
||
return 0xffff;
|
||
}
|
||
offset += (elen+2);
|
||
}
|
||
return 0xffff;
|
||
}
|
||
|
||
u16_t zfFindBroadcomExtCap(zdev_t* dev, zbuf_t* buf)
|
||
{
|
||
u8_t subType;
|
||
u16_t offset;
|
||
u16_t bufLen;
|
||
u16_t elen;
|
||
u8_t id;
|
||
u8_t tmp;
|
||
|
||
/* Get offset of first element */
|
||
subType = (zmw_rx_buf_readb(dev, buf, 0) >> 4);
|
||
|
||
if ((offset = zgElementOffsetTable[subType]) == 0xff)
|
||
{
|
||
zm_assert(0);
|
||
}
|
||
|
||
/* Plus wlan header */
|
||
offset += 24;
|
||
|
||
bufLen = zfwBufGetSize(dev, buf);
|
||
|
||
/* Search loop */
|
||
while((offset+2) < bufLen) // including element ID and length (2bytes)
|
||
{
|
||
/* Search target element */
|
||
if ((id = zmw_rx_buf_readb(dev, buf, offset)) == ZM_WLAN_EID_WIFI_IE)
|
||
{
|
||
/* Bingo */
|
||
if ((elen = zmw_rx_buf_readb(dev, buf, offset+1)) > (bufLen - offset))
|
||
{
|
||
/* Element length error */
|
||
return 0xffff;
|
||
}
|
||
|
||
if (elen == 0)
|
||
{
|
||
return 0xffff;
|
||
}
|
||
|
||
if ( ((tmp = zmw_rx_buf_readb(dev, buf, offset+2)) == 0x00)
|
||
&& ((tmp = zmw_rx_buf_readb(dev, buf, offset+3)) == 0x10)
|
||
&& ((tmp = zmw_rx_buf_readb(dev, buf, offset+4)) == 0x18) )
|
||
{
|
||
return offset;
|
||
}
|
||
}
|
||
|
||
/* Advance to next element */
|
||
if ((elen = zmw_rx_buf_readb(dev, buf, offset+1)) == 0)
|
||
{
|
||
return 0xffff;
|
||
}
|
||
|
||
offset += (elen+2);
|
||
}
|
||
|
||
return 0xffff;
|
||
}
|
||
|
||
u16_t zfFindRlnkExtCap(zdev_t* dev, zbuf_t* buf)
|
||
{
|
||
u8_t subType;
|
||
u16_t offset;
|
||
u16_t bufLen;
|
||
u16_t elen;
|
||
u8_t id;
|
||
u8_t tmp;
|
||
|
||
/* Get offset of first element */
|
||
subType = (zmw_rx_buf_readb(dev, buf, 0) >> 4);
|
||
|
||
if ((offset = zgElementOffsetTable[subType]) == 0xff)
|
||
{
|
||
zm_assert(0);
|
||
}
|
||
|
||
/* Plus wlan header */
|
||
offset += 24;
|
||
|
||
bufLen = zfwBufGetSize(dev, buf);
|
||
|
||
/* Search loop */
|
||
while((offset+2) < bufLen) // including element ID and length (2bytes)
|
||
{
|
||
/* Search target element */
|
||
if ((id = zmw_rx_buf_readb(dev, buf, offset)) == 0x7F)
|
||
{
|
||
/* Bingo */
|
||
if ((elen = zmw_rx_buf_readb(dev, buf, offset+1)) > (bufLen - offset))
|
||
{
|
||
/* Element length error */
|
||
return 0xffff;
|
||
}
|
||
|
||
if ( elen == 0 )
|
||
{
|
||
return 0xffff;
|
||
}
|
||
|
||
if ((tmp = zmw_rx_buf_readb(dev, buf, offset+2)) == 0x01)
|
||
|
||
{
|
||
return offset;
|
||
}
|
||
}
|
||
|
||
/* Advance to next element */
|
||
if ((elen = zmw_rx_buf_readb(dev, buf, offset+1)) == 0)
|
||
{
|
||
return 0xffff;
|
||
}
|
||
|
||
offset += (elen+2);
|
||
}
|
||
|
||
return 0xffff;
|
||
}
|