1219b2ee8SDavid du Colombier #include <u.h>
2219b2ee8SDavid du Colombier #include <libc.h>
3219b2ee8SDavid du Colombier #include <bio.h>
4219b2ee8SDavid du Colombier
5219b2ee8SDavid du Colombier #include "modem.h"
6219b2ee8SDavid du Colombier
7219b2ee8SDavid du Colombier static char buf[102400];
8219b2ee8SDavid du Colombier
9219b2ee8SDavid du Colombier static int
page(Modem * m,char * spool)10219b2ee8SDavid du Colombier page(Modem *m, char *spool)
11219b2ee8SDavid du Colombier {
12219b2ee8SDavid du Colombier int count, r;
13219b2ee8SDavid du Colombier char c;
14219b2ee8SDavid du Colombier
15219b2ee8SDavid du Colombier /*
16219b2ee8SDavid du Colombier * Start data reception. We should receive CONNECT in response
17219b2ee8SDavid du Colombier * to +FDR, then data reception starts when we send DC2.
18219b2ee8SDavid du Colombier */
19219b2ee8SDavid du Colombier m->valid &= ~(Vfhng|Vfet|Vfpts);
20219b2ee8SDavid du Colombier if(command(m, "AT+FDR") != Eok)
21219b2ee8SDavid du Colombier return Esys;
22219b2ee8SDavid du Colombier
23219b2ee8SDavid du Colombier switch(response(m, 30)){
24219b2ee8SDavid du Colombier
25219b2ee8SDavid du Colombier case Rconnect:
26219b2ee8SDavid du Colombier m->phase = 'C';
27219b2ee8SDavid du Colombier if((r = createfaxfile(m, spool)) != Eok)
28219b2ee8SDavid du Colombier return r;
29219b2ee8SDavid du Colombier if((r = putmchar(m, "\022")) != Eok)
30219b2ee8SDavid du Colombier return r;
31219b2ee8SDavid du Colombier break;
32219b2ee8SDavid du Colombier
33219b2ee8SDavid du Colombier case Rhangup:
34219b2ee8SDavid du Colombier return Eok;
35219b2ee8SDavid du Colombier
36219b2ee8SDavid du Colombier default:
37219b2ee8SDavid du Colombier return seterror(m, Eattn);
38219b2ee8SDavid du Colombier }
39219b2ee8SDavid du Colombier
40219b2ee8SDavid du Colombier /*
41219b2ee8SDavid du Colombier * Receive data.
42219b2ee8SDavid du Colombier */
43219b2ee8SDavid du Colombier verbose("starting page %d", m->pageno);
44219b2ee8SDavid du Colombier count = 0;
45219b2ee8SDavid du Colombier while((r = getmchar(m, &c, 6)) == Eok){
46219b2ee8SDavid du Colombier if(c == '\020'){
47219b2ee8SDavid du Colombier if((r = getmchar(m, &c, 3)) != Eok)
48219b2ee8SDavid du Colombier break;
49219b2ee8SDavid du Colombier if(c == '\003')
50219b2ee8SDavid du Colombier break;
51219b2ee8SDavid du Colombier if(c != '\020'){
52219b2ee8SDavid du Colombier verbose("B%2.2ux", c);
53219b2ee8SDavid du Colombier continue;
54219b2ee8SDavid du Colombier }
55219b2ee8SDavid du Colombier }
56219b2ee8SDavid du Colombier buf[count++] = c;
57219b2ee8SDavid du Colombier if(count >= sizeof(buf)){
58*7dd7cddfSDavid du Colombier if(write(m->pagefd, buf, count) < 0){
59219b2ee8SDavid du Colombier close(m->pagefd);
60219b2ee8SDavid du Colombier return seterror(m, Esys);
61219b2ee8SDavid du Colombier }
62219b2ee8SDavid du Colombier count = 0;
63219b2ee8SDavid du Colombier }
64219b2ee8SDavid du Colombier }
65219b2ee8SDavid du Colombier verbose("page %d done, count %d", m->pageno, count);
66219b2ee8SDavid du Colombier if(count && write(m->pagefd, buf, count) < 0){
67219b2ee8SDavid du Colombier close(m->pagefd);
68219b2ee8SDavid du Colombier return seterror(m, Esys);
69219b2ee8SDavid du Colombier }
70219b2ee8SDavid du Colombier if(r != Eok)
71219b2ee8SDavid du Colombier return r;
72219b2ee8SDavid du Colombier
73219b2ee8SDavid du Colombier /*
74219b2ee8SDavid du Colombier * Wait for either OK or ERROR.
75219b2ee8SDavid du Colombier */
76219b2ee8SDavid du Colombier switch(r = response(m, 20)){
77219b2ee8SDavid du Colombier
78219b2ee8SDavid du Colombier case Rok:
79219b2ee8SDavid du Colombier case Rrerror:
80219b2ee8SDavid du Colombier return Eok;
81219b2ee8SDavid du Colombier
82219b2ee8SDavid du Colombier default:
83219b2ee8SDavid du Colombier verbose("page: response %d", r);
84219b2ee8SDavid du Colombier return Eproto;
85219b2ee8SDavid du Colombier }
86219b2ee8SDavid du Colombier }
87219b2ee8SDavid du Colombier
88219b2ee8SDavid du Colombier static int
receive(Modem * m,char * spool)89219b2ee8SDavid du Colombier receive(Modem *m, char *spool)
90219b2ee8SDavid du Colombier {
91219b2ee8SDavid du Colombier int r;
92219b2ee8SDavid du Colombier
93219b2ee8SDavid du Colombier loop:
94219b2ee8SDavid du Colombier switch(r = page(m, spool)){
95219b2ee8SDavid du Colombier
96219b2ee8SDavid du Colombier case Eok:
97219b2ee8SDavid du Colombier /*
98219b2ee8SDavid du Colombier * Check we have a valid page reponse.
99219b2ee8SDavid du Colombier */
100219b2ee8SDavid du Colombier if((m->valid & Vfhng) == 0 && (m->valid & (Vfet|Vfpts)) != (Vfet|Vfpts)){
101219b2ee8SDavid du Colombier verbose("receive: invalid page reponse: #%4.4ux", m->valid);
102219b2ee8SDavid du Colombier return seterror(m, Eproto);
103219b2ee8SDavid du Colombier }
104219b2ee8SDavid du Colombier
105219b2ee8SDavid du Colombier /*
106219b2ee8SDavid du Colombier * Was the page successfully received?
107219b2ee8SDavid du Colombier * If not, try again.
108219b2ee8SDavid du Colombier */
109219b2ee8SDavid du Colombier if((m->valid & Vfpts) && m->fpts[0] != 1)
110219b2ee8SDavid du Colombier goto loop;
111219b2ee8SDavid du Colombier
112219b2ee8SDavid du Colombier /*
113219b2ee8SDavid du Colombier * Another page of the same document, a new document
114219b2ee8SDavid du Colombier * or no more pages.
115219b2ee8SDavid du Colombier * If no more pages we still have to get the FHNG, so
116219b2ee8SDavid du Colombier * the code is just the same as if there was another
117219b2ee8SDavid du Colombier * page.
118219b2ee8SDavid du Colombier */
119219b2ee8SDavid du Colombier if(m->valid & Vfet){
120219b2ee8SDavid du Colombier switch(m->fet){
121219b2ee8SDavid du Colombier
122219b2ee8SDavid du Colombier case 0: /* another page */
123219b2ee8SDavid du Colombier case 2: /* no more pages */
124219b2ee8SDavid du Colombier m->pageno++;
125219b2ee8SDavid du Colombier goto loop;
126219b2ee8SDavid du Colombier
127219b2ee8SDavid du Colombier case 1: /* new document */
128219b2ee8SDavid du Colombier /*
129219b2ee8SDavid du Colombier * Bug: currently no way to run the
130219b2ee8SDavid du Colombier * fax-received process for this, so it
131219b2ee8SDavid du Colombier * just stays queued.
132219b2ee8SDavid du Colombier */
133219b2ee8SDavid du Colombier faxrlog(m, Eok);
134219b2ee8SDavid du Colombier m->pageno = 1;
135219b2ee8SDavid du Colombier m->time = time(0);
136219b2ee8SDavid du Colombier m->pid = getpid();
137219b2ee8SDavid du Colombier goto loop;
138219b2ee8SDavid du Colombier }
139219b2ee8SDavid du Colombier
140219b2ee8SDavid du Colombier verbose("receive: invalid FET: %d", m->fet);
141219b2ee8SDavid du Colombier return seterror(m, Eproto);
142219b2ee8SDavid du Colombier }
143219b2ee8SDavid du Colombier
144219b2ee8SDavid du Colombier /*
145219b2ee8SDavid du Colombier * All done or hangup error.
146219b2ee8SDavid du Colombier * On error remove all pages in the current document.
147219b2ee8SDavid du Colombier * Yik.
148219b2ee8SDavid du Colombier */
149219b2ee8SDavid du Colombier if(m->valid & Vfhng){
150219b2ee8SDavid du Colombier if(m->fhng == 0)
151219b2ee8SDavid du Colombier return Eok;
152219b2ee8SDavid du Colombier verbose("receive: FHNG: %d", m->fhng);
153219b2ee8SDavid du Colombier /*
154219b2ee8SDavid du Colombier for(r = 1; r <= m->pageno; r++){
155219b2ee8SDavid du Colombier char pageid[128];
156219b2ee8SDavid du Colombier
157219b2ee8SDavid du Colombier setpageid(pageid, spool, m->time, m->pid, r);
158219b2ee8SDavid du Colombier remove(pageid);
159219b2ee8SDavid du Colombier }
160219b2ee8SDavid du Colombier */
161219b2ee8SDavid du Colombier return seterror(m, Eattn);
162219b2ee8SDavid du Colombier }
163219b2ee8SDavid du Colombier /*FALLTHROUGH*/
164219b2ee8SDavid du Colombier
165219b2ee8SDavid du Colombier default:
166219b2ee8SDavid du Colombier return r;
167219b2ee8SDavid du Colombier }
168219b2ee8SDavid du Colombier }
169219b2ee8SDavid du Colombier
170219b2ee8SDavid du Colombier int
faxreceive(Modem * m,char * spool)171219b2ee8SDavid du Colombier faxreceive(Modem *m, char *spool)
172219b2ee8SDavid du Colombier {
173219b2ee8SDavid du Colombier int r;
174219b2ee8SDavid du Colombier
175219b2ee8SDavid du Colombier verbose("faxdaemon");
176219b2ee8SDavid du Colombier if((r = initfaxmodem(m)) != Eok)
177219b2ee8SDavid du Colombier return r;
178219b2ee8SDavid du Colombier
179219b2ee8SDavid du Colombier /*
180219b2ee8SDavid du Colombier * assume that the phone has been answered and
181219b2ee8SDavid du Colombier * we have received +FCON
182219b2ee8SDavid du Colombier */
183219b2ee8SDavid du Colombier m->pageno = 1;
184219b2ee8SDavid du Colombier m->time = time(0);
185219b2ee8SDavid du Colombier m->pid = getpid();
186219b2ee8SDavid du Colombier fcon(m);
187219b2ee8SDavid du Colombier
188219b2ee8SDavid du Colombier /*
189219b2ee8SDavid du Colombier * I wish I knew how to set the default parameters on the
190219b2ee8SDavid du Colombier * MT1432 modem (+FIP in Class 2.0).
191219b2ee8SDavid du Colombier */
192219b2ee8SDavid du Colombier return receive(m, spool);
193219b2ee8SDavid du Colombier }
194