eph_cmd.c


/*
	Copyright (c) 1997,1998 Eugene G. Crosser
	Copyright (c) 1998 Bruce D. Lightner (DOS/Windows support)

	You may do virtually what you wish with this software, as long
	as the explicit reference to its original author is retained.

	THIS SOFTWARE IS PROVIDED AS IS AND COME WITH NO WARRANTY OF ANY
	KIND, EITHER EXPRESSED OR IMPLIED.  IN NO EVENT WILL THE
	COPYRIGHT HOLDER BE LIABLE FOR ANY DAMAGES RESULTING FROM THE
	USE OF THIS SOFTWARE.
*/

#include "eph_io.h"
#include "eph_priv.h"
#include <stdio.h>

#define TMPBUF_SIZE (2048)

#define MAYRETRY(rc) ((rc == -2) || (rc == NAK))

int eph_writecmd(eph_iob *iob,char *data,size_t length) {
	return eph_writepkt(iob,PKT_CMD,SEQ_CMD,data,length);
}

int eph_writeicmd(eph_iob *iob,char *data,size_t length) {
	return eph_writepkt(iob,PKT_CMD,SEQ_INITCMD,data,length);
}

int eph_setispeed(eph_iob *iob,long val) {
	unsigned char buf[6];
	int rc;
	int count=0;

	buf[0]=CMD_SETINT;
	buf[1]=REG_SPEED;
	buf[2]=(val)&0xff;
	buf[3]=(val>>8)&0xff;
	buf[4]=(val>>16)&0xff;
	buf[5]=(val>>24)&0xff;
	do {
		if ((rc=eph_writeicmd(iob,buf,6))) return rc;
		rc=eph_waitack(iob,ACKTIMEOUT);
	} while (rc && (count++ < RETRIES));
	if (count >= RETRIES)
		eph_error(iob,ERR_EXCESSIVE_RETRY,
				"excessive retries on setispeed");
	return rc;
}

int eph_setint(eph_iob *iob,int reg,long val) {
	unsigned char buf[6];
	int rc;
	int count=0;

	buf[0]=CMD_SETINT;
	buf[1]=reg;
	buf[2]=(val)&0xff;
	buf[3]=(val>>8)&0xff;
	buf[4]=(val>>16)&0xff;
	buf[5]=(val>>24)&0xff;

writeagain:
	if ((rc=eph_writecmd(iob,buf,6))) return rc;
	rc=eph_waitack(iob,(reg == REG_FRAME)?BIGACKTIMEOUT:ACKTIMEOUT);
	if (MAYRETRY(rc) && (count++ < RETRIES)) goto writeagain;
	if (count >= RETRIES)
		eph_error(iob,ERR_EXCESSIVE_RETRY,
				"excessive retries on setint");

	return rc;
}

int eph_getint(eph_iob *iob,int reg,long *val) {
	unsigned char buf[4];
	eph_pkthdr pkt;
	int rc,size=4;
	int count=0;

	(*val)=0L;
	buf[0]=CMD_GETINT;
	buf[1]=reg;

writeagain:
	if ((rc=eph_writecmd(iob,buf,2))) return rc;
readagain:
	rc=eph_readpkt(iob,&pkt,buf,&size,BIGDATATIMEOUT);
	if (MAYRETRY(rc) && (count++ < RETRIES)) goto writeagain;
	if ((rc == 0) && (pkt.typ == PKT_LAST) && (pkt.seq == 0)) {
		(*val)=((unsigned long)buf[0]) | ((unsigned long)buf[1]<<8) |
			((unsigned long)buf[2]<<16) | ((unsigned long)buf[3]<<24);
		eph_writeack(iob);
		return 0;
	} else if ((rc == -1) && (count++ < RETRIES)) {
		eph_writenak(iob);
		goto readagain;
	}
	if (count >= RETRIES)
		eph_error(iob,ERR_EXCESSIVE_RETRY,
				"excessive retries on getint");

	return rc;
}

int eph_action(eph_iob *iob,int reg,char *val,size_t length) {
	unsigned char buf[2050];
	int rc;
	int count=0;

	if (length > (sizeof(buf) - 2)) {
		eph_error(iob,ERR_DATA_TOO_LONG,"arg action length %ld",
				(long)length);
		return -1;
	}

	buf[0]=CMD_ACTION;
	buf[1]=reg;
	memcpy(buf+2,val,length);

writeagain:
	if ((rc=eph_writecmd(iob,buf,length+2))) return rc;
	rc=eph_waitack(iob,ACKTIMEOUT);

	if (MAYRETRY(rc) && (count++ < RETRIES)) goto writeagain;

	if (rc == 0) rc=eph_waitcomplete(iob);
	if (count >= RETRIES)
		eph_error(iob,ERR_EXCESSIVE_RETRY,
				"excessive retries on action");
	return rc;
}

int eph_setvar(eph_iob *iob,int reg,char *val,off_t length) {
	unsigned char buf[2048];
	int rc=0,seq=-1;
	int count=0;
	int pkttyp,pktseq;
	size_t pktsize,maywrite,written=0;
	unsigned char *getpoint,*putpoint;

	getpoint=val;
	while (length && !rc) {
		if (seq == -1) {
			pkttyp=PKT_CMD;
			pktseq=SEQ_CMD;
			buf[0]=CMD_SETVAR;
			buf[1]=reg;
			putpoint=buf+2;
			maywrite=sizeof(buf)-2;
			pktsize=2;
		} else {
			pkttyp=PKT_DATA;
			pktseq=seq;
			putpoint=buf;
			maywrite=sizeof(buf);
			pktsize=0;
			(iob->runcb)(written);
		}
		if (length <= maywrite) {
			maywrite=length;
			if (pkttyp == PKT_DATA) pkttyp=PKT_LAST;
		}
		memcpy(putpoint,getpoint,maywrite);
		pktsize+=maywrite;
		length-=maywrite;
		getpoint+=maywrite;
		written+=maywrite;
		seq++;
writeagain:
		if ((rc=eph_writepkt(iob,pkttyp,pktseq,buf,pktsize)))
			return rc;
		rc=eph_waitack(iob,ACKTIMEOUT);
		if (MAYRETRY(rc) && (count++ < RETRIES)) goto writeagain;
	}
	if (count >= RETRIES)
		eph_error(iob,ERR_EXCESSIVE_RETRY,
				"excessive retries on setvar");
	return rc;
}

int eph_getvar(eph_iob *iob,int reg,char **buffer,off_t *bufsize) {
	unsigned char buf[2];
	eph_pkthdr pkt;
	int rc;
	int count=0;
	unsigned char expect=0;
	size_t index,readsize;
	char *ptr;
	char *tmpbuf=NULL;
	size_t tmpbufsize=0;

	if ((buffer == NULL) && (iob->storecb == NULL)) {
		eph_error(iob,ERR_BADARGS,
			"NULL buffer and no store callback for getvar");
		return -1;
	}

	if (buffer == NULL) {
		tmpbuf=(iob->realloccb)(NULL,(size_t)TMPBUF_SIZE);
		tmpbufsize=TMPBUF_SIZE;
		if (tmpbuf == NULL) {
			eph_error(iob,ERR_NOMEM,
				"could not alloc %lu for tmpbuf in getvar",
				(long)TMPBUF_SIZE);
			return -1;
		}
	}

	buf[0]=CMD_GETVAR;
	buf[1]=reg;

writeagain:
	if ((rc=eph_writecmd(iob,buf,2))) return rc;
	index=0;
readagain:
	if (buffer) { /* read to memory reallocating it */
		if (((*bufsize) - index) < 2048) {
			if (iob->debug)
				printf("reallocing %lu",(unsigned long)(*bufsize));
#ifdef LOWMEMORY
			/* small memory! round up to next 2048 boundary */
			(*bufsize)=(((index + 2048)-1)/2048L+1)*2048L;
#else
			/* multiply current size by 2 and round up to 2048 boundary */
			(*bufsize)=((((*bufsize)*2)-1)/2048+1)*2048;
#endif
			if (iob->debug)
				printf(" -> %lu\n",(unsigned long)(*bufsize));
			(*buffer)=(iob->realloccb)(*buffer,*bufsize);
			if ((*buffer) == NULL) {
				eph_error(iob,ERR_NOMEM,
					"could not realloc %lu for getvar",
					(long)*bufsize);
				return -1;
			}
		}
		ptr=(*buffer)+index;
		readsize=(*bufsize)-index;
	} else { /* pass data to store callback */
		ptr=tmpbuf;
		readsize=tmpbufsize;
	}
	rc=eph_readpkt(iob,&pkt,ptr,&readsize,
			(expect || ((reg != REG_IMG) || (reg != REG_TMN)))?
						DATATIMEOUT:BIGDATATIMEOUT);
	if (MAYRETRY(rc) && (expect == 0) && (count++ < RETRIES))
		goto writeagain;
	if ((rc == 0) &&
	    ((pkt.seq == expect) || (pkt.seq  == (expect-1)))) {
		count=0;
		if (pkt.seq == expect) {
			index+=readsize;
			expect++;
			(iob->runcb)(index);
			if (buffer == NULL) {
				if (iob->debug)
					printf("storing %lu at %08lx\n",
						(unsigned long)readsize,
						(unsigned long)ptr);
				if ((iob->storecb)(ptr,readsize))
					return -1;
			}
		}
		eph_writeack(iob);
		if (pkt.typ == PKT_LAST) {
			if (buffer) (*bufsize)=index;
			if (tmpbuf) free(tmpbuf);
			return 0;
		}
		else goto readagain;
	}
	if ((rc <= 0) && (count++ < RETRIES)) {
		eph_writenak(iob);
		goto readagain;
	}
	if (tmpbuf) free(tmpbuf);
	if (count >= RETRIES)
		eph_error(iob,ERR_EXCESSIVE_RETRY,
				"excessive retries on getvar");
	return rc;
}

Back