comparison spandsp-0.0.6pre17/src/fax.c @ 4:26cd8f1ef0b1

import spandsp-0.0.6pre17
author Peter Meerwald <pmeerw@cosy.sbg.ac.at>
date Fri, 25 Jun 2010 15:50:58 +0200
parents
children
comparison
equal deleted inserted replaced
3:c6c5a16ce2f2 4:26cd8f1ef0b1
1 //#define LOG_FAX_AUDIO
2 /*
3 * SpanDSP - a series of DSP components for telephony
4 *
5 * fax.c - Analogue line ITU T.30 FAX transfer processing
6 *
7 * Written by Steve Underwood <steveu@coppice.org>
8 *
9 * Copyright (C) 2003, 2005, 2006 Steve Underwood
10 *
11 * All rights reserved.
12 *
13 * This program is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU Lesser General Public License version 2.1,
15 * as published by the Free Software Foundation.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU Lesser General Public License for more details.
21 *
22 * You should have received a copy of the GNU Lesser General Public
23 * License along with this program; if not, write to the Free Software
24 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
25 *
26 * $Id: fax.c,v 1.96.4.1 2009/12/19 10:44:10 steveu Exp $
27 */
28
29 /*! \file */
30
31 #if defined(HAVE_CONFIG_H)
32 #include "config.h"
33 #endif
34
35 #include <inttypes.h>
36 #include <stdlib.h>
37 #include <stdio.h>
38 #include <string.h>
39 #if defined(HAVE_TGMATH_H)
40 #include <tgmath.h>
41 #endif
42 #if defined(HAVE_MATH_H)
43 #include <math.h>
44 #endif
45 #include "floating_fudge.h"
46 #include <assert.h>
47 #include <fcntl.h>
48 #include <time.h>
49 #if defined(LOG_FAX_AUDIO)
50 #include <unistd.h>
51 #endif
52 #include <tiffio.h>
53
54 #include "spandsp/telephony.h"
55 #include "spandsp/logging.h"
56 #include "spandsp/queue.h"
57 #include "spandsp/dc_restore.h"
58 #include "spandsp/power_meter.h"
59 #include "spandsp/complex.h"
60 #include "spandsp/tone_detect.h"
61 #include "spandsp/tone_generate.h"
62 #include "spandsp/async.h"
63 #include "spandsp/hdlc.h"
64 #include "spandsp/silence_gen.h"
65 #include "spandsp/fsk.h"
66 #include "spandsp/v29tx.h"
67 #include "spandsp/v29rx.h"
68 #include "spandsp/v27ter_tx.h"
69 #include "spandsp/v27ter_rx.h"
70 #include "spandsp/v17tx.h"
71 #include "spandsp/v17rx.h"
72 #include "spandsp/super_tone_rx.h"
73 #include "spandsp/modem_connect_tones.h"
74 #include "spandsp/t4_rx.h"
75 #include "spandsp/t4_tx.h"
76
77 #include "spandsp/t30_fcf.h"
78 #include "spandsp/t35.h"
79 #include "spandsp/t30.h"
80 #include "spandsp/t30_api.h"
81 #include "spandsp/t30_logging.h"
82
83 #include "spandsp/fax_modems.h"
84 #include "spandsp/fax.h"
85
86 #include "spandsp/private/logging.h"
87 #include "spandsp/private/silence_gen.h"
88 #include "spandsp/private/fsk.h"
89 #include "spandsp/private/v17tx.h"
90 #include "spandsp/private/v17rx.h"
91 #include "spandsp/private/v27ter_tx.h"
92 #include "spandsp/private/v27ter_rx.h"
93 #include "spandsp/private/v29tx.h"
94 #include "spandsp/private/v29rx.h"
95 #include "spandsp/private/modem_connect_tones.h"
96 #include "spandsp/private/hdlc.h"
97 #include "spandsp/private/fax_modems.h"
98 #include "spandsp/private/t4_rx.h"
99 #include "spandsp/private/t4_tx.h"
100 #include "spandsp/private/t30.h"
101 #include "spandsp/private/fax.h"
102
103 #define HDLC_FRAMING_OK_THRESHOLD 8
104
105 static void fax_send_hdlc(void *user_data, const uint8_t *msg, int len)
106 {
107 fax_state_t *s;
108
109 s = (fax_state_t *) user_data;
110
111 hdlc_tx_frame(&s->modems.hdlc_tx, msg, len);
112 }
113 /*- End of function --------------------------------------------------------*/
114
115 static void tone_detected(void *user_data, int tone, int level, int delay)
116 {
117 t30_state_t *s;
118
119 s = (t30_state_t *) user_data;
120 span_log(&s->logging, SPAN_LOG_FLOW, "%s detected (%ddBm0)\n", modem_connect_tone_to_str(tone), level);
121 }
122 /*- End of function --------------------------------------------------------*/
123
124 static void hdlc_underflow_handler(void *user_data)
125 {
126 t30_state_t *s;
127
128 s = (t30_state_t *) user_data;
129 t30_front_end_status(s, T30_FRONT_END_SEND_STEP_COMPLETE);
130 }
131 /*- End of function --------------------------------------------------------*/
132
133 static void set_rx_handler(fax_state_t *s,
134 span_rx_handler_t *rx_handler,
135 span_rx_fillin_handler_t *fillin_handler,
136 void *user_data)
137 {
138 s->modems.rx_handler = rx_handler;
139 s->modems.rx_fillin_handler = fillin_handler;
140 s->modems.rx_user_data = user_data;
141 }
142 /*- End of function --------------------------------------------------------*/
143
144 static void set_tx_handler(fax_state_t *s, span_tx_handler_t *handler, void *user_data)
145 {
146 s->modems.tx_handler = handler;
147 s->modems.tx_user_data = user_data;
148 }
149 /*- End of function --------------------------------------------------------*/
150
151 static void set_next_tx_handler(fax_state_t *s, span_tx_handler_t *handler, void *user_data)
152 {
153 s->modems.next_tx_handler = handler;
154 s->modems.next_tx_user_data = user_data;
155 }
156 /*- End of function --------------------------------------------------------*/
157
158 static int v17_v21_rx(void *user_data, const int16_t amp[], int len)
159 {
160 fax_state_t *t;
161 fax_modems_state_t *s;
162
163 t = (fax_state_t *) user_data;
164 s = &t->modems;
165 v17_rx(&s->v17_rx, amp, len);
166 if (t->t30.rx_trained)
167 {
168 /* The fast modem has trained, so we no longer need to run the slow
169 one in parallel. */
170 span_log(&t->logging, SPAN_LOG_FLOW, "Switching from V.17 + V.21 to V.17 (%.2fdBm0)\n", v17_rx_signal_power(&s->v17_rx));
171 set_rx_handler(t, (span_rx_handler_t *) &v17_rx, (span_rx_fillin_handler_t *) &v17_rx_fillin, &s->v17_rx);
172 }
173 else
174 {
175 fsk_rx(&s->v21_rx, amp, len);
176 if (t->t30.rx_frame_received)
177 {
178 /* We have received something, and the fast modem has not trained. We must
179 be receiving valid V.21 */
180 span_log(&t->logging, SPAN_LOG_FLOW, "Switching from V.17 + V.21 to V.21 (%.2fdBm0)\n", fsk_rx_signal_power(&s->v21_rx));
181 set_rx_handler(t, (span_rx_handler_t *) &fsk_rx, (span_rx_fillin_handler_t *) &fsk_rx_fillin, &s->v21_rx);
182 }
183 }
184 return 0;
185 }
186 /*- End of function --------------------------------------------------------*/
187
188 static int v17_v21_rx_fillin(void *user_data, int len)
189 {
190 fax_state_t *t;
191 fax_modems_state_t *s;
192
193 t = (fax_state_t *) user_data;
194 s = &t->modems;
195 v17_rx_fillin(&s->v17_rx, len);
196 fsk_rx_fillin(&s->v21_rx, len);
197 return 0;
198 }
199 /*- End of function --------------------------------------------------------*/
200
201 static int v27ter_v21_rx(void *user_data, const int16_t amp[], int len)
202 {
203 fax_state_t *t;
204 fax_modems_state_t *s;
205
206 t = (fax_state_t *) user_data;
207 s = &t->modems;
208 v27ter_rx(&s->v27ter_rx, amp, len);
209 if (t->t30.rx_trained)
210 {
211 /* The fast modem has trained, so we no longer need to run the slow
212 one in parallel. */
213 span_log(&t->logging, SPAN_LOG_FLOW, "Switching from V.27ter + V.21 to V.27ter (%.2fdBm0)\n", v27ter_rx_signal_power(&s->v27ter_rx));
214 set_rx_handler(t, (span_rx_handler_t *) &v27ter_rx, (span_rx_fillin_handler_t *) &v27ter_rx_fillin, &s->v27ter_rx);
215 }
216 else
217 {
218 fsk_rx(&s->v21_rx, amp, len);
219 if (t->t30.rx_frame_received)
220 {
221 /* We have received something, and the fast modem has not trained. We must
222 be receiving valid V.21 */
223 span_log(&s->logging, SPAN_LOG_FLOW, "Switching from V.27ter + V.21 to V.21 (%.2fdBm0)\n", fsk_rx_signal_power(&s->v21_rx));
224 set_rx_handler(t, (span_rx_handler_t *) &fsk_rx, (span_rx_fillin_handler_t *) &fsk_rx_fillin, &s->v21_rx);
225 }
226 }
227 return 0;
228 }
229 /*- End of function --------------------------------------------------------*/
230
231 static int v27ter_v21_rx_fillin(void *user_data, int len)
232 {
233 fax_state_t *t;
234 fax_modems_state_t *s;
235
236 t = (fax_state_t *) user_data;
237 s = &t->modems;
238 v27ter_rx_fillin(&s->v27ter_rx, len);
239 fsk_rx_fillin(&s->v21_rx, len);
240 return 0;
241 }
242 /*- End of function --------------------------------------------------------*/
243
244 static int v29_v21_rx(void *user_data, const int16_t amp[], int len)
245 {
246 fax_state_t *t;
247 fax_modems_state_t *s;
248
249 t = (fax_state_t *) user_data;
250 s = &t->modems;
251 v29_rx(&s->v29_rx, amp, len);
252 if (t->t30.rx_trained)
253 {
254 /* The fast modem has trained, so we no longer need to run the slow
255 one in parallel. */
256 span_log(&t->logging, SPAN_LOG_FLOW, "Switching from V.29 + V.21 to V.29 (%.2fdBm0)\n", v29_rx_signal_power(&s->v29_rx));
257 set_rx_handler(t, (span_rx_handler_t *) &v29_rx, (span_rx_fillin_handler_t *) &v29_rx_fillin, &s->v29_rx);
258 }
259 else
260 {
261 fsk_rx(&s->v21_rx, amp, len);
262 if (t->t30.rx_frame_received)
263 {
264 /* We have received something, and the fast modem has not trained. We must
265 be receiving valid V.21 */
266 span_log(&t->logging, SPAN_LOG_FLOW, "Switching from V.29 + V.21 to V.21 (%.2fdBm0)\n", fsk_rx_signal_power(&s->v21_rx));
267 set_rx_handler(t, (span_rx_handler_t *) &fsk_rx, (span_rx_fillin_handler_t *) &fsk_rx_fillin, &s->v21_rx);
268 }
269 }
270 return 0;
271 }
272 /*- End of function --------------------------------------------------------*/
273
274 static int v29_v21_rx_fillin(void *user_data, int len)
275 {
276 fax_state_t *t;
277 fax_modems_state_t *s;
278
279 t = (fax_state_t *) user_data;
280 s = &t->modems;
281 v29_rx_fillin(&s->v29_rx, len);
282 fsk_rx_fillin(&s->v21_rx, len);
283 return 0;
284 }
285 /*- End of function --------------------------------------------------------*/
286
287 SPAN_DECLARE(int) fax_rx(fax_state_t *s, int16_t *amp, int len)
288 {
289 int i;
290
291 #if defined(LOG_FAX_AUDIO)
292 if (s->modems.audio_rx_log >= 0)
293 write(s->modems.audio_rx_log, amp, len*sizeof(int16_t));
294 #endif
295 for (i = 0; i < len; i++)
296 amp[i] = dc_restore(&s->modems.dc_restore, amp[i]);
297 s->modems.rx_handler(s->modems.rx_user_data, amp, len);
298 t30_timer_update(&s->t30, len);
299 return 0;
300 }
301 /*- End of function --------------------------------------------------------*/
302
303 SPAN_DECLARE(int) fax_rx_fillin(fax_state_t *s, int len)
304 {
305 /* To mitigate the effect of lost packets on a packet network we should
306 try to sustain the status quo. If there is no receive modem running, keep
307 things that way. If there is a receive modem running, try to sustain its
308 operation, without causing a phase hop, or letting its adaptive functions
309 diverge. */
310 #if defined(LOG_FAX_AUDIO)
311 if (s->modems.audio_rx_log >= 0)
312 {
313 int i;
314 #if defined(_MSC_VER)
315 int16_t *amp = (int16_t *) _alloca(sizeof(int16_t)*len);
316 #else
317 int16_t amp[len];
318 #endif
319
320 vec_zeroi16(amp, len);
321 write(s->modems.audio_rx_log, amp, len*sizeof(int16_t));
322 }
323 #endif
324 /* Call the fillin function of the current modem (if there is one). */
325 s->modems.rx_fillin_handler(s->modems.rx_user_data, len);
326 t30_timer_update(&s->t30, len);
327 return len;
328 }
329 /*- End of function --------------------------------------------------------*/
330
331 static int set_next_tx_type(fax_state_t *s)
332 {
333 fax_modems_state_t *t;
334
335 t = &s->modems;
336 if (t->next_tx_handler)
337 {
338 set_tx_handler(s, t->next_tx_handler, t->next_tx_user_data);
339 t->next_tx_handler = NULL;
340 return 0;
341 }
342 /* If there is nothing else to change to, so use zero length silence */
343 silence_gen_alter(&t->silence_gen, 0);
344 set_tx_handler(s, (span_tx_handler_t *) &silence_gen, &t->silence_gen);
345 set_next_tx_handler(s, (span_tx_handler_t *) NULL, NULL);
346 t->transmit = FALSE;
347 return -1;
348 }
349 /*- End of function --------------------------------------------------------*/
350
351 SPAN_DECLARE(int) fax_tx(fax_state_t *s, int16_t *amp, int max_len)
352 {
353 int len;
354 #if defined(LOG_FAX_AUDIO)
355 int required_len;
356
357 required_len = max_len;
358 #endif
359 len = 0;
360 if (s->modems.transmit)
361 {
362 while ((len += s->modems.tx_handler(s->modems.tx_user_data, amp + len, max_len - len)) < max_len)
363 {
364 /* Allow for a change of tx handler within a block */
365 if (set_next_tx_type(s) && s->modems.current_tx_type != T30_MODEM_NONE && s->modems.current_tx_type != T30_MODEM_DONE)
366 t30_front_end_status(&s->t30, T30_FRONT_END_SEND_STEP_COMPLETE);
367 if (!s->modems.transmit)
368 {
369 if (s->modems.transmit_on_idle)
370 {
371 /* Pad to the requested length with silence */
372 memset(amp + len, 0, (max_len - len)*sizeof(int16_t));
373 len = max_len;
374 }
375 break;
376 }
377 }
378 }
379 else
380 {
381 if (s->modems.transmit_on_idle)
382 {
383 /* Pad to the requested length with silence */
384 memset(amp, 0, max_len*sizeof(int16_t));
385 len = max_len;
386 }
387 }
388 #if defined(LOG_FAX_AUDIO)
389 if (s->modems.audio_tx_log >= 0)
390 {
391 if (len < required_len)
392 memset(amp + len, 0, (required_len - len)*sizeof(int16_t));
393 write(s->modems.audio_tx_log, amp, required_len*sizeof(int16_t));
394 }
395 #endif
396 return len;
397 }
398 /*- End of function --------------------------------------------------------*/
399
400 static void fax_set_rx_type(void *user_data, int type, int bit_rate, int short_train, int use_hdlc)
401 {
402 fax_state_t *s;
403 put_bit_func_t put_bit_func;
404 void *put_bit_user_data;
405 fax_modems_state_t *t;
406
407 s = (fax_state_t *) user_data;
408 t = &s->modems;
409 span_log(&s->logging, SPAN_LOG_FLOW, "Set rx type %d\n", type);
410 if (t->current_rx_type == type)
411 return;
412 t->current_rx_type = type;
413 t->rx_bit_rate = bit_rate;
414 if (use_hdlc)
415 {
416 put_bit_func = (put_bit_func_t) hdlc_rx_put_bit;
417 put_bit_user_data = (void *) &t->hdlc_rx;
418 hdlc_rx_init(&t->hdlc_rx, FALSE, TRUE, HDLC_FRAMING_OK_THRESHOLD, t30_hdlc_accept, &s->t30);
419 }
420 else
421 {
422 put_bit_func = t30_non_ecm_put_bit;
423 put_bit_user_data = (void *) &s->t30;
424 }
425 switch (type)
426 {
427 case T30_MODEM_V21:
428 fsk_rx_init(&t->v21_rx, &preset_fsk_specs[FSK_V21CH2], FSK_FRAME_MODE_SYNC, (put_bit_func_t) hdlc_rx_put_bit, put_bit_user_data);
429 fsk_rx_signal_cutoff(&t->v21_rx, -45.5f);
430 set_rx_handler(s, (span_rx_handler_t *) &fsk_rx, (span_rx_fillin_handler_t *) &fsk_rx_fillin, &t->v21_rx);
431 break;
432 case T30_MODEM_V27TER:
433 v27ter_rx_restart(&t->v27ter_rx, bit_rate, FALSE);
434 v27ter_rx_set_put_bit(&t->v27ter_rx, put_bit_func, put_bit_user_data);
435 set_rx_handler(s, &v27ter_v21_rx, &v27ter_v21_rx_fillin, s);
436 break;
437 case T30_MODEM_V29:
438 v29_rx_restart(&t->v29_rx, bit_rate, FALSE);
439 v29_rx_set_put_bit(&t->v29_rx, put_bit_func, put_bit_user_data);
440 set_rx_handler(s, &v29_v21_rx, &v29_v21_rx_fillin, s);
441 break;
442 case T30_MODEM_V17:
443 v17_rx_restart(&t->v17_rx, bit_rate, short_train);
444 v17_rx_set_put_bit(&t->v17_rx, put_bit_func, put_bit_user_data);
445 set_rx_handler(s, &v17_v21_rx, &v17_v21_rx_fillin, s);
446 break;
447 case T30_MODEM_DONE:
448 span_log(&s->logging, SPAN_LOG_FLOW, "FAX exchange complete\n");
449 default:
450 set_rx_handler(s, (span_rx_handler_t *) &span_dummy_rx, (span_rx_fillin_handler_t *) &span_dummy_rx_fillin, s);
451 break;
452 }
453 }
454 /*- End of function --------------------------------------------------------*/
455
456 static void fax_set_tx_type(void *user_data, int type, int bit_rate, int short_train, int use_hdlc)
457 {
458 fax_state_t *s;
459 get_bit_func_t get_bit_func;
460 void *get_bit_user_data;
461 fax_modems_state_t *t;
462 int tone;
463
464 s = (fax_state_t *) user_data;
465 t = &s->modems;
466 span_log(&s->logging, SPAN_LOG_FLOW, "Set tx type %d\n", type);
467 if (t->current_tx_type == type)
468 return;
469 if (use_hdlc)
470 {
471 get_bit_func = (get_bit_func_t) hdlc_tx_get_bit;
472 get_bit_user_data = (void *) &t->hdlc_tx;
473 }
474 else
475 {
476 get_bit_func = t30_non_ecm_get_bit;
477 get_bit_user_data = (void *) &s->t30;
478 }
479 switch (type)
480 {
481 case T30_MODEM_PAUSE:
482 silence_gen_alter(&t->silence_gen, ms_to_samples(short_train));
483 set_tx_handler(s, (span_tx_handler_t *) &silence_gen, &t->silence_gen);
484 set_next_tx_handler(s, (span_tx_handler_t *) NULL, NULL);
485 t->transmit = TRUE;
486 break;
487 case T30_MODEM_CED:
488 case T30_MODEM_CNG:
489 if (type == T30_MODEM_CED)
490 tone = MODEM_CONNECT_TONES_FAX_CED;
491 else
492 tone = MODEM_CONNECT_TONES_FAX_CNG;
493 modem_connect_tones_tx_init(&t->connect_tx, tone);
494 set_tx_handler(s, (span_tx_handler_t *) &modem_connect_tones_tx, &t->connect_tx);
495 set_next_tx_handler(s, (span_tx_handler_t *) NULL, NULL);
496 t->transmit = TRUE;
497 break;
498 case T30_MODEM_V21:
499 fsk_tx_init(&t->v21_tx, &preset_fsk_specs[FSK_V21CH2], get_bit_func, get_bit_user_data);
500 /* The spec says 1s +-15% of preamble. So, the minimum is 32 octets. */
501 hdlc_tx_flags(&t->hdlc_tx, 32);
502 /* Pause before switching from phase C, as per T.30 5.3.2.2. If we omit this, the receiver
503 might not see the carrier fall between the high speed and low speed sections. In practice,
504 a 75ms gap before any V.21 transmission is harmless, adds little to the overall length of
505 a call, and ensures the receiving end is ready. */
506 silence_gen_alter(&t->silence_gen, ms_to_samples(75));
507 set_tx_handler(s, (span_tx_handler_t *) &silence_gen, &t->silence_gen);
508 set_next_tx_handler(s, (span_tx_handler_t *) &fsk_tx, &t->v21_tx);
509 t->transmit = TRUE;
510 break;
511 case T30_MODEM_V27TER:
512 silence_gen_alter(&t->silence_gen, ms_to_samples(75));
513 /* For any fast modem, set 200ms of preamble flags */
514 hdlc_tx_flags(&t->hdlc_tx, bit_rate/(8*5));
515 v27ter_tx_restart(&t->v27ter_tx, bit_rate, t->use_tep);
516 v27ter_tx_set_get_bit(&t->v27ter_tx, get_bit_func, get_bit_user_data);
517 set_tx_handler(s, (span_tx_handler_t *) &silence_gen, &t->silence_gen);
518 set_next_tx_handler(s, (span_tx_handler_t *) &v27ter_tx, &t->v27ter_tx);
519 t->transmit = TRUE;
520 break;
521 case T30_MODEM_V29:
522 silence_gen_alter(&t->silence_gen, ms_to_samples(75));
523 /* For any fast modem, set 200ms of preamble flags */
524 hdlc_tx_flags(&t->hdlc_tx, bit_rate/(8*5));
525 v29_tx_restart(&t->v29_tx, bit_rate, t->use_tep);
526 v29_tx_set_get_bit(&t->v29_tx, get_bit_func, get_bit_user_data);
527 set_tx_handler(s, (span_tx_handler_t *) &silence_gen, &t->silence_gen);
528 set_next_tx_handler(s, (span_tx_handler_t *) &v29_tx, &t->v29_tx);
529 t->transmit = TRUE;
530 break;
531 case T30_MODEM_V17:
532 silence_gen_alter(&t->silence_gen, ms_to_samples(75));
533 /* For any fast modem, set 200ms of preamble flags */
534 hdlc_tx_flags(&t->hdlc_tx, bit_rate/(8*5));
535 v17_tx_restart(&t->v17_tx, bit_rate, t->use_tep, short_train);
536 v17_tx_set_get_bit(&t->v17_tx, get_bit_func, get_bit_user_data);
537 set_tx_handler(s, (span_tx_handler_t *) &silence_gen, &t->silence_gen);
538 set_next_tx_handler(s, (span_tx_handler_t *) &v17_tx, &t->v17_tx);
539 t->transmit = TRUE;
540 break;
541 case T30_MODEM_DONE:
542 span_log(&s->logging, SPAN_LOG_FLOW, "FAX exchange complete\n");
543 /* Fall through */
544 default:
545 silence_gen_alter(&t->silence_gen, 0);
546 set_tx_handler(s, (span_tx_handler_t *) &silence_gen, &t->silence_gen);
547 set_next_tx_handler(s, (span_tx_handler_t *) NULL, NULL);
548 t->transmit = FALSE;
549 break;
550 }
551 t->tx_bit_rate = bit_rate;
552 t->current_tx_type = type;
553 }
554 /*- End of function --------------------------------------------------------*/
555
556 SPAN_DECLARE(void) fax_set_transmit_on_idle(fax_state_t *s, int transmit_on_idle)
557 {
558 s->modems.transmit_on_idle = transmit_on_idle;
559 }
560 /*- End of function --------------------------------------------------------*/
561
562 SPAN_DECLARE(void) fax_set_tep_mode(fax_state_t *s, int use_tep)
563 {
564 s->modems.use_tep = use_tep;
565 }
566 /*- End of function --------------------------------------------------------*/
567
568 SPAN_DECLARE(t30_state_t *) fax_get_t30_state(fax_state_t *s)
569 {
570 return &s->t30;
571 }
572 /*- End of function --------------------------------------------------------*/
573
574 SPAN_DECLARE(logging_state_t *) fax_get_logging_state(fax_state_t *s)
575 {
576 return &s->logging;
577 }
578 /*- End of function --------------------------------------------------------*/
579
580 SPAN_DECLARE(fax_state_t *) fax_init(fax_state_t *s, int calling_party)
581 {
582 if (s == NULL)
583 {
584 if ((s = (fax_state_t *) malloc(sizeof(*s))) == NULL)
585 return NULL;
586 }
587 memset(s, 0, sizeof(*s));
588 span_log_init(&s->logging, SPAN_LOG_NONE, NULL);
589 span_log_set_protocol(&s->logging, "FAX");
590 fax_modems_init(&s->modems,
591 FALSE,
592 t30_hdlc_accept,
593 hdlc_underflow_handler,
594 t30_non_ecm_put_bit,
595 t30_non_ecm_get_bit,
596 tone_detected,
597 &s->t30);
598 t30_init(&s->t30,
599 calling_party,
600 fax_set_rx_type,
601 (void *) s,
602 fax_set_tx_type,
603 (void *) s,
604 fax_send_hdlc,
605 (void *) s);
606 t30_set_supported_modems(&s->t30, T30_SUPPORT_V27TER | T30_SUPPORT_V29 | T30_SUPPORT_V17);
607 t30_restart(&s->t30);
608 #if defined(LOG_FAX_AUDIO)
609 {
610 char buf[100 + 1];
611 struct tm *tm;
612 time_t now;
613
614 time(&now);
615 tm = localtime(&now);
616 sprintf(buf,
617 "/tmp/fax-rx-audio-%p-%02d%02d%02d%02d%02d%02d",
618 s,
619 tm->tm_year%100,
620 tm->tm_mon + 1,
621 tm->tm_mday,
622 tm->tm_hour,
623 tm->tm_min,
624 tm->tm_sec);
625 s->modems.audio_rx_log = open(buf, O_CREAT | O_TRUNC | O_WRONLY, 0666);
626 sprintf(buf,
627 "/tmp/fax-tx-audio-%p-%02d%02d%02d%02d%02d%02d",
628 s,
629 tm->tm_year%100,
630 tm->tm_mon + 1,
631 tm->tm_mday,
632 tm->tm_hour,
633 tm->tm_min,
634 tm->tm_sec);
635 s->modems.audio_tx_log = open(buf, O_CREAT | O_TRUNC | O_WRONLY, 0666);
636 }
637 #endif
638 return s;
639 }
640 /*- End of function --------------------------------------------------------*/
641
642 SPAN_DECLARE(int) fax_release(fax_state_t *s)
643 {
644 t30_release(&s->t30);
645 return 0;
646 }
647 /*- End of function --------------------------------------------------------*/
648
649 SPAN_DECLARE(int) fax_free(fax_state_t *s)
650 {
651 t30_release(&s->t30);
652 free(s);
653 return 0;
654 }
655 /*- End of function --------------------------------------------------------*/
656 /*- End of file ------------------------------------------------------------*/

Repositories maintained by Peter Meerwald, pmeerw@pmeerw.net.