eph_open.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 <sys/types.h>
#if defined(MSWINDOWS)
#include "usleep.h"
#elif defined(UNIX)
#include <unistd.h>
#include <termios.h>
#elif defined(DOS)
#include "comio.h"
#include "usleep.h"
#else
#error platform not defined
#endif
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <errno.h>

#ifdef MSWINDOWS
#define ERRNO GetLastError()
#else
#define ERRNO errno
#endif

#if defined(MSWINDOWS)

#define DEFSPEED 19200
#define CLOSE CloseHandle

#elif defined(UNIX)

#define DEFSPEED EXTA
#define CLOSE close

#elif defined(DOS)

#define DEFSPEED 19200
#define CLOSE(x)  ttclose()

void exit_cleanup(void) {
	ttclose();
}

#define ABORT 0

int c_break(void) {
	printf("\naborting program...%c\n", 7);
	ttclose();
	exit(255);	/* will call any exit handlers */
	/* notreached */
}

#else
#error platform not defined
#endif

int eph_open(eph_iob *iob,char *devname,long speed) {
#if defined(MSWINDOWS)
	DCB dcb = { 0 };
	char commtext[80];
#elif defined(UNIX)
	struct termios tios;
	speed_t tspeed;
#elif defined(DOS)
	int port;
#else
#error platform not defined
#endif
	long ephspeed;
	int rc;
	int count=0;

	if (speed == 0) speed=MAX_SPEED;

	switch (speed) {
	case 9600:
#ifdef UNIX
		tspeed=B9600;
#endif
		ephspeed=1;	break;
	case 19200:
#ifdef UNIX
		tspeed=EXTA;
#endif
		ephspeed=2;	break;
	case 38400:
#ifdef UNIX
		tspeed=EXTB;
#endif
		ephspeed=3;	break;
	case 57600:
#ifdef UNIX
#ifdef B57600
		tspeed=B57600;
#else
		eph_error(iob,ERR_BADSPEED,"specified speed %ld unsupported",
									speed);
		return -1;
#endif
#endif
		ephspeed=4;	break;
	case 115200:
#ifdef UNIX
#ifdef B115200
		tspeed=B115200;
#else
		eph_error(iob,ERR_BADSPEED,"specified speed %ld unsupported",
									speed);
		return -1;
#endif
#endif
		ephspeed=5;	break;
	default:
		eph_error(iob,ERR_BADSPEED,"specified speed %ld invalid",speed);
		return -1;
	}

	iob->timeout=DATATIMEOUT+((2048000000L)/speed)*10;
	if (iob->debug) printf("set timeout to %lu\n",DATATIMEOUT+iob->timeout);

#if defined(DOS)
	if (strcasecmp(devname,"COM1:") == 0) {
		port = 1;
	} else if (strcasecmp(devname,"COM2:") == 0) {
		port = 2;
	} else {
		eph_error(iob,ERRNO,"device name %s not COM1: or COM2:",
					devname);
		return -1;
	}
	ctrlbrk(c_break);
	atexit(exit_cleanup);
	usleep(1);
	if (iob->debug)
		printf("delay factor: %g loops/usec\n",(float)delay_factor);
	TTinit(port, DEFSPEED);
	if (ttopen()) {
		errno=2;
#elif defined(MSWINDOWS)
	if ((iob->fd=CreateFile(devname,
				GENERIC_READ | GENERIC_WRITE,
				0,
				0,
				OPEN_EXISTING,
				0,
				0)) == INVALID_HANDLE_VALUE) {
#elif defined(UNIX)
#ifndef O_NONBLOCK
#define O_NONBLOCK O_NDELAY
#endif
	if ((iob->fd=open(devname,O_RDWR | O_NONBLOCK)) < 0) {
#else
#error platform not defined
#endif
		if (strlen(devname) < 400) /* we have 512 byte buffer there */
			eph_error(iob,ERRNO,"open %s error %s",
						devname,strerror(ERRNO));
		return -1;
	}

#if defined(MSWINDOWS)

	if (!GetCommState(iob->fd, &dcb)) {
		eph_error(iob,ERRNO,"GetCommState error %s",strerror(ERRNO));
		CLOSE(iob->fd);
		return -1;
	}

	memcpy(&iob->savedcb,&dcb,sizeof(dcb));
	memset((char*)&dcb,0,sizeof(dcb));
	dcb.DCBlength = sizeof(dcb);
	sprintf(commtext, "%d,n,8,1", DEFSPEED);
	if (!BuildCommDCB(commtext, &dcb)) {
		eph_error(iob,ERRNO,"BuildCommDCB error %s",strerror(ERRNO));
		CLOSE(iob->fd);
		return -1;
	}
	if (!SetCommState(iob->fd, &dcb)) {
		eph_error(iob,ERRNO,"SetCommState error %s",strerror(ERRNO));
		CLOSE(iob->fd);
		return -1;
	}

	if (!GetCommTimeouts(iob->fd, &iob->savetimeouts)) {
		eph_error(iob,ERRNO,"GetCommTimeouts error %s",strerror(ERRNO));
		CLOSE(iob->fd);
		return -1;
	}
	iob->worktimeouts.ReadIntervalTimeout=0;
	iob->worktimeouts.ReadTotalTimeoutMultiplier=1;
	iob->worktimeouts.ReadTotalTimeoutConstant=1000;
	iob->worktimeouts.WriteTotalTimeoutMultiplier=0;
	iob->worktimeouts.WriteTotalTimeoutConstant=0;
	if (!SetCommTimeouts(iob->fd, &iob->worktimeouts)) {
		eph_error(iob,ERRNO,"SetCommTimeouts initial attr error %s",
					strerror(ERRNO));
		CLOSE(iob->fd);
		return -1;
	}

#elif defined(UNIX)

	if (tcgetattr(iob->fd,&tios) < 0) {
		eph_error(iob,ERRNO,"tcgetattr error %s",strerror(ERRNO));
		close(iob->fd);
		return -1;
	}
	memcpy(&iob->savetios,&tios,sizeof(tios));
#ifdef HAVE_CFMAKERAW
	cfmakeraw(&tios);
#else
	tios.c_iflag=0;
	tios.c_oflag=0;
	tios.c_lflag=0;
#endif
	cfsetospeed(&tios,DEFSPEED);
	cfsetispeed(&tios,DEFSPEED);
#ifdef USE_VMIN_AND_VTIME
	tios.c_cc[VMIN]=127;
	tios.c_cc[VTIME]=1;
#else
	tios.c_cc[VMIN]=1;
	tios.c_cc[VTIME]=0;
#endif
	tios.c_cflag|=(CS8|CLOCAL|CREAD);
	tios.c_cflag&=~(PARENB|PARODD
#ifdef TRY_FLOW_CONTROL
# ifdef CRTSXOFF
					|CRTSXOFF
# endif
# ifdef CRTSCTS
						|CRTSCTS
# endif
# ifdef CRTSFL
							|CRTSFL
# endif
#endif
								);
	tios.c_iflag&=~INPCK;
	tios.c_iflag|=IGNBRK;
	if (tcsetattr(iob->fd,TCSANOW,&tios)) {
		eph_error(iob,ERRNO,"tcsetattr initial attr error %s",
					strerror(ERRNO));
		close(iob->fd);
		return -1;
	}

#endif /* MSWINDOWS/UNIX; do nothing for DOS */

	do {
		eph_writeinit(iob);
		rc=eph_waitsig(iob);
		if (rc) usleep(3000000L);
	} while (rc && (count++ < RETRIES));
	if (rc) {
		CLOSE(iob->fd);
		return -1;
	}

	if (eph_setispeed(iob,ephspeed)) {
		eph_error(iob,ERRNO,"could not switch camera speed %d: %s",
				ephspeed,strerror(ERRNO));
		CLOSE(iob->fd);
		return -1;
	}

#if defined(MSWINDOWS)
	dcb.BaudRate = speed;
	if (!SetCommState(iob->fd, &dcb)) {
		eph_error(iob,ERRNO,"SetCommState working attr error %s",
					strerror(ERRNO));
#elif defined(UNIX)
	cfsetospeed(&tios,tspeed);
	cfsetispeed(&tios,tspeed);
	if (tcsetattr(iob->fd,TCSANOW,&tios)) {
		eph_error(iob,ERRNO,"tcsetattr working attr error %s",
					strerror(ERRNO));
#elif defined(DOS)
	ttclose();
	TTinit(port, speed);
	if (ttopen()) {
		errno = 0;
		eph_error(iob,ERRNO,"dobaud set working attr error %s",
					strerror(ERRNO));
#else
#error platform not defined
#endif
		CLOSE(iob->fd);
		return -1;
	}

	usleep(SPEEDCHGDELAY);
	return 0;
}

int eph_close(eph_iob *iob,int newmodel) {

	if (newmodel) {
		eph_setispeed(iob,0L);
	} else {
		char zero=0;

		eph_action(iob,4,&zero,1);
		eph_waiteot(iob);
	}

#if defined(MSWINDOWS)
	if (!SetCommState(iob->fd, &iob->savedcb))
		eph_error(iob,ERRNO,"SetCommState reset attr error %s",
					strerror(ERRNO));
	if (!SetCommTimeouts(iob->fd, &iob->savetimeouts))
		eph_error(iob,ERRNO,"SetCommTimeouts reset attr error %s",
					strerror(ERRNO));
#elif defined(UNIX)
	if (tcsetattr(iob->fd,TCSANOW,&iob->savetios))
		eph_error(iob,ERRNO,"tcsetattr cound not reset attr: %s",
					strerror(ERRNO));
#endif /* MSWINDOWS/UNIX; do nothing for DOS */

	return CLOSE(iob->fd);
}

Back