/* 
 * Thomas Pantzer: main.cc, v0.1b  8.6.99 16:51 
 * 
 * 
 * Copyright 1999 by Thomas Pantzer
 * 
 * Permission to use, copy, modify, and distribute this software for noncommercial 
 * use and without fee is hereby granted, provided that the above copyright notice 
 * appear in all copies and that both that copyright notice and this permission 
 * notice appear in supporting documentation, and that the name of the Author not be 
 * used in advertising or publicity pertaining to distribution of the software 
 * without specific, written prior permission. The Author makes no representations about
 * the suitability of this software for any purpose.  It is provided "as is" 
 * without expressed or implied warranty. 
 * 
 * 
 * pantec@isys2.informatik.uni-leipzig.de   (Thomas Pantzer) 
 * 
 */






#include <unistd.h>
#include <sys/types.h>
#include <fcntl.h>

#define MAIN_G
#include "copyright.h"

#include "khep_serial.h"
#include "utils.h"
#include "mkopts.h"

#define cmd_QUIT 1
#define cmd_BAUD 2
#define cmd_LOAD 3
#define cmd_PORT 4
#define cmd_HELP 5

typedef struct { char name[64];
                 int id; 
		 char helptext[256];
               } t_cmd;


t_cmd Command[] = {{"/quit\0",cmd_QUIT,"\n/quit\n\tstops the program\0"},
                   {"/baud\0",cmd_BAUD,"\n/baud 19200\n\tchanges the baudrate to 19200 baud\0"},
                   {"/load\0",cmd_LOAD,"\n/load <filename>\n\tdownloads a .s28-file and starts the downloaded program immediatly\0"},
                   {"/port\0",cmd_PORT,"\n/port /dev/ttyb\n\tswitches to the second serial port (B) on suns\0"},
                   {"/help\0",cmd_HELP,"\n/help\n\tdisplays this text\0"},
                   {"\0",0}};


int sfd;
// int Baud = 38400;
// char Port[64] = "/dev/ttya\0"; 

#ifdef __linux__
#define DEFAULT_PORT	"/dev/ttyS0"
#else
#define DEFAULT_PORT	"/dev/ttya"
#endif

t_opts opts[] = {
	{empty_func,e_integer,'b',"baud\0","baudrate to use\t\t\0",false,38400,0.0,"\0"},
#define Baud  opts[0].i

	{empty_func,e_string,'d',"device\0","serial port name\t\0",false,0,0.0,DEFAULT_PORT"\0                                                                                                          "},
#define Port opts[1].s

// 	{empty_func,e_boolean,'u',"uniq\0","print a uniq list of all read words\0",false,0,0.0,"\0"},
// #define uniq_mode opts[1].b

	{empty_func,e_unknown,'\0',"\0","\0",0,0,0.0,"\0"}
	};



#define MAIN_G
#include "copyright.h"



void LoadCmd(char *kbuf)
{
    char st[256],fn[256];
    if (sscanf(kbuf,"/load %s\n",fn) == 1)
       {
	int fd = open(fn,O_RDONLY);
	int r = read(fd,kbuf,256*1024);

	if (r > 0)
	   {
	    fcntl(sfd,F_SETFL,O_SYNC);
	    sprintf(st,"run sloader\n");
	    write(sfd,st,strlen(st));

	    sprintf(st,"loader started, file [%s], bytes: %d\t",fn,r);
	    write(fileno(stdout),st,strlen(st));		
	    st[0] = '.';

	    for (int z=0; z<r; z+=1024)
   	      {
	       int w = 1024; 
	       if ((r-z) > 1024)
		  w = 1024;
 		else
		  w = r - z;

	       write(sfd,&kbuf[z],w);	
	       write(fileno(stdout),st,1);	
	      }		
	    close(fd);
	    st[0] = '\n';	
	    write(fileno(stdout),st,1);
	    fcntl(sfd,F_SETFL,O_NDELAY);
	   } 
       }	
}

char RunCommand(char *kbuf)
{
    if (kbuf[0] != '/')
	return false;
	
    int c = 0;
    while (Command[c].id != 0)	
    {
     if (strncmp(kbuf,Command[c].name,strlen(Command[c].name)) == 0)
	{
	 switch (Command[c].id)
	   {
	    case cmd_QUIT:
	      close(sfd);
	      exit(0);	
	      break;

	    case cmd_BAUD:
              {
	       int i; 
	       if (sscanf(kbuf,"/baud %d",&i) == 1)
	 	  {
		   Baud = i;
		   serial_configure(sfd,Baud);
		  }	
	      } 
	      break;

	    case cmd_LOAD:
	      LoadCmd(kbuf);
	      break;	

	    case cmd_HELP:
	      {
	       int i = 0;
	 	
	       while (Command[i].id != 0)
		  {
		   write(fileno(stdout),Command[i].helptext,strlen(Command[i].helptext));		   
	           i++;
		  }	
	       char st[6];
	       sprintf(st,"\n\n");
	       write(fileno(stdout),st,strlen(st));
	      }	
	      break;

	    case cmd_PORT:
              {
	       char st[256]; 
	       if (sscanf(kbuf,"/port %s",st) == 1)
	 	  {
		   int f = open(st,O_RDWR);
		   if (f != -1)
	              {
		       if (serial_configure(f,Baud) == TRUE)
		          {
			   close(sfd);
		           sfd = f;
			   fcntl(sfd,F_SETFL,O_NDELAY);
			   strcpy(Port,st);
			   sprintf(st,"switched to port [%s] @ %d Baud\n",Port,Baud);
		           write(fileno(stdout),st,strlen(st));
			  }
		      }
		  }	
	      } 
	      break;		
	   }

	 break;	
	}

     c++;
    }

   if (Command[c].id == 0)
      return false;

   return true;		
}

int main(int argc, char *argv[])
{

	scan_args(argc,argv,opts);

	sfd = open(Port,O_RDWR);
        serial_configure(sfd,Baud);
	fcntl(sfd,F_SETFL,O_NDELAY);
//	fcntl(0,F_SETFL,O_NDELAY);
	char kbuf[256 * 1024];

	while (true) 
          {
	   if (FD_Ready(0) == true)
	      {
               int i = read(0,kbuf,128);
	       kbuf[i] = '\0';

	       if (RunCommand(kbuf) == false)
		  write(sfd,kbuf,i);
	      }

           if (FD_Ready(sfd) == true) 
	      {
               int i = read(sfd,kbuf,1024);
	       kbuf[i] = '\0';
	       write(fileno(stdout),kbuf,i);
	      }
	  }
}
