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 |