1/*
2 * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
3 * Use is subject to license terms.
4 */
5
6/*
7 * Copyright (c) 1983 Regents of the University of California.
8 * All rights reserved. The Berkeley software License Agreement
9 * specifies the terms and conditions for redistribution.
10 */
11
12#pragma ident	"%Z%%M%	%I%	%E% SMI"
13
14#include "tip.h"
15
16static int	hayes_sync(int);
17static void	sigALRM(void);
18static sigjmp_buf	timeoutbuf;
19
20void	hayes_disconnect(void);
21
22/*
23 * Dial up on a Hayes Smart Modem 1200 or 2400
24 */
25/* ARGSUSED */
26int
27hayes_dialer(char *num, char *acu)
28{
29	char code = 0, cr = 0;
30	sig_handler_t	f;
31	struct termios buf;
32
33	f = signal(SIGALRM, (sig_handler_t)sigALRM);
34
35	if (!hayes_sync(FD)) {
36		(void) printf("can't synchronize with hayes\n");
37#ifdef ACULOG
38		logent(value(HOST), num, "hayes", "can't synch up");
39#endif
40		(void) signal(SIGALRM, f);
41		return (0);
42	}
43	if (boolean(value(VERBOSE)))
44		(void) printf("\ndialing...");
45	(void) fflush(stdout);
46	(void) ioctl(FD, TCGETS, &buf);
47	buf.c_cflag |= HUPCL;
48	(void) ioctl(FD, TCSETS, &buf);
49	(void) ioctl(FD, TCFLSH, TCIOFLUSH);
50
51	if (sigsetjmp(timeoutbuf, 1)) {
52#ifdef ACULOG
53		char line[80];
54
55		(void) sprintf(line, "%d second dial timeout",
56		    number(value(DIALTIMEOUT)));
57		logent(value(HOST), num, "hayes", line);
58#endif
59		hayes_disconnect();
60		(void) signal(SIGALRM, f);
61		return (0);
62	}
63	(void) alarm(number(value(DIALTIMEOUT)));
64	(void) ioctl(FD, TCFLSH, TCIOFLUSH);
65	if (*num == 'S')
66		(void) write(FD, "AT", 2);
67	else
68		(void) write(FD, "ATDT", 4);	/* use tone dialing */
69	(void) write(FD, num, strlen(num));
70	(void) write(FD, "\r", 1);
71	(void) read(FD, &code, 1);
72	(void) read(FD, &cr, 1);
73	if (code == '1' && cr == '0')
74		(void) read(FD, &cr, 1);
75	(void) alarm(0);
76	(void) signal(SIGALRM, f);
77	if ((code == '1' || code == '5') && cr == '\r')
78		return (1);
79	return (0);
80}
81
82void
83hayes_disconnect(void)
84{
85	(void) close(FD);
86}
87
88void
89hayes_abort(void)
90{
91	int dtr = TIOCM_DTR;
92
93	(void) alarm(0);
94	(void) ioctl(FD, TIOCMBIC, &dtr);
95	(void) sleep(2);
96	(void) ioctl(FD, TCFLSH, TCIOFLUSH);
97	(void) close(FD);
98}
99
100static void
101sigALRM(void)
102{
103	siglongjmp(timeoutbuf, 1);
104}
105
106/*
107 * This piece of code attempts to get the hayes in sync.
108 */
109static int
110hayes_sync(int fd)
111{
112	int tries;
113	char code = 0, cr = 0;
114	int dtr = TIOCM_DTR;
115
116	/*
117	 * Toggle DTR to force anyone off that might have left
118	 * the modem connected, and insure a consistent state
119	 * to start from.
120	 */
121	(void) ioctl(fd, TIOCMBIC, &dtr);
122	(void) sleep(1);
123	(void) ioctl(fd, TIOCMBIS, &dtr);
124	for (tries = 0; tries < 3; tries++) {
125		/*
126		 * After reseting the modem, initialize all
127		 * parameters to required vaules:
128		 *
129		 *	V0	- result codes are single digits
130		 *	Q0	- result codes ARE sent
131		 *	E0	- do not echo
132		 *	S0=1	- automatically answer phone
133		 *	S2=255	- disable escape character
134		 *	S12=255	- longest possible escape guard time
135		 */
136		(void) write(fd, "ATV0Q0E0S0=1S2=255S12=255\r", 26);
137		(void) sleep(1);
138		/* flush any echoes or return codes */
139		(void) ioctl(fd, TCFLSH, TCIOFLUSH);
140		/* now see if the modem is talking to us properly */
141		(void) write(fd, "AT\r", 3);
142		if (sigsetjmp(timeoutbuf, 1) == 0) {
143			(void) alarm(2);
144			(void) read(FD, &code, 1);
145			(void) read(FD, &cr, 1);
146			if (code == '0' && cr == '\r')
147				return (1);
148		}
149	}
150	return (0);
151}
152