xref: /plan9/sys/src/cmd/fax/fax2send.c (revision 80ee5cbfe36716af62da8896207e9763b8e3d760)
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 int
faxsend(Modem * m,int argc,char * argv[])8219b2ee8SDavid du Colombier faxsend(Modem *m, int argc, char *argv[])
9219b2ee8SDavid du Colombier {
107dd7cddfSDavid du Colombier 	int c, count, r, flow;
11219b2ee8SDavid du Colombier 	char buf[128];
12219b2ee8SDavid du Colombier 
13219b2ee8SDavid du Colombier 	verbose("faxsend");
14219b2ee8SDavid du Colombier 	if((r = initfaxmodem(m)) != Eok)
15219b2ee8SDavid du Colombier 		return r;
16219b2ee8SDavid du Colombier 
17219b2ee8SDavid du Colombier 	/* telco just does the dialing */
18219b2ee8SDavid du Colombier 	r = response(m, 120);
19219b2ee8SDavid du Colombier 	switch(r){
20219b2ee8SDavid du Colombier 	case Rok:
21219b2ee8SDavid du Colombier 		break;
22219b2ee8SDavid du Colombier 	default:
23219b2ee8SDavid du Colombier 		r = seterror(m, Enoanswer);
24219b2ee8SDavid du Colombier 		return r;
25219b2ee8SDavid du Colombier 
26219b2ee8SDavid du Colombier 	}
27219b2ee8SDavid du Colombier 
287dd7cddfSDavid du Colombier 	xonoff(m, 1);
297dd7cddfSDavid du Colombier 	verbose("sending");
30219b2ee8SDavid du Colombier 	m->pageno = 1;
31219b2ee8SDavid du Colombier 	while(argc--){
32219b2ee8SDavid du Colombier 		if(m->pageno != 1)
33219b2ee8SDavid du Colombier 			sleep(1000);	/* let the paper catch up */
34219b2ee8SDavid du Colombier 
35219b2ee8SDavid du Colombier 		m->valid &= ~(Vfhng|Vfet|Vfpts|Vftsi|Vfdcs);
36219b2ee8SDavid du Colombier 		if((r = openfaxfile(m, *argv)) != Eok)
37219b2ee8SDavid du Colombier 			return r;
38219b2ee8SDavid du Colombier 
397dd7cddfSDavid du Colombier 		verbose("sending geometry");
407dd7cddfSDavid du Colombier 		sprint(buf, "AT+FDT=%ld,%ld,%ld,%ld", m->df, m->vr, m->wd, m->ln);
41219b2ee8SDavid du Colombier 		if(command(m, buf) != Eok)
42219b2ee8SDavid du Colombier 			goto buggery;
43219b2ee8SDavid du Colombier 		if(response(m, 20) != Rconnect){
44219b2ee8SDavid du Colombier 			r = seterror(m, Eincompatible);
45219b2ee8SDavid du Colombier 			goto buggery;
46219b2ee8SDavid du Colombier 		}
47219b2ee8SDavid du Colombier 
48219b2ee8SDavid du Colombier 		/*
49219b2ee8SDavid du Colombier 		 * Write the data, stuffing DLE's.
50219b2ee8SDavid du Colombier 		 * After each bufferfull check if the remote
51219b2ee8SDavid du Colombier 		 * sent us anything, e.g. CAN to abort.
52219b2ee8SDavid du Colombier 		 * This also flushes out the ^S/^Q characters
53219b2ee8SDavid du Colombier 		 * which the driver insists on sending us.
54219b2ee8SDavid du Colombier 		 * (Could fix the driver, of course...).
55219b2ee8SDavid du Colombier 		 */
567dd7cddfSDavid du Colombier 		verbose("sending data");
57219b2ee8SDavid du Colombier 		for(;;){
587dd7cddfSDavid du Colombier 			flow = 0;
59219b2ee8SDavid du Colombier 			count = 0;
60219b2ee8SDavid du Colombier 			c = 0;
61219b2ee8SDavid du Colombier 			while(count < sizeof(buf)-1){
627dd7cddfSDavid du Colombier 				if((c = Bgetc(m->bp)) < 0)
63219b2ee8SDavid du Colombier 					break;
64219b2ee8SDavid du Colombier 				buf[count++] = c;
65219b2ee8SDavid du Colombier 				if(c == '\020')
66219b2ee8SDavid du Colombier 					buf[count++] = c;
67219b2ee8SDavid du Colombier 			}
687dd7cddfSDavid du Colombier 			verbose("sending %d bytes", count);
69219b2ee8SDavid du Colombier 			if(count && write(m->fd, buf, count) < 0){
707dd7cddfSDavid du Colombier 				verbose("write failed: %r");
71219b2ee8SDavid du Colombier 				r = seterror(m, Esys);
72219b2ee8SDavid du Colombier 				goto buggery;
73219b2ee8SDavid du Colombier 			}
747dd7cddfSDavid du Colombier 			/*
757dd7cddfSDavid du Colombier 			 *  this does really rough flow control since the
767dd7cddfSDavid du Colombier 			 *  avanstar is even worse
777dd7cddfSDavid du Colombier 			 */
787dd7cddfSDavid du Colombier 			verbose("flow control");
79*80ee5cbfSDavid du Colombier 			while((r = rawmchar(m, buf)) == Eok || flow){
807dd7cddfSDavid du Colombier 				if(r != Eok){
817dd7cddfSDavid du Colombier 					if(flow-- == 0)
82219b2ee8SDavid du Colombier 						break;
837dd7cddfSDavid du Colombier 					sleep(250);
847dd7cddfSDavid du Colombier 					continue;
857dd7cddfSDavid du Colombier 				}
867dd7cddfSDavid du Colombier 				switch(buf[0]){
877dd7cddfSDavid du Colombier 				case '\030':
88219b2ee8SDavid du Colombier 					verbose("%c", buf[0]);
89219b2ee8SDavid du Colombier 					if(write(m->fd, "\020\003", 2) < 0){
90219b2ee8SDavid du Colombier 						r = seterror(m, Esys);
91219b2ee8SDavid du Colombier 						goto buggery;
92219b2ee8SDavid du Colombier 					}
93219b2ee8SDavid du Colombier 					goto okexit;
947dd7cddfSDavid du Colombier 				case '\021':
957dd7cddfSDavid du Colombier 					flow = 0;
967dd7cddfSDavid du Colombier 					break;
977dd7cddfSDavid du Colombier 				case '\023':
987dd7cddfSDavid du Colombier 					flow = 4;
997dd7cddfSDavid du Colombier 					break;
1007dd7cddfSDavid du Colombier 				case '\n':
1017dd7cddfSDavid du Colombier 					break;
1027dd7cddfSDavid du Colombier 				default:
103219b2ee8SDavid du Colombier 					verbose("%c", buf[0]);
104219b2ee8SDavid du Colombier 					r = seterror(m, Eproto);
105219b2ee8SDavid du Colombier 					goto buggery;
1067dd7cddfSDavid du Colombier 
107219b2ee8SDavid du Colombier 				}
108219b2ee8SDavid du Colombier 			}
1097dd7cddfSDavid du Colombier 			if(c < 0)
1107dd7cddfSDavid du Colombier 				break;
111219b2ee8SDavid du Colombier 		}
112219b2ee8SDavid du Colombier 
1137dd7cddfSDavid du Colombier 
114219b2ee8SDavid du Colombier 		/*
115219b2ee8SDavid du Colombier 		 * End of page, send DLE+ETX,
116219b2ee8SDavid du Colombier 		 * get OK in response.
117219b2ee8SDavid du Colombier 		 */
1187dd7cddfSDavid du Colombier 		verbose("sending end of page");
119219b2ee8SDavid du Colombier 		if(write(m->fd, "\020\003", 2) < 0){
120219b2ee8SDavid du Colombier 			r = seterror(m, Esys);
121219b2ee8SDavid du Colombier 			goto buggery;
122219b2ee8SDavid du Colombier 		}
1237dd7cddfSDavid du Colombier 		verbose("waiting for OK");
1247dd7cddfSDavid du Colombier 		if(response(m, 120) != Rok){
125219b2ee8SDavid du Colombier 			r = seterror(m, Enoresponse);
126219b2ee8SDavid du Colombier 			goto buggery;
127219b2ee8SDavid du Colombier 		}
128219b2ee8SDavid du Colombier 
129219b2ee8SDavid du Colombier 		/*
130219b2ee8SDavid du Colombier 		 * Did you hear me? - IT'S THE END OF THE PAGE.
131219b2ee8SDavid du Colombier 		 * Argument is 0 if more pages to follow.
132219b2ee8SDavid du Colombier 		 * Should get back an FPTS with an indication
133219b2ee8SDavid du Colombier 		 * as to whether the page was successfully
134219b2ee8SDavid du Colombier 		 * transmitted or not.
135219b2ee8SDavid du Colombier 		 */
136219b2ee8SDavid du Colombier 		sprint(buf, "AT+FET=%d", argc == 0? 2: 0);
137219b2ee8SDavid du Colombier 		if(command(m, buf) != Eok)
138219b2ee8SDavid du Colombier 			goto buggery;
139219b2ee8SDavid du Colombier 		switch(response(m, 20)){
140219b2ee8SDavid du Colombier 		case Rok:
141219b2ee8SDavid du Colombier 			break;
142219b2ee8SDavid du Colombier 		case Rhangup:
143219b2ee8SDavid du Colombier 			if(m->fhng == 0 && argc == 0)
144219b2ee8SDavid du Colombier 				break;
145219b2ee8SDavid du Colombier 			r = seterror(m, Eproto);
146219b2ee8SDavid du Colombier 			goto buggery;
147219b2ee8SDavid du Colombier 		default:
148219b2ee8SDavid du Colombier 			r = seterror(m, Enoresponse);
149219b2ee8SDavid du Colombier 			goto buggery;
150219b2ee8SDavid du Colombier 		}
151219b2ee8SDavid du Colombier 
152219b2ee8SDavid du Colombier 		if((m->valid & Vfpts) == 0 || m->fpts[0] != 1){
153219b2ee8SDavid du Colombier 			r = seterror(m, Eproto);
154219b2ee8SDavid du Colombier 			goto buggery;
155219b2ee8SDavid du Colombier 		}
156219b2ee8SDavid du Colombier 
157219b2ee8SDavid du Colombier 		Bterm(m->bp);
158219b2ee8SDavid du Colombier 		m->pageno++;
159219b2ee8SDavid du Colombier 		argv++;
160219b2ee8SDavid du Colombier 	}
161219b2ee8SDavid du Colombier okexit:
1627dd7cddfSDavid du Colombier 	xonoff(m, 0);
163219b2ee8SDavid du Colombier 	return Eok;
164219b2ee8SDavid du Colombier 
165219b2ee8SDavid du Colombier buggery:
1667dd7cddfSDavid du Colombier 	xonoff(m, 0);
167219b2ee8SDavid du Colombier 	Bterm(m->bp);
168219b2ee8SDavid du Colombier 	command(m, "AT+FK");
169219b2ee8SDavid du Colombier 	response(m, 5);
170219b2ee8SDavid du Colombier 	return r;
171219b2ee8SDavid du Colombier }
172