47#if defined(BSD) && !defined(__GNU__)
48#include <IOKit/serial/ioss.h>
67#define snprintf _snprintf
70#pragma warning(disable : 4996)
86#if defined(_WIN32) || defined(ANDROID)
99 FD_SET(m_PortFD, &readout);
106 retval = select(m_PortFD + 1, &readout,
nullptr,
nullptr, &tv);
112 else if (retval == -1)
135 bytes_w =
::write(m_PortFD, buffer + (*nbytes_written), nbytes);
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]);
143 *nbytes_written += bytes_w;
154 uint32_t nbytes = strlen(
string);
155 return write(
reinterpret_cast<const uint8_t*
>(
string), nbytes, nbytes_written);
167 uint32_t numBytesToRead = nbytes;
169 int zero_read_count = 0;
170 const int MAX_ZERO_READS = 3;
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);
180 while (numBytesToRead > 0)
182 if ((timeoutResponse = checkTimeout(timeout)))
183 return timeoutResponse;
185 bytesRead =
::read(m_PortFD, buffer + (*nbytes_read), numBytesToRead);
193 if (zero_read_count >= MAX_ZERO_READS)
196 "%s: Device not responding (zero bytes read %d times)", __FUNCTION__, MAX_ZERO_READS);
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]);
210 *nbytes_read += bytesRead;
211 numBytesToRead -= bytesRead;
220 uint32_t *nbytes_read)
230 int zero_read_count = 0;
231 const int MAX_ZERO_READS = 3;
234 memset(buffer, 0, nsize);
236 uint8_t *read_char =
nullptr;
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);
243 if ((timeoutResponse = checkTimeout(timeout)))
244 return timeoutResponse;
246 read_char =
reinterpret_cast<uint8_t*
>(buffer + *nbytes_read);
247 bytesRead =
::read(m_PortFD, read_char, 1);
255 if (zero_read_count >= MAX_ZERO_READS)
258 "%s: Device not responding (zero bytes read %d times)", __FUNCTION__, MAX_ZERO_READS);
267 DEBUGFDEVICE(m_DriverName, m_DebugChannel,
"%s: buffer[%d]=%#X (%c)", __FUNCTION__, (*nbytes_read), *read_char, *read_char);
271 if (*read_char == stop_byte)
273 else if (*nbytes_read >= nsize)
280#if defined(BSD) && !defined(__GNU__)
294 t_fd = open(
device, O_RDWR | O_NOCTTY | O_NONBLOCK);
306 if (ioctl(t_fd, TIOCEXCL) == -1)
315 if (fcntl(t_fd, F_SETFL, 0) == -1)
397 DEBUGFDEVICE(m_DriverName, m_DebugChannel,
"connect: %d is not a valid bit rate.", bit_rate);
418 DEBUGFDEVICE(m_DriverName, m_DebugChannel,
"connect: %d is not a valid data bit count.", word_size);
434 DEBUGFDEVICE(m_DriverName, m_DebugChannel,
"connect: %d is not a valid parity selection value.", parity);
447 DEBUGFDEVICE(m_DriverName, m_DebugChannel,
"connect: %d is not a valid stop bit count.", stop_bits);
451#if defined(MAC_OS_X_VERSION_10_4) && (MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_4)
457 speed_t speed = 14400;
458 if (ioctl(t_fd, IOSSIOSPEED, &speed) == -1)
460 IDLog(
"Error calling ioctl(..., IOSSIOSPEED, ...) - %s(%d).\n", strerror(
errno),
errno);
474 if (ioctl(t_fd, TIOCSDTR) == -1)
479 if (ioctl(t_fd, TIOCCDTR) == -1)
484 handshake = TIOCM_DTR | TIOCM_RTS | TIOCM_CTS | TIOCM_DSR;
485 if (ioctl(t_fd, TIOCMSET, &handshake) == -1)
494 if (ioctl(t_fd, TIOCMGET, &handshake) == -1)
500 DEBUGFDEVICE(m_DriverName, m_DebugChannel,
"Handshake lines currently set to %d", handshake);
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;
511 if (ioctl(t_fd, IOSSDATALAT, &mics) == -1)
545 if ((t_fd = open(
device, O_RDWR | O_NOCTTY)) == -1)
555 DEBUGDEVICE(m_DriverName, m_DebugChannel,
"connect: failed getting tty attributes.");
621 DEBUGFDEVICE(m_DriverName, m_DebugChannel,
"connect: %d is not a valid bit rate.", bit_rate);
626 perror(
"connect: failed setting bit rate.");
634 tty_setting.c_cflag &= ~(CSIZE | CSTOPB | PARENB | PARODD | HUPCL | CRTSCTS);
653 DEBUGFDEVICE(m_DriverName, m_DebugChannel,
"connect: %d is not a valid data bit count.", word_size);
669 DEBUGFDEVICE(m_DriverName, m_DebugChannel,
"connect: %d is not a valid parity selection value.", parity);
682 DEBUGFDEVICE(m_DriverName, m_DebugChannel,
"connect: %d is not a valid stop bit count.", stop_bits);
688 tty_setting.c_iflag &= ~(PARMRK | ISTRIP | IGNCR | ICRNL | INLCR | IXOFF | IXON | IXANY);
697 tty_setting.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG | IEXTEN | NOFLSH | TOSTOP);
705 tcflush(t_fd, TCIOFLUSH);
708 DEBUGDEVICE(m_DriverName, m_DebugChannel,
"connect: failed setting attributes on serial port.");
730 tcflush(m_PortFD, TCIOFLUSH);
731 int err = close(m_PortFD);
742 char error_string[512] = {0};
750 snprintf(error_string, 512,
"Read Error: %s", strerror(
errno));
754 snprintf(error_string, 512,
"Write Error: %s", strerror(
errno));
758 snprintf(error_string, 512,
"Select Error: %s", strerror(
errno));
762 return "Timeout error";
766 snprintf(error_string, 512,
767 "Port failure Error: %s. Try adding your user to the dialout group and restart (sudo adduser "
771 snprintf(error_string, 512,
"Port failure Error: %s. Check if device is connected to this port.",
776 return "Parameter error";
780 snprintf(error_string, 512,
"%s", strerror(
errno));
784 return "Read overflow";
787 return "Error: unrecognized error code";
TTY_RESPONSE read(uint8_t *buffer, uint32_t nbytes, uint8_t timeout, uint32_t *nbytes_read)
read buffer from terminal
TTYBase(const char *driverName)
const std::string error(TTY_RESPONSE code) const
Retrieve the tty error message.
TTY_RESPONSE writeString(const char *string, uint32_t *nbytes_written)
Writes a null terminated string to fd.
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
TTY_RESPONSE disconnect()
Closes a tty connection and flushes the bus.
TTY_RESPONSE write(const uint8_t *buffer, uint32_t nbytes, uint32_t *nbytes_written)
Writes a buffer to fd.
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.
void IDLog(const char *fmt,...)
#define DEBUGDEVICE(device, priority, msg)
#define DEBUGFDEVICE(device, priority, msg,...)
struct termios tty_setting