/home/fwph/code/wurde/modules/rFlexBase/SerialPort.cpp

Go to the documentation of this file.
00001 #include <SerialPort.H>
00002 
00003 #include <termios.h>
00004 #include <sys/stat.h>
00005 
00006 #include <cassert>
00007 
00008 
00009 #warning Get rid of this
00010 #include <iostream>
00011 
00012 
00013 using namespace std;
00014 
00015 
00016 // These are the mappings from integer baud rates to the macros used by the system calls that manipulate the termios struct
00017 static const int g_num_rates = 31;
00018 static const speed_t g_baud_rates[g_num_rates] = {
00019         B0, B50, B75, B110, B134, B150, B200, B300, B600, B1200,
00020         B1800, B2400, B4800, B9600, B19200, B38400, B57600, B115200, B230400, B460800,
00021         B500000, B576000, B921600, B1000000, B1152000, B1500000, B2000000, B2500000, B3000000, B3500000,
00022   B4000000};
00023 static const int g_speeds[g_num_rates] = {
00024         0, 50, 75, 110, 134, 150, 200, 300, 600, 1200,
00025         1800, 2400, 4800, 9600, 19200, 38400, 57600, 115200, 230400, 460800,
00026         500000, 576000, 921600, 1000000, 1152000, 1500000, 2000000, 2500000, 3000000, 3500000,
00027   4000000};
00028 
00029 
00030 SerialPort::SerialPort(const string &filename, const int speed, mode_t mode) :m_filename(filename) {
00031         assert(speed > 0);
00032 
00033         // Open the port
00034         m_fd = open(filename.c_str(), mode);
00035         if (m_fd == -1) {
00036                 cerr << "Could not open serial port " << filename << endl;
00037                 return;
00038         }
00039 
00040         // Get the terminal info
00041         struct termios info;
00042         if (tcgetattr(m_fd, &info) < 0) {
00043                 cerr << "Could not get terminal information for " << filename << endl;
00044                 return;
00045         }
00046 
00047   // Turn off echo, canonical mode, extended processing, signals, break signal, cr to newline, parity off, 8 bit strip, flow control,
00048   // size, parity bit, and output processing
00049   info.c_lflag &= ~(ECHO | ICANON | IEXTEN | ISIG | BRKINT | ICRNL | INPCK | ISTRIP | IXON | CSIZE | PARENB | OPOST);
00050 
00051         // Set size to 8 bits
00052   info.c_cflag |= CS8;
00053 
00054   // Set time and bytes to enable read at once
00055   info.c_cc[VTIME] = 0;
00056   info.c_cc[VMIN] = 0;
00057 
00058         // Actually set the controls on the terminal
00059         if (tcsetattr(m_fd, TCSAFLUSH, &info) < 0) {
00060                 close(m_fd);
00061                 cerr << "Could not set controls on serial port " << filename << endl;
00062         }
00063 
00064         setBaudRate(speed);
00065 }
00066 
00067 
00068 SerialPort::~SerialPort() {
00069         if (m_fd != -1)
00070                 close(m_fd);
00071 }
00072 
00073 
00074 int SerialPort::setBaudRate(const int speed) const {
00075         assert(speed > 0);
00076 
00077         // Set the actual speed to pass into the terminal.
00078         speed_t baud_rate = baud(speed);
00079 
00080         // Now, get the terminal information and set the speed
00081         struct termios info;
00082         if (tcgetattr(m_fd, &info) < 0) {
00083                 cerr << "Could not get terminal information for " << m_filename << endl;
00084                 return baudRate();
00085         }
00086 
00087         if (cfsetospeed(&info, baud_rate) < 0) {
00088                 cerr << "Could not set the output speed for " << m_filename << endl;
00089                 return baudRate();
00090         }
00091 
00092         if (cfsetispeed(&info, baud_rate) < 0) {
00093                 cerr << "Could not set the input speed for " << m_filename << endl;
00094                 return baudRate();
00095         }
00096 
00097         if (tcsetattr(m_fd, TCSAFLUSH, &info) < 0) {
00098                 close(m_fd);
00099                 cerr << "Could not set controls on serial port " << m_filename << endl;
00100         }
00101 
00102         return rate(baud_rate);
00103 }
00104 
00105 
00106 int SerialPort::baudRate() const {
00107         // Open the terminal.  We actually need to check the read device in case someone else has sneakily set the speed.
00108         struct termios info;
00109         if (tcgetattr(m_fd, &info) < 0) {
00110                 cerr << "Could not get terminal information for " << m_filename << endl;
00111                 return 0;
00112         }
00113 
00114         // Get the speeds
00115         speed_t ospeed = cfgetospeed(&info);
00116         speed_t ispeed = cfgetispeed(&info);
00117 
00118         // Ensure that they are the same
00119         if (ospeed != ispeed) {
00120                 cerr << "Input and output speeds are different for " << m_filename << "\n  input: " << rate(ispeed) << "\n  output: " << rate(ospeed) << endl;
00121                 return 0;
00122         }
00123 
00124         return rate(ospeed);
00125 }
00126 
00127 
00128 int SerialPort::rate(speed_t baud) {
00129         for(int i = 0; i < g_num_rates ; ++i)
00130                 if (baud == g_baud_rates[i])
00131                         return g_speeds[i];
00132 
00133         // Should never get here
00134         return 0;
00135 }
00136 
00137 
00138 speed_t SerialPort::baud(const int speed) {
00139         assert(speed > 0);
00140 
00141         for(int i = g_num_rates - 1; i >= 0; --i)
00142                 if (speed >= g_speeds[i])
00143                         return g_baud_rates[i];
00144 
00145         // Should never get here
00146         return B0;
00147 }

Generated on Thu Feb 1 15:31:52 2007 for WURDE by  doxygen 1.5.1