]> git.lizzy.rs Git - plan9front.git/blob - sys/src/cmd/con/hayes.c
devproc: can't wait for ourselfs to stop (thanks Shamar)
[plan9front.git] / sys / src / cmd / con / hayes.c
1 #include <u.h>
2 #include <libc.h>
3
4 void setspeed(int, int);
5 int getspeed(char*, int);
6 void godial(int, int, char*);
7 int readmsg(int, int);
8 void punt(char*, ...);
9
10 int pulsed;
11 int verbose;
12 char msgbuf[128];               /* last message read */
13
14 enum
15 {
16         Ok,
17         Success,
18         Failure,
19         Noise,
20 };
21
22 typedef struct Msg      Msg;
23 struct Msg
24 {
25         char    *text;
26         int     type;
27 };
28
29
30 Msg msgs[] =
31 {
32         { "OK",                 Ok, },
33         { "NO CARRIER",         Failure, },
34         { "ERROR",              Failure, },
35         { "NO DIALTONE",        Failure, },
36         { "BUSY",               Failure, },
37         { "NO ANSWER",          Failure, },
38         { "CONNECT",            Success, },
39         { 0,                    0 },
40 };
41
42 void
43 usage(void)
44 {
45         punt("usage: hayes [-p] telno [device]");
46 }
47
48 void
49 main(int argc, char **argv)
50 {
51         int data = -1;
52         int ctl = -1;
53         char *cname;
54
55         ARGBEGIN{
56         case 'p':
57                 pulsed = 1;
58                 break;
59         case 'v':
60                 verbose = 1;
61                 break;
62         default:
63                 usage();
64         }ARGEND
65
66         switch(argc){
67         case 1:
68                 data = 1;
69                 break;
70         case 2:
71                 data = open(argv[1], ORDWR);
72                 if(data < 0){
73                         fprint(2, "hayes: %r opening %s\n", argv[1]);
74                         exits("hayes");
75                 }
76                 cname = malloc(strlen(argv[1])+4);
77                 sprint(cname, "%sctl", argv[1]);
78                 ctl = open(cname, ORDWR);
79                 free(cname);
80                 break;
81         default:
82                 usage();
83         }
84         godial(data, ctl, argv[0]);
85         exits(0);
86 }
87
88 int
89 send(int fd, char *x)
90 {
91         return write(fd, x, strlen(x));
92 }
93
94 void
95 godial(int data, int ctl, char *number)
96 {
97         char *dialstr;
98         int m;
99         int baud;
100
101         /* get the modem's attention */
102         if(send(data, "\r+++\r") < 0)
103                 punt("failed write");
104         readmsg(data, 2);
105         sleep(1000);
106
107         /* initialize */
108         if(send(data, "ATZ\r") < 0)
109                 punt("failed write");
110         m = readmsg(data, 2);
111         if(m < 0)
112                 punt("can't get modem's attention");
113
114         /*
115          *      Q0 = report result codes
116          *      V1 = full word result codes
117          *      W1 = negotiation progress codes enabled
118          *      E1 = echo commands
119          *      M1 = speaker on until on-line
120          */
121         if(send(data, "ATQ0V1E1M1\r") < 0)
122                 punt("failed write");
123         m = readmsg(data, 2);
124         if(m != Ok)
125                 punt("can't get modem's attention");
126         if(send(data, "ATW1\r") < 0)
127                 punt("failed write");
128         readmsg(data, 2);
129         sleep(1000);
130
131         /* godial */
132         dialstr = malloc(6+strlen(number));
133         sprint(dialstr, "ATD%c%s\r", pulsed ? 'P' : 'T', number);
134         if(send(data, dialstr) < 0) {
135                 free(dialstr);
136                 punt("failed write");
137         }
138         free(dialstr);
139         m = readmsg(data, 60);
140         if(m != Success)
141                 punt("dial failed: %s", msgbuf);
142         baud = getspeed(msgbuf, 9600);
143         setspeed(ctl, baud);
144         fprint(2, "hayes: connected at %d baud\n", baud);
145 }
146
147 /*
148  *  read until we see a message or we time out
149  */
150 int
151 readmsg(int f, int secs)
152 {
153         ulong start;
154         char *p;
155         int len;
156         Dir *d;
157         Msg *pp;
158
159         p = msgbuf;
160         len = sizeof(msgbuf) - 1;
161         for(start = time(0); time(0) <= start+secs;){
162                 if((d = dirfstat(f)) == nil)
163                         punt("failed read");
164                 if(d->length == 0){
165                         free(d);
166                         sleep(100);
167                         continue;
168                 }
169                 free(d);
170                 if(read(f, p, 1) <= 0)
171                         punt("failed read");
172                 if(*p == '\n' || *p == '\r' || len == 0){
173                         *p = 0;
174                         if(verbose && p != msgbuf)
175                                 fprint(2, "%s\n", msgbuf);
176                         for(pp = msgs; pp->text; pp++)
177                                 if(strncmp(pp->text, msgbuf, strlen(pp->text))==0)
178                                         return pp->type;
179                         start = time(0);
180                         p = msgbuf;
181                         len = sizeof(msgbuf) - 1;
182                         continue;
183                 }
184                 len--;
185                 p++;
186         }
187         strcpy(msgbuf, "No response from modem");
188         return Noise;
189 }
190
191 /*
192  *  get baud rate from a connect message
193  */
194 int
195 getspeed(char *msg, int speed)
196 {
197         char *p;
198         int s;
199
200         p = msg + sizeof("CONNECT") - 1;
201         while(*p == ' ' || *p == '\t')
202                 p++;
203         s = atoi(p);
204         if(s <= 0)
205                 return speed;
206         else
207                 return s;
208 }
209
210 /*
211  *  set speed and RTS/CTS modem flow control
212  */
213 void
214 setspeed(int ctl, int baud)
215 {
216         char buf[32];
217
218         if(ctl < 0)
219                 return;
220         sprint(buf, "b%d", baud);
221         write(ctl, buf, strlen(buf));
222         write(ctl, "m1", 2);
223 }
224
225
226 void
227 punt(char *fmt, ...)
228 {
229         char buf[256];
230         va_list arg;
231         int n;
232
233         strcpy(buf, "hayes: ");
234         va_start(arg, fmt);
235         n = vseprint(buf+strlen(buf), buf+sizeof(buf), fmt, arg) - buf;
236         va_end(arg);
237         buf[n] = '\n';
238         write(2, buf, n+1);
239         exits("hayes");
240 }