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

📄 mdd.c

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

    /* Free our resources */
    if ( pSerialHead->hSerialEvent )
        CloseHandle(pSerialHead->hSerialEvent);
    if ( pSerialHead->hKillDispatchThread )
        CloseHandle(pSerialHead->hKillDispatchThread);
    if ( pSerialHead->hTransmitEvent )
        CloseHandle(pSerialHead->hTransmitEvent);
    if ( pSerialHead->hReadEvent )
        CloseHandle(pSerialHead->hReadEvent);

    DeleteCriticalSection(&(pSerialHead->ReceiveCritSec1));
    DeleteCriticalSection(&(pSerialHead->TransmitCritSec1));
    DeleteCriticalSection(&(pSerialHead->RxBufferInfo.CS));
    DeleteCriticalSection(&(pSerialHead->TxBufferInfo.CS));
    DeleteCriticalSection(&(pSerialHead->OpenCS));

    if ( pSerialHead->RxBufferInfo.RxCharBuffer )
        LocalFree(pSerialHead->RxBufferInfo.RxCharBuffer);

    /* Now, call HW specific deinit function */
    if ( pSerialHead->pHWObj && pSerialHead->pHWObj->pFuncTbl ) {
        DEBUGMSG (ZONE_INIT, (TEXT("About to call HWDeinit\r\n")));
        pSerialHead->pHWObj->pFuncTbl->HWDeinit(pSerialHead->pHWHead);
        DEBUGMSG (ZONE_INIT, (TEXT("Returned from HWDeinit\r\n")));
    }

    LocalFree(pSerialHead);

    DEBUGMSG (ZONE_INIT|ZONE_FUNCTION, (TEXT("-COM_Deinit\r\n")));
    return(TRUE);
}


/*
   @doc EXTERNAL
   @func	ULONG | COM_Read | Allows application to receive characters from
   *	serial port. This routine sets the buffer and bufferlength to be used
   *	by the reading thread. It also enables reception and controlling when
   *	to return to the user. It writes to the referent of the fourth argument
   *	the number of bytes transacted. It returns the status of the call.
   *
   *	Exported to users.
   @rdesc This routine returns: -1 if error, or number of bytes read.
   */
ULONG
COM_Read(
        HANDLE      pHead,          //@parm [IN]	 HANDLE returned by COM_Open   
        PUCHAR      pTargetBuffer,  //@parm [IN,OUT] Pointer to valid memory.	  
        ULONG       BufferLength    //@parm [IN]	 Size in bytes of pTargetBuffer.
        )
{
    PHW_OPEN_INFO   pOpenHead = (PHW_OPEN_INFO)pHead;
    PHW_INDEP_INFO  pSerialHead = pOpenHead->pSerialHead;
    PHW_VTBL        pFuncTbl       = pSerialHead->pHWObj->pFuncTbl;
    PVOID           pHWHead        = pSerialHead->pHWHead;
    ULONG           Ticks;
    ULONG           Timeout;
    ULONG           BytesRead = 0;
    ULONG           IntervalTimeout;    // The interval timeout
	ULONG			AddIntervalTimeout;
    ULONG           TotalTimeout;       // The Total Timeout
    ULONG           TimeSpent = 0;      // How much time have we been waiting?
    ULONG           Len;

    DEBUGMSG (ZONE_USR_READ|ZONE_FUNCTION,
              (TEXT("+COM_READ(0x%X,0x%X,%d)\r\n"),
               pHead, pTargetBuffer, BufferLength));

    // Check to see that the call is valid.
    if ( !pSerialHead || !pSerialHead->OpenCnt ) {
        DEBUGMSG (ZONE_USR_READ|ZONE_ERROR,
                  (TEXT("COM_READ, device not open\r\n") ));
        SetLastError (ERROR_INVALID_HANDLE);
        return(ULONG)-1;
    }

    // Make sure the caller has access permissions
    if ( !(pOpenHead->AccessCode & GENERIC_READ) ) {
        DEBUGMSG(ZONE_USR_READ|ZONE_ERROR,
                 (TEXT("COM_Read: Access permission failure x%X\n\r"),
                  pOpenHead->AccessCode));
        SetLastError (ERROR_INVALID_ACCESS);
        return(ULONG)-1;
    }

#ifdef DEBUG
    if ( IsBadWritePtr(pTargetBuffer, BufferLength) ) {
        BytesRead = (ULONG)-1;
        SetLastError(ERROR_INVALID_PARAMETER);        
        return(ULONG)-1;
    }
#endif

    COM_INC_USAGE_CNT(pOpenHead);

    /* Practice safe threading.
     */
    EnterCriticalSection(&(pSerialHead->ReceiveCritSec1));

    /* Compute total time to wait. Take product and add constant.
     */
    if ( MAXDWORD != pSerialHead->CommTimeouts.ReadTotalTimeoutMultiplier ) {
        TotalTimeout = pSerialHead->CommTimeouts.ReadTotalTimeoutMultiplier*BufferLength +
                       pSerialHead->CommTimeouts.ReadTotalTimeoutConstant;
		// Because we are using FIFO and water level is set to 8, we have to do following
		AddIntervalTimeout=pSerialHead->CommTimeouts.ReadTotalTimeoutMultiplier*8;
    } else {
        TotalTimeout = pSerialHead->CommTimeouts.ReadTotalTimeoutConstant;
		AddIntervalTimeout=0;
    }
    IntervalTimeout = pSerialHead->CommTimeouts.ReadIntervalTimeout;
	if (IntervalTimeout < MAXDWORD  - AddIntervalTimeout) {
		IntervalTimeout +=AddIntervalTimeout;
	};

    DEBUGMSG (ZONE_USR_READ, (TEXT("TotalTimeout:%d\r\n"), TotalTimeout));

    while ( BufferLength ) {
        DEBUGMSG (ZONE_USR_READ,
                  (TEXT("Top of Loop Fifo(R=%d,W=%d,L=%d,BA=%d)\r\n"),
                   RxRead(pSerialHead), RxWrite(pSerialHead),
                   RxLength(pSerialHead),
                   RxBytesAvail(pSerialHead)));
        if ( RxBytesAvail(pSerialHead) ) {
            RxEnterCS(pSerialHead);
            // Copy the data over
            // This only copies the continous portion, This will cause a loop
            // if the receive data spans the end of the buffer.
            Len = MIN(RxBytesAvail(pSerialHead),
                      RxLength(pSerialHead)-RxRead(pSerialHead));
            Len = MIN(Len, BufferLength);
            DEBUGMSG (ZONE_USR_READ, (TEXT("About to copy %d bytes\r\n"), Len));
            memcpy (pTargetBuffer, RxBuffRead(pSerialHead), Len);
            // Update Fifo info
            RxRead(pSerialHead) += Len;
            RxRead(pSerialHead) %= RxLength(pSerialHead);

            // Update all the pointers.
            BufferLength -= Len;
            pTargetBuffer += Len;
            BytesRead += Len;
            RxLeaveCS(pSerialHead);
        } else {
            // Wait for a serial event?
            if ( (IntervalTimeout == MAXDWORD) && (TotalTimeout == 0) ) {
                // For some reason this means don't wait.
                break;
            }

            if ( (IntervalTimeout == 0) && (TotalTimeout == 0) ) {
                // Not completely clear but this could mean wait
                // for ever
                Timeout = INFINITE;
            } else if ( TotalTimeout == 0 ) {
                if ( !BytesRead ) {
                    // On first character we only use total timeout
                    Timeout = INFINITE;
                } else {
                    // No total timeout in use.	 Just use interval timer
                    Timeout = IntervalTimeout;
                }
            } else {
                // Total timeout is valid
                if ( TimeSpent >= TotalTimeout ) {
                    // Timed out.
                    break;
                }
                Timeout = TotalTimeout - TimeSpent;
                // On first byte we only use interval timeout
                // on subsequent we use minimum of Interval and Timeout
                if ( BytesRead && (IntervalTimeout != 0) ) {
                    Timeout = MIN(Timeout, IntervalTimeout);
                }

                // Yet another special case.
                if ( BytesRead &&
                     (MAXDWORD == pSerialHead->CommTimeouts.ReadTotalTimeoutMultiplier) &&
                     (MAXDWORD == IntervalTimeout) ) {
                    // If Interval==MAXDWORD, Mult=MAXDWORD, 0<Const<MAXDWORD
                    // then return immediately if there is data.
                    // else wait up to Const time for data
                    break;
                }
            }
            Ticks = GetTickCount();
            DEBUGMSG (ZONE_USR_READ, (TEXT("About to wait %dms\r\n"), Timeout));

            pSerialHead->fAbortRead = 0;
            if ( WAIT_TIMEOUT == WaitForSingleObject (pSerialHead->hReadEvent,
                                                      Timeout) ) {
                // Timeout
                break;
            }
            // Since ticks is a ULONG this handles wrap.
            Ticks = GetTickCount() - Ticks;
            TimeSpent += Ticks;

            // In the absense of WaitForMultipleObjects, we use flags to
            // handle errors/aborts. Check for aborts or asynchronous closes.
            if ( pSerialHead->fAbortRead ) {
                DEBUGMSG(ZONE_USR_READ,(TEXT("COM_Read - Aborting read\r\n")));
                break;
            }

            if ( !pSerialHead->OpenCnt ) {
                DEBUGMSG(ZONE_USR_READ|ZONE_ERROR,
                         (TEXT("COM_Read - device was closed\n\r")));
                SetLastError(ERROR_INVALID_HANDLE);
                break;
            }
        }

        // Are we below the SW flow control limits?
        if ( pSerialHead->DCB.fInX && pSerialHead->SentXoff &&
             (pSerialHead->DCB.XoffLim <
              (RxLength(pSerialHead) - RxBytesAvail(pSerialHead))) ) {
            PHWOBJ  pHWObj  = pSerialHead->pHWObj;

            DEBUGMSG (ZONE_FLOW, (TEXT("Sending XON\r\n")));
            pSerialHead->SentXoff = 0;
            if ( !pSerialHead->DCB.fTXContinueOnXoff ) {
                pSerialHead->StopXmit = 0;
            }
            pHWObj->pFuncTbl->HWXmitComChar(pSerialHead->pHWHead,
                                            pSerialHead->DCB.XonChar);
        }

        // Are we below the HW flow control limits?
        if ( 2*RxBytesAvail(pSerialHead) < RxLength(pSerialHead) ) {
            // When buffer is less then 1/2 full we set RTS/DTR
            if ( pSerialHead->RtsFlow &&
                 (pSerialHead->DCB.fRtsControl == RTS_CONTROL_HANDSHAKE) ) {
                DEBUGMSG (ZONE_USR_READ|ZONE_FLOW,
                          (TEXT("RTS_CONTROL_HANDSHAKE Setting RTS\r\n")));
                pSerialHead->RtsFlow = 0;
                pFuncTbl->HWSetRTS(pHWHead);
            }
            if ( pSerialHead->DtrFlow && 
                 (pSerialHead->DCB.fDtrControl == DTR_CONTROL_HANDSHAKE) ) {
                DEBUGMSG (ZONE_USR_READ|ZONE_FLOW,
                          (TEXT("DTR_CONTROL_HANDSHAKE Setting DTR\r\n")));
                pSerialHead->DtrFlow = 0;
                pFuncTbl->HWSetDTR(pHWHead);
            }
        }

    }

    DEBUGMSG (ZONE_USR_READ, (TEXT("ReceiveBytes exiting\r\n")));

    LeaveCriticalSection(&(pSerialHead->ReceiveCritSec1));

    DEBUGMSG (ZONE_USR_READ|ZONE_FUNCTION,
              (TEXT("-COM_READ: returning %d (total %d, dropped %d,%d)\r\n"),
               BytesRead, pSerialHead->RxBytes, pSerialHead->DroppedBytesMDD,pSerialHead->DroppedBytesPDD));

    COM_DEC_USAGE_CNT(pOpenHead);

    return(BytesRead);
}

/*
   @doc EXTERNAL
   @func ULONG | COM_Write | Allows application to transmit bytes to the serial port. Exported to users.
   *
   @rdesc It returns the number of bytes written or -1 if error.
   *
   *
   */
ULONG
COM_Write(HANDLE pHead,         /*@parm [IN]  HANDLE returned by COM_Open.*/
          PUCHAR pSourceBytes,  /*@parm [IN]  Pointer to bytes to be written.*/
          ULONG  NumberOfBytes  /*@parm [IN]  Number of bytes to be written. */
         )
{
    PHW_OPEN_INFO   pOpenHead = (PHW_OPEN_INFO)pHead;
    PHW_INDEP_INFO  pSerialHead = pOpenHead->pSerialHead;
    ULONG               BytesWritten   = 0;
    ULONG               TotalWritten   = 0;
    PHWOBJ              pHWObj         = NULL;
    PVOID               pHWHead        = NULL;
    PHW_VTBL            pFuncTbl       = NULL;
    ULONG               TotalTimeout;   // The Total Timeout
    ULONG               Timeout;        // The Timeout value actually used
    ULONG               WaitReturn;

	Sleep(10);
    DEBUGMSG (ZONE_WRITE|ZONE_FUNCTION,
              (TEXT("+COM_WRITE(0x%X, 0x%X, %d)\r\n"), pHead,
               pSourceBytes, NumberOfBytes));       


    // Check validity of handle
    if ( !pSerialHead || !pSerialHead->OpenCnt ) {
        DEBUGMSG (ZONE_WRITE|ZONE_ERROR,
                  (TEXT("COM_WRITE, device not open\r\n") ));
        SetLastError (ERROR_INVALID_HANDLE);
        return(ULONG)-1;
    }

    // Make sure the caller has access permissions
    if ( !(pOpenHead->AccessCode & GENERIC_WRITE) ) {
        DEBUGMSG(ZONE_USR_READ|ZONE_ERROR,
                 (TEXT("COM_Write: Access permission failure x%X\n\r"),
                  pOpenHead->AccessCode));
        SetLastError (ERROR_INVALID_ACCESS);
        return(ULONG)-1;
    }

#ifdef DEBUG
    if ( IsBadReadPtr(pSourceBytes, NumberOfBytes) ) {
        DEBUGMSG (ZONE_WRITE|ZONE_ERROR,
                  (TEXT("COM_WRITE, bad read pointer\r\n") ));
        SetLastError(ERROR_INVALID_PARAMETER);
        return(ULONG)-1;
    }
#endif

    COM_INC_USAGE_CNT(pOpenHead);

    pHWObj   = pSerialHead->pHWObj;
    pHWHead  = pSerialHead->pHWHead;
    pFuncTbl = pHWObj->pFuncTbl;

    pSerialHead->fAbortTransmit = 0;
    // Clear any pending event
    WaitForSingleObject(pSerialHead->hTransmitEvent,0);

    /* Lock out other threads from messing with these pointers.
     */
    DEBUGMSG (ZONE_WRITE, (TEXT("COM_Write wait for CritSec %x.\r\n"),
                           &(pSerialHead->TransmitCritSec1)));
    EnterCriticalSection(&(pSerialHead->TransmitCritSec1));
    DEBUGMSG (ZONE_WRITE, (TEXT("COM_Write Got Cr

⌨️ 快捷键说明

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