📄 serialport.cpp
字号:
/*************************************************************************** * Copyright (C) 2004 by Manish Pagey * * crayzeewulf@users.sourceforge.net * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/#include "SerialPort.h"#include "PosixSignalDispatcher.h"#include "PosixSignalHandler.h"#include <queue>#include <map>#include <cerrno>#include <cassert>#include <termios.h>#include <fcntl.h>#include <sys/ioctl.h>#include <sys/time.h>#include <signal.h>namespace{ // // Various error messages used in this file while throwing // exceptions. // const std::string ERR_MSG_PORT_NOT_OPEN = "Serial port not open." ; const std::string ERR_MSG_PORT_ALREADY_OPEN = "Serial port already open." ; const std::string ERR_MSG_UNSUPPORTED_BAUD = "Unsupported baud rate." ; const std::string ERR_MSG_UNKNOWN_BAUD = "Unknown baud rate." ; const std::string ERR_MSG_INVALID_PARITY = "Invalid parity setting." ; const std::string ERR_MSG_INVALID_STOP_BITS = "Invalid number of stop bits." ; const std::string ERR_MSG_INVALID_FLOW_CONTROL = "Invalid flow control." ; /* * Return the difference between the two specified timeval values. * This method subtracts secondOperand from firstOperand and returns * the result as a timeval. The time represented by firstOperand must * be later than the time represented by secondOperand. Otherwise, * the result of this operator may be undefined. */ const struct timeval operator-( const struct timeval& firstOperand, const struct timeval& secondOperand ) ;} ;class SerialPort::SerialPortImpl : public PosixSignalHandler{public: /** * Constructor. */ SerialPortImpl( const std::string& serialPortName ) ; /** * Destructor. */ ~SerialPortImpl() ; /** * Open the serial port. */ void Open() throw( SerialPort::OpenFailed, SerialPort::AlreadyOpen ) ; /** * Check if the serial port is currently open. */ bool IsOpen() const ; /** * Close the serial port. */ void Close() throw(SerialPort::NotOpen) ; /** * Set the baud rate of the serial port. */ void SetBaudRate( const SerialPort::BaudRate baudRate ) throw( SerialPort::NotOpen, SerialPort::UnsupportedBaudRate, std::invalid_argument, std::runtime_error ) ; /** * Get the current baud rate. */ SerialPort::BaudRate GetBaudRate() const throw( SerialPort::NotOpen, std::runtime_error ) ; /** * Set the character size. */ void SetCharSize( const SerialPort::CharacterSize charSize ) throw( SerialPort::NotOpen, std::invalid_argument, std::runtime_error ) ; /** * Get the current character size. */ SerialPort::CharacterSize GetCharSize() const throw( SerialPort::NotOpen, std::runtime_error ) ; void SetParity( const SerialPort::Parity parityType ) throw( SerialPort::NotOpen, std::invalid_argument, std::runtime_error ) ; SerialPort::Parity GetParity() const throw(SerialPort::NotOpen) ; void SetNumOfStopBits( const SerialPort::StopBits numOfStopBits ) throw( SerialPort::NotOpen, std::invalid_argument ) ; SerialPort::StopBits GetNumOfStopBits() const throw(SerialPort::NotOpen) ; void SetFlowControl( const SerialPort::FlowControl flowControl ) throw( SerialPort::NotOpen, std::invalid_argument ) ; SerialPort::FlowControl GetFlowControl() const throw( SerialPort::NotOpen ) ; bool IsDataAvailable() const throw( SerialPort::NotOpen, std::runtime_error ) ; unsigned char ReadByte(const unsigned int msTimeout = 0 ) throw( SerialPort::NotOpen, SerialPort::ReadTimeout, std::runtime_error ) ; void Read( SerialPort::DataBuffer& dataBuffer, const unsigned int numOfBytes, const unsigned int msTimeout ) throw( SerialPort::NotOpen, SerialPort::ReadTimeout, std::runtime_error ) ; const std::string ReadLine( const unsigned int msTimeout = 0, const char lineTerminator = '\n' ) throw( SerialPort::NotOpen, SerialPort::ReadTimeout, std::runtime_error ) ; void WriteByte( const unsigned char dataByte ) throw( SerialPort::NotOpen, std::runtime_error ) ; void Write(const SerialPort::DataBuffer& dataBuffer) throw( SerialPort::NotOpen, std::runtime_error ) ; void Write( const unsigned char* dataBuffer, const unsigned int bufferSize ) throw( SerialPort::NotOpen, std::runtime_error ) ; /* * This method must be defined by all subclasses of PosixSignalHandler. */ void HandlePosixSignal(int signalNumber) ;private: /** * Name of the serial port. On POSIX systems this is the name of * the device file. */ std::string mSerialPortName ; /** * Flag that indicates whether the serial port is currently open. */ bool mIsOpen ; /** * The file descriptor corresponding to the serial port. */ int mFileDescriptor ; /** * Serial port settings are saved into this variable immediately * after the port is opened. These settings are restored when the * serial port is closed. */ termios mOldPortSettings ; /** * Circular buffer used to store the received data. This is done * asynchronously so we do not let tty buffer get filled. */ std::queue<unsigned char> mInputBuffer ;} ;SerialPort::SerialPort( const std::string& serialPortName ) : mSerialPortImpl(new SerialPortImpl(serialPortName) ){ /* empty */}SerialPort::~SerialPort() throw(){ /* * Close the serial port if it is open. */ if ( this->IsOpen() ) { this->Close() ; } /* * Free the memory allocated to the implementation instance. */ if ( mSerialPortImpl ) { delete mSerialPortImpl ; } return ;}voidSerialPort::Open( const BaudRate baudRate, const CharacterSize charSize, const Parity parityType, const StopBits stopBits, const FlowControl flowControl ) throw( OpenFailed, AlreadyOpen, UnsupportedBaudRate, std::invalid_argument ){ // // Open the serial port. mSerialPortImpl->Open() ; // // Set the various parameters of the serial port if it is open. // this->SetBaudRate(baudRate) ; this->SetCharSize(charSize) ; this->SetParity(parityType) ; this->SetNumOfStopBits(stopBits) ; this->SetFlowControl(flowControl) ; // // All done. // return ;}boolSerialPort::IsOpen() const{ return mSerialPortImpl->IsOpen() ;}voidSerialPort::Close() throw(NotOpen){ mSerialPortImpl->Close() ; return ;}voidSerialPort::SetBaudRate( const BaudRate baudRate ) throw( UnsupportedBaudRate, NotOpen, std::invalid_argument ){ mSerialPortImpl->SetBaudRate( baudRate ) ; return ;}SerialPort::BaudRateSerialPort::GetBaudRate() const throw( NotOpen, std::runtime_error ){ return mSerialPortImpl->GetBaudRate() ;}voidSerialPort::SetCharSize( const CharacterSize charSize ) throw( NotOpen, std::invalid_argument ){ mSerialPortImpl->SetCharSize(charSize) ;}SerialPort::CharacterSizeSerialPort::GetCharSize() const throw(NotOpen){ return mSerialPortImpl->GetCharSize() ;}voidSerialPort::SetParity( const Parity parityType ) throw( NotOpen, std::invalid_argument ){ mSerialPortImpl->SetParity( parityType ) ; return ;}SerialPort::ParitySerialPort::GetParity() const throw(NotOpen){ return mSerialPortImpl->GetParity() ;}voidSerialPort::SetNumOfStopBits( const StopBits numOfStopBits ) throw( NotOpen, std::invalid_argument ){ mSerialPortImpl->SetNumOfStopBits(numOfStopBits) ; return ;}SerialPort::StopBitsSerialPort::GetNumOfStopBits() const throw(NotOpen){ return mSerialPortImpl->GetNumOfStopBits() ;}voidSerialPort::SetFlowControl( const FlowControl flowControl ) throw( NotOpen, std::invalid_argument ){ mSerialPortImpl->SetFlowControl( flowControl ) ; return ;}SerialPort::FlowControlSerialPort::GetFlowControl() const throw( NotOpen ){ return mSerialPortImpl->GetFlowControl() ;}boolSerialPort::IsDataAvailable() const throw(NotOpen){ return mSerialPortImpl->IsDataAvailable() ;}unsigned charSerialPort::ReadByte( const unsigned int msTimeout ) throw( NotOpen, ReadTimeout, std::runtime_error ){ return mSerialPortImpl->ReadByte(msTimeout) ;}voidSerialPort::Read( SerialPort::DataBuffer& dataBuffer, const unsigned int numOfBytes, const unsigned int msTimeout ) throw( NotOpen, ReadTimeout, std::runtime_error ){ return mSerialPortImpl->Read( dataBuffer, numOfBytes, msTimeout ) ;}const std::stringSerialPort::ReadLine( const unsigned int msTimeout, const char lineTerminator ) throw( NotOpen, ReadTimeout, std::runtime_error ){ return mSerialPortImpl->ReadLine( msTimeout, lineTerminator ) ;}voidSerialPort::WriteByte( const unsigned char dataByte ) throw( SerialPort::NotOpen, std::runtime_error ){ mSerialPortImpl->WriteByte( dataByte ) ; return ;}voidSerialPort::Write(const DataBuffer& dataBuffer) throw( NotOpen, std::runtime_error ){ mSerialPortImpl->Write( dataBuffer ) ; return ;}voidSerialPort::Write(const std::string& dataString) throw( NotOpen, std::runtime_error ){ mSerialPortImpl->Write( reinterpret_cast<const unsigned char*>(dataString.c_str()), dataString.length() ) ; return ;}/* ------------------------------------------------------------ */inlineSerialPort::SerialPortImpl::SerialPortImpl( const std::string& serialPortName ) : mSerialPortName(serialPortName), mIsOpen(false), mFileDescriptor(-1), mOldPortSettings(){ /* empty */}inline
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -