00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00028
00029
00030
00031
00032 #include "icl_comm_serial/Serial.h"
00033
00034 #include <cassert>
00035 #include <algorithm>
00036
00037 #include <icl_core/os_lxrt.h>
00038
00039 #ifdef _SYSTEM_LXRT_
00040 # include <sys/mman.h>
00041 # include <rtai_serial.h>
00042 #endif
00043
00044 #ifdef _SYSTEM_LINUX_
00045 # include <stdio.h>
00046 # include <fcntl.h>
00047 # include <sys/time.h>
00048 # include <errno.h>
00049 # include <string.h>
00050 #endif
00051
00052 #include "icl_core/TimeStamp.h"
00053 #include "icl_core/TimeSpan.h"
00054
00055
00056 #ifdef _SYSTEM_WIN32_
00057 #include <math.h>
00058 #include <stdio.h>
00059 #endif
00060
00061 #undef SERIAL_DUMP_DATA
00062
00063
00064
00065 #if defined(_SYSTEM_LXRT_33_) || defined(_SYSTEM_LXRT_35_)
00066 # define rt_spset_mcr(tty, mask, setbits) rt_spset_msr(tty, mask, setbits)
00067 #endif
00068
00069 namespace icl_comm {
00070 namespace serial {
00071
00072 Serial::Serial(const char *dev_name, const SerialFlags& flags)
00073 :m_dev_name(strdup(dev_name)),
00074 m_serial_flags(flags)
00075 {
00076 #ifdef _SYSTEM_WIN32_
00077 m_com=INVALID_HANDLE_VALUE;
00078 #else
00079 file_descr=-1;
00080 is_lxrt_serial = false;
00081 #endif
00082
00083 Open();
00084 }
00085
00086 Serial::Serial(const char *dev_name, SerialFlags::BaudRate baud_rate, const SerialFlags& flags)
00087 :m_dev_name(strdup(dev_name)),
00088 m_serial_flags(flags)
00089 {
00090 #ifdef _SYSTEM_WIN32_
00091 m_com=INVALID_HANDLE_VALUE;
00092 #else
00093 file_descr=-1;
00094 is_lxrt_serial = false;
00095 #endif
00096
00097 m_serial_flags.setBaudRate(baud_rate);
00098 Open();
00099 }
00100
00101 bool Serial::Open()
00102 {
00103 Close();
00104
00105 #if defined _SYSTEM_LINUX_
00106 #ifdef _SYSTEM_LXRT_
00107 if (icl_core::os::IsThisLxrtTask() && IsLXRTDeviceName(m_dev_name))
00108 {
00109 is_lxrt_serial = true;
00110 int baud= m_serial_flags.getBaudRate();
00111 int numbits;
00112 switch (m_serial_flags.DataBits())
00113 {
00114 case SerialFlags::eDB_5:
00115 numbits = 5;
00116 break;
00117 case SerialFlags::eDB_6:
00118 numbits = 6;
00119 break;
00120 case SerialFlags::eDB_7:
00121 numbits = 7;
00122 break;
00123 case SerialFlags::eDB_8:
00124 numbits = 8;
00125 break;
00126 default:
00127 numbits = 8;
00128 }
00129
00130 int stopbits;
00131 if (m_serial_flags.StopBits())
00132 stopbits = 2;
00133 else
00134 stopbits = 1;
00135
00136 int parity=0;
00137 switch (m_serial_flags.Parity())
00138 {
00139 case SerialFlags::eP_EVEN:
00140 {
00141 parity = RT_SP_PARITY_EVEN;
00142 break;
00143 }
00144 case SerialFlags::eP_ODD:
00145 {
00146 parity = RT_SP_PARITY_ODD;
00147 break;
00148 }
00149 case SerialFlags::eP_NONE:
00150 case SerialFlags::eP_MARK:
00151 case SerialFlags::eP_SPACE:
00152 {
00153 parity = RT_SP_PARITY_NONE;
00154 break;
00155 }
00156 }
00157
00158 int mode=0;
00159 switch (m_serial_flags.FlowControl())
00160 {
00161 case SerialFlags::eFC_FLOW:
00162 {
00163 mode = RT_SP_HW_FLOW;
00164 break;
00165 }
00166 case SerialFlags::eFC_HAND_SHAKE:
00167 {
00168 mode = RT_SP_NO_HAND_SHAKE;
00169 break;
00170 }
00171 }
00172
00173 int fifotrig = RT_SP_FIFO_SIZE_DEFAULT;
00174
00175 LOGGING_INFO_C(SERIAL, Serial, "Using LXRT extension for accessing serial device " << tty << " (" << m_dev_name << "): " <<
00176 baud << " " << numbits << " " << stopbits << " " << parity << " " << mode << " " << fifotrig << endl);
00177
00178 if ((m_status = rt_spopen(tty, baud, numbits, stopbits, parity, mode, fifotrig)) < 0)
00179 {
00180 LOGGING_DEBUG_C(SERIAL, Serial, "Cannot open lxrt serial device '" << tty << " (" << m_dev_name << ")'. Status (" << m_status << ":" << strerror(-m_status) << ")" << endl);
00181
00182 return false;
00183 }
00184 else
00185 {
00186 file_descr = tty;
00187 m_status = 0;
00188
00189 if (m_serial_flags.getModemControlFlags()!=SerialFlags::eMCF_UNDEFINED)
00190 {
00191 LOGGING_DEBUG_C(SERIAL, Serial, "Serial(" << m_dev_name << ") setting hardware modem control flags to 0x" << m_serial_flags.getModemControlFlags() << endl);
00192
00193
00194 int mask = 0;
00195
00196 if (m_serial_flags.getModemControlFlags() & SerialFlags::eMCF_RTS)
00197 mask |= RT_SP_RTS;
00198 if (m_serial_flags.getModemControlFlags() & SerialFlags::eMCF_DTR)
00199 mask |= RT_SP_DTR;
00200
00201 int ret = rt_spset_mcr(tty, mask, 1);
00202
00203
00204
00205
00206 mask = 0;
00207 if (~(m_serial_flags.getModemControlFlags() & SerialFlags::eMCF_RTS))
00208 mask |= RT_SP_RTS;
00209 if (~(m_serial_flags.getModemControlFlags() & SerialFlags::eMCF_DTR))
00210 mask |= RT_SP_DTR;
00211
00212 ret = rt_spset_mcr(tty, mask, 0);
00213
00214 }
00215 }
00216 }
00217 else
00218 #endif
00219
00220
00221 {
00222
00223 termios io_set_new;
00224
00225
00226 if ((file_descr = open(m_dev_name, O_RDWR | O_NONBLOCK)) < 0)
00227 {
00228 m_status = -errno;
00229 LOGGING_DEBUG_C(SERIAL, Serial, "Cannot open serial device '" << m_dev_name << "'. Status (" << m_status << ":" << strerror(-m_status) << endl);
00230
00231 return false;
00232 }
00233 else
00234 m_status = 0;
00235
00236
00237 if (tcgetattr(file_descr, &io_set_old) < 0)
00238 {
00239 m_status = -errno;
00240 LOGGING_DEBUG_C(SERIAL, Serial, "Cannot get serial device m_status '" << m_dev_name << "'. Status (" << m_status << ":" << strerror(-m_status) << endl);
00241
00242 return false;
00243 }
00244 else
00245 m_status = 0;
00246
00247
00248 io_set_new = io_set_old;
00249
00250
00251 io_set_new.c_cflag = m_serial_flags.CFlags();
00252 io_set_new.c_oflag = 0;
00253 io_set_new.c_iflag = IGNPAR;
00254 io_set_new.c_lflag = 0;
00255 io_set_new.c_cc[VMIN] = 1;
00256 io_set_new.c_cc[VTIME] = 0;
00257
00258
00259 if (tcsetattr(file_descr, TCSANOW, &io_set_new) < 0)
00260 {
00261 m_status = -errno;
00262 LOGGING_DEBUG_C(SERIAL, Serial, "Serial(" << m_dev_name << ") Error>> tcsetattr failed. Status (" << m_status << ":" << strerror(-m_status) << endl);
00263
00264 return false;
00265 }
00266 else
00267 m_status = 0;
00268
00269 if (m_serial_flags.getModemControlFlags()!=SerialFlags::eMCF_UNDEFINED)
00270 {
00271 LOGGING_DEBUG_C(SERIAL, Serial, "Serial(" << m_dev_name << ") setting hardware modem control flags to 0x" << m_serial_flags.getModemControlFlags() << endl);
00272
00273 int modem_control_flags=0;
00274 if (m_serial_flags.getModemControlFlags() & SerialFlags::eMCF_DTR)
00275 {
00276 modem_control_flags |= TIOCM_DTR;
00277 }
00278 if (m_serial_flags.getModemControlFlags() & SerialFlags::eMCF_RTS)
00279 {
00280 modem_control_flags |= TIOCM_RTS;
00281 }
00282
00283 ioctl(file_descr, TIOCMSET, modem_control_flags);
00284 }
00285 }
00286
00287 #elif defined _SYSTEM_WIN32_
00288
00289 m_read_buffer_fill = 0;
00290 m_status = 0;
00291
00292
00293 m_com = CreateFile(m_dev_name, GENERIC_READ | GENERIC_WRITE, 0, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
00294 if (m_com == INVALID_HANDLE_VALUE)
00295 {
00296 m_status = GetLastError();
00297 LOGGING_WARNING_C(SERIAL, Serial, "Serial(" << m_dev_name << "): ERROR>> open port failed (" << StatusText().c_str() << ")." << endl);
00298
00299 }
00300
00301
00302 if (m_status == 0)
00303 {
00304 if (!SetupComm(m_com, 0x4000, 0x4000))
00305 {
00306 m_status = GetLastError();
00307 LOGGING_WARNING_C(SERIAL, Serial, "Serial(" << m_dev_name << "): ERROR>> SetupComm failed (" << StatusText().c_str() << ")." << endl);
00308
00309 }
00310 }
00311
00312
00313 DCB dcb;
00314 memset(&dcb, 0, sizeof(DCB));
00315 if (m_status == 0)
00316 {
00317 if (!GetCommState(m_com, &dcb))
00318 {
00319 m_status = GetLastError();
00320 LOGGING_WARNING_C(SERIAL, Serial, "Serial(" << m_dev_name << "): ERROR>> GetCommState failed (" << StatusText().c_str() << ")." << endl);
00321
00322 }
00323 }
00324
00325
00326 if (m_status == 0)
00327 {
00328 m_serial_flags.GetDCB(&dcb);
00329 if (!SetCommState(m_com, &dcb))
00330 {
00331 m_status = GetLastError();
00332 LOGGING_WARNING_C(SERIAL, Serial, "Serial(" << m_dev_name << "): ERROR>> SetCommState failed (" << StatusText().c_str() << ")." << endl);
00333
00334 return false;
00335 }
00336 }
00337 #endif
00338
00339 return m_status==0;
00340 }
00341
00342 void Serial::DumpData(void *data, size_t length)
00343 {
00344 unsigned char *c_data = static_cast<unsigned char *>(data);
00345 printf("Serial::DumpData: ");
00346 for (size_t i = 0; i < length; ++i)
00347 {
00348 printf("%02X ", int(c_data[i]));
00349 }
00350 printf("\n");
00351 }
00352
00353 int Serial::ChangeBaudrate(SerialFlags::BaudRate speed)
00354 {
00355
00356 if (m_serial_flags.getBaudRate()==speed)
00357 {
00358
00359 return 0;
00360 }
00361 m_serial_flags.setBaudRate(speed);
00362
00363 #if defined _SYSTEM_LINUX_
00364
00365 # ifdef _SYSTEM_LXRT_
00366 if (is_lxrt_serial)
00367 {
00368 if (icl_core::os::IsThisLxrtTask())
00369 {
00370
00371 Close();
00372 Open();
00373 }
00374 else
00375 {
00376 LOGGING_DEBUG_CO(SERIAL, Serial, ChangeBaudrate, "Serial Error>> could not change baudrate of a lxrt serial in non lxrt thread." << endl);
00377 }
00378 }
00379 else
00380 # endif
00381 {
00382 if (file_descr < 0)
00383 return m_status;
00384
00385 struct termios io_set;
00386
00387
00388 if (tcgetattr(file_descr, &io_set) < 0)
00389 {
00390 m_status = -errno;
00391 LOGGING_DEBUG_C(SERIAL, Serial, "Serial(" << m_dev_name << "): Error>> tcgetattr failed. Status (" << m_status << ":" << strerror(-m_status) << endl);
00392
00393 }
00394 else
00395 {
00396
00397 io_set.c_cflag &= ~CBAUD;
00398
00399 io_set.c_cflag |= SerialFlags::CFlags(speed);
00400
00401
00402 if (tcsetattr(file_descr, TCSANOW, &io_set) < 0)
00403 {
00404 m_status = -errno;
00405 LOGGING_DEBUG_C(SERIAL, Serial, "Serial(" << m_dev_name << "): Error>> tcsetattr failed. Status (" << m_status << ":" << strerror(-m_status) << endl);
00406
00407 }
00408 else
00409 {
00410 LOGGING_INFO_C(SERIAL, Serial, "Serial:ChangeBaudrate " << speed << " successful." << endl);
00411
00412 m_status = 0;
00413 }
00414 }
00415 }
00416
00417 return m_status;
00418 #endif
00419
00420 #ifdef _SYSTEM_DARWIN_
00421 LOGGING_WARNING_C(SERIAL, Serial, "Serial:changeBaudrate() >> to be implemented" << endl);
00422
00423 return -1;
00424 #endif
00425
00426 #ifdef _SYSTEM_WIN32_
00427 m_status = 0;
00428
00429
00430 if (!PurgeComm(m_com, PURGE_RXCLEAR)
00431 || !PurgeComm(m_com, PURGE_TXCLEAR))
00432 {
00433 m_status = GetLastError();
00434 LOGGING_WARNING_C(SERIAL, Serial, "Serial(" << m_dev_name << "): ERROR>> PurgeComm failed (" << StatusText().c_str() << ")." << endl);
00435
00436 }
00437
00438
00439 DCB dcb;
00440 memset(&dcb, 0, sizeof(DCB));
00441 if (m_status == 0)
00442 {
00443 if (!GetCommState(m_com, &dcb))
00444 {
00445 m_status = GetLastError();
00446 LOGGING_WARNING_C(SERIAL, Serial, "Serial(" << m_dev_name << "): ERROR>> GetCommState failed (" << StatusText().c_str() << ")." << endl);
00447
00448 }
00449 }
00450
00451
00452 if (m_status == 0)
00453 {
00454 m_serial_flags.GetDCB(&dcb);
00455 if (!SetCommState(m_com, &dcb))
00456 {
00457 m_status = GetLastError();
00458 LOGGING_WARNING_C(SERIAL, Serial, "Serial(" << m_dev_name << "): ERROR>> SetCommState failed (" << StatusText().c_str() << ")." << endl);
00459
00460 }
00461 }
00462
00463 return -m_status;
00464 #endif
00465 }
00466
00467 int Serial::ClearReceiveBuffer()
00468 {
00469 #ifdef _SYSTEM_WIN32_
00470 m_status = 0;
00471
00472
00473 if (PurgeComm(m_com, PURGE_RXCLEAR))
00474 {
00475 m_read_buffer_fill = 0;
00476 }
00477 else
00478 {
00479 m_status = GetLastError();
00480 LOGGING_WARNING_C(SERIAL, Serial, "Serial(" << m_dev_name << "): ERROR>> PurgeComm failed (" << StatusText().c_str() << ")." << endl);
00481
00482 }
00483
00484 return m_status;
00485 #elif defined _SYSTEM_LINUX_
00486
00487 # ifdef _SYSTEM_LXRT_
00488 return -1;
00489 #endif
00490 if (tcflush(file_descr, TCIFLUSH) != 0)
00491 {
00492 LOGGING_WARNING_C(SERIAL, Serial, "tcflush failed :(" << endl);
00493 return -1;
00494 }
00495 #else
00496 return -1;
00497 #endif
00498 return 0;
00499 }
00500
00501 int Serial::ClearSendBuffer()
00502 {
00503 #ifdef _SYSTEM_WIN32_
00504 m_status = 0;
00505
00506
00507 if (PurgeComm(m_com, PURGE_TXCLEAR))
00508 {
00509 m_read_buffer_fill = 0;
00510 }
00511 else
00512 {
00513 m_status = GetLastError();
00514 LOGGING_WARNING_C(SERIAL, Serial, "Serial(" << m_dev_name << "): ERROR>> PurgeComm failed (" << StatusText().c_str() << ")." << endl);
00515
00516 }
00517
00518 return m_status;
00519 #elif defined _SYSTEM_LINUX_
00520
00521 # ifdef _SYSTEM_LXRT_
00522 return -1;
00523 #endif
00524 if (tcflush(file_descr, TCOFLUSH) != 0)
00525 {
00526 LOGGING_WARNING_C(SERIAL, Serial, "tcflush failed :(" << endl);
00527 return -1;
00528 }
00529 #else
00530 return -1;
00531 #endif
00532 return 0;
00533 }
00534
00535 ssize_t Serial::Write(const void *data, ssize_t size)
00536 {
00537 #if defined _SYSTEM_LINUX_
00538 if (file_descr < 0)
00539 return m_status;
00540
00541 int bytes_out = 0;
00542
00543 # ifdef _SYSTEM_LXRT_
00544 if (is_lxrt_serial)
00545 {
00546 if (icl_core::os::IsThisLxrtTask())
00547 {
00548 int bytes_to_send=size;
00549 int bytes_sent=0;
00550 while (bytes_to_send>0)
00551 {
00552 int bytes_not_sent=rt_spwrite(tty, ((char*)data)+bytes_sent, bytes_to_send);
00553 if (bytes_not_sent < 0)
00554 {
00555 m_status = bytes_not_sent;
00556 LOGGING_DEBUG_C(SERIAL, Serial, "Serial(" << m_dev_name << ":" << tty << "): Error on lxrt-writing. Status (" << m_status << ":" << strerror(-m_status) << ")." << endl);
00557
00558
00559
00560 bytes_to_send = 0;
00561 }
00562 else
00563 {
00564 m_status = 0;
00565 bytes_sent += bytes_to_send - bytes_not_sent;
00566
00567
00568 bytes_to_send = bytes_not_sent;
00569 }
00570 }
00571 }
00572 else
00573 {
00574 LOGGING_DEBUG_C(SERIAL, Serial, "Serial(" << m_dev_name << ":" << tty << "): Error>> could not write to a lxrt serial in non lxrt thread." << endl);
00575
00576 }
00577 }
00578 else
00579 # endif
00580 {
00581
00582 if ((bytes_out = write(file_descr, (char*)data, size)) < 0)
00583 {
00584 m_status = -errno;
00585 LOGGING_DEBUG_C(SERIAL, Serial, "Serial(" << m_dev_name << ":" << m_dev_name << "): Error on writing. Status (" << m_status << ":" << strerror(-m_status) << ")." << endl);
00586
00587 }
00588 else
00589 {
00590 m_status = 0;
00591 }
00592 }
00593
00594 return bytes_out;
00595
00596 #elif defined _SYSTEM_WIN32_
00597
00598 assert(m_com != INVALID_HANDLE_VALUE);
00599
00600 DWORD bytes_written;
00601 if (!WriteFile(m_com, data, size, &bytes_written, NULL))
00602 {
00603 m_status = GetLastError();
00604 LOGGING_WARNING_C(SERIAL, Serial, "Serial(" << m_dev_name << "): ERROR>> could not write data (" << StatusText().c_str() << ")." << endl);
00605
00606 }
00607 else
00608 {
00609 m_status = 0;
00610 #ifdef SERIAL_DUMP_DATA
00611 DumpData(data, bytes_written);
00612 #endif
00613 }
00614
00615 return (m_status == 0 ? bytes_written : -m_status);
00616 #else
00617 return -1;
00618 #endif
00619 }
00620
00621 ssize_t Serial::Read(void *data, ssize_t size, unsigned long time, bool return_on_less_data)
00622 {
00623
00624 icl_core::TimeStamp end_time = icl_core::TimeStamp::futureMSec(time / 1000);
00625
00626 #if defined _SYSTEM_LINUX_
00627 if (file_descr < 0)
00628 return m_status;
00629
00630 icl_core::TimeSpan tz;
00631 fd_set fds;
00632 int bytes_read = 0;
00633 int bytes_read_inc;
00634 int select_return;
00635 char *buffer = (char*)data;
00636
00637 if (time <= 0) time = 1;
00638
00639
00640 m_status = 0;
00641 # ifdef _SYSTEM_LXRT_
00642 if (is_lxrt_serial)
00643 {
00644 if (icl_core::os::IsThisLxrtTask())
00645 {
00646 int msg_size = size;
00647 RTIME timeout_relative = time;
00648 timeout_relative = nano2count(timeout_relative * 1000);
00649 int read_return;
00650
00651 if ((read_return = rt_spread_timed(tty, (char*)data, msg_size, timeout_relative)) != 0)
00652 {
00653
00654 if (return_on_less_data)
00655 {
00656 read_return = rt_spread(tty, (char*)data, msg_size);
00657
00658 if (read_return == 0)
00659 {
00660 LOGGING_ERROR_CO(SERIAL, Serial, Read, "Serial(" << m_dev_name << ")::Read(" << size << ": rt_spread_timed should have returned with data." << endl);
00661
00662 }
00663
00664 if (read_return < 0)
00665 {
00666 m_status = read_return;
00667 LOGGING_DEBUG_CO(SERIAL, Serial, Read, "Error on reading " << tty " (" << m_dev_name << "). Status (" << m_status << ":" << strerror(-m_status) << ")" << endl);
00668
00669
00670 icl_core::TimeSpan excess_read_time = icl_core::TimeStamp::now() - end_time;
00671 if (excess_read_time > icl_core::TimeSpan().fromMSec(1))
00672 {
00673 LOGGING_ERROR_CO(SERIAL, Serial, Read, "Serial(" << m_dev_name << ")::Read(" << size << "took too long (" << excess_read_time.toUSec() << "us)" << endl);
00674
00675 }
00676
00677 return m_status;
00678 }
00679 bytes_read = size - read_return;
00680
00681 }
00682 }
00683 else
00684 {
00685 bytes_read = msg_size;
00686
00687 }
00688
00689 icl_core::TimeSpan() excess_read_time = icl_core::TimeStamp::now() - end_time;
00690 if (excess_read_time > icl_core::TimeSpan().fromMSec(1))
00691 {
00692 LOGGING_ERROR_CO(SERIAL, Serial, Read, "Serial(" << m_dev_name << ")::Read(" << size << "took too long (" << excess_read_time.toUSec() << "us)" << endl);
00693
00694 }
00695 }
00696 else
00697 {
00698 LOGGING_DEBUG_CO(SERIAL, Serial, "Serial(" << m_dev_name << ":" << tty << "). Error>> could not read from a lxrt serial in non lxrt thread." << endl);
00699
00700 }
00701 }
00702 else
00703 # endif
00704 {
00705
00706 do
00707 {
00708 tz = end_time - icl_core::TimeStamp::now();
00709
00710 if (tz < icl_core::TimeSpan(0, 1000))
00711 {
00712 tz = icl_core::TimeSpan(0, 1000);
00713 }
00714
00715
00716
00717 FD_ZERO(&fds);
00718 FD_SET(file_descr, &fds);
00719
00720 if ((select_return = select(FD_SETSIZE, &fds, 0, 0, (timeval*) & tz)) > 0)
00721 {
00722
00723 if (return_on_less_data)
00724 {
00725 if ((bytes_read_inc = read(file_descr, &buffer[bytes_read], size - bytes_read)) < 0)
00726 {
00727 m_status = -errno;
00728 LOGGING_DEBUG_C(SERIAL, Serial, "Error on reading '" << m_dev_name << "'. Status (" << m_status << ":" << strerror(-m_status) << ")" << endl);
00729
00730 return m_status;
00731 }
00732
00733 if (bytes_read_inc > 0)
00734 {
00735 bytes_read += bytes_read_inc;
00736
00737 if (bytes_read == size)
00738 {
00739 return bytes_read;
00740 }
00741 }
00742 }
00743 else
00744 {
00745
00746
00747 if (ioctl(file_descr, FIONREAD, &bytes_read_inc) < 0)
00748 {
00749 m_status = -errno;
00750 LOGGING_DEBUG_C(SERIAL, Serial, "Error on ioctl FIONREAD '" << m_dev_name << "'. Status (" << m_status << ":" << strerror(-m_status) << ")" << endl);
00751
00752 return m_status;
00753 }
00754 else
00755 {
00756
00757 if (bytes_read_inc >= size)
00758 {
00759 if ((bytes_read = read(file_descr, buffer, size)) < 0)
00760 {
00761 m_status = -errno;
00762 LOGGING_DEBUG_C(SERIAL, Serial, "Error on read '" << m_dev_name << "'. Status (" << m_status << ":" << strerror(-m_status) << ")" << endl);
00763
00764 return m_status;
00765 }
00766 else
00767 {
00768
00769 return bytes_read;
00770 }
00771 }
00772
00773 }
00774 }
00775 }
00776 else if (select_return < 0)
00777 {
00778 m_status = -errno;
00779 LOGGING_DEBUG_C(SERIAL, Serial, "Error on select '" << m_dev_name << "'. Status (" << m_status << ":" << strerror(-m_status) << ")" << endl);
00780
00781 return m_status;
00782 }
00783 }
00784
00785 while (icl_core::TimeStamp::now() < end_time);
00786 }
00787
00788
00789 return bytes_read;
00790 #endif
00791
00792
00793 #ifdef _SYSTEM_DARWIN_
00794 LOGGING_WARNING_C(SERIAL, Serial, "Serial:Read() >> to be implemented!" << endl);
00795
00796 return 0;
00797 #endif
00798
00799 #ifdef _SYSTEM_WIN32_
00800 assert(m_com != INVALID_HANDLE_VALUE);
00801
00802 m_status = 0;
00803
00804
00805 COMMTIMEOUTS timeout;
00806 timeout.ReadIntervalTimeout = time / 1000;
00807 timeout.ReadTotalTimeoutMultiplier = 1;
00808 timeout.ReadTotalTimeoutConstant = time / 1000;
00809 timeout.WriteTotalTimeoutMultiplier = 1;
00810 timeout.WriteTotalTimeoutConstant = MAXDWORD;
00811 if (!SetCommTimeouts(m_com, &timeout))
00812 {
00813 m_status = GetLastError();
00814 LOGGING_WARNING_C(SERIAL, Serial, "Serial(" << m_dev_name << "): ERROR>> setting read timeout failed (" << StatusText().c_str() << ")" << endl);
00815
00816 }
00817
00818
00819 if (m_read_buffer_fill <= size
00820 && m_status == 0)
00821 {
00822 DWORD bytes_received = 0;
00823 size_t bytes_remaining = (m_read_buffer_fill < size ? size - m_read_buffer_fill : 0);
00824 icl_core::TimeStamp now;
00825 do
00826 {
00827 if (ReadFile(m_com, m_read_buffer + m_read_buffer_fill, bytes_remaining, &bytes_received, NULL))
00828 {
00829 m_read_buffer_fill += bytes_received;
00830 if (bytes_remaining > bytes_received)
00831 {
00832 bytes_remaining -= bytes_received;
00833 }
00834 else
00835 {
00836 bytes_remaining = 0;
00837 }
00838 }
00839 else
00840 {
00841 DWORD error = GetLastError();
00842 if (error != ERROR_TIMEOUT)
00843 {
00844 m_status = error;
00845 LOGGING_WARNING_C(SERIAL, Serial, "Serial(" << m_dev_name << "): ERROR>> error during read (" << StatusText().c_str() << ")" << endl);
00846
00847 }
00848 }
00849 now = icl_core::TimeStamp::now();
00850 }
00851 while (m_status == 0 && !return_on_less_data && bytes_remaining && now < end_time);
00852
00853 if (m_status == 0 && !return_on_less_data && bytes_remaining && now >= end_time)
00854 {
00855 m_status = ERROR_TIMEOUT;
00856 LOGGING_WARNING_C(SERIAL, Serial, "Serial(" << m_dev_name << "): ERROR>> error during read (" << StatusText().c_str() << ")" << endl);
00857
00858 }
00859 }
00860
00861
00862 ssize_t bytes_received;
00863 if (m_status == 0)
00864 {
00865 bytes_received = std::min(size, m_read_buffer_fill);
00866 memcpy(data, m_read_buffer, bytes_received);
00867
00868
00869 for (ssize_t write_index = 0, read_index = bytes_received; read_index < m_read_buffer_fill; ++write_index, ++read_index)
00870 {
00871 m_read_buffer[write_index] = m_read_buffer[read_index];
00872 }
00873 m_read_buffer_fill -= bytes_received;
00874
00875 #ifdef SERIAL_DUMP_DATA
00876 DumpData(data, bytes_received);
00877 #endif
00878 }
00879
00880 return (m_status == 0 ? bytes_received : -m_status);
00881 #endif
00882 }
00883
00884 std::string Serial::StatusText() const
00885 {
00886 #if defined _SYSTEM_LINUX_
00887 return strerror(-m_status);
00888 #elif defined _SYSTEM_WIN32_
00889 LPVOID msg_buff = NULL;
00890 DWORD res = FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
00891 NULL,
00892 m_status,
00893 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
00894 (LPTSTR) &msg_buff,
00895 0,
00896 NULL);
00897 std::string result;
00898 if (res)
00899 {
00900 result = (LPCTSTR)msg_buff;
00901 LocalFree(msg_buff);
00902 }
00903 else
00904 {
00905 result = "fatal internal error";
00906 }
00907 return result;
00908 #else
00909 return "Plattform not supported!";
00910 #endif
00911 }
00912
00913 bool Serial::IsOpen() const
00914 {
00915 #ifdef _SYSTEM_LINUX_
00916 return file_descr >= 0;
00917 #elif defined _SYSTEM_WIN32_
00918 return m_com != INVALID_HANDLE_VALUE;
00919 #else
00920 return false;
00921 #endif
00922 }
00923
00924 void Serial::Close()
00925 {
00926
00927 #ifdef _SYSTEM_LINUX_
00928 if (file_descr >= 0)
00929 {
00930 # ifdef _SYSTEM_LXRT_
00931 if (is_lxrt_serial)
00932 {
00933 if (icl_core::os::IsThisLxrtTask())
00934 {
00935
00936 if ((m_status = rt_spclose(tty)) < 0)
00937 {
00938 LOGGING_DEBUG_C(SERIAL, Serial, "Serial Error>> closing lxrt serial " << tty << " (" << m_dev_name << "). Status (" << m_status << ":" << strerror(-m_status) << ")" << endl);
00939
00940 }
00941 }
00942 else
00943 {
00944 LOGGING_DEBUG_C(SERIAL, Serial, "Serial Error>> could not close a lxrt serial in non lxrt thread." << endl);
00945
00946 }
00947 }
00948 else
00949 # endif
00950 {
00951
00952 if (tcsetattr(file_descr, TCSANOW, &io_set_old) < 0)
00953 {
00954 m_status = -errno;
00955 LOGGING_DEBUG_C(SERIAL, Serial, "Serial(" << m_dev_name << ") Error>> tcsetattr failed. Status (" << m_status << ":" << strerror(-m_status) << ")" << endl);
00956
00957 }
00958
00959 if (close(file_descr) < 0)
00960 {
00961 m_status = -errno;
00962 LOGGING_DEBUG_C(SERIAL, Serial, "Serial>> Error closing serial " << m_dev_name << ". Status (" << m_status << ":" << strerror(-m_status) << ")" << endl);
00963
00964 }
00965 }
00966
00967 file_descr=-1;
00968 is_lxrt_serial = false;
00969 }
00970 #endif
00971
00972 #ifdef _SYSTEM_WIN32_
00973 if (m_com != INVALID_HANDLE_VALUE)
00974 {
00975 CloseHandle(m_com);
00976 m_com=INVALID_HANDLE_VALUE;
00977 }
00978 #endif
00979 m_status=0;
00980
00981 }
00982
00983 Serial::~Serial()
00984 {
00985
00986
00987 Close();
00988
00989 m_dev_name = NULL;
00990
00991
00992 }
00993
00994
00995 #ifdef _SYSTEM_LXRT_
00996 bool Serial::IsLXRTDeviceName(const char* device_name)
00997 {
00998 char *check_pointer;
00999 tty = strtol(device_name, &check_pointer, 10);
01000 if (*check_pointer == 0)
01001 {
01002 LOGGING_DEBUG_C(SERIAL, Serial,"Serial::IsLXRTDeviceName(" << m_dev_name << ") Using LXRT-serial-device " << tty << endl);
01003
01004 return true;
01005 }
01006 else
01007 {
01008 LOGGING_DEBUG_C(SERIAL, Serial, "Serial::IsLXRTDeviceName(" << m_dev_name << ") Using LINUX-serial-device " << tty << " (non lxrt access)" endl);
01009
01010 return false;
01011 }
01012 }
01013 #endif
01014
01015 }
01016 }