This is hayes.c in view mode; [Download] [Up]
/*
* Copyright (c) 1983 The Regents of the University of California.
* All rights reserved.
*
* Redistribution and use in source and binary forms are permitted
* provided that: (1) source distributions retain this entire copyright
* notice and comment, and (2) distributions including binaries display
* the following acknowledgement: ``This product includes software
* developed by the University of California, Berkeley and its contributors''
* in the documentation or other materials provided with the distribution
* and in all advertising materials mentioning features or use of this
* software. Neither the name of the University nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*/
#ifndef lint
static char sccsid[] = "@(#)hayes.c 5.3 (Berkeley) 6/1/90";
#endif /* not lint */
/*
* Routines for calling up on a Hayes Modem
* (based on the old VenTel driver).
* The modem is expected to be strapped for "echo".
* Also, the switches enabling the DTR and CD lines
* must be set correctly.
* NOTICE:
* The easy way to hang up a modem is always simply to
* clear the DTR signal. However, if the +++ sequence
* (which switches the modem back to local mode) is sent
* before modem is hung up, removal of the DTR signal
* has no effect (except that it prevents the modem from
* recognizing commands).
* (by Helge Skrivervik, Calma Company, Sunnyvale, CA. 1984)
*/
/*
* TODO:
* It is probably not a good idea to switch the modem
* state between 'verbose' and terse (status messages).
* This should be kicked out and we should use verbose
* mode only. This would make it consistent with normal
* interactive use thru the command 'tip dialer'.
*/
/*
* Added support for more result codes - we need 2400.
* Made sure that it works with Hayes compatible Supra 2400.
* (Michal Jaegermann)
*/
/*
* Rehack to make it work with my ZyXEL which communicates with
* my computer at a fixed speed of 38400. It is using verbose
* modem messages to recognize speed of a telephone connection
* to get reasonable estimates for transfer times. It may or may
* not work with some other modem. You may need to modify
* code somewhere in vicinity of line 155. (Michal J.)
*/
#include "tip.h"
#include <string.h>
#define min(a,b) ((a < b) ? a : b)
static int sigALRM();
static int timeout = 0;
static jmp_buf timeoutbuf;
static int gobble();
#define DUMBUFLEN 80
static char dumbuf[DUMBUFLEN];
static char *dpos = dumbuf;
#define DIALING 1
#define IDLE 2
#define CONNECTED 3
#define FAILED 4
static int state = IDLE;
int Cbaudrate; /* baud rate of connection we got - it does not
have to be the same as a speed of DCE-DTE link */
hay_dialer(num, acu)
register char *num;
char *acu;
{
register char *cp;
register int connected = 0;
char dummy;
/* void error_rep(); */
int len;
char *strp;
#ifdef ACULOG
char line[80];
#endif
if (hay_sync() == 0) /* make sure we can talk to the modem */
return(0);
if (boolean(value(VERBOSE)))
printf("\ndialing... %s ", num);
fflush(stdout);
ioctl(FD, TIOCHPCL, 0);
ioctl(FD, TIOCFLUSH, 0); /* get rid of garbage */
/* write(FD, "ATV0\r", 5); *//* tell modem to use short status codes */
write(FD, "ATV1\r", 5); /* tell modem to use long status codes */
(void) gobble("\r");
(void) gobble("\r");
write(FD, "ATDT", 4); /* send dial command */
write(FD, num, strlen(num));
state = DIALING;
write(FD, "\r", 1);
connected = 0;
sleep(2);
gobble("\n");
ioctl(FD, FIONREAD, &len);
len = read(FD, dumbuf, min(len, DUMBUFLEN));
#ifdef DEBUG
dumbuf[len] = '\0';
printf("\n****%d %s\r\n*****", len, dumbuf);
if (boolean(value(VERBOSE)))
printf(" %s ", num);
#endif
ioctl(FD, TIOCFLUSH, 0);
dumbuf[0] = '\0';
if (0 != gobble("\r")) {
while(1) {
#if 0
ioctl(FD, FIONREAD, &len);
len = read(FD, dumbuf, min(len, DUMBUFLEN));
ioctl(FD, TIOCFLUSH, 0);
dumbuf[len] = '\0';
#endif
dpos = dumbuf;
gobble("\r");
strp = dumbuf;
while (' ' > *strp && *strp > '\0')
strp++;
if ('A' == *strp || /* "AT" */
'O' == *strp || /* "OK" */
'R' == *strp || /* "RINGING" */
'\0' == *strp)
continue;
if (boolean(value(VERBOSE)))
printf("%s\n", strp);
if ('R' != *strp)
break;
}
connected = ( 'C' == *strp );
/* error_rep(dummy); */
/*
if (1 != dummy && dummy < 10)
error_rep(dummy);
else
connected = 1;
*/
}
if (connected) {
state = CONNECTED;
strp += sizeof("CONNECT 38400/V.32");
if (sscanf((const char *)strp, "%d", &Cbaudrate) <= 0)
Cbaudrate = 300;
}
else {
state = FAILED;
return (connected); /* lets get out of here.. */
}
ioctl(FD, TIOCFLUSH, 0);
#ifdef ACULOG
if (timeout) {
sprintf(line, "%d second dial timeout",
number(value(DIALTIMEOUT)));
logent(value(HOST), num, "hayes", line);
}
#endif
if (timeout)
hay_disconnect(); /* insurance */
return (connected);
}
hay_disconnect()
{
char c;
int len, rlen;
/* first hang up the modem*/
#ifdef DEBUG
printf("\rdisconnecting modem....\n\r");
#endif
ioctl(FD, TIOCCDTR, 0);
sleep(1);
ioctl(FD, TIOCSDTR, 0);
goodbye();
}
hay_abort()
{
char c;
write(FD, "\r", 1); /* send anything to abort the call */
hay_disconnect();
}
static int
sigALRM()
{
printf("\07timeout waiting for reply\n\r");
timeout = 1;
longjmp(timeoutbuf, 1);
}
static int
gobble(match)
register char *match;
{
char c;
int (*f)();
int i, status = 0;
signal(SIGALRM, sigALRM);
timeout = 0;
#ifdef DEBUG
printf("\ngobble: waiting for (0x%x)\n%s **\n", *match, match);
#endif
for(;;) {
if (setjmp(timeoutbuf)) {
signal(SIGALRM, f);
return (-1);
}
alarm(number(value(DIALTIMEOUT)));
read(FD, &c, 1);
alarm(0);
c &= 0177;
#ifdef DEBUG
printf("%c 0x%x ", (c >= ' ' ? c : '_'), c);
#endif
*dpos++ = c;
if (NULL != index(match, c)) {
*dpos = '\0';
dpos = dumbuf;
status = 1;
break;
}
#if 0
if ('\r' == c || '\n' == c) {
if (c == *match)
status = 1;
break;
}
for (i = 0; i < strlen(match); i++)
if (c == match[i]) {
status *= 10;
status += i;
}
#endif
}
signal(SIGALRM, SIG_DFL);
#ifdef DEBUG
printf("\n");
printf("status = %d\n", status);
#endif
return (status);
}
#if 0
static char *ret_message[] = {
"OK", /* 0 */
"CONNECT", /* 1 */
"RING", /* 2 */
"NO CARRIER", /* 3 */
"ERROR in input", /* 4 */
"CONNECT 1200", /* 5 */
"NO DIALTONE", /* 6 */
"BUSY", /* 7 */
"NO ANSWER", /* 8 */
"RINGING", /* 9 */
"CONNECT 2400", /* 10 */
"CONNECT 4800", /* 11 */
"CONNECT 9600", /* 12 */
"", /* 13 */
"CONNECT 19200", /* 14 */
"CONNECT 7200", /* 15 */
"CONNECT 12000", /* 16 */
"CONNECT 14400", /* 17 */
"CONNECT 16800", /* 18 */
"CONNECT 38400", /* 19 */
"CONNECT 57600", /* 20 */
"CONNECT 76800" /* 21 */
};
void
error_rep(c)
register int c;
{
printf("\n\r");
if (c < sizeof(ret_message)/sizeof(char *)) {
printf("%s", ret_message[c]);
}
else {
printf("Unknown Modem error: %c (0x%x)", c, c);
}
printf("\n\r");
return;
}
#endif
/*
* set modem back to normal verbose status codes.
*/
goodbye()
{
int len, rlen;
int c;
ioctl(FD, TIOCFLUSH, &len); /* get rid of trash */
if (hay_sync()) {
sleep(1);
#ifndef DEBUG
ioctl(FD, TIOCFLUSH, 0);
#endif
write(FD, "ATH0\r", 5); /* insurance */
#ifndef DEBUG
write(FD, "ATV0\r", 5);
sleep(2);
c = gobble("03");
if (c != 0 && c != 1) {
printf("cannot hang up modem\n\r");
printf("please use 'tip dialer' to make sure the line is hung up\n\r");
}
#endif
sleep(1);
ioctl(FD, FIONREAD, &len);
#ifdef DEBUG
printf("\ngoodbye1: len=%d -- ", len);
rlen = read(FD, dumbuf, min(len, DUMBUFLEN));
dumbuf[rlen] = '\0';
printf("read (%d): %s\r\n", rlen, dumbuf);
{
int ii;
for (ii = 0; ii < rlen; ii++)
printf("0x%x ", dumbuf[ii]);
printf("\r\n\n");
}
#endif
write(FD, "ATV1\r", 5);
sleep(1);
#ifdef DEBUG
ioctl(FD, FIONREAD, &len);
printf("goodbye2: len=%d -- ", len);
rlen = read(FD, dumbuf, min(len, DUMBUFLEN));
dumbuf[rlen] = '\0';
printf("read (%d): %s\r\n", rlen, dumbuf);
{
int ii;
for (ii = 0; ii < rlen; ii++)
printf("0x%x ", dumbuf[ii]);
printf("\r\n\n");
}
#endif
}
ioctl(FD, TIOCFLUSH, 0); /* clear the input buffer */
ioctl(FD, TIOCCDTR, 0); /* clear DTR (insurance) */
close(FD);
}
#define MAXRETRY 5
hay_sync()
{
int len, retry = 0;
while (retry++ <= MAXRETRY) {
write(FD, "AT\r", 3);
sleep(1);
ioctl(FD, FIONREAD, &len);
if (len) {
len = read(FD, dumbuf, min(len, DUMBUFLEN));
if (index(dumbuf, '0') ||
(index(dumbuf, 'O') && index(dumbuf, 'K')))
return(1);
#ifdef DEBUG
dumbuf[len] = '\0';
printf("hay_sync: (\"%s\") %d\n\r", dumbuf, retry);
#endif
}
ioctl(FD, TIOCCDTR, 0);
ioctl(FD, TIOCSDTR, 0);
}
printf("Cannot synchronize with hayes...\n\r");
return(0);
}
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.