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

📄 irlmp.c

📁 WinCE5.0部分核心源码
💻 C
📖 第 1 页 / 共 5 页
字号:
        
        // OK to request exclusive mode from peer
        pIrlmpCb->pExclLsapCb = pRequestingLsapCb;  
        
        if (pMsg->IRDA_MSG_IrLPTMode == TRUE)
        {
            pMsg->Prim = IRLMP_ACCESSMODE_CONF;
            pMsg->IRDA_MSG_AccessMode = IRLMP_EXCLUSIVE;
            pMsg->IRDA_MSG_ModeStatus = IRLMP_ACCESSMODE_SUCCESS;
            
            TdiUp(pRequestingLsapCb->pTdiContext, pMsg);
            return SUCCESS;
        }
        else
        {
            pRequestingLsapCb->State = LSAP_EXCLUSIVEMODE_PEND;

            SendCntlPdu(pRequestingLsapCb, IRLMP_ACCESSMODE_PDU,
                        IRLMP_ABIT_REQUEST, IRLMP_RSVD_PARM,
                        IRLMP_EXCLUSIVE);

            IrdaTimerRestart(&pRequestingLsapCb->ResponseTimer);

        }        
        break;
        
      case IRLMP_MULTIPLEXED:
        if (pIrlmpCb->pExclLsapCb == NULL)
        {
            return IRLMP_IN_MULTIPLEXED_MODE;
        }
        if (pIrlmpCb->pExclLsapCb != pRequestingLsapCb)
        {
            return IRLMP_NOT_LSAP_IN_EXCLUSIVE_MODE;
        }

        if (pMsg->IRDA_MSG_IrLPTMode == TRUE)
        {
            pIrlmpCb->pExclLsapCb = NULL;
            pMsg->Prim = IRLMP_ACCESSMODE_CONF;
            pMsg->IRDA_MSG_AccessMode = IRLMP_MULTIPLEXED;
            pMsg->IRDA_MSG_ModeStatus = IRLMP_ACCESSMODE_SUCCESS;
            return TdiUp(pRequestingLsapCb->pTdiContext,
                                   pMsg);
        }
        else
        {
            pRequestingLsapCb->State = LSAP_MULTIPLEXEDMODE_PEND;
        
            SendCntlPdu(pRequestingLsapCb, IRLMP_ACCESSMODE_PDU,
                        IRLMP_ABIT_REQUEST, IRLMP_RSVD_PARM,
                        IRLMP_MULTIPLEXED);     

            IrdaTimerRestart(&pRequestingLsapCb->ResponseTimer);            
        }
        break;
      default:
        return IRLMP_BAD_ACCESSMODE;
    }
    return SUCCESS;
}
/*****************************************************************************
*
*   @func   UINT | SendCntlPdu | Sends connect request to IRLAP
*
*   @rdesc  SUCCESS or an error code
*
*   @parm   IRLMP_LSAP_CB * | pLsapCb | pointer LSAP control block
*/
VOID
SendCntlPdu(IRLMP_LSAP_CB *pLsapCb, int OpCode, int ABit,
            int Parm1, int Parm2)
{
    IRDA_MSG            *pMsg = AllocIrdaBuf(IrdaMsgPool);
    IRLMP_HEADER        *pLMHeader;
    IRLMP_CNTL_FORMAT   *pCntlFormat;
    TTP_CONN_HEADER     *pTTPHeader;
    TTP_CONN_PARM       *pTTPParm;
    UINT                rc = SUCCESS;
    
    VALIDLSAP(pLsapCb);

    if (pMsg == NULL)
    {
        DEBUGMSG(DBG_ERROR, (TEXT("IRLMP: Alloc failed\n")));
        ASSERT(0);
        return;// IRLMP_ALLOC_FAILED;
    }

    pMsg->IRDA_MSG_SegFlags = SEG_LOCAL | SEG_FINAL;

    // 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) + \
                             sizeof(IRLMP_CNTL_FORMAT));
    
    // move it forward for non access mode control requests
    // (connect and disconnect don't have a Parm2)
    if (OpCode != IRLMP_ACCESSMODE_PDU)
    {
        pMsg->IRDA_MSG_pHdrRead++;
    }

    // If using Tiny TPP back up the read pointer for its header
    // From LMPs point of view this is where the user data begins.
    // We are sticking it in the header because TTP is now part of IRLMP.

    // TTP connect PDU's are only used for connection establishment
    if (pLsapCb->UseTtp && OpCode == IRLMP_CONNECT_PDU)
    {
        pMsg->IRDA_MSG_pHdrRead -= sizeof(TTP_CONN_HEADER);

        if (pLsapCb->RxMaxSDUSize > 0)
        {
            pMsg->IRDA_MSG_pHdrRead -= sizeof(TTP_CONN_PARM);
        }
    }

    // Build the IRLMP header
    pLMHeader = (IRLMP_HEADER *) pMsg->IRDA_MSG_pHdrRead;
    pLMHeader->DstLsapSel = pLsapCb->RemoteLsapSel;
    pLMHeader->SrcLsapSel = pLsapCb->LocalLsapSel;
    pLMHeader->CntlBit = IRLMP_CNTL_PDU;
    pLMHeader->RsvrdBit = 0;
    // Control portion of header
    pCntlFormat = (IRLMP_CNTL_FORMAT *) (pLMHeader + 1);
    pCntlFormat->OpCode = OpCode; 
    pCntlFormat->ABit = ABit;
    pCntlFormat->Parm1 = Parm1;
    if (OpCode == IRLMP_ACCESSMODE_PDU)
    {
        pCntlFormat->Parm2 = Parm2; // Access mode
    }
    
    // Build the TTP header if needed (we are using TTP and this is a
    // connection request or confirmation not).
    if (pLsapCb->UseTtp && OpCode == IRLMP_CONNECT_PDU)
    {
        // Always using the MaxSDUSize parameter. If the client wishes
        // to disable, MaxSDUSize = 0

        pTTPHeader = (TTP_CONN_HEADER *) (pCntlFormat + 1) - 1;
        // -1, LM-Connect-PDU doesn't use parm2

        /*
           #define TTP_PFLAG_NO_PARMS      0
           #define TTP_PFLAG_PARMS         1
        */

        pTTPHeader->ParmFlag = (pLsapCb->RxMaxSDUSize > 0);
        
        pTTPHeader->InitialCredit = pLsapCb->RemoteTxCredit;
        
        pTTPParm = (TTP_CONN_PARM *) (pTTPHeader + 1);

        if (pLsapCb->RxMaxSDUSize > 0)
        {
            // HARDCODE-O-RAMA
            pTTPParm->PLen = 6;
            pTTPParm->PI = TTP_MAX_SDU_SIZE_PI;
            pTTPParm->PL = TTP_MAX_SDU_SIZE_PL;
            pTTPParm->PV[3] = (UCHAR) (pLsapCb->RxMaxSDUSize & 0xFF);
            pTTPParm->PV[2] = (UCHAR) ((pLsapCb->RxMaxSDUSize & 0xFF00)
                                      >> 8);
            pTTPParm->PV[1] = (UCHAR) ((pLsapCb->RxMaxSDUSize & 0xFF0000)
                                      >> 16);
            pTTPParm->PV[0] = (UCHAR) ((pLsapCb->RxMaxSDUSize & 0xFF000000)
                                      >> 24);
        }
        
    }

    // Client connection data, Access mode does not include client data
    if (pLsapCb->UserDataLen == 0 || OpCode == IRLMP_ACCESSMODE_PDU) 
    {
        pMsg->IRDA_MSG_pBase =
        pMsg->IRDA_MSG_pRead =
        pMsg->IRDA_MSG_pWrite =
        pMsg->IRDA_MSG_pLimit = NULL;
    }
    else
    {
        pMsg->IRDA_MSG_pBase = pLsapCb->UserData;
        pMsg->IRDA_MSG_pRead = pLsapCb->UserData;
        pMsg->IRDA_MSG_pWrite = pLsapCb->UserData + pLsapCb->UserDataLen;
        pMsg->IRDA_MSG_pLimit = pMsg->IRDA_MSG_pWrite;
    }

    // Message built, send data request to IRLAP
    pMsg->Prim = IRLAP_DATA_REQ;

    pMsg->IRDA_MSG_pOwner = 0;

    DEBUGMSG(DBG_IRLMP,(TEXT("IRLMP: Sending LM_%s_%s for l=%d,r=%d pMsg:%X LsapCb:%X\n"), 
                         (OpCode == IRLMP_CONNECT_PDU ? TEXT("CONNECT") :
                         OpCode == IRLMP_DISCONNECT_PDU ? TEXT("DISCONNECT") :
                         OpCode == IRLMP_ACCESSMODE_PDU ? TEXT("ACCESSMODE") :
                         TEXT("!!oops!!")), 
                         (ABit==IRLMP_ABIT_REQUEST?TEXT("REQ"):TEXT("CONF")),
                         pLsapCb->LocalLsapSel,
                         pLsapCb->RemoteLsapSel,
                         pMsg, pLsapCb));

    IrlapDown(pLsapCb->pIrlmpCb->pIrdaLinkCb->IrlapContext, pMsg);
}
/*****************************************************************************
*
*   @func   UINT | LsapResponseTimerExp | Timer expiration callback
*
*   @rdesc  SUCCESS or an error code
*
*/
VOID
LsapResponseTimerExp(PVOID Context)
{
    IRLMP_LSAP_CB   *pLsapCb = (IRLMP_LSAP_CB *) Context;
    IRDA_MSG        IMsg;
    UINT            rc = SUCCESS;
    PIRLMP_LINK_CB  pIrlmpCb = pLsapCb->pIrlmpCb;
    
    DEBUGMSG(DBG_IRLMP, (TEXT("IRLMP: LSAP timer expired\n")));

    VALIDLSAP(pLsapCb);

    switch (pLsapCb->State)
    {
      case LSAP_LMCONN_CONF_PEND:
        if (pLsapCb->LocalLsapSel == IAS_LSAP_SEL)
        {
            IasServerDisconnectReq(pLsapCb);
            break;
        }
        
        if (pLsapCb->LocalLsapSel == IAS_LOCAL_LSAP_SEL && 
            pLsapCb->RemoteLsapSel == IAS_LSAP_SEL)
        {
            IasClientDisconnectReq(pLsapCb, IRLMP_NO_RESPONSE_LSAP) ;
        }
        else
        {
            // Tell upper layer the connect request failed
            IMsg.Prim = IRLMP_DISCONNECT_IND;
            IMsg.IRDA_MSG_DiscReason = IRLMP_NO_RESPONSE_LSAP;
            TdiUp(pLsapCb->pTdiContext, &IMsg);
            IrdaTimerRestart(&pIrlmpCb->DiscDelayTimer);
            CleanupLsap(pLsapCb);
        }
        break;

      case LSAP_CONN_RESP_PEND:
        pLsapCb->UserDataLen = 0; // This will ensure no client data sent in
                                   // Disconnect PDU below

        // Tell remote LSAP that its peer did not respond
        SendCntlPdu(pLsapCb,IRLMP_DISCONNECT_PDU,IRLMP_ABIT_REQUEST,
                    IRLMP_NO_RESPONSE_LSAP, 0);
        IrdaTimerRestart(&pIrlmpCb->DiscDelayTimer);

        CleanupLsap(pLsapCb);
        break;

      case LSAP_MULTIPLEXEDMODE_PEND:
        // Spec says peer can't refuse request to return to multiplex mode
        // but if no answer, go into multiplexed anyway?
      case LSAP_EXCLUSIVEMODE_PEND:
        pIrlmpCb->pExclLsapCb = NULL;
        // Peer didn't respond, maybe we are not connected anymore ???

        pLsapCb->State = LSAP_READY;
        
        IMsg.Prim = IRLMP_ACCESSMODE_CONF;
        IMsg.IRDA_MSG_AccessMode = IRLMP_MULTIPLEXED;
        IMsg.IRDA_MSG_ModeStatus = IRLMP_ACCESSMODE_FAILURE;
        TdiUp(pLsapCb->pTdiContext, &IMsg);
        break;
         
      default:
        DEBUGMSG(DBG_IRLMP, (TEXT("Ignoring timer expiry in this state\n")));
        ; // ignore
    }
}
/*****************************************************************************
*
*   @func   UINT | IrlmpUp | Bottom of IRLMP, called by IRLAP with
*                             IRLAP messages. This is the MUX
*
*   @rdesc  SUCCESS or an error code
*
*/
UINT
IrlmpUp(PIRDA_LINK_CB pIrdaLinkCb, IRDA_MSG *pMsg)
{
    PIRLMP_LINK_CB  pIrlmpCb;

    if (NULL == pIrdaLinkCb) {
        return IRLMP_LINK_BAD_STATE;
    }

    pIrlmpCb = (PIRLMP_LINK_CB) pIrdaLinkCb->IrlmpContext;

    switch (pMsg->Prim)
    {
      case IRLAP_DISCOVERY_IND:
        DEBUGMSG(ZONE_DSCV, (TEXT("IRLAP_DISCOVERY_IND\r\n")));  
        UpdateDeviceList(pIrdaLinkCb, pMsg->IRDA_MSG_pDevList);
        pMsg->Prim = IRLMP_DISCOVERY_IND;
        pMsg->IRDA_MSG_pDevList = &DeviceList;
        TdiUp(NULL, pMsg);
        return SUCCESS;

      case IRLAP_DISCOVERY_CONF:
        IrlapDiscoveryConf(pIrlmpCb, pMsg);
        return SUCCESS;

      case IRLAP_CONNECT_IND:
        IrlapConnectInd(pIrlmpCb, pMsg);
        return SUCCESS;

      case IRLAP_CONNECT_CONF:
        IrlapConnectConf(pIrlmpCb, pMsg);
        return SUCCESS;

      case IRLAP_DISCONNECT_IND:
        IrlapDisconnectInd(pIrlmpCb, pMsg);
        return SUCCESS;

      case IRLAP_DATA_CONF:
        IrlapDataConf(pMsg);
        return SUCCESS;

      case IRLAP_DATA_IND:
        IrlapDataInd(pIrlmpCb, pMsg);
        if (pIrlmpCb->pExclLsapCb &&
            pIrlmpCb->pExclLsapCb->RemoteTxCredit <=0)
            return IRLMP_LOCAL_BUSY;
        else
            return SUCCESS;

      case IRLAP_UDATA_IND:
        ASSERT(0);
        return SUCCESS;
        
      case IRLAP_STATUS_IND:
        TdiUp(NULL, pMsg);
        return SUCCESS;
    }
    return (SUCCESS);
}

/*****************************************************************************
*
*   @func   UINT | IrlapDiscoveryConf | Process the discovery confirm
*/
VOID
IrlapDiscoveryConf(PIRLMP_LINK_CB pIrlmpCb, IRDA_MSG *pMsg)
{
    DEBUGMSG(DBG_IRLMP, (TEXT("IRLMP: IRLAP_DISCOVERY_CONF\n")));
    
    if (pIrlmpCb->LinkState != LINK_IN_DISCOVERY)
    {
        DEBUGMSG(DBG_ERROR, (TEXT("IRLMP: Link bad state\n")));

        ASSERT(0);
        
        return;// IRLMP_LINK_BAD_STATE;
    }

    pIrlmpCb->LinkState = LINK_DISCONNECTED;

    if (pMsg->IRDA_MSG_DscvStatus == IRLAP_DISCOVERY_COMPLETED)
    {
        DEBUGMSG(ZONE_DSCV, (TEXT("IRLAP_DISCOVERY_CONF\r\n")));
        UpdateDeviceList(pIrlmpCb->pIrdaLinkCb, pMsg->IRDA_MSG_pDevList);
    }
    
    // Initiate discovery on next link
    IrdaEventSchedule(&EvDiscoveryReq, NULL);

    // Initiate a connection if one was requested while in discovery
    ScheduleConnectReq(pIrlmpCb);    
}
/*****************************************************************************
*
*   @func   void | UpdateDeviceList | Determines if new devices need to be
*                                  added or old ones removed from the device
*                                  list maintained by IRLMP
*
*   @parm   LIST_ENTRY * | pDevList | pointer to a list of devices
*/
void
UpdateDeviceList(PIRDA_LINK_CB pIrdaLinkCb, LIST_ENTRY *pNewDevList)
{
    IRDA_DEVICE     *pNewDevice;
    IRDA_DEVICE     *pOldDevice;
    IRDA_DEVICE     *pDevice;
    BOOLEAN         DeviceInList;
    
    DEBUGMSG(ZONE_DSCV, (TEXT("+UpdateDeviceList(0x%x, 0x%x)\r\n"),
                         pIrdaLinkCb, pNewDevList));
    
    NdisAcquireSpinLock(&SpinLock);
    
    // Add new devices, set not seen count to zero if devices is
    // seen again
    for (pNewDevice = (IRDA_D

⌨️ 快捷键说明

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