123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240 |
- #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");
- }
|