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

📄 irlmp.c

📁 WinCE5.0部分核心源码
💻 C
📖 第 1 页 / 共 5 页
字号:

      case IRLMP_CONNECT_RESP:
        rc = IrlmpConnectResp(pLsapCb, pMsg);
        break;

      case IRLMP_DISCONNECT_REQ:
        rc = IrlmpDisconnectReq(pLsapCb, pMsg);
        break;

      case IRLMP_DATA_REQ:
        if (pLsapCb->pIrlmpCb->pExclLsapCb != NULL)
        {
            rc = IrlmpDataReqExclusive(pLsapCb, pMsg);
        }
        else
        {
            rc = IrlmpDataReqMultiplexed(pLsapCb, pMsg);
        }
        break;

      case IRLMP_ACCESSMODE_REQ:
        rc = IrlmpAccessModeReq(pLsapCb, pMsg);
        break;
        
      case IRLMP_MORECREDIT_REQ:
        IrlmpMoreCreditReq(pLsapCb, pMsg);
        break;

      case IRLMP_GETVALUEBYCLASS_REQ:
        rc = IrlmpGetValueByClassReq(pMsg);
        break;

      case IRLMP_REGISTERLSAP_REQ:
        RegisterLsapProtocol(pMsg->IRDA_MSG_LocalLsapSel,
                             pMsg->IRDA_MSG_UseTtp);
        break;

      case IRLMP_DEREGISTERLSAP_REQ:
        DeregisterLsapProtocol(pMsg->IRDA_MSG_LocalLsapSel);
        break;

      case IRLMP_ADDATTRIBUTE_REQ:
        rc = IasAddAttribute(pMsg->IRDA_MSG_pIasSet, pMsg->IRDA_MSG_pAttribHandle);
        break;

      case IRLMP_DELATTRIBUTE_REQ:
        IasDelAttribute(pMsg->IRDA_MSG_AttribHandle);
        break;
        
      case IRLMP_LINKCONTROL_REQ:
        rc = IrlmpLinkControlReq(pMsg);
        break;

      default:
        ASSERT(0);
    }

    if (pLsapCb)
    {
        UNLOCK_LINK(pLsapCb->pIrlmpCb->pIrdaLinkCb);
        REFDEL(&pLsapCb->RefCnt, 'NWOD');
    }
    
    return rc;
}

UINT
IrlmpLinkControlReq(IRDA_MSG *pMsg)
{
    PIRDA_LINK_CB pIrdaLinkCb, pIrdaLinkCbNext;
    UINT          rc = SUCCESS;
    PIRLMP_LINK_CB pIrlmpCb;

    NdisAcquireSpinLock(&SpinLock);

    for (pIrdaLinkCb = (PIRDA_LINK_CB) IrdaLinkCbList.Flink;
         (LIST_ENTRY *) pIrdaLinkCb != &IrdaLinkCbList;
         pIrdaLinkCb = pIrdaLinkCbNext)
    {
        pIrdaLinkCbNext = (PIRDA_LINK_CB) pIrdaLinkCb->Linkage.Flink;

        pIrlmpCb = pIrdaLinkCb->IrlmpContext;
    
        while (pIrlmpCb->LinkState != LINK_DISCONNECTED)
        {
            NdisReleaseSpinLock(&SpinLock);
            // TDI should ensure that we never get a connect request while
            // we are trying to release the link.
            DEBUGMSG(ZONE_WARN,
                (TEXT("Irlmp: waiting for LMP to disconnect to release link.\r\n"))
                );
            Sleep(500); 
            NdisAcquireSpinLock(&SpinLock);
        }
    
        NdisReleaseSpinLock(&SpinLock);

        // If we are re-acquiring resources, we need to reload the device
        // name and change the IAS database. 
        if (pMsg->IRDA_MSG_AcquireResources == TRUE)
        {
            UpdateIasDeviceName(pIrlmpCb);
        }

        pMsg->Prim = IRLAP_LINKCONTROL_REQ;
        // AcquireResources is already set.
        // Currently we will not use the link configuration block.
        pMsg->IRDA_MSG_pLinkConfig  = NULL;
        pMsg->IRDA_MSG_pLinkContext = pIrdaLinkCb;
        rc = IrlapDown(pIrdaLinkCb->IrlapContext, pMsg);

        NdisAcquireSpinLock(&SpinLock);

        if (rc != SUCCESS)
        {
            DEBUGMSG(DBG_ERROR,
                     (TEXT("IRLAP_LINKCONTROL_REQ failure - 0x%x\r\n"), rc));
                        break; 
        }
    }

    NdisReleaseSpinLock(&SpinLock);

    return (rc);
}

VOID
IrlmpMoreCreditReq(IRLMP_LSAP_CB *pLsapCb, IRDA_MSG *pMsg)
{
    int CurrentAvail = pLsapCb->AvailableCredit;

    pLsapCb->AvailableCredit += pMsg->IRDA_MSG_TtpCredits;
    
    if (pLsapCb->UseTtp)
    {
        if ((CurrentAvail == 0) || (pLsapCb->RemoteTxCredit == 0))
        {
            // remote peer completely out of credit, send'm some
            SendCreditPdu(pLsapCb);
        }
    }
    else
    {
        if (pLsapCb == pLsapCb->pIrlmpCb->pExclLsapCb)
        {
            pLsapCb->RemoteTxCredit += pMsg->IRDA_MSG_TtpCredits;
            pMsg->Prim = IRLAP_FLOWON_REQ;
            IrlapDown(pLsapCb->pIrlmpCb->pIrdaLinkCb->IrlapContext, pMsg);
        }
    }
}

/*****************************************************************************
*
*   @func   UINT | IrlmpDiscoveryReq | initiates a discovery request
*
*   @rdesc  SUCCESS or an error code
*
*   @parm   IRDA_MSG * | pMsg | Pointer to an IRDA Message
*/
VOID
IrlmpDiscoveryReq(IRDA_MSG *pMsg)
{
    PIRDA_LINK_CB   pIrdaLinkCb;
    PIRLMP_LINK_CB  pIrlmpCb;
    
    DEBUGMSG(DBG_IRLMP, (TEXT("IRLMP: IRLMP_DISCOVERY_REQ\n")));

    NdisAcquireSpinLock(&SpinLock);

    if (DscvReqScheduled)
    {
        DEBUGMSG(DBG_IRLMP, (TEXT("Discovery already schedule\n")));
        NdisReleaseSpinLock(&SpinLock);
    }
    else
    {
        // Flag each link for discovery
        for (pIrdaLinkCb = (PIRDA_LINK_CB) IrdaLinkCbList.Flink;
             (LIST_ENTRY *) pIrdaLinkCb != &IrdaLinkCbList;
             pIrdaLinkCb = (PIRDA_LINK_CB) pIrdaLinkCb->Linkage.Flink)    
        {
            pIrlmpCb = (PIRLMP_LINK_CB) pIrdaLinkCb->IrlmpContext;
            pIrlmpCb->DiscoveryPending = TRUE;
        }
        
        DscvReqScheduled = TRUE;
        
        NdisReleaseSpinLock(&SpinLock);

        // Schedule the first link
    
        IrdaEventSchedule(&EvDiscoveryReq, NULL);
    }
}
/*****************************************************************************
*
*   @func   UINT | IrlmpConnectReq | Process IRLMP connect request
*
*   @rdesc  SUCCESS or an error code
*
*   @parm   IRDA_MSG * | pMsg | Pointer to an IRDA Message
*/
UINT
IrlmpConnectReq(IRDA_MSG *pMsg)
{
    PIRLMP_LSAP_CB  pLsapCb;
    PIRLMP_LINK_CB  pIrlmpCb = GetIrlmpCb(pMsg->IRDA_MSG_RemoteDevAddr);
    UINT            rc = SUCCESS;

    if (pIrlmpCb == NULL)
        return IRLMP_BAD_DEV_ADDR;
        
    LOCK_LINK(pIrlmpCb->pIrdaLinkCb);        
    
    if (pIrlmpCb->pExclLsapCb != NULL)
    {
        rc = IRLMP_IN_EXCLUSIVE_MODE;
    } 
    else if (GetLsap(pIrlmpCb, pMsg->IRDA_MSG_LocalLsapSel, 
            pMsg->IRDA_MSG_RemoteLsapSel) != NULL)
    {        
        rc = IRLMP_LSAP_SEL_IN_USE;
    } 
    else if ((UINT)pMsg->IRDA_MSG_ConnDataLen > IRLMP_MAX_USER_DATA_LEN)
    {
        rc = IRLMP_USER_DATA_LEN_EXCEEDED;
    }    
    else if (CreateLsap(pIrlmpCb, &pLsapCb) != SUCCESS)
    {
        rc = 1;
    }    
    
    if (rc != SUCCESS)
        goto exit;


    // Initialize the LSAP endpoint
    pLsapCb->LocalLsapSel          = pMsg->IRDA_MSG_LocalLsapSel;
    pLsapCb->RemoteLsapSel         = pMsg->IRDA_MSG_RemoteLsapSel;
    pLsapCb->pTdiContext           = pMsg->IRDA_MSG_pContext;
    pLsapCb->UseTtp                = pMsg->IRDA_MSG_UseTtp;
    pLsapCb->RxMaxSDUSize          = pMsg->IRDA_MSG_MaxSDUSize;
    pLsapCb->AvailableCredit       = pMsg->IRDA_MSG_TtpCredits;
    pLsapCb->UserDataLen           = pMsg->IRDA_MSG_ConnDataLen;    
    RtlCopyMemory(pLsapCb->UserData, pMsg->IRDA_MSG_pConnData,
           pMsg->IRDA_MSG_ConnDataLen);
    
    // TDI can abort this connection before the confirm
    // from peer is received. TDI will call into LMP to
    // do this so we must return the Lsap context now.
    // This is the only time we actually return something
    // in an Irda Message.
    pMsg->IRDA_MSG_pContext = pLsapCb;

    DEBUGMSG((DBG_IRLMP | DBG_IRLMP_CONN), 
            (TEXT("IRLMP: IRLMP_CONNECT_REQ (l=%d,r=%d), Tdi:%X LinkState=%s\r\n"),
            pLsapCb->LocalLsapSel, pLsapCb->RemoteLsapSel, pLsapCb->pTdiContext,
            pIrlmpCb->LinkState == LINK_DISCONNECTED ? TEXT("DISCONNECTED") :
            pIrlmpCb->LinkState == LINK_IN_DISCOVERY ? TEXT("IN_DISCOVERY") :
            pIrlmpCb->LinkState == LINK_DISCONNECTING? TEXT("DISCONNECTING"):
            pIrlmpCb->LinkState == LINK_READY ? TEXT("READY") : TEXT("oh!")));

    switch (pIrlmpCb->LinkState)
    {
      case LINK_DISCONNECTED:
        RtlCopyMemory(pIrlmpCb->ConnDevAddr, pMsg->IRDA_MSG_RemoteDevAddr,
               IRDA_DEV_ADDR_LEN);

        pLsapCb->State = LSAP_CONN_REQ_PEND;
        SetupTtp(pLsapCb);

        // Initiate a connection on another thrd cuz this might be the rx thread
        ScheduleConnectReq(pIrlmpCb);
        break;

      case LINK_IN_DISCOVERY:
      case LINK_DISCONNECTING:
        if (pIrlmpCb->ConnDevAddrSet == FALSE)
        {
            // Ensure that only the first device to request a connection
            // sets the device address of the remote to be connected to.
            RtlCopyMemory(pIrlmpCb->ConnDevAddr, pMsg->IRDA_MSG_RemoteDevAddr,
                    IRDA_DEV_ADDR_LEN);
            pIrlmpCb->ConnDevAddrSet = TRUE;
        }
        else
        {
            DEBUGMSG(DBG_IRLMP, (TEXT("IRLMP: Link in use!\r\n")));
            
        #ifdef UNDER_CE
            if (memcmp(pMsg->IRDA_MSG_RemoteDevAddr,
                       pIrlmpCb->ConnDevAddr,
                       IRDA_DEV_ADDR_LEN) != 0)
        #else
            if (RtlCompareMemory(pMsg->IRDA_MSG_RemoteDevAddr,
                                 pIrlmpCb->ConnDevAddr,
                                 IRDA_DEV_ADDR_LEN) != IRDA_DEV_ADDR_LEN)
        #endif // !UNDER_CE
            {
                // This LSAP is requesting a connection to another device
                CleanupLsap(pLsapCb);
                rc = IRLMP_LINK_IN_USE;
                break;
            }
        }

        pLsapCb->State = LSAP_CONN_REQ_PEND;
        SetupTtp(pLsapCb);

        // This request will complete when discovery/disconnect ends
        break;

      case LINK_CONNECTING:

    #ifdef UNDER_CE
        if (memcmp(pMsg->IRDA_MSG_RemoteDevAddr,
                   pIrlmpCb->ConnDevAddr,
                   IRDA_DEV_ADDR_LEN) != 0)
    #else
        if (RtlCompareMemory(pMsg->IRDA_MSG_RemoteDevAddr,
                             pIrlmpCb->ConnDevAddr,
                             IRDA_DEV_ADDR_LEN) != IRDA_DEV_ADDR_LEN)
    #endif // !UNDER_CE
        {
            DEBUGMSG(DBG_IRLMP, (TEXT("IRLMP: Link in use!\r\n")));
            // This LSAP is requesting a connection to another device,
            // not the one IRLAP is currently connected to
            CleanupLsap(pLsapCb);
            rc = IRLMP_LINK_IN_USE;
            break;
        }

        // The LSAP will be notified when the IRLAP connection that is
        // underway has completed (see IRLAP_ConnectConf)
        pLsapCb->State = LSAP_IRLAP_CONN_PEND; 

        SetupTtp(pLsapCb);

        break;

      case LINK_READY:
    #ifdef UNDER_CE
        if (memcmp(pMsg->IRDA_MSG_RemoteDevAddr,
                   pIrlmpCb->ConnDevAddr,
                   IRDA_DEV_ADDR_LEN) != 0)
    #else
        if (RtlCompareMemory(pMsg->IRDA_MSG_RemoteDevAddr,
                             pIrlmpCb->ConnDevAddr,
                             IRDA_DEV_ADDR_LEN) != IRDA_DEV_ADDR_LEN)
    #endif // !UNDER_CE
        {
            DEBUGMSG(DBG_IRLMP, (TEXT("IRLMP: Link in use!\r\n")));
            // This LSAP is requesting a connection to another device
            CleanupLsap(pLsapCb);
            rc = IRLMP_LINK_IN_USE;
            break;
        }
        IrdaTimerRestart(&pLsapCb->ResponseTimer);

        pLsapCb->State = LSAP_LMCONN_CONF_PEND;
        SetupTtp(pLsapCb);

        // Ask remote LSAP for a connection
        SendCntlPdu(pLsapCb, IRLMP_CONNECT_PDU,
                    IRLMP_ABIT_REQUEST, IRLMP_RSVD_PARM, 0);
        break;
    }
    
exit:

    UNLOCK_LINK(pIrlmpCb->pIrdaLinkCb);    

    return rc;
}
/*****************************************************************************
*
*   @func   void | SetupTtp | if using TTP, calculate initial credits
*
*   @rdesc  SUCCESS or an error code
*
*   @parm   IRLMP_LSAP_CB * | pLsapCb | pointer LSAP control block
*/
void
SetupTtp(IRLMP_LSAP_CB *pLsapCb)
{
    VALIDLSAP(pLsapCb);

    if (pLsapCb->AvailableCredit > 127)
    {
        pLsapCb->RemoteTxCredit = 127;
        pLsapCb->AvailableCredit -= 127;
    }
    else
    {
        pLsapCb->RemoteTxCredit = pLsapCb->AvailableCredit;
        pLsapCb->AvailableCredit = 0;
    }
    DEBUGMSG(DBG_IRLMP, (TEXT("IRLMP: RemoteTxCredit %d\n"),
                         pLsapCb->RemoteTxCredit));
}
/*****************************************************************************
*
*   @func   UINT | IrlmpConnectResp | Process IRLMP connect response
*
*   @rdesc  SUCCESS or an error code
*

⌨️ 快捷键说明

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