ucommon
commoncpp/serial.h
Go to the documentation of this file.
00001 // Copyright (C) 1999-2005 Open Source Telecom Corporation.
00002 // Copyright (C) 2006-2014 David Sugar, Tycho Softworks.
00003 //
00004 // This program is free software; you can redistribute it and/or modify
00005 // it under the terms of the GNU General Public License as published by
00006 // the Free Software Foundation; either version 2 of the License, or
00007 // (at your option) any later version.
00008 //
00009 // This program is distributed in the hope that it will be useful,
00010 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00011 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012 // GNU General Public License for more details.
00013 //
00014 // You should have received a copy of the GNU Lesser General Public License
00015 // along with this program.  If not, see <http://www.gnu.org/licenses/>.
00016 //
00017 // As a special exception, you may use this file as part of a free software
00018 // library without restriction.  Specifically, if other files instantiate
00019 // templates or use macros or inline functions from this file, or you compile
00020 // this file and link it with other files to produce an executable, this
00021 // file does not by itself cause the resulting executable to be covered by
00022 // the GNU General Public License.  This exception does not however
00023 // invalidate any other reasons why the executable file might be covered by
00024 // the GNU General Public License.
00025 //
00026 // This exception applies only to the code released under the name GNU
00027 // Common C++.  If you copy code from other releases into a copy of GNU
00028 // Common C++, as the General Public License permits, the exception does
00029 // not apply to the code that you add in this way.  To avoid misleading
00030 // anyone as to the status of such modified files, you must delete
00031 // this exception notice from them.
00032 //
00033 // If you write modifications of your own for GNU Common C++, it is your choice
00034 // whether to permit this exception to apply to your modifications.
00035 // If you do not wish that, delete this exception notice.
00036 //
00037 
00043 #ifndef COMMONCPP_SERIAL_H_
00044 #define COMMONCPP_SERIAL_H_
00045 
00046 #ifndef COMMONCPP_CONFIG_H_
00047 #include <commoncpp/config.h>
00048 #endif
00049 
00050 #ifndef COMMONCPP_THREAD_H_
00051 #include <commoncpp/thread.h>
00052 #endif
00053 
00054 #ifndef COMMMONCPP_EXCEPTION_H_
00055 #include <commoncpp/exception.h>
00056 #endif
00057 
00058 namespace ost {
00059 
00090 class __EXPORT Serial
00091 {
00092 public:
00093     enum Error {
00094         errSuccess = 0,
00095         errOpenNoTty,
00096         errOpenFailed,
00097         errSpeedInvalid,
00098         errFlowInvalid,
00099         errParityInvalid,
00100         errCharsizeInvalid,
00101         errStopbitsInvalid,
00102         errOptionInvalid,
00103         errResourceFailure,
00104         errOutput,
00105         errInput,
00106         errTimeout,
00107         errExtended
00108     };
00109     typedef enum Error Error;
00110 
00111     enum Flow {
00112         flowNone,
00113         flowSoft,
00114         flowHard,
00115         flowBoth
00116     };
00117     typedef enum Flow Flow;
00118 
00119     enum Parity {
00120         parityNone,
00121         parityOdd,
00122         parityEven
00123     };
00124     typedef enum Parity Parity;
00125 
00126     enum Pending {
00127         pendingInput,
00128         pendingOutput,
00129         pendingError
00130     };
00131     typedef enum Pending Pending;
00132 
00133 private:
00134     Error errid;
00135     char *errstr;
00136 
00137     struct {
00138         bool thrown: 1;
00139         bool linebuf: 1;
00140     } flags;
00141 
00142     void *original;
00143     void *current;
00144 
00148     void initSerial(void);
00149 
00150 protected:
00151     fd_t dev;
00152     int bufsize;
00153 
00159     void open(const char *fname);
00160 
00165     void close(void);
00166 
00174     virtual int aRead(char * Data, const int Length);
00175 
00182     virtual int aWrite(const char * Data, const int Length);
00183 
00191     Error error(Error error, char *errstr = NULL);
00192 
00199     inline void error(char *err)
00200         {error(errExtended, err);}
00201 
00202 
00209     inline void setError(bool enable)
00210         {flags.thrown = !enable;}
00211 
00222     int setPacketInput(int size, unsigned char btimer = 0);
00223 
00233     int setLineInput(char newline = 13, char nl1 = 0);
00234 
00238     void restore(void);
00239 
00243     void flushInput(void);
00244 
00248     void flushOutput(void);
00249 
00253     void waitOutput(void);
00254 
00259     void endSerial(void);
00260 
00266     void initConfig(void);
00267 
00272     Serial()
00273         {initSerial();}
00274 
00281     Serial(const char *name);
00282 
00283 
00284 public:
00285 
00292     virtual ~Serial();
00293 
00298     Serial &operator=(const Serial &from);
00299 
00306     Error setSpeed(unsigned long speed);
00307 
00314     Error setCharBits(int bits);
00315 
00322     Error setParity(Parity parity);
00323 
00330     Error setStopBits(int bits);
00331 
00338     Error setFlowControl(Flow flow);
00339 
00345     void toggleDTR(timeout_t millisec);
00346 
00350     void sendBreak(void);
00351 
00358     inline Error getErrorNumber(void)
00359         {return errid;}
00360 
00367     inline char *getErrorString(void)
00368         {return errstr;}
00369 
00377     inline int getBufferSize(void)
00378         {return bufsize;}
00379 
00389     virtual bool isPending(Pending pend, timeout_t timeout = TIMEOUT_INF);
00390 };
00391 
00413 class __EXPORT TTYStream : protected std::streambuf, public Serial, public std::iostream
00414 {
00415 private:
00416     int doallocate();
00417 
00418     friend TTYStream& crlf(TTYStream&);
00419     friend TTYStream& lfcr(TTYStream&);
00420 
00421 protected:
00422     char *gbuf, *pbuf;
00423     timeout_t timeout;
00424 
00429     TTYStream();
00430 
00435     void allocate(void);
00436 
00441     void endStream(void);
00442 
00449     int underflow(void);
00450 
00459     int uflow(void);
00460 
00468     int overflow(int ch);
00469 
00470 public:
00477     TTYStream(const char *filename, timeout_t to = 0);
00478 
00482     virtual ~TTYStream();
00483 
00489     inline void setTimeout(timeout_t to)
00490         {timeout = to;}
00491 
00499     void interactive(bool flag);
00500 
00507     int sync(void);
00508 
00520     bool isPending(Pending pend, timeout_t timeout = TIMEOUT_INF);
00521 };
00522 
00532 class __EXPORT ttystream : public TTYStream
00533 {
00534 public:
00538     ttystream();
00539 
00547     ttystream(const char *name);
00548 
00554     void open(const char *name);
00555 
00559     void close(void);
00560 
00564     inline bool operator!()
00565         {return (dev < 0);}
00566 };
00567 
00578 class __EXPORT TTYSession : public Thread, public TTYStream
00579 {
00580 public:
00588     TTYSession(const char *name, int pri = 0, int stack = 0);
00589 
00590     virtual ~TTYSession();
00591 };
00592 
00593 #ifndef _MSWINDOWS_
00594 
00595 //  Not support this right now.......
00596 //
00597 class SerialPort;
00598 class SerialService;
00599 
00621 class __EXPORT SerialPort: public Serial, public TimerPort
00622 {
00623 private:
00624     SerialPort *next, *prev;
00625     SerialService *service;
00626 #ifdef  USE_POLL
00627     struct pollfd *ufd;
00628 #endif
00629     bool detect_pending;
00630     bool detect_output;
00631     bool detect_disconnect;
00632 
00633     friend class SerialService;
00634 
00635 protected:
00642     SerialPort(SerialService *svc, const char *name);
00643 
00648     virtual ~SerialPort();
00649 
00654     void setDetectPending( bool );
00655 
00659     inline bool getDetectPending( void ) const
00660         { return detect_pending; }
00661 
00666     void setDetectOutput( bool );
00667 
00671     inline bool getDetectOutput( void ) const
00672         { return detect_output; }
00673 
00678     virtual void expired(void);
00679 
00685     virtual void pending(void);
00686 
00691     virtual void disconnect(void);
00692 
00702     inline int output(void *buf, int len)
00703         {return aWrite((char *)buf, len);}
00704 
00708     virtual void output(void);
00709 
00719     inline int input(void *buf, int len)
00720         {return aRead((char *)buf, len);}
00721 
00722 public:
00730     void setTimer(timeout_t timeout = 0);
00731 
00737     void incTimer(timeout_t timeout);
00738 };
00739 
00762 class __EXPORT SerialService : public Thread, private Mutex
00763 {
00764 private:
00765     fd_set connect;
00766     int iosync[2];
00767     int hiwater;
00768     int count;
00769     SerialPort *first, *last;
00770 
00776     void attach(SerialPort *port);
00777 
00783     void detach(SerialPort *port);
00784 
00788     void run(void);
00789 
00790     friend class SerialPort;
00791 
00792 protected:
00799     virtual void onUpdate(unsigned char flag);
00800 
00805     virtual void onEvent(void);
00806 
00813     virtual void onCallback(SerialPort *port);
00814 
00815 public:
00825     void update(unsigned char flag = 0xff);
00826 
00835     SerialService(int pri = 0, size_t stack = 0, const char *id = NULL);
00836 
00840     virtual ~SerialService();
00841 
00848     inline int getCount(void)
00849         {return count;}
00850 };
00851 
00852 #endif
00853 
00854 #ifdef  CCXX_EXCEPTIONS
00855 class __EXPORT SerException : public IOException
00856 {
00857 public:
00858     SerException(const String &str) : IOException(str) {}
00859 };
00860 #endif
00861 
00862 } // namespace ost
00863 
00864 #endif