READSTAT.C 9.73 KB
/*-----------------------------------------------------------------------------
    This is a part of the Microsoft Source Code Samples. 
    Copyright (C) 1995 Microsoft Corporation.
    All rights reserved. 
    This source code is only intended as a supplement to 
    Microsoft Development Tools and/or WinHelp documentation.
    See these sources for detailed information regarding the 
    Microsoft samples programs.

    MODULE: ReadStat.c

    PURPOSE: 
    线程过程负责读取通信端口,报告状态事件,报告状态消息,并定期更新状态控制

    FUNCTIONS:
        ReaderAndStatusProc - Thread procedure does the work here
 
-----------------------------------------------------------------------------*/

#include <windows.h>
#include "mttty.h"

#define AMOUNT_TO_READ          512
#define NUM_READSTAT_HANDLES    4

/*-----------------------------------------------------------------------------

FUNCTION: ReaderAndStatusProc(LPVOID)

PURPOSE: 线程功能控制通信端口读取、通信端口状态检查和状态消息。

PARMATERS:
    lpV - 4 byte value contains the tty child window handle

RETURN: always 1

COMMENTS: Waits on various events in the applications to handle
          port reading, status checking, status messages and modem status.

HISTORY:   Date:      Author:     Comment:
           10/27/95   AllenD      Wrote it
           11/21/95   AllenD      Incorporated status message heap

-----------------------------------------------------------------------------*/
DWORD WINAPI ReaderAndStatusProc(LPVOID lpV)
{
    OVERLAPPED osReader = {0};  // overlapped structure for read operations
    OVERLAPPED osStatus = {0};  // overlapped structure for status operations
    HANDLE     hArray[NUM_READSTAT_HANDLES];
    DWORD      dwStoredFlags = 0xFFFFFFFF;      // local copy of event flags
    DWORD      dwCommEvent;     // result from WaitCommEvent
    DWORD      dwOvRes;         // result from GetOverlappedResult
    DWORD 	   dwRead;          // bytes actually read
    DWORD      dwRes;           // result from WaitForSingleObject
    BOOL       fWaitingOnRead = FALSE;
    BOOL       fWaitingOnStat = FALSE;
    BOOL       fThreadDone = FALSE;
    char   	   lpBuf[AMOUNT_TO_READ];
	char   	   lpBuf_first[AMOUNT_TO_READ];
	char			Flashed_percent;
    HWND  	   hTTY;

    hTTY = (HANDLE) lpV;

    //
    // create two overlapped structures, one for read events
    // and another for status events
    //
    osReader.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
    if (osReader.hEvent == NULL)
        ErrorInComm("CreateEvent (Reader Event)");

    osStatus.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
    if (osStatus.hEvent == NULL)
        ErrorInComm("CreateEvent (Status Event)");

    //
    // We want to detect the following events:
    //   Read events (from ReadFile)
    //   Status events (from WaitCommEvent)
    //   Status message events (from our UpdateStatus)
    //   Thread exit evetns (from our shutdown functions)
    //
    hArray[0] = osReader.hEvent;
    hArray[1] = osStatus.hEvent;
    hArray[2] = ghStatusMessageEvent;
    hArray[3] = ghThreadExitEvent;

    //
    // initial check, forces updates
    //
    CheckModemStatus(TRUE);
    CheckComStat(TRUE);

    while ( !fThreadDone ) {

        //
        // If no reading is allowed, then set flag to
        // make it look like a read is already outstanding.
        //
        if (g_appdata.fNoReading)
            fWaitingOnRead = TRUE;
        
        //
        // if no read is outstanding, then issue another one
        //
        if (!fWaitingOnRead) {
            if (!ReadFile(g_appdata.hCommPort, lpBuf_first, AMOUNT_TO_READ, &dwRead, &osReader)) {
                if (GetLastError() != ERROR_IO_PENDING)	  // read not delayed?
                    ErrorInComm("ReadFile in ReaderAndStatusProc");

                fWaitingOnRead = TRUE;
            }
            else {    // read completed immediately
                if ((dwRead != MAX_READ_BUFFER) && g_appdata.fDisplayTimeouts)
                    UpdateStatus("Read timed out immediately.\r\n");

                if (dwRead)
				{
                    OutputABuffer(hTTY, lpBuf, dwRead);
				}
            }
        }

        //
        // 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 != g_appdata.dwEventFlags) {
            dwStoredFlags = g_appdata.dwEventFlags;
            if (!SetCommMask(g_appdata.hCommPort, dwStoredFlags))
                ErrorReporter("SetCommMask");
        }

        //
        // If event checks are not allowed, then make it look
        // like an event check operation is outstanding
        //
        if (g_appdata.fNoEvents)
            fWaitingOnStat = TRUE;
        //
        // if no status check is outstanding, then issue another one
        //
        if (!fWaitingOnStat) {
            if (g_appdata.fNoEvents)
                fWaitingOnStat = TRUE;
            else {
                if (!WaitCommEvent(g_appdata.hCommPort, &dwCommEvent, &osStatus)) {
                    if (GetLastError() != ERROR_IO_PENDING)	  // Wait not delayed?
                        ErrorReporter("WaitCommEvent");
                    else
                        fWaitingOnStat = TRUE;
                }
                else
                    // WaitCommEvent returned immediately
                    ReportStatusEvent(dwCommEvent);
            }
        }

        //
        // wait for pending operations to complete
        //
        if ( fWaitingOnStat && fWaitingOnRead ) {
            dwRes = WaitForMultipleObjects(NUM_READSTAT_HANDLES, hArray, FALSE, STATUS_CHECK_TIMEOUT);
            switch(dwRes)
			{
				// read completed
				case WAIT_OBJECT_0: if (!GetOverlappedResult(g_appdata.hCommPort, &osReader, &dwRead, FALSE))
				{
					if (GetLastError() == ERROR_OPERATION_ABORTED)
						UpdateStatus("Read aborted\r\n");
					else 
						ErrorInComm("GetOverlappedResult (in Reader)");
				}
				else 
				{ // read completed successfully
					if ((dwRead != MAX_READ_BUFFER) && g_appdata.fDisplayTimeouts)
						UpdateStatus("Read timed out overlapped.\r\n");
					if (dwRead)
					{
						int 			loop1, loop2;			
						loop2				= 0;
						for (loop1 = 0; loop1 < AMOUNT_TO_READ; loop1++)
						{
							if (lpBuf_first[loop1] < 0x0A || lpBuf_first[loop1] >= 0x7f)
								continue;
							else 
								lpBuf[loop2++] = lpBuf_first[loop1];
						}
						lpBuf[loop2++]		= '\r';
						lpBuf[loop2++]		= '\n';
						lpBuf[loop2]		= 0;
						if (strstr(lpBuf, "ROM boot"))
						{
							if (GetTickCount() -g_appdata.tickcountFinish < 2000)
							{ //  在很短的时间内收到PCB板的下载信号,  视为PCB板自动复位,	而不是合上夹具
								return 0;
							}
							g_appdata.rgbBGColor = RGB(255, 255, 255);
							OutputABuffer(hTTY, "进入下载模式\r\n", dwRead);
							g_appdata.DownloadReday = TRUE;
							if (strlen(g_appdata.szFileName) != 0)
								TransferFileTextStart(g_appdata.szFileName);
						}
						else if (strstr(lpBuf, "Verify successful"))
						{
							g_appdata.tickcountFinish = GetTickCount();
							g_appdata.rgbBGColor = RGB(50, 255, 50);
							OutputABuffer(hTTY, "下载完成\r\n", dwRead);
							g_appdata.DownloadReday = FALSE;
						}
						else if (strstr(lpBuf, "Programming:"))
						{
							char *			pchar_percent = strstr(lpBuf, "Programming:");
							char			ascbufpercent[64];			
							if (pchar_percent != NULL)
							{
								g_appdata.tickcountFinish = GetTickCount();
								g_appdata.rgbBGColor = RGB(255, 255, 255);
								memset(ascbufpercent, 0, 64);
								strncpy(ascbufpercent, pchar_percent + 12, 2);
								Flashed_percent 	= atoi(ascbufpercent);
								sprintf(ascbufpercent, "下载已完成%d\r\n", Flashed_percent);
								OutputABuffer(hTTY, ascbufpercent, dwRead);
								g_appdata.DownloadReday = FALSE;
							}
						}
						else if (strstr(lpBuf, "Verify fail"))
						{
							//g_appdata.tickcountFinish = GetTickCount();
							g_appdata.rgbBGColor = RGB(255, 50, 50);
							OutputABuffer(hTTY, "下载失败\r\n", dwRead);
							g_appdata.DownloadReday = FALSE;
						}
						else 
						{
							g_appdata.rgbBGColor = RGB(255, 255, 255);
							OutputABuffer(hTTY, lpBuf, dwRead);
							g_appdata.DownloadReday = FALSE;
						}
					}
				}
				fWaitingOnRead		= FALSE;
				break;
				// status completed
				case WAIT_OBJECT_0 + 1: if (!GetOverlappedResult(g_appdata.hCommPort, &osStatus, &dwOvRes, FALSE))
				{
					if (GetLastError() == ERROR_OPERATION_ABORTED)
						UpdateStatus("WaitCommEvent aborted\r\n");
					else 
						ErrorInComm("GetOverlappedResult (in Reader)");
				}
				else 
					// status check completed successfully
					ReportStatusEvent(dwCommEvent);
				fWaitingOnStat		= FALSE;
				break;
				// status message event
				case WAIT_OBJECT_0 + 2: StatusMessage();
				break;
				// thread exit event
				case WAIT_OBJECT_0 + 3: fThreadDone = TRUE;
				break;
				case WAIT_TIMEOUT:								//
			
				// timeouts are not reported because they happen too often
				// OutputDebugString("Timeout in Reader & Status checking\n\r");
				//
				//
				// if status checks are not allowed, then don't issue the
				// modem status check nor the com stat check
				//
				if (!g_appdata.fNoStatus)
				{
					CheckModemStatus(FALSE);					// take this opportunity to do
					CheckComStat(FALSE);						//	 a modem status check and
			
					//	 a comm status check
				}
				break;
			default:
				ErrorReporter("WaitForMultipleObjects(Reader & Status handles)");
				break;
			}
			
			
        }
    }

    //
    // close event handles
    //
    CloseHandle(osReader.hEvent);
    CloseHandle(osStatus.hEvent);

    return 1;
}


/*

int loop1,loop2;
loop2 = 0;
for (loop1 = 0;loop1 < AMOUNT_TO_READ;loop1++)
{
if (lpBuf_first[loop1] == 0)
continue;
else
lpBuf[loop2++] = lpBuf_first[loop1];
}
lpBuf[loop2] = 0;


*/