/*
 * Program to write to a no-name scrolling LED device
 * Upon plugging in comes up as a prolific USB->Serial converter
 * Ian Wienand <ianw@ieee.org>
 * Public Domain
 */

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

/* format is
 * 0xAA SPEED MESSAGE 0xCC
 * where speed is 0x1-0x6
 * message is up to 73 characters
 * (by experimentation, after this the screen crashes)
 * baud rate must be 9600,N,8,1
 */

#define HEADER 0xAA
#define TRAILER 0xCC
#define MAX_LEN 73

char *device = "/dev/ttyUSB0";

#define xstr(s) str(s)
#define str(s) #s

#define USAGE "scroller [-s speed] [-d device] [-v] \"your message\"\n"		\
              "\t -d device : defaults to /dev/ttyUSB0\n"			\
              "\t -s speed  : defaults to 1.  Between 1-5 (larger is slower)\n"	\
              "\t message   : less than " xstr(MAX_LEN) " characters\n"		\
              "\t -v        : verbose\n"


int main(int argc, char *argv[])
{
	struct termios options;
	int fd, len;
	char buf[MAX_LEN+3];
	unsigned char speed = 1;
	int verbose = 0;

	extern char *optarg;
	extern int optind, optopt;
	int errflg = 0, c;

	while ((c = getopt (argc, argv, "d:s:hv")) != -1) {
		switch (c)
		{
		case 'h':
			fprintf (stdout, "%s", USAGE);
			exit (0);
		case 's':
			speed = atoi(optarg);
			if (speed < 1 || speed > 5) {
				fprintf(stderr, "%s", USAGE);
				exit(1);
			}
			break;
		case 'd':
			device = optarg;
			break;
		case 'v':
			verbose = 1;
			break;
		case ':':
			errflg++;
			break;
		case '?':
			errflg++;
		}
	}

	if (errflg || optind != (argc-1)) {
		fprintf(stderr, "%s", USAGE);
		exit(1);
	}

	if (strlen(argv[optind]) > MAX_LEN) {
		fprintf(stderr, "message must be < 150 characters\n");
		exit(1);
	}

	fd = open (device, O_RDWR | O_NONBLOCK );
	if (fd == -1) {
		fprintf(stderr, "can't open port %s: %s\n", device, strerror(errno));
		exit(1);
	}

	tcgetattr (fd, &options);
	cfsetspeed (&options, B9600);
	options.c_iflag = 0;
	options.c_cflag |= (CLOCAL|CS8);
	options.c_lflag = 0;
	options.c_oflag = 0;

	if ((tcsetattr (fd, TCSANOW, &options)==-1))
		fprintf(stderr, "ipbenchd: tcsetattr error: %s\n", strerror(errno));
	tcflush (fd, TCIOFLUSH);

	len = sprintf(buf, "%c%c%s%c", HEADER, speed, argv[optind], TRAILER);

	if (verbose)
	{
		printf("writing output to %s\n", device);
		write(1, buf, len);
	}

	write(fd, buf, len);

	close(fd);

	return 0;
}

