]> git.lizzy.rs Git - plan9front.git/blob - sys/src/cmd/fax/modem.c
ip/ipconfig: format ipmask with %M instead of %I
[plan9front.git] / sys / src / cmd / fax / modem.c
1 #include <u.h>
2 #include <libc.h>
3 #include <bio.h>
4
5 #include "modem.h"
6
7 typedef struct {
8         char    *terse;
9         char    *verbose;
10         int     result;
11         int     (*f)(Modem*);
12 } ResultCode;
13
14 static ResultCode results[] = {
15         { "0",  "OK",           Rok,            0, },
16         { "1",  "CONNECT",      Rconnect,       0, },
17         { "2",  "RING",         Rring,          0, },
18         { "3",  "NO CARRIER",   Rfailure,       0, },
19         { "4",  "ERROR",        Rrerror,        0, },
20         { "5",  "CONNECT 1200", Rconnect,       0, },
21         { "6",  "NO DIALTONE",  Rfailure,       0, },
22         { "7",  "BUSY",         Rfailure,       0, },
23         { "8",  "NO ANSWER",    Rfailure,       0, },
24         { "9",  "CONNECT 2400", Rconnect,       0, },           /* MT1432BA */
25         { "10", "CONNECT 2400", Rconnect,       0, },           /* Hayes */
26         { "11", "CONNECT 4800", Rconnect,       0, },
27         { "12", "CONNECT 9600", Rconnect,       0, },
28         { "13", "CONNECT 14400",Rconnect,       0, },
29         { "23", "CONNECT 1275", Rconnect,       0, },           /* MT1432BA */
30
31         { "-1", "+FCON",        Rcontinue,      fcon, },
32         { "-1", "+FTSI",        Rcontinue,      ftsi, },
33         { "-1", "+FDCS",        Rcontinue,      fdcs, },
34         { "-1", "+FCFR",        Rcontinue,      fcfr, },
35         { "-1", "+FPTS",        Rcontinue,      fpts, },
36         { "-1", "+FET",         Rcontinue,      fet, },
37         { "-1", "+FHNG",        Rcontinue,      fhng, },
38
39         { 0 },
40 };
41
42 void
43 initmodem(Modem *m, int fd, int cfd, char *type, char *id)
44 {
45         m->fd = fd;
46         m->cfd = cfd;
47         if(id == 0)
48                 id = "Plan 9";
49         m->id = id;
50         m->t = type;
51 }
52
53 int
54 rawmchar(Modem *m, char *p)
55 {
56         Dir *d;
57         int n;
58
59         if(m->icount == 0)
60                 m->iptr = m->ibuf;
61
62         if(m->icount){
63                 *p = *m->iptr++;
64                 m->icount--;
65                 return Eok;
66         }
67
68         m->iptr = m->ibuf;
69
70         if((d = dirfstat(m->fd)) == nil){
71                 verbose("rawmchar: dirfstat: %r");
72                 return seterror(m, Esys);
73         }
74         n = d->length;
75         free(d);
76         if(n == 0)
77                 return Enoresponse;
78
79         if(n > sizeof(m->ibuf)-1)
80                 n = sizeof(m->ibuf)-1;
81         if((m->icount = read(m->fd, m->ibuf, n)) <= 0){
82                 verbose("rawmchar: read: %r");
83                 m->icount = 0;
84                 return seterror(m, Esys);
85         }
86         *p = *m->iptr++;
87         m->icount--;
88
89         return Eok;
90 }
91
92 int
93 getmchar(Modem *m, char *buf, long timeout)
94 {
95         int r, t;
96
97         timeout += time(0);
98         while((t = time(0)) <= timeout){
99                 switch(r = rawmchar(m, buf)){
100
101                 case Eok:
102                         return Eok;
103
104                 case Enoresponse:
105                         sleep(100);
106                         continue;
107
108                 default:
109                         return r;
110                 }
111         }
112         verbose("getmchar: time %ud, timeout %ud", t, timeout);
113
114         return seterror(m, Enoresponse);
115 }
116
117 int
118 putmchar(Modem *m, char *p)
119 {
120         if(write(m->fd, p, 1) < 0)
121                 return seterror(m, Esys);
122         return Eok;
123 }
124
125 /*
126  *  lines terminate with cr-lf
127  */
128 static int
129 getmline(Modem *m, char *buf, int len, long timeout)
130 {
131         int r, t;
132         char *e = buf+len-1;
133         char last = 0;
134
135         timeout += time(0);
136         while((t = time(0)) <= timeout){
137                 switch(r = rawmchar(m, buf)){
138
139                 case Eok:
140                         /* ignore ^s ^q which are used for flow */
141                         if(*buf == '\021' || *buf == '\023')
142                                 continue;
143                         if(*buf == '\n'){
144                                 /* ignore nl if its not with a cr */
145                                 if(last == '\r'){
146                                         *buf = 0;
147                                         return Eok;
148                                 }
149                                 continue;
150                         }
151                         last = *buf;
152                         if(*buf == '\r')
153                                 continue;
154                         buf++;
155                         if(buf == e){
156                                 *buf = 0;
157                                 return Eok;
158                         }
159                         continue;
160
161                 case Enoresponse:
162                         sleep(100);
163                         continue;
164
165                 default:
166                         return r;
167                 }
168         }
169         verbose("getmline: time %ud, timeout %ud", t, timeout);
170
171         return seterror(m, Enoresponse);
172 }
173
174 int
175 command(Modem *m, char *s)
176 {
177         verbose("m->: %s", s);
178         if(fprint(m->fd, "%s\r", s) < 0)
179                 return seterror(m, Esys);
180         return Eok;
181 }
182
183 /*
184  * Read till we see a message or we time out.
185  * BUG: line lengths not checked;
186  *      newlines
187  */
188 int
189 response(Modem *m, int timeout)
190 {
191         int r;
192         ResultCode *rp;
193
194         while(getmline(m, m->response, sizeof(m->response), timeout) == Eok){
195                 if(m->response[0] == 0)
196                         continue;
197                 verbose("<-m: %s", m->response);
198                 for(rp = results; rp->terse; rp++){
199                         if(strncmp(rp->verbose, m->response, strlen(rp->verbose)))
200                                 continue;
201                         r = rp->result;
202                         if(rp->f && (r = (*rp->f)(m)) == Rcontinue)
203                                 break;
204                         return r;
205                 }
206         }
207
208         m->response[0] = 0;
209         return Rnoise;
210 }
211
212 void
213 xonoff(Modem *m, int i)
214 {
215         char buf[8];
216
217         sprint(buf, "x%d", i);
218         i = strlen(buf);
219         write(m->cfd, buf, i);
220 }