00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037 #include "arch/linux/arch_linux.h"
00038 #include "arch/linux/net_serial.h"
00039 #include <termios.h>
00040 #include <sys/select.h>
00041
00042 namespace rp{ namespace arch{ namespace net{
00043
00044 raw_serial::raw_serial()
00045 : rp::hal::serial_rxtx()
00046 , _baudrate(0)
00047 , _flags(0)
00048 , serial_fd(-1)
00049 {
00050 _init();
00051 }
00052
00053 raw_serial::~raw_serial()
00054 {
00055 close();
00056
00057 }
00058
00059 bool raw_serial::open()
00060 {
00061 return open(_portName, _baudrate, _flags);
00062 }
00063
00064 bool raw_serial::bind(const char * portname, uint32_t baudrate, uint32_t flags)
00065 {
00066 strncpy(_portName, portname, sizeof(_portName));
00067 _baudrate = baudrate;
00068 _flags = flags;
00069 return true;
00070 }
00071
00072 bool raw_serial::open(const char * portname, uint32_t baudrate, uint32_t flags)
00073 {
00074 if (isOpened()) close();
00075
00076 serial_fd = ::open(portname, O_RDWR | O_NOCTTY | O_NDELAY);
00077
00078 if (serial_fd == -1) return false;
00079
00080 struct termios options, oldopt;
00081 tcgetattr(serial_fd, &oldopt);
00082 bzero(&options,sizeof(struct termios));
00083
00084 _u32 termbaud = getTermBaudBitmap(baudrate);
00085
00086 if (termbaud == (_u32)-1) {
00087 close();
00088 return false;
00089 }
00090 cfsetispeed(&options, termbaud);
00091 cfsetospeed(&options, termbaud);
00092
00093
00094 options.c_cflag |= (CLOCAL | CREAD);
00095
00096
00097 options.c_cflag &= ~PARENB;
00098 options.c_cflag &= ~CSTOPB;
00099
00100 options.c_cflag &= ~CSIZE;
00101 options.c_cflag |= CS8;
00102
00103 #ifdef CNEW_RTSCTS
00104 options.c_cflag &= ~CNEW_RTSCTS;
00105 #endif
00106
00107 options.c_iflag &= ~(IXON | IXOFF | IXANY);
00108
00109
00110 options.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);
00111
00112 options.c_oflag &= ~OPOST;
00113
00114 tcflush(serial_fd,TCIFLUSH);
00115
00116 if (fcntl(serial_fd, F_SETFL, FNDELAY))
00117 {
00118 close();
00119 return false;
00120 }
00121 if (tcsetattr(serial_fd, TCSANOW, &options))
00122 {
00123 close();
00124 return false;
00125 }
00126
00127
00128 uint32_t controll = TIOCM_DTR;
00129
00130 ioctl(serial_fd, TIOCMBIC, &controll);
00131
00132 _is_serial_opened = true;
00133 return true;
00134 }
00135
00136 void raw_serial::close()
00137 {
00138 if (serial_fd != -1)
00139 ::close(serial_fd);
00140 serial_fd = -1;
00141
00142 _is_serial_opened = false;
00143 }
00144
00145 int raw_serial::senddata(const unsigned char * data, size_t size)
00146 {
00147
00148 if (!isOpened()) return 0;
00149
00150 if (data == NULL || size ==0) return 0;
00151
00152 size_t tx_len = 0;
00153 required_tx_cnt = 0;
00154 do {
00155 int ans = ::write(serial_fd, data + tx_len, size-tx_len);
00156
00157 if (ans == -1) return tx_len;
00158
00159 tx_len += ans;
00160 required_tx_cnt = tx_len;
00161 }while (tx_len<size);
00162
00163
00164 return tx_len;
00165 }
00166
00167
00168 int raw_serial::recvdata(unsigned char * data, size_t size)
00169 {
00170 if (!isOpened()) return 0;
00171
00172 int ans = ::read(serial_fd, data, size);
00173
00174 if (ans == -1) ans=0;
00175 required_rx_cnt = ans;
00176 return ans;
00177 }
00178
00179
00180 void raw_serial::flush( _u32 flags)
00181 {
00182 tcflush(serial_fd,TCIFLUSH);
00183 }
00184
00185 int raw_serial::waitforsent(_u32 timeout, size_t * returned_size)
00186 {
00187 if (returned_size) *returned_size = required_tx_cnt;
00188 return 0;
00189 }
00190
00191 int raw_serial::waitforrecv(_u32 timeout, size_t * returned_size)
00192 {
00193 if (!isOpened() ) return -1;
00194
00195 if (returned_size) *returned_size = required_rx_cnt;
00196 return 0;
00197 }
00198
00199 int raw_serial::waitfordata(size_t data_count, _u32 timeout, size_t * returned_size)
00200 {
00201 size_t length = 0;
00202 if (returned_size==NULL) returned_size=(size_t *)&length;
00203 *returned_size = 0;
00204
00205 int max_fd;
00206 fd_set input_set;
00207 struct timeval timeout_val;
00208
00209
00210 FD_ZERO(&input_set);
00211 FD_SET(serial_fd, &input_set);
00212 max_fd = serial_fd + 1;
00213
00214
00215 timeout_val.tv_sec = timeout / 1000;
00216 timeout_val.tv_usec = (timeout % 1000) * 1000;
00217
00218 if ( isOpened() )
00219 {
00220 if ( ioctl(serial_fd, FIONREAD, returned_size) == -1) return ANS_DEV_ERR;
00221 if (*returned_size >= data_count)
00222 {
00223 return 0;
00224 }
00225 }
00226
00227 while ( isOpened() )
00228 {
00229
00230 int n = ::select(max_fd, &input_set, NULL, NULL, &timeout_val);
00231
00232 if (n < 0)
00233 {
00234
00235 return ANS_DEV_ERR;
00236 }
00237 else if (n == 0)
00238 {
00239
00240 return ANS_TIMEOUT;
00241 }
00242 else
00243 {
00244
00245 assert (FD_ISSET(serial_fd, &input_set));
00246
00247
00248 if ( ioctl(serial_fd, FIONREAD, returned_size) == -1) return ANS_DEV_ERR;
00249 if (*returned_size >= data_count)
00250 {
00251 return 0;
00252 }
00253 else
00254 {
00255 int remain_timeout = timeout_val.tv_sec*1000000 + timeout_val.tv_usec;
00256 int expect_remain_time = (data_count - *returned_size)*1000000*8/_baudrate;
00257 if (remain_timeout > expect_remain_time)
00258 usleep(expect_remain_time);
00259 }
00260 }
00261
00262 }
00263
00264 return ANS_DEV_ERR;
00265 }
00266
00267 size_t raw_serial::rxqueue_count()
00268 {
00269 if ( !isOpened() ) return 0;
00270 size_t remaining;
00271
00272 if (::ioctl(serial_fd, FIONREAD, &remaining) == -1) return 0;
00273 return remaining;
00274 }
00275
00276 void raw_serial::setDTR()
00277 {
00278 if(!isOpened()) return;
00279 uint32_t status;
00280 ioctl(serial_fd, TIOCMGET, &status);
00281 status |= TIOCM_DTR;
00282 ioctl(serial_fd, TIOCMSET, &status);
00283 }
00284
00285 void raw_serial::clearDTR()
00286 {
00287 if(!isOpened()) return;
00288
00289 uint32_t status;
00290 ioctl(serial_fd, TIOCMGET, &status);
00291 status &= ~TIOCM_DTR;
00292 ioctl(serial_fd, TIOCMSET, &status);
00293 }
00294
00295 void raw_serial::_init()
00296 {
00297 serial_fd = 0;
00298 _portName[0] = 0;
00299 required_tx_cnt = required_rx_cnt = 0;
00300 }
00301
00302
00303
00304 _u32 raw_serial::getTermBaudBitmap(_u32 baud)
00305 {
00306 #define BAUD_CONV( _baud_) case _baud_: return B##_baud_
00307 switch (baud) {
00308 BAUD_CONV(1200);
00309 BAUD_CONV(1800);
00310 BAUD_CONV(2400);
00311 BAUD_CONV(4800);
00312 BAUD_CONV(9600);
00313 BAUD_CONV(19200);
00314 BAUD_CONV(38400);
00315 BAUD_CONV(57600);
00316 BAUD_CONV(115200);
00317 BAUD_CONV(230400);
00318 BAUD_CONV(460800);
00319 BAUD_CONV(500000);
00320 BAUD_CONV(576000);
00321 BAUD_CONV(921600);
00322 BAUD_CONV(1000000);
00323 BAUD_CONV(1152000);
00324 BAUD_CONV(1500000);
00325 BAUD_CONV(2000000);
00326 BAUD_CONV(2500000);
00327 BAUD_CONV(3000000);
00328 BAUD_CONV(3500000);
00329 BAUD_CONV(4000000);
00330 }
00331 return -1;
00332 }
00333
00334 }}}
00335
00336
00337 namespace rp{ namespace hal{
00338
00339 serial_rxtx * serial_rxtx::CreateRxTx()
00340 {
00341 return new rp::arch::net::raw_serial();
00342 }
00343
00344 void serial_rxtx::ReleaseRxTx(serial_rxtx *rxtx)
00345 {
00346 delete rxtx;
00347 }
00348
00349 }}