/[projects]/smsdaemon/serialport/SerialPort.cpp
ViewVC logotype

Diff of /smsdaemon/serialport/SerialPort.cpp

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 195 by torben, Sun Nov 2 20:14:20 2008 UTC revision 196 by torben, Thu Dec 18 06:53:29 2008 UTC
# Line 36  Line 36 
36    
37  namespace  namespace
38  {  {
39      //          //
40      // Various error messages used in this file while throwing          // Various error messages used in this file while throwing
41      // exceptions.          // exceptions.
42      //          //
43      const std::string ERR_MSG_PORT_NOT_OPEN     = "Serial port not open." ;          const std::string ERR_MSG_PORT_NOT_OPEN     = "Serial port not open." ;
44      const std::string ERR_MSG_PORT_ALREADY_OPEN = "Serial port already open." ;          const std::string ERR_MSG_PORT_ALREADY_OPEN = "Serial port already open." ;
45      const std::string ERR_MSG_UNSUPPORTED_BAUD  = "Unsupported baud rate." ;          const std::string ERR_MSG_UNSUPPORTED_BAUD  = "Unsupported baud rate." ;
46      const std::string ERR_MSG_UNKNOWN_BAUD      = "Unknown baud rate." ;          const std::string ERR_MSG_UNKNOWN_BAUD      = "Unknown baud rate." ;
47      const std::string ERR_MSG_INVALID_PARITY    = "Invalid parity setting." ;          const std::string ERR_MSG_INVALID_PARITY    = "Invalid parity setting." ;
48      const std::string ERR_MSG_INVALID_STOP_BITS = "Invalid number of stop bits." ;          const std::string ERR_MSG_INVALID_STOP_BITS = "Invalid number of stop bits." ;
49      const std::string ERR_MSG_INVALID_FLOW_CONTROL = "Invalid flow control." ;          const std::string ERR_MSG_INVALID_FLOW_CONTROL = "Invalid flow control." ;
50    
51      /*          /*
52       * Return the difference between the two specified timeval values.           * Return the difference between the two specified timeval values.
53       * This method subtracts secondOperand from firstOperand and returns           * This method subtracts secondOperand from firstOperand and returns
54       * the result as a timeval. The time represented by firstOperand must           * the result as a timeval. The time represented by firstOperand must
55       * be later than the time represented by secondOperand. Otherwise,           * be later than the time represented by secondOperand. Otherwise,
56       * the result of this operator may be undefined.           * the result of this operator may be undefined.
57       */           */
58      const struct timeval          const struct timeval
59      operator-( const struct timeval& firstOperand,                                  operator-( const struct timeval& firstOperand,
60                 const struct timeval& secondOperand ) ;                                             const struct timeval& secondOperand ) ;
61  } ;  } ;
62    
63  class SerialPort::SerialPortImpl : public PosixSignalHandler  class SerialPort::SerialPortImpl : public PosixSignalHandler
64  {  {
65  public:  public:
66      /**          /**
67       * Constructor.           * Constructor.
68       */           */
69      SerialPortImpl( const std::string& serialPortName ) ;          SerialPortImpl( const std::string& serialPortName ) ;
70    
71      /**          /**
72       * Destructor.           * Destructor.
73       */           */
74      ~SerialPortImpl() ;          ~SerialPortImpl() ;
75    
76      /**          /**
77       * Open the serial port.           * Open the serial port.
78       */           */
79      void Open()          void Open()
80          throw( SerialPort::OpenFailed,          throw( SerialPort::OpenFailed,
81                 SerialPort::AlreadyOpen ) ;                 SerialPort::AlreadyOpen ) ;
82    
83      /**          /**
84       * Check if the serial port is currently open.           * Check if the serial port is currently open.
85       */           */
86      bool          bool
87      IsOpen() const ;          IsOpen() const ;
88    
89      /**          /**
90       * Close the serial port.           * Close the serial port.
91       */           */
92      void          void
93      Close()          Close()
94          throw(SerialPort::NotOpen) ;          throw(SerialPort::NotOpen) ;
95    
96      /**          /**
97       * Set the baud rate of the serial port.           * Set the baud rate of the serial port.
98       */           */
99      void          void
100      SetBaudRate( const SerialPort::BaudRate baudRate )          SetBaudRate( const SerialPort::BaudRate baudRate )
101          throw( SerialPort::NotOpen,          throw( SerialPort::NotOpen,
102                 SerialPort::UnsupportedBaudRate,                 SerialPort::UnsupportedBaudRate,
103                 std::invalid_argument,                 std::invalid_argument,
104                 std::runtime_error ) ;                 std::runtime_error ) ;
105    
106      /**          /**
107       * Get the current baud rate.           * Get the current baud rate.
108       */           */
109      SerialPort::BaudRate          SerialPort::BaudRate
110      GetBaudRate() const          GetBaudRate() const
111          throw( SerialPort::NotOpen,          throw( SerialPort::NotOpen,
112                 std::runtime_error ) ;                 std::runtime_error ) ;
113    
114      /**          /**
115       * Set the character size.           * Set the character size.
116       */           */
117      void          void
118      SetCharSize( const SerialPort::CharacterSize charSize )          SetCharSize( const SerialPort::CharacterSize charSize )
119          throw( SerialPort::NotOpen,          throw( SerialPort::NotOpen,
120                 std::invalid_argument,                 std::invalid_argument,
121                 std::runtime_error ) ;                 std::runtime_error ) ;
122    
123      /**          /**
124       * Get the current character size.           * Get the current character size.
125       */           */
126      SerialPort::CharacterSize          SerialPort::CharacterSize
127      GetCharSize() const          GetCharSize() const
128          throw( SerialPort::NotOpen,          throw( SerialPort::NotOpen,
129                 std::runtime_error )  ;                 std::runtime_error )  ;
130    
131      void          void
132      SetParity( const SerialPort::Parity parityType )          SetParity( const SerialPort::Parity parityType )
133          throw( SerialPort::NotOpen,          throw( SerialPort::NotOpen,
134                 std::invalid_argument,                 std::invalid_argument,
135                 std::runtime_error )  ;                 std::runtime_error )  ;
136    
137      SerialPort::Parity          SerialPort::Parity
138      GetParity() const          GetParity() const
139          throw(SerialPort::NotOpen) ;          throw(SerialPort::NotOpen) ;
140    
141      void          void
142      SetNumOfStopBits( const SerialPort::StopBits numOfStopBits )          SetNumOfStopBits( const SerialPort::StopBits numOfStopBits )
143          throw( SerialPort::NotOpen,          throw( SerialPort::NotOpen,
144                 std::invalid_argument )  ;                 std::invalid_argument )  ;
145    
146      SerialPort::StopBits          SerialPort::StopBits
147      GetNumOfStopBits() const          GetNumOfStopBits() const
148          throw(SerialPort::NotOpen) ;          throw(SerialPort::NotOpen) ;
149    
150      void          void
151      SetFlowControl( const SerialPort::FlowControl flowControl )          SetFlowControl( const SerialPort::FlowControl flowControl )
152          throw( SerialPort::NotOpen,          throw( SerialPort::NotOpen,
153                 std::invalid_argument ) ;                 std::invalid_argument ) ;
154    
155      SerialPort::FlowControl          SerialPort::FlowControl
156      GetFlowControl() const          GetFlowControl() const
157          throw( SerialPort::NotOpen ) ;          throw( SerialPort::NotOpen ) ;
158    
159      bool          bool
160      IsDataAvailable() const          IsDataAvailable() const
161          throw( SerialPort::NotOpen,          throw( SerialPort::NotOpen,
162                 std::runtime_error ) ;                 std::runtime_error ) ;
163    
164      unsigned char          unsigned char
165      ReadByte(const unsigned int msTimeout = 0 )          ReadByte(const unsigned int msTimeout = 0 )
166          throw( SerialPort::NotOpen,          throw( SerialPort::NotOpen,
167                 SerialPort::ReadTimeout,                 SerialPort::ReadTimeout,
168                 std::runtime_error ) ;                 std::runtime_error ) ;
169    
170      void          void
171      Read( SerialPort::DataBuffer& dataBuffer,          Read( SerialPort::DataBuffer& dataBuffer,
172            const unsigned int      numOfBytes,                const unsigned int      numOfBytes,
173            const unsigned int      msTimeout )                const unsigned int      msTimeout )
174          throw( SerialPort::NotOpen,          throw( SerialPort::NotOpen,
175                 SerialPort::ReadTimeout,                 SerialPort::ReadTimeout,
176                 std::runtime_error  ) ;                 std::runtime_error  ) ;
177    
178      const std::string          const std::string
179      ReadLine( const unsigned int msTimeout = 0,          ReadLine( const unsigned int msTimeout = 0,
180                const char         lineTerminator = '\n' )                    const char         lineTerminator = '\n' )
181          throw( SerialPort::NotOpen,          throw( SerialPort::NotOpen,
182                 SerialPort::ReadTimeout,                 SerialPort::ReadTimeout,
183                 std::runtime_error ) ;                 std::runtime_error ) ;
184    
185      void          void
186      WriteByte( const unsigned char dataByte )          WriteByte( const unsigned char dataByte )
187          throw( SerialPort::NotOpen,          throw( SerialPort::NotOpen,
188                 std::runtime_error ) ;                 std::runtime_error ) ;
189    
190      void          void
191      Write(const SerialPort::DataBuffer& dataBuffer)          Write(const SerialPort::DataBuffer& dataBuffer)
192          throw( SerialPort::NotOpen,          throw( SerialPort::NotOpen,
193                 std::runtime_error ) ;                 std::runtime_error ) ;
194    
195      void          void
196      Write( const unsigned char* dataBuffer,          Write( const unsigned char* dataBuffer,
197             const unsigned int   bufferSize )                 const unsigned int   bufferSize )
198          throw( SerialPort::NotOpen,          throw( SerialPort::NotOpen,
199                 std::runtime_error ) ;                 std::runtime_error ) ;
200    
201      void          void
202      SetDtr( const bool dtrState )          SetDtr( const bool dtrState )
203          throw( SerialPort::NotOpen,          throw( SerialPort::NotOpen,
204                 std::runtime_error ) ;                 std::runtime_error ) ;
205        
206      bool          bool
207      GetDtr() const          GetDtr() const
208          throw( SerialPort::NotOpen,          throw( SerialPort::NotOpen,
209                 std::runtime_error ) ;                 std::runtime_error ) ;
210    
211      void          void
212      SetRts( const bool rtsState )          SetRts( const bool rtsState )
213          throw( SerialPort::NotOpen,          throw( SerialPort::NotOpen,
214                 std::runtime_error ) ;                 std::runtime_error ) ;
215        
216      bool          bool
217      GetRts() const          GetRts() const
218          throw( SerialPort::NotOpen,          throw( SerialPort::NotOpen,
219                 std::runtime_error ) ;                 std::runtime_error ) ;
220    
221      bool          bool
222      GetCts() const          GetCts() const
223          throw( SerialPort::NotOpen,          throw( SerialPort::NotOpen,
224                 std::runtime_error ) ;                 std::runtime_error ) ;
225    
226        
227      bool          bool
228      GetDsr() const          GetDsr() const
229          throw( SerialPort::NotOpen,          throw( SerialPort::NotOpen,
230                 std::runtime_error ) ;                 std::runtime_error ) ;
231      /*          /*
232       * This method must be defined by all subclasses of           * This method must be defined by all subclasses of
233       * PosixSignalHandler.           * PosixSignalHandler.
234       */           */
235      void          void
236      HandlePosixSignal(int signalNumber) ;          HandlePosixSignal(int signalNumber) ;
237  private:  private:
238      /**          /**
239       * Name of the serial port. On POSIX systems this is the name of           * Name of the serial port. On POSIX systems this is the name of
240       * the device file.           * the device file.
241       */           */
242      std::string mSerialPortName ;          std::string mSerialPortName ;
243    
244      /**          /**
245       * Flag that indicates whether the serial port is currently open.           * Flag that indicates whether the serial port is currently open.
246       */           */
247      bool mIsOpen ;          bool mIsOpen ;
248    
249      /**          /**
250       * The file descriptor corresponding to the serial port.           * The file descriptor corresponding to the serial port.
251       */           */
252      int mFileDescriptor ;          int mFileDescriptor ;
253    
254      /**          /**
255       * Serial port settings are saved into this variable immediately           * Serial port settings are saved into this variable immediately
256       * after the port is opened. These settings are restored when the           * after the port is opened. These settings are restored when the
257       * serial port is closed.           * serial port is closed.
258       */           */
259      termios mOldPortSettings ;          termios mOldPortSettings ;
260    
261      /**          /**
262       * Circular buffer used to store the received data. This is done           * Circular buffer used to store the received data. This is done
263       * asynchronously and helps prevent overflow of the corresponding           * asynchronously and helps prevent overflow of the corresponding
264       * tty's input buffer.           * tty's input buffer.
265       *           *
266       * :TODO: The size of this buffer is allowed to increase indefinitely. If           * :TODO: The size of this buffer is allowed to increase indefinitely. If
267       * data keeps arriving at the serial port and is never read then this           * data keeps arriving at the serial port and is never read then this
268       * buffer will continue occupying more and more memory. We need to put a           * buffer will continue occupying more and more memory. We need to put a
269       * cap on the size of this buffer. It might even be worth providing a           * cap on the size of this buffer. It might even be worth providing a
270       * method to set the size of this buffer.             * method to set the size of this buffer.
271       */           */
272      std::queue<unsigned char> mInputBuffer ;          std::queue<unsigned char> mInputBuffer ;
273    
274      /**          /**
275       * Set the specified modem control line to the specified value.           * Set the specified modem control line to the specified value.
276       *           *
277       * @param modemLine One of the following four values: TIOCM_DTR,           * @param modemLine One of the following four values: TIOCM_DTR,
278       * TIOCM_RTS, TIOCM_CTS, or TIOCM_DSR.           * TIOCM_RTS, TIOCM_CTS, or TIOCM_DSR.
279       *           *
280       * @param lineState State of the modem line after successful           * @param lineState State of the modem line after successful
281       * call to this method.           * call to this method.
282       */           */
283      void          void
284      SetModemControlLine( const int modemLine,          SetModemControlLine( const int modemLine,
285                           const bool lineState )                               const bool lineState )
286          throw( SerialPort::NotOpen,          throw( SerialPort::NotOpen,
287                 std::runtime_error ) ;                 std::runtime_error ) ;
288    
289      /**          /**
290       * Get the current state of the specified modem control line.           * Get the current state of the specified modem control line.
291       *           *
292       * @param modemLine One of the following four values: TIOCM_DTR,           * @param modemLine One of the following four values: TIOCM_DTR,
293       * TIOCM_RTS, TIOCM_CTS, or TIOCM_DSR.           * TIOCM_RTS, TIOCM_CTS, or TIOCM_DSR.
294       *           *
295       * @return True if the specified line is currently set and false           * @return True if the specified line is currently set and false
296       * otherwise.           * otherwise.
297       */           */
298      bool          bool
299      GetModemControlLine( const int modemLine ) const          GetModemControlLine( const int modemLine ) const
300          throw( SerialPort::NotOpen,          throw( SerialPort::NotOpen,
301                 std::runtime_error ) ;                         std::runtime_error ) ;
302  } ;  } ;
303    
304  SerialPort::SerialPort( const std::string& serialPortName ) :  SerialPort::SerialPort( const std::string& serialPortName ) :
305      mSerialPortImpl(new SerialPortImpl(serialPortName) )                  mSerialPortImpl(new SerialPortImpl(serialPortName) )
306  {  {
307      /* empty */          /* empty */
308  }  }
309    
310  SerialPort::~SerialPort()  SerialPort::~SerialPort()
311      throw()  throw()
312  {  {
313      /*          /*
314       * Close the serial port if it is open.           * Close the serial port if it is open.
315       */           */
316      if ( this->IsOpen() )          if ( this->IsOpen() )
317      {          {
318          this->Close() ;                  this->Close() ;
319      }          }
320      /*          /*
321       * Free the memory allocated to the implementation instance.           * Free the memory allocated to the implementation instance.
322       */           */
323      if ( mSerialPortImpl )          if ( mSerialPortImpl )
324      {          {
325          delete mSerialPortImpl ;                  delete mSerialPortImpl ;
326      }          }
327      return ;          return ;
328  }  }
329    
330  void  void
# Line 333  SerialPort::Open( const BaudRate      ba Line 333  SerialPort::Open( const BaudRate      ba
333                    const Parity        parityType,                    const Parity        parityType,
334                    const StopBits      stopBits,                    const StopBits      stopBits,
335                    const FlowControl   flowControl )                    const FlowControl   flowControl )
336      throw( OpenFailed,  throw( OpenFailed,
337             AlreadyOpen,         AlreadyOpen,
338             UnsupportedBaudRate,         UnsupportedBaudRate,
339             std::invalid_argument )         std::invalid_argument )
340  {  {
341      //          //
342      // Open the serial port.          // Open the serial port.
343      mSerialPortImpl->Open() ;          mSerialPortImpl->Open() ;
344      //          //
345      // Set the various parameters of the serial port if it is open.          // Set the various parameters of the serial port if it is open.
346      //          //
347      this->SetBaudRate(baudRate) ;          this->SetBaudRate(baudRate) ;
348      this->SetCharSize(charSize) ;          this->SetCharSize(charSize) ;
349      this->SetParity(parityType) ;          this->SetParity(parityType) ;
350      this->SetNumOfStopBits(stopBits) ;          this->SetNumOfStopBits(stopBits) ;
351      this->SetFlowControl(flowControl) ;          this->SetFlowControl(flowControl) ;
352      //          //
353      // All done.          // All done.
354      //          //
355      return ;          return ;
356  }  }
357    
358  bool  bool
359  SerialPort::IsOpen() const  SerialPort::IsOpen() const
360  {  {
361      return mSerialPortImpl->IsOpen() ;          return mSerialPortImpl->IsOpen() ;
362  }  }
363    
364  void  void
365  SerialPort::Close()  SerialPort::Close()
366      throw(NotOpen)  throw(NotOpen)
367  {  {
368      mSerialPortImpl->Close() ;          mSerialPortImpl->Close() ;
369      return ;          return ;
370  }  }
371    
372  void  void
373  SerialPort::SetBaudRate( const BaudRate baudRate )  SerialPort::SetBaudRate( const BaudRate baudRate )
374      throw( UnsupportedBaudRate,  throw( UnsupportedBaudRate,
375             NotOpen,         NotOpen,
376             std::invalid_argument )         std::invalid_argument )
377  {  {
378      mSerialPortImpl->SetBaudRate( baudRate ) ;          mSerialPortImpl->SetBaudRate( baudRate ) ;
379      return ;          return ;
380  }  }
381    
382  SerialPort::BaudRate  SerialPort::BaudRate
383  SerialPort::GetBaudRate() const  SerialPort::GetBaudRate() const
384      throw( NotOpen,  throw( NotOpen,
385             std::runtime_error )         std::runtime_error )
386  {  {
387      return mSerialPortImpl->GetBaudRate() ;          return mSerialPortImpl->GetBaudRate() ;
388  }  }
389    
390    
391  void  void
392  SerialPort::SetCharSize( const CharacterSize charSize )  SerialPort::SetCharSize( const CharacterSize charSize )
393      throw( NotOpen,  throw( NotOpen,
394             std::invalid_argument )         std::invalid_argument )
395  {  {
396      mSerialPortImpl->SetCharSize(charSize) ;          mSerialPortImpl->SetCharSize(charSize) ;
397  }  }
398    
399  SerialPort::CharacterSize  SerialPort::CharacterSize
400  SerialPort::GetCharSize() const  SerialPort::GetCharSize() const
401      throw(NotOpen)  throw(NotOpen)
402  {  {
403      return mSerialPortImpl->GetCharSize() ;          return mSerialPortImpl->GetCharSize() ;
404  }  }
405    
406  void  void
407  SerialPort::SetParity( const Parity parityType )  SerialPort::SetParity( const Parity parityType )
408      throw( NotOpen,  throw( NotOpen,
409             std::invalid_argument )         std::invalid_argument )
410  {  {
411      mSerialPortImpl->SetParity( parityType ) ;          mSerialPortImpl->SetParity( parityType ) ;
412      return ;          return ;
413  }  }
414    
415  SerialPort::Parity  SerialPort::Parity
416  SerialPort::GetParity() const  SerialPort::GetParity() const
417      throw(NotOpen)  throw(NotOpen)
418  {  {
419      return mSerialPortImpl->GetParity() ;          return mSerialPortImpl->GetParity() ;
420  }  }
421    
422  void  void
423  SerialPort::SetNumOfStopBits( const StopBits numOfStopBits )  SerialPort::SetNumOfStopBits( const StopBits numOfStopBits )
424      throw( NotOpen,  throw( NotOpen,
425             std::invalid_argument )         std::invalid_argument )
426  {  {
427      mSerialPortImpl->SetNumOfStopBits(numOfStopBits) ;          mSerialPortImpl->SetNumOfStopBits(numOfStopBits) ;
428      return ;          return ;
429  }  }
430    
431  SerialPort::StopBits  SerialPort::StopBits
432  SerialPort::GetNumOfStopBits() const  SerialPort::GetNumOfStopBits() const
433      throw(NotOpen)  throw(NotOpen)
434  {  {
435      return mSerialPortImpl->GetNumOfStopBits() ;          return mSerialPortImpl->GetNumOfStopBits() ;
436  }  }
437    
438    
439  void  void
440  SerialPort::SetFlowControl( const FlowControl   flowControl )  SerialPort::SetFlowControl( const FlowControl   flowControl )
441      throw( NotOpen,  throw( NotOpen,
442             std::invalid_argument )         std::invalid_argument )
443  {  {
444      mSerialPortImpl->SetFlowControl( flowControl ) ;          mSerialPortImpl->SetFlowControl( flowControl ) ;
445      return ;          return ;
446  }  }
447    
448  SerialPort::FlowControl  SerialPort::FlowControl
449  SerialPort::GetFlowControl() const  SerialPort::GetFlowControl() const
450      throw( NotOpen )  throw( NotOpen )
451  {  {
452      return mSerialPortImpl->GetFlowControl() ;          return mSerialPortImpl->GetFlowControl() ;
453  }  }
454    
455  bool  bool
456  SerialPort::IsDataAvailable() const  SerialPort::IsDataAvailable() const
457      throw(NotOpen)  throw(NotOpen)
458  {  {
459      return mSerialPortImpl->IsDataAvailable() ;          return mSerialPortImpl->IsDataAvailable() ;
460  }  }
461    
462  unsigned char  unsigned char
463  SerialPort::ReadByte( const unsigned int msTimeout )  SerialPort::ReadByte( const unsigned int msTimeout )
464      throw( NotOpen,  throw( NotOpen,
465             ReadTimeout,         ReadTimeout,
466             std::runtime_error )         std::runtime_error )
467  {  {
468      return mSerialPortImpl->ReadByte(msTimeout) ;          return mSerialPortImpl->ReadByte(msTimeout) ;
469  }  }
470    
471  void  void
472  SerialPort::Read( SerialPort::DataBuffer& dataBuffer,  SerialPort::Read( SerialPort::DataBuffer& dataBuffer,
473                    const unsigned int      numOfBytes,                    const unsigned int      numOfBytes,
474                    const unsigned int      msTimeout )                    const unsigned int      msTimeout )
475      throw( NotOpen,  throw( NotOpen,
476             ReadTimeout,         ReadTimeout,
477             std::runtime_error )         std::runtime_error )
478  {  {
479      return mSerialPortImpl->Read( dataBuffer,          return mSerialPortImpl->Read( dataBuffer,
480                                    numOfBytes,                                        numOfBytes,
481                                    msTimeout ) ;                                        msTimeout ) ;
482  }  }
483    
484    
485  const std::string  const std::string
486  SerialPort::ReadLine( const unsigned int msTimeout,  SerialPort::ReadLine( const unsigned int msTimeout,
487                        const char         lineTerminator )                        const char         lineTerminator )
488      throw( NotOpen,  throw( NotOpen,
489             ReadTimeout,         ReadTimeout,
490             std::runtime_error )         std::runtime_error )
491  {  {
492      return mSerialPortImpl->ReadLine( msTimeout,          return mSerialPortImpl->ReadLine( msTimeout,
493                                        lineTerminator ) ;                                            lineTerminator ) ;
494  }  }
495    
496    
497  void  void
498  SerialPort::WriteByte( const unsigned char dataByte )  SerialPort::WriteByte( const unsigned char dataByte )
499      throw( SerialPort::NotOpen,  throw( SerialPort::NotOpen,
500             std::runtime_error )         std::runtime_error )
501  {  {
502      mSerialPortImpl->WriteByte( dataByte ) ;          mSerialPortImpl->WriteByte( dataByte ) ;
503      return ;          return ;
504  }  }
505    
506    
507  void  void
508  SerialPort::Write(const DataBuffer& dataBuffer)  SerialPort::Write(const DataBuffer& dataBuffer)
509      throw( NotOpen,  throw( NotOpen,
510             std::runtime_error )         std::runtime_error )
511  {  {
512      mSerialPortImpl->Write( dataBuffer ) ;          mSerialPortImpl->Write( dataBuffer ) ;
513      return ;          return ;
514  }  }
515    
516  void  void
517  SerialPort::Write(const std::string& dataString)  SerialPort::Write(const std::string& dataString)
518      throw( NotOpen,  throw( NotOpen,
519             std::runtime_error )         std::runtime_error )
520  {  {
521      mSerialPortImpl->Write( reinterpret_cast<const unsigned char*>(dataString.c_str()),          mSerialPortImpl->Write( reinterpret_cast<const unsigned char*>(dataString.c_str()),
522                              dataString.length() ) ;                                  dataString.length() ) ;
523      return ;          return ;
524  }  }
525    
526  void  void
527  SerialPort::SetDtr( const bool dtrState )  SerialPort::SetDtr( const bool dtrState )
528      throw( SerialPort::NotOpen,  throw( SerialPort::NotOpen,
529             std::runtime_error )         std::runtime_error )
530  {  {
531      mSerialPortImpl->SetDtr( dtrState ) ;          mSerialPortImpl->SetDtr( dtrState ) ;
532      return ;          return ;
533  }  }
534    
535  bool  bool
536  SerialPort::GetDtr() const  SerialPort::GetDtr() const
537      throw( SerialPort::NotOpen,  throw( SerialPort::NotOpen,
538             std::runtime_error )         std::runtime_error )
539  {  {
540      return mSerialPortImpl->GetDtr() ;          return mSerialPortImpl->GetDtr() ;
541  }  }
542    
543  void  void
544  SerialPort::SetRts( const bool rtsState )  SerialPort::SetRts( const bool rtsState )
545      throw( SerialPort::NotOpen,  throw( SerialPort::NotOpen,
546             std::runtime_error )         std::runtime_error )
547  {  {
548      mSerialPortImpl->SetRts( rtsState ) ;          mSerialPortImpl->SetRts( rtsState ) ;
549      return ;          return ;
550  }  }
551    
552  bool  bool
553  SerialPort::GetRts() const  SerialPort::GetRts() const
554      throw( SerialPort::NotOpen,  throw( SerialPort::NotOpen,
555             std::runtime_error )         std::runtime_error )
556  {  {
557      return mSerialPortImpl->GetRts() ;          return mSerialPortImpl->GetRts() ;
558  }  }
559    
560    
561  bool  bool
562  SerialPort::GetCts() const  SerialPort::GetCts() const
563      throw( SerialPort::NotOpen,  throw( SerialPort::NotOpen,
564             std::runtime_error )         std::runtime_error )
565  {  {
566      return mSerialPortImpl->GetCts() ;          return mSerialPortImpl->GetCts() ;
567  }  }
568    
569  bool  bool
570  SerialPort::GetDsr() const  SerialPort::GetDsr() const
571      throw( SerialPort::NotOpen,  throw( SerialPort::NotOpen,
572             std::runtime_error )         std::runtime_error )
573  {  {
574      return mSerialPortImpl->GetDsr() ;          return mSerialPortImpl->GetDsr() ;
575  }  }
576    
577  /* ------------------------------------------------------------ */  /* ------------------------------------------------------------ */
578  inline  inline
579  SerialPort::SerialPortImpl::SerialPortImpl( const std::string& serialPortName ) :  SerialPort::SerialPortImpl::SerialPortImpl( const std::string& serialPortName ) :
580      mSerialPortName(serialPortName),                  mSerialPortName(serialPortName),
581      mIsOpen(false),                  mIsOpen(false),
582      mFileDescriptor(-1),                  mFileDescriptor(-1),
583      mOldPortSettings(),                  mOldPortSettings(),
584      mInputBuffer()                  mInputBuffer()
585  {  {
586      /* empty */          /* empty */
587  }  }
588    
589  inline  inline
590  SerialPort::SerialPortImpl::~SerialPortImpl()  SerialPort::SerialPortImpl::~SerialPortImpl()
591  {  {
592      //          //
593      // Close the serial port if it is open.          // Close the serial port if it is open.
594      //          //
595      if ( this->IsOpen() )          if ( this->IsOpen() )
596      {          {
597          this->Close() ;                  this->Close() ;
598      }          }
599      return ;          return ;
600  }  }
601    
602  inline  inline
603  void  void
604  SerialPort::SerialPortImpl::Open()  SerialPort::SerialPortImpl::Open()
605      throw( SerialPort::OpenFailed,  throw( SerialPort::OpenFailed,
606             SerialPort::AlreadyOpen )         SerialPort::AlreadyOpen )
607  {  {
608      /*          /*
609       * Throw an exception if the port is already open.           * Throw an exception if the port is already open.
610       */           */
611      if ( this->IsOpen() )          if ( this->IsOpen() )
612      {          {
613          throw SerialPort::AlreadyOpen( ERR_MSG_PORT_ALREADY_OPEN ) ;                  throw SerialPort::AlreadyOpen( ERR_MSG_PORT_ALREADY_OPEN ) ;
614      }          }
615      /*          /*
616       * Try to open the serial port and throw an exception if we are           * Try to open the serial port and throw an exception if we are
617       * not able to open it.           * not able to open it.
618       *           *
619       * :FIXME: Exception thrown by this method after opening the           * :FIXME: Exception thrown by this method after opening the
620       * serial port might leave the port open even though mIsOpen           * serial port might leave the port open even though mIsOpen
621       * is false. We need to close the port before throwing an           * is false. We need to close the port before throwing an
622       * exception or close it next time this method is called before           * exception or close it next time this method is called before
623       * calling open() again.           * calling open() again.
624       */           */
625      mFileDescriptor = open( mSerialPortName.c_str(),          mFileDescriptor = open( mSerialPortName.c_str(),
626                              O_RDWR | O_NOCTTY | O_NONBLOCK ) ;                                  O_RDWR | O_NOCTTY | O_NONBLOCK ) ;
627      if ( mFileDescriptor < 0 )          if ( mFileDescriptor < 0 )
628      {          {
629          throw SerialPort::OpenFailed( strerror(errno) )  ;                  throw SerialPort::OpenFailed( strerror(errno) )  ;
630      }          }
631    
632    
633      PosixSignalDispatcher& signal_dispatcher = PosixSignalDispatcher::Instance() ;          PosixSignalDispatcher& signal_dispatcher = PosixSignalDispatcher::Instance() ;
634      signal_dispatcher.AttachHandler( SIGIO,          signal_dispatcher.AttachHandler( SIGIO,
635                                       *this ) ;                                           *this ) ;
636    
637      /*          /*
638       * Direct all SIGIO and SIGURG signals for the port to the current           * Direct all SIGIO and SIGURG signals for the port to the current
639       * process.           * process.
640       */           */
641      if ( fcntl( mFileDescriptor,          if ( fcntl( mFileDescriptor,
642                  F_SETOWN,                      F_SETOWN,
643                  getpid() ) < 0 )                      getpid() ) < 0 )
644      {          {
645          throw SerialPort::OpenFailed( strerror(errno) ) ;                  throw SerialPort::OpenFailed( strerror(errno) ) ;
646      }          }
647    
648      /*          /*
649       * Enable asynchronous I/O with the serial port.           * Enable asynchronous I/O with the serial port.
650       */           */
651      if ( fcntl( mFileDescriptor,          if ( fcntl( mFileDescriptor,
652                  F_SETFL,                      F_SETFL,
653                  FASYNC ) < 0 )                      FASYNC ) < 0 )
654      {          {
655          throw SerialPort::OpenFailed( strerror(errno) ) ;                  throw SerialPort::OpenFailed( strerror(errno) ) ;
656      }          }
657    
658      /*          /*
659       * Save the current settings of the serial port so they can be           * Save the current settings of the serial port so they can be
660       * restored when the serial port is closed.           * restored when the serial port is closed.
661       */           */
662      if ( tcgetattr( mFileDescriptor,          if ( tcgetattr( mFileDescriptor,
663                      &mOldPortSettings ) < 0 )                          &mOldPortSettings ) < 0 )
664      {          {
665          throw SerialPort::OpenFailed( strerror(errno) ) ;                  throw SerialPort::OpenFailed( strerror(errno) ) ;
666      }          }
667    
668      //          //
669      // Start assembling the new port settings.          // Start assembling the new port settings.
670      //          //
671      termios port_settings ;          termios port_settings ;
672      bzero( &port_settings,          bzero( &port_settings,
673             sizeof( port_settings ) ) ;                 sizeof( port_settings ) ) ;
674    
675      //          //
676      // Enable the receiver (CREAD) and ignore modem control lines          // Enable the receiver (CREAD) and ignore modem control lines
677      // (CLOCAL).          // (CLOCAL).
678      //          //
679      port_settings.c_cflag |= CREAD | CLOCAL ;          port_settings.c_cflag |= CREAD | CLOCAL ;
680    
681      //          //
682      // Set the VMIN and VTIME parameters to zero by default. VMIN is          // Set the VMIN and VTIME parameters to zero by default. VMIN is
683      // the minimum number of characters for non-canonical read and          // the minimum number of characters for non-canonical read and
684      // VTIME is the timeout in deciseconds for non-canonical          // VTIME is the timeout in deciseconds for non-canonical
685      // read. Setting both of these parameters to zero implies that a          // read. Setting both of these parameters to zero implies that a
686      // read will return immediately only giving the currently          // read will return immediately only giving the currently
687      // available characters.          // available characters.
688      //          //
689      port_settings.c_cc[ VMIN  ] = 0 ;          port_settings.c_cc[ VMIN  ] = 0 ;
690      port_settings.c_cc[ VTIME ] = 0 ;          port_settings.c_cc[ VTIME ] = 0 ;
691      /*          /*
692       * Flush the input buffer associated with the port.           * Flush the input buffer associated with the port.
693       */           */
694      if ( tcflush( mFileDescriptor,          if ( tcflush( mFileDescriptor,
695                    TCIFLUSH ) < 0 )                        TCIFLUSH ) < 0 )
696      {          {
697          throw SerialPort::OpenFailed( strerror(errno) ) ;                  throw SerialPort::OpenFailed( strerror(errno) ) ;
698      }          }
699      /*          /*
700       * Write the new settings to the port.           * Write the new settings to the port.
701       */           */
702      if ( tcsetattr( mFileDescriptor,          if ( tcsetattr( mFileDescriptor,
703                      TCSANOW,                          TCSANOW,
704                      &port_settings ) < 0 )                          &port_settings ) < 0 )
705      {          {
706          throw SerialPort::OpenFailed( strerror(errno) ) ;                  throw SerialPort::OpenFailed( strerror(errno) ) ;
707      }          }
708    
709      /*          /*
710       * The serial port is open at this point.           * The serial port is open at this point.
711       */           */
712      mIsOpen = true ;          mIsOpen = true ;
713      return ;          return ;
714  }  }
715    
716  inline  inline
717  bool  bool
718  SerialPort::SerialPortImpl::IsOpen() const  SerialPort::SerialPortImpl::IsOpen() const
719  {  {
720      return mIsOpen ;          return mIsOpen ;
721  }  }
722    
723  inline  inline
724  void  void
725  SerialPort::SerialPortImpl::Close()  SerialPort::SerialPortImpl::Close()
726      throw( SerialPort::NotOpen )  throw( SerialPort::NotOpen )
727  {  {
728      //          //
729      // Throw an exception if the serial port is not open.          // Throw an exception if the serial port is not open.
730      //          //
731      if ( ! this->IsOpen() )          if ( ! this->IsOpen() )
732      {          {
733          throw SerialPort::NotOpen( ERR_MSG_PORT_NOT_OPEN ) ;                  throw SerialPort::NotOpen( ERR_MSG_PORT_NOT_OPEN ) ;
734      }          }
735      //          //
736      PosixSignalDispatcher& signal_dispatcher = PosixSignalDispatcher::Instance() ;          PosixSignalDispatcher& signal_dispatcher = PosixSignalDispatcher::Instance() ;
737      signal_dispatcher.DetachHandler( SIGIO,          signal_dispatcher.DetachHandler( SIGIO,
738                                       *this ) ;                                           *this ) ;
739      //          //
740      // Restore the old settings of the port.          // Restore the old settings of the port.
741      //          //
742      tcsetattr( mFileDescriptor,          tcsetattr( mFileDescriptor,
743                 TCSANOW,                     TCSANOW,
744                 &mOldPortSettings ) ;                     &mOldPortSettings ) ;
745      //          //
746      // Close the serial port file descriptor.          // Close the serial port file descriptor.
747      //          //
748      close(mFileDescriptor) ;          close(mFileDescriptor) ;
749      //          //
750      // The port is not open anymore.          // The port is not open anymore.
751      //          //
752      mIsOpen = false ;          mIsOpen = false ;
753      //          //
754      return ;          return ;
755  }  }
756    
757  inline  inline
758  void  void
759  SerialPort::SerialPortImpl::SetBaudRate( const SerialPort::BaudRate baudRate )  SerialPort::SerialPortImpl::SetBaudRate( const SerialPort::BaudRate baudRate )
760      throw( SerialPort::NotOpen,  throw( SerialPort::NotOpen,
761             SerialPort::UnsupportedBaudRate,         SerialPort::UnsupportedBaudRate,
762             std::invalid_argument,         std::invalid_argument,
763             std::runtime_error )         std::runtime_error )
764  {  {
765      //          //
766      // Throw an exception if the serial port is not open.          // Throw an exception if the serial port is not open.
767      //          //
768      if ( ! this->IsOpen() )          if ( ! this->IsOpen() )
769      {          {
770          throw SerialPort::NotOpen( ERR_MSG_PORT_NOT_OPEN ) ;                  throw SerialPort::NotOpen( ERR_MSG_PORT_NOT_OPEN ) ;
771      }          }
772      //          //
773      // Get the current settings of the serial port.          // Get the current settings of the serial port.
774      //          //
775      termios port_settings ;          termios port_settings ;
776      if ( tcgetattr( mFileDescriptor,          if ( tcgetattr( mFileDescriptor,
777                      &port_settings ) < 0 )                          &port_settings ) < 0 )
778      {          {
779          throw std::runtime_error( strerror(errno) ) ;                  throw std::runtime_error( strerror(errno) ) ;
780      }          }
781      //          //
782      // Set the baud rate for both input and output.          // Set the baud rate for both input and output.
783      //          //
784      if ( ( cfsetispeed( &port_settings,          if ( ( cfsetispeed( &port_settings,
785                          baudRate ) < 0 ) ||                              baudRate ) < 0 ) ||
786           ( cfsetospeed( &port_settings,                  ( cfsetospeed( &port_settings,
787                          baudRate ) < 0 ) )                                 baudRate ) < 0 ) )
788      {          {
789          //                  //
790          // If any of the settings fail, we abandon this method.                  // If any of the settings fail, we abandon this method.
791          //                  //
792          throw SerialPort::UnsupportedBaudRate( ERR_MSG_UNSUPPORTED_BAUD ) ;                  throw SerialPort::UnsupportedBaudRate( ERR_MSG_UNSUPPORTED_BAUD ) ;
793      }          }
794      //          //
795      // Set the new attributes of the serial port.          // Set the new attributes of the serial port.
796      //          //
797      if ( tcsetattr( mFileDescriptor,          if ( tcsetattr( mFileDescriptor,
798                      TCSANOW,                          TCSANOW,
799                      &port_settings ) < 0 )                          &port_settings ) < 0 )
800      {          {
801          throw SerialPort::UnsupportedBaudRate( strerror(errno) ) ;                  throw SerialPort::UnsupportedBaudRate( strerror(errno) ) ;
802      }          }
803      return ;          return ;
804  }  }
805    
806  inline  inline
807  SerialPort::BaudRate  SerialPort::BaudRate
808  SerialPort::SerialPortImpl::GetBaudRate() const  SerialPort::SerialPortImpl::GetBaudRate() const
809      throw( SerialPort::NotOpen,  throw( SerialPort::NotOpen,
810             std::runtime_error )         std::runtime_error )
811  {  {
812      //          //
813      // Make sure that the serial port is open.          // Make sure that the serial port is open.
814      //          //
815      if ( ! this->IsOpen() )          if ( ! this->IsOpen() )
816      {          {
817          throw SerialPort::NotOpen( ERR_MSG_PORT_NOT_OPEN ) ;                  throw SerialPort::NotOpen( ERR_MSG_PORT_NOT_OPEN ) ;
818      }          }
819      //          //
820      // Read the current serial port settings.          // Read the current serial port settings.
821      //          //
822      termios port_settings ;          termios port_settings ;
823      if ( tcgetattr( mFileDescriptor,          if ( tcgetattr( mFileDescriptor,
824                      &port_settings ) < 0 )                          &port_settings ) < 0 )
825      {          {
826          throw std::runtime_error( strerror(errno) ) ;                  throw std::runtime_error( strerror(errno) ) ;
827      }          }
828      //          //
829      // Obtain the input baud rate from the current settings.          // Obtain the input baud rate from the current settings.
830      //          //
831      return SerialPort::BaudRate(cfgetispeed( &port_settings )) ;          return SerialPort::BaudRate(cfgetispeed( &port_settings )) ;
832  }  }
833    
834  inline  inline
835  void  void
836  SerialPort::SerialPortImpl::SetCharSize( const SerialPort::CharacterSize charSize )  SerialPort::SerialPortImpl::SetCharSize( const SerialPort::CharacterSize charSize )
837      throw( SerialPort::NotOpen,  throw( SerialPort::NotOpen,
838             std::invalid_argument,         std::invalid_argument,
839             std::runtime_error )         std::runtime_error )
840  {  {
841      //          //
842      // Make sure that the serial port is open.          // Make sure that the serial port is open.
843      //          //
844      if ( ! this->IsOpen() )          if ( ! this->IsOpen() )
845      {          {
846          throw SerialPort::NotOpen( ERR_MSG_PORT_NOT_OPEN ) ;                  throw SerialPort::NotOpen( ERR_MSG_PORT_NOT_OPEN ) ;
847      }          }
848      //          //
849      // Get the current settings of the serial port.          // Get the current settings of the serial port.
850      //          //
851      termios port_settings ;          termios port_settings ;
852      if ( tcgetattr( mFileDescriptor,          if ( tcgetattr( mFileDescriptor,
853                      &port_settings ) < 0 )                          &port_settings ) < 0 )
854      {          {
855          throw std::runtime_error( strerror(errno) ) ;                  throw std::runtime_error( strerror(errno) ) ;
856      }          }
857      //          //
858      // Set the character size.          // Set the character size.
859      //          //
860      port_settings.c_cflag &= ~CSIZE ;          port_settings.c_cflag &= ~CSIZE ;
861      port_settings.c_cflag |= charSize ;          port_settings.c_cflag |= charSize ;
862      //          //
863      // Apply the modified settings.          // Apply the modified settings.
864      //          //
865      if ( tcsetattr( mFileDescriptor,          if ( tcsetattr( mFileDescriptor,
866                      TCSANOW,                          TCSANOW,
867                      &port_settings ) < 0 )                          &port_settings ) < 0 )
868      {          {
869          throw std::invalid_argument( strerror(errno) ) ;                  throw std::invalid_argument( strerror(errno) ) ;
870      }          }
871      return ;          return ;
872  }  }
873    
874  inline  inline
875  SerialPort::CharacterSize  SerialPort::CharacterSize
876  SerialPort::SerialPortImpl::GetCharSize() const  SerialPort::SerialPortImpl::GetCharSize() const
877      throw( SerialPort::NotOpen,  throw( SerialPort::NotOpen,
878             std::runtime_error )         std::runtime_error )
879  {  {
880      //          //
881      // Make sure that the serial port is open.          // Make sure that the serial port is open.
882      //          //
883      if ( ! this->IsOpen() )          if ( ! this->IsOpen() )
884      {          {
885          throw SerialPort::NotOpen( ERR_MSG_PORT_NOT_OPEN ) ;                  throw SerialPort::NotOpen( ERR_MSG_PORT_NOT_OPEN ) ;
886      }          }
887      //          //
888      // Get the current port settings.          // Get the current port settings.
889      //          //
890      termios port_settings ;          termios port_settings ;
891      if ( tcgetattr( mFileDescriptor,          if ( tcgetattr( mFileDescriptor,
892                      &port_settings ) < 0 )                          &port_settings ) < 0 )
893      {          {
894          throw std::runtime_error( strerror(errno) ) ;                  throw std::runtime_error( strerror(errno) ) ;
895      }          }
896      //          //
897      // Read the character size from the setttings.          // Read the character size from the setttings.
898      //          //
899      return SerialPort::CharacterSize( port_settings.c_cflag & CSIZE ) ;          return SerialPort::CharacterSize( port_settings.c_cflag & CSIZE ) ;
900  }  }
901    
902  inline  inline
903  void  void
904  SerialPort::SerialPortImpl::SetParity( const SerialPort::Parity parityType )  SerialPort::SerialPortImpl::SetParity( const SerialPort::Parity parityType )
905      throw( SerialPort::NotOpen,  throw( SerialPort::NotOpen,
906             std::invalid_argument,         std::invalid_argument,
907             std::runtime_error )         std::runtime_error )
908  {  {
909      //          //
910      // Make sure that the serial port is open.          // Make sure that the serial port is open.
911      //          //
912      if ( ! this->IsOpen() )          if ( ! this->IsOpen() )
913      {          {
914          throw SerialPort::NotOpen( ERR_MSG_PORT_NOT_OPEN ) ;                  throw SerialPort::NotOpen( ERR_MSG_PORT_NOT_OPEN ) ;
915      }          }
916      //          //
917      // Get the current port settings.          // Get the current port settings.
918      //          //
919      termios port_settings ;          termios port_settings ;
920      if ( tcgetattr( mFileDescriptor,          if ( tcgetattr( mFileDescriptor,
921                      &port_settings ) < 0 )                          &port_settings ) < 0 )
922      {          {
923          throw std::runtime_error( strerror(errno) ) ;                  throw std::runtime_error( strerror(errno) ) ;
924      }          }
925      //          //
926      // Set the parity type depending on the specified parameter.          // Set the parity type depending on the specified parameter.
927      //          //
928      switch( parityType )          switch ( parityType )
929      {          {
930      case SerialPort::PARITY_EVEN:          case SerialPort::PARITY_EVEN:
931          port_settings.c_cflag |= PARENB ;                  port_settings.c_cflag |= PARENB ;
932          port_settings.c_cflag &= ~PARODD ;                  port_settings.c_cflag &= ~PARODD ;
933          port_settings.c_iflag |= INPCK ;                  port_settings.c_iflag |= INPCK ;
934          break ;                  break ;
935      case SerialPort::PARITY_ODD:          case SerialPort::PARITY_ODD:
936          port_settings.c_cflag |= ( PARENB | PARODD ) ;                  port_settings.c_cflag |= ( PARENB | PARODD ) ;
937          port_settings.c_iflag |= INPCK ;                  port_settings.c_iflag |= INPCK ;
938          break ;                  break ;
939      case SerialPort::PARITY_NONE:          case SerialPort::PARITY_NONE:
940          port_settings.c_cflag &= ~(PARENB) ;                  port_settings.c_cflag &= ~(PARENB) ;
941          port_settings.c_iflag |= IGNPAR ;                  port_settings.c_iflag |= IGNPAR ;
942          break ;                  break ;
943      default:          default:
944          throw std::invalid_argument( ERR_MSG_INVALID_PARITY ) ;                  throw std::invalid_argument( ERR_MSG_INVALID_PARITY ) ;
945          break ;                  break ;
946      }          }
947      //          //
948      // Apply the modified port settings.          // Apply the modified port settings.
949      //          //
950      if ( tcsetattr( mFileDescriptor,          if ( tcsetattr( mFileDescriptor,
951                      TCSANOW,                          TCSANOW,
952                      &port_settings ) < 0 )                          &port_settings ) < 0 )
953      {          {
954          throw std::invalid_argument( strerror(errno) ) ;                  throw std::invalid_argument( strerror(errno) ) ;
955      }          }
956      return ;          return ;
957  }  }
958    
959  inline  inline
960  SerialPort::Parity  SerialPort::Parity
961  SerialPort::SerialPortImpl::GetParity() const  SerialPort::SerialPortImpl::GetParity() const
962      throw(SerialPort::NotOpen)  throw(SerialPort::NotOpen)
963  {  {
964      //          //
965      // Make sure that the serial port is open.          // Make sure that the serial port is open.
966      //          //
967      if ( ! this->IsOpen() )          if ( ! this->IsOpen() )
968      {          {
969          throw SerialPort::NotOpen( ERR_MSG_PORT_NOT_OPEN ) ;                  throw SerialPort::NotOpen( ERR_MSG_PORT_NOT_OPEN ) ;
970      }          }
971      //          //
972      // Get the current port settings.          // Get the current port settings.
973      //          //
974      termios port_settings ;          termios port_settings ;
975      if ( tcgetattr( mFileDescriptor,          if ( tcgetattr( mFileDescriptor,
976                      &port_settings ) < 0 )                          &port_settings ) < 0 )
977      {          {
978          throw std::runtime_error( strerror(errno) ) ;                  throw std::runtime_error( strerror(errno) ) ;
979      }          }
980      //          //
981      // Get the parity type from the current settings.          // Get the parity type from the current settings.
982      //          //
983      if ( port_settings.c_cflag & PARENB )          if ( port_settings.c_cflag & PARENB )
984      {          {
985          //                  //
986          // Parity is enabled. Lets check if it is odd or even.                  // Parity is enabled. Lets check if it is odd or even.
987          //                  //
988          if ( port_settings.c_cflag & PARODD )                  if ( port_settings.c_cflag & PARODD )
989          {                  {
990              return SerialPort::PARITY_ODD ;                          return SerialPort::PARITY_ODD ;
991          }                  }
992          else                  else
993          {                  {
994              return SerialPort::PARITY_EVEN ;                          return SerialPort::PARITY_EVEN ;
995          }                  }
996      }          }
997      //          //
998      // Parity is disabled.          // Parity is disabled.
999      //          //
1000      return SerialPort::PARITY_NONE ;          return SerialPort::PARITY_NONE ;
1001  }  }
1002    
1003  inline  inline
1004  void  void
1005  SerialPort::SerialPortImpl::SetNumOfStopBits( const SerialPort::StopBits numOfStopBits )  SerialPort::SerialPortImpl::SetNumOfStopBits( const SerialPort::StopBits numOfStopBits )
1006      throw( SerialPort::NotOpen,  throw( SerialPort::NotOpen,
1007             std::invalid_argument )         std::invalid_argument )
1008  {  {
1009      //          //
1010      // Make sure that the serial port is open.          // Make sure that the serial port is open.
1011      //          //
1012      if ( ! this->IsOpen() )          if ( ! this->IsOpen() )
1013      {          {
1014          throw SerialPort::NotOpen( ERR_MSG_PORT_NOT_OPEN ) ;                  throw SerialPort::NotOpen( ERR_MSG_PORT_NOT_OPEN ) ;
1015      }          }
1016      //          //
1017      // Get the current port settings.          // Get the current port settings.
1018      //          //
1019      termios port_settings ;          termios port_settings ;
1020      if ( tcgetattr( mFileDescriptor,          if ( tcgetattr( mFileDescriptor,
1021                      &port_settings ) < 0 )                          &port_settings ) < 0 )
1022      {          {
1023          throw std::runtime_error( strerror(errno) ) ;                  throw std::runtime_error( strerror(errno) ) ;
1024      }          }
1025      //          //
1026      // Set the number of stop bits.          // Set the number of stop bits.
1027      //          //
1028      switch( numOfStopBits )          switch ( numOfStopBits )
1029      {          {
1030      case SerialPort::STOP_BITS_1:          case SerialPort::STOP_BITS_1:
1031          port_settings.c_cflag &= ~(CSTOPB) ;                  port_settings.c_cflag &= ~(CSTOPB) ;
1032          break ;                  break ;
1033      case SerialPort::STOP_BITS_2:          case SerialPort::STOP_BITS_2:
1034          port_settings.c_cflag |= CSTOPB ;                  port_settings.c_cflag |= CSTOPB ;
1035          break ;                  break ;
1036      default:          default:
1037          throw std::invalid_argument( ERR_MSG_INVALID_STOP_BITS ) ;                  throw std::invalid_argument( ERR_MSG_INVALID_STOP_BITS ) ;
1038          break ;                  break ;
1039      }          }
1040      //          //
1041      // Apply the modified settings.          // Apply the modified settings.
1042      //          //
1043      if ( tcsetattr( mFileDescriptor,          if ( tcsetattr( mFileDescriptor,
1044                      TCSANOW,                          TCSANOW,
1045                      &port_settings ) < 0 )                          &port_settings ) < 0 )
1046      {          {
1047          throw std::invalid_argument( strerror(errno) ) ;                  throw std::invalid_argument( strerror(errno) ) ;
1048      }          }
1049      return ;          return ;
1050  }  }
1051    
1052  inline  inline
1053  SerialPort::StopBits  SerialPort::StopBits
1054  SerialPort::SerialPortImpl::GetNumOfStopBits() const  SerialPort::SerialPortImpl::GetNumOfStopBits() const
1055      throw(SerialPort::NotOpen)  throw(SerialPort::NotOpen)
1056  {  {
1057      //          //
1058      // Make sure that the serial port is open.          // Make sure that the serial port is open.
1059      //          //
1060      if ( ! this->IsOpen() )          if ( ! this->IsOpen() )
1061      {          {
1062          throw SerialPort::NotOpen( ERR_MSG_PORT_NOT_OPEN ) ;                  throw SerialPort::NotOpen( ERR_MSG_PORT_NOT_OPEN ) ;
1063      }          }
1064      //          //
1065      // Get the current port settings.          // Get the current port settings.
1066      //          //
1067      termios port_settings ;          termios port_settings ;
1068      if ( tcgetattr( mFileDescriptor,          if ( tcgetattr( mFileDescriptor,
1069                      &port_settings ) < 0 )                          &port_settings ) < 0 )
1070      {          {
1071          throw std::runtime_error( strerror(errno) ) ;                  throw std::runtime_error( strerror(errno) ) ;
1072      }          }
1073      //          //
1074      // If CSTOPB is set then we are using two stop bits, otherwise we          // If CSTOPB is set then we are using two stop bits, otherwise we
1075      // are using 1 stop bit.          // are using 1 stop bit.
1076      //          //
1077      if ( port_settings.c_cflag & CSTOPB )          if ( port_settings.c_cflag & CSTOPB )
1078      {          {
1079          return SerialPort::STOP_BITS_2 ;                  return SerialPort::STOP_BITS_2 ;
1080      }          }
1081      return SerialPort::STOP_BITS_1 ;          return SerialPort::STOP_BITS_1 ;
1082  }  }
1083    
1084  inline  inline
1085  void  void
1086  SerialPort::SerialPortImpl::SetFlowControl( const SerialPort::FlowControl   flowControl )  SerialPort::SerialPortImpl::SetFlowControl( const SerialPort::FlowControl   flowControl )
1087      throw( SerialPort::NotOpen,  throw( SerialPort::NotOpen,
1088             std::invalid_argument )         std::invalid_argument )
1089  {  {
1090      //          //
1091      // Make sure that the serial port is open.          // Make sure that the serial port is open.
1092      //          //
1093      if ( ! this->IsOpen() )          if ( ! this->IsOpen() )
1094      {          {
1095          throw SerialPort::NotOpen( ERR_MSG_PORT_NOT_OPEN ) ;                  throw SerialPort::NotOpen( ERR_MSG_PORT_NOT_OPEN ) ;
1096      }          }
1097      //          //
1098      // Get the current port settings.          // Get the current port settings.
1099      //          //
1100      termios port_settings ;          termios port_settings ;
1101      if ( tcgetattr( mFileDescriptor,          if ( tcgetattr( mFileDescriptor,
1102                      &port_settings ) < 0 )                          &port_settings ) < 0 )
1103      {          {
1104          throw std::runtime_error( strerror(errno) ) ;                  throw std::runtime_error( strerror(errno) ) ;
1105      }          }
1106      //          //
1107      // Set the flow control.          // Set the flow control.
1108      //          //
1109      switch( flowControl )          switch ( flowControl )
1110      {          {
1111      case SerialPort::FLOW_CONTROL_HARD:          case SerialPort::FLOW_CONTROL_HARD:
1112          port_settings.c_cflag |= CRTSCTS ;                  port_settings.c_cflag |= CRTSCTS ;
1113          break ;                  break ;
1114      case SerialPort::FLOW_CONTROL_NONE:          case SerialPort::FLOW_CONTROL_NONE:
1115          port_settings.c_cflag &= ~(CRTSCTS) ;                  port_settings.c_cflag &= ~(CRTSCTS) ;
1116          break ;                  break ;
1117      default:          default:
1118          throw std::invalid_argument( ERR_MSG_INVALID_FLOW_CONTROL ) ;                  throw std::invalid_argument( ERR_MSG_INVALID_FLOW_CONTROL ) ;
1119          break ;                  break ;
1120      }          }
1121      //          //
1122      // Apply the modified settings.          // Apply the modified settings.
1123      //          //
1124      if ( tcsetattr( mFileDescriptor,          if ( tcsetattr( mFileDescriptor,
1125                      TCSANOW,                          TCSANOW,
1126                      &port_settings ) < 0 )                          &port_settings ) < 0 )
1127      {          {
1128          throw std::invalid_argument( strerror(errno) ) ;                  throw std::invalid_argument( strerror(errno) ) ;
1129      }          }
1130      return ;          return ;
1131  }  }
1132    
1133  inline  inline
1134  SerialPort::FlowControl  SerialPort::FlowControl
1135  SerialPort::SerialPortImpl::GetFlowControl() const  SerialPort::SerialPortImpl::GetFlowControl() const
1136      throw( SerialPort::NotOpen )  throw( SerialPort::NotOpen )
1137  {  {
1138      //          //
1139      // Make sure that the serial port is open.          // Make sure that the serial port is open.
1140      //          //
1141      if ( ! this->IsOpen() )          if ( ! this->IsOpen() )
1142      {          {
1143          throw SerialPort::NotOpen( ERR_MSG_PORT_NOT_OPEN ) ;                  throw SerialPort::NotOpen( ERR_MSG_PORT_NOT_OPEN ) ;
1144      }          }
1145      //          //
1146      // Get the current port settings.          // Get the current port settings.
1147      //          //
1148      termios port_settings ;          termios port_settings ;
1149      if ( tcgetattr( mFileDescriptor,          if ( tcgetattr( mFileDescriptor,
1150                      &port_settings ) < 0 )                          &port_settings ) < 0 )
1151      {          {
1152          throw std::runtime_error( strerror(errno) ) ;                  throw std::runtime_error( strerror(errno) ) ;
1153      }          }
1154      //          //
1155      // If CRTSCTS is set then we are using hardware flow          // If CRTSCTS is set then we are using hardware flow
1156      // control. Otherwise, we are not using any flow control.          // control. Otherwise, we are not using any flow control.
1157      //          //
1158      if ( port_settings.c_cflag & CRTSCTS )          if ( port_settings.c_cflag & CRTSCTS )
1159      {          {
1160          return SerialPort::FLOW_CONTROL_HARD ;                  return SerialPort::FLOW_CONTROL_HARD ;
1161      }          }
1162      return SerialPort::FLOW_CONTROL_NONE ;          return SerialPort::FLOW_CONTROL_NONE ;
1163  }  }
1164    
1165  inline  inline
1166  bool  bool
1167  SerialPort::SerialPortImpl::IsDataAvailable() const  SerialPort::SerialPortImpl::IsDataAvailable() const
1168      throw( SerialPort::NotOpen,  throw( SerialPort::NotOpen,
1169             std::runtime_error )         std::runtime_error )
1170  {  {
1171      //          //
1172      // Make sure that the serial port is open.          // Make sure that the serial port is open.
1173      //          //
1174      if ( ! this->IsOpen() )          if ( ! this->IsOpen() )
1175      {          {
1176          throw SerialPort::NotOpen( ERR_MSG_PORT_NOT_OPEN ) ;                  throw SerialPort::NotOpen( ERR_MSG_PORT_NOT_OPEN ) ;
1177      }          }
1178      //          //
1179      // Check if any data is available in the input buffer.          // Check if any data is available in the input buffer.
1180      //          //
1181      return ( mInputBuffer.size() > 0 ? true : false ) ;          return ( mInputBuffer.size() > 0 ? true : false ) ;
1182  }  }
1183    
1184  inline  inline
1185  unsigned char  unsigned char
1186  SerialPort::SerialPortImpl::ReadByte(const unsigned int msTimeout)  SerialPort::SerialPortImpl::ReadByte(const unsigned int msTimeout)
1187      throw( SerialPort::NotOpen,  throw( SerialPort::NotOpen,
1188             SerialPort::ReadTimeout,         SerialPort::ReadTimeout,
1189             std::runtime_error )         std::runtime_error )
1190  {  {
1191      //          //
1192      // Make sure that the serial port is open.          // Make sure that the serial port is open.
1193      //          //
1194      if ( ! this->IsOpen() )          if ( ! this->IsOpen() )
1195      {          {
1196          throw SerialPort::NotOpen( ERR_MSG_PORT_NOT_OPEN ) ;                  throw SerialPort::NotOpen( ERR_MSG_PORT_NOT_OPEN ) ;
1197      }          }
1198      //          //
1199      // Get the current time. Throw an exception if we are unable          // Get the current time. Throw an exception if we are unable
1200      // to read the current time.          // to read the current time.
1201      //          //
1202      struct timeval entry_time ;          struct timeval entry_time ;
1203      if ( gettimeofday( &entry_time,          if ( gettimeofday( &entry_time,
1204                         NULL ) < 0 )                             NULL ) < 0 )
1205      {          {
1206          throw std::runtime_error( strerror(errno) ) ;                  throw std::runtime_error( strerror(errno) ) ;
1207      }          }
1208      //          //
1209      // Wait for data to be available.          // Wait for data to be available.
1210      //          //
1211      const int MICROSECONDS_PER_MS  = 1000 ;          const int MICROSECONDS_PER_MS  = 1000 ;
1212      const int MILLISECONDS_PER_SEC = 1000 ;          const int MILLISECONDS_PER_SEC = 1000 ;
1213      //          //
1214      while( 0 == mInputBuffer.size() )          while ( 0 == mInputBuffer.size() )
1215      {          {
1216          //                  //
1217          // Read the current time.                  // Read the current time.
1218          //                  //
1219          struct timeval curr_time ;                  struct timeval curr_time ;
1220          if ( gettimeofday( &curr_time,                  if ( gettimeofday( &curr_time,
1221                             NULL ) < 0 )                                     NULL ) < 0 )
1222          {                  {
1223              throw std::runtime_error( strerror(errno) ) ;                          throw std::runtime_error( strerror(errno) ) ;
1224          }                  }
1225          //                  //
1226          // Obtain the elapsed time.                  // Obtain the elapsed time.
1227          //                  //
1228          struct timeval elapsed_time = curr_time - entry_time ;                  struct timeval elapsed_time = curr_time - entry_time ;
1229          //                  //
1230          // Increase the elapsed number of milliseconds.                  // Increase the elapsed number of milliseconds.
1231          //                  //
1232          unsigned int elapsed_ms = ( elapsed_time.tv_sec  * MILLISECONDS_PER_SEC +                  unsigned int elapsed_ms = ( elapsed_time.tv_sec  * MILLISECONDS_PER_SEC +
1233                             elapsed_time.tv_usec / MICROSECONDS_PER_MS ) ;                                              elapsed_time.tv_usec / MICROSECONDS_PER_MS ) ;
1234          //                  //
1235          // If more than msTimeout milliseconds have elapsed while                  // If more than msTimeout milliseconds have elapsed while
1236          // waiting for data, then we throw a ReadTimeout exception.                  // waiting for data, then we throw a ReadTimeout exception.
1237          //                  //
1238          if ( ( msTimeout > 0 ) &&                  if ( ( msTimeout > 0 ) &&
1239               ( elapsed_ms > msTimeout ) )                          ( elapsed_ms > msTimeout ) )
1240          {                  {
1241              throw SerialPort::ReadTimeout() ;                          throw SerialPort::ReadTimeout() ;
1242          }                  }
1243          //                  //
1244          // Wait for 1ms (1000us) for data to arrive.                  // Wait for 1ms (1000us) for data to arrive.
1245          //                  //
1246          usleep( MICROSECONDS_PER_MS ) ;                  usleep( MICROSECONDS_PER_MS ) ;
1247      }          }
1248      //          //
1249      // Return the first byte and remove it from the queue.          // Return the first byte and remove it from the queue.
1250      //          //
1251      unsigned char next_char = mInputBuffer.front() ;          unsigned char next_char = mInputBuffer.front() ;
1252      mInputBuffer.pop() ;          mInputBuffer.pop() ;
1253      return next_char ;          return next_char ;
1254  }  }
1255    
1256  inline  inline
# Line 1258  void Line 1258  void
1258  SerialPort::SerialPortImpl::Read( SerialPort::DataBuffer& dataBuffer,  SerialPort::SerialPortImpl::Read( SerialPort::DataBuffer& dataBuffer,
1259                                    const unsigned int      numOfBytes,                                    const unsigned int      numOfBytes,
1260                                    const unsigned int      msTimeout )                                    const unsigned int      msTimeout )
1261      throw( SerialPort::NotOpen,  throw( SerialPort::NotOpen,
1262             SerialPort::ReadTimeout,         SerialPort::ReadTimeout,
1263             std::runtime_error )         std::runtime_error )
1264  {  {
1265      //          //
1266      // Make sure that the serial port is open.          // Make sure that the serial port is open.
1267      //          //
1268      if ( ! this->IsOpen() )          if ( ! this->IsOpen() )
1269      {          {
1270          throw SerialPort::NotOpen( ERR_MSG_PORT_NOT_OPEN ) ;                  throw SerialPort::NotOpen( ERR_MSG_PORT_NOT_OPEN ) ;
1271      }          }
1272      //          //
1273      // Empty the data buffer.          // Empty the data buffer.
1274      //          //
1275      dataBuffer.resize(0) ;          dataBuffer.resize(0) ;
1276      //          //
1277      if ( 0 == numOfBytes )          if ( 0 == numOfBytes )
1278      {          {
1279          //                  //
1280          // Read all available data if numOfBytes is zero.                  // Read all available data if numOfBytes is zero.
1281          //                  //
1282          while( this->IsDataAvailable() )                  while ( this->IsDataAvailable() )
1283          {                  {
1284              dataBuffer.push_back( ReadByte(msTimeout) ) ;                          dataBuffer.push_back( ReadByte(msTimeout) ) ;
1285          }                  }
1286      }          }
1287      else          else
1288      {          {
1289          //                  //
1290          // Reserve enough space in the buffer to store the incoming                  // Reserve enough space in the buffer to store the incoming
1291          // data.                  // data.
1292          //                  //
1293          dataBuffer.reserve( numOfBytes ) ;                  dataBuffer.reserve( numOfBytes ) ;
1294          //                  //
1295          for(unsigned int i=0; i<numOfBytes; ++i)                  for (unsigned int i=0; i<numOfBytes; ++i)
1296          {                  {
1297              dataBuffer.push_back( ReadByte(msTimeout) ) ;                          dataBuffer.push_back( ReadByte(msTimeout) ) ;
1298          }                  }
1299      }          }
1300      return ;          return ;
1301  }  }
1302    
1303  inline  inline
1304  const std::string  const std::string
1305  SerialPort::SerialPortImpl::ReadLine( const unsigned int msTimeout,  SerialPort::SerialPortImpl::ReadLine( const unsigned int msTimeout,
1306                                        const char         lineTerminator )                                        const char         lineTerminator )
1307      throw( SerialPort::NotOpen,  throw( SerialPort::NotOpen,
1308             SerialPort::ReadTimeout,         SerialPort::ReadTimeout,
1309             std::runtime_error )         std::runtime_error )
1310  {  {
1311      std::string result ;          std::string result ;
1312      char next_char = 0 ;          char next_char = 0 ;
1313      do          do
1314      {          {
1315          next_char = this->ReadByte( msTimeout ) ;                  next_char = this->ReadByte( msTimeout ) ;
1316          result += next_char ;                  result += next_char ;
1317      }          }
1318      while( next_char != lineTerminator ) ;          while ( next_char != lineTerminator ) ;
1319      return result ;          return result ;
1320  }  }
1321    
1322  inline  inline
1323  void  void
1324  SerialPort::SerialPortImpl::WriteByte( const unsigned char dataByte )  SerialPort::SerialPortImpl::WriteByte( const unsigned char dataByte )
1325      throw( SerialPort::NotOpen,  throw( SerialPort::NotOpen,
1326             std::runtime_error )         std::runtime_error )
1327  {  {
1328      //          //
1329      // Make sure that the serial port is open.          // Make sure that the serial port is open.
1330      //          //
1331      if ( ! this->IsOpen() )          if ( ! this->IsOpen() )
1332      {          {
1333          throw SerialPort::NotOpen( ERR_MSG_PORT_NOT_OPEN ) ;                  throw SerialPort::NotOpen( ERR_MSG_PORT_NOT_OPEN ) ;
1334      }          }
1335      //          //
1336      // Write the byte to the serial port.          // Write the byte to the serial port.
1337      //          //
1338      this->Write( &dataByte,          this->Write( &dataByte,
1339                   1 ) ;                       1 ) ;
1340      return ;          return ;
1341  }  }
1342    
1343  inline  inline
1344  void  void
1345  SerialPort::SerialPortImpl::Write(const SerialPort::DataBuffer& dataBuffer)  SerialPort::SerialPortImpl::Write(const SerialPort::DataBuffer& dataBuffer)
1346      throw( SerialPort::NotOpen,  throw( SerialPort::NotOpen,
1347             std::runtime_error )         std::runtime_error )
1348  {  {
1349      //          //
1350      // Make sure that the serial port is open.          // Make sure that the serial port is open.
1351      //          //
1352      if ( ! this->IsOpen() )          if ( ! this->IsOpen() )
1353      {          {
1354          throw SerialPort::NotOpen( ERR_MSG_PORT_NOT_OPEN ) ;                  throw SerialPort::NotOpen( ERR_MSG_PORT_NOT_OPEN ) ;
1355      }          }
1356      //          //
1357      // Nothing needs to be done if there is no data in the buffer.          // Nothing needs to be done if there is no data in the buffer.
1358      //          //
1359      if ( 0 == dataBuffer.size() )          if ( 0 == dataBuffer.size() )
1360      {          {
1361          return ;                  return ;
1362      }          }
1363      //          //
1364      // Allocate memory for storing the contents of the          // Allocate memory for storing the contents of the
1365      // dataBuffer. This allows us to write all the data using a single          // dataBuffer. This allows us to write all the data using a single
1366      // call to write() instead of writing one byte at a time.          // call to write() instead of writing one byte at a time.
1367      //          //
1368      unsigned char* local_buffer = new unsigned char[dataBuffer.size()] ;          unsigned char* local_buffer = new unsigned char[dataBuffer.size()] ;
1369      if ( 0 == local_buffer )          if ( 0 == local_buffer )
1370      {          {
1371          throw std::runtime_error( std::string(__FUNCTION__) +                  throw std::runtime_error( std::string(__FUNCTION__) +
1372                                    ": Cannot allocate memory while writing"                                            ": Cannot allocate memory while writing"
1373                                    "data to the serial port." ) ;                                            "data to the serial port." ) ;
1374      }          }
1375      //          //
1376      // Copy the data into local_buffer.          // Copy the data into local_buffer.
1377      //          //
1378      std::copy( dataBuffer.begin(),          std::copy( dataBuffer.begin(),
1379                 dataBuffer.end(),                     dataBuffer.end(),
1380                 local_buffer ) ;                     local_buffer ) ;
1381      //          //
1382      // Write data to the serial port.          // Write data to the serial port.
1383      //          //
1384      try          try
1385      {          {
1386          this->Write( local_buffer,                  this->Write( local_buffer,
1387                       dataBuffer.size() ) ;                               dataBuffer.size() ) ;
1388      }          }
1389      catch( ... )          catch ( ... )
1390      {          {
1391          //                  //
1392          // Free the allocated memory.                  // Free the allocated memory.
1393          //                  //
1394          delete [] local_buffer ;                  delete [] local_buffer ;
1395          throw ;                  throw ;
1396      }          }
1397      //          //
1398      // Free the allocated memory.          // Free the allocated memory.
1399      //          //
1400      delete [] local_buffer ;          delete [] local_buffer ;
1401      return ;          return ;
1402  }  }
1403    
1404  inline  inline
1405  void  void
1406  SerialPort::SerialPortImpl::Write( const unsigned char* dataBuffer,  SerialPort::SerialPortImpl::Write( const unsigned char* dataBuffer,
1407                                     const unsigned int   bufferSize )                                     const unsigned int   bufferSize )
1408      throw( SerialPort::NotOpen,  throw( SerialPort::NotOpen,
1409             std::runtime_error )         std::runtime_error )
1410  {  {
1411      //          //
1412      // Make sure that the serial port is open.          // Make sure that the serial port is open.
1413      //          //
1414      if ( ! this->IsOpen() )          if ( ! this->IsOpen() )
1415      {          {
1416          throw SerialPort::NotOpen( ERR_MSG_PORT_NOT_OPEN ) ;                  throw SerialPort::NotOpen( ERR_MSG_PORT_NOT_OPEN ) ;
1417      }          }
1418      //          //
1419      // Write the data to the serial port. Keep retrying if EAGAIN          // Write the data to the serial port. Keep retrying if EAGAIN
1420      // error is received.          // error is received.
1421      //          //
1422      int num_of_bytes_written = -1 ;          int num_of_bytes_written = -1 ;
1423      do          do
1424      {          {
1425          num_of_bytes_written = write( mFileDescriptor,                  num_of_bytes_written = write( mFileDescriptor,
1426                                        dataBuffer,                                                dataBuffer,
1427                                        bufferSize ) ;                                                bufferSize ) ;
1428      }          }
1429      while ( ( num_of_bytes_written < 0 ) &&          while ( ( num_of_bytes_written < 0 ) &&
1430              ( EAGAIN == errno ) ) ;                  ( EAGAIN == errno ) ) ;
1431      //          //
1432      if ( num_of_bytes_written < 0 )          if ( num_of_bytes_written < 0 )
1433      {          {
1434          throw std::runtime_error( strerror(errno) ) ;                  throw std::runtime_error( strerror(errno) ) ;
1435      }          }
1436      //          //
1437      // :FIXME: What happens if num_of_bytes_written < bufferSize ?          // :FIXME: What happens if num_of_bytes_written < bufferSize ?
1438      //          //
1439      return ;          return ;
1440  }  }
1441    
1442  inline  inline
1443  void  void
1444  SerialPort::SerialPortImpl::SetDtr( const bool dtrState )  SerialPort::SerialPortImpl::SetDtr( const bool dtrState )
1445      throw( SerialPort::NotOpen,  throw( SerialPort::NotOpen,
1446             std::runtime_error )         std::runtime_error )
1447  {  {
1448      this->SetModemControlLine( TIOCM_DTR,          this->SetModemControlLine( TIOCM_DTR,
1449                                 dtrState ) ;                                     dtrState ) ;
1450      return ;          return ;
1451  }  }
1452    
1453  inline  inline
1454  bool  bool
1455  SerialPort::SerialPortImpl::GetDtr() const  SerialPort::SerialPortImpl::GetDtr() const
1456      throw( SerialPort::NotOpen,  throw( SerialPort::NotOpen,
1457             std::runtime_error )         std::runtime_error )
1458  {  {
1459      return this->GetModemControlLine( TIOCM_DTR ) ;          return this->GetModemControlLine( TIOCM_DTR ) ;
1460  }      }
1461    
1462  inline  inline
1463  void  void
1464  SerialPort::SerialPortImpl::SetRts( const bool rtsState )  SerialPort::SerialPortImpl::SetRts( const bool rtsState )
1465      throw( SerialPort::NotOpen,  throw( SerialPort::NotOpen,
1466             std::runtime_error )         std::runtime_error )
1467  {  {
1468      this->SetModemControlLine( TIOCM_RTS,          this->SetModemControlLine( TIOCM_RTS,
1469                                 rtsState ) ;                                     rtsState ) ;
1470      return ;          return ;
1471  }  }
1472    
1473  inline  inline
1474  bool  bool
1475  SerialPort::SerialPortImpl::GetRts() const  SerialPort::SerialPortImpl::GetRts() const
1476      throw( SerialPort::NotOpen,  throw( SerialPort::NotOpen,
1477             std::runtime_error )         std::runtime_error )
1478  {  {
1479      return this->GetModemControlLine( TIOCM_RTS ) ;          return this->GetModemControlLine( TIOCM_RTS ) ;
1480  }      }
1481    
1482    
1483  inline  inline
1484  bool  bool
1485  SerialPort::SerialPortImpl::GetCts() const  SerialPort::SerialPortImpl::GetCts() const
1486      throw( SerialPort::NotOpen,  throw( SerialPort::NotOpen,
1487             std::runtime_error )         std::runtime_error )
1488  {  {
1489      return this->GetModemControlLine( TIOCM_CTS ) ;          return this->GetModemControlLine( TIOCM_CTS ) ;
1490  }      }
1491    
1492    
1493  inline  inline
1494  bool  bool
1495  SerialPort::SerialPortImpl::GetDsr() const  SerialPort::SerialPortImpl::GetDsr() const
1496      throw( SerialPort::NotOpen,  throw( SerialPort::NotOpen,
1497             std::runtime_error )         std::runtime_error )
1498  {  {
1499      return this->GetModemControlLine( TIOCM_DSR ) ;          return this->GetModemControlLine( TIOCM_DSR ) ;
1500  }      }
1501    
1502  inline  inline
1503  void  void
1504  SerialPort::SerialPortImpl::HandlePosixSignal( int signalNumber )  SerialPort::SerialPortImpl::HandlePosixSignal( int signalNumber )
1505  {  {
1506      //          //
1507      // We only want to deal with SIGIO signals here.          // We only want to deal with SIGIO signals here.
1508      //          //
1509      if ( SIGIO != signalNumber )          if ( SIGIO != signalNumber )
1510      {          {
1511          return ;                  return ;
1512      }          }
1513      //          //
1514      // Check if any data is available at the specified file          // Check if any data is available at the specified file
1515      // descriptor.          // descriptor.
1516      //          //
1517      int num_of_bytes_available = 0 ;          int num_of_bytes_available = 0 ;
1518      if ( ioctl( mFileDescriptor,          if ( ioctl( mFileDescriptor,
1519                  FIONREAD,                      FIONREAD,
1520                  &num_of_bytes_available ) < 0 )                      &num_of_bytes_available ) < 0 )
1521      {          {
1522          /*                  /*
1523           * Ignore any errors and return immediately.                   * Ignore any errors and return immediately.
1524           */                   */
1525          return ;                  return ;
1526      }          }
1527      //          //
1528      // If data is available, read all available data and shove          // If data is available, read all available data and shove
1529      // it into the corresponding input buffer.          // it into the corresponding input buffer.
1530      //          //
1531      for(int i=0; i<num_of_bytes_available; ++i)          for (int i=0; i<num_of_bytes_available; ++i)
1532      {          {
1533          unsigned char next_byte ;                  unsigned char next_byte ;
1534          if ( read( mFileDescriptor,                  if ( read( mFileDescriptor,
1535                     &next_byte,                             &next_byte,
1536                     1 ) > 0 )                             1 ) > 0 )
1537          {                  {
1538              mInputBuffer.push( next_byte ) ;                          mInputBuffer.push( next_byte ) ;
1539          }                  }
1540          else                  else
1541          {                  {
1542              break ;                          break ;
1543          }                  }
1544      }          }
1545      return ;          return ;
1546  }  }
1547    
1548  inline  inline
1549  void  void
1550  SerialPort::SerialPortImpl::SetModemControlLine( const int  modemLine,  SerialPort::SerialPortImpl::SetModemControlLine( const int  modemLine,
1551                                                   const bool lineState )          const bool lineState )
1552      throw( SerialPort::NotOpen,  throw( SerialPort::NotOpen,
1553             std::runtime_error )         std::runtime_error )
1554  {  {
1555      //          //
1556      // Make sure that the serial port is open.          // Make sure that the serial port is open.
1557      //          //
1558      if ( ! this->IsOpen() )          if ( ! this->IsOpen() )
1559      {          {
1560          throw SerialPort::NotOpen( ERR_MSG_PORT_NOT_OPEN ) ;                  throw SerialPort::NotOpen( ERR_MSG_PORT_NOT_OPEN ) ;
1561      }          }
1562      //          //
1563      // :TODO: Check to make sure that modemLine is a valid value.          // :TODO: Check to make sure that modemLine is a valid value.
1564      //          //
1565      // Set or unset the specified bit according to the value of          // Set or unset the specified bit according to the value of
1566      // lineState.          // lineState.
1567      //          //
1568      int ioctl_result = -1 ;          int ioctl_result = -1 ;
1569      if ( true == lineState )          if ( true == lineState )
1570      {          {
1571          int set_line_mask = modemLine ;                  int set_line_mask = modemLine ;
1572          ioctl_result = ioctl( mFileDescriptor,                  ioctl_result = ioctl( mFileDescriptor,
1573                                TIOCMBIS,                                        TIOCMBIS,
1574                                &set_line_mask ) ;                                        &set_line_mask ) ;
1575      }          }
1576      else          else
1577      {          {
1578          int reset_line_mask = modemLine ;                  int reset_line_mask = modemLine ;
1579          ioctl_result = ioctl( mFileDescriptor,                  ioctl_result = ioctl( mFileDescriptor,
1580                                TIOCMBIC,                                        TIOCMBIC,
1581                                &reset_line_mask ) ;                                        &reset_line_mask ) ;
1582      }          }
1583      //          //
1584      // Check for errors.          // Check for errors.
1585      //          //
1586      if ( -1 == ioctl_result )          if ( -1 == ioctl_result )
1587      {          {
1588          throw std::runtime_error( strerror(errno) ) ;                  throw std::runtime_error( strerror(errno) ) ;
1589      }          }
1590      return ;          return ;
1591  }  }
1592    
1593  inline  inline
1594  bool  bool
1595  SerialPort::SerialPortImpl::GetModemControlLine( const int modemLine ) const  SerialPort::SerialPortImpl::GetModemControlLine( const int modemLine ) const
1596      throw( SerialPort::NotOpen,  throw( SerialPort::NotOpen,
1597             std::runtime_error )         std::runtime_error )
1598  {  {
1599      //          //
1600      // Make sure that the serial port is open.          // Make sure that the serial port is open.
1601      //          //
1602      if ( ! this->IsOpen() )          if ( ! this->IsOpen() )
1603      {          {
1604          throw SerialPort::NotOpen( ERR_MSG_PORT_NOT_OPEN ) ;                  throw SerialPort::NotOpen( ERR_MSG_PORT_NOT_OPEN ) ;
1605      }          }
1606      //          //
1607      // Use an ioctl() call to get the state of the line.          // Use an ioctl() call to get the state of the line.
1608      //          //
1609      int serial_port_state = 0 ;          int serial_port_state = 0 ;
1610      if ( -1 == ioctl( mFileDescriptor,          if ( -1 == ioctl( mFileDescriptor,
1611                        TIOCMGET,                            TIOCMGET,
1612                        &serial_port_state ) )                            &serial_port_state ) )
1613      {          {
1614          throw std::runtime_error( strerror(errno) ) ;                  throw std::runtime_error( strerror(errno) ) ;
1615      }          }
1616      //          //
1617      // :TODO: Verify that modemLine is a valid value.          // :TODO: Verify that modemLine is a valid value.
1618      //          //
1619      return ( serial_port_state & modemLine ) ;          return ( serial_port_state & modemLine ) ;
1620  }  }
1621    
1622  namespace  namespace
1623  {  {
1624      const struct timeval          const struct timeval
1625      operator-( const struct timeval& firstOperand,                                  operator-( const struct timeval& firstOperand,
1626                 const struct timeval& secondOperand )                                             const struct timeval& secondOperand )
1627      {          {
1628          /*                  /*
1629           * This implementation may result in undefined behavior if the                   * This implementation may result in undefined behavior if the
1630           * platform uses unsigned values for storing tv_sec and tv_usec                   * platform uses unsigned values for storing tv_sec and tv_usec
1631           * members of struct timeval.                   * members of struct timeval.
1632           */                   */
1633          //                  //
1634          // Number of microseconds in a second.                  // Number of microseconds in a second.
1635          //                  //
1636          const int MICROSECONDS_PER_SECOND = 1000000 ;                  const int MICROSECONDS_PER_SECOND = 1000000 ;
1637          struct timeval result ;                  struct timeval result ;
1638          //                  //
1639          // Take the difference of individual members of the two operands.                  // Take the difference of individual members of the two operands.
1640          //                  //
1641          result.tv_sec  = firstOperand.tv_sec - secondOperand.tv_sec ;                  result.tv_sec  = firstOperand.tv_sec - secondOperand.tv_sec ;
1642          result.tv_usec = firstOperand.tv_usec - secondOperand.tv_usec ;                  result.tv_usec = firstOperand.tv_usec - secondOperand.tv_usec ;
1643          //                  //
1644          // If abs(result.tv_usec) is larger than MICROSECONDS_PER_SECOND,                  // If abs(result.tv_usec) is larger than MICROSECONDS_PER_SECOND,
1645          // then increment/decrement result.tv_sec accordingly.                  // then increment/decrement result.tv_sec accordingly.
1646          //                  //
1647          if ( abs( result.tv_usec ) > MICROSECONDS_PER_SECOND )                  if ( abs( result.tv_usec ) > MICROSECONDS_PER_SECOND )
1648          {                  {
1649              int num_of_seconds = (result.tv_usec / MICROSECONDS_PER_SECOND ) ;                          int num_of_seconds = (result.tv_usec / MICROSECONDS_PER_SECOND ) ;
1650              result.tv_sec  += num_of_seconds ;                          result.tv_sec  += num_of_seconds ;
1651              result.tv_usec -= ( MICROSECONDS_PER_SECOND * num_of_seconds ) ;                          result.tv_usec -= ( MICROSECONDS_PER_SECOND * num_of_seconds ) ;
1652          }                  }
1653          return result ;                  return result ;
1654      }          }
1655  } ;  } ;
1656    

Legend:
Removed from v.195  
changed lines
  Added in v.196

  ViewVC Help
Powered by ViewVC 1.1.20