summaryrefslogtreecommitdiff
path: root/sys/src/cmd/fax/fax2receive.c
blob: e3c905a182495ee65b305701e213545998b21f9c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
#include <u.h>
#include <libc.h>
#include <bio.h>

#include "modem.h"

static char buf[102400];

static int
page(Modem *m, char *spool)
{
	int count, r;
	char c;

	/*
	 * Start data reception. We should receive CONNECT in response
	 * to +FDR, then data reception starts when we send DC2.
	 */
	m->valid &= ~(Vfhng|Vfet|Vfpts);
	if(command(m, "AT+FDR") != Eok)
		return Esys;

	switch(response(m, 30)){

	case Rconnect:
		m->phase = 'C';
		if((r = createfaxfile(m, spool)) != Eok)
			return r;
		if((r = putmchar(m, "\022")) != Eok)
			return r;
		break;

	case Rhangup:
		return Eok;

	default:
		return seterror(m, Eattn);
	}

	/*
	 * Receive data.
	 */
	verbose("starting page %d", m->pageno);
	count = 0;
	while((r = getmchar(m, &c, 6)) == Eok){
		if(c == '\020'){
			if((r = getmchar(m, &c, 3)) != Eok)
				break;
			if(c == '\003')
				break;
			if(c != '\020'){
				verbose("B%2.2ux", c);
				continue;
			}
		}
		buf[count++] = c;
		if(count >= sizeof(buf)){
			if(write(m->pagefd, buf, count) < 0){
				close(m->pagefd);
				return seterror(m, Esys);
			}
			count = 0;
		}	
	}
	verbose("page %d done, count %d", m->pageno, count);
	if(count && write(m->pagefd, buf, count) < 0){
		close(m->pagefd);
		return seterror(m, Esys);
	}
	if(r != Eok)
		return r;

	/*
	 * Wait for either OK or ERROR.
	 */
	switch(r = response(m, 20)){

	case Rok:
	case Rrerror:
		return Eok;

	default:
		verbose("page: response %d", r);
		return Eproto;
	}
}

static int
receive(Modem *m, char *spool)
{
	int r;

   loop:
	switch(r = page(m, spool)){

	case Eok:
		/*
		 * Check we have a valid page reponse.
		 */
		if((m->valid & Vfhng) == 0 && (m->valid & (Vfet|Vfpts)) != (Vfet|Vfpts)){
			verbose("receive: invalid page reponse: #%4.4ux", m->valid);
			return seterror(m, Eproto);
		}

		/*
		 * Was the page successfully received?
		 * If not, try again.
		 */
		if((m->valid & Vfpts) && m->fpts[0] != 1)
			goto loop;

		/*
		 * Another page of the same document, a new document
		 * or no more pages.
		 * If no more pages we still have to get the FHNG, so
		 * the code is just the same as if there was another
		 * page.
		 */
		if(m->valid & Vfet){
			switch(m->fet){

			case 0:				/* another page */
			case 2:				/* no more pages */
				m->pageno++;
				goto loop;

			case 1:				/* new document */
				/*
				 * Bug: currently no way to run the
				 * fax-received process for this, so it
				 * just stays queued.
				 */
				faxrlog(m, Eok);
				m->pageno = 1;
				m->time = time(0);
				m->pid = getpid();
				goto loop;
			}

			verbose("receive: invalid FET: %d", m->fet);
			return seterror(m, Eproto);
		}

		/*
		 * All done or hangup error.
		 * On error remove all pages in the current document.
		 * Yik.
		 */
		if(m->valid & Vfhng){
			if(m->fhng == 0)
				return Eok;
			verbose("receive: FHNG: %d", m->fhng);
			/*
			for(r = 1; r <= m->pageno; r++){
				char pageid[128];

				setpageid(pageid, spool, m->time, m->pid, r);
				remove(pageid);
			}
			 */
			return seterror(m, Eattn);
		}
		/*FALLTHROUGH*/

	default:
		return r;
	}
}

int
faxreceive(Modem *m, char *spool)
{
	int r;

	verbose("faxdaemon");
	if((r = initfaxmodem(m)) != Eok)
		return r;

	/*
	 *  assume that the phone has been answered and
	 *  we have received +FCON
	 */
	m->pageno = 1;
	m->time = time(0);
	m->pid = getpid();
	fcon(m);

	/*
	 * I wish I knew how to set the default parameters on the
	 * MT1432 modem (+FIP in Class 2.0).
	 */
	return receive(m, spool);
}