2018-12-12 14:38:32 +01:00
|
|
|
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdlib.h>
|
2018-12-20 11:57:23 +01:00
|
|
|
#include <errno.h>
|
2018-12-12 20:07:49 +01:00
|
|
|
#include <sys/select.h>
|
2018-12-20 11:57:23 +01:00
|
|
|
#include <string.h>
|
2018-12-12 14:38:32 +01:00
|
|
|
#include <unistd.h> //Used for UART
|
|
|
|
#include <fcntl.h> //Used for UART
|
|
|
|
#include <termios.h> //Used for UART
|
|
|
|
|
|
|
|
#include "serial.h"
|
|
|
|
|
|
|
|
/* -------------------------------------------------------------------- */
|
2018-12-12 14:47:57 +01:00
|
|
|
static int baudrate2const(int bauds)
|
2018-12-12 14:38:32 +01:00
|
|
|
{
|
|
|
|
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
|
|
|
|
fprintf(stderr, "%s ( %s %d )\n", __func__, port, baudrate);
|
|
|
|
#endif
|
2018-12-12 16:10:02 +01:00
|
|
|
// OPEN THE UART
|
|
|
|
// The flags (defined in fcntl.h):
|
2018-12-12 14:38:32 +01:00
|
|
|
// 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.
|
|
|
|
|
2018-12-20 11:57:23 +01:00
|
|
|
uart0 = open(port, O_RDONLY | O_NOCTTY);
|
|
|
|
if (uart0 < 0)
|
2018-12-12 14:38:32 +01:00
|
|
|
{
|
|
|
|
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 12:09:34 +01:00
|
|
|
#if DEBUG_LEVEL > 1
|
2018-12-12 20:07:49 +01:00
|
|
|
fprintf(stderr, "%d -> 0x%04x\n", baudrate, baudbits);
|
2018-12-12 14:38:32 +01:00
|
|
|
#endif
|
2018-12-20 11:57:23 +01:00
|
|
|
|
2018-12-20 17:53:18 +01:00
|
|
|
memset(&options, 0, sizeof(options));
|
2018-12-20 11:57:23 +01:00
|
|
|
|
2018-12-12 14:38:32 +01:00
|
|
|
tcgetattr(uart0, &options);
|
2018-12-20 17:53:18 +01:00
|
|
|
options.c_cflag = baudbits | CS8 | CLOCAL | CREAD;
|
2018-12-12 14:38:32 +01:00
|
|
|
options.c_iflag = IGNPAR;
|
|
|
|
options.c_oflag = 0;
|
|
|
|
options.c_lflag = 0;
|
2018-12-29 12:09:34 +01:00
|
|
|
|
|
|
|
options.c_cc[VMIN] = 1; /* ask for blocking read */
|
|
|
|
|
2018-12-12 14:38:32 +01:00
|
|
|
tcflush(uart0, TCIFLUSH);
|
|
|
|
tcsetattr(uart0, TCSANOW, &options);
|
|
|
|
|
|
|
|
return uart0;
|
|
|
|
}
|
2018-12-12 16:06:18 +01:00
|
|
|
/* -------------------------------------------------------------------- */
|
2018-12-12 16:10:02 +01:00
|
|
|
/*
|
2018-12-12 20:07:49 +01:00
|
|
|
* this function have NO timeout !
|
2018-12-20 11:57:23 +01:00
|
|
|
* blocking read is not blocking, wtf ?
|
2018-12-12 16:10:02 +01:00
|
|
|
*/
|
2018-12-12 16:06:18 +01:00
|
|
|
int getbyte(int fd)
|
|
|
|
{
|
|
|
|
unsigned char byte;
|
|
|
|
int foo;
|
|
|
|
|
2018-12-20 11:57:23 +01:00
|
|
|
byte = 0;
|
|
|
|
|
2018-12-12 16:06:18 +01:00
|
|
|
foo = read(fd, &byte, 1);
|
|
|
|
if (1 != foo)
|
|
|
|
{
|
2018-12-20 11:57:23 +01:00
|
|
|
fprintf(stderr, "byte %d rd %d errno %d\n",
|
|
|
|
byte, foo, errno);
|
2018-12-12 16:06:18 +01:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
return (int)byte;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* -------------------------------------------------------------------- */
|
2018-12-12 20:07:49 +01:00
|
|
|
/* timeout is in milliseconds */
|
|
|
|
int getbyte_to (int fd, int to_ms)
|
|
|
|
{
|
|
|
|
unsigned char byte;
|
|
|
|
struct timeval timeout;
|
2018-12-12 22:26:54 +01:00
|
|
|
fd_set rfds;
|
|
|
|
int retval;
|
2018-12-12 20:07:49 +01:00
|
|
|
|
2018-12-29 12:09:34 +01:00
|
|
|
timeout.tv_sec = to_ms / 1000;
|
2018-12-12 20:07:49 +01:00
|
|
|
timeout.tv_usec = (to_ms % 1000) * 1000;
|
2018-12-29 12:09:34 +01:00
|
|
|
#if DEBUG_LEVEL > 1
|
2018-12-20 11:57:23 +01:00
|
|
|
fprintf(stderr, "timeout %6d is %4ld.%6ld\n", to_ms,
|
2018-12-12 20:07:49 +01:00
|
|
|
timeout.tv_sec, timeout.tv_usec);
|
|
|
|
#endif
|
|
|
|
|
2018-12-12 22:26:54 +01:00
|
|
|
FD_ZERO (&rfds);
|
|
|
|
FD_SET (fd, &rfds);
|
|
|
|
|
|
|
|
retval = select(1, &rfds, NULL, NULL, &timeout);
|
|
|
|
#if DEBUG_LEVEL
|
2018-12-29 17:07:23 +01:00
|
|
|
fprintf(stderr, "%s : select on fd %d -> %d\n", __func__, fd, retval);
|
2018-12-12 22:26:54 +01:00
|
|
|
#endif
|
|
|
|
|
|
|
|
switch (retval) {
|
|
|
|
|
|
|
|
case -1:
|
2018-12-13 18:43:49 +01:00
|
|
|
fprintf(stderr, "omg ?\n");
|
2018-12-20 11:57:23 +01:00
|
|
|
retval = -1;
|
2018-12-13 18:43:49 +01:00
|
|
|
break;
|
2018-12-12 22:26:54 +01:00
|
|
|
|
|
|
|
case 0:
|
2018-12-29 12:09:34 +01:00
|
|
|
fprintf(stderr, "timeout %ld.%ld\n",
|
|
|
|
timeout.tv_sec, timeout.tv_usec);
|
2018-12-20 11:57:23 +01:00
|
|
|
retval = -99;
|
2018-12-13 18:43:49 +01:00
|
|
|
break;
|
2018-12-12 22:26:54 +01:00
|
|
|
|
|
|
|
default:
|
2018-12-20 11:57:23 +01:00
|
|
|
fprintf(stderr, "%s default -> %d\n", __func__, retval);
|
2018-12-13 18:43:49 +01:00
|
|
|
if (retval==fd) {
|
|
|
|
read(fd, &byte, 1);
|
|
|
|
fprintf(stderr, "got 0x%02x\n", byte);
|
2018-12-20 11:57:23 +01:00
|
|
|
retval = byte;
|
2018-12-13 18:43:49 +01:00
|
|
|
}
|
|
|
|
else {
|
|
|
|
fprintf(stderr, "%d bad fd ?\n", retval);
|
2018-12-20 11:57:23 +01:00
|
|
|
retval = -3;
|
2018-12-13 18:43:49 +01:00
|
|
|
}
|
|
|
|
break;
|
2018-12-12 22:26:54 +01:00
|
|
|
}
|
|
|
|
|
2018-12-20 11:57:23 +01:00
|
|
|
return retval;
|
2018-12-12 20:07:49 +01:00
|
|
|
}
|
|
|
|
/* -------------------------------------------------------------------- */
|
2018-12-14 18:52:06 +01:00
|
|
|
/* timeout is in milliseconds */
|
|
|
|
|
|
|
|
int getline_to(int fd, char *where, int szm, int to_ms)
|
|
|
|
{
|
|
|
|
int curpos, byte, retval;
|
|
|
|
|
2018-12-29 17:07:23 +01:00
|
|
|
#if DEBUG_LEVEL
|
|
|
|
fprintf(stderr, ">>> %s ( %d %p %d %d )\n", __func__,
|
|
|
|
fd, where, szm, to_ms);
|
|
|
|
#endif
|
|
|
|
|
2018-12-14 18:52:06 +01:00
|
|
|
curpos = 0;
|
|
|
|
retval = -7; /* magic number powa */
|
|
|
|
where[0] = '\0'; /* erase all the bs */
|
|
|
|
|
|
|
|
for(;;) {
|
2018-12-29 17:07:23 +01:00
|
|
|
if (to_ms) {
|
|
|
|
byte = getbyte_to (fd, to_ms);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
byte = getbyte(fd);
|
|
|
|
}
|
2018-12-14 18:52:06 +01:00
|
|
|
|
|
|
|
if (byte < 0) {
|
|
|
|
fprintf(stderr, "%s : somthing is wrong %d\n",
|
|
|
|
__func__, byte);
|
|
|
|
retval = byte;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ('\n' == byte) { /* got an EOL ? */
|
|
|
|
where[curpos] = '\0';
|
|
|
|
retval = curpos;
|
2018-12-29 17:07:23 +01:00
|
|
|
break;
|
2018-12-14 18:52:06 +01:00
|
|
|
}
|
|
|
|
|
2018-12-20 11:57:23 +01:00
|
|
|
if (curpos < szm) { /* ya de la place */
|
|
|
|
where[curpos] = byte;
|
|
|
|
curpos++;
|
|
|
|
}
|
|
|
|
else { /* oups overflow */
|
|
|
|
retval = -6;
|
|
|
|
break;
|
|
|
|
}
|
2018-12-14 18:52:06 +01:00
|
|
|
|
|
|
|
}
|
|
|
|
|
2018-12-29 09:45:22 +01:00
|
|
|
#if DEBUG_LEVEL
|
2018-12-14 18:52:06 +01:00
|
|
|
fprintf(stderr, "%s -> '%s'\n", __func__, where);
|
2018-12-29 09:45:22 +01:00
|
|
|
#endif
|
2018-12-20 11:57:23 +01:00
|
|
|
return retval;
|
2018-12-14 18:52:06 +01:00
|
|
|
}
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
|