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

📄 tdiup.c

📁 WinCE5.0部分核心源码
💻 C
📖 第 1 页 / 共 3 页
字号:
                    // out in the world.
                    DEBUGMSG (ZONE_WARN, (TEXT("Got IRLAP_DISC in SharpMode\r\n")));
                    TdiStatus = TDI_DISCONNECT_WAIT;
                    break;
                }
                // Else fall into following
            case IRLMP_IRLAP_RESET:
            case IRLMP_IRLAP_CONN_FAILED:
            case IRLMP_UNSPECIFIED_DISC:
                TdiStatus = TDI_DISCONNECT_ABORT;
                break;

            default:
                TdiStatus = TDI_DISCONNECT_ABORT;
                break;
        }

        if (TdiStatus == TDI_DISCONNECT_WAIT)
        {
            DEBUGMSG(ZONE_WARN, (TEXT("IrlmpDisconnectInd - Starting linger timer.\r\n")));

            pConn->TdiStatus = TdiStatus;
            pConn->LastSendsRemaining = pConn->SendsRemaining;
            pConn->LingerTime = 10000;
            CTEStopTimer(&pConn->LingerTimer);
            CTEInitTimer(&pConn->LingerTimer);
            CTEStartTimer(&pConn->LingerTimer, 1000, LingerTimerFunc, pConn);
            FREE_CONN_LOCK(pConn);
        }
        else
        {
            BOOL fIndicateRecv = FALSE;

            pConn->ConnState = IRLMP_CONN_CLOSING;

            if (pConn->pUsrNDISBuff)
            {
                pConn->pUsrNDISBuff = NULL;
                pConn->UsrBuffLen   = 0;
                fIndicateRecv       = TRUE;
            }

            FREE_CONN_LOCK(pConn);

            IrdaAutoSuspend(FALSE);    // one less active connection

            if (fIndicateRecv == TRUE &&
                TdiStatus != TDI_DISCONNECT_ABORT)
            {
                pConn->pRecvComplete(
                    pConn->pRecvCompleteContext,
                    TDI_SUCCESS,
                    0);
            }

            if (pConn->pAddrObj->pEventDisconnect(
                 pConn->pAddrObj->pEventDisconnectContext,
                 pConn->pConnectionContext, 0, NULL, 0, NULL, 
                 TdiStatus) != STATUS_SUCCESS)
            {
                DEBUGMSG(ZONE_ERROR, (TEXT("TdiUp() EventDisconnect() failed\r\n")));
            }

            if (fIndicateRecv == TRUE &&
                TdiStatus == TDI_DISCONNECT_ABORT)
            {
                pConn->pRecvComplete(
                    pConn->pRecvCompleteContext,
                    TDI_CONNECTION_RESET,
                    0);
            }
        }
    }
    else 
    {
        FREE_CONN_LOCK(pConn);
        DEBUGMSG(ZONE_WARN, (TEXT("TdiUp() IRLMP_DISC_IND ignored\r\n")));
    }

    REFDELCONN(pConn);

    DEBUGMSG(ZONE_TDI, (TEXT("TdiUp: -IRLMP_DISCONNECT_IND\r\n")));
    return;
}

UINT ConnConfDiscReq(void  *pIrlmpContext) 
{
    // Disconnect because either the connection context has gone away, 
    // or is about to go away (IRLMP_CONN_CLOSING).

    IRDA_MSG IMsg;
    UINT     rc;
    
    DEBUGMSG(ZONE_WARN,
        (TEXT("ConnConfDiscReq - invalid connection handle or closing.\r\n")));

    IMsg.Prim                 = IRLMP_DISCONNECT_REQ;
    IMsg.IRDA_MSG_pDiscData   = NULL;
    IMsg.IRDA_MSG_DiscDataLen = 0;

    rc = IrlmpDown(pIrlmpContext, &IMsg);

    return (rc);
}

/*++

 Function:       IrlmpConnectConf

 Description:    Processes an IRLMP_CONNECT_CONF.

 Comments:

--*/

VOID
IrlmpConnectConf(void *pConnContext, IRDA_MSG *pIrDAMsg)
{
    int                 rc;
    IRDA_MSG            IrDAMsg;
    PIRLMP_CONNECTION   pConn;

    DEBUGMSG(ZONE_TDI, (TEXT("TdiUp: +IRLMP_CONNECT_CONF\r\n")));
    
    pConn = GETCONN(pConnContext);

    if (pConn == NULL)
    {
        // If we get a close while trying to connect, our connection
        // object.

        // 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("IrlmpConnectConf - connection gone.\r\n")));
        
        rc = ConnConfDiscReq(pIrDAMsg->IRDA_MSG_pContext);
        ASSERT(rc == 0);
        goto done;
    }

    VALIDCONN(pConn);
    GET_CONN_LOCK(pConn);

    if (pConn->ConnState == IRLMP_CONN_OPENING)
    {
        pConn->pIrLMPContext = pIrDAMsg->IRDA_MSG_pContext;
        pConn->SendMaxSDU    = pIrDAMsg->IRDA_MSG_MaxSDUSize;
        pConn->SendMaxPDU    = pIrDAMsg->IRDA_MSG_MaxPDUSize;

        if (pConn->UseExclusiveMode || pConn->UseIrLPTMode)
        {
            IrDAMsg.Prim                 = IRLMP_ACCESSMODE_REQ;
            IrDAMsg.IRDA_MSG_AccessMode  = IRLMP_EXCLUSIVE;

            IrDAMsg.IRDA_MSG_IrLPTMode = pConn->UseIrLPTMode;

            FREE_CONN_LOCK(pConn);
            if ((rc = IrlmpDown(pConn->pIrLMPContext, &IrDAMsg)) != 0)
            {
                pConn->fConnPending = FALSE;
                if (pConn->pConnectCompleteContext) {
                    if (rc == IRLMP_IN_MULTIPLEXED_MODE)
                    {
                        pConn->pConnectComplete(
                            pConn->pConnectCompleteContext, 
                            TDI_LINK_BUSY, 
                            0);
                    }
                    else if (rc == IRLMP_IN_EXCLUSIVE_MODE)
                    {
                        pConn->pConnectComplete(
                            pConn->pConnectCompleteContext, 
                            TDI_SUCCESS, 
                            0);
                    }
                    else
                    {
                        ASSERT(0);
                    }
                }
                // IRLMP_Connect left us an extra ref to take care of.
                REFDELCONN(pConn);
            }
            // If the ACCESSMODE_REQ returned success -- really pending. Keep
            // our extra reference.
        }
        else
        {
            pConn->ConnState = IRLMP_CONN_OPEN;
            pConn->fConnPending = FALSE;
            FREE_CONN_LOCK(pConn);
            if (pConn->pConnectCompleteContext) {
                IrdaAutoSuspend(TRUE);    // new active connection
                pConn->pConnectComplete(pConn->pConnectCompleteContext, 
                                        TDI_SUCCESS, 0);
            }
            // IRLMP_Connect left us an extra ref to take care of.
            REFDELCONN(pConn);
        }
    }
    else  
    {
        // ConnState = IRLMP_CONN_CLOSING, IRLMP_CONN_CREATED, IRLMP_CONN_OPEN
        ASSERT(pConn->ConnState == IRLMP_CONN_CLOSING);
        FREE_CONN_LOCK(pConn);

        DEBUGMSG(ZONE_WARN,
            (TEXT("IrlmpConnectConf - connection closing.\r\n")));
        
        rc = ConnConfDiscReq(pIrDAMsg->IRDA_MSG_pContext);
        ASSERT(rc == 0);

        if (pConn->pConnectCompleteContext) {
            pConn->pConnectComplete(
                pConn->pConnectCompleteContext,
                TDI_CONNECTION_ABORTED,
                0);
        }
        // IRLMP_Connect left us an extra ref to take care of.
        REFDELCONN(pConn);
    }

    REFDELCONN(pConn);

done:

    DEBUGMSG(ZONE_TDI, (TEXT("TdiUp: -IRLMP_CONNECT_CONF\r\n")));
    return;
}

/*++

 Function:       IrlmpGetValueByClassConf

 Description:    Process an IRLMP_GETVALUEBYCLASS_CONF.

 Arguments:

--*/

__inline VOID
IrlmpGetValueByClassConf(IRDA_MSG *pIrDAMsg)
{
    DEBUGMSG(ZONE_TDI, (TEXT("TdiUp: +IRLMP_GETVALUEBYCLASS_CONF\r\n")));
    
    EnterCriticalSection(&csIasQuery);
    IASQueryStatus = pIrDAMsg->IRDA_MSG_IASStatus;
    SetEvent(IASQueryConfEvent);
    LeaveCriticalSection(&csIasQuery);

    DEBUGMSG(ZONE_TDI, (TEXT("TdiUp: -IRLMP_GETVALUEBYCLASS_CONF\r\n")));
    return;
}

/*++

 Function:       IrlmpDataConf

 Description:    Process an IRLMP_DATA_CONF.

 Comments:

--*/

VOID
IrlmpDataConf(void *pConnContext, IRDA_MSG *pIrDAMsg)
{
    PIRLMP_CONNECTION  pConn;

    DEBUGMSG(ZONE_TDI, (TEXT("TdiUp: +IRLMP_DATA_CONF\r\n")));

    if (pIrDAMsg->IRDA_MSG_DataStatus == IRLMP_DATA_REQUEST_COMPLETED)
    {
        ((PIRLMP_SEND_COMPLETE) pIrDAMsg->IRDA_MSG_pTdiSendComp)(
            pIrDAMsg->IRDA_MSG_pTdiSendCompCnxt, 
            TDI_SUCCESS, 
            pIrDAMsg->IRDA_MSG_SendLen);

        pConn = GETCONN(pConnContext);

        if (pConn)
        {
            VALIDCONN(pConn);
            GET_CONN_LOCK(pConn);

            if (pConn->SendsRemaining) {
                pConn->SendsRemaining--;
            }

            FREE_CONN_LOCK(pConn);
            REFDELCONN(pConn);
        }
    }
    else
    {
        ((PIRLMP_SEND_COMPLETE) pIrDAMsg->IRDA_MSG_pTdiSendComp)(
            pIrDAMsg->IRDA_MSG_pTdiSendCompCnxt, 
            TDI_GRACEFUL_DISC, 
            0);
    }

    IrdaFree(pIrDAMsg);

    DEBUGMSG(ZONE_TDI, (TEXT("TdiUp: -IRLMP_DATA_CONF\r\n")));
    return;
}

/*++

 Function:       BufferRecv

 Description:    

 Arguments:

 Returns:

 Comments:

--*/

BOOL
BufferRecv(
    PIRLMP_CONNECTION pConn,
    PUCHAR            pData,
    DWORD             cbData,
    BYTE              bFinalSeg
    )
{
    PIRDATDI_RECV_BUFF pRecvBuf;

    pRecvBuf = IrdaAlloc(
        (offsetof(IRDATDI_RECV_BUFF, Data) + cbData),
        MT_TDI_RECV_BUFF);

    if (pRecvBuf == NULL)
    {
        ASSERT(0);
        return (FALSE);
    }

    pConn->RecvQBytes += cbData;
    pRecvBuf->DataLen  = cbData;
    pRecvBuf->pRead    = &pRecvBuf->Data[0];
    pRecvBuf->FinalSeg = bFinalSeg;
    memcpy(pRecvBuf->pRead, pData, cbData);
    InsertHeadList(&pConn->RecvBuffList, &pRecvBuf->Linkage);

    return (TRUE);
}

/*++

 Function:       IrlmpDataInd

 Description:    Process an IRLMP_DATA_IND.

 Comments:

--*/

VOID IrlmpDataInd(void *pConnContext, IRDA_MSG *pIrDAMsg)
{
    IRDA_MSG           IrDAMsg;
    TDI_STATUS         TdiStatus;
    int                rc;
    DWORD              OldPermissions;
    
    // IRLMP_DATA_IND
    EventRcvBuffer     EventRecvCompleteInfo;    
    int                BytesTaken;
    
    PIRLMP_CONNECTION  pConn;

    int             cbCopyToNdisBuf;
    int             cbCopyToRecvBuf;
    PNDIS_BUFFER    pNdisBuf;
    BOOL            fEventReceive;
    BYTE            FinalSeg;
    
    DEBUGMSG(ZONE_TDI, (TEXT("TdiUp: +IRLMP_DATA_IND\r\n")));
    
    pConn = GETCONN(pConnContext);

    if (pConn == NULL)
    {
        DEBUGMSG(ZONE_WARN,
            (TEXT("IrlmpDataInd - invalid connection handle.\r\n")));
        goto done;
    }

    VALIDCONN(pConn);
    GET_CONN_LOCK(pConn);

    if (pConn->ConnState != IRLMP_CONN_OPEN)
    {
        DEBUGMSG(ZONE_WARN, (TEXT("TdiUp() IRLMP_DATA_IND ignored\r\n")));
        // wmz open the window?

        goto done;
    }

    pConn->TinyTPRecvCreditsLeft--;

    //
    // Is this an IrCOMM connection?
    //

    if (pConn->Use9WireMode)
    {
        // 
        // When a packet arrives that has both contrl parameters and data, the 
        // control data will be acted up first, then the data will be 
        // processed. In this case, all processing for control parameters is to
        // ignore (discard). The first byte in an IrCOMM frame is the byte count
        // of the control parameters.
        // 

        BYTE cbControlPacket = *(BYTE *)pIrDAMsg->IRDA_MSG_pRead;

        // Increment past the byte count.
        pIrDAMsg->IRDA_MSG_pRead++;

        DEBUGMSG(ZONE_TDI,
            (TEXT("IrlmpDataInd: IrCOMM frame - ControlParm Len = %d/%d\r\n"),
             cbControlPacket,
             pIrDAMsg->IRDA_MSG_pWrite - pIrDAMsg->IRDA_MSG_pRead));
        
        //  Skip over any control parameters in the packet
        pIrDAMsg->IRDA_MSG_pRead += cbControlPacket;

        // Make sure that we didn't advance beyond the end of the buffer.
        // If so, the peer is violating the protocol.
        if (pIrDAMsg->IRDA_MSG_pRead > pIrDAMsg->IRDA_MSG_pWrite)
			DEBUGMSG(ZONE_ERROR,
				(TEXT("IrlmpDataInd: Invalid IrCOMM frame - ControlParm Len = %d too large\r\n"),
                 cbControlPacket));

        // If there is no data (i.e. there was only control parameters, then
        // skip the data ind path. 
        if (pIrDAMsg->IRDA_MSG_pRead >= pIrDAMsg->IRDA_MSG_pWrite)
        {
            goto IgnoreIRLMP_DATA_IND;
        }
    }
    
    //
    // Four main cases to deal with:
    // 1) Copy all data to pending NDIS buffer. Call CompleteReceive.
    // 2) No pending NDIS buffer. Other data has already been indicated
    //    but not accepted.
    //
    // The above two cases are easy, grab the locks copy the data, get out.
    //
    // 3) Copy some data (as much as possible) to pending NDIS buffer.
    //    Call CompleteReceive. Call IndicateReceive for remaining bytes and Q
    //    the remaining bytes.
    // 4) Need to indicate all the data. Call IndicateReceive and Q bytes.

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -