2018 lines
54 KiB
C
2018 lines
54 KiB
C
/*
|
|
***************************************************************************
|
|
* Ralink Tech Inc.
|
|
* 4F, No. 2 Technology 5th Rd.
|
|
* Science-based Industrial Park
|
|
* Hsin-chu, Taiwan, R.O.C.
|
|
*
|
|
* (c) Copyright 2002-2011, Ralink Technology, Inc.
|
|
*
|
|
* All rights reserved. Ralink's source code is an unpublished work and the
|
|
* use of a copyright notice does not imply otherwise. This source code
|
|
* contains confidential trade secret material of Ralink Tech. Any attemp
|
|
* or participation in deciphering, decoding, reverse engineering or in any
|
|
* way altering the source code is stricitly prohibited, unless the prior
|
|
* written consent of Ralink Technology, Inc. is obtained.
|
|
***************************************************************************
|
|
|
|
Module Name:
|
|
gas.c
|
|
|
|
Abstract:
|
|
generic advertisement service(GAS)
|
|
|
|
Revision History:
|
|
Who When What
|
|
-------- ---------- ----------------------------------------------
|
|
*/
|
|
|
|
#include "rt_config.h"
|
|
|
|
|
|
enum DOT11U_ADVERTISMENT_PROTOCOL_ID dot11GASAdvertisementID[] =
|
|
{
|
|
ACCESS_NETWORK_QUERY_PROTOCOL,
|
|
};
|
|
|
|
static VOID SendGASIndication(
|
|
IN PRTMP_ADAPTER pAd,
|
|
GAS_EVENT_DATA *Event);
|
|
|
|
#ifdef CONFIG_STA_SUPPORT
|
|
void wext_send_anqp_rsp_event(PNET_DEV net_dev, const char *peer_mac_addr,
|
|
u16 status, const char *anqp_rsp, u16 anqp_rsp_len)
|
|
{
|
|
|
|
struct anqp_rsp_data *rsp_data;
|
|
u16 buflen = 0;
|
|
UCHAR *buf;
|
|
|
|
buflen = sizeof(*rsp_data) + anqp_rsp_len;
|
|
os_alloc_mem(NULL, (UCHAR **)&buf, buflen);
|
|
NdisZeroMemory(buf, buflen);
|
|
|
|
rsp_data = (struct anqp_rsp_data *)buf;
|
|
rsp_data->ifindex = RtmpOsGetNetIfIndex(net_dev);
|
|
memcpy(rsp_data->peer_mac_addr, peer_mac_addr, 6);
|
|
rsp_data->status = status;
|
|
rsp_data->anqp_rsp_len = anqp_rsp_len;
|
|
memcpy(rsp_data->anqp_rsp, anqp_rsp, anqp_rsp_len);
|
|
|
|
RtmpOSWrielessEventSend(net_dev, RT_WLAN_EVENT_CUSTOM,
|
|
OID_802_11_HS_ANQP_RSP, NULL, (PUCHAR)buf, buflen);
|
|
|
|
os_free_mem(NULL, buf);
|
|
}
|
|
|
|
|
|
void SendAnqpRspEvent(PNET_DEV net_dev, const char *peer_mac_addr,
|
|
u16 status, const char *anqp_rsp, u16 anqp_rsp_len)
|
|
{
|
|
wext_send_anqp_rsp_event(net_dev,
|
|
peer_mac_addr,
|
|
status,
|
|
anqp_rsp,
|
|
anqp_rsp_len);
|
|
|
|
}
|
|
|
|
|
|
static VOID SendGASReq(
|
|
IN PRTMP_ADAPTER pAd,
|
|
IN MLME_QUEUE_ELEM *Elem)
|
|
{
|
|
GAS_EVENT_DATA *Event = (GAS_EVENT_DATA *)Elem->Msg;
|
|
UCHAR *Buf, *Pos;
|
|
GAS_FRAME *GASFrame;
|
|
UINT32 FrameLen = 0, VarLen = 0;
|
|
UINT16 tmpLen = 0;
|
|
|
|
DBGPRINT(RT_DEBUG_TRACE, ("%s\n", __FUNCTION__));
|
|
|
|
if (Event->u.GAS_REQ_DATA.AdvertisementProID == ACCESS_NETWORK_QUERY_PROTOCOL)
|
|
{
|
|
/* Advertisement protocol element + Query request length field */
|
|
VarLen += 6;
|
|
}
|
|
|
|
/* Query request field*/
|
|
VarLen += Event->u.GAS_REQ_DATA.QueryReqLen;
|
|
|
|
os_alloc_mem(pAd, (UCHAR **)&Buf, sizeof(*GASFrame) + VarLen);
|
|
|
|
if (!Buf)
|
|
{
|
|
DBGPRINT(RT_DEBUG_ERROR, ("%s Not available memory\n", __FUNCTION__));
|
|
return;
|
|
}
|
|
|
|
NdisZeroMemory(Buf, sizeof(*GASFrame) + VarLen);
|
|
|
|
GASFrame = (GAS_FRAME *)Buf;
|
|
|
|
ActHeaderInit(pAd, &GASFrame->Hdr, Event->PeerMACAddr ,pAd->CurrentAddress,
|
|
Event->PeerMACAddr);
|
|
|
|
FrameLen += sizeof(HEADER_802_11);
|
|
|
|
GASFrame->Category = CATEGORY_PUBLIC;
|
|
GASFrame->u.GAS_INIT_REQ.Action = ACTION_GAS_INIT_REQ;
|
|
GASFrame->u.GAS_INIT_REQ.DialogToken = Event->u.GAS_REQ_DATA.DialogToken;
|
|
FrameLen += 3;
|
|
|
|
Pos = GASFrame->u.GAS_INIT_REQ.Variable;
|
|
*Pos++ = IE_ADVERTISEMENT_PROTO;
|
|
*Pos++ = 2; /* Length field */
|
|
*Pos++ = 0; /* Query response info field */
|
|
*Pos++ = Event->u.GAS_REQ_DATA.AdvertisementProID; /* Advertisement Protocol ID field */
|
|
|
|
tmpLen = cpu2le16(Event->u.GAS_REQ_DATA.QueryReqLen);
|
|
NdisMoveMemory(Pos, &tmpLen, 2);
|
|
Pos += 2;
|
|
FrameLen += 6;
|
|
|
|
NdisMoveMemory(Pos, Event->u.GAS_REQ_DATA.QueryReq, Event->u.GAS_REQ_DATA.QueryReqLen);
|
|
FrameLen += Event->u.GAS_REQ_DATA.QueryReqLen;
|
|
|
|
MiniportMMRequest(pAd, 0, Buf, FrameLen);
|
|
|
|
GASSetPeerCurrentState(pAd, Elem, WAIT_PEER_GAS_RSP);
|
|
|
|
os_free_mem(NULL, Buf);
|
|
}
|
|
|
|
|
|
void GASCBDelayTimeout(
|
|
IN PVOID SystemSpecific1,
|
|
IN PVOID FunctionContext,
|
|
IN PVOID SystemSpecific2,
|
|
IN PVOID SystemSpecific3)
|
|
{
|
|
GAS_PEER_ENTRY *GASPeerEntry = (GAS_PEER_ENTRY *)FunctionContext;
|
|
GAS_EVENT_DATA *Event;
|
|
PRTMP_ADAPTER pAd;
|
|
UCHAR *Buf;
|
|
UINT32 Len = 0;
|
|
|
|
DBGPRINT(RT_DEBUG_TRACE, ("%s\n", __FUNCTION__));
|
|
|
|
if (!GASPeerEntry)
|
|
return;
|
|
|
|
pAd = GASPeerEntry->Priv;
|
|
|
|
if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS
|
|
| fRTMP_ADAPTER_NIC_NOT_EXIST))
|
|
return;
|
|
|
|
if (GASPeerEntry->GASCBDelayTimerRunning)
|
|
{
|
|
GASPeerEntry->GASCBDelayTimerRunning = FALSE;
|
|
|
|
os_alloc_mem(NULL, (UCHAR **)&Buf, sizeof(*Event));
|
|
|
|
if (!Buf)
|
|
{
|
|
DBGPRINT(RT_DEBUG_ERROR, ("%s Not available memory\n", __FUNCTION__));
|
|
return;
|
|
}
|
|
|
|
NdisZeroMemory(Buf, sizeof(*Event));
|
|
|
|
Event = (GAS_EVENT_DATA *)Buf;
|
|
|
|
Event->ControlIndex = GASPeerEntry->ControlIndex;
|
|
Len += 1;
|
|
|
|
NdisMoveMemory(Event->PeerMACAddr, GASPeerEntry->PeerMACAddr, MAC_ADDR_LEN);
|
|
Len += MAC_ADDR_LEN;
|
|
|
|
Event->EventType = PEER_GAS_RSP_MORE;
|
|
Len += 2;
|
|
|
|
Event->u.PEER_GAS_RSP_MORE_DATA.DialogToken = GASPeerEntry->DialogToken;
|
|
Len += 1;
|
|
|
|
MlmeEnqueue(pAd, GAS_STATE_MACHINE, PEER_GAS_RSP_MORE, Len, Buf,0);
|
|
|
|
os_free_mem(NULL, Buf);
|
|
}
|
|
}
|
|
BUILD_TIMER_FUNCTION(GASCBDelayTimeout);
|
|
|
|
|
|
VOID ReceiveGASInitRsp(
|
|
IN PRTMP_ADAPTER pAd,
|
|
IN MLME_QUEUE_ELEM *Elem)
|
|
{
|
|
GAS_EVENT_DATA *Event;
|
|
GAS_FRAME *GASFrame = (GAS_FRAME *)Elem->Msg;
|
|
GAS_PEER_ENTRY *GASPeerEntry;
|
|
PGAS_CTRL pGASCtrl = &pAd->StaCfg.GASCtrl;
|
|
UCHAR *Pos, *Buf;
|
|
UINT16 VarLen;
|
|
UINT32 Len = 0;
|
|
INT32 Ret;
|
|
BOOLEAN Cancelled;
|
|
|
|
DBGPRINT(RT_DEBUG_TRACE, ("%s\n", __FUNCTION__));
|
|
|
|
if (GASFrame->u.GAS_INIT_RSP.GASComebackDelay == 0)
|
|
{
|
|
VarLen = le2cpu16(*(UINT16 *)(GASFrame->u.GAS_INIT_RSP.Variable + 4));
|
|
os_alloc_mem(NULL, (UCHAR **)&Buf, sizeof(*Event) + VarLen);
|
|
|
|
if (!Buf)
|
|
{
|
|
DBGPRINT(RT_DEBUG_ERROR, ("%s Not available memory\n", __FUNCTION__));
|
|
return;
|
|
}
|
|
|
|
NdisZeroMemory(Buf, sizeof(*Event) + VarLen);
|
|
|
|
Event = (GAS_EVENT_DATA *)Buf;
|
|
|
|
Event->ControlIndex = 0;
|
|
Len += 1;
|
|
|
|
NdisMoveMemory(Event->PeerMACAddr, GASFrame->Hdr.Addr2, MAC_ADDR_LEN);
|
|
Len += MAC_ADDR_LEN;
|
|
|
|
Event->EventType = PEER_GAS_RSP;
|
|
Len += 2;
|
|
|
|
Event->u.PEER_GAS_RSP_DATA.StatusCode = le2cpu16(GASFrame->u.GAS_INIT_RSP.StatusCode);
|
|
Len += 2;
|
|
Pos = GASFrame->u.GAS_INIT_RSP.Variable + 3;
|
|
|
|
Event->u.PEER_GAS_RSP_DATA.AdvertisementProID = *Pos;
|
|
Len += 1;
|
|
Pos++;
|
|
|
|
Event->u.PEER_GAS_RSP_DATA.QueryRspLen = le2cpu16(*(UINT16 *)Pos);
|
|
Len += 2;
|
|
Pos += 2;
|
|
|
|
if (Event->u.PEER_GAS_RSP_DATA.QueryRspLen > 0)
|
|
NdisMoveMemory(Event->u.PEER_GAS_RSP_DATA.QueryRsp, Pos,
|
|
Event->u.PEER_GAS_RSP_DATA.QueryRspLen);
|
|
|
|
Len += Event->u.PEER_GAS_RSP_DATA.QueryRspLen;
|
|
|
|
RTMP_SEM_EVENT_WAIT(&pGASCtrl->GASPeerListLock, Ret);
|
|
/* Cancel GASResponse Timer */
|
|
DlListForEach(GASPeerEntry, &pGASCtrl->GASPeerList, GAS_PEER_ENTRY, List)
|
|
{
|
|
if (MAC_ADDR_EQUAL(GASPeerEntry->PeerMACAddr, Event->PeerMACAddr))
|
|
{
|
|
if (GASPeerEntry->GASResponseTimerRunning)
|
|
{
|
|
RTMPCancelTimer(&GASPeerEntry->GASResponseTimer, &Cancelled);
|
|
GASPeerEntry->GASResponseTimerRunning = FALSE;
|
|
}
|
|
|
|
break;
|
|
}
|
|
}
|
|
RTMP_SEM_EVENT_UP(&pGASCtrl->GASPeerListLock);
|
|
|
|
MlmeEnqueue(pAd, GAS_STATE_MACHINE, PEER_GAS_RSP, Len, Buf,0);
|
|
|
|
os_free_mem(NULL, Buf);
|
|
}
|
|
else
|
|
{
|
|
RTMP_SEM_EVENT_WAIT(&pGASCtrl->GASPeerListLock, Ret);
|
|
DlListForEach(GASPeerEntry, &pGASCtrl->GASPeerList, GAS_PEER_ENTRY, List)
|
|
{
|
|
if (MAC_ADDR_EQUAL(GASPeerEntry->PeerMACAddr, GASFrame->Hdr.Addr2))
|
|
{
|
|
GASPeerEntry->DialogToken = GASFrame->u.GAS_INIT_RSP.DialogToken;
|
|
|
|
/* Set a GAS comeback delay timeout timer
|
|
* to send out GAS comeback request
|
|
*/
|
|
GASPeerEntry->Priv = pAd;
|
|
if (!GASPeerEntry->GASCBDelayTimerRunning)
|
|
{
|
|
RTMPSetTimer(&GASPeerEntry->GASCBDelayTimer,
|
|
(GASFrame->u.GAS_INIT_RSP.GASComebackDelay * 1024) / 1000);
|
|
GASPeerEntry->GASCBDelayTimerRunning = TRUE;
|
|
}
|
|
|
|
break;
|
|
}
|
|
}
|
|
RTMP_SEM_EVENT_UP(&pGASCtrl->GASPeerListLock);
|
|
}
|
|
}
|
|
|
|
|
|
static VOID SendGASCBReq(
|
|
IN PRTMP_ADAPTER pAd,
|
|
IN MLME_QUEUE_ELEM *Elem)
|
|
{
|
|
GAS_EVENT_DATA *Event = (GAS_EVENT_DATA *)Elem->Msg;
|
|
UCHAR *Buf;
|
|
GAS_FRAME *GASFrame;
|
|
UINT32 FrameLen = 0;
|
|
|
|
DBGPRINT(RT_DEBUG_TRACE, ("%s\n", __FUNCTION__));
|
|
|
|
os_alloc_mem(pAd, (UCHAR **)&Buf, sizeof(*GASFrame));
|
|
|
|
if (!Buf)
|
|
{
|
|
DBGPRINT(RT_DEBUG_ERROR, ("%s Not available memory\n", __FUNCTION__));
|
|
return;
|
|
}
|
|
|
|
NdisZeroMemory(Buf, sizeof(*GASFrame));
|
|
|
|
GASFrame = (GAS_FRAME *)Buf;
|
|
|
|
ActHeaderInit(pAd, &GASFrame->Hdr, Event->PeerMACAddr ,pAd->CurrentAddress,
|
|
Event->PeerMACAddr);
|
|
|
|
FrameLen += sizeof(HEADER_802_11);
|
|
|
|
GASFrame->Category = CATEGORY_PUBLIC;
|
|
GASFrame->u.GAS_CB_REQ.Action = ACTION_GAS_CB_REQ;
|
|
|
|
if (Event->EventType == PEER_GAS_RSP_MORE)
|
|
GASFrame->u.GAS_CB_REQ.DialogToken = Event->u.PEER_GAS_RSP_MORE_DATA.DialogToken;
|
|
else if (Event->EventType == GAS_CB_RSP_MORE)
|
|
GASFrame->u.GAS_CB_REQ.DialogToken = Event->u.GAS_CB_RSP_MORE_DATA.DialogToken;
|
|
|
|
FrameLen += 3;
|
|
|
|
MiniportMMRequest(pAd, 0, Buf, FrameLen);
|
|
|
|
GASSetPeerCurrentState(pAd, Elem, WAIT_GAS_CB_RSP);
|
|
|
|
os_free_mem(NULL, Buf);
|
|
}
|
|
|
|
|
|
VOID ReceiveGASCBRsp(
|
|
IN PRTMP_ADAPTER pAd,
|
|
IN MLME_QUEUE_ELEM *Elem)
|
|
{
|
|
GAS_EVENT_DATA *Event;
|
|
GAS_FRAME *GASFrame = (GAS_FRAME *)Elem->Msg;
|
|
PGAS_CTRL pGASCtrl = &pAd->StaCfg.GASCtrl;
|
|
UINT16 VarLen = 0, QueryRspLen = 0;
|
|
GAS_PEER_ENTRY *GASPeerEntry;
|
|
GAS_QUERY_RSP_FRAGMENT *GASQueryRspFrag;
|
|
UCHAR *Pos, *Buf;
|
|
BOOLEAN Cancelled;
|
|
INT32 Ret;
|
|
UINT32 Len = 0;
|
|
UINT16 StatusCode;
|
|
|
|
DBGPRINT(RT_DEBUG_TRACE, ("%s\n", __FUNCTION__));
|
|
|
|
/* GAS comeback response length */
|
|
Pos = GASFrame->u.GAS_CB_RSP.Variable + 4;
|
|
QueryRspLen = le2cpu16(*(UINT16 *)(Pos));
|
|
|
|
RTMP_SEM_EVENT_WAIT(&pGASCtrl->GASPeerListLock, Ret);
|
|
DlListForEach(GASPeerEntry, &pGASCtrl->GASPeerList, GAS_PEER_ENTRY, List)
|
|
{
|
|
if (MAC_ADDR_EQUAL(GASPeerEntry->PeerMACAddr, GASFrame->Hdr.Addr2))
|
|
{
|
|
if (QueryRspLen > 0)
|
|
{
|
|
Pos += 2;
|
|
|
|
os_alloc_mem(NULL, (UCHAR **)&GASQueryRspFrag, sizeof(*GASQueryRspFrag));
|
|
|
|
if (!GASQueryRspFrag)
|
|
{
|
|
DBGPRINT(RT_DEBUG_ERROR, ("%s Not available memory\n", __FUNCTION__));
|
|
RTMP_SEM_EVENT_UP(&pGASCtrl->GASPeerListLock);
|
|
return;
|
|
}
|
|
|
|
NdisZeroMemory(GASQueryRspFrag, sizeof(*GASQueryRspFrag));
|
|
|
|
GASQueryRspFrag->GASRspFragID =
|
|
GASFrame->u.GAS_CB_RSP.GASRspFragID & 0x7F;
|
|
|
|
GASQueryRspFrag->FragQueryRspLen = QueryRspLen;
|
|
|
|
os_alloc_mem(NULL, (UCHAR **)&GASQueryRspFrag->FragQueryRsp,
|
|
GASQueryRspFrag->FragQueryRspLen);
|
|
|
|
if (!GASQueryRspFrag->FragQueryRsp)
|
|
{
|
|
DBGPRINT(RT_DEBUG_ERROR, ("%s Not available memory\n", __FUNCTION__));
|
|
RTMP_SEM_EVENT_UP(&pGASCtrl->GASPeerListLock);
|
|
goto error0;
|
|
}
|
|
|
|
NdisMoveMemory(GASQueryRspFrag->FragQueryRsp, Pos,
|
|
GASQueryRspFrag->FragQueryRspLen);
|
|
|
|
DlListAddTail(&GASPeerEntry->GASQueryRspFragList,
|
|
&GASQueryRspFrag->List);
|
|
|
|
GASPeerEntry->GASRspFragNum++;
|
|
GASPeerEntry->CurrentGASFragNum++;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
RTMP_SEM_EVENT_UP(&pGASCtrl->GASPeerListLock);
|
|
|
|
StatusCode = le2cpu16(GASFrame->u.GAS_CB_RSP.StatusCode);
|
|
|
|
if ((StatusCode == RESPONSE_NOT_RECEIVED_FROM_SERVER) ||
|
|
((StatusCode == 0) &&
|
|
((GASFrame->u.GAS_CB_RSP.GASRspFragID & 0x80) == 0x80)))
|
|
{
|
|
os_alloc_mem(NULL, (UCHAR **)&Buf, sizeof(*Event));
|
|
|
|
if (!Buf)
|
|
{
|
|
DBGPRINT(RT_DEBUG_ERROR, ("%s Not available memory\n", __FUNCTION__));
|
|
goto error1;
|
|
}
|
|
|
|
NdisZeroMemory(Buf, sizeof(*Event));
|
|
|
|
Event = (GAS_EVENT_DATA *)Buf;
|
|
|
|
Event->ControlIndex = 0;
|
|
Len += 1;
|
|
|
|
NdisMoveMemory(Event->PeerMACAddr, GASFrame->Hdr.Addr2, MAC_ADDR_LEN);
|
|
Len += MAC_ADDR_LEN;
|
|
|
|
Event->EventType = GAS_CB_RSP_MORE;
|
|
Len += 2;
|
|
|
|
Event->u.GAS_CB_RSP_MORE_DATA.DialogToken = GASPeerEntry->DialogToken;
|
|
Len += 1;
|
|
|
|
/* Reset dot11GASResponse timer */
|
|
if (GASPeerEntry->GASResponseTimerRunning)
|
|
RTMPModTimer(&GASPeerEntry->GASResponseTimer, dot11GASResponseTimeout);
|
|
|
|
MlmeEnqueue(pAd, GAS_STATE_MACHINE, GAS_CB_RSP_MORE, Len, Buf,0);
|
|
|
|
os_free_mem(NULL, Buf);
|
|
|
|
}else if ((StatusCode == TIMEOUT) ||
|
|
(StatusCode == QUERY_RESPONSE_TOO_LARGE) ||
|
|
(StatusCode == UNSPECIFIED_FAILURE) ||
|
|
((StatusCode == 0) &&
|
|
((GASFrame->u.GAS_CB_RSP.GASRspFragID & 0x80) == 0x00)))
|
|
{
|
|
if (StatusCode == 0)
|
|
{
|
|
RTMP_SEM_EVENT_WAIT(&pGASCtrl->GASPeerListLock, Ret);
|
|
DlListForEach(GASQueryRspFrag, &GASPeerEntry->GASQueryRspFragList, GAS_QUERY_RSP_FRAGMENT, List)
|
|
VarLen += GASQueryRspFrag->FragQueryRspLen;
|
|
RTMP_SEM_EVENT_UP(&pGASCtrl->GASPeerListLock);
|
|
}
|
|
|
|
os_alloc_mem(NULL, (UCHAR **)&Buf, sizeof(*Event) + VarLen);
|
|
|
|
if (!Buf)
|
|
{
|
|
DBGPRINT(RT_DEBUG_ERROR, ("%s Not available memory\n", __FUNCTION__));
|
|
goto error1;
|
|
}
|
|
|
|
NdisZeroMemory(Buf, sizeof(*Event) + VarLen);
|
|
|
|
Event = (GAS_EVENT_DATA *)Buf;
|
|
|
|
Event->ControlIndex = 0;
|
|
Len += 1;
|
|
|
|
NdisMoveMemory(Event->PeerMACAddr, GASFrame->Hdr.Addr2, MAC_ADDR_LEN);
|
|
Len += MAC_ADDR_LEN;
|
|
|
|
Event->EventType = GAS_CB_RSP;
|
|
Len += 2;
|
|
|
|
Event->u.GAS_CB_RSP_DATA.StatusCode = StatusCode;
|
|
Len += 2;
|
|
|
|
Event->u.GAS_CB_RSP_DATA.AdvertisementProID = GASPeerEntry->AdvertisementProID;
|
|
Len += 1;
|
|
|
|
if (GASFrame->u.GAS_CB_RSP.StatusCode == 0)
|
|
Event->u.GAS_CB_RSP_DATA.QueryRspLen = VarLen;
|
|
else
|
|
Event->u.GAS_CB_RSP_DATA.QueryRspLen = 0;
|
|
|
|
Len += 2;
|
|
|
|
if (Event->u.GAS_CB_RSP_DATA.QueryRspLen > 0)
|
|
{
|
|
Pos = Event->u.GAS_CB_RSP_DATA.QueryRsp;
|
|
|
|
RTMP_SEM_EVENT_WAIT(&pGASCtrl->GASPeerListLock, Ret);
|
|
DlListForEach(GASQueryRspFrag, &GASPeerEntry->GASQueryRspFragList, GAS_QUERY_RSP_FRAGMENT, List)
|
|
{
|
|
NdisMoveMemory(Pos, GASQueryRspFrag->FragQueryRsp,
|
|
GASQueryRspFrag->FragQueryRspLen);
|
|
Pos += GASQueryRspFrag->FragQueryRspLen;
|
|
}
|
|
RTMP_SEM_EVENT_UP(&pGASCtrl->GASPeerListLock);
|
|
}
|
|
|
|
Len += Event->u.GAS_CB_RSP_DATA.QueryRspLen;
|
|
|
|
if (GASPeerEntry->GASResponseTimerRunning)
|
|
{
|
|
RTMPCancelTimer(&GASPeerEntry->GASResponseTimer, &Cancelled);
|
|
GASPeerEntry->GASResponseTimerRunning = FALSE;
|
|
}
|
|
|
|
MlmeEnqueue(pAd, GAS_STATE_MACHINE, GAS_CB_RSP, Len, Buf,0);
|
|
os_free_mem(NULL, Buf);
|
|
}
|
|
|
|
return;
|
|
|
|
error1:
|
|
if (QueryRspLen > 0)
|
|
os_free_mem(NULL, GASQueryRspFrag->FragQueryRsp);
|
|
error0:
|
|
os_free_mem(NULL, GASQueryRspFrag);
|
|
}
|
|
|
|
|
|
static VOID SendGASConfirm(
|
|
IN PRTMP_ADAPTER pAd,
|
|
IN MLME_QUEUE_ELEM *Elem)
|
|
{
|
|
|
|
PGAS_CTRL pGASCtrl = &pAd->StaCfg.GASCtrl;
|
|
GAS_EVENT_DATA *Event = (GAS_EVENT_DATA *)Elem->Msg;
|
|
GAS_PEER_ENTRY *GASPeerEntry, *GASPeerEntryTmp;
|
|
GAS_QUERY_RSP_FRAGMENT *GASQueryRspFrag, *GASQueryRspFragTmp;
|
|
INT32 Ret;
|
|
BOOLEAN Cancelled;
|
|
|
|
DBGPRINT(RT_DEBUG_TRACE, ("%s\n", __FUNCTION__));
|
|
|
|
if (Event->EventType == PEER_GAS_RSP)
|
|
{
|
|
if (Event->u.PEER_GAS_RSP_DATA.AdvertisementProID == ACCESS_NETWORK_QUERY_PROTOCOL)
|
|
{
|
|
/* Send GAS confirm to daemon */
|
|
SendAnqpRspEvent(pAd->net_dev,
|
|
Event->PeerMACAddr,
|
|
Event->u.PEER_GAS_RSP_DATA.StatusCode,
|
|
Event->u.PEER_GAS_RSP_DATA.QueryRsp,
|
|
Event->u.PEER_GAS_RSP_DATA.QueryRspLen);
|
|
}
|
|
}
|
|
else if (Event->EventType == GAS_CB_RSP)
|
|
{
|
|
if (Event->u.GAS_CB_RSP_DATA.AdvertisementProID == ACCESS_NETWORK_QUERY_PROTOCOL)
|
|
{
|
|
/* Send GAS confirm to daemon */
|
|
SendAnqpRspEvent(pAd->net_dev,
|
|
Event->PeerMACAddr,
|
|
Event->u.GAS_CB_RSP_DATA.StatusCode,
|
|
Event->u.GAS_CB_RSP_DATA.QueryRsp,
|
|
Event->u.GAS_CB_RSP_DATA.QueryRspLen);
|
|
|
|
}
|
|
}
|
|
|
|
RTMP_SEM_EVENT_WAIT(&pGASCtrl->GASPeerListLock, Ret);
|
|
DlListForEachSafe(GASPeerEntry, GASPeerEntryTmp, &pGASCtrl->GASPeerList, GAS_PEER_ENTRY, List)
|
|
{
|
|
if (MAC_ADDR_EQUAL(GASPeerEntry->PeerMACAddr, Event->PeerMACAddr))
|
|
{
|
|
|
|
DlListForEachSafe(GASQueryRspFrag, GASQueryRspFragTmp, &GASPeerEntry->GASQueryRspFragList,
|
|
GAS_QUERY_RSP_FRAGMENT, List)
|
|
{
|
|
DlListDel(&GASQueryRspFrag->List);
|
|
os_free_mem(NULL, GASQueryRspFrag->FragQueryRsp);
|
|
os_free_mem(NULL, GASQueryRspFrag);
|
|
}
|
|
DlListInit(&GASPeerEntry->GASQueryRspFragList);
|
|
DlListDel(&GASPeerEntry->List);
|
|
if (GASPeerEntry->GASResponseTimerRunning)
|
|
RTMPCancelTimer(&GASPeerEntry->GASResponseTimer, &Cancelled);
|
|
if (GASPeerEntry->GASCBDelayTimerRunning)
|
|
RTMPCancelTimer(&GASPeerEntry->GASCBDelayTimer, &Cancelled);
|
|
RTMPReleaseTimer(&GASPeerEntry->GASResponseTimer, &Cancelled);
|
|
RTMPReleaseTimer(&GASPeerEntry->GASCBDelayTimer, &Cancelled);
|
|
os_free_mem(NULL, GASPeerEntry);
|
|
break;
|
|
}
|
|
}
|
|
RTMP_SEM_EVENT_UP(&pGASCtrl->GASPeerListLock);
|
|
}
|
|
|
|
|
|
void GASResponseTimeout(
|
|
IN PVOID SystemSpecific1,
|
|
IN PVOID FunctionContext,
|
|
IN PVOID SystemSpecific2,
|
|
IN PVOID SystemSpecific3)
|
|
{
|
|
GAS_PEER_ENTRY *GASPeerEntry = (GAS_PEER_ENTRY *)FunctionContext;
|
|
GAS_EVENT_DATA *Event;
|
|
IN PRTMP_ADAPTER pAd;
|
|
UCHAR *Buf;
|
|
UINT32 Len = 0;
|
|
|
|
DBGPRINT(RT_DEBUG_TRACE, ("%s\n", __FUNCTION__));
|
|
|
|
if (!GASPeerEntry)
|
|
return;
|
|
|
|
pAd = GASPeerEntry->Priv;
|
|
|
|
if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS
|
|
| fRTMP_ADAPTER_NIC_NOT_EXIST))
|
|
return;
|
|
|
|
if (GASPeerEntry->GASResponseTimerRunning)
|
|
{
|
|
GASPeerEntry->GASResponseTimerRunning = FALSE;
|
|
|
|
os_alloc_mem(NULL, (UCHAR **)&Buf, sizeof(*Event));
|
|
|
|
if (!Buf)
|
|
{
|
|
DBGPRINT(RT_DEBUG_ERROR, ("%s Not available memory\n", __FUNCTION__));
|
|
return;
|
|
}
|
|
|
|
NdisZeroMemory(Buf, sizeof(*Event));
|
|
|
|
Event = (GAS_EVENT_DATA *)Buf;
|
|
|
|
Event->ControlIndex = GASPeerEntry->ControlIndex;
|
|
Len += 1;
|
|
|
|
NdisMoveMemory(Event->PeerMACAddr, GASPeerEntry->PeerMACAddr, MAC_ADDR_LEN);
|
|
Len += MAC_ADDR_LEN;
|
|
|
|
if (GASPeerEntry->CurrentState == WAIT_PEER_GAS_RSP)
|
|
{
|
|
Event->EventType = PEER_GAS_RSP;
|
|
Len += 2;
|
|
|
|
Event->u.PEER_GAS_RSP_DATA.StatusCode = TIMEOUT;
|
|
Len += 2;
|
|
|
|
Event->u.PEER_GAS_RSP_DATA.AdvertisementProID = GASPeerEntry->AdvertisementProID;
|
|
Len += 1;
|
|
|
|
Event->u.PEER_GAS_RSP_DATA.QueryRspLen = 0;
|
|
Len += 2;
|
|
|
|
MlmeEnqueue(pAd, GAS_STATE_MACHINE, PEER_GAS_RSP, Len, Buf,0);
|
|
}
|
|
else if (GASPeerEntry->CurrentState == WAIT_GAS_CB_RSP)
|
|
{
|
|
Event->EventType = GAS_CB_RSP;
|
|
Len += 2;
|
|
|
|
Event->u.GAS_CB_RSP_DATA.StatusCode = TIMEOUT;
|
|
Len += 2;
|
|
|
|
Event->u.GAS_CB_RSP_DATA.AdvertisementProID = GASPeerEntry->AdvertisementProID;
|
|
Len += 1;
|
|
|
|
Event->u.GAS_CB_RSP_DATA.QueryRspLen = 0;
|
|
Len += 2;
|
|
|
|
MlmeEnqueue(pAd, GAS_STATE_MACHINE, GAS_CB_RSP, Len, Buf,0);
|
|
}
|
|
|
|
os_free_mem(NULL, Buf);
|
|
}
|
|
}
|
|
BUILD_TIMER_FUNCTION(GASResponseTimeout);
|
|
#endif /* CONFIG_STA_SUPPORT */
|
|
|
|
enum GAS_STATE GASPeerCurrentState(
|
|
IN PRTMP_ADAPTER pAd,
|
|
IN MLME_QUEUE_ELEM *Elem)
|
|
{
|
|
PGAS_CTRL pGASCtrl;
|
|
PGAS_PEER_ENTRY GASPeerEntry;
|
|
PGAS_EVENT_DATA Event = (PGAS_EVENT_DATA)Elem->Msg;
|
|
INT32 Ret;
|
|
|
|
#ifdef CONFIG_AP_SUPPORT
|
|
pGASCtrl = &pAd->ApCfg.MBSSID[Event->ControlIndex].GASCtrl;
|
|
#endif /* CONFIG_AP_SUPPORT */
|
|
|
|
#ifdef CONFIG_STA_SUPPORT
|
|
pGASCtrl = &pAd->StaCfg.GASCtrl;
|
|
#endif /* CONFIG_STA_SUPPORT */
|
|
|
|
RTMP_SEM_LOCK(&pGASCtrl->GASPeerListLock);
|
|
DlListForEach(GASPeerEntry, &pGASCtrl->GASPeerList, GAS_PEER_ENTRY, List)
|
|
{
|
|
if (MAC_ADDR_EQUAL(GASPeerEntry->PeerMACAddr, Event->PeerMACAddr))
|
|
{
|
|
|
|
RTMP_SEM_UNLOCK(&pGASCtrl->GASPeerListLock);
|
|
return GASPeerEntry->CurrentState;
|
|
}
|
|
}
|
|
RTMP_SEM_UNLOCK(&pGASCtrl->GASPeerListLock);
|
|
|
|
return GAS_UNKNOWN;
|
|
}
|
|
|
|
|
|
VOID GASSetPeerCurrentState(
|
|
IN PRTMP_ADAPTER pAd,
|
|
//IN MLME_QUEUE_ELEM *Elem,
|
|
PGAS_EVENT_DATA Event,
|
|
IN enum GAS_STATE State)
|
|
{
|
|
|
|
PGAS_CTRL pGASCtrl;
|
|
PGAS_PEER_ENTRY GASPeerEntry;
|
|
//PGAS_EVENT_DATA Event = (PGAS_EVENT_DATA)Elem->Msg;
|
|
|
|
#ifdef CONFIG_AP_SUPPORT
|
|
pGASCtrl = &pAd->ApCfg.MBSSID[Event->ControlIndex].GASCtrl;
|
|
#endif /* CONFIG_AP_SUPPORT */
|
|
|
|
#ifdef CONFIG_STA_SUPPORT
|
|
pGASCtrl = &pAd->StaCfg.GASCtrl;
|
|
#endif /* CONFIG_STA_SUPPORT */
|
|
|
|
RTMP_SEM_LOCK(&pGASCtrl->GASPeerListLock);
|
|
DlListForEach(GASPeerEntry, &pGASCtrl->GASPeerList, GAS_PEER_ENTRY, List)
|
|
{
|
|
if (MAC_ADDR_EQUAL(GASPeerEntry->PeerMACAddr, Event->PeerMACAddr))
|
|
{
|
|
GASPeerEntry->CurrentState = State;
|
|
break;
|
|
}
|
|
|
|
}
|
|
RTMP_SEM_UNLOCK(&pGASCtrl->GASPeerListLock);
|
|
}
|
|
|
|
|
|
#ifdef CONFIG_AP_SUPPORT
|
|
void wext_send_anqp_req_event(PNET_DEV net_dev, const char *peer_mac_addr,
|
|
const char *anqp_req, UINT16 anqp_req_len)
|
|
{
|
|
struct anqp_req_data *req_data;
|
|
UINT16 buflen = 0;
|
|
char *buf;
|
|
|
|
buflen = sizeof(*req_data) + anqp_req_len;
|
|
os_alloc_mem(NULL, (UCHAR **)&buf, buflen);
|
|
NdisZeroMemory(buf, buflen);
|
|
|
|
req_data = (struct anqp_req_data *)buf;
|
|
req_data->ifindex = RtmpOsGetNetIfIndex(net_dev);
|
|
memcpy(req_data->peer_mac_addr, peer_mac_addr, 6);
|
|
req_data->anqp_req_len = anqp_req_len;
|
|
memcpy(req_data->anqp_req, anqp_req, anqp_req_len);
|
|
|
|
RtmpOSWrielessEventSend(net_dev, RT_WLAN_EVENT_CUSTOM,
|
|
OID_802_11_HS_ANQP_REQ, NULL, (PUCHAR)buf, buflen);
|
|
|
|
os_free_mem(NULL, buf);
|
|
|
|
}
|
|
|
|
|
|
void SendAnqpReqEvent(PNET_DEV net_dev, const char *peer_mac_addr,
|
|
const char *anqp_req, UINT16 anqp_req_len)
|
|
{
|
|
wext_send_anqp_req_event(net_dev,
|
|
peer_mac_addr,
|
|
anqp_req,
|
|
anqp_req_len);
|
|
}
|
|
|
|
|
|
//static VOID SendGASRsp(
|
|
// IN PRTMP_ADAPTER pAd,
|
|
// IN MLME_QUEUE_ELEM *Elem)
|
|
VOID SendGASRsp(
|
|
IN PRTMP_ADAPTER pAd,
|
|
GAS_EVENT_DATA *Event)
|
|
{
|
|
|
|
//GAS_EVENT_DATA *Event = (GAS_EVENT_DATA *)Elem->Msg;
|
|
UCHAR *Buf, *Pos;
|
|
GAS_FRAME *GASFrame;
|
|
ULONG FrameLen = 0, VarLen = 0, tmpValue = 0;
|
|
PGAS_CTRL pGASCtrl = &pAd->ApCfg.MBSSID[Event->ControlIndex].GASCtrl;
|
|
GAS_PEER_ENTRY *GASPeerEntry;
|
|
BOOLEAN Cancelled;
|
|
unsigned long irqFlags=0;
|
|
|
|
DBGPRINT(RT_DEBUG_TRACE, ("%s\n", __FUNCTION__));
|
|
|
|
RTMP_SEM_LOCK(&pGASCtrl->GASPeerListLock);
|
|
DlListForEach(GASPeerEntry, &pGASCtrl->GASPeerList, GAS_PEER_ENTRY, List)
|
|
{
|
|
if (MAC_ADDR_EQUAL(GASPeerEntry->PeerMACAddr, Event->PeerMACAddr))
|
|
break;
|
|
}
|
|
RTMP_SEM_UNLOCK(&pGASCtrl->GASPeerListLock);
|
|
|
|
if (Event->u.GAS_RSP_DATA.AdvertisementProID == ACCESS_NETWORK_QUERY_PROTOCOL)
|
|
{
|
|
/* Advertisement protocol element + Query response length field */
|
|
VarLen += 6;
|
|
}
|
|
|
|
if (Event->EventType == GAS_RSP)
|
|
{
|
|
/* Query response field*/
|
|
VarLen += Event->u.GAS_RSP_DATA.QueryRspLen;
|
|
}
|
|
|
|
os_alloc_mem(NULL, (UCHAR **)&Buf, sizeof(*GASFrame) + VarLen);
|
|
|
|
if (!Buf)
|
|
{
|
|
DBGPRINT(RT_DEBUG_ERROR, ("%s Not available memory\n", __FUNCTION__));
|
|
//GASSetPeerCurrentState(pAd, Elem, WAIT_PEER_GAS_REQ);
|
|
GASSetPeerCurrentState(pAd, Event, WAIT_PEER_GAS_REQ);
|
|
|
|
RTMP_SEM_LOCK(&pGASCtrl->GASPeerListLock);
|
|
DlListDel(&GASPeerEntry->List);
|
|
DlListInit(&GASPeerEntry->GASQueryRspFragList);
|
|
RTMP_SEM_UNLOCK(&pGASCtrl->GASPeerListLock);
|
|
if (GASPeerEntry->PostReplyTimerRunning)
|
|
{
|
|
RTMPCancelTimer(&GASPeerEntry->PostReplyTimer, &Cancelled);
|
|
GASPeerEntry->PostReplyTimerRunning = FALSE;
|
|
}
|
|
RTMPReleaseTimer(&GASPeerEntry->PostReplyTimer, &Cancelled);
|
|
|
|
if (GASPeerEntry->GASRspBufferingTimerRunning)
|
|
{
|
|
RTMPCancelTimer(&GASPeerEntry->GASRspBufferingTimer, &Cancelled);
|
|
GASPeerEntry->GASRspBufferingTimerRunning = FALSE;
|
|
}
|
|
RTMPReleaseTimer(&GASPeerEntry->GASRspBufferingTimer, &Cancelled);
|
|
os_free_mem(NULL, GASPeerEntry);
|
|
return;
|
|
}
|
|
|
|
NdisZeroMemory(Buf, sizeof(*GASFrame) + VarLen);
|
|
|
|
GASFrame = (GAS_FRAME *)Buf;
|
|
|
|
ActHeaderInit(pAd, &GASFrame->Hdr, Event->PeerMACAddr ,pAd->ApCfg.MBSSID[Event->ControlIndex].wdev.bssid,
|
|
pAd->ApCfg.MBSSID[Event->ControlIndex].wdev.bssid);
|
|
|
|
FrameLen += sizeof(HEADER_802_11);
|
|
|
|
GASFrame->Category = CATEGORY_PUBLIC;
|
|
FrameLen += 1;
|
|
GASFrame->u.GAS_INIT_RSP.Action = ACTION_GAS_INIT_RSP;
|
|
FrameLen += 1;
|
|
|
|
if (Event->EventType == GAS_RSP)
|
|
{
|
|
GASFrame->u.GAS_INIT_RSP.DialogToken = Event->u.GAS_RSP_DATA.DialogToken;
|
|
FrameLen += 1;
|
|
|
|
GASFrame->u.GAS_INIT_RSP.StatusCode = cpu2le16(Event->u.GAS_RSP_DATA.StatusCode);
|
|
FrameLen += 2;
|
|
|
|
GASFrame->u.GAS_INIT_RSP.GASComebackDelay = Event->u.GAS_RSP_DATA.GASComebackDelay;
|
|
FrameLen += 2;
|
|
|
|
Pos = GASFrame->u.GAS_INIT_RSP.Variable;
|
|
*Pos++ = IE_ADVERTISEMENT_PROTO;
|
|
*Pos++ = 2; /* Length field */
|
|
*Pos++ = 0; /* Query response info field */
|
|
|
|
*Pos++ = Event->u.GAS_RSP_DATA.AdvertisementProID; /* Advertisement Protocol ID field */
|
|
|
|
tmpValue = cpu2le16(Event->u.GAS_RSP_DATA.QueryRspLen);
|
|
NdisMoveMemory(Pos, &tmpValue, 2);
|
|
Pos += 2;
|
|
FrameLen += 6;
|
|
|
|
if (Event->u.GAS_RSP_DATA.QueryRspLen > 0)
|
|
NdisMoveMemory(Pos, Event->u.GAS_RSP_DATA.QueryRsp, Event->u.GAS_RSP_DATA.QueryRspLen);
|
|
|
|
FrameLen += Event->u.GAS_RSP_DATA.QueryRspLen;
|
|
|
|
//GASSetPeerCurrentState(pAd, Elem, WAIT_PEER_GAS_REQ);
|
|
GASSetPeerCurrentState(pAd, Event, WAIT_PEER_GAS_REQ);
|
|
|
|
RTMP_SEM_LOCK(&pGASCtrl->GASPeerListLock);
|
|
DlListDel(&GASPeerEntry->List);
|
|
DlListInit(&GASPeerEntry->GASQueryRspFragList);
|
|
RTMP_SEM_UNLOCK(&pGASCtrl->GASPeerListLock);
|
|
|
|
if (GASPeerEntry->PostReplyTimerRunning)
|
|
{
|
|
RTMPCancelTimer(&GASPeerEntry->PostReplyTimer, &Cancelled);
|
|
GASPeerEntry->PostReplyTimerRunning = FALSE;
|
|
}
|
|
RTMPReleaseTimer(&GASPeerEntry->PostReplyTimer, &Cancelled);
|
|
GASPeerEntry->FreeResource++;
|
|
|
|
if (GASPeerEntry->GASRspBufferingTimerRunning)
|
|
{
|
|
RTMPCancelTimer(&GASPeerEntry->GASRspBufferingTimer, &Cancelled);
|
|
GASPeerEntry->GASRspBufferingTimerRunning = FALSE;
|
|
}
|
|
RTMPReleaseTimer(&GASPeerEntry->GASRspBufferingTimer, &Cancelled);
|
|
GASPeerEntry->FreeResource++;
|
|
|
|
GASPeerEntry->FreeResource++;
|
|
os_free_mem(NULL, GASPeerEntry);
|
|
|
|
}
|
|
else if (Event->EventType == GAS_RSP_MORE)
|
|
{
|
|
|
|
GASFrame->u.GAS_INIT_RSP.DialogToken = Event->u.GAS_RSP_MORE_DATA.DialogToken;
|
|
FrameLen += 1;
|
|
|
|
GASFrame->u.GAS_INIT_RSP.StatusCode = cpu2le16(Event->u.GAS_RSP_MORE_DATA.StatusCode);
|
|
FrameLen += 2;
|
|
|
|
GASFrame->u.GAS_INIT_RSP.GASComebackDelay = Event->u.GAS_RSP_MORE_DATA.GASComebackDelay;
|
|
FrameLen += 2;
|
|
|
|
Pos = GASFrame->u.GAS_INIT_RSP.Variable;
|
|
*Pos++ = IE_ADVERTISEMENT_PROTO;
|
|
*Pos++ = 2; /* Length field */
|
|
*Pos++ = 0; /* Query response info field */
|
|
|
|
*Pos++ = Event->u.GAS_RSP_MORE_DATA.AdvertisementProID; /* Advertisement Protocol ID field */
|
|
|
|
tmpValue = 0;
|
|
NdisMoveMemory(Pos, &tmpValue, 2);
|
|
|
|
Pos += 2;
|
|
FrameLen += 6;
|
|
|
|
//GASSetPeerCurrentState(pAd, Elem, WAIT_GAS_CB_REQ);
|
|
GASSetPeerCurrentState(pAd, Event, WAIT_GAS_CB_REQ);
|
|
|
|
/*
|
|
* Buffer the query response for a minimun of dotGASResponseBufferingTime
|
|
* after the expiry of the GAS comeback delay
|
|
*/
|
|
if (!GASPeerEntry->GASRspBufferingTimerRunning)
|
|
{
|
|
RTMPSetTimer(&GASPeerEntry->GASRspBufferingTimer, dotGASResponseBufferingTime
|
|
+ GASFrame->u.GAS_INIT_RSP.GASComebackDelay);
|
|
GASPeerEntry->GASRspBufferingTimerRunning = TRUE;
|
|
}
|
|
|
|
}
|
|
|
|
MiniportMMRequest(pAd, 0, Buf, FrameLen);
|
|
|
|
os_free_mem(NULL, Buf);
|
|
}
|
|
|
|
|
|
VOID ReceiveGASInitReq(
|
|
IN PRTMP_ADAPTER pAd,
|
|
IN MLME_QUEUE_ELEM *Elem)
|
|
{
|
|
GAS_EVENT_DATA *Event;
|
|
GAS_FRAME *GASFrame = (GAS_FRAME *)Elem->Msg;
|
|
GAS_PEER_ENTRY *GASPeerEntry, *GASPeerEntryTmp;
|
|
PGAS_CTRL pGASCtrl = NULL;
|
|
UCHAR APIndex, *Pos, *Buf;
|
|
UINT16 VarLen;
|
|
UINT32 Len = 0;
|
|
BOOLEAN IsFound = FALSE, Cancelled;;
|
|
|
|
DBGPRINT(RT_DEBUG_TRACE, ("%s\n", __FUNCTION__));
|
|
|
|
for (APIndex = 0; APIndex < MAX_MBSSID_NUM(pAd); APIndex++)
|
|
{
|
|
if (MAC_ADDR_EQUAL(GASFrame->Hdr.Addr3, pAd->ApCfg.MBSSID[APIndex].wdev.bssid))
|
|
{
|
|
pGASCtrl = &pAd->ApCfg.MBSSID[APIndex].GASCtrl;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (!pGASCtrl)
|
|
{
|
|
DBGPRINT(RT_DEBUG_ERROR, ("%s Can not find Peer Control\n", __FUNCTION__));
|
|
return;
|
|
}
|
|
|
|
RTMP_SEM_LOCK(&pGASCtrl->GASPeerListLock);
|
|
DlListForEach(GASPeerEntry, &pGASCtrl->GASPeerList, GAS_PEER_ENTRY, List)
|
|
{
|
|
if (MAC_ADDR_EQUAL(GASPeerEntry->PeerMACAddr, GASFrame->Hdr.Addr2))
|
|
{
|
|
IsFound = TRUE;
|
|
GASPeerEntry->QueryNum++;
|
|
break;
|
|
}
|
|
}
|
|
RTMP_SEM_UNLOCK(&pGASCtrl->GASPeerListLock);
|
|
|
|
if (IsFound) {
|
|
|
|
//if (GASPeerEntry->QueryNum++ >= 15)
|
|
{
|
|
/* Query too many times, remove the peer address from list */
|
|
DBGPRINT(RT_DEBUG_OFF, ("%s Q %d, old 0x%x, 0x%x, %02x:%02x:%02x:%02x:%02x:%02x remove peer\n", __FUNCTION__, GASPeerEntry->QueryNum, GASPeerEntry->DialogToken, GASFrame->u.GAS_INIT_REQ.DialogToken, GASPeerEntry->PeerMACAddr[0], GASPeerEntry->PeerMACAddr[1], GASPeerEntry->PeerMACAddr[2], GASPeerEntry->PeerMACAddr[3], GASPeerEntry->PeerMACAddr[4], GASPeerEntry->PeerMACAddr[5]));
|
|
|
|
RTMP_SEM_LOCK(&pGASCtrl->GASPeerListLock);
|
|
DlListForEachSafe(GASPeerEntry, GASPeerEntryTmp, &pGASCtrl->GASPeerList, GAS_PEER_ENTRY, List)
|
|
{
|
|
if (MAC_ADDR_EQUAL(GASPeerEntry->PeerMACAddr, GASFrame->Hdr.Addr2))
|
|
{
|
|
DlListDel(&GASPeerEntry->List);
|
|
DlListInit(&GASPeerEntry->GASQueryRspFragList);
|
|
|
|
if (GASPeerEntry->PostReplyTimerRunning)
|
|
{
|
|
RTMPCancelTimer(&GASPeerEntry->PostReplyTimer, &Cancelled);
|
|
GASPeerEntry->PostReplyTimerRunning = FALSE;
|
|
}
|
|
RTMPReleaseTimer(&GASPeerEntry->PostReplyTimer, &Cancelled);
|
|
|
|
if (GASPeerEntry->GASRspBufferingTimerRunning)
|
|
{
|
|
RTMPCancelTimer(&GASPeerEntry->GASRspBufferingTimer, &Cancelled);
|
|
GASPeerEntry->GASRspBufferingTimerRunning = FALSE;
|
|
}
|
|
RTMPReleaseTimer(&GASPeerEntry->GASRspBufferingTimer, &Cancelled);
|
|
GASPeerEntry->FreeResource++;
|
|
|
|
os_free_mem(NULL, GASPeerEntry);
|
|
}
|
|
}
|
|
RTMP_SEM_UNLOCK(&pGASCtrl->GASPeerListLock);
|
|
}
|
|
//return;
|
|
}
|
|
|
|
os_alloc_mem(NULL, (UCHAR **)&GASPeerEntry, sizeof(*GASPeerEntry));
|
|
|
|
if (!GASPeerEntry)
|
|
{
|
|
DBGPRINT(RT_DEBUG_ERROR, ("%s Not available memory\n", __FUNCTION__));
|
|
return;
|
|
}
|
|
|
|
NdisZeroMemory(GASPeerEntry, sizeof(*GASPeerEntry));
|
|
GASPeerEntry->AllocResource++;
|
|
|
|
GASPeerEntry->CurrentState = WAIT_PEER_GAS_REQ;
|
|
GASPeerEntry->QueryNum++;
|
|
NdisMoveMemory(GASPeerEntry->PeerMACAddr, GASFrame->Hdr.Addr2, MAC_ADDR_LEN);
|
|
GASPeerEntry->DialogToken = GASFrame->u.GAS_INIT_REQ.DialogToken;
|
|
GASPeerEntry->Priv = pAd;
|
|
RTMPInitTimer(pAd, &GASPeerEntry->PostReplyTimer,
|
|
GET_TIMER_FUNCTION(PostReplyTimeout), GASPeerEntry, FALSE);
|
|
GASPeerEntry->AllocResource++;
|
|
RTMPInitTimer(pAd, &GASPeerEntry->GASRspBufferingTimer,
|
|
GET_TIMER_FUNCTION(GASRspBufferingTimeout), GASPeerEntry, FALSE);
|
|
GASPeerEntry->AllocResource++;
|
|
|
|
DlListInit(&GASPeerEntry->GASQueryRspFragList);
|
|
|
|
RTMP_SEM_LOCK(&pGASCtrl->GASPeerListLock);
|
|
DlListAddTail(&pGASCtrl->GASPeerList, &GASPeerEntry->List);
|
|
RTMP_SEM_UNLOCK(&pGASCtrl->GASPeerListLock);
|
|
|
|
NdisMoveMemory(&VarLen, GASFrame->u.GAS_INIT_REQ.Variable + 4, 2);
|
|
VarLen = le2cpu16(VarLen);
|
|
|
|
os_alloc_mem(NULL, (UCHAR **)&Buf, sizeof(*Event) + VarLen);
|
|
|
|
if (!Buf)
|
|
{
|
|
DBGPRINT(RT_DEBUG_ERROR, ("%s Not available memory\n", __FUNCTION__));
|
|
goto error;
|
|
}
|
|
|
|
NdisZeroMemory(Buf, sizeof(*Event) + VarLen);
|
|
|
|
Event = (GAS_EVENT_DATA *)Buf;
|
|
|
|
Event->ControlIndex = APIndex;
|
|
Len += 1;
|
|
|
|
NdisMoveMemory(Event->PeerMACAddr, GASFrame->Hdr.Addr2, MAC_ADDR_LEN);
|
|
Len += MAC_ADDR_LEN;
|
|
|
|
Event->EventType = PEER_GAS_REQ;
|
|
Len += 2;
|
|
|
|
Event->u.PEER_GAS_REQ_DATA.DialogToken = GASFrame->u.GAS_INIT_REQ.DialogToken;
|
|
Len += 1;
|
|
|
|
Pos = GASFrame->u.GAS_INIT_REQ.Variable + 3;
|
|
Event->u.PEER_GAS_REQ_DATA.AdvertisementProID = *Pos;
|
|
GASPeerEntry->AdvertisementProID = *Pos;
|
|
Len += 1;
|
|
Pos++;
|
|
|
|
NdisMoveMemory(&Event->u.PEER_GAS_REQ_DATA.QueryReqLen, Pos, 2);
|
|
Event->u.PEER_GAS_REQ_DATA.QueryReqLen = le2cpu16(Event->u.PEER_GAS_REQ_DATA.QueryReqLen);
|
|
Len += 2;
|
|
Pos += 2;
|
|
|
|
NdisMoveMemory(Event->u.PEER_GAS_REQ_DATA.QueryReq, Pos, Event->u.PEER_GAS_REQ_DATA.QueryReqLen);
|
|
Len += Event->u.PEER_GAS_REQ_DATA.QueryReqLen;
|
|
|
|
SendGASIndication(pAd, (GAS_EVENT_DATA *)Buf);
|
|
//MlmeEnqueue(pAd, GAS_STATE_MACHINE, PEER_GAS_REQ, Len, Buf,0);
|
|
|
|
//RTMP_MLME_HANDLER(pAd);
|
|
|
|
os_free_mem(NULL, Buf);
|
|
|
|
return;
|
|
|
|
error:
|
|
DlListDel(&GASPeerEntry->List);
|
|
os_free_mem(NULL, GASPeerEntry);
|
|
}
|
|
|
|
|
|
static VOID SendGASCBRsp(
|
|
IN PRTMP_ADAPTER pAd,
|
|
//IN MLME_QUEUE_ELEM *Elem)
|
|
GAS_EVENT_DATA *Event)
|
|
{
|
|
//GAS_EVENT_DATA *Event = (GAS_EVENT_DATA *)Elem->Msg;
|
|
UCHAR *Buf, *Pos;
|
|
GAS_FRAME *GASFrame;
|
|
ULONG FrameLen = 0, VarLen = 0, tmpLen = 0;
|
|
GAS_PEER_ENTRY *GASPeerEntry;
|
|
GAS_QUERY_RSP_FRAGMENT *GASQueryRspFrag = NULL, *GASQueryRspFragTmp;
|
|
PGAS_CTRL pGASCtrl = &pAd->ApCfg.MBSSID[Event->ControlIndex].GASCtrl;
|
|
BOOLEAN bGASQueryRspFragFound = FALSE;
|
|
BOOLEAN Cancelled;
|
|
unsigned long irqFlags=0;
|
|
|
|
DBGPRINT(RT_DEBUG_TRACE, ("%s\n", __FUNCTION__));
|
|
|
|
RTMP_SEM_LOCK(&pGASCtrl->GASPeerListLock);
|
|
DlListForEach(GASPeerEntry, &pGASCtrl->GASPeerList, GAS_PEER_ENTRY, List)
|
|
{
|
|
if (MAC_ADDR_EQUAL(GASPeerEntry->PeerMACAddr, Event->PeerMACAddr))
|
|
{
|
|
if (GASPeerEntry->AdvertisementProID == ACCESS_NETWORK_QUERY_PROTOCOL)
|
|
{
|
|
/* Advertisement protocol element + Query response length field */
|
|
VarLen += 6;
|
|
}
|
|
|
|
DlListForEach(GASQueryRspFrag, &GASPeerEntry->GASQueryRspFragList,
|
|
GAS_QUERY_RSP_FRAGMENT, List)
|
|
{
|
|
if (GASPeerEntry->CurrentGASFragNum ==
|
|
GASQueryRspFrag->GASRspFragID)
|
|
{
|
|
GASPeerEntry->CurrentGASFragNum++;
|
|
VarLen += GASQueryRspFrag->FragQueryRspLen;
|
|
bGASQueryRspFragFound = TRUE;
|
|
break;
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
RTMP_SEM_UNLOCK(&pGASCtrl->GASPeerListLock);
|
|
|
|
os_alloc_mem(NULL, (UCHAR **)&Buf, sizeof(*GASFrame) + VarLen);
|
|
|
|
if (!Buf)
|
|
{
|
|
DBGPRINT(RT_DEBUG_ERROR, ("%s Not available memory\n", __FUNCTION__));
|
|
return;
|
|
}
|
|
|
|
NdisZeroMemory(Buf, sizeof(*GASFrame) + VarLen);
|
|
|
|
GASFrame = (GAS_FRAME *)Buf;
|
|
|
|
ActHeaderInit(pAd, &GASFrame->Hdr, Event->PeerMACAddr ,pAd->ApCfg.MBSSID[Event->ControlIndex].wdev.bssid,
|
|
pAd->ApCfg.MBSSID[Event->ControlIndex].wdev.bssid);
|
|
|
|
FrameLen += sizeof(HEADER_802_11);
|
|
|
|
GASFrame->Category = CATEGORY_PUBLIC;
|
|
FrameLen += 1;
|
|
|
|
GASFrame->u.GAS_CB_RSP.Action = ACTION_GAS_CB_RSP;
|
|
FrameLen += 1;
|
|
|
|
if (Event->EventType == GAS_CB_REQ)
|
|
{
|
|
GASFrame->u.GAS_CB_RSP.DialogToken = Event->u.GAS_CB_REQ_DATA.DialogToken;
|
|
FrameLen += 1;
|
|
|
|
GASFrame->u.GAS_CB_RSP.StatusCode = cpu2le16(Event->u.GAS_CB_REQ_DATA.StatusCode);
|
|
FrameLen += 2;
|
|
|
|
if (bGASQueryRspFragFound)
|
|
GASFrame->u.GAS_CB_RSP.GASRspFragID = (GASQueryRspFrag->GASRspFragID & 0x7F);
|
|
else
|
|
GASFrame->u.GAS_CB_RSP.GASRspFragID = 0;
|
|
|
|
DBGPRINT(RT_DEBUG_OFF, ("GASRspFragID = %d\n", GASFrame->u.GAS_CB_RSP.GASRspFragID));
|
|
|
|
FrameLen += 1;
|
|
|
|
GASFrame->u.GAS_CB_RSP.GASComebackDelay = 0;
|
|
FrameLen += 2;
|
|
|
|
Pos = GASFrame->u.GAS_CB_RSP.Variable;
|
|
*Pos++ = IE_ADVERTISEMENT_PROTO;
|
|
*Pos++ = 2; /* Length field */
|
|
*Pos++ = 0; /* Query response info field */
|
|
|
|
*Pos++ = Event->u.GAS_CB_REQ_DATA.AdvertisementProID; /* Advertisement Protocol ID field */
|
|
|
|
if (Event->u.GAS_CB_REQ_DATA.StatusCode == 0)
|
|
{
|
|
|
|
tmpLen = cpu2le16(GASQueryRspFrag->FragQueryRspLen);
|
|
|
|
NdisMoveMemory(Pos, &tmpLen, 2);
|
|
Pos += 2;
|
|
FrameLen += 6;
|
|
|
|
NdisMoveMemory(Pos, GASQueryRspFrag->FragQueryRsp,
|
|
GASQueryRspFrag->FragQueryRspLen);
|
|
|
|
FrameLen += GASQueryRspFrag->FragQueryRspLen;
|
|
}
|
|
else
|
|
{
|
|
tmpLen = 0;
|
|
|
|
NdisMoveMemory(Pos, &tmpLen, 2);
|
|
Pos += 2;
|
|
FrameLen += 6;
|
|
}
|
|
|
|
RTMP_SEM_LOCK(&pGASCtrl->GASPeerListLock);
|
|
DlListDel(&GASPeerEntry->List);
|
|
|
|
DlListForEachSafe(GASQueryRspFrag, GASQueryRspFragTmp,
|
|
&GASPeerEntry->GASQueryRspFragList, GAS_QUERY_RSP_FRAGMENT, List)
|
|
{
|
|
DlListDel(&GASQueryRspFrag->List);
|
|
os_free_mem(NULL, GASQueryRspFrag->FragQueryRsp);
|
|
os_free_mem(NULL, GASQueryRspFrag);
|
|
GASPeerEntry->FreeResource += 2;
|
|
}
|
|
|
|
DlListInit(&GASPeerEntry->GASQueryRspFragList);
|
|
RTMP_SEM_UNLOCK(&pGASCtrl->GASPeerListLock);
|
|
|
|
if (GASPeerEntry->PostReplyTimerRunning)
|
|
{
|
|
RTMPCancelTimer(&GASPeerEntry->PostReplyTimer, &Cancelled);
|
|
GASPeerEntry->PostReplyTimerRunning = FALSE;
|
|
}
|
|
|
|
if (GASPeerEntry->GASRspBufferingTimerRunning)
|
|
{
|
|
RTMPCancelTimer(&GASPeerEntry->GASRspBufferingTimer, &Cancelled);
|
|
GASPeerEntry->GASRspBufferingTimerRunning = FALSE;
|
|
}
|
|
RTMPReleaseTimer(&GASPeerEntry->PostReplyTimer, &Cancelled);
|
|
GASPeerEntry->FreeResource += 1;
|
|
|
|
RTMPReleaseTimer(&GASPeerEntry->GASRspBufferingTimer, & Cancelled);
|
|
|
|
os_free_mem(NULL, GASPeerEntry);
|
|
}
|
|
else if (Event->EventType == GAS_CB_REQ_MORE)
|
|
{
|
|
|
|
GASFrame->u.GAS_CB_RSP.DialogToken = Event->u.GAS_CB_REQ_MORE_DATA.DialogToken;
|
|
FrameLen += 1;
|
|
|
|
GASFrame->u.GAS_CB_RSP.StatusCode = cpu2le16(Event->u.GAS_CB_REQ_MORE_DATA.StatusCode);
|
|
FrameLen += 2;
|
|
|
|
GASFrame->u.GAS_CB_RSP.GASRspFragID = (0x80 | (GASQueryRspFrag->GASRspFragID & 0x7F));
|
|
DBGPRINT(RT_DEBUG_OFF, ("GASRspFragID = %d\n", GASFrame->u.GAS_CB_RSP.GASRspFragID));
|
|
FrameLen += 1;
|
|
|
|
GASFrame->u.GAS_CB_RSP.GASComebackDelay = 0;
|
|
FrameLen += 2;
|
|
|
|
Pos = GASFrame->u.GAS_CB_RSP.Variable;
|
|
*Pos++ = IE_ADVERTISEMENT_PROTO;
|
|
*Pos++ = 2; /* Length field */
|
|
*Pos++ = 0; /* Query response info field */
|
|
|
|
*Pos++ = Event->u.GAS_CB_REQ_MORE_DATA.AdvertisementProID; /* Advertisement Protocol ID field */
|
|
|
|
tmpLen = cpu2le16(GASQueryRspFrag->FragQueryRspLen);
|
|
|
|
NdisMoveMemory(Pos, &tmpLen, 2);
|
|
Pos += 2;
|
|
FrameLen += 6;
|
|
|
|
NdisMoveMemory(Pos, GASQueryRspFrag->FragQueryRsp,
|
|
GASQueryRspFrag->FragQueryRspLen);
|
|
|
|
FrameLen += GASQueryRspFrag->FragQueryRspLen;
|
|
|
|
//GASSetPeerCurrentState(pAd, Elem, WAIT_GAS_CB_REQ);
|
|
GASSetPeerCurrentState(pAd, Event, WAIT_GAS_CB_REQ);
|
|
}
|
|
|
|
MiniportMMRequest(pAd, 0, Buf, FrameLen);
|
|
|
|
os_free_mem(NULL, Buf);
|
|
}
|
|
|
|
|
|
VOID ReceiveGASCBReq(
|
|
IN PRTMP_ADAPTER pAd,
|
|
IN MLME_QUEUE_ELEM *Elem)
|
|
{
|
|
GAS_EVENT_DATA *Event;
|
|
GAS_FRAME *GASFrame = (GAS_FRAME *)Elem->Msg;
|
|
GAS_PEER_ENTRY *GASPeerEntry;
|
|
PGAS_CTRL pGASCtrl = NULL;
|
|
UCHAR APIndex, *Buf;
|
|
UINT32 Len = 0;
|
|
BOOLEAN IsGASCBReqMore = FALSE;
|
|
BOOLEAN IsFound = FALSE;
|
|
|
|
DBGPRINT(RT_DEBUG_TRACE, ("%s\n", __FUNCTION__));
|
|
|
|
for (APIndex = 0; APIndex < MAX_MBSSID_NUM(pAd); APIndex++)
|
|
{
|
|
if (MAC_ADDR_EQUAL(GASFrame->Hdr.Addr3, pAd->ApCfg.MBSSID[APIndex].wdev.bssid))
|
|
{
|
|
pGASCtrl = &pAd->ApCfg.MBSSID[APIndex].GASCtrl;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (!pGASCtrl)
|
|
{
|
|
DBGPRINT(RT_DEBUG_ERROR, ("%s Can not find Peer Control\n", __FUNCTION__));
|
|
return;
|
|
}
|
|
|
|
os_alloc_mem(NULL, (UCHAR **)&Buf, sizeof(*Event));
|
|
|
|
if (!Buf)
|
|
{
|
|
DBGPRINT(RT_DEBUG_ERROR, ("%s Not available memory\n", __FUNCTION__));
|
|
return;
|
|
}
|
|
|
|
NdisZeroMemory(Buf, sizeof(*Event));
|
|
|
|
Event = (GAS_EVENT_DATA *)Buf;
|
|
|
|
Event->ControlIndex = APIndex;
|
|
Len += 1;
|
|
|
|
NdisMoveMemory(Event->PeerMACAddr, GASFrame->Hdr.Addr2, MAC_ADDR_LEN);
|
|
Len += MAC_ADDR_LEN;
|
|
|
|
RTMP_SEM_LOCK(&pGASCtrl->GASPeerListLock);
|
|
DlListForEach(GASPeerEntry, &pGASCtrl->GASPeerList, GAS_PEER_ENTRY, List)
|
|
{
|
|
if (MAC_ADDR_EQUAL(GASPeerEntry->PeerMACAddr, Event->PeerMACAddr))
|
|
{
|
|
if ((GASPeerEntry->CurrentGASFragNum + 1) <
|
|
GASPeerEntry->GASRspFragNum)
|
|
IsGASCBReqMore = TRUE;
|
|
|
|
IsFound = TRUE;
|
|
break;
|
|
}
|
|
}
|
|
RTMP_SEM_UNLOCK(&pGASCtrl->GASPeerListLock);
|
|
|
|
if (!IsGASCBReqMore)
|
|
{
|
|
if(IsFound)
|
|
{
|
|
Event->EventType = GAS_CB_REQ;
|
|
Len += 2;
|
|
|
|
Event->u.GAS_CB_REQ_DATA.DialogToken = GASFrame->u.GAS_CB_REQ.DialogToken;
|
|
Len += 1;
|
|
|
|
Event->u.GAS_CB_REQ_DATA.AdvertisementProID = GASPeerEntry->AdvertisementProID;
|
|
Len += 1;
|
|
|
|
if (pGASCtrl->ExternalANQPServerTest == 2)
|
|
Event->u.GAS_CB_REQ_DATA.StatusCode = SERVER_UNREACHABLE;
|
|
else
|
|
Event->u.GAS_CB_REQ_DATA.StatusCode = 0;
|
|
|
|
Len += 2;
|
|
|
|
SendGASCBRsp(pAd, (GAS_EVENT_DATA *)Buf);
|
|
//MlmeEnqueue(pAd, GAS_STATE_MACHINE, GAS_CB_REQ, Len, Buf, 0);
|
|
|
|
//RTMP_MLME_HANDLER(pAd);
|
|
}
|
|
else
|
|
{
|
|
os_alloc_mem(NULL, (UCHAR **)&GASPeerEntry, sizeof(*GASPeerEntry));
|
|
|
|
if (!GASPeerEntry)
|
|
{
|
|
DBGPRINT(RT_DEBUG_ERROR, ("%s Not available memory\n", __FUNCTION__));
|
|
goto error;
|
|
}
|
|
|
|
NdisZeroMemory(GASPeerEntry, sizeof(*GASPeerEntry));
|
|
|
|
GASPeerEntry->CurrentState = WAIT_GAS_CB_REQ;
|
|
GASPeerEntry->ControlIndex = Event->ControlIndex;
|
|
NdisMoveMemory(GASPeerEntry->PeerMACAddr, GASFrame->Hdr.Addr2, MAC_ADDR_LEN);
|
|
GASPeerEntry->DialogToken = GASFrame->u.GAS_CB_REQ.DialogToken;
|
|
GASPeerEntry->AdvertisementProID = ACCESS_NETWORK_QUERY_PROTOCOL; // FIXME
|
|
GASPeerEntry->Priv = pAd;
|
|
DlListInit(&GASPeerEntry->GASQueryRspFragList);
|
|
|
|
RTMP_SEM_LOCK(&pGASCtrl->GASPeerListLock);
|
|
DlListAddTail(&pGASCtrl->GASPeerList, &GASPeerEntry->List);
|
|
RTMP_SEM_UNLOCK(&pGASCtrl->GASPeerListLock);
|
|
|
|
Event->EventType = GAS_CB_REQ;
|
|
Len += 2;
|
|
|
|
Event->u.GAS_CB_REQ_DATA.DialogToken = GASFrame->u.GAS_CB_REQ.DialogToken;
|
|
Len += 1;
|
|
|
|
Event->u.GAS_CB_REQ_DATA.AdvertisementProID = ACCESS_NETWORK_QUERY_PROTOCOL;
|
|
Len += 1;
|
|
|
|
Event->u.GAS_CB_REQ_DATA.StatusCode = UNSPECIFIED_FAILURE;
|
|
Len += 2;
|
|
|
|
SendGASCBRsp(pAd, (GAS_EVENT_DATA *)Buf);
|
|
//MlmeEnqueue(pAd, GAS_STATE_MACHINE, GAS_CB_REQ, Len, Buf, 0);
|
|
|
|
//RTMP_MLME_HANDLER(pAd);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
Event->EventType = GAS_CB_REQ_MORE;
|
|
Len += 2;
|
|
|
|
Event->u.GAS_CB_REQ_MORE_DATA.DialogToken = GASFrame->u.GAS_CB_REQ.DialogToken;
|
|
Len += 1;
|
|
|
|
Event->u.GAS_CB_REQ_MORE_DATA.AdvertisementProID = GASPeerEntry->AdvertisementProID;
|
|
Len += 1;
|
|
|
|
Event->u.GAS_CB_REQ_MORE_DATA.StatusCode = 0;
|
|
Len += 2;
|
|
|
|
SendGASCBRsp(pAd, (GAS_EVENT_DATA *)Buf);
|
|
//MlmeEnqueue(pAd, GAS_STATE_MACHINE, GAS_CB_REQ_MORE, Len, Buf,0);
|
|
|
|
//RTMP_MLME_HANDLER(pAd);
|
|
}
|
|
|
|
|
|
error:
|
|
os_free_mem(NULL, Buf);
|
|
}
|
|
|
|
|
|
static BOOLEAN IsAdvertisementProIDValid(
|
|
IN PRTMP_ADAPTER pAd,
|
|
IN enum DOT11U_ADVERTISMENT_PROTOCOL_ID AdvertisementProtoID)
|
|
{
|
|
INT32 i;
|
|
|
|
for (i = 0; i < sizeof(dot11GASAdvertisementID)
|
|
/ sizeof(enum DOT11U_ADVERTISMENT_PROTOCOL_ID); i++)
|
|
{
|
|
if (AdvertisementProtoID == dot11GASAdvertisementID[i])
|
|
return TRUE;
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
void PostReplyTimeout(
|
|
IN PVOID SystemSpecific1,
|
|
IN PVOID FunctionContext,
|
|
IN PVOID SystemSpecific2,
|
|
IN PVOID SystemSpecific3)
|
|
{
|
|
GAS_PEER_ENTRY *GASPeerEntry = (GAS_PEER_ENTRY *)FunctionContext;
|
|
PGAS_CTRL pGASCtrl;
|
|
PRTMP_ADAPTER pAd;
|
|
BOOLEAN Cancelled;
|
|
|
|
DBGPRINT(RT_DEBUG_TRACE, ("%s\n", __FUNCTION__));
|
|
|
|
if (!GASPeerEntry)
|
|
{
|
|
DBGPRINT(RT_DEBUG_OFF, ("%s: GASPeerEntry is NULL\n", __FUNCTION__));
|
|
return;
|
|
}
|
|
|
|
pAd = GASPeerEntry->Priv;
|
|
|
|
if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS))
|
|
{
|
|
DBGPRINT(RT_DEBUG_OFF, ("%s: fRTMP_ADAPTER_HALT_IN_PROGRESS\n", __FUNCTION__));
|
|
return;
|
|
}
|
|
|
|
pGASCtrl = &pAd->ApCfg.MBSSID[GASPeerEntry->ControlIndex].GASCtrl;
|
|
|
|
GASPeerEntry->PostReplyTimerRunning = FALSE;
|
|
|
|
RTMP_SEM_LOCK(&pGASCtrl->GASPeerListLock);
|
|
DlListDel(&GASPeerEntry->List);
|
|
|
|
DlListInit(&GASPeerEntry->GASQueryRspFragList);
|
|
RTMP_SEM_UNLOCK(&pGASCtrl->GASPeerListLock);
|
|
|
|
RTMPReleaseTimer(&GASPeerEntry->PostReplyTimer, &Cancelled);
|
|
GASPeerEntry->FreeResource += 1;
|
|
|
|
RTMPReleaseTimer(&GASPeerEntry->GASRspBufferingTimer, & Cancelled);
|
|
GASPeerEntry->FreeResource += 1;
|
|
|
|
GASPeerEntry->FreeResource += 1;
|
|
|
|
os_free_mem(NULL, GASPeerEntry);
|
|
|
|
}
|
|
BUILD_TIMER_FUNCTION(PostReplyTimeout);
|
|
|
|
|
|
VOID GASRspBufferingTimeout(
|
|
IN PVOID SystemSpecific1,
|
|
IN PVOID FunctionContext,
|
|
IN PVOID SystemSpecific2,
|
|
IN PVOID SystemSpecific3)
|
|
{
|
|
GAS_PEER_ENTRY *GASPeerEntry = (GAS_PEER_ENTRY *)FunctionContext;
|
|
PRTMP_ADAPTER pAd;
|
|
PGAS_CTRL pGASCtrl;
|
|
GAS_QUERY_RSP_FRAGMENT *GASQueryRspFrag = NULL, *GASQueryRspFragTmp;
|
|
BOOLEAN Cancelled;
|
|
|
|
DBGPRINT(RT_DEBUG_TRACE, ("%s\n", __FUNCTION__));
|
|
|
|
if (!GASPeerEntry)
|
|
{
|
|
DBGPRINT(RT_DEBUG_OFF, ("%s: GASPeerEntry is NULL\n", __FUNCTION__));
|
|
return;
|
|
}
|
|
|
|
pAd = GASPeerEntry->Priv;
|
|
|
|
|
|
if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS
|
|
| fRTMP_ADAPTER_NIC_NOT_EXIST))
|
|
{
|
|
DBGPRINT(RT_DEBUG_OFF, ("%s: fRTMP_ADAPTER_HALT_IN_PROGRESS\n", __FUNCTION__));
|
|
return;
|
|
}
|
|
|
|
pGASCtrl = &pAd->ApCfg.MBSSID[GASPeerEntry->ControlIndex].GASCtrl;
|
|
|
|
if (GASPeerEntry->GASRspBufferingTimerRunning)
|
|
{
|
|
GASPeerEntry->GASRspBufferingTimerRunning = FALSE;
|
|
|
|
RTMP_SEM_LOCK(&pGASCtrl->GASPeerListLock);
|
|
DlListDel(&GASPeerEntry->List);
|
|
|
|
DlListForEachSafe(GASQueryRspFrag, GASQueryRspFragTmp,
|
|
&GASPeerEntry->GASQueryRspFragList, GAS_QUERY_RSP_FRAGMENT, List)
|
|
{
|
|
DlListDel(&GASQueryRspFrag->List);
|
|
os_free_mem(NULL, GASQueryRspFrag->FragQueryRsp);
|
|
os_free_mem(NULL, GASQueryRspFrag);
|
|
GASPeerEntry->FreeResource += 2;
|
|
}
|
|
|
|
DlListInit(&GASPeerEntry->GASQueryRspFragList);
|
|
RTMP_SEM_UNLOCK(&pGASCtrl->GASPeerListLock);
|
|
|
|
RTMPReleaseTimer(&GASPeerEntry->PostReplyTimer, &Cancelled);
|
|
GASPeerEntry->FreeResource += 1;
|
|
|
|
RTMPReleaseTimer(&GASPeerEntry->GASRspBufferingTimer, & Cancelled);
|
|
GASPeerEntry->FreeResource += 1;
|
|
|
|
GASPeerEntry->FreeResource += 1;
|
|
|
|
os_free_mem(NULL, GASPeerEntry);
|
|
}
|
|
}
|
|
BUILD_TIMER_FUNCTION(GASRspBufferingTimeout);
|
|
|
|
|
|
static VOID SendGASIndication(
|
|
IN PRTMP_ADAPTER pAd,
|
|
//IN MLME_QUEUE_ELEM *Elem)
|
|
GAS_EVENT_DATA *Event)
|
|
{
|
|
PGAS_PEER_ENTRY GASPeerEntry;
|
|
//GAS_EVENT_DATA *Event = (GAS_EVENT_DATA *)Elem->Msg;
|
|
GAS_EVENT_DATA *GASRspEvent;
|
|
PGAS_CTRL pGASCtrl = &pAd->ApCfg.MBSSID[Event->ControlIndex].GASCtrl;
|
|
PNET_DEV NetDev = pAd->ApCfg.MBSSID[Event->ControlIndex].wdev.if_dev;
|
|
UCHAR *Buf;
|
|
UINT32 Len = 0;
|
|
|
|
DBGPRINT(RT_DEBUG_TRACE, ("%s\n", __FUNCTION__));
|
|
/*
|
|
* If advertisement protocol ID equals to the value
|
|
* contained in any dot11GASAdvertisementID MID objects
|
|
*/
|
|
if (IsAdvertisementProIDValid(pAd, Event->u.PEER_GAS_REQ_DATA.AdvertisementProID) &&
|
|
!pGASCtrl->ExternalANQPServerTest)
|
|
{
|
|
|
|
RTMP_SEM_LOCK(&pGASCtrl->GASPeerListLock);
|
|
/* Init PostReply timer */
|
|
DlListForEach(GASPeerEntry, &pGASCtrl->GASPeerList, GAS_PEER_ENTRY, List)
|
|
{
|
|
if (MAC_ADDR_EQUAL(GASPeerEntry->PeerMACAddr, Event->PeerMACAddr))
|
|
{
|
|
if (!GASPeerEntry->PostReplyTimerRunning)
|
|
{
|
|
RTMPSetTimer(&GASPeerEntry->PostReplyTimer, dot11GASResponseTimeout);
|
|
GASPeerEntry->PostReplyTimerRunning = TRUE;
|
|
}
|
|
|
|
break;
|
|
}
|
|
}
|
|
|
|
RTMP_SEM_UNLOCK(&pGASCtrl->GASPeerListLock);
|
|
|
|
//GASSetPeerCurrentState(pAd, Elem, WAIT_GAS_RSP);
|
|
GASSetPeerCurrentState(pAd, Event, WAIT_GAS_RSP);
|
|
|
|
if (Event->u.PEER_GAS_REQ_DATA.AdvertisementProID == ACCESS_NETWORK_QUERY_PROTOCOL)
|
|
{
|
|
/* Send anqp request indication to daemon */
|
|
SendAnqpReqEvent(NetDev,
|
|
Event->PeerMACAddr,
|
|
Event->u.PEER_GAS_REQ_DATA.QueryReq,
|
|
Event->u.PEER_GAS_REQ_DATA.QueryReqLen);
|
|
}
|
|
}
|
|
else if (IsAdvertisementProIDValid(pAd, Event->u.PEER_GAS_REQ_DATA.AdvertisementProID) &&
|
|
pGASCtrl->ExternalANQPServerTest == 1) /* server not reachable for 2F test */
|
|
{
|
|
os_alloc_mem(NULL, (UCHAR **)&Buf, sizeof(*GASRspEvent));
|
|
|
|
if (!Buf)
|
|
{
|
|
DBGPRINT(RT_DEBUG_ERROR, ("%s Not available memory\n", __FUNCTION__));
|
|
return;
|
|
}
|
|
|
|
NdisZeroMemory(Buf, sizeof(*GASRspEvent));
|
|
|
|
GASRspEvent = (GAS_EVENT_DATA *)Buf;
|
|
|
|
GASRspEvent->ControlIndex = Event->ControlIndex;
|
|
Len += 1;
|
|
NdisMoveMemory(GASRspEvent->PeerMACAddr, Event->PeerMACAddr, MAC_ADDR_LEN);
|
|
Len += MAC_ADDR_LEN;
|
|
|
|
GASRspEvent->EventType = GAS_RSP;
|
|
Len += 2;
|
|
|
|
RTMP_SEM_LOCK(&pGASCtrl->GASPeerListLock);
|
|
DlListForEach(GASPeerEntry, &pGASCtrl->GASPeerList, GAS_PEER_ENTRY, List)
|
|
{
|
|
if (MAC_ADDR_EQUAL(GASPeerEntry->PeerMACAddr, Event->PeerMACAddr))
|
|
{
|
|
GASRspEvent->u.GAS_RSP_DATA.DialogToken = GASPeerEntry->DialogToken;
|
|
Len += 1;
|
|
break;
|
|
}
|
|
}
|
|
RTMP_SEM_UNLOCK(&pGASCtrl->GASPeerListLock);
|
|
|
|
GASRspEvent->u.GAS_RSP_DATA.StatusCode = SERVER_UNREACHABLE;
|
|
Len += 2;
|
|
|
|
GASRspEvent->u.GAS_RSP_DATA.GASComebackDelay = 0;
|
|
Len += 2;
|
|
|
|
GASRspEvent->u.GAS_RSP_DATA.AdvertisementProID = GASPeerEntry->AdvertisementProID;
|
|
Len += 1;
|
|
|
|
GASRspEvent->u.GAS_RSP_DATA.QueryRspLen = 0;
|
|
Len += 2;
|
|
|
|
//GASSetPeerCurrentState(pAd, Elem, WAIT_GAS_RSP);
|
|
GASSetPeerCurrentState(pAd, Event, WAIT_GAS_RSP);
|
|
|
|
SendGASRsp(pAd, (GAS_EVENT_DATA *)Buf);
|
|
//MlmeEnqueue(pAd, GAS_STATE_MACHINE, GAS_RSP, Len, Buf, 0);
|
|
|
|
//RTMP_MLME_HANDLER(pAd);
|
|
|
|
os_free_mem(NULL, Buf);
|
|
}
|
|
else if (IsAdvertisementProIDValid(pAd, Event->u.PEER_GAS_REQ_DATA.AdvertisementProID) &&
|
|
pGASCtrl->ExternalANQPServerTest == 2) /* server not reachable for 4F test */
|
|
{
|
|
os_alloc_mem(NULL, (UCHAR **)&Buf, sizeof(*GASRspEvent));
|
|
|
|
if (!Buf)
|
|
{
|
|
DBGPRINT(RT_DEBUG_ERROR, ("%s Not available memory\n", __FUNCTION__));
|
|
return;
|
|
}
|
|
|
|
NdisZeroMemory(Buf, sizeof(*GASRspEvent));
|
|
|
|
GASRspEvent = (GAS_EVENT_DATA *)Buf;
|
|
|
|
GASRspEvent->ControlIndex = Event->ControlIndex;
|
|
Len += 1;
|
|
NdisMoveMemory(GASRspEvent->PeerMACAddr, Event->PeerMACAddr, MAC_ADDR_LEN);
|
|
Len += MAC_ADDR_LEN;
|
|
|
|
GASRspEvent->EventType = GAS_RSP_MORE;
|
|
Len += 2;
|
|
|
|
RTMP_SEM_LOCK(&pGASCtrl->GASPeerListLock);
|
|
DlListForEach(GASPeerEntry, &pGASCtrl->GASPeerList, GAS_PEER_ENTRY, List)
|
|
{
|
|
if (MAC_ADDR_EQUAL(GASPeerEntry->PeerMACAddr, Event->PeerMACAddr))
|
|
{
|
|
GASRspEvent->u.GAS_RSP_MORE_DATA.DialogToken = GASPeerEntry->DialogToken;
|
|
Len += 1;
|
|
break;
|
|
}
|
|
}
|
|
RTMP_SEM_UNLOCK(&pGASCtrl->GASPeerListLock);
|
|
|
|
GASRspEvent->u.GAS_RSP_MORE_DATA.StatusCode = 0;
|
|
Len += 2;
|
|
|
|
GASRspEvent->u.GAS_RSP_MORE_DATA.GASComebackDelay = 1;
|
|
Len += 2;
|
|
|
|
GASRspEvent->u.GAS_RSP_MORE_DATA.AdvertisementProID = GASPeerEntry->AdvertisementProID;
|
|
Len += 1;
|
|
|
|
//GASSetPeerCurrentState(pAd, Elem, WAIT_GAS_RSP);
|
|
GASSetPeerCurrentState(pAd, Event, WAIT_GAS_RSP);
|
|
|
|
SendGASRsp(pAd, (GAS_EVENT_DATA *)Buf);
|
|
//MlmeEnqueue(pAd, GAS_STATE_MACHINE, GAS_RSP_MORE, Len, Buf, 0);
|
|
|
|
//RTMP_MLME_HANDLER(pAd);
|
|
|
|
os_free_mem(NULL, Buf);
|
|
}
|
|
else if (!IsAdvertisementProIDValid(pAd, Event->u.PEER_GAS_REQ_DATA.AdvertisementProID))
|
|
{
|
|
/* Do not support this advertisement protocol, such as MIH */
|
|
os_alloc_mem(NULL, (UCHAR **)&Buf, sizeof(*GASRspEvent));
|
|
|
|
if (!Buf)
|
|
{
|
|
DBGPRINT(RT_DEBUG_ERROR, ("%s Not available memory\n", __FUNCTION__));
|
|
return;
|
|
}
|
|
|
|
NdisZeroMemory(Buf, sizeof(*GASRspEvent));
|
|
|
|
GASRspEvent = (GAS_EVENT_DATA *)Buf;
|
|
|
|
GASRspEvent->ControlIndex = Event->ControlIndex;
|
|
Len += 1;
|
|
NdisMoveMemory(GASRspEvent->PeerMACAddr, Event->PeerMACAddr, MAC_ADDR_LEN);
|
|
Len += MAC_ADDR_LEN;
|
|
|
|
GASRspEvent->EventType = GAS_RSP;
|
|
Len += 2;
|
|
|
|
RTMP_SEM_LOCK(&pGASCtrl->GASPeerListLock);
|
|
DlListForEach(GASPeerEntry, &pGASCtrl->GASPeerList, GAS_PEER_ENTRY, List)
|
|
{
|
|
if (MAC_ADDR_EQUAL(GASPeerEntry->PeerMACAddr, Event->PeerMACAddr))
|
|
{
|
|
GASRspEvent->u.GAS_RSP_DATA.DialogToken = GASPeerEntry->DialogToken;
|
|
Len += 1;
|
|
break;
|
|
}
|
|
}
|
|
RTMP_SEM_UNLOCK(&pGASCtrl->GASPeerListLock);
|
|
|
|
GASRspEvent->u.GAS_RSP_DATA.StatusCode = ADVERTISEMENT_PROTOCOL_NOT_SUPPORTED;
|
|
Len += 2;
|
|
|
|
GASRspEvent->u.GAS_RSP_DATA.GASComebackDelay = 0;
|
|
Len += 2;
|
|
|
|
GASRspEvent->u.GAS_RSP_DATA.AdvertisementProID = GASPeerEntry->AdvertisementProID;
|
|
Len += 1;
|
|
|
|
GASRspEvent->u.GAS_RSP_DATA.QueryRspLen = 0;
|
|
Len += 2;
|
|
|
|
//GASSetPeerCurrentState(pAd, Elem, WAIT_GAS_RSP);
|
|
GASSetPeerCurrentState(pAd, Event, WAIT_GAS_RSP);
|
|
|
|
MlmeEnqueue(pAd, GAS_STATE_MACHINE, GAS_RSP, Len, Buf, 0);
|
|
RTMP_MLME_HANDLER(pAd);
|
|
|
|
os_free_mem(NULL, Buf);
|
|
}
|
|
else
|
|
DBGPRINT(RT_DEBUG_ERROR, ("%s: should not in this case\n", __FUNCTION__));
|
|
}
|
|
#endif /* CONFIG_AP_SUPPORT */
|
|
|
|
static VOID GASCtrlInit(IN PRTMP_ADAPTER pAd)
|
|
{
|
|
PGAS_CTRL pGASCtrl;
|
|
#ifdef CONFIG_AP_SUPPORT
|
|
UCHAR APIndex;
|
|
#endif
|
|
|
|
#ifdef CONFIG_STA_SUPPORT
|
|
pGASCtrl = &pAd->StaCfg.GASCtrl;
|
|
NdisZeroMemory(pGASCtrl, sizeof(*pGASCtrl));
|
|
NdisAllocateSpinLock(pAd, &pGASCtrl->GASPeerListLock);
|
|
DlListInit(&pGASCtrl->GASPeerList);
|
|
#endif
|
|
|
|
#ifdef CONFIG_AP_SUPPORT
|
|
for (APIndex = 0; APIndex < MAX_MBSSID_NUM(pAd); APIndex++)
|
|
{
|
|
pGASCtrl = &pAd->ApCfg.MBSSID[APIndex].GASCtrl;
|
|
NdisZeroMemory(pGASCtrl, sizeof(*pGASCtrl));
|
|
NdisAllocateSpinLock(pAd, &pGASCtrl->GASPeerListLock);
|
|
DlListInit(&pGASCtrl->GASPeerList);
|
|
}
|
|
#endif
|
|
}
|
|
|
|
VOID GASCtrlExit(IN PRTMP_ADAPTER pAd)
|
|
{
|
|
PGAS_CTRL pGASCtrl;
|
|
GAS_PEER_ENTRY *GASPeerEntry, *GASPeerEntryTmp;
|
|
GAS_QUERY_RSP_FRAGMENT *GASQueryRspFrag, *GASQueryRspFragTmp;
|
|
BOOLEAN Cancelled;
|
|
#ifdef CONFIG_AP_SUPPORT
|
|
UCHAR APIndex;
|
|
#endif
|
|
|
|
#ifdef CONFIG_STA_SUPPORT
|
|
pGASCtrl = &pAd->StaCfg.GASCtrl;
|
|
|
|
RTMP_SEM_LOCK(&pGASCtrl->GASPeerListLock);
|
|
/* Remove all GAS peer entry */
|
|
DlListForEachSafe(GASPeerEntry, GASPeerEntryTmp,
|
|
&pGASCtrl->GASPeerList, GAS_PEER_ENTRY, List)
|
|
{
|
|
|
|
DlListDel(&GASPeerEntry->List);
|
|
|
|
DlListForEachSafe(GASQueryRspFrag, GASQueryRspFragTmp,
|
|
&GASPeerEntry->GASQueryRspFragList, GAS_QUERY_RSP_FRAGMENT, List)
|
|
{
|
|
DlListDel(&GASQueryRspFrag->List);
|
|
os_free_mem(NULL, GASQueryRspFrag->FragQueryRsp);
|
|
os_free_mem(NULL, GASQueryRspFrag);
|
|
}
|
|
|
|
DlListInit(&GASPeerEntry->GASQueryRspFragList);
|
|
|
|
if (GASPeerEntry->GASResponseTimerRunning)
|
|
{
|
|
RTMPCancelTimer(&GASPeerEntry->GASResponseTimer, &Cancelled);
|
|
GASPeerEntry->GASResponseTimerRunning = FALSE;
|
|
}
|
|
|
|
if (GASPeerEntry->GASCBDelayTimerRunning)
|
|
{
|
|
RTMPCancelTimer(&GASPeerEntry->GASCBDelayTimer, &Cancelled);
|
|
GASPeerEntry->GASCBDelayTimerRunning = FALSE;
|
|
}
|
|
|
|
RTMPReleaseTimer(&GASPeerEntry->GASResponseTimer, &Cancelled);
|
|
RTMPReleaseTimer(&GASPeerEntry->GASCBDelayTimer, &Cancelled);
|
|
os_free_mem(NULL, GASPeerEntry);
|
|
|
|
}
|
|
|
|
DlListInit(&pGASCtrl->GASPeerList);
|
|
RTMP_SEM_UNLOCK(&pGASCtrl->GASPeerListLock);
|
|
NdisFreeSpinLock(&pGASCtrl->GASPeerListLock);
|
|
#endif
|
|
|
|
#ifdef CONFIG_AP_SUPPORT
|
|
for (APIndex = 0; APIndex < MAX_MBSSID_NUM(pAd); APIndex++)
|
|
{
|
|
pGASCtrl = &pAd->ApCfg.MBSSID[APIndex].GASCtrl;
|
|
|
|
RTMP_SEM_LOCK(&pGASCtrl->GASPeerListLock);
|
|
/* Remove all GAS peer entry */
|
|
DlListForEachSafe(GASPeerEntry, GASPeerEntryTmp,
|
|
&pGASCtrl->GASPeerList, GAS_PEER_ENTRY, List)
|
|
{
|
|
|
|
DlListDel(&GASPeerEntry->List);
|
|
|
|
DlListForEachSafe(GASQueryRspFrag, GASQueryRspFragTmp,
|
|
&GASPeerEntry->GASQueryRspFragList, GAS_QUERY_RSP_FRAGMENT, List)
|
|
{
|
|
DlListDel(&GASQueryRspFrag->List);
|
|
os_free_mem(NULL, GASQueryRspFrag->FragQueryRsp);
|
|
os_free_mem(NULL, GASQueryRspFrag);
|
|
}
|
|
|
|
DlListInit(&GASPeerEntry->GASQueryRspFragList);
|
|
|
|
if (GASPeerEntry->PostReplyTimerRunning)
|
|
{
|
|
RTMPCancelTimer(&GASPeerEntry->PostReplyTimer, &Cancelled);
|
|
GASPeerEntry->PostReplyTimerRunning = FALSE;
|
|
}
|
|
|
|
if (GASPeerEntry->GASRspBufferingTimerRunning)
|
|
{
|
|
RTMPCancelTimer(&GASPeerEntry->GASRspBufferingTimer, &Cancelled);
|
|
GASPeerEntry->GASRspBufferingTimerRunning = FALSE;
|
|
}
|
|
|
|
RTMPReleaseTimer(&GASPeerEntry->PostReplyTimer, &Cancelled);
|
|
RTMPReleaseTimer(&GASPeerEntry->GASRspBufferingTimer, &Cancelled);
|
|
os_free_mem(NULL, GASPeerEntry);
|
|
}
|
|
|
|
DlListInit(&pGASCtrl->GASPeerList);
|
|
RTMP_SEM_UNLOCK(&pGASCtrl->GASPeerListLock);
|
|
NdisFreeSpinLock(&pGASCtrl->GASPeerListLock);
|
|
}
|
|
#endif /* CONFIG_AP_SUPPORT */
|
|
}
|
|
|
|
|
|
VOID GASStateMachineInit(
|
|
IN PRTMP_ADAPTER pAd,
|
|
IN STATE_MACHINE *S,
|
|
OUT STATE_MACHINE_FUNC Trans[])
|
|
{
|
|
DBGPRINT(RT_DEBUG_TRACE, ("%s\n", __FUNCTION__));
|
|
|
|
GASCtrlInit(pAd);
|
|
|
|
StateMachineInit(S, (STATE_MACHINE_FUNC*)Trans, MAX_GAS_STATE, MAX_GAS_MSG, (STATE_MACHINE_FUNC)Drop, GAS_UNKNOWN, GAS_MACHINE_BASE);
|
|
|
|
#ifdef CONFIG_STA_SUPPORT
|
|
StateMachineSetAction(S, WAIT_GAS_REQ, GAS_REQ, (STATE_MACHINE_FUNC)SendGASReq);
|
|
StateMachineSetAction(S, WAIT_PEER_GAS_RSP, PEER_GAS_RSP_MORE, (STATE_MACHINE_FUNC)SendGASCBReq);
|
|
StateMachineSetAction(S, WAIT_PEER_GAS_RSP, PEER_GAS_RSP, (STATE_MACHINE_FUNC)SendGASConfirm);
|
|
StateMachineSetAction(S, WAIT_GAS_CB_RSP, GAS_CB_RSP_MORE, (STATE_MACHINE_FUNC)SendGASCBReq);
|
|
StateMachineSetAction(S, WAIT_GAS_CB_RSP, GAS_CB_RSP, (STATE_MACHINE_FUNC)SendGASConfirm);
|
|
#endif /* CONFIG_STA_SUPPORT */
|
|
|
|
#ifdef CONFIG_AP_SUPPORT
|
|
StateMachineSetAction(S, WAIT_PEER_GAS_REQ, PEER_GAS_REQ, (STATE_MACHINE_FUNC)SendGASIndication);
|
|
StateMachineSetAction(S, WAIT_GAS_RSP, GAS_RSP, (STATE_MACHINE_FUNC)SendGASRsp);
|
|
StateMachineSetAction(S, WAIT_GAS_RSP, GAS_RSP_MORE, (STATE_MACHINE_FUNC)SendGASRsp);
|
|
StateMachineSetAction(S, WAIT_GAS_RSP, GAS_CB_REQ, (STATE_MACHINE_FUNC)SendGASCBRsp);
|
|
StateMachineSetAction(S, WAIT_GAS_CB_REQ, GAS_CB_REQ, (STATE_MACHINE_FUNC)SendGASCBRsp);
|
|
StateMachineSetAction(S, WAIT_GAS_CB_REQ, GAS_CB_REQ_MORE, (STATE_MACHINE_FUNC)SendGASCBRsp);
|
|
#endif /* CONFIG_AP_SUPPORT */
|
|
}
|