posix_qextserialport.cpp 35.2 KB
Newer Older
pixhawk's avatar
pixhawk committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43

/*!
\class Posix_QextSerialPort
\version 1.0.0
\author Stefan Sander
\author Michal Policht

A cross-platform serial port class.
This class encapsulates the POSIX portion of QextSerialPort.  The user will be notified of errors
and possible portability conflicts at run-time by default - this behavior can be turned off by
defining _TTY_NOWARN_ (to turn off all warnings) or _TTY_NOWARN_PORT_ (to turn off portability
warnings) in the project.  Note that _TTY_NOWARN_ will also turn off portability warnings.
*/

#include <fcntl.h>
#include <stdio.h>
#include "posix_qextserialport.h"

/*!
\fn Posix_QextSerialPort::Posix_QextSerialPort()
Default constructor.  Note that the name of the device used by a QextSerialPort constructed with
this constructor will be determined by #defined constants, or lack thereof - the default behavior
is the same as _TTY_LINUX_.  Possible naming conventions and their associated constants are:

\verbatim

Constant         Used By         Naming Convention
----------       -------------   ------------------------
_TTY_WIN_        Windows         COM1, COM2
_TTY_IRIX_       SGI/IRIX        /dev/ttyf1, /dev/ttyf2
_TTY_HPUX_       HP-UX           /dev/tty1p0, /dev/tty2p0
_TTY_SUN_        SunOS/Solaris   /dev/ttya, /dev/ttyb
_TTY_DIGITAL_    Digital UNIX    /dev/tty01, /dev/tty02
_TTY_FREEBSD_    FreeBSD         /dev/ttyd0, /dev/ttyd1
_TTY_OPENBSD_    OpenBSD         /dev/tty00, /dev/tty01
_TTY_LINUX_      Linux           /dev/ttyS0, /dev/ttyS1
<none>           Linux           /dev/ttyS0, /dev/ttyS1
\endverbatim

This constructor assigns the device name to the name of the first port on the specified system.
See the other constructors if you need to open a different port.
*/
Posix_QextSerialPort::Posix_QextSerialPort(QextSerialBase::QueryMode mode)
44
    : QextSerialBase()
pixhawk's avatar
pixhawk committed
45 46 47 48 49 50 51 52 53 54
{
    setQueryMode(mode);
    init();
}

/*!
\fn Posix_QextSerialPort::Posix_QextSerialPort(const Posix_QextSerialPort&)
Copy constructor.
*/
Posix_QextSerialPort::Posix_QextSerialPort(const Posix_QextSerialPort& s)
55
    : QextSerialBase(s.port)
pixhawk's avatar
pixhawk committed
56
{
57
    setOpenMode(s.openMode());
pixhawk's avatar
pixhawk committed
58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78
    port = s.port;
    Settings.BaudRate=s.Settings.BaudRate;
    Settings.DataBits=s.Settings.DataBits;
    Settings.Parity=s.Settings.Parity;
    Settings.StopBits=s.Settings.StopBits;
    Settings.FlowControl=s.Settings.FlowControl;
    lastErr=s.lastErr;

    fd = s.fd;
    memcpy(&Posix_Timeout, &s.Posix_Timeout, sizeof(struct timeval));
    memcpy(&Posix_Copy_Timeout, &s.Posix_Copy_Timeout, sizeof(struct timeval));
    memcpy(&Posix_CommConfig, &s.Posix_CommConfig, sizeof(struct termios));
}

/*!
\fn Posix_QextSerialPort::Posix_QextSerialPort(const QString & name)
Constructs a serial port attached to the port specified by name.
name is the name of the device, which is windowsystem-specific,
e.g."COM1" or "/dev/ttyS0".
*/
Posix_QextSerialPort::Posix_QextSerialPort(const QString & name, QextSerialBase::QueryMode mode)
79
    : QextSerialBase(name)
pixhawk's avatar
pixhawk committed
80 81 82 83 84 85 86 87 88 89
{
    setQueryMode(mode);
    init();
}

/*!
\fn Posix_QextSerialPort::Posix_QextSerialPort(const PortSettings& settings)
Constructs a port with default name and specified settings.
*/
Posix_QextSerialPort::Posix_QextSerialPort(const PortSettings& settings, QextSerialBase::QueryMode mode)
90
    : QextSerialBase()
pixhawk's avatar
pixhawk committed
91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107
{
    setBaudRate(settings.BaudRate);
    setDataBits(settings.DataBits);
    setParity(settings.Parity);
    setStopBits(settings.StopBits);
    setFlowControl(settings.FlowControl);

    setTimeout(settings.Timeout_Millisec);
    setQueryMode(mode);
    init();
}

/*!
\fn Posix_QextSerialPort::Posix_QextSerialPort(const QString & name, const PortSettings& settings)
Constructs a port with specified name and settings.
*/
Posix_QextSerialPort::Posix_QextSerialPort(const QString & name, const PortSettings& settings, QextSerialBase::QueryMode mode)
108
    : QextSerialBase(name)
pixhawk's avatar
pixhawk committed
109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125
{
    setBaudRate(settings.BaudRate);
    setDataBits(settings.DataBits);
    setParity(settings.Parity);
    setStopBits(settings.StopBits);
    setFlowControl(settings.FlowControl);

    setTimeout(settings.Timeout_Millisec);
    setQueryMode(mode);
    init();
}

/*!
\fn Posix_QextSerialPort& Posix_QextSerialPort::operator=(const Posix_QextSerialPort& s)
Override the = operator.
*/
Posix_QextSerialPort& Posix_QextSerialPort::operator=(const Posix_QextSerialPort& s)
126
{
127
    setOpenMode(s.openMode());
pixhawk's avatar
pixhawk committed
128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144
    port = s.port;
    Settings.BaudRate=s.Settings.BaudRate;
    Settings.DataBits=s.Settings.DataBits;
    Settings.Parity=s.Settings.Parity;
    Settings.StopBits=s.Settings.StopBits;
    Settings.FlowControl=s.Settings.FlowControl;
    lastErr=s.lastErr;

    fd = s.fd;
    memcpy(& Posix_Timeout, &(s.Posix_Timeout), sizeof(struct timeval));
    memcpy(& Posix_Copy_Timeout, &(s.Posix_Copy_Timeout), sizeof(struct timeval));
    memcpy(& Posix_CommConfig, &(s.Posix_CommConfig), sizeof(struct termios));
    return *this;
}

void Posix_QextSerialPort::init()
{
145 146 147
    fd = 0;
    if (queryMode() == QextSerialBase::EventDriven)
        qWarning("POSIX doesn't have event driven mechanism implemented yet");
pixhawk's avatar
pixhawk committed
148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196
}

/*!
\fn Posix_QextSerialPort::~Posix_QextSerialPort()
Standard destructor.
*/
Posix_QextSerialPort::~Posix_QextSerialPort()
{
    if (isOpen()) {
        close();
    }
}

/*!
\fn void Posix_QextSerialPort::setBaudRate(BaudRateType baudRate)
Sets the baud rate of the serial port.  Note that not all rates are applicable on
all platforms.  The following table shows translations of the various baud rate
constants on Windows(including NT/2000) and POSIX platforms.  Speeds marked with an *
are speeds that are usable on both Windows and POSIX.

\note
BAUD76800 may not be supported on all POSIX systems.  SGI/IRIX systems do not support
BAUD1800.

\verbatim

  RATE          Windows Speed   POSIX Speed
  -----------   -------------   -----------
   BAUD50                 110          50
   BAUD75                 110          75
  *BAUD110                110         110
   BAUD134                110         134.5
   BAUD150                110         150
   BAUD200                110         200
  *BAUD300                300         300
  *BAUD600                600         600
  *BAUD1200              1200        1200
   BAUD1800              1200        1800
  *BAUD2400              2400        2400
  *BAUD4800              4800        4800
  *BAUD9600              9600        9600
   BAUD14400            14400        9600
  *BAUD19200            19200       19200
  *BAUD38400            38400       38400
   BAUD56000            56000       38400
  *BAUD57600            57600       57600
   BAUD76800            57600       76800
  *BAUD115200          115200      115200
   BAUD128000          128000      115200
197
   BAUD230400          230400      115200
pixhawk's avatar
pixhawk committed
198
   BAUD256000          256000      115200
199 200
   BAUD460800          460800      115200
   BAUD921600          921600      115200
pixhawk's avatar
pixhawk committed
201 202 203 204 205 206 207
\endverbatim
*/
void Posix_QextSerialPort::setBaudRate(BaudRateType baudRate)
{
    LOCK_MUTEX();
    if (Settings.BaudRate!=baudRate) {
        switch (baudRate) {
208 209 210
        case BAUD14400:
            Settings.BaudRate=BAUD9600;
            break;
pixhawk's avatar
pixhawk committed
211

212 213 214
        case BAUD56000:
            Settings.BaudRate=BAUD38400;
            break;
pixhawk's avatar
pixhawk committed
215

216
        case BAUD76800:
pixhawk's avatar
pixhawk committed
217 218

#ifndef B76800
219
            Settings.BaudRate=BAUD57600;
pixhawk's avatar
pixhawk committed
220
#else
221
            Settings.BaudRate=baudRate;
pixhawk's avatar
pixhawk committed
222
#endif
223
            break;
pixhawk's avatar
pixhawk committed
224

225 226 227 228 229 230 231
        case BAUD128000:
        case BAUD230400:
        case BAUD460800:
        case BAUD921600:
        case BAUD256000:
            Settings.BaudRate=BAUD115200;
            break;
pixhawk's avatar
pixhawk committed
232

233 234 235
        default:
            Settings.BaudRate=baudRate;
            break;
pixhawk's avatar
pixhawk committed
236 237 238 239 240 241
        }
    }
    if (isOpen()) {
        switch (baudRate) {

            /*50 baud*/
242 243
        case BAUD50:
            TTY_PORTABILITY_WARNING("Posix_QextSerialPort Portability Warning: Windows does not support 50 baud operation.");
pixhawk's avatar
pixhawk committed
244
#ifdef CBAUD
245 246
            Posix_CommConfig.c_cflag&=(~CBAUD);
            Posix_CommConfig.c_cflag|=B50;
pixhawk's avatar
pixhawk committed
247
#else
248 249
            cfsetispeed(&Posix_CommConfig, B50);
            cfsetospeed(&Posix_CommConfig, B50);
pixhawk's avatar
pixhawk committed
250
#endif
251
            break;
pixhawk's avatar
pixhawk committed
252 253

            /*75 baud*/
254 255
        case BAUD75:
            TTY_PORTABILITY_WARNING("Posix_QextSerialPort Portability Warning: Windows does not support 75 baud operation.");
pixhawk's avatar
pixhawk committed
256
#ifdef CBAUD
257 258
            Posix_CommConfig.c_cflag&=(~CBAUD);
            Posix_CommConfig.c_cflag|=B75;
pixhawk's avatar
pixhawk committed
259
#else
260 261
            cfsetispeed(&Posix_CommConfig, B75);
            cfsetospeed(&Posix_CommConfig, B75);
pixhawk's avatar
pixhawk committed
262
#endif
263
            break;
pixhawk's avatar
pixhawk committed
264 265

            /*110 baud*/
266
        case BAUD110:
pixhawk's avatar
pixhawk committed
267
#ifdef CBAUD
268 269
            Posix_CommConfig.c_cflag&=(~CBAUD);
            Posix_CommConfig.c_cflag|=B110;
pixhawk's avatar
pixhawk committed
270
#else
271 272
            cfsetispeed(&Posix_CommConfig, B110);
            cfsetospeed(&Posix_CommConfig, B110);
pixhawk's avatar
pixhawk committed
273
#endif
274
            break;
pixhawk's avatar
pixhawk committed
275 276

            /*134.5 baud*/
277 278
        case BAUD134:
            TTY_PORTABILITY_WARNING("Posix_QextSerialPort Portability Warning: Windows does not support 134.5 baud operation.");
pixhawk's avatar
pixhawk committed
279
#ifdef CBAUD
280 281
            Posix_CommConfig.c_cflag&=(~CBAUD);
            Posix_CommConfig.c_cflag|=B134;
pixhawk's avatar
pixhawk committed
282
#else
283 284
            cfsetispeed(&Posix_CommConfig, B134);
            cfsetospeed(&Posix_CommConfig, B134);
pixhawk's avatar
pixhawk committed
285
#endif
286
            break;
pixhawk's avatar
pixhawk committed
287 288

            /*150 baud*/
289 290
        case BAUD150:
            TTY_PORTABILITY_WARNING("Posix_QextSerialPort Portability Warning: Windows does not support 150 baud operation.");
pixhawk's avatar
pixhawk committed
291
#ifdef CBAUD
292 293
            Posix_CommConfig.c_cflag&=(~CBAUD);
            Posix_CommConfig.c_cflag|=B150;
pixhawk's avatar
pixhawk committed
294
#else
295 296
            cfsetispeed(&Posix_CommConfig, B150);
            cfsetospeed(&Posix_CommConfig, B150);
pixhawk's avatar
pixhawk committed
297
#endif
298
            break;
pixhawk's avatar
pixhawk committed
299 300

            /*200 baud*/
301 302
        case BAUD200:
            TTY_PORTABILITY_WARNING("Posix_QextSerialPort Portability Warning: Windows does not support 200 baud operation.");
pixhawk's avatar
pixhawk committed
303
#ifdef CBAUD
304 305
            Posix_CommConfig.c_cflag&=(~CBAUD);
            Posix_CommConfig.c_cflag|=B200;
pixhawk's avatar
pixhawk committed
306
#else
307 308
            cfsetispeed(&Posix_CommConfig, B200);
            cfsetospeed(&Posix_CommConfig, B200);
pixhawk's avatar
pixhawk committed
309
#endif
310
            break;
pixhawk's avatar
pixhawk committed
311 312

            /*300 baud*/
313
        case BAUD300:
pixhawk's avatar
pixhawk committed
314
#ifdef CBAUD
315 316
            Posix_CommConfig.c_cflag&=(~CBAUD);
            Posix_CommConfig.c_cflag|=B300;
pixhawk's avatar
pixhawk committed
317
#else
318 319
            cfsetispeed(&Posix_CommConfig, B300);
            cfsetospeed(&Posix_CommConfig, B300);
pixhawk's avatar
pixhawk committed
320
#endif
321
            break;
pixhawk's avatar
pixhawk committed
322 323

            /*600 baud*/
324
        case BAUD600:
pixhawk's avatar
pixhawk committed
325
#ifdef CBAUD
326 327
            Posix_CommConfig.c_cflag&=(~CBAUD);
            Posix_CommConfig.c_cflag|=B600;
pixhawk's avatar
pixhawk committed
328
#else
329 330
            cfsetispeed(&Posix_CommConfig, B600);
            cfsetospeed(&Posix_CommConfig, B600);
pixhawk's avatar
pixhawk committed
331
#endif
332
            break;
pixhawk's avatar
pixhawk committed
333 334

            /*1200 baud*/
335
        case BAUD1200:
pixhawk's avatar
pixhawk committed
336
#ifdef CBAUD
337 338
            Posix_CommConfig.c_cflag&=(~CBAUD);
            Posix_CommConfig.c_cflag|=B1200;
pixhawk's avatar
pixhawk committed
339
#else
340 341
            cfsetispeed(&Posix_CommConfig, B1200);
            cfsetospeed(&Posix_CommConfig, B1200);
pixhawk's avatar
pixhawk committed
342
#endif
343
            break;
pixhawk's avatar
pixhawk committed
344 345

            /*1800 baud*/
346 347
        case BAUD1800:
            TTY_PORTABILITY_WARNING("Posix_QextSerialPort Portability Warning: Windows and IRIX do not support 1800 baud operation.");
pixhawk's avatar
pixhawk committed
348
#ifdef CBAUD
349 350
            Posix_CommConfig.c_cflag&=(~CBAUD);
            Posix_CommConfig.c_cflag|=B1800;
pixhawk's avatar
pixhawk committed
351
#else
352 353
            cfsetispeed(&Posix_CommConfig, B1800);
            cfsetospeed(&Posix_CommConfig, B1800);
pixhawk's avatar
pixhawk committed
354
#endif
355
            break;
pixhawk's avatar
pixhawk committed
356 357

            /*2400 baud*/
358
        case BAUD2400:
pixhawk's avatar
pixhawk committed
359
#ifdef CBAUD
360 361
            Posix_CommConfig.c_cflag&=(~CBAUD);
            Posix_CommConfig.c_cflag|=B2400;
pixhawk's avatar
pixhawk committed
362
#else
363 364
            cfsetispeed(&Posix_CommConfig, B2400);
            cfsetospeed(&Posix_CommConfig, B2400);
pixhawk's avatar
pixhawk committed
365
#endif
366
            break;
pixhawk's avatar
pixhawk committed
367 368

            /*4800 baud*/
369
        case BAUD4800:
pixhawk's avatar
pixhawk committed
370
#ifdef CBAUD
371 372
            Posix_CommConfig.c_cflag&=(~CBAUD);
            Posix_CommConfig.c_cflag|=B4800;
pixhawk's avatar
pixhawk committed
373
#else
374 375
            cfsetispeed(&Posix_CommConfig, B4800);
            cfsetospeed(&Posix_CommConfig, B4800);
pixhawk's avatar
pixhawk committed
376
#endif
377
            break;
pixhawk's avatar
pixhawk committed
378 379

            /*9600 baud*/
380
        case BAUD9600:
pixhawk's avatar
pixhawk committed
381
#ifdef CBAUD
382 383
            Posix_CommConfig.c_cflag&=(~CBAUD);
            Posix_CommConfig.c_cflag|=B9600;
pixhawk's avatar
pixhawk committed
384
#else
385 386
            cfsetispeed(&Posix_CommConfig, B9600);
            cfsetospeed(&Posix_CommConfig, B9600);
pixhawk's avatar
pixhawk committed
387
#endif
388
            break;
pixhawk's avatar
pixhawk committed
389 390

            /*14400 baud*/
391 392
        case BAUD14400:
            TTY_WARNING("Posix_QextSerialPort: POSIX does not support 14400 baud operation.  Switching to 9600 baud.");
pixhawk's avatar
pixhawk committed
393
#ifdef CBAUD
394 395
            Posix_CommConfig.c_cflag&=(~CBAUD);
            Posix_CommConfig.c_cflag|=B9600;
pixhawk's avatar
pixhawk committed
396
#else
397 398
            cfsetispeed(&Posix_CommConfig, B9600);
            cfsetospeed(&Posix_CommConfig, B9600);
pixhawk's avatar
pixhawk committed
399
#endif
400
            break;
pixhawk's avatar
pixhawk committed
401 402

            /*19200 baud*/
403
        case BAUD19200:
pixhawk's avatar
pixhawk committed
404
#ifdef CBAUD
405 406
            Posix_CommConfig.c_cflag&=(~CBAUD);
            Posix_CommConfig.c_cflag|=B19200;
pixhawk's avatar
pixhawk committed
407
#else
408 409
            cfsetispeed(&Posix_CommConfig, B19200);
            cfsetospeed(&Posix_CommConfig, B19200);
pixhawk's avatar
pixhawk committed
410
#endif
411
            break;
pixhawk's avatar
pixhawk committed
412 413

            /*38400 baud*/
414
        case BAUD38400:
pixhawk's avatar
pixhawk committed
415
#ifdef CBAUD
416 417
            Posix_CommConfig.c_cflag&=(~CBAUD);
            Posix_CommConfig.c_cflag|=B38400;
pixhawk's avatar
pixhawk committed
418
#else
419 420
            cfsetispeed(&Posix_CommConfig, B38400);
            cfsetospeed(&Posix_CommConfig, B38400);
pixhawk's avatar
pixhawk committed
421
#endif
422
            break;
pixhawk's avatar
pixhawk committed
423 424

            /*56000 baud*/
425 426
        case BAUD56000:
            TTY_WARNING("Posix_QextSerialPort: POSIX does not support 56000 baud operation.  Switching to 38400 baud.");
pixhawk's avatar
pixhawk committed
427
#ifdef CBAUD
428 429
            Posix_CommConfig.c_cflag&=(~CBAUD);
            Posix_CommConfig.c_cflag|=B38400;
pixhawk's avatar
pixhawk committed
430
#else
431 432
            cfsetispeed(&Posix_CommConfig, B38400);
            cfsetospeed(&Posix_CommConfig, B38400);
pixhawk's avatar
pixhawk committed
433
#endif
434
            break;
pixhawk's avatar
pixhawk committed
435 436

            /*57600 baud*/
437
        case BAUD57600:
pixhawk's avatar
pixhawk committed
438
#ifdef CBAUD
439 440
            Posix_CommConfig.c_cflag&=(~CBAUD);
            Posix_CommConfig.c_cflag|=B57600;
pixhawk's avatar
pixhawk committed
441
#else
442 443
            cfsetispeed(&Posix_CommConfig, B57600);
            cfsetospeed(&Posix_CommConfig, B57600);
pixhawk's avatar
pixhawk committed
444
#endif
445
            break;
pixhawk's avatar
pixhawk committed
446 447

            /*76800 baud*/
448 449
        case BAUD76800:
            TTY_PORTABILITY_WARNING("Posix_QextSerialPort Portability Warning: Windows and some POSIX systems do not support 76800 baud operation.");
pixhawk's avatar
pixhawk committed
450
#ifdef CBAUD
451
            Posix_CommConfig.c_cflag&=(~CBAUD);
pixhawk's avatar
pixhawk committed
452 453

#ifdef B76800
454
            Posix_CommConfig.c_cflag|=B76800;
pixhawk's avatar
pixhawk committed
455
#else
456 457
            TTY_WARNING("Posix_QextSerialPort: Posix_QextSerialPort was compiled without 76800 baud support.  Switching to 57600 baud.");
            Posix_CommConfig.c_cflag|=B57600;
pixhawk's avatar
pixhawk committed
458 459 460
#endif //B76800
#else  //CBAUD
#ifdef B76800
461 462
            cfsetispeed(&Posix_CommConfig, B76800);
            cfsetospeed(&Posix_CommConfig, B76800);
pixhawk's avatar
pixhawk committed
463
#else
464 465 466
            TTY_WARNING("Posix_QextSerialPort: Posix_QextSerialPort was compiled without 76800 baud support.  Switching to 57600 baud.");
            cfsetispeed(&Posix_CommConfig, B57600);
            cfsetospeed(&Posix_CommConfig, B57600);
pixhawk's avatar
pixhawk committed
467 468
#endif //B76800
#endif //CBAUD
469
            break;
pixhawk's avatar
pixhawk committed
470 471

            /*115200 baud*/
472
        case BAUD115200:
pixhawk's avatar
pixhawk committed
473
#ifdef CBAUD
474 475
            Posix_CommConfig.c_cflag&=(~CBAUD);
            Posix_CommConfig.c_cflag|=B115200;
pixhawk's avatar
pixhawk committed
476
#else
477 478
            cfsetispeed(&Posix_CommConfig, B115200);
            cfsetospeed(&Posix_CommConfig, B115200);
pixhawk's avatar
pixhawk committed
479
#endif
480
            break;
pixhawk's avatar
pixhawk committed
481 482

            /*128000 baud*/
483 484
        case BAUD128000:
            TTY_WARNING("Posix_QextSerialPort: POSIX does not support 128000 baud operation.  Switching to 115200 baud.");
pixhawk's avatar
pixhawk committed
485
#ifdef CBAUD
486 487
            Posix_CommConfig.c_cflag&=(~CBAUD);
            Posix_CommConfig.c_cflag|=B115200;
pixhawk's avatar
pixhawk committed
488
#else
489 490
            cfsetispeed(&Posix_CommConfig, B115200);
            cfsetospeed(&Posix_CommConfig, B115200);
pixhawk's avatar
pixhawk committed
491
#endif
492
            break;
pixhawk's avatar
pixhawk committed
493 494

            /*256000 baud*/
495 496 497 498 499
        case BAUD230400:
        case BAUD460800:
        case BAUD921600:
        case BAUD256000:
            TTY_WARNING("Posix_QextSerialPort: POSIX does not support baud rates above 115200 baud.  Switching to 115200 baud.");
pixhawk's avatar
pixhawk committed
500
#ifdef CBAUD
501 502
            Posix_CommConfig.c_cflag&=(~CBAUD);
            Posix_CommConfig.c_cflag|=B115200;
pixhawk's avatar
pixhawk committed
503
#else
504 505
            cfsetispeed(&Posix_CommConfig, B115200);
            cfsetospeed(&Posix_CommConfig, B115200);
pixhawk's avatar
pixhawk committed
506
#endif
507
            break;
pixhawk's avatar
pixhawk committed
508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536
        }
        tcsetattr(fd, TCSAFLUSH, &Posix_CommConfig);
    }
    UNLOCK_MUTEX();
}

/*!
\fn void Posix_QextSerialPort::setDataBits(DataBitsType dataBits)
Sets the number of data bits used by the serial port.  Possible values of dataBits are:
\verbatim
    DATA_5      5 data bits
    DATA_6      6 data bits
    DATA_7      7 data bits
    DATA_8      8 data bits
\endverbatim

\note
This function is subject to the following restrictions:
\par
    5 data bits cannot be used with 2 stop bits.
\par
    8 data bits cannot be used with space parity on POSIX systems.

*/
void Posix_QextSerialPort::setDataBits(DataBitsType dataBits)
{
    LOCK_MUTEX();
    if (Settings.DataBits!=dataBits) {
        if ((Settings.StopBits==STOP_2 && dataBits==DATA_5) ||
537 538 539
                (Settings.StopBits==STOP_1_5 && dataBits!=DATA_5) ||
                (Settings.Parity==PAR_SPACE && dataBits==DATA_8)) {
        } else {
pixhawk's avatar
pixhawk committed
540 541 542 543 544 545 546
            Settings.DataBits=dataBits;
        }
    }
    if (isOpen()) {
        switch(dataBits) {

            /*5 data bits*/
547 548 549
        case DATA_5:
            if (Settings.StopBits==STOP_2) {
                TTY_WARNING("Posix_QextSerialPort: 5 Data bits cannot be used with 2 stop bits.");
550
            } else {
551 552 553 554 555 556
                Settings.DataBits=dataBits;
                Posix_CommConfig.c_cflag&=(~CSIZE);
                Posix_CommConfig.c_cflag|=CS5;
                tcsetattr(fd, TCSAFLUSH, &Posix_CommConfig);
            }
            break;
pixhawk's avatar
pixhawk committed
557 558

            /*6 data bits*/
559
        case DATA_6:
560 561
            if (Settings.StopBits==STOP_1_5) {
                TTY_WARNING("Posix_QextSerialPort: 6 Data bits cannot be used with 1.5 stop bits.");
562
            } else {
563 564 565 566 567 568
                Settings.DataBits=dataBits;
                Posix_CommConfig.c_cflag&=(~CSIZE);
                Posix_CommConfig.c_cflag|=CS6;
                tcsetattr(fd, TCSAFLUSH, &Posix_CommConfig);
            }
            break;
pixhawk's avatar
pixhawk committed
569 570

            /*7 data bits*/
571
        case DATA_7:
572 573
            if (Settings.StopBits==STOP_1_5) {
                TTY_WARNING("Posix_QextSerialPort: 7 Data bits cannot be used with 1.5 stop bits.");
574
            } else {
575 576 577 578 579 580
                Settings.DataBits=dataBits;
                Posix_CommConfig.c_cflag&=(~CSIZE);
                Posix_CommConfig.c_cflag|=CS7;
                tcsetattr(fd, TCSAFLUSH, &Posix_CommConfig);
            }
            break;
pixhawk's avatar
pixhawk committed
581 582

            /*8 data bits*/
583
        case DATA_8:
584 585
            if (Settings.StopBits==STOP_1_5) {
                TTY_WARNING("Posix_QextSerialPort: 8 Data bits cannot be used with 1.5 stop bits.");
586
            } else {
587 588 589 590 591 592
                Settings.DataBits=dataBits;
                Posix_CommConfig.c_cflag&=(~CSIZE);
                Posix_CommConfig.c_cflag|=CS8;
                tcsetattr(fd, TCSAFLUSH, &Posix_CommConfig);
            }
            break;
pixhawk's avatar
pixhawk committed
593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622
        }
    }
    UNLOCK_MUTEX();
}

/*!
\fn void Posix_QextSerialPort::setParity(ParityType parity)
Sets the parity associated with the serial port.  The possible values of parity are:
\verbatim
    PAR_SPACE       Space Parity
    PAR_MARK        Mark Parity
    PAR_NONE        No Parity
    PAR_EVEN        Even Parity
    PAR_ODD         Odd Parity
\endverbatim

\note
This function is subject to the following limitations:
\par
POSIX systems do not support mark parity.
\par
POSIX systems support space parity only if tricked into doing so, and only with
   fewer than 8 data bits.  Use space parity very carefully with POSIX systems.

*/
void Posix_QextSerialPort::setParity(ParityType parity)
{
    LOCK_MUTEX();
    if (Settings.Parity!=parity) {
        if (parity==PAR_MARK || (parity==PAR_SPACE && Settings.DataBits==DATA_8)) {
623
        } else {
pixhawk's avatar
pixhawk committed
624 625 626 627 628 629 630
            Settings.Parity=parity;
        }
    }
    if (isOpen()) {
        switch (parity) {

            /*space parity*/
631 632 633
        case PAR_SPACE:
            if (Settings.DataBits==DATA_8) {
                TTY_PORTABILITY_WARNING("Posix_QextSerialPort:  Space parity is only supported in POSIX with 7 or fewer data bits");
634
            } else {
635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655

                /*space parity not directly supported - add an extra data bit to simulate it*/
                Posix_CommConfig.c_cflag&=~(PARENB|CSIZE);
                switch(Settings.DataBits) {
                case DATA_5:
                    Settings.DataBits=DATA_6;
                    Posix_CommConfig.c_cflag|=CS6;
                    break;

                case DATA_6:
                    Settings.DataBits=DATA_7;
                    Posix_CommConfig.c_cflag|=CS7;
                    break;

                case DATA_7:
                    Settings.DataBits=DATA_8;
                    Posix_CommConfig.c_cflag|=CS8;
                    break;

                case DATA_8:
                    break;
pixhawk's avatar
pixhawk committed
656
                }
657 658 659
                tcsetattr(fd, TCSAFLUSH, &Posix_CommConfig);
            }
            break;
pixhawk's avatar
pixhawk committed
660 661

            /*mark parity - WINDOWS ONLY*/
662
        case PAR_MARK:
663 664
            TTY_WARNING("Posix_QextSerialPort: Mark parity is not supported by POSIX.");
            break;
pixhawk's avatar
pixhawk committed
665 666

            /*no parity*/
667
        case PAR_NONE:
668 669 670
            Posix_CommConfig.c_cflag&=(~PARENB);
            tcsetattr(fd, TCSAFLUSH, &Posix_CommConfig);
            break;
pixhawk's avatar
pixhawk committed
671 672

            /*even parity*/
673
        case PAR_EVEN:
674 675 676 677
            Posix_CommConfig.c_cflag&=(~PARODD);
            Posix_CommConfig.c_cflag|=PARENB;
            tcsetattr(fd, TCSAFLUSH, &Posix_CommConfig);
            break;
pixhawk's avatar
pixhawk committed
678 679

            /*odd parity*/
680
        case PAR_ODD:
681 682 683
            Posix_CommConfig.c_cflag|=(PARENB|PARODD);
            tcsetattr(fd, TCSAFLUSH, &Posix_CommConfig);
            break;
pixhawk's avatar
pixhawk committed
684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717
        }
    }
    UNLOCK_MUTEX();
}

/*!
\fn void Posix_QextSerialPort::setStopBits(StopBitsType stopBits)
Sets the number of stop bits used by the serial port.  Possible values of stopBits are:
\verbatim
    STOP_1      1 stop bit
    STOP_1_5    1.5 stop bits
    STOP_2      2 stop bits
\endverbatim
\note
This function is subject to the following restrictions:
\par
    2 stop bits cannot be used with 5 data bits.
\par
    POSIX does not support 1.5 stop bits.

*/
void Posix_QextSerialPort::setStopBits(StopBitsType stopBits)
{
    LOCK_MUTEX();
    if (Settings.StopBits!=stopBits) {
        if ((Settings.DataBits==DATA_5 && stopBits==STOP_2) || stopBits==STOP_1_5) {}
        else {
            Settings.StopBits=stopBits;
        }
    }
    if (isOpen()) {
        switch (stopBits) {

            /*one stop bit*/
718 719 720 721 722
        case STOP_1:
            Settings.StopBits=stopBits;
            Posix_CommConfig.c_cflag&=(~CSTOPB);
            tcsetattr(fd, TCSAFLUSH, &Posix_CommConfig);
            break;
pixhawk's avatar
pixhawk committed
723 724

            /*1.5 stop bits*/
725 726 727
        case STOP_1_5:
            TTY_WARNING("Posix_QextSerialPort: 1.5 stop bit operation is not supported by POSIX.");
            break;
pixhawk's avatar
pixhawk committed
728 729

            /*two stop bits*/
730 731 732
        case STOP_2:
            if (Settings.DataBits==DATA_5) {
                TTY_WARNING("Posix_QextSerialPort: 2 stop bits cannot be used with 5 data bits");
733
            } else {
734 735 736 737 738
                Settings.StopBits=stopBits;
                Posix_CommConfig.c_cflag|=CSTOPB;
                tcsetattr(fd, TCSAFLUSH, &Posix_CommConfig);
            }
            break;
pixhawk's avatar
pixhawk committed
739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766
        }
    }
    UNLOCK_MUTEX();
}

/*!
\fn void Posix_QextSerialPort::setFlowControl(FlowType flow)
Sets the flow control used by the port.  Possible values of flow are:
\verbatim
    FLOW_OFF            No flow control
    FLOW_HARDWARE       Hardware (RTS/CTS) flow control
    FLOW_XONXOFF        Software (XON/XOFF) flow control
\endverbatim
\note
FLOW_HARDWARE may not be supported on all versions of UNIX.  In cases where it is
unsupported, FLOW_HARDWARE is the same as FLOW_OFF.

*/
void Posix_QextSerialPort::setFlowControl(FlowType flow)
{
    LOCK_MUTEX();
    if (Settings.FlowControl!=flow) {
        Settings.FlowControl=flow;
    }
    if (isOpen()) {
        switch(flow) {

            /*no flow control*/
767 768 769 770 771
        case FLOW_OFF:
            Posix_CommConfig.c_cflag&=(~CRTSCTS);
            Posix_CommConfig.c_iflag&=(~(IXON|IXOFF|IXANY));
            tcsetattr(fd, TCSAFLUSH, &Posix_CommConfig);
            break;
pixhawk's avatar
pixhawk committed
772 773

            /*software (XON/XOFF) flow control*/
774 775 776 777 778
        case FLOW_XONXOFF:
            Posix_CommConfig.c_cflag&=(~CRTSCTS);
            Posix_CommConfig.c_iflag|=(IXON|IXOFF|IXANY);
            tcsetattr(fd, TCSAFLUSH, &Posix_CommConfig);
            break;
pixhawk's avatar
pixhawk committed
779

780 781 782 783 784
        case FLOW_HARDWARE:
            Posix_CommConfig.c_cflag|=CRTSCTS;
            Posix_CommConfig.c_iflag&=(~(IXON|IXOFF|IXANY));
            tcsetattr(fd, TCSAFLUSH, &Posix_CommConfig);
            break;
pixhawk's avatar
pixhawk committed
785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814
        }
    }
    UNLOCK_MUTEX();
}

/*!
\fn void Posix_QextSerialPort::setTimeout(ulong sec);
Sets the read and write timeouts for the port to millisec milliseconds.
Note that this is a per-character timeout, i.e. the port will wait this long for each
individual character, not for the whole read operation.  This timeout also applies to the
bytesWaiting() function.

\note
POSIX does not support millisecond-level control for I/O timeout values.  Any
timeout set using this function will be set to the next lowest tenth of a second for
the purposes of detecting read or write timeouts.  For example a timeout of 550 milliseconds
will be seen by the class as a timeout of 500 milliseconds for the purposes of reading and
writing the port.  However millisecond-level control is allowed by the select() system call,
so for example a 550-millisecond timeout will be seen as 550 milliseconds on POSIX systems for
the purpose of detecting available bytes in the read buffer.

*/
void Posix_QextSerialPort::setTimeout(long millisec)
{
    LOCK_MUTEX();
    Settings.Timeout_Millisec = millisec;
    Posix_Copy_Timeout.tv_sec = millisec / 1000;
    Posix_Copy_Timeout.tv_usec = millisec % 1000;
    if (isOpen()) {
        if (millisec == -1)
815
            fcntl(fd, F_SETFL, O_NDELAY);
pixhawk's avatar
pixhawk committed
816
        else
817 818 819
            //O_SYNC should enable blocking ::write()
            //however this seems not working on Linux 2.6.21 (works on OpenBSD 4.2)
            fcntl(fd, F_SETFL, O_SYNC);
pixhawk's avatar
pixhawk committed
820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836
        tcgetattr(fd, & Posix_CommConfig);
        Posix_CommConfig.c_cc[VTIME] = millisec/100;
        tcsetattr(fd, TCSAFLUSH, & Posix_CommConfig);
    }
    UNLOCK_MUTEX();
}

/*!
\fn bool Posix_QextSerialPort::open(OpenMode mode)
Opens the serial port associated to this class.
This function has no effect if the port associated with the class is already open.
The port is also configured to the current settings, as stored in the Settings structure.
*/
bool Posix_QextSerialPort::open(OpenMode mode)
{
    LOCK_MUTEX();
    if (mode == QIODevice::NotOpen)
837
        return isOpen();
pixhawk's avatar
pixhawk committed
838 839 840 841 842 843 844
    if (!isOpen()) {
        /*open the port*/
        qDebug("trying to open file");
        //note: linux 2.6.21 seems to ignore O_NDELAY flag
        if ((fd = ::open(port.toAscii() ,O_RDWR | O_NOCTTY | O_NDELAY)) != -1) {
            qDebug("file opened succesfully");

845 846 847 848
            setOpenMode(mode);			// Flag the port as opened
            tcgetattr(fd, &old_termios);	// Save the old termios
            Posix_CommConfig = old_termios;	// Make a working copy
            cfmakeraw(&Posix_CommConfig);	// Enable raw access
pixhawk's avatar
pixhawk committed
849 850 851 852 853 854 855 856

            /*set up other port settings*/
            Posix_CommConfig.c_cflag|=CREAD|CLOCAL;
            Posix_CommConfig.c_lflag&=(~(ICANON|ECHO|ECHOE|ECHOK|ECHONL|ISIG));
            Posix_CommConfig.c_iflag&=(~(INPCK|IGNPAR|PARMRK|ISTRIP|ICRNL|IXANY));
            Posix_CommConfig.c_oflag&=(~OPOST);
            Posix_CommConfig.c_cc[VMIN]= 0;
#ifdef _POSIX_VDISABLE	// Is a disable character available on this system?
857 858 859 860 861 862 863 864
            // Some systems allow for per-device disable-characters, so get the
            //  proper value for the configured device
            const long vdisable = fpathconf(fd, _PC_VDISABLE);
            Posix_CommConfig.c_cc[VINTR] = vdisable;
            Posix_CommConfig.c_cc[VQUIT] = vdisable;
            Posix_CommConfig.c_cc[VSTART] = vdisable;
            Posix_CommConfig.c_cc[VSTOP] = vdisable;
            Posix_CommConfig.c_cc[VSUSP] = vdisable;
pixhawk's avatar
pixhawk committed
865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888
#endif //_POSIX_VDISABLE
            setBaudRate(Settings.BaudRate);
            setDataBits(Settings.DataBits);
            setParity(Settings.Parity);
            setStopBits(Settings.StopBits);
            setFlowControl(Settings.FlowControl);
            setTimeout(Settings.Timeout_Millisec);
            tcsetattr(fd, TCSAFLUSH, &Posix_CommConfig);
        } else {
            qDebug("could not open file: %s", strerror(errno));
        }
    }
    UNLOCK_MUTEX();
    return isOpen();
}

/*!
\fn void Posix_QextSerialPort::close()
Closes a serial port.  This function has no effect if the serial port associated with the class
is not currently open.
*/
void Posix_QextSerialPort::close()
{
    LOCK_MUTEX();
889 890 891 892 893 894 895 896 897 898
    if( isOpen() ) {
        // Force a flush and then restore the original termios
        flush();
        // Using both TCSAFLUSH and TCSANOW here discards any pending input
        tcsetattr(fd, TCSAFLUSH | TCSANOW, &old_termios);   // Restore termios
        // Be a good QIODevice and call QIODevice::close() before POSIX close()
        //  so the aboutToClose() signal is emitted at the proper time
        QIODevice::close();	// Flag the device as closed
        // QIODevice::close() doesn't actually close the port, so do that here
        ::close(fd);
pixhawk's avatar
pixhawk committed
899 900 901 902 903 904 905 906 907 908 909 910 911
    }
    UNLOCK_MUTEX();
}

/*!
\fn void Posix_QextSerialPort::flush()
Flushes all pending I/O to the serial port.  This function has no effect if the serial port
associated with the class is not currently open.
*/
void Posix_QextSerialPort::flush()
{
    LOCK_MUTEX();
    if (isOpen())
912
        tcflush(fd, TCIOFLUSH);
pixhawk's avatar
pixhawk committed
913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971
    UNLOCK_MUTEX();
}

/*!
\fn qint64 Posix_QextSerialPort::size() const
This function will return the number of bytes waiting in the receive queue of the serial port.
It is included primarily to provide a complete QIODevice interface, and will not record errors
in the lastErr member (because it is const).  This function is also not thread-safe - in
multithreading situations, use Posix_QextSerialPort::bytesWaiting() instead.
*/
qint64 Posix_QextSerialPort::size() const
{
    int numBytes;
    if (ioctl(fd, FIONREAD, &numBytes)<0) {
        numBytes = 0;
    }
    return (qint64)numBytes;
}

/*!
\fn qint64 Posix_QextSerialPort::bytesAvailable()
Returns the number of bytes waiting in the port's receive queue.  This function will return 0 if
the port is not currently open, or -1 on error.
*/
qint64 Posix_QextSerialPort::bytesAvailable() const
{
    LOCK_MUTEX();
    if (isOpen()) {
        int bytesQueued;
        if (ioctl(fd, FIONREAD, &bytesQueued) == -1) {
            UNLOCK_MUTEX();
            return (qint64)-1;
        }
        UNLOCK_MUTEX();
        return bytesQueued + QIODevice::bytesAvailable();
    }
    UNLOCK_MUTEX();
    return 0;
}

/*!
\fn void Posix_QextSerialPort::ungetChar(char)
This function is included to implement the full QIODevice interface, and currently has no
purpose within this class.  This function is meaningless on an unbuffered device and currently
only prints a warning message to that effect.
*/
void Posix_QextSerialPort::ungetChar(char)
{
    /*meaningless on unbuffered sequential device - return error and print a warning*/
    TTY_WARNING("Posix_QextSerialPort: ungetChar() called on an unbuffered sequential device - operation is meaningless");
}

/*!
\fn void Posix_QextSerialPort::translateError(ulong error)
Translates a system-specific error code to a QextSerialPort error code.  Used internally.
*/
void Posix_QextSerialPort::translateError(ulong error)
{
    switch (error) {
972 973 974 975 976 977 978 979 980 981 982 983
    case EBADF:
    case ENOTTY:
        lastErr=E_INVALID_FD;
        break;

    case EINTR:
        lastErr=E_CAUGHT_NON_BLOCKED_SIGNAL;
        break;

    case ENOMEM:
        lastErr=E_NO_MEMORY;
        break;
pixhawk's avatar
pixhawk committed
984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999
    }
}

/*!
\fn void Posix_QextSerialPort::setDtr(bool set)
Sets DTR line to the requested state (high by default).  This function will have no effect if
the port associated with the class is not currently open.
*/
void Posix_QextSerialPort::setDtr(bool set)
{
    LOCK_MUTEX();
    if (isOpen()) {
        int status;
        ioctl(fd, TIOCMGET, &status);
        if (set) {
            status|=TIOCM_DTR;
1000
        } else {
pixhawk's avatar
pixhawk committed
1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020
            status&=~TIOCM_DTR;
        }
        ioctl(fd, TIOCMSET, &status);
    }
    UNLOCK_MUTEX();
}

/*!
\fn void Posix_QextSerialPort::setRts(bool set)
Sets RTS line to the requested state (high by default).  This function will have no effect if
the port associated with the class is not currently open.
*/
void Posix_QextSerialPort::setRts(bool set)
{
    LOCK_MUTEX();
    if (isOpen()) {
        int status;
        ioctl(fd, TIOCMGET, &status);
        if (set) {
            status|=TIOCM_RTS;
1021
        } else {
pixhawk's avatar
pixhawk committed
1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121
            status&=~TIOCM_RTS;
        }
        ioctl(fd, TIOCMSET, &status);
    }
    UNLOCK_MUTEX();
}

/*!
\fn unsigned long Posix_QextSerialPort::lineStatus()
returns the line status as stored by the port function.  This function will retrieve the states
of the following lines: DCD, CTS, DSR, and RI.  On POSIX systems, the following additional lines
can be monitored: DTR, RTS, Secondary TXD, and Secondary RXD.  The value returned is an unsigned
long with specific bits indicating which lines are high.  The following constants should be used
to examine the states of individual lines:

\verbatim
Mask        Line
------      ----
LS_CTS      CTS
LS_DSR      DSR
LS_DCD      DCD
LS_RI       RI
LS_RTS      RTS (POSIX only)
LS_DTR      DTR (POSIX only)
LS_ST       Secondary TXD (POSIX only)
LS_SR       Secondary RXD (POSIX only)
\endverbatim

This function will return 0 if the port associated with the class is not currently open.
*/
unsigned long Posix_QextSerialPort::lineStatus()
{
    unsigned long Status=0, Temp=0;
    LOCK_MUTEX();
    if (isOpen()) {
        ioctl(fd, TIOCMGET, &Temp);
        if (Temp&TIOCM_CTS) {
            Status|=LS_CTS;
        }
        if (Temp&TIOCM_DSR) {
            Status|=LS_DSR;
        }
        if (Temp&TIOCM_RI) {
            Status|=LS_RI;
        }
        if (Temp&TIOCM_CD) {
            Status|=LS_DCD;
        }
        if (Temp&TIOCM_DTR) {
            Status|=LS_DTR;
        }
        if (Temp&TIOCM_RTS) {
            Status|=LS_RTS;
        }
        if (Temp&TIOCM_ST) {
            Status|=LS_ST;
        }
        if (Temp&TIOCM_SR) {
            Status|=LS_SR;
        }
    }
    UNLOCK_MUTEX();
    return Status;
}

/*!
\fn qint64 Posix_QextSerialPort::readData(char * data, qint64 maxSize)
Reads a block of data from the serial port.  This function will read at most maxSize bytes from
the serial port and place them in the buffer pointed to by data.  Return value is the number of
bytes actually read, or -1 on error.

\warning before calling this function ensure that serial port associated with this class
is currently open (use isOpen() function to check if port is open).
*/
qint64 Posix_QextSerialPort::readData(char * data, qint64 maxSize)
{
    LOCK_MUTEX();
    int retVal = 0;
    retVal = ::read(fd, data, maxSize);
    if (retVal == -1)
        lastErr = E_READ_FAILED;
    UNLOCK_MUTEX();

    return retVal;
}

/*!
\fn qint64 Posix_QextSerialPort::writeData(const char * data, qint64 maxSize)
Writes a block of data to the serial port.  This function will write maxSize bytes
from the buffer pointed to by data to the serial port.  Return value is the number
of bytes actually written, or -1 on error.

\warning before calling this function ensure that serial port associated with this class
is currently open (use isOpen() function to check if port is open).
*/
qint64 Posix_QextSerialPort::writeData(const char * data, qint64 maxSize)
{
    LOCK_MUTEX();
    int retVal = 0;
    retVal = ::write(fd, data, maxSize);
1122
    if (retVal == -1) {
1123
        lastErr = E_WRITE_FAILED;
1124
    }
pixhawk's avatar
pixhawk committed
1125
    UNLOCK_MUTEX();
1126

pixhawk's avatar
pixhawk committed
1127 1128
    return (qint64)retVal;
}