Serial.cpp
Go to the documentation of this file.
1 //
3 // © Copyright 2022 SCHUNK Mobile Greifsysteme GmbH, Lauffen/Neckar Germany
4 // © Copyright 2022 FZI Forschungszentrum Informatik, Karlsruhe, Germany
5 //
6 // This file is part of the Schunk SVH Library.
7 //
8 // The Schunk SVH Library is free software: you can redistribute it and/or
9 // modify it under the terms of the GNU General Public License as published by
10 // the Free Software Foundation, either version 3 of the License, or (at your
11 // option) any later version.
12 //
13 // The Schunk SVH Library is distributed in the hope that it will be useful,
14 // but WITHOUT ANY WARRANTY; without even the implied warranty of
15 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
16 // Public License for more details.
17 //
18 // You should have received a copy of the GNU General Public License along with
19 // the Schunk SVH Library. If not, see <https://www.gnu.org/licenses/>.
20 //
22 
23 //----------------------------------------------------------------------
36 //----------------------------------------------------------------------
37 
38 // Not functional with Mac OS X (UH)
39 
42 
43 #include <algorithm>
44 #include <cassert>
45 
46 #include <ratio>
47 
48 #ifdef _SYSTEM_LINUX_
49 # include <errno.h>
50 # include <fcntl.h>
51 # include <stdio.h>
52 # include <string.h>
53 # include <sys/time.h>
54 #endif
55 
56 #include <chrono>
57 //#include "mcal_math/OwnMath.h"
58 
59 #ifdef _SYSTEM_WIN32_
60 # include <math.h>
61 # include <stdio.h>
62 #endif
63 
64 #undef SERIAL_DUMP_DATA
65 //#define SERIAL_DUMP_DATA
66 
67 namespace driver_svh {
68 namespace serial {
69 
70 Serial::Serial(const char* dev_name, const SerialFlags& flags)
71  : m_dev_name(strdup(dev_name))
72  , m_serial_flags(flags)
73 {
74 #ifdef _SYSTEM_WIN32_
75  m_com = INVALID_HANDLE_VALUE;
76 #else
77  m_file_descr = -1;
78 #endif
79 
80  open();
81 }
82 
83 Serial::Serial(const char* dev_name, SerialFlags::BaudRate baud_rate, const SerialFlags& flags)
84  : m_dev_name(strdup(dev_name))
85  , m_serial_flags(flags)
86 {
87 #ifdef _SYSTEM_WIN32_
88  m_com = INVALID_HANDLE_VALUE;
89 #else
90  m_file_descr = -1;
91 #endif
92 
93  m_serial_flags.setBaudRate(baud_rate);
94  open();
95 }
96 
98 {
99  close();
100 
101 #if defined _SYSTEM_LINUX_
102  // Attention! The following code will be executed,
103  // if we are not a lxrt-task or no lxrt interface is available:
104  {
105  termios io_set_new;
106 
107  // open device
108  if ((m_file_descr = ::open(m_dev_name, O_RDWR | O_NONBLOCK)) < 0)
109  {
110  m_status = -errno;
111  SVH_LOG_DEBUG_STREAM("Serial",
112  "Cannot open serial device '" << m_dev_name << "'. Status (" << m_status
113  << ":" << strerror(-m_status));
114  // DEBUGMSG(DD_SYSTEM, DL_DEBUG, "Cannot open serial device '%s'. Status (%i:%s)\n",
115  // m_dev_name, m_status, strerror(-m_status));
116  return false;
117  }
118  else
119  m_status = 0;
120 
121  // get device-settings
122  if (tcgetattr(m_file_descr, &m_io_set_old) < 0)
123  {
124  m_status = -errno;
125  SVH_LOG_DEBUG_STREAM("Serial",
126  "Cannot get serial device m_status '" << m_dev_name << "'. Status ("
127  << m_status << ":"
128  << strerror(-m_status));
129  // DEBUGMSG(DD_SYSTEM, DL_DEBUG, "Cannot get serial device m_status '%s'. Status (%i:%s)\n",
130  // m_dev_name, m_status, strerror(-m_status));
131  return false;
132  }
133  else
134  m_status = 0;
135 
136  // copy settings from old settings
137  io_set_new = m_io_set_old;
138 
139  // declare new settings
140  io_set_new.c_cflag = m_serial_flags.cFlags();
141  io_set_new.c_oflag = 0;
142  io_set_new.c_iflag = IGNPAR;
143  io_set_new.c_lflag = 0;
144  io_set_new.c_cc[VMIN] = 1;
145  io_set_new.c_cc[VTIME] = 0;
146 
147  // set new settings
148  if (tcsetattr(m_file_descr, TCSANOW, &io_set_new) < 0)
149  {
150  m_status = -errno;
151  SVH_LOG_DEBUG_STREAM("Serial",
152  "Serial(" << m_dev_name << ") Error>> tcsetattr failed. Status ("
153  << m_status << ":" << strerror(-m_status));
154  // DEBUGMSG(DD_SYSTEM, DL_DEBUG, "Serial(%s) Error>> tcsetattr failed. Status (%i:%s)\n",
155  // m_dev_name, m_status, strerror(-m_status));
156  return false;
157  }
158  else
159  m_status = 0;
160 
162  {
163  SVH_LOG_DEBUG_STREAM("Serial",
164  "Serial(" << m_dev_name << ") setting hardware modem control flags to 0x"
166  // DEBUGMSG(DD_SYSTEM, DL_DEBUG, "Serial(%s) setting hardware modem control flags to 0x%x\n",
167  // m_dev_name, m_serial_flags.getModemControlFlags());
168  int modem_control_flags = 0;
170  {
171  modem_control_flags |= TIOCM_DTR;
172  }
174  {
175  modem_control_flags |= TIOCM_RTS;
176  }
177 
178  ioctl(m_file_descr, TIOCMSET, modem_control_flags);
179  }
180  }
181 
182 #elif defined _SYSTEM_WIN32_
183 
184  m_read_buffer_fill = 0;
185  m_status = 0;
186 
187  // Try to open the serial port.
188  m_com = CreateFile(
189  m_dev_name, GENERIC_READ | GENERIC_WRITE, 0, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
190  if (m_com == INVALID_HANDLE_VALUE)
191  {
192  m_status = GetLastError();
193  SVH_LOG_WARN_STREAM("Serial",
194  "Serial(" << m_dev_name << "): ERROR>> open port failed ("
195  << StatusText().c_str() << ").");
196  // WARNINGMSG("Serial(%s): ERROR>> open port failed (%s).\n", m_dev_name, StatusText().c_str());
197  }
198 
199  // Set the receive and send buffer size.
200  if (m_status == 0)
201  {
202  if (!SetupComm(m_com, 0x4000, 0x4000))
203  {
204  m_status = GetLastError();
205  SVH_LOG_WARN_STREAM("Serial",
206  "Serial(" << m_dev_name << "): ERROR>> SetupComm failed ("
207  << StatusText().c_str() << ").");
208  // WARNINGMSG("Serial(%s): ERROR>> SetupComm failed (%s).\n", m_dev_name,
209  // StatusText().c_str());
210  }
211  }
212 
213  // Get the current serial port configuration.
214  DCB dcb;
215  memset(&dcb, 0, sizeof(DCB));
216  if (m_status == 0)
217  {
218  if (!GetCommState(m_com, &dcb))
219  {
220  m_status = GetLastError();
221  SVH_LOG_WARN_STREAM("Serial",
222  "Serial(" << m_dev_name << "): ERROR>> GetCommState failed ("
223  << StatusText().c_str() << ").");
224  // WARNINGMSG("Serial(%s): ERROR>> GetCommState failed (%s).\n", m_dev_name,
225  // StatusText().c_str());
226  }
227  }
228 
229  // Set the serial port configuration from the supplied seiral flags.
230  if (m_status == 0)
231  {
232  m_serial_flags.GetDCB(&dcb);
233  if (!SetCommState(m_com, &dcb))
234  {
235  m_status = GetLastError();
236  SVH_LOG_WARN_STREAM("Serial",
237  "Serial(" << m_dev_name << "): ERROR>> SetCommState failed ("
238  << StatusText().c_str() << ").");
239  // WARNINGMSG("Serial(%s): ERROR>> SetCommState failed (%s).\n", m_dev_name,
240  // StatusText().c_str());
241  return false;
242  }
243  }
244 #endif
245 
246  return m_status == 0;
247 }
248 
249 void Serial::dumpData(void* data, size_t length)
250 {
251  unsigned char* c_data = static_cast<unsigned char*>(data);
252  printf("Serial::DumpData: ");
253  for (size_t i = 0; i < length; ++i)
254  {
255  printf("%02X ", int(c_data[i]));
256  }
257  printf("\n");
258 }
259 
261 {
262  // Nothing to be done here.
263  if (m_serial_flags.getBaudRate() == speed)
264  {
265  // success
266  return 0;
267  }
269 
270 #if defined _SYSTEM_LINUX_
271  {
272  if (m_file_descr < 0)
273  return m_status;
274 
275  struct termios io_set;
276 
277  // Get device settings
278  if (tcgetattr(m_file_descr, &io_set) < 0)
279  {
280  m_status = -errno;
281  SVH_LOG_DEBUG_STREAM("Serial",
282  "Serial(" << m_dev_name << "): Error>> tcgetattr failed. Status ("
283  << m_status << ":" << strerror(-m_status));
284  // DEBUGMSG(DD_SYSTEM, DL_DEBUG, "Serial Error>> tcgetattr (%s) failed. m_status (%i:%s)\n",
285  // m_dev_name, m_status, strerror(-m_status));
286  }
287  else
288  {
289  // clear speed-settings
290  io_set.c_cflag &= ~CBAUD;
291  // add new speed-settings
292  io_set.c_cflag |= SerialFlags::cFlags(speed);
293 
294  // set new device settings
295  if (tcsetattr(m_file_descr, TCSANOW, &io_set) < 0)
296  {
297  m_status = -errno;
298  SVH_LOG_DEBUG_STREAM("Serial",
299  "Serial(" << m_dev_name << "): Error>> tcsetattr failed. Status ("
300  << m_status << ":" << strerror(-m_status));
301  // DEBUGMSG(DD_SYSTEM, DL_DEBUG, "Serial(%s) Error>> tcsetattr failed. Status (%i:%s)\n",
302  // m_dev_name, m_status, strerror(-m_status));
303  }
304  else
305  {
306  SVH_LOG_INFO_STREAM("Serial", "Serial:ChangeBaudrate " << speed << " successful.");
307  // INFOMSG("Serial:ChangeBaudrate %i successful\n", speed);
308  m_status = 0;
309  }
310  }
311  }
312 
313  return m_status;
314 #endif
315 
316 #ifdef _SYSTEM_DARWIN_
317  SVH_LOG_WARN_STREAM("Serial", "Serial:changeBaudrate() >> to be implemented");
318  // WARNINGMSG("Serial:changeBaudrate() >> to be implemented\n");
319  return -1;
320 #endif
321 
322 #ifdef _SYSTEM_WIN32_
323  m_status = 0;
324 
325  // Clears the output and input buffers.
326  if (!PurgeComm(m_com, PURGE_RXCLEAR) || !PurgeComm(m_com, PURGE_TXCLEAR))
327  {
328  m_status = GetLastError();
329  SVH_LOG_WARN_STREAM("Serial",
330  "Serial(" << m_dev_name << "): ERROR>> PurgeComm failed ("
331  << StatusText().c_str() << ").");
332  // WARNINGMSG("Serial(%s): ERROR>> PurgeComm failed (%s).\n", m_dev_name, StatusText().c_str());
333  }
334 
335  // Get the current serial port configuration.
336  DCB dcb;
337  memset(&dcb, 0, sizeof(DCB));
338  if (m_status == 0)
339  {
340  if (!GetCommState(m_com, &dcb))
341  {
342  m_status = GetLastError();
343  SVH_LOG_WARN_STREAM("Serial",
344  "Serial(" << m_dev_name << "): ERROR>> GetCommState failed ("
345  << StatusText().c_str() << ").");
346  // WARNINGMSG("Serial(%s): ERROR>> GetCommState failed (%s).\n", m_dev_name,
347  // StatusText().c_str());
348  }
349  }
350 
351  // Set the serial port configuration with the new baud rate.
352  if (m_status == 0)
353  {
354  m_serial_flags.GetDCB(&dcb);
355  if (!SetCommState(m_com, &dcb))
356  {
357  m_status = GetLastError();
358  SVH_LOG_WARN_STREAM("Serial",
359  "Serial(" << m_dev_name << "): ERROR>> SetCommState failed ("
360  << StatusText().c_str() << ").");
361  // WARNINGMSG("Serial(%s): ERROR>> SetCommState failed (%s).\n", m_dev_name,
362  // StatusText().c_str());
363  }
364  }
365 
366  return -m_status;
367 #endif
368 }
369 
371 {
372 #ifdef _SYSTEM_WIN32_
373  m_status = 0;
374 
375  // Clears the input buffers.
376  if (PurgeComm(m_com, PURGE_RXCLEAR))
377  {
378  m_read_buffer_fill = 0;
379  }
380  else
381  {
382  m_status = GetLastError();
383  SVH_LOG_WARN_STREAM("Serial",
384  "Serial(" << m_dev_name << "): ERROR>> PurgeComm failed ("
385  << StatusText().c_str() << ").");
386  // WARNINGMSG("Serial(%s): ERROR>> PurgeComm failed (%s).\n", m_dev_name, StatusText().c_str());
387  }
388 
389  return m_status;
390 #elif defined _SYSTEM_LINUX_
391  // could not test for LXRT device, so return -1 to be on the safe side
392  if (tcflush(m_file_descr, TCIFLUSH) != 0)
393  {
394  SVH_LOG_WARN_STREAM("Serial", "tcflush failed :(");
395  return -1;
396  }
397 #else
398  return -1;
399 #endif
400  return 0;
401 }
402 
404 {
405 #ifdef _SYSTEM_WIN32_
406  m_status = 0;
407 
408  // Clears the output buffers.
409  if (PurgeComm(m_com, PURGE_TXCLEAR))
410  {
411  m_read_buffer_fill = 0;
412  }
413  else
414  {
415  m_status = GetLastError();
416  SVH_LOG_WARN_STREAM("Serial",
417  "Serial(" << m_dev_name << "): ERROR>> PurgeComm failed ("
418  << StatusText().c_str() << ").");
419  // WARNINGMSG("Serial(%s): ERROR>> PurgeComm failed (%s).\n", m_dev_name, StatusText().c_str());
420  }
421 
422  return m_status;
423 #elif defined _SYSTEM_LINUX_
424  // could not test for LXRT device, so return -1 to be on the safe side
425  if (tcflush(m_file_descr, TCOFLUSH) != 0)
426  {
427  SVH_LOG_WARN_STREAM("Serial", "tcflush failed :(");
428  return -1;
429  }
430 #else
431  return -1;
432 #endif
433  return 0;
434 }
435 
436 ssize_t Serial::write(const void* data, ssize_t size)
437 {
438 #if defined _SYSTEM_LINUX_
439  if (m_file_descr < 0)
440  return m_status;
441 
442  ssize_t bytes_out = 0;
443 
444  {
445  // just write it to device
446  if ((bytes_out = ::write(m_file_descr, (char*)data, size)) < 0)
447  {
448  m_status = -errno;
449  SVH_LOG_DEBUG_STREAM("Serial",
450  "Serial(" << m_dev_name << ":" << m_dev_name
451  << "): Error on writing. Status (" << m_status << ":"
452  << strerror(-m_status) << ").");
453  // DEBUGMSG(DD_SYSTEM, DL_DEBUG, "Serial(%s) Error on writing. Status (%i:%s)\n", m_dev_name,
454  // m_status, strerror(-m_status));
455  }
456  else
457  {
458  m_status = 0;
459  }
460  }
461 
462  return bytes_out;
463 
464 #elif defined _SYSTEM_WIN32_
465 
466  assert(m_com != INVALID_HANDLE_VALUE);
467 
468  DWORD bytes_written;
469  if (!WriteFile(m_com, data, size, &bytes_written, NULL))
470  {
471  m_status = GetLastError();
472  SVH_LOG_WARN_STREAM("Serial",
473  "Serial(" << m_dev_name << "): ERROR>> could not write data ("
474  << StatusText().c_str() << ").");
475  // WARNINGMSG("Serial(%s): ERROR>> could not write data (%s).\n", m_dev_name,
476  // StatusText().c_str());
477  }
478  else
479  {
480  m_status = 0;
481 # ifdef SERIAL_DUMP_DATA
482  DumpData(data, bytes_written);
483 # endif
484  }
485 
486  return (m_status == 0 ? bytes_written : -m_status);
487 #else
488  return -1;
489 #endif
490 }
491 
492 ssize_t Serial::read(void* data, ssize_t size, unsigned long time, bool return_on_less_data)
493 {
494  // tTime end_time = tTime().FutureUSec(time);
495  auto end_time = std::chrono::high_resolution_clock::now() + std::chrono::microseconds(time);
496 
497 #if defined _SYSTEM_LINUX_
498  if (m_file_descr < 0)
499  return m_status;
500 
501  std::chrono::duration<double, std::milli> tz;
502  fd_set fds;
503  ssize_t bytes_read = 0;
504  ssize_t bytes_read_inc;
505  int select_return;
506  char* buffer = (char*)data;
507 
508  // if (time <= 0)
509  // time = 1;
510  // LDM("Serial(%s)::Read(%i) (time left %li us)\n", m_dev_name, size, time);
511 
512  m_status = 0;
513  {
514  // We wait max time
515  do
516  {
517  tz = end_time - std::chrono::high_resolution_clock::now();
518  // min 1 us, otherwise we will read nothing at all
519  if (tz < std::chrono::microseconds(1))
520  {
521  tz = std::chrono::microseconds(1);
522  }
523 
524  // LDM("Serial(%s) Check Read.\n", m_dev_name);
525 
526  FD_ZERO(&fds);
527  FD_SET(m_file_descr, &fds);
528  timeval select_timeout = {0,
529  std::chrono::duration_cast<std::chrono::microseconds>(tz).count()};
530  // Look for received data:
531  if ((select_return = select(FD_SETSIZE, &fds, 0, 0, &select_timeout)) > 0)
532  {
533  // LDM("Serial(%s) Select successful.\n", m_dev_name);
534  if (return_on_less_data)
535  {
536  if ((bytes_read_inc = ::read(m_file_descr, &buffer[bytes_read], size - bytes_read)) < 0)
537  {
538  m_status = -errno;
539  SVH_LOG_DEBUG_STREAM("Serial",
540  "Error on reading '" << m_dev_name << "'. Status (" << m_status
541  << ":" << strerror(-m_status) << ")");
542  // DEBUGMSG(DD_SYSTEM, DL_DEBUG, "Error on reading '%s'. Status (%i:%s)\n", m_dev_name,
543  // m_status, strerror(-m_status));
544  return m_status;
545  }
546  // Any bytes read ?
547  if (bytes_read_inc > 0)
548  {
549  bytes_read += bytes_read_inc;
550  // LDM("Serial(%s) Data read (%i => %i).\n", m_dev_name, bytes_read_inc, bytes_read);
551  if (bytes_read == size)
552  {
553  return bytes_read;
554  }
555  }
556  }
557  else
558  {
559  // LDM("serial:time left %lu\n",Time2Long(tz));
560  // Are there already enough bytes received ?
561  if (ioctl(m_file_descr, FIONREAD, &bytes_read_inc) < 0)
562  {
563  m_status = -errno;
564  SVH_LOG_DEBUG_STREAM("Serial",
565  "Error on ioctl FIONREAD '" << m_dev_name << "'. Status ("
566  << m_status << ":"
567  << strerror(-m_status) << ")");
568  // DEBUGMSG(DD_SYSTEM, DL_DEBUG, "Error on ioctl FIONREAD '%s'. Status (%i:%s)\n",
569  // m_dev_name, m_status, strerror(-m_status));
570  return m_status;
571  }
572  else
573  {
574  // Yes? then read data
575  if (bytes_read_inc >= size)
576  {
577  if ((bytes_read = ::read(m_file_descr, buffer, size)) < 0)
578  {
579  m_status = -errno;
580  SVH_LOG_DEBUG_STREAM("Serial",
581  "Error on read '" << m_dev_name << "'. Status (" << m_status
582  << ":" << strerror(-m_status) << ")");
583  // DEBUGMSG(DD_SYSTEM, DL_DEBUG, "Error on read '%s'. Status (%i:%s)\n", m_dev_name,
584  // m_status, strerror(-m_status));
585  return m_status;
586  }
587  else
588  {
589  // LDM("Serial(%s) Data read (%i bytes).\n", m_dev_name, bytes_read);
590  return bytes_read;
591  }
592  }
593  // No ? do nothing
594  }
595  }
596  }
597  else if (select_return < 0)
598  {
599  m_status = -errno;
600  SVH_LOG_DEBUG_STREAM("Serial",
601  "Error on select '" << m_dev_name << "'. Status (" << m_status << ":"
602  << strerror(-m_status) << ")");
603  // DEBUGMSG(DD_SYSTEM, DL_DEBUG, "Error on select '%s'. Status (%i:%s)\n", m_dev_name,
604  // m_status, strerror(-m_status));
605  return m_status;
606  }
607  }
608  // Look again for data, if any time left
609  while (std::chrono::high_resolution_clock::now() < end_time);
610  }
611 
612  // LDM("Serial(%s)::Read(%i) (time left %li us) = %i.\n", m_dev_name, size, (end_time -
613  // std::chrono::high_resolution_clock::now()).toUSec(), bytes_read);
614  return bytes_read;
615 #endif
616 
617 
618 #ifdef _SYSTEM_DARWIN_
619  SVH_LOG_WARN_STREAM("Serial", "Serial:Read() >> to be implemented!");
620  // WARNINGMSG("Serial:Read() >> to be implemented\n");
621  return 0;
622 #endif
623 
624 #ifdef _SYSTEM_WIN32_
625  assert(m_com != INVALID_HANDLE_VALUE);
626 
627  m_status = 0;
628 
629  // Set the timeout for the read operation.
630  COMMTIMEOUTS timeout;
631  timeout.ReadIntervalTimeout = time / 1000;
632  timeout.ReadTotalTimeoutMultiplier = 1;
633  timeout.ReadTotalTimeoutConstant = time / 1000;
634  timeout.WriteTotalTimeoutMultiplier = 1;
635  timeout.WriteTotalTimeoutConstant = MAXDWORD;
636  if (!SetCommTimeouts(m_com, &timeout))
637  {
638  m_status = GetLastError();
639  SVH_LOG_WARN_STREAM("Serial",
640  "Serial(" << m_dev_name << "): ERROR>> setting read timeout failed ("
641  << StatusText().c_str() << ")");
642  // WARNINGMSG("Serial(%s): ERROR>> setting read timeout failed (%s).\n", m_dev_name,
643  // StatusText().c_str());
644  }
645 
646  // Try to receive data.
647  if (m_read_buffer_fill <= size && m_status == 0)
648  {
649  DWORD bytes_received = 0;
650  size_t bytes_remaining = (m_read_buffer_fill < size ? size - m_read_buffer_fill : 0);
651  auto now std::chrono::high_resolution_clock::now();
652  do
653  {
654  if (ReadFile(
655  m_com, m_read_buffer + m_read_buffer_fill, bytes_remaining, &bytes_received, NULL))
656  {
657  m_read_buffer_fill += bytes_received;
658  if (bytes_remaining > bytes_received)
659  {
660  bytes_remaining -= bytes_received;
661  }
662  else
663  {
664  bytes_remaining = 0;
665  }
666  }
667  else
668  {
669  DWORD error = GetLastError();
670  if (error != ERROR_TIMEOUT)
671  {
672  m_status = error;
673  SVH_LOG_WARN_STREAM("Serial",
674  "Serial(" << m_dev_name << "): ERROR>> error during read ("
675  << StatusText().c_str() << ")");
676  // WARNINGMSG("Serial(%s): ERROR>> error during read (%s).\n", m_dev_name,
677  // StatusText().c_str());
678  }
679  }
680  now = std::chrono::high_resolution_clock::now();
681  } while (m_status == 0 && !return_on_less_data && bytes_remaining && now < end_time);
682 
683  if (m_status == 0 && !return_on_less_data && bytes_remaining && now >= end_time)
684  {
685  m_status = ERROR_TIMEOUT;
686  SVH_LOG_WARN_STREAM("Serial",
687  "Serial(" << m_dev_name << "): ERROR>> error during read ("
688  << StatusText().c_str() << ")");
689  // WARNINGMSG("Serial(%s): ERROR>> error during read (%s).\n", m_dev_name,
690  // StatusText().c_str());
691  }
692  }
693 
694  // Copy data to output buffer.
695  ssize_t bytes_received;
696  if (m_status == 0)
697  {
698  bytes_received = std::min(size, m_read_buffer_fill);
699  memcpy(data, m_read_buffer, bytes_received);
700 
701  // \todo Make this more efficient.
702  for (ssize_t write_index = 0, read_index = bytes_received; read_index < m_read_buffer_fill;
703  ++write_index, ++read_index)
704  {
705  m_read_buffer[write_index] = m_read_buffer[read_index];
706  }
707  m_read_buffer_fill -= bytes_received;
708 
709 # ifdef SERIAL_DUMP_DATA
710  DumpData(data, bytes_received);
711 # endif
712  }
713 
714  return (m_status == 0 ? bytes_received : -m_status);
715 #endif
716 }
717 
718 std::string Serial::statusText() const
719 {
720 #if defined _SYSTEM_LINUX_
721  return strerror(-m_status);
722 #elif defined _SYSTEM_WIN32_
723  LPVOID msg_buff = NULL;
724  DWORD res = FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM |
725  FORMAT_MESSAGE_IGNORE_INSERTS,
726  NULL,
727  m_status, // from GetLastError(),
728  MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
729  (LPTSTR)&msg_buff,
730  0,
731  NULL);
732  std::string result;
733  if (res)
734  {
735  result = (LPCTSTR)msg_buff;
736  LocalFree(msg_buff);
737  }
738  else
739  {
740  result = "fatal internal error";
741  }
742  return result;
743 #else
744  return "Plattform not supported!";
745 #endif
746 }
747 
748 bool Serial::isOpen() const
749 {
750 #ifdef _SYSTEM_LINUX_
751  return m_file_descr >= 0;
752 #elif defined _SYSTEM_WIN32_
753  return m_com != INVALID_HANDLE_VALUE;
754 #else
755  return false;
756 #endif
757 }
758 
760 {
761  // LDM("Serial::Close\n");
762 #ifdef _SYSTEM_LINUX_
763  if (m_file_descr >= 0)
764  {
765  {
766  // restore old setting
767  if (tcsetattr(m_file_descr, TCSANOW, &m_io_set_old) < 0)
768  {
769  m_status = -errno;
770  SVH_LOG_DEBUG_STREAM("Serial",
771  "Serial(" << m_dev_name << ") Error>> tcsetattr failed. Status ("
772  << m_status << ":" << strerror(-m_status) << ")");
773  // DEBUGMSG(DD_SYSTEM, DL_CREATE, "Serial(%s) Error>> tcsetattr failed. Status (%i:%s)\n",
774  // m_dev_name, m_status, strerror(-m_status));
775  }
776  // close device
777  if (::close(m_file_descr) < 0)
778  {
779  m_status = -errno;
780  SVH_LOG_DEBUG_STREAM("Serial",
781  "Serial>> Error closing serial " << m_dev_name << ". Status ("
782  << m_status << ":"
783  << strerror(-m_status) << ")");
784  // DEBUGMSG(DD_SYSTEM, DL_CREATE, "Serial>> Error closing serial %s. Status(%i:%s)\n",
785  // m_dev_name, m_status, strerror(-m_status));
786  }
787  }
788 
789  m_file_descr = -1;
790  }
791 #endif
792 
793 #ifdef _SYSTEM_WIN32_
794  if (m_com != INVALID_HANDLE_VALUE)
795  {
796  CloseHandle(m_com); // close device
797  m_com = INVALID_HANDLE_VALUE;
798  }
799 #endif
800  m_status = 0;
801  // LDM("Serial::Close done.\n");
802 }
803 
805 {
806  // LDM("~Serial start\n");
807 
808  close();
809  // free(m_dev_name);
810  m_dev_name = NULL;
811 
812  // LDM("~Serial done\n");
813 }
814 
815 
816 } // namespace serial
817 } // namespace driver_svh
ssize_t read(void *data, ssize_t size, unsigned long time=100, bool return_on_less_data=true)
Definition: Serial.cpp:492
#define SVH_LOG_INFO_STREAM(NAME, M)
Definition: Logger.h:46
void setBaudRate(BaudRate baud_rate)
Definition: SerialFlags.h:210
Serial(const char *dev_name, const SerialFlags &flags)
Definition: Serial.cpp:70
ssize_t write(const void *data, ssize_t size)
Definition: Serial.cpp:436
#define SVH_LOG_DEBUG_STREAM(NAME, M)
Definition: Logger.h:39
std::string statusText() const
Definition: Serial.cpp:718
Contains a class that enables access to serial devices.
ModemControlFlags getModemControlFlags() const
Definition: SerialFlags.h:212
void dumpData(void *data, size_t length)
Definition: Serial.cpp:249
int changeBaudrate(SerialFlags::BaudRate speed)
Definition: Serial.cpp:260
SerialFlags m_serial_flags
Definition: Serial.h:203
#define SVH_LOG_WARN_STREAM(NAME, M)
Definition: Logger.h:53
Short description of tSerialFlags.
Definition: SerialFlags.h:52


schunk_svh_library
Author(s): Georg Heppner, Lars Pfotzer, Felix Exner, Johannes Mangler, Stefan Scherzinger, Pascal Becker
autogenerated on Fri Apr 14 2023 02:26:23