// CommPort.h: interface for the CCommPort class.
//
//////////////////////////////////////////////////////////////////////

#if !defined(AFX_COMMPORT_H__B1615C5E_6BA5_11D3_8AB6_5254AB104A0B__INCLUDED_)
#define AFX_COMMPORT_H__B1615C5E_6BA5_11D3_8AB6_5254AB104A0B__INCLUDED_

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000

#define WM_COMMPORT_COM1_DATA		(WM_USER + 0x230)
#define WM_COMMPORT_COM2_DATA		(WM_USER + 0x231)
#define WM_COMMPORT_COM3_DATA		(WM_USER + 0x232)
#define WM_COMMPORT_COM4_DATA		(WM_USER + 0x233)
#define WM_COMMPORT_LPT1_DATA		(WM_USER + 0x234)
#define WM_COMMPORT_LPT2_DATA		(WM_USER + 0x235)
#define WM_COMMPORT_ERROR			(WM_USER + 0x236)

#define COMMPORT_DATA_SIZE		1024
#define COMMPORT_QUEUE_SIZE		16

struct Data
{
	char * pData;
	int iLength;
};


class CCommPort  
{
public:
	CCommPort();
	virtual ~CCommPort();

	BOOL Open(HWND hWnd, int iBaudRate = CBR_57600, CString strDeviceName = "COM1", UINT uMsg = WM_COMMPORT_COM1_DATA, HANDLE hCommFile = INVALID_HANDLE_VALUE);
	void Close();

	BOOL Write(char * pData, int iLength);
	BOOL Put(char ch);
	BOOL Busy();

	int  GetBaudRate();

	inline BOOL IsConnected()	{	return (m_hCommFile != INVALID_HANDLE_VALUE);	}

public:
	static DWORD WINAPI ReadThreadFunc(LPVOID pParam);
	static DWORD WINAPI WriteThreadFunc(LPVOID pParam);

protected:
	BOOL Prepare(HWND hWnd, int iBaudRate, UINT uMsg);
	void Unprepare();

	BOOL PrepareOverlapped(OVERLAPPED * p);
	void UnprepareOverlapped(OVERLAPPED * p);

	BOOL SetState();

	BOOL SetupReadEvent();
	BOOL HandleReadEvent();

	BOOL SetupCommEvent();
	BOOL HandleCommEvent(BOOL bRetrieveEvent);

	BOOL HandleWriteEvent();

//protected:
public:
	CString m_strDeviceName;
	HANDLE  m_hCommFile;
	DWORD   m_dwReadThreadId;
	DWORD   m_dwWriteThreadId;

	HWND   m_hWnd;		// Window handle to receive multicast data
	UINT   m_uMsg;		// Message to send to window when receive data

	HANDLE m_hReadThread;	// handle to thread that receive data
	HANDLE m_hWriteThread;	// handle to thread that send data

	int m_iBaudRate;

	OVERLAPPED m_overlappedWrite;
	OVERLAPPED m_overlappedRead;
	OVERLAPPED m_overlappedCommEvent;
	DWORD	   m_dwEventMask;

	HANDLE m_hOutputEvent;	// handle to event signaled when output is ready to be shipped
	HANDLE m_hQuitEvent;		// handle to event signaled when quit

	CList<Data *, Data *> m_sendQueue;
	CCriticalSection m_critical;

	char * m_pOverlappedRead;
};

#endif // !defined(AFX_COMMPORT_H__B1615C5E_6BA5_11D3_8AB6_5254AB104A0B__INCLUDED_)
