DD2-monitor/serial/serial.c

262 lines
5.9 KiB
C
Raw Normal View History

#include <stdio.h>
#include <stdlib.h>
2018-12-20 21:57:23 +11:00
#include <errno.h>
2018-12-13 06:07:49 +11:00
#include <sys/select.h>
2018-12-20 21:57:23 +11:00
#include <string.h>
#include <unistd.h> //Used for UART
#include <fcntl.h> //Used for UART
#include <termios.h> //Used for UART
#include "serial.h"
extern int verbosity;
/* -------------------------------------------------------------------- */
2018-12-13 00:47:57 +11:00
static int baudrate2const(int bauds)
{
int br;
switch (bauds)
{
case 1200: br = B1200; break;
case 2400: br = B2400; break;
case 4800: br = B4800; break;
case 9600: br = B9600; break;
case 19200: br = B19200; break;
case 38400: br = B38400; break;
case 57600: br = B57600; break;
case 115200: br = B115200; break;
default:
fprintf(stderr, "baudrate %d invalide\n", bauds);
exit(1);
break;
}
return br;
}
/* -------------------------------------------------------------------- */
int prepare_UART(char *port, int baudrate)
{
int uart0 = -1;
int baudbits;
struct termios options;
#if DEBUG_LEVEL
2019-01-06 02:15:48 +11:00
fprintf(stderr, ">>> %s ( %s %d )\n", __func__, port, baudrate);
#endif
2018-12-13 02:10:02 +11:00
// OPEN THE UART
// The flags (defined in fcntl.h):
// Access modes (use 1 of these):
// O_RDONLY - Open for reading only.
// O_RDWR - Open for reading and writing.
// O_WRONLY - Open for writing only.
//
// O_NDELAY / O_NONBLOCK (same function) - Enables nonblocking mode.
// When set read requests on the file can return immediately with a
// failure status
// if there is no input immediately available (instead of blocking).
// Likewise, write requests can also return
// immediately with a failure status if the output can't be written
// immediately.
//
// O_NOCTTY - When set and path identifies a terminal device, open()
// shall not cause the terminal device to become the controlling terminal
// for the process.
2019-05-15 00:43:44 +11:00
uart0 = open(port, O_RDWR | O_NOCTTY);
2018-12-20 21:57:23 +11:00
if (uart0 < 0)
{
perror("unable to open uart ");
return -1;
}
// CONFIGURE THE UART
// The flags defined in /usr/include/termios.h -
// see http://pubs.opengroup.org/onlinepubs/007908799/xsh/termios.h.html
// Baud rate:- B1200, B2400, B4800, B9600, B19200, B38400, B57600,
// B115200, B230400, B460800, B500000, B576000, B921600, B1000000,
// B1152000, B1500000, B2000000, B2500000, B3000000, B3500000, B4000000
// CSIZE:- CS5, CS6, CS7, CS8
// CLOCAL - Ignore modem status lines
// CREAD - Enable receiver
// IGNPAR = Ignore characters with parity errors
// ICRNL - Map CR to NL on input (Use for ASCII comms where you want
// to auto correct end of line characters - don't use for bianry comms!)
// PARENB - Parity enable
// PARODD - Odd parity (else even)
baudbits = baudrate2const(baudrate);
2018-12-29 22:09:34 +11:00
#if DEBUG_LEVEL > 1
2018-12-13 06:07:49 +11:00
fprintf(stderr, "%d -> 0x%04x\n", baudrate, baudbits);
#endif
2018-12-20 21:57:23 +11:00
2018-12-21 03:53:18 +11:00
memset(&options, 0, sizeof(options));
2018-12-20 21:57:23 +11:00
tcgetattr(uart0, &options);
2018-12-21 03:53:18 +11:00
options.c_cflag = baudbits | CS8 | CLOCAL | CREAD;
options.c_iflag = IGNPAR;
2019-05-15 19:10:26 +11:00
options.c_oflag = IGNPAR;
options.c_lflag = 0;
2018-12-29 22:09:34 +11:00
2019-05-15 19:10:26 +11:00
cfmakeraw(&options); /* XXX */
2018-12-29 22:09:34 +11:00
options.c_cc[VMIN] = 1; /* ask for blocking read */
2019-05-15 19:10:26 +11:00
tcflush(uart0, TCIOFLUSH);
tcsetattr(uart0, TCSANOW, &options);
2019-01-06 02:15:48 +11:00
tcflush(uart0, TCIFLUSH); /* do it again, sam */
if (verbosity) {
fprintf(stderr, "%s %s uart0 = %d\n",
__FILE__, __func__, uart0);
}
return uart0;
}
2018-12-13 02:06:18 +11:00
/* -------------------------------------------------------------------- */
2018-12-13 02:10:02 +11:00
/*
2018-12-13 06:07:49 +11:00
* this function have NO timeout !
2018-12-20 21:57:23 +11:00
* blocking read is not blocking, wtf ?
2018-12-13 02:10:02 +11:00
*/
2018-12-13 02:06:18 +11:00
int getbyte(int fd)
{
unsigned char byte;
int foo;
2018-12-20 21:57:23 +11:00
byte = 0;
2018-12-13 02:06:18 +11:00
foo = read(fd, &byte, 1);
if (1 != foo)
{
2019-05-15 00:33:00 +11:00
fprintf(stderr, "%s : byte %d rd %d errno %d\n",
__func__, byte, foo, errno);
2018-12-13 02:06:18 +11:00
return -1;
}
return (int)byte;
}
2019-05-15 00:33:00 +11:00
/* -------------------------------------------------------------------- */
int putbyte(int fd, unsigned char byte)
{
int foo = -1;
2018-12-13 02:06:18 +11:00
2019-05-15 00:33:00 +11:00
foo = write(fd, &byte, 1);
if (1 != foo)
{
fprintf(stderr, "%s : %d -> %d errno %d\n",
__func__, byte, foo, errno);
}
return foo;
}
2018-12-13 02:06:18 +11:00
/* -------------------------------------------------------------------- */
2018-12-13 06:07:49 +11:00
/* timeout is in milliseconds */
int getbyte_to (int fd, int to_ms)
{
unsigned char byte;
struct timeval timeout;
2018-12-13 08:26:54 +11:00
fd_set rfds;
int retval;
2018-12-13 06:07:49 +11:00
2018-12-29 22:09:34 +11:00
timeout.tv_sec = to_ms / 1000;
2018-12-13 06:07:49 +11:00
timeout.tv_usec = (to_ms % 1000) * 1000;
2018-12-29 22:09:34 +11:00
#if DEBUG_LEVEL > 1
2018-12-20 21:57:23 +11:00
fprintf(stderr, "timeout %6d is %4ld.%6ld\n", to_ms,
2018-12-13 06:07:49 +11:00
timeout.tv_sec, timeout.tv_usec);
#endif
2018-12-13 08:26:54 +11:00
FD_ZERO (&rfds);
FD_SET (fd, &rfds);
retval = select(1, &rfds, NULL, NULL, &timeout);
#if DEBUG_LEVEL
fprintf(stderr, "%s : select on fd %d -> %d\n", __func__, fd, retval);
2018-12-13 08:26:54 +11:00
#endif
switch (retval) {
case -1:
fprintf(stderr, "omg ?\n");
2018-12-20 21:57:23 +11:00
retval = -1;
break;
2018-12-13 08:26:54 +11:00
case 0:
2018-12-29 22:09:34 +11:00
fprintf(stderr, "timeout %ld.%ld\n",
timeout.tv_sec, timeout.tv_usec);
2018-12-20 21:57:23 +11:00
retval = -99;
break;
2018-12-13 08:26:54 +11:00
default:
2018-12-20 21:57:23 +11:00
fprintf(stderr, "%s default -> %d\n", __func__, retval);
if (retval==fd) {
read(fd, &byte, 1);
fprintf(stderr, "got 0x%02x\n", byte);
2018-12-20 21:57:23 +11:00
retval = byte;
}
else {
fprintf(stderr, "%d bad fd ?\n", retval);
2018-12-20 21:57:23 +11:00
retval = -3;
}
break;
2018-12-13 08:26:54 +11:00
}
2018-12-20 21:57:23 +11:00
return retval;
2018-12-13 06:07:49 +11:00
}
/* -------------------------------------------------------------------- */
2018-12-15 04:52:06 +11:00
/* timeout is in milliseconds */
int getline_to(int fd, char *where, int szm, int to_ms)
{
int curpos, byte, retval;
#if DEBUG_LEVEL
fprintf(stderr, ">>> %s ( %d %p %d %d )\n", __func__,
fd, where, szm, to_ms);
#endif
2018-12-15 04:52:06 +11:00
curpos = 0;
retval = -7; /* magic number powa */
where[0] = '\0'; /* erase all the bs */
for(;;) {
if (to_ms) {
byte = getbyte_to (fd, to_ms);
}
else {
byte = getbyte(fd);
}
2018-12-15 04:52:06 +11:00
if (byte < 0) {
2019-01-01 03:19:52 +11:00
fprintf(stderr, "%s : something is wrong %d\n",
2018-12-15 04:52:06 +11:00
__func__, byte);
retval = byte;
break;
}
if ('\n' == byte) { /* got an EOL ? */
where[curpos] = '\0';
retval = curpos;
break;
2018-12-15 04:52:06 +11:00
}
2018-12-20 21:57:23 +11:00
if (curpos < szm) { /* ya de la place */
where[curpos] = byte;
curpos++;
}
else { /* oups overflow */
retval = -6;
break;
}
2018-12-15 04:52:06 +11:00
}
2018-12-29 19:45:22 +11:00
#if DEBUG_LEVEL
2018-12-15 04:52:06 +11:00
fprintf(stderr, "%s -> '%s'\n", __func__, where);
2018-12-29 19:45:22 +11:00
#endif
2018-12-20 21:57:23 +11:00
return retval;
2018-12-15 04:52:06 +11:00
}
/* -------------------------------------------------------------------- */