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

📄 tdiup.c

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