1 #ident "$Id: class1.c,v 4.20 2009/03/19 15:51:17 gert Exp $ Copyright (c) Gert Doering"
2 
3 /* class1.c
4  *
5  * High-level functions to handle class 1 fax --
6  * state machines for fax phase A, B, C, D. Error recovery.
7  *
8  * Uses library functions in class1lib.c, faxlib.c and modem.c
9  *
10  * $Log: class1.c,v $
11  * Revision 4.20  2009/03/19 15:51:17  gert
12  * bugfix: new NSF sending code was introducing extra "AT+FTH=3" commands
13  * (due to confusion about internal requirements of fax1_send_frame())
14  *
15  * Revision 4.19  2009/03/19 15:33:59  gert
16  * send NSF frames on reception (if modem quirk 0x40, for now)
17  * handle different modem behaviour regarding AT+FTS=8;+FTH=3 gracefully
18  *
19  * Revision 4.18  2006/10/27 09:07:12  gert
20  * add file name of page currently sent to log message
21  *
22  * Revision 4.17  2006/10/25 10:55:01  gert
23  * class 1 receive: log current try #, send DIS only if CSI went without error
24  *
25  * Revision 4.16  2006/09/29 19:30:26  gert
26  * properly calculate scan line time -> padding bytes
27  * implement FTT -> retraining, with baud rate reduction
28  *
29  * Revision 4.15  2006/09/26 15:36:07  gert
30  * - handle modems that don't get AT+FTS=8;+FTM=nn right
31  *   (re-do AT+FTM if the first command yields "OK")
32  * - switch on and off Xon/Xoff flow control before/after sending page data
33  *
34  * Revision 4.14  2006/09/25 22:26:54  gert
35  * fax1_send_page(): move all the G3 file handling to g3file.c functions
36  *  (-> cleanup code, build common infrastructure for class 1 + class 2)
37  *
38  * Revision 4.13  2006/03/22 14:13:12  gert
39  * when sending, hand over received NSF to NSF decoder (faxlib.c/hyla_nsf.c)
40  *
41  * Revision 4.12  2006/03/07 21:31:50  gert
42  * class 1 sending implementation:
43  *   - handle end-of-page (return to phase B or phase C, or send DCN/hangup)
44  *   - move sending of TSI and DCS inside fax1_send_page(), to be able to
45  *     handle RTN/RTP transparently - somewhat sloppy "phase B" definition,
46  *     but much cleaner this way
47  *   - fix reading of G3 files - skip digifax header, also send last chunk
48  *   - fix bit swapping (fax_send_swaptable)
49  * -> class 1 sending now works, if the receiver doesn't need EOL padding
50  *
51  * Revision 4.11  2006/03/07 14:16:56  gert
52  * fax1_dial_and_phase_AB(): add torture test code, refusing incoming CSI/DIS
53  * 2 times before going on (mainly for testing receiver robustness)
54  * fax1_send_page(): add log message to point out unimplemented stuff
55  *
56  * Revision 4.10  2006/01/04 21:07:12  gert
57  * remove "speed" argument from fax1_send_dcs() (use fax1_max global)
58  *
59  * Revision 4.9  2006/01/03 09:12:20  gert
60  * initialize "tries" in fax1_receive_page()
61  *
62  * Revision 4.8  2006/01/01 17:07:43  gert
63  * change all fax1_send_dcn() to already set appropriate hangup code
64  * add prototypes for local functions
65  * add timeout handling and re-try logic to fax1_highlevel_receive(),
66  *     fax1_receive_tcf() and fax1_receive_page()
67  * add handling of incoming DCNs (give up)
68  * add calculation of "how long should TCF be?" + checking to fax1_receive_tcf()
69  *
70  * Revision 4.7  2005/12/31 17:47:10  gert
71  * use fax1_send_dis() instead of doing it here
72  *
73  * Revision 4.6  2005/12/31 15:52:08  gert
74  * more comments
75  * fax 1 receiver:
76  *   * use global variable fax1_receive_have_connect to
77  *     communicate answering status ("have we seen CONNECT?") from mgetty.c
78  *   * prepare full T.30 receive state machine, including EOM->phase B
79  *     and RTP/RTN->TCF (not complete)
80  *   * set fax_hangup/fax_hangup_code correctly upon some error situations
81  *
82  * Revision 4.5  2005/12/30 23:05:05  gert
83  * rework fax1_send_frame(): leading 0xff is now implicit
84  *   (symmetric to fax1_receive_frame())
85  *   change all callers to use new "frame" layout without 0xff
86  * change lots of occurences of "3" to use "T30_CAR_V21"
87  * rename fax1_receive() to fax1_highlevel_receive()
88  * use "fd" and not "STDIN" everywhere
89  * hand DCS frame to class1lib/fax1_parse_dcs()
90  *   -> use proper carrier values for TCF and page reception (partially untested)
91  * change "simple" frame sending to use fax1_send_simf_final()
92  * add more comments about individual fax phases
93  *
94  * Revision 4.4  2005/12/28 21:53:08  gert
95  * fix some compiler warnings and typos
96  * adapt to changed fax1_send_idframe()
97  * add CVS header
98  * add (very rough and incomplete) fax class 1 implementation, consisting
99  *  - fax1_receive() (to be called from faxrec.c)
100  *  - fax1_receive_tcf() (handle TCF training frame + responses)
101  *  - fax1_receive_page() (setup page reception, hand to fax_get_page_data())
102  *
103  */
104 
105 #ifdef CLASS1
106 
107 #include <stdio.h>
108 #include <stdlib.h>
109 #include <string.h>
110 #include <unistd.h>
111 #include <signal.h>
112 #include <fcntl.h>
113 
114 #include "mgetty.h"
115 #include "fax_lib.h"
116 #include "tio.h"
117 #include "class1.h"
118 #include "policy.h"
119 
120 enum T30_phases { Phase_A, Phase_B, Phase_C, Phase_D, Phase_E } fax1_phase;
121 
122 /* maping of "st" codes to actual time (for normal res.) */
123 static int fax_scan_times[8] = { 0, 5, 10, 10, 20, 20, 40, 40 };
124 
125 int fax1_dial_and_phase_AB _P2( (dial_cmd,fd),  char * dial_cmd, int fd )
126 {
127 char * p;			/* modem response */
128 uch framebuf[FRAMESIZE];
129 int first;
130 int len;
131 #ifdef TORTURE_TEST
132 int t_tries=0;
133 #endif
134 
135     /* send dial command */
136     if ( fax_send( dial_cmd, fd ) == ERROR )
137     {
138 	fax_hangup = TRUE; fax_hangup_code = FHUP_ERROR;
139 	return ERROR;
140     }
141 
142     /* wait for ERROR/NO CARRIER/CONNECT */
143     signal( SIGALRM, fax1_sig_alarm );
144     alarm(FAX_RESPONSE_TIMEOUT);
145 
146     while( !fax_hangup )
147     {
148         p = mdm_get_line ( fd );
149 
150 	if ( p == NULL )
151 	    { lprintf( L_ERROR, "fax1_dial: hard error dialing out" );
152 	      fax_hangup = TRUE; fax_hangup_code = FHUP_ERROR; break; }
153 
154 	lprintf( L_NOISE, "fax1_dial: string '%s'", p );
155 
156 	if ( strcmp( p, "ERROR" ) == 0 ||
157 	     strcmp( p, "NO CARRIER" ) == 0 )
158 	    { fax_hangup = TRUE; fax_hangup_code = FHUP_ERROR; break; }
159 
160 	if ( strcmp( p, "NO DIALTONE" ) == 0 ||
161 	     strcmp( p, "NO DIAL TONE" ) == 0 )
162 	    { fax_hangup = TRUE; fax_hangup_code = FHUP_NODIAL; break; }
163 
164 	if ( strcmp( p, "BUSY" ) == 0 )
165 	    { fax_hangup = TRUE; fax_hangup_code = FHUP_BUSY; break; }
166 
167         if ( strcmp( p, "CONNECT" ) == 0 )		/* gotcha! */
168 	    { break; }
169     }
170 
171     alarm(0);
172     if ( fax_hangup ) return ERROR;
173 
174     /* now start fax negotiation (receive CSI, DIS, send DCS)
175      * read all incoming frames until FINAL bit is set
176      */
177     first=TRUE;
178 again:
179     do
180     {
181 	if ( (len = fax1_receive_frame( fd, first? 0:3, 30, framebuf ) )
182 	       == ERROR )
183 	{
184 	    /*!!!! try 3 times! (flow diagram from T.30 / T30_T1 timeout) */
185 	    fax_hangup = TRUE; fax_hangup_code = 11; return ERROR;
186 	}
187 	switch ( framebuf[1] )		/* FCF */
188 	{
189 	    case T30_CSI: fax1_copy_id( framebuf ); break;
190 	    case T30_NSF: fax1_incoming_nsf( framebuf+2, len-2 ); break;
191 	    case T30_DIS: fax1_parse_dis( framebuf ); break;
192 	    case T30_DCN: fax1_send_dcn( fd, 20 ); return ERROR;
193 	    default:
194 	        lprintf( L_WARN, "unexpected frame type 0x%02x", framebuf[1] );
195 	}
196 	first=FALSE;
197     }
198     while( ( framebuf[0] & T30_FINAL ) == 0 );
199 
200 #ifdef TORTURE_TEST
201     while( ++t_tries < 3 )
202 	{ mdm_command( "AT+FRS=200", fd ); goto again; }
203 #endif
204 
205 
206     fax1_phase = Phase_B;			/* Phase A done */
207 
208     return NOERROR;
209 }
210 
211 
212 /* fax1_send_page
213  *
214  * send a page of G3 data
215  * - if phase is "B", include sending of DCS, TCF and possibly
216  *   baud rate stepdown and repeated transmission of DCS.
217  * - if phase is "C", directly send page data
218  */
219 
220 int fax1_send_page _P5( (g3_file, bytes_sent, tio, ppm, fd),
221 		        char * g3_file, int * bytes_sent, TIO * tio,
222 		        Post_page_messages ppm, int fd )
223 {
224 uch framebuf[FRAMESIZE];
225 char * line;
226 char cmd[40];
227 char dleetx[] = { DLE, ETX };
228 char rtc[] = { 0x00, 0x08, 0x80, 0x00, 0x08, 0x80, 0x00, 0x08 };
229 int pad_bytes, s_time;
230 
231     /* if we're in T.30 phase B, send DCS + training frame (TCF) now...
232      * don't forget delay (75ms +/- 20ms)!
233      *
234      * NOTE: this is not strictly "phase B" - in T.30, phase B begins
235      * after sending the DCS, and before sending TCF.  But since RTN/RTP
236      * return to sending DCS (bullet "D" in T.30 chart 5-2a), grouping it
237      * this way is much more logical to implement
238      */
239 
240     /* calculate scan line time
241      * in fine mode, some of the values get divided by 2
242      */
243     s_time = fax_scan_times[ remote_cap.st & 0x7 ];
244     if ( remote_cap.vr == 1 &&
245 	(remote_cap.st & 0x1) == 0 ) s_time /= 2;
246 
247     if ( fax1_phase == Phase_B )
248     {
249         char train[150];
250 	int i, num;
251 	int tries=0;
252 
253 retrain:			/* "(D)" in T.30/Figure 5-2a */
254 
255 	/* send local id frame (TSI) */
256 	fax1_send_idframe( fd, T30_TSI|0x01, T30_CAR_V21 );
257 
258 	/* send DCS */
259 	if ( fax1_send_dcs( fd, s_time ) == ERROR )
260 	{
261 	    fax_hangup = TRUE; fax_hangup_code = 10; return ERROR;
262 	}
263 
264 	sprintf( cmd, "AT+FTS=8;+FTM=%d", dcs_btp->c_long );
265 	fax_send( cmd, fd );
266 
267 	line = mdm_get_line( fd );
268 	if ( line != NULL && strcmp( line, cmd ) == 0 )
269 		line = mdm_get_line( fd );
270 
271 	if ( strcmp( line, "OK" ) == 0 )
272 	{
273 	    lprintf( L_MESG, "fax1_send_page: unexpected OK, re-do AT+FTM" );
274 
275 	    sprintf( cmd, "AT+FTM=%d", dcs_btp->c_long );
276 	    fax_send( cmd, fd );
277 
278 	    line = mdm_get_line( fd );
279 	    if ( line != NULL && strcmp( line, cmd ) == 0 )
280 		line = mdm_get_line( fd );
281 	}
282 
283 	if ( line == NULL || strcmp( line, "CONNECT" ) != 0 )
284 	{
285 	    lprintf( L_ERROR, "fax1_send_page: unexpected response 1: '%s'", line );
286 	    fax_hangup = TRUE; fax_hangup_code = 20; return ERROR;
287 	}
288 
289 	/* send data for training (1.5s worth) */
290 
291 	num = (dcs_btp->speed/8)*1.5;
292 	lprintf( L_NOISE, "fax1_send_page: send %d bytes training (TCF)", num );
293 	memset( train, 0, sizeof(train));
294 
295 	for( i=0; i<num; i+=sizeof(train))
296 		write( fd, train, sizeof(train) );
297 	write( fd, dleetx, 2 );
298 
299 	line = mdm_get_line( fd );
300 	if ( line == NULL || strcmp( line, "OK" ) != 0 )
301 	{
302 	    lprintf( L_ERROR, "fax1_send_page: unexpected response 2: '%s'", line );
303 	    fax_hangup = TRUE; fax_hangup_code = 20; return ERROR;
304 	}
305 
306 	/* receive frame - FTT or CFR */
307 	/*!!! return code! TODO: retry logic - T.30 fig. 5-2a/p.16 */
308 	fax1_receive_frame( fd, 3, 30, framebuf );
309 
310 	if ( ( framebuf[0] & T30_FINAL ) == 0 ||
311 	     framebuf[1] != T30_CFR )
312 	{
313 	    tries++;
314 	    lprintf( L_WARN, "fax1_send_frame: failed to train (%d)", tries);
315 
316 	    if ( tries > 1 ) fax1_reduce_max();
317 	    if ( tries < 3 ) goto retrain;
318 
319 	    /* give up */
320 	    fax1_send_dcn( fd, 27 ); return ERROR;
321 	}
322 
323 	/* phase B done, go to phase C */
324 	fax1_phase = Phase_C;
325     }
326 
327     if ( fax1_phase != Phase_C )
328     {
329         lprintf( L_ERROR, "fax1_send_page: internal error: not Phase C" );
330 	fax_hangup = TRUE; fax_hangup_code = FHUP_ERROR;
331 	return ERROR;
332     }
333 
334     /* open G3 file, read first chunk, potentially skipping digifax header
335      */
336     if ( g3_open_read( g3_file ) < 0 )
337     {
338 	/*!!! do something smart here...? */
339 	fax1_send_dcn( fd, FHUP_ERROR );
340 	return ERROR;
341     }
342 
343 
344     /* number of bytes to pad depend on scan time */
345     pad_bytes = ((dcs_btp->speed/8) * s_time + 999) / 1000;
346     lprintf( L_MESG, "scan line time: %d ms -> %d bytes/line at %d bps",
347 		s_time, pad_bytes, dcs_btp->speed );
348 
349     /* Phase C: send page data with high-speed carrier
350      */
351     sprintf( cmd, "AT+FTM=%d", dcs_btp->c_short );
352     fax_send( cmd, fd );
353 
354     line = mdm_get_line( fd );
355     if ( line != NULL && strcmp( line, cmd ) == 0 )
356 	    line = mdm_get_line( fd );
357 
358     if ( line == NULL || strcmp( line, "CONNECT" ) != 0 )
359     {
360 	lprintf( L_ERROR, "fax1_send_page: unexpected response 3: '%s'", line );
361 	fax_hangup = TRUE; fax_hangup_code = 40; return ERROR;
362     }
363 
364     lprintf( L_NOISE, "send page data (\"%s\")...", g3_file );
365 
366     /* turn on xon/xoff flow control now, for page data sending
367      */
368     if ( (FAXSEND_FLOW) & FLOW_SOFT )
369     {
370 	tio_set_flow_control( fd, tio, (FAXSEND_FLOW) & (FLOW_HARD|FLOW_XON_OUT));
371 	tio_set( fd, tio );
372     }
373 
374     /* read page data from file, invert byte order,
375      * insert padding bits (if scan line time > 0),
376      * at end-of-file, add RTC
377      */
378     if ( g3_send_file( g3_rf_chunk, fd, TRUE, TRUE, pad_bytes, 0 /*TODO!*/) < 0 )
379     {
380 	lprintf( L_ERROR, "error in g3_send_file()" );
381 	return ERROR;
382     }
383 
384     /*!!! ERROR HANDLING!! */
385     /*!!! PARANOIA: alarm()!! */
386     /* end of page: RTC */
387     write( fd, rtc, sizeof(rtc) );
388 
389     /* end of data: DLE ETX */
390     write( fd, dleetx, 2 );
391 
392     line = mdm_get_line( fd );
393     if ( line == NULL || strcmp( line, "OK" ) != 0 )
394     {
395 	lprintf( L_ERROR, "fax1_send_page: unexpected response 3a: '%s'", line );
396 	fax_hangup = TRUE; fax_hangup_code = 40; return ERROR;
397     }
398 
399     /* turn off xon/xoff flow control (will interfere with received frames) */
400     if ( (FAXSEND_FLOW) & FLOW_SOFT )
401     {
402 	tio_set_flow_control( fd, tio, (FAXSEND_FLOW) & FLOW_HARD );
403 	tio_set( fd, tio );
404     }
405 
406     /* now send end-of-page frame (MPS/EOM/EOP) and get pps */
407 
408     fax1_phase = Phase_D;
409     lprintf( L_MESG, "page data sent, sending end-of-page frame (C->D)" );
410     sprintf( cmd, "AT+FTS=8;+FTH=3" );
411     fax_send( cmd, fd );
412 
413     line = mdm_get_line( fd );
414     if ( line != NULL && strcmp( line, cmd ) == 0 )
415 	    line = mdm_get_line( fd );
416 
417     if ( line == NULL || strcmp( line, "CONNECT" ) != 0 )
418     {
419         if ( strcmp( line, "OK" ) == 0 ) goto tryanyway;
420 	lprintf( L_ERROR, "fax1_send_page: unexpected response 4: '%s'", line );
421 	fax_hangup = TRUE; fax_hangup_code = 50; return ERROR;
422     }
423 
424     /* some modems seemingly can't handle AT+FTS=8;+FTH=3 (returning
425      * "OK" instead of "CONNECT"), so send AT+FTH=3 again for those.
426      */
427 tryanyway:
428 
429     framebuf[0] = 0x03 | T30_FINAL;
430     switch( ppm )
431     {
432         case pp_eom: framebuf[1] = T30_EOM | fax1_dis; break;
433 	case pp_eop: framebuf[1] = T30_EOP | fax1_dis; break;
434 	case pp_mps: framebuf[1] = T30_MPS | fax1_dis; break;
435 	default:
436 	   lprintf( L_WARN, "fax1_send_page: canthappen(1) - PRI not supported" );
437     }
438 
439     if ( strcmp( line, "OK" ) == 0 )	/* re-send AT+FTH=3 */
440     {
441         fax1_send_frame( fd, T30_CAR_V21, framebuf, 2 );
442     }
443     else				/* it got sent & acked */
444     {
445         fax1_send_frame( fd, T30_CAR_HAVE_V21, framebuf, 2 );
446     }
447 
448     /* get MPS/RTP/RTN code */
449     fax1_receive_frame( fd, T30_CAR_V21, 30, framebuf );
450 
451     /*!!! T.30 flow chart... */
452 
453     switch( framebuf[1] )
454     {
455         case T30_MCF:		/* page good */
456 		fax_page_tx_status = 1; fax1_phase = Phase_C; break;
457 	case T30_RTN:		/* retrain / negative */
458 		fax_page_tx_status = 2; fax1_phase = Phase_B; break;
459 	case T30_RTP:		/* retrain / positive */
460 		fax_page_tx_status = 3; fax1_phase = Phase_B; break;
461 	case T30_PIN:		/* procedure interrupt */
462 		fax_page_tx_status = 4; fax1_phase = Phase_B; break;
463 	case T30_PIP:
464 		fax_page_tx_status = 5; fax1_phase = Phase_C; break;
465 	default:
466 		lprintf( L_ERROR, "fax1_transmit_page: unexpected frame" );
467 		fax1_send_dcn(fd, 53); break;
468     }
469 
470     /* if this was the last page, and the receiver is happy
471      * (MCF or RTP), send DCN, and call it quits
472      */
473     if ( ppm == pp_eop &&
474 	 ( fax_page_tx_status == 1 || fax_page_tx_status == 3 ||
475 	   fax_page_tx_status == 5 ) )
476     {
477 	fax1_send_dcn( fd, 0 );
478 	fax1_phase = Phase_E;
479     }
480 
481     /* otherwise, nothing to do - caller will re-enter fax1_send_page(),
482      * for next page / re-send of same page (we won't know)
483      */
484     return NOERROR;
485 }
486 
487 boolean fax1_receive_have_connect = FALSE;
488 
489 int fax1_receive_tcf _PROTO((int fd, int carrier, int wantbytes));
490 int fax1_receive_page _PROTO((int fd, int carrier, int * pagenum,
491 			      char * dirlist, int uid, int gid, int mode ));
492 
493 int fax1_highlevel_receive _P6( (fd, pagenum, dirlist, uid, gid, mode ),
494 			       int fd, int * pagenum, char * dirlist,
495 			       int uid, int gid, int mode)
496 {
497 int rc;
498 uch frame[FRAMESIZE];
499 char * p;
500 Post_page_messages ppm = pp_mps;
501 boolean first = TRUE;
502 int tries;
503 boolean have_dcs;
504 
505     /* after ATA/CONNECT, first AT+FTH=3 is implicit -> send frames
506        right away (first=TRUE) - when coming back to phase B after EOM,
507        AT+FTH=3 must be sent */
508 
509     /* with +FAE=1, the sequence seems to be
510      *  RING
511      *     ATA
512      *  FAX
513      *  CONNECT
514      */
515 
516     if ( !fax1_receive_have_connect )
517     {
518 	alarm(10);
519 	p = mdm_get_line( fd );
520 	alarm(0);
521 
522 	if ( p == NULL || strcmp( p, "CONNECT" ) != 0 )
523 	{
524 	    lprintf( L_WARN, "fax1_receive: initial CONNECT not seen" );
525 	    fax_hangup = TRUE; fax_hangup_code = FHUP_TIMEOUT;
526 	    return ERROR;
527 	}
528     }
529 
530     *pagenum = 0;
531 
532     /* phase B: Fax negotiations
533      */
534     tries=0; have_dcs=FALSE;
535 
536 receive_phase_b:
537     lprintf( L_MESG, "fax1 T.30 receive phase B (try %d)", tries+1 );
538 
539     /* send NSF frame (if requested) */
540     if ( modem_quirks & MQ_SHOW_NSF )
541     {
542 	rc = fax1_send_nsf( fd, first?T30_CAR_HAVE_V21: T30_CAR_V21 );
543     }
544 
545     /* send local ID frame (CSI) - non-final */
546     rc = fax1_send_idframe( fd, T30_CSI, first?T30_CAR_HAVE_V21: T30_CAR_V21 );
547     first = FALSE;
548 
549     /* send DIS (but only if we haven't seen an error sending CSI) */
550     if ( rc == NOERROR )
551         rc = fax1_send_dis( fd );
552 
553     /* now see what the other side has to say... */
554 wait_for_dcs:
555 
556     do
557     {
558         if ( fax1_receive_frame( fd, T30_CAR_V21, 30, frame ) == ERROR )
559 	{
560 	    if ( ++tries < 3 ) goto receive_phase_b;
561 	    fax1_send_dcn( fd, 70 );
562 	    return ERROR;
563 	}
564 	switch( frame[1] & 0xfe )		/* FCF, ignoring X-bit */
565 	{
566 	    case T30_TSI: fax1_copy_id( frame ); break;
567 	    case T30_NSF: break;
568 	    case T30_DCS: fax1_parse_dcs( frame ); have_dcs=TRUE; break;
569 	    case T30_DCN: fax1_send_dcn( fd, 70 );
570 			  return ERROR; break;
571 	    default:
572 		lprintf( L_WARN, "unexpected frame type 0x%02x", frame[1] );
573 	}
574     }
575     while( ( frame[0] & T30_FINAL ) == 0 );
576 
577     if ( !have_dcs )
578     {
579 	lprintf( L_WARN, "T.30 B: final frame, but no DCS seen, re-send DIS" );
580 	if ( ++tries < 3 ) goto receive_phase_b;
581 	fax1_send_dcn( fd, 70 );
582 	return ERROR;
583     }
584 
585     /* fax1_parse_dcs() has setup dcs_btp and fax_par_d for us */
586 
587     /* receive 1.5s training sequence */
588     rc = fax1_receive_tcf( fd, dcs_btp->c_long, (dcs_btp->speed/8)*1.5 );
589 
590     /* error receiving TCF ("no carrier seen") -> redo DIS/DCS */
591     if ( rc < 0 )
592 	goto receive_phase_b;
593 
594     /* TCF bad? send FTT (failure to train), wait for next DCS */
595     if ( rc == 0 )
596     {
597 	rc = fax1_send_simf_final( fd, T30_CAR_V21, T30_FTT );
598 	if ( ++tries < 10 ) goto wait_for_dcs;
599 	fax1_send_dcn( fd, 73 );
600 	return ERROR;
601     }
602 
603     /* TCF good, send CFR frame (confirmation to receive) */
604     rc = fax1_send_simf_final( fd, T30_CAR_V21, T30_CFR );
605 
606 receive_next_page:
607 
608     /* phase C: start page reception & get page data
609      */
610     lprintf( L_MESG, "fax1 T.30 receive phase C" );
611 
612     rc = fax1_receive_page( fd, dcs_btp->c_short, pagenum,
613 			    dirlist, uid, gid, mode );
614 
615     /* if we have already hung up, not worth doing any retries etc.
616      */
617     if ( rc == ERROR && fax_hangup ) return ERROR;
618 
619     /* phase D: post-message status
620      * switch back to low-speed carrier, get (PRI-)EOM/MPS/EOP code
621      */
622 
623     tries=0;
624 receive_phase_d:
625     lprintf( L_MESG, "fax1 T.30 receive phase D" );
626 
627     /* TODO: T.30 flow chart: will we ever hit non-final frames here?
628      * what to do on error?
629      */
630     do
631     {
632         if ( fax1_receive_frame( fd, T30_CAR_V21, 30, frame ) == ERROR )
633 	{
634 	    /* retry post-page handshake 3 times, then give up */
635 	    if ( ++tries < 3 ) goto receive_phase_d;
636 	    fax1_send_dcn( fd, 100 );
637 	    return ERROR;
638 	}
639 	switch( frame[1] & 0xfe & ~T30_PRI )	/* FCF, ignoring X-bit */
640 	{
641 	    case T30_MPS:
642 	        lprintf( L_MESG, "MPS: end of page, more to come" ); ppm = pp_mps;
643 	        break;
644 	    case T30_EOM:
645 		lprintf( L_MESG, "EOM: back to phase B" ); ppm = pp_eom;
646 		break;
647 	    case T30_EOP:
648 		lprintf( L_MESG, "EOP: end of transmission" );
649 		ppm = pp_eop;
650 		break;
651 	    case T30_DCN:
652 		fax1_send_dcn( fd, 101 );
653 	        return ERROR;
654 		break;
655 	    default:
656 		lprintf( L_WARN, "unexpected frame type 0x%02x", frame[1] );
657 	}
658     }
659     while( ( frame[0] & T30_FINAL ) == 0 );
660 
661     /* send back page good/bad return code (TODO: RTN/RTP codes) */
662     /* TODO: for RTN/RTP, restart training sequence (TCF) (??) */
663     rc = fax1_send_simf_final( fd, T30_CAR_V21, T30_MCF );
664 
665     /* go back to phase B (EOM), go to next page (MPS), done (EOP) */
666     if ( ppm == pp_eom )
667 	{ goto receive_phase_b; }
668     if ( ppm == pp_mps )
669 	{ goto receive_next_page; }
670 
671     /* EOP - get goodbye frame (DCN) from remote end, hang up */
672     fax1_receive_frame( fd, T30_CAR_V21, 30, frame );
673 
674     if ( (frame[1] & 0xfe) != T30_DCN )
675     {
676 	lprintf( L_WARN, "fax1_receive: unexpected frame 0x%02x 0x%02x after EOP", frame[0], frame[1] );
677     }
678 
679     fax_hangup = TRUE;
680     fax_hangup_code = 0;
681     return NOERROR;
682 }
683 
684 int fax1_receive_tcf _P3((fd,carrier,wantbytes),
685 			  int fd, int carrier, int wantbytes)
686 {
687 int rc, count, notnull;
688 char c, *p;
689 boolean wasDLE=FALSE;
690 int tries;
691 
692     tries=0;
693 
694     lprintf( L_NOISE, "fax1_r_tcf: carrier=%d", carrier );
695 
696 get_carrier:
697     rc = fax1_init_FRM( fd, carrier );
698     if ( rc == ERROR )
699     {
700 	while( ++tries<3 ) goto get_carrier;
701 	return ERROR;
702     }
703 
704     /* TODO: proper timeout settings as per T.30 (?) */
705     alarm(5);
706     count = notnull = 0;
707 
708     lprintf( L_JUNK, "fax1_r_tcf: got: " );
709     while(1)
710     {
711 	if ( mdm_read_byte( fd, &c ) != 1 )
712 	{
713 	    /* timeout? corrupted DLE/ETX?  let caller send FTT and retry */
714 	    lprintf( L_ERROR, "fax1_r_tcf: cannot read byte, return" );
715 	    return 0;
716 	}
717 	if ( c != 0 ) lputc( L_JUNK, c );
718 
719 	if ( wasDLE )
720 	{
721 	    if ( c == ETX ) break;
722 	    wasDLE = 0;
723 	}
724 	if ( c == DLE ) { wasDLE = 1; continue; }
725 
726 	count++;
727 	if ( c != 0 ) notnull++;
728     }
729 
730     /* read post-frame "NO CARRIER" message */
731     p = mdm_get_line( fd );
732     alarm(0);
733     if ( p == NULL || strcmp( p, "NO CARRIER" ) != 0 )
734 	lprintf( L_WARN, "unexpected post-TCF modem response: '%s'", p );
735 
736     if ( count < (wantbytes*3)/4 ||		/* not enough bytes */
737 	 notnull > count/10  )			/* or too many errors */
738     {
739 	lprintf( L_NOISE, "TCF: want %d, got %d, %d non-null -> retry",
740 		 wantbytes, count, notnull );
741 	return 0;				/* try again */
742     }
743 
744     lprintf( L_NOISE, "TCF: want %d, got %d, %d non-null -> OK",
745 	     wantbytes, count, notnull );
746     return 1;					/* acceptable, go ahead */
747 }
748 
749 int fax1_receive_page _P7( (fd,carrier,pagenum,dirlist,uid,gid,mode),
750 				int fd, int carrier,
751 				int * pagenum, char * dirlist,
752 				int uid, int gid, int mode )
753 {
754 int rc;
755 char *p;
756 int tries;
757 
758 char directory[MAXPATH];
759 
760     fax_find_directory( dirlist, directory, sizeof(directory) );
761 
762     tries=0;
763 
764     lprintf( L_NOISE, "fax1_rp: carrier=%d", carrier );
765 
766 get_carrier:
767     /* TODO: proper timeout settings as per T.30 */
768     alarm(10);
769     rc = fax1_init_FRM( fd, carrier );
770     alarm(0);
771 
772     if ( rc == ERROR )
773     {
774 	if ( ++tries < 3 ) goto get_carrier;
775 	fax1_send_dcn( fd, 90 );
776 	return ERROR;
777     }
778 
779     /* now get page data (common function for class 1 and class 2)
780      * note: fax_get_page_data() has its own alarm/timeout handling
781      */
782     rc = fax_get_page_data( fd, ++(*pagenum), directory, uid, gid, mode );
783 
784     /* read post-page "NO CARRIER" message */
785     alarm(10);
786     p = mdm_get_line( fd );
787     alarm(0);
788     if ( p == NULL || strcmp( p, "NO CARRIER" ) != 0 )
789 	lprintf( L_WARN, "unexpected post-page modem response: '%s'", p );
790 
791     if ( rc == ERROR )
792 	{ fax1_send_dcn( fd, 90 ); return ERROR; }
793 
794     /* TODO: copy quality checking */
795 
796     return NOERROR;
797 }
798 
799 #endif /* CLASS 1 */
800