Main MRPT website > C++ reference for MRPT 1.5.6
serialinterface.cpp
Go to the documentation of this file.
1 /* +---------------------------------------------------------------------------+
2  | Mobile Robot Programming Toolkit (MRPT) |
3  | http://www.mrpt.org/ |
4  | |
5  | Copyright (c) 2005-2017, Individual contributors, see AUTHORS file |
6  | See: http://www.mrpt.org/Authors - All rights reserved. |
7  | Released under BSD License. See details in http://www.mrpt.org/License |
8  +---------------------------------------------------------------------------+ */
9 #include "serialinterface.h"
10 #include <xsens/xsportinfo.h>
11 #include <xsens/xscontrolline.h>
12 
13 #include <errno.h>
14 #ifndef _WIN32
15 # include <unistd.h> // close
16 # include <sys/ioctl.h> // ioctl
17 # include <fcntl.h> // open, O_RDWR
18 # include <string.h> // strcpy
19 # include <sys/param.h>
20 # include <sys/file.h>
21 # include <stdarg.h>
22 #else
23 # include <winbase.h>
24 # include <io.h>
25 #endif
26 
27 #ifndef _CRT_SECURE_NO_DEPRECATE
28 # define _CRT_SECURE_NO_DEPRECATE
29 # ifdef _WIN32
30 # pragma warning(disable:4996)
31 # endif
32 #endif
33 
34 //lint -emacro(534, FSEEK, FSEEK_R)
35 //lint -emacro({534}, FSEEK, FSEEK_R)
36 #ifdef _WIN32
37 # define FSEEK(x) _fseeki64(m_handle, x, SEEK_SET)
38 # define FSEEK_R(x) _fseeki64(m_handle, x, SEEK_END)
39 # define FTELL() _ftelli64(m_handle)
40 #else
41 # define FSEEK(x) fseeko(m_handle, x, SEEK_SET)
42 # define FSEEK_R(x) fseeko(m_handle, x, SEEK_END)
43 # define FTELL() ftello(m_handle)
44 #endif
45 
46 // maybe log to nothing at this level
47 #ifdef LOG_CMT1
48 # include "xslog.h"
49 # define XDA1LOG_OBSOLETE XSENSLOG
50 #else
51 # define XDA1LOG_OBSOLETE(...) (void)0
52 #endif
53 
54 //////////////////////////////////////////////////////////////////////////////////////////
55 ///////////////////////////////////////// SerialInterface /////////////////////////////////////////
56 //////////////////////////////////////////////////////////////////////////////////////////
57 
58 //! \brief Default constructor, initializes all members to their default values.
60 {
61  m_port = 0;
63  m_timeout = 0;
64  m_endTime = 0;
66  m_portname[0] = 0;
67 #ifdef _WIN32
68  m_handle = INVALID_HANDLE_VALUE;
69 #else
70  m_handle = -1;
71  memset(&m_commState, 0, sizeof(m_commState));
72 #endif
73 
74  rx_log = NULL;
75  tx_log = NULL;
76 }
77 
78 //! Destructor, de-initializes, frees memory allocated for buffers, etc.
80 {
81  try {
82  closeLive(); //lint !e534
83  } catch(...)
84  {}
85 }
86 
87 //! \brief Close the serial communication port.
89 {
90  return closeLive();
91 }
92 
93 //! \brief Close the serial communication port.
95 {
96 #ifdef LOG_RX_TX
97  if (rx_log != NULL)
98  fclose(rx_log);
99  if (tx_log != NULL)
100  fclose(tx_log);
101  rx_log = NULL;
102  tx_log = NULL;
103 #endif
104  if (!isOpen())
105  return m_lastResult = XRV_NOPORTOPEN;
106 
108 #ifdef _WIN32
109  if (::FlushFileBuffers(m_handle))
110  {
111  // read all data before closing the handle, a Flush is not enough for FTDI devices unfortunately
112  // we first need to set the COMM timeouts to instantly return when no more data is available
113  COMMTIMEOUTS cto;
114  if (::GetCommTimeouts(m_handle,&cto))
115  {
116  cto.ReadIntervalTimeout = MAXDWORD;
117  cto.ReadTotalTimeoutConstant = 0;
118  cto.ReadTotalTimeoutMultiplier = 0;
119  if (::SetCommTimeouts(m_handle,&cto))
120  {
121  char buffer[1024];
122  DWORD length;
123  do {
124  if (!::ReadFile(m_handle, buffer, 1024, &length, NULL))
125  break;
126  } while (length > 0);
127  }
128  else
130  }
131  else
133  }
134  if (!::CloseHandle(m_handle))
136  m_handle = INVALID_HANDLE_VALUE;
137 #else
138  flushData();
139  ::close(m_handle);
140  m_handle = -1;
141 #endif
142  m_endTime = 0;
143 
144  return m_lastResult;
145 }
146 
147 /*! \brief Manipulate the Serial control lines
148 
149  The function manipulates the serial control lines that are indicated by the
150  mask parameter. Note that only the DTR and RTS lines can be set by win32.
151  \param mask Indicates which lines are to be manipulated and which should be
152  left alone.
153  \param state Contains the new state of the control lines.
154  \returns XRV_OK if the function succeeded
155 */
157 {
158  //lint --e{655} bitwise operations are intended on these enums
159  if (!isOpen())
160  return (m_lastResult = XRV_NOPORTOPEN);
161 #ifdef _WIN32
162  BOOL rv = 0;
163  if (mask & XCL_DTR)
164  {
165  if (state & XCL_DTR)
166  rv = EscapeCommFunction(m_handle,SETDTR);
167  else
168  rv = EscapeCommFunction(m_handle,CLRDTR);
169  }
170 
171  if (mask & XCL_RTS)
172  {
173  if (state & XCL_RTS)
174  rv = EscapeCommFunction(m_handle,SETRTS);
175  else
176  rv = EscapeCommFunction(m_handle,CLRRTS);
177  }
178  if (rv)
179  return m_lastResult = XRV_OK;
180  else
181  return m_lastResult = XRV_ERROR;
182 #else
183  bool rv = true;
184  int32_t status;
185  if (mask & XCL_DTR)
186  {
187  if (ioctl(m_handle, TIOCMGET, &status) == -1)
188  {
189  if (state & XCL_DTR) status |= TIOCM_DTR;
190  else status &= ~TIOCM_DTR;
191  rv = (ioctl(m_handle, TIOCMSET, &status) == -1);
192  }
193  else
194  rv = false;
195  }
196  if (rv && (mask & XCL_RTS))
197  {
198  if (ioctl(m_handle, TIOCMGET, &status) == -1)
199  {
200  if (state & XCL_RTS) status |= TIOCM_RTS;
201  else status &= ~TIOCM_RTS;
202  rv = (ioctl(m_handle, TIOCMSET, &status) == -1);
203  }
204  else
205  rv = false;
206  }
207  if (rv)
208  return m_lastResult = XRV_OK;
209  else
210  return m_lastResult = XRV_ERROR;
211 #endif
212 }
213 
214 /*! \copydoc IoInterface::flushData
215  \note This function tries to send and receive any remaining data immediately
216  and does not return until the buffers are empty.
217 */
219 {
221 #ifdef _WIN32
222  // Remove any 'old' data in buffer
223  if (!PurgeComm(m_handle, PURGE_TXCLEAR | PURGE_RXCLEAR))
225 #else
226  tcflush(m_handle, TCIOFLUSH);
227 #endif
228  m_endTime = 0;
229  return m_lastResult;
230 }
231 
232 //! Return the baudrate that is currently being used by the port
234 {
235  if (isOpen())
236  return m_baudrate;
237  return XBR_Invalid;
238 }
239 //! Return the handle of the port
241 //! Retrieve the port number that was last successfully opened.
243 //! Retrieve the port name that was last successfully opened.
244 void SerialInterface::getPortName(XsString& portname) const { portname = m_portname; }
245 //! Return the error code of the last operation.
247 //! Return the current timeout value
249 //! Return whether the communication port is open or not.
250 bool SerialInterface::isOpen (void) const
251 {
252 #ifdef _WIN32
253  return m_handle != INVALID_HANDLE_VALUE;
254 #else
255  return m_handle >= 0;
256 #endif
257 }
258 
259 /*! \brief Open a communication channel to the given port info.
260  \details If the baudrate in \a portInfo is set to XBR_Invalid, the baud rate is automatically
261  detected if possible.
262  \param portInfo The details of the port that should be opened. Depending on the type of interface,
263  parts of this parameter may be ignored.
264  \param readBufSize The size of the read buffer in bytes (if appliccable to the device)
265  \param writeBufSize The size of the write buffer in bytes (if appliccable to the device)
266  \returns XRV_OK if the device was opened successfully
267 */
269  uint32_t readBufSize,
270  uint32_t writeBufSize)
271 {
272  m_endTime = 0;
273 
274  JLDEBUG(gJournal, "port " << portInfo.portName().toStdString() << " at " << portInfo.baudrate() << " baud");
275 
276  if (isOpen())
277  {
278  JLALERT(gJournal, "Port " << portInfo.portName().toStdString() << " is already open");
279  return (m_lastResult = XRV_ALREADYOPEN);
280  }
281  m_baudrate = portInfo.baudrate();
282 
283 #ifdef _WIN32
284  XsResultValue fail = XRV_OK;
285  char winPortName[256];
286 
287  // Open port
288  sprintf(winPortName, "\\\\.\\%s", portInfo.portName().c_str());
289  m_handle = CreateFileA(winPortName, GENERIC_READ | GENERIC_WRITE, 0, NULL,
290  OPEN_EXISTING, 0, NULL);
291  if (m_handle == INVALID_HANDLE_VALUE)
292  {
293  JLDEBUG(gJournal, "Port " << portInfo.portName().toStdString() << " cannot be opened");
295  }
296 
297  DCB commState; //!< Stored settings about the serial port
298 
299  commState.DCBlength = sizeof(DCB);
300 
301  //Get the current state & then change it
302  if (!GetCommState(m_handle, &commState)) // Get current state
303  fail = XRV_ERROR;
304 
305  commState.BaudRate = (int) portInfo.baudrate(); // Setup the baud rate
306  commState.Parity = NOPARITY; // Setup the Parity
307  commState.ByteSize = 8; // Setup the data bits
308  commState.StopBits = TWOSTOPBITS; // Setup the stop bits
309  commState.fDsrSensitivity = FALSE; // Setup the flow control
310  commState.fOutxCtsFlow = FALSE; // NoFlowControl:
311  commState.fOutxDsrFlow = FALSE;
312  commState.fOutX = FALSE;
313  commState.fInX = FALSE;
314  commState.fRtsControl = RTS_CONTROL_ENABLE;
315  if (!SetCommState(m_handle, (LPDCB)&commState)) // Set new state
316  {
317  // Bluetooth ports cannot always be opened with 2 stopbits
318  // Now try to open port with 1 stopbit.
319  commState.StopBits = ONESTOPBIT;
320  if (!SetCommState(m_handle, (LPDCB)&commState))
322  }
323  std::string tmp = portInfo.portName().toStdString();
324  m_port = atoi(&tmp.c_str()[3]);
325  sprintf(m_portname, "%s", tmp.c_str());
326 
327  if (setTimeout(20))
328  fail = m_lastResult;
329 
330  // Other initialization functions
331  if (!EscapeCommFunction(m_handle, SETDTR)) // Set DTR (Calibration sensors need DTR to startup, won't hurt otherwise
332  fail = XRV_ERROR;
333  if (!SetupComm(m_handle,readBufSize,writeBufSize)) // Set queue size
334  fail = XRV_ERROR;
335 
336  // Remove any 'old' data in buffer
337  //PurgeComm(m_handle, PURGE_TXCLEAR | PURGE_RXCLEAR);
338  if (!PurgeComm(m_handle, PURGE_TXABORT | PURGE_RXABORT | PURGE_TXCLEAR | PURGE_RXCLEAR))
339  fail = XRV_ERROR;
340 
341  if (fail != XRV_OK)
342  {
343  CloseHandle(m_handle); //lint !e534
344  m_handle = INVALID_HANDLE_VALUE;
345  return (m_lastResult = fail);
346  }
347 
348 #else // !_WIN32
349  (void)readBufSize;
350  (void)writeBufSize;
351  // Open port
352  std::string pn = portInfo.portName().toStdString();
353  m_handle = ::open(pn.c_str(), O_RDWR | O_NOCTTY);
354 
355  // O_RDWR: Read+Write
356  // O_NOCTTY: Raw input, no "controlling terminal"
357  // O_NDELAY: Don't care about DCD signal
358 
359  if (m_handle < 0) {
360  // Port not open
362  }
363 
364  // Check if the file is already opened by someome else (other thread/process)
365  if (flock(m_handle, LOCK_EX | LOCK_NB))
366  {
367  closeLive();
369  }
370 
371  /* Start configuring of port for non-canonical transfer mode */
372  // Get current options for the port
373  if (tcgetattr(m_handle, &m_commState) != 0)
374  return XRV_ERROR;
375 
376  // Set baudrate.
377  if (cfsetispeed(&m_commState, portInfo.baudrate()) != 0)
378  return XRV_ERROR;
379 
380  if (cfsetospeed(&m_commState, portInfo.baudrate()) != 0)
381  return XRV_ERROR;
382 
383  // Enable the receiver and set local mode
384  m_commState.c_cflag |= (CLOCAL | CREAD);
385  // Set character size to data bits and set no parity Mask the characte size bits
386  m_commState.c_cflag &= ~(CSIZE|PARENB);
387  m_commState.c_cflag |= CS8; // Select 8 data bits
388  m_commState.c_cflag |= CSTOPB; // send 2 stop bits
389  // Disable hardware flow control
390  m_commState.c_cflag &= ~CRTSCTS;
391  m_commState.c_lflag &= ~(ECHO|ECHONL|ICANON|ISIG|IEXTEN);
392  // Disable software flow control
393  m_commState.c_iflag &= ~(IGNBRK|BRKINT|PARMRK|ISTRIP|INLCR|IGNCR|ICRNL|IXON);
394  // Set Raw output
395  m_commState.c_oflag &= ~OPOST;
396  // Timeout 0.001 sec for first byte, read minimum of 0 bytes
397  m_commState.c_cc[VMIN] = 0;
398  m_commState.c_cc[VTIME] = (m_timeout+99)/100; // 1
399 
400  // Set the new options for the port
401  if (tcsetattr(m_handle,TCSANOW, &m_commState) != 0)
403 
404  termios checkCommState;
405  if (tcgetattr(m_handle, &checkCommState) != 0)
406  return XRV_ERROR;
407 
408  if ((m_commState.c_cflag != checkCommState.c_cflag) ||
409  (m_commState.c_iflag != checkCommState.c_iflag) ||
410  (m_commState.c_oflag != checkCommState.c_oflag) ||
411  (m_commState.c_cc[VMIN] != checkCommState.c_cc[VMIN]) ||
412  (m_commState.c_cc[VTIME] != checkCommState.c_cc[VTIME]))
413  {
414  JLDEBUG(gJournal, "commstates do not match, which is OK for USB connected MkIV devices");
415  }
416 
417  m_port = 1;
418  sprintf(m_portname, "%s", pn.c_str());
419 
420  tcflush(m_handle, TCIOFLUSH);
421 
422  // setting RTS and DTR; RTS for Xbus Master, DTR for calibration sensors
423  int cmbits;
424  if (ioctl(m_handle, TIOCMGET, &cmbits) < 0)
425  {
426  JLDEBUG(gJournal, "TIOCMGET failed, which is OK for USB connected MkIV devices");
427  }
428 
429  cmbits |= TIOCM_RTS|TIOCM_DTR;
430 
431  if (ioctl(m_handle, TIOCMSET, &cmbits) < 0)
432  {
433  JLDEBUG(gJournal, "TIOCMSET failed, which is OK for USB connected MkIV devices");
434  }
435 #endif // !_WIN32
436 
437  JLDEBUG(gJournal, "Port " << portInfo.portName().toStdString() << " opened");
438  return (m_lastResult = XRV_OK);
439 }
440 
441 /*! \brief Helper function for making filename of log file unique
442 */
443 bool doesFileExist(char* filename)
444 {
445  FILE* pf = fopen(filename, "r");
446  if (pf == NULL)
447  return false;
448  fclose (pf);
449  return true;
450 }
451 
452 /*! \brief Helper function for making filename of log file unique
453 */
454 void makeFilenameUnique(char* filename)
455 {
456  if (doesFileExist(filename)) // if a file already exist with the same name,
457  {
458  // create a unique filename by adding a counter:
459  char filename2[XS_MAX_FILENAME_LENGTH];
460  char basename[XS_MAX_FILENAME_LENGTH];
461  strcpy(basename, filename);
462  basename[strlen(basename) - 4] = 0; // remove .log extension
463  int counter = 1;
464  do
465  {
466  sprintf(filename2, "%s_%d.log", basename, counter++);
467  if (counter > 10) // don't count further than 10
468  {
469  sprintf(filename2, "%s_n.log", basename);
470  break;
471  }
472  }
473  while (doesFileExist(filename2));
474  strcpy(filename, filename2);
475  }
476 }
477 
478 /*! \brief Read data from the serial port and put it into the data buffer.
479  \details This function reads up to \a maxLength bytes from the port (non-blocking) and
480  puts it into the \a data buffer.
481  \param maxLength The maximum amount of data read.
482  \param data The buffer that will store the received data.
483  \returns XRV_OK if no error occurred. It can be that no data is available and XRV_OK will be
484  returned. Check data.size() for the number of bytes that were read.
485 */
487 {
488  if (!isOpen())
489  return (m_lastResult = XRV_NOPORTOPEN);
490 
491 #ifdef _WIN32
492  DWORD length;
493  data.setSize(maxLength);
494  BOOL rres = ::ReadFile(m_handle, data.data(), (DWORD) maxLength, &length, NULL);
495  data.pop_back(maxLength-length);
496  JLTRACE(gJournal, "ReadFile result " << rres << ", length " << length);
497 
498  if (!rres)
499  {
500  DWORD wErr = ::GetLastError();
501  JLALERT(gJournal, "ReadFile returned windows error " << wErr);
502  if (wErr >= ERROR_INVALID_FUNCTION && wErr <= ERROR_INVALID_HANDLE)
504  return (m_lastResult = XRV_ERROR);
505  }
506 
507  if (length == 0)
508  return (m_lastResult = XRV_TIMEOUT);
509 #else
510  fd_set fd;
511  fd_set err;
512  timeval timeout;
513  FD_ZERO(&fd);
514  FD_ZERO(&err);
515  FD_SET(m_handle, &fd);
516  FD_SET(m_handle, &err);
517 
518  timeout.tv_sec = m_timeout/1000;
519  timeout.tv_usec = (m_timeout - (timeout.tv_sec * 1000)) * 1000;
520 
521  int res = select(FD_SETSIZE, &fd, NULL, &err, &timeout);
522  if (res < 0 || FD_ISSET(m_handle, &err))
523  {
524  data.clear();
525  return (m_lastResult = XRV_ERROR);
526  } else if (res == 0) {
527  data.clear();
528  return (m_lastResult = XRV_TIMEOUT);
529  }
530 
531  data.setSize(maxLength);
532  int length = read(m_handle, (void*)data.data(), maxLength);
533  data.pop_back(maxLength - length);
534 #endif
535 
536 #ifdef LOG_RX_TX
537  if (length > 0)
538  {
539  if (rx_log == NULL)
540  {
541  char fname[XS_MAX_FILENAME_LENGTH];
542 #ifdef _WIN32
543  sprintf(fname, "rx_%03d_%d.log", (int32_t) m_port, m_baudrate);
544 #else
545  char *devname = strrchr(m_portname, '/');
546  sprintf(fname, "rx_%s_%d.log", devname + 1, XsBaud::rateToNumeric(m_baudrate));
547 #endif
548  makeFilenameUnique(fname);
549 
550  rx_log = fopen(fname, "wb");
551  }
552  fwrite(data.data(), 1, length, rx_log);
553 #ifdef LOG_RX_TX_FLUSH
554  fflush(rx_log);
555 #endif
556  }
557 #endif
558 
559  JLTRACE(gJournal, "returned success, read " << length << " of " << maxLength << " bytes, first: " << JLHEXLOG(data[0]));
560  return (m_lastResult = XRV_OK);
561 }
562 
563 /*! \brief Set the default timeout value to use in blocking operations.
564  \details This function sets the value of m_timeout. There is no infinity value. The value 0
565  means that all blocking operations now become polling (non-blocking) operations.
566  If the value is set to or from 0, the low-level serial port settings may be
567  changed in addition to the m_timeout value.
568  \param ms The new timeout in milliseconds
569  \returns XRV_OK if the function succeeded
570 */
572 {
573  JLDEBUG(gJournal, "Setting timeout to " << ms << " ms");
574 
575  m_timeout = ms;
576 #ifdef _WIN32
577  // Set COM timeouts
578  COMMTIMEOUTS commTimeouts;
579 
580  if (!GetCommTimeouts(m_handle,&commTimeouts)) // Fill CommTimeouts structure
581  return m_lastResult = XRV_ERROR;
582 
583  // immediate return if data is available, wait 1ms otherwise
584  if (m_timeout > 0)
585  {
586  commTimeouts.ReadIntervalTimeout = 0;
587  commTimeouts.ReadTotalTimeoutConstant = m_timeout; // ms time
588  commTimeouts.ReadTotalTimeoutMultiplier = 0;
589  commTimeouts.WriteTotalTimeoutConstant = m_timeout;
590  commTimeouts.WriteTotalTimeoutMultiplier = 0;
591  }
592  else
593  {
594  // immediate return whether data is available or not
595  commTimeouts.ReadIntervalTimeout = MAXDWORD;
596  commTimeouts.ReadTotalTimeoutConstant = 0;
597  commTimeouts.ReadTotalTimeoutMultiplier = 0;
598  commTimeouts.WriteTotalTimeoutConstant = 0;
599  commTimeouts.WriteTotalTimeoutMultiplier = 0;
600  }
601 
602  if (!SetCommTimeouts(m_handle, &commTimeouts)) // Set CommTimeouts structure
603  return m_lastResult = XRV_ERROR;
604 #else
605  // Timeout 0.1 sec for first byte, read minimum of 0 bytes
606  m_commState.c_cc[VMIN] = 0;
607  m_commState.c_cc[VTIME] = (m_timeout+99)/100; // ds time
608 
609  // Set the new options for the port if it is open
610  if (isOpen())
611  tcsetattr(m_handle,TCSANOW, &m_commState);
612 #endif
613  return (m_lastResult = XRV_OK);
614 }
615 
616 /*! \brief Wait for data to arrive or a timeout to occur.
617  \details The function waits until \c maxLength data is available or until a timeout occurs.
618  The function returns success if data is available or XsResultValue::TIMEOUT if a
619  timeout occurred. A timeout value of 0 indicates that the default timeout stored
620  in the class should be used.
621  \param maxLength The maximum number of bytes to read before returning
622  \param data The buffer to put the read data in.
623  \returns XRV_OK if \a maxLength bytes were read, XRV_TIMEOUT if less was read, XRV_TIMEOUTNODATA if nothing was read
624 */
626 {
627  data.clear();
628  data.reserve(maxLength);
629 
630  //char *data = (char *)&_data[0];
631  JLTRACE(gJournal, "timeout=" << m_timeout << ", maxLength=" << maxLength);
632  uint32_t timeout = m_timeout;
633 
634  uint32_t eTime = XsTime_getTimeOfDay(NULL, NULL) + timeout;
635 // uint32_t newLength = 0;
636 
637  while ((data.size() < maxLength) && (XsTime_getTimeOfDay(NULL, NULL) <= eTime))
638  {
639  XsByteArray raw;
640 
641  if (readData(maxLength - data.size(), raw) != XRV_OK)
642  return m_lastResult;
643  data.append(raw);
644  }
645  JLTRACE(gJournal, "Read " << data.size() << " of " << maxLength << " bytes");
646 
647  if (data.size() < maxLength)
648  return (m_lastResult = XRV_TIMEOUT);
649  else
650  return (m_lastResult = XRV_OK);
651 }
652 
653 /*! \copydoc IoInterface::writeData
654  \note The default timeout is respected in this operation.
655 */
657 {
658  XsSize bytes;
659  if (written == NULL)
660  written = &bytes;
661 
662  if (!isOpen())
663  return (m_lastResult = XRV_NOPORTOPEN);
664 
665  *written = 0;
666 
667 #ifdef _WIN32
668  DWORD lwritten = 0;
669  if (WriteFile(m_handle, data.data(), (DWORD) data.size(), &lwritten, NULL) == 0)
670  return (m_lastResult = XRV_ERROR);
671 
672  *written = lwritten;
673 #else
674  ssize_t result = write(m_handle, (const void*)data.data(), data.size());
675  if (result < 0)
676  return (m_lastResult = XRV_ERROR);
677 
678  *written = result;
679 #endif
680 
681 #ifdef LOG_RX_TX
682  if (written[0] > 0)
683  {
684  if (tx_log == NULL)
685  {
686  char fname[XS_MAX_FILENAME_LENGTH];
687 #ifdef _WIN32
688  sprintf(fname, "tx_%03d_%d.log", (int32_t) m_port, m_baudrate);
689 #else
690  char *devname = strrchr(m_portname, '/');
691  sprintf(fname,"tx_%s_%d.log", devname + 1, XsBaud::rateToNumeric(m_baudrate));
692 #endif
693  makeFilenameUnique(fname);
694 
695  tx_log = fopen(fname, "wb");
696  }
697  fwrite(data.data(), 1, *written, tx_log);
698 #ifdef LOG_RX_TX_FLUSH
699  fflush(tx_log);
700 #endif
701  }
702 #endif
703 
704  return (m_lastResult = XRV_OK);
705 }
706 
707 /*! \brief Cancel any pending io requests */
709 {
710 #ifdef _WIN32
711  /* This function is only available on Windows Vista and higher.
712  When a read action hangs, this function can cancel IO operations from another thread.
713  */
714  //CancelIoEx(m_handle, NULL);
715 #endif
716 }
Operation was performed successfully.
Definition: xsens_std.h:32
XsIoHandle m_handle
The serial port handle, also indicates if the port is open or not.
FILE BASE_IMPEXP * fopen(const char *fileName, const char *mode) MRPT_NO_THROWS
An OS-independent version of fopen.
Definition: os.cpp:255
uint16_t getPortNumber(void) const
Retrieve the port number that was last successfully opened.
GLenum GLint GLuint mask
Definition: glext.h:3888
#define XS_MAX_FILENAME_LENGTH
Definition: iointerface.h:30
unsigned __int16 uint16_t
Definition: rptypes.h:46
A timeout occurred.
Definition: xsens_std.h:60
uint16_t m_port
The opened COM port nr.
int BASE_IMPEXP void BASE_IMPEXP fclose(FILE *f)
An OS-independent version of fclose.
Definition: os.cpp:272
GLuint buffer
Definition: glext.h:3775
XsFileHandle * rx_log
bool isOpen(void) const
Return whether the communication port is open or not.
pin 4: Data Terminal Ready
Definition: xscontrolline.h:20
HANDLE XsIoHandle
Definition: xsfilepos.h:37
struct XsByteArray XsByteArray
Definition: xsbytearray.h:25
The specified i/o device can not be opened.
Definition: xsens_std.h:69
XsControlLine
Serial control lines.
Definition: xscontrolline.h:16
size_t XsSize
XsSize must be unsigned number!
Definition: xstypedefs.h:17
char BASE_IMPEXP * strcpy(char *dest, size_t destSize, const char *source) MRPT_NO_THROWS
An OS-independent version of strcpy.
Definition: os.cpp:296
XSTYPES_DLL_API uint32_t XsTime_getTimeOfDay(struct tm *date_, time_t *secs_)
int BOOL
Definition: xstypedefs.h:62
XsResultValue readData(XsSize maxLength, XsByteArray &data)
Read data from the serial port and put it into the data buffer.
XsBaudRate getBaudrate(void) const
Return the baudrate that is currently being used by the port.
Not a valid baud rate.
Definition: xsbaudrate.h:28
XsResultValue
Xsens result values.
Definition: xsresultvalue.h:26
XsBaudRate m_baudrate
The baudrate that was last set to be used by the port.
char m_portname[32]
The name of the open serial port.
#define FALSE
Definition: jmorecfg.h:227
XsResultValue escape(XsControlLine mask, XsControlLine state)
Manipulate the Serial control lines.
No serial port opened for reading/writing.
Definition: xsens_std.h:92
XsResultValue closeLive(void)
Close the serial communication port.
void cancelIo(void) const
Cancel any pending io requests.
XsResultValue open(const XsPortInfo &portInfo, uint32_t readBufSize=XS_DEFAULT_READ_BUFFER_SIZE, uint32_t writeBufSize=XS_DEFAULT_WRITE_BUFFER_SIZE)
Open a communication channel to the given port info.
XsResultValue m_lastResult
The last result of an operation.
virtual ~SerialInterface()
Destructor, de-initializes, frees memory allocated for buffers, etc.
GLsizei const GLchar ** string
Definition: glext.h:3919
void makeFilenameUnique(char *filename)
Helper function for making filename of log file unique.
XsResultValue getLastResult(void) const
Return the error code of the last operation.
__int32 int32_t
Definition: rptypes.h:48
XsIoHandle getHandle(void) const
Return the handle of the port.
XsResultValue flushData(void)
Flush all data in the buffers to and from the device.
#define JLDEBUG(...)
XsFileHandle * tx_log
XsResultValue setTimeout(uint32_t ms)
Set the default timeout value to use in blocking operations.
GLuint GLsizei GLsizei * length
Definition: glext.h:3900
uint32_t getTimeout(void) const
Return the current timeout value.
uint32_t m_endTime
The time at which an operation will end in ms, used by several functions.
_u8 status
Definition: rplidar_cmd.h:21
pin 7: Request To Send
Definition: xscontrolline.h:23
int BASE_IMPEXP sprintf(char *buf, size_t bufSize, const char *format,...) MRPT_NO_THROWS MRPT_printf_format_check(3
An OS-independent version of sprintf (Notice the bufSize param, which may be ignored in some compiler...
Definition: os.cpp:191
typedef void(APIENTRYP PFNGLBLENDCOLORPROC)(GLclampf red
A generic error occurred.
Definition: xsens_std.h:58
GLsizei maxLength
Definition: glext.h:4504
#define JLTRACE(...)
void getPortName(XsString &portname) const
Retrieve the port name that was last successfully opened.
GLuint res
Definition: glext.h:6298
XsResultValue waitForData(XsSize maxLength, XsByteArray &data)
Wait for data to arrive or a timeout to occur.
struct XsString XsString
Definition: xsstring.h:34
XsResultValue close(void)
Close the serial communication port.
unsigned __int32 uint32_t
Definition: rptypes.h:49
XsResultValue writeData(const XsByteArray &data, XsSize *written=0)
Write the data contained in data to the device.
XsBaudRate
Communication speed.
Definition: xsbaudrate.h:27
GLsizei GLsizei GLenum GLenum const GLvoid * data
Definition: glext.h:3520
#define JLALERT(...)
SerialInterface()
Default constructor, initializes all members to their default values.
An I/O device is already opened with this object.
Definition: xsens_std.h:71
bool doesFileExist(char *filename)
Helper function for making filename of log file unique.
No file or serial port opened for reading/writing.
Definition: xsens_std.h:93



Page generated by Doxygen 1.8.14 for MRPT 1.5.6 Git: 4c65e8431 Tue Apr 24 08:18:17 2018 +0200 at lun oct 28 01:35:26 CET 2019