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;
|
|||
|
}
|