#include <u.h>
#include <libc.h>
void setspeed(int, int);
int getspeed(char*, int);
void godial(int, int, char*);
int readmsg(int, int);
void punt(char*, ...);
int pulsed;
int verbose;
char msgbuf[128]; /* last message read */
enum
{
Ok,
Success,
Failure,
Noise,
};
typedef struct Msg Msg;
struct Msg
{
char *text;
int type;
};
Msg msgs[] =
{
{ "OK", Ok, },
{ "NO CARRIER", Failure, },
{ "ERROR", Failure, },
{ "NO DIALTONE", Failure, },
{ "BUSY", Failure, },
{ "NO ANSWER", Failure, },
{ "CONNECT", Success, },
{ 0, 0 },
};
void
usage(void)
{
punt("usage: hayes [-p] telno [device]");
}
void
main(int argc, char **argv)
{
int data = -1;
int ctl = -1;
char *cname;
ARGBEGIN{
case 'p':
pulsed = 1;
break;
case 'v':
verbose = 1;
break;
default:
usage();
}ARGEND
switch(argc){
case 1:
data = 1;
break;
case 2:
data = open(argv[1], ORDWR);
if(data < 0){
fprint(2, "hayes: %r opening %s\n", argv[1]);
exits("hayes");
}
cname = malloc(strlen(argv[1])+4);
sprint(cname, "%sctl", argv[1]);
ctl = open(cname, ORDWR);
free(cname);
break;
default:
usage();
}
godial(data, ctl, argv[0]);
exits(0);
}
int
send(int fd, char *x)
{
return write(fd, x, strlen(x));
}
void
godial(int data, int ctl, char *number)
{
char *dialstr;
int m;
int baud;
/* get the modem's attention */
if(send(data, "\r+++\r") < 0)
punt("failed write");
readmsg(data, 2);
sleep(1000);
/* initialize */
if(send(data, "ATZ\r") < 0)
punt("failed write");
m = readmsg(data, 2);
if(m < 0)
punt("can't get modem's attention");
/*
* Q0 = report result codes
* V1 = full word result codes
* W1 = negotiation progress codes enabled
* E1 = echo commands
* M1 = speaker on until on-line
*/
if(send(data, "ATQ0V1E1M1\r") < 0)
punt("failed write");
m = readmsg(data, 2);
if(m != Ok)
punt("can't get modem's attention");
if(send(data, "ATW1\r") < 0)
punt("failed write");
readmsg(data, 2);
sleep(1000);
/* godial */
dialstr = malloc(6+strlen(number));
sprint(dialstr, "ATD%c%s\r", pulsed ? 'P' : 'T', number);
if(send(data, dialstr) < 0) {
free(dialstr);
punt("failed write");
}
free(dialstr);
m = readmsg(data, 60);
if(m != Success)
punt("dial failed: %s", msgbuf);
baud = getspeed(msgbuf, 9600);
setspeed(ctl, baud);
fprint(2, "hayes: connected at %d baud\n", baud);
}
/*
* read until we see a message or we time out
*/
int
readmsg(int f, int secs)
{
ulong start;
char *p;
int len;
Dir *d;
Msg *pp;
p = msgbuf;
len = sizeof(msgbuf) - 1;
for(start = time(0); time(0) <= start+secs;){
if((d = dirfstat(f)) == nil)
punt("failed read");
if(d->length == 0){
free(d);
sleep(100);
continue;
}
free(d);
if(read(f, p, 1) <= 0)
punt("failed read");
if(*p == '\n' || *p == '\r' || len == 0){
*p = 0;
if(verbose && p != msgbuf)
fprint(2, "%s\n", msgbuf);
for(pp = msgs; pp->text; pp++)
if(strncmp(pp->text, msgbuf, strlen(pp->text))==0)
return pp->type;
start = time(0);
p = msgbuf;
len = sizeof(msgbuf) - 1;
continue;
}
len--;
p++;
}
strcpy(msgbuf, "No response from modem");
return Noise;
}
/*
* get baud rate from a connect message
*/
int
getspeed(char *msg, int speed)
{
char *p;
int s;
p = msg + sizeof("CONNECT") - 1;
while(*p == ' ' || *p == '\t')
p++;
s = atoi(p);
if(s <= 0)
return speed;
else
return s;
}
/*
* set speed and RTS/CTS modem flow control
*/
void
setspeed(int ctl, int baud)
{
char buf[32];
if(ctl < 0)
return;
sprint(buf, "b%d", baud);
write(ctl, buf, strlen(buf));
write(ctl, "m1", 2);
}
void
punt(char *fmt, ...)
{
char buf[256];
va_list arg;
int n;
strcpy(buf, "hayes: ");
va_start(arg, fmt);
n = vseprint(buf+strlen(buf), buf+sizeof(buf), fmt, arg) - buf;
va_end(arg);
buf[n] = '\n';
write(2, buf, n+1);
exits("hayes");
}
|