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

📄 irdatdi.c

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

    if (pAddrObj == NULL)
    {
        DEBUGMSG(ZONE_ERROR, (TEXT("IRLMP_AssociateAddress(0x%X,0x%X) pAddrObj==NULL\r\n"), pTDIReq, (unsigned) AddrHandle));
        TdiStatus = TDI_ADDR_INVALID;
        goto done;
    }

    if (pConn == NULL)
    {
        DEBUGMSG(ZONE_ERROR, (TEXT("IRLMP_AssociateAddress(0x%X,0x%X) pConn==NULL\r\n"), pTDIReq, (unsigned) AddrHandle));
        REFDELADDR(pAddrObj);
        TdiStatus = TDI_INVALID_CONNECTION;
        goto done;
    }

    VALIDCONN(pConn);
    VALIDADDR(pAddrObj);

    DEBUGMSG(ZONE_TDI,
        (TEXT("Associate Addr:%#x, id:%d; Conn:%#x, id:%d\r\n"), 
         pAddrObj, pAddrObj->dwId, pConn, pConn->dwId));
    
    EnterCriticalSection(&csIrObjList);
    ASSERT(pConn->pAddrObj == NULL);

    // Connection should be on unassociated list.
    RemoveEntryList(&pConn->Linkage);

    // Associate address and connection.
    InsertHeadList(&pAddrObj->ConnList, (PLIST_ENTRY)pConn);

    GET_CONN_LOCK(pConn);

    memcpy(&pConn->SockAddrLocal, &pAddrObj->SockAddrLocal, 
           sizeof(SOCKADDR_IRDA));
    pConn->IsServer         = pAddrObj->IsServer;
    pConn->LSAPSelLocal     = pAddrObj->LSAPSelLocal;
    pConn->UseExclusiveMode = pAddrObj->UseExclusiveMode;
    pConn->UseIrLPTMode     = pAddrObj->UseIrLPTMode;
    pConn->Use9WireMode     = pAddrObj->Use9WireMode;
    pConn->UseSharpMode     = pAddrObj->UseSharpMode;
    
    // Link IRLMP_CONNECTION to IRLMP_ADDR_OBJ.
    pConn->pAddrObj         = pAddrObj;

    FREE_CONN_LOCK(pConn);

    LeaveCriticalSection(&csIrObjList);

    // Keep reference to Address since we have pAddrObj in connection.
    // But remove reference to connection.
    REFDELCONN(pConn);

done:
    
    DEBUGMSG(ZONE_FUNCTION,
        (TEXT("-IRLMP_AssociateAddress [%#x (%d)]\r\n"), TdiStatus, TdiStatus));
    
    return(TdiStatus);
}

/*****************************************************************************
*
*   @func   TDI_STATUS  |   IRLMP_DisAssociateAddress   | NOT DONE
*/

TDI_STATUS
IRLMP_DisAssociateAddress(PTDI_REQUEST pTDIReq)
{
	DEBUGMSG(ZONE_FUNCTION, 
        (TEXT("IRLMP_DisAssociateAddress(0x%X)\r\n"), pTDIReq));

    ASSERT(0);

    return(TDI_SUCCESS);
}

// Our own internal disassociate. 
TDI_STATUS
TdiDisassociateAddress(PIRLMP_CONNECTION pConn)
{
    PIRLMP_ADDR_OBJ   pAddr;

    EnterCriticalSection(&csIrObjList);

    VALIDCONN(pConn);
    if (pConn) {

        // Remove from address list.
        RemoveEntryList((PLIST_ENTRY)pConn);
        // Add to unassociated connection list.
        InsertHeadList(&IrConnObjList, (PLIST_ENTRY)pConn);

        GET_CONN_LOCK(pConn);
        pAddr = pConn->pAddrObj;
        VALIDADDR(pAddr); // Shouldn't be NULL here.
        pConn->pAddrObj = NULL;
        FREE_CONN_LOCK(pConn);

        REFDELADDR(pAddr);
    }
    LeaveCriticalSection(&csIrObjList);

    return (TDI_SUCCESS);
}

/*****************************************************************************
*
*   @func   TDI_STATUS  |   IRLMP_Connect   |
*           Called after connect(). Initiates an IRLMP connection. 
*           IRLMP will call ConnectComplete() when the connection is
*           established.
*
*	@rdesc
*           TDI_SUCCESS (tdistat.h) on success, or (tdistat.h)
*   @errors
*           @ecode TDI_PENDING  | ConnectComplete() will be called.
*
*   @parm   PTDI_REQUEST                |   pTDIReq     |
*           (tdi.h) pTDIReq->Handle.ConnectionContext contains the 
*           CONNECTION_CONTEXT (tdi.h, PVOID) of the IRLMP_CONNECTION. 
*           IRLMP_OpenConnection() assigns this value to be a pointer to
*           the IRLMP_CONNECTION.
*           <nl>pTDIReq->RequestNotifyObject is a pointer (void (*)(PVOID 
*           Context, TDI_STATUS FinalStatus, unsigned long ByteCount)) to a
*           Winsock routine to call if this function returns TDI_PENDING.
*           <nl>pTDIReq->RequestNotifyContext is a Winsock context to return in
*           the callback.
*   @parm   PVOID                       |   pTimeOut    |
*           sockutil.c appears to always set this -1. IrLMP will ignore it.
*   @parm   PTDI_CONNECTION_INFORMATION |   pReqAddr    |
*           Pointer to input TDI_CONNECTION_INFORMATION (tdi.h) struct.
*           IrLMP assumes RemoteAddress points to a TRANSPORT_ADDRESS (tdi.h)
*           struct. IrLMP assumes one TA_ADDRESS entry with the Address field
*           containing the remaining bytes of a SOCKADDR_IRDA struct minus the
*           first two bytes.
*   @parm   PTDI_CONNECTION_INFORMATION |   pRetAddr    |
*           Pointer to output TDI_CONNECTION_INFORMATION (tdi.h) struct.
*
*   @xref   <f ConnectComplete>
*/

TDI_STATUS
IRLMP_Connect(PTDI_REQUEST                  pTDIReq,
              PVOID                         pTimeOut,
              PTDI_CONNECTION_INFORMATION   pReqAddr,
              PTDI_CONNECTION_INFORMATION   pRetAddr)
{
    TDI_STATUS        TdiStatus = TDI_PENDING;
    PIRLMP_CONNECTION pConn;
    IRDA_MSG          IrDAMsg;
    int               rc;
    int               i;
	int				  RetryCount = 0;
    int               IrlptMode = 1;

    DWORD             dwTemp;	// For compiler 

    BOOL              bLPTMode;
    DWORD             dwAddr;
    BYTE              ServiceName[25];
    DWORD             dwLSAPSelRemote;

	DEBUGMSG(ZONE_FUNCTION,
        (TEXT("+IRLMP_Connect(0x%X,0x%X,0x%X,0x%X)\r\n"), 
        pTDIReq, pTimeOut, pReqAddr, pRetAddr));

    pConn = GETCONN(pTDIReq->Handle.ConnectionContext);

    if (pConn == NULL)
    {
        TdiStatus = TDI_INVALID_CONNECTION;
        goto done_nolocks;
    }

    GET_CONN_LOCK(pConn);

    if (pConn->IsServer)
    {
        TdiStatus = TDI_INVALID_REQUEST;
        goto ExitIRLMP_Connect;
    }

    memcpy(&pConn->SockAddrRemote, 
           (BYTE *) &((PTRANSPORT_ADDRESS) 
                      pReqAddr->RemoteAddress)->Address[0].AddressType,
           sizeof(SOCKADDR_IRDA));

    pConn->pConnectComplete        = pTDIReq->RequestNotifyObject;
    pConn->pConnectCompleteContext = NULL;

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

    EnterCriticalSection(&csIasQuery);
    if (memcmp(&pConn->SockAddrRemote.irdaServiceName[0], LSAPSEL_TXT, LSAPSEL_TXTLEN) == 0)
    {
        pConn->LSAPSelRemote = ParseLsapSel(
            &pConn->SockAddrRemote.irdaServiceName[LSAPSEL_TXTLEN]);

        LeaveCriticalSection(&csIasQuery);
        if (pConn->LSAPSelRemote == -1)
        {
            TdiStatus = TDI_ADDR_INVALID;
            goto ExitIRLMP_Connect;
        }
    }
    else
    {
        LeaveCriticalSection(&csIasQuery);
        //
        // Let go of the connection during the query and reacquire it later.
        //
        memcpy(&dwAddr, &pConn->SockAddrRemote.irdaDeviceID, IRDA_DEV_ADDR_LEN);
        memcpy(ServiceName, pConn->SockAddrRemote.irdaServiceName, 25);
        bLPTMode = pConn->UseIrLPTMode;
        FREE_CONN_LOCK(pConn);
        REFDELCONN(pConn);
        pConn = NULL;
        EnterCriticalSection(&csIasQuery);

RetryIASQuery:
        
        if (IASQueryInProgress)
        {
						DEBUGMSG (ZONE_ERROR,
					  (TEXT("TDI:IRLMP_Connect returning TDI_IN_PROGRESS ")
					   TEXT("because IASQueryInProgress\r\n")));
            TdiStatus = TDI_IN_PROGRESS;
            goto ExitIRLMP_Connect_IASQuery;
        }

		// If we've been going around too many times then give up
		if (RetryCount++ > 20) {
			DEBUGMSG (ZONE_ERROR,
					  (TEXT("TDI:IRLMP_Connect returning TDI_NET_DOWN ")
					   TEXT("because too many retries of IAS Query\r\n")));
			TdiStatus = TDI_NET_DOWN;
			goto ExitIRLMP_Connect_IASQuery;
		}

        IASQueryInProgress = TRUE;

        pIASQuery = &ConnectIASQuery;

        IrDAMsg.Prim                   = IRLMP_GETVALUEBYCLASS_REQ;
        IrDAMsg.IRDA_MSG_pIasQuery     = pIASQuery;
        IrDAMsg.IRDA_MSG_AttribLen     = 1;

        memcpy(&pIASQuery->irdaDeviceID[0], &dwAddr, IRDA_DEV_ADDR_LEN);
        
        i = 0;
        // sh - Only allow 24 chars. We truncate the name because we
        //      have doc'd that it must be a NULL-terminated string
        //      in a 25 char array.
        while (ServiceName[i] && i < 24)
        {
            pIASQuery->irdaClassName[i] = ServiceName[i];
            i++;
        }
        pIASQuery->irdaClassName[i] = 0;

        if (bLPTMode)
        {
            // Two different attribute names for printers...most common
            // is IrDA:IrLMP:LsapSel.
            if (IrlptMode == 1)
            {
                strcpy(pIASQuery->irdaAttribName, "IrDA:IrLMP:LsapSel");
            }
            else
            {
                ASSERT(IrlptMode == 2);
                strcpy(pIASQuery->irdaAttribName, "IrDA:IrLMP:LSAPSel");            
            }
        }
        else
        {
            strcpy(pIASQuery->irdaAttribName, IasAttribName_TTPLsapSel);
        }

        LeaveCriticalSection(&csIasQuery);

        rc = IrlmpDown(NULL, &IrDAMsg);

        if (rc != 0)
        {
            EnterCriticalSection(&csIasQuery);
            IASQueryInProgress = FALSE;
            LeaveCriticalSection(&csIasQuery);

            if (rc == IRLMP_LINK_IN_USE)
            {
                TdiStatus = TDI_ADDR_IN_USE;
            }
            else if (rc == IRLMP_BAD_DEV_ADDR)
            {
                DEBUGMSG(ZONE_ERROR,
                    (TEXT("IrLMP: Can't connect - invalid address\r\n")));

                TdiStatus = TDI_ADDR_INVALID;
            }
            else    
            {
                ERRORMSG(1,
                    (TEXT("IrLMP: unrecoverable error %d\r\n"), rc));
                
                TdiStatus = WSANO_RECOVERY;
            }
            goto done_nolocks;
        }

		// We might get an IRLMP_IRLAP_REMOTE_DISCOVERY_IN_PROGRESS error
		// which means we want to wait until the discovery is complete.
		// We need to do this here to ensure that we don't miss the
		// Discovery Indication as we enter and leave the critical section
		ResetEvent(DscvIndEvent);

        WaitForSingleObject(IASQueryConfEvent, INFINITE);

        EnterCriticalSection(&csIasQuery);

        IASQueryInProgress = FALSE;

        if (IASQueryStatus == IRLMP_IAS_SUCCESS)
        {
            dwLSAPSelRemote = pIASQuery->irdaAttribute.irdaAttribInt;

            if (dwLSAPSelRemote > HIGHEST_LSAP_SEL)
            {
                TdiStatus = TDI_BAD_ADDR;
                goto ExitIRLMP_Connect_IASQuery;
            }

            LeaveCriticalSection(&csIasQuery);
        }
        else    
        {
            switch(IASQueryStatus)
            {
              case IRLMP_MAC_MEDIA_BUSY:
								DEBUGMSG (1, (TEXT("GOT IRLMP_MAC_MEDIA_BUSY in TDI:IRLMPConnect, retrying query\r\n")));
                *(volatile DWORD*)&dwTemp = 0;	// This avoids an SH3 compiler (#14740).
                goto RetryIASQuery;
                break;
                
              case IRLMP_IRLAP_REMOTE_DISCOVERY_IN_PROGRESS:
                /* wmz retry the query after DISCOVERY_IND */
								DEBUGMSG (1, (TEXT("GOT IRLMP_IRLAP_REMOTE_DISCOVERY_IN_PROGRESS in TDI:IRLMPConnect\r\n")));

                LeaveCriticalSection(&csIasQuery);

				WaitForSingleObject (DscvIndEvent, INFINITE);

                EnterCriticalSection(&csIasQuery);
		
				DEBUGMSG (1, (TEXT("GOT IRLMP_IRLAP_REMOTE_DISCOVERY_IN_PROGRESS in TDI:IRLMPConnect\r\n")));
                goto RetryIASQuery;
                break;
                
              case IRLMP_DISC_LSAP:
                TdiStatus = TDI_CONN_REFUSED;
                break;

              case IRLMP_NO_RESPONSE_LSAP:
                TdiStatus = TDI_TIMED_OUT;
                break;

              case IRLMP_IAS_NO_SUCH_OBJECT:
                TdiStatus = TDI_CONN_REFUSED;
                break;
            
              case IRLMP_IAS_NO_SUCH_ATTRIB:
                // This will retry the different Irlpt printer attribute names.
                if (IrlptMode == 1)
                {
                    IrlptMode++;
                    goto RetryIASQuery;
                }
                TdiStatus = TDI_CONN_REFUSED;
                break;

              default:
                TdiStatus = TDI_CONNECTION_ABORTED;
                break;
            }

            goto ExitIRLMP_Connect_IASQuery;
        }
    }

    if (pConn == NULL) {
        //
        // Reacquire conn after query
        //
        pConn = GETCONN(pTDIReq->Handle.ConnectionContext);
    
        if (pConn == NULL) {
            DEBUGMSG(ZONE_WARN, (TEXT("IRLMP_Connect - connection 0x%X gone after query\r\n"), pTDIReq->Handle.ConnectionContext));
            TdiStatus = TDI_CONNECTION_ABORTED;
            goto done_nolocks;
        }

        GET_CONN_LOCK(pConn);
        pConn->LSAPSelRemote = dwLSAPSelRemote;

⌨️ 快捷键说明

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