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

📄 communication.cpp

📁 PW芯片方案Flash ROM烧写程序
💻 CPP
📖 第 1 页 / 共 3 页
字号:
    {
        TRACE("CreateEvent failed\n");
        return 0;   // TODO: Notify parent that thread is dead
    }

    HANDLE hArray[NUMBER_OF_READER_EVENTS];

    hArray[reKILL] = pThis->m_hKillEvent;
    hArray[reREADER] = osReader.hEvent;
    hArray[reSTATUS] = osStatus.hEvent;

    // perform initial status checks
    pThis->CheckModemStatus();
    pThis->CheckComStatus();

    DWORD dwStoredFlags = -1;

    char *pBuffer[AMOUNT_TO_READ];

    DWORD dwCommEvent = 0;

    BOOL bWaitingOnRead = FALSE;
    BOOL bWaitingOnStatus = FALSE;

    BOOL bKeepAlive = TRUE;
    while (bKeepAlive)
    {
        //--------------------------------------------------------------------
        // If not connected, suspend thread (if not being killed).
        //--------------------------------------------------------------------
        if (FALSE == pThis->m_bConnected)
        {
            if (WAIT_OBJECT_0 == WaitForSingleObject(pThis->m_hKillEvent, 0))
            {
                break;
            }

            SuspendThread(pThis->m_hReaderThread);
            dwStoredFlags = -1;     // reset stored flags
        }

        //--------------------------------------------------------------------

        // if no read is outstanding, then issue another one
        if (FALSE == bWaitingOnRead)
        {
            bWaitingOnRead = pThis->AttemptToRead((char*)pBuffer, AMOUNT_TO_READ,
                                                  &osReader);
        }

        // If status flags have changed, then reset comm mask.
        // This will cause a pending WaitCommEvent to complete
        // and the resultant event flag will be NULL.
        if (dwStoredFlags != pThis->m_dwEventFlags)
        {
            dwStoredFlags = pThis->m_dwEventFlags;

            if (INVALID_HANDLE_VALUE != pThis->m_hPortHandle)
            {
                if (FALSE == SetCommMask(pThis->m_hPortHandle, dwStoredFlags))
                {
                    TRACE("SetCommMask failed\n");
                }
            }
        }

        // if no status check is outstanding, then issue another one
        if (FALSE == bWaitingOnStatus)
        {
            bWaitingOnStatus = pThis->AttemptToGetCommEvent(&osStatus, dwCommEvent);
        }

        // wait for pending operations to complete
        if (bWaitingOnStatus || bWaitingOnRead)
        {
            DWORD dwRes = WaitForMultipleObjects(NUMBER_OF_READER_EVENTS,
                                                 hArray,
                                                 FALSE,
                                                 STATUS_CHECK_TIMEOUT);
            switch(dwRes)
            {
                // read completed
                case WAIT_OBJECT_0 + reREADER:
                {
                    if (INVALID_HANDLE_VALUE != pThis->m_hPortHandle)
                    {
                        DWORD dwRead = 0;
                        if (FALSE == GetOverlappedResult(pThis->m_hPortHandle,
                                                         &osReader,
                                                         &dwRead,
                                                         FALSE))
                        {
                            TRACE("GetOverlappedResult failed Err=%d\n", GetLastError());
                        }
                        else
                        {
                            // read completed successfully
                            if (MAX_READ_BUFFER == dwRead)
                            {
                                TRACE("Read timed-out overlapped\n");
                            }

                            if (dwRead)
                            {
                                pThis->PutDataReadInQue((char*)pBuffer, dwRead);
                            }
                        }
                    }

                    bWaitingOnRead = FALSE;
                }
                break;

                // status completed
                case WAIT_OBJECT_0 + reSTATUS:
                {
                    if (INVALID_HANDLE_VALUE != pThis->m_hPortHandle)
                    {
                        DWORD dwSize;
                        if (FALSE == GetOverlappedResult(pThis->m_hPortHandle,
                                                         &osStatus,
                                                         &dwSize,
                                                         FALSE))
                        {
                            TRACE("GetOverlappedResult failed Err=%d\n", GetLastError());
                        }
                        else
                        {
                            // status check completed successfully
                            pThis->ReportStatusEvent(dwCommEvent);
                        }
                    }

                    bWaitingOnStatus = FALSE;
                }
                break;

                // thread exit event
                case WAIT_OBJECT_0 + reKILL:
                    bKeepAlive = FALSE;
                    break;

                case WAIT_TIMEOUT:
                    // timeouts are not reported because they happen too often.
                    // Take this opportunity to do a modem status check and a
                    // comm status check.
                    pThis->CheckModemStatus();
                    pThis->CheckComStatus();
                    break;
                
                case WAIT_FAILED:
                    {
                        DWORD dwError = GetLastError();
                        ASSERT(1);
                    }
                    break;

                default:
                    TRACE("Unkown value from WaitForMultipleObjects\n");
                    break;
            }
        }
        else
        {
            if (WAIT_OBJECT_0 == WaitForSingleObject(pThis->m_hKillEvent, 0))
            {
                bKeepAlive = FALSE;
            }
        }
    }

    CloseHandle(osReader.hEvent);
    CloseHandle(osStatus.hEvent);

    return 0;
}

typedef enum
{
    whKILL,
    whOVERLAPPED
} HWREVENTS;
#define NUMBER_OF_HWR_EVENTS     (2)
extern BOOL afxTraceEnabled;

//----------------------------------------------------------------------------
// Private method (called by writer thread).
//----------------------------------------------------------------------------
void CCommunication::HandleWriteRequest(OVERLAPPED *posWrite)
{
    HANDLE hArray[NUMBER_OF_HWR_EVENTS];
    hArray[whOVERLAPPED] = posWrite->hEvent;
    hArray[whKILL] = m_hKillEvent;

    // Get any data to write from byte array and copy into local byte array
    // for sending it.

    int nChunkSize = 0;
    CByteArray byteArray;
    {
        CMakeSafe ms(&m_MakeSafeWriterArray);   // make access to que thread-safe

        nChunkSize = m_WriterByteArray.GetSize();
        if (0 == nChunkSize)
        {
            return;     // no data to write
        }

        if (nChunkSize > MAX_WRITE_SIZE)
        {
            nChunkSize = MAX_WRITE_SIZE;

            byteArray.SetSize(nChunkSize);
            CopyMemory((void*)byteArray.GetData(), m_WriterByteArray.GetData(),
                       nChunkSize);

            int nUnusedSize = m_WriterByteArray.GetSize() - nChunkSize;
            CopyMemory((void*)m_WriterByteArray.GetData(),
                       (void*)((char*)m_WriterByteArray.GetData() + nChunkSize),
                       nUnusedSize);

            m_WriterByteArray.SetSize(nUnusedSize);

            ::SetEvent(m_hWriteDataEvent);
        }
        else
        {
            byteArray.Copy(m_WriterByteArray);      // copy data to local array
            m_WriterByteArray.RemoveAll();          // empty original array
        }
    }

    char *pData = (char*)byteArray.GetData();
    DWORD dwSize = byteArray.GetSize();
    DWORD dwSizeRemaining = dwSize;
    BOOL bOk = TRUE;

    while (dwSizeRemaining && bOk)
    {
        // issue write
        DWORD dwWritten = 0;
#ifdef _MAX_DEBUG
        if (dwSize > 1536)
        {
            ASSERT(0);
        }
        TRACE("Writing %d bytes\n", dwSize);
#endif
        if (!WriteFile(m_hPortHandle, pData, dwSize, &dwWritten, posWrite))
        {
            DWORD dwError = GetLastError();
            if (ERROR_IO_PENDING == dwError)
            { 
                // write is delayed
                DWORD dwRes = WaitForMultipleObjects(NUMBER_OF_HWR_EVENTS,
                                                     hArray,
                                                     FALSE,
                                                     INFINITE);
                switch(dwRes)
                {
                    // write event set
                    case WAIT_OBJECT_0 + whOVERLAPPED:
                        SetLastError(ERROR_SUCCESS);

                        if (INVALID_HANDLE_VALUE == m_hPortHandle)
                        {
                            bOk = FALSE;
                            break;
                        }

                        if (FALSE == GetOverlappedResult(m_hPortHandle,
                                                         posWrite,
                                                         &dwWritten,
                                                         FALSE))
                        {
                            TRACE("GetOverlappedResult failed Err=%d\n", GetLastError());
                        }

                        if (dwWritten != dwSize)
                        {
                            TRACE("Buffer full. Wrote %d of %d bytes\n", dwWritten, dwSize);
                        }
                        break;

                    // thread exit event set
                    case WAIT_OBJECT_0 + whKILL:
                        bOk = FALSE;
                        break;

                    case WAIT_TIMEOUT:
                        TRACE("WaitForMultipleObjects timed-out\n");
                        bOk = FALSE;
                        break;

                    default:
                        TRACE("Unknown value from WaitForMultipleObjects\n");
                        bOk = FALSE;
                        break;
                }
            }
            else
            {
                TRACE("(not pending) WriteFile failed\n");

                // We must clear the device's error flag to enable additional I/O operations.
                CheckComStatus();

                bOk = FALSE;
            }
        }
        else
        {
            if (dwWritten != dwSize)
            {
                TRACE("(not pending) Buffer full. Wrote %d of %d bytes\n", dwWritten, dwSize);
            }
        }

        dwSizeRemaining -= dwWritten;
        pData += dwWritten;
    }

    CMakeSafe ms(&m_MakeSafeWriterArray);   // make access to que thread-safe
    if (0 == m_WriterByteArray.GetSize())
    {
        ::SetEvent(m_hWriteBufferEmptyEvent);   // writer buffer is empty
    }

    return;
}

typedef enum
{
    weNEWDATA,
    weKILL
} WRITEREVENTS;
#define NUMBER_OF_WRITER_EVENTS     (2)
//----------------------------------------------------------------------------
// Static private thread procedure.
//----------------------------------------------------------------------------
DWORD WINAPI CCommunication::WriterThreadProc(LPVOID pParam)
{
    CCommunication *pThis = (CCommunication*)pParam;

    OVERLAPPED osWrite = {0};
    osWrite.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
    if (0 == osWrite.hEvent)
    {
        TRACE("CreateEvent failed\n");
        return 0;   // TODO: Notify parent that thread is dead
    }
    
    HANDLE hArray[NUMBER_OF_WRITER_EVENTS];

    hArray[weNEWDATA] = pThis->m_hWriteDataEvent;
    hArray[weKILL] = pThis->m_hKillEvent;

    BOOL bKeepAlive = TRUE;
    while (bKeepAlive)
    {
        //--------------------------------------------------------------------
        // If not connected, suspend thread (if not being killed).
        //--------------------------------------------------------------------
        if (FALSE == pThis->m_bConnected)
        {
            if (WAIT_OBJECT_0 == WaitForSingleObject(pThis->m_hKillEvent, 0))
            {
                break;
            }

            SuspendThread(pThis->m_hWriterThread);
        }

        DWORD dwRes = WaitForMultipleObjects(NUMBER_OF_WRITER_EVENTS,
                                             hArray,
                                             FALSE,
                                             WRITE_CHECK_TIMEOUT);
        switch(dwRes)
        {
            case WAIT_TIMEOUT:
                break;

            case WAIT_FAILED:
                TRACE("WaitForMultipleObjects failed\n");
                break;

            // write request event
            case WAIT_OBJECT_0 + weNEWDATA:
                pThis->HandleWriteRequest(&osWrite);
                break;

            // thread exit event
            case WAIT_OBJECT_0 + weKILL:
                bKeepAlive = FALSE;
                break;
        }
    }

    CloseHandle(osWrite.hEvent);
    return 0;
}

⌨️ 快捷键说明

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