www.pudn.com > HDTV_play_flash.rar > Tserial_event.cpp


// wan: _endthread() 来中止线程? 
//com3 单位的,是仿真的串口,必须有时间限制,不然线程关闭不了 
//ReadFile 时间溢出也会设置 overlapped 事件! 此时只好再读,应该不会丢数的! 
 
 
/* ------------------------------------------------------------------------ -- 
--                                                                          -- 
--                        PC serial port connection object                  -- 
--                           for  event-driven programs                     -- 
--                                                                          -- 
--                                                                          -- 
--                                                                          -- 
--  Copyright @ 2001-2002     Thierry Schneider                             -- 
--                            thierry@tetraedre.com                         -- 
--                                                                          -- 
--                                                                          -- 
--                                                                          -- 
-- ------------------------------------------------------------------------ -- 
--                                                                          -- 
--  Filename : Tserial_event.cpp                                            -- 
--  Author   : Thierry Schneider                                            -- 
--  Created  : April 4th 2000                                               -- 
--  Modified : June 22nd 2002                                               -- 
--  Plateform: Windows 95, 98, NT, 2000, XP (Win32)                         -- 
-- ------------------------------------------------------------------------ -- 
--                                                                          -- 
--  This software is given without any warranty. It can be distributed      -- 
--  free of charge as long as this header remains, unchanged.               -- 
--                                                                          -- 
-- ------------------------------------------------------------------------ -- 
--                                                                          -- 
-- 01.04.24      Comments added                                             -- 
-- 01.04.28      Bug 010427 corrected. OnDisconnectedManager was not        -- 
--                initialized                                               -- 
-- 01.04.28      connect() function prototype modified to handle 7-bit      -- 
--                communication                                             -- 
-- 01.04.29      "ready" field added to remove a bug that occured during    -- 
--                 reconnect (event manager pointers cleared)               -- 
--                 I removed the "delete" in Tserial_event_thread_start     -- 
--                 because it was destroying the object even if we would    -- 
--                 use it again                                             -- 
--                                                                          -- 
-- 02.01.30      Version 2.0 of the serial event object                     -- 
--                                                                          -- 
--                                                                          -- 
-- 02.06.22      - wait for the thread termination before                   -- 
--                 quiting or restarting                                    -- 
--               - "owner" field added to be able to call C++ object from   -- 
--                  the event manager routine                               -- 
--               - Correction of a bug that occured when receiving data     -- 
--                 (setting twice the SIG_READ_DONE event)                  -- 
--                                                                          -- 
--                                                                          -- 
--                                                                          -- 
-- ------------------------------------------------------------------------ -- 
--                                                                          -- 
--    Note to Visual C++ users:  Don't forget to compile with the           -- 
--     "Multithreaded" option in your project settings                      -- 
--                                                                          -- 
--         See   Project settings                                           -- 
--                   |                                                      -- 
--                   *--- C/C++                                             -- 
--                          |                                               -- 
--                          *--- Code generation                            -- 
--                                       |                                  -- 
--                                       *---- Use run-time library         -- 
--                                                     |                    -- 
--                                                     *---- Multithreaded  -- 
--                                                                          -- 
--                                                                          -- 
--                                                                          -- 
-- ------------------------------------------------------------------------ */ 
 
 
 
 
/* ---------------------------------------------------------------------- */ 
 
#define STRICT 
//#include  
#include  
#include  
#include  
#include  
#include  
#include  
#include  
#pragma hdrstop 
 
#include "BThread.h" 
#include "Tserial_event.h" 
 
#define SIG_POWER_DOWN     0    //主程序Disconnect() 发出 
#define SIG_READER         1    //硬件发出,收到数了 
#define SIG_READ_DONE      2    //主程序HasBeenRead() 发出,data received has been read 
#define SIG_WRITER         3    //硬件发出,发送buffer 的数写完了 
#define SIG_DATA_TO_TX     4    // 主程序data waiting to be sent 
#define SIG_MODEM_EVENTS   5    //modem 硬件发出 
#define SIG_MODEM_CHECKED  6 
 
//void Tserial_event_thread_start(void *arg); 
/* ---------------------------------------------------------------------- */ 
/* ---------------------  Tserial_event_thread_start  ------------------- */ 
/* ---------------------------------------------------------------------- */ 
/** 
    This function is not part of the Tserial_event object. It is simply used 
    to start the thread from an external point of the object. 
*/ 
/*void Tserial_event_thread_start(void *arg)   //注意,谁的成员函数也不是!!! 
{ 
    class Tserial_event *serial_unit; 
    serial_unit = (Tserial_event *) arg; 
    if (serial_unit!=0) 
        serial_unit->run(); 
} 
*/ 
 
/* -------------------------------------------------------------------- */ 
/* -------------------------    Tserial_event ------------------------- */ 
/* -------------------------------------------------------------------- */ 
Tserial_event::Tserial_event() 
{ 
    int i; 
    MyThread = 0; 
    ready            = false; 
    parityMode       = SERIAL_PARITY_NONE; 
    port[0]          = 0; 
    rate             = 0; 
    threadid         = 0; 
    serial_handle    = INVALID_HANDLE_VALUE; 
    thread_handle    = 0; 
    owner            = 0; 
    tx_in_progress   = 0; 
    rx_in_progress   = 0; 
    max_rx_size      = 1; 
    tx_size          = 0; 
    received_size    = 0; 
    check_modem      = false; 
 
    manager          = 0; 
 
    /* -------------------------------------------------------------- */ 
    // creating Events for the different sources 
    for (i=0; iSuspended) 
    { 
        ready = false; 
        SetEvent(serial_events[SIG_POWER_DOWN]); //让waitformulti...退出 
        MyThread->Terminate(); //中止线程 //置 tthread::terminated=1 
        MyThread->WaitFor();   //等待线程中止 
    } 
 
    if (serial_handle!=INVALID_HANDLE_VALUE)  //关闭串口, 
        CloseHandle(serial_handle); 
    serial_handle = INVALID_HANDLE_VALUE; 
 
    if(MyThread)                              //删除线程 
      { delete MyThread; 
        MyThread=0; 
      } 
} 
/* -------------------------------------------------------------------- */ 
/* --------------------------    connect     ResetEvent waitforsingleobject ------------------------- */ 
/* -------------------------------------------------------------------- */ 
/** 
     Serial port, file and overlapped structures initialization 
*/ 
int  Tserial_event::connect (char *port_arg, int  rate_arg,  int parity_arg, 
                             char ByteSize , bool modem_events) 
{ 
    int  erreur; 
    DCB  dcb; 
    int  i; 
    COMMTIMEOUTS cto = { 500, 200, 500, 500, 5000 }; //old is all 0  wan, 会不会丢数? 
    /* --------------------------------------------- */ 
    if (serial_handle!=INVALID_HANDLE_VALUE) 
        CloseHandle(serial_handle); 
    serial_handle = INVALID_HANDLE_VALUE; 
 
    if (port_arg!=0) 
    { 
        strncpy(port, port_arg, 10); 
        rate        = rate_arg; 
        parityMode  = parity_arg; 
        check_modem = modem_events; 
 
        erreur      = 0; 
        ZeroMemory(&ovReader   ,sizeof(ovReader)   );  // clearing the overlapped 
        ZeroMemory(&ovWriter   ,sizeof(ovWriter)   ); 
        ZeroMemory(&ovWaitEvent,sizeof(ovWaitEvent)); 
        memset(&dcb,0,sizeof(dcb)); 
 
        /* -------------------------------------------------------------------- */ 
        // set DCB to configure the serial port 
        dcb.DCBlength       = sizeof(dcb); 
         
        /* ---------- Serial Port Config ------- */ 
        dcb.BaudRate        = rate; 
 
        switch(parityMode) 
        { 
            case SERIAL_PARITY_NONE: 
                            dcb.Parity      = NOPARITY; 
                            dcb.fParity     = 0; 
                            break; 
            case SERIAL_PARITY_EVEN: 
                            dcb.Parity      = EVENPARITY; 
                            dcb.fParity     = 1; 
                            break; 
            case SERIAL_PARITY_ODD: 
                            dcb.Parity      = ODDPARITY; 
                            dcb.fParity     = 1; 
                            break; 
        } 
 
 
        dcb.StopBits        = ONESTOPBIT ; 
        dcb.ByteSize        = (BYTE) ByteSize; 
 
        dcb.fOutxCtsFlow    = 0; 
        dcb.fOutxDsrFlow    = 0; 
        dcb.fDtrControl     = DTR_CONTROL_DISABLE; 
        dcb.fDsrSensitivity = 0; 
        dcb.fRtsControl     = RTS_CONTROL_DISABLE; 
        dcb.fOutX           = 0;  //流控也不要 
        dcb.fInX            = 0; 
         
        /* ----------------- misc parameters ----- */ 
        dcb.fErrorChar      = 0; 
        dcb.fBinary         = 1; 
        dcb.fNull           = 0; 
        dcb.fAbortOnError   = 0; 
        dcb.wReserved       = 0; 
        dcb.XonLim          = 2; 
        dcb.XoffLim         = 4; 
        dcb.XonChar         = 0x13;       //各人自己定义 
        dcb.XoffChar        = 0x19; 
        dcb.EvtChar         = 0; 
 
         /* -------------------------------------------------------------------- */ 
        serial_handle    = CreateFile(port, GENERIC_READ | GENERIC_WRITE, 
                   0, NULL, OPEN_EXISTING,FILE_FLAG_OVERLAPPED,NULL); 
                   // opening serial port 
 
        ovReader.hEvent    = serial_events[SIG_READER]; 
        ovWriter.hEvent    = serial_events[SIG_WRITER]; 
        ovWaitEvent.hEvent = serial_events[SIG_MODEM_EVENTS]; 
 
        if (serial_handle    != INVALID_HANDLE_VALUE) 
        { 
            if (check_modem) 
            { 
                if(!SetCommMask(serial_handle, EV_RING | EV_RLSD)) 
                    erreur = 1; 
            } 
            else 
            { 
                if(!SetCommMask(serial_handle, 0)) //EV_RXCHAR )) //old is 0 
                    erreur = 1; 
            } 
 
 
            // set timeouts 
            if(!SetCommTimeouts(serial_handle,&cto))   //全0,不要超时 
                erreur = 2; 
 
            // set DCB 
            if(!SetCommState(serial_handle,&dcb))      //口、波特率、流控等 
                erreur = 4; 
        } 
        else 
            erreur = 8; 
    } 
    else  //port_arg=0 
        erreur = 16; 
 
 
    /* --------------------------------------------- */ 
    for (i=0; iOOOwner = this; 
        MyThread->Resume(); 
    } 
   /* --------------------------------------------- */ 
    return(erreur); 
} 
 
 
/* -------------------------------------------------------------------- */ 
/* ---------------------           setManager     --------------------- */ 
/* -------------------------------------------------------------------- */ 
void   Tserial_event::setManager(type_myCallBack manager_arg) 
{ 
        manager = manager_arg; 
} 
/* -------------------------------------------------------------------- */ 
/* ---------------------           setRxSize      --------------------- */ 
/* -------------------------------------------------------------------- */ 
void    Tserial_event::setRxSize(int size) 
{ 
        max_rx_size = size; 
        if (max_rx_size>SERIAL_MAX_RX) 
            max_rx_size = SERIAL_MAX_RX; 
} 
/* -------------------------------------------------------------------- */ 
/* ---------------------           setManager     --------------------- */ 
/* -------------------------------------------------------------------- */ 
char *      Tserial_event::getDataInBuffer(void) 
{ 
    return(rxBuffer); 
} 
/* -------------------------------------------------------------------- */ 
/* ---------------------           setManager     --------------------- */ 
/* -------------------------------------------------------------------- */ 
int      Tserial_event::getDataInSize(void) 
{ 
    return(received_size); 
} 
/* -------------------------------------------------------------------- */ 
/* ---------------------           setManager     --------------------- */ 
/* -------------------------------------------------------------------- */ 
void   Tserial_event::dataHasBeenRead(void) 
{ 
    SetEvent(serial_events[SIG_READ_DONE]); 
} 
/* -------------------------------------------------------------------- */ 
/* -----------------------   getNbrOfBytes  --------------------------- */ 
/* -------------------------------------------------------------------- */ 
int Tserial_event::getNbrOfBytes    (void) 
{ 
    struct _COMSTAT status; 
    int             n; 
    unsigned long   etat; 
 
    n = 0; 
 
    if (serial_handle!=INVALID_HANDLE_VALUE) 
    { 
        ClearCommError(serial_handle, &etat, &status); 
        n = status.cbInQue; 
    } 
    return(n); 
} 
/* -------------------------------------------------------------------- */ 
/* --------------------------    sendData     ------------------------- */ 
/* -------------------------------------------------------------------- */ 
void Tserial_event::sendData (char *buffer, int size) 
{ 
    if ((!tx_in_progress) && (sizeExecute() 循环调用 
{ 
    bool          done=false; 
    long          status; 
    unsigned long read_nbr, result_nbr; 
    char          success; 
  
 
   if(FirstTime) 
    { 
     //类的成员 
     ready                   = true; 
     done                    = false; 
     tx_in_progress          = 0; 
     rx_in_progress          = 0; 
     WaitCommEventInProgress = 0; 
 
     if (manager!=0) 
        manager((uint32) this, SERIAL_CONNECTED);  //向主程序发送消息 
     GetLastError();               // just to clear any pending error 
     SetEvent(serial_events[SIG_READ_DONE]); 
     if (check_modem) 
        SetEvent(serial_events[SIG_MODEM_CHECKED]); 
     FirstTime=false; 
    } 
        /* ------------------------------------------------------------------ */ 
        /*                                                                    */ 
        /*                          Waiting  for signals                      */ 
        /*                                                                    */ 
        /* ------------------------------------------------------------------ */ 
        // Main wait function. Waiting for something to happen. 
        // This may be either the completion of a Read or a Write or 
        // the reception of modem events, Power Down, new Tx 
        // 
        status = WaitForMultipleObjects(SERIAL_SIGNAL_NBR, serial_events, 
                                        FALSE,INFINITE); 
//      if(status == WAIT_TIMEOUT)  return;                 //wan 
 
        // processing answer to filter other failures 
        status = status - WAIT_OBJECT_0; 
        if ((status<0) || (status>=SERIAL_SIGNAL_NBR)) 
            done=true;   // error 
        else 
        { 
            /* ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */ 
            /* ++++++++++++++++++++ EVENT DISPATCHER ++++++++++++++++++ */ 
            /* ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */ 
            switch(status) 
            { 
                /* ######################################################## */ 
                case SIG_POWER_DOWN: 
                    // receiving a POWER down signal. Stopping the thread 
                    done = true; 
                    break; 
                /* ######################################################## */ 
                /* #                                                      # */ 
                /* #                                                      # */ 
                /* #                       RX                             # */ 
                /* #                                                      # */ 
                /* #                                                      # */ 
                /* ######################################################## */ 
                case SIG_READ_DONE: 
                    // previous reading is finished 
                    // I start a new one here 
 
                    if (!rx_in_progress) 
                    { 
wanmmm:                 // locking reading 
                        rx_in_progress = 1; 
                        // starting a new read 
                        success = (char) ReadFile(serial_handle,&rxBuffer, 
                                         max_rx_size,&read_nbr, &ovReader); 
                        if (!success) 
                        { 
                            // failure 
                            if(GetLastError() != ERROR_IO_PENDING ) 
                            { 
                                // real failure => quiting 
                                done = true; 
                                #ifdef DEBUG_EVENTS 
                                printf("Readfile error (not pending)\n"); 
                                #endif DEBUG_EVENTS 
                            } 
                            #ifdef DEBUG_EVENTS 
                            else 
                                printf("ReadFile pending\n"); 
                            #endif DEBUG_EVENTS 
                        } 
                        #ifdef DEBUG_EVENTS 
                        else 
                        { 
                            // I make nothing here since the overlapped 
                            // will be signaled anyway, so I'll make 
                            // the processing there 
                            printf("ReadFile immediate success\n"); 
                        } 
                        #endif 
                    } 
                    break; 
                /* ######################################################## */ 
                case SIG_READER: 
                    // reading the result of the terminated read 
                    //BOOL GetOverlappedResult( 
                    //    HANDLE hFile,	// handle of file, pipe, or communications device 
                    //    LPOVERLAPPED lpOverlapped,	// address of overlapped structure 
                    //    LPDWORD lpNumberOfBytesTransferred,	// address of actual bytes count 
                    //    BOOL bWait 	// wait flag 
                    //   ); 
                    // 
                    if (GetOverlappedResult(serial_handle, &ovReader, 
                        &result_nbr, FALSE)) 
                    { 
                        #ifdef DEBUG_EVENTS 
                            printf("ReadFile => GetOverlappedResult done\n"); 
                        #endif DEBUG_EVENTS 
                        // no error => OK 
                        // Read operation completed successfully 
                        ResetEvent(serial_events[SIG_READER]); 
                        // Write operation completed successfully 
 
                        if (result_nbr==0 && !done) 
                           { 
                             done=done; 
                             goto wanmmm;  //wan add,时间溢出也会设置事件! 此时只好再读 
                           } 
                         
                        received_size  = result_nbr; 
                        rx_in_progress = 0; // read has ended 
                        // if incoming data, I process them 
                        if ((result_nbr!=0) &&(manager!=0)) 
                            manager((uint32) this, SERIAL_DATA_ARRIVAL); 
                        // I automatically restart a new read once the 
                        // previous is completed. 
                        //SetEvent(serial_events[SIG_READ_DONE]); 
                        // BUG CORRECTION 02.06.22 
                    } 
                    else 
                    { 
                        // GetOverlapped didn't succeed ! 
                        // What's the reason ? 
                        if(GetLastError()!= ERROR_IO_PENDING ) 
                            done = 1;  // failure 
                    } 
                    break; 
                /* ######################################################## */ 
                /* #                                                      # */ 
                /* #                                                      # */ 
                /* #                       TX                             # */ 
                /* #                                                      # */ 
                /* #                                                      # */ 
                /* ######################################################## */ 
                case SIG_DATA_TO_TX: 
                    // Signal asserted that there is a new valid message 
                    // in the "txBuffer" variable 
                    // sending data to the port 
                     success = (char) WriteFile(serial_handle, txBuffer, tx_size, 
                                        &result_nbr, &ovWriter);  //wan 2002/9/24 cut 
                     //wannnn: success = (char) WriteFile(serial_handle, txBuffer+SPoint,1,&result_nbr, &ovWriter); 
                     //SPoint++; 
                        if (!success) 
                        { 
                            // ouups, failure 
                            if(GetLastError() != ERROR_IO_PENDING ) 
                            { 
                                // real failure => quiting 
                                done = true; 
                                #ifdef DEBUG_EVENTS 
                                printf("WriteFile error (not pending)\n"); 
                                #endif DEBUG_EVENTS 
                            } 
                            #ifdef DEBUG_EVENTS 
                            else 
                                printf("WriteFile pending\n"); 
                            #endif DEBUG_EVENTS 
                        } 
                        #ifdef DEBUG_EVENTS 
                        else 
                        { 
                            // I make nothing here since the overlapped 
                            // will be signaled anyway, so I'll make 
                            // the processing there 
                            printf("WriteFile immediate success\n"); 
                        } 
                        #endif 
                    break; 
                /* ######################################################## */ 
                case SIG_WRITER: 
                    // WriteFile has terminated 
                    // checking the result of the operation 
                    //if(SPoint quiting 
                                done = true; 
                                #ifdef DEBUG_EVENTS 
                                printf("WaitCommEvent error (not pending)\n"); 
                                #endif DEBUG_EVENTS 
                            } 
                            #ifdef DEBUG_EVENTS 
                            else 
                                printf("WaitCommEvent pending\n"); 
                            #endif DEBUG_EVENTS 
                        } 
                        #ifdef DEBUG_EVENTS 
                        else 
                        { 
                            // I make nothing here since the overlapped 
                            // will be signaled anyway, so I'll make 
                            // the processing there 
                            printf("WaitCommEvent immediate success\n"); 
                        } 
                        #endif 
                    } 
                    break; 
                /* ######################################################## */ 
                case SIG_MODEM_EVENTS: 
                    // reading the result of the terminated wait 
                    if (GetOverlappedResult(serial_handle, &ovWaitEvent, 
                        &result_nbr, FALSE)) 
                    { 
                        // Wait operation completed successfully 
                        ResetEvent(serial_events[SIG_MODEM_EVENTS]); 
                        WaitCommEventInProgress = 0; 
                        // if incoming data, I process them 
                        OnEvent(dwCommEvent); 
                        // automatically starting a new check 
                        SetEvent(serial_events[SIG_MODEM_CHECKED]); 
                    } 
                    else 
                    { 
                        // GetOverlapped didn't succeed ! 
                        // What's the reason ? 
                        if(GetLastError() != ERROR_IO_PENDING ) 
                            done = 1;  // failure 
                    } 
                    break; 
                /* ######################################################## */ 
            } 
            /* ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */ 
            /* ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */ 
            /* ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */ 
        } 
} 
/* -------------------------------------------------------------------- */ 
/* -------------------------------------------------------------------- */