Go to the documentation of this file.00001
00010 #include <fcntl.h>
00011 #include <termios.h>
00012 #include <cerrno>
00013 #include <cstring>
00014 #include <cstdio>
00015
00016
00017 class RawSerialDevice
00018 {
00019 enum {
00020 InvalidFd = -1,
00021 };
00022
00023 string error_message_;
00024 int fd_;
00025 struct termios sio_;
00026 fd_set rfds_;
00027
00028
00029 bool waitReceive(int timeout)
00030 {
00031
00032 FD_ZERO(&rfds_);
00033 FD_SET(fd_, &rfds_);
00034
00035 struct timeval tv;
00036 tv.tv_sec = timeout / 1000;
00037 tv.tv_usec = (timeout % 1000) * 1000;
00038
00039 if (select(fd_ + 1, &rfds_, NULL, NULL,
00040 (timeout < 0) ? NULL : &tv) <= 0) {
00041
00042 return false;
00043 }
00044 return true;
00045 }
00046
00047
00048 public:
00049 RawSerialDevice(void) : error_message_("no error."), fd_(InvalidFd)
00050 {
00051 }
00052
00053
00054 const char* what(void)
00055 {
00056 return error_message_.c_str();
00057 }
00058
00059
00060 bool connect(const char* device, long baudrate)
00061 {
00062 #ifndef MAC_OS
00063 enum { O_EXLOCK = 0x0 };
00064 #endif
00065 fd_ = open(device, O_RDWR | O_EXLOCK | O_NONBLOCK | O_NOCTTY);
00066 if (fd_ < 0) {
00067
00068 error_message_ = string(device) + ": " + strerror(errno);
00069 return false;
00070 }
00071 int flags = fcntl(fd_, F_GETFL, 0);
00072 fcntl(fd_, F_SETFL, flags & ~O_NONBLOCK);
00073
00074
00075 tcgetattr(fd_, &sio_);
00076 sio_.c_iflag = 0;
00077 sio_.c_oflag = 0;
00078 sio_.c_cflag &= ~(CSIZE | PARENB | CSTOPB);
00079 sio_.c_cflag |= CS8 | CREAD | CLOCAL;
00080 sio_.c_lflag &= ~(ICANON | ECHO | ISIG | IEXTEN);
00081
00082 sio_.c_cc[VMIN] = 0;
00083 sio_.c_cc[VTIME] = 0;
00084
00085
00086 if (! setBaudrate(baudrate)) {
00087 return false;
00088 }
00089 return true;
00090 }
00091
00092
00093 void disconnect(void)
00094 {
00095 if (fd_ != InvalidFd) {
00096 close(fd_);
00097 fd_ = InvalidFd;
00098 }
00099 }
00100
00101
00102 bool isConnected(void)
00103 {
00104 return (fd_ == InvalidFd) ? false : true;
00105 }
00106
00107
00108 bool setBaudrate(long baudrate)
00109 {
00110 long baudrate_value = -1;
00111 enum { ErrorMessageSize = 256 };
00112 char error_message[ErrorMessageSize];
00113
00114 switch (baudrate) {
00115
00116 case 4800:
00117 baudrate_value = B4800;
00118 break;
00119
00120 case 9600:
00121 baudrate_value = B9600;
00122 break;
00123
00124 case 19200:
00125 baudrate_value = B19200;
00126 break;
00127
00128 case 38400:
00129 baudrate_value = B38400;
00130 break;
00131
00132 case 57600:
00133 baudrate_value = B57600;
00134 break;
00135
00136 case 115200:
00137 baudrate_value = B115200;
00138 break;
00139
00140 default:
00141 sprintf(error_message, "No handle baudrate value: %ld", baudrate);
00142 error_message_ = string(error_message);
00143 return false;
00144 }
00145
00146
00147 cfsetospeed(&sio_, baudrate_value);
00148 cfsetispeed(&sio_, baudrate_value);
00149 tcsetattr(fd_, TCSANOW, &sio_);
00150 flush();
00151
00152 return true;
00153 }
00154
00155
00156 int send(const char* data, int count)
00157 {
00158 if (! isConnected()) {
00159 error_message_ = "no connection.";
00160 return 0;
00161 }
00162 return write(fd_, data, count);
00163 }
00164
00165
00166 int receive(char buffer[], int count, int timeout)
00167 {
00168 int filled = 0;
00169
00170
00171 int n = read(fd_, buffer, count);
00172 if (n < 0) {
00173 return n;
00174 }
00175 filled += n;
00176
00177
00178 if (filled >= count) {
00179 return filled;
00180 }
00181
00182
00183 while (filled < count) {
00184 if (! waitReceive(timeout)) {
00185 break;
00186 }
00187
00188 int required_n = count - filled;
00189 n = read(fd_, &buffer[filled], required_n);
00190 if (n <= 0) {
00191
00192 break;
00193 }
00194 filled += n;
00195 }
00196 return filled;
00197 }
00198
00199
00200 void flush(void)
00201 {
00202 tcdrain(fd_);
00203 tcflush(fd_, TCIOFLUSH);
00204 }
00205 };