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 #include "di_serial_io.h"
00027
00028 #include <unistd.h>
00029 #include <sys/ioctl.h>
00030 #include <time.h>
00031 #include <fcntl.h>
00032
00033 di_serial_io::di_serial_io()
00034 {
00035 m_comm_fd = -1;
00036 m_baudrate = B4800;
00037 m_old_tiocm = 0;
00038 m_timeout = 2;
00039 }
00040
00041 di_serial_io::~di_serial_io()
00042 {
00043 if(m_comm_fd != -1)
00044 disconnect();
00045 }
00046
00064 const u_int16_t di_serial_io::connect(const char *const dev_file, const u_int8_t device)
00065 {
00066 my_errno = 0;
00067
00068 m_comm_fd = open(dev_file, O_RDWR | O_NOCTTY | O_NDELAY);
00069 if (m_comm_fd == -1)
00070 {
00071 my_errno = errno;
00072 return my_errno;
00073 }
00074 else
00075 fcntl(m_comm_fd, F_SETFL, FNDELAY);
00076
00077 struct termios serial_opts;
00078
00079
00080 flush_receive();
00081 tcflush(m_comm_fd, TCOFLUSH);
00082
00083
00084 if(tcgetattr(m_comm_fd, &m_old_termios) == -1)
00085 {
00086 my_errno = errno;
00087 return my_errno;
00088 }
00089
00090 if(ioctl(m_comm_fd, TIOCMGET, &m_old_tiocm) == -1)
00091 {
00092 my_errno = errno;
00093 return my_errno;
00094 }
00095
00096
00097 if(tcgetattr(m_comm_fd, &serial_opts) == -1)
00098 {
00099 my_errno = errno;
00100 return my_errno;
00101 }
00102
00103
00104 serial_opts.c_cflag = 0;
00105 serial_opts.c_iflag = 0;
00106 serial_opts.c_lflag = 0;
00107 serial_opts.c_oflag = 0;
00108
00109
00110 if(cfsetispeed(&serial_opts, m_baudrate) == -1)
00111 {
00112 my_errno = errno;
00113 return my_errno;
00114 }
00115 if(cfsetospeed(&serial_opts, m_baudrate) == -1)
00116 {
00117 my_errno = errno;
00118 return my_errno;
00119 }
00120
00121
00122 serial_opts.c_cflag &= ~PARENB;
00123 serial_opts.c_iflag &= ~INPCK;
00124
00125
00126
00127
00128 if(tcsetattr(m_comm_fd, TCSANOW, &serial_opts) == -1)
00129 {
00130 my_errno = errno;
00131 return my_errno;
00132 }
00133
00134 serial_opts.c_cflag &= ~CSTOPB;
00135 serial_opts.c_cflag &= ~CSIZE;
00136 serial_opts.c_cflag |= CS8;
00137
00138
00139 if(tcsetattr(m_comm_fd, TCSANOW, &serial_opts) == -1)
00140 {
00141 my_errno = errno;
00142 return my_errno;
00143 }
00144
00145
00146 serial_opts.c_cflag &= ~CRTSCTS;
00147
00148
00149 if(tcsetattr(m_comm_fd, TCSANOW, &serial_opts) == -1)
00150 {
00151 my_errno = errno;
00152 return my_errno;
00153 }
00154
00155
00156 serial_opts.c_iflag &= ~(IXON | IXOFF | IXANY);
00157
00158
00159 if(tcsetattr(m_comm_fd, TCSANOW, &serial_opts) == -1)
00160 {
00161 my_errno = errno;
00162 return my_errno;
00163 }
00164
00165
00166 serial_opts.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);
00167 serial_opts.c_oflag &= ~OPOST;
00168
00169
00170 if(tcsetattr(m_comm_fd, TCSANOW, &serial_opts) == -1)
00171 {
00172 my_errno = errno;
00173 return my_errno;
00174 }
00175
00176
00177 serial_opts.c_cc[VMIN] = 0;
00178 serial_opts.c_cc[VTIME] = 10;
00179
00180
00181 if(tcsetattr(m_comm_fd, TCSANOW, &serial_opts) == -1)
00182 {
00183 my_errno = errno;
00184 return my_errno;
00185 }
00186
00187
00188 serial_opts.c_cflag |= HUPCL;
00189 serial_opts.c_cflag |= (CLOCAL | CREAD);
00190
00191
00192 if(tcsetattr(m_comm_fd, TCSANOW, &serial_opts) == -1)
00193 {
00194 my_errno = errno;
00195 return my_errno;
00196 }
00197
00198 int status = m_old_tiocm;
00199 switch(device)
00200 {
00201 default:
00202 status |= TIOCM_DTR;
00203 status |= TIOCM_RTS;
00204
00205 if(ioctl(m_comm_fd, TIOCMSET, &status) == -1)
00206 {
00207 my_errno = errno;
00208 return my_errno;
00209 }
00210
00211
00212 usleep(100000);
00213 }
00214
00215
00216 flush_receive();
00217 tcflush(m_comm_fd, TCOFLUSH);
00218
00219 return 0;
00220 }
00221
00232 const u_int16_t di_serial_io::disconnect()
00233 {
00234 my_errno = 0;
00235
00236 flush_receive();
00237 tcflush(m_comm_fd, TCOFLUSH);
00238
00239
00240 tcsetattr(m_comm_fd, TCSANOW, &m_old_termios);
00241
00242 ioctl(m_comm_fd, TIOCMSET, &m_old_tiocm);
00243
00244
00245 if(close(m_comm_fd) == -1)
00246 {
00247 my_errno = errno;
00248 return my_errno;
00249 }
00250 m_comm_fd = -1;
00251 return 0;
00252 }
00253
00258 const bool di_serial_io::is_comm_open()
00259 {
00260 if(m_comm_fd == -1)
00261 return false;
00262 else
00263 return true;
00264 }
00265
00285 const bool di_serial_io::di_read(u_int8_t *data,
00286 u_int16_t &amount,
00287 const u_int8_t packet_len)
00288 {
00289 my_errno = 0;
00290 int16_t available = 0;
00291 u_int8_t retries = 4;
00292 time_t time_start = time(NULL);
00293
00294 ioctl(m_comm_fd, FIONREAD, &available);
00295
00296 while((time(NULL) - time_start < m_timeout) &&
00297 (available < amount))
00298 {
00299 usleep(50);
00300 ioctl(m_comm_fd, FIONREAD, &available);
00301 }
00302
00303
00304 if(available == 0)
00305 {
00306 my_errno = ENODATA;
00307 return true;
00308 }
00309
00310 if(time(NULL) - time_start >= m_timeout && available < amount)
00311 {
00312
00313 if(read(m_comm_fd, data, available) == -1)
00314 {
00315 my_errno = errno;
00316 return true;
00317 }
00318
00319
00320 amount = available;
00321 my_errno = ETIMEDOUT;
00322 return true;
00323 }
00324
00325
00326 if(read(m_comm_fd, data, amount) == -1)
00327 {
00328 my_errno = errno;
00329 return true;
00330 }
00331
00332
00333 if(packet_len > 0)
00334 {
00335 time_start = time(NULL);
00336 while(retries-- > 0 && !di_valid(data, packet_len))
00337 {
00338
00339 if(!di_synchronize(data, amount, packet_len))
00340 {
00341 return true;
00342 }
00343 }
00344 }
00345
00346 return false;
00347 }
00348
00367 const bool di_serial_io::di_send(const u_int8_t *const data,
00368 u_int16_t &amount,
00369 const u_int8_t echo,
00370 const u_int8_t retry)
00371 {
00372 my_errno = 0;
00373 u_int8_t tries = retry;
00374 int write_return = 0;
00375
00376 while(tries-- > 0)
00377 {
00378
00379 tcflush(m_comm_fd, TCOFLUSH);
00380 if(echo > 0)
00381
00382 flush_receive();
00383
00384
00385 write_return = write(m_comm_fd, data, amount);
00386 if(write_return <= 0)
00387 {
00388 my_errno = errno;
00389 return true;
00390 }
00391
00392
00393 for(u_int16_t i = static_cast<u_int16_t>(write_return); i < amount; i++)
00394 {
00395 if(write(m_comm_fd, data + i, 1) <= 0)
00396 {
00397 my_errno = errno;
00398 return true;
00399 }
00400 }
00401
00402 if(echo > 0)
00403 {
00404
00405 my_errno = 0;
00406 if(!di_echo(data, echo))
00407 {
00408 my_errno = EBADRSVP;
00409
00410 usleep(500000);
00411 continue;
00412 }
00413 else if(my_errno != 0)
00414 {
00415 return true;
00416 }
00417 }
00418
00419 my_errno = 0;
00420 return false;
00421 }
00422
00423 return true;
00424 }
00425
00430 const int16_t di_serial_io::bytes_in_receive()
00431 {
00432 int bytes = 0;
00433
00434 ioctl(m_comm_fd, FIONREAD, &bytes);
00435 return bytes;
00436 }
00437
00442 void di_serial_io::flush_receive()
00443 {
00444 time_t time_start = time(NULL);
00445
00446 while(bytes_in_receive() > 0 && (time(NULL) - time_start < 2))
00447 {
00448
00449 tcflush(m_comm_fd, TCIFLUSH);
00450 usleep(50);
00451 }
00452
00453 return;
00454 }
00455
00466 const bool di_serial_io::di_valid(const u_int8_t *const data,
00467 const u_int8_t packet_len)
00468 {
00469
00470 if((data[0] & 0x1) != 0)
00471 return false;
00472
00473
00474 for(int i = 1; i < packet_len; i++)
00475 {
00476 if((data[i] & 0x1) != 1)
00477 return false;
00478 }
00479
00480 return true;
00481 }
00482
00495 const bool di_serial_io::di_synchronize(u_int8_t *data,
00496 const u_int8_t data_len,
00497 const u_int8_t packet_len)
00498 {
00499 u_int8_t i = 0, j = 0;
00500
00501
00502 for(i = 0; i < data_len && (data[i] & 0x1) != 0; i++);
00503
00504
00505 for(j = 0; i < data_len; j++, i++)
00506 data[j] = data[i];
00507
00508
00509 u_int16_t amount = packet_len - j;
00510 if(di_read(data + j, amount, 0))
00511 return true;
00512
00513 return false;
00514 }
00515
00527 const bool di_serial_io::di_echo(const u_int8_t *const expected,
00528 const u_int8_t amount)
00529 {
00530 u_int16_t bytes = amount;
00531 u_int8_t *buf = new u_int8_t[bytes];
00532
00533 if(di_read(buf, bytes, 0))
00534 {
00535 delete [] buf;
00536 return false;
00537 }
00538 for(unsigned int i = 1; i <= bytes; i++)
00539 {
00540
00541 if(expected[i] != buf[i-1])
00542 {
00543 delete [] buf;
00544 return false;
00545 }
00546 }
00547 delete [] buf;
00548 return true;
00549 }
00550