Instrument Neutral Distributed Interface INDI 2.2.5
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
73TTYBase::TTYBase(const char *driverName) : m_DriverName(driverName)
74{
75
76}
77
79{
80 if (m_PortFD != -1)
81 disconnect();
82}
83
84TTYBase::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
121TTYBase::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
152TTYBase::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
158TTYBase::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 int zero_read_count = 0;
170 const int MAX_ZERO_READS = 3;
171 TTY_RESPONSE timeoutResponse = TTY_OK;
172 *nbytes_read = 0;
173
174 if (nbytes <= 0)
175 return TTY_PARAM_ERROR;
176
177 DEBUGFDEVICE(m_DriverName, m_DebugChannel, "%s: Request to read %d bytes with %d timeout for m_PortFD %d", __FUNCTION__,
178 nbytes, timeout, m_PortFD);
179
180 while (numBytesToRead > 0)
181 {
182 if ((timeoutResponse = checkTimeout(timeout)))
183 return timeoutResponse;
184
185 bytesRead = ::read(m_PortFD, buffer + (*nbytes_read), numBytesToRead);
186
187 if (bytesRead < 0)
188 return TTY_READ_ERROR;
189
190 if (bytesRead == 0)
191 {
192 zero_read_count++;
193 if (zero_read_count >= MAX_ZERO_READS)
194 {
195 DEBUGFDEVICE(m_DriverName, m_DebugChannel,
196 "%s: Device not responding (zero bytes read %d times)", __FUNCTION__, MAX_ZERO_READS);
197 return TTY_READ_ERROR;
198 }
199 usleep(10000); // 10ms delay before retry
200 continue;
201 }
202
203 zero_read_count = 0; // Reset counter on successful read
204
205 DEBUGFDEVICE(m_DriverName, m_DebugChannel, "%d bytes read and %d bytes remaining...", bytesRead,
206 numBytesToRead - bytesRead);
207 for (uint32_t i = *nbytes_read; i < (*nbytes_read + bytesRead); i++)
208 DEBUGFDEVICE(m_DriverName, m_DebugChannel, "%s: buffer[%d]=%#X (%c)", __FUNCTION__, i, buffer[i], buffer[i]);
209
210 *nbytes_read += bytesRead;
211 numBytesToRead -= bytesRead;
212 }
213
214 return TTY_OK;
215
216#endif
217}
218
219TTYBase::TTY_RESPONSE TTYBase::readSection(uint8_t *buffer, uint32_t nsize, uint8_t stop_byte, uint8_t timeout,
220 uint32_t *nbytes_read)
221{
222#ifdef _WIN32
223 return TTY_ERRNO;
224#else
225
226 if (m_PortFD == -1)
227 return TTY_ERRNO;
228
229 int bytesRead = 0;
230 int zero_read_count = 0;
231 const int MAX_ZERO_READS = 3;
232 TTY_RESPONSE timeoutResponse = TTY_OK;
233 *nbytes_read = 0;
234 memset(buffer, 0, nsize);
235
236 uint8_t *read_char = nullptr;
237
238 DEBUGFDEVICE(m_DriverName, m_DebugChannel, "%s: Request to read until stop char '%#02X' with %d timeout for m_PortFD %d",
239 __FUNCTION__, stop_byte, timeout, m_PortFD);
240
241 for (;;)
242 {
243 if ((timeoutResponse = checkTimeout(timeout)))
244 return timeoutResponse;
245
246 read_char = reinterpret_cast<uint8_t*>(buffer + *nbytes_read);
247 bytesRead = ::read(m_PortFD, read_char, 1);
248
249 if (bytesRead < 0)
250 return TTY_READ_ERROR;
251
252 if (bytesRead == 0)
253 {
254 zero_read_count++;
255 if (zero_read_count >= MAX_ZERO_READS)
256 {
257 DEBUGFDEVICE(m_DriverName, m_DebugChannel,
258 "%s: Device not responding (zero bytes read %d times)", __FUNCTION__, MAX_ZERO_READS);
259 return TTY_READ_ERROR;
260 }
261 usleep(10000); // 10ms delay before retry
262 continue;
263 }
264
265 zero_read_count = 0; // Reset counter on successful read
266
267 DEBUGFDEVICE(m_DriverName, m_DebugChannel, "%s: buffer[%d]=%#X (%c)", __FUNCTION__, (*nbytes_read), *read_char, *read_char);
268
269 (*nbytes_read)++;
270
271 if (*read_char == stop_byte)
272 return TTY_OK;
273 else if (*nbytes_read >= nsize)
274 return TTY_OVERFLOW;
275 }
276
277#endif
278}
279
280#if defined(BSD) && !defined(__GNU__)
281// BSD - OSX version
282TTYBase::TTY_RESPONSE TTYBase::connect(const char *device, uint32_t bit_rate, uint8_t word_size, uint8_t parity,
283 uint8_t stop_bits)
284{
285 int t_fd = -1;
286 int bps;
287 int handshake;
288 struct termios tty_setting;
289
290 // Open the serial port read/write, with no controlling terminal, and don't wait for a connection.
291 // The O_NONBLOCK flag also causes subsequent I/O on the device to be non-blocking.
292 // See open(2) ("man 2 open") for details.
293
294 t_fd = open(device, O_RDWR | O_NOCTTY | O_NONBLOCK);
295 if (t_fd == -1)
296 {
297 DEBUGFDEVICE(m_DriverName, m_DebugChannel, "Error opening serial port (%s) - %s(%d).", device, strerror(errno), errno);
298 goto error;
299 }
300
301 // Note that open() follows POSIX semantics: multiple open() calls to the same file will succeed
302 // unless the TIOCEXCL ioctl is issued. This will prevent additional opens except by root-owned
303 // processes.
304 // See tty(4) ("man 4 tty") and ioctl(2) ("man 2 ioctl") for details.
305
306 if (ioctl(t_fd, TIOCEXCL) == -1)
307 {
308 DEBUGFDEVICE(m_DriverName, m_DebugChannel, "Error setting TIOCEXCL on %s - %s(%d).", device, strerror(errno), errno);
309 goto error;
310 }
311
312 // Now that the device is open, clear the O_NONBLOCK flag so subsequent I/O will block.
313 // See fcntl(2) ("man 2 fcntl") for details.
314
315 if (fcntl(t_fd, F_SETFL, 0) == -1)
316 {
317 DEBUGFDEVICE(m_DriverName, m_DebugChannel, "Error clearing O_NONBLOCK %s - %s(%d).", device, strerror(errno), errno);
318 goto error;
319 }
320
321 // Get the current options and save them so we can restore the default settings later.
322 if (tcgetattr(t_fd, &tty_setting) == -1)
323 {
324 DEBUGFDEVICE(m_DriverName, m_DebugChannel, "Error getting tty attributes %s - %s(%d).", device, strerror(errno), errno);
325 goto error;
326 }
327
328 // Set raw input (non-canonical) mode, with reads blocking until either a single character
329 // has been received or a one second timeout expires.
330 // See tcsetattr(4) ("man 4 tcsetattr") and termios(4) ("man 4 termios") for details.
331
332 cfmakeraw(&tty_setting);
333 tty_setting.c_cc[VMIN] = 1;
334 tty_setting.c_cc[VTIME] = 10;
335
336 // The baud rate, word length, and handshake options can be set as follows:
337 switch (bit_rate)
338 {
339 case 0:
340 bps = B0;
341 break;
342 case 50:
343 bps = B50;
344 break;
345 case 75:
346 bps = B75;
347 break;
348 case 110:
349 bps = B110;
350 break;
351 case 134:
352 bps = B134;
353 break;
354 case 150:
355 bps = B150;
356 break;
357 case 200:
358 bps = B200;
359 break;
360 case 300:
361 bps = B300;
362 break;
363 case 600:
364 bps = B600;
365 break;
366 case 1200:
367 bps = B1200;
368 break;
369 case 1800:
370 bps = B1800;
371 break;
372 case 2400:
373 bps = B2400;
374 break;
375 case 4800:
376 bps = B4800;
377 break;
378 case 9600:
379 bps = B9600;
380 break;
381 case 19200:
382 bps = B19200;
383 break;
384 case 38400:
385 bps = B38400;
386 break;
387 case 57600:
388 bps = B57600;
389 break;
390 case 115200:
391 bps = B115200;
392 break;
393 case 230400:
394 bps = B230400;
395 break;
396 default:
397 DEBUGFDEVICE(m_DriverName, m_DebugChannel, "connect: %d is not a valid bit rate.", bit_rate);
398 return TTY_PARAM_ERROR;
399 }
400
401 cfsetspeed(&tty_setting, bps); // Set baud rate
402 /* word size */
403 switch (word_size)
404 {
405 case 5:
406 tty_setting.c_cflag |= CS5;
407 break;
408 case 6:
409 tty_setting.c_cflag |= CS6;
410 break;
411 case 7:
412 tty_setting.c_cflag |= CS7;
413 break;
414 case 8:
415 tty_setting.c_cflag |= CS8;
416 break;
417 default:
418 DEBUGFDEVICE(m_DriverName, m_DebugChannel, "connect: %d is not a valid data bit count.", word_size);
419 return TTY_PARAM_ERROR;
420 }
421
422 /* parity */
423 switch (parity)
424 {
425 case PARITY_NONE:
426 break;
427 case PARITY_EVEN:
428 tty_setting.c_cflag |= PARENB;
429 break;
430 case PARITY_ODD:
431 tty_setting.c_cflag |= PARENB | PARODD;
432 break;
433 default:
434 DEBUGFDEVICE(m_DriverName, m_DebugChannel, "connect: %d is not a valid parity selection value.", parity);
435 return TTY_PARAM_ERROR;
436 }
437
438 /* stop_bits */
439 switch (stop_bits)
440 {
441 case 1:
442 break;
443 case 2:
444 tty_setting.c_cflag |= CSTOPB;
445 break;
446 default:
447 DEBUGFDEVICE(m_DriverName, m_DebugChannel, "connect: %d is not a valid stop bit count.", stop_bits);
448 return TTY_PARAM_ERROR;
449 }
450
451#if defined(MAC_OS_X_VERSION_10_4) && (MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_4)
452 // Starting with Tiger, the IOSSIOSPEED ioctl can be used to set arbitrary baud rates
453 // other than those specified by POSIX. The driver for the underlying serial hardware
454 // ultimately determines which baud rates can be used. This ioctl sets both the input
455 // and output speed.
456
457 speed_t speed = 14400; // Set 14400 baud
458 if (ioctl(t_fd, IOSSIOSPEED, &speed) == -1)
459 {
460 IDLog("Error calling ioctl(..., IOSSIOSPEED, ...) - %s(%d).\n", strerror(errno), errno);
461 }
462#endif
463
464 // Cause the new options to take effect immediately.
465 if (tcsetattr(t_fd, TCSANOW, &tty_setting) == -1)
466 {
467 DEBUGFDEVICE(m_DriverName, m_DebugChannel, "Error setting tty attributes %s - %s(%d).", device, strerror(errno), errno);
468 goto error;
469 }
470
471 // To set the modem handshake lines, use the following ioctls.
472 // See tty(4) ("man 4 tty") and ioctl(2) ("man 2 ioctl") for details.
473
474 if (ioctl(t_fd, TIOCSDTR) == -1) // Assert Data Terminal Ready (DTR)
475 {
476 DEBUGFDEVICE(m_DriverName, m_DebugChannel, "Error asserting DTR %s - %s(%d).", device, strerror(errno), errno);
477 }
478
479 if (ioctl(t_fd, TIOCCDTR) == -1) // Clear Data Terminal Ready (DTR)
480 {
481 DEBUGFDEVICE(m_DriverName, m_DebugChannel, "Error clearing DTR %s - %s(%d).", device, strerror(errno), errno);
482 }
483
484 handshake = TIOCM_DTR | TIOCM_RTS | TIOCM_CTS | TIOCM_DSR;
485 if (ioctl(t_fd, TIOCMSET, &handshake) == -1)
486 // Set the modem lines depending on the bits set in handshake
487 {
488 DEBUGFDEVICE(m_DriverName, m_DebugChannel, "Error setting handshake lines %s - %s(%d).", device, strerror(errno), errno);
489 }
490
491 // To read the state of the modem lines, use the following ioctl.
492 // See tty(4) ("man 4 tty") and ioctl(2) ("man 2 ioctl") for details.
493
494 if (ioctl(t_fd, TIOCMGET, &handshake) == -1)
495 // Store the state of the modem lines in handshake
496 {
497 DEBUGFDEVICE(m_DriverName, m_DebugChannel, "Error getting handshake lines %s - %s(%d).", device, strerror(errno), errno);
498 }
499
500 DEBUGFDEVICE(m_DriverName, m_DebugChannel, "Handshake lines currently set to %d", handshake);
501
502#if defined(MAC_OS_X_VERSION_10_3) && (MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_3)
503 unsigned long mics = 1UL;
504
505 // Set the receive latency in microseconds. Serial drivers use this value to determine how often to
506 // dequeue characters received by the hardware. Most applications don't need to set this value: if an
507 // app reads lines of characters, the app can't do anything until the line termination character has been
508 // received anyway. The most common applications which are sensitive to read latency are MIDI and IrDA
509 // applications.
510
511 if (ioctl(t_fd, IOSSDATALAT, &mics) == -1)
512 {
513 // set latency to 1 microsecond
514 DEBUGFDEVICE(m_DriverName, m_DebugChannel, "Error setting read latency %s - %s(%d).\n", device, strerror(errno), errno);
515 goto error;
516 }
517#endif
518
519 m_PortFD = t_fd;
520 /* return success */
521 return TTY_OK;
522
523 // Failure path
524error:
525 if (t_fd != -1)
526 {
527 close(t_fd);
528 m_PortFD = -1;
529 }
530
531 return TTY_PORT_FAILURE;
532}
533#else
534TTYBase::TTY_RESPONSE TTYBase::connect(const char *device, uint32_t bit_rate, uint8_t word_size, uint8_t parity,
535 uint8_t stop_bits)
536{
537#ifdef _WIN32
538 return TTY_PORT_FAILURE;
539
540#else
541 int t_fd = -1;
542 int bps;
543 struct termios tty_setting;
544
545 if ((t_fd = open(device, O_RDWR | O_NOCTTY)) == -1)
546 {
547 m_PortFD = -1;
548
549 return TTY_PORT_FAILURE;
550 }
551
552 // Get the current options and save them so we can restore the default settings later.
553 if (tcgetattr(t_fd, &tty_setting) == -1)
554 {
555 DEBUGDEVICE(m_DriverName, m_DebugChannel, "connect: failed getting tty attributes.");
556 return TTY_PORT_FAILURE;
557 }
558
559 /* Control Modes
560 Set bps rate */
561 switch (bit_rate)
562 {
563 case 0:
564 bps = B0;
565 break;
566 case 50:
567 bps = B50;
568 break;
569 case 75:
570 bps = B75;
571 break;
572 case 110:
573 bps = B110;
574 break;
575 case 134:
576 bps = B134;
577 break;
578 case 150:
579 bps = B150;
580 break;
581 case 200:
582 bps = B200;
583 break;
584 case 300:
585 bps = B300;
586 break;
587 case 600:
588 bps = B600;
589 break;
590 case 1200:
591 bps = B1200;
592 break;
593 case 1800:
594 bps = B1800;
595 break;
596 case 2400:
597 bps = B2400;
598 break;
599 case 4800:
600 bps = B4800;
601 break;
602 case 9600:
603 bps = B9600;
604 break;
605 case 19200:
606 bps = B19200;
607 break;
608 case 38400:
609 bps = B38400;
610 break;
611 case 57600:
612 bps = B57600;
613 break;
614 case 115200:
615 bps = B115200;
616 break;
617 case 230400:
618 bps = B230400;
619 break;
620 default:
621 DEBUGFDEVICE(m_DriverName, m_DebugChannel, "connect: %d is not a valid bit rate.", bit_rate);
622 return TTY_PARAM_ERROR;
623 }
624 if ((cfsetispeed(&tty_setting, bps) < 0) || (cfsetospeed(&tty_setting, bps) < 0))
625 {
626 perror("connect: failed setting bit rate.");
627 return TTY_PORT_FAILURE;
628 }
629
630 /* Control Modes
631 set no flow control word size, parity and stop bits.
632 Also don't hangup automatically and ignore modem status.
633 Finally enable receiving characters. */
634 tty_setting.c_cflag &= ~(CSIZE | CSTOPB | PARENB | PARODD | HUPCL | CRTSCTS);
635 tty_setting.c_cflag |= (CLOCAL | CREAD);
636
637 /* word size */
638 switch (word_size)
639 {
640 case 5:
641 tty_setting.c_cflag |= CS5;
642 break;
643 case 6:
644 tty_setting.c_cflag |= CS6;
645 break;
646 case 7:
647 tty_setting.c_cflag |= CS7;
648 break;
649 case 8:
650 tty_setting.c_cflag |= CS8;
651 break;
652 default:
653 DEBUGFDEVICE(m_DriverName, m_DebugChannel, "connect: %d is not a valid data bit count.", word_size);
654 return TTY_PARAM_ERROR;
655 }
656
657 /* parity */
658 switch (parity)
659 {
660 case PARITY_NONE:
661 break;
662 case PARITY_EVEN:
663 tty_setting.c_cflag |= PARENB;
664 break;
665 case PARITY_ODD:
666 tty_setting.c_cflag |= PARENB | PARODD;
667 break;
668 default:
669 DEBUGFDEVICE(m_DriverName, m_DebugChannel, "connect: %d is not a valid parity selection value.", parity);
670 return TTY_PARAM_ERROR;
671 }
672
673 /* stop_bits */
674 switch (stop_bits)
675 {
676 case 1:
677 break;
678 case 2:
679 tty_setting.c_cflag |= CSTOPB;
680 break;
681 default:
682 DEBUGFDEVICE(m_DriverName, m_DebugChannel, "connect: %d is not a valid stop bit count.", stop_bits);
683 return TTY_PARAM_ERROR;
684 }
685 /* Control Modes complete */
686
687 /* Ignore bytes with parity errors and make terminal raw and dumb.*/
688 tty_setting.c_iflag &= ~(PARMRK | ISTRIP | IGNCR | ICRNL | INLCR | IXOFF | IXON | IXANY);
689 tty_setting.c_iflag |= INPCK | IGNPAR | IGNBRK;
690
691 /* Raw output.*/
692 tty_setting.c_oflag &= ~(OPOST | ONLCR);
693
694 /* Local Modes
695 Don't echo characters. Don't generate signals.
696 Don't process any characters.*/
697 tty_setting.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG | IEXTEN | NOFLSH | TOSTOP);
698 tty_setting.c_lflag |= NOFLSH;
699
700 /* blocking read until 1 char arrives */
701 tty_setting.c_cc[VMIN] = 1;
702 tty_setting.c_cc[VTIME] = 0;
703
704 /* now clear input and output buffers and activate the new terminal settings */
705 tcflush(t_fd, TCIOFLUSH);
706 if (tcsetattr(t_fd, TCSANOW, &tty_setting))
707 {
708 DEBUGDEVICE(m_DriverName, m_DebugChannel, "connect: failed setting attributes on serial port.");
709 close(t_fd);
710 return TTY_PORT_FAILURE;
711 }
712
713 m_PortFD = t_fd;
714 /* return success */
715 return TTY_OK;
716#endif
717}
718// Unix - Linux version
719
720#endif
721
723{
724 if (m_PortFD == -1)
725 return TTY_ERRNO;
726
727#ifdef _WIN32
728 return TTY_ERRNO;
729#else
730 tcflush(m_PortFD, TCIOFLUSH);
731 int err = close(m_PortFD);
732
733 if (err != 0)
734 return TTY_ERRNO;
735
736 return TTY_OK;
737#endif
738}
739
740const std::string TTYBase::error(TTY_RESPONSE code) const
741{
742 char error_string[512] = {0};
743
744 switch (code)
745 {
746 case TTY_OK:
747 return "No Error";
748
749 case TTY_READ_ERROR:
750 snprintf(error_string, 512, "Read Error: %s", strerror(errno));
751 return error_string;
752
753 case TTY_WRITE_ERROR:
754 snprintf(error_string, 512, "Write Error: %s", strerror(errno));
755 return error_string;
756
757 case TTY_SELECT_ERROR:
758 snprintf(error_string, 512, "Select Error: %s", strerror(errno));
759 return error_string;
760
761 case TTY_TIME_OUT:
762 return "Timeout error";
763
764 case TTY_PORT_FAILURE:
765 if (errno == EACCES)
766 snprintf(error_string, 512,
767 "Port failure Error: %s. Try adding your user to the dialout group and restart (sudo adduser "
768 "$USER dialout)",
769 strerror(errno));
770 else
771 snprintf(error_string, 512, "Port failure Error: %s. Check if device is connected to this port.",
772 strerror(errno));
773 return error_string;
774
775 case TTY_PARAM_ERROR:
776 return "Parameter error";
777
778
779 case TTY_ERRNO:
780 snprintf(error_string, 512, "%s", strerror(errno));
781 return error_string;
782
783 case TTY_OVERFLOW:
784 return "Read overflow";
785 }
786
787 return "Error: unrecognized error code";
788}
789
790#if defined(_MSC_VER)
791#undef snprintf
792#pragma warning(pop)
793#endif
#define PARITY_ODD
Definition Lx.cpp:14
#define PARITY_EVEN
Definition Lx.cpp:13
#define PARITY_NONE
Definition Lx.cpp:12
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:740
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:219
TTY_RESPONSE disconnect()
Closes a tty connection and flushes the bus.
Definition ttybase.cpp:722
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:534
int errno
void IDLog(const char *fmt,...)
Definition indicom.c:305
#define INDI_UNUSED(x)
Definition indidevapi.h:132
#define DEBUGDEVICE(device, priority, msg)
Definition indilogger.h:60
#define DEBUGFDEVICE(device, priority, msg,...)
Definition indilogger.h:61
struct termios tty_setting
Definition stvdriver.c:51