/* GPS port-related user commands
 *   (c) 1993 Brian A. Lantz
 */
#include <stdio.h>
#include "global.h"
#include "mbuf.h"
#include "proc.h"
#include "netuser.h"
#include "internet.h"
#include "cmdparse.h"
#include "timer.h"
#include "iface.h"
#include "udp.h"
#ifndef UNIX
#include "i8250.h"
#endif
#include "asy.h"
#ifdef UNIX
#include "unixasy.h"
#endif
#include "socket.h"
#include "usock.h"
#include "commands.h"
#include "gps.h"
#include "config.h"

#undef GPSDIAG 1

static short GPStype = 0;
struct iface *GPSactive;
static struct proc *GPSproc;
static int dev;
static char incoming[1024];
static char fullbuf[GPSMAXLEN];
static char *CmdStr, *InitStr, *TermStr;
#ifdef notyet
static char *TimeStr;
#endif

void GPSrawsend __ARGS((unsigned char *str, int len));
char *GPSgetstr __ARGS((void));
int GPSstart __ARGS((int argc,char *argv[],void *p));
static int dostr __ARGS((int argc,char *argv[],char *label, char *description, char **str));

extern struct asy Asy[ASY_MAX];

#ifdef GPSDIAG
void
pprintf (str, arg)
char *str;
char *arg;
{
	printf (str, arg);
	fflush(stdout);
}
#endif

unsigned char MAG[] = { 0,0,0 };

static gpstype Gtypes[] = {
	{ "Standard", 0, (unsigned char *) 0	},
	{ "Magellan", 0, MAG			},
	{ (char *) 0, 0, (unsigned char *) 0	}
};


void
GPSrawsend (str, len)
unsigned char *str;
int len;
{
#ifdef GPSDIAG
	pprintf("GPSrawsend() reached\n");
#endif
	if (!len)
		return;
	asy_send (dev, qdata (str, len));
}


char *
GPSgetstr ()
{
char *cp;
int c;
	
	cp = incoming;
	memset (incoming, 0x20, 1024);
	while((c = get_asy(dev)) != -1){
		*cp++ = ((c == '\r') || (c == 0x0a)) ? ' ' : c;
		if (c == 0x0a)
			break;
	}
	*cp = 0;
	return (strdup (incoming));
}


char *
GPSsendstr (str)
char *str;
{
char buf[256];
int response = 1;

#ifdef GPSDIAG
	pprintf("GPSsendstr() reached\n");
#endif
#ifdef nope
	return (strdup(""));
#else
	if ((GPSactive == NULLIF) || !str || !strlen (str))
		return (strdup (""));
	if (*str == '-')	{
		response = 0;
		str++;
	}
#ifdef TNOS_68K
	sprintf (buf, "%s\n\l", str);
#else
	sprintf (buf, "%s\r\n", str);
#endif
	GPSrawsend ((unsigned char *)buf, (int) strlen (buf));
	if (!response)
		return (strdup (""));
	return (GPSgetstr());
#endif
}


/* Start GPS on serial line */
int
GPSstart(argc,argv,p)
int argc;
char *argv[];
void *p;
{
register struct iface *ifp;
register struct asy *ap;
char *response, *cp;
int (*rawsave)__ARGS((struct iface *,struct mbuf *));

	if((ifp = if_lookup(argv[1])) == NULLIF){
		tprintf(Badinterface,argv[1]);
		return 1;
	}
	for(dev=0,ap = Asy;dev < ASY_MAX;dev++,ap++)
		if(ap->iface == ifp)
			break;
	if(dev == ASY_MAX){
		tprintf("Interface %s not asy port\n",argv[1]);
		return 1;
	}
	if (GPSactive != NULLIF)	{
		tprintf("GPS session already active on %s\n",GPSactive->name);
		return 1;
	}
	psignal(Curproc,0);	/* Don't keep the parser waiting */
	chname(Curproc,"GPS tip");
	GPSactive = ifp;
	GPSproc = Curproc;
	tprintf("GPS started on %s\n",argv[1]);

	/* Save output handler and temporarily redirect output to null */
	rawsave = ifp->raw;
	ifp->raw = bitbucket;
	/* Suspend packet input drivers */
	suspend(ifp->rxproc);
	GPSrawsend (Gtypes[GPStype].data, Gtypes[GPStype].len);
	free (GPSsendstr (InitStr));
#ifdef GPSDIAG
		pprintf("GPScmd reached\n");
#endif
#ifdef GPSDIAG
		pprintf("GPS initialization complete\n");
#endif

	for(;;) {
		response = GPSgetstr ();
#ifdef GPSDIAG
		pprintf("GPSgetstr response - '%s'\n",response);
#endif
		{
		FILE *fp;
			strcpy (fullbuf, Hostname);
			cp = strchr (fullbuf, '.');
			if (cp)
				*cp = 0;
			strcat (fullbuf, ": ");
			strcat (fullbuf, response);
			free (response);
			if (CurrentPos)
				free (CurrentPos);
			CurrentPos = strdup (fullbuf);
			fp = fopen (GPSfile, "a+");	/* no error checking yet */
			rewind (fp);
			fwrite (fullbuf, 1, GPSMAXLEN, fp);
			fclose (fp);
		}
	}
#ifdef GPSDIAG
	pprintf("GPS shutting down\n");
#endif
	free (GPSsendstr (TermStr));
	GPSactive = NULLIF;
	ifp->raw = rawsave;
	resume(ifp->rxproc);
	return 0;
}

int
GPSstop(argc,argv,p)
int argc;
char *argv[];
void *p;
{
struct iface *ifp;

	if((ifp = if_lookup(argv[1])) == NULLIF){
		tprintf(Badinterface,argv[1]);
		return 1;
	}
	if ((GPSactive == NULLIF) || GPSactive != ifp)	{
		tprintf ("There is no GPS active on %s!\n", argv[1]);
		return 1; 	/* wasn't active anyway */
	}
	alert (GPSproc, -1);
	return 0;
}


static int
dostr(argc,argv,label,description,str)
int argc;
char *argv[];
char *label, *description, **str;
{
	if(argc > 2) {
	        tprintf ("Usage: gps %s \"<gps command string>\"\n", label);
		return 0;
	}

	if(argc < 2) {
		if(*str != NULLCHAR)
			tprintf("%s: %s", description, *str);
	}
	else {
		if(*str != NULLCHAR){
			free(*str);
			*str = NULLCHAR;	/* reset the pointer */
		}
		if(!strlen(argv[1]))
			return 0;		/* clearing the buffer */
		*str = mallocw(strlen(argv[1])+5);/* allow for the EOL char */
		strcpy(*str, argv[1]);
		strcat(*str, "\n");		/* add the EOL char */
	}
	return 0;
}

static int docmdstring __ARGS((int argc,char *argv[],void *p)); 
static int doinitstring __ARGS((int argc,char *argv[],void *p)); 
static int dosendstring __ARGS((int argc,char *argv[],void *p)); 
#ifdef GPSDIAG
static int dosetstring __ARGS((int argc,char *argv[],void *p)); 
#endif
static int dotermstring __ARGS((int argc,char *argv[],void *p));
static int dotype __ARGS((int argc,char *argv[],void *p));
#ifdef notyet
static int dotimestring __ARGS((int argc,char *argv[],void *p)); 
#endif

static struct cmds GPScmds[] = {
	"cmdstring",	docmdstring,	0,	0,	NULLCHAR,
	"initstring",	doinitstring,	0,	0,	NULLCHAR,
	"sendstring",	dosendstring,	0,	0,	NULLCHAR,
#ifdef GPSDIAG
	"setstring",	dosetstring,	0,	0,	NULLCHAR,
#endif
	"termstring",	dotermstring,	0,	0,	NULLCHAR,
#ifdef notyet
	"timestring",	dotimestring,	0,	0,	NULLCHAR,
#endif
	"type",		dotype,		0,	0,	NULLCHAR,
	NULLCHAR,
};

int
dogps(argc,argv,p)
int argc;
char *argv[];
void *p;
{
	return subcmd(GPScmds,argc,argv,p);
}


static int
dotype(argc,argv,p)
int argc;
char *argv[];
void *p;
{
	return setshort (&GPStype, "GPS manufacturer type:",argc, argv);
}


static int
docmdstring(argc,argv,p)
int argc;
char *argv[];
void *p;
{
	return dostr (argc, argv, "cmdstring", "GPS Position Command String", &CmdStr);
}

static int
doinitstring(argc,argv,p)
int argc;
char *argv[];
void *p;
{
	return dostr (argc, argv, "initstring", "GPS Initialization String", &InitStr);
}

#ifdef GPSDIAG
static int
dosetstring(argc,argv,p)
int argc;
char *argv[];
void *p;
{
	return dostr (argc, argv, "setstring", "Current GPS data string", &CurrentPos);
}
#endif

static int
dotermstring(argc,argv,p)
int argc;
char *argv[];
void *p;
{
	return dostr (argc, argv, "termstring", "GPS Termination String", &TermStr);
}

#ifdef notyet
static int
dotimestring(argc,argv,p)
int argc;
char *argv[];
void *p;
{
	return dostr (argc, argv, "timestring", "GPS Time String", &TimeStr);
}
#endif

static int
dosendstring(argc,argv,p)
int argc;
char *argv[];
void *p;
{
char *response;

	response = GPSsendstr (argv[1]);
	if (*response)
		tprintf ("GPS Response: %s\n", response);
	free (response);
	return 0;
}

