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

📄 mdd.c

📁 我自己编译的armv4i wince60模拟器的bps源文件,已经验证可以使用,欢迎下载
💻 C
📖 第 1 页 / 共 5 页
字号:

            // 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);
            }

            /* Sleep, let threads finish */
            Sleep(100);
        }
        if ( i==20 )
            DEBUGMSG(ZONE_CLOSE|ZONE_INIT|ZONE_ERROR,
                     (TEXT("SERDMA_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("SERDMA_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("SERDMA_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("-SERDMA_Close\r\n")));

    return RetCode;
}

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

    if ( !pSerialHead ) {
        /* Can't do much without this */
        DEBUGMSG (ZONE_INIT|ZONE_ERROR,
                  (TEXT("SERDMA_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 ));
            SERDMA_Close(pOpenHead);
        }
    }

    /* Free our resources */
    if ( pSerialHead->hKillDispatchThread )
        CloseHandle(pSerialHead->hKillDispatchThread);
    if ( pSerialHead->hReadEvent )
        CloseHandle(pSerialHead->hReadEvent);
    if ( pSerialHead->hReceiveBufferEmpty )
        CloseHandle(pSerialHead->hReceiveBufferEmpty);
    if ( pSerialHead->hReceiveDataReady )
        CloseHandle(pSerialHead->hReceiveDataReady);

    DeleteCriticalSection(&(pSerialHead->ReceiveCritSec1));
    DeleteCriticalSection(&(pSerialHead->OpenCS));

    /* 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("-SERDMA_Deinit\r\n")));
    return TRUE;
}

/*
   @doc EXTERNAL
   @func        ULONG | SERDMA_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
SERDMA_Read(
        HANDLE      pHead,          //@parm [IN]         HANDLE returned by SERDMA_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;
    PVOID           pHWHead;
    ULONG           BytesRead = 0; // this initial value is returned if there is a timeout
    int             ReadTries;
    ULONG           Ticks;
    ULONG           Timeout;
    ULONG           IntervalTimeout;    // The interval timeout
    ULONG           AddIntervalTimeout;
    ULONG           TotalTimeout;       // The Total Timeout
    ULONG           TimeSpent = 0;      // How much time have we been waiting?

    DEBUGMSG (ZONE_USR_READ|ZONE_FUNCTION,
              (TEXT("+SERDMA_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("SERDMA_Read, device not open\r\n") ));
        SetLastError (ERROR_INVALID_HANDLE);
        return (ULONG)-1;
    }
    pFuncTbl       = pSerialHead->pHWObj->pFuncTbl;
    pHWHead        = pSerialHead->pHWHead;

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

    if ( BufferLength > DMA_PACKET_SIZE) {
        SetLastError(ERROR_INVALID_PARAMETER);
        return (ULONG)-1;
    }

    if (pTargetBuffer == NULL) {
        BytesRead = (ULONG)-1;
        SetLastError(ERROR_INVALID_PARAMETER);
        return (ULONG)-1;
    }

    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));

    for (ReadTries=0;ReadTries<2;ReadTries++) {
        if (pSerialHead->RxDataReady) {
            // A packet is already ready.  Copy it to the caller's buffer
            BytesRead = min(BufferLength, pSerialHead->ReceivePacketBuffer.u.PacketLength);
            if (!CeSafeCopyMemory(pTargetBuffer,
                    pSerialHead->ReceivePacketBuffer.u.PacketContents, BytesRead)) {
                DEBUGMSG(ZONE_USR_READ|ZONE_ERROR,
                         (TEXT("SERDMA_Read: Buffer error\n\r")));
                SetLastError(ERROR_INVALID_PARAMETER);
                BytesRead = -1;
                break;
            }

            // Indicate that the ReceivePacketBuffer is available again
            pSerialHead->RxDataReady = 0;
            SetEvent(pSerialHead->hReceiveBufferEmpty);
            break;
        }

        // Else no packet is ready - wait until one arrives or we time out

        // 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 ) {
            // On first character we only use total timeout
            Timeout = INFINITE;
        } else {
            // Total timeout is valid
            if ( TimeSpent >= TotalTimeout ) {
                // Timed out.
                break;
            }
            Timeout = TotalTimeout - TimeSpent;
            // On first byte we only use interval timeout
        }
        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;
        }

        // 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("SERDMA_Read - Aborting read\r\n")));
            break;
        }

        if ( !pSerialHead->OpenCnt ) {
            DEBUGMSG(ZONE_USR_READ|ZONE_ERROR,
                     (TEXT("SERDMA_Read - device was closed\n\r")));
            SetLastError(ERROR_INVALID_HANDLE);
            break;
        }
    }
    LeaveCriticalSection(&(pSerialHead->ReceiveCritSec1));
    COM_DEC_USAGE_CNT(pOpenHead);

    DEBUGMSG (ZONE_USR_READ|ZONE_FUNCTION,
              (TEXT("-SERDMA_Read: returning %d\r\n"),
               BytesRead));

    return BytesRead;
}

/*
   @doc EXTERNAL
   @func ULONG | SERDMA_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
SERDMA_Write(HANDLE pHead,      /*@parm [IN]  HANDLE returned by SERDMA_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;
    PHW_VTBL        pFuncTbl;
    PHWOBJ          pHWObj;
    PVOID           pHWHead;
    ULONG           Len;
    ULONG           ulRet = -1;
    DMA_PACKET_BUFFER *pTransmitPacketBuffer = NULL;

    // bugbug:  COM_Write in the SMDK2410 version begins with a Sleep(10).  Remove it!

    DEBUGMSG (ZONE_WRITE|ZONE_FUNCTION,
              (TEXT("+SERDMA_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("SERDMA_Write, device not open\r\n") ));
        SetLastError (ERROR_INVALID_HANDLE);
        return (ULONG)-1;
    }

⌨️ 快捷键说明

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