xref: /freebsd/usr.bin/tip/libacu/t3000.c (revision 5e3934b15a2741b2de6b217e77dc9d798d740804)
1fa92e883SRuslan Ermilov /*	$OpenBSD: t3000.c,v 1.14 2006/03/17 19:17:13 moritz Exp $	*/
20f3bdf5dSMark Murray /*	$NetBSD: t3000.c,v 1.5 1997/02/11 09:24:18 mrg Exp $	*/
30f3bdf5dSMark Murray 
4*8a16b7a1SPedro F. Giffuni /*-
5*8a16b7a1SPedro F. Giffuni  * SPDX-License-Identifier: BSD-3-Clause
6*8a16b7a1SPedro F. Giffuni  *
718cc36fbSJordan K. Hubbard  * Copyright (c) 1992, 1993
818cc36fbSJordan K. Hubbard  *	The Regents of the University of California.  All rights reserved.
918cc36fbSJordan K. Hubbard  *
1018cc36fbSJordan K. Hubbard  * Redistribution and use in source and binary forms, with or without
1118cc36fbSJordan K. Hubbard  * modification, are permitted provided that the following conditions
1218cc36fbSJordan K. Hubbard  * are met:
1318cc36fbSJordan K. Hubbard  * 1. Redistributions of source code must retain the above copyright
1418cc36fbSJordan K. Hubbard  *    notice, this list of conditions and the following disclaimer.
1518cc36fbSJordan K. Hubbard  * 2. Redistributions in binary form must reproduce the above copyright
1618cc36fbSJordan K. Hubbard  *    notice, this list of conditions and the following disclaimer in the
1718cc36fbSJordan K. Hubbard  *    documentation and/or other materials provided with the distribution.
18fa92e883SRuslan Ermilov  * 3. Neither the name of the University nor the names of its contributors
1918cc36fbSJordan K. Hubbard  *    may be used to endorse or promote products derived from this software
2018cc36fbSJordan K. Hubbard  *    without specific prior written permission.
2118cc36fbSJordan K. Hubbard  *
2218cc36fbSJordan K. Hubbard  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
2318cc36fbSJordan K. Hubbard  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2418cc36fbSJordan K. Hubbard  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2518cc36fbSJordan K. Hubbard  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
2618cc36fbSJordan K. Hubbard  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2718cc36fbSJordan K. Hubbard  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2818cc36fbSJordan K. Hubbard  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2918cc36fbSJordan K. Hubbard  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
3018cc36fbSJordan K. Hubbard  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
3118cc36fbSJordan K. Hubbard  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
3218cc36fbSJordan K. Hubbard  * SUCH DAMAGE.
3318cc36fbSJordan K. Hubbard  */
3418cc36fbSJordan K. Hubbard 
3518cc36fbSJordan K. Hubbard /*
3618cc36fbSJordan K. Hubbard  * Routines for calling up on a Telebit T3000 modem.
3718cc36fbSJordan K. Hubbard  * Derived from Courier driver.
3818cc36fbSJordan K. Hubbard  */
3918cc36fbSJordan K. Hubbard #include "tip.h"
400f3bdf5dSMark Murray 
410f3bdf5dSMark Murray #include <sys/ioctl.h>
4218cc36fbSJordan K. Hubbard #include <stdio.h>
4318cc36fbSJordan K. Hubbard 
4418cc36fbSJordan K. Hubbard #define	MAXRETRY	5
4518cc36fbSJordan K. Hubbard 
46fa92e883SRuslan Ermilov static	int dialtimeout = 0;
4718cc36fbSJordan K. Hubbard static	int connected = 0;
48fa92e883SRuslan Ermilov static	jmp_buf timeoutbuf;
49fa92e883SRuslan Ermilov 
50fa92e883SRuslan Ermilov static void	sigALRM(int);
51fa92e883SRuslan Ermilov static int	t3000_swallow(char *);
52fa92e883SRuslan Ermilov static int	t3000_connect(void);
53fa92e883SRuslan Ermilov static int	t3000_sync(void);
54fa92e883SRuslan Ermilov static void	t3000_write(int, char *, int);
55fa92e883SRuslan Ermilov static void	t3000_nap(void);
56fa92e883SRuslan Ermilov #ifdef DEBUG
57fa92e883SRuslan Ermilov static void	t3000_verbose_read(void);
58fa92e883SRuslan Ermilov #endif
5918cc36fbSJordan K. Hubbard 
600f3bdf5dSMark Murray int
t3000_dialer(char * num,char * acu)61fa92e883SRuslan Ermilov t3000_dialer(char *num, char *acu)
6218cc36fbSJordan K. Hubbard {
630f3bdf5dSMark Murray 	char *cp;
640f3bdf5dSMark Murray 	struct termios cntrl;
650f3bdf5dSMark Murray #ifdef ACULOG
6618cc36fbSJordan K. Hubbard 	char line[80];
6718cc36fbSJordan K. Hubbard #endif
6818cc36fbSJordan K. Hubbard 
6918cc36fbSJordan K. Hubbard 	if (boolean(value(VERBOSE)))
7018cc36fbSJordan K. Hubbard 		printf("Using \"%s\"\n", acu);
7118cc36fbSJordan K. Hubbard 
720f3bdf5dSMark Murray 	tcgetattr(FD, &cntrl);
730f3bdf5dSMark Murray 	cntrl.c_cflag |= HUPCL;
740f3bdf5dSMark Murray 	tcsetattr(FD, TCSANOW, &cntrl);
7518cc36fbSJordan K. Hubbard 	/*
7618cc36fbSJordan K. Hubbard 	 * Get in synch.
7718cc36fbSJordan K. Hubbard 	 */
7818cc36fbSJordan K. Hubbard 	if (!t3000_sync()) {
7918cc36fbSJordan K. Hubbard badsynch:
8018cc36fbSJordan K. Hubbard 		printf("can't synchronize with t3000\n");
810f3bdf5dSMark Murray #ifdef ACULOG
8218cc36fbSJordan K. Hubbard 		logent(value(HOST), num, "t3000", "can't synch up");
8318cc36fbSJordan K. Hubbard #endif
8418cc36fbSJordan K. Hubbard 		return (0);
8518cc36fbSJordan K. Hubbard 	}
8618cc36fbSJordan K. Hubbard 	t3000_write(FD, "AT E0\r", 6);	/* turn off echoing */
8718cc36fbSJordan K. Hubbard 	sleep(1);
8818cc36fbSJordan K. Hubbard #ifdef DEBUG
8918cc36fbSJordan K. Hubbard 	if (boolean(value(VERBOSE)))
9018cc36fbSJordan K. Hubbard 		t3000_verbose_read();
9118cc36fbSJordan K. Hubbard #endif
920f3bdf5dSMark Murray 	tcflush(FD, TCIOFLUSH);
9318cc36fbSJordan K. Hubbard 	t3000_write(FD, "AT E0 H0 Q0 X4 V1\r", 18);
9418cc36fbSJordan K. Hubbard 	if (!t3000_swallow("\r\nOK\r\n"))
9518cc36fbSJordan K. Hubbard 		goto badsynch;
9618cc36fbSJordan K. Hubbard 	fflush(stdout);
9718cc36fbSJordan K. Hubbard 	t3000_write(FD, "AT D", 4);
9818cc36fbSJordan K. Hubbard 	for (cp = num; *cp; cp++)
9918cc36fbSJordan K. Hubbard 		if (*cp == '=')
10018cc36fbSJordan K. Hubbard 			*cp = ',';
10118cc36fbSJordan K. Hubbard 	t3000_write(FD, num, strlen(num));
10218cc36fbSJordan K. Hubbard 	t3000_write(FD, "\r", 1);
10318cc36fbSJordan K. Hubbard 	connected = t3000_connect();
1040f3bdf5dSMark Murray #ifdef ACULOG
105fa92e883SRuslan Ermilov 	if (dialtimeout) {
106fa92e883SRuslan Ermilov 		(void)snprintf(line, sizeof line, "%ld second dial timeout",
10718cc36fbSJordan K. Hubbard 			number(value(DIALTIMEOUT)));
10818cc36fbSJordan K. Hubbard 		logent(value(HOST), num, "t3000", line);
10918cc36fbSJordan K. Hubbard 	}
11018cc36fbSJordan K. Hubbard #endif
111fa92e883SRuslan Ermilov 	if (dialtimeout)
11218cc36fbSJordan K. Hubbard 		t3000_disconnect();
11318cc36fbSJordan K. Hubbard 	return (connected);
11418cc36fbSJordan K. Hubbard }
11518cc36fbSJordan K. Hubbard 
1160f3bdf5dSMark Murray void
t3000_disconnect(void)117fa92e883SRuslan Ermilov t3000_disconnect(void)
11818cc36fbSJordan K. Hubbard {
11918cc36fbSJordan K. Hubbard 	 /* first hang up the modem*/
12018cc36fbSJordan K. Hubbard 	ioctl(FD, TIOCCDTR, 0);
12118cc36fbSJordan K. Hubbard 	sleep(1);
12218cc36fbSJordan K. Hubbard 	ioctl(FD, TIOCSDTR, 0);
12318cc36fbSJordan K. Hubbard 	t3000_sync();				/* reset */
12418cc36fbSJordan K. Hubbard 	close(FD);
12518cc36fbSJordan K. Hubbard }
12618cc36fbSJordan K. Hubbard 
1270f3bdf5dSMark Murray void
t3000_abort(void)128fa92e883SRuslan Ermilov t3000_abort(void)
12918cc36fbSJordan K. Hubbard {
13018cc36fbSJordan K. Hubbard 	t3000_write(FD, "\r", 1);	/* send anything to abort the call */
13118cc36fbSJordan K. Hubbard 	t3000_disconnect();
13218cc36fbSJordan K. Hubbard }
13318cc36fbSJordan K. Hubbard 
134fa92e883SRuslan Ermilov /*ARGSUSED*/
13518cc36fbSJordan K. Hubbard static void
sigALRM(int signo)136fa92e883SRuslan Ermilov sigALRM(int signo)
13718cc36fbSJordan K. Hubbard {
13818cc36fbSJordan K. Hubbard 	printf("\07timeout waiting for reply\n");
139fa92e883SRuslan Ermilov 	dialtimeout = 1;
14018cc36fbSJordan K. Hubbard 	longjmp(timeoutbuf, 1);
14118cc36fbSJordan K. Hubbard }
14218cc36fbSJordan K. Hubbard 
14318cc36fbSJordan K. Hubbard static int
t3000_swallow(char * match)144fa92e883SRuslan Ermilov t3000_swallow(char *match)
14518cc36fbSJordan K. Hubbard {
14618cc36fbSJordan K. Hubbard 	sig_t f;
14718cc36fbSJordan K. Hubbard 	char c;
14818cc36fbSJordan K. Hubbard 
14918cc36fbSJordan K. Hubbard 	f = signal(SIGALRM, sigALRM);
150fa92e883SRuslan Ermilov 	dialtimeout = 0;
15118cc36fbSJordan K. Hubbard 	do {
15218cc36fbSJordan K. Hubbard 		if (*match =='\0') {
15318cc36fbSJordan K. Hubbard 			signal(SIGALRM, f);
15418cc36fbSJordan K. Hubbard 			return (1);
15518cc36fbSJordan K. Hubbard 		}
15618cc36fbSJordan K. Hubbard 		if (setjmp(timeoutbuf)) {
15718cc36fbSJordan K. Hubbard 			signal(SIGALRM, f);
15818cc36fbSJordan K. Hubbard 			return (0);
15918cc36fbSJordan K. Hubbard 		}
16018cc36fbSJordan K. Hubbard 		alarm(number(value(DIALTIMEOUT)));
16118cc36fbSJordan K. Hubbard 		read(FD, &c, 1);
16218cc36fbSJordan K. Hubbard 		alarm(0);
16318cc36fbSJordan K. Hubbard 		c &= 0177;
16418cc36fbSJordan K. Hubbard #ifdef DEBUG
16518cc36fbSJordan K. Hubbard 		if (boolean(value(VERBOSE)))
16618cc36fbSJordan K. Hubbard 			putchar(c);
16718cc36fbSJordan K. Hubbard #endif
16818cc36fbSJordan K. Hubbard 	} while (c == *match++);
16918cc36fbSJordan K. Hubbard #ifdef DEBUG
17018cc36fbSJordan K. Hubbard 	if (boolean(value(VERBOSE)))
17118cc36fbSJordan K. Hubbard 		fflush(stdout);
17218cc36fbSJordan K. Hubbard #endif
17318cc36fbSJordan K. Hubbard 	signal(SIGALRM, SIG_DFL);
17418cc36fbSJordan K. Hubbard 	return (0);
17518cc36fbSJordan K. Hubbard }
17618cc36fbSJordan K. Hubbard 
17718cc36fbSJordan K. Hubbard #ifndef B19200		/* XXX */
17818cc36fbSJordan K. Hubbard #define	B19200	EXTA
17918cc36fbSJordan K. Hubbard #define	B38400	EXTB
18018cc36fbSJordan K. Hubbard #endif
18118cc36fbSJordan K. Hubbard 
18218cc36fbSJordan K. Hubbard struct tbaud_msg {
18318cc36fbSJordan K. Hubbard 	char *msg;
18418cc36fbSJordan K. Hubbard 	int baud;
18518cc36fbSJordan K. Hubbard 	int baud2;
18618cc36fbSJordan K. Hubbard } tbaud_msg[] = {
187fa92e883SRuslan Ermilov 	{ "",		B300,	0 },
188fa92e883SRuslan Ermilov 	{ " 1200",	B1200,	0 },
189fa92e883SRuslan Ermilov 	{ " 2400",	B2400,	0 },
190fa92e883SRuslan Ermilov 	{ " 4800",	B4800,	0 },
191fa92e883SRuslan Ermilov 	{ " 9600",	B9600,	0 },
192fa92e883SRuslan Ermilov 	{ " 14400",	B19200,	B9600 },
193fa92e883SRuslan Ermilov 	{ " 19200",	B19200,	B9600 },
194fa92e883SRuslan Ermilov 	{ " 38400",	B38400,	B9600 },
195fa92e883SRuslan Ermilov 	{ " 57600",	B38400,	B9600 },
196fa92e883SRuslan Ermilov 	{ " 7512",	B9600,	0 },
197fa92e883SRuslan Ermilov 	{ " 1275",	B2400,	0 },
198fa92e883SRuslan Ermilov 	{ " 7200",	B9600,	0 },
199fa92e883SRuslan Ermilov 	{ " 12000",	B19200,	B9600 },
200fa92e883SRuslan Ermilov 	{ 0,		0,	0 },
20118cc36fbSJordan K. Hubbard };
20218cc36fbSJordan K. Hubbard 
20318cc36fbSJordan K. Hubbard static int
t3000_connect(void)204fa92e883SRuslan Ermilov t3000_connect(void)
20518cc36fbSJordan K. Hubbard {
20618cc36fbSJordan K. Hubbard 	char c;
20718cc36fbSJordan K. Hubbard 	int nc, nl, n;
20818cc36fbSJordan K. Hubbard 	char dialer_buf[64];
20918cc36fbSJordan K. Hubbard 	struct tbaud_msg *bm;
21018cc36fbSJordan K. Hubbard 	sig_t f;
21118cc36fbSJordan K. Hubbard 
21218cc36fbSJordan K. Hubbard 	if (t3000_swallow("\r\n") == 0)
21318cc36fbSJordan K. Hubbard 		return (0);
21418cc36fbSJordan K. Hubbard 	f = signal(SIGALRM, sigALRM);
21518cc36fbSJordan K. Hubbard again:
21618cc36fbSJordan K. Hubbard 	nc = 0; nl = sizeof(dialer_buf)-1;
21718cc36fbSJordan K. Hubbard 	bzero(dialer_buf, sizeof(dialer_buf));
218fa92e883SRuslan Ermilov 	dialtimeout = 0;
21918cc36fbSJordan K. Hubbard 	for (nc = 0, nl = sizeof(dialer_buf)-1 ; nl > 0 ; nc++, nl--) {
22018cc36fbSJordan K. Hubbard 		if (setjmp(timeoutbuf))
22118cc36fbSJordan K. Hubbard 			break;
22218cc36fbSJordan K. Hubbard 		alarm(number(value(DIALTIMEOUT)));
22318cc36fbSJordan K. Hubbard 		n = read(FD, &c, 1);
22418cc36fbSJordan K. Hubbard 		alarm(0);
22518cc36fbSJordan K. Hubbard 		if (n <= 0)
22618cc36fbSJordan K. Hubbard 			break;
22718cc36fbSJordan K. Hubbard 		c &= 0x7f;
22818cc36fbSJordan K. Hubbard 		if (c == '\r') {
22918cc36fbSJordan K. Hubbard 			if (t3000_swallow("\n") == 0)
23018cc36fbSJordan K. Hubbard 				break;
23118cc36fbSJordan K. Hubbard 			if (!dialer_buf[0])
23218cc36fbSJordan K. Hubbard 				goto again;
23318cc36fbSJordan K. Hubbard 			if (strcmp(dialer_buf, "RINGING") == 0 &&
23418cc36fbSJordan K. Hubbard 			    boolean(value(VERBOSE))) {
23518cc36fbSJordan K. Hubbard #ifdef DEBUG
23618cc36fbSJordan K. Hubbard 				printf("%s\r\n", dialer_buf);
23718cc36fbSJordan K. Hubbard #endif
23818cc36fbSJordan K. Hubbard 				goto again;
23918cc36fbSJordan K. Hubbard 			}
24018cc36fbSJordan K. Hubbard 			if (strncmp(dialer_buf, "CONNECT",
24118cc36fbSJordan K. Hubbard 				    sizeof("CONNECT")-1) != 0)
24218cc36fbSJordan K. Hubbard 				break;
24318cc36fbSJordan K. Hubbard 			for (bm = tbaud_msg ; bm->msg ; bm++)
24418cc36fbSJordan K. Hubbard 				if (strcmp(bm->msg,
24518cc36fbSJordan K. Hubbard 				    dialer_buf+sizeof("CONNECT")-1) == 0) {
2460f3bdf5dSMark Murray 					struct termios	cntrl;
2470f3bdf5dSMark Murray 
2480f3bdf5dSMark Murray 					tcgetattr(FD, &cntrl);
2490f3bdf5dSMark Murray 					cfsetospeed(&cntrl, bm->baud);
2500f3bdf5dSMark Murray 					cfsetispeed(&cntrl, bm->baud);
2510f3bdf5dSMark Murray 					tcsetattr(FD, TCSAFLUSH, &cntrl);
25218cc36fbSJordan K. Hubbard 					signal(SIGALRM, f);
25318cc36fbSJordan K. Hubbard #ifdef DEBUG
25418cc36fbSJordan K. Hubbard 					if (boolean(value(VERBOSE)))
25518cc36fbSJordan K. Hubbard 						printf("%s\r\n", dialer_buf);
25618cc36fbSJordan K. Hubbard #endif
25718cc36fbSJordan K. Hubbard 					return (1);
25818cc36fbSJordan K. Hubbard 				}
25918cc36fbSJordan K. Hubbard 			break;
26018cc36fbSJordan K. Hubbard 		}
26118cc36fbSJordan K. Hubbard 		dialer_buf[nc] = c;
26218cc36fbSJordan K. Hubbard #ifdef notdef
26318cc36fbSJordan K. Hubbard 		if (boolean(value(VERBOSE)))
26418cc36fbSJordan K. Hubbard 			putchar(c);
26518cc36fbSJordan K. Hubbard #endif
26618cc36fbSJordan K. Hubbard 	}
26718cc36fbSJordan K. Hubbard 	printf("%s\r\n", dialer_buf);
26818cc36fbSJordan K. Hubbard 	signal(SIGALRM, f);
26918cc36fbSJordan K. Hubbard 	return (0);
27018cc36fbSJordan K. Hubbard }
27118cc36fbSJordan K. Hubbard 
27218cc36fbSJordan K. Hubbard /*
27318cc36fbSJordan K. Hubbard  * This convoluted piece of code attempts to get
27418cc36fbSJordan K. Hubbard  * the t3000 in sync.
27518cc36fbSJordan K. Hubbard  */
27618cc36fbSJordan K. Hubbard static int
t3000_sync(void)277fa92e883SRuslan Ermilov t3000_sync(void)
27818cc36fbSJordan K. Hubbard {
27918cc36fbSJordan K. Hubbard 	int already = 0;
28018cc36fbSJordan K. Hubbard 	int len;
28118cc36fbSJordan K. Hubbard 	char buf[40];
28218cc36fbSJordan K. Hubbard 
28318cc36fbSJordan K. Hubbard 	while (already++ < MAXRETRY) {
2840f3bdf5dSMark Murray 		tcflush(FD, TCIOFLUSH);
28518cc36fbSJordan K. Hubbard 		t3000_write(FD, "\rAT Z\r", 6);	/* reset modem */
28618cc36fbSJordan K. Hubbard 		bzero(buf, sizeof(buf));
28718cc36fbSJordan K. Hubbard 		sleep(2);
28818cc36fbSJordan K. Hubbard 		ioctl(FD, FIONREAD, &len);
28918cc36fbSJordan K. Hubbard #if 1
29018cc36fbSJordan K. Hubbard if (len == 0) len = 1;
29118cc36fbSJordan K. Hubbard #endif
29218cc36fbSJordan K. Hubbard 		if (len) {
29318cc36fbSJordan K. Hubbard 			len = read(FD, buf, sizeof(buf));
29418cc36fbSJordan K. Hubbard #ifdef DEBUG
29518cc36fbSJordan K. Hubbard 			buf[len] = '\0';
29618cc36fbSJordan K. Hubbard 			printf("t3000_sync: (\"%s\")\n\r", buf);
29718cc36fbSJordan K. Hubbard #endif
2980f3bdf5dSMark Murray 			if (strchr(buf, '0') ||
2990f3bdf5dSMark Murray 		   	   (strchr(buf, 'O') && strchr(buf, 'K')))
30018cc36fbSJordan K. Hubbard 				return(1);
30118cc36fbSJordan K. Hubbard 		}
30218cc36fbSJordan K. Hubbard 		/*
30318cc36fbSJordan K. Hubbard 		 * If not strapped for DTR control,
30418cc36fbSJordan K. Hubbard 		 * try to get command mode.
30518cc36fbSJordan K. Hubbard 		 */
30618cc36fbSJordan K. Hubbard 		sleep(1);
30718cc36fbSJordan K. Hubbard 		t3000_write(FD, "+++", 3);
30818cc36fbSJordan K. Hubbard 		sleep(1);
30918cc36fbSJordan K. Hubbard 		/*
31018cc36fbSJordan K. Hubbard 		 * Toggle DTR to force anyone off that might have left
31118cc36fbSJordan K. Hubbard 		 * the modem connected.
31218cc36fbSJordan K. Hubbard 		 */
31318cc36fbSJordan K. Hubbard 		ioctl(FD, TIOCCDTR, 0);
31418cc36fbSJordan K. Hubbard 		sleep(1);
31518cc36fbSJordan K. Hubbard 		ioctl(FD, TIOCSDTR, 0);
31618cc36fbSJordan K. Hubbard 	}
31718cc36fbSJordan K. Hubbard 	t3000_write(FD, "\rAT Z\r", 6);
31818cc36fbSJordan K. Hubbard 	return (0);
31918cc36fbSJordan K. Hubbard }
32018cc36fbSJordan K. Hubbard 
321fa92e883SRuslan Ermilov static void
t3000_write(int fd,char * cp,int n)322fa92e883SRuslan Ermilov t3000_write(int fd, char *cp, int n)
32318cc36fbSJordan K. Hubbard {
32418cc36fbSJordan K. Hubbard #ifdef notdef
32518cc36fbSJordan K. Hubbard 	if (boolean(value(VERBOSE)))
3260f3bdf5dSMark Murray 		write(1, cp, n);
32718cc36fbSJordan K. Hubbard #endif
3280f3bdf5dSMark Murray 	tcdrain(fd);
32918cc36fbSJordan K. Hubbard 	t3000_nap();
33018cc36fbSJordan K. Hubbard 	for ( ; n-- ; cp++) {
33118cc36fbSJordan K. Hubbard 		write(fd, cp, 1);
3320f3bdf5dSMark Murray 		tcdrain(fd);
33318cc36fbSJordan K. Hubbard 		t3000_nap();
33418cc36fbSJordan K. Hubbard 	}
33518cc36fbSJordan K. Hubbard }
33618cc36fbSJordan K. Hubbard 
33718cc36fbSJordan K. Hubbard #ifdef DEBUG
338fa92e883SRuslan Ermilov static void
t3000_verbose_read(void)339fa92e883SRuslan Ermilov t3000_verbose_read(void)
34018cc36fbSJordan K. Hubbard {
34118cc36fbSJordan K. Hubbard 	int n = 0;
34218cc36fbSJordan K. Hubbard 	char buf[BUFSIZ];
34318cc36fbSJordan K. Hubbard 
34418cc36fbSJordan K. Hubbard 	if (ioctl(FD, FIONREAD, &n) < 0)
34518cc36fbSJordan K. Hubbard 		return;
34618cc36fbSJordan K. Hubbard 	if (n <= 0)
34718cc36fbSJordan K. Hubbard 		return;
34818cc36fbSJordan K. Hubbard 	if (read(FD, buf, n) != n)
34918cc36fbSJordan K. Hubbard 		return;
3500f3bdf5dSMark Murray 	write(1, buf, n);
35118cc36fbSJordan K. Hubbard }
35218cc36fbSJordan K. Hubbard #endif
35318cc36fbSJordan K. Hubbard 
3540f3bdf5dSMark Murray /* Give the t3000 50 milliseconds between characters */
355fa92e883SRuslan Ermilov static void
t3000_nap(void)356fa92e883SRuslan Ermilov t3000_nap(void)
35718cc36fbSJordan K. Hubbard {
3580f3bdf5dSMark Murray 	struct timespec ts;
35918cc36fbSJordan K. Hubbard 
3600f3bdf5dSMark Murray 	ts.tv_sec = 0;
3610f3bdf5dSMark Murray 	ts.tv_nsec = 50 * 1000000;
3620f3bdf5dSMark Murray 
3630f3bdf5dSMark Murray 	nanosleep(&ts, NULL);
3640f3bdf5dSMark Murray }
365