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

📄 tdiup.c

📁 WinCE5.0部分核心源码
💻 C
📖 第 1 页 / 共 3 页
字号:
//
// Copyright (c) Microsoft Corporation.  All rights reserved.
//
//
// This source code is licensed under Microsoft Shared Source License
// Version 1.0 for Windows CE.
// For a copy of the license visit http://go.microsoft.com/fwlink/?LinkId=3223.
//
/*++


 Module Name:    TdiUp.c

 Abstract:       Contains interface from IrLMP up to TDI.

 Contents:

--*/

#include "irdatdi.h"

extern BOOL AutoSuspend;
DWORD g_cActiveConnections = 0;

//
// Allow auto suspend while sockets are opened but there are no active connections.
//
void IrdaAutoSuspend(BOOL bAddConn)
{
    BOOL bCallCxport;
    if (TRUE == AutoSuspend) {
        bCallCxport = FALSE;
        EnterCriticalSection(&csIrObjList);
        if (bAddConn) {
            if (0 == g_cActiveConnections) {
                //
                // Only call the cxport function to disable suspend
                // if the number of active connections goes from 0 to 1.
                //
                bCallCxport = TRUE;
            }
            g_cActiveConnections++;
        } else{
            ASSERT(g_cActiveConnections);
            g_cActiveConnections--;
            if (0 == g_cActiveConnections) {
                //
                // Only call the cxport function to enable suspend
                // if the number of active connections goes from 1 to 0.
                //
                bCallCxport = TRUE;
            }
        }
        LeaveCriticalSection(&csIrObjList);

        if (bCallCxport) {
            CTEIOControl(
                bAddConn ? CTE_IOCTL_SET_IDLE_TIMER_RESET : CTE_IOCTL_CLEAR_IDLE_TIMER_RESET,
                NULL, 0, NULL, 0, NULL);
        }
    }
}   // IrdaAutoSuspend


/*++

 Function:       IrlmpDiscoveryConf

 Description:    Processes an IRLMP_DISCOVERY_CONFIRM. Completes a client
                 discovery request. The discovery request is stored in 
                 globals data.

 Comments:

--*/

VOID
IrlmpDiscoveryConf(IRDA_MSG *pIrDAMsg)
{
    IRDA_DEVICE       *pIrDADevice;         
    int                NickNameByte;
    int                NumDevices;
    DWORD              OldPermissions;

    DEBUGMSG(ZONE_TDI, (TEXT("TdiUp: +IRLMP_DISCOVERY_CONF\r\n")));
    
    EnterCriticalSection(&csDscv);

    if (DscvInProgress) {
    
        OldPermissions = SetProcPermissions(DscvCallersPermissions);
    
        pIrDADevice = (IRDA_DEVICE *) pIrDAMsg->IRDA_MSG_pDevList->Flink;
    
        if (pIrDAMsg->IRDA_MSG_pDevList == (LIST_ENTRY *) pIrDADevice)
        {
            NumDevices = 0;
        }
        else
        {
            NumDevices = 1;
            while (pIrDAMsg->IRDA_MSG_pDevList != (LIST_ENTRY *) pIrDADevice &&
                   NumDevices <= DscvNumDevices)
            {
                memcpy(&pDscvDevList->Device[NumDevices - 1].irdaDeviceID[0],
                       &pIrDADevice->DevAddr[0], IRDA_DEV_ADDR_LEN);
    
                // Retrieve the first 2 hint bytes
                pDscvDevList->Device[NumDevices-1].irdaDeviceHints1 = pIrDADevice->DscvInfo[0];
                pDscvDevList->Device[NumDevices-1].irdaDeviceHints2 = pIrDADevice->DscvInfo[1];
    
                // Skip additional hint bytes.
                NickNameByte = 0;
                while (pIrDADevice->DscvInfo[NickNameByte++] & 0x80);
            
                // Get the char set byte
                pDscvDevList->Device[NumDevices-1].irdaCharSet = pIrDADevice->DscvInfo[NickNameByte++];
    
                // copy the nickame
                memcpy(pDscvDevList->Device[NumDevices-1].irdaDeviceName, &(pIrDADevice->DscvInfo[NickNameByte]), IRDA_MAX_DEVICE_NAME);
                pDscvDevList->numDevice = NumDevices++;
            
                pIrDADevice = (IRDA_DEVICE *) pIrDADevice->Linkage.Flink;
            }
        }
    
        SetProcPermissions(OldPermissions);
        SetEvent(DscvConfEvent);
    }

    LeaveCriticalSection(&csDscv);

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

/*++

 Function:       IrlmpDiscoveryInd

 Description:    Process an IRLMP_DISCOVERY_IND.

 Comments:

--*/

__inline VOID
IrlmpDiscoveryInd()
{
    // Release all threads waiting on the DiscoveryIndication
    DEBUGMSG (ZONE_TDI, (TEXT("IRLMP_DISCOVERY_IND\r\n")));
    SetEvent(DscvIndEvent);

    // This is a manual reset event.  Anyone who wants to wait for the next
    // DISCOVERY_IND should reset the event before leaving the critical
    // section and doing the WaitForSingleObject()
}

/*++

 Function:       IrlmpConnectInd

 Description:    Processes an IRLMP_CONNECT_IND. Calls client connect
                 handler if we can find a matching address object.

 Comments:

--*/

VOID
IrlmpConnectInd(IRDA_MSG *pIrDAMsg)
{
    IRDA_MSG           IrDAMsg;
    TDI_STATUS         TdiStatus;
    int                rc;
    int                i;

    // IRLMP_CONNECT_IND
    BYTE               RemAddrBuf[sizeof(TRANSPORT_ADDRESS) +
                                  sizeof(SOCKADDR_IRDA) - 3];
    PTRANSPORT_ADDRESS pRemAddr = (PTRANSPORT_ADDRESS) RemAddrBuf;
    PSOCKADDR_IRDA     pSockAddr;
    void              *pConnectionContext;
    ConnectEventInfo   EventConnectCompleteInfo;
    int                Val, Digit;
    char               TmpStr[4];
    int                StrLen;
    PIRLMP_ADDR_OBJ    pAddrObj  = NULL;
    PIRLMP_CONNECTION  pConn     = NULL;
    PLIST_ENTRY        pAddrEntry, pConnEntry;

    DEBUGMSG(ZONE_TDI, (TEXT("TdiUp: +IRLMP_CONNECT_IND\r\n")));
    
    EnterCriticalSection(&csIrObjList);
    
    for (pAddrEntry = IrAddrObjList.Flink;
         pAddrEntry != &IrAddrObjList;
         pAddrEntry = pAddrEntry->Flink)
    {
        if (((PIRLMP_ADDR_OBJ)pAddrEntry)->LSAPSelLocal == pIrDAMsg->IRDA_MSG_LocalLsapSel)
        {
            pAddrObj = (PIRLMP_ADDR_OBJ)pAddrEntry;
            REFADDADDR(pAddrObj);
            VALIDADDR(pAddrObj);
            break;
        }
    }

    LeaveCriticalSection(&csIrObjList);

    if (NULL == pAddrObj)
    {
        //
        // No such address
        //
        IrDAMsg.Prim                 = IRLMP_DISCONNECT_REQ;
        IrDAMsg.IRDA_MSG_pDiscData   = NULL;
        IrDAMsg.IRDA_MSG_DiscDataLen = 0;
            
        rc = IrlmpDown(pIrDAMsg->IRDA_MSG_pContext, &IrDAMsg);
        ASSERT(rc == 0);
        goto done;
    }

    if (NULL == pAddrObj->pEventConnect)
    {
        //
        // Address not ready for connections (listen not called yet)
        //
        goto done;
    }

    pRemAddr->TAAddressCount           = 1;
    pRemAddr->Address[0].AddressLength = sizeof(SOCKADDR_IRDA) - 2;

    pSockAddr = (PSOCKADDR_IRDA) &pRemAddr->Address[0].AddressType;

    pSockAddr->irdaAddressFamily = AF_IRDA;

    memcpy(&pSockAddr->irdaDeviceID[0],
           &pIrDAMsg->IRDA_MSG_RemoteDevAddr[0], 
           IRDA_DEV_ADDR_LEN);
    
    Val = pIrDAMsg->IRDA_MSG_RemoteLsapSel;            
    StrLen = 0;
    while (Val > 0 && StrLen < 3)
    {
        Digit = Val % 10;
        Val = Val / 10;
        TmpStr[StrLen] = Digit + '0';
        StrLen++;
    }

    memcpy(&pSockAddr->irdaServiceName[0], LSAPSEL_TXT, LSAPSEL_TXTLEN);
        
    for (i = 0; i < StrLen; i++)
    {
        pSockAddr->irdaServiceName[i + 8] = TmpStr[StrLen - 1 - i];
    }

    pSockAddr->irdaServiceName[StrLen + 8] = 0;

    TdiStatus = pAddrObj->pEventConnect(
                    pAddrObj->pEventConnectContext,
                    offsetof(TRANSPORT_ADDRESS, 
                             Address[0].AddressType) + 
                    sizeof(SOCKADDR_IRDA),
                    pRemAddr,
                    0, NULL, 0, NULL,
                    &pConnectionContext,
                    &EventConnectCompleteInfo);

    if (TdiStatus != TDI_MORE_PROCESSING)
    {
        // The only error that we expect?
        ASSERT(TdiStatus == STATUS_REQUEST_NOT_ACCEPTED);
        goto done;
    }
    
    EnterCriticalSection(&csIrObjList);

    for (pConnEntry = pAddrObj->ConnList.Flink;
         pConnEntry != &pAddrObj->ConnList;
         pConnEntry = pConnEntry->Flink)
    {
        if (((PIRLMP_CONNECTION)pConnEntry)->pConnectionContext == pConnectionContext)
        {
            pConn = (PIRLMP_CONNECTION)pConnEntry;
            REFADDCONN(pConn);
            VALIDCONN(pConn);
            break;
        }
    }

    LeaveCriticalSection(&csIrObjList);

    if (pConn == NULL)
    {
        IrDAMsg.Prim                 = IRLMP_DISCONNECT_REQ;
        IrDAMsg.IRDA_MSG_pDiscData   = NULL;
        IrDAMsg.IRDA_MSG_DiscDataLen = 0;
            
        rc = IrlmpDown(pIrDAMsg->IRDA_MSG_pContext, &IrDAMsg);
        ASSERT(rc == 0);

        EventConnectCompleteInfo.cei_rtn(
            EventConnectCompleteInfo.cei_context,
            TDI_NO_FREE_ADDR, 
            0);
        goto done;
    }
    
    GET_CONN_LOCK(pConn);

    ASSERT(pConn->ConnState == IRLMP_CONN_CREATED);
    
    pConn->ConnState             = IRLMP_CONN_OPEN;
    pConn->LSAPSelRemote         = pIrDAMsg->IRDA_MSG_RemoteLsapSel;
    pConn->SendMaxSDU            = pIrDAMsg->IRDA_MSG_MaxSDUSize;
    pConn->SendMaxPDU            = pIrDAMsg->IRDA_MSG_MaxPDUSize;
    pConn->pIrLMPContext         = pIrDAMsg->IRDA_MSG_pContext;
    pConn->TinyTPRecvCreditsLeft = TINY_TP_RECV_CREDITS;
    // IRDA_MSG_pQos ignored

    memcpy(&pConn->SockAddrRemote, pSockAddr, sizeof(SOCKADDR_IRDA));

    FREE_CONN_LOCK(pConn);

    IrdaAutoSuspend(TRUE);    // new active connection

    IrDAMsg.Prim                 = IRLMP_CONNECT_RESP;
    IrDAMsg.IRDA_MSG_pConnData   = NULL;      
    IrDAMsg.IRDA_MSG_ConnDataLen = 0;      
    IrDAMsg.IRDA_MSG_pContext    = pConn;      
    IrDAMsg.IRDA_MSG_MaxSDUSize  = TINY_TP_RECV_MAX_SDU;
    IrDAMsg.IRDA_MSG_TtpCredits  = TINY_TP_RECV_CREDITS;

    rc = IrlmpDown(pIrDAMsg->IRDA_MSG_pContext, &IrDAMsg);
    ASSERT(rc == 0);

    EventConnectCompleteInfo.cei_rtn(
        EventConnectCompleteInfo.cei_context,
        TDI_SUCCESS, 
        0);

done:
    
    if (pAddrObj)   REFDELADDR(pAddrObj);
    if (pConn)      REFDELCONN(pConn);

    DEBUGMSG(ZONE_TDI, (TEXT("TdiUp: -IRLMP_CONNECT_IND\r\n")));

    return;
}


extern void
LingerTimerFunc(
    CTEEvent * pCTEEvent,
    void * pContext
    );

/*++

 Function:       IrlmpDisconnectInd

 Description:    Processes an IRLMP_DISCONNECT_IND.

 Comments:

--*/

VOID
IrlmpDisconnectInd(void *pConnContext, IRDA_MSG *pIrDAMsg)
{
    TDI_STATUS         TdiStatus;
    PIRLMP_CONNECTION  pConn;
    BOOL fConnPending;

    DEBUGMSG(ZONE_TDI, (TEXT("TdiUp: +IRLMP_DISCONNECT_IND\r\n")));
    
    pConn = GETCONN(pConnContext);
    
    if (pConn == NULL)
    {
        DEBUGMSG(ZONE_WARN,
            (TEXT("IrlmpDisconnectInd - invalid connection handle.\r\n")));
        
        return;
    }
    
    VALIDCONN(pConn);

    GET_CONN_LOCK(pConn);

    DEBUGMSG(ZONE_WARN,
             (TEXT("Got IrLMP Disconnect IND: ConnState=%d DiscReason=%d\r\n"),
              pConn->ConnState, pIrDAMsg->IRDA_MSG_DiscReason)
             );

    //
    // Make IRLMP_Disconnect quit its disconnect process because a disconnect indication
    // from the peer makes the LsapCb go away no matter what the connection state.
    //
    pConn->pIrLMPContext = NULL;

    if (pConn->ConnState == IRLMP_CONN_OPENING)
    {
        switch (pIrDAMsg->IRDA_MSG_DiscReason)
        {
            case IRLMP_MAC_MEDIA_BUSY:
                DEBUGMSG(ZONE_WARN, (TEXT("GOT IRLMP_MAC_MEDIA_BUSY in TDI:TdiUp\r\n")));
                /* wmz retry the connect */
                TdiStatus = TDI_NET_DOWN;
                break;

            case IRLMP_IRLAP_REMOTE_DISCOVERY_IN_PROGRESS:
                /* wmz retry the connect after DISCOVERY_IND */
                DEBUGMSG(ZONE_WARN, (TEXT("GOT IRLMP_IRLAP_REMOTE_DISCOVERY_IN_PROGRESS in TDI:TdiUp\r\n")));
                TdiStatus = TDI_NET_DOWN;
                break;

            case IRLMP_DISC_LSAP:
                TdiStatus = TDI_CONN_REFUSED;
                break;

            case IRLMP_NO_RESPONSE_LSAP:
                TdiStatus = TDI_TIMED_OUT;
                break;

            default:
                TdiStatus = TDI_CONNECTION_ABORTED;
                break;
        }

        fConnPending = pConn->fConnPending;
        pConn->fConnPending = FALSE;
        pConn->ConnState    = IRLMP_CONN_CLOSING;

        FREE_CONN_LOCK(pConn);

        if (fConnPending && pConn->pConnectCompleteContext) {
            pConn->pConnectComplete(pConn->pConnectCompleteContext, 
                                    TdiStatus, 0);
            // IRLMP_Connect left us an extra ref to take care of.
            REFDELCONN(pConn);
        }
    }
    else if (pConn->ConnState == IRLMP_CONN_OPEN)
    {
        switch (pIrDAMsg->IRDA_MSG_DiscReason)
        {
            case IRLMP_USER_REQUEST:
                TdiStatus = TDI_DISCONNECT_WAIT;
                break;

            case IRLMP_UNEXPECTED_IRLAP_DISC:
                if (pConn->UseSharpMode)
                {
                    // If special sharp mode is set then
                    // we pretend that an IRLAP_DISC is really
                    // just a normal close.
                    // Major hack but there are a lot of Zaurus's

⌨️ 快捷键说明

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