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

📄 mdd.c

📁 SBC2410 WinCE 5.0 BSP.绝大多数驱动已经调通。
💻 C
📖 第 1 页 / 共 5 页
字号:

        pSerialHead->StopXmit = 0;
        pSerialHead->SentXoff = 0;
        pSerialHead->DtrFlow = 0;
        pSerialHead->RtsFlow = 0;

        ApplyDCB (pSerialHead, &(pSerialHead->DCB), FALSE);

        pHWObj->pFuncTbl->HWSetCommTimeouts(pSerialHead->pHWHead,
                                            &(pSerialHead->CommTimeouts));

        if ( !pHWObj->pFuncTbl->HWOpen(pSerialHead->pHWHead) ) {
            DEBUGMSG (ZONE_OPEN|ZONE_ERROR, (TEXT("HW Open failed.\r\n")));
            goto OpenFail;
        }

        pHWObj->pFuncTbl->HWPurgeComm(pSerialHead->pHWHead, PURGE_RXCLEAR);
        memset(pSerialHead->RxBufferInfo.RxCharBuffer, 0, pSerialHead->RxBufferInfo.Length);
        if ( pHWObj->BindFlags & THREAD_IN_MDD ) {
            CeSetThreadPriority(pSerialHead->pDispatchThread,
                                pSerialHead->Priority256);
        }

        RxResetFifo (pSerialHead);
    }

    ++(pSerialHead->OpenCnt);

    // OK, we are finally back in a stable state.  Release the CS.
    LeaveCriticalSection(&(pSerialHead->OpenCS));

    DEBUGMSG (ZONE_OPEN|ZONE_FUNCTION, (TEXT("-COM_Open handle x%X, x%X, Ref x%X\r\n"),
                                        pOpenHead, pOpenHead->pSerialHead, pSerialHead->OpenCnt));

    return(pOpenHead);

    OpenFail :
    DEBUGMSG (ZONE_OPEN|ZONE_FUNCTION, (TEXT("-COM_Open handle x%X, x%X, Ref x%X\r\n"),
                                        NULL, pOpenHead->pSerialHead, pSerialHead->OpenCnt));

    SetLastError(ERROR_OPEN_FAILED);

    // If this was the handle with access permission, remove pointer
    if ( pOpenHead == pSerialHead->pAccessOwner )
        pSerialHead->pAccessOwner = NULL;

    // Remove the Open entry from the linked list
    RemoveEntryList(&pOpenHead->llist);

    // OK, everything is stable so release the critical section
    LeaveCriticalSection(&(pSerialHead->OpenCS));

    // Free all data allocated in open
    if ( pOpenHead->CommEvents.hCommEvent )
        CloseHandle(pOpenHead->CommEvents.hCommEvent);
	DeleteCriticalSection(&(pOpenHead->CommEvents.EventCS));
    LocalFree( pOpenHead );

    return(NULL);


}

// ****************************************************************
//
//	@doc EXTERNAL
//
//	@func BOOL	| COM_Close | close the serial device.
//
//	@parm DWORD | pHead		| Context pointer returned from COM_Open
//
//	@rdesc TRUE if success; FALSE if failure
//
//	@remark This routine is called by the device manager to close the device.
//			
//
//
BOOL
COM_Close(PHW_OPEN_INFO pOpenHead)
{
    PHW_INDEP_INFO  pSerialHead = pOpenHead->pSerialHead;
    PHWOBJ          pHWObj;
    int i;
    BOOL            RetCode = TRUE;

    DEBUGMSG (ZONE_CLOSE|ZONE_FUNCTION, (TEXT("+COM_Close\r\n")));

    if ( !pSerialHead ) {
        DEBUGMSG (ZONE_ERROR, (TEXT("!!COM_Close: pSerialHead == NULL!!\r\n")));
        SetLastError(ERROR_INVALID_HANDLE);
        return(FALSE);
    }
    pHWObj = (PHWOBJ)pSerialHead->pHWObj;

    // Use the OpenCS to make sure we don't collide with an in-progress open.
    EnterCriticalSection(&(pSerialHead->OpenCS));

    if ( pSerialHead->OpenCnt ) {
        --(pSerialHead->OpenCnt);

        DEBUGMSG (1,
                  (TEXT("COM_Close: (%d handles) total RX %d, total TX %d, dropped (mdd, pdd) %d,%d\r\n"),
                   pSerialHead->OpenCnt, pSerialHead->RxBytes, pSerialHead->TxBytes, pSerialHead->DroppedBytesMDD, pSerialHead->DroppedBytesPDD));

        // In multi open case, do we need to restore state later on or something????
        if ( pHWObj && (pHWObj->BindFlags & THREAD_IN_MDD) &&
             pSerialHead->pDispatchThread ) {
            SetThreadPriority(pSerialHead->pDispatchThread,
                              THREAD_PRIORITY_NORMAL);
        }

        // Free up any threads which may be blocked waiting for events.
        // Monitor users count to make sure no one is still in one of
        // the COM_ functions before proceeding (wait up to 2 s). 
        for ( i=0; i<20 && pOpenHead->StructUsers; i++ ) {
            DEBUGMSG(ZONE_INIT|ZONE_CLOSE,
                     (TEXT("COM_Close: %d users in MDD functions\n\r"),pOpenHead->StructUsers));

            // For any open handle, we must free pending waitcommevents
			EnterCriticalSection(&(pOpenHead->CommEvents.EventCS));
            pOpenHead->CommEvents.fEventMask = 0;
            pOpenHead->CommEvents.fAbort = 1;
            SetEvent(pOpenHead->CommEvents.hCommEvent);
			LeaveCriticalSection(&(pOpenHead->CommEvents.EventCS));

            // And only for the handle with access permissions do we
            // have to worry about read, write, etc being blocked.
            if ( pOpenHead->AccessCode & (GENERIC_READ | GENERIC_WRITE) ) {
                SetEvent(pSerialHead->hReadEvent);
                SetEvent(pSerialHead->hTransmitEvent);
            }

            /* Sleep, let threads finish */
            Sleep(100);
        }
        if ( i==20 )
            DEBUGMSG(ZONE_CLOSE|ZONE_INIT|ZONE_ERROR,
                     (TEXT("COM_Close: Waited 2s for serial users to exit, %d left\n\r"),
                      pOpenHead->StructUsers));

        // If we are closing the last open handle, then close PDD also
        if ( !pSerialHead->OpenCnt ) {
            DEBUGMSG (ZONE_CLOSE, (TEXT("About to call HWClose\r\n")));
            if ( pHWObj )
                pHWObj->pFuncTbl->HWClose(pSerialHead->pHWHead);
            DEBUGMSG (ZONE_CLOSE, (TEXT("Returned from HWClose\r\n")));

            // And if thread was spun in open, kill it now.
            if ( pSerialHead->pHWObj->BindFlags & THREAD_AT_OPEN ) {
                DEBUGMSG (ZONE_CLOSE, (TEXT("COM_Close : Stopping Dispatch Thread\r\n")));
                StopDispatchThread( pSerialHead );
            }
        }

        // If this was the handle with access permission, remove pointer
        if ( pOpenHead == pSerialHead->pAccessOwner ) {
            DEBUGMSG(ZONE_INIT|ZONE_CLOSE,
                     (TEXT("COM_Close: Closed access owner handle\n\r"),
                      pOpenHead));

            pSerialHead->pAccessOwner = NULL;
        }

        // Remove the entry from the linked list
        RemoveEntryList(&pOpenHead->llist);

        // Free all data allocated in open
		DeleteCriticalSection(&(pOpenHead->CommEvents.EventCS));
        if ( pOpenHead->CommEvents.hCommEvent )
            CloseHandle(pOpenHead->CommEvents.hCommEvent);
        LocalFree( pOpenHead );
    } else {
        DEBUGMSG (ZONE_ERROR, (TEXT("!!Close of non-open serial port\r\n")));
        SetLastError(ERROR_INVALID_HANDLE);        
        RetCode = FALSE;
    }

    // OK, other inits/opens can go ahead.
    LeaveCriticalSection(&(pSerialHead->OpenCS));

    DEBUGMSG (ZONE_CLOSE|ZONE_FUNCTION, (TEXT("-COM_Close\r\n")));
    return(RetCode);
}

// Routine to handle the PROCESS_EXITING flag.  Should let free any threads blocked on pOpenHead,
// so they can be killed and the process closed.

BOOL
ProcessExiting(PHW_OPEN_INFO pOpenHead)
{
    PHW_INDEP_INFO  pSerialHead = pOpenHead->pSerialHead;
    PHWOBJ          pHWObj;
    int i;
    BOOL            RetCode = TRUE;

    DEBUGMSG (ZONE_CLOSE|ZONE_FUNCTION, (TEXT("+ProcessExiting\r\n")));

    if ( !pSerialHead ) {
        DEBUGMSG (ZONE_ERROR, (TEXT("!!ProcessExiting: pSerialHead == NULL!!\r\n")));
        SetLastError(ERROR_INVALID_HANDLE);
        return(FALSE);
    }
    pHWObj = (PHWOBJ)pSerialHead->pHWObj;

    // Use the OpenCS to make sure we don't collide with an in-progress open.
    EnterCriticalSection(&(pSerialHead->OpenCS));

    if ( pSerialHead->OpenCnt ) {
//        --(pSerialHead->OpenCnt);

        DEBUGMSG (1,
                  (TEXT("ProcessClose: (%d handles) total RX %d, total TX %d, dropped (mdd, pdd) %d,%d\r\n"),
                   pSerialHead->OpenCnt, pSerialHead->RxBytes, pSerialHead->TxBytes, pSerialHead->DroppedBytesMDD, pSerialHead->DroppedBytesPDD));

        // In multi open case, do we need to restore state later on or something????
        if ( pHWObj && (pHWObj->BindFlags & THREAD_IN_MDD) &&
             pSerialHead->pDispatchThread ) {
            SetThreadPriority(pSerialHead->pDispatchThread,
                              THREAD_PRIORITY_NORMAL);
        }

        // Free up any threads which may be blocked waiting for events.
        // Monitor users count to make sure no one is still in one of
        // the COM_ functions before proceeding (wait up to 2 s). 
        for ( i=0; i<20 && pOpenHead->StructUsers; i++ ) {
            DEBUGMSG(ZONE_INIT|ZONE_CLOSE,
                     (TEXT("ProcessExiting: %d users in MDD functions\n\r"),pOpenHead->StructUsers));

            // For any open handle, we must free pending waitcommevents
			EnterCriticalSection(&(pOpenHead->CommEvents.EventCS));
            pOpenHead->CommEvents.fEventMask = 0;
            pOpenHead->CommEvents.fAbort = 1;
            SetEvent(pOpenHead->CommEvents.hCommEvent);
			LeaveCriticalSection(&(pOpenHead->CommEvents.EventCS));

            // And only for the handle with access permissions do we
            // have to worry about read, write, etc being blocked.
            if ( pOpenHead->AccessCode & (GENERIC_READ | GENERIC_WRITE) ) {
                SetEvent(pSerialHead->hReadEvent);
                SetEvent(pSerialHead->hTransmitEvent);
            }

            /* Sleep, let threads finish */
            Sleep(100);
        }
        if ( i==20 )
            DEBUGMSG(ZONE_CLOSE|ZONE_INIT|ZONE_ERROR,
                     (TEXT("ProcessExiting: Waited 2s for serial users to exit, %d left\n\r"),
                      pOpenHead->StructUsers));

/*           Don't really want to close everything.  Just want to free threads
             // If we are closing the last open handle, then close PDD also
        if ( !pSerialHead->OpenCnt ) {
            DEBUGMSG (ZONE_CLOSE, (TEXT("About to call HWClose\r\n")));
            if ( pHWObj )
                pHWObj->pFuncTbl->HWClose(pSerialHead->pHWHead);
            DEBUGMSG (ZONE_CLOSE, (TEXT("Returned from HWClose\r\n")));

            // And if thread was spun in open, kill it now.
            if ( pSerialHead->pHWObj->BindFlags & THREAD_AT_OPEN ) {
                DEBUGMSG (ZONE_CLOSE, (TEXT("COM_Close : Stopping Dispatch Thread\r\n")));
                StopDispatchThread( pSerialHead );
            }
        }

        // If this was the handle with access permission, remove pointer
        if ( pOpenHead == pSerialHead->pAccessOwner ) {
            DEBUGMSG(ZONE_INIT|ZONE_CLOSE,
                     (TEXT("COM_Close: Closed access owner handle\n\r"),
                      pOpenHead));

            pSerialHead->pAccessOwner = NULL;
        }

        // Remove the entry from the linked list
        RemoveEntryList(&pOpenHead->llist);

        // Free all data allocated in open
        if ( pOpenHead->CommEvents.hCommEvent )
            CloseHandle(pOpenHead->CommEvents.hCommEvent);
        LocalFree( pOpenHead );
*/
    } else {
        DEBUGMSG (ZONE_ERROR, (TEXT("!!Close of non-open serial port\r\n")));
        SetLastError(ERROR_INVALID_HANDLE);        
        RetCode = FALSE;
    }

    // OK, other inits/opens can go ahead.
    LeaveCriticalSection(&(pSerialHead->OpenCS));

    DEBUGMSG (ZONE_CLOSE|ZONE_FUNCTION, (TEXT("-ProcessExiting\r\n")));
    return(RetCode);
}

/*
 @doc EXTERNAL
 @func	BOOL | COM_Deinit | De-initialize serial port.
 @parm DWORD | pSerialHead | Context pointer returned from COM_Init
 *
 @rdesc None.
 */
BOOL
COM_Deinit(PHW_INDEP_INFO pSerialHead)
{
    DEBUGMSG (ZONE_INIT|ZONE_FUNCTION, (TEXT("+COM_Deinit\r\n")));

    if ( !pSerialHead ) {
        /* Can't do much without this */
        DEBUGMSG (ZONE_INIT|ZONE_ERROR,
                  (TEXT("COM_Deinit can't find pSerialHead\r\n")));
        SetLastError(ERROR_INVALID_HANDLE);
        return(FALSE);
    }

    // If we have an interrupt handler thread, kill it
    if ( pSerialHead->pHWObj->BindFlags & THREAD_IN_MDD ) {
        StopDispatchThread( pSerialHead );
    }

    /*
    ** Call close, if we have a user.  Note that this call will ensure that
    ** all users are out of the serial routines before it returns, so we can
    ** go ahead and free our internal memory.
    */
    if ( pSerialHead->OpenCnt ) {
        PLIST_ENTRY     pEntry;
        PHW_OPEN_INFO   pOpenHead;

        pEntry = pSerialHead->OpenList.Flink;
        while ( pEntry != &pSerialHead->OpenList ) {
            pOpenHead = CONTAINING_RECORD( pEntry, HW_OPEN_INFO, llist);
            pEntry = pEntry->Flink;  // advance to next 

            DEBUGMSG (ZONE_INIT | ZONE_CLOSE, (TEXT(" Deinit - Closing Handle 0x%X\r\n"),
                                               pOpenHead ));
            COM_Close(pOpenHead);
        }

⌨️ 快捷键说明

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