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