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

📄 irlmp.c

📁 WinCE5.0部分核心源码
💻 C
📖 第 1 页 / 共 5 页
字号:
*   @parm   IRLMP_LSAP_CB * | pLsapCb | pointer LSAP control block
*   @parm   IRDA_MSG * | pMsg | Pointer to an IRDA Message
*/
UINT
IrlmpConnectResp(IRLMP_LSAP_CB *pLsapCb, IRDA_MSG *pMsg)
{
    DEBUGMSG(DBG_IRLMP, (TEXT("IRLMP: Connect response\n")));
    
    if (pLsapCb->pIrlmpCb->LinkState != LINK_READY)
    {
        DEBUGMSG(DBG_ERROR, (TEXT("IRLMP: Bad link state\n")));
        ASSERT(0);
        return IRLMP_LINK_BAD_STATE;
    }

    if (pLsapCb->State != LSAP_CONN_RESP_PEND)
    {
        DEBUGMSG(DBG_ERROR, (TEXT("IRLMP: Bad LSAP state\n")));
        ASSERT(0);
        return IRLMP_LSAP_BAD_STATE;
    }

    IrdaTimerStop(&pLsapCb->ResponseTimer);

    if (pMsg->IRDA_MSG_ConnDataLen > IRLMP_MAX_USER_DATA_LEN)
    {
        DEBUGMSG(DBG_ERROR, (TEXT("IRLMP: User data len exceeded\n")));
        return IRLMP_USER_DATA_LEN_EXCEEDED;
    }

    pLsapCb->RxMaxSDUSize       = pMsg->IRDA_MSG_MaxSDUSize;
    pLsapCb->UserDataLen        = pMsg->IRDA_MSG_ConnDataLen;
    pLsapCb->AvailableCredit    = pMsg->IRDA_MSG_TtpCredits;
    RtlCopyMemory(pLsapCb->UserData, pMsg->IRDA_MSG_pConnData,
           pMsg->IRDA_MSG_ConnDataLen);

    pLsapCb->pTdiContext = pMsg->IRDA_MSG_pContext;

    SetupTtp(pLsapCb);

    pLsapCb->State = LSAP_READY;

    SendCntlPdu(pLsapCb, IRLMP_CONNECT_PDU, IRLMP_ABIT_CONFIRM,
                IRLMP_RSVD_PARM, 0);

    return SUCCESS;
}
/*****************************************************************************
*
*   @func   UINT | IrlmpDisconnectReq | Process IRLMP disconnect request
*
*   @rdesc  SUCCESS or an error code
*
*   @parm   IRLMP_LSAP_CB * | pLsapCb | pointer LSAP control block
*   @parm   IRDA_MSG * | pMsg | Pointer to an IRDA Message
*/
UINT
IrlmpDisconnectReq(IRLMP_LSAP_CB *pLsapCb, IRDA_MSG *pMsg)
{
    //
    // If the peer initiated a disconnect while TDI was requesting a disconnect,
    // then the IRLMP_LSAP_CB gets destroyed.
    //
    if (pLsapCb == NULL) {
        return IRLMP_INVALID_LSAP_CB;
    }

    DEBUGMSG((DBG_IRLMP | DBG_IRLMP_CONN), 
            (TEXT("IRLMP: IRLMP_DISCONNECT_REQ (l=%d,r=%d)\r\n"),
             pLsapCb->LocalLsapSel, pLsapCb->RemoteLsapSel));
    
    if (pLsapCb->State == LSAP_DISCONNECTED)
    {
        DEBUGMSG(DBG_ERROR, (TEXT("IRLMP: Disconnect in bad state\n")));
        return IRLMP_LSAP_BAD_STATE;
    }

    if (pLsapCb->State == LSAP_LMCONN_CONF_PEND ||
        pLsapCb->State == LSAP_CONN_RESP_PEND)
    {
        IrdaTimerStop(&pLsapCb->ResponseTimer);
    }

    if (pLsapCb->State == LSAP_CONN_RESP_PEND || pLsapCb->State >= LSAP_READY)
    {
        // Either the LSAP is connected or the peer is waiting for a
        // response from our client

        if (pMsg->IRDA_MSG_DiscDataLen > IRLMP_MAX_USER_DATA_LEN)
        {
            DEBUGMSG(DBG_ERROR, (TEXT("IRLMP: User data len exceeded\n")));
            return IRLMP_USER_DATA_LEN_EXCEEDED;
        }

        pLsapCb->UserDataLen = pMsg->IRDA_MSG_DiscDataLen;
        RtlCopyMemory(pLsapCb->UserData, pMsg->IRDA_MSG_pDiscData,
               pMsg->IRDA_MSG_DiscDataLen);

        // Notify peer of the disconnect request, reason: user request
        // Send on different thread in case TranportAPI calls this on rx thread
        SendCntlPdu(pLsapCb,IRLMP_DISCONNECT_PDU,IRLMP_ABIT_REQUEST,
                         IRLMP_USER_REQUEST, 0);
    }

    IrdaTimerRestart(&pLsapCb->pIrlmpCb->DiscDelayTimer);

    CleanupLsap(pLsapCb);
    
    return 0;
}
/*****************************************************************************
*
*   @func   UINT | IrlmpDataReqExclusive | Process IRLMP data request
*
*   @rdesc  SUCCESS or an error code
*
*   @parm   IRLMP_LSAP_CB * | pLsapCb | pointer LSAP control block
*   @parm   IRDA_MSG * | pMsg | Pointer to an IRDA Message
*
*   WinCE can pass down multiple NDIS bufs. We need to segment -
*             just call IrlmpDataReqMultiplexed.
*/
UINT
IrlmpDataReqExclusive(IRLMP_LSAP_CB *pLsapCb, IRDA_MSG *pMsg)
{
    DEBUGMSG(DBG_IRLMP, (TEXT("IRLMP: Exclusive mode data request\n")));

    if (pLsapCb->pIrlmpCb->LinkState != LINK_READY)
    {
        return IRLMP_LINK_BAD_STATE;
    }

    if (pLsapCb != pLsapCb->pIrlmpCb->pExclLsapCb)
    {
        return IRLMP_INVALID_LSAP_CB;
    }
    
    return (IrlmpDataReqMultiplexed(pLsapCb, pMsg));
}
/*****************************************************************************
*
*   @func   UINT | IrlmpDataReqMultiplexed | Process IRLMP data request
*
*   @rdesc  SUCCESS or an error code
*
*   @parm   IRLMP_LSAP_CB * | pLsapCb | pointer LSAP control block
*   @parm   IRDA_MSG * | pMsg | Pointer to an IRDA Message
*/
UINT
IrlmpDataReqMultiplexed(IRLMP_LSAP_CB *pLsapCb, IRDA_MSG *pMsg)
{
    NDIS_BUFFER         *pNBuf = (NDIS_BUFFER *) pMsg->DataContext;
    NDIS_BUFFER         *pNextNBuf;
    UCHAR                *pData;
    int                 DataLen;
    int                 SegLen;
    IRDA_MSG            *pSegMsg;

    if (pLsapCb->State < LSAP_READY)
    {
        return IRLMP_LSAP_BAD_STATE;
    }
    
    // Place this message on the LSAP's TxMsgList. The message remains
    // here until all segments for it are sent and confirmed
    InsertTailList(&pLsapCb->TxMsgList, &pMsg->Linkage);

    pMsg->IRDA_MSG_SegCount = 0;
    // If it fails, this will be changed
    pMsg->IRDA_MSG_DataStatus = IRLMP_DATA_REQUEST_COMPLETED;

    // Segment the message into PDUs. The segment will either be:
    //  1. Sent immediately to IRLAP if the link is not busy
    //  2. If link is busy, placed on TxMsgList contained in IRLMP_LCB
    //  3. If no credit, placed onto this LSAPS SegTxMsgList

    while (pNBuf != NULL)
    {
        NdisQueryBuffer(pNBuf, &pData, &DataLen);
        
         // Get the next one now so I know when to set SegFlag to final
        NdisGetNextBuffer(pNBuf, &pNextNBuf);

        while (DataLen != 0)
        {
            if ((pSegMsg = AllocIrdaBuf(IrdaMsgPool))
                == NULL)
            {
                ASSERT(0);
                return IRLMP_ALLOC_FAILED;
            }
            pSegMsg->IRDA_MSG_pOwner = pLsapCb; // MUX routing
            pSegMsg->DataContext = pMsg; // Parent of segment
            pSegMsg->IRDA_MSG_IrCOMM_9Wire = pMsg->IRDA_MSG_IrCOMM_9Wire;

            // Increment segment count contained in original messages
            pMsg->IRDA_MSG_SegCount++;
            
            if (DataLen > pLsapCb->pIrlmpCb->MaxPDUSize)
            {
                SegLen = pLsapCb->pIrlmpCb->MaxPDUSize;
            }
            else
            {
                SegLen = DataLen;
            }
            
            DEBUGMSG(DBG_IRLMP, (TEXT("IRMLP: Sending SegLen %d\n"),
                                  SegLen));
            
            pSegMsg->IRDA_MSG_pRead = pData;
            pSegMsg->IRDA_MSG_pWrite = pData + SegLen;

            // Indicate this message is part of a segmented message
            pSegMsg->IRDA_MSG_SegCount = pMsg->IRDA_MSG_SegCount;
            
            pData += SegLen;
            DataLen -= SegLen;
            
            if (DataLen == 0 && pNextNBuf == NULL)
            {
                pSegMsg->IRDA_MSG_SegFlags = SEG_FINAL;
            }
            else
            {
                pSegMsg->IRDA_MSG_SegFlags = 0;
            }

            if (pLsapCb->State == LSAP_NO_TX_CREDIT)
            {
                DEBUGMSG(DBG_IRLMP, 
                        (TEXT("IRLMP: Out of credit, placing on SegList\n")));
                InsertTailList(&pLsapCb->SegTxMsgList, &pSegMsg->Linkage);
            }
            else
            {
                FormatAndSendDataReq(pLsapCb, pSegMsg, FALSE);
            }
        }
        pNBuf = pNextNBuf;
    }

    return SUCCESS;
}

VOID
FormatAndSendDataReq(IRLMP_LSAP_CB *pLsapCb, IRDA_MSG *pMsg,
                     BOOLEAN LocallyGenerated)
{
    IRLMP_HEADER        *pLMHeader;
    TTP_DATA_HEADER     *pTTPHeader;
    int                 AdditionalCredit;
    UCHAR                *pLastHdrByte;

    VALIDLSAP(pLsapCb);

    // Initialize the header pointers to the end of the header block
    pMsg->IRDA_MSG_pHdrRead  =
    pMsg->IRDA_MSG_pHdrWrite = pMsg->IRDA_MSG_Header + IRDA_HEADER_LEN;

    // Back up the read pointer for the LMP header
    pMsg->IRDA_MSG_pHdrRead -= sizeof(IRLMP_HEADER);

    // Back up header read pointer for TTP
    if (pLsapCb->UseTtp)
    {
        pMsg->IRDA_MSG_pHdrRead -= (sizeof(TTP_DATA_HEADER));
    }

        if (pMsg->IRDA_MSG_IrCOMM_9Wire == TRUE)
    {
        pMsg->IRDA_MSG_pHdrRead -= 1;
    }

    ASSERT(pMsg->IRDA_MSG_pHdrRead >= pMsg->IRDA_MSG_Header);

    // Build the LMP Header
    pLMHeader = (IRLMP_HEADER *) pMsg->IRDA_MSG_pHdrRead;
    pLMHeader->DstLsapSel = pLsapCb->RemoteLsapSel;
    pLMHeader->SrcLsapSel = pLsapCb->LocalLsapSel;
    pLMHeader->CntlBit = IRLMP_DATA_PDU;
    pLMHeader->RsvrdBit = 0;

    pLastHdrByte = (UCHAR *) (pLMHeader + 1);
    
    // Build the TTP Header
    if (pLsapCb->UseTtp)
    {
        pTTPHeader = (TTP_DATA_HEADER *) (pLMHeader + 1);

        // Credit
        if (pLsapCb->AvailableCredit > 127)
        {
            AdditionalCredit = 127;
            pLsapCb->AvailableCredit -= 127;
        }
        else
        {
            AdditionalCredit = pLsapCb->AvailableCredit;
            pLsapCb->AvailableCredit = 0;
        }

        pTTPHeader->AdditionalCredit = AdditionalCredit;
        pLsapCb->RemoteTxCredit += AdditionalCredit;

        if (pMsg->IRDA_MSG_pRead != pMsg->IRDA_MSG_pWrite)
        {
            // Only decrement my TxCredit if I'm sending data
            // (may be sending dataless PDU to extend credit to peer)
            pLsapCb->LocalTxCredit -= 1;
        
            if (pLsapCb->LocalTxCredit == 0)
            {
                DEBUGMSG(DBG_IRLMP, 
                         (TEXT("IRLMP: l%d,r%d No credit\n"), pLsapCb->LocalLsapSel,
                          pLsapCb->RemoteLsapSel));
                pLsapCb->State = LSAP_NO_TX_CREDIT;
            }
        }
        
        // SAR
        if (pMsg->IRDA_MSG_SegFlags & SEG_FINAL)
        {
            pTTPHeader->MoreBit = TTP_MBIT_FINAL;
        }
        else
        {
            pTTPHeader->MoreBit = TTP_MBIT_NOT_FINAL;
        }

        pLastHdrByte = (UCHAR *) (pTTPHeader + 1);
    }
    
        if (pMsg->IRDA_MSG_IrCOMM_9Wire == TRUE)
    {
        *pLastHdrByte = 0;
    }

    pMsg->Prim = IRLAP_DATA_REQ;
    if (LocallyGenerated)
    {
        pMsg->IRDA_MSG_SegFlags = SEG_LOCAL | SEG_FINAL;
        pMsg->IRDA_MSG_pOwner = 0;
    }
    else
    {
        pMsg->IRDA_MSG_pOwner = pLsapCb;
        REFADD(&pLsapCb->RefCnt, 'ATAD');
    }

    
    DEBUGMSG(DBG_IRLMP, (TEXT("IRLMP: Sending Data request pMsg:%X LsapCb:%X\n"),
             pMsg, pMsg->IRDA_MSG_pOwner));
    IrlapDown(pLsapCb->pIrlmpCb->pIrdaLinkCb->IrlapContext, pMsg);
    
    DEBUGMSG(DBG_IRLMP_CRED,
             (TEXT("IRLMP(l%d,r%d): Tx LocTxCredit %d,RemoteTxCredit %d\n"),
              pLsapCb->LocalLsapSel, pLsapCb->RemoteLsapSel,
              pLsapCb->LocalTxCredit, pLsapCb->RemoteTxCredit));
}
/*****************************************************************************
*
*   @func   UINT | IrlmpAccessModeReq | Processes the IRLMP_ACCESSMODE_REQ
*
*   @rdesc  SUCCESS or an error code
*
*   @parm   IRLMP_LSAP_CB * | pLsapCb | pointer LSAP control block
*   @parm   IRDA_MSG * | pMsg | Pointer to an IRDA Message
*/
UINT
IrlmpAccessModeReq(IRLMP_LSAP_CB *pRequestingLsapCb, IRDA_MSG *pMsg)
{
    IRLMP_LSAP_CB   *pLsapCb;
    PIRLMP_LINK_CB  pIrlmpCb = pRequestingLsapCb->pIrlmpCb;
    
    if (pIrlmpCb->LinkState != LINK_READY)
    {
        DEBUGMSG(DBG_ERROR, (TEXT("IRLMP: Link bad state %x\n"), 
                              pIrlmpCb->LinkState));        
        return IRLMP_LINK_BAD_STATE;
    }
    if (pRequestingLsapCb->State != LSAP_READY)
    {
        DEBUGMSG(DBG_ERROR, (TEXT("IRLMP: LSAP bad state %x\n"), 
                              pRequestingLsapCb->State));        
        return IRLMP_LSAP_BAD_STATE;
    }
    switch (pMsg->IRDA_MSG_AccessMode)
    {
      case IRLMP_EXCLUSIVE:
        if (pIrlmpCb->pExclLsapCb != NULL)
        {
            // Another LSAP has it already
            return IRLMP_IN_EXCLUSIVE_MODE;
        }
        for (pLsapCb = (IRLMP_LSAP_CB *) pIrlmpCb->LsapCbList.Flink;
             (LIST_ENTRY *) pLsapCb != &pIrlmpCb->LsapCbList;
             pLsapCb = (IRLMP_LSAP_CB *) pLsapCb->Linkage.Flink)
        {
            VALIDLSAP(pLsapCb);

            if (pLsapCb->State != LSAP_DISCONNECTED && 
                pLsapCb != pRequestingLsapCb)
            {
                return IRLMP_IN_MULTIPLEXED_MODE;
            }
        }

⌨️ 快捷键说明

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