1 #include <u.h>
2 #include <libc.h>
3 #include <bio.h>
4
5 #include "modem.h"
6
7 int
faxsend(Modem * m,int argc,char * argv[])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 }
172