]> git.lizzy.rs Git - plan9front.git/blob - sys/src/cmd/fax/fax2send.c
libtags, zuke: add *.mod support (thanks kemal)
[plan9front.git] / sys / src / cmd / fax / fax2send.c
1 #include <u.h>
2 #include <libc.h>
3 #include <bio.h>
4
5 #include "modem.h"
6
7 int
8 faxsend(Modem *m, int argc, char *argv[])
9 {
10         int c, count, r, flow;
11         char buf[128];
12
13         verbose("faxsend");
14         if((r = initfaxmodem(m)) != Eok)
15                 return r;
16
17         /* telco just does the dialing */
18         r = response(m, 120);
19         switch(r){
20         case Rok:
21                 break;
22         default:
23                 r = seterror(m, Enoanswer);
24                 return r;
25                 
26         }
27
28         xonoff(m, 1);
29         verbose("sending");
30         m->pageno = 1;
31         while(argc--){
32                 if(m->pageno != 1)
33                         sleep(1000);    /* let the paper catch up */
34
35                 m->valid &= ~(Vfhng|Vfet|Vfpts|Vftsi|Vfdcs);
36                 if((r = openfaxfile(m, *argv)) != Eok)
37                         return r;
38
39                 verbose("sending geometry");
40                 sprint(buf, "AT+FDT=%ld,%ld,%ld,%ld", m->df, m->vr, m->wd, m->ln);
41                 if(command(m, buf) != Eok)
42                         goto buggery;
43                 if(response(m, 20) != Rconnect){
44                         r = seterror(m, Eincompatible);
45                         goto buggery;
46                 }
47
48                 /*
49                  * Write the data, stuffing DLE's.
50                  * After each bufferfull check if the remote
51                  * sent us anything, e.g. CAN to abort.
52                  * This also flushes out the ^S/^Q characters
53                  * which the driver insists on sending us.
54                  * (Could fix the driver, of course...).
55                  */
56                 verbose("sending data");
57                 for(;;){
58                         flow = 0;
59                         count = 0;
60                         c = 0;
61                         while(count < sizeof(buf)-1){
62                                 if((c = Bgetc(m->bp)) < 0)
63                                         break;
64                                 buf[count++] = c;
65                                 if(c == '\020')
66                                         buf[count++] = c;
67                         }
68                         verbose("sending %d bytes", count);
69                         if(count && write(m->fd, buf, count) < 0){
70                                 verbose("write failed: %r");
71                                 r = seterror(m, Esys);
72                                 goto buggery;
73                         }
74                         /*
75                          *  this does really rough flow control since the
76                          *  avanstar is even worse
77                          */
78                         verbose("flow control");
79                         while((r = rawmchar(m, buf)) == Eok || flow){
80                                 if(r != Eok){
81                                         if(flow-- == 0)
82                                                 break;
83                                         sleep(250);
84                                         continue;
85                                 }
86                                 switch(buf[0]){
87                                 case '\030':
88                                         verbose("%c", buf[0]);
89                                         if(write(m->fd, "\020\003", 2) < 0){
90                                                 r = seterror(m, Esys);
91                                                 goto buggery;
92                                         }
93                                         goto okexit;
94                                 case '\021':
95                                         flow = 0;
96                                         break;
97                                 case '\023':
98                                         flow = 4;
99                                         break;
100                                 case '\n':
101                                         break;
102                                 default:
103                                         verbose("%c", buf[0]);
104                                         r = seterror(m, Eproto);
105                                         goto buggery;
106                                 
107                                 }
108                         }
109                         if(c < 0)
110                                 break;
111                 }
112
113
114                 /*
115                  * End of page, send DLE+ETX,
116                  * get OK in response.
117                  */
118                 verbose("sending end of page");
119                 if(write(m->fd, "\020\003", 2) < 0){
120                         r = seterror(m, Esys);
121                         goto buggery;
122                 }
123                 verbose("waiting for OK");
124                 if(response(m, 120) != Rok){
125                         r = seterror(m, Enoresponse);
126                         goto buggery;
127                 }
128
129                 /*
130                  * Did you hear me? - IT'S THE END OF THE PAGE.
131                  * Argument is 0 if more pages to follow.
132                  * Should get back an FPTS with an indication
133                  * as to whether the page was successfully
134                  * transmitted or not.
135                  */
136                 sprint(buf, "AT+FET=%d", argc == 0? 2: 0);
137                 if(command(m, buf) != Eok)
138                         goto buggery;
139                 switch(response(m, 20)){
140                 case Rok:
141                         break;
142                 case Rhangup:
143                         if(m->fhng == 0 && argc == 0)
144                                 break;
145                         r = seterror(m, Eproto);
146                         goto buggery;
147                 default:
148                         r = seterror(m, Enoresponse);
149                         goto buggery;
150                 }
151
152                 if((m->valid & Vfpts) == 0 || m->fpts[0] != 1){
153                         r = seterror(m, Eproto);
154                         goto buggery;
155                 }
156
157                 Bterm(m->bp);
158                 m->pageno++;
159                 argv++;
160         }
161 okexit:
162         xonoff(m, 0);
163         return Eok;
164
165 buggery:
166         xonoff(m, 0);
167         Bterm(m->bp);
168         command(m, "AT+FK");
169         response(m, 5);
170         return r;
171 }