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

📄 mdd.c

📁 Windows CE操作系统中适用的蓝牙驱动程序
💻 C
📖 第 1 页 / 共 5 页
字号:

            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\r\n")));
                SetLastError(ERROR_INVALID_HANDLE);
                break;
            }
        }
    }

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

    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 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("DTR_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);
        }
    }

    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 Total Timeout
    ULONG               Ticks;          // Time for a loop.
    ULONG               TimeSpent = 0;  // How much time have we been waiting?
    ULONG               WaitReturn;
    ULONG               PutRet;

    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\r\n"),
                  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 CritSec %x.\r\n"),
                           &(pSerialHead->TransmitCritSec1)));

    pSerialHead->TxBytesPending = NumberOfBytes;

    TotalTimeout = pSerialHead->CommTimeouts.WriteTotalTimeoutMultiplier*NumberOfBytes +
                   pSerialHead->CommTimeouts.WriteTotalTimeoutConstant;

    Ticks = GetTickCount();

    while ( 1 ) {
        /* Check used flag to see if there are no users the device.
         */
        if ( !pSerialHead->OpenCnt ) {
            break;
        }

        if ( NumberOfBytes ) {
            if ( pSerialHead->DCB.fRtsControl == RTS_CONTROL_TOGGLE ) {
                pFuncTbl->HWSetRTS(pHWHead);
            }

            // Don't call PutBytes if we are flowed off.
            if ( !pSerialHead->StopXmit ) {
                PutRet = pFuncTbl->HWPutBytes(pHWHead, pSourceBytes, NumberOfBytes,
                                              &BytesWritten);
            } else {
                // If we are flowed off, then no bytes were written.  For now, we
                // will set PutRet to 10 to cause polling for a flow-on condition.
                // We could change this so that XON generates a TX Event and then
                // we could wait forever (i.e. PutRet = 0).
                BytesWritten = 0;
                PutRet = 10;
            }

        } else {
            break;
        }

        pSerialHead->TxBytes += BytesWritten;

        if ( BytesWritten ) {
            TotalWritten += BytesWritten;
            NumberOfBytes -= BytesWritten;
            pSourceBytes += BytesWritten;

            DEBUGMSG (ZONE_WRITE,
                      (TEXT("COM_Write: wrote %d, remaining %d\r\n"),
                       BytesWritten, NumberOfBytes));
            BytesWritten    = 0;
        }

        // If data still left, wait until the Dispatch thread has
        // signalled that a transmit event has occurred and try again.
        if ( NumberOfBytes ) {
            DEBUGMSG (ZONE_WRITE,
                      (TEXT("COM_Write awaiting xmit event, %d bytes remain\r\n"),
                       NumberOfBytes));

            // Calculate the timeout
            if ( !TotalTimeout ) {
                Timeout = (ULONG)-1;
            } else if ( TimeSpent >= TotalTimeout ) {
                DEBUGMSG (ZONE_WARN,
                          (TEXT("COM_Write - Timeout1 (%d written, %d remain)\r\n"),
                           TotalWritten, NumberOfBytes));
                break;
            } else {
                Timeout = TotalTimeout - TimeSpent;
            }
            if ( PutRet ) {
                // If HWPutBytes returns true, then we need
                // to call back (after a pdd specified interval) to
                // see if the flow control condition has
                // been removed.
                Timeout = (Timeout > PutRet) ? PutRet : Timeout;
            }

            Ticks = GetTickCount();
            DEBUGMSG (ZONE_WRITE,
                      (TEXT("COM_WRITE: About to wait for %dms\r\n"),
                       Timeout));

            WaitReturn = WaitForSingleObject(pSerialHead->hTransmitEvent, Timeout);

            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->fAbortTransmit ) {
                DEBUGMSG(ZONE_USR_READ,(TEXT("COM_Write - Aborting write\r\n")));
                break;
            }

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

            if ( WaitReturn == WAIT_TIMEOUT ) {
                // If we were told to wait by the pdd, then loop again
                // otherwise it is a write timeout
                if ( ! PutRet ) {
                    DEBUGMSG (ZONE_WARN,
                              (TEXT("COM_Write - Timeout2 (%d written, %d remain)\r\n"),
                               TotalWritten, NumberOfBytes));
                    break;
                }

            }
        }

        pSerialHead->TxBytesPending = NumberOfBytes;
    }

    LeaveCriticalSection(&(pSerialHead->TransmitCritSec1));

    DEBUGMSG (ZONE_WRITE|ZONE_FUNCTION,
              (TEXT("COM_Write released CritSec: %x. Exiting\r\n"),
               &(pSerialHead->TransmitCritSec1)));

    /* OK, the Transmitter has gone empty.
     */
    EvaluateEventFlag(pSerialHead, EV_TXEMPTY);

    if ( pSerialHead->DCB.fRtsControl == RTS_CONTROL_TOGGLE ) {
        pFuncTbl->HWClearRTS(pHWHead);
    }

    COM_DEC_USAGE_CNT(pOpenHead);
    DEBUGMSG (ZONE_WRITE|ZONE_FUNCTION,
              (TEXT("-COM_WRITE, returning %d\r\n"),TotalWritten));
    return (TotalWritten);
}


ULONG
COM_Seek(
        HANDLE  pHead,
        LONG    Position,
        DWORD   Type
        )
{
    return (ULONG)-1;
}

/*
 @doc EXTERNAL
 @func	BOOL | COM_PowerUp | Turn power on to serial device
 * Exported to users.
 @rdesc This routine returns a status of 1 if unsuccessful and 0 otherwise.
 */
BOOL
COM_PowerUp(
           HANDLE      pHead       /*@parm Handle to device. */
           )
{
    PHW_INDEP_INFO  pHWIHead    = (PHW_INDEP_INFO)pHead;
    PHWOBJ          pHWObj;

    PREFAST_ASSERT (pHWIHead);
    pHWObj = (PHWOBJ)pHWIHead->pHWObj;

    PREFAST_ASSERT (pHWObj);

    return (pHWObj->pFuncTbl->HWPowerOn(pHWIHead->pHWHead));
}

/*
 @doc EXTERNAL
 @func	BOOL | COM_PowerDown | Turns off power to serial device.
 * Exported to users.
 @rdesc This routine returns a status of 1 if unsuccessful and 0 otherwise.
 */
BOOL
COM_PowerDown(
             HANDLE      pHead       /*@parm Handle to device. */
             )
{
    PHW_INDEP_INFO          pHWIHead    = (PHW_INDEP_INFO)pHead;

    if ( pHWIHead ) {
        PHWOBJ  pHWObj = (PHWOBJ)pHWIHead->pHWObj;
        return (pHWObj->pFuncTbl->HWPowerOff(pHWIHead->pHWHead));
    } else {
        return (1);
    }
}



/*
 @doc INTERNAL
 @func	ULONG | SerialGetDroppedByteNumber | Returns Number of dropped b

⌨️ 快捷键说明

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