Mercurial > hg > audiostuff
comparison spandsp-0.0.6pre17/src/t38_terminal.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 /* | |
2 * SpanDSP - a series of DSP components for telephony | |
3 * | |
4 * t38_terminal.c - T.38 termination, less the packet exchange part | |
5 * | |
6 * Written by Steve Underwood <steveu@coppice.org> | |
7 * | |
8 * Copyright (C) 2005, 2006, 2008 Steve Underwood | |
9 * | |
10 * All rights reserved. | |
11 * | |
12 * This program is free software; you can redistribute it and/or modify | |
13 * it under the terms of the GNU Lesser General Public License version 2.1, | |
14 * as published by the Free Software Foundation. | |
15 * | |
16 * This program is distributed in the hope that it will be useful, | |
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
19 * GNU Lesser General Public License for more details. | |
20 * | |
21 * You should have received a copy of the GNU Lesser General Public | |
22 * License along with this program; if not, write to the Free Software | |
23 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |
24 * | |
25 * $Id: t38_terminal.c,v 1.129.4.2 2009/12/19 10:44:10 steveu Exp $ | |
26 */ | |
27 | |
28 /*! \file */ | |
29 | |
30 #if defined(HAVE_CONFIG_H) | |
31 #include "config.h" | |
32 #endif | |
33 | |
34 #include <inttypes.h> | |
35 #include <stdlib.h> | |
36 #include <stdio.h> | |
37 #include <fcntl.h> | |
38 #include <time.h> | |
39 #include <string.h> | |
40 #if defined(HAVE_TGMATH_H) | |
41 #include <tgmath.h> | |
42 #endif | |
43 #if defined(HAVE_MATH_H) | |
44 #include <math.h> | |
45 #endif | |
46 #include "floating_fudge.h" | |
47 #include <assert.h> | |
48 #include <tiffio.h> | |
49 | |
50 #include "spandsp/telephony.h" | |
51 #include "spandsp/logging.h" | |
52 #include "spandsp/bit_operations.h" | |
53 #include "spandsp/queue.h" | |
54 #include "spandsp/power_meter.h" | |
55 #include "spandsp/complex.h" | |
56 #include "spandsp/tone_generate.h" | |
57 #include "spandsp/async.h" | |
58 #include "spandsp/hdlc.h" | |
59 #include "spandsp/fsk.h" | |
60 #include "spandsp/v29tx.h" | |
61 #include "spandsp/v29rx.h" | |
62 #include "spandsp/v27ter_tx.h" | |
63 #include "spandsp/v27ter_rx.h" | |
64 #include "spandsp/v17tx.h" | |
65 #include "spandsp/v17rx.h" | |
66 #include "spandsp/t4_rx.h" | |
67 #include "spandsp/t4_tx.h" | |
68 #include "spandsp/t30_fcf.h" | |
69 #include "spandsp/t35.h" | |
70 #include "spandsp/t30.h" | |
71 #include "spandsp/t30_api.h" | |
72 #include "spandsp/t30_logging.h" | |
73 #include "spandsp/t38_core.h" | |
74 #include "spandsp/t38_terminal.h" | |
75 | |
76 #include "spandsp/private/logging.h" | |
77 #include "spandsp/private/t4_rx.h" | |
78 #include "spandsp/private/t4_tx.h" | |
79 #include "spandsp/private/t30.h" | |
80 #include "spandsp/private/t38_core.h" | |
81 #include "spandsp/private/t38_terminal.h" | |
82 | |
83 /* Settings suitable for paced transmission over a UDP transport */ | |
84 #define MS_PER_TX_CHUNK 30 | |
85 | |
86 #define INDICATOR_TX_COUNT 3 | |
87 #define DATA_TX_COUNT 1 | |
88 #define DATA_END_TX_COUNT 3 | |
89 | |
90 /* Settings suitable for unpaced transmission over a TCP transport */ | |
91 #define MAX_OCTETS_PER_UNPACED_CHUNK 300 | |
92 | |
93 /* Backstop timeout if reception of packets stops in the middle of a burst */ | |
94 #define MID_RX_TIMEOUT 15000 | |
95 | |
96 enum | |
97 { | |
98 T38_CHUNKING_MERGE_FCS_WITH_DATA = 0x0001, | |
99 T38_CHUNKING_WHOLE_FRAMES = 0x0002, | |
100 T38_CHUNKING_ALLOW_TEP_TIME = 0x0004 | |
101 }; | |
102 | |
103 enum | |
104 { | |
105 T38_TIMED_STEP_NONE = 0, | |
106 T38_TIMED_STEP_NON_ECM_MODEM = 0x10, | |
107 T38_TIMED_STEP_NON_ECM_MODEM_2 = 0x11, | |
108 T38_TIMED_STEP_NON_ECM_MODEM_3 = 0x12, | |
109 T38_TIMED_STEP_NON_ECM_MODEM_4 = 0x13, | |
110 T38_TIMED_STEP_NON_ECM_MODEM_5 = 0x14, | |
111 T38_TIMED_STEP_HDLC_MODEM = 0x20, | |
112 T38_TIMED_STEP_HDLC_MODEM_2 = 0x21, | |
113 T38_TIMED_STEP_HDLC_MODEM_3 = 0x22, | |
114 T38_TIMED_STEP_HDLC_MODEM_4 = 0x23, | |
115 T38_TIMED_STEP_HDLC_MODEM_5 = 0x24, | |
116 T38_TIMED_STEP_CED = 0x30, | |
117 T38_TIMED_STEP_CED_2 = 0x31, | |
118 T38_TIMED_STEP_CED_3 = 0x32, | |
119 T38_TIMED_STEP_CNG = 0x40, | |
120 T38_TIMED_STEP_CNG_2 = 0x41, | |
121 T38_TIMED_STEP_PAUSE = 0x50 | |
122 }; | |
123 | |
124 static __inline__ void front_end_status(t38_terminal_state_t *s, int status) | |
125 { | |
126 t30_front_end_status(&s->t30, status); | |
127 } | |
128 /*- End of function --------------------------------------------------------*/ | |
129 | |
130 static __inline__ void hdlc_accept_frame(t38_terminal_state_t *s, const uint8_t *msg, int len, int ok) | |
131 { | |
132 t30_hdlc_accept(&s->t30, msg, len, ok); | |
133 } | |
134 /*- End of function --------------------------------------------------------*/ | |
135 | |
136 static int extra_bits_in_stuffed_frame(const uint8_t buf[], int len) | |
137 { | |
138 int bitstream; | |
139 int ones; | |
140 int stuffed; | |
141 int i; | |
142 int j; | |
143 | |
144 bitstream = 0; | |
145 ones = 0; | |
146 stuffed = 0; | |
147 /* We should really append the CRC, and include the stuffed bits for that, to get | |
148 the exact number of bits in the frame. */ | |
149 //len = crc_itu16_append(buf, len); | |
150 for (i = 0; i < len; i++) | |
151 { | |
152 bitstream = buf[i]; | |
153 for (j = 0; j < 8; j++) | |
154 { | |
155 if ((bitstream & 1)) | |
156 { | |
157 if (++ones >= 5) | |
158 { | |
159 ones = 0; | |
160 stuffed++; | |
161 } | |
162 } | |
163 else | |
164 { | |
165 ones = 0; | |
166 } | |
167 bitstream >>= 1; | |
168 } | |
169 } | |
170 /* The total length of the frame is: | |
171 the number of bits in the body | |
172 + the number of additional bits in the body due to stuffing | |
173 + the number of bits in the CRC | |
174 + the number of additional bits in the CRC due to stuffing | |
175 + 16 bits for the two terminating flag octets. | |
176 Lets just allow 3 bits for the CRC, which is the worst case. It | |
177 avoids calculating the real CRC, and the worst it can do is cause | |
178 a flag octet's worth of additional output. | |
179 */ | |
180 return stuffed + 16 + 3 + 16; | |
181 } | |
182 /*- End of function --------------------------------------------------------*/ | |
183 | |
184 static int process_rx_missing(t38_core_state_t *t, void *user_data, int rx_seq_no, int expected_seq_no) | |
185 { | |
186 t38_terminal_state_t *s; | |
187 | |
188 s = (t38_terminal_state_t *) user_data; | |
189 s->t38_fe.rx_data_missing = TRUE; | |
190 return 0; | |
191 } | |
192 /*- End of function --------------------------------------------------------*/ | |
193 | |
194 static int process_rx_indicator(t38_core_state_t *t, void *user_data, int indicator) | |
195 { | |
196 t38_terminal_state_t *s; | |
197 t38_terminal_front_end_state_t *fe; | |
198 | |
199 s = (t38_terminal_state_t *) user_data; | |
200 fe = &s->t38_fe; | |
201 | |
202 if (t->current_rx_indicator == indicator) | |
203 { | |
204 /* This is probably due to the far end repeating itself, or slipping | |
205 preamble messages in between HDLC frames. T.38/V.1.3 tells us to | |
206 ignore it. Its harmless. */ | |
207 return 0; | |
208 } | |
209 /* In termination mode we don't care very much about indicators telling us training | |
210 is starting. We only care about V.21 preamble starting, for timeout control, and | |
211 the actual data. */ | |
212 switch (indicator) | |
213 { | |
214 case T38_IND_NO_SIGNAL: | |
215 if (t->current_rx_indicator == T38_IND_V21_PREAMBLE | |
216 && | |
217 (fe->current_rx_type == T30_MODEM_V21 || fe->current_rx_type == T30_MODEM_CNG)) | |
218 { | |
219 hdlc_accept_frame(s, NULL, SIG_STATUS_CARRIER_DOWN, TRUE); | |
220 } | |
221 fe->timeout_rx_samples = 0; | |
222 front_end_status(s, T30_FRONT_END_SIGNAL_ABSENT); | |
223 break; | |
224 case T38_IND_CNG: | |
225 /* We are completely indifferent to the startup tones. They serve no purpose for us. | |
226 We can't even assume that the existance of a tone means the far end is achieving | |
227 proper communication. Some T.38 gateways will just send out a CED or CNG indicator | |
228 without having seen anything from the far end FAX terminal. | |
229 Just report them for completeness. */ | |
230 front_end_status(s, T30_FRONT_END_CNG_PRESENT); | |
231 break; | |
232 case T38_IND_CED: | |
233 front_end_status(s, T30_FRONT_END_CED_PRESENT); | |
234 break; | |
235 case T38_IND_V21_PREAMBLE: | |
236 fe->timeout_rx_samples = fe->samples + ms_to_samples(MID_RX_TIMEOUT); | |
237 front_end_status(s, T30_FRONT_END_SIGNAL_PRESENT); | |
238 break; | |
239 case T38_IND_V27TER_2400_TRAINING: | |
240 case T38_IND_V27TER_4800_TRAINING: | |
241 case T38_IND_V29_7200_TRAINING: | |
242 case T38_IND_V29_9600_TRAINING: | |
243 case T38_IND_V17_7200_SHORT_TRAINING: | |
244 case T38_IND_V17_7200_LONG_TRAINING: | |
245 case T38_IND_V17_9600_SHORT_TRAINING: | |
246 case T38_IND_V17_9600_LONG_TRAINING: | |
247 case T38_IND_V17_12000_SHORT_TRAINING: | |
248 case T38_IND_V17_12000_LONG_TRAINING: | |
249 case T38_IND_V17_14400_SHORT_TRAINING: | |
250 case T38_IND_V17_14400_LONG_TRAINING: | |
251 case T38_IND_V34_CNTL_CHANNEL_1200: | |
252 case T38_IND_V34_PRI_CHANNEL: | |
253 case T38_IND_V33_12000_TRAINING: | |
254 case T38_IND_V33_14400_TRAINING: | |
255 /* We really don't care what kind of modem is delivering the following image data. | |
256 We only care that some kind of fast modem signal is coming next. */ | |
257 fe->timeout_rx_samples = fe->samples + ms_to_samples(MID_RX_TIMEOUT); | |
258 front_end_status(s, T30_FRONT_END_SIGNAL_PRESENT); | |
259 break; | |
260 case T38_IND_V8_ANSAM: | |
261 case T38_IND_V8_SIGNAL: | |
262 case T38_IND_V34_CC_RETRAIN: | |
263 /* V.34 support is a work in progress. */ | |
264 break; | |
265 default: | |
266 front_end_status(s, T30_FRONT_END_SIGNAL_ABSENT); | |
267 break; | |
268 } | |
269 /*endswitch*/ | |
270 fe->hdlc_rx.len = 0; | |
271 fe->rx_data_missing = FALSE; | |
272 return 0; | |
273 } | |
274 /*- End of function --------------------------------------------------------*/ | |
275 | |
276 static int fake_rx_indicator(t38_core_state_t *t, t38_terminal_state_t *s, int indicator) | |
277 { | |
278 int ret; | |
279 | |
280 ret = process_rx_indicator(t, s, indicator); | |
281 t->current_rx_indicator = indicator; | |
282 return ret; | |
283 } | |
284 /*- End of function --------------------------------------------------------*/ | |
285 | |
286 static int process_rx_data(t38_core_state_t *t, void *user_data, int data_type, int field_type, const uint8_t *buf, int len) | |
287 { | |
288 t38_terminal_state_t *s; | |
289 t38_terminal_front_end_state_t *fe; | |
290 #if defined(_MSC_VER) | |
291 uint8_t *buf2 = (uint8_t *) _alloca(len); | |
292 #else | |
293 uint8_t buf2[len]; | |
294 #endif | |
295 | |
296 s = (t38_terminal_state_t *) user_data; | |
297 fe = &s->t38_fe; | |
298 /* In termination mode we don't care very much what the data type is apart from a couple of | |
299 special cases. */ | |
300 switch (data_type) | |
301 { | |
302 case T38_DATA_V8: | |
303 switch (field_type) | |
304 { | |
305 case T38_FIELD_CM_MESSAGE: | |
306 if (len >= 1) | |
307 span_log(&s->logging, SPAN_LOG_FLOW, "CM profile %d - %s\n", buf[0] - '0', t38_cm_profile_to_str(buf[0])); | |
308 else | |
309 span_log(&s->logging, SPAN_LOG_FLOW, "Bad length for CM message - %d\n", len); | |
310 //front_end_status(s, T30_FRONT_END_RECEIVE_COMPLETE); | |
311 break; | |
312 case T38_FIELD_JM_MESSAGE: | |
313 if (len >= 2) | |
314 span_log(&s->logging, SPAN_LOG_FLOW, "JM - %s\n", t38_jm_to_str(buf, len)); | |
315 else | |
316 span_log(&s->logging, SPAN_LOG_FLOW, "Bad length for JM message - %d\n", len); | |
317 //front_end_status(s, T30_FRONT_END_RECEIVE_COMPLETE); | |
318 break; | |
319 case T38_FIELD_CI_MESSAGE: | |
320 if (len >= 1) | |
321 span_log(&s->logging, SPAN_LOG_FLOW, "CI 0x%X\n", buf[0]); | |
322 else | |
323 span_log(&s->logging, SPAN_LOG_FLOW, "Bad length for CI message - %d\n", len); | |
324 //front_end_status(s, T30_FRONT_END_RECEIVE_COMPLETE); | |
325 break; | |
326 default: | |
327 break; | |
328 } | |
329 /*endswitch*/ | |
330 return 0; | |
331 case T38_DATA_V34_PRI_RATE: | |
332 switch (field_type) | |
333 { | |
334 case T38_FIELD_V34RATE: | |
335 if (len >= 3) | |
336 { | |
337 /* Just get and store the rate. The front end has no real interest in the | |
338 actual bit rate. */ | |
339 fe->t38.v34_rate = t38_v34rate_to_bps(buf, len); | |
340 span_log(&s->logging, SPAN_LOG_FLOW, "V.34 rate %d bps\n", fe->t38.v34_rate); | |
341 } | |
342 else | |
343 { | |
344 span_log(&s->logging, SPAN_LOG_FLOW, "Bad length for V34rate message - %d\n", len); | |
345 } | |
346 break; | |
347 default: | |
348 break; | |
349 } | |
350 /*endswitch*/ | |
351 return 0; | |
352 default: | |
353 break; | |
354 } | |
355 /*endswitch*/ | |
356 switch (field_type) | |
357 { | |
358 case T38_FIELD_HDLC_DATA: | |
359 if (fe->timeout_rx_samples == 0) | |
360 { | |
361 /* HDLC can just start without any signal indicator on some platforms, even when | |
362 there is zero packet lost. Nasty, but true. Its a good idea to be tolerant of | |
363 loss, though, so accepting a sudden start of HDLC data is the right thing to do. */ | |
364 fake_rx_indicator(t, s, T38_IND_V21_PREAMBLE); | |
365 /* All real HDLC messages in the FAX world start with 0xFF. If this one is not starting | |
366 with 0xFF it would appear some octets must have been missed before this one. */ | |
367 if (len <= 0 || buf[0] != 0xFF) | |
368 fe->rx_data_missing = TRUE; | |
369 } | |
370 if (len > 0 && fe->hdlc_rx.len + len <= T38_MAX_HDLC_LEN) | |
371 { | |
372 bit_reverse(fe->hdlc_rx.buf + fe->hdlc_rx.len, buf, len); | |
373 fe->hdlc_rx.len += len; | |
374 } | |
375 fe->timeout_rx_samples = fe->samples + ms_to_samples(MID_RX_TIMEOUT); | |
376 break; | |
377 case T38_FIELD_HDLC_FCS_OK: | |
378 if (len > 0) | |
379 { | |
380 span_log(&s->logging, SPAN_LOG_WARNING, "There is data in a T38_FIELD_HDLC_FCS_OK!\n"); | |
381 /* The sender has incorrectly included data in this message. It is unclear what we should do | |
382 with it, to maximise tolerance of buggy implementations. */ | |
383 } | |
384 /* Some T.38 implementations send multiple T38_FIELD_HDLC_FCS_OK messages, in IFP packets with | |
385 incrementing sequence numbers, which are actually repeats. They get through to this point because | |
386 of the incrementing sequence numbers. We need to filter them here in a context sensitive manner. */ | |
387 if (t->current_rx_data_type != data_type || t->current_rx_field_type != field_type) | |
388 { | |
389 span_log(&s->logging, SPAN_LOG_FLOW, "Type %s - CRC OK (%s)\n", (fe->hdlc_rx.len >= 3) ? t30_frametype(fe->hdlc_rx.buf[2]) : "???", (fe->rx_data_missing) ? "missing octets" : "clean"); | |
390 hdlc_accept_frame(s, fe->hdlc_rx.buf, fe->hdlc_rx.len, !fe->rx_data_missing); | |
391 } | |
392 fe->hdlc_rx.len = 0; | |
393 fe->rx_data_missing = FALSE; | |
394 fe->timeout_rx_samples = fe->samples + ms_to_samples(MID_RX_TIMEOUT); | |
395 break; | |
396 case T38_FIELD_HDLC_FCS_BAD: | |
397 if (len > 0) | |
398 { | |
399 span_log(&s->logging, SPAN_LOG_WARNING, "There is data in a T38_FIELD_HDLC_FCS_BAD!\n"); | |
400 /* The sender has incorrectly included data in this message. We can safely ignore it, as the | |
401 bad FCS means we will throw away the whole message, anyway. */ | |
402 } | |
403 /* Some T.38 implementations send multiple T38_FIELD_HDLC_FCS_BAD messages, in IFP packets with | |
404 incrementing sequence numbers, which are actually repeats. They get through to this point because | |
405 of the incrementing sequence numbers. We need to filter them here in a context sensitive manner. */ | |
406 if (t->current_rx_data_type != data_type || t->current_rx_field_type != field_type) | |
407 { | |
408 span_log(&s->logging, SPAN_LOG_FLOW, "Type %s - CRC bad (%s)\n", (fe->hdlc_rx.len >= 3) ? t30_frametype(fe->hdlc_rx.buf[2]) : "???", (fe->rx_data_missing) ? "missing octets" : "clean"); | |
409 hdlc_accept_frame(s, fe->hdlc_rx.buf, fe->hdlc_rx.len, FALSE); | |
410 } | |
411 fe->hdlc_rx.len = 0; | |
412 fe->rx_data_missing = FALSE; | |
413 fe->timeout_rx_samples = fe->samples + ms_to_samples(MID_RX_TIMEOUT); | |
414 break; | |
415 case T38_FIELD_HDLC_FCS_OK_SIG_END: | |
416 if (len > 0) | |
417 { | |
418 span_log(&s->logging, SPAN_LOG_WARNING, "There is data in a T38_FIELD_HDLC_FCS_OK_SIG_END!\n"); | |
419 /* The sender has incorrectly included data in this message. It is unclear what we should do | |
420 with it, to maximise tolerance of buggy implementations. */ | |
421 } | |
422 /* Some T.38 implementations send multiple T38_FIELD_HDLC_FCS_OK_SIG_END messages, in IFP packets with | |
423 incrementing sequence numbers, which are actually repeats. They get through to this point because | |
424 of the incrementing sequence numbers. We need to filter them here in a context sensitive manner. */ | |
425 if (t->current_rx_data_type != data_type || t->current_rx_field_type != field_type) | |
426 { | |
427 span_log(&s->logging, SPAN_LOG_FLOW, "Type %s - CRC OK, sig end (%s)\n", (fe->hdlc_rx.len >= 3) ? t30_frametype(fe->hdlc_rx.buf[2]) : "???", (fe->rx_data_missing) ? "missing octets" : "clean"); | |
428 hdlc_accept_frame(s, fe->hdlc_rx.buf, fe->hdlc_rx.len, !fe->rx_data_missing); | |
429 hdlc_accept_frame(s, NULL, SIG_STATUS_CARRIER_DOWN, TRUE); | |
430 } | |
431 fe->hdlc_rx.len = 0; | |
432 fe->rx_data_missing = FALSE; | |
433 /* Treat this like a no signal indicator has occurred, so if the no signal indicator is missing, we are still OK */ | |
434 fake_rx_indicator(t, s, T38_IND_NO_SIGNAL); | |
435 break; | |
436 case T38_FIELD_HDLC_FCS_BAD_SIG_END: | |
437 if (len > 0) | |
438 { | |
439 span_log(&s->logging, SPAN_LOG_WARNING, "There is data in a T38_FIELD_HDLC_FCS_BAD_SIG_END!\n"); | |
440 /* The sender has incorrectly included data in this message. We can safely ignore it, as the | |
441 bad FCS means we will throw away the whole message, anyway. */ | |
442 } | |
443 /* Some T.38 implementations send multiple T38_FIELD_HDLC_FCS_BAD_SIG_END messages, in IFP packets with | |
444 incrementing sequence numbers, which are actually repeats. They get through to this point because | |
445 of the incrementing sequence numbers. We need to filter them here in a context sensitive manner. */ | |
446 if (t->current_rx_data_type != data_type || t->current_rx_field_type != field_type) | |
447 { | |
448 span_log(&s->logging, SPAN_LOG_FLOW, "Type %s - CRC bad, sig end (%s)\n", (fe->hdlc_rx.len >= 3) ? t30_frametype(fe->hdlc_rx.buf[2]) : "???", (fe->rx_data_missing) ? "missing octets" : "clean"); | |
449 hdlc_accept_frame(s, fe->hdlc_rx.buf, fe->hdlc_rx.len, FALSE); | |
450 hdlc_accept_frame(s, NULL, SIG_STATUS_CARRIER_DOWN, TRUE); | |
451 } | |
452 fe->hdlc_rx.len = 0; | |
453 fe->rx_data_missing = FALSE; | |
454 /* Treat this like a no signal indicator has occurred, so if the no signal indicator is missing, we are still OK */ | |
455 fake_rx_indicator(t, s, T38_IND_NO_SIGNAL); | |
456 break; | |
457 case T38_FIELD_HDLC_SIG_END: | |
458 if (len > 0) | |
459 { | |
460 span_log(&s->logging, SPAN_LOG_WARNING, "There is data in a T38_FIELD_HDLC_SIG_END!\n"); | |
461 /* The sender has incorrectly included data in this message, but there seems nothing meaningful | |
462 it could be. There could not be an FCS good/bad report beyond this. */ | |
463 } | |
464 /* Some T.38 implementations send multiple T38_FIELD_HDLC_SIG_END messages, in IFP packets with | |
465 incrementing sequence numbers, which are actually repeats. They get through to this point because | |
466 of the incrementing sequence numbers. We need to filter them here in a context sensitive manner. */ | |
467 if (t->current_rx_data_type != data_type || t->current_rx_field_type != field_type) | |
468 { | |
469 /* WORKAROUND: At least some Mediatrix boxes have a bug, where they can send this message at the | |
470 end of non-ECM data. We need to tolerate this. We use the generic receive complete | |
471 indication, rather than the specific HDLC carrier down. */ | |
472 /* This message is expected under 2 circumstances. One is as an alternative to T38_FIELD_HDLC_FCS_OK_SIG_END - | |
473 i.e. they send T38_FIELD_HDLC_FCS_OK, and then T38_FIELD_HDLC_SIG_END when the carrier actually drops. | |
474 The other is because the HDLC signal drops unexpectedly - i.e. not just after a final frame. */ | |
475 fe->hdlc_rx.len = 0; | |
476 fe->rx_data_missing = FALSE; | |
477 front_end_status(s, T30_FRONT_END_RECEIVE_COMPLETE); | |
478 } | |
479 /* Treat this like a no signal indicator has occurred, so if the no signal indicator is missing, we are still OK */ | |
480 fake_rx_indicator(t, s, T38_IND_NO_SIGNAL); | |
481 break; | |
482 case T38_FIELD_T4_NON_ECM_DATA: | |
483 if (!fe->rx_signal_present) | |
484 { | |
485 t30_non_ecm_put_bit(&s->t30, SIG_STATUS_TRAINING_SUCCEEDED); | |
486 fe->rx_signal_present = TRUE; | |
487 } | |
488 if (len > 0) | |
489 { | |
490 bit_reverse(buf2, buf, len); | |
491 t30_non_ecm_put_chunk(&s->t30, buf2, len); | |
492 } | |
493 fe->timeout_rx_samples = fe->samples + ms_to_samples(MID_RX_TIMEOUT); | |
494 break; | |
495 case T38_FIELD_T4_NON_ECM_SIG_END: | |
496 /* Some T.38 implementations send multiple T38_FIELD_T4_NON_ECM_SIG_END messages, in IFP packets with | |
497 incrementing sequence numbers, which are actually repeats. They get through to this point because | |
498 of the incrementing sequence numbers. We need to filter them here in a context sensitive manner. */ | |
499 if (t->current_rx_data_type != data_type || t->current_rx_field_type != field_type) | |
500 { | |
501 if (len > 0) | |
502 { | |
503 if (!fe->rx_signal_present) | |
504 { | |
505 t30_non_ecm_put_bit(&s->t30, SIG_STATUS_TRAINING_SUCCEEDED); | |
506 fe->rx_signal_present = TRUE; | |
507 } | |
508 bit_reverse(buf2, buf, len); | |
509 t30_non_ecm_put_chunk(&s->t30, buf2, len); | |
510 } | |
511 /* WORKAROUND: At least some Mediatrix boxes have a bug, where they can send HDLC signal end where | |
512 they should send non-ECM signal end. It is possible they also do the opposite. | |
513 We need to tolerate this, so we use the generic receive complete | |
514 indication, rather than the specific non-ECM carrier down. */ | |
515 front_end_status(s, T30_FRONT_END_RECEIVE_COMPLETE); | |
516 } | |
517 fe->rx_signal_present = FALSE; | |
518 /* Treat this like a no signal indicator has occurred, so if the no signal indicator is missing, we are still OK */ | |
519 fake_rx_indicator(t, s, T38_IND_NO_SIGNAL); | |
520 break; | |
521 default: | |
522 break; | |
523 } | |
524 /*endswitch*/ | |
525 return 0; | |
526 } | |
527 /*- End of function --------------------------------------------------------*/ | |
528 | |
529 static void send_hdlc(void *user_data, const uint8_t *msg, int len) | |
530 { | |
531 t38_terminal_state_t *s; | |
532 | |
533 s = (t38_terminal_state_t *) user_data; | |
534 if (len <= 0) | |
535 { | |
536 s->t38_fe.hdlc_tx.len = -1; | |
537 } | |
538 else | |
539 { | |
540 s->t38_fe.hdlc_tx.extra_bits = extra_bits_in_stuffed_frame(msg, len); | |
541 bit_reverse(s->t38_fe.hdlc_tx.buf, msg, len); | |
542 s->t38_fe.hdlc_tx.len = len; | |
543 s->t38_fe.hdlc_tx.ptr = 0; | |
544 } | |
545 } | |
546 /*- End of function --------------------------------------------------------*/ | |
547 | |
548 static __inline__ int bits_to_us(t38_terminal_state_t *s, int bits) | |
549 { | |
550 if (s->t38_fe.ms_per_tx_chunk == 0 || s->t38_fe.tx_bit_rate == 0) | |
551 return 0; | |
552 return bits*1000000/s->t38_fe.tx_bit_rate; | |
553 } | |
554 /*- End of function --------------------------------------------------------*/ | |
555 | |
556 static void set_octets_per_data_packet(t38_terminal_state_t *s, int bit_rate) | |
557 { | |
558 s->t38_fe.tx_bit_rate = bit_rate; | |
559 if (s->t38_fe.ms_per_tx_chunk) | |
560 { | |
561 s->t38_fe.octets_per_data_packet = s->t38_fe.ms_per_tx_chunk*bit_rate/(8*1000); | |
562 /* Make sure we have a positive number (i.e. we didn't truncate to zero). */ | |
563 if (s->t38_fe.octets_per_data_packet < 1) | |
564 s->t38_fe.octets_per_data_packet = 1; | |
565 } | |
566 else | |
567 { | |
568 s->t38_fe.octets_per_data_packet = MAX_OCTETS_PER_UNPACED_CHUNK; | |
569 } | |
570 } | |
571 /*- End of function --------------------------------------------------------*/ | |
572 | |
573 static int stream_non_ecm(t38_terminal_state_t *s) | |
574 { | |
575 t38_terminal_front_end_state_t *fe; | |
576 uint8_t buf[MAX_OCTETS_PER_UNPACED_CHUNK + 50]; | |
577 int delay; | |
578 int len; | |
579 | |
580 fe = &s->t38_fe; | |
581 for (delay = 0; delay == 0; ) | |
582 { | |
583 switch (fe->timed_step) | |
584 { | |
585 case T38_TIMED_STEP_NON_ECM_MODEM: | |
586 /* Create a 75ms silence */ | |
587 if (fe->t38.current_tx_indicator != T38_IND_NO_SIGNAL) | |
588 delay = t38_core_send_indicator(&fe->t38, T38_IND_NO_SIGNAL); | |
589 else | |
590 delay = 75000; | |
591 fe->timed_step = T38_TIMED_STEP_NON_ECM_MODEM_2; | |
592 fe->next_tx_samples = fe->samples; | |
593 break; | |
594 case T38_TIMED_STEP_NON_ECM_MODEM_2: | |
595 /* Switch on a fast modem, and give the training time to complete */ | |
596 delay = t38_core_send_indicator(&fe->t38, fe->next_tx_indicator); | |
597 fe->timed_step = T38_TIMED_STEP_NON_ECM_MODEM_3; | |
598 break; | |
599 case T38_TIMED_STEP_NON_ECM_MODEM_3: | |
600 /* Send a chunk of non-ECM image data */ | |
601 /* T.38 says it is OK to send the last of the non-ECM data in the signal end message. | |
602 However, I think the early versions of T.38 said the signal end message should not | |
603 contain data. Hopefully, following the current spec will not cause compatibility | |
604 issues. */ | |
605 len = t30_non_ecm_get_chunk(&s->t30, buf, fe->octets_per_data_packet); | |
606 if (len > 0) | |
607 bit_reverse(buf, buf, len); | |
608 if (len < fe->octets_per_data_packet) | |
609 { | |
610 /* That's the end of the image data. */ | |
611 if (s->t38_fe.ms_per_tx_chunk) | |
612 { | |
613 /* Pad the end of the data with some zeros. If we just stop abruptly | |
614 at the end of the EOLs, some ATAs fail to clean up properly before | |
615 shutting down their transmit modem, and the last few rows of the image | |
616 are lost or corrupted. Simply delaying the no-signal message does not | |
617 help for all implentations. It is usually ignored, which is probably | |
618 the right thing to do after receiving a message saying the signal has | |
619 ended. */ | |
620 memset(buf + len, 0, fe->octets_per_data_packet - len); | |
621 fe->non_ecm_trailer_bytes = 3*fe->octets_per_data_packet + len; | |
622 len = fe->octets_per_data_packet; | |
623 fe->timed_step = T38_TIMED_STEP_NON_ECM_MODEM_4; | |
624 } | |
625 else | |
626 { | |
627 /* If we are sending quickly there seems no point in doing any padding */ | |
628 t38_core_send_data(&fe->t38, fe->current_tx_data_type, T38_FIELD_T4_NON_ECM_SIG_END, buf, len, T38_PACKET_CATEGORY_IMAGE_DATA_END); | |
629 fe->timed_step = T38_TIMED_STEP_NON_ECM_MODEM_5; | |
630 delay = 0; | |
631 break; | |
632 } | |
633 } | |
634 t38_core_send_data(&fe->t38, fe->current_tx_data_type, T38_FIELD_T4_NON_ECM_DATA, buf, len, T38_PACKET_CATEGORY_IMAGE_DATA); | |
635 delay = bits_to_us(s, 8*len); | |
636 break; | |
637 case T38_TIMED_STEP_NON_ECM_MODEM_4: | |
638 /* Send padding */ | |
639 len = fe->octets_per_data_packet; | |
640 fe->non_ecm_trailer_bytes -= fe->octets_per_data_packet; | |
641 if (fe->non_ecm_trailer_bytes <= 0) | |
642 { | |
643 len += fe->non_ecm_trailer_bytes; | |
644 memset(buf, 0, len); | |
645 t38_core_send_data(&fe->t38, fe->current_tx_data_type, T38_FIELD_T4_NON_ECM_SIG_END, buf, len, T38_PACKET_CATEGORY_IMAGE_DATA_END); | |
646 fe->timed_step = T38_TIMED_STEP_NON_ECM_MODEM_5; | |
647 /* Allow a bit more time than the data will take to play out, to ensure the far ATA does not | |
648 cut things short. */ | |
649 delay = bits_to_us(s, 8*len); | |
650 if (s->t38_fe.ms_per_tx_chunk) | |
651 delay += 60000; | |
652 front_end_status(s, T30_FRONT_END_SEND_STEP_COMPLETE); | |
653 break; | |
654 } | |
655 memset(buf, 0, len); | |
656 t38_core_send_data(&fe->t38, fe->current_tx_data_type, T38_FIELD_T4_NON_ECM_DATA, buf, len, T38_PACKET_CATEGORY_IMAGE_DATA); | |
657 delay = bits_to_us(s, 8*len); | |
658 break; | |
659 case T38_TIMED_STEP_NON_ECM_MODEM_5: | |
660 /* This should not be needed, since the message above indicates the end of the signal, but it | |
661 seems like it can improve compatibility with quirky implementations. */ | |
662 delay = t38_core_send_indicator(&fe->t38, T38_IND_NO_SIGNAL); | |
663 fe->timed_step = T38_TIMED_STEP_NONE; | |
664 return delay; | |
665 } | |
666 } | |
667 return delay; | |
668 } | |
669 /*- End of function --------------------------------------------------------*/ | |
670 | |
671 static int stream_hdlc(t38_terminal_state_t *s) | |
672 { | |
673 t38_terminal_front_end_state_t *fe; | |
674 uint8_t buf[MAX_OCTETS_PER_UNPACED_CHUNK + 50]; | |
675 t38_data_field_t data_fields[2]; | |
676 int category; | |
677 int previous; | |
678 int delay; | |
679 int i; | |
680 | |
681 fe = &s->t38_fe; | |
682 for (delay = 0; delay == 0; ) | |
683 { | |
684 switch (fe->timed_step) | |
685 { | |
686 case T38_TIMED_STEP_HDLC_MODEM: | |
687 /* Create a 75ms silence */ | |
688 if (fe->t38.current_tx_indicator != T38_IND_NO_SIGNAL) | |
689 delay = t38_core_send_indicator(&fe->t38, T38_IND_NO_SIGNAL); | |
690 else | |
691 delay = 75000; | |
692 fe->timed_step = T38_TIMED_STEP_HDLC_MODEM_2; | |
693 fe->next_tx_samples = fe->samples; | |
694 break; | |
695 case T38_TIMED_STEP_HDLC_MODEM_2: | |
696 /* Send HDLC preambling */ | |
697 delay = t38_core_send_indicator(&fe->t38, fe->next_tx_indicator); | |
698 delay += t38_core_send_flags_delay(&fe->t38, fe->next_tx_indicator); | |
699 fe->timed_step = T38_TIMED_STEP_HDLC_MODEM_3; | |
700 break; | |
701 case T38_TIMED_STEP_HDLC_MODEM_3: | |
702 /* Send a chunk of HDLC data */ | |
703 i = fe->hdlc_tx.len - fe->hdlc_tx.ptr; | |
704 if (fe->octets_per_data_packet >= i) | |
705 { | |
706 /* The last part of an HDLC frame */ | |
707 if (fe->chunking_modes & T38_CHUNKING_MERGE_FCS_WITH_DATA) | |
708 { | |
709 /* Copy the data, as we might be about to refill the buffer it is in */ | |
710 memcpy(buf, &fe->hdlc_tx.buf[fe->hdlc_tx.ptr], i); | |
711 data_fields[0].field_type = T38_FIELD_HDLC_DATA; | |
712 data_fields[0].field = buf; | |
713 data_fields[0].field_len = i; | |
714 | |
715 /* Now see about the next HDLC frame. This will tell us whether to send FCS_OK or FCS_OK_SIG_END */ | |
716 previous = fe->current_tx_data_type; | |
717 fe->hdlc_tx.ptr = 0; | |
718 fe->hdlc_tx.len = 0; | |
719 front_end_status(s, T30_FRONT_END_SEND_STEP_COMPLETE); | |
720 /* The above step should have got the next HDLC step ready - either another frame, or an instruction to stop transmission. */ | |
721 if (fe->hdlc_tx.len < 0) | |
722 { | |
723 data_fields[1].field_type = T38_FIELD_HDLC_FCS_OK_SIG_END; | |
724 data_fields[1].field = NULL; | |
725 data_fields[1].field_len = 0; | |
726 category = (s->t38_fe.current_tx_data_type == T38_DATA_V21) ? T38_PACKET_CATEGORY_CONTROL_DATA_END : T38_PACKET_CATEGORY_IMAGE_DATA_END; | |
727 t38_core_send_data_multi_field(&fe->t38, fe->current_tx_data_type, data_fields, 2, category); | |
728 fe->timed_step = T38_TIMED_STEP_HDLC_MODEM_5; | |
729 /* We add a bit of extra time here, as with some implementations | |
730 the carrier falling too abruptly causes data loss. */ | |
731 delay = bits_to_us(s, i*8 + fe->hdlc_tx.extra_bits); | |
732 if (s->t38_fe.ms_per_tx_chunk) | |
733 delay += 100000; | |
734 front_end_status(s, T30_FRONT_END_SEND_STEP_COMPLETE); | |
735 } | |
736 else | |
737 { | |
738 data_fields[1].field_type = T38_FIELD_HDLC_FCS_OK; | |
739 data_fields[1].field = NULL; | |
740 data_fields[1].field_len = 0; | |
741 category = (s->t38_fe.current_tx_data_type == T38_DATA_V21) ? T38_PACKET_CATEGORY_CONTROL_DATA : T38_PACKET_CATEGORY_IMAGE_DATA; | |
742 t38_core_send_data_multi_field(&fe->t38, fe->current_tx_data_type, data_fields, 2, category); | |
743 fe->timed_step = T38_TIMED_STEP_HDLC_MODEM_3; | |
744 delay = bits_to_us(s, i*8 + fe->hdlc_tx.extra_bits); | |
745 } | |
746 break; | |
747 } | |
748 category = (s->t38_fe.current_tx_data_type == T38_DATA_V21) ? T38_PACKET_CATEGORY_CONTROL_DATA : T38_PACKET_CATEGORY_IMAGE_DATA; | |
749 t38_core_send_data(&fe->t38, fe->current_tx_data_type, T38_FIELD_HDLC_DATA, &fe->hdlc_tx.buf[fe->hdlc_tx.ptr], i, category); | |
750 fe->timed_step = T38_TIMED_STEP_HDLC_MODEM_4; | |
751 } | |
752 else | |
753 { | |
754 i = fe->octets_per_data_packet; | |
755 category = (s->t38_fe.current_tx_data_type == T38_DATA_V21) ? T38_PACKET_CATEGORY_CONTROL_DATA : T38_PACKET_CATEGORY_IMAGE_DATA; | |
756 t38_core_send_data(&fe->t38, fe->current_tx_data_type, T38_FIELD_HDLC_DATA, &fe->hdlc_tx.buf[fe->hdlc_tx.ptr], i, category); | |
757 fe->hdlc_tx.ptr += i; | |
758 } | |
759 delay = bits_to_us(s, i*8); | |
760 break; | |
761 case T38_TIMED_STEP_HDLC_MODEM_4: | |
762 /* End of HDLC frame */ | |
763 previous = fe->current_tx_data_type; | |
764 fe->hdlc_tx.ptr = 0; | |
765 fe->hdlc_tx.len = 0; | |
766 front_end_status(s, T30_FRONT_END_SEND_STEP_COMPLETE); | |
767 /* The above step should have got the next HDLC step ready - either another frame, or an instruction to stop transmission. */ | |
768 if (fe->hdlc_tx.len < 0) | |
769 { | |
770 /* End of transmission */ | |
771 category = (s->t38_fe.current_tx_data_type == T38_DATA_V21) ? T38_PACKET_CATEGORY_CONTROL_DATA_END : T38_PACKET_CATEGORY_IMAGE_DATA_END; | |
772 t38_core_send_data(&fe->t38, previous, T38_FIELD_HDLC_FCS_OK_SIG_END, NULL, 0, category); | |
773 fe->timed_step = T38_TIMED_STEP_HDLC_MODEM_5; | |
774 /* We add a bit of extra time here, as with some implementations | |
775 the carrier falling too abruptly causes data loss. */ | |
776 delay = bits_to_us(s, fe->hdlc_tx.extra_bits); | |
777 if (s->t38_fe.ms_per_tx_chunk) | |
778 delay += 100000; | |
779 front_end_status(s, T30_FRONT_END_SEND_STEP_COMPLETE); | |
780 break; | |
781 } | |
782 if (fe->hdlc_tx.len == 0) | |
783 { | |
784 /* Now, how did we get here? We have finished a frame, but have no new frame to | |
785 send, and no end of transmission condition. */ | |
786 span_log(&s->logging, SPAN_LOG_FLOW, "No new frame or end transmission condition.\n"); | |
787 } | |
788 /* Finish the current frame off, and prepare for the next one. */ | |
789 category = (s->t38_fe.current_tx_data_type == T38_DATA_V21) ? T38_PACKET_CATEGORY_CONTROL_DATA : T38_PACKET_CATEGORY_IMAGE_DATA; | |
790 t38_core_send_data(&fe->t38, previous, T38_FIELD_HDLC_FCS_OK, NULL, 0, category); | |
791 fe->timed_step = T38_TIMED_STEP_HDLC_MODEM_3; | |
792 /* We should now wait enough time for everything to clear through an analogue modem at the far end. */ | |
793 delay = bits_to_us(s, fe->hdlc_tx.extra_bits); | |
794 break; | |
795 case T38_TIMED_STEP_HDLC_MODEM_5: | |
796 /* Note that some boxes do not like us sending a T38_FIELD_HDLC_SIG_END at this point. | |
797 A T38_IND_NO_SIGNAL should always be OK. */ | |
798 delay = t38_core_send_indicator(&fe->t38, T38_IND_NO_SIGNAL); | |
799 fe->timed_step = T38_TIMED_STEP_NONE; | |
800 return delay; | |
801 } | |
802 } | |
803 return delay; | |
804 } | |
805 /*- End of function --------------------------------------------------------*/ | |
806 | |
807 static int stream_ced(t38_terminal_state_t *s) | |
808 { | |
809 t38_terminal_front_end_state_t *fe; | |
810 int delay; | |
811 | |
812 fe = &s->t38_fe; | |
813 for (delay = 0; delay == 0; ) | |
814 { | |
815 switch (fe->timed_step) | |
816 { | |
817 case T38_TIMED_STEP_CED: | |
818 /* It seems common practice to start with a no signal indicator, though | |
819 this is not a specified requirement. Since we should be sending 200ms | |
820 of silence, starting the delay with a no signal indication makes sense. | |
821 We do need a 200ms delay, as that is a specification requirement. */ | |
822 fe->timed_step = T38_TIMED_STEP_CED_2; | |
823 delay = t38_core_send_indicator(&fe->t38, T38_IND_NO_SIGNAL); | |
824 delay = 200000; | |
825 fe->next_tx_samples = fe->samples; | |
826 break; | |
827 case T38_TIMED_STEP_CED_2: | |
828 /* Initial 200ms delay over. Send the CED indicator */ | |
829 fe->timed_step = T38_TIMED_STEP_CED_3; | |
830 delay = t38_core_send_indicator(&fe->t38, T38_IND_CED); | |
831 fe->current_tx_data_type = T38_DATA_NONE; | |
832 break; | |
833 case T38_TIMED_STEP_CED_3: | |
834 /* End of CED */ | |
835 fe->timed_step = T38_TIMED_STEP_NONE; | |
836 front_end_status(s, T30_FRONT_END_SEND_STEP_COMPLETE); | |
837 return 0; | |
838 } | |
839 } | |
840 return delay; | |
841 } | |
842 /*- End of function --------------------------------------------------------*/ | |
843 | |
844 static int stream_cng(t38_terminal_state_t *s) | |
845 { | |
846 t38_terminal_front_end_state_t *fe; | |
847 int delay; | |
848 | |
849 fe = &s->t38_fe; | |
850 for (delay = 0; delay == 0; ) | |
851 { | |
852 switch (fe->timed_step) | |
853 { | |
854 case T38_TIMED_STEP_CNG: | |
855 /* It seems common practice to start with a no signal indicator, though | |
856 this is not a specified requirement of the T.38 spec. Since we should | |
857 be sending 200ms of silence, according to T.30, starting that delay with | |
858 a no signal indication makes sense. */ | |
859 fe->timed_step = T38_TIMED_STEP_CNG_2; | |
860 delay = t38_core_send_indicator(&fe->t38, T38_IND_NO_SIGNAL); | |
861 delay = 200000; | |
862 fe->next_tx_samples = fe->samples; | |
863 break; | |
864 case T38_TIMED_STEP_CNG_2: | |
865 /* Initial short delay over. Send the CNG indicator. CNG persists until something | |
866 coming the other way interrupts it, or a long timeout controlled by the T.30 engine | |
867 expires. */ | |
868 fe->timed_step = T38_TIMED_STEP_NONE; | |
869 delay = t38_core_send_indicator(&fe->t38, T38_IND_CNG); | |
870 fe->current_tx_data_type = T38_DATA_NONE; | |
871 return delay; | |
872 } | |
873 } | |
874 return delay; | |
875 } | |
876 /*- End of function --------------------------------------------------------*/ | |
877 | |
878 SPAN_DECLARE(int) t38_terminal_send_timeout(t38_terminal_state_t *s, int samples) | |
879 { | |
880 t38_terminal_front_end_state_t *fe; | |
881 int delay; | |
882 | |
883 fe = &s->t38_fe; | |
884 if (fe->current_rx_type == T30_MODEM_DONE || fe->current_tx_type == T30_MODEM_DONE) | |
885 return TRUE; | |
886 | |
887 fe->samples += samples; | |
888 t30_timer_update(&s->t30, samples); | |
889 if (fe->timeout_rx_samples && fe->samples > fe->timeout_rx_samples) | |
890 { | |
891 span_log(&s->logging, SPAN_LOG_FLOW, "Timeout mid-receive\n"); | |
892 fe->timeout_rx_samples = 0; | |
893 front_end_status(s, T30_FRONT_END_RECEIVE_COMPLETE); | |
894 } | |
895 if (fe->timed_step == T38_TIMED_STEP_NONE) | |
896 return FALSE; | |
897 /* Wait until the right time comes along, unless we are working in "no delays" mode, while talking to an | |
898 IAF terminal. */ | |
899 if (fe->ms_per_tx_chunk && fe->samples < fe->next_tx_samples) | |
900 return FALSE; | |
901 /* Its time to send something */ | |
902 delay = 0; | |
903 switch (fe->timed_step & 0xFFF0) | |
904 { | |
905 case T38_TIMED_STEP_NON_ECM_MODEM: | |
906 delay = stream_non_ecm(s); | |
907 break; | |
908 case T38_TIMED_STEP_HDLC_MODEM: | |
909 delay = stream_hdlc(s); | |
910 break; | |
911 case T38_TIMED_STEP_CED: | |
912 delay = stream_ced(s); | |
913 break; | |
914 case T38_TIMED_STEP_CNG: | |
915 delay = stream_cng(s); | |
916 break; | |
917 case T38_TIMED_STEP_PAUSE: | |
918 /* End of timed pause */ | |
919 fe->timed_step = T38_TIMED_STEP_NONE; | |
920 front_end_status(s, T30_FRONT_END_SEND_STEP_COMPLETE); | |
921 break; | |
922 } | |
923 fe->next_tx_samples += us_to_samples(delay); | |
924 return FALSE; | |
925 } | |
926 /*- End of function --------------------------------------------------------*/ | |
927 | |
928 static void set_rx_type(void *user_data, int type, int bit_rate, int short_train, int use_hdlc) | |
929 { | |
930 t38_terminal_state_t *s; | |
931 | |
932 s = (t38_terminal_state_t *) user_data; | |
933 span_log(&s->logging, SPAN_LOG_FLOW, "Set rx type %d\n", type); | |
934 s->t38_fe.current_rx_type = type; | |
935 } | |
936 /*- End of function --------------------------------------------------------*/ | |
937 | |
938 static void start_tx(t38_terminal_front_end_state_t *fe, int use_hdlc) | |
939 { | |
940 /* The actual transmission process depends on whether we are sending at a paced manner, | |
941 for interaction with a traditional FAX machine, or streaming as fast as we can, normally | |
942 over a TCP connection to a machine directly connected to the internet. */ | |
943 if (fe->ms_per_tx_chunk) | |
944 { | |
945 /* Start the paced packet transmission process. */ | |
946 fe->timed_step = (use_hdlc) ? T38_TIMED_STEP_HDLC_MODEM : T38_TIMED_STEP_NON_ECM_MODEM; | |
947 if (fe->next_tx_samples < fe->samples) | |
948 fe->next_tx_samples = fe->samples; | |
949 } | |
950 else | |
951 { | |
952 /* Start the fast streaming transmission process. */ | |
953 } | |
954 } | |
955 /*- End of function --------------------------------------------------------*/ | |
956 | |
957 static void set_tx_type(void *user_data, int type, int bit_rate, int short_train, int use_hdlc) | |
958 { | |
959 t38_terminal_state_t *s; | |
960 t38_terminal_front_end_state_t *fe; | |
961 | |
962 s = (t38_terminal_state_t *) user_data; | |
963 fe = &s->t38_fe; | |
964 span_log(&s->logging, SPAN_LOG_FLOW, "Set tx type %d\n", type); | |
965 if (fe->current_tx_type == type) | |
966 return; | |
967 | |
968 set_octets_per_data_packet(s, bit_rate); | |
969 switch (type) | |
970 { | |
971 case T30_MODEM_NONE: | |
972 /* If a "no signal" indicator is waiting to be played out, don't disturb it. */ | |
973 if (fe->timed_step != T38_TIMED_STEP_NON_ECM_MODEM_5 && fe->timed_step != T38_TIMED_STEP_HDLC_MODEM_5) | |
974 fe->timed_step = T38_TIMED_STEP_NONE; | |
975 fe->current_tx_data_type = T38_DATA_NONE; | |
976 break; | |
977 case T30_MODEM_PAUSE: | |
978 fe->next_tx_samples = fe->samples + ms_to_samples(short_train); | |
979 fe->timed_step = T38_TIMED_STEP_PAUSE; | |
980 fe->current_tx_data_type = T38_DATA_NONE; | |
981 break; | |
982 case T30_MODEM_CED: | |
983 fe->next_tx_samples = fe->samples; | |
984 fe->timed_step = T38_TIMED_STEP_CED; | |
985 fe->current_tx_data_type = T38_DATA_NONE; | |
986 break; | |
987 case T30_MODEM_CNG: | |
988 fe->next_tx_samples = fe->samples; | |
989 fe->timed_step = T38_TIMED_STEP_CNG; | |
990 fe->current_tx_data_type = T38_DATA_NONE; | |
991 break; | |
992 case T30_MODEM_V21: | |
993 fe->next_tx_indicator = T38_IND_V21_PREAMBLE; | |
994 fe->current_tx_data_type = T38_DATA_V21; | |
995 start_tx(fe, use_hdlc); | |
996 break; | |
997 case T30_MODEM_V27TER: | |
998 switch (bit_rate) | |
999 { | |
1000 case 2400: | |
1001 fe->next_tx_indicator = T38_IND_V27TER_2400_TRAINING; | |
1002 fe->current_tx_data_type = T38_DATA_V27TER_2400; | |
1003 break; | |
1004 case 4800: | |
1005 fe->next_tx_indicator = T38_IND_V27TER_4800_TRAINING; | |
1006 fe->current_tx_data_type = T38_DATA_V27TER_4800; | |
1007 break; | |
1008 } | |
1009 start_tx(fe, use_hdlc); | |
1010 break; | |
1011 case T30_MODEM_V29: | |
1012 switch (bit_rate) | |
1013 { | |
1014 case 7200: | |
1015 fe->next_tx_indicator = T38_IND_V29_7200_TRAINING; | |
1016 fe->current_tx_data_type = T38_DATA_V29_7200; | |
1017 break; | |
1018 case 9600: | |
1019 fe->next_tx_indicator = T38_IND_V29_9600_TRAINING; | |
1020 fe->current_tx_data_type = T38_DATA_V29_9600; | |
1021 break; | |
1022 } | |
1023 start_tx(fe, use_hdlc); | |
1024 break; | |
1025 case T30_MODEM_V17: | |
1026 switch (bit_rate) | |
1027 { | |
1028 case 7200: | |
1029 fe->next_tx_indicator = (short_train) ? T38_IND_V17_7200_SHORT_TRAINING : T38_IND_V17_7200_LONG_TRAINING; | |
1030 fe->current_tx_data_type = T38_DATA_V17_7200; | |
1031 break; | |
1032 case 9600: | |
1033 fe->next_tx_indicator = (short_train) ? T38_IND_V17_9600_SHORT_TRAINING : T38_IND_V17_9600_LONG_TRAINING; | |
1034 fe->current_tx_data_type = T38_DATA_V17_9600; | |
1035 break; | |
1036 case 12000: | |
1037 fe->next_tx_indicator = (short_train) ? T38_IND_V17_12000_SHORT_TRAINING : T38_IND_V17_12000_LONG_TRAINING; | |
1038 fe->current_tx_data_type = T38_DATA_V17_12000; | |
1039 break; | |
1040 case 14400: | |
1041 fe->next_tx_indicator = (short_train) ? T38_IND_V17_14400_SHORT_TRAINING : T38_IND_V17_14400_LONG_TRAINING; | |
1042 fe->current_tx_data_type = T38_DATA_V17_14400; | |
1043 break; | |
1044 } | |
1045 start_tx(fe, use_hdlc); | |
1046 break; | |
1047 case T30_MODEM_DONE: | |
1048 span_log(&s->logging, SPAN_LOG_FLOW, "FAX exchange complete\n"); | |
1049 fe->timed_step = T38_TIMED_STEP_NONE; | |
1050 fe->current_tx_data_type = T38_DATA_NONE; | |
1051 break; | |
1052 } | |
1053 fe->current_tx_type = type; | |
1054 } | |
1055 /*- End of function --------------------------------------------------------*/ | |
1056 | |
1057 SPAN_DECLARE(void) t38_terminal_set_config(t38_terminal_state_t *s, int without_pacing) | |
1058 { | |
1059 if (without_pacing) | |
1060 { | |
1061 /* Continuous streaming mode, as used for TPKT over TCP transport */ | |
1062 /* Inhibit indicator packets */ | |
1063 t38_set_redundancy_control(&s->t38_fe.t38, T38_PACKET_CATEGORY_INDICATOR, 0); | |
1064 t38_set_redundancy_control(&s->t38_fe.t38, T38_PACKET_CATEGORY_CONTROL_DATA, 1); | |
1065 t38_set_redundancy_control(&s->t38_fe.t38, T38_PACKET_CATEGORY_CONTROL_DATA_END, 1); | |
1066 t38_set_redundancy_control(&s->t38_fe.t38, T38_PACKET_CATEGORY_IMAGE_DATA, 1); | |
1067 t38_set_redundancy_control(&s->t38_fe.t38, T38_PACKET_CATEGORY_IMAGE_DATA_END, 1); | |
1068 s->t38_fe.ms_per_tx_chunk = 0; | |
1069 } | |
1070 else | |
1071 { | |
1072 /* Paced streaming mode, as used for UDP transports */ | |
1073 t38_set_redundancy_control(&s->t38_fe.t38, T38_PACKET_CATEGORY_INDICATOR, INDICATOR_TX_COUNT); | |
1074 t38_set_redundancy_control(&s->t38_fe.t38, T38_PACKET_CATEGORY_CONTROL_DATA, DATA_TX_COUNT); | |
1075 t38_set_redundancy_control(&s->t38_fe.t38, T38_PACKET_CATEGORY_CONTROL_DATA_END, DATA_END_TX_COUNT); | |
1076 t38_set_redundancy_control(&s->t38_fe.t38, T38_PACKET_CATEGORY_IMAGE_DATA, DATA_TX_COUNT); | |
1077 t38_set_redundancy_control(&s->t38_fe.t38, T38_PACKET_CATEGORY_IMAGE_DATA_END, DATA_END_TX_COUNT); | |
1078 s->t38_fe.ms_per_tx_chunk = MS_PER_TX_CHUNK; | |
1079 } | |
1080 set_octets_per_data_packet(s, 300); | |
1081 } | |
1082 /*- End of function --------------------------------------------------------*/ | |
1083 | |
1084 SPAN_DECLARE(void) t38_terminal_set_tep_mode(t38_terminal_state_t *s, int use_tep) | |
1085 { | |
1086 if (use_tep) | |
1087 s->t38_fe.chunking_modes |= T38_CHUNKING_ALLOW_TEP_TIME; | |
1088 else | |
1089 s->t38_fe.chunking_modes &= ~T38_CHUNKING_ALLOW_TEP_TIME; | |
1090 t38_set_tep_handling(&s->t38_fe.t38, use_tep); | |
1091 } | |
1092 /*- End of function --------------------------------------------------------*/ | |
1093 | |
1094 SPAN_DECLARE(void) t38_terminal_set_fill_bit_removal(t38_terminal_state_t *s, int remove) | |
1095 { | |
1096 if (remove) | |
1097 s->t38_fe.iaf |= T30_IAF_MODE_NO_FILL_BITS; | |
1098 else | |
1099 s->t38_fe.iaf &= ~T30_IAF_MODE_NO_FILL_BITS; | |
1100 t30_set_iaf_mode(&s->t30, s->t38_fe.iaf); | |
1101 } | |
1102 /*- End of function --------------------------------------------------------*/ | |
1103 | |
1104 SPAN_DECLARE(t30_state_t *) t38_terminal_get_t30_state(t38_terminal_state_t *s) | |
1105 { | |
1106 return &s->t30; | |
1107 } | |
1108 /*- End of function --------------------------------------------------------*/ | |
1109 | |
1110 SPAN_DECLARE(t38_core_state_t *) t38_terminal_get_t38_core_state(t38_terminal_state_t *s) | |
1111 { | |
1112 return &s->t38_fe.t38; | |
1113 } | |
1114 /*- End of function --------------------------------------------------------*/ | |
1115 | |
1116 static int t38_terminal_t38_fe_init(t38_terminal_state_t *t, | |
1117 t38_tx_packet_handler_t *tx_packet_handler, | |
1118 void *tx_packet_user_data) | |
1119 { | |
1120 t38_terminal_front_end_state_t *s; | |
1121 | |
1122 s = &t->t38_fe; | |
1123 t38_core_init(&s->t38, | |
1124 process_rx_indicator, | |
1125 process_rx_data, | |
1126 process_rx_missing, | |
1127 (void *) t, | |
1128 tx_packet_handler, | |
1129 tx_packet_user_data); | |
1130 t38_set_fastest_image_data_rate(&s->t38, 14400); | |
1131 | |
1132 s->rx_signal_present = FALSE; | |
1133 s->timed_step = T38_TIMED_STEP_NONE; | |
1134 //s->iaf = T30_IAF_MODE_T37 | T30_IAF_MODE_T38; | |
1135 s->iaf = T30_IAF_MODE_T38; | |
1136 | |
1137 s->current_tx_data_type = T38_DATA_NONE; | |
1138 s->next_tx_samples = 0; | |
1139 s->chunking_modes = T38_CHUNKING_ALLOW_TEP_TIME; | |
1140 | |
1141 s->hdlc_tx.ptr = 0; | |
1142 | |
1143 return 0; | |
1144 } | |
1145 /*- End of function --------------------------------------------------------*/ | |
1146 | |
1147 SPAN_DECLARE(logging_state_t *) t38_terminal_get_logging_state(t38_terminal_state_t *s) | |
1148 { | |
1149 return &s->logging; | |
1150 } | |
1151 /*- End of function --------------------------------------------------------*/ | |
1152 | |
1153 SPAN_DECLARE(t38_terminal_state_t *) t38_terminal_init(t38_terminal_state_t *s, | |
1154 int calling_party, | |
1155 t38_tx_packet_handler_t *tx_packet_handler, | |
1156 void *tx_packet_user_data) | |
1157 { | |
1158 if (tx_packet_handler == NULL) | |
1159 return NULL; | |
1160 | |
1161 if (s == NULL) | |
1162 { | |
1163 if ((s = (t38_terminal_state_t *) malloc(sizeof(*s))) == NULL) | |
1164 return NULL; | |
1165 } | |
1166 memset(s, 0, sizeof(*s)); | |
1167 span_log_init(&s->logging, SPAN_LOG_NONE, NULL); | |
1168 span_log_set_protocol(&s->logging, "T.38T"); | |
1169 | |
1170 t38_terminal_t38_fe_init(s, tx_packet_handler, tx_packet_user_data); | |
1171 | |
1172 t38_terminal_set_config(s, FALSE); | |
1173 | |
1174 t30_init(&s->t30, | |
1175 calling_party, | |
1176 set_rx_type, | |
1177 (void *) s, | |
1178 set_tx_type, | |
1179 (void *) s, | |
1180 send_hdlc, | |
1181 (void *) s); | |
1182 t30_set_iaf_mode(&s->t30, s->t38_fe.iaf); | |
1183 t30_set_supported_modems(&s->t30, | |
1184 T30_SUPPORT_V27TER | T30_SUPPORT_V29 | T30_SUPPORT_V17 | T30_SUPPORT_IAF); | |
1185 t30_restart(&s->t30); | |
1186 return s; | |
1187 } | |
1188 /*- End of function --------------------------------------------------------*/ | |
1189 | |
1190 SPAN_DECLARE(int) t38_terminal_release(t38_terminal_state_t *s) | |
1191 { | |
1192 t30_release(&s->t30); | |
1193 return 0; | |
1194 } | |
1195 /*- End of function --------------------------------------------------------*/ | |
1196 | |
1197 SPAN_DECLARE(int) t38_terminal_free(t38_terminal_state_t *s) | |
1198 { | |
1199 t38_terminal_release(s); | |
1200 free(s); | |
1201 return 0; | |
1202 } | |
1203 /*- End of function --------------------------------------------------------*/ | |
1204 /*- End of file ------------------------------------------------------------*/ |