view src/lwwire-serial.c @ 9:a11b330771e0

Fix buffer pointer handling when logging received bytes Actually save the read buffer pointer so we can log the actual protocol bytes read in all cases correctly instead of displaying out of bounds memory in the case where the packet arrives in multiple pieces.
author William Astle <lost@l-w.ca>
date Sat, 30 Jul 2016 10:35:14 -0600
parents cfc9524cca2c
children
line wrap: on
line source

/*
Set up a serial port and launch a lwwire process to handle it. The lwwire
process will be called with "exec".

Usage:

lwwire-serial <port> [speed] [lwwire binary args...]

<port> is the device name for the serial port. [speed] is the optional speed
to set the port to with a default of 115200. [lwwire binary] is the optional
name for the lwwire binary. Default is "./lwwire". If [lwwire binary] is
specified, then [speed] must also be specified.

*/

#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <termios.h>
#include <unistd.h>

int main(int argc, char **argv)
{
	char *lwwire = "lwwire";
	int speed = 115200;
	char *port;
	int i, rargc;
	char **rargv;
	int fd;
	struct termios io_mod;

	if (argc >= 4)
	{
		lwwire = argv[3];
	}
	if (argc >= 3)
	{
		speed = strtol(argv[2], NULL, 10);
	}
	if (argc < 2)
	{
		fprintf(stderr, "Usage: %s <port> [<speed> [<lwwire binary> [args]]]\n", argv[0]);
		exit(0);
	}
	port = argv[1];
	
	fprintf(stderr, "Starting lwwire on port '%s' at speed %d\n", port, speed);
	
	// open serial port
	fd = open(port, O_RDWR | O_NOCTTY);
	if (fd < 0)
	{
		fprintf(stderr, "Error opening port %s: %s\n", port, strerror(errno));
		exit(1);
	}
	// set up parameters
	// this is all theoretically *mostly* posix correct except for some of the 
	// Bxxxx constants.	
	tcgetattr(fd, &io_mod);
	io_mod.c_iflag &= 
		~(IGNBRK|BRKINT|PARMRK|ISTRIP|INLCR|IGNCR|ICRNL|IXON);
	io_mod.c_oflag &= ~OPOST;
	io_mod.c_lflag &= ~(ECHO|ECHONL|ICANON|ISIG|IEXTEN);
	io_mod.c_cflag &= ~(CSIZE|PARENB);
	io_mod.c_cflag |= CS8;
	switch (speed)
	{
	case 38400:
		cfsetispeed(&io_mod, B38400);
		cfsetospeed(&io_mod, B38400);
		break;
	
	case 57600:
		cfsetispeed(&io_mod, B57600);
		cfsetospeed(&io_mod, B57600);
		break;
	
	case 115200:
		cfsetispeed(&io_mod, B115200);
		cfsetospeed(&io_mod, B115200);
		break;

#ifdef B230400	
	case 230400:
		cfsetispeed(&io_mod, B230400);
		cfsetospeed(&io_mod, B230400);
		break;
#endif

#ifdef B460800
	case 460800:
		cfsetispeed(&io_mod, B460800);
		cfsetospeed(&io_mod, B460800);
		break;
#endif

#ifdef B921600
	case 921600:
		cfsetispeed(&io_mod, B921600);
		cfsetospeed(&io_mod, B921600);
		break;
#endif

	default:
		fprintf(stderr, "Unrecognzied speed %d on port %s; using 38400\n", speed, port);
		cfsetispeed(&io_mod, B38400);
		cfsetospeed(&io_mod, B38400);
		break;	
	}

	if (tcsetattr(fd, TCSANOW, &io_mod) < 0)
	{
		fprintf(stderr, "Cannot set serial line mode properly: %s", strerror(errno));
		exit(1);
	}

	// set up stdin/stdout
	if (dup2(fd, 0) < 0)
	{
		fprintf(stderr, "Cannot set up stdin file descriptor: %s\n", strerror(errno));
		exit(1);
	}
	if (dup2(fd, 1) < 0)
	{
		fprintf(stderr, "Cannot set up stdout file descriptor: %s\n", strerror(errno));
		exit(1);
	}
	// close the original FD since we don't need it any more.
	close(fd);

	// execute binary
	rargc = 1;
	if (argc >= 5)
	{
		rargc += argc - 4;
	}
	rargv = malloc(sizeof(char *) * (rargc + 1));
	rargv[0] = lwwire;
	for (i = 4; i < argc; i++)
	{
		fprintf(stderr, "Passing argument %d of %d: %s\n", i - 3, rargc, argv[i]);
		rargv[i - 3] = argv[i];
	}
	rargv[rargc] = NULL;
	
	execv(lwwire, rargv);
	fprintf(stderr, "Failed to execute %s: %s\n", lwwire, strerror(errno));
	exit(1);
}