📄 irlmp.c
字号:
* @parm IRLMP_LSAP_CB * | pLsapCb | pointer LSAP control block
* @parm IRDA_MSG * | pMsg | Pointer to an IRDA Message
*/
UINT
IrlmpConnectResp(IRLMP_LSAP_CB *pLsapCb, IRDA_MSG *pMsg)
{
DEBUGMSG(DBG_IRLMP, (TEXT("IRLMP: Connect response\n")));
if (pLsapCb->pIrlmpCb->LinkState != LINK_READY)
{
DEBUGMSG(DBG_ERROR, (TEXT("IRLMP: Bad link state\n")));
ASSERT(0);
return IRLMP_LINK_BAD_STATE;
}
if (pLsapCb->State != LSAP_CONN_RESP_PEND)
{
DEBUGMSG(DBG_ERROR, (TEXT("IRLMP: Bad LSAP state\n")));
ASSERT(0);
return IRLMP_LSAP_BAD_STATE;
}
IrdaTimerStop(&pLsapCb->ResponseTimer);
if (pMsg->IRDA_MSG_ConnDataLen > IRLMP_MAX_USER_DATA_LEN)
{
DEBUGMSG(DBG_ERROR, (TEXT("IRLMP: User data len exceeded\n")));
return IRLMP_USER_DATA_LEN_EXCEEDED;
}
pLsapCb->RxMaxSDUSize = pMsg->IRDA_MSG_MaxSDUSize;
pLsapCb->UserDataLen = pMsg->IRDA_MSG_ConnDataLen;
pLsapCb->AvailableCredit = pMsg->IRDA_MSG_TtpCredits;
RtlCopyMemory(pLsapCb->UserData, pMsg->IRDA_MSG_pConnData,
pMsg->IRDA_MSG_ConnDataLen);
pLsapCb->pTdiContext = pMsg->IRDA_MSG_pContext;
SetupTtp(pLsapCb);
pLsapCb->State = LSAP_READY;
SendCntlPdu(pLsapCb, IRLMP_CONNECT_PDU, IRLMP_ABIT_CONFIRM,
IRLMP_RSVD_PARM, 0);
return SUCCESS;
}
/*****************************************************************************
*
* @func UINT | IrlmpDisconnectReq | Process IRLMP disconnect request
*
* @rdesc SUCCESS or an error code
*
* @parm IRLMP_LSAP_CB * | pLsapCb | pointer LSAP control block
* @parm IRDA_MSG * | pMsg | Pointer to an IRDA Message
*/
UINT
IrlmpDisconnectReq(IRLMP_LSAP_CB *pLsapCb, IRDA_MSG *pMsg)
{
//
// If the peer initiated a disconnect while TDI was requesting a disconnect,
// then the IRLMP_LSAP_CB gets destroyed.
//
if (pLsapCb == NULL) {
return IRLMP_INVALID_LSAP_CB;
}
DEBUGMSG((DBG_IRLMP | DBG_IRLMP_CONN),
(TEXT("IRLMP: IRLMP_DISCONNECT_REQ (l=%d,r=%d)\r\n"),
pLsapCb->LocalLsapSel, pLsapCb->RemoteLsapSel));
if (pLsapCb->State == LSAP_DISCONNECTED)
{
DEBUGMSG(DBG_ERROR, (TEXT("IRLMP: Disconnect in bad state\n")));
return IRLMP_LSAP_BAD_STATE;
}
if (pLsapCb->State == LSAP_LMCONN_CONF_PEND ||
pLsapCb->State == LSAP_CONN_RESP_PEND)
{
IrdaTimerStop(&pLsapCb->ResponseTimer);
}
if (pLsapCb->State == LSAP_CONN_RESP_PEND || pLsapCb->State >= LSAP_READY)
{
// Either the LSAP is connected or the peer is waiting for a
// response from our client
if (pMsg->IRDA_MSG_DiscDataLen > IRLMP_MAX_USER_DATA_LEN)
{
DEBUGMSG(DBG_ERROR, (TEXT("IRLMP: User data len exceeded\n")));
return IRLMP_USER_DATA_LEN_EXCEEDED;
}
pLsapCb->UserDataLen = pMsg->IRDA_MSG_DiscDataLen;
RtlCopyMemory(pLsapCb->UserData, pMsg->IRDA_MSG_pDiscData,
pMsg->IRDA_MSG_DiscDataLen);
// Notify peer of the disconnect request, reason: user request
// Send on different thread in case TranportAPI calls this on rx thread
SendCntlPdu(pLsapCb,IRLMP_DISCONNECT_PDU,IRLMP_ABIT_REQUEST,
IRLMP_USER_REQUEST, 0);
}
IrdaTimerRestart(&pLsapCb->pIrlmpCb->DiscDelayTimer);
CleanupLsap(pLsapCb);
return 0;
}
/*****************************************************************************
*
* @func UINT | IrlmpDataReqExclusive | Process IRLMP data request
*
* @rdesc SUCCESS or an error code
*
* @parm IRLMP_LSAP_CB * | pLsapCb | pointer LSAP control block
* @parm IRDA_MSG * | pMsg | Pointer to an IRDA Message
*
* WinCE can pass down multiple NDIS bufs. We need to segment -
* just call IrlmpDataReqMultiplexed.
*/
UINT
IrlmpDataReqExclusive(IRLMP_LSAP_CB *pLsapCb, IRDA_MSG *pMsg)
{
DEBUGMSG(DBG_IRLMP, (TEXT("IRLMP: Exclusive mode data request\n")));
if (pLsapCb->pIrlmpCb->LinkState != LINK_READY)
{
return IRLMP_LINK_BAD_STATE;
}
if (pLsapCb != pLsapCb->pIrlmpCb->pExclLsapCb)
{
return IRLMP_INVALID_LSAP_CB;
}
return (IrlmpDataReqMultiplexed(pLsapCb, pMsg));
}
/*****************************************************************************
*
* @func UINT | IrlmpDataReqMultiplexed | Process IRLMP data request
*
* @rdesc SUCCESS or an error code
*
* @parm IRLMP_LSAP_CB * | pLsapCb | pointer LSAP control block
* @parm IRDA_MSG * | pMsg | Pointer to an IRDA Message
*/
UINT
IrlmpDataReqMultiplexed(IRLMP_LSAP_CB *pLsapCb, IRDA_MSG *pMsg)
{
NDIS_BUFFER *pNBuf = (NDIS_BUFFER *) pMsg->DataContext;
NDIS_BUFFER *pNextNBuf;
UCHAR *pData;
int DataLen;
int SegLen;
IRDA_MSG *pSegMsg;
if (pLsapCb->State < LSAP_READY)
{
return IRLMP_LSAP_BAD_STATE;
}
// Place this message on the LSAP's TxMsgList. The message remains
// here until all segments for it are sent and confirmed
InsertTailList(&pLsapCb->TxMsgList, &pMsg->Linkage);
pMsg->IRDA_MSG_SegCount = 0;
// If it fails, this will be changed
pMsg->IRDA_MSG_DataStatus = IRLMP_DATA_REQUEST_COMPLETED;
// Segment the message into PDUs. The segment will either be:
// 1. Sent immediately to IRLAP if the link is not busy
// 2. If link is busy, placed on TxMsgList contained in IRLMP_LCB
// 3. If no credit, placed onto this LSAPS SegTxMsgList
while (pNBuf != NULL)
{
NdisQueryBuffer(pNBuf, &pData, &DataLen);
// Get the next one now so I know when to set SegFlag to final
NdisGetNextBuffer(pNBuf, &pNextNBuf);
while (DataLen != 0)
{
if ((pSegMsg = AllocIrdaBuf(IrdaMsgPool))
== NULL)
{
ASSERT(0);
return IRLMP_ALLOC_FAILED;
}
pSegMsg->IRDA_MSG_pOwner = pLsapCb; // MUX routing
pSegMsg->DataContext = pMsg; // Parent of segment
pSegMsg->IRDA_MSG_IrCOMM_9Wire = pMsg->IRDA_MSG_IrCOMM_9Wire;
// Increment segment count contained in original messages
pMsg->IRDA_MSG_SegCount++;
if (DataLen > pLsapCb->pIrlmpCb->MaxPDUSize)
{
SegLen = pLsapCb->pIrlmpCb->MaxPDUSize;
}
else
{
SegLen = DataLen;
}
DEBUGMSG(DBG_IRLMP, (TEXT("IRMLP: Sending SegLen %d\n"),
SegLen));
pSegMsg->IRDA_MSG_pRead = pData;
pSegMsg->IRDA_MSG_pWrite = pData + SegLen;
// Indicate this message is part of a segmented message
pSegMsg->IRDA_MSG_SegCount = pMsg->IRDA_MSG_SegCount;
pData += SegLen;
DataLen -= SegLen;
if (DataLen == 0 && pNextNBuf == NULL)
{
pSegMsg->IRDA_MSG_SegFlags = SEG_FINAL;
}
else
{
pSegMsg->IRDA_MSG_SegFlags = 0;
}
if (pLsapCb->State == LSAP_NO_TX_CREDIT)
{
DEBUGMSG(DBG_IRLMP,
(TEXT("IRLMP: Out of credit, placing on SegList\n")));
InsertTailList(&pLsapCb->SegTxMsgList, &pSegMsg->Linkage);
}
else
{
FormatAndSendDataReq(pLsapCb, pSegMsg, FALSE);
}
}
pNBuf = pNextNBuf;
}
return SUCCESS;
}
VOID
FormatAndSendDataReq(IRLMP_LSAP_CB *pLsapCb, IRDA_MSG *pMsg,
BOOLEAN LocallyGenerated)
{
IRLMP_HEADER *pLMHeader;
TTP_DATA_HEADER *pTTPHeader;
int AdditionalCredit;
UCHAR *pLastHdrByte;
VALIDLSAP(pLsapCb);
// Initialize the header pointers to the end of the header block
pMsg->IRDA_MSG_pHdrRead =
pMsg->IRDA_MSG_pHdrWrite = pMsg->IRDA_MSG_Header + IRDA_HEADER_LEN;
// Back up the read pointer for the LMP header
pMsg->IRDA_MSG_pHdrRead -= sizeof(IRLMP_HEADER);
// Back up header read pointer for TTP
if (pLsapCb->UseTtp)
{
pMsg->IRDA_MSG_pHdrRead -= (sizeof(TTP_DATA_HEADER));
}
if (pMsg->IRDA_MSG_IrCOMM_9Wire == TRUE)
{
pMsg->IRDA_MSG_pHdrRead -= 1;
}
ASSERT(pMsg->IRDA_MSG_pHdrRead >= pMsg->IRDA_MSG_Header);
// Build the LMP Header
pLMHeader = (IRLMP_HEADER *) pMsg->IRDA_MSG_pHdrRead;
pLMHeader->DstLsapSel = pLsapCb->RemoteLsapSel;
pLMHeader->SrcLsapSel = pLsapCb->LocalLsapSel;
pLMHeader->CntlBit = IRLMP_DATA_PDU;
pLMHeader->RsvrdBit = 0;
pLastHdrByte = (UCHAR *) (pLMHeader + 1);
// Build the TTP Header
if (pLsapCb->UseTtp)
{
pTTPHeader = (TTP_DATA_HEADER *) (pLMHeader + 1);
// Credit
if (pLsapCb->AvailableCredit > 127)
{
AdditionalCredit = 127;
pLsapCb->AvailableCredit -= 127;
}
else
{
AdditionalCredit = pLsapCb->AvailableCredit;
pLsapCb->AvailableCredit = 0;
}
pTTPHeader->AdditionalCredit = AdditionalCredit;
pLsapCb->RemoteTxCredit += AdditionalCredit;
if (pMsg->IRDA_MSG_pRead != pMsg->IRDA_MSG_pWrite)
{
// Only decrement my TxCredit if I'm sending data
// (may be sending dataless PDU to extend credit to peer)
pLsapCb->LocalTxCredit -= 1;
if (pLsapCb->LocalTxCredit == 0)
{
DEBUGMSG(DBG_IRLMP,
(TEXT("IRLMP: l%d,r%d No credit\n"), pLsapCb->LocalLsapSel,
pLsapCb->RemoteLsapSel));
pLsapCb->State = LSAP_NO_TX_CREDIT;
}
}
// SAR
if (pMsg->IRDA_MSG_SegFlags & SEG_FINAL)
{
pTTPHeader->MoreBit = TTP_MBIT_FINAL;
}
else
{
pTTPHeader->MoreBit = TTP_MBIT_NOT_FINAL;
}
pLastHdrByte = (UCHAR *) (pTTPHeader + 1);
}
if (pMsg->IRDA_MSG_IrCOMM_9Wire == TRUE)
{
*pLastHdrByte = 0;
}
pMsg->Prim = IRLAP_DATA_REQ;
if (LocallyGenerated)
{
pMsg->IRDA_MSG_SegFlags = SEG_LOCAL | SEG_FINAL;
pMsg->IRDA_MSG_pOwner = 0;
}
else
{
pMsg->IRDA_MSG_pOwner = pLsapCb;
REFADD(&pLsapCb->RefCnt, 'ATAD');
}
DEBUGMSG(DBG_IRLMP, (TEXT("IRLMP: Sending Data request pMsg:%X LsapCb:%X\n"),
pMsg, pMsg->IRDA_MSG_pOwner));
IrlapDown(pLsapCb->pIrlmpCb->pIrdaLinkCb->IrlapContext, pMsg);
DEBUGMSG(DBG_IRLMP_CRED,
(TEXT("IRLMP(l%d,r%d): Tx LocTxCredit %d,RemoteTxCredit %d\n"),
pLsapCb->LocalLsapSel, pLsapCb->RemoteLsapSel,
pLsapCb->LocalTxCredit, pLsapCb->RemoteTxCredit));
}
/*****************************************************************************
*
* @func UINT | IrlmpAccessModeReq | Processes the IRLMP_ACCESSMODE_REQ
*
* @rdesc SUCCESS or an error code
*
* @parm IRLMP_LSAP_CB * | pLsapCb | pointer LSAP control block
* @parm IRDA_MSG * | pMsg | Pointer to an IRDA Message
*/
UINT
IrlmpAccessModeReq(IRLMP_LSAP_CB *pRequestingLsapCb, IRDA_MSG *pMsg)
{
IRLMP_LSAP_CB *pLsapCb;
PIRLMP_LINK_CB pIrlmpCb = pRequestingLsapCb->pIrlmpCb;
if (pIrlmpCb->LinkState != LINK_READY)
{
DEBUGMSG(DBG_ERROR, (TEXT("IRLMP: Link bad state %x\n"),
pIrlmpCb->LinkState));
return IRLMP_LINK_BAD_STATE;
}
if (pRequestingLsapCb->State != LSAP_READY)
{
DEBUGMSG(DBG_ERROR, (TEXT("IRLMP: LSAP bad state %x\n"),
pRequestingLsapCb->State));
return IRLMP_LSAP_BAD_STATE;
}
switch (pMsg->IRDA_MSG_AccessMode)
{
case IRLMP_EXCLUSIVE:
if (pIrlmpCb->pExclLsapCb != NULL)
{
// Another LSAP has it already
return IRLMP_IN_EXCLUSIVE_MODE;
}
for (pLsapCb = (IRLMP_LSAP_CB *) pIrlmpCb->LsapCbList.Flink;
(LIST_ENTRY *) pLsapCb != &pIrlmpCb->LsapCbList;
pLsapCb = (IRLMP_LSAP_CB *) pLsapCb->Linkage.Flink)
{
VALIDLSAP(pLsapCb);
if (pLsapCb->State != LSAP_DISCONNECTED &&
pLsapCb != pRequestingLsapCb)
{
return IRLMP_IN_MULTIPLEXED_MODE;
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -