This file is indexed.

/usr/include/commoncpp/serial.h is in libucommon-dev 7.0.0-9.

This file is owned by root:root, with mode 0o644.

The actual contents of the file can be viewed below.

  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
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
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
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
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
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
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
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
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
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
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
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
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
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
// Copyright (C) 1999-2005 Open Source Telecom Corporation.
// Copyright (C) 2006-2014 David Sugar, Tycho Softworks.
// Copyright (C) 2015 Cherokees of Idaho.
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with this program.  If not, see <http://www.gnu.org/licenses/>.
//
// As a special exception, you may use this file as part of a free software
// library without restriction.  Specifically, if other files instantiate
// templates or use macros or inline functions from this file, or you compile
// this file and link it with other files to produce an executable, this
// file does not by itself cause the resulting executable to be covered by
// the GNU General Public License.  This exception does not however
// invalidate any other reasons why the executable file might be covered by
// the GNU General Public License.
//
// This exception applies only to the code released under the name GNU
// Common C++.  If you copy code from other releases into a copy of GNU
// Common C++, as the General Public License permits, the exception does
// not apply to the code that you add in this way.  To avoid misleading
// anyone as to the status of such modified files, you must delete
// this exception notice from them.
//
// If you write modifications of your own for GNU Common C++, it is your choice
// whether to permit this exception to apply to your modifications.
// If you do not wish that, delete this exception notice.
//

/**
 * @file serial.h
 * @short Serial I/O services.
 **/

#ifndef COMMONCPP_SERIAL_H_
#define COMMONCPP_SERIAL_H_

#ifndef COMMONCPP_CONFIG_H_
#include <commoncpp/config.h>
#endif

#ifndef COMMONCPP_THREAD_H_
#include <commoncpp/thread.h>
#endif

#ifndef COMMMONCPP_EXCEPTION_H_
#include <commoncpp/exception.h>
#endif

namespace ost {

/**
 * The Serial class is used as the base for all serial I/O services
 * under APE.  A serial is a system serial port that is used either
 * for line or packet based data input.  Serial ports may also be
 * "streamable" in a derived form.
 *
 *  Common C++ serial I/O classes are used to manage serial devices and
 *  implement serial device protocols.  From the point of view of Common C++,
 *  serial devices are supported by the underlying Posix specified "termios"
 *  call interface.
 *
 *  The serial I/O base class is used to hold a descriptor to a serial device
 *  and to provide an exception handling interface for all serial I/O classes.
 *  The base class is also used to specify serial I/O properties such as
 *  communication speed, flow control, data size, and parity.  The "Serial"
 *  base class is not itself directly used in application development,
 *  however.
 *
 *  Common C++ Serial I/O is itself divided into two conceptual modes; frame
 *  oriented and line oriented I/O.  Both frame and line oriented I/O makes
 *  use of the ability of the underlying tty driver to buffer data and return
 *  "ready" status from when select either a specified number of bytes or
 *  newline record has been reached by manipulating termios c_cc fields
 *  appropriately.  This provides some advantage in that a given thread
 *  servicing a serial port can block and wait rather than have to continually
 *  poll or read each and every byte as soon as it appears at the serial port.
 *
 * @author David Sugar <dyfet@ostel.com>
 * @short base class for all serial I/O services.
 */
class __EXPORT Serial
{
public:
    enum Error {
        errSuccess = 0,
        errOpenNoTty,
        errOpenFailed,
        errSpeedInvalid,
        errFlowInvalid,
        errParityInvalid,
        errCharsizeInvalid,
        errStopbitsInvalid,
        errOptionInvalid,
        errResourceFailure,
        errOutput,
        errInput,
        errTimeout,
        errExtended
    };
    typedef enum Error Error;

    enum Flow {
        flowNone,
        flowSoft,
        flowHard,
        flowBoth
    };
    typedef enum Flow Flow;

    enum Parity {
        parityNone,
        parityOdd,
        parityEven
    };
    typedef enum Parity Parity;

    enum Pending {
        pendingInput,
        pendingOutput,
        pendingError
    };
    typedef enum Pending Pending;

private:
    Error errid;
    char *errstr;

    struct {
        bool thrown: 1;
        bool linebuf: 1;
    } flags;

    void *original;
    void *current;

    /**
     * Used to properly initialize serial object.
     */
    void initSerial(void);

protected:
    fd_t dev;
    int bufsize;

    /**
     * Opens the serial device.
     *
     * @param fname Pathname of device to open
     */
    void open(const char *fname);

    /**
     * Closes the serial device.
     *
     */
    void close(void);

    /**
     * Reads from serial device.
     *
     * @param Data  Point to character buffer to receive data.  Buffers MUST
     *              be at least Length + 1 bytes in size.
     * @param Length Number of bytes to read.
     */
    virtual int aRead(char * Data, const int Length);

    /**
     * Writes to serial device.
     *
     * @param Data  Point to character buffer containing data to write.  Buffers MUST
     * @param Length Number of bytes to write.
     */
    virtual int aWrite(const char * Data, const int Length);

    /**
     * This service is used to throw all serial errors which usually
     * occur during the serial constructor.
     *
     * @param error defined serial error id.
     * @param errstr string or message to optionally pass.
     */
    Error error(Error error, char *errstr = NULL);

    /**
     * This service is used to thow application defined serial
     * errors where the application specific error code is a string.
     *
     * @param err string or message to pass.
     */
    inline void error(char *err) {
        error(errExtended, err);
    }


    /**
     * This method is used to turn the error handler on or off for
     * "throwing" execptions by manipulating the thrown flag.
     *
     * @param enable true to enable handler.
     */
    inline void setError(bool enable) {
        flags.thrown = !enable;
    }

    /**
     * Set packet read mode and "size" of packet read buffer.
     * This sets VMIN to x.  VTIM is normally set to "0" so that
     * "isPending()" can wait for an entire packet rather than just
     * the first byte.
     *
     * @return actual buffer size set.
     * @param size of packet read request.
     * @param btimer optional inter-byte data packet timeout.
     */
    int setPacketInput(int size, uint8_t btimer = 0);

    /**
     * Set "line buffering" read mode and specifies the newline
     * character to be used in seperating line records.  isPending
     * can then be used to wait for an entire line of input.
     *
     * @param newline newline character.
     * @param nl1 EOL2 control character.
     * @return size of conical input buffer.
     */
    int setLineInput(char newline = 13, char nl1 = 0);

    /**
     * Restore serial device to the original settings at time of open.
     */
    void restore(void);

    /**
     * Used to flush the input waiting queue.
     */
    void flushInput(void);

    /**
     * Used to flush any pending output data.
     */
    void flushOutput(void);

    /**
     * Used to wait until all output has been sent.
     */
    void waitOutput(void);

    /**
     * Used as the default destructor for ending serial I/O
     * services.  It will restore the port to it's original state.
     */
    void endSerial(void);

    /**
     * Used to initialize a newly opened serial file handle.  You
     * should set serial properties and DTR manually before first
     * use.
     */
    void initConfig(void);

    /**
     * This allows later ttystream class to open and close a serial
     * device.
     */
    Serial() {
        initSerial();
    }

    /**
     * A serial object may be constructed from a named file on the
     * file system.  This named device must be "isatty()".
     *
     * @param name of file.
     */
    Serial(const char *name);


public:

    /**
     * The serial base class may be "thrown" as a result on an error,
     * and the "catcher" may then choose to destory the object.  By
     * assuring the socket base class is a virtual destructor, we
     * can assure the full object is properly terminated.
     */
    virtual ~Serial();

    /**
     * Serial ports may also be duplecated by the assignment
     * operator.
     */
    Serial &operator=(const Serial &from);

    /**
     * Set serial port speed for both input and output.
     *
     * @return 0 on success.
     * @param speed to select. 0 signifies modem "hang up".
     */
    Error setSpeed(unsigned long speed);

    /**
     * Set character size.
     *
     * @return 0 on success.
     * @param bits character size to use (usually 7 or 8).
     */
    Error setCharBits(int bits);

    /**
     * Set parity mode.
     *
     * @return 0 on success.
     * @param parity mode.
     */
    Error setParity(Parity parity);

    /**
     * Set number of stop bits.
     *
     * @return 0 on success.
     * @param bits stop bits.
     */
    Error setStopBits(int bits);

    /**
     * Set flow control.
     *
     * @return 0 on success.
     * @param flow control mode.
     */
    Error setFlowControl(Flow flow);

    /**
     * Set the DTR mode off momentarily.
     *
     * @param millisec number of milliseconds.
     */
    void toggleDTR(timeout_t millisec);

    /**
     * Send the "break" signal.
     */
    void sendBreak(void);

    /**
     * Often used by a "catch" to fetch the last error of a thrown
     * serial.
     *
     * @return error numbr of last Error.
     */
    inline Error getErrorNumber(void) const {
        return errid;
    }

    /**
     * Often used by a "catch" to fetch the user set error string
     * of a thrown serial.
     *
     * @return string for error message.
     */
    inline char *getErrorString(void) const {
        return errstr;
    }

    /**
     * Get the "buffer" size for buffered operations.  This can
     * be used when setting packet or line read modes to determine
     * how many bytes to wait for in a given read call.
     *
     * @return number of bytes used for buffering.
     */
    inline int getBufferSize(void) const {
        return bufsize;
    }

    /**
     * Get the status of pending operations.  This can be used to
     * examine if input or output is waiting, or if an error has
     * occured on the serial device.
     *
     * @return true if ready, false if timeout.
     * @param pend ready check to perform.
     * @param timeout in milliseconds.
     */
    virtual bool isPending(Pending pend, timeout_t timeout = TIMEOUT_INF);
};

/**
 * TTY streams are used to represent serial connections that are fully
 * "streamable" objects using C++ stream classes and friends.
 *
 * The first application relevant serial I/O class is the TTYStream class.
 * TTYStream offers a linearly buffered "streaming" I/O session with the
 * serial device.  Furthermore, traditional C++ "stream" operators (<< and
 * >>) may be used with the serial device.  A more "true" to ANSI C++ library
 * format "ttystream" is also available, and this supports an "open" method
 * in which one can pass initial serial device parameters immediately
 * following the device name in a single string, as in
 * "/dev/tty3a:9600,7,e,1", as an example.
 *
 * The TTYSession aggragates a TTYStream and a Common C++ Thread which is
 * assumed to be the execution context that will be used to perform actual
 * I/O operations.  This class is very anagolous to TCPSession.
 *
 *
 * @author David Sugar <dyfet@ostel.com>
 * @short streamable tty serial I/O class.
 */
class __EXPORT TTYStream : protected std::streambuf, public Serial, public std::iostream
{
private:
    int doallocate();

    friend TTYStream& crlf(TTYStream&);
    friend TTYStream& lfcr(TTYStream&);

    __DELETE_COPY(TTYStream);

protected:
    char *gbuf, *pbuf;
    timeout_t timeout;

    /**
     * This constructor is used to derive "ttystream", a more
     * C++ style version of the TTYStream class.
     */
    TTYStream();

    /**
     * Used to allocate the buffer space needed for iostream
     * operations.  This is based on MAX_INPUT.
     */
    void allocate(void);

    /**
     * Used to terminate the buffer space and clean up the tty
     * connection.  This function is called by the destructor.
     */
    void endStream(void);

    /**
     * This streambuf method is used to load the input buffer
     * through the established tty serial port.
     *
     * @return char from get buffer, EOF also possible.
     */
    int underflow(void) __OVERRIDE;

    /**
     * This streambuf method is used for doing unbuffered reads
     * through the establish tty serial port when in interactive mode.
     * Also this method will handle proper use of buffers if not in
     * interative mode.
     *
     * @return char from tty serial port, EOF also possible.
     */
    int uflow(void) __OVERRIDE;

    /**
     * This streambuf method is used to write the output
     * buffer through the established tty port.
     *
     * @param ch char to push through.
     * @return char pushed through.
     */
    int overflow(int ch) __OVERRIDE;

public:
    /**
     * Create and open a tty serial port.
     *
     * @param filename char name of device to open.
     * @param to default timeout.
     */
    TTYStream(const char *filename, timeout_t to = 0);

    /**
     * End the tty stream and cleanup.
     */
    virtual ~TTYStream();

    /**
     * Set the timeout control.
     *
     * @param to timeout to use.
     */
    inline void setTimeout(timeout_t to) {
        timeout = to;
    }

    /**
     * Set tty mode to buffered or "interactive".  When interactive,
     * all streamed I/O is directly sent to the serial port
     * immediately.
     *
     * @param flag bool set to true to make interactive.
     */
    void interactive(bool flag);

    /**
     * Flushes the stream input and out buffers, writes
     * pending output.
     *
     * @return 0 on success.
     */
    int sync(void);

    /**
     * Get the status of pending operations.  This can be used to
     * examine if input or output is waiting, or if an error has
     * occured on the serial device.  If read buffer contains data
     * then input is ready and if write buffer contains data it is
     * first flushed then checked.
     *
     * @return true if ready, false if timeout.
     * @param pend ready check to perform.
     * @param timeout in milliseconds.
     */
    bool isPending(Pending pend, timeout_t timeout = TIMEOUT_INF) __OVERRIDE;
};

/**
 * A more natural C++ "ttystream" class for use by non-threaded
 * applications.  This class behaves a lot more like fstream and
 * similar classes.
 *
 * @author David Sugar <dyfet@ostel.com>
 * @short C++ "fstream" style ttystream class.
 */

class __EXPORT ttystream : public TTYStream
{
private:
    __DELETE_COPY(ttystream);

public:
    /**
     * Construct an unopened "ttystream" object.
     */
    ttystream();

    /**
     * Construct and "open" a tty stream object.  A filename in
     * the form "device:options[,options]" may be used to pass
     * device options as part of the open.
     *
     * @param name of file and serial options.
     */
    ttystream(const char *name);

    /**
     * Open method for a tty stream.
     *
     * @param name filename to open.
     */
    void open(const char *name);

    /**
     * Close method for a tty stream.
     */
    void close(void);

    /**
     * Test to see if stream is opened.
     */
    inline bool operator!() {
        return (dev < 0);
    }
};

/**
 *
 * The TTYSession aggragates a TTYStream and a Common C++ Thread which is
 * assumed to be the execution context that will be used to perform actual
 * I/O operations.  This class is very anagolous to TCPSession.
 *
 * @author David Sugar <dyfet@ostel.com>
 * @short This class is very anagolous to TCPSession.
 */

class __EXPORT TTYSession : public Thread, public TTYStream
{
private:
    __DELETE_COPY(TTYSession);

public:
    /**
     * Create TTY stream that will be managed by it's own thread.
     *
     * @param name of tty device to open.
     * @param pri execution priority.
     * @param stack allocation needed on some platforms.
     */
    TTYSession(const char *name, int pri = 0, int stack = 0);

    virtual ~TTYSession();
};

#ifndef _MSWINDOWS_

//  Not support this right now.......
//
class SerialPort;
class SerialService;

/**
 * The serial port is an internal class which is attached to and then
 * serviced by a specified SerialService thread.  Derived versions of
 * this class offer specific functionality such as serial integration
 * protocols.
 *
 * The TTYPort and TTYService classes are used to form thread-pool serviced
 * serial I/O protocol sets.  These can be used when one has a large number
 * of serial devices to manage, and a single (or limited number of) thread(s)
 * can then be used to service the tty port objects present.  Each tty port
 * supports a timer control and several virtual methods that the service
 * thread can call when events occur.  This model provides for "callback"
 * event management, whereby the service thread performs a "callback" into
 * the port object when events occur.  Specific events supported include the
 * expiration of a TTYPort timer, pending input data waiting to be read, and
 * "sighup" connection breaks.
 *
 *
 * @author David Sugar <dyfet@ostel.com>
 * @short base class for thread pool serviced serial I/O.
 */
class __EXPORT SerialPort: public Serial, public TimerPort
{
private:
    SerialPort *next, *prev;
    SerialService *service;
#ifdef  USE_POLL
    struct pollfd *ufd;
#endif
    bool detect_pending;
    bool detect_output;
    bool detect_disconnect;

    friend class SerialService;

    __DELETE_COPY(SerialPort);

protected:
    /**
     * Construct a tty serial port for a named serial device.
     *
     * @param svc pool thread object.
     * @param name of tty port.
     */
    SerialPort(SerialService *svc, const char *name);

    /**
     * Disconnect the Serial Port from the service pool thread
     * and shutdown the port.
     */
    virtual ~SerialPort();

    /**
     * Used to indicate if the service thread should monitor pending
     * data for us.
     */
    void setDetectPending( bool );

    /**
     * Get the current state of the DetectPending flag.
     */
    inline bool getDetectPending( void ) const {
        return detect_pending; 
    }

    /**
     * Used to indicate if output ready monitoring should be performed
     * by the service thread.
     */
    void setDetectOutput( bool );

    /**
     * Get the current state of the DetectOutput flag.
     */
    inline bool getDetectOutput( void ) const {
        return detect_output; 
    }

    /**
     * Called by the service thread when the objects timer
     * has expired.
     */
    virtual void expired(void);

    /**
     * Called by the service thread when input data is pending
     * for this tty port.  Effected by setPacketInput and by
     * setLineInput.
     */
    virtual void pending(void);

    /**
     * Called by the service thread when an exception has occured
     * such as a hangup.
     */
    virtual void disconnect(void);

    /**
     * Transmit "send" data to the serial port.  This is not public
     * since it's meant to support internal protocols rather than
     * direct public access to the device.
     *
     * @return number of bytes send.
     * @param buf address of buffer to send.
     * @param len of bytes to send.
     */
    inline int output(void *buf, int len) {
        return aWrite((char *)buf, len);
    }

    /**
     * Perform when output is available for sending data.
     */
    virtual void output(void);

    /**
     * Receive "input" for pending data from the serial port.  This
     * is not a public member since it's meant to support internal
     * protocols rather than direct external access to the device.
     *
     * @return number of bytes received.
     * @param buf address of buffer to input.
     * @param len of input buffer used.
     */
    inline int input(void *buf, int len) {
        return aRead((char *)buf, len);
    }

public:
    /**
     * Derived setTimer to notify the service thread pool of changes
     * in expected timeout.  This allows SerialService to
     * reschedule all timers.
     *
     * @param timeout in milliseconds.
     */
    void setTimer(timeout_t timeout = 0);

    /**
     * Derived incTimer to notify the service thread pool of a
     * change in expected timeout.  This allows SerialService to
     * reschedule all timers.
     */
    void incTimer(timeout_t timeout);
};

/**
 * The SerialService is a thead service object that is meant to service
 * attached serial ports.  Multiple pool objects may be created and
 * multiple serial ports may be attached to the same thread of
 * of execution.  This allows one to balance threads and the serial ports
 * they service.
 *
 *  The TTYPort and TTYService classes are used to form thread-pool serviced
 *  serial I/O protocol sets.  These can be used when one has a large number
 *  of serial devices to manage, and a single (or limited number of) thread(s)
 *  can then be used to service the tty port objects present.  Each tty port
 *  supports a timer control and several virtual methods that the service
 *  thread can call when events occur.  This model provides for "callback"
 *  event management, whereby the service thread performs a "callback" into
 *  the port object when events occur.  Specific events supported include the
 *  expiration of a TTYPort timer, pending input data waiting to be read, and
 *  "sighup" connection breaks.
 *
 *
 * @author David Sugar <dyfet@ostel.com>
 * @short Thread pool service for serial ports.
 */
class __EXPORT SerialService : public Thread, private Mutex
{
private:
    fd_set connect;
    int iosync[2];
    int hiwater;
    int count;
    SerialPort *first, *last;

    __DELETE_COPY(SerialService);

    /**
     * Attach a new serial port to this service thread.
     *
     * @param port of SerialPort derived object to attach.
     */
    void attach(SerialPort *port);

    /**
     * Detach a serial port from this service thread.
     *
     * @param port of SerialPort derived object to remove.
     */
    void detach(SerialPort *port);

    /**
     * The service thread itself.
     */
    void run(void) __OVERRIDE;

    friend class SerialPort;

protected:
    /**
     * A virtual handler for processing user defined update
     * requests (1-254) which have been posted through Update.
     *
     * @param flag of update request.
     */
    virtual void onUpdate(uint8_t flag);

    /**
     * A virtual handler for event loop calls.  This can be
     * used to extend event loop processing.
     */
    virtual void onEvent(void);

    /**
     * A virtual handler for adding support for additional
     * callback events into SerialPort.
     *
     * @param port serial port currently being evaluated.
     */
    virtual void onCallback(SerialPort *port);

public:
    /**
     * Notify service thread that a port has been added or
     * removed, or a timer changed, so that a new schedule
     * can be computed for expiring attached ports.  This
     * can also be used to pass requests to the OnUpdate()
     * event handler.
     *
     * @param flag event for OnUpdate, termination, or reschedule.
     */
    void update(uint8_t flag = 0xff);

    /**
     * Create a service thread for attaching serial ports.  The
     * thread begins execution with the first attached port.
     *
     * @param pri of this thread to run under.
     * @param stack stack size.
     * @param id stack ID.
     */
    SerialService(int pri = 0, size_t stack = 0, const char *id = NULL);

    /**
     * Terminate the service thread and update attached objects.
     */
    virtual ~SerialService();

    /**
     * Get current reference count.  This can be used when selecting
     * the lead used service handler from a pool.
     *
     * @return count of active ports.
     */
    inline int getCount(void) const {
        return count;
    }
};

#endif

#ifdef  CCXX_EXCEPTIONS
class __EXPORT SerException : public IOException
{
public:
    SerException(const String &str) : IOException(str) {}
};
#endif

} // namespace ost

#endif