📄 irdatdi.c
字号:
DWORD v_cRecvs;
#endif
TDI_STATUS
IRLMP_Receive(PTDI_REQUEST pTDIReq,
ushort * pFlags,
uint * pRecvLen,
PNDIS_BUFFER pNDISBuf)
{
TDI_STATUS TdiStatus = TDI_SUCCESS;
PIRLMP_CONNECTION pConn;
PIRDATDI_RECV_BUFF pRecvBuff;
int SpaceLeft;
IRDA_MSG IrDAMsg;
int rc;
#ifdef DEBUG
DWORD cRecvs = v_cRecvs++;
#endif
DEBUGMSG(ZONE_FUNCTION,
(TEXT("+IRLMP_Receive(0x%X,0x%X,0x%X,0x%X)\r\n"),
pTDIReq, pFlags, pRecvLen, pNDISBuf));
pConn = GETCONN(pTDIReq->Handle.ConnectionContext);
if (pConn == NULL)
{
TdiStatus = TDI_INVALID_CONNECTION;
goto done;
}
VALIDCONN(pConn);
GET_CONN_LOCK(pConn);
if (! IsListEmpty(&pConn->RecvBuffList))
{
PVOID VirtualAddress;
UINT BufferLength;
SpaceLeft = *pRecvLen;
DUMP_RECVLIST(ZONE_TDI, pConn);
NdisQueryBuffer(pNDISBuf, &VirtualAddress, &BufferLength);
BufferLength = 0;
while (SpaceLeft > 0 && ! IsListEmpty(&pConn->RecvBuffList))
{
pRecvBuff =
(PIRDATDI_RECV_BUFF) RemoveTailList(&pConn->RecvBuffList);
DEBUGMSG(ZONE_TDI,
(TEXT("IRLMP_Receive() forwarding %d bytes\r\n"),
min(pRecvBuff->DataLen, SpaceLeft)));
memcpy(((BYTE *) VirtualAddress) + BufferLength,
pRecvBuff->pRead,
min(pRecvBuff->DataLen, SpaceLeft));
BufferLength += min(pRecvBuff->DataLen, SpaceLeft);
// requeue the remaining bytes
if (pRecvBuff->DataLen > (int) SpaceLeft)
{
pRecvBuff->DataLen -= SpaceLeft;
pRecvBuff->pRead += SpaceLeft;
DEBUGMSG(ZONE_TDI,
(TEXT("IRLMP_Receive() reQing remaining %d bytes\r\n"),
pRecvBuff->DataLen));
InsertTailList(&pConn->RecvBuffList, &pRecvBuff->Linkage);
}
else
IrdaFree(pRecvBuff);
SpaceLeft = *pRecvLen - BufferLength;
}
NdisAdjustBufferLength(pNDISBuf, BufferLength);
*pRecvLen = BufferLength;
pConn->RecvQBytes -= BufferLength;
if ((DWORD) pConn->IndicatedNotAccepted >= BufferLength)
pConn->IndicatedNotAccepted -= BufferLength;
else
{
pConn->NotIndicated -= BufferLength - pConn->IndicatedNotAccepted;
pConn->IndicatedNotAccepted = 0;
}
if (pConn->IndicatedNotAccepted == 0 && pConn->NotIndicated > 0)
{
EventRcvBuffer EventRecvCompleteInfo;
DWORD BytesTaken = 0;
DEBUGMSG(ZONE_TDI,
(TEXT("%x IR : IRLMP_Receive (%d) calling TdiEventReceive\r\n"),
GetCurrentThreadId(), cRecvs)
);
pConn->pAddrObj->pEventReceive(
pConn->pAddrObj->pEventReceiveContext,
pConn->pConnectionContext,
0, pConn->NotIndicated, pConn->NotIndicated,
&BytesTaken, NULL,
&EventRecvCompleteInfo);
pConn->IndicatedNotAccepted = pConn->NotIndicated - BytesTaken;
pConn->NotIndicated = 0;
}
// Is is time to disconnect?
if (pConn->NotIndicated == 0 &&
pConn->IndicatedNotAccepted == 0 &&
pConn->TdiStatus == TDI_DISCONNECT_WAIT &&
pConn->ConnState == IRLMP_CONN_CLOSING)
{
if (pConn->pAddrObj->pEventDisconnect(
pConn->pAddrObj->pEventDisconnectContext,
pConn->pConnectionContext, 0, NULL, 0, NULL,
pConn->TdiStatus)
!= STATUS_SUCCESS)
{
DEBUGMSG(ZONE_ERROR,
(TEXT("IRLMP_Receive() EventDisconnect() failed\r\n")));
}
FREE_CONN_LOCK(pConn);
goto done;
}
if (pConn->RecvQBytes < IRDATDI_RECVQ_LEN &&
pConn->TinyTPRecvCreditsLeft == 0 &&
pConn->ConnState != IRLMP_CONN_CLOSING)
{
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);
}
else
{
FREE_CONN_LOCK(pConn);
}
goto done;
}
pConn->pRecvComplete = pTDIReq->RequestNotifyObject;
pConn->pRecvCompleteContext = pTDIReq->RequestContext;
pConn->pUsrNDISBuff = pNDISBuf;
pConn->UsrBuffLen = *pRecvLen;
pConn->UsrBuffPerm = pTDIReq->ProcPerm;
FREE_CONN_LOCK(pConn);
TdiStatus = TDI_PENDING;
done:
if (pConn)
{
REFDELCONN(pConn);
}
DEBUGMSG(ZONE_FUNCTION,
(TEXT("-IRLMP_Receive [%#x (%d)]\r\n"), TdiStatus, TdiStatus));
return (TdiStatus);
}
/*****************************************************************************
*
* @func TDI_STATUS | IRLMP_Send |
* Called to send data.
*
* @rdesc
* TDI_SUCCESS (tdistat.h) on success, or (tdistat.h)
* @errors
* @ecode TDI_PENDING |
* @ecode TDI_NO_RESOURCES |
* @ecode TDI_INVALID_STATE |
* @ecode TDI_INVALID_CONNECTION |
*
* @parm PTDI_REQUEST | pTDIReq |
* (tdi.h) pTDIReq->Handle.ConnectionContext contains the
* CONNECTION_CONTEXT (tdi.h, PVOID) of the IRLMP_CONNECTION.
* IRLMP_OpenConnection() assigns this value to be a pointer to
* the IRLMP_CONNECTION.
* <nl>pTDIReq->RequestNotifyObject is a pointer (void (*)(PVOID
* Context, TDI_STATUS TdiStatus, DWORD BytesSent)) to a Winsock
* routine to call if this function returns TDI_PENDING.
* <nl>pTDIReq->RequestNotifyContext is a Winsock context to return in
* the callback.
* @parm ushort | Flags |
* (tdi.h) One of
* <nl>TDI_SEND_EXPEDITED
* <nl>TDI_SEND_PARTIAL
* <nl>TDI_SEND_NO_RESPONSE_EXPECTED
* <nl>TDI_SEND_NON_BLOCKING
* @parm unit | SendLen |
* Data size of the NDIS buffer (chain?).
* @parm PNDIS_BUFFER | pNDISBuf |
* (ndis.h) Pointer to input NDIS_BUFFER.
*/
TDI_STATUS
IRLMP_Send(PTDI_REQUEST pTDIReq,
ushort Flags,
uint SendLen,
PNDIS_BUFFER pNDISBuf)
{
TDI_STATUS TdiStatus = TDI_PENDING;
IRDA_MSG *pIrDAMsg = NULL;
PIRLMP_CONNECTION pConn;
int rc;
DEBUGMSG(ZONE_FUNCTION,
(TEXT("+IRLMP_Send(0x%X,0x%X,0x%X,0x%X)\r\n"),
pTDIReq, (unsigned) Flags, SendLen, pNDISBuf));
pConn = GETCONN(pTDIReq->Handle.ConnectionContext);
if (pConn == NULL)
{
TdiStatus = TDI_INVALID_CONNECTION;
goto done;
}
VALIDCONN(pConn);
pIrDAMsg = IrdaAlloc(sizeof(IRDA_MSG), MT_TDI_MESSAGE);
if (pIrDAMsg == NULL)
{
DEBUGMSG(ZONE_ERROR,
(TEXT("IRLMP_Send() CTEAllocMem() failed\r\n")));
FREE_CONN_LOCK(pConn);
TdiStatus = TDI_NO_RESOURCES;
goto done;
}
GET_CONN_LOCK(pConn);
if (pConn->UseExclusiveMode || pConn->UseIrLPTMode)
{
if (SendLen > (uint) pConn->SendMaxSDU)
{
FREE_CONN_LOCK(pConn);
TdiStatus = TDI_BUFFER_OVERFLOW;
goto done;
}
}
if (pConn->Use9WireMode) {
if (SendLen > (uint) pConn->SendMaxPDU)
{
FREE_CONN_LOCK(pConn);
TdiStatus = TDI_BUFFER_OVERFLOW;
goto done;
}
}
pIrDAMsg->Prim = IRLMP_DATA_REQ;
pIrDAMsg->DataContext = pNDISBuf;
pIrDAMsg->IRDA_MSG_pTdiSendComp = pTDIReq->RequestNotifyObject;
pIrDAMsg->IRDA_MSG_pTdiSendCompCnxt = pTDIReq->RequestContext;
pIrDAMsg->IRDA_MSG_SendLen = SendLen;
// send leading zero byte for IrCOMM?
pIrDAMsg->IRDA_MSG_IrCOMM_9Wire = pConn->Use9WireMode;
switch(pConn->ConnState)
{
case IRLMP_CONN_OPEN:
pConn->SendsRemaining++;
FREE_CONN_LOCK(pConn);
rc = IrlmpDown(pConn->pIrLMPContext, pIrDAMsg);
ASSERT(rc == 0);
break;
default:
FREE_CONN_LOCK(pConn);
TdiStatus = TDI_INVALID_STATE;
break;
}
done:
if (pConn)
{
REFDELCONN(pConn);
// DataReq should always pend.
ASSERT(TdiStatus != TDI_SUCCESS);
if (TdiStatus != TDI_PENDING )
{
if (pIrDAMsg) IrdaFree(pIrDAMsg);
}
}
DEBUGMSG(ZONE_FUNCTION,
(TEXT("-IRLMP_Send [%#x (%d)]\r\n"), TdiStatus, TdiStatus));
return(TdiStatus);
}
/*****************************************************************************
*
* @func TDI_STATUS | IRLMP_SendDatagram | THIS IS NEVER CALLED. wmz
*/
TDI_STATUS
IRLMP_SendDatagram(PTDI_REQUEST pTDIReq,
PTDI_CONNECTION_INFORMATION pConnInfo,
uint SendLen,
ULONG * pBytesSent,
PNDIS_BUFFER pNDISBuf)
{
DEBUGMSG(ZONE_FUNCTION,
(TEXT("IRLMP_SendDatagram(0x%X,0x%X,0x%X,0x%X,0x%X)\r\n"),
pTDIReq, pConnInfo, SendLen, pBytesSent, pNDISBuf));
ASSERT(0);
return(TDI_SUCCESS);
}
/*****************************************************************************
*
* @func TDI_STATUS | IRLMP_SendDatagram | THIS IS NEVER CALLED. wmz
*/
TDI_STATUS
IRLMP_ReceiveDatagram(PTDI_REQUEST pTDIReq,
PTDI_CONNECTION_INFORMATION pConnInfo,
PTDI_CONNECTION_INFORMATION pRetInfo,
uint RecvLen,
uint * pBytesRecvd,
PNDIS_BUFFER pNDISBuf)
{
DEBUGMSG(ZONE_FUNCTION,
(TEXT("IRLMP_ReceiveDatagram(0x%X,0x%X,0x%X,0x%X,0x%X,0x%X)\r\n"),
pTDIReq, pConnInfo, pRetInfo, RecvLen, pBytesRecvd, pNDISBuf));
ASSERT(0);
return(TDI_SUCCESS);
}
/*****************************************************************************
*
* @func TDI_STATUS | IRLMP_SetEvent |
* Informs the stack of each Winsock entry point (event handler).
* Called after bind() for each event handler except
* TDI_EVENT_CONNECT. Called for TDI_EVENT_CONNECT after listen().
* Each Address Object can have unique event handlers. The mind
* boggles.
*
* @rdesc
* TDI_SUCCESS (tdistat.h) on success, or (tdistat.h)
* @errors
* @ecode TDI_BAD_EVENT_TYPE | Event not suppoerted.
*
* @parm PVOID | pHandle |
* Pointer to the IRLMP_ADDR_OBJ struct that will be associated with
* this event handler. IrLMP will store the address of the event
* handler here.
* @parm int | Type | TDI_EVENT_ (tdi.h) handler being set.
* <nl> TDI_EVENT_CONNECT
* <nl> TDI_EVENT_DISCONNECT
* <nl> TDI_EVENT_ERROR
* <nl> TDI_EVENT_RECEIVE
* <nl> TDI_EVENT_RECEIVE_DATAGRAM
* <nl> TDI_EVENT_RECEIVE_EXPEDITED
* <nl> TDI_EVENT_SEND_POSSIBLE
* @parm PVOID | pHandler |
* Address of the Winsock event handler (tdice.h).
* @parm PVOID | pContext |
* Pointer to a context to return to Winsock when calling the event
* handler. IrLMP will store this pointer in the IRLMP_ADDR_OBJ.
*/
TDI_STATUS
IRLMP_SetEvent(PVOID pHandle,
int Type,
PVOID pHandler,
PVOID pContext)
{
TDI_STATUS TdiStatus = TDI_SUCCESS;
PIRLMP_ADDR_OBJ pAddrObj;
DEBUGMSG(ZONE_FUNCTION,
(TEXT("+IRLMP_SetEvent(0x%X,0x%X,0x%X,0x%X)\r\n"),
pHandle, Type, pHandler, pContext));
pAddrObj = GETADDR(pHandle);
if (pAddrObj == NULL)
{
TdiStatus = TDI_A
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -