📄 irlmp.c
字号:
{
RemoveEntryList(&pDevice->Linkage);
IRDA_FREE_MEM(pDevice);
}
}
// remove IrdaLinkCb from List
RemoveEntryList(&pIrlmpCb->pIrdaLinkCb->Linkage);
ASSERT(IsListEmpty(&pIrlmpCb->LsapCbList));
NdisReleaseSpinLock(&SpinLock);
IasDelAttribute(pIrlmpCb->hAttribDeviceName);
IasDelAttribute(pIrlmpCb->hAttribIrlmpSupport);
CTEFreeMem(pIrlmpCb);
/*
// Cleanup registered LSAP
while (!IsListEmpty(&RegisteredLsaps))
{
pPtr = RemoveHeadList(&RegisteredLsaps);
IRDA_FREE_MEM(pPtr);
}
// And the device list
while (!IsListEmpty(&DeviceList))
{
pPtr = RemoveHeadList(&DeviceList);
IRDA_FREE_MEM(pPtr);
}
// And IAS entries
for (pObject = (IAS_OBJECT *) IasObjects.Flink;
(LIST_ENTRY *) pObject != &IasObjects;
pObject = pNextObject)
{
DEBUGMSG(DBG_IRLMP, (TEXT("IRLMP: Deleting object %s\n"),
pObject->pClassName));
// Get the next cuz this ones being deleted
pNextObject = (IAS_OBJECT *) pObject->Linkage.Flink;
IasDeleteObject(pObject->pClassName);
}
*/
}
/*****************************************************************************
*
* @func UINT | IrlmpCloseLink | Shuts down IRDA stack
*
* @rdesc SUCCESS or error
*
*/
VOID
IrlmpCloseLink(PIRDA_LINK_CB pIrdaLinkCb)
{
DEBUGMSG(1, (TEXT("IRLMP: CloseLink request\n")));
IrdaEventSchedule(&EvIrlmpCloseLink, pIrdaLinkCb);
return;
}
/*****************************************************************************
*
* @func UINT | IrlmpRegisterLSAPProtocol | Bag to let IRLMP know if
* a connect ind is using TTP
* @rdesc SUCCESS or error
*
* @parm int | LSAP | LSAP being registered
* @parm BOOLEAN | UseTtp |
*/
VOID
RegisterLsapProtocol(int Lsap, BOOLEAN UseTtp)
{
PIRLMP_REGISTERED_LSAP pRegLsap;
NdisAcquireSpinLock(&SpinLock);
for (pRegLsap = (PIRLMP_REGISTERED_LSAP) RegisteredLsaps.Flink;
(LIST_ENTRY *) pRegLsap != &RegisteredLsaps;
pRegLsap = (PIRLMP_REGISTERED_LSAP) pRegLsap->Linkage.Flink)
{
if (pRegLsap->Lsap == Lsap)
{
pRegLsap->UseTtp = UseTtp;
goto done;
}
}
if (IRDA_ALLOC_MEM(pRegLsap, sizeof(IRLMP_REGISTERED_LSAP),
MT_IRLMP_REGLSAP) == NULL)
{
ASSERT(0);
goto done;
}
pRegLsap->Lsap = Lsap;
pRegLsap->UseTtp = UseTtp;
InsertTailList(&RegisteredLsaps, &pRegLsap->Linkage);
done:
NdisReleaseSpinLock(&SpinLock);
DEBUGMSG(DBG_IRLMP, (TEXT("IRLMP: LSAP %x registered, %s\n"), Lsap,
UseTtp ? TEXT("use TTP") : TEXT("no TTP")));
}
VOID
DeregisterLsapProtocol(int Lsap)
{
PIRLMP_REGISTERED_LSAP pRegLsap;
NdisAcquireSpinLock(&SpinLock);
for (pRegLsap = (PIRLMP_REGISTERED_LSAP) RegisteredLsaps.Flink;
(LIST_ENTRY *) pRegLsap != &RegisteredLsaps;
pRegLsap = (PIRLMP_REGISTERED_LSAP) pRegLsap->Linkage.Flink)
{
if (pRegLsap->Lsap == Lsap)
{
DEBUGMSG(DBG_IRLMP, (TEXT("IRLMP: LSAP %x deregistered\n"),
Lsap));
RemoveEntryList(&pRegLsap->Linkage);
IRDA_FREE_MEM(pRegLsap);
break;
}
}
NdisReleaseSpinLock(&SpinLock);
}
/*****************************************************************************
*
* @func UINT | DeleteLsap | Delete an Lsap control context and
*
* @rdesc pointer to Lsap context or 0 on error
*
* @parm void | pLsapCb | pointer to an Lsap control block
*/
void
DeleteLsap(IRLMP_LSAP_CB *pLsapCb)
{
VALIDLSAP(pLsapCb);
ASSERT(pLsapCb->State == LSAP_DISCONNECTED);
ASSERT(IsListEmpty(&pLsapCb->SegTxMsgList));
ASSERT(IsListEmpty(&pLsapCb->TxMsgList));
LOCK_LINK(pLsapCb->pIrlmpCb->pIrdaLinkCb);
#ifdef DBG
pLsapCb->Sig = 0xdaeddead;
#endif
RemoveEntryList(&pLsapCb->Linkage);
UNLOCK_LINK(pLsapCb->pIrlmpCb->pIrdaLinkCb);
REFDEL(&pLsapCb->pIrlmpCb->pIrdaLinkCb->RefCnt, 'PASL');
IrdaTimerStop(&pLsapCb->ResponseTimer);
DEBUGMSG(DBG_IRLMP, (TEXT("IRLMP: Deleting LsapCb:%X (%d,%d)\n"),
pLsapCb, pLsapCb->LocalLsapSel, pLsapCb->RemoteLsapSel));
memset(pLsapCb, 0, sizeof(IRLMP_LSAP_CB));
IRDA_FREE_MEM(pLsapCb);
}
/*****************************************************************************
*
* @func UINT | CreateLsap | Create an LSAP control context and
*/
UINT
CreateLsap(PIRLMP_LINK_CB pIrlmpCb, IRLMP_LSAP_CB **ppLsapCb)
{
IRLMP_LSAP_CB * pLsapCb;
*ppLsapCb = NULL;
IRDA_ALLOC_MEM(pLsapCb, sizeof(IRLMP_LSAP_CB), MT_IRLMP_LSAP_CB);
if (pLsapCb == NULL)
{
return IRLMP_ALLOC_FAILED;
}
*ppLsapCb = pLsapCb;
memset(pLsapCb, 0, sizeof(IRLMP_LSAP_CB));
pLsapCb->pIrlmpCb = pIrlmpCb;
pLsapCb->State = LSAP_CREATED;
pLsapCb->UserDataLen = 0;
InitializeListHead(&pLsapCb->TxMsgList);
InitializeListHead(&pLsapCb->SegTxMsgList);
ReferenceInit(&pLsapCb->RefCnt, *ppLsapCb, DeleteLsap);
REFADD(&pLsapCb->RefCnt, ' TS1');
#if DBG
pLsapCb->ResponseTimer.pName = "ResponseTimer";
pLsapCb->Sig = LSAPSIG;
#endif
IrdaTimerInitialize(&pLsapCb->ResponseTimer,
LsapResponseTimerExp,
LSAP_RESPONSE_TIMEOUT,
pLsapCb,
pIrlmpCb->pIrdaLinkCb);
// Insert into list in the link control block
NdisAcquireSpinLock(&SpinLock);
InsertTailList(&pIrlmpCb->LsapCbList, &pLsapCb->Linkage);
NdisReleaseSpinLock(&SpinLock);
REFADD(&pIrlmpCb->pIrdaLinkCb->RefCnt, 'PASL');
DEBUGMSG(DBG_IRLMP, (TEXT("IRLMP: New LsapCb:%X\n"),
pLsapCb));
return SUCCESS;
}
void
CleanupLsap(IRLMP_LSAP_CB *pLsapCb)
{
IRDA_MSG *pMsg, *pNextMsg, *pSegParentMsg;
VALIDLSAP(pLsapCb);
DEBUGMSG(DBG_IRLMP, (TEXT("IRLMP: CleanupLsap:%X\n"), pLsapCb));
if (pLsapCb->State == LSAP_DISCONNECTED)
{
ASSERT(0);
return;
}
if (pLsapCb == pLsapCb->pIrlmpCb->pExclLsapCb)
{
pLsapCb->pIrlmpCb->pExclLsapCb = NULL;
}
pLsapCb->State = LSAP_DISCONNECTED;
// Clean up the segmented tx msg list
while (!IsListEmpty(&pLsapCb->SegTxMsgList))
{
pMsg = (IRDA_MSG *) RemoveHeadList(&pLsapCb->SegTxMsgList);
// Decrement the segment counter contained in the parent data request
pSegParentMsg = pMsg->DataContext;
pSegParentMsg->IRDA_MSG_SegCount -= 1;
// IRLMP owns these
FreeIrdaBuf(IrdaMsgPool, pMsg);
}
// return any outstanding data requests (unless there are outstanding segments)
for (pMsg = (IRDA_MSG *) pLsapCb->TxMsgList.Flink;
(LIST_ENTRY *) pMsg != &(pLsapCb->TxMsgList);
pMsg = pNextMsg)
{
pNextMsg = (IRDA_MSG *) pMsg->Linkage.Flink;
if (pMsg->IRDA_MSG_SegCount == 0)
{
RemoveEntryList(&pMsg->Linkage);
pMsg->Prim = IRLMP_DATA_CONF;
pMsg->IRDA_MSG_DataStatus = IRLMP_DATA_REQUEST_FAILED;
TdiUp(pLsapCb->pTdiContext, pMsg);
}
}
REFDEL(&pLsapCb->RefCnt, ' TS1');
}
/*****************************************************************************
*
* @func void | TearDownConnections | Tears down and cleans up connections
*
* @parm IRLMP_DISC_REASONE| DiscReason | The reason connections are being
* torn down. Passed to IRLMP clients
* in IRLMP_DISCONNECT_IND
*/
void
TearDownConnections(PIRLMP_LINK_CB pIrlmpCb, IRLMP_DISC_REASON DiscReason)
{
IRLMP_LSAP_CB *pLsapCb, *pLsapCbNext;
IRDA_MSG IMsg;
pIrlmpCb->pExclLsapCb = NULL;
DEBUGMSG(DBG_IRLMP, (TEXT("IRLMP: Tearing down connections\r\n")));
// Clean up each LSAP
for (pLsapCb = (IRLMP_LSAP_CB *) pIrlmpCb->LsapCbList.Flink;
(LIST_ENTRY *) pLsapCb != &pIrlmpCb->LsapCbList;
pLsapCb = pLsapCbNext)
{
pLsapCbNext = (IRLMP_LSAP_CB *) pLsapCb->Linkage.Flink;
DEBUGMSG(DBG_IRLMP, (TEXT("IRLMP: Teardown LsapCb:%X\n"), pLsapCb));
VALIDLSAP(pLsapCb);
if (pLsapCb->LocalLsapSel == IAS_LSAP_SEL)
{
IasServerDisconnectReq(pLsapCb);
continue;
}
if (pLsapCb->LocalLsapSel == IAS_LOCAL_LSAP_SEL &&
pLsapCb->RemoteLsapSel == IAS_LSAP_SEL)
{
IasClientDisconnectReq(pLsapCb, DiscReason);
}
else
{
IrdaTimerStop(&pLsapCb->ResponseTimer);
if (pLsapCb->State != LSAP_DISCONNECTED)
{
DEBUGMSG(DBG_IRLMP,
(TEXT("IRLMP: Sending IRLMP Disconnect Ind\r\n")));
// Now tell client this LSAP is history
IMsg.Prim = IRLMP_DISCONNECT_IND;
IMsg.IRDA_MSG_DiscReason = DiscReason;
IMsg.IRDA_MSG_pDiscData = NULL;
IMsg.IRDA_MSG_DiscDataLen = 0;
TdiUp(pLsapCb->pTdiContext, &IMsg);
CleanupLsap(pLsapCb);
}
}
}
}
/*****************************************************************************
*
* @func UINT | IrlmpDown | Message from Upper layer to LMP
*
* @rdesc SUCCESS or an error code
*
* @parm void * | void_pLsapCb | void pointer to an LSAP_CB. Can be NULL
* @parm IRDA_MSG * | pMsg | Pointer to an IRDA Message
*/
UINT
IrlmpDown(void *void_pLsapCb, IRDA_MSG *pMsg)
{
UINT rc = SUCCESS;
IRLMP_LSAP_CB *pLsapCb =
(IRLMP_LSAP_CB *) void_pLsapCb;
if (pLsapCb != NULL && pLsapCb->State == LSAP_DISCONNECTED)
{
return IRLMP_INVALID_LSAP_CB;
}
if (pLsapCb)
{
#ifdef DEBUG
if (pLsapCb->Sig != LSAPSIG) {
DEBUGMSG(DBG_ERROR, (L"IRLMP:IrlmpDown IRLMP_LSAP_SIG==0x%x vs. 0x%x\n", pLsapCb->Sig, LSAPSIG));
ASSERT(0);
return IRLMP_INVALID_LSAP_CB;
}
#endif
VALIDLSAP(pLsapCb);
REFADD(&pLsapCb->RefCnt, 'NWOD');
if (pLsapCb->pIrlmpCb == NULL) {
REFDEL(&pLsapCb->RefCnt, 'NWOD');
DEBUGMSG(DBG_ERROR, (L"IRLMP:IrlmpDown pIrlmpCb==NULL\n"));
return IRLMP_INVALID_LSAP_CB;
}
LOCK_LINK(pLsapCb->pIrlmpCb->pIrdaLinkCb);
} else {
//
// These requests cannot have a NULL LsapCb
//
switch (pMsg->Prim) {
case IRLMP_CONNECT_RESP:
case IRLMP_DATA_REQ:
case IRLMP_ACCESSMODE_REQ:
case IRLMP_MORECREDIT_REQ:
return IRLMP_INVALID_LSAP_CB;
}
}
switch (pMsg->Prim)
{
case IRLMP_DISCOVERY_REQ:
IrlmpDiscoveryReq(pMsg);
break;
case IRLMP_CONNECT_REQ:
rc = IrlmpConnectReq(pMsg);
break;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -