/*
 * File:      wxSerial.h
 * Purpose:   Serial port class header file
 * Author:    George Tasker
 * Created:   30-05-1997
 */


/* static const char sccsid[] = "%W% %G%"; */


#ifndef WXSERIAL_DOT_H
#define WXSERIAL_DOT_H

#define USING_WXWINDOWS 1

#if USING_WXWINDOWS
#include <windows.h>
#endif

// Used for interrupt driven notification
#define WM_COMMNOTIFY 0x0044
#define CN_EVENT 0x04

// Used to identify the buffer that an operation such as Flush or Abort
// is to be performed on
const int wxSERIAL_TX   = 1;
const int wxSERIAL_RX   = 2;
const int wxSERIAL_BOTH = wxSERIAL_TX | wxSERIAL_RX;


// Baud rate constants
enum wxBaud {wxBAUD_150   =   150, wxBAUD_300    =    300, wxBAUD_600    =    600,
             wxBAUD_1200  =  1200, wxBAUD_2400   =   2400, wxBAUD_4800   =   4800, 
             wxBAUD_9600  =  9600, wxBAUD_19200  =  19200, wxBAUD_38400  =  38400, 
             wxBAUD_57600 = 57600, wxBAUD_115200 = 115200};


// Parity values
enum wxParity {wxPARITY_NONE=0, wxPARITY_ODD, wxPARITY_EVEN, wxPARITY_MARK, wxPARITY_SPACE};

struct wxCommTimeouts
{
    DWORD   readTimeoutConstant;
    DWORD   readIntervalTimeout;
    DWORD   readTimeoutMultiplier;
    DWORD   writeTimeoutConstant;
    DWORD   writeTimeoutMultiplier;
    DWORD   overlappedTimeout;
};

// Default XON/XOFF characters
#ifndef IXON
    #define IXON 17;
#endif
#ifndef IXOFF
    #define IXOFF 19;
#endif

// wxSerial Error Codes
#define wxSERIAL_PORT_IS_ALREADY_OPEN              1
#define wxSERIAL_PORT_IS_NOT_OPEN                  2
#define wxSERIAL_PORT_IS_NOT_NAMED                 3
#define wxSERIAL_COULD_NOT_OPEN_PORT               4
#define wxSERIAL_CANNOT_CREATE_PORT_SETTINGS       5
#define wxSERIAL_CANNOT_CHANGE_PORT_SETTINGS       6
#define wxSERIAL_CANNOT_ALLOCATE_BUFFERS           7
#define wxSERIAL_READ_ERROR                         8

// Windows specific
#define wxSERIAL_CANNOT_CREATE_READ_EVENT       1000
#define wxSERIAL_CANNOT_CREATE_WRITE_EVENT  1001
#define wxSERIAL_CANNOT_CREATE_POST_EVENT       1002
#define wxSERIAL_CANNOT_INIT_THREAD             1003


// Forward declaration
class wxSerial;


class wxSerial_CallBack
{
    public:
        virtual int DoCallBack(wxSerial *port);
};  


typedef struct COMMSETTINGS
{
    public:
        int  baudRate;
        char parity;
        int  wordLen;
        int  stopBits;
} CommSettings;


typedef struct THREADINFO
{
    public:
        HANDLE               id;
        char                *portName;
        DCB                 *dcb;

        // For use with interrupt driven communication
        HWND                 hPostWnd;
        bool                 connected;
        DWORD                threadId;
        OVERLAPPED           osWrite, osRead;
        HANDLE               hPostEvent;
        HANDLE               hCommWatchThread;
        int                  softEnable;
        wxSerial_CallBack   *cb;
} ThreadInfo;


class wxSerial 
{
    friend               class wxSerial_CallBack;

    private:
        int              lastErrorCode;
        bool             toggleRTS;
        int              delayForRTS;
        bool             usingCTS;
        bool             usingDSR;
        bool             usingXonXoff;

        void             setError(int errorCode);

    public:
        DWORD            timeoutVal;
        ThreadInfo       info;

                         wxSerial(char *name); 
                        ~wxSerial();

        int              GetError() { return lastErrorCode; };
        const char      *GetErrorText();

        bool             ChangeSettings(wxBaud baudRate, wxParity parity, int wordLen, byte stopBits);
        void             GetSettings(CommSettings *cs);
		  const char *		 GetPortName() {  return info.portName; };

        bool             Close();
        bool             Create(char *name);
        bool             IsOpen();
        bool             Open(wxBaud baudRate=wxBAUD_4800, wxParity parity=wxPARITY_NONE, int wordLen=8, byte stopBits=1, int inSize=1024, int outSize=512, int RTSdelay=2);

        bool             Abort(int buffer=wxSERIAL_BOTH);
        bool             Break(bool setting);
        bool             Flush(int buffer=wxSERIAL_BOTH);
        int              Read(char *data, int maxLen=1);  
        int              Read(char *data, int maxLen, int termChar, bool includeTerm=TRUE);
        int              Write(char data, bool lastByte=TRUE, bool calledFromWrite2=FALSE);
        int              Write(DWORD len, const char *data);
        bool             Xon();
        bool             Xoff();

        DWORD            PendingIn();
        DWORD            PendingOut();

        bool             SetDTR(bool setting);
        bool             SetRTS(bool setting);
        void             SetRTSDelay(int delay);
        bool             SetTimeouts(DWORD timeout);
        bool             SetTimeouts(wxCommTimeouts timeouts);
        void             ToggleRTS(bool setting);

        void             UseCTS(bool setting) 
                            { wxMessageBox("UseCTS is still not written","DEBUG"); };
        
        void             UseDSR(bool setting)
                            { wxMessageBox("UseDSR is still not written","DEBUG"); };

        void             UseXonXoff(bool setting, char xonChar=(char)17, char xoffChar=(char)19)
                            { wxMessageBox("UseXonXoff is still not written","DEBUG"); };

        // Methods for doing interrupt driven event handling (not complete)
        bool             Enable(HWND hwnd);
        void             Enable ();
        void             Disable();
        void             SetCallBack(wxSerial_CallBack *scb);
};

#endif

