/* GPS port-related user commands
 *   (c) 1993 Brian A. Lantz
 */
#include "global.h"
#ifdef GPS
#include "commands.h"
#include "mbuf.h"
#include "proc.h"
#include "netuser.h"
#include "internet.h"
#include "iface.h"
#ifndef UNIX
#include "n8250.h"
#endif
#include "asy.h"
#ifdef UNIX
#include "unixasy.h"
#endif
#include "gps.h"
#include "files.h"

#if !defined(_lint)
static char rcsid[] OPTIONAL = "$Id: gps.c,v 1.21 2001/05/06 16:32:56 brian Exp $";
#endif

#define GPSDIAG 1

static unsigned short GPStype = 0;
static struct iface *GPSactive = NULLIF;
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

static void GPSrawsend (unsigned char *str, int len);
static char *GPSgetstr (void);
static int dogpsstr (int argc,char *argv[],const char *label, const char *description, char **str);

#ifdef GPSDIAG
static void pprintf (const char *str, char *arg);

static void
pprintf (str, arg)
const char *str;
char *arg;
{
	tcmdprintf (str, arg);
	(void) fflush(stdout);
}
#endif

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

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


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


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


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

#ifdef GPSDIAG
	pprintf("GPSsendstr() reached\n", NULLCHAR);
#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 OPTIONAL;
char *argv[];
void *p OPTIONAL;
{
register struct iface *ifp;
register struct asy *ap;
char *response, *cp;
#if 0
int (*rawsave)(struct iface *,struct mbuf *);
#endif

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

	/* Save output handler and temporarily redirect output to null */
#if 0
	rawsave = ifp->raw;
#endif
	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", NULLCHAR);
#endif
#ifdef GPSDIAG
		pprintf("GPS initialization complete\n", NULLCHAR);
#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 */
			if (fp)	{
				rewind (fp);
				fwrite (fullbuf, 1, GPSMAXLEN, fp);
				(void) fclose (fp);
			}
		}
	}
#if 0
#ifdef GPSDIAG
	pprintf("GPS shutting down\n", NULLCHAR);
#endif
	free (GPSsendstr (TermStr));
	GPSactive = NULLIF;
	ifp->raw = rawsave;
	resume(ifp->rxproc);
	return 0;
#endif
}

int
GPSstop(argc,argv,p)
int argc OPTIONAL;
char *argv[];
void *p OPTIONAL;
{
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
dogpsstr(argc,argv,label,description,str)
int argc;
char *argv[];
const char *label, *description;
char **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 (int argc,char *argv[],void *p); 
static int doinitstring (int argc,char *argv[],void *p); 
static int dosendstring (int argc,char *argv[],void *p);
#ifdef GPSDIAG
static int dosetstring (int argc,char *argv[],void *p);
#endif
static int dotermstring (int argc,char *argv[],void *p);
static int dotype (int argc,char *argv[],void *p);
#ifdef notyet
static int dotimestring (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,	NULL,		0,	0,	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 OPTIONAL;
{
	return setshort (&GPStype, "GPS manufacturer type:",argc, argv);
}


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

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

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

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

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

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

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

#endif
