Instrument Neutral Distributed Interface INDI  2.0.2
ttybase.cpp
Go to the documentation of this file.
1 /*
2  TTY Base
3 
4  Base class for TTY Serial Connections.
5 
6  Copyright (C) 2018 Jasem Mutlaq
7  Copyright (C) 2011 Wildi Markus
8 
9  This library is free software; you can redistribute it and/or
10  modify it under the terms of the GNU Lesser General Public
11  License as published by the Free Software Foundation; either
12  version 2.1 of the License, or (at your option) any later version.
13 
14  This library is distributed in the hope that it will be useful,
15  but WITHOUT ANY WARRANTY; without even the implied warranty of
16  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17  Lesser General Public License for more details.
18 
19  You should have received a copy of the GNU Lesser General Public
20  License along with this library; if not, write to the Free Software
21  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22 
23 */
24 
25 #ifndef _GNU_SOURCE
26 #define _GNU_SOURCE 1
27 #endif
28 
29 #include "ttybase.h"
30 
31 #include "locale_compat.h"
32 
33 #include <errno.h>
34 #include <fcntl.h>
35 #include <math.h>
36 #include <stdarg.h>
37 #include <stdint.h>
38 #include <stdio.h>
39 #include <stdlib.h>
40 #include <string.h>
41 #include <time.h>
42 
43 #ifdef __APPLE__
44 #include <sys/param.h>
45 #endif
46 
47 #if defined(BSD) && !defined(__GNU__)
48 #include <IOKit/serial/ioss.h>
49 #include <sys/ioctl.h>
50 #endif
51 
52 #ifdef _WIN32
53 #undef CX
54 #undef CY
55 #endif
56 
57 #ifndef _WIN32
58 #include <unistd.h>
59 #include <termios.h>
60 #include <sys/param.h>
61 #define PARITY_NONE 0
62 #define PARITY_EVEN 1
63 #define PARITY_ODD 2
64 #endif
65 
66 #if defined(_MSC_VER)
67 #define snprintf _snprintf
68 #pragma warning(push)
70 #pragma warning(disable : 4996)
71 #endif
72 
73 TTYBase::TTYBase(const char *driverName) : m_DriverName(driverName)
74 {
75 
76 }
77 
79 {
80  if (m_PortFD != -1)
81  disconnect();
82 }
83 
84 TTYBase::TTY_RESPONSE TTYBase::checkTimeout(uint8_t timeout)
85 {
86 #if defined(_WIN32) || defined(ANDROID)
87  INDI_UNUSED(timeout);
88  return TTY_ERRNO;
89 #else
90 
91  if (m_PortFD == -1)
92  return TTY_ERRNO;
93 
94  struct timeval tv;
95  fd_set readout;
96  int retval;
97 
98  FD_ZERO(&readout);
99  FD_SET(m_PortFD, &readout);
100 
101  /* wait for 'timeout' seconds */
102  tv.tv_sec = timeout;
103  tv.tv_usec = 0;
104 
105  /* Wait till we have a change in the m_PortFD status */
106  retval = select(m_PortFD + 1, &readout, nullptr, nullptr, &tv);
107 
108  /* Return 0 on successful m_PortFD change */
109  if (retval > 0)
110  return TTY_OK;
111  /* Return -1 due to an error */
112  else if (retval == -1)
113  return TTY_SELECT_ERROR;
114  /* Return -2 if time expires before anything interesting happens */
115  else
116  return TTY_TIME_OUT;
117 
118 #endif
119 }
120 
121 TTYBase::TTY_RESPONSE TTYBase::write(const uint8_t *buffer, uint32_t nbytes, uint32_t *nbytes_written)
122 {
123 #ifdef _WIN32
124  return TTY_ERRNO;
125 #else
126 
127  if (m_PortFD == -1)
128  return TTY_ERRNO;
129 
130  int bytes_w = 0;
131  *nbytes_written = 0;
132 
133  while (nbytes > 0)
134  {
135  bytes_w = ::write(m_PortFD, buffer + (*nbytes_written), nbytes);
136 
137  if (bytes_w < 0)
138  return TTY_WRITE_ERROR;
139 
140  for (uint32_t i = *nbytes_written; i < bytes_w + *nbytes_written; i++)
141  DEBUGFDEVICE(m_DriverName, m_DebugChannel, "%s: buffer[%d]=%#X (%c)", __FUNCTION__, i, buffer[i], buffer[i]);
142 
143  *nbytes_written += bytes_w;
144  nbytes -= bytes_w;
145  }
146 
147  return TTY_OK;
148 
149 #endif
150 }
151 
152 TTYBase::TTY_RESPONSE TTYBase::writeString(const char *string, uint32_t *nbytes_written)
153 {
154  uint32_t nbytes = strlen(string);
155  return write(reinterpret_cast<const uint8_t*>(string), nbytes, nbytes_written);
156 }
157 
158 TTYBase::TTY_RESPONSE TTYBase::read(uint8_t *buffer, uint32_t nbytes, uint8_t timeout, uint32_t *nbytes_read)
159 {
160 #ifdef _WIN32
161  return TTY_ERRNO;
162 #else
163 
164  if (m_PortFD == -1)
165  return TTY_ERRNO;
166 
167  uint32_t numBytesToRead = nbytes;
168  int bytesRead = 0;
169  TTY_RESPONSE timeoutResponse = TTY_OK;
170  *nbytes_read = 0;
171 
172  if (nbytes <= 0)
173  return TTY_PARAM_ERROR;
174 
175  DEBUGFDEVICE(m_DriverName, m_DebugChannel, "%s: Request to read %d bytes with %d timeout for m_PortFD %d", __FUNCTION__,
176  nbytes, timeout, m_PortFD);
177 
178  while (numBytesToRead > 0)
179  {
180  if ((timeoutResponse = checkTimeout(timeout)))
181  return timeoutResponse;
182 
183  bytesRead = ::read(m_PortFD, buffer + (*nbytes_read), numBytesToRead);
184 
185  if (bytesRead < 0)
186  return TTY_READ_ERROR;
187 
188  DEBUGFDEVICE(m_DriverName, m_DebugChannel, "%d bytes read and %d bytes remaining...", bytesRead,
189  numBytesToRead - bytesRead);
190  for (uint32_t i = *nbytes_read; i < (*nbytes_read + bytesRead); i++)
191  DEBUGFDEVICE(m_DriverName, m_DebugChannel, "%s: buffer[%d]=%#X (%c)", __FUNCTION__, i, buffer[i], buffer[i]);
192 
193  *nbytes_read += bytesRead;
194  numBytesToRead -= bytesRead;
195  }
196 
197  return TTY_OK;
198 
199 #endif
200 }
201 
202 TTYBase::TTY_RESPONSE TTYBase::readSection(uint8_t *buffer, uint32_t nsize, uint8_t stop_byte, uint8_t timeout,
203  uint32_t *nbytes_read)
204 {
205 #ifdef _WIN32
206  return TTY_ERRNO;
207 #else
208 
209  if (m_PortFD == -1)
210  return TTY_ERRNO;
211 
212  int bytesRead = 0;
213  TTY_RESPONSE timeoutResponse = TTY_OK;
214  *nbytes_read = 0;
215  memset(buffer, 0, nsize);
216 
217  uint8_t *read_char = nullptr;
218 
219  DEBUGFDEVICE(m_DriverName, m_DebugChannel, "%s: Request to read until stop char '%#02X' with %d timeout for m_PortFD %d",
220  __FUNCTION__, stop_byte, timeout, m_PortFD);
221 
222  for (;;)
223  {
224  if ((timeoutResponse = checkTimeout(timeout)))
225  return timeoutResponse;
226 
227  read_char = reinterpret_cast<uint8_t*>(buffer + *nbytes_read);
228  bytesRead = ::read(m_PortFD, read_char, 1);
229 
230  if (bytesRead < 0)
231  return TTY_READ_ERROR;
232 
233  DEBUGFDEVICE(m_DriverName, m_DebugChannel, "%s: buffer[%d]=%#X (%c)", __FUNCTION__, (*nbytes_read), *read_char, *read_char);
234 
235  (*nbytes_read)++;
236 
237  if (*read_char == stop_byte)
238  return TTY_OK;
239  else if (*nbytes_read >= nsize)
240  return TTY_OVERFLOW;
241  }
242 
243 #endif
244 }
245 
246 #if defined(BSD) && !defined(__GNU__)
247 // BSD - OSX version
248 TTYBase::TTY_RESPONSE TTYBase::connect(const char *device, uint32_t bit_rate, uint8_t word_size, uint8_t parity,
249  uint8_t stop_bits)
250 {
251  int t_fd = -1;
252  int bps;
253  int handshake;
254  struct termios tty_setting;
255 
256  // Open the serial port read/write, with no controlling terminal, and don't wait for a connection.
257  // The O_NONBLOCK flag also causes subsequent I/O on the device to be non-blocking.
258  // See open(2) ("man 2 open") for details.
259 
260  t_fd = open(device, O_RDWR | O_NOCTTY | O_NONBLOCK);
261  if (t_fd == -1)
262  {
263  DEBUGFDEVICE(m_DriverName, m_DebugChannel, "Error opening serial port (%s) - %s(%d).", device, strerror(errno), errno);
264  goto error;
265  }
266 
267  // Note that open() follows POSIX semantics: multiple open() calls to the same file will succeed
268  // unless the TIOCEXCL ioctl is issued. This will prevent additional opens except by root-owned
269  // processes.
270  // See tty(4) ("man 4 tty") and ioctl(2) ("man 2 ioctl") for details.
271 
272  if (ioctl(t_fd, TIOCEXCL) == -1)
273  {
274  DEBUGFDEVICE(m_DriverName, m_DebugChannel, "Error setting TIOCEXCL on %s - %s(%d).", device, strerror(errno), errno);
275  goto error;
276  }
277 
278  // Now that the device is open, clear the O_NONBLOCK flag so subsequent I/O will block.
279  // See fcntl(2) ("man 2 fcntl") for details.
280 
281  if (fcntl(t_fd, F_SETFL, 0) == -1)
282  {
283  DEBUGFDEVICE(m_DriverName, m_DebugChannel, "Error clearing O_NONBLOCK %s - %s(%d).", device, strerror(errno), errno);
284  goto error;
285  }
286 
287  // Get the current options and save them so we can restore the default settings later.
288  if (tcgetattr(t_fd, &tty_setting) == -1)
289  {
290  DEBUGFDEVICE(m_DriverName, m_DebugChannel, "Error getting tty attributes %s - %s(%d).", device, strerror(errno), errno);
291  goto error;
292  }
293 
294  // Set raw input (non-canonical) mode, with reads blocking until either a single character
295  // has been received or a one second timeout expires.
296  // See tcsetattr(4) ("man 4 tcsetattr") and termios(4) ("man 4 termios") for details.
297 
298  cfmakeraw(&tty_setting);
299  tty_setting.c_cc[VMIN] = 1;
300  tty_setting.c_cc[VTIME] = 10;
301 
302  // The baud rate, word length, and handshake options can be set as follows:
303  switch (bit_rate)
304  {
305  case 0:
306  bps = B0;
307  break;
308  case 50:
309  bps = B50;
310  break;
311  case 75:
312  bps = B75;
313  break;
314  case 110:
315  bps = B110;
316  break;
317  case 134:
318  bps = B134;
319  break;
320  case 150:
321  bps = B150;
322  break;
323  case 200:
324  bps = B200;
325  break;
326  case 300:
327  bps = B300;
328  break;
329  case 600:
330  bps = B600;
331  break;
332  case 1200:
333  bps = B1200;
334  break;
335  case 1800:
336  bps = B1800;
337  break;
338  case 2400:
339  bps = B2400;
340  break;
341  case 4800:
342  bps = B4800;
343  break;
344  case 9600:
345  bps = B9600;
346  break;
347  case 19200:
348  bps = B19200;
349  break;
350  case 38400:
351  bps = B38400;
352  break;
353  case 57600:
354  bps = B57600;
355  break;
356  case 115200:
357  bps = B115200;
358  break;
359  case 230400:
360  bps = B230400;
361  break;
362  default:
363  DEBUGFDEVICE(m_DriverName, m_DebugChannel, "connect: %d is not a valid bit rate.", bit_rate);
364  return TTY_PARAM_ERROR;
365  }
366 
367  cfsetspeed(&tty_setting, bps); // Set baud rate
368  /* word size */
369  switch (word_size)
370  {
371  case 5:
372  tty_setting.c_cflag |= CS5;
373  break;
374  case 6:
375  tty_setting.c_cflag |= CS6;
376  break;
377  case 7:
378  tty_setting.c_cflag |= CS7;
379  break;
380  case 8:
381  tty_setting.c_cflag |= CS8;
382  break;
383  default:
384  DEBUGFDEVICE(m_DriverName, m_DebugChannel, "connect: %d is not a valid data bit count.", word_size);
385  return TTY_PARAM_ERROR;
386  }
387 
388  /* parity */
389  switch (parity)
390  {
391  case PARITY_NONE:
392  break;
393  case PARITY_EVEN:
394  tty_setting.c_cflag |= PARENB;
395  break;
396  case PARITY_ODD:
397  tty_setting.c_cflag |= PARENB | PARODD;
398  break;
399  default:
400  DEBUGFDEVICE(m_DriverName, m_DebugChannel, "connect: %d is not a valid parity selection value.", parity);
401  return TTY_PARAM_ERROR;
402  }
403 
404  /* stop_bits */
405  switch (stop_bits)
406  {
407  case 1:
408  break;
409  case 2:
410  tty_setting.c_cflag |= CSTOPB;
411  break;
412  default:
413  DEBUGFDEVICE(m_DriverName, m_DebugChannel, "connect: %d is not a valid stop bit count.", stop_bits);
414  return TTY_PARAM_ERROR;
415  }
416 
417 #if defined(MAC_OS_X_VERSION_10_4) && (MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_4)
418  // Starting with Tiger, the IOSSIOSPEED ioctl can be used to set arbitrary baud rates
419  // other than those specified by POSIX. The driver for the underlying serial hardware
420  // ultimately determines which baud rates can be used. This ioctl sets both the input
421  // and output speed.
422 
423  speed_t speed = 14400; // Set 14400 baud
424  if (ioctl(t_fd, IOSSIOSPEED, &speed) == -1)
425  {
426  IDLog("Error calling ioctl(..., IOSSIOSPEED, ...) - %s(%d).\n", strerror(errno), errno);
427  }
428 #endif
429 
430  // Cause the new options to take effect immediately.
431  if (tcsetattr(t_fd, TCSANOW, &tty_setting) == -1)
432  {
433  DEBUGFDEVICE(m_DriverName, m_DebugChannel, "Error setting tty attributes %s - %s(%d).", device, strerror(errno), errno);
434  goto error;
435  }
436 
437  // To set the modem handshake lines, use the following ioctls.
438  // See tty(4) ("man 4 tty") and ioctl(2) ("man 2 ioctl") for details.
439 
440  if (ioctl(t_fd, TIOCSDTR) == -1) // Assert Data Terminal Ready (DTR)
441  {
442  DEBUGFDEVICE(m_DriverName, m_DebugChannel, "Error asserting DTR %s - %s(%d).", device, strerror(errno), errno);
443  }
444 
445  if (ioctl(t_fd, TIOCCDTR) == -1) // Clear Data Terminal Ready (DTR)
446  {
447  DEBUGFDEVICE(m_DriverName, m_DebugChannel, "Error clearing DTR %s - %s(%d).", device, strerror(errno), errno);
448  }
449 
450  handshake = TIOCM_DTR | TIOCM_RTS | TIOCM_CTS | TIOCM_DSR;
451  if (ioctl(t_fd, TIOCMSET, &handshake) == -1)
452  // Set the modem lines depending on the bits set in handshake
453  {
454  DEBUGFDEVICE(m_DriverName, m_DebugChannel, "Error setting handshake lines %s - %s(%d).", device, strerror(errno), errno);
455  }
456 
457  // To read the state of the modem lines, use the following ioctl.
458  // See tty(4) ("man 4 tty") and ioctl(2) ("man 2 ioctl") for details.
459 
460  if (ioctl(t_fd, TIOCMGET, &handshake) == -1)
461  // Store the state of the modem lines in handshake
462  {
463  DEBUGFDEVICE(m_DriverName, m_DebugChannel, "Error getting handshake lines %s - %s(%d).", device, strerror(errno), errno);
464  }
465 
466  DEBUGFDEVICE(m_DriverName, m_DebugChannel, "Handshake lines currently set to %d", handshake);
467 
468 #if defined(MAC_OS_X_VERSION_10_3) && (MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_3)
469  unsigned long mics = 1UL;
470 
471  // Set the receive latency in microseconds. Serial drivers use this value to determine how often to
472  // dequeue characters received by the hardware. Most applications don't need to set this value: if an
473  // app reads lines of characters, the app can't do anything until the line termination character has been
474  // received anyway. The most common applications which are sensitive to read latency are MIDI and IrDA
475  // applications.
476 
477  if (ioctl(t_fd, IOSSDATALAT, &mics) == -1)
478  {
479  // set latency to 1 microsecond
480  DEBUGFDEVICE(m_DriverName, m_DebugChannel, "Error setting read latency %s - %s(%d).\n", device, strerror(errno), errno);
481  goto error;
482  }
483 #endif
484 
485  m_PortFD = t_fd;
486  /* return success */
487  return TTY_OK;
488 
489  // Failure path
490 error:
491  if (t_fd != -1)
492  {
493  close(t_fd);
494  m_PortFD = -1;
495  }
496 
497  return TTY_PORT_FAILURE;
498 }
499 #else
500 TTYBase::TTY_RESPONSE TTYBase::connect(const char *device, uint32_t bit_rate, uint8_t word_size, uint8_t parity,
501  uint8_t stop_bits)
502 {
503 #ifdef _WIN32
504  return TTY_PORT_FAILURE;
505 
506 #else
507  int t_fd = -1;
508  int bps;
509  struct termios tty_setting;
510 
511  if ((t_fd = open(device, O_RDWR | O_NOCTTY)) == -1)
512  {
513  m_PortFD = -1;
514 
515  return TTY_PORT_FAILURE;
516  }
517 
518  // Get the current options and save them so we can restore the default settings later.
519  if (tcgetattr(t_fd, &tty_setting) == -1)
520  {
521  DEBUGDEVICE(m_DriverName, m_DebugChannel, "connect: failed getting tty attributes.");
522  return TTY_PORT_FAILURE;
523  }
524 
525  /* Control Modes
526  Set bps rate */
527  switch (bit_rate)
528  {
529  case 0:
530  bps = B0;
531  break;
532  case 50:
533  bps = B50;
534  break;
535  case 75:
536  bps = B75;
537  break;
538  case 110:
539  bps = B110;
540  break;
541  case 134:
542  bps = B134;
543  break;
544  case 150:
545  bps = B150;
546  break;
547  case 200:
548  bps = B200;
549  break;
550  case 300:
551  bps = B300;
552  break;
553  case 600:
554  bps = B600;
555  break;
556  case 1200:
557  bps = B1200;
558  break;
559  case 1800:
560  bps = B1800;
561  break;
562  case 2400:
563  bps = B2400;
564  break;
565  case 4800:
566  bps = B4800;
567  break;
568  case 9600:
569  bps = B9600;
570  break;
571  case 19200:
572  bps = B19200;
573  break;
574  case 38400:
575  bps = B38400;
576  break;
577  case 57600:
578  bps = B57600;
579  break;
580  case 115200:
581  bps = B115200;
582  break;
583  case 230400:
584  bps = B230400;
585  break;
586  default:
587  DEBUGFDEVICE(m_DriverName, m_DebugChannel, "connect: %d is not a valid bit rate.", bit_rate);
588  return TTY_PARAM_ERROR;
589  }
590  if ((cfsetispeed(&tty_setting, bps) < 0) || (cfsetospeed(&tty_setting, bps) < 0))
591  {
592  perror("connect: failed setting bit rate.");
593  return TTY_PORT_FAILURE;
594  }
595 
596  /* Control Modes
597  set no flow control word size, parity and stop bits.
598  Also don't hangup automatically and ignore modem status.
599  Finally enable receiving characters. */
600  tty_setting.c_cflag &= ~(CSIZE | CSTOPB | PARENB | PARODD | HUPCL | CRTSCTS);
601  tty_setting.c_cflag |= (CLOCAL | CREAD);
602 
603  /* word size */
604  switch (word_size)
605  {
606  case 5:
607  tty_setting.c_cflag |= CS5;
608  break;
609  case 6:
610  tty_setting.c_cflag |= CS6;
611  break;
612  case 7:
613  tty_setting.c_cflag |= CS7;
614  break;
615  case 8:
616  tty_setting.c_cflag |= CS8;
617  break;
618  default:
619  DEBUGFDEVICE(m_DriverName, m_DebugChannel, "connect: %d is not a valid data bit count.", word_size);
620  return TTY_PARAM_ERROR;
621  }
622 
623  /* parity */
624  switch (parity)
625  {
626  case PARITY_NONE:
627  break;
628  case PARITY_EVEN:
629  tty_setting.c_cflag |= PARENB;
630  break;
631  case PARITY_ODD:
632  tty_setting.c_cflag |= PARENB | PARODD;
633  break;
634  default:
635  DEBUGFDEVICE(m_DriverName, m_DebugChannel, "connect: %d is not a valid parity selection value.", parity);
636  return TTY_PARAM_ERROR;
637  }
638 
639  /* stop_bits */
640  switch (stop_bits)
641  {
642  case 1:
643  break;
644  case 2:
645  tty_setting.c_cflag |= CSTOPB;
646  break;
647  default:
648  DEBUGFDEVICE(m_DriverName, m_DebugChannel, "connect: %d is not a valid stop bit count.", stop_bits);
649  return TTY_PARAM_ERROR;
650  }
651  /* Control Modes complete */
652 
653  /* Ignore bytes with parity errors and make terminal raw and dumb.*/
654  tty_setting.c_iflag &= ~(PARMRK | ISTRIP | IGNCR | ICRNL | INLCR | IXOFF | IXON | IXANY);
655  tty_setting.c_iflag |= INPCK | IGNPAR | IGNBRK;
656 
657  /* Raw output.*/
658  tty_setting.c_oflag &= ~(OPOST | ONLCR);
659 
660  /* Local Modes
661  Don't echo characters. Don't generate signals.
662  Don't process any characters.*/
663  tty_setting.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG | IEXTEN | NOFLSH | TOSTOP);
664  tty_setting.c_lflag |= NOFLSH;
665 
666  /* blocking read until 1 char arrives */
667  tty_setting.c_cc[VMIN] = 1;
668  tty_setting.c_cc[VTIME] = 0;
669 
670  /* now clear input and output buffers and activate the new terminal settings */
671  tcflush(t_fd, TCIOFLUSH);
672  if (tcsetattr(t_fd, TCSANOW, &tty_setting))
673  {
674  DEBUGDEVICE(m_DriverName, m_DebugChannel, "connect: failed setting attributes on serial port.");
675  close(t_fd);
676  return TTY_PORT_FAILURE;
677  }
678 
679  m_PortFD = t_fd;
680  /* return success */
681  return TTY_OK;
682 #endif
683 }
684 // Unix - Linux version
685 
686 #endif
687 
689 {
690  if (m_PortFD == -1)
691  return TTY_ERRNO;
692 
693 #ifdef _WIN32
694  return TTY_ERRNO;
695 #else
696  tcflush(m_PortFD, TCIOFLUSH);
697  int err = close(m_PortFD);
698 
699  if (err != 0)
700  return TTY_ERRNO;
701 
702  return TTY_OK;
703 #endif
704 }
705 
706 const std::string TTYBase::error(TTY_RESPONSE code) const
707 {
708  char error_string[512] = {0};
709 
710  switch (code)
711  {
712  case TTY_OK:
713  return "No Error";
714 
715  case TTY_READ_ERROR:
716  snprintf(error_string, 512, "Read Error: %s", strerror(errno));
717  return error_string;
718 
719  case TTY_WRITE_ERROR:
720  snprintf(error_string, 512, "Write Error: %s", strerror(errno));
721  return error_string;
722 
723  case TTY_SELECT_ERROR:
724  snprintf(error_string, 512, "Select Error: %s", strerror(errno));
725  return error_string;
726 
727  case TTY_TIME_OUT:
728  return "Timeout error";
729 
730  case TTY_PORT_FAILURE:
731  if (errno == EACCES)
732  snprintf(error_string, 512,
733  "Port failure Error: %s. Try adding your user to the dialout group and restart (sudo adduser "
734  "$USER dialout)",
735  strerror(errno));
736  else
737  snprintf(error_string, 512, "Port failure Error: %s. Check if device is connected to this port.",
738  strerror(errno));
739  return error_string;
740 
741  case TTY_PARAM_ERROR:
742  return "Parameter error";
743 
744 
745  case TTY_ERRNO:
746  snprintf(error_string, 512, "%s", strerror(errno));
747  return error_string;
748 
749  case TTY_OVERFLOW:
750  return "Read overflow";
751  }
752 
753  return "Error: unrecognized error code";
754 }
755 
756 #if defined(_MSC_VER)
757 #undef snprintf
758 #pragma warning(pop)
759 #endif
hid_device * device
TTY_RESPONSE read(uint8_t *buffer, uint32_t nbytes, uint8_t timeout, uint32_t *nbytes_read)
read buffer from terminal
Definition: ttybase.cpp:158
TTYBase(const char *driverName)
Definition: ttybase.cpp:73
const std::string error(TTY_RESPONSE code) const
Retrieve the tty error message.
Definition: ttybase.cpp:706
TTY_RESPONSE writeString(const char *string, uint32_t *nbytes_written)
Writes a null terminated string to fd.
Definition: ttybase.cpp:152
virtual ~TTYBase()
Definition: ttybase.cpp:78
TTY_RESPONSE readSection(uint8_t *buffer, uint32_t nsize, uint8_t stop_byte, uint8_t timeout, uint32_t *nbytes_read)
read buffer from terminal with a delimiter
Definition: ttybase.cpp:202
TTY_RESPONSE disconnect()
Closes a tty connection and flushes the bus.
Definition: ttybase.cpp:688
TTY_RESPONSE
Definition: ttybase.h:46
@ TTY_PORT_FAILURE
Definition: ttybase.h:52
@ TTY_OK
Definition: ttybase.h:47
@ TTY_READ_ERROR
Definition: ttybase.h:48
@ TTY_WRITE_ERROR
Definition: ttybase.h:49
@ TTY_TIME_OUT
Definition: ttybase.h:51
@ TTY_PARAM_ERROR
Definition: ttybase.h:53
@ TTY_SELECT_ERROR
Definition: ttybase.h:50
@ TTY_ERRNO
Definition: ttybase.h:54
@ TTY_OVERFLOW
Definition: ttybase.h:55
TTY_RESPONSE write(const uint8_t *buffer, uint32_t nbytes, uint32_t *nbytes_written)
Writes a buffer to fd.
Definition: ttybase.cpp:121
TTY_RESPONSE connect(const char *device, uint32_t bit_rate, uint8_t word_size, uint8_t parity, uint8_t stop_bits)
Establishes a tty connection to a terminal device.
Definition: ttybase.cpp:500
int errno
void IDLog(const char *fmt,...)
Definition: indicom.c:316
#define INDI_UNUSED(x)
Definition: indidevapi.h:131
#define DEBUGDEVICE(device, priority, msg)
Definition: indilogger.h:60
#define DEBUGFDEVICE(device, priority, msg,...)
Definition: indilogger.h:61
std::vector< uint8_t > buffer
struct termios tty_setting
Definition: stvdriver.c:51
#define PARITY_ODD
Definition: ttybase.cpp:63
#define PARITY_EVEN
Definition: ttybase.cpp:62
#define PARITY_NONE
Definition: ttybase.cpp:61