Mercurial > hg > audiostuff
comparison spandsp-0.0.3/spandsp-0.0.3/src/t38_gateway.c @ 5:f762bf195c4b
import spandsp-0.0.3
author | Peter Meerwald <pmeerw@cosy.sbg.ac.at> |
---|---|
date | Fri, 25 Jun 2010 16:00:21 +0200 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
4:26cd8f1ef0b1 | 5:f762bf195c4b |
---|---|
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 ------------------------------------------------------------*/ |