h45547
s 00002/00002/00457
d D 1.6 90/09/25 09:08:57 opcode 6 5
c fixed problem in readn for Sun version
e
s 00022/00001/00437
d D 1.5 90/09/08 09:16:29 opcode 5 4
c 386i compatibility - #ifdef TCSANOW
e
s 00034/00040/00404
d D 1.4 90/09/07 17:13:10 opcode 4 3
c use termios
e
s 00036/00008/00408
d D 1.3 90/06/08 09:29:45 opcode 3 2
c -r and -b command line args
e
s 00005/00002/00411
d D 1.2 89/10/19 09:50:18 opcode 2 1
c WIRETAP ifdefs
e
s 00413/00000/00000
d D 1.1 89/10/12 17:03:22 opcode 1 0
c date and time created 89/10/12 17:03:22 by opcode
e
u
U
f e 0
t
T
I 1
#ifndef	lint
D 3
static char sccsid[] = "@(#)rs232_c 1.5 88/12/21";
E 3
I 3
D 4
static char sccsid[] = "%Z% %M% %I% %E%";
E 4
I 4
static char sccsid[] = "@(#) rs232.c 1.4 90/06/25";
E 4
E 3
#endif

#include "cbratp.h"
#include <stdio.h>
#include <fcntl.h>
D 4
#include <sgtty.h>
E 4
I 4
#include <sys/filio.h>
E 4
I 3
#include <termios.h>
E 3

#ifdef ATT
#include <2681.h>
#endif

#if	ATARI || ATT
#define	DEFAULT_BAUDRATE	1
static int ttybaudrates[] = {
    19200, 9600, 4800,  0 /* 3600 */, 2400, 0 /* 2000 */, 1800,
    1200, 600, 300, 200, 150, 134, 110, 75, 50, -1
};
#endif	ATARI || ATT

#ifdef	SUN
#define	DEFAULT_BAUDRATE	(B9600)
static int ttybaudrates[] = {
    0, 50, 75, 110, 134, 150, 200, 300, 600,
    1200, 1800, 2400, 4800, 9600, 19200, 38400,
};
D 4
struct sgttyb initialsg;
struct sgttyb rs232sg;
E 4
I 4
struct termios rs232_termios;
E 4
I 2
extern void exit();
E 2
#endif	SUN

#define BUFSIZE	1024

int	rs232_fd;
static int	rs232_icnt;
static u_char	*rs232_head;
static u_char	*rs232_tail;
static u_char	*rs232_optr;
static u_char	rs232_ibuf[BUFSIZE];
static u_char	rs232_obuf[MAXPKTSIZE];

long bytes_in;
long bytes_out;
long escapes_in;
long escapes_out;
/*
D 3
 * rs232init(p)
E 3
I 3
 * rs232init(p, baud, rtscts)
E 3
 *	opens 'p' as the raw io layer. sets the initial baudrate
I 3
 *	to the default or 'baud' if it is nonzero.  On a Sun,
 *	sets RTS/CTS flow control if 'rtscts' nonzero.
E 3
 *
 * Returns: 1 if successful
 *	    0 if failed
 */
D 3
rs232init(p)
    char	*p;
E 3
I 3
rs232init(p, baud, rtscts)
    char *p;
    int baud;
    int rtscts;
E 3
{
I 4
    int ispeed;

E 4
D 3
    default_baudrate = ttybaudrates[DEFAULT_BAUDRATE];
    rs232baudrate = default_baudrate;
E 3
I 3
    rs232baudrate = ttybaudrates[DEFAULT_BAUDRATE];
E 3

#ifdef SUN
    if (((rs232_fd = open(p, O_RDWR)) < 0) ||
D 3
				    (fcntl(rs232_fd, F_SETFL, FNDELAY) < 0))
E 3
I 3
	(fcntl(rs232_fd, F_SETFL, FNDELAY) < 0)) {
	perror("rs232init, open");
E 3
	return 0;
I 3
    }
E 3

#ifdef	DEBUG
    if (rs232_debug)
	(void) fprintf(rs232_debugfile, "rs232fd = %d\n", rs232_fd);
#endif	DEBUG
I 3

I 5
#ifdef	TCSANOW
E 5
E 3
D 4
    (void) ioctl(rs232_fd, TIOCGETP, &initialsg);
    rs232sg = initialsg;
    rs232setraw();
    rs232baudrate = ttybaudrates[rs232sg.sg_ispeed];
E 4
I 4
    tcgetattr(rs232_fd, &rs232_termios);
    setraw(rs232_fd, &rs232_termios);
    if ((ispeed = cfgetispeed(&rs232_termios)) == 0)
	if ((ispeed = cfgetospeed(&rs232_termios)) == 0)
	    ispeed = DEFAULT_BAUDRATE;
I 5
#else
    ioctl(rs232_fd, TCGETS, &rs232_termios);
    setraw(rs232_fd, &rs232_termios);
    if ((ispeed = rs232_termios.c_cflag & (CIBAUD << IBSHIFT)) == 0)
	if ((ispeed = rs232_termios.c_cflag & CBAUD) == 0)
	    ispeed = DEFAULT_BAUDRATE;
#endif	/*TCSANOW*/
E 5
E 4
I 3

D 4
    if (rtscts) {
	struct termios  termios;
E 4
I 4
    rs232baudrate = ttybaudrates[ispeed];
E 4

D 4
	/* Enable RTS/CTS flow control */
	if (ioctl(rs232_fd, TCGETS, &termios) < 0) {
	    (void) ioctl(rs232_fd, TIOCSETP, &initialsg);
	    perror("Enabling RTS/CTS flow control: TCGETS");
	    return(0);
	}

	termios.c_cflag |= CRTSCTS;

	if (ioctl(rs232_fd, TCSETS, &termios) < 0) {
	    (void) ioctl(rs232_fd, TIOCSETP, &initialsg);
	    perror("Enabling RTS/CTS flow control: TCSETS");
	    return(0);
	}
E 4
I 4
    if (rtscts) {
	rs232_termios.c_cflag |= CRTSCTS;
I 5
#ifdef	TCSANOW
E 5
	tcsetattr(rs232_fd, TCSANOW, &rs232_termios);
I 5
#else
	ioctl(rs232_fd, TCSETS, &rs232_termios);
#endif	/*TCSANOW*/
E 5
E 4
    }
E 3
#endif	SUN

I 3
    if (baud)
	rs232baudrate = baud;

E 3
    (void) set_baudrate(rs232baudrate);
    min_timeout = 10000000 / rs232baudrate;
    rs232_optr = rs232_obuf;
    rs232_head = rs232_ibuf;
    rs232_tail = rs232_head;
    rs232_icnt = 0;

    return 1;
}

/*
 * set_baudrate(speed)
 *	sets the baudrate to speed.
 *	returns 0 if can't
 */
set_baudrate(speed)
    register int speed;
{
    register int i;

#ifdef	ATARI
    extern short curspd;

    for (i = 0; ttybaudrates[i] != speed && ttybaudrates[i] >= 0;)
	i++;
    if (ttybaudrates[i] < 0)
	return 0;

    curspd = i;
    rs232set();
#endif	ATARI

#ifdef ATT
    switch (speed) {
    case 300:
	DUART->a_sr_csr = (char) BD300BPS;
	break;
    case 600:
	DUART->a_sr_csr = (char) BD600BPS;
	break;
    case 1200:
	DUART->a_sr_csr = (char) BD1200BPS;
	break;
    case 2400:
	DUART->a_sr_csr = (char) BD2400BPS;
	break;
    case 4800:
	DUART->a_sr_csr = (char) BD4800BPS;
	break;
    case 9600:
	DUART->a_sr_csr = (char) BD9600BPS;
	break;
    case 19200:
	DUART->a_sr_csr = (char) BD19200BPS;
	break;
    default:
	return 0;
    }
#endif ATT

#ifdef	SUN
    for (i = B38400; i >= B1200; i--)
	if (ttybaudrates[i] == speed)
	    break;
    
    if (i == B600)
	return(0);

I 5
#ifdef	TCSANOW
E 5
D 4
    rs232sg.sg_ispeed = i;
    rs232sg.sg_ospeed = i;
E 4
I 4
    cfsetispeed(&rs232_termios, i);
    cfsetospeed(&rs232_termios, i);
    tcsetattr(rs232_fd, TCSANOW, &rs232_termios);
I 5
#else
    rs232_termios.c_cflag |= i;
    ioctl(rs232_fd, TCSETS, &rs232_termios);
#endif	/*TCSANOW*/
E 5
E 4

    if (rs232_stats != NULL)
	(void) fprintf(rs232_stats, "sp\t%d\n", speed);
D 4
    rs232setraw();
    if (ioctl(rs232_fd, TIOCSETP, &rs232sg) < 0) {
	perror("setspeed");
        exit(1);
    }
E 4
I 4

    setraw(rs232_fd, &rs232_termios);
E 4
D 3

E 3
#endif	SUN

    rs232baudrate = speed;
    usleep(100000);
    min_timeout = 10000000 / speed;

    return 1;
}

#ifdef	SUN
/*
D 4
 * rs232setraw()
 * 	sets the line to be 8 bit with no special characters
E 4
I 4
 * setraw(fd, termios_p)
 * 	sets the line associated with fd to be 8 bit
 *	with no special characters.  Returns the new
 *	setting in *termios_p.
E 4
 */
D 4
rs232setraw()
E 4
I 4
setraw(fd, termios_p)
    int fd;
    register struct termios *termios_p;
E 4
{
D 4
    rs232sg.sg_flags &= ~ECHO;
    rs232sg.sg_flags |= RAW;
    if (ioctl(rs232_fd, TIOCSETP, &rs232sg) < 0) {
	perror("setraw");
	exit(1);
    }
E 4
I 4
    termios_p->c_cflag |= CS8;
    termios_p->c_cflag &= ~(PARENB);
    termios_p->c_iflag &= ~(IMAXBEL|BRKINT|IGNPAR|PARMRK|INPCK|ISTRIP|INLCR|
		    IGNCR|ICRNL|IUCLC|IXON);
    termios_p->c_oflag &= ~(OPOST);
D 5
    termios_p->c_lflag &= ~(ISIG|ICANON|XCASE|IEXTEN|ECHO);
E 5
I 5
    termios_p->c_lflag &= ~(ISIG|ICANON|XCASE|ECHO);
E 5

I 5
#ifdef	TCSANOW
E 5
    tcsetattr(fd, TCSANOW, termios_p);
I 5
#else
    ioctl(fd, TCSETS, termios_p);
#endif	/*TCSANOW*/
E 5
E 4
}
#endif	SUN

/*
 * rs232rawkey()
 *	returns the next character off the input queue
 *	returns NEED_MORE if no characters available
 */
rs232rawkey()
{
    int	i;

    if (rs232_icnt == 0)
	return NEED_MORE;

    bytes_in++;
    rs232_icnt--;
    i = *rs232_head++ & 0xff;
    if (rs232_head == rs232_ibuf + BUFSIZE)
	rs232_head = rs232_ibuf;

    return i;
}

static int escaped;

/*
 * rs232in()
 *	returns the next charcter off the input queue
 *	escaped characters are expanded.
 *	returns START_STOP if the start/stop character was next
 *	returns NEED_MORE if there are no characters
 */
rs232in()
{
    register int	c;

    if ((c = rs232rawkey()) == NEED_MORE)
	return NEED_MORE;

    if (escaped) {
	escapes_in++;
	escaped = 0;
	return c ^ 0x20;
    }

    if (c == START_STOP)
	return START;

    if (c == ESCAPE_BYTE) {
	escaped = 1;
	c = rs232in();
    }

    return c;
}

/*
 * rs232ready()
 *	returns the number of characters in the input queue
 *	and fills the input queue from the raw device
 */
rs232ready()
{
    int	i = 0;

#if	ATARI||ATT
    while (rs232rdy() && rs232_icnt != BUFSIZE) {
	i = rs232key();
	*rs232_tail++ = i;
	if (rs232_tail == rs232_ibuf + BUFSIZE)
	    rs232_tail = rs232_ibuf;
	rs232_icnt++;
    }
#endif	ATARI||ATT

#ifdef	SUN
    if (ioctl(rs232_fd, FIONREAD, &i) < 0)
	perror("rs232ready");
    if (i <= 0)
	return rs232_icnt;
    
    if (i > BUFSIZE - rs232_icnt)
	i = BUFSIZE - rs232_icnt;

    if (rs232_tail >= rs232_head) 
    {
	register int	above = rs232_ibuf + BUFSIZE - rs232_tail;

	if (above > i)
	    readn(rs232_fd, (char *) rs232_tail, i);
	else {
	    readn(rs232_fd, (char *) rs232_tail, above);
	    readn(rs232_fd, (char *) rs232_ibuf, i - above);
	}
    }
    else
	readn(rs232_fd, (char *) rs232_tail, i);
    rs232_icnt += i;
    rs232_tail += i;
    if (rs232_tail >= rs232_ibuf + BUFSIZE)
	rs232_tail -= BUFSIZE;
#endif	SUN

    return rs232_icnt;
}

#ifdef	SUN
/*
 * readn(fd, ptr, n)
 *	reads n bytes from file descriptor fd to ptr.
 *	assumes that n bytes are guaranteed
 */
readn(fd, ptr, n)
    int	fd;
    register char *ptr;
    register int n;
{
D 6
    int i;
E 6
I 6
    register int i;
E 6

    while ((i = read(fd, ptr, n)) >= 0 && (n -= i) > 0) {
#ifdef	DEBUG
	if (rs232_debug)
	    (void) fprintf(rs232_debugfile, "readn(%d)...\n", n);
#endif	DEBUG
D 6
	ptr += n;
E 6
I 6
	ptr += i;
E 6
    }
}
#endif	SUN

/*
 * rs232oready()
 *	returns number of characters on raw output device being send
 */
rs232oready()
{
#ifdef	SUN
    int	i = 0;

    if (ioctl(rs232_fd, TIOCOUTQ, &i) < 0)
	perror("rs232oready");
    return i;
#endif	SUN

#ifdef ATT
    return !rs232ordy();
#endif ATT

#ifdef	ATARI
    /* ### flow cntrl bug return !rs232ordy(); */
    return 0;
#endif	ATARI
}

/*
 * rs232rawemit(c)
 *	write character c onto output queue
 */
rs232rawemit(c)
u_char	c;
{
    *rs232_optr++ = c;
}

/*
 * rs232flush()
 *	write all characters on output queue to raw output device
 */
rs232flush()
{
#ifndef	SUN
    register u_char *p;
#endif	/*SUN*/

    timeout = timer() + 1000 + 2 * MAXPKTSIZE * min_timeout/1000;
#ifdef	DEBUG
    if (*rs232_obuf&RETRY && rs232_debug) {
	u_char *cp = rs232_obuf;
	(void) fprintf(rs232_debugfile,
		    "retry: seq = %d, ack = %d, myseq = %d, myack = %d",
		    SEQ(*cp), ACK(*cp), reader.lastack, writer.frame);
	++cp;
	(void) fprintf(rs232_debugfile, "\tchannel = %d\n\t[ ", *cp);
	while (++cp != rs232_optr)
	    (void) fprintf(rs232_debugfile, "%02x ", *cp);
	(void) fprintf(rs232_debugfile, "]\n");
    }
#endif	DEBUG

#if ATARI||ATT
    for (p = rs232_obuf; p != rs232_optr; p++) {
	while (!rs232ordy())
	    ;
	rs232emit(*p);
    }
#endif ATARI||ATT

#ifdef SUN
    if (write(rs232_fd, (char *) rs232_obuf, rs232_optr - rs232_obuf) < 0)
	perror("rs232write");
#endif	SUN

    rs232_optr = rs232_obuf;
}

/*
 * rs232out(c)
 *	write character c to the output queue escaping it if necessary
 */
rs232out(c)
    u_char	c;
{
    bytes_out++;
#ifdef ESCAPEDCONTROL
    if ( c < 0x20 || c == START_STOP || c == ESCAPE_BYTE || c == '~') {
#else
    if (c == START_STOP || c == ESCAPE_BYTE || c == '~') {
#endif
	escapes_out++;
	rs232rawemit(ESCAPE_BYTE);
	rs232rawemit(c^0x20);
	return;
    }
    rs232rawemit(c);
}

D 2
#ifdef SUN
E 2
I 2
#ifndef	WIRETAP
#ifdef	SUN
E 2
#ifndef	HELPER
/*
 * con_emit(s)
 *	output string s to the console
 */
con_emit(s)
    char *s;
{
    (void) write(1, s, strlen(s));
}
#endif	/*HELPER*/
D 2
#endif SUN
E 2
I 2
#endif	/*SUN*/
#endif	/*WIRETAP*/
E 2
E 1
