⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 irdatdi.c

📁 WinCE5.0部分核心源码
💻 C
📖 第 1 页 / 共 5 页
字号:
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 + -