📄 tdiup.c
字号:
//
// Cases 3 and 4 need to release locks to indicate receive, but before the
// data is really queued. Therefore, when the locks are re-acquired
// we need to check to see if a buffer is pending.
//
// Default - will buffer recv.
fEventReceive = TRUE;
cbCopyToNdisBuf = 0;
cbCopyToRecvBuf = pIrDAMsg->IRDA_MSG_pWrite - pIrDAMsg->IRDA_MSG_pRead;
pNdisBuf = pConn->pUsrNDISBuff;
FinalSeg = (pIrDAMsg->IRDA_MSG_SegFlags & SEG_FINAL) ? 1 : 0;
DEBUGMSG(ZONE_TDI,
(TEXT("TdiUp() got %d bytes, pConn->UsrBuffLen %d\r\n"),
cbCopyToRecvBuf,
pConn->UsrBuffLen));
do
{
// First off, if we have a pending NDIS buffer, fill it.
if (pNdisBuf)
{
PVOID VirtualAddress;
UINT BufferLength;
cbCopyToNdisBuf = min(pConn->UsrBuffLen,
pIrDAMsg->IRDA_MSG_pWrite - pIrDAMsg->IRDA_MSG_pRead);
OldPermissions = SetProcPermissions(pConn->UsrBuffPerm);
NdisQueryBuffer(pNdisBuf, &VirtualAddress, &BufferLength);
memcpy(
VirtualAddress,
pIrDAMsg->IRDA_MSG_pRead,
cbCopyToNdisBuf);
SetProcPermissions(OldPermissions);
pIrDAMsg->IRDA_MSG_pRead += cbCopyToNdisBuf;
cbCopyToRecvBuf -= cbCopyToNdisBuf;
if (pConn->IndicatedNotAccepted > 0)
{
pConn->IndicatedNotAccepted -= cbCopyToNdisBuf;
ASSERT(pConn->IndicatedNotAccepted >= 0);
// Should not have bytes indicated but not accepted on first
// iteration through loop.
ASSERT(fEventReceive == FALSE);
}
pConn->pUsrNDISBuff = NULL;
pConn->UsrBuffLen = 0;
}
else if (pConn->IndicatedNotAccepted > 0)
{
// Buffer data and get out -- no indications required.
BufferRecv(
pConn,
pIrDAMsg->IRDA_MSG_pRead,
cbCopyToRecvBuf,
FinalSeg);
pConn->NotIndicated += cbCopyToRecvBuf;
break;
}
FREE_CONN_LOCK(pConn);
// If we copied data to a pending NDIS buffer, we must complete
// the receive.
if (pNdisBuf)
{
pConn->pRecvComplete(
pConn->pRecvCompleteContext,
TDI_SUCCESS,
cbCopyToNdisBuf);
pNdisBuf = NULL;
}
// If we need to queue any data, we indicate it first.
// Only indicate the first time since we are using the same data.
if (cbCopyToRecvBuf && fEventReceive)
{
TdiStatus = pConn->pAddrObj->pEventReceive(
pConn->pAddrObj->pEventReceiveContext,
pConn->pConnectionContext,
0, cbCopyToRecvBuf, cbCopyToRecvBuf,
&BytesTaken, NULL,
&EventRecvCompleteInfo);
}
GET_CONN_LOCK(pConn);
if (cbCopyToRecvBuf && fEventReceive)
{
pConn->IndicatedNotAccepted = cbCopyToRecvBuf;
fEventReceive = FALSE;
}
if (pConn->pUsrNDISBuff)
{
// Was a new NDIS buffer pended while we dropped the locks?
// If so, we will loop and fill the buffer.
pNdisBuf = pConn->pUsrNDISBuff;
}
else if (cbCopyToRecvBuf > 0)
{
// Else, queue any bytes.
if (TDI_NOT_ACCEPTED == TdiStatus) {
if (BufferRecv(
pConn,
pIrDAMsg->IRDA_MSG_pRead,
cbCopyToRecvBuf,
FinalSeg) == FALSE)
{
// sh - drop data (failed to allocate buffer)?
break;
}
}
cbCopyToRecvBuf = 0;
}
}
while (cbCopyToRecvBuf && pNdisBuf);
#if 0
if (pConn->pUsrNDISBuff)
{
DEBUGMSG(ZONE_TDI, (TEXT("%x IR : +IrlmpDataInd - copy %d bytes to buf\r\n"),
GetCurrentThreadId(),
min(pConn->UsrBuffLen, BytesRecvd)));
DEBUGMSG(ZONE_TDI,
(TEXT("TdiUp() copying %d bytes\r\n"),
min(pConn->UsrBuffLen, BytesRecvd)));
OldPermissions = SetProcPermissions(pConn->UsrBuffPerm);
memcpy(pConn->pUsrNDISBuff->VirtualAddress,
pIrDAMsg->IRDA_MSG_pRead,
min(pConn->UsrBuffLen, BytesRecvd));
pConn->pUsrNDISBuff->BufferLength =
min(pConn->UsrBuffLen, BytesRecvd);
SetProcPermissions(OldPermissions);
FREE_CONN_LOCK(pConn);
pConn->pRecvComplete(pConn->pRecvCompleteContext, TDI_SUCCESS,
min(pConn->UsrBuffLen, BytesRecvd));
GET_CONN_LOCK(pConn);
// enqueue the remaining bytes
if (BytesRecvd > (int) pConn->UsrBuffLen)
{
BytesRecvd -= pConn->UsrBuffLen;
pIrDAMsg->IRDA_MSG_pRead += pConn->UsrBuffLen;
DEBUGMSG(ZONE_TDI,
(TEXT("TdiUp() enQing remaining %d bytes\r\n"),
BytesRecvd));
pRecvBuff = IrdaAlloc((offsetof(IRDATDI_RECV_BUFF, Data) + BytesRecvd),
MT_TDI_RECV_BUFF);
if (pRecvBuff == NULL)
{
DEBUGMSG(ZONE_ERROR, (TEXT("TdiUp CTEAllocMem() failed\r\n")));
ASSERT(0);
}
pRecvBuff->DataLen = BytesRecvd;
pRecvBuff->pRead = &pRecvBuff->Data[0];
pRecvBuff->FinalSeg = (pIrDAMsg->IRDA_MSG_SegFlags & SEG_FINAL)
? TRUE: FALSE;
memcpy(pRecvBuff->pRead, pIrDAMsg->IRDA_MSG_pRead, BytesRecvd);
pConn->RecvQBytes += BytesRecvd;
InsertHeadList(&pConn->RecvBuffList, &pRecvBuff->Linkage);
FREE_CONN_LOCK(pConn);
DEBUGMSG(ZONE_TDI,
(TEXT("%x IR : IrlmpDataInd calling TdiEventReceive %d bytes\r\n"),
GetCurrentThreadId(), BytesRecvd)
);
TdiStatus = pConn->pAddrObj->pEventReceive(
pConn->pAddrObj->pEventReceiveContext,
pConn->pConnectionContext,
0, BytesRecvd, BytesRecvd,
&BytesTaken, NULL,
&EventRecvCompleteInfo);
ASSERT(TdiStatus == TDI_NOT_ACCEPTED);
ASSERT(BytesTaken == 0);
GET_CONN_LOCK(pConn);
pConn->IndicatedNotAccepted = BytesRecvd;
}
pConn->pUsrNDISBuff = NULL;
pConn->UsrBuffLen = 0;
}
else
{
if (pConn->IndicatedNotAccepted > 0)
{
DEBUGMSG(ZONE_TDI,
(TEXT("%x IR : IrlmpDataInd Qing %d bytes.\r\n"),
GetCurrentThreadId(), BytesRecvd)
);
pConn->NotIndicated += BytesRecvd;
}
else
{
FREE_CONN_LOCK(pConn);
DEBUGMSG(ZONE_TDI,
(TEXT("%x IR : IrlmpDataInd2 calling TdiEventReceive %d bytes\r\n"),
GetCurrentThreadId(), BytesRecvd)
);
TdiStatus = pConn->pAddrObj->pEventReceive(
pConn->pAddrObj->pEventReceiveContext,
pConn->pConnectionContext,
0, BytesRecvd, BytesRecvd,
&BytesTaken, NULL,
&EventRecvCompleteInfo);
GET_CONN_LOCK(pConn);
pConn->IndicatedNotAccepted = BytesRecvd;
ASSERT(TdiStatus == TDI_NOT_ACCEPTED);
}
DEBUGMSG(ZONE_TDI, (TEXT("TdiUp() enQing %d bytes\r\n"), BytesRecvd));
pRecvBuff = IrdaAlloc((offsetof(IRDATDI_RECV_BUFF, Data) + BytesRecvd),
MT_TDI_RECV_BUFF);
if (pRecvBuff == NULL)
{
DEBUGMSG(ZONE_ERROR, (TEXT("TdiUp CTEAllocMem() failed\r\n")));
ASSERT(0);
}
pRecvBuff->DataLen = BytesRecvd;
pRecvBuff->pRead = &pRecvBuff->Data[0];
pRecvBuff->FinalSeg = (pIrDAMsg->IRDA_MSG_SegFlags & SEG_FINAL)
? TRUE : FALSE;
memcpy(pRecvBuff->pRead, pIrDAMsg->IRDA_MSG_pRead, BytesRecvd);
pConn->RecvQBytes += BytesRecvd;
InsertHeadList(&pConn->RecvBuffList, &pRecvBuff->Linkage);
}
#endif // 0
IgnoreIRLMP_DATA_IND:
if (pConn->RecvQBytes < IRDATDI_RECVQ_LEN &&
pConn->TinyTPRecvCreditsLeft == 0)
{
pConn->TinyTPRecvCreditsLeft = TINY_TP_RECV_CREDITS;
IrDAMsg.Prim = IRLMP_MORECREDIT_REQ;
IrDAMsg.IRDA_MSG_TtpCredits = TINY_TP_RECV_CREDITS;
FREE_CONN_LOCK(pConn);
rc = IrlmpDown(pConn->pIrLMPContext, &IrDAMsg);
ASSERT(rc == 0);
GET_CONN_LOCK(pConn);
}
done:
if (pConn)
{
FREE_CONN_LOCK(pConn);
REFDELCONN(pConn);
}
DEBUGMSG(ZONE_TDI, (TEXT("TdiUp: -IRLMP_DATA_IND\r\n")));
return;
}
/*++
Function: IrlmpAccessmodeConf
Description: Processes an IRLMP_ACCESSMODE_CONF.
Comments:
--*/
__inline VOID
IrlmpAccessmodeConf(void *pConnContext, IRDA_MSG *pIrDAMsg)
{
IRDA_MSG IrDAMsg;
int rc;
PIRLMP_CONNECTION pConn;
DEBUGMSG(ZONE_TDI, (TEXT("TdiUp: +IRLMP_ACCESSMODE_CONF\r\n")));
pConn = GETCONN(pConnContext);
if (pConn == NULL)
{
// We don't expect to get here, because we will keep an extra
// ref on the connection if a connection is pending.
// Normally we don't keep an extra ref on pending requests, but
// we need to be able to do a connect complete to AFD, other
// wise, AFD blocks....
DEBUGMSG(ZONE_WARN,
(TEXT("IrlmpAccessModeConf - invalid connection handle\r\n")));
ASSERT(FALSE);
return;
}
VALIDCONN(pConn);
GET_CONN_LOCK(pConn);
if (pConn->ConnState == IRLMP_CONN_OPENING)
{
if (pIrDAMsg->IRDA_MSG_ModeStatus == IRLMP_ACCESSMODE_SUCCESS)
{
// assume IRDA_MSG_AccessMode == IRLMP_EXCLUSIVE
pConn->ConnState = IRLMP_CONN_OPEN;
FREE_CONN_LOCK(pConn);
if (pConn->pConnectCompleteContext) {
IrdaAutoSuspend(TRUE); // new active connection
pConn->pConnectComplete(
pConn->pConnectCompleteContext,
TDI_SUCCESS,
0);
}
}
else
{
IrDAMsg.Prim = IRLMP_DISCONNECT_REQ;
IrDAMsg.IRDA_MSG_pDiscData = NULL;
IrDAMsg.IRDA_MSG_DiscDataLen = 0;
FREE_CONN_LOCK(pConn);
rc = IrlmpDown(pConn->pIrLMPContext, &IrDAMsg);
ASSERT(rc == 0);
if (pConn->pConnectCompleteContext) {
pConn->pConnectComplete(
pConn->pConnectCompleteContext,
TDI_LINK_BUSY,
0);
}
}
// IRLMP_Connect left us an extra ref to take care of.
REFDELCONN(pConn);
}
else if (pConn->ConnState == IRLMP_CONN_CLOSING &&
pConn->fConnPending == TRUE)
{
pConn->fConnPending = FALSE;
FREE_CONN_LOCK(pConn);
if (pConn->pConnectCompleteContext) {
pConn->pConnectComplete(
pConn->pConnectCompleteContext,
TDI_CONNECTION_ABORTED,
0);
}
// IRLMP_Connect left us an extra ref to take care of.
REFDELCONN(pConn);
}
else
{
FREE_CONN_LOCK(pConn);
}
REFDELCONN(pConn);
DEBUGMSG(ZONE_TDI, (TEXT("TdiUp: -IRLMP_ACCESSMODE_CONF\r\n")));
return;
}
/*++
Function: TdiUp
Description: Indications and confirmations for LMP.
Comments:
--*/
UINT
TdiUp(void *pConnContext, IRDA_MSG *pIrDAMsg)
{
switch(pIrDAMsg->Prim)
{
case IRLMP_DISCOVERY_CONF:
IrlmpDiscoveryConf(pIrDAMsg);
break;
case IRLMP_DISCOVERY_IND:
IrlmpDiscoveryInd();
break;
case IRLMP_CONNECT_IND:
IrlmpConnectInd(pIrDAMsg);
break;
case IRLMP_DISCONNECT_IND:
IrlmpDisconnectInd(pConnContext, pIrDAMsg);
break;
case IRLMP_CONNECT_CONF:
IrlmpConnectConf(pConnContext, pIrDAMsg);
break;
case IRLMP_GETVALUEBYCLASS_CONF:
IrlmpGetValueByClassConf(pIrDAMsg);
break;
case IRLMP_DATA_CONF:
IrlmpDataConf(pConnContext, pIrDAMsg);
break;
case IRLMP_ACCESSMODE_CONF:
IrlmpAccessmodeConf(pConnContext, pIrDAMsg);
break;
case IRLMP_DATA_IND:
IrlmpDataInd(pConnContext, pIrDAMsg);
break;
case IRLMP_ACCESSMODE_IND:
break;
case IRLAP_STATUS_IND:
// sh: we now do status indications for different link status'.
// It does not mean that communication has been interrupted.
// DEBUGMSG(1, (TEXT("WARNING: Ir communication has been interrupted\n")));
break;
case IRLAP_DISCONNECT_IND:
DEBUGMSG(1, (TEXT("WARNING: Ir communication has been terminated\n")));
break;
default:
DEBUGMSG(ZONE_ERROR, (TEXT("TdiUp: Bad primitive %d\r\n"),
pIrDAMsg->Prim) );
ASSERT(0);
break;
}
return(0);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -