📄 serialstreambuf.cc
字号:
#include <iostream>#ifndef _sys_types_h_INCLUDED_# include <sys/types.h># define _sys_types_h_INCLUDED_#endif#ifndef _sys_stat_h_INCLUDED_# include <sys/stat.h># define _sys_stat_h_INCLUDED_#endif#ifndef _fcntl_h_INCLUDED_# include <fcntl.h># define _fcntl_h_INCLUDED_#endif#ifndef _unistd_h_INCLUDED_# include <unistd.h># define _unistd_h_INCLUDED_#endif#ifndef _std_cassert_INCLUDED_# include <cassert># define _std_cassert_INCLUDED_#endif#ifndef _std_fstream_INCLUDED_# include <fstream># define _std_fstream_INCLUDED_#endif#ifndef _limits_h_INCLUDED_# include <limits.h># define _limits_h_INCLUDED_#endif#ifndef _SerialStreamBuf_h_# include "SerialStreamBuf.h"#endifusing namespace std ;using namespace LibSerial ;//// Set the values of the static members of the SerialStream class. //const SerialStreamBuf::BaudRateEnum SerialStreamBuf::DEFAULT_BAUD = BAUD_9600 ;const SerialStreamBuf::CharSizeEnum SerialStreamBuf::DEFAULT_CHAR_SIZE = CHAR_SIZE_7 ;const short SerialStreamBuf::DEFAULT_NO_OF_STOP_BITS = 1 ;const SerialStreamBuf::ParityEnum SerialStreamBuf::DEFAULT_PARITY = PARITY_NONE ;const SerialStreamBuf::FlowControlEnumSerialStreamBuf::DEFAULT_FLOW_CONTROL = FLOW_CONTROL_NONE ;const shortSerialStreamBuf::DEFAULT_VMIN = 1 ;const shortSerialStreamBuf::DEFAULT_VTIME = 0 ;SerialStreamBuf*SerialStreamBuf::open( const string filename, ios_base::openmode mode ) { // // If the buffer is alreay open then we should not allow a call to // another open(). // if( is_open() != false ) { return 0 ; } // // We only allow three different combinations of ios_base::openmode // so we can use a switch here to construct the flags to be used // with the open() system call. // int flags ; if ( mode == (ios_base::in|ios_base::out) ) { flags = O_RDWR ; } else if ( mode == ios_base::in ) { flags = O_RDONLY ; } else if ( mode == ios_base::out ) { flags = O_WRONLY ; } else { return 0 ; } /* switch( mode ) { case ios_base::in: flags = O_RDONLY ; break ; case ios_base::out: flags = O_WRONLY ; break ; case (ios_base::in|ios_base::out): flags = O_RDWR ; break ; default: return 0 ; break ; } */ // // Since we are dealing with the serial port we need to use the // O_NOCTTY option. // flags |= O_NOCTTY ; // // Try to open the serial port. // this->mFileDescriptor = ::open(filename.data(), flags) ; if( -1 == this->mFileDescriptor ) { return 0 ; } // // Initialize the serial port. // if( -1 == this->InitializeSerialPort() ) { return 0 ; } return this;}intSerialStreamBuf::InitializeSerialPort() { // // If we do not have a valid file descriptor then return with // failure. // if( -1 == this->mFileDescriptor ) { return -1 ; } // // Use non-blocking mode while configuring the serial port. // int flags = fcntl(this->mFileDescriptor, F_GETFL, 0) ; if( -1 == fcntl( this->mFileDescriptor, F_SETFL, flags | O_NONBLOCK ) ) { return -1 ; } // // Flush out any garbage left behind in the buffers associated // with the port from any previous operations. // if( -1 == tcflush(this->mFileDescriptor, TCIOFLUSH) ) { return -1 ; } // // Set up the default configuration for the serial port. // if( -1 == this->SetParametersToDefault() ) { return -1 ; } // // Allow all further communications to happen in blocking // mode. // flags = fcntl(this->mFileDescriptor, F_GETFL, 0) ; if( -1 == fcntl( this->mFileDescriptor, F_SETFL, flags & ~O_NONBLOCK ) ) { return -1 ; } // // If we get here without problems then we are good; return a value // different from -1. // return 0 ;}intSerialStreamBuf::SetParametersToDefault() { if( -1 == mFileDescriptor ) { return -1 ; } // // Set all values (also the ones, which are not covered by the // parametrisation-functions of this library). // struct termios tio; tio.c_iflag = IGNBRK; tio.c_oflag = 0; tio.c_cflag = B19200 | CS8 | CLOCAL | CREAD; tio.c_lflag = 0; tio.c_line = '\0'; bzero( &tio.c_cc, sizeof(tio.c_cc) ); tio.c_cc[VTIME] = 0; tio.c_cc[VMIN] = 1; if ( -1 == tcsetattr(mFileDescriptor,TCSANOW,&tio) ) { return -1 ; } // // Baud rate // if( BAUD_INVALID == SetBaudRate(DEFAULT_BAUD) ) { return -1 ; } ; // // Character size. // if( -1 == SetCharSize(DEFAULT_CHAR_SIZE) ) { return -1 ; } // // Number of stop bits. // if( -1 == SetNumOfStopBits(DEFAULT_NO_OF_STOP_BITS) ) { return -1 ; } // // Parity // if( -1 == SetParity(DEFAULT_PARITY) ) { return -1 ; } // // Flow control // if( -1 == SetFlowControl(DEFAULT_FLOW_CONTROL) ) { return -1 ; } // // VMin // if ( -1 == SetVMin(DEFAULT_VMIN) ) { return -1 ; } // // VTime // if ( -1 == SetVTime(DEFAULT_VTIME) ) { return -1 ; } // // All done. Return a value other than -1. // return 0 ;}const SerialStreamBuf::BaudRateEnumSerialStreamBuf::SetBaudRate(const BaudRateEnum baud_rate) { if( -1 == mFileDescriptor ) { return BAUD_INVALID ; } switch (baud_rate) { case BAUD_50: case BAUD_75: case BAUD_110: case BAUD_134: case BAUD_150: case BAUD_200: case BAUD_300: case BAUD_600: case BAUD_1200: case BAUD_1800: case BAUD_2400: case BAUD_4800: case BAUD_9600: case BAUD_19200: case BAUD_38400: case BAUD_57600: case BAUD_115200: // // Get the current terminal settings. // struct termios term_setting ; if( -1 == tcgetattr(mFileDescriptor, &term_setting) ) { return BAUD_INVALID ; } // // Modify the baud rate in the term_setting structure. // cfsetispeed( &term_setting, baud_rate ) ; cfsetospeed( &term_setting, baud_rate ) ; // // Apply the modified termios structure to the serial // port. // if( -1 == tcsetattr(mFileDescriptor, TCSANOW, &term_setting) ) { return BAUD_INVALID ; } break ; default: // // :TODO: Thu Jul 13 16:30:14 2000 Pagey // // There is obviously a problem if we reach here. The method // must have been called with an invalid value of the baud // rate. We should probably throw an exception here. I will // print something on cerr for the time being but leave the // stream in "good" state. // return BAUD_INVALID ; break ; } ; // // If we succeeded in setting the baud rate then we need to return // the baud rate. // return BaudRate() ;}const SerialStreamBuf::BaudRateEnumSerialStreamBuf::BaudRate() const { if( -1 == mFileDescriptor ) { return BAUD_INVALID ; } // // Get the current terminal settings. // struct termios term_setting ; if( -1 == tcgetattr(mFileDescriptor, &term_setting) ) { return BAUD_INVALID ; } // // Read the input and output baud rates. // speed_t input_baud = cfgetispeed( &term_setting ) ; speed_t output_baud = cfgetospeed( &term_setting ) ; // // Make sure that the input and output baud rates are // equal. Otherwise, we do not know which one to return. // if( input_baud != output_baud ) { return BAUD_INVALID ; } switch( input_baud ) { case B50: return BAUD_50 ; break ; case B75: return BAUD_75 ; break ; case B110: return BAUD_110 ; break ; case B134: return BAUD_134 ; break ; case B150: return BAUD_150 ; break ; case B200: return BAUD_200 ; break ; case B300: return BAUD_300 ; break ; case B600: return BAUD_600 ; break ; case B1200: return BAUD_1200 ; break ; case B1800: return BAUD_1800 ; break ; case B2400: return BAUD_2400 ; break ; case B4800: return BAUD_4800 ; break ; case B9600: return BAUD_9600 ; break ; case B19200: return BAUD_19200 ; break ; case B38400: return BAUD_38400 ; break ; case B57600: return BAUD_57600 ; break ; case B115200: return BAUD_115200 ; break ; default: return BAUD_INVALID ; // we return an invalid value in this case. break ; } // // The code should never reach here due to the fact that the default // section of the above switch statement returns. So we force an // abort here using an assertion which will always fail. // assert( false ) ; return BAUD_INVALID ;}const SerialStreamBuf::CharSizeEnumSerialStreamBuf::SetCharSize(const CharSizeEnum char_size) { if( -1 == mFileDescriptor ) { return CHAR_SIZE_INVALID ; } switch(char_size) { case CHAR_SIZE_5: case CHAR_SIZE_6: case CHAR_SIZE_7: case CHAR_SIZE_8: // // Get the current terminal settings. // struct termios term_setting ; if( -1 == tcgetattr(mFileDescriptor, &term_setting) ) { return CHAR_SIZE_INVALID ; } // // Set the character size to the specified value. If the character // size is not 8 then it is also important to set ISTRIP. Setting // ISTRIP causes all but the 7 low-order bits to be set to // zero. Otherwise they are set to unspecified values and may // cause problems. At the same time, we should clear the ISTRIP // flag when the character size is 8 otherwise the MSB will always // be set to zero (ISTRIP does not check the character size // setting; it just sets every bit above the low 7 bits to zero). // if( char_size == CHAR_SIZE_8 ) { term_setting.c_iflag &= ~ISTRIP ; // clear the ISTRIP flag. } else { term_setting.c_iflag |= ISTRIP ; // set the ISTRIP flag. } term_setting.c_cflag &= ~CSIZE ; // clear all the CSIZE bits. term_setting.c_cflag |= char_size ; // set the character size. // // Set the new settings for the serial port. // if( -1 == tcsetattr(mFileDescriptor, TCSANOW, &term_setting) ) { return CHAR_SIZE_INVALID ; } break ; default: return CHAR_SIZE_INVALID ; break ; } return this->CharSize() ;}const SerialStreamBuf::CharSizeEnumSerialStreamBuf::CharSize() const { if( -1 == mFileDescriptor ) { return CHAR_SIZE_INVALID ; } // // Get the current terminal settings. // struct termios term_setting ; if( -1 == tcgetattr(mFileDescriptor, &term_setting) ) { return CHAR_SIZE_INVALID ; } // // Extract the character size from the terminal settings. // int char_size = (term_setting.c_cflag & CSIZE) ; switch( char_size ) { case CS5: return CHAR_SIZE_5 ; break ; case CS6: return CHAR_SIZE_6 ; break ; case CS7: return CHAR_SIZE_7 ; break ; case CS8: return CHAR_SIZE_8 ; break ; default: // // If we get an invalid character, we set the badbit for the // stream associated with the serial port. // return CHAR_SIZE_INVALID ; break ; } ; return CHAR_SIZE_INVALID ;}shortSerialStreamBuf::SetNumOfStopBits(short stop_bits) { if( -1 == mFileDescriptor ) { return 0 ; } // // Get the current terminal settings. // struct termios term_setting ; if( -1 == tcgetattr(mFileDescriptor, &term_setting) ) { return 0 ; } switch( stop_bits ) { case 1: term_setting.c_cflag &= ~CSTOPB ; break ; case 2: term_setting.c_cflag |= CSTOPB ; break ; default: return 0 ; break ; } // // Set the new settings for the serial port. // if( -1 == tcsetattr(mFileDescriptor, TCSANOW, &term_setting) ) { return 0 ; } return this->NumOfStopBits() ;}short SerialStreamBuf::NumOfStopBits() const { if( -1 == mFileDescriptor ) { return 0 ; } // // Get the current terminal settings. // struct termios term_setting ; if( -1 == tcgetattr(mFileDescriptor, &term_setting) ) { return 0 ; } // // If CSTOPB is set then the number of stop bits is 2 otherwise it // is 1. // if( term_setting.c_cflag & CSTOPB ) { return 2 ;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -