/*

  Copyright 2004, by Robert Forsman
  projectormount@thoth.purplefrog.com

  GNU General Public License

  http://www.purplefrog.com/~thoth/album/projector-mount/

 */

#include <stdio.h>
#include <fcntl.h>
#include <termios.h>

char * serialDevice = "/dev/ttyS0";

struct command {
    char *name;
    int crc;
    int command;
};

struct command cmds[] = {
    { "power",	0xffc6, 0x01 },
    { "menu",	0xbfc7, 0x02 },
    { "up",	0x7e07, 0x03 },
    { "down",	0x3fc5, 0x04 },
    { "left",	0xfe05, 0x05 },
    { "right",	0xbe04, 0x06 },
    { "resync",	0x7fc4, 0x07 },
    { "source",	0x3fc0, 0x08 },
    { "volume+",	0xfe00, 0x09 },
    { "volume-",	0xbe01, 0x0a },
    { "mute",	0xffc3, 0x0d },
    { "freeze",	0xbfc3, 0x0e },
    { "hide",	0x7e02, 0x0f },
    { "mode",	0x3fca, 0x10 },
    { "keystone+",0x7fcb, 0x13 },
    { "keystone-",0x3e09, 0x14 },
    { "aspect",	0x7e08, 0x17 },
};

#define NCOMMANDS ( sizeof(cmds) / sizeof(*cmds) )

char * progname;


struct command *lookup(char *name)
{
    int i;

    for (i=0; i<NCOMMANDS; i++) {
	if (0 == strcasecmp(cmds[i].name, name)) {
	    return & cmds[i];
	}
    }
    return (struct command*)0;
}

void usage()
{
    int i;
    fprintf(stderr, "Usage: %s [ -s serial_device ] command\n  Where command is one of \n", progname);
    for (i=0; i<NCOMMANDS; i++) {
	fprintf(stderr, "\t%s\n", cmds[i].name);
    }
}

int main(int argc, char **argv)
{
    int fd;
    struct termios t;
    struct command * cmd;

    progname = argv[0];
    {
	int i;
	for (i=1; i<argc; i++) {
	    if (0 == strcmp(argv[i], "-s") ) {
		if (i+1 < argc) {
		    serialDevice = argv[++i];
		} else {
		    usage();
		    exit (1);
		}
	    } else {
		break;
	    }
	}
	if (i>=argc || 
	    0 == ( cmd = lookup(argv[i]) )
	    ) {
	    usage();
	    exit(1);
	}
    }
   

    fd = open(serialDevice, O_RDWR);

    if (fd<0) {
	fprintf(stderr, "Unable to open %s for write: ", serialDevice);
	perror("");
	exit (1);
    }
    

    if (0!=tcgetattr(fd, &t)) {
	fprintf(stderr, "error during tcgetattr: ");
	perror("");
	exit(1);
    }

    cfsetospeed(&t, B19200);
    t.c_oflag =  t.c_oflag & ~(PARENB|CSTOPB);

    if (0 != tcsetattr(fd, TCSANOW, &t)) {
	fprintf(stderr, "error during tcsetattr: ");
	perror("");
	exit(1);
    }

    usleep(100000);

    {
	/*	int code = atoi(argv[1]);*/
	char bytes[] = {  0xbe, 0xef, 0x10, 0x05, 0x00, 0xc7, 0xbf, 0x11, 0x11, 0x01, 0x00, 0x02};

	int written = 0;
	int toWrite = sizeof(bytes);
	int n;

	bytes[5] = cmd->crc;
	bytes[6] = cmd->crc>>8;
	bytes[11] = cmd->command;

	while (written < toWrite) {
	    int a = toWrite-written;
	    n = write(fd, bytes+written, a);
	    if (n<0) {
		fprintf(stderr, "failed to write()");
		perror("");
		exit(1);
	    }
	    written += n;
	}
    }

    close(fd);

    exit(0);
}

/*

To compile:


  cc -o 2300mp-cmd 2300mp-cmd.c

 */
