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
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
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
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
00048
00049 info.c_lflag &= ~(ECHO | ICANON | IEXTEN | ISIG | BRKINT | ICRNL | INPCK | ISTRIP | IXON | CSIZE | PARENB | OPOST);
00050
00051
00052 info.c_cflag |= CS8;
00053
00054
00055 info.c_cc[VTIME] = 0;
00056 info.c_cc[VMIN] = 0;
00057
00058
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
00078 speed_t baud_rate = baud(speed);
00079
00080
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
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
00115 speed_t ospeed = cfgetospeed(&info);
00116 speed_t ispeed = cfgetispeed(&info);
00117
00118
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
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
00146 return B0;
00147 }