Subversion Repositories HomeAutomation

Rev

Details | Last modification | View Log | SVN | RSS feed

Rev Author Line No. Line
270 johboh 1
//  Serial.h - Definition of the CSerial class
2
//
3
//  Copyright (C) 1999-2003 Ramon de Klein (Ramon.de.Klein@ict.nl)
4
//
5
// This library is free software; you can redistribute it and/or
6
// modify it under the terms of the GNU Lesser General Public
7
// License as published by the Free Software Foundation; either
8
// version 2.1 of the License, or (at your option) any later version.
9
// 
10
// This library is distributed in the hope that it will be useful,
11
// but WITHOUT ANY WARRANTY; without even the implied warranty of
12
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13
// Lesser General Public License for more details.
14
// 
15
// You should have received a copy of the GNU Lesser General Public
16
// License along with this library; if not, write to the Free Software
17
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
18
 
19
 
20
#ifndef __SERIAL_H
21
#define __SERIAL_H
22
 
23
 
24
//////////////////////////////////////////////////////////////////////
25
// The SERIAL_DEFAULT_OVERLAPPED defines if the default open mode uses
26
// overlapped I/O. When overlapped I/O is available (normal Win32
27
// platforms) it uses overlapped I/O. Windows CE doesn't allow the use
28
// of overlapped I/O, so it is disabled there by default.
29
 
30
#ifndef SERIAL_DEFAULT_OVERLAPPED
31
#ifndef SERIAL_NO_OVERLAPPED
32
#define SERIAL_DEFAULT_OVERLAPPED   true
33
#else
34
#define SERIAL_DEFAULT_OVERLAPPED   false
35
#endif
36
#endif
37
 
38
 
39
//////////////////////////////////////////////////////////////////////
40
//
41
// CSerial - Win32 wrapper for serial communications
42
//
43
// Serial communication often causes a lot of problems. This class
44
// tries to supply an easy to use interface to deal with serial
45
// devices.
46
//
47
// The class is actually pretty ease to use. You only need to open
48
// the COM-port, where you need to specify the basic serial
49
// communication parameters. You can also choose to setup handshaking
50
// and read timeout behaviour.
51
//
52
// The following serial classes are available:
53
//
54
// CSerial      - Serial communication support.
55
// CSerialEx    - Serial communication with listener thread for events
56
// CSerialSync  - Serial communication with synchronized event handler
57
// CSerialWnd   - Asynchronous serial support, which uses the Win32
58
//                message queue for event notification.
59
// CSerialMFC   - Preferred class to use in MFC-based GUI windows.
60
// 
61
//
62
// Pros:
63
// -----
64
//  - Easy to use (hides a lot of nasty Win32 stuff)
65
//  - Fully ANSI and Unicode aware
66
//
67
// Cons:
68
// -----
69
//  - Little less flexibility then native Win32 API, however you can
70
//    use this API at the same time for features which are missing
71
//    from this class.
72
//  - Incompatible with Windows 95 or Windows NT v3.51 (or earlier),
73
//    because CancelIo isn't support on these platforms. Define the
74
//    SERIAL_NO_CANCELIO macro for support of these platforms as
75
//    well. When this macro is defined, then only time-out values of
76
//    0 or INFINITE are valid.
77
//
78
//
79
// Copyright (C) 1999-2003 Ramon de Klein
80
//                         (Ramon.de.Klein@ict.nl)
81
 
82
class CSerial
83
{
84
// Class enumerations
85
public:
86
    // Communication event
87
    typedef enum
88
    {
89
        EEventUnknown      = -1,            // Unknown event
90
        EEventNone         = 0,             // Event trigged without cause
91
        EEventBreak        = EV_BREAK,      // A break was detected on input
92
        EEventCTS          = EV_CTS,        // The CTS signal changed state
93
        EEventDSR          = EV_DSR,        // The DSR signal changed state
94
        EEventError        = EV_ERR,        // A line-status error occurred
95
        EEventRing         = EV_RING,       // A ring indicator was detected
96
        EEventRLSD         = EV_RLSD,       // The RLSD signal changed state
97
        EEventRecv         = EV_RXCHAR,     // Data is received on input
98
        EEventRcvEv        = EV_RXFLAG,     // Event character was received on input
99
        EEventSend         = EV_TXEMPTY,    // Last character on output was sent
100
        EEventPrinterError = EV_PERR,       // Printer error occured
101
        EEventRx80Full     = EV_RX80FULL,   // Receive buffer is 80 percent full
102
        EEventProviderEvt1 = EV_EVENT1,     // Provider specific event 1
103
        EEventProviderEvt2 = EV_EVENT2,     // Provider specific event 2
104
    }
105
    EEvent;
106
 
107
    // Baudrate
108
    typedef enum
109
    {
110
        EBaudUnknown = -1,          // Unknown
111
        EBaud110     = CBR_110,     // 110 bits/sec
112
        EBaud300     = CBR_300,     // 300 bits/sec
113
        EBaud600     = CBR_600,     // 600 bits/sec
114
        EBaud1200    = CBR_1200,    // 1200 bits/sec
115
        EBaud2400    = CBR_2400,    // 2400 bits/sec
116
        EBaud4800    = CBR_4800,    // 4800 bits/sec
117
        EBaud9600    = CBR_9600,    // 9600 bits/sec
118
        EBaud14400   = CBR_14400,   // 14400 bits/sec
119
        EBaud19200   = CBR_19200,   // 19200 bits/sec (default)
120
        EBaud38400   = CBR_38400,   // 38400 bits/sec
121
        EBaud56000   = CBR_56000,   // 56000 bits/sec
122
        EBaud57600   = CBR_57600,   // 57600 bits/sec
123
        EBaud115200  = CBR_115200,  // 115200 bits/sec
124
        EBaud128000  = CBR_128000,  // 128000 bits/sec
125
        EBaud256000  = CBR_256000,  // 256000 bits/sec
126
    }
127
    EBaudrate;
128
 
129
    // Data bits (5-8)
130
    typedef enum
131
    {
132
        EDataUnknown = -1,          // Unknown
133
        EData5       =  5,          // 5 bits per byte
134
        EData6       =  6,          // 6 bits per byte
135
        EData7       =  7,          // 7 bits per byte
136
        EData8       =  8           // 8 bits per byte (default)
137
    }
138
    EDataBits;
139
 
140
    // Parity scheme
141
    typedef enum
142
    {
143
        EParUnknown = -1,           // Unknown
144
        EParNone    = NOPARITY,     // No parity (default)
145
        EParOdd     = ODDPARITY,    // Odd parity
146
        EParEven    = EVENPARITY,   // Even parity
147
        EParMark    = MARKPARITY,   // Mark parity
148
        EParSpace   = SPACEPARITY   // Space parity
149
    }
150
    EParity;
151
 
152
    // Stop bits
153
    typedef enum
154
    {
155
        EStopUnknown = -1,          // Unknown
156
        EStop1       = ONESTOPBIT,  // 1 stopbit (default)
157
        EStop1_5     = ONE5STOPBITS,// 1.5 stopbit
158
        EStop2       = TWOSTOPBITS  // 2 stopbits
159
    }
160
    EStopBits;
161
 
162
    // Handshaking
163
    typedef enum
164
    {
165
        EHandshakeUnknown       = -1,   // Unknown
166
        EHandshakeOff           =  0,   // No handshaking
167
        EHandshakeHardware      =  1,   // Hardware handshaking (RTS/CTS)
168
        EHandshakeSoftware      =  2    // Software handshaking (XON/XOFF)
169
    }
170
    EHandshake;
171
 
172
    // Timeout settings
173
    typedef enum
174
    {
175
        EReadTimeoutUnknown     = -1,   // Unknown
176
        EReadTimeoutNonblocking =  0,   // Always return immediately
177
        EReadTimeoutBlocking    =  1    // Block until everything is retrieved
178
    }
179
    EReadTimeout;
180
 
181
    // Communication errors
182
    typedef enum
183
    {
184
        EErrorUnknown = 0,          // Unknown
185
        EErrorBreak   = CE_BREAK,   // Break condition detected
186
        EErrorFrame   = CE_FRAME,   // Framing error
187
        EErrorIOE     = CE_IOE,     // I/O device error
188
        EErrorMode    = CE_MODE,    // Unsupported mode
189
        EErrorOverrun = CE_OVERRUN, // Character buffer overrun, next byte is lost
190
        EErrorRxOver  = CE_RXOVER,  // Input buffer overflow, byte lost
191
        EErrorParity  = CE_RXPARITY,// Input parity error
192
        EErrorTxFull  = CE_TXFULL   // Output buffer full
193
    }
194
    EError;
195
 
196
    // Port availability
197
    typedef enum
198
    {
199
        EPortUnknownError = -1,     // Unknown error occurred
200
        EPortAvailable    =  0,     // Port is available
201
        EPortNotAvailable =  1,     // Port is not present
202
        EPortInUse        =  2      // Port is in use
203
 
204
    }
205
    EPort;
206
 
207
// Construction
208
public:
209
    CSerial();
210
    virtual ~CSerial();
211
 
212
// Operations
213
public:
214
    // Check if particular COM-port is available (static method).
215
    static EPort CheckPort (LPCTSTR lpszDevice);
216
 
217
    // Open the serial communications for a particular COM port. You
218
    // need to use the full devicename (i.e. "COM1") to open the port.
219
    // It's possible to specify the size of the input/output queues.
220
    virtual LONG Open (LPCTSTR lpszDevice, DWORD dwInQueue = 0, DWORD dwOutQueue = 0, bool fOverlapped = SERIAL_DEFAULT_OVERLAPPED);
221
 
222
    // Close the serial port.
223
    virtual LONG Close (void);
224
 
225
    // Setup the communication settings such as baudrate, databits,
226
    // parity and stopbits. The default settings are applied when the
227
    // device has been opened. Call this function if these settings do
228
    // not apply for your application. If you prefer to use integers
229
    // instead of the enumerated types then just cast the integer to
230
    // the required type. So the following two initializations are
231
    // equivalent:
232
    //
233
    //   Setup(EBaud9600,EData8,EParNone,EStop1)
234
    //
235
    // or
236
    //
237
    //   Setup(EBaudrate(9600),EDataBits(8),EParity(NOPARITY),EStopBits(ONESTOPBIT))
238
    //
239
    // In the latter case, the types are not validated. So make sure
240
    // that you specify the appropriate values.
241
    virtual LONG Setup (EBaudrate eBaudrate = EBaud9600,
242
                        EDataBits eDataBits = EData8,
243
                        EParity   eParity   = EParNone,
244
                        EStopBits eStopBits = EStop1);
245
 
246
    // Set/clear the event character. When this byte is being received
247
    // on the serial port then the EEventRcvEv event is signalled,
248
    // when the mask has been set appropriately. If the fAdjustMask flag
249
    // has been set, then the event mask is automatically adjusted.
250
    virtual LONG SetEventChar (BYTE bEventChar, bool fAdjustMask = true);
251
 
252
    // Set the event mask, which indicates what events should be
253
    // monitored. The WaitEvent method can only monitor events that
254
    // have been enabled. The default setting only monitors the
255
    // error events and data events. An application may choose to
256
    // monitor CTS. DSR, RLSD, etc as well.
257
    virtual LONG SetMask (DWORD dwMask = EEventBreak|EEventError|EEventRecv);
258
 
259
    // The WaitEvent method waits for one of the events that are
260
    // enabled (see SetMask).
261
    virtual LONG WaitEvent (LPOVERLAPPED lpOverlapped = 0, DWORD dwTimeout = INFINITE);
262
 
263
    // Setup the handshaking protocol. There are three forms of
264
    // handshaking:
265
    //
266
    // 1) No handshaking, so data is always send even if the receiver
267
    //    cannot handle the data anymore. This can lead to data loss,
268
    //    when the sender is able to transmit data faster then the
269
    //    receiver can handle.
270
    // 2) Hardware handshaking, where the RTS/CTS lines are used to
271
    //    indicate if data can be sent. This mode requires that both
272
    //    ports and the cable support hardware handshaking. Hardware
273
    //    handshaking is the most reliable and efficient form of
274
    //    handshaking available, but is hardware dependant.
275
    // 3) Software handshaking, where the XON/XOFF characters are used
276
    //    to throttle the data. A major drawback of this method is that
277
    //    these characters cannot be used for data anymore.
278
    virtual LONG SetupHandshaking (EHandshake eHandshake);
279
 
280
    // Read operations can be blocking or non-blocking. You can use
281
    // this method to setup wether to use blocking or non-blocking
282
    // reads. Non-blocking reads is the default, which is required
283
    // for most applications.
284
    //
285
    // 1) Blocking reads, which will cause the 'Read' method to block
286
    //    until the requested number of bytes have been read. This is
287
    //    useful if you know how many data you will receive.
288
    // 2) Non-blocking reads, which will read as many bytes into your
289
    //    buffer and returns almost immediately. This is often the
290
    //    preferred setting.
291
    virtual LONG SetupReadTimeouts (EReadTimeout eReadTimeout);
292
 
293
    // Obtain communication settings
294
    virtual EBaudrate  GetBaudrate    (void);
295
    virtual EDataBits  GetDataBits    (void);
296
    virtual EParity    GetParity      (void);
297
    virtual EStopBits  GetStopBits    (void);
298
    virtual EHandshake GetHandshaking (void);
299
    virtual DWORD      GetEventMask   (void);
300
    virtual BYTE       GetEventChar   (void);
301
 
302
    // Write data to the serial port. Note that we are only able to
303
    // send ANSI strings, because it probably doesn't make sense to
304
    // transmit Unicode strings to an application.
305
    virtual LONG Write (const void* pData, size_t iLen, DWORD* pdwWritten = 0, LPOVERLAPPED lpOverlapped = 0, DWORD dwTimeout = INFINITE);
306
    virtual LONG Write (LPCSTR pString, DWORD* pdwWritten = 0, LPOVERLAPPED lpOverlapped = 0, DWORD dwTimeout = INFINITE);
307
 
308
    // Read data from the serial port. Refer to the description of
309
    // the 'SetupReadTimeouts' for an explanation about (non) blocking
310
    // reads and how to use this.
311
    virtual LONG Read (void* pData, size_t iLen, DWORD* pdwRead = 0, LPOVERLAPPED lpOverlapped = 0, DWORD dwTimeout = INFINITE);
312
 
313
    // Send a break
314
    LONG Break (void);
315
 
316
    // Determine what caused the event to trigger
317
    EEvent GetEventType (void);
318
 
319
    // Obtain the error
320
    EError GetError (void);
321
 
322
    // Obtain the COMM and event handle
323
    HANDLE GetCommHandle (void)     { return m_hFile; }
324
 
325
    // Check if com-port is opened
326
    bool IsOpen (void) const        { return (m_hFile != 0); }
327
 
328
    // Obtain last error status
329
    LONG GetLastError (void) const  { return m_lLastError; }
330
 
331
    // Obtain CTS/DSR/RING/RLSD settings
332
    bool GetCTS (void);
333
    bool GetDSR (void);
334
    bool GetRing (void);
335
    bool GetRLSD (void);
336
 
337
    // Purge all buffers
338
    LONG Purge (void);
339
 
340
protected:
341
    // Internal helper class which wraps DCB structure
342
    class CDCB : public DCB
343
    {
344
    public:
345
        CDCB() { DCBlength = sizeof(DCB); }
346
    };
347
 
348
// Attributes
349
protected:
350
    LONG    m_lLastError;       // Last serial error
351
    HANDLE  m_hFile;            // File handle
352
    EEvent  m_eEvent;           // Event type
353
    DWORD   m_dwEventMask;      // Event mask
354
 
355
#ifndef SERIAL_NO_OVERLAPPED
356
    HANDLE  m_hevtOverlapped;   // Event handle for internal overlapped operations
357
#endif
358
 
359
protected:
360
    // Check the requirements
361
    void CheckRequirements (LPOVERLAPPED lpOverlapped, DWORD dwTimeout) const;
362
 
363
    // CancelIo wrapper (for Win95 compatibility)
364
    BOOL CancelCommIo (void);
365
};
366
 
367
#endif  // __SERIAL_H