ftp.nice.ch/pub/next/unix/communication/pcomm.NIHS.bs.tar.gz#/pcomm/Source/tty_ucb.c

This is tty_ucb.c in view mode; [Download] [Up]

/*
 * Berkeley specific routines for manipulating the TTY
 */

#include <stdio.h>
#include <sgtty.h>
#include <fcntl.h>
#include "dial_dir.h"
#include "modem.h"
#include "param.h"

static struct sgttyb hold;

/*
 * Change the communication line settings to the new values.
 */

void
line_set()
{
	static int first = 1;
	extern int fd;
	struct sgttyb tbuf;
	int baud;

	if (first) {
		ioctl(fd, TIOCGETP, &hold);
		first = 0;
	}

	/*
	 * The manual dial entry also serves to store the previous
	 * line settings.  How else would the manual dial entry
	 * know what line setting to use?
	 */
	if (dir->d_cur != 0) {
		dir->baud[0] = dir->baud[dir->d_cur];
		dir->parity[0] = dir->parity[dir->d_cur];
		dir->dbits[0] = dir->dbits[dir->d_cur];
		dir->sbits[0] = dir->sbits[dir->d_cur];
	}
					/* nothing to do! */
	if (fd == -1)
		return;
					/* get the current settings */
	ioctl(fd, TIOCGETP, &tbuf);
					/* set some beginning values */
	tbuf.sg_flags = CBREAK;

	if (*param->flow == 'X')
		tbuf.sg_flags |= TANDEM;
					/* the baud rate */
	baud = modem->init_sp[modem->m_cur];
	if (baud == 0)
		baud = dir->baud[dir->d_cur];

	switch (baud) {
		case 300:
			tbuf.sg_ispeed = B300;
			tbuf.sg_ospeed = B300;
			break;
		case 1200:
			tbuf.sg_ispeed = B1200;
			tbuf.sg_ospeed = B1200;
			break;
		case 2400:
			tbuf.sg_ispeed = B2400;
			tbuf.sg_ospeed = B2400;
			break;
		case 4800:
			tbuf.sg_ispeed = B4800;
			tbuf.sg_ospeed = B4800;
			break;
		case 9600:
			tbuf.sg_ispeed = B9600;
			tbuf.sg_ospeed = B9600;
			break;
		case 19200:
#ifdef B19200
			tbuf.sg_ispeed = B19200;
			tbuf.sg_ospeed = B19200;
#else /* B19200 */
#ifdef EXTA
			tbuf.sg_ispeed = EXTA;
			tbuf.sg_ospeed = EXTA;
#endif /* EXTA */
#endif /* B19200 */
			break;
	}
					/* the parity */
	switch (dir->parity[dir->d_cur]) {
		case 'N':
			tbuf.sg_flags |= RAW;
			break;
		case 'O':
			tbuf.sg_flags |= ODDP;
			break;
		case 'E':
			tbuf.sg_flags |= EVENP;
			break;
	}
					/* now set 'em! */
	ioctl(fd, TIOCSETP, &tbuf);
	ioctl(fd, TIOCHPCL, 0);
	return;
}

/*
 * Put things back the way they were.
 */

void
reset_line()
{
	extern int fd;

	ioctl(fd, TIOCSETP, &hold);
	return;
}

/*
 * Put the stdin/stdout in terminal mode.  We've divided up the
 * responsibility for the line settings options between the serial port
 * and the stdin and stdout.
 */

void
term_mode()
{
	struct sgttyb tbuf;

	ioctl(0, TIOCGETP, &tbuf);
	
	tbuf.sg_flags |= RAW;
	tbuf.sg_flags &= ~(CRMOD|ECHO);

	if (dir->duplex[dir->d_cur] == 'H')
		tbuf.sg_flags |= ECHO;

	ioctl(0, TIOCSETP, &tbuf);
	return;
}

/*
 * Put the TTY driver in the mode suitable for xmodem transfers.
 */

void
xmodem_mode(fds)
int fds;
{
	struct sgttyb tbuf;

	ioctl(fds, TIOCGETP, &tbuf);
	/*
	 * Turn off the XON/XOFF flow control, turn off echoing, and
	 * switch to 8 bit no parity.
	 */
	tbuf.sg_flags |= (RAW|ANYP);
	tbuf.sg_flags &= ~ECHO;
	ioctl(fds, TIOCSETP, &tbuf);
	return;
}

/*
 * Put the TTY line in a mode suitable for the ASCII transfer.
 */

void
ascii_mode(up)
int up;
{
	extern int fd;
	struct sgttyb tbuf;

	ioctl(fd, TIOCGETP, &tbuf);

	tbuf.sg_flags |= (CBREAK|TANDEM);
	tbuf.sg_flags &= ~(RAW|CRMOD|ECHO|CRDELAY);

	if (up) {
					/* CR delay times */
		switch (param->cr_delay) {
			case 0:
				break;
			case 100:
				tbuf.sg_flags |= CR1;
				break;
			case 150:
				tbuf.sg_flags |= CR2;
				break;
		}
	}

	ioctl(fd, TIOCSETP, &tbuf);
	return;
}

/*
 * Flush the file descriptor.  Very messy... flushing the input causes a
 * wait for the output to drain, and there is no output flushing.
 */

int
tty_flush(fds, mode)
int fds, mode;
{
	int ret_code = 0;
	struct sgttyb tbuf;

	switch(mode) {
		case 0:			/* flush input queue */
			ioctl(fds, TIOCGETP, &tbuf);
			ioctl(fds, TIOCSETP, &tbuf);
			break;
		case 1:			/* flush output queue */
			/* sorry! */
			break;
		case 2:			/* flush both input and output */
			ioctl(fds, TIOCFLUSH, 0);
			break;
		default:
			ret_code++;
			break;
	}
	return(ret_code);
}

/*
 * Wait for the output to drain
 */

int
tty_drain(fds)
int fds;
{
	struct sgttyb tbuf;
					/* this flushes the input too */
	ioctl(fds, TIOCGETP, &tbuf);
	return(ioctl(fds, TIOCSETP, &tbuf));
}

/*
 * Send a modem break
 */

int
tty_break(fds)
int fds;
{
	unsigned int sleep();

	ioctl(fds, TIOCSBRK, (struct sgttyb *) 0);
	sleep(1);
	return(ioctl(fds, TIOCCBRK, (struct sgttyb *) 0));
}

/*
 * Fix the file descriptor so that a read is satisfied immediately.  When
 * read() is called it returns the character in the queue, or an error if
 * no key was pressed.
 */

int
tty_noblock(fds, on)
int fds, on;
{
	int current;

	current = fcntl(fds, F_GETFL, 0);
	if (on)
		return(fcntl(fds, F_SETFL, current | FNDELAY));
	else
		return(fcntl(fds, F_SETFL, current & ~FNDELAY));
}

/*
 * Get the current baud rate of the terminal
 */

int
my_speed()
{
	static int speed[15] = {0, 50, 75, 110, 134, 150, 200, 300, 600,
	 1200, 1800, 2400, 4800, 9600, 19200};
	struct sgttyb tbuf;

	ioctl(0, TIOCGETP, &tbuf);
	return(speed[tbuf.sg_ispeed]);
}

/*
 * Restart any XON/XOFF flow control that may have stopped the tty 
 */

void
tty_restart()
{
	extern int fd;

	if (fd != -1 && *param->flow == 'X')
		ioctl(fd, TIOCFLUSH, (struct sgttyb *) 0);
	return;
}

These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.