Files
Linux_Drivers/osdrv/extdrv/wireless/mediatek/mt7603/common/gas.c
forum_service 213c880673 add driver of tp、wiegand-gpio and wireless
Change-Id: Ie3c11d9d85cf1a05042f5690ac711856fe8b1ad7
2023-12-22 09:56:05 +08:00

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 */
}