1 /*!
2 \class Win_QextSerialPort
3 \version 1.0.0
4 \author Stefan Sander
5 
6 A cross-platform serial port class.
7 This class encapsulates the Windows portion of QextSerialPort.  The user will be notified of
8 errors and possible portability conflicts at run-time by default - this behavior can be turned
9 off by defining _TTY_NOWARN_ (to turn off all warnings) or _TTY_NOWARN_PORT_ (to turn off
10 portability warnings) in the project.  Note that defining _TTY_NOWARN_ also defines
11 _TTY_NOWARN_PORT_.
12 
13 \note
14 On Windows NT/2000/XP this class uses Win32 serial port functions by default.  The user may
15 select POSIX behavior under NT, 2000, or XP ONLY by defining _TTY_POSIX_ in the project. I can
16 make no guarantees as to the quality of POSIX support under NT/2000 however.
17 
18 */
19 
20 #include <stdio.h>
21 #include "win_qextserialport.h"
22 
23 /*!
24 \fn Win_QextSerialPort::Win_QextSerialPort()
25 Default constructor.  Note that the name of the device used by a Win_QextSerialPort constructed
26 with this constructor will be determined by #defined constants, or lack thereof - the default
27 behavior is the same as _TTY_LINUX_.  Possible naming conventions and their associated constants
28 are:
29 
30 \verbatim
31 
32 Constant         Used By         Naming Convention
33 ----------       -------------   ------------------------
34 _TTY_WIN_        Windows         COM1, COM2
35 _TTY_IRIX_       SGI/IRIX        /dev/ttyf1, /dev/ttyf2
36 _TTY_HPUX_       HP-UX           /dev/tty1p0, /dev/tty2p0
37 _TTY_SUN_        SunOS/Solaris   /dev/ttya, /dev/ttyb
38 _TTY_DIGITAL_    Digital UNIX    /dev/tty01, /dev/tty02
39 _TTY_FREEBSD_    FreeBSD         /dev/ttyd0, /dev/ttyd1
40 _TTY_LINUX_      Linux           /dev/ttyS0, /dev/ttyS1
41 <none>           Linux           /dev/ttyS0, /dev/ttyS1
42 \endverbatim
43 
44 This constructor associates the object with the first port on the system, e.g. COM1 for Windows
45 platforms.  See the other constructor if you need a port other than the first.
46 */
Win_QextSerialPort()47 Win_QextSerialPort::Win_QextSerialPort():QextSerialBase() {
48     Win_Handle=INVALID_HANDLE_VALUE;
49 }
50 
51 /*!Win_QextSerialPort::Win_QextSerialPort(const Win_QextSerialPort&)
52 Copy constructor.
53 */
Win_QextSerialPort(const Win_QextSerialPort & s)54 Win_QextSerialPort::Win_QextSerialPort(const Win_QextSerialPort& s):QextSerialBase(s.port) {
55     Win_Handle=INVALID_HANDLE_VALUE;
56     setOpenMode(s.openMode());
57     lastErr=s.lastErr;
58     port = s.port;
59     Settings.FlowControl=s.Settings.FlowControl;
60     Settings.Parity=s.Settings.Parity;
61     Settings.DataBits=s.Settings.DataBits;
62     Settings.StopBits=s.Settings.StopBits;
63     Settings.BaudRate=s.Settings.BaudRate;
64     Win_Handle=s.Win_Handle;
65     memcpy(&Win_CommConfig, &s.Win_CommConfig, sizeof(COMMCONFIG));
66     memcpy(&Win_CommTimeouts, &s.Win_CommTimeouts, sizeof(COMMTIMEOUTS));
67 }
68 
69 /*!
70 \fn Win_QextSerialPort::Win_QextSerialPort(const QString & name)
71 Constructs a serial port attached to the port specified by devName.
72 devName is the name of the device, which is windowsystem-specific,
73 e.g."COM2" or "/dev/ttyS0".
74 */
Win_QextSerialPort(const QString & name)75 Win_QextSerialPort::Win_QextSerialPort(const QString & name):QextSerialBase(name) {
76     Win_Handle=INVALID_HANDLE_VALUE;
77 }
78 
79 /*!
80 \fn Win_QextSerialPort::Win_QextSerialPort(const PortSettings& settings)
81 Constructs a port with default name and specified settings.
82 */
Win_QextSerialPort(const PortSettings & settings)83 Win_QextSerialPort::Win_QextSerialPort(const PortSettings& settings) {
84     Win_Handle=INVALID_HANDLE_VALUE;
85     setBaudRate(settings.BaudRate);
86     setDataBits(settings.DataBits);
87     setStopBits(settings.StopBits);
88     setParity(settings.Parity);
89     setFlowControl(settings.FlowControl);
90     setTimeout(settings.Timeout_Sec, settings.Timeout_Millisec);
91 }
92 
93 /*!
94 \fn Win_QextSerialPort::Win_QextSerialPort(const QString & name, const PortSettings& settings)
95 Constructs a port with specified name and settings.
96 */
Win_QextSerialPort(const QString & name,const PortSettings & settings)97 Win_QextSerialPort::Win_QextSerialPort(const QString & name, const PortSettings& settings) {
98     Win_Handle=INVALID_HANDLE_VALUE;
99     setPortName(name);
100     setBaudRate(settings.BaudRate);
101     setDataBits(settings.DataBits);
102     setStopBits(settings.StopBits);
103     setParity(settings.Parity);
104     setFlowControl(settings.FlowControl);
105     setTimeout(settings.Timeout_Sec, settings.Timeout_Millisec);
106 }
107 
108 /*!
109 \fn Win_QextSerialPort::~Win_QextSerialPort()
110 Standard destructor.
111 */
~Win_QextSerialPort()112 Win_QextSerialPort::~Win_QextSerialPort() {
113     if (isOpen()) {
114         close();
115     }
116 }
117 
118 /*!
119 \fn Win_QextSerialPort& Win_QextSerialPort::operator=(const Win_QextSerialPort& s)
120 overrides the = operator
121 */
operator =(const Win_QextSerialPort & s)122 Win_QextSerialPort& Win_QextSerialPort::operator=(const Win_QextSerialPort& s) {
123     setOpenMode(s.openMode());
124     lastErr=s.lastErr;
125     port = s.port;
126     Settings.FlowControl=s.Settings.FlowControl;
127     Settings.Parity=s.Settings.Parity;
128     Settings.DataBits=s.Settings.DataBits;
129     Settings.StopBits=s.Settings.StopBits;
130     Settings.BaudRate=s.Settings.BaudRate;
131     Win_Handle=s.Win_Handle;
132     memcpy(&Win_CommConfig, &s.Win_CommConfig, sizeof(COMMCONFIG));
133     memcpy(&Win_CommTimeouts, &s.Win_CommTimeouts, sizeof(COMMTIMEOUTS));
134     return *this;
135 }
136 
137 /*!
138 \fn bool Win_QextSerialPort::open(OpenMode mode)
139 Opens a serial port.  Note that this function does not specify which device to open.  If you need
140 to open a device by name, see Win_QextSerialPort::open(const char*).  This function has no effect
141 if the port associated with the class is already open.  The port is also configured to the current
142 settings, as stored in the Settings structure.
143 */
open(OpenMode mode)144 bool Win_QextSerialPort::open(OpenMode mode) {
145     //unsigned long confSize = sizeof(COMMCONFIG);
146     //Win_CommConfig.dwSize = confSize;
147 
148     LOCK_MUTEX();
149     if (mode == QIODevice::NotOpen)
150         return isOpen();
151     if (!isOpen()) {
152         /*open the port*/
153         Win_Handle=CreateFileW((LPCWSTR)port.utf16(), GENERIC_READ|GENERIC_WRITE,
154                               0, NULL, OPEN_EXISTING, 0, NULL);
155         if (Win_Handle!=INVALID_HANDLE_VALUE) {
156             /*set open mode*/
157             QIODevice::open(mode);
158 
159             /*configure port settings*/
160             //GetCommConfig(Win_Handle, &Win_CommConfig, &confSize);
161             GetCommState(Win_Handle, &(Win_CommConfig));
162 
163             /*set up parameters*/
164             Win_CommConfig.fBinary=TRUE;
165             Win_CommConfig.fInX=FALSE;
166             Win_CommConfig.fOutX=FALSE;
167             Win_CommConfig.fAbortOnError=FALSE;
168             Win_CommConfig.fNull=FALSE;
169             setBaudRate(Settings.BaudRate);
170             setDataBits(Settings.DataBits);
171             setStopBits(Settings.StopBits);
172             setParity(Settings.Parity);
173             setFlowControl(Settings.FlowControl);
174             setTimeout(Settings.Timeout_Sec, Settings.Timeout_Millisec);
175             //SetCommConfig(Win_Handle, &Win_CommConfig, sizeof(COMMCONFIG));
176             SetCommState(Win_Handle, &Win_CommConfig);
177         } else 		{
178             qDebug("Device handle failed with error : %d\n", (int)GetLastError());
179         }
180     }
181     UNLOCK_MUTEX();
182     return isOpen();
183 }
184 
185 /*!
186 \fn void Win_QextSerialPort::close()
187 Closes a serial port.  This function has no effect if the serial port associated with the class
188 is not currently open.
189 */
close()190 void Win_QextSerialPort::close() {
191     LOCK_MUTEX();
192     CloseHandle(Win_Handle);
193     QIODevice::close();
194     UNLOCK_MUTEX();
195 }
196 
197 /*!
198 \fn void Win_QextSerialPort::flush()
199 Flushes all pending I/O to the serial port.  This function has no effect if the serial port
200 associated with the class is not currently open.
201 */
flush()202 void Win_QextSerialPort::flush() {
203     LOCK_MUTEX();
204     if (isOpen()) {
205         FlushFileBuffers(Win_Handle);
206     }
207     UNLOCK_MUTEX();
208 }
209 
210 /*!
211 \fn qint64 Win_QextSerialPort::size() const
212 This function will return the number of bytes waiting in the receive queue of the serial port.
213 It is included primarily to provide a complete QIODevice interface, and will not record errors
214 in the lastErr member (because it is const).  This function is also not thread-safe - in
215 multithreading situations, use Win_QextSerialPort::bytesAvailable() instead.
216 */
size() const217 qint64 Win_QextSerialPort::size() const {
218     int availBytes;
219     COMSTAT Win_ComStat;
220     DWORD Win_ErrorMask=0;
221     ClearCommError(Win_Handle, &Win_ErrorMask, &Win_ComStat);
222     availBytes = Win_ComStat.cbInQue;
223     return (qint64)availBytes;
224 }
225 
226 /*!
227 \fn qint64 Win_QextSerialPort::bytesAvailable()
228 Returns the number of bytes waiting in the port's receive queue.  This function will return 0 if
229 the port is not currently open, or -1 on error.  Error information can be retrieved by calling
230 Win_QextSerialPort::getLastError().
231 */
bytesAvailable()232 qint64 Win_QextSerialPort::bytesAvailable() {
233     LOCK_MUTEX();
234     if (isOpen()) {
235         DWORD Errors;
236         COMSTAT Status;
237         bool success=ClearCommError(Win_Handle, &Errors, &Status);
238         translateError(Errors);
239         if (success) {
240             lastErr=E_NO_ERROR;
241             UNLOCK_MUTEX();
242             return Status.cbInQue + QIODevice::bytesAvailable();
243         }
244         UNLOCK_MUTEX();
245         return (int)-1;
246     }
247     UNLOCK_MUTEX();
248     return 0;
249 }
250 
251 /*!
252 \fn void Win_QextSerialPort::translateError(ulong error)
253 Translates a system-specific error code to a QextSerialPort error code.  Used internally.
254 */
translateError(ulong error)255 void Win_QextSerialPort::translateError(ulong error) {
256     if (error&CE_BREAK) {
257         lastErr=E_BREAK_CONDITION;
258     }
259     else if (error&CE_FRAME) {
260         lastErr=E_FRAMING_ERROR;
261     }
262     else if (error&CE_IOE) {
263         lastErr=E_IO_ERROR;
264     }
265     else if (error&CE_MODE) {
266         lastErr=E_INVALID_FD;
267     }
268     else if (error&CE_OVERRUN) {
269         lastErr=E_BUFFER_OVERRUN;
270     }
271     else if (error&CE_RXPARITY) {
272         lastErr=E_RECEIVE_PARITY_ERROR;
273     }
274     else if (error&CE_RXOVER) {
275         lastErr=E_RECEIVE_OVERFLOW;
276     }
277     else if (error&CE_TXFULL) {
278         lastErr=E_TRANSMIT_OVERFLOW;
279     }
280 }
281 
282 /*!
283 \fn qint64 Win_QextSerialPort::readData(char *data, qint64 maxSize)
284 Reads a block of data from the serial port.  This function will read at most maxlen bytes from
285 the serial port and place them in the buffer pointed to by data.  Return value is the number of
286 bytes actually read, or -1 on error.
287 
288 \warning before calling this function ensure that serial port associated with this class
289 is currently open (use isOpen() function to check if port is open).
290 */
readData(char * data,qint64 maxSize)291 qint64 Win_QextSerialPort::readData(char *data, qint64 maxSize)
292 {
293     LOCK_MUTEX();
294     int retVal=0;
295     COMSTAT Win_ComStat;
296     DWORD Win_BytesRead=0;
297     DWORD Win_ErrorMask=0;
298     ClearCommError(Win_Handle, &Win_ErrorMask, &Win_ComStat);
299     if (Win_ComStat.cbInQue &&
300         (!ReadFile(Win_Handle, (void*)data, (DWORD)maxSize, &Win_BytesRead, NULL)
301         || Win_BytesRead==0)) {
302         lastErr=E_READ_FAILED;
303         retVal=-1;
304     }
305     else {
306         retVal=((int)Win_BytesRead);
307     }
308     UNLOCK_MUTEX();
309 
310     return retVal;
311 }
312 
313 /*!
314 \fn qint64 Win_QextSerialPort::writeData(const char *data, qint64 maxSize)
315 Writes a block of data to the serial port.  This function will write len bytes
316 from the buffer pointed to by data to the serial port.  Return value is the number
317 of bytes actually written, or -1 on error.
318 
319 \warning before calling this function ensure that serial port associated with this class
320 is currently open (use isOpen() function to check if port is open).
321 */
writeData(const char * data,qint64 maxSize)322 qint64 Win_QextSerialPort::writeData(const char *data, qint64 maxSize)
323 {
324     LOCK_MUTEX();
325     int retVal=0;
326     DWORD Win_BytesWritten;
327     if (!WriteFile(Win_Handle, (void*)data, (DWORD)maxSize, &Win_BytesWritten, NULL)) {
328         lastErr=E_WRITE_FAILED;
329         retVal=-1;
330     }
331     else {
332         retVal=((int)Win_BytesWritten);
333     }
334     UNLOCK_MUTEX();
335 
336     flush();
337     return retVal;
338 }
339 
340 /*!
341 \fn void Win_QextSerialPort::ungetChar(char c)
342 This function is included to implement the full QIODevice interface, and currently has no
343 purpose within this class.  This function is meaningless on an unbuffered device and currently
344 only prints a warning message to that effect.
345 */
ungetChar(char c)346 void Win_QextSerialPort::ungetChar(char c) {
347     Q_UNUSED(c);
348     /*meaningless on unbuffered sequential device - return error and print a warning*/
349     TTY_WARNING("Win_QextSerialPort: ungetChar() called on an unbuffered sequential device - operation is meaningless");
350 }
351 
352 /*!
353 \fn void Win_QextSerialPort::setFlowControl(FlowType flow)
354 Sets the flow control used by the port.  Possible values of flow are:
355 \verbatim
356     FLOW_OFF            No flow control
357     FLOW_HARDWARE       Hardware (RTS/CTS) flow control
358     FLOW_XONXOFF        Software (XON/XOFF) flow control
359 \endverbatim
360 */
setFlowControl(FlowType flow)361 void Win_QextSerialPort::setFlowControl(FlowType flow) {
362     LOCK_MUTEX();
363     if (Settings.FlowControl!=flow) {
364         Settings.FlowControl=flow;
365     }
366     if (isOpen()) {
367         switch(flow) {
368 
369             /*no flow control*/
370             case FLOW_OFF:
371                 Win_CommConfig.fOutxCtsFlow=FALSE;
372                 Win_CommConfig.fRtsControl=RTS_CONTROL_DISABLE;
373                 Win_CommConfig.fInX=FALSE;
374                 Win_CommConfig.fOutX=FALSE;
375                 SetCommState(Win_Handle, &Win_CommConfig);
376                 break;
377 
378             /*software (XON/XOFF) flow control*/
379             case FLOW_XONXOFF:
380                 Win_CommConfig.fOutxCtsFlow=FALSE;
381                 Win_CommConfig.fRtsControl=RTS_CONTROL_DISABLE;
382                 Win_CommConfig.fInX=TRUE;
383                 Win_CommConfig.fOutX=TRUE;
384                 SetCommState(Win_Handle, &Win_CommConfig);
385                 break;
386 
387             case FLOW_HARDWARE:
388                 Win_CommConfig.fOutxCtsFlow=TRUE;
389                 Win_CommConfig.fRtsControl=RTS_CONTROL_HANDSHAKE;
390                 Win_CommConfig.fInX=FALSE;
391                 Win_CommConfig.fOutX=FALSE;
392                 SetCommState(Win_Handle, &Win_CommConfig);
393                 break;
394         }
395     }
396     UNLOCK_MUTEX();
397 }
398 
399 /*!
400 \fn void Win_QextSerialPort::setParity(ParityType parity)
401 Sets the parity associated with the serial port.  The possible values of parity are:
402 \verbatim
403     PAR_SPACE       Space Parity
404     PAR_MARK        Mark Parity
405     PAR_NONE        No Parity
406     PAR_EVEN        Even Parity
407     PAR_ODD         Odd Parity
408 \endverbatim
409 */
setParity(ParityType parity)410 void Win_QextSerialPort::setParity(ParityType parity) {
411     LOCK_MUTEX();
412     if (Settings.Parity!=parity) {
413         Settings.Parity=parity;
414     }
415     if (isOpen()) {
416         Win_CommConfig.Parity=(unsigned char)parity;
417         switch (parity) {
418 
419             /*space parity*/
420             case PAR_SPACE:
421                 if (Settings.DataBits==DATA_8) {
422                     TTY_PORTABILITY_WARNING("Win_QextSerialPort Portability Warning: Space parity with 8 data bits is not supported by POSIX systems.");
423                 }
424                 Win_CommConfig.fParity=TRUE;
425                 break;
426 
427             /*mark parity - WINDOWS ONLY*/
428             case PAR_MARK:
429                 TTY_PORTABILITY_WARNING("Win_QextSerialPort Portability Warning:  Mark parity is not supported by POSIX systems");
430                 Win_CommConfig.fParity=TRUE;
431                 break;
432 
433             /*no parity*/
434             case PAR_NONE:
435                 Win_CommConfig.fParity=FALSE;
436                 break;
437 
438             /*even parity*/
439             case PAR_EVEN:
440                 Win_CommConfig.fParity=TRUE;
441                 break;
442 
443             /*odd parity*/
444             case PAR_ODD:
445                 Win_CommConfig.fParity=TRUE;
446                 break;
447         }
448         SetCommState(Win_Handle, &Win_CommConfig);
449     }
450     UNLOCK_MUTEX();
451 }
452 
453 /*!
454 \fn void Win_QextSerialPort::setDataBits(DataBitsType dataBits)
455 Sets the number of data bits used by the serial port.  Possible values of dataBits are:
456 \verbatim
457     DATA_5      5 data bits
458     DATA_6      6 data bits
459     DATA_7      7 data bits
460     DATA_8      8 data bits
461 \endverbatim
462 
463 \note
464 This function is subject to the following restrictions:
465 \par
466     5 data bits cannot be used with 2 stop bits.
467 \par
468     1.5 stop bits can only be used with 5 data bits.
469 \par
470     8 data bits cannot be used with space parity on POSIX systems.
471 
472 */
setDataBits(DataBitsType dataBits)473 void Win_QextSerialPort::setDataBits(DataBitsType dataBits) {
474     LOCK_MUTEX();
475     if (Settings.DataBits!=dataBits) {
476         if ((Settings.StopBits==STOP_2 && dataBits==DATA_5) ||
477             (Settings.StopBits==STOP_1_5 && dataBits!=DATA_5)) {
478         }
479         else {
480             Settings.DataBits=dataBits;
481         }
482     }
483     if (isOpen()) {
484         switch(dataBits) {
485 
486             /*5 data bits*/
487             case DATA_5:
488                 if (Settings.StopBits==STOP_2) {
489                     TTY_WARNING("Win_QextSerialPort: 5 Data bits cannot be used with 2 stop bits.");
490                 }
491                 else {
492                     Win_CommConfig.ByteSize=5;
493                     SetCommState(Win_Handle, &Win_CommConfig);
494                 }
495                 break;
496 
497             /*6 data bits*/
498             case DATA_6:
499                 if (Settings.StopBits==STOP_1_5) {
500                     TTY_WARNING("Win_QextSerialPort: 6 Data bits cannot be used with 1.5 stop bits.");
501                 }
502                 else {
503                     Win_CommConfig.ByteSize=6;
504                     SetCommState(Win_Handle, &Win_CommConfig);
505                 }
506                 break;
507 
508             /*7 data bits*/
509             case DATA_7:
510                 if (Settings.StopBits==STOP_1_5) {
511                     TTY_WARNING("Win_QextSerialPort: 7 Data bits cannot be used with 1.5 stop bits.");
512                 }
513                 else {
514                     Win_CommConfig.ByteSize=7;
515                     SetCommState(Win_Handle, &Win_CommConfig);
516                 }
517                 break;
518 
519             /*8 data bits*/
520             case DATA_8:
521                 if (Settings.StopBits==STOP_1_5) {
522                     TTY_WARNING("Win_QextSerialPort: 8 Data bits cannot be used with 1.5 stop bits.");
523                 }
524                 else {
525                     Win_CommConfig.ByteSize=8;
526                     SetCommState(Win_Handle, &Win_CommConfig);
527                 }
528                 break;
529         }
530     }
531     UNLOCK_MUTEX();
532 }
533 
534 /*!
535 \fn void Win_QextSerialPort::setStopBits(StopBitsType stopBits)
536 Sets the number of stop bits used by the serial port.  Possible values of stopBits are:
537 \verbatim
538     STOP_1      1 stop bit
539     STOP_1_5    1.5 stop bits
540     STOP_2      2 stop bits
541 \endverbatim
542 
543 \note
544 This function is subject to the following restrictions:
545 \par
546     2 stop bits cannot be used with 5 data bits.
547 \par
548     1.5 stop bits cannot be used with 6 or more data bits.
549 \par
550     POSIX does not support 1.5 stop bits.
551 */
setStopBits(StopBitsType stopBits)552 void Win_QextSerialPort::setStopBits(StopBitsType stopBits) {
553     LOCK_MUTEX();
554     if (Settings.StopBits!=stopBits) {
555         if ((Settings.DataBits==DATA_5 && stopBits==STOP_2) ||
556             (stopBits==STOP_1_5 && Settings.DataBits!=DATA_5)) {
557         }
558         else {
559             Settings.StopBits=stopBits;
560         }
561     }
562     if (isOpen()) {
563         switch (stopBits) {
564 
565             /*one stop bit*/
566             case STOP_1:
567                 Win_CommConfig.StopBits=ONESTOPBIT;
568                 SetCommState(Win_Handle, &Win_CommConfig);
569                 break;
570 
571             /*1.5 stop bits*/
572             case STOP_1_5:
573                 TTY_PORTABILITY_WARNING("Win_QextSerialPort Portability Warning: 1.5 stop bit operation is not supported by POSIX.");
574                 if (Settings.DataBits!=DATA_5) {
575                     TTY_WARNING("Win_QextSerialPort: 1.5 stop bits can only be used with 5 data bits");
576                 }
577                 else {
578                     Win_CommConfig.StopBits=ONE5STOPBITS;
579                     SetCommState(Win_Handle, &Win_CommConfig);
580                 }
581                 break;
582 
583             /*two stop bits*/
584             case STOP_2:
585                 if (Settings.DataBits==DATA_5) {
586                     TTY_WARNING("Win_QextSerialPort: 2 stop bits cannot be used with 5 data bits");
587                 }
588                 else {
589                     Win_CommConfig.StopBits=TWOSTOPBITS;
590                     SetCommState(Win_Handle, &Win_CommConfig);
591                 }
592                 break;
593         }
594     }
595     UNLOCK_MUTEX();
596 }
597 
598 /*!
599 \fn void Win_QextSerialPort::setBaudRate(BaudRateType baudRate)
600 Sets the baud rate of the serial port.  Note that not all rates are applicable on
601 all platforms.  The following table shows translations of the various baud rate
602 constants on Windows(including NT/2000) and POSIX platforms.  Speeds marked with an *
603 are speeds that are usable on both Windows and POSIX.
604 \verbatim
605 
606   RATE          Windows Speed   POSIX Speed
607   -----------   -------------   -----------
608    BAUD50                 110          50
609    BAUD75                 110          75
610   *BAUD110                110         110
611    BAUD134                110         134.5
612    BAUD150                110         150
613    BAUD200                110         200
614   *BAUD300                300         300
615   *BAUD600                600         600
616   *BAUD1200              1200        1200
617    BAUD1800              1200        1800
618   *BAUD2400              2400        2400
619   *BAUD4800              4800        4800
620   *BAUD9600              9600        9600
621    BAUD14400            14400        9600
622   *BAUD19200            19200       19200
623   *BAUD38400            38400       38400
624    BAUD56000            56000       38400
625   *BAUD57600            57600       57600
626    BAUD76800            57600       76800
627   *BAUD115200          115200      115200
628    BAUD128000          128000      115200
629    BAUD256000          256000      115200
630 \endverbatim
631 */
setBaudRate(BaudRateType baudRate)632 void Win_QextSerialPort::setBaudRate(BaudRateType baudRate) {
633     LOCK_MUTEX();
634     if (Settings.BaudRate!=baudRate) {
635         switch (baudRate) {
636             case BAUD50:
637             case BAUD75:
638             case BAUD134:
639             case BAUD150:
640             case BAUD200:
641                 Settings.BaudRate=BAUD110;
642                 break;
643 
644             case BAUD1800:
645                 Settings.BaudRate=BAUD1200;
646                 break;
647 
648             case BAUD76800:
649                 Settings.BaudRate=BAUD57600;
650                 break;
651 
652             default:
653                 Settings.BaudRate=baudRate;
654                 break;
655         }
656     }
657     if (isOpen()) {
658         switch (baudRate) {
659 
660             /*50 baud*/
661             case BAUD50:
662                 TTY_WARNING("Win_QextSerialPort: Windows does not support 50 baud operation.  Switching to 110 baud.");
663                 Win_CommConfig.BaudRate=CBR_110;
664                 break;
665 
666             /*75 baud*/
667             case BAUD75:
668                 TTY_WARNING("Win_QextSerialPort: Windows does not support 75 baud operation.  Switching to 110 baud.");
669                 Win_CommConfig.BaudRate=CBR_110;
670                 break;
671 
672             /*110 baud*/
673             case BAUD110:
674                 Win_CommConfig.BaudRate=CBR_110;
675                 break;
676 
677             /*134.5 baud*/
678             case BAUD134:
679                 TTY_WARNING("Win_QextSerialPort: Windows does not support 134.5 baud operation.  Switching to 110 baud.");
680                 Win_CommConfig.BaudRate=CBR_110;
681                 break;
682 
683             /*150 baud*/
684             case BAUD150:
685                 TTY_WARNING("Win_QextSerialPort: Windows does not support 150 baud operation.  Switching to 110 baud.");
686                 Win_CommConfig.BaudRate=CBR_110;
687                 break;
688 
689             /*200 baud*/
690             case BAUD200:
691                 TTY_WARNING("Win_QextSerialPort: Windows does not support 200 baud operation.  Switching to 110 baud.");
692                 Win_CommConfig.BaudRate=CBR_110;
693                 break;
694 
695             /*300 baud*/
696             case BAUD300:
697                 Win_CommConfig.BaudRate=CBR_300;
698                 break;
699 
700             /*600 baud*/
701             case BAUD600:
702                 Win_CommConfig.BaudRate=CBR_600;
703                 break;
704 
705             /*1200 baud*/
706             case BAUD1200:
707                 Win_CommConfig.BaudRate=CBR_1200;
708                 break;
709 
710             /*1800 baud*/
711             case BAUD1800:
712                 TTY_WARNING("Win_QextSerialPort: Windows does not support 1800 baud operation.  Switching to 1200 baud.");
713                 Win_CommConfig.BaudRate=CBR_1200;
714                 break;
715 
716             /*2400 baud*/
717             case BAUD2400:
718                 Win_CommConfig.BaudRate=CBR_2400;
719                 break;
720 
721             /*4800 baud*/
722             case BAUD4800:
723                 Win_CommConfig.BaudRate=CBR_4800;
724                 break;
725 
726             /*9600 baud*/
727             case BAUD9600:
728                 Win_CommConfig.BaudRate=CBR_9600;
729                 break;
730 
731             /*14400 baud*/
732             case BAUD14400:
733                 TTY_PORTABILITY_WARNING("Win_QextSerialPort Portability Warning: POSIX does not support 14400 baud operation.");
734                 Win_CommConfig.BaudRate=CBR_14400;
735                 break;
736 
737             /*19200 baud*/
738             case BAUD19200:
739                 Win_CommConfig.BaudRate=CBR_19200;
740                 break;
741 
742             /*38400 baud*/
743             case BAUD38400:
744                 Win_CommConfig.BaudRate=CBR_38400;
745                 break;
746 
747             /*56000 baud*/
748             case BAUD56000:
749                 TTY_PORTABILITY_WARNING("Win_QextSerialPort Portability Warning: POSIX does not support 56000 baud operation.");
750                 Win_CommConfig.BaudRate=CBR_56000;
751                 break;
752 
753             /*57600 baud*/
754             case BAUD57600:
755                 Win_CommConfig.BaudRate=CBR_57600;
756                 break;
757 
758             /*76800 baud*/
759             case BAUD76800:
760                 TTY_WARNING("Win_QextSerialPort: Windows does not support 76800 baud operation.  Switching to 57600 baud.");
761                 Win_CommConfig.BaudRate=CBR_57600;
762                 break;
763 
764             /*115200 baud*/
765             case BAUD115200:
766                 Win_CommConfig.BaudRate=CBR_115200;
767                 break;
768 
769             /*128000 baud*/
770             case BAUD128000:
771                 TTY_PORTABILITY_WARNING("Win_QextSerialPort Portability Warning: POSIX does not support 128000 baud operation.");
772                 Win_CommConfig.BaudRate=CBR_128000;
773                 break;
774 
775             /*256000 baud*/
776             case BAUD256000:
777                 TTY_PORTABILITY_WARNING("Win_QextSerialPort Portability Warning: POSIX does not support 256000 baud operation.");
778                 Win_CommConfig.BaudRate=CBR_256000;
779                 break;
780         }
781         SetCommState(Win_Handle, &Win_CommConfig);
782     }
783     UNLOCK_MUTEX();
784 }
785 
786 /*!
787 \fn void Win_QextSerialPort::setDtr(bool set)
788 Sets DTR line to the requested state (high by default).  This function will have no effect if
789 the port associated with the class is not currently open.
790 */
setDtr(bool set)791 void Win_QextSerialPort::setDtr(bool set) {
792     LOCK_MUTEX();
793     if (isOpen()) {
794         if (set) {
795             EscapeCommFunction(Win_Handle, SETDTR);
796         }
797         else {
798             EscapeCommFunction(Win_Handle, CLRDTR);
799         }
800     }
801     UNLOCK_MUTEX();
802 }
803 
804 /*!
805 \fn void Win_QextSerialPort::setRts(bool set)
806 Sets RTS line to the requested state (high by default).  This function will have no effect if
807 the port associated with the class is not currently open.
808 */
setRts(bool set)809 void Win_QextSerialPort::setRts(bool set) {
810     LOCK_MUTEX();
811     if (isOpen()) {
812         if (set) {
813             EscapeCommFunction(Win_Handle, SETRTS);
814         }
815         else {
816             EscapeCommFunction(Win_Handle, CLRRTS);
817         }
818     }
819     UNLOCK_MUTEX();
820 }
821 
822 /*!
823 \fn ulong Win_QextSerialPort::lineStatus(void)
824 returns the line status as stored by the port function.  This function will retrieve the states
825 of the following lines: DCD, CTS, DSR, and RI.  On POSIX systems, the following additional lines
826 can be monitored: DTR, RTS, Secondary TXD, and Secondary RXD.  The value returned is an unsigned
827 long with specific bits indicating which lines are high.  The following constants should be used
828 to examine the states of individual lines:
829 
830 \verbatim
831 Mask        Line
832 ------      ----
833 LS_CTS      CTS
834 LS_DSR      DSR
835 LS_DCD      DCD
836 LS_RI       RI
837 \endverbatim
838 
839 This function will return 0 if the port associated with the class is not currently open.
840 */
lineStatus(void)841 ulong Win_QextSerialPort::lineStatus(void) {
842     unsigned long Status=0, Temp=0;
843     LOCK_MUTEX();
844     if (isOpen()) {
845         GetCommModemStatus(Win_Handle, &Temp);
846         if (Temp&MS_CTS_ON) {
847             Status|=LS_CTS;
848         }
849         if (Temp&MS_DSR_ON) {
850             Status|=LS_DSR;
851         }
852         if (Temp&MS_RING_ON) {
853             Status|=LS_RI;
854         }
855         if (Temp&MS_RLSD_ON) {
856             Status|=LS_DCD;
857         }
858     }
859     UNLOCK_MUTEX();
860     return Status;
861 }
862 
863 /*!
864 \fn void Win_QextSerialPort::setTimeout(ulong sec, ulong millisec);
865 Sets the read and write timeouts for the port to sec seconds and millisec milliseconds.
866 */
setTimeout(ulong sec,ulong millisec)867 void Win_QextSerialPort::setTimeout(ulong sec, ulong millisec) {
868     LOCK_MUTEX();
869     Settings.Timeout_Sec=sec;
870     Settings.Timeout_Millisec=millisec;
871     if(isOpen()) {
872         Win_CommTimeouts.ReadIntervalTimeout = sec*1000+millisec;
873         Win_CommTimeouts.ReadTotalTimeoutMultiplier = sec*1000+millisec;
874         Win_CommTimeouts.ReadTotalTimeoutConstant = 0;
875         Win_CommTimeouts.WriteTotalTimeoutMultiplier = sec*1000+millisec;
876         Win_CommTimeouts.WriteTotalTimeoutConstant = 0;
877         SetCommTimeouts(Win_Handle, &Win_CommTimeouts);
878     }
879     UNLOCK_MUTEX();
880 }
881