Solved

Programming COM Port

Posted on 1997-08-17
1
1,223 Views
Last Modified: 2013-11-15
Can anyone provide me with the codes for sending a string of data to Com1. I tried using the Bios.h file and manage only to perform setting for the port and not able to send a string of data.
0
Comment
Question by:kcong
1 Comment
 
LVL 2

Accepted Solution

by:
alexxx earned 100 total points
Comment Utility
This code is 32-bits for Windows95 and is good enough to get started. After creation of the MSPort object call to MSPort::WriteByte(byte) repeatedly.

h-file:
/*++ BUILD Version: 0001     Increment this if a change has global effects

Copyright (c)

Module Name:

      MSPort.h

Responsible:

      Who wrote it.

Abstract:

      The MSPort class declaration.

Revision History:

      Bug fixes and new features history (for THIS file only).

      //API implementation map (c[onstruction], i[mplementation], m[ethod]):

         //GENERAL SYSTEM CALLS:
      //m:  BOOL ReadFile(HANDLE, LPVOID, DWORD, LPDWORD, LPOVERLAPPED)
      //tdf Read()
      //m:  BOOL WriteFile(HANDLE, LPCVOID, DWORD, LPDWORD, LPOVERLAPPED)
      //tdf Write()
      //m:  BOOL DeviceIoControl(HANDLE, DWORD, LPVOID, DWORD, LPVOID, DWORD, LPDWORD, LPOVERLAPPED)
      //BOOL InsertLSRMST(BOOL a_bInsert);
      //c:  HANDLE CreateFile(LPCTSTR, DWORD, DWORD, LPSECURITY_ATTRIBUTES, DWORD, DWORD, HANDLE)
      //c:  BOOL CloseHandle(HANDLE)   //c
      //i:  BOOL GetOverlappedResult(HANDLE, LPOVERLAPPED, LPDWORD, BOOL)
      //i:  BOOL FlushFileBuffers(HANDLE)
      //i:  DWORD GetLastError(VOID)

   COMM CONFIGURATION CALLS:
BOOL CommConfigDialog(LPTSTR, HWND, LPCOMMCONFIG)
BOOL GetDefaultCommConfig(LPCSTR, LPCOMMCONFIG, LPDWORD)
BOOL SetDefaultCommConfig(LPCSTR, LPCOMMCONFIG, DWORD)
BOOL GetCommConfig(HANDLE, LPCOMMCONFIG, LPDWORD)
BOOL SetCommConfig(HANDLE, LPCOMMCONFIG, DWORD)
BOOL BuildCommDCB(LPCTSTR, LPDCB)
BOOL BuildCommDCBAndTimeouts(LPCTSTR, LPDCB, LPCOMMTIMEOUTS)
BOOL GetCommProperties(HANDLE, LPCOMMPROP)
BOOL SetupComm(HANDLE, DWORD, DWORD)

   OTHER COMM CALLS:
BOOL GetCommMask(HANDLE, LPDWORD)
BOOL SetCommMask(HANDLE, DWORD)
BOOL GetCommState(HANDLE, LPDCB)
BOOL SetCommState(HANDLE, LPDCB)
BOOL GetCommTimeouts(HANDLE, LPCOMMTIMEOUTS)
BOOL SetCommTimeouts(HANDLE, LPCOMMTIMEOUTS)
BOOL GetCommModemStatus(HANDLE, LPDWORD)
BOOL SetCommBreak(HANDLE)
BOOL ClearCommBreak(HANDLE)
BOOL ClearCommError(HANDLE, LPDWORD, LPCOMSTAT)
BOOL PurgeComm(HANDLE, DWORD)
BOOL EscapeCommFunction(HANDLE, DWORD)
BOOL TransmitCommChar(HANDLE, char)
BOOL WaitCommEvent(HANDLE, LPDWORD, LPOVERLAPPED)

--*/

#ifndef _MSPORT_            //name of this h-file or the class it defines
#define _MSPORT_


//optional defines


//standard header files
#include <windows.h>
#include <winioctl.h>

//product header files
//...

//other header files
#include "aobject.h"


//declarations
#define ID_ERROR_STRING_TABLE_MSPORT ID_ERROR_STRING_TABLE_BASE + 200
#define MSPORT_NAMELEN     8
#define MSPORT_MAXPORTS    10
#define MSPORT_MAXBLOCK    80
#define CN_EVENT 0x04
#define UM_RECEIVED            (WM_USER + 1)

//enum eTechnique
//{
//   eTechniqueTTY,    //TTY
//};

typedef BOOL (WritePortBlock)(HWND, LPSTR, int);

class MSPort : public AObject
{

   //friends
   friend DWORD FAR PASCAL CWatchProc(LPVOID pData);
   friend LRESULT CALLBACK COMMCallback(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);   //for window

   public:

      static const DCB* CreateDCB(DWORD a_BaudRate,   //###initialize, rearrange the variables
                                  DWORD a_dwFlags,
                                  WORD a_wXonLim,
                                  WORD a_wXoffLim,
                                  BYTE a_bByteSize,
                                  BYTE a_bParity,
                                  BYTE a_bStopBits,
                                  char a_cXonChar,
                                  char a_cXoffChar,
                                  char a_cErrorChar,
                                  char a_cEofChar,
                                  char a_cEvtChar);
      static const COMMTIMEOUTS* CreateTimeOuts(DWORD a_dwReadTimeout,  //###initialize, rearrange the variables
                                                DWORD a_dwReadMultiplier,
                                                DWORD a_dwReadConstant,
                                                DWORD a_dwWriteMultiplier,
                                                DWORD a_dwWriteConstant);

      //describe class interface briefly
      //...

      MSPort(BOOL& a_bOK, HINSTANCE a_hInst, HWND a_hwnd, BYTE a_bPort, const DCB* a_pDCB, WritePortBlock* a_pFunc);
      /*
      MSPort(BOOL& a_bOK, HINSTANCE a_hInst, HWND a_hwnd,
             const char* a_szPortName,
             const DCB* a_pDCB,
             const COMMTIMEOUTS* a_pTimeOuts,
             eTechnique a_eTechnique = eTechniqueTTY);
             */
      ~MSPort();

      //
      // API analogs
      //

      BOOL Read(LPVOID a_pBuf, DWORD a_dwToRead, LPDWORD a_pdwRead, LPOVERLAPPED a_pOvrLap);
      BOOL Read(LPVOID a_pBuf, DWORD a_dwToRead, LPDWORD a_pdwRead);
      BOOL Write(LPCVOID a_pBuf, DWORD a_dwToWrite, LPDWORD a_pdwWritten, LPOVERLAPPED a_pOvrLap);
      BOOL Write(LPCVOID a_pBuf, DWORD a_dwToWrite, LPDWORD a_pdwWritten);
      BOOL InsertLSRMST(BOOL a_bInsert, BYTE a_bEscChar = '$');

      BOOL BuildDCB(LPCTSTR a_szDef, LPDCB a_pDCB);
      BOOL BuildDCBAndTimeouts(LPCTSTR a_szDef, LPDCB a_pDCB, LPCOMMTIMEOUTS a_pTimeOuts);

      BOOL ConfigDialog(LPCOMMCONFIG a_pCC);
      BOOL GetDefaultConfig(LPCOMMCONFIG a_pCC, LPDWORD a_pdwSize);
      BOOL SetDefaultConfig(LPCOMMCONFIG a_pCC, DWORD a_dwSize);
      BOOL GetConfig(LPCOMMCONFIG a_lpCC, LPDWORD a_pdwSize);
      BOOL SetConfig(LPCOMMCONFIG a_lpCC, DWORD a_dwSize);
      BOOL GetProperties(LPCOMMPROP a_pCommProp);
      BOOL Setup(DWORD a_dwInQueue, DWORD a_dwOutQueue);

      BOOL GetMask(LPDWORD a_pdwEvtMask);
      BOOL SetMask(DWORD a_dwEvtMask);
      BOOL GetState(LPDCB a_pDCB);
      BOOL SetState(LPDCB a_pDCB);
      BOOL GetTimeouts(LPCOMMTIMEOUTS a_pTimeOuts);
      BOOL SetTimeouts(LPCOMMTIMEOUTS a_pTimeOuts);
      BOOL GetModemStatus(LPDWORD a_pModemStat);
      BOOL SetBreak(void);
      BOOL ClearBreak(void);
      BOOL ClearError(LPDWORD a_pdwErrors, LPCOMSTAT a_pStat);
      BOOL Purge(DWORD a_dwFlags);
      BOOL EscapeFunction(DWORD a_dwFunc);
      BOOL TransmitChar(char a_cChar);
      BOOL WaitEvent(LPDWORD a_pdwEvtMask, LPOVERLAPPED a_pOvrLap);

      //
      // Other functions
      //

        void WaitOnReceive(DWORD a_dwCnt);
        BOOL SignalOnReceive(void);

      //ReadByte()
      DWORD ReadBlock(void* a_pBlock, DWORD a_dwSize);
      BOOL WriteByte(BYTE a_bByte);
      //WriteBlock()

   protected:
      static WORD m_wWndCnt;  //###transfer to private

   private:

      enum eMSPortError
      {
         ePort_unknown_error,
      };

      DWORD WatchProc(void);  //thread works here!
      BOOL GetNotification(WPARAM a_wParam, LPARAM a_lParam);   //notification form port got here!
      virtual BOOL InitMembers(void);
         virtual void ErrorHandler(eErrorMode a_eErrorMode, WORD a_wErrorNum);

      HANDLE m_hPort;         //###idComDev
      HANDLE m_hPostEvent;    //###hPostEvent
      HANDLE m_hWatchThread;  //###hWatchThread
        HANDLE hCommWatchThread;
      DWORD m_dwThreadID;     //###dwThreadID
      OVERLAPPED m_osWrite;   //###osWrite
      OVERLAPPED m_osRead;    //###osRead

      HWND  m_hwnd1;    //###
      WritePortBlock* m_pFunc;

      DWORD m_dwCnt;

      DWORD m_dwOpenFlags;
      BYTE m_bEscChar;
      char m_caName[MSPORT_NAMELEN];
      OVERLAPPED m_Overlapped;  //???

      static DCB m_StandardDCB;
      static COMMTIMEOUTS m_StandardTimeOuts;

      DCB m_DCB;
      COMMTIMEOUTS m_TimeOuts;
      COMSTAT m_Stat;
      COMMCONFIG m_Config;
      COMMPROP m_Prop;

      static const char* m_szClassName;   //name of class
      static UINT m_uErrRes;   //error strings resource ID for class
};


#endif //_MSPORT_

cpp-file
:
/*++ BUILD Version: 0001     Increment this if a change has global effects

Copyright (c)

Module Name:

      MSPort.cpp

Responsible:

      Who wrote it.

Abstract:

      What it is for.

Revision History:

      Bug fixes and new features history (for THIS file only).

--*/


//optional defines


//standard header files
#include "stdafx.h"
#include <string.h>

//product header files
//...

//other header files
#include "MSPort.h"


//declarations
//...


const char* MSPort::m_szClassName = "MSPort";   //name of class
UINT MSPort::m_uErrRes = ID_ERROR_STRING_TABLE_MSPORT;   //error strings resource ID for class
DCB MSPort::m_StandardDCB;    //###initialize
COMMTIMEOUTS MSPort::m_StandardTimeOuts;


const DCB* MSPort::CreateDCB(DWORD a_BaudRate,
                             DWORD a_dwFlags,
                             WORD a_wXonLim,
                             WORD a_wXoffLim,
                             BYTE a_bByteSize,
                             BYTE a_bParity,
                             BYTE a_bStopBits,
                             char a_cXonChar,
                             char a_cXoffChar,
                             char a_cErrorChar,
                             char a_cEofChar,
                             char a_cEvtChar)
{
   ;;;
   //perform checks for validity of data
   //fill the static member structure

   return NULL;
}  //MSPort::CreateDCB()


const COMMTIMEOUTS* MSPort::CreateTimeOuts(DWORD a_dwReadTimeout,
                                           DWORD a_dwReadMultiplier,
                                           DWORD a_dwReadConstant,
                                           DWORD a_dwWriteMultiplier,
                                           DWORD a_dwWriteConstant)
{
   ;;;
   //perform checks for validity of data
   //fill the static member structure

   return NULL;
}  //MSPort::CreateTimeOuts()

WORD MSPort::m_wWndCnt = 0;


MSPort::MSPort(BOOL& a_bOK, HINSTANCE a_hInst, HWND a_hwnd, BYTE a_bPort, const DCB* a_pDCB, WritePortBlock* a_pFunc)
   : AObject(a_hInst, a_hwnd)
{
   char       szPort[ 15 ];
   //HANDLE        hCommWatchThread ;
   DWORD         dwThreadID ;
   COMMTIMEOUTS  CommTimeOuts ;
   WNDCLASS wcSimple;

   //create window
 if(m_wWndCnt == 0)   //first object which uses window, create window class
 {
   wcSimple.style = 0;
   wcSimple.lpfnWndProc = COMMCallback;
   wcSimple.cbClsExtra = 0;
   wcSimple.cbWndExtra = 4;
   wcSimple.hInstance = m_hInst;
   wcSimple.hIcon = NULL;        
   wcSimple.hCursor = NULL;  
   wcSimple.hbrBackground = NULL;    
   wcSimple.lpszMenuName = NULL;    
   wcSimple.lpszClassName = m_szClassName;
   if(!RegisterClass(&wcSimple))
   {
      ErrorHandler(eErrorModeUnrec, (WORD)ePort_unknown_error);
      a_bOK = FALSE;
      return;
   }
 }
   m_hwnd1 = CreateWindow(m_szClassName, NULL, 0, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
                         CW_USEDEFAULT, m_hwnd, (HMENU)NULL, (HINSTANCE)m_hInst, NULL);
   if(m_hwnd1 == NULL)
   {
      ErrorHandler(eErrorModeUnrec, (WORD)ePort_unknown_error);
      UnregisterClass(m_szClassName, m_hInst);
      a_bOK = FALSE;
      return;
   }
 m_wWndCnt++;

   m_pFunc = a_pFunc;

   SetWindowLong(m_hwnd1, 0, (LONG)this);  //remember COMM object
///
   // create I/O event used for overlapped reads / writes
   m_osRead.hEvent = CreateEvent(NULL,    // no security
                                 TRUE,    // explicit reset req
                                 FALSE,   // initial event reset
                                 NULL);   // no name
   if(m_osRead.hEvent == NULL)
   {
      ;;;
   }
   m_osWrite.hEvent = CreateEvent(NULL,    // no security
                                  TRUE,    // explicit reset req
                                  FALSE,   // initial event reset
                                  NULL);   // no name
   if(NULL == m_osWrite.hEvent)
   {
      CloseHandle(m_osRead.hEvent);
      ;;;
   }

   // create "posted notification" event
   m_hPostEvent = CreateEvent(NULL,     // no security
                              TRUE,     // manual reset
                              TRUE,     // initial event is set
                              NULL);    // no name
   if(m_hPostEvent == NULL)
   {
      CloseHandle(m_osRead.hEvent);
      CloseHandle(m_osWrite.hEvent);
      ;;;
   }
///

   if(InitMembers() == FALSE)
   {
      a_bOK = FALSE;  
      return;
   }
 
   // HACK!  This checks for the PORT number defined by
   // the combo box selection.  If it is greater than the
   // maximum number of ports, assume TELNET.

   if (a_bPort > MSPORT_MAXPORTS)
      lstrcpy( szPort, "\\\\.\\TELNET" ) ;
   else
   {
      // load the COM prefix string and append port number
      wsprintf( szPort, "%s%d", "COM", a_bPort) ;
   }

   // open COMM device

   if ((m_hPort =
       CreateFile( szPort, GENERIC_READ | GENERIC_WRITE,
                  0,                    // exclusive access
                  NULL,                 // no security attrs
                  OPEN_EXISTING,
                  FILE_ATTRIBUTE_NORMAL |
                  FILE_FLAG_OVERLAPPED, // overlapped I/O
                  NULL )) == INVALID_HANDLE_VALUE)
   {
      a_bOK = FALSE;
      return;
   }
   else
   {
      // get any early notifications

      SetMask( EV_RXCHAR ) ;

      // setup device buffers

      Setup(4096, 4096 );

      // purge any information in the buffer

      // HACK! HACK! Not really needed... the buffers are allocated
      // and clear.  If TELNET is active, the buffer will contain
      // immediate data.

//      Purge( PURGE_TXABORT | PURGE_RXABORT |
//                                      PURGE_TXCLEAR | PURGE_RXCLEAR ) ;

      // set up for overlapped non-blocking I/O

      CommTimeOuts.ReadIntervalTimeout = 0xFFFFFFFF ;
      CommTimeOuts.ReadTotalTimeoutMultiplier = 0 ;
      CommTimeOuts.ReadTotalTimeoutConstant = 0 ;
      CommTimeOuts.WriteTotalTimeoutMultiplier = 0 ;
      CommTimeOuts.WriteTotalTimeoutConstant = 5000 ;
      SetTimeouts( &CommTimeOuts ) ;
   }

   DCB dcb;

   dcb.DCBlength = sizeof(DCB);

   GetState(&dcb);

   dcb.BaudRate = a_pDCB->BaudRate;
   dcb.ByteSize = a_pDCB->ByteSize;
   dcb.Parity = a_pDCB->Parity;
   dcb.StopBits = a_pDCB->StopBits;

   // setup hardware flow control
   dcb.fOutxDsrFlow = a_pDCB->fOutxDsrFlow;
   dcb.fDtrControl = a_pDCB->fDtrControl;

   dcb.fOutxCtsFlow = a_pDCB->fOutxCtsFlow;
   dcb.fRtsControl = a_pDCB->fRtsControl;

   // setup software flow control
   dcb.fInX = a_pDCB->fInX;
   dcb.fOutX = a_pDCB->fOutX;
   dcb.XonChar = a_pDCB->XonChar;
   dcb.XoffChar = a_pDCB->XoffChar;
   dcb.XonLim = a_pDCB->XonLim;
   dcb.XoffLim = a_pDCB->XoffLim;

   // other various settings
   dcb.fBinary = a_pDCB->fBinary;
   dcb.fParity = a_pDCB->fParity;

   a_bOK = SetState(&dcb);

   if (a_bOK)
   {
      // In the case of Win32, we create a secondary thread
      // to watch for an event.
      if (NULL == (hCommWatchThread =
                      CreateThread( (LPSECURITY_ATTRIBUTES) NULL,
                                    0,
                                    CWatchProc,
                                    (LPVOID) this,
                                    0, &dwThreadID )))
      {
         CloseHandle(m_hPort) ;
         a_bOK = FALSE ;
             return;
      }
      else
      {
         m_dwThreadID = dwThreadID ;
         m_hWatchThread = hCommWatchThread ;

         // Adjust thread priority
       
         SetThreadPriority( hCommWatchThread, THREAD_PRIORITY_BELOW_NORMAL ) ;
         ResumeThread( hCommWatchThread ) ;

         // assert DTR

         EscapeFunction( SETDTR ) ;

         // kick TELNET into operation

         //GetNotification((WPARAM) m_hPort, MAKELONG( CN_EVENT, 0 ) ) ;

      }
   }
   else
   {
      CloseHandle(m_hPort) ;
   }

   a_bOK = TRUE;
   return;
}  //MSPort::MSPort()


MSPort::~MSPort()
{
   // disable event notification and wait for thread
   // to halt

   SetMask( 0 ) ;

   // drop DTR

   EscapeFunction( CLRDTR ) ;

   // purge any outstanding reads/writes and close device handle

   Purge( PURGE_TXABORT | PURGE_RXABORT |
                                   PURGE_TXCLEAR | PURGE_RXCLEAR ) ;
   CloseHandle(m_hPort) ;

///
   // clean up event objects
   CloseHandle(m_osRead.hEvent);
   CloseHandle(m_osWrite.hEvent);
   CloseHandle(m_hPostEvent);
///
   DestroyWindow(m_hwnd1); //ausc of callback window
   m_wWndCnt--;
     if(m_wWndCnt == 0)   //last window based object
        UnregisterClass(m_szClassName, m_hInst);
 
       m_hPort = NULL;
   // block until thread has been halted

   //while (m_dwThreadID != 0)
      //            ResumeThread( hCommWatchThread ) ;


}  //MSPort::~MSPort()


//API analog
BOOL MSPort::Read(LPVOID a_pBuf, DWORD a_dwToRead, LPDWORD a_pdwRead, LPOVERLAPPED a_pOvrLap)
{
   return ReadFile(m_hPort, a_pBuf, a_dwToRead, a_pdwRead, a_pOvrLap);
}  //MSPort::Read()


//API analog
BOOL MSPort::Read(LPVOID a_pBuf, DWORD a_dwToRead, LPDWORD a_pdwRead)
{
   if(m_dwOpenFlags & FILE_FLAG_OVERLAPPED)
      return Read(a_pBuf, a_dwToRead, a_pdwRead, &m_Overlapped);
   else
      return Read(a_pBuf, a_dwToRead, a_pdwRead, NULL);
}  //MSPort::Read()


//API analog
BOOL MSPort::Write(LPCVOID a_pBuf, DWORD a_dwToWrite, LPDWORD a_pdwWritten, LPOVERLAPPED a_pOvrLap)
{
   return WriteFile(m_hPort, a_pBuf, a_dwToWrite, a_pdwWritten, a_pOvrLap);
}  //MSPort::Write()


//API analog
BOOL MSPort::Write(LPCVOID a_pBuf, DWORD a_dwToWrite, LPDWORD a_pdwWritten)
{
   if(m_dwOpenFlags & FILE_FLAG_OVERLAPPED)
      return Write(a_pBuf, a_dwToWrite, a_pdwWritten, &m_Overlapped);
   else
      return Write(a_pBuf, a_dwToWrite, a_pdwWritten, NULL);
}  //MSPort::Write()


//API analog
BOOL MSPort::InsertLSRMST(BOOL a_bInsert, BYTE a_bEscChar)
{
   BOOL bOK = FALSE;
   DWORD dw;

   do
   {
      if(a_bEscChar == '\0')
         break;   //not valid char

      if(a_bInsert == FALSE   //reset
         || (a_bEscChar != m_bEscChar
             && m_bEscChar != '\0'))
      {
         if(m_dwOpenFlags & FILE_FLAG_OVERLAPPED)
            bOK = DeviceIoControl(m_hPort, IOCTL_SERIAL_LSRMST_INSERT, &m_bEscChar, 1, NULL, 0, &dw, &m_Overlapped);
         else
            bOK = DeviceIoControl(m_hPort, IOCTL_SERIAL_LSRMST_INSERT, &m_bEscChar, 1, NULL, 0, &dw, NULL);

         if(bOK == FALSE)
            break;

         m_bEscChar = '\0';
      }

      if(a_bInsert == TRUE)   //set
      {
         if(m_dwOpenFlags & FILE_FLAG_OVERLAPPED)
            bOK = DeviceIoControl(m_hPort, IOCTL_SERIAL_LSRMST_INSERT, &m_bEscChar, 1, NULL, 0, &dw, &m_Overlapped);
         else
            bOK = DeviceIoControl(m_hPort, IOCTL_SERIAL_LSRMST_INSERT, &m_bEscChar, 1, NULL, 0, &dw, NULL);
         
         if(bOK == FALSE)
            break;

         m_bEscChar = a_bEscChar;
      }
   }
   while(0);

   return bOK;
}  //MSPort::InsertLSRMST()


//API analog
BOOL MSPort::BuildDCB(LPCTSTR a_szDef, LPDCB a_pDCB)
{
   return TRUE;
}  //MSPort::BuildDCB()


//API analog
BOOL MSPort::BuildDCBAndTimeouts(LPCTSTR a_szDef, LPDCB a_pDCB, LPCOMMTIMEOUTS a_pTimeOuts)
{
   return TRUE;
}  //MSPort::BuildDCBAndTimeouts()


//API analog
BOOL MSPort::ConfigDialog(LPCOMMCONFIG a_pCC)
{
   return CommConfigDialog(m_caName, m_hwnd, a_pCC);
}  //MSPort::ConfigDialog()


//API analog
BOOL MSPort::GetDefaultConfig(LPCOMMCONFIG a_pCC, LPDWORD a_pdwSize)
{
   return GetDefaultCommConfig(m_caName, a_pCC, a_pdwSize);
}  //MSPort::GetDefaultConfig()


//API analog
BOOL MSPort::SetDefaultConfig(LPCOMMCONFIG a_pCC, DWORD a_dwSize)
{
   return SetDefaultCommConfig(m_caName, a_pCC, a_dwSize);
}  //MSPort::SetDefaultConfig()


//API analog
BOOL MSPort::GetConfig(LPCOMMCONFIG a_lpCC, LPDWORD a_pdwSize)
{
   return GetCommConfig(m_hPort, a_lpCC, a_pdwSize);
}  //MSPort::GetConfig()


//API analog
BOOL MSPort::SetConfig(LPCOMMCONFIG a_lpCC, DWORD a_dwSize)
{
   return SetCommConfig(m_hPort, a_lpCC, a_dwSize);
}  //MSPort::SetConfig()


//API analog
BOOL MSPort::GetProperties(LPCOMMPROP a_pCommProp)
{
   return GetCommProperties(m_hPort, a_pCommProp);
}  //MSPort::GetProperties()


//API analog
BOOL MSPort::Setup(DWORD a_dwInQueue, DWORD a_dwOutQueue)
{
   return SetupComm(m_hPort, a_dwInQueue, a_dwOutQueue);
}  //MSPort::Setup()


//API analog
BOOL MSPort::GetMask(LPDWORD a_pdwEvtMask)
{
   return GetCommMask(m_hPort, a_pdwEvtMask);
}  //MSPort::GetMask()


//API analog
BOOL MSPort::SetMask(DWORD a_dwEvtMask)
{
   return SetCommMask(m_hPort, a_dwEvtMask);
}  //MSPort::SetMask()


//API analog
BOOL MSPort::GetState(LPDCB a_pDCB)
{
   return GetCommState(m_hPort, a_pDCB);
}  //MSPort::GetState()


//API analog
BOOL MSPort::SetState(LPDCB a_pDCB)
{
   return SetCommState(m_hPort, a_pDCB);
}  //MSPort::SetState()


//API analog
BOOL MSPort::GetTimeouts(LPCOMMTIMEOUTS a_pTimeOuts)
{
   return GetCommTimeouts(m_hPort, a_pTimeOuts);
}  //MSPort::GetTimeouts()


//API analog
BOOL MSPort::SetTimeouts(LPCOMMTIMEOUTS a_pTimeOuts)
{
   return SetCommTimeouts(m_hPort, a_pTimeOuts);
}  //MSPort::SetTimeouts()


//API analog
BOOL MSPort::GetModemStatus(LPDWORD a_pModemStat)
{
   return GetCommModemStatus(m_hPort, a_pModemStat);
}  //MSPort::GetModemStatus()


//API analog
BOOL MSPort::SetBreak(void)
{
   return SetCommBreak(m_hPort);
}  //MSPort::SetBreak()


//API analog
BOOL MSPort::ClearBreak(void)
{
   return ClearCommBreak(m_hPort);
}  //MSPort::ClearBreak()


//API analog
BOOL MSPort::ClearError(LPDWORD a_pdwErrors, LPCOMSTAT a_pStat)
{
   return ClearCommError(m_hPort, a_pdwErrors, a_pStat);
}  //MSPort::ClearError()


//API analog
BOOL MSPort::Purge(DWORD a_dwFlags)
{
   return PurgeComm(m_hPort, a_dwFlags);
}  //MSPort::Purge()


//API analog
BOOL MSPort::EscapeFunction(DWORD a_dwFunc)
{
   return EscapeCommFunction(m_hPort, a_dwFunc);
}  //MSPort::EscapeFunction()


//API analog
BOOL MSPort::TransmitChar(char a_cChar)
{
   return TransmitCommChar(m_hPort, a_cChar);
}  //MSPort::TransmitChar()


//API analog
BOOL MSPort::WaitEvent(LPDWORD a_pdwEvtMask, LPOVERLAPPED a_pOvrLap)
{
   return WaitCommEvent(m_hPort, a_pdwEvtMask, a_pOvrLap);
}  //MSPort::WaitEvent()


DWORD MSPort::ReadBlock(void* a_pBlock, DWORD a_dwSize)
{
   BOOL       fReadStat;
   COMSTAT    ComStat;
   DWORD      dwErrorFlags, dwLength;

   ClearError(&dwErrorFlags, &ComStat);
   if((dwErrorFlags > 0))
   {
      //###print out the error
      ErrorHandler(eErrorModeRec, ePort_unknown_error);
   }

   dwLength = min(a_dwSize, ComStat.cbInQue);

   if(dwLength > 0)
   {
      fReadStat = Read(a_pBlock, dwLength, &dwLength, &m_osRead);
      if(!fReadStat)
      {
         if(GetLastError() == ERROR_IO_PENDING)
         {
            // wait for a second for this transmission to complete
            if(WaitForSingleObject(m_osRead.hEvent, 1000))
               dwLength = 0;
            else
            {
               GetOverlappedResult(m_hPort,
                                   &m_osRead,
                                   &dwLength, FALSE);
               m_osRead.Offset += dwLength;
            }
         }
         else
            dwLength = 0; // some other error occurred
      }
   }

   return dwLength;
}  //MSPort::ReadBlock()


BOOL MSPort::WriteByte(BYTE a_bByte)
{
   BOOL        fWriteStat ;
   DWORD       dwBytesWritten ;

   fWriteStat = Write((LPSTR)&a_bByte, 1, &dwBytesWritten, &m_osWrite);

   if(!fWriteStat
      && (GetLastError() == ERROR_IO_PENDING))
   {
      // wait for a second for this transmission to complete
      if(WaitForSingleObject(m_osWrite.hEvent, 1000))
         dwBytesWritten = 0 ;
      else
      {
         GetOverlappedResult(m_hPort,
                             &m_osWrite,
                             &dwBytesWritten, FALSE);
         m_osWrite.Offset += dwBytesWritten;
      }
   }

   return TRUE;
}  //MSPort::WriteByte()


BOOL MSPort::InitMembers(void)
{
   m_hPort = NULL;
   m_dwOpenFlags = 0;
   m_caName[0] = '\0';
   m_bEscChar = '\0';

   m_dwCnt = 0;

   return TRUE;
}  //MSPort::InitMembers()


void MSPort::ErrorHandler(eErrorMode a_eErrorMode, WORD a_wErrorNum)
{
   AObject::ErrorHandler(a_eErrorMode, a_wErrorNum, m_uErrRes, m_szClassName);
}      //MSPort::ErrorHandler()


DWORD FAR PASCAL CWatchProc(LPVOID pData)
{
   return ((MSPort*)pData)->WatchProc();
}  //CWatchProc()


DWORD MSPort::WatchProc(void)
{
   DWORD       dwTransfer, dwEvtMask ;
   OVERLAPPED  os ;

   memset( &os, 0, sizeof( OVERLAPPED ) ) ;

   // create I/O event used for overlapped read

   os.hEvent = CreateEvent( NULL,    // no security
                            TRUE,    // explicit reset req
                            FALSE,   // initial event reset
                            NULL ) ; // no name
   if (os.hEvent == NULL)
   {
      MessageBox( NULL, "Failed to create event for thread!", "TTY Error!",
                  MB_ICONEXCLAMATION | MB_OK ) ;
      return ( FALSE ) ;
   }

   if (!SetMask( EV_RXCHAR ))
      return ( FALSE ) ;

   while (m_hPort)
   {
      dwEvtMask = 0 ;

      if (!WaitEvent( &dwEvtMask, &os ))
      {
         if (ERROR_IO_PENDING == GetLastError())
         {
            GetOverlappedResult(m_hPort, &os, &dwTransfer, TRUE ) ;
            os.Offset += dwTransfer ;
         }
      }

      if ((dwEvtMask & EV_RXCHAR) == EV_RXCHAR)
      {
         // wait for "posted notification" flag to clear

         WaitForSingleObject(m_hPostEvent, 0xFFFFFFFF ) ;

         // reset event

         ResetEvent(m_hPostEvent) ;

         // last message was processed, O.K. to post

         PostMessage(m_hwnd1, WM_COMMNOTIFY,
                      (WPARAM)m_hPort,
                      MAKELONG( CN_EVENT, 0 ) ) ;
      }
   }

   // get rid of event handle

   CloseHandle( os.hEvent ) ;

   // clear information in structure (kind of a "we're done flag")

   m_dwThreadID = 0 ;
   m_hWatchThread = NULL ;

   return( TRUE ) ;

}  //WatchProc()


BOOL MSPort::GetNotification(WPARAM a_wParam, LPARAM a_lParam)
{
   int        nLength ;
   BYTE       abIn[ MSPORT_MAXBLOCK + 1] ;
   MSG        msg ;

   // verify that it is a COMM event sent by our thread
   if (CN_EVENT & LOWORD( a_lParam ) != CN_EVENT)
      return ( FALSE ) ;

   // We loop here since it is highly likely that the buffer
   // can been filled while we are reading this block.  This
   // is especially true when operating at high baud rates
   // (e.g. >= 9600 baud).

   do
   {
      if (nLength = ReadBlock((LPSTR)abIn, MSPORT_MAXBLOCK))
      {
         m_dwCnt += nLength;
         m_pFunc( m_hwnd, (LPSTR) abIn, nLength ) ;

         // force a paint

         UpdateWindow( m_hwnd ) ;
      }
   }
   while (!PeekMessage( &msg, NULL, 0, 0, PM_NOREMOVE) || (nLength > 0)) ;

   // clear our "posted notification" flag
   SetEvent(m_hPostEvent);

   return ( TRUE ) ;
}  //MSPort::GetNotification()


void MSPort::WaitOnReceive(DWORD a_dwCnt)
{
   MSG Msg;

   if(a_dwCnt)
   {
      while(GetMessage(&Msg, NULL, 0, UM_RECEIVED))
      {
         TranslateMessage(&Msg);
         DispatchMessage(&Msg);

         if(Msg.message == UM_RECEIVED    //wait for all bytes expected to arrive
            && m_dwCnt == a_dwCnt)
            break;
      }
   }
   else
   {
      m_dwCnt = 0;   //reset received bytes count
   }
}  //MSPort::WaitOnReceive


BOOL MSPort::SignalOnReceive(void)
{
   return PostMessage(NULL, UM_RECEIVED, 0, 0);
}


LRESULT CALLBACK COMMCallback(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
   MSPort* pMSPort;

   switch(LOWORD(uMsg))
   {
      case WM_COMMNOTIFY:
         pMSPort = (MSPort*)GetWindowLong(hwnd, 0);
         pMSPort->GetNotification(wParam, lParam);
         break;

      default:
         return DefWindowProc(hwnd, uMsg, wParam, lParam);
   }

   return 0L;
}      //COMMCallback()

0

Featured Post

Free Gift Card with Acronis Backup Purchase!

Backup any data in any location: local and remote systems, physical and virtual servers, private and public clouds, Macs and PCs, tablets and mobile devices, & more! For limited time only, buy any Acronis backup products and get a FREE Amazon/Best Buy gift card worth up to $200!

Join & Write a Comment

Suggested Solutions

Article by: Rob
Notes 8.5 Archiving Steps and Tips This article covers setting up a Notes archive, and helps understand some of the menu choices making setting up and maintaining a Notes archive file easier.
I previously wrote an article addressing the use of UBCD4WIN and SARDU. All are great, but I have always been an advocate of SARDU. Recently it was suggested that I go back and take a look at Easy2Boot in comparison.
The viewer will learn how to successfully download and install the SARDU utility on Windows 8, without downloading adware.
XMind Plus helps organize all details/aspects of any project from large to small in an orderly and concise manner. If you are working on a complex project, use this micro tutorial to show you how to make a basic flow chart. The software is free when…

772 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

10 Experts available now in Live!

Get 1:1 Help Now