5
|
1 /*
|
|
2 * SpanDSP - a series of DSP components for telephony
|
|
3 *
|
|
4 * t38_gateway.c - An implementation of a T.38 gateway, less the packet exchange part
|
|
5 *
|
|
6 * Written by Steve Underwood <steveu@coppice.org>
|
|
7 *
|
|
8 * Copyright (C) 2005, 2006 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 General Public License version 2, as
|
|
14 * 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 General Public License for more details.
|
|
20 *
|
|
21 * You should have received a copy of the GNU General Public License
|
|
22 * 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_gateway.c,v 1.62 2006/12/08 12:47:29 steveu Exp $
|
|
26 */
|
|
27
|
|
28 /*! \file */
|
|
29
|
|
30 #ifdef 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 <assert.h>
|
|
47 #include <tiffio.h>
|
|
48
|
|
49 #include "spandsp/telephony.h"
|
|
50 #include "spandsp/logging.h"
|
|
51 #include "spandsp/queue.h"
|
|
52 #include "spandsp/bit_operations.h"
|
|
53 #include "spandsp/power_meter.h"
|
|
54 #include "spandsp/complex.h"
|
|
55 #include "spandsp/tone_generate.h"
|
|
56 #include "spandsp/async.h"
|
|
57 #include "spandsp/hdlc.h"
|
|
58 #include "spandsp/silence_gen.h"
|
|
59 #include "spandsp/fsk.h"
|
|
60 #include "spandsp/v29rx.h"
|
|
61 #include "spandsp/v29tx.h"
|
|
62 #include "spandsp/v27ter_rx.h"
|
|
63 #include "spandsp/v27ter_tx.h"
|
|
64 #if defined(ENABLE_V17)
|
|
65 #include "spandsp/v17rx.h"
|
|
66 #include "spandsp/v17tx.h"
|
|
67 #endif
|
|
68 #include "spandsp/t4.h"
|
|
69
|
|
70 #include "spandsp/t30_fcf.h"
|
|
71 #include "spandsp/t35.h"
|
|
72 #include "spandsp/t30.h"
|
|
73
|
|
74 #include "spandsp/t38_core.h"
|
|
75 #include "spandsp/t38_gateway.h"
|
|
76
|
|
77 #define MS_PER_TX_CHUNK 30
|
|
78
|
|
79 #define INDICATOR_TX_COUNT 3
|
|
80
|
|
81 #define DISBIT1 0x01
|
|
82 #define DISBIT2 0x02
|
|
83 #define DISBIT3 0x04
|
|
84 #define DISBIT4 0x08
|
|
85 #define DISBIT5 0x10
|
|
86 #define DISBIT6 0x20
|
|
87 #define DISBIT7 0x40
|
|
88 #define DISBIT8 0x80
|
|
89
|
|
90 enum
|
|
91 {
|
|
92 T38_NONE,
|
|
93 T38_V27TER_RX,
|
|
94 T38_V29_RX,
|
|
95 T38_V17_RX
|
|
96 };
|
|
97
|
|
98 enum
|
|
99 {
|
|
100 HDLC_FLAG_FINISHED = 0x01,
|
|
101 HDLC_FLAG_CORRUPT_CRC = 0x02,
|
|
102 HDLC_FLAG_PROCEED_WITH_OUTPUT = 0x04,
|
|
103 HDLC_FLAG_MISSING_DATA = 0x08
|
|
104 };
|
|
105
|
|
106 static int restart_rx_modem(t38_gateway_state_t *s);
|
|
107 static void add_to_non_ecm_tx_buffer(t38_gateway_state_t *s, const uint8_t *buf, int len);
|
|
108 static int non_ecm_get_bit(void *user_data);
|
|
109 static int process_rx_indicator(t38_core_state_t *t, void *user_data, int indicator);
|
|
110
|
|
111 static void hdlc_underflow_handler(void *user_data)
|
|
112 {
|
|
113 t38_gateway_state_t *s;
|
|
114 int old_data_type;
|
|
115
|
|
116 s = (t38_gateway_state_t *) user_data;
|
|
117 span_log(&s->logging, SPAN_LOG_FLOW, "HDLC underflow at %d\n", s->hdlc_out);
|
|
118 /* If the current HDLC buffer is not at the HDLC_FLAG_PROCEED_WITH_OUTPUT stage, this
|
|
119 underflow must be an end of preamble condition. */
|
|
120 if ((s->hdlc_flags[s->hdlc_out] & HDLC_FLAG_PROCEED_WITH_OUTPUT))
|
|
121 {
|
|
122 old_data_type = s->hdlc_contents[s->hdlc_out];
|
|
123 s->hdlc_len[s->hdlc_out] = 0;
|
|
124 s->hdlc_flags[s->hdlc_out] = 0;
|
|
125 s->hdlc_contents[s->hdlc_out] = 0;
|
|
126 if (++s->hdlc_out >= T38_TX_HDLC_BUFS)
|
|
127 s->hdlc_out = 0;
|
|
128 span_log(&s->logging, SPAN_LOG_FLOW, "HDLC next is 0x%X\n", s->hdlc_contents[s->hdlc_out]);
|
|
129 if ((s->hdlc_contents[s->hdlc_out] & 0x100))
|
|
130 {
|
|
131 /* The next thing in the queue is an indicator, so we need to stop this modem. */
|
|
132 span_log(&s->logging, SPAN_LOG_FLOW, "HDLC shutdown\n");
|
|
133 hdlc_tx_frame(&s->hdlctx, NULL, 0);
|
|
134 }
|
|
135 else if ((s->hdlc_contents[s->hdlc_out] & 0x200))
|
|
136 {
|
|
137 /* Check if we should start sending the next frame */
|
|
138 if ((s->hdlc_flags[s->hdlc_out] & HDLC_FLAG_PROCEED_WITH_OUTPUT))
|
|
139 {
|
|
140 /* This frame is ready to go, and uses the same modem we are running now. So, send
|
|
141 whatever we have. This might or might not be an entire frame. */
|
|
142 span_log(&s->logging, SPAN_LOG_FLOW, "HDLC start next frame\n");
|
|
143 hdlc_tx_frame(&s->hdlctx, s->hdlc_buf[s->hdlc_out], s->hdlc_len[s->hdlc_out]);
|
|
144 if ((s->hdlc_flags[s->hdlc_out] & HDLC_FLAG_CORRUPT_CRC))
|
|
145 hdlc_tx_corrupt_frame(&s->hdlctx);
|
|
146 }
|
|
147 }
|
|
148 }
|
|
149 }
|
|
150 /*- End of function --------------------------------------------------------*/
|
|
151
|
|
152 static int set_next_tx_type(t38_gateway_state_t *s)
|
|
153 {
|
|
154 tone_gen_descriptor_t tone_desc;
|
|
155 get_bit_func_t get_bit_func;
|
|
156 void *get_bit_user_data;
|
|
157 int indicator;
|
|
158
|
|
159 if (s->next_tx_handler)
|
|
160 {
|
|
161 /* There is a handler queued, so that is the next one */
|
|
162 s->tx_handler = s->next_tx_handler;
|
|
163 s->tx_user_data = s->next_tx_user_data;
|
|
164 s->next_tx_handler = NULL;
|
|
165 return TRUE;
|
|
166 }
|
|
167 if (s->hdlc_in == s->hdlc_out)
|
|
168 return FALSE;
|
|
169 if ((s->hdlc_contents[s->hdlc_out] & 0x100) == 0)
|
|
170 return FALSE;
|
|
171 indicator = (s->hdlc_contents[s->hdlc_out] & 0xFF);
|
|
172 s->hdlc_len[s->hdlc_out] = 0;
|
|
173 s->hdlc_flags[s->hdlc_out] = 0;
|
|
174 s->hdlc_contents[s->hdlc_out] = 0;
|
|
175 if (++s->hdlc_out >= T38_TX_HDLC_BUFS)
|
|
176 s->hdlc_out = 0;
|
|
177 span_log(&s->logging, SPAN_LOG_FLOW, "Changing to %s\n", t38_indicator(indicator));
|
|
178 if (s->short_train && s->ecm_mode)
|
|
179 {
|
|
180 span_log(&s->logging, SPAN_LOG_FLOW, "HDLC mode\n");
|
|
181 hdlc_tx_init(&s->hdlctx, FALSE, 2, TRUE, hdlc_underflow_handler, s);
|
|
182 get_bit_func = (get_bit_func_t) hdlc_tx_get_bit;
|
|
183 get_bit_user_data = (void *) &s->hdlctx;
|
|
184 }
|
|
185 else
|
|
186 {
|
|
187 span_log(&s->logging, SPAN_LOG_FLOW, "non-ECM mode\n");
|
|
188 get_bit_func = non_ecm_get_bit;
|
|
189 get_bit_user_data = (void *) s;
|
|
190 }
|
|
191 switch (indicator)
|
|
192 {
|
|
193 case T38_IND_NO_SIGNAL:
|
|
194 /* Impose 75ms minimum on transmitted silence */
|
|
195 silence_gen_set(&s->silence_gen, ms_to_samples(75));
|
|
196 s->tx_handler = (span_tx_handler_t *) &(silence_gen);
|
|
197 s->tx_user_data = &(s->silence_gen);
|
|
198 s->next_tx_handler = NULL;
|
|
199 break;
|
|
200 case T38_IND_CNG:
|
|
201 /* 0.5s of 1100Hz + 3.0s of silence repeating */
|
|
202 make_tone_gen_descriptor(&tone_desc,
|
|
203 1100,
|
|
204 -11,
|
|
205 0,
|
|
206 0,
|
|
207 500,
|
|
208 3000,
|
|
209 0,
|
|
210 0,
|
|
211 TRUE);
|
|
212 tone_gen_init(&(s->tone_gen), &tone_desc);
|
|
213 s->tx_handler = (span_tx_handler_t *) &(tone_gen);
|
|
214 s->tx_user_data = &(s->tone_gen);
|
|
215 silence_gen_set(&s->silence_gen, 0);
|
|
216 s->next_tx_handler = (span_tx_handler_t *) &(silence_gen);
|
|
217 s->next_tx_user_data = &(s->silence_gen);
|
|
218 break;
|
|
219 case T38_IND_CED:
|
|
220 /* 0.2s of silence, then 2.6s to 4s of 2100Hz tone, then 75ms of silence. */
|
|
221 silence_gen_alter(&s->silence_gen, ms_to_samples(200));
|
|
222 make_tone_gen_descriptor(&tone_desc,
|
|
223 2100,
|
|
224 -11,
|
|
225 0,
|
|
226 0,
|
|
227 2600,
|
|
228 75,
|
|
229 0,
|
|
230 0,
|
|
231 FALSE);
|
|
232 tone_gen_init(&(s->tone_gen), &tone_desc);
|
|
233 s->tx_handler = (span_tx_handler_t *) &(silence_gen);
|
|
234 s->tx_user_data = &(s->silence_gen);
|
|
235 s->next_tx_handler = (span_tx_handler_t *) &(tone_gen);
|
|
236 s->next_tx_user_data = &(s->tone_gen);
|
|
237 break;
|
|
238 case T38_IND_V21_PREAMBLE:
|
|
239 hdlc_tx_init(&s->hdlctx, FALSE, 2, TRUE, hdlc_underflow_handler, s);
|
|
240 hdlc_tx_preamble(&s->hdlctx, 32);
|
|
241 s->hdlc_len[s->hdlc_in] = 0;
|
|
242 fsk_tx_init(&(s->v21tx), &preset_fsk_specs[FSK_V21CH2], (get_bit_func_t) hdlc_tx_get_bit, &s->hdlctx);
|
|
243 /* Impose a minimum silence */
|
|
244 silence_gen_alter(&s->silence_gen, ms_to_samples(75));
|
|
245 s->tx_handler = (span_tx_handler_t *) &(silence_gen);
|
|
246 s->tx_user_data = &(s->silence_gen);
|
|
247 s->next_tx_handler = (span_tx_handler_t *) &(fsk_tx);
|
|
248 s->next_tx_user_data = &(s->v21tx);
|
|
249 break;
|
|
250 case T38_IND_V27TER_2400_TRAINING:
|
|
251 silence_gen_alter(&s->silence_gen, ms_to_samples(75));
|
|
252 hdlc_tx_preamble(&s->hdlctx, 60);
|
|
253 v27ter_tx_restart(&(s->v27ter_tx), 2400, s->use_tep);
|
|
254 v27ter_tx_set_get_bit(&(s->v27ter_tx), get_bit_func, get_bit_user_data);
|
|
255 s->tx_handler = (span_tx_handler_t *) &(silence_gen);
|
|
256 s->tx_user_data = &(s->silence_gen);
|
|
257 s->next_tx_handler = (span_tx_handler_t *) &(v27ter_tx);
|
|
258 s->next_tx_user_data = &(s->v27ter_tx);
|
|
259 break;
|
|
260 case T38_IND_V27TER_4800_TRAINING:
|
|
261 hdlc_tx_preamble(&s->hdlctx, 120);
|
|
262 silence_gen_alter(&s->silence_gen, ms_to_samples(75));
|
|
263 v27ter_tx_restart(&(s->v27ter_tx), 4800, s->use_tep);
|
|
264 v27ter_tx_set_get_bit(&(s->v27ter_tx), get_bit_func, get_bit_user_data);
|
|
265 s->tx_handler = (span_tx_handler_t *) &(silence_gen);
|
|
266 s->tx_user_data = &(s->silence_gen);
|
|
267 s->next_tx_handler = (span_tx_handler_t *) &(v27ter_tx);
|
|
268 s->next_tx_user_data = &(s->v27ter_tx);
|
|
269 break;
|
|
270 case T38_IND_V29_7200_TRAINING:
|
|
271 hdlc_tx_preamble(&s->hdlctx, 180);
|
|
272 silence_gen_alter(&s->silence_gen, ms_to_samples(75));
|
|
273 v29_tx_restart(&(s->v29tx), 7200, s->use_tep);
|
|
274 v29_tx_set_get_bit(&(s->v29tx), get_bit_func, get_bit_user_data);
|
|
275 s->tx_handler = (span_tx_handler_t *) &(silence_gen);
|
|
276 s->tx_user_data = &(s->silence_gen);
|
|
277 s->next_tx_handler = (span_tx_handler_t *) &(v29_tx);
|
|
278 s->next_tx_user_data = &(s->v29tx);
|
|
279 break;
|
|
280 case T38_IND_V29_9600_TRAINING:
|
|
281 hdlc_tx_preamble(&s->hdlctx, 240);
|
|
282 silence_gen_alter(&s->silence_gen, ms_to_samples(75));
|
|
283 v29_tx_restart(&(s->v29tx), 9600, s->use_tep);
|
|
284 v29_tx_set_get_bit(&(s->v29tx), get_bit_func, get_bit_user_data);
|
|
285 s->tx_handler = (span_tx_handler_t *) &(silence_gen);
|
|
286 s->tx_user_data = &(s->silence_gen);
|
|
287 s->next_tx_handler = (span_tx_handler_t *) &(v29_tx);
|
|
288 s->next_tx_user_data = &(s->v29tx);
|
|
289 break;
|
|
290 #if defined(ENABLE_V17)
|
|
291 case T38_IND_V17_7200_SHORT_TRAINING:
|
|
292 hdlc_tx_preamble(&s->hdlctx, 180);
|
|
293 silence_gen_alter(&s->silence_gen, ms_to_samples(75));
|
|
294 v17_tx_restart(&(s->v17tx), 7200, s->use_tep, s->short_train);
|
|
295 v17_tx_set_get_bit(&(s->v17tx), get_bit_func, get_bit_user_data);
|
|
296 s->tx_handler = (span_tx_handler_t *) &(silence_gen);
|
|
297 s->tx_user_data = &(s->silence_gen);
|
|
298 s->next_tx_handler = (span_tx_handler_t *) &(v17_tx);
|
|
299 s->next_tx_user_data = &(s->v17tx);
|
|
300 break;
|
|
301 case T38_IND_V17_7200_LONG_TRAINING:
|
|
302 hdlc_tx_preamble(&s->hdlctx, 180);
|
|
303 silence_gen_alter(&s->silence_gen, ms_to_samples(75));
|
|
304 v17_tx_restart(&(s->v17tx), 7200, s->use_tep, s->short_train);
|
|
305 v17_tx_set_get_bit(&(s->v17tx), get_bit_func, get_bit_user_data);
|
|
306 s->tx_handler = (span_tx_handler_t *) &(silence_gen);
|
|
307 s->tx_user_data = &(s->silence_gen);
|
|
308 s->next_tx_handler = (span_tx_handler_t *) &(v17_tx);
|
|
309 s->next_tx_user_data = &(s->v17tx);
|
|
310 break;
|
|
311 case T38_IND_V17_9600_SHORT_TRAINING:
|
|
312 hdlc_tx_preamble(&s->hdlctx, 240);
|
|
313 silence_gen_alter(&s->silence_gen, ms_to_samples(75));
|
|
314 v17_tx_restart(&(s->v17tx), 9600, s->use_tep, s->short_train);
|
|
315 v17_tx_set_get_bit(&(s->v17tx), get_bit_func, get_bit_user_data);
|
|
316 s->tx_handler = (span_tx_handler_t *) &(silence_gen);
|
|
317 s->tx_user_data = &(s->silence_gen);
|
|
318 s->next_tx_handler = (span_tx_handler_t *) &(v17_tx);
|
|
319 s->next_tx_user_data = &(s->v17tx);
|
|
320 break;
|
|
321 case T38_IND_V17_9600_LONG_TRAINING:
|
|
322 hdlc_tx_preamble(&s->hdlctx, 240);
|
|
323 silence_gen_alter(&s->silence_gen, ms_to_samples(75));
|
|
324 v17_tx_restart(&(s->v17tx), 9600, s->use_tep, s->short_train);
|
|
325 v17_tx_set_get_bit(&(s->v17tx), get_bit_func, get_bit_user_data);
|
|
326 s->tx_handler = (span_tx_handler_t *) &(silence_gen);
|
|
327 s->tx_user_data = &(s->silence_gen);
|
|
328 s->next_tx_handler = (span_tx_handler_t *) &(v17_tx);
|
|
329 s->next_tx_user_data = &(s->v17tx);
|
|
330 break;
|
|
331 case T38_IND_V17_12000_SHORT_TRAINING:
|
|
332 hdlc_tx_preamble(&s->hdlctx, 300);
|
|
333 silence_gen_alter(&s->silence_gen, ms_to_samples(75));
|
|
334 v17_tx_restart(&(s->v17tx), 12000, s->use_tep, s->short_train);
|
|
335 v17_tx_set_get_bit(&(s->v17tx), get_bit_func, get_bit_user_data);
|
|
336 s->tx_handler = (span_tx_handler_t *) &(silence_gen);
|
|
337 s->tx_user_data = &(s->silence_gen);
|
|
338 s->next_tx_handler = (span_tx_handler_t *) &(v17_tx);
|
|
339 s->next_tx_user_data = &(s->v17tx);
|
|
340 break;
|
|
341 case T38_IND_V17_12000_LONG_TRAINING:
|
|
342 hdlc_tx_preamble(&s->hdlctx, 300);
|
|
343 silence_gen_alter(&s->silence_gen, ms_to_samples(75));
|
|
344 v17_tx_restart(&(s->v17tx), 12000, s->use_tep, s->short_train);
|
|
345 v17_tx_set_get_bit(&(s->v17tx), get_bit_func, get_bit_user_data);
|
|
346 s->tx_handler = (span_tx_handler_t *) &(silence_gen);
|
|
347 s->tx_user_data = &(s->silence_gen);
|
|
348 s->next_tx_handler = (span_tx_handler_t *) &(v17_tx);
|
|
349 s->next_tx_user_data = &(s->v17tx);
|
|
350 break;
|
|
351 case T38_IND_V17_14400_SHORT_TRAINING:
|
|
352 hdlc_tx_preamble(&s->hdlctx, 360);
|
|
353 silence_gen_alter(&s->silence_gen, ms_to_samples(75));
|
|
354 v17_tx_restart(&(s->v17tx), 14400, s->use_tep, s->short_train);
|
|
355 v17_tx_set_get_bit(&(s->v17tx), get_bit_func, get_bit_user_data);
|
|
356 s->tx_handler = (span_tx_handler_t *) &(silence_gen);
|
|
357 s->tx_user_data = &(s->silence_gen);
|
|
358 s->next_tx_handler = (span_tx_handler_t *) &(v17_tx);
|
|
359 s->next_tx_user_data = &(s->v17tx);
|
|
360 break;
|
|
361 case T38_IND_V17_14400_LONG_TRAINING:
|
|
362 hdlc_tx_preamble(&s->hdlctx, 360);
|
|
363 silence_gen_alter(&s->silence_gen, ms_to_samples(75));
|
|
364 v17_tx_restart(&(s->v17tx), 14400, s->use_tep, s->short_train);
|
|
365 v17_tx_set_get_bit(&(s->v17tx), get_bit_func, get_bit_user_data);
|
|
366 s->tx_handler = (span_tx_handler_t *) &(silence_gen);
|
|
367 s->tx_user_data = &(s->silence_gen);
|
|
368 s->next_tx_handler = (span_tx_handler_t *) &(v17_tx);
|
|
369 s->next_tx_user_data = &(s->v17tx);
|
|
370 break;
|
|
371 #endif
|
|
372 case T38_IND_V8_ANSAM:
|
|
373 break;
|
|
374 case T38_IND_V8_SIGNAL:
|
|
375 break;
|
|
376 case T38_IND_V34_CNTL_CHANNEL_1200:
|
|
377 break;
|
|
378 case T38_IND_V34_PRI_CHANNEL:
|
|
379 break;
|
|
380 case T38_IND_V34_CC_RETRAIN:
|
|
381 break;
|
|
382 case T38_IND_V33_12000_TRAINING:
|
|
383 break;
|
|
384 case T38_IND_V33_14400_TRAINING:
|
|
385 break;
|
|
386 default:
|
|
387 break;
|
|
388 }
|
|
389 s->non_ecm_bit_no = 0;
|
|
390 s->current_non_ecm_octet = 0xFF;
|
|
391 s->non_ecm_flow_control_fill_octet = 0xFF;
|
|
392 s->non_ecm_at_initial_all_ones = TRUE;
|
|
393 s->bit_stream = 0;
|
|
394 if (s->non_ecm_flow_control_fill_octets)
|
|
395 {
|
|
396 span_log(&s->logging, SPAN_LOG_WARNING, "Flow control generated %d octets\n", s->non_ecm_flow_control_fill_octets);
|
|
397 s->non_ecm_flow_control_fill_octets = 0;
|
|
398 }
|
|
399 s->in_progress_rx_indicator = indicator;
|
|
400 return TRUE;
|
|
401 }
|
|
402 /*- End of function --------------------------------------------------------*/
|
|
403
|
|
404 static void pump_out_final_hdlc(t38_gateway_state_t *s, int good_fcs)
|
|
405 {
|
|
406 if (!good_fcs)
|
|
407 s->hdlc_flags[s->hdlc_in] |= HDLC_FLAG_CORRUPT_CRC;
|
|
408 if (s->hdlc_in == s->hdlc_out)
|
|
409 {
|
|
410 /* This is the frame in progress at the output. */
|
|
411 if ((s->hdlc_flags[s->hdlc_out] & HDLC_FLAG_PROCEED_WITH_OUTPUT) == 0)
|
|
412 {
|
|
413 /* Output of this frame has not yet begun. Throw it all out now. */
|
|
414 hdlc_tx_frame(&s->hdlctx, s->hdlc_buf[s->hdlc_out], s->hdlc_len[s->hdlc_out]);
|
|
415 }
|
|
416 if ((s->hdlc_flags[s->hdlc_out] & HDLC_FLAG_CORRUPT_CRC))
|
|
417 hdlc_tx_corrupt_frame(&s->hdlctx);
|
|
418 }
|
|
419 s->hdlc_flags[s->hdlc_in] |= (HDLC_FLAG_PROCEED_WITH_OUTPUT | HDLC_FLAG_FINISHED);
|
|
420 if (++s->hdlc_in >= T38_TX_HDLC_BUFS)
|
|
421 s->hdlc_in = 0;
|
|
422 }
|
|
423 /*- End of function --------------------------------------------------------*/
|
|
424
|
|
425 static void constrain_fast_modem(t38_gateway_state_t *s, uint8_t *buf, int len)
|
|
426 {
|
|
427 /* We may need to adjust the capabilities, so they do not exceed our own */
|
|
428 if (len < 5)
|
|
429 return;
|
|
430 /* TODO: fiddle the contents */
|
|
431 switch (buf[4] & (DISBIT6 | DISBIT5 | DISBIT4 | DISBIT3))
|
|
432 {
|
|
433 case 0:
|
|
434 case DISBIT4:
|
|
435 /* V.27ter only */
|
|
436 break;
|
|
437 case DISBIT3:
|
|
438 case (DISBIT4 | DISBIT3):
|
|
439 /* V.27ter and V.29 */
|
|
440 break;
|
|
441 case (DISBIT6 | DISBIT4 | DISBIT3):
|
|
442 /* V.27ter, V.29 and V.17 */
|
|
443 #if !defined(ENABLE_V17)
|
|
444 buf[4] &= ~DISBIT6;
|
|
445 #endif
|
|
446 break;
|
|
447 case (DISBIT5 | DISBIT4):
|
|
448 case (DISBIT6 | DISBIT4):
|
|
449 case (DISBIT6 | DISBIT5 | DISBIT4):
|
|
450 case (DISBIT6 | DISBIT5 | DISBIT4 | DISBIT3):
|
|
451 /* Reserved */
|
|
452 buf[4] &= ~(DISBIT6 | DISBIT5);
|
|
453 buf[4] |= (DISBIT4 | DISBIT3);
|
|
454 break;
|
|
455 default:
|
|
456 /* Not used */
|
|
457 buf[4] &= ~(DISBIT6 | DISBIT5);
|
|
458 buf[4] |= (DISBIT4 | DISBIT3);
|
|
459 break;
|
|
460 }
|
|
461 }
|
|
462 /*- End of function --------------------------------------------------------*/
|
|
463
|
|
464 static void monitor_control_messages(t38_gateway_state_t *s, uint8_t *buf, int len, int from_modem)
|
|
465 {
|
|
466 span_log(&s->logging, SPAN_LOG_FLOW, "monitor 0x%x\n", buf[2]);
|
|
467 if (len < 3)
|
|
468 return;
|
|
469 /* Monitor the control messages, so we can see what is happening to things like
|
|
470 training success/failure. */
|
|
471 switch (buf[2])
|
|
472 {
|
|
473 case T30_CFR:
|
|
474 /* We are changing from TCF exchange to image exchange */
|
|
475 /* Successful training means we should change to short training */
|
|
476 s->short_train = TRUE;
|
|
477 span_log(&s->logging, SPAN_LOG_FLOW, "CFR - short = %d, ECM = %d\n", s->short_train, s->ecm_mode);
|
|
478 if (!from_modem)
|
|
479 restart_rx_modem(s);
|
|
480 break;
|
|
481 case T30_RTP:
|
|
482 /* We are going back to the exchange of fresh TCF */
|
|
483 s->short_train = FALSE;
|
|
484 break;
|
|
485 case T30_DTC:
|
|
486 case T30_DCS:
|
|
487 case T30_DCS + 1:
|
|
488 /* We need to check which modem type is about to be used. */
|
|
489 switch (buf[4] & (DISBIT6 | DISBIT5 | DISBIT4 | DISBIT3))
|
|
490 {
|
|
491 case 0:
|
|
492 s->fast_bit_rate = 2400;
|
|
493 s->fast_modem = T38_V27TER_RX;
|
|
494 s->short_train = FALSE;
|
|
495 break;
|
|
496 case DISBIT4:
|
|
497 s->fast_bit_rate = 4800;
|
|
498 s->fast_modem = T38_V27TER_RX;
|
|
499 s->short_train = FALSE;
|
|
500 break;
|
|
501 case DISBIT3:
|
|
502 s->fast_bit_rate = 9600;
|
|
503 s->fast_modem = T38_V29_RX;
|
|
504 s->short_train = FALSE;
|
|
505 break;
|
|
506 case (DISBIT4 | DISBIT3):
|
|
507 s->fast_bit_rate = 7200;
|
|
508 s->fast_modem = T38_V29_RX;
|
|
509 s->short_train = FALSE;
|
|
510 break;
|
|
511 #if defined(ENABLE_V17)
|
|
512 case DISBIT6:
|
|
513 s->fast_bit_rate = 14400;
|
|
514 s->fast_modem = T38_V17_RX;
|
|
515 s->short_train = FALSE;
|
|
516 break;
|
|
517 case (DISBIT6 | DISBIT4):
|
|
518 s->fast_bit_rate = 12000;
|
|
519 s->fast_modem = T38_V17_RX;
|
|
520 s->short_train = FALSE;
|
|
521 break;
|
|
522 case (DISBIT6 | DISBIT3):
|
|
523 s->fast_bit_rate = 9600;
|
|
524 s->fast_modem = T38_V17_RX;
|
|
525 s->short_train = FALSE;
|
|
526 break;
|
|
527 case (DISBIT6 | DISBIT4 | DISBIT3):
|
|
528 s->fast_bit_rate = 7200;
|
|
529 s->fast_modem = T38_V17_RX;
|
|
530 s->short_train = FALSE;
|
|
531 break;
|
|
532 #endif
|
|
533 case (DISBIT5 | DISBIT3):
|
|
534 case (DISBIT5 | DISBIT4 | DISBIT3):
|
|
535 case (DISBIT6 | DISBIT5):
|
|
536 case (DISBIT6 | DISBIT5 | DISBIT3):
|
|
537 case (DISBIT6 | DISBIT5 | DISBIT4):
|
|
538 case (DISBIT6 | DISBIT5 | DISBIT4 | DISBIT3):
|
|
539 /* Reserved */
|
|
540 s->fast_bit_rate = 0;
|
|
541 s->fast_modem = T38_NONE;
|
|
542 break;
|
|
543 default:
|
|
544 /* Not used */
|
|
545 s->fast_bit_rate = 0;
|
|
546 s->fast_modem = T38_NONE;
|
|
547 break;
|
|
548 }
|
|
549 s->ecm_mode = (buf[6] & DISBIT3);
|
|
550 break;
|
|
551 default:
|
|
552 break;
|
|
553 }
|
|
554 }
|
|
555 /*- End of function --------------------------------------------------------*/
|
|
556
|
|
557 static void queue_missing_indicator(t38_gateway_state_t *s, int data_type)
|
|
558 {
|
|
559 t38_core_state_t *t;
|
|
560
|
|
561 t = &s->t38;
|
|
562 /* Missing packets might have lost us the indicator that should have put us in
|
|
563 the required mode of operation. It might be a bit late to fill in such a gap
|
|
564 now, but we should try. We may also want to force indicators into the queue,
|
|
565 such as when the data says 'end of signal'. */
|
|
566 switch (data_type)
|
|
567 {
|
|
568 case -1:
|
|
569 if (s->t38.current_rx_indicator != T38_IND_NO_SIGNAL)
|
|
570 process_rx_indicator(t, (void *) s, T38_IND_NO_SIGNAL);
|
|
571 break;
|
|
572 case T38_DATA_V21:
|
|
573 if (s->t38.current_rx_indicator != T38_IND_V21_PREAMBLE)
|
|
574 process_rx_indicator(t, (void *) s, T38_IND_V21_PREAMBLE);
|
|
575 break;
|
|
576 case T38_DATA_V27TER_2400:
|
|
577 if (s->t38.current_rx_indicator != T38_IND_V27TER_2400_TRAINING)
|
|
578 process_rx_indicator(t, (void *) s, T38_IND_V27TER_2400_TRAINING);
|
|
579 break;
|
|
580 case T38_DATA_V27TER_4800:
|
|
581 if (s->t38.current_rx_indicator != T38_IND_V27TER_4800_TRAINING)
|
|
582 process_rx_indicator(t, (void *) s, T38_IND_V27TER_4800_TRAINING);
|
|
583 break;
|
|
584 case T38_DATA_V29_7200:
|
|
585 if (s->t38.current_rx_indicator != T38_IND_V29_7200_TRAINING)
|
|
586 process_rx_indicator(t, (void *) s, T38_IND_V29_7200_TRAINING);
|
|
587 break;
|
|
588 case T38_DATA_V29_9600:
|
|
589 if (s->t38.current_rx_indicator != T38_IND_V29_9600_TRAINING)
|
|
590 process_rx_indicator(t, (void *) s, T38_IND_V29_9600_TRAINING);
|
|
591 break;
|
|
592 case T38_DATA_V17_7200:
|
|
593 if (s->t38.current_rx_indicator != T38_IND_V17_7200_SHORT_TRAINING && s->t38.current_rx_indicator != T38_IND_V17_7200_LONG_TRAINING)
|
|
594 process_rx_indicator(t, (void *) s, T38_IND_V17_7200_LONG_TRAINING);
|
|
595 break;
|
|
596 case T38_DATA_V17_9600:
|
|
597 if (s->t38.current_rx_indicator != T38_IND_V17_9600_SHORT_TRAINING && s->t38.current_rx_indicator != T38_IND_V17_9600_LONG_TRAINING)
|
|
598 process_rx_indicator(t, (void *) s, T38_IND_V17_9600_LONG_TRAINING);
|
|
599 break;
|
|
600 case T38_DATA_V17_12000:
|
|
601 if (s->t38.current_rx_indicator != T38_IND_V17_12000_SHORT_TRAINING && s->t38.current_rx_indicator != T38_IND_V17_12000_LONG_TRAINING)
|
|
602 process_rx_indicator(t, (void *) s, T38_IND_V17_12000_LONG_TRAINING);
|
|
603 break;
|
|
604 case T38_DATA_V17_14400:
|
|
605 if (s->t38.current_rx_indicator != T38_IND_V17_14400_SHORT_TRAINING && s->t38.current_rx_indicator != T38_IND_V17_14400_LONG_TRAINING)
|
|
606 process_rx_indicator(t, (void *) s, T38_IND_V17_14400_LONG_TRAINING);
|
|
607 break;
|
|
608 case T38_DATA_V8:
|
|
609 break;
|
|
610 case T38_DATA_V34_PRI_RATE:
|
|
611 break;
|
|
612 case T38_DATA_V34_CC_1200:
|
|
613 break;
|
|
614 case T38_DATA_V34_PRI_CH:
|
|
615 break;
|
|
616 case T38_DATA_V33_12000:
|
|
617 break;
|
|
618 case T38_DATA_V33_14400:
|
|
619 break;
|
|
620 }
|
|
621 }
|
|
622 /*- End of function --------------------------------------------------------*/
|
|
623
|
|
624 static int process_rx_missing(t38_core_state_t *t, void *user_data, int rx_seq_no, int expected_seq_no)
|
|
625 {
|
|
626 t38_gateway_state_t *s;
|
|
627
|
|
628 s = (t38_gateway_state_t *) user_data;
|
|
629 s->hdlc_flags[s->hdlc_in] |= HDLC_FLAG_MISSING_DATA;
|
|
630 return 0;
|
|
631 }
|
|
632 /*- End of function --------------------------------------------------------*/
|
|
633
|
|
634 static int process_rx_indicator(t38_core_state_t *t, void *user_data, int indicator)
|
|
635 {
|
|
636 t38_gateway_state_t *s;
|
|
637
|
|
638 s = (t38_gateway_state_t *) user_data;
|
|
639
|
|
640 if (s->t38.current_rx_indicator != indicator)
|
|
641 {
|
|
642 if (s->hdlc_contents[s->hdlc_in])
|
|
643 {
|
|
644 if (++s->hdlc_in >= T38_TX_HDLC_BUFS)
|
|
645 s->hdlc_in = 0;
|
|
646 }
|
|
647 s->hdlc_contents[s->hdlc_in] = (indicator | 0x100);
|
|
648 if (++s->hdlc_in >= T38_TX_HDLC_BUFS)
|
|
649 s->hdlc_in = 0;
|
|
650 span_log(&s->logging,
|
|
651 SPAN_LOG_FLOW,
|
|
652 "Queued change - (%d) %s -> %s\n",
|
|
653 silence_gen_remainder(&(s->silence_gen)),
|
|
654 t38_indicator(s->t38.current_rx_indicator),
|
|
655 t38_indicator(indicator));
|
|
656 s->current_rx_field_class = T38_FIELD_CLASS_NONE;
|
|
657 }
|
|
658 return 0;
|
|
659 }
|
|
660 /*- End of function --------------------------------------------------------*/
|
|
661
|
|
662 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)
|
|
663 {
|
|
664 int i;
|
|
665 int previous;
|
|
666 t38_gateway_state_t *s;
|
|
667
|
|
668 s = (t38_gateway_state_t *) user_data;
|
|
669 switch (field_type)
|
|
670 {
|
|
671 case T38_FIELD_HDLC_DATA:
|
|
672 s->current_rx_field_class = T38_FIELD_CLASS_HDLC;
|
|
673 if (s->hdlc_contents[s->hdlc_in] != (data_type | 0x200))
|
|
674 queue_missing_indicator(s, data_type);
|
|
675 previous = s->hdlc_len[s->hdlc_in];
|
|
676 /* Check if this data would overflow the buffer. */
|
|
677 if (s->hdlc_len[s->hdlc_in] + len > T38_MAX_HDLC_LEN)
|
|
678 break;
|
|
679 s->hdlc_contents[s->hdlc_in] = (data_type | 0x200);
|
|
680 if (data_type == T38_DATA_V21)
|
|
681 {
|
|
682 for (i = 0; i < len; i++)
|
|
683 {
|
|
684 s->hdlc_buf[s->hdlc_in][s->hdlc_len[s->hdlc_in]++] = bit_reverse8(buf[i]);
|
|
685 /* Edit the message, if we need to control the communication between the end points. */
|
|
686 switch (s->hdlc_len[s->hdlc_in])
|
|
687 {
|
|
688 case 4:
|
|
689 /* Check if we need to corrupt this message */
|
|
690 if (s->hdlc_buf[s->hdlc_in][2] == T30_NSF
|
|
691 ||
|
|
692 s->hdlc_buf[s->hdlc_in][2] == T30_NSC
|
|
693 ||
|
|
694 s->hdlc_buf[s->hdlc_in][2] == T30_NSS)
|
|
695 {
|
|
696 /* Corrupt the message, so it will be ignored */
|
|
697 span_log(&s->logging, SPAN_LOG_FLOW, "Corrupting non-specific procedures message\n");
|
|
698 s->hdlc_buf[s->hdlc_in][3] = 0;
|
|
699 }
|
|
700 break;
|
|
701 case 6:
|
|
702 switch (s->hdlc_buf[s->hdlc_in][2])
|
|
703 {
|
|
704 case T30_DIS:
|
|
705 /* We may need to adjust the capabilities, so they do not exceed our own */
|
|
706 span_log(&s->logging, SPAN_LOG_FLOW, "Constraining the fast modem\n");
|
|
707 constrain_fast_modem(s, s->hdlc_buf[s->hdlc_in], s->hdlc_len[s->hdlc_in]);
|
|
708 break;
|
|
709 default:
|
|
710 break;
|
|
711 }
|
|
712 break;
|
|
713 case 7:
|
|
714 if (!s->ecm_allowed)
|
|
715 {
|
|
716 switch (s->hdlc_buf[s->hdlc_in][2])
|
|
717 {
|
|
718 case T30_DIS:
|
|
719 /* Do not allow ECM or T.6 coding */
|
|
720 span_log(&s->logging, SPAN_LOG_FLOW, "Inhibiting ECM\n");
|
|
721 s->hdlc_buf[s->hdlc_in][6] &= ~(DISBIT3 | DISBIT7);
|
|
722 break;
|
|
723 }
|
|
724 }
|
|
725 break;
|
|
726 }
|
|
727 }
|
|
728 /* We need to send out the control messages as they are arriving. They are
|
|
729 too slow to capture a whole frame, and then pass it on. */
|
|
730 /* Don't start pumping data into the actual output stream until there is
|
|
731 enough backlog to create some elasticity for jitter tolerance. */
|
|
732 if (s->hdlc_len[s->hdlc_in] >= 8)
|
|
733 {
|
|
734 if (s->hdlc_in == s->hdlc_out)
|
|
735 {
|
|
736 if ((s->hdlc_flags[s->hdlc_in] & HDLC_FLAG_PROCEED_WITH_OUTPUT) == 0)
|
|
737 previous = 0;
|
|
738 hdlc_tx_frame(&s->hdlctx, s->hdlc_buf[s->hdlc_out] + previous, s->hdlc_len[s->hdlc_out] - previous);
|
|
739 }
|
|
740 s->hdlc_flags[s->hdlc_in] |= HDLC_FLAG_PROCEED_WITH_OUTPUT;
|
|
741 }
|
|
742 }
|
|
743 else
|
|
744 {
|
|
745 /* For the faster frames, take in the whole frame before sending it out. Also, there
|
|
746 is no need to monitor, or modify, the contents of the faster frames. */
|
|
747 for (i = 0; i < len; i++)
|
|
748 s->hdlc_buf[s->hdlc_in][s->hdlc_len[s->hdlc_in] + i] = bit_reverse8(buf[i]);
|
|
749 s->hdlc_len[s->hdlc_in] += len;
|
|
750 }
|
|
751 break;
|
|
752 case T38_FIELD_HDLC_FCS_OK:
|
|
753 s->current_rx_field_class = T38_FIELD_CLASS_HDLC;
|
|
754 if (len > 0)
|
|
755 {
|
|
756 span_log(&s->logging, SPAN_LOG_WARNING, "There is data in a T38_FIELD_HDLC_FCS_OK!\n");
|
|
757 /* The sender has incorrectly included data in this message. It is unclear what we should do
|
|
758 with it, to maximise tolerance of buggy implementations. */
|
|
759 }
|
|
760 span_log(&s->logging, SPAN_LOG_FLOW, "Type %s - CRC good\n", t30_frametype(s->hdlc_buf[s->hdlc_in][2]));
|
|
761 if (s->hdlc_contents[s->hdlc_in] != (data_type | 0x200))
|
|
762 queue_missing_indicator(s, data_type);
|
|
763 /* Don't deal with zero length frames. Some T.38 implementations send multiple T38_FIELD_HDLC_FCS_OK
|
|
764 packets, when they have sent no data for the body of the frame. */
|
|
765 if (s->hdlc_len[s->hdlc_in] > 0)
|
|
766 {
|
|
767 s->hdlc_contents[s->hdlc_in] = (data_type | 0x200);
|
|
768 if (data_type == T38_DATA_V21 && (s->hdlc_flags[s->hdlc_in] & HDLC_FLAG_MISSING_DATA) == 0)
|
|
769 monitor_control_messages(s, s->hdlc_buf[s->hdlc_in], s->hdlc_len[s->hdlc_in], FALSE);
|
|
770 pump_out_final_hdlc(s, (s->hdlc_flags[s->hdlc_in] & HDLC_FLAG_MISSING_DATA) == 0);
|
|
771 }
|
|
772 s->hdlc_len[s->hdlc_in] = 0;
|
|
773 s->hdlc_flags[s->hdlc_in] = 0;
|
|
774 break;
|
|
775 case T38_FIELD_HDLC_FCS_BAD:
|
|
776 s->current_rx_field_class = T38_FIELD_CLASS_HDLC;
|
|
777 if (len > 0)
|
|
778 {
|
|
779 span_log(&s->logging, SPAN_LOG_WARNING, "There is data in a T38_FIELD_HDLC_FCS_BAD!\n");
|
|
780 /* The sender has incorrectly included data in this message. We can safely ignore it, as the
|
|
781 bad FCS means we will throw away the whole message, anyway. */
|
|
782 }
|
|
783 span_log(&s->logging, SPAN_LOG_FLOW, "Type %s - CRC bad\n", t30_frametype(s->hdlc_buf[s->hdlc_in][2]));
|
|
784 if (s->hdlc_contents[s->hdlc_in] != (data_type | 0x200))
|
|
785 queue_missing_indicator(s, data_type);
|
|
786 if (s->hdlc_len[s->hdlc_in] > 0)
|
|
787 {
|
|
788 s->hdlc_contents[s->hdlc_in] = (data_type | 0x200);
|
|
789 pump_out_final_hdlc(s, FALSE);
|
|
790 }
|
|
791 s->hdlc_len[s->hdlc_in] = 0;
|
|
792 s->hdlc_flags[s->hdlc_in] = 0;
|
|
793 break;
|
|
794 case T38_FIELD_HDLC_FCS_OK_SIG_END:
|
|
795 s->current_rx_field_class = T38_FIELD_CLASS_HDLC;
|
|
796 if (len > 0)
|
|
797 {
|
|
798 span_log(&s->logging, SPAN_LOG_WARNING, "There is data in a T38_FIELD_HDLC_FCS_OK_SIG_END!\n");
|
|
799 /* The sender has incorrectly included data in this message. It is unclear what we should do
|
|
800 with it, to maximise tolerance of buggy implementations. */
|
|
801 }
|
|
802 span_log(&s->logging, SPAN_LOG_FLOW, "Type %s - CRC OK, sig end\n", t30_frametype(s->hdlc_buf[s->hdlc_in][2]));
|
|
803 if (s->hdlc_contents[s->hdlc_in] != (data_type | 0x200))
|
|
804 queue_missing_indicator(s, data_type);
|
|
805 /* Don't deal with zero length frames. Some T.38 implementations send multiple T38_FIELD_HDLC_FCS_OK
|
|
806 packets, when they have sent no data for the body of the frame. */
|
|
807 if (s->hdlc_len[s->hdlc_in] > 0)
|
|
808 {
|
|
809 s->hdlc_contents[s->hdlc_in] = (data_type | 0x200);
|
|
810 if (data_type == T38_DATA_V21 && (s->hdlc_flags[s->hdlc_in] & HDLC_FLAG_MISSING_DATA) == 0)
|
|
811 monitor_control_messages(s, s->hdlc_buf[s->hdlc_in], s->hdlc_len[s->hdlc_in], FALSE);
|
|
812 pump_out_final_hdlc(s, (s->hdlc_flags[s->hdlc_in] & HDLC_FLAG_MISSING_DATA) == 0);
|
|
813 }
|
|
814 s->hdlc_len[s->hdlc_in] = 0;
|
|
815 s->hdlc_flags[s->hdlc_in] = 0;
|
|
816 s->hdlc_contents[s->hdlc_in] = 0;
|
|
817 queue_missing_indicator(s, -1);
|
|
818 break;
|
|
819 case T38_FIELD_HDLC_FCS_BAD_SIG_END:
|
|
820 s->current_rx_field_class = T38_FIELD_CLASS_HDLC;
|
|
821 if (len > 0)
|
|
822 {
|
|
823 span_log(&s->logging, SPAN_LOG_WARNING, "There is data in a T38_FIELD_HDLC_FCS_BAD_SIG_END!\n");
|
|
824 /* The sender has incorrectly included data in this message. We can safely ignore it, as the
|
|
825 bad FCS means we will throw away the whole message, anyway. */
|
|
826 }
|
|
827 span_log(&s->logging, SPAN_LOG_FLOW, "Type %s - CRC bad, sig end\n", t30_frametype(s->hdlc_buf[s->hdlc_in][2]));
|
|
828 if (s->hdlc_contents[s->hdlc_in] != (data_type | 0x200))
|
|
829 queue_missing_indicator(s, data_type);
|
|
830 if (s->hdlc_len[s->hdlc_in] > 0)
|
|
831 {
|
|
832 s->hdlc_contents[s->hdlc_in] = (data_type | 0x200);
|
|
833 pump_out_final_hdlc(s, FALSE);
|
|
834 }
|
|
835 s->hdlc_len[s->hdlc_in] = 0;
|
|
836 s->hdlc_flags[s->hdlc_in] = 0;
|
|
837 s->hdlc_contents[s->hdlc_in] = 0;
|
|
838 queue_missing_indicator(s, -1);
|
|
839 break;
|
|
840 case T38_FIELD_HDLC_SIG_END:
|
|
841 if (len > 0)
|
|
842 {
|
|
843 span_log(&s->logging, SPAN_LOG_WARNING, "There is data in a T38_FIELD_HDLC_SIG_END!\n");
|
|
844 /* The sender has incorrectly included data in this message, but there seems nothing meaningful
|
|
845 it could be. There could not be an FCS good/bad report beyond this. */
|
|
846 }
|
|
847 if (s->hdlc_contents[s->hdlc_in] != (data_type | 0x200))
|
|
848 queue_missing_indicator(s, data_type);
|
|
849 /* WORKAROUND: At least some Mediatrix boxes have a bug, where they can send this message at the
|
|
850 end of non-ECM data. We need to tolerate this. */
|
|
851 if (s->current_rx_field_class != T38_FIELD_CLASS_NON_ECM)
|
|
852 {
|
|
853 /* This message is expected under 2 circumstances. One is as an alternative to T38_FIELD_HDLC_FCS_OK_SIG_END -
|
|
854 i.e. they send T38_FIELD_HDLC_FCS_OK, and then T38_FIELD_HDLC_SIG_END when the carrier actually drops.
|
|
855 The other is because the HDLC signal drops unexpectedly - i.e. not just after a final frame. */
|
|
856 s->hdlc_len[s->hdlc_in] = 0;
|
|
857 s->hdlc_flags[s->hdlc_in] = 0;
|
|
858 s->hdlc_contents[s->hdlc_in] = 0;
|
|
859 }
|
|
860 else
|
|
861 {
|
|
862 span_log(&s->logging, SPAN_LOG_WARNING, "T38_FIELD_HDLC_SIG_END received at the end of non-ECM data!\n");
|
|
863 /* Don't flow control the data any more. Just pump out the remainder as fast as we can. */
|
|
864 s->non_ecm_tx_latest_eol_ptr = s->non_ecm_tx_in_ptr;
|
|
865 s->non_ecm_data_finished = TRUE;
|
|
866 }
|
|
867 queue_missing_indicator(s, -1);
|
|
868 s->current_rx_field_class = T38_FIELD_CLASS_NONE;
|
|
869 break;
|
|
870 case T38_FIELD_T4_NON_ECM_DATA:
|
|
871 s->current_rx_field_class = T38_FIELD_CLASS_NON_ECM;
|
|
872 if (s->hdlc_contents[s->hdlc_in] != (data_type | 0x200))
|
|
873 queue_missing_indicator(s, data_type);
|
|
874 add_to_non_ecm_tx_buffer(s, buf, len);
|
|
875 break;
|
|
876 case T38_FIELD_T4_NON_ECM_SIG_END:
|
|
877 if (len > 0)
|
|
878 {
|
|
879 if (s->hdlc_contents[s->hdlc_in] != (data_type | 0x200))
|
|
880 queue_missing_indicator(s, data_type);
|
|
881 add_to_non_ecm_tx_buffer(s, buf, len);
|
|
882 }
|
|
883 if (s->hdlc_contents[s->hdlc_in] != (data_type | 0x200))
|
|
884 queue_missing_indicator(s, data_type);
|
|
885 /* WORKAROUND: At least some Mediatrix boxes have a bug, where they can send HDLC signal end where
|
|
886 they should send non-ECM signal end. It is possible they also do the opposite.
|
|
887 We need to tolerate this. */
|
|
888 if (s->current_rx_field_class != T38_FIELD_CLASS_HDLC)
|
|
889 {
|
|
890 /* Don't flow control the data any more. Just pump out the remainder as fast as we can. */
|
|
891 s->non_ecm_tx_latest_eol_ptr = s->non_ecm_tx_in_ptr;
|
|
892 s->non_ecm_data_finished = TRUE;
|
|
893 }
|
|
894 else
|
|
895 {
|
|
896 span_log(&s->logging, SPAN_LOG_WARNING, "T38_FIELD_NON_ECM_SIG_END received at the end of HDLC data!\n");
|
|
897 s->hdlc_len[s->hdlc_in] = 0;
|
|
898 s->hdlc_flags[s->hdlc_in] = 0;
|
|
899 s->hdlc_contents[s->hdlc_in] = 0;
|
|
900 }
|
|
901 queue_missing_indicator(s, -1);
|
|
902 s->current_rx_field_class = T38_FIELD_CLASS_NONE;
|
|
903 break;
|
|
904 case T38_FIELD_CM_MESSAGE:
|
|
905 case T38_FIELD_JM_MESSAGE:
|
|
906 case T38_FIELD_CI_MESSAGE:
|
|
907 case T38_FIELD_V34RATE:
|
|
908 default:
|
|
909 break;
|
|
910 }
|
|
911 s->current_rx_field_type = field_type;
|
|
912 s->current_rx_data_type = data_type;
|
|
913
|
|
914 #if 0
|
|
915 if (span_log_test(&s->logging, SPAN_LOG_FLOW))
|
|
916 {
|
|
917 int i;
|
|
918
|
|
919 if (len > 0)
|
|
920 {
|
|
921 span_log(&s->logging, SPAN_LOG_FLOW, "Data: ");
|
|
922 for (i = 0; i < len; i++)
|
|
923 span_log(&s->logging, SPAN_LOG_FLOW | SPAN_LOG_SUPPRESS_LABELLING, " %02X", buf[i]);
|
|
924 }
|
|
925 }
|
|
926 span_log(&s->logging, SPAN_LOG_FLOW | SPAN_LOG_SUPPRESS_LABELLING, "\n");
|
|
927 #endif
|
|
928 return 0;
|
|
929 }
|
|
930 /*- End of function --------------------------------------------------------*/
|
|
931
|
|
932 static void announce_training(t38_gateway_state_t *s)
|
|
933 {
|
|
934 int ind;
|
|
935
|
|
936 ind = T38_IND_NO_SIGNAL;
|
|
937 switch (s->fast_rx_active)
|
|
938 {
|
|
939 #if defined(ENABLE_V17)
|
|
940 case T38_V17_RX:
|
|
941 switch (s->fast_bit_rate)
|
|
942 {
|
|
943 case 7200:
|
|
944 ind = (s->short_train) ? T38_IND_V17_7200_SHORT_TRAINING : T38_IND_V17_7200_LONG_TRAINING;
|
|
945 s->current_tx_data_type = T38_DATA_V17_7200;
|
|
946 s->octets_per_data_packet = MS_PER_TX_CHUNK*7200/(8*1000);
|
|
947 break;
|
|
948 case 9600:
|
|
949 ind = (s->short_train) ? T38_IND_V17_9600_SHORT_TRAINING : T38_IND_V17_9600_LONG_TRAINING;
|
|
950 s->current_tx_data_type = T38_DATA_V17_9600;
|
|
951 s->octets_per_data_packet = MS_PER_TX_CHUNK*9600/(8*1000);
|
|
952 break;
|
|
953 case 12000:
|
|
954 ind = (s->short_train) ? T38_IND_V17_12000_SHORT_TRAINING : T38_IND_V17_12000_LONG_TRAINING;
|
|
955 s->current_tx_data_type = T38_DATA_V17_12000;
|
|
956 s->octets_per_data_packet = MS_PER_TX_CHUNK*12000/(8*1000);
|
|
957 break;
|
|
958 default:
|
|
959 case 14400:
|
|
960 ind = (s->short_train) ? T38_IND_V17_14400_SHORT_TRAINING : T38_IND_V17_14400_LONG_TRAINING;
|
|
961 s->current_tx_data_type = T38_DATA_V17_14400;
|
|
962 s->octets_per_data_packet = MS_PER_TX_CHUNK*14400/(8*1000);
|
|
963 break;
|
|
964 }
|
|
965 break;
|
|
966 #endif
|
|
967 case T38_V27TER_RX:
|
|
968 switch (s->fast_bit_rate)
|
|
969 {
|
|
970 case 2400:
|
|
971 ind = T38_IND_V27TER_2400_TRAINING;
|
|
972 s->current_tx_data_type = T38_DATA_V27TER_2400;
|
|
973 s->octets_per_data_packet = MS_PER_TX_CHUNK*2400/(8*1000);
|
|
974 break;
|
|
975 default:
|
|
976 case 4800:
|
|
977 ind = T38_IND_V27TER_4800_TRAINING;
|
|
978 s->current_tx_data_type = T38_DATA_V27TER_4800;
|
|
979 s->octets_per_data_packet = MS_PER_TX_CHUNK*4800/(8*1000);
|
|
980 break;
|
|
981 }
|
|
982 break;
|
|
983 case T38_V29_RX:
|
|
984 switch (s->fast_bit_rate)
|
|
985 {
|
|
986 case 7200:
|
|
987 ind = T38_IND_V29_7200_TRAINING;
|
|
988 s->current_tx_data_type = T38_DATA_V29_7200;
|
|
989 s->octets_per_data_packet = MS_PER_TX_CHUNK*7200/(8*1000);
|
|
990 break;
|
|
991 default:
|
|
992 case 9600:
|
|
993 ind = T38_IND_V29_9600_TRAINING;
|
|
994 s->current_tx_data_type = T38_DATA_V29_9600;
|
|
995 s->octets_per_data_packet = MS_PER_TX_CHUNK*9600/(8*1000);
|
|
996 break;
|
|
997 }
|
|
998 break;
|
|
999 }
|
|
1000 t38_core_send_indicator(&s->t38, ind, INDICATOR_TX_COUNT);
|
|
1001 }
|
|
1002 /*- End of function --------------------------------------------------------*/
|
|
1003
|
|
1004 static void non_ecm_put_bit(void *user_data, int bit)
|
|
1005 {
|
|
1006 t38_gateway_state_t *s;
|
|
1007
|
|
1008 s = (t38_gateway_state_t *) user_data;
|
|
1009 if (bit < 0)
|
|
1010 {
|
|
1011 /* Special conditions */
|
|
1012 switch (bit)
|
|
1013 {
|
|
1014 case PUTBIT_TRAINING_FAILED:
|
|
1015 span_log(&s->logging, SPAN_LOG_FLOW, "Non-ECM carrier training failed\n");
|
|
1016 break;
|
|
1017 case PUTBIT_TRAINING_SUCCEEDED:
|
|
1018 /* The modem is now trained */
|
|
1019 span_log(&s->logging, SPAN_LOG_FLOW, "Non-ECM carrier trained\n");
|
|
1020 s->rx_signal_present = TRUE;
|
|
1021 s->v21_rx_active = FALSE;
|
|
1022 announce_training(s);
|
|
1023 s->samples_since_last_tx_packet = 0;
|
|
1024 s->rx_data_ptr = 0;
|
|
1025 break;
|
|
1026 case PUTBIT_CARRIER_UP:
|
|
1027 span_log(&s->logging, SPAN_LOG_FLOW, "Non-ECM carrier up\n");
|
|
1028 break;
|
|
1029 case PUTBIT_CARRIER_DOWN:
|
|
1030 span_log(&s->logging, SPAN_LOG_FLOW, "Non-ECM carrier down\n");
|
|
1031 switch (s->current_tx_data_type)
|
|
1032 {
|
|
1033 case T38_DATA_V17_7200:
|
|
1034 case T38_DATA_V17_9600:
|
|
1035 case T38_DATA_V17_12000:
|
|
1036 case T38_DATA_V17_14400:
|
|
1037 case T38_DATA_V27TER_2400:
|
|
1038 case T38_DATA_V27TER_4800:
|
|
1039 case T38_DATA_V29_7200:
|
|
1040 case T38_DATA_V29_9600:
|
|
1041 t38_core_send_data(&s->t38, s->current_tx_data_type, T38_FIELD_T4_NON_ECM_SIG_END, NULL, 0);
|
|
1042 t38_core_send_indicator(&s->t38, T38_IND_NO_SIGNAL, INDICATOR_TX_COUNT);
|
|
1043 s->rx_signal_present = FALSE;
|
|
1044 restart_rx_modem(s);
|
|
1045 break;
|
|
1046 }
|
|
1047 break;
|
|
1048 default:
|
|
1049 span_log(&s->logging, SPAN_LOG_WARNING, "Unexpected non-ECM special bit - %d!\n", bit);
|
|
1050 break;
|
|
1051 }
|
|
1052 return;
|
|
1053 }
|
|
1054 s->current_non_ecm_octet = (s->current_non_ecm_octet << 1) | (bit & 1);
|
|
1055 if (++s->non_ecm_bit_no >= 8)
|
|
1056 {
|
|
1057 s->rx_data[s->rx_data_ptr++] = (uint8_t) s->current_non_ecm_octet;
|
|
1058 if (++s->octets_since_last_tx_packet >= s->octets_per_data_packet)
|
|
1059 {
|
|
1060 t38_core_send_data(&s->t38, s->current_tx_data_type, T38_FIELD_T4_NON_ECM_DATA, s->rx_data, s->rx_data_ptr);
|
|
1061 /* Since we delay transmission by 2 octets, we should now have sent the last of the data octets when
|
|
1062 we have just received the last of the CRC octets. */
|
|
1063 s->rx_data_ptr = 0;
|
|
1064 s->samples_since_last_tx_packet = 0;
|
|
1065 s->octets_since_last_tx_packet = 0;
|
|
1066 }
|
|
1067 s->non_ecm_bit_no = 0;
|
|
1068 s->current_non_ecm_octet = 0;
|
|
1069 }
|
|
1070 }
|
|
1071 /*- End of function --------------------------------------------------------*/
|
|
1072
|
|
1073 static int non_ecm_get_bit(void *user_data)
|
|
1074 {
|
|
1075 t38_gateway_state_t *s;
|
|
1076 int bit;
|
|
1077
|
|
1078 /* A rate adapting data stuffer for non-ECM image data */
|
|
1079 s = (t38_gateway_state_t *) user_data;
|
|
1080 if (s->non_ecm_bit_no <= 0)
|
|
1081 {
|
|
1082 /* We need another byte */
|
|
1083 if (s->non_ecm_tx_out_ptr != s->non_ecm_tx_latest_eol_ptr)
|
|
1084 {
|
|
1085 s->current_non_ecm_octet = s->non_ecm_tx_data[s->non_ecm_tx_out_ptr];
|
|
1086 s->non_ecm_tx_out_ptr = (s->non_ecm_tx_out_ptr + 1) & (T38_TX_BUF_LEN - 1);
|
|
1087 }
|
|
1088 else
|
|
1089 {
|
|
1090 if (s->non_ecm_data_finished)
|
|
1091 {
|
|
1092 /* The queue is empty, and we have received the end of data signal. This must
|
|
1093 really be the end to transmission. */
|
|
1094 s->non_ecm_data_finished = FALSE;
|
|
1095 /* Reset the data pointers for next time. */
|
|
1096 s->non_ecm_tx_out_ptr = 0;
|
|
1097 s->non_ecm_tx_in_ptr = 0;
|
|
1098 s->non_ecm_tx_latest_eol_ptr = 0;
|
|
1099 return PUTBIT_END_OF_DATA;
|
|
1100 }
|
|
1101 /* The queue is empty, but this does not appear to be the end of the data. Idle with
|
|
1102 fill octets, which should be safe at this point. */
|
|
1103 s->current_non_ecm_octet = s->non_ecm_flow_control_fill_octet;
|
|
1104 s->non_ecm_flow_control_fill_octets++;
|
|
1105 }
|
|
1106 s->non_ecm_bit_no = 8;
|
|
1107 }
|
|
1108 s->non_ecm_bit_no--;
|
|
1109 bit = (s->current_non_ecm_octet >> 7) & 1;
|
|
1110 s->current_non_ecm_octet <<= 1;
|
|
1111 return bit;
|
|
1112 }
|
|
1113 /*- End of function --------------------------------------------------------*/
|
|
1114
|
|
1115 static void add_to_non_ecm_tx_buffer(t38_gateway_state_t *s, const uint8_t *buf, int len)
|
|
1116 {
|
|
1117 int i;
|
|
1118 int upper;
|
|
1119 int lower;
|
|
1120
|
|
1121 /* A rate adapting data stuffer for non-ECM image data */
|
|
1122 i = 0;
|
|
1123 if (s->non_ecm_at_initial_all_ones)
|
|
1124 {
|
|
1125 /* Dump initial 0xFF bytes. We will add enough of our own to makes things flow
|
|
1126 smoothly. If we don't strip these off we might end up delaying the start of
|
|
1127 forwarding by a large amount, as we could end up with a large block of 0xFF
|
|
1128 bytes before the real data begins. This is especially true with PC FAX
|
|
1129 systems. */
|
|
1130 for ( ; i < len; i++)
|
|
1131 {
|
|
1132 if (buf[i] != 0xFF)
|
|
1133 {
|
|
1134 s->non_ecm_at_initial_all_ones = FALSE;
|
|
1135 break;
|
|
1136 }
|
|
1137 }
|
|
1138 }
|
|
1139 if (s->short_train)
|
|
1140 {
|
|
1141 for ( ; i < len; i++)
|
|
1142 {
|
|
1143 /* Check for EOLs, because at an EOL we can pause and pump out zeros while
|
|
1144 waiting for more incoming data. */
|
|
1145 if (buf[i])
|
|
1146 {
|
|
1147 /* There might be an EOL here. Look for at least 11 zeros, followed by a one. */
|
|
1148 upper = bottom_bit((s->bit_stream | 0x800) & 0xFFF);
|
|
1149 lower = top_bit(buf[i] & 0xFF);
|
|
1150 if (lower > 0 && upper - lower >= 3)
|
|
1151 {
|
|
1152 s->non_ecm_tx_latest_eol_ptr = s->non_ecm_tx_in_ptr;
|
|
1153 s->non_ecm_flow_control_fill_octet = 0x00;
|
|
1154 }
|
|
1155 }
|
|
1156 s->bit_stream = (s->bit_stream << 8) | buf[i];
|
|
1157 s->non_ecm_tx_data[s->non_ecm_tx_in_ptr] = buf[i];
|
|
1158 /* TODO: We can't buffer overflow, since we wrap around. However, the tail could overwrite
|
|
1159 itself if things fall badly behind. */
|
|
1160 s->non_ecm_tx_in_ptr = (s->non_ecm_tx_in_ptr + 1) & (T38_TX_BUF_LEN - 1);
|
|
1161 }
|
|
1162 }
|
|
1163 else
|
|
1164 {
|
|
1165 for ( ; i < len; i++)
|
|
1166 {
|
|
1167 /* Check for zero bytes, as we can pause and pump out zeros while waiting
|
|
1168 for more incoming data. */
|
|
1169 if (buf[i] == 0)
|
|
1170 {
|
|
1171 s->non_ecm_tx_latest_eol_ptr = s->non_ecm_tx_in_ptr;
|
|
1172 s->non_ecm_flow_control_fill_octet = 0x00;
|
|
1173 }
|
|
1174 s->non_ecm_tx_data[s->non_ecm_tx_in_ptr] = buf[i];
|
|
1175 /* TODO: We can't buffer overflow, since we wrap around. However, the tail could overwrite
|
|
1176 itself if things fall badly behind. */
|
|
1177 s->non_ecm_tx_in_ptr = (s->non_ecm_tx_in_ptr + 1) & (T38_TX_BUF_LEN - 1);
|
|
1178 }
|
|
1179 }
|
|
1180 }
|
|
1181 /*- End of function --------------------------------------------------------*/
|
|
1182
|
|
1183 static void t38_hdlc_rx_put_bit(hdlc_rx_state_t *t, int new_bit)
|
|
1184 {
|
|
1185 t38_gateway_state_t *s;
|
|
1186 int final;
|
|
1187
|
|
1188 s = (t38_gateway_state_t *) t->user_data;
|
|
1189 if (new_bit < 0)
|
|
1190 {
|
|
1191 /* Special conditions */
|
|
1192 switch (new_bit)
|
|
1193 {
|
|
1194 case PUTBIT_TRAINING_FAILED:
|
|
1195 span_log(&s->logging, SPAN_LOG_FLOW, "HDLC carrier training failed\n");
|
|
1196 break;
|
|
1197 case PUTBIT_TRAINING_SUCCEEDED:
|
|
1198 /* The modem is now trained */
|
|
1199 span_log(&s->logging, SPAN_LOG_FLOW, "HDLC carrier trained\n");
|
|
1200 s->rx_signal_present = TRUE;
|
|
1201 s->v21_rx_active = FALSE;
|
|
1202 announce_training(s);
|
|
1203 /* Behave like HDLC preamble has been announced */
|
|
1204 t->framing_ok_announced = TRUE;
|
|
1205 s->samples_since_last_tx_packet = 0;
|
|
1206 s->rx_data_ptr = 0;
|
|
1207 break;
|
|
1208 case PUTBIT_CARRIER_UP:
|
|
1209 span_log(&s->logging, SPAN_LOG_FLOW, "HDLC carrier up\n");
|
|
1210 /* Reset the HDLC receiver. */
|
|
1211 t->len = 0;
|
|
1212 t->num_bits = 0;
|
|
1213 t->flags_seen = 0;
|
|
1214 t->framing_ok_announced = FALSE;
|
|
1215 s->rx_signal_present = TRUE;
|
|
1216 break;
|
|
1217 case PUTBIT_CARRIER_DOWN:
|
|
1218 span_log(&s->logging, SPAN_LOG_FLOW, "HDLC carrier down\n");
|
|
1219 if (t->framing_ok_announced)
|
|
1220 {
|
|
1221 t38_core_send_data(&s->t38, s->current_tx_data_type, T38_FIELD_HDLC_SIG_END, NULL, 0);
|
|
1222 t38_core_send_indicator(&s->t38, T38_IND_NO_SIGNAL, INDICATOR_TX_COUNT);
|
|
1223 t->framing_ok_announced = FALSE;
|
|
1224 }
|
|
1225 s->rx_signal_present = FALSE;
|
|
1226 restart_rx_modem(s);
|
|
1227 break;
|
|
1228 default:
|
|
1229 span_log(&s->logging, SPAN_LOG_WARNING, "Unexpected HDLC special bit - %d!\n", new_bit);
|
|
1230 break;
|
|
1231 }
|
|
1232 return;
|
|
1233 }
|
|
1234 t->raw_bit_stream |= (new_bit & 1);
|
|
1235 if ((t->raw_bit_stream & 0x3F) == 0x3E)
|
|
1236 {
|
|
1237 if ((t->raw_bit_stream & 0x40) == 0)
|
|
1238 {
|
|
1239 /* Stuffing */
|
|
1240 }
|
|
1241 else if ((t->raw_bit_stream & 0x80))
|
|
1242 {
|
|
1243 /* Hit HDLC abort */
|
|
1244 t->rx_aborts++;
|
|
1245 t->len = 0;
|
|
1246 t->num_bits = 0;
|
|
1247 s->corrupt_the_frame = FALSE;
|
|
1248 s->octets_since_last_tx_packet = 0;
|
|
1249 }
|
|
1250 else
|
|
1251 {
|
|
1252 /* Hit HDLC flag */
|
|
1253 if (t->flags_seen >= t->framing_ok_threshold)
|
|
1254 {
|
|
1255 if (t->len)
|
|
1256 {
|
|
1257 if (t->len >= 2)
|
|
1258 {
|
|
1259 if ((s->crc & 0xFFFF) == 0xF0B8)
|
|
1260 {
|
|
1261 t->rx_frames++;
|
|
1262 t->rx_bytes += t->len - 2;
|
|
1263 final = (t->len - 2 >= 2 && t->buffer[0] == 0xFF && t->buffer[1] == 0x13);
|
|
1264 span_log(&s->logging, SPAN_LOG_FLOW, "E Type %s\n", t30_frametype(t->buffer[2]));
|
|
1265 if (s->current_tx_data_type == T38_DATA_V21)
|
|
1266 monitor_control_messages(s, t->buffer, t->len, TRUE);
|
|
1267 if (s->rx_data_ptr)
|
|
1268 {
|
|
1269 t38_core_send_data(&s->t38, s->current_tx_data_type, T38_FIELD_HDLC_DATA, s->rx_data, s->rx_data_ptr);
|
|
1270 s->rx_data_ptr = 0;
|
|
1271 }
|
|
1272 /* It seems some boxes may not like us sending a _SIG_END here, and then another
|
|
1273 when the carrier actually drops. Lets just send T38_FIELD_HDLC_FCS_OK here. */
|
|
1274 t38_core_send_data(&s->t38, s->current_tx_data_type, T38_FIELD_HDLC_FCS_OK, NULL, 0);
|
|
1275 }
|
|
1276 else
|
|
1277 {
|
|
1278 t->rx_crc_errors++;
|
|
1279 final = (t->len - 2 >= 2 && t->buffer[0] == 0xFF && t->buffer[1] == 0x13);
|
|
1280 span_log(&s->logging, SPAN_LOG_FLOW, "F Type %s\n", t30_frametype(t->buffer[2]));
|
|
1281 if (s->rx_data_ptr)
|
|
1282 {
|
|
1283 t38_core_send_data(&s->t38, s->current_tx_data_type, T38_FIELD_HDLC_DATA, s->rx_data, s->rx_data_ptr);
|
|
1284 s->rx_data_ptr = 0;
|
|
1285 }
|
|
1286 /* It seems some boxes may not like us sending a _SIG_END here, and then another
|
|
1287 when the carrier actually drops. Lets just send T38_FIELD_HDLC_FCS_OK here. */
|
|
1288 t38_core_send_data(&s->t38, s->current_tx_data_type, T38_FIELD_HDLC_FCS_BAD, NULL, 0);
|
|
1289 }
|
|
1290 }
|
|
1291 else
|
|
1292 {
|
|
1293 /* Frame too short */
|
|
1294 t->rx_length_errors++;
|
|
1295 }
|
|
1296 }
|
|
1297 }
|
|
1298 else
|
|
1299 {
|
|
1300 if (++t->flags_seen >= t->framing_ok_threshold && !t->framing_ok_announced)
|
|
1301 {
|
|
1302 if (s->current_tx_data_type == T38_DATA_V21)
|
|
1303 t38_core_send_indicator(&s->t38, T38_IND_V21_PREAMBLE, INDICATOR_TX_COUNT);
|
|
1304 if (s->in_progress_rx_indicator == T38_IND_CNG)
|
|
1305 set_next_tx_type(s);
|
|
1306 t->framing_ok_announced = TRUE;
|
|
1307 }
|
|
1308 }
|
|
1309 s->crc = 0xFFFF;
|
|
1310 t->len = 0;
|
|
1311 t->num_bits = 0;
|
|
1312 s->corrupt_the_frame = FALSE;
|
|
1313 s->octets_since_last_tx_packet = 0;
|
|
1314 }
|
|
1315 }
|
|
1316 else
|
|
1317 {
|
|
1318 if (t->framing_ok_announced)
|
|
1319 {
|
|
1320 t->byte_in_progress = (t->byte_in_progress >> 1) | ((t->raw_bit_stream & 0x01) << 7);
|
|
1321 if (++t->num_bits == 8)
|
|
1322 {
|
|
1323 if (t->len >= (int) sizeof(t->buffer))
|
|
1324 {
|
|
1325 /* Frame too long */
|
|
1326 t->rx_length_errors++;
|
|
1327 t->flags_seen = t->framing_ok_threshold - 1;
|
|
1328 t->len = 0;
|
|
1329 }
|
|
1330 else
|
|
1331 {
|
|
1332 t->buffer[t->len] = (uint8_t) t->byte_in_progress;
|
|
1333 /* Calculate the CRC progressively, before we start altering the frame */
|
|
1334 s->crc = crc_itu16_calc(&t->buffer[t->len], 1, s->crc);
|
|
1335 if (t->len >= 2)
|
|
1336 {
|
|
1337 /* Make the transmission lag by two bytes, so we do not send the CRC, and
|
|
1338 do not report the CRC result too late. */
|
|
1339 if (s->current_tx_data_type == T38_DATA_V21)
|
|
1340 {
|
|
1341 /* Edit the message, if we need to control the communication between the
|
|
1342 end points. */
|
|
1343 switch (t->len)
|
|
1344 {
|
|
1345 case 4:
|
|
1346 switch (t->buffer[2])
|
|
1347 {
|
|
1348 case T30_NSF:
|
|
1349 case T30_NSC:
|
|
1350 case T30_NSS:
|
|
1351 /* We need to corrupt the rest of this message */
|
|
1352 span_log(&s->logging, SPAN_LOG_FLOW, "Corrupting non-specific procedures message\n");
|
|
1353 s->corrupt_the_frame = TRUE;
|
|
1354 break;
|
|
1355 default:
|
|
1356 break;
|
|
1357 }
|
|
1358 break;
|
|
1359 case 6:
|
|
1360 switch (t->buffer[2])
|
|
1361 {
|
|
1362 case T30_DIS:
|
|
1363 /* We may need to adjust the capabilities, so they do not exceed our own */
|
|
1364 span_log(&s->logging, SPAN_LOG_FLOW, "Constraining the fast modem\n");
|
|
1365 constrain_fast_modem(s, t->buffer, t->len);
|
|
1366 break;
|
|
1367 default:
|
|
1368 break;
|
|
1369 }
|
|
1370 break;
|
|
1371 case 7:
|
|
1372 if (!s->ecm_allowed)
|
|
1373 {
|
|
1374 switch (t->buffer[2])
|
|
1375 {
|
|
1376 case T30_DIS:
|
|
1377 /* Do not allow ECM or T.6 coding */
|
|
1378 span_log(&s->logging, SPAN_LOG_FLOW, "Inhibiting ECM\n");
|
|
1379 t->buffer[6] &= ~(DISBIT3 | DISBIT7);
|
|
1380 break;
|
|
1381 }
|
|
1382 }
|
|
1383 break;
|
|
1384 }
|
|
1385 }
|
|
1386 s->rx_data[s->rx_data_ptr++] = (s->corrupt_the_frame) ? 0 : bit_reverse8(t->buffer[t->len - 2]);
|
|
1387 if (s->rx_data_ptr >= s->octets_per_data_packet)
|
|
1388 {
|
|
1389 t38_core_send_data(&s->t38, s->current_tx_data_type, T38_FIELD_HDLC_DATA, s->rx_data, s->rx_data_ptr);
|
|
1390 /* Since we delay transmission by 2 octets, we should now have sent the last of the data octets when
|
|
1391 we have just received the last of the CRC octets. */
|
|
1392 s->rx_data_ptr = 0;
|
|
1393 s->samples_since_last_tx_packet = 0;
|
|
1394 }
|
|
1395 }
|
|
1396 t->len++;
|
|
1397 }
|
|
1398 t->num_bits = 0;
|
|
1399 }
|
|
1400 }
|
|
1401 }
|
|
1402 t->raw_bit_stream <<= 1;
|
|
1403 }
|
|
1404 /*- End of function --------------------------------------------------------*/
|
|
1405
|
|
1406 static int restart_rx_modem(t38_gateway_state_t *s)
|
|
1407 {
|
|
1408 put_bit_func_t put_bit_func;
|
|
1409 void *put_bit_user_data;
|
|
1410
|
|
1411 span_log(&s->logging, SPAN_LOG_FLOW, "Restart modem - short = %d, ECM = %d\n", s->short_train, s->ecm_mode);
|
|
1412
|
|
1413 hdlc_rx_init(&(s->hdlcrx), FALSE, TRUE, 5, NULL, s);
|
|
1414 s->crc = 0xFFFF;
|
|
1415 s->rx_signal_present = FALSE;
|
|
1416 /* Default to the transmit data being V.21, unless a faster modem pops up trained. */
|
|
1417 s->current_tx_data_type = T38_DATA_V21;
|
|
1418 fsk_rx_init(&(s->v21rx), &preset_fsk_specs[FSK_V21CH2], TRUE, (put_bit_func_t) t38_hdlc_rx_put_bit, &(s->hdlcrx));
|
|
1419 s->v21_rx_active = TRUE;
|
|
1420 if (s->short_train && s->ecm_mode)
|
|
1421 {
|
|
1422 put_bit_func = (put_bit_func_t) t38_hdlc_rx_put_bit;
|
|
1423 put_bit_user_data = (void *) &(s->hdlcrx);
|
|
1424 }
|
|
1425 else
|
|
1426 {
|
|
1427 put_bit_func = non_ecm_put_bit;
|
|
1428 put_bit_user_data = (void *) s;
|
|
1429 }
|
|
1430 s->rx_data_ptr = 0;
|
|
1431 s->octets_per_data_packet = 1;
|
|
1432 switch (s->fast_modem)
|
|
1433 {
|
|
1434 #if defined(ENABLE_V17)
|
|
1435 case T38_V17_RX:
|
|
1436 v17_rx_restart(&(s->v17rx), s->fast_bit_rate, s->short_train);
|
|
1437 v17_rx_set_put_bit(&(s->v17rx), put_bit_func, put_bit_user_data);
|
|
1438 s->fast_rx_active = T38_V17_RX;
|
|
1439 break;
|
|
1440 #endif
|
|
1441 case T38_V27TER_RX:
|
|
1442 v27ter_rx_restart(&(s->v27ter_rx), s->fast_bit_rate, FALSE);
|
|
1443 v27ter_rx_set_put_bit(&(s->v27ter_rx), put_bit_func, put_bit_user_data);
|
|
1444 s->fast_rx_active = T38_V27TER_RX;
|
|
1445 break;
|
|
1446 case T38_V29_RX:
|
|
1447 v29_rx_restart(&(s->v29rx), s->fast_bit_rate, FALSE);
|
|
1448 v29_rx_set_put_bit(&(s->v29rx), put_bit_func, put_bit_user_data);
|
|
1449 s->fast_rx_active = T38_V29_RX;
|
|
1450 break;
|
|
1451 }
|
|
1452 return 0;
|
|
1453 }
|
|
1454 /*- End of function --------------------------------------------------------*/
|
|
1455
|
|
1456 int t38_gateway_rx(t38_gateway_state_t *s, const int16_t *amp, int len)
|
|
1457 {
|
|
1458 s->samples_since_last_tx_packet += len;
|
|
1459 if (s->v21_rx_active)
|
|
1460 fsk_rx(&(s->v21rx), amp, len);
|
|
1461 switch (s->fast_rx_active)
|
|
1462 {
|
|
1463 #if defined(ENABLE_V17)
|
|
1464 case T38_V17_RX:
|
|
1465 v17_rx(&(s->v17rx), amp, len);
|
|
1466 break;
|
|
1467 #endif
|
|
1468 case T38_V27TER_RX:
|
|
1469 v27ter_rx(&(s->v27ter_rx), amp, len);
|
|
1470 break;
|
|
1471 case T38_V29_RX:
|
|
1472 v29_rx(&(s->v29rx), amp, len);
|
|
1473 break;
|
|
1474 }
|
|
1475 return 0;
|
|
1476 }
|
|
1477 /*- End of function --------------------------------------------------------*/
|
|
1478
|
|
1479 int t38_gateway_tx(t38_gateway_state_t *s, int16_t *amp, int max_len)
|
|
1480 {
|
|
1481 int len;
|
|
1482
|
|
1483 if ((len = s->tx_handler(s->tx_user_data, amp, max_len)) < max_len)
|
|
1484 {
|
|
1485 if (set_next_tx_type(s))
|
|
1486 {
|
|
1487 /* Give the new handler a chance to file the remaining buffer space */
|
|
1488 len += s->tx_handler(s->tx_user_data, amp + len, max_len - len);
|
|
1489 if (len < max_len)
|
|
1490 {
|
|
1491 silence_gen_set(&(s->silence_gen), 0);
|
|
1492 set_next_tx_type(s);
|
|
1493 }
|
|
1494 }
|
|
1495 }
|
|
1496 return len;
|
|
1497 }
|
|
1498 /*- End of function --------------------------------------------------------*/
|
|
1499
|
|
1500 void t38_gateway_ecm_control(t38_gateway_state_t *s, int ecm_allowed)
|
|
1501 {
|
|
1502 s->ecm_allowed = ecm_allowed;
|
|
1503 }
|
|
1504 /*- End of function --------------------------------------------------------*/
|
|
1505
|
|
1506 t38_gateway_state_t *t38_gateway_init(t38_gateway_state_t *s,
|
|
1507 t38_tx_packet_handler_t *tx_packet_handler,
|
|
1508 void *tx_packet_user_data)
|
|
1509 {
|
|
1510 if (tx_packet_handler == NULL)
|
|
1511 return NULL;
|
|
1512
|
|
1513 memset(s, 0, sizeof(*s));
|
|
1514 span_log_init(&s->logging, SPAN_LOG_NONE, NULL);
|
|
1515 span_log_set_protocol(&s->logging, "T.38G");
|
|
1516 #if defined(ENABLE_V17)
|
|
1517 v17_rx_init(&(s->v17rx), 14400, non_ecm_put_bit, s);
|
|
1518 v17_tx_init(&(s->v17tx), 14400, FALSE, non_ecm_get_bit, s);
|
|
1519 #endif
|
|
1520 v29_rx_init(&(s->v29rx), 9600, non_ecm_put_bit, s);
|
|
1521 v29_tx_init(&(s->v29tx), 9600, FALSE, non_ecm_get_bit, s);
|
|
1522 v27ter_rx_init(&(s->v27ter_rx), 4800, non_ecm_put_bit, s);
|
|
1523 v27ter_tx_init(&(s->v27ter_tx), 4800, FALSE, non_ecm_get_bit, s);
|
|
1524 s->octets_per_data_packet = 1;
|
|
1525 silence_gen_init(&(s->silence_gen), 0);
|
|
1526 hdlc_tx_init(&s->hdlctx, FALSE, 2, TRUE, hdlc_underflow_handler, s);
|
|
1527 s->rx_signal_present = FALSE;
|
|
1528 s->tx_handler = (span_tx_handler_t *) &(silence_gen);
|
|
1529 s->tx_user_data = &(s->silence_gen);
|
|
1530 t38_core_init(&s->t38, process_rx_indicator, process_rx_data, process_rx_missing, (void *) s);
|
|
1531 s->t38.iaf = FALSE;
|
|
1532 s->t38.tx_packet_handler = tx_packet_handler;
|
|
1533 s->t38.tx_packet_user_data = tx_packet_user_data;
|
|
1534 #if defined(ENABLE_V17)
|
|
1535 s->t38.fastest_image_data_rate = 14400;
|
|
1536 #else
|
|
1537 s->t38.fastest_image_data_rate = 9600;
|
|
1538 #endif
|
|
1539 s->ecm_allowed = FALSE;
|
|
1540 restart_rx_modem(s);
|
|
1541 return s;
|
|
1542 }
|
|
1543 /*- End of function --------------------------------------------------------*/
|
|
1544 /*- End of file ------------------------------------------------------------*/
|