17dd7cddfSDavid du Colombier #include <u.h>
27dd7cddfSDavid du Colombier #include <libc.h>
37dd7cddfSDavid du Colombier
47dd7cddfSDavid du Colombier void setspeed(int, int);
57dd7cddfSDavid du Colombier int getspeed(char*, int);
67dd7cddfSDavid du Colombier void godial(int, int, char*);
77dd7cddfSDavid du Colombier int readmsg(int, int);
87dd7cddfSDavid du Colombier void punt(char*, ...);
97dd7cddfSDavid du Colombier
107dd7cddfSDavid du Colombier int pulsed;
117dd7cddfSDavid du Colombier int verbose;
127dd7cddfSDavid du Colombier char msgbuf[128]; /* last message read */
137dd7cddfSDavid du Colombier
147dd7cddfSDavid du Colombier enum
157dd7cddfSDavid du Colombier {
167dd7cddfSDavid du Colombier Ok,
177dd7cddfSDavid du Colombier Success,
187dd7cddfSDavid du Colombier Failure,
197dd7cddfSDavid du Colombier Noise,
207dd7cddfSDavid du Colombier };
217dd7cddfSDavid du Colombier
227dd7cddfSDavid du Colombier typedef struct Msg Msg;
237dd7cddfSDavid du Colombier struct Msg
247dd7cddfSDavid du Colombier {
257dd7cddfSDavid du Colombier char *text;
267dd7cddfSDavid du Colombier int type;
277dd7cddfSDavid du Colombier };
287dd7cddfSDavid du Colombier
297dd7cddfSDavid du Colombier
307dd7cddfSDavid du Colombier Msg msgs[] =
317dd7cddfSDavid du Colombier {
327dd7cddfSDavid du Colombier { "OK", Ok, },
337dd7cddfSDavid du Colombier { "NO CARRIER", Failure, },
347dd7cddfSDavid du Colombier { "ERROR", Failure, },
357dd7cddfSDavid du Colombier { "NO DIALTONE", Failure, },
367dd7cddfSDavid du Colombier { "BUSY", Failure, },
377dd7cddfSDavid du Colombier { "NO ANSWER", Failure, },
387dd7cddfSDavid du Colombier { "CONNECT", Success, },
397dd7cddfSDavid du Colombier { 0, 0 },
407dd7cddfSDavid du Colombier };
417dd7cddfSDavid du Colombier
427dd7cddfSDavid du Colombier void
usage(void)437dd7cddfSDavid du Colombier usage(void)
447dd7cddfSDavid du Colombier {
457dd7cddfSDavid du Colombier punt("usage: hayes [-p] telno [device]");
467dd7cddfSDavid du Colombier }
477dd7cddfSDavid du Colombier
487dd7cddfSDavid du Colombier void
main(int argc,char ** argv)497dd7cddfSDavid du Colombier main(int argc, char **argv)
507dd7cddfSDavid du Colombier {
517dd7cddfSDavid du Colombier int data = -1;
527dd7cddfSDavid du Colombier int ctl = -1;
53*9a747e4fSDavid du Colombier char *cname;
547dd7cddfSDavid du Colombier
557dd7cddfSDavid du Colombier ARGBEGIN{
567dd7cddfSDavid du Colombier case 'p':
577dd7cddfSDavid du Colombier pulsed = 1;
587dd7cddfSDavid du Colombier break;
597dd7cddfSDavid du Colombier case 'v':
607dd7cddfSDavid du Colombier verbose = 1;
617dd7cddfSDavid du Colombier break;
627dd7cddfSDavid du Colombier default:
637dd7cddfSDavid du Colombier usage();
647dd7cddfSDavid du Colombier }ARGEND
657dd7cddfSDavid du Colombier
667dd7cddfSDavid du Colombier switch(argc){
677dd7cddfSDavid du Colombier case 1:
687dd7cddfSDavid du Colombier data = 1;
697dd7cddfSDavid du Colombier break;
707dd7cddfSDavid du Colombier case 2:
717dd7cddfSDavid du Colombier data = open(argv[1], ORDWR);
727dd7cddfSDavid du Colombier if(data < 0){
737dd7cddfSDavid du Colombier fprint(2, "hayes: %r opening %s\n", argv[1]);
747dd7cddfSDavid du Colombier exits("hayes");
757dd7cddfSDavid du Colombier }
76*9a747e4fSDavid du Colombier cname = malloc(strlen(argv[1])+4);
777dd7cddfSDavid du Colombier sprint(cname, "%sctl", argv[1]);
787dd7cddfSDavid du Colombier ctl = open(cname, ORDWR);
79*9a747e4fSDavid du Colombier free(cname);
807dd7cddfSDavid du Colombier break;
817dd7cddfSDavid du Colombier default:
827dd7cddfSDavid du Colombier usage();
837dd7cddfSDavid du Colombier }
847dd7cddfSDavid du Colombier godial(data, ctl, argv[0]);
857dd7cddfSDavid du Colombier exits(0);
867dd7cddfSDavid du Colombier }
877dd7cddfSDavid du Colombier
887dd7cddfSDavid du Colombier int
send(int fd,char * x)897dd7cddfSDavid du Colombier send(int fd, char *x)
907dd7cddfSDavid du Colombier {
917dd7cddfSDavid du Colombier return write(fd, x, strlen(x));
927dd7cddfSDavid du Colombier }
937dd7cddfSDavid du Colombier
947dd7cddfSDavid du Colombier void
godial(int data,int ctl,char * number)957dd7cddfSDavid du Colombier godial(int data, int ctl, char *number)
967dd7cddfSDavid du Colombier {
97*9a747e4fSDavid du Colombier char *dialstr;
987dd7cddfSDavid du Colombier int m;
997dd7cddfSDavid du Colombier int baud;
1007dd7cddfSDavid du Colombier
1017dd7cddfSDavid du Colombier /* get the modem's attention */
1027dd7cddfSDavid du Colombier if(send(data, "\r+++\r") < 0)
1037dd7cddfSDavid du Colombier punt("failed write");
1047dd7cddfSDavid du Colombier readmsg(data, 2);
1057dd7cddfSDavid du Colombier sleep(1000);
1067dd7cddfSDavid du Colombier
1077dd7cddfSDavid du Colombier /* initialize */
1087dd7cddfSDavid du Colombier if(send(data, "ATZ\r") < 0)
1097dd7cddfSDavid du Colombier punt("failed write");
1107dd7cddfSDavid du Colombier m = readmsg(data, 2);
1117dd7cddfSDavid du Colombier if(m < 0)
1127dd7cddfSDavid du Colombier punt("can't get modem's attention");
1137dd7cddfSDavid du Colombier
1147dd7cddfSDavid du Colombier /*
1157dd7cddfSDavid du Colombier * Q0 = report result codes
1167dd7cddfSDavid du Colombier * V1 = full word result codes
1177dd7cddfSDavid du Colombier * W1 = negotiation progress codes enabled
1187dd7cddfSDavid du Colombier * E1 = echo commands
1197dd7cddfSDavid du Colombier * M1 = speaker on until on-line
1207dd7cddfSDavid du Colombier */
1217dd7cddfSDavid du Colombier if(send(data, "ATQ0V1E1M1\r") < 0)
1227dd7cddfSDavid du Colombier punt("failed write");
1237dd7cddfSDavid du Colombier m = readmsg(data, 2);
1247dd7cddfSDavid du Colombier if(m != Ok)
1257dd7cddfSDavid du Colombier punt("can't get modem's attention");
1267dd7cddfSDavid du Colombier if(send(data, "ATW1\r") < 0)
1277dd7cddfSDavid du Colombier punt("failed write");
1287dd7cddfSDavid du Colombier readmsg(data, 2);
1297dd7cddfSDavid du Colombier sleep(1000);
1307dd7cddfSDavid du Colombier
1317dd7cddfSDavid du Colombier /* godial */
132*9a747e4fSDavid du Colombier dialstr = malloc(6+strlen(number));
1337dd7cddfSDavid du Colombier sprint(dialstr, "ATD%c%s\r", pulsed ? 'P' : 'T', number);
134*9a747e4fSDavid du Colombier if(send(data, dialstr) < 0) {
135*9a747e4fSDavid du Colombier free(dialstr);
1367dd7cddfSDavid du Colombier punt("failed write");
137*9a747e4fSDavid du Colombier }
138*9a747e4fSDavid du Colombier free(dialstr);
1397dd7cddfSDavid du Colombier m = readmsg(data, 60);
1407dd7cddfSDavid du Colombier if(m != Success)
1417dd7cddfSDavid du Colombier punt("dial failed: %s", msgbuf);
1427dd7cddfSDavid du Colombier baud = getspeed(msgbuf, 9600);
1437dd7cddfSDavid du Colombier setspeed(ctl, baud);
1447dd7cddfSDavid du Colombier fprint(2, "hayes: connected at %d baud\n", baud);
1457dd7cddfSDavid du Colombier }
1467dd7cddfSDavid du Colombier
1477dd7cddfSDavid du Colombier /*
1487dd7cddfSDavid du Colombier * read until we see a message or we time out
1497dd7cddfSDavid du Colombier */
1507dd7cddfSDavid du Colombier int
readmsg(int f,int secs)1517dd7cddfSDavid du Colombier readmsg(int f, int secs)
1527dd7cddfSDavid du Colombier {
1537dd7cddfSDavid du Colombier ulong start;
1547dd7cddfSDavid du Colombier char *p;
1557dd7cddfSDavid du Colombier int len;
156*9a747e4fSDavid du Colombier Dir *d;
1577dd7cddfSDavid du Colombier Msg *pp;
1587dd7cddfSDavid du Colombier
1597dd7cddfSDavid du Colombier p = msgbuf;
1607dd7cddfSDavid du Colombier len = sizeof(msgbuf) - 1;
1617dd7cddfSDavid du Colombier for(start = time(0); time(0) <= start+secs;){
162*9a747e4fSDavid du Colombier if((d = dirfstat(f)) == nil)
1637dd7cddfSDavid du Colombier punt("failed read");
164*9a747e4fSDavid du Colombier if(d->length == 0){
165*9a747e4fSDavid du Colombier free(d);
1667dd7cddfSDavid du Colombier sleep(100);
1677dd7cddfSDavid du Colombier continue;
1687dd7cddfSDavid du Colombier }
169*9a747e4fSDavid du Colombier free(d);
1707dd7cddfSDavid du Colombier if(read(f, p, 1) <= 0)
1717dd7cddfSDavid du Colombier punt("failed read");
1727dd7cddfSDavid du Colombier if(*p == '\n' || *p == '\r' || len == 0){
1737dd7cddfSDavid du Colombier *p = 0;
1747dd7cddfSDavid du Colombier if(verbose && p != msgbuf)
1757dd7cddfSDavid du Colombier fprint(2, "%s\n", msgbuf);
1767dd7cddfSDavid du Colombier for(pp = msgs; pp->text; pp++)
1777dd7cddfSDavid du Colombier if(strncmp(pp->text, msgbuf, strlen(pp->text))==0)
1787dd7cddfSDavid du Colombier return pp->type;
1797dd7cddfSDavid du Colombier start = time(0);
1807dd7cddfSDavid du Colombier p = msgbuf;
1817dd7cddfSDavid du Colombier len = sizeof(msgbuf) - 1;
1827dd7cddfSDavid du Colombier continue;
1837dd7cddfSDavid du Colombier }
1847dd7cddfSDavid du Colombier len--;
1857dd7cddfSDavid du Colombier p++;
1867dd7cddfSDavid du Colombier }
1877dd7cddfSDavid du Colombier strcpy(msgbuf, "No response from modem");
1887dd7cddfSDavid du Colombier return Noise;
1897dd7cddfSDavid du Colombier }
1907dd7cddfSDavid du Colombier
1917dd7cddfSDavid du Colombier /*
1927dd7cddfSDavid du Colombier * get baud rate from a connect message
1937dd7cddfSDavid du Colombier */
1947dd7cddfSDavid du Colombier int
getspeed(char * msg,int speed)1957dd7cddfSDavid du Colombier getspeed(char *msg, int speed)
1967dd7cddfSDavid du Colombier {
1977dd7cddfSDavid du Colombier char *p;
1987dd7cddfSDavid du Colombier int s;
1997dd7cddfSDavid du Colombier
2007dd7cddfSDavid du Colombier p = msg + sizeof("CONNECT") - 1;
2017dd7cddfSDavid du Colombier while(*p == ' ' || *p == '\t')
2027dd7cddfSDavid du Colombier p++;
2037dd7cddfSDavid du Colombier s = atoi(p);
2047dd7cddfSDavid du Colombier if(s <= 0)
2057dd7cddfSDavid du Colombier return speed;
2067dd7cddfSDavid du Colombier else
2077dd7cddfSDavid du Colombier return s;
2087dd7cddfSDavid du Colombier }
2097dd7cddfSDavid du Colombier
2107dd7cddfSDavid du Colombier /*
2117dd7cddfSDavid du Colombier * set speed and RTS/CTS modem flow control
2127dd7cddfSDavid du Colombier */
2137dd7cddfSDavid du Colombier void
setspeed(int ctl,int baud)2147dd7cddfSDavid du Colombier setspeed(int ctl, int baud)
2157dd7cddfSDavid du Colombier {
2167dd7cddfSDavid du Colombier char buf[32];
2177dd7cddfSDavid du Colombier
2187dd7cddfSDavid du Colombier if(ctl < 0)
2197dd7cddfSDavid du Colombier return;
2207dd7cddfSDavid du Colombier sprint(buf, "b%d", baud);
2217dd7cddfSDavid du Colombier write(ctl, buf, strlen(buf));
2227dd7cddfSDavid du Colombier write(ctl, "m1", 2);
2237dd7cddfSDavid du Colombier }
2247dd7cddfSDavid du Colombier
2257dd7cddfSDavid du Colombier
2267dd7cddfSDavid du Colombier void
punt(char * fmt,...)2277dd7cddfSDavid du Colombier punt(char *fmt, ...)
2287dd7cddfSDavid du Colombier {
2297dd7cddfSDavid du Colombier char buf[256];
2307dd7cddfSDavid du Colombier va_list arg;
2317dd7cddfSDavid du Colombier int n;
2327dd7cddfSDavid du Colombier
2337dd7cddfSDavid du Colombier strcpy(buf, "hayes: ");
2347dd7cddfSDavid du Colombier va_start(arg, fmt);
235*9a747e4fSDavid du Colombier n = vseprint(buf+strlen(buf), buf+sizeof(buf), fmt, arg) - buf;
2367dd7cddfSDavid du Colombier va_end(arg);
2377dd7cddfSDavid du Colombier buf[n] = '\n';
2387dd7cddfSDavid du Colombier write(2, buf, n+1);
2397dd7cddfSDavid du Colombier exits("hayes");
2407dd7cddfSDavid du Colombier }
241