xref: /plan9/sys/src/cmd/fax/fax2receive.c (revision b85a83648eec38fe82b6f00adfd7828ceec5ee8d)
1 #include <u.h>
2 #include <libc.h>
3 #include <bio.h>
4 
5 #include "modem.h"
6 
7 static char buf[102400];
8 
9 static int
page(Modem * m,char * spool)10 page(Modem *m, char *spool)
11 {
12 	int count, r;
13 	char c;
14 
15 	/*
16 	 * Start data reception. We should receive CONNECT in response
17 	 * to +FDR, then data reception starts when we send DC2.
18 	 */
19 	m->valid &= ~(Vfhng|Vfet|Vfpts);
20 	if(command(m, "AT+FDR") != Eok)
21 		return Esys;
22 
23 	switch(response(m, 30)){
24 
25 	case Rconnect:
26 		m->phase = 'C';
27 		if((r = createfaxfile(m, spool)) != Eok)
28 			return r;
29 		if((r = putmchar(m, "\022")) != Eok)
30 			return r;
31 		break;
32 
33 	case Rhangup:
34 		return Eok;
35 
36 	default:
37 		return seterror(m, Eattn);
38 	}
39 
40 	/*
41 	 * Receive data.
42 	 */
43 	verbose("starting page %d", m->pageno);
44 	count = 0;
45 	while((r = getmchar(m, &c, 6)) == Eok){
46 		if(c == '\020'){
47 			if((r = getmchar(m, &c, 3)) != Eok)
48 				break;
49 			if(c == '\003')
50 				break;
51 			if(c != '\020'){
52 				verbose("B%2.2ux", c);
53 				continue;
54 			}
55 		}
56 		buf[count++] = c;
57 		if(count >= sizeof(buf)){
58 			if(write(m->pagefd, buf, count) < 0){
59 				close(m->pagefd);
60 				return seterror(m, Esys);
61 			}
62 			count = 0;
63 		}
64 	}
65 	verbose("page %d done, count %d", m->pageno, count);
66 	if(count && write(m->pagefd, buf, count) < 0){
67 		close(m->pagefd);
68 		return seterror(m, Esys);
69 	}
70 	if(r != Eok)
71 		return r;
72 
73 	/*
74 	 * Wait for either OK or ERROR.
75 	 */
76 	switch(r = response(m, 20)){
77 
78 	case Rok:
79 	case Rrerror:
80 		return Eok;
81 
82 	default:
83 		verbose("page: response %d", r);
84 		return Eproto;
85 	}
86 }
87 
88 static int
receive(Modem * m,char * spool)89 receive(Modem *m, char *spool)
90 {
91 	int r;
92 
93    loop:
94 	switch(r = page(m, spool)){
95 
96 	case Eok:
97 		/*
98 		 * Check we have a valid page reponse.
99 		 */
100 		if((m->valid & Vfhng) == 0 && (m->valid & (Vfet|Vfpts)) != (Vfet|Vfpts)){
101 			verbose("receive: invalid page reponse: #%4.4ux", m->valid);
102 			return seterror(m, Eproto);
103 		}
104 
105 		/*
106 		 * Was the page successfully received?
107 		 * If not, try again.
108 		 */
109 		if((m->valid & Vfpts) && m->fpts[0] != 1)
110 			goto loop;
111 
112 		/*
113 		 * Another page of the same document, a new document
114 		 * or no more pages.
115 		 * If no more pages we still have to get the FHNG, so
116 		 * the code is just the same as if there was another
117 		 * page.
118 		 */
119 		if(m->valid & Vfet){
120 			switch(m->fet){
121 
122 			case 0:				/* another page */
123 			case 2:				/* no more pages */
124 				m->pageno++;
125 				goto loop;
126 
127 			case 1:				/* new document */
128 				/*
129 				 * Bug: currently no way to run the
130 				 * fax-received process for this, so it
131 				 * just stays queued.
132 				 */
133 				faxrlog(m, Eok);
134 				m->pageno = 1;
135 				m->time = time(0);
136 				m->pid = getpid();
137 				goto loop;
138 			}
139 
140 			verbose("receive: invalid FET: %d", m->fet);
141 			return seterror(m, Eproto);
142 		}
143 
144 		/*
145 		 * All done or hangup error.
146 		 * On error remove all pages in the current document.
147 		 * Yik.
148 		 */
149 		if(m->valid & Vfhng){
150 			if(m->fhng == 0)
151 				return Eok;
152 			verbose("receive: FHNG: %d", m->fhng);
153 			/*
154 			for(r = 1; r <= m->pageno; r++){
155 				char pageid[128];
156 
157 				setpageid(pageid, spool, m->time, m->pid, r);
158 				remove(pageid);
159 			}
160 			 */
161 			return seterror(m, Eattn);
162 		}
163 		/*FALLTHROUGH*/
164 
165 	default:
166 		return r;
167 	}
168 }
169 
170 int
faxreceive(Modem * m,char * spool)171 faxreceive(Modem *m, char *spool)
172 {
173 	int r;
174 
175 	verbose("faxdaemon");
176 	if((r = initfaxmodem(m)) != Eok)
177 		return r;
178 
179 	/*
180 	 *  assume that the phone has been answered and
181 	 *  we have received +FCON
182 	 */
183 	m->pageno = 1;
184 	m->time = time(0);
185 	m->pid = getpid();
186 	fcon(m);
187 
188 	/*
189 	 * I wish I knew how to set the default parameters on the
190 	 * MT1432 modem (+FIP in Class 2.0).
191 	 */
192 	return receive(m, spool);
193 }
194