240 lines
		
	
	
		
			5.4 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			240 lines
		
	
	
		
			5.4 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
 | 
						|
#include <stdio.h>
 | 
						|
#include  <stdlib.h>
 | 
						|
#include  <errno.h>
 | 
						|
#include  <sys/select.h>
 | 
						|
#include  <string.h>
 | 
						|
#include <unistd.h>			//Used for UART
 | 
						|
#include <fcntl.h>			//Used for UART
 | 
						|
#include <termios.h>		//Used for UART
 | 
						|
 | 
						|
#include  "serial.h"
 | 
						|
 | 
						|
/* -------------------------------------------------------------------- */
 | 
						|
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
 | 
						|
fprintf(stderr, ">>> %s ( %s %d )\n", __func__, port, baudrate);
 | 
						|
#endif
 | 
						|
// 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.
 | 
						|
 | 
						|
uart0 = open(port, O_RDONLY | O_NOCTTY);
 | 
						|
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);
 | 
						|
#if DEBUG_LEVEL > 1
 | 
						|
fprintf(stderr, "%d -> 0x%04x\n", baudrate, baudbits);
 | 
						|
#endif
 | 
						|
 | 
						|
memset(&options, 0, sizeof(options));	
 | 
						|
 | 
						|
tcgetattr(uart0, &options);
 | 
						|
options.c_cflag = baudbits | CS8 | CLOCAL | CREAD;
 | 
						|
options.c_iflag = IGNPAR;
 | 
						|
options.c_oflag = 0;
 | 
						|
options.c_lflag = 0;
 | 
						|
 | 
						|
options.c_cc[VMIN] = 1;			/* ask for blocking read */
 | 
						|
 | 
						|
tcflush(uart0, TCIFLUSH);
 | 
						|
tcsetattr(uart0, TCSANOW, &options);
 | 
						|
 | 
						|
tcflush(uart0, TCIFLUSH);		/* do it again, sam */
 | 
						|
 | 
						|
return uart0;
 | 
						|
}
 | 
						|
/* -------------------------------------------------------------------- */
 | 
						|
/*
 | 
						|
 *	this function have NO timeout !
 | 
						|
 *	blocking read is not blocking, wtf ?
 | 
						|
 */
 | 
						|
int getbyte(int fd)
 | 
						|
{
 | 
						|
unsigned char   byte;
 | 
						|
int             foo;
 | 
						|
 | 
						|
byte = 0;
 | 
						|
 | 
						|
foo = read(fd, &byte, 1);
 | 
						|
if (1 != foo)
 | 
						|
        {
 | 
						|
	fprintf(stderr, "byte %d rd %d errno %d\n",
 | 
						|
					byte, foo, errno);
 | 
						|
        return -1;
 | 
						|
        }
 | 
						|
return (int)byte;
 | 
						|
}
 | 
						|
 | 
						|
/* -------------------------------------------------------------------- */
 | 
						|
/* timeout is in milliseconds */
 | 
						|
int getbyte_to (int fd, int to_ms)
 | 
						|
{
 | 
						|
unsigned char   byte;
 | 
						|
struct timeval	timeout;
 | 
						|
fd_set 		rfds;
 | 
						|
int		retval;
 | 
						|
 | 
						|
timeout.tv_sec  =  to_ms / 1000;
 | 
						|
timeout.tv_usec = (to_ms % 1000) * 1000;
 | 
						|
#if DEBUG_LEVEL > 1
 | 
						|
fprintf(stderr, "timeout %6d is %4ld.%6ld\n", to_ms,
 | 
						|
				timeout.tv_sec, timeout.tv_usec);
 | 
						|
#endif
 | 
						|
 | 
						|
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);
 | 
						|
#endif
 | 
						|
 | 
						|
switch (retval) {
 | 
						|
 | 
						|
	case -1:
 | 
						|
		fprintf(stderr, "omg ?\n");
 | 
						|
		retval = -1;
 | 
						|
		break;
 | 
						|
 | 
						|
	case 0:
 | 
						|
		fprintf(stderr, "timeout %ld.%ld\n",
 | 
						|
				 timeout.tv_sec, timeout.tv_usec);
 | 
						|
		retval = -99;
 | 
						|
		break;
 | 
						|
 | 
						|
	default:
 | 
						|
		fprintf(stderr, "%s default -> %d\n", __func__, retval);
 | 
						|
		if (retval==fd) {
 | 
						|
			read(fd, &byte, 1);
 | 
						|
			fprintf(stderr, "got 0x%02x\n", byte);
 | 
						|
			retval = byte;
 | 
						|
			}
 | 
						|
		else	{
 | 
						|
			fprintf(stderr, "%d bad fd ?\n", retval);
 | 
						|
			retval = -3;
 | 
						|
			}
 | 
						|
		break;
 | 
						|
	}
 | 
						|
 | 
						|
return retval;
 | 
						|
}
 | 
						|
/* -------------------------------------------------------------------- */
 | 
						|
/* 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
 | 
						|
 | 
						|
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);
 | 
						|
		}
 | 
						|
 | 
						|
	if (byte < 0) {
 | 
						|
		fprintf(stderr, "%s : something is wrong %d\n", 
 | 
						|
				__func__, byte);
 | 
						|
		retval = byte;
 | 
						|
		break;
 | 
						|
		}
 | 
						|
 | 
						|
	if ('\n' == byte) {			/* got an EOL ? */
 | 
						|
		where[curpos] = '\0';
 | 
						|
		retval = curpos;
 | 
						|
		break;
 | 
						|
		}
 | 
						|
 | 
						|
	if (curpos < szm) {			/* ya de la place */
 | 
						|
		where[curpos] = byte;
 | 
						|
		curpos++;
 | 
						|
		}
 | 
						|
	else	{				/* oups overflow */
 | 
						|
		retval = -6;
 | 
						|
		break;
 | 
						|
		}
 | 
						|
 | 
						|
	}
 | 
						|
 | 
						|
#if DEBUG_LEVEL
 | 
						|
fprintf(stderr, "%s -> '%s'\n", __func__, where);
 | 
						|
#endif
 | 
						|
return retval;
 | 
						|
}
 | 
						|
/* -------------------------------------------------------------------- */
 | 
						|
 |