Various updates to spandsp tests

spandsp logging now passes an opaque pointer to the logging routine, to
increase flexibility. Right now the pointer is set to NULL in all calls.
This commit is contained in:
Steve Underwood 2012-03-28 23:36:30 +08:00
parent c1203b5863
commit 7b9e4ff674
49 changed files with 2067 additions and 1437 deletions

View File

@ -528,9 +528,11 @@ SPAN_DECLARE(void) adsi_tx_set_preamble(adsi_tx_state_t *s,
}
if (postamble_ones_len < 0)
{
#if 0
if (s->standard == ADSI_STANDARD_JCLIP)
s->postamble_ones_len = 5;
else
#endif
s->postamble_ones_len = 5;
}
else

View File

@ -360,8 +360,11 @@ SPAN_DECLARE(void) at_display_call_info(at_state_t *s)
while (call_id)
{
snprintf(buf, sizeof(buf), "%s=%s",
call_id->id ? call_id->id : "NULL", call_id->value ? call_id->value : "<NONE>");
snprintf(buf,
sizeof(buf),
"%s=%s",
call_id->id ? call_id->id : "NULL",
call_id->value ? call_id->value : "<NONE>");
at_put_response(s, buf);
call_id = call_id->next;
}
@ -845,7 +848,6 @@ static const char *at_cmd_D(at_state_t *s, const char *t)
{
int ok;
char *u;
const char *w;
char num[100 + 1];
char ch;
@ -858,7 +860,6 @@ static const char *at_cmd_D(at_state_t *s, const char *t)
ok = FALSE;
/* There are a numbers of options in a dial command string.
Many are completely irrelevant in this application. */
w = t;
u = num;
for ( ; (ch = *t); t++)
{
@ -924,11 +925,13 @@ static const char *at_cmd_D(at_state_t *s, const char *t)
case 'G':
case 'g':
/* GSM07.07 6.2 - Control the CUG supplementary service for this call */
/* Uses index and info values set with command +CCUG. See +CCUG */
/* TODO: */
break;
case 'I':
case 'i':
/* GSM07.07 6.2 - Override Calling Line Identification Restriction (CLIR) */
/* I=invocation (restrict CLI presentation), i=suppression (allow CLI presentation). See +CLIR */
/* TODO: */
break;
case ';':
@ -2326,6 +2329,10 @@ static const char *at_cmd_plus_CLIR(at_state_t *s, const char *t)
{
/* 3GPP TS 27.007 7.7 - Calling line identification restriction */
/* TODO: */
/* Parameter sets the adjustment for outgoing calls:
0 presentation indicator is used according to the subscription of the CLIR service
1 CLIR invocation
2 CLIR suppression */
t += 5;
if (!parse_out(s, &t, NULL, 1, "+CLIR:", ""))
return NULL;

View File

@ -42,146 +42,274 @@
#include "spandsp/complex.h"
#include "spandsp/dds.h"
/* In a A-law or u-law channel, a 128 step sine table is adequate to keep the spectral
/* In a A-law or u-law channel, a fairly coarse step sine table is adequate to keep the spectral
mess due to the DDS at a similar level to the spectral mess due to the A-law or u-law
compression. */
#define SLENK 7
#define SLENK 8
#define DDS_STEPS (1 << SLENK)
#define DDS_SHIFT (32 - 2 - SLENK)
/* This is a simple set of direct digital synthesis (DDS) functions to generate sine
waves. This version uses a 128 entry sin/cos table to cover one quadrant. */
waves. This version uses a 256 entry sin/cos table to cover one quadrant. */
static const int16_t sine_table[DDS_STEPS + 1] =
{
0,
201,
402,
603,
804,
1005,
1206,
1407,
1608,
1809,
2009,
2210,
2410,
2611,
2811,
3012,
3212,
3412,
3812,
4211,
3612,
3811,
4011,
4210,
4410,
4609,
4808,
5007,
5205,
5404,
5602,
5800,
5998,
6195,
6393,
6590,
6786,
6983,
7376,
7179,
7375,
7571,
7767,
7962,
8157,
8546,
8351,
8545,
8739,
8933,
9126,
9319,
9512,
9704,
10088,
9896,
10087,
10278,
10469,
10850,
10659,
10849,
11039,
11228,
11417,
11605,
11793,
11980,
12354,
12167,
12353,
12539,
12725,
13095,
13463,
12910,
13094,
13279,
13462,
13645,
13828,
14192,
14010,
14191,
14372,
14553,
14732,
14912,
15090,
15269,
15624,
15446,
15623,
15800,
15976,
16326,
16151,
16325,
16499,
16673,
16846,
17018,
17361,
17189,
17360,
17530,
17700,
17869,
18037,
18372,
18204,
18371,
18537,
18703,
18868,
19032,
19358,
19681,
20001,
20318,
20632,
20943,
21251,
21555,
19195,
19357,
19519,
19680,
19841,
20000,
20159,
20317,
20475,
20631,
20787,
20942,
21096,
21250,
21403,
21554,
21705,
21856,
22005,
22154,
22449,
22740,
23028,
23312,
23593,
22301,
22448,
22594,
22739,
22884,
23027,
23170,
23311,
23452,
23592,
23731,
23870,
24144,
24414,
24007,
24143,
24279,
24413,
24547,
24680,
24943,
25202,
25457,
24811,
24942,
25072,
25201,
25329,
25456,
25582,
25708,
25956,
26199,
26439,
25832,
25955,
26077,
26198,
26319,
26438,
26556,
26674,
26906,
26790,
26905,
27019,
27133,
27357,
27576,
27791,
28002,
28209,
27245,
27356,
27466,
27575,
27683,
27790,
27896,
28001,
28105,
28208,
28310,
28411,
28610,
28510,
28609,
28706,
28803,
28993,
29178,
29359,
29535,
29707,
29875,
30038,
30196,
30350,
30499,
30644,
30784,
30920,
28898,
28992,
29085,
29177,
29268,
29358,
29447,
29534,
29621,
29706,
29791,
29874,
29956,
30037,
30117,
30195,
30273,
30349,
30424,
30498,
30571,
30643,
30714,
30783,
30852,
30919,
30985,
31050,
31177,
31298,
31415,
31527,
31634,
31737,
31834,
31927,
32015,
32099,
32177,
32251,
32319,
32383,
32442,
32496,
32546,
32590,
32629,
32664,
32693,
32718,
32738,
32753,
32762,
32767,
31113,
31176,
31237,
31297,
31356,
31414,
31470,
31526,
31580,
31633,
31685,
31736,
31785,
31833,
31880,
31926,
31971,
32014,
32057,
32098,
32137,
32176,
32213,
32250,
32285,
32318,
32351,
32382,
32412,
32441,
32469,
32495,
32521,
32545,
32567,
32589,
32609,
32628,
32646,
32663,
32678,
32692,
32705,
32717,
32728,
32737,
32745,
32752,
32757,
32761,
32765,
32766,
32767
};

View File

@ -224,11 +224,12 @@ SPAN_DECLARE(int) dtmf_rx(dtmf_rx_state_t *s, const int16_t amp[], int samples)
total, row and coloumn power levels for detailed analysis of detection problems. */
span_log(&s->logging,
SPAN_LOG_FLOW,
"Potentially '%c' - total %.2fdB, row %.2fdB, col %.2fdB - %s\n",
"Potentially '%c' - total %.2fdB, row %.2fdB, col %.2fdB, duration %d - %s\n",
dtmf_positions[(best_row << 2) + best_col],
log10f(s->energy)*10.0f - DTMF_POWER_OFFSET + DBM0_MAX_POWER,
log10f(row_energy[best_row]/DTMF_TO_TOTAL_ENERGY)*10.0f - DTMF_POWER_OFFSET + DBM0_MAX_POWER,
log10f(col_energy[best_col]/DTMF_TO_TOTAL_ENERGY)*10.0f - DTMF_POWER_OFFSET + DBM0_MAX_POWER,
s->duration,
(hit) ? "hit" : "miss");
}
}
@ -315,6 +316,28 @@ SPAN_DECLARE(int) dtmf_rx(dtmf_rx_state_t *s, const int16_t amp[], int samples)
}
/*- End of function --------------------------------------------------------*/
SPAN_DECLARE(int) dtmf_rx_fillin(dtmf_rx_state_t *s, int samples)
{
int i;
/* Restart any Goertzel and energy gathering operation we might be in the middle of. */
for (i = 0; i < 4; i++)
{
goertzel_reset(&s->row_out[i]);
goertzel_reset(&s->col_out[i]);
}
#if defined(SPANDSP_USE_FIXED_POINT)
s->energy = 0;
#else
s->energy = 0.0f;
#endif
s->current_sample = 0;
/* Don't update the hit detection. Pretend it never happened. */
/* TODO: Surely we can be a cleverer than this. */
return 0;
}
/*- End of function --------------------------------------------------------*/
SPAN_DECLARE(int) dtmf_rx_status(dtmf_rx_state_t *s)
{
if (s->in_digit)

View File

@ -183,14 +183,14 @@ static void set_rx_handler(fax_state_t *s,
}
/*- End of function --------------------------------------------------------*/
static void set_tx_handler(fax_state_t *s, span_tx_handler_t *handler, void *user_data)
static void fax_modems_set_tx_handler(fax_state_t *s, span_tx_handler_t *handler, void *user_data)
{
s->modems.tx_handler = handler;
s->modems.tx_user_data = user_data;
}
/*- End of function --------------------------------------------------------*/
static void set_next_tx_handler(fax_state_t *s, span_tx_handler_t *handler, void *user_data)
static void fax_modems_set_next_tx_handler(fax_state_t *s, span_tx_handler_t *handler, void *user_data)
{
s->modems.next_tx_handler = handler;
s->modems.next_tx_user_data = user_data;
@ -204,13 +204,12 @@ static int v17_v21_rx(void *user_data, const int16_t amp[], int len)
t = (fax_state_t *) user_data;
s = &t->modems;
v17_rx(&s->v17_rx, amp, len);
v17_rx(&s->fast_modems.v17_rx, amp, len);
if (t->t30.rx_trained)
{
/* The fast modem has trained, so we no longer need to run the slow
one in parallel. */
span_log(&t->logging, SPAN_LOG_FLOW, "Switching from V.17 + V.21 to V.17 (%.2fdBm0)\n", v17_rx_signal_power(&s->v17_rx));
set_rx_handler(t, (span_rx_handler_t *) &v17_rx, (span_rx_fillin_handler_t *) &v17_rx_fillin, &s->v17_rx);
/* The fast modem has trained, so we no longer need to run the slow one in parallel. */
span_log(&t->logging, SPAN_LOG_FLOW, "Switching from V.17 + V.21 to V.17 (%.2fdBm0)\n", v17_rx_signal_power(&s->fast_modems.v17_rx));
set_rx_handler(t, (span_rx_handler_t *) &v17_rx, (span_rx_fillin_handler_t *) &v17_rx_fillin, &s->fast_modems.v17_rx);
}
else
{
@ -234,7 +233,7 @@ static int v17_v21_rx_fillin(void *user_data, int len)
t = (fax_state_t *) user_data;
s = &t->modems;
v17_rx_fillin(&s->v17_rx, len);
v17_rx_fillin(&s->fast_modems.v17_rx, len);
fsk_rx_fillin(&s->v21_rx, len);
return 0;
}
@ -247,13 +246,12 @@ static int v27ter_v21_rx(void *user_data, const int16_t amp[], int len)
t = (fax_state_t *) user_data;
s = &t->modems;
v27ter_rx(&s->v27ter_rx, amp, len);
v27ter_rx(&s->fast_modems.v27ter_rx, amp, len);
if (t->t30.rx_trained)
{
/* The fast modem has trained, so we no longer need to run the slow
one in parallel. */
span_log(&t->logging, SPAN_LOG_FLOW, "Switching from V.27ter + V.21 to V.27ter (%.2fdBm0)\n", v27ter_rx_signal_power(&s->v27ter_rx));
set_rx_handler(t, (span_rx_handler_t *) &v27ter_rx, (span_rx_fillin_handler_t *) &v27ter_rx_fillin, &s->v27ter_rx);
/* The fast modem has trained, so we no longer need to run the slow one in parallel. */
span_log(&t->logging, SPAN_LOG_FLOW, "Switching from V.27ter + V.21 to V.27ter (%.2fdBm0)\n", v27ter_rx_signal_power(&s->fast_modems.v27ter_rx));
set_rx_handler(t, (span_rx_handler_t *) &v27ter_rx, (span_rx_fillin_handler_t *) &v27ter_rx_fillin, &s->fast_modems.v27ter_rx);
}
else
{
@ -277,7 +275,7 @@ static int v27ter_v21_rx_fillin(void *user_data, int len)
t = (fax_state_t *) user_data;
s = &t->modems;
v27ter_rx_fillin(&s->v27ter_rx, len);
v27ter_rx_fillin(&s->fast_modems.v27ter_rx, len);
fsk_rx_fillin(&s->v21_rx, len);
return 0;
}
@ -290,13 +288,12 @@ static int v29_v21_rx(void *user_data, const int16_t amp[], int len)
t = (fax_state_t *) user_data;
s = &t->modems;
v29_rx(&s->v29_rx, amp, len);
v29_rx(&s->fast_modems.v29_rx, amp, len);
if (t->t30.rx_trained)
{
/* The fast modem has trained, so we no longer need to run the slow
one in parallel. */
span_log(&t->logging, SPAN_LOG_FLOW, "Switching from V.29 + V.21 to V.29 (%.2fdBm0)\n", v29_rx_signal_power(&s->v29_rx));
set_rx_handler(t, (span_rx_handler_t *) &v29_rx, (span_rx_fillin_handler_t *) &v29_rx_fillin, &s->v29_rx);
/* The fast modem has trained, so we no longer need to run the slow one in parallel. */
span_log(&t->logging, SPAN_LOG_FLOW, "Switching from V.29 + V.21 to V.29 (%.2fdBm0)\n", v29_rx_signal_power(&s->fast_modems.v29_rx));
set_rx_handler(t, (span_rx_handler_t *) &v29_rx, (span_rx_fillin_handler_t *) &v29_rx_fillin, &s->fast_modems.v29_rx);
}
else
{
@ -320,7 +317,7 @@ static int v29_v21_rx_fillin(void *user_data, int len)
t = (fax_state_t *) user_data;
s = &t->modems;
v29_rx_fillin(&s->v29_rx, len);
v29_rx_fillin(&s->fast_modems.v29_rx, len);
fsk_rx_fillin(&s->v21_rx, len);
return 0;
}
@ -377,14 +374,14 @@ static int set_next_tx_type(fax_state_t *s)
t = &s->modems;
if (t->next_tx_handler)
{
set_tx_handler(s, t->next_tx_handler, t->next_tx_user_data);
fax_modems_set_tx_handler(s, t->next_tx_handler, t->next_tx_user_data);
t->next_tx_handler = NULL;
return 0;
}
/* If there is nothing else to change to, so use zero length silence */
silence_gen_alter(&t->silence_gen, 0);
set_tx_handler(s, (span_tx_handler_t *) &silence_gen, &t->silence_gen);
set_next_tx_handler(s, (span_tx_handler_t *) NULL, NULL);
fax_modems_set_tx_handler(s, (span_tx_handler_t *) &silence_gen, &t->silence_gen);
fax_modems_set_next_tx_handler(s, (span_tx_handler_t *) NULL, NULL);
t->transmit = FALSE;
return -1;
}
@ -472,18 +469,18 @@ static void fax_set_rx_type(void *user_data, int type, int bit_rate, int short_t
set_rx_handler(s, (span_rx_handler_t *) &fsk_rx, (span_rx_fillin_handler_t *) &fsk_rx_fillin, &t->v21_rx);
break;
case T30_MODEM_V27TER:
v27ter_rx_restart(&t->v27ter_rx, bit_rate, FALSE);
v27ter_rx_set_put_bit(&t->v27ter_rx, put_bit_func, put_bit_user_data);
v27ter_rx_restart(&t->fast_modems.v27ter_rx, bit_rate, FALSE);
v27ter_rx_set_put_bit(&t->fast_modems.v27ter_rx, put_bit_func, put_bit_user_data);
set_rx_handler(s, &v27ter_v21_rx, &v27ter_v21_rx_fillin, s);
break;
case T30_MODEM_V29:
v29_rx_restart(&t->v29_rx, bit_rate, FALSE);
v29_rx_set_put_bit(&t->v29_rx, put_bit_func, put_bit_user_data);
v29_rx_restart(&t->fast_modems.v29_rx, bit_rate, FALSE);
v29_rx_set_put_bit(&t->fast_modems.v29_rx, put_bit_func, put_bit_user_data);
set_rx_handler(s, &v29_v21_rx, &v29_v21_rx_fillin, s);
break;
case T30_MODEM_V17:
v17_rx_restart(&t->v17_rx, bit_rate, short_train);
v17_rx_set_put_bit(&t->v17_rx, put_bit_func, put_bit_user_data);
v17_rx_restart(&t->fast_modems.v17_rx, bit_rate, short_train);
v17_rx_set_put_bit(&t->fast_modems.v17_rx, put_bit_func, put_bit_user_data);
set_rx_handler(s, &v17_v21_rx, &v17_v21_rx_fillin, s);
break;
case T30_MODEM_DONE:
@ -522,8 +519,8 @@ static void fax_set_tx_type(void *user_data, int type, int bit_rate, int short_t
{
case T30_MODEM_PAUSE:
silence_gen_alter(&t->silence_gen, ms_to_samples(short_train));
set_tx_handler(s, (span_tx_handler_t *) &silence_gen, &t->silence_gen);
set_next_tx_handler(s, (span_tx_handler_t *) NULL, NULL);
fax_modems_set_tx_handler(s, (span_tx_handler_t *) &silence_gen, &t->silence_gen);
fax_modems_set_next_tx_handler(s, (span_tx_handler_t *) NULL, NULL);
t->transmit = TRUE;
break;
case T30_MODEM_CED:
@ -533,8 +530,8 @@ static void fax_set_tx_type(void *user_data, int type, int bit_rate, int short_t
else
tone = MODEM_CONNECT_TONES_FAX_CNG;
modem_connect_tones_tx_init(&t->connect_tx, tone);
set_tx_handler(s, (span_tx_handler_t *) &modem_connect_tones_tx, &t->connect_tx);
set_next_tx_handler(s, (span_tx_handler_t *) NULL, NULL);
fax_modems_set_tx_handler(s, (span_tx_handler_t *) &modem_connect_tones_tx, &t->connect_tx);
fax_modems_set_next_tx_handler(s, (span_tx_handler_t *) NULL, NULL);
t->transmit = TRUE;
break;
case T30_MODEM_V21:
@ -546,38 +543,38 @@ static void fax_set_tx_type(void *user_data, int type, int bit_rate, int short_t
a 75ms gap before any V.21 transmission is harmless, adds little to the overall length of
a call, and ensures the receiving end is ready. */
silence_gen_alter(&t->silence_gen, ms_to_samples(75));
set_tx_handler(s, (span_tx_handler_t *) &silence_gen, &t->silence_gen);
set_next_tx_handler(s, (span_tx_handler_t *) &fsk_tx, &t->v21_tx);
fax_modems_set_tx_handler(s, (span_tx_handler_t *) &silence_gen, &t->silence_gen);
fax_modems_set_next_tx_handler(s, (span_tx_handler_t *) &fsk_tx, &t->v21_tx);
t->transmit = TRUE;
break;
case T30_MODEM_V27TER:
silence_gen_alter(&t->silence_gen, ms_to_samples(75));
/* For any fast modem, set 200ms of preamble flags */
hdlc_tx_flags(&t->hdlc_tx, bit_rate/(8*5));
v27ter_tx_restart(&t->v27ter_tx, bit_rate, t->use_tep);
v27ter_tx_set_get_bit(&t->v27ter_tx, get_bit_func, get_bit_user_data);
set_tx_handler(s, (span_tx_handler_t *) &silence_gen, &t->silence_gen);
set_next_tx_handler(s, (span_tx_handler_t *) &v27ter_tx, &t->v27ter_tx);
v27ter_tx_restart(&t->fast_modems.v27ter_tx, bit_rate, t->use_tep);
v27ter_tx_set_get_bit(&t->fast_modems.v27ter_tx, get_bit_func, get_bit_user_data);
fax_modems_set_tx_handler(s, (span_tx_handler_t *) &silence_gen, &t->silence_gen);
fax_modems_set_next_tx_handler(s, (span_tx_handler_t *) &v27ter_tx, &t->fast_modems.v27ter_tx);
t->transmit = TRUE;
break;
case T30_MODEM_V29:
silence_gen_alter(&t->silence_gen, ms_to_samples(75));
/* For any fast modem, set 200ms of preamble flags */
hdlc_tx_flags(&t->hdlc_tx, bit_rate/(8*5));
v29_tx_restart(&t->v29_tx, bit_rate, t->use_tep);
v29_tx_set_get_bit(&t->v29_tx, get_bit_func, get_bit_user_data);
set_tx_handler(s, (span_tx_handler_t *) &silence_gen, &t->silence_gen);
set_next_tx_handler(s, (span_tx_handler_t *) &v29_tx, &t->v29_tx);
v29_tx_restart(&t->fast_modems.v29_tx, bit_rate, t->use_tep);
v29_tx_set_get_bit(&t->fast_modems.v29_tx, get_bit_func, get_bit_user_data);
fax_modems_set_tx_handler(s, (span_tx_handler_t *) &silence_gen, &t->silence_gen);
fax_modems_set_next_tx_handler(s, (span_tx_handler_t *) &v29_tx, &t->fast_modems.v29_tx);
t->transmit = TRUE;
break;
case T30_MODEM_V17:
silence_gen_alter(&t->silence_gen, ms_to_samples(75));
/* For any fast modem, set 200ms of preamble flags */
hdlc_tx_flags(&t->hdlc_tx, bit_rate/(8*5));
v17_tx_restart(&t->v17_tx, bit_rate, t->use_tep, short_train);
v17_tx_set_get_bit(&t->v17_tx, get_bit_func, get_bit_user_data);
set_tx_handler(s, (span_tx_handler_t *) &silence_gen, &t->silence_gen);
set_next_tx_handler(s, (span_tx_handler_t *) &v17_tx, &t->v17_tx);
v17_tx_restart(&t->fast_modems.v17_tx, bit_rate, t->use_tep, short_train);
v17_tx_set_get_bit(&t->fast_modems.v17_tx, get_bit_func, get_bit_user_data);
fax_modems_set_tx_handler(s, (span_tx_handler_t *) &silence_gen, &t->silence_gen);
fax_modems_set_next_tx_handler(s, (span_tx_handler_t *) &v17_tx, &t->fast_modems.v17_tx);
t->transmit = TRUE;
break;
case T30_MODEM_DONE:
@ -585,8 +582,8 @@ static void fax_set_tx_type(void *user_data, int type, int bit_rate, int short_t
/* Fall through */
default:
silence_gen_alter(&t->silence_gen, 0);
set_tx_handler(s, (span_tx_handler_t *) &silence_gen, &t->silence_gen);
set_next_tx_handler(s, (span_tx_handler_t *) NULL, NULL);
fax_modems_set_tx_handler(s, (span_tx_handler_t *) &silence_gen, &t->silence_gen);
fax_modems_set_next_tx_handler(s, (span_tx_handler_t *) NULL, NULL);
t->transmit = FALSE;
break;
}

View File

@ -91,7 +91,7 @@ SPAN_DECLARE_NONSTD(int) fax_modems_v17_v21_rx(void *user_data, const int16_t am
fax_modems_state_t *s;
s = (fax_modems_state_t *) user_data;
v17_rx(&s->v17_rx, amp, len);
v17_rx(&s->fast_modems.v17_rx, amp, len);
fsk_rx(&s->v21_rx, amp, len);
if (s->rx_frame_received)
{
@ -111,7 +111,7 @@ SPAN_DECLARE_NONSTD(int) fax_modems_v17_v21_rx_fillin(void *user_data, int len)
fax_modems_state_t *s;
s = (fax_modems_state_t *) user_data;
v17_rx_fillin(&s->v17_rx, len);
v17_rx_fillin(&s->fast_modems.v17_rx, len);
fsk_rx_fillin(&s->v21_rx, len);
return 0;
}
@ -122,7 +122,7 @@ SPAN_DECLARE_NONSTD(int) fax_modems_v27ter_v21_rx(void *user_data, const int16_t
fax_modems_state_t *s;
s = (fax_modems_state_t *) user_data;
v27ter_rx(&s->v27ter_rx, amp, len);
v27ter_rx(&s->fast_modems.v27ter_rx, amp, len);
fsk_rx(&s->v21_rx, amp, len);
if (s->rx_frame_received)
{
@ -142,7 +142,7 @@ SPAN_DECLARE_NONSTD(int) fax_modems_v27ter_v21_rx_fillin(void *user_data, int le
fax_modems_state_t *s;
s = (fax_modems_state_t *) user_data;
v27ter_rx_fillin(&s->v27ter_rx, len);
v27ter_rx_fillin(&s->fast_modems.v27ter_rx, len);
fsk_rx_fillin(&s->v21_rx, len);
return 0;
}
@ -153,7 +153,7 @@ SPAN_DECLARE_NONSTD(int) fax_modems_v29_v21_rx(void *user_data, const int16_t am
fax_modems_state_t *s;
s = (fax_modems_state_t *) user_data;
v29_rx(&s->v29_rx, amp, len);
v29_rx(&s->fast_modems.v29_rx, amp, len);
fsk_rx(&s->v21_rx, amp, len);
if (s->rx_frame_received)
{
@ -173,7 +173,7 @@ SPAN_DECLARE_NONSTD(int) fax_modems_v29_v21_rx_fillin(void *user_data, int len)
fax_modems_state_t *s;
s = (fax_modems_state_t *) user_data;
v29_rx_fillin(&s->v29_rx, len);
v29_rx_fillin(&s->fast_modems.v29_rx, len);
fsk_rx_fillin(&s->v21_rx, len);
return 0;
}
@ -195,10 +195,10 @@ static void v17_rx_status_handler(void *user_data, int status)
switch (status)
{
case SIG_STATUS_TRAINING_SUCCEEDED:
span_log(&s->logging, SPAN_LOG_FLOW, "Switching to V.17 (%.2fdBm0)\n", v17_rx_signal_power(&s->v17_rx));
span_log(&s->logging, SPAN_LOG_FLOW, "Switching to V.17 (%.2fdBm0)\n", v17_rx_signal_power(&s->fast_modems.v17_rx));
s->rx_handler = (span_rx_handler_t *) &v17_rx;
s->rx_fillin_handler = (span_rx_fillin_handler_t *) &v17_rx_fillin;
s->rx_user_data = &s->v17_rx;
s->rx_user_data = &s->fast_modems.v17_rx;
break;
}
}
@ -212,10 +212,10 @@ static void v27ter_rx_status_handler(void *user_data, int status)
switch (status)
{
case SIG_STATUS_TRAINING_SUCCEEDED:
span_log(&s->logging, SPAN_LOG_FLOW, "Switching to V.27ter (%.2fdBm0)\n", v27ter_rx_signal_power(&s->v27ter_rx));
span_log(&s->logging, SPAN_LOG_FLOW, "Switching to V.27ter (%.2fdBm0)\n", v27ter_rx_signal_power(&s->fast_modems.v27ter_rx));
s->rx_handler = (span_rx_handler_t *) &v27ter_rx;
s->rx_fillin_handler = (span_rx_fillin_handler_t *) &v27ter_rx_fillin;
s->rx_user_data = &s->v27ter_rx;
s->rx_user_data = &s->fast_modems.v27ter_rx;
break;
}
}
@ -229,10 +229,10 @@ static void v29_rx_status_handler(void *user_data, int status)
switch (status)
{
case SIG_STATUS_TRAINING_SUCCEEDED:
span_log(&s->logging, SPAN_LOG_FLOW, "Switching to V.29 (%.2fdBm0)\n", v29_rx_signal_power(&s->v29_rx));
span_log(&s->logging, SPAN_LOG_FLOW, "Switching to V.29 (%.2fdBm0)\n", v29_rx_signal_power(&s->fast_modems.v29_rx));
s->rx_handler = (span_rx_handler_t *) &v29_rx;
s->rx_fillin_handler = (span_rx_fillin_handler_t *) &v29_rx_fillin;
s->rx_user_data = &s->v29_rx;
s->rx_user_data = &s->fast_modems.v29_rx;
break;
}
}
@ -243,13 +243,13 @@ SPAN_DECLARE(void) fax_modems_start_rx_modem(fax_modems_state_t *s, int which)
switch (which)
{
case FAX_MODEM_V17_RX:
v17_rx_set_modem_status_handler(&s->v17_rx, v17_rx_status_handler, s);
v17_rx_set_modem_status_handler(&s->fast_modems.v17_rx, v17_rx_status_handler, s);
break;
case FAX_MODEM_V27TER_RX:
v27ter_rx_set_modem_status_handler(&s->v27ter_rx, v27ter_rx_status_handler, s);
v27ter_rx_set_modem_status_handler(&s->fast_modems.v27ter_rx, v27ter_rx_status_handler, s);
break;
case FAX_MODEM_V29_RX:
v29_rx_set_modem_status_handler(&s->v29_rx, v29_rx_status_handler, s);
v29_rx_set_modem_status_handler(&s->fast_modems.v29_rx, v29_rx_status_handler, s);
break;
}
fsk_rx_set_modem_status_handler(&s->v21_rx, v21_rx_status_handler, s);
@ -262,6 +262,12 @@ SPAN_DECLARE(void) fax_modems_set_tep_mode(fax_modems_state_t *s, int use_tep)
}
/*- End of function --------------------------------------------------------*/
SPAN_DECLARE(logging_state_t *) fax_modems_get_logging_state(fax_modems_state_t *s)
{
return &s->logging;
}
/*- End of function --------------------------------------------------------*/
SPAN_DECLARE(int) fax_modems_restart(fax_modems_state_t *s)
{
return 0;
@ -290,13 +296,13 @@ SPAN_DECLARE(fax_modems_state_t *) fax_modems_init(fax_modems_state_t *s,
fsk_rx_init(&s->v21_rx, &preset_fsk_specs[FSK_V21CH2], FSK_FRAME_MODE_SYNC, (put_bit_func_t) hdlc_rx_put_bit, &s->hdlc_rx);
fsk_rx_signal_cutoff(&s->v21_rx, -39.09f);
fsk_tx_init(&s->v21_tx, &preset_fsk_specs[FSK_V21CH2], (get_bit_func_t) hdlc_tx_get_bit, &s->hdlc_tx);
v17_rx_init(&s->v17_rx, 14400, non_ecm_put_bit, user_data);
v17_tx_init(&s->v17_tx, 14400, s->use_tep, non_ecm_get_bit, user_data);
v29_rx_init(&s->v29_rx, 9600, non_ecm_put_bit, user_data);
v29_rx_signal_cutoff(&s->v29_rx, -45.5f);
v29_tx_init(&s->v29_tx, 9600, s->use_tep, non_ecm_get_bit, user_data);
v27ter_rx_init(&s->v27ter_rx, 4800, non_ecm_put_bit, user_data);
v27ter_tx_init(&s->v27ter_tx, 4800, s->use_tep, non_ecm_get_bit, user_data);
v17_rx_init(&s->fast_modems.v17_rx, 14400, non_ecm_put_bit, user_data);
v17_tx_init(&s->fast_modems.v17_tx, 14400, s->use_tep, non_ecm_get_bit, user_data);
v29_rx_init(&s->fast_modems.v29_rx, 9600, non_ecm_put_bit, user_data);
v29_rx_signal_cutoff(&s->fast_modems.v29_rx, -45.5f);
v29_tx_init(&s->fast_modems.v29_tx, 9600, s->use_tep, non_ecm_get_bit, user_data);
v27ter_rx_init(&s->fast_modems.v27ter_rx, 4800, non_ecm_put_bit, user_data);
v27ter_tx_init(&s->fast_modems.v27ter_tx, 4800, s->use_tep, non_ecm_get_bit, user_data);
silence_gen_init(&s->silence_gen, 0);
modem_connect_tones_tx_init(&s->connect_tx, MODEM_CONNECT_TONES_FAX_CNG);
if (tone_callback)

View File

@ -46,10 +46,10 @@
#include "spandsp/private/logging.h"
static void default_message_handler(int level, const char *text);
static void default_message_handler(void *user_data, int level, const char *text);
static message_handler_func_t __span_message = &default_message_handler;
static error_handler_func_t __span_error = NULL;
static void *__user_data = NULL;
/* Note that this list *must* match the enum definition in logging.h */
static const char *severities[] =
@ -67,7 +67,7 @@ static const char *severities[] =
"DEBUG 3"
};
static void default_message_handler(int level, const char *text)
static void default_message_handler(void *user_data, int level, const char *text)
{
fprintf(stderr, "%s", text);
}
@ -138,14 +138,10 @@ SPAN_DECLARE(int) span_log(logging_state_t *s, int level, const char *format, ..
}
/*endif*/
len += vsnprintf(msg + len, 1024 - len, format, arg_ptr);
if (s->span_error && level == SPAN_LOG_ERROR)
s->span_error(msg);
else if (__span_error && level == SPAN_LOG_ERROR)
__span_error(msg);
else if (s->span_message)
s->span_message(level, msg);
if (s->span_message)
s->span_message(s->user_data, level, msg);
else if (__span_message)
__span_message(level, msg);
__span_message(s->user_data, level, msg);
/*endif*/
va_end(arg_ptr);
return 1;
@ -215,27 +211,17 @@ SPAN_DECLARE(int) span_log_bump_samples(logging_state_t *s, int samples)
}
/*- End of function --------------------------------------------------------*/
SPAN_DECLARE(void) span_log_set_message_handler(logging_state_t *s, message_handler_func_t func)
SPAN_DECLARE(void) span_log_set_message_handler(logging_state_t *s, message_handler_func_t func, void *user_data)
{
s->span_message = func;
s->user_data = user_data;
}
/*- End of function --------------------------------------------------------*/
SPAN_DECLARE(void) span_log_set_error_handler(logging_state_t *s, error_handler_func_t func)
{
s->span_error = func;
}
/*- End of function --------------------------------------------------------*/
SPAN_DECLARE(void) span_set_message_handler(message_handler_func_t func)
SPAN_DECLARE(void) span_set_message_handler(message_handler_func_t func, void *user_data)
{
__span_message = func;
}
/*- End of function --------------------------------------------------------*/
SPAN_DECLARE(void) span_set_error_handler(error_handler_func_t func)
{
__span_error = func;
__user_data = user_data;
}
/*- End of function --------------------------------------------------------*/
@ -246,7 +232,6 @@ SPAN_DECLARE(logging_state_t *) span_log_init(logging_state_t *s, int level, con
if ((s = (logging_state_t *) malloc(sizeof(*s))) == NULL)
return NULL;
}
s->span_error = __span_error;
s->span_message = __span_message;
s->level = level;
s->tag = tag;

View File

@ -203,7 +203,6 @@ static void dynamic_pitch_tracking(lpc10_encode_state_t *s,
{
int32_t pbar;
float sbar;
int32_t path[2];
int32_t i;
int32_t j;
float alpha;
@ -292,10 +291,7 @@ static void dynamic_pitch_tracking(lpc10_encode_state_t *s,
/* TRACE: look back two frames to find minimum cost pitch estimate */
*pitch = *midx;
for (i = 0, j = s->ipoint; i < 2; i++, j++)
{
*pitch = s->p[j & 1][*pitch - 1];
path[i] = *pitch;
}
/* The following statement subtracts one from IPOINT, mod DEPTH. I */
/* think the author chose to add DEPTH-1, instead of subtracting 1, */

View File

@ -165,10 +165,8 @@ SPAN_DECLARE(int) plc_fillin(plc_state_t *s, int16_t amp[], int len)
float old_weight;
float new_weight;
float gain;
//int16_t *orig_amp;
int orig_len;
//orig_amp = amp;
orig_len = len;
if (s->missing_samples == 0)
{

View File

@ -188,7 +188,6 @@ SPAN_DECLARE(int) queue_read(queue_state_t *s, uint8_t *buf, int len)
SPAN_DECLARE(int) queue_read_byte(queue_state_t *s)
{
int real_len;
int to_end;
int iptr;
int optr;
int byte;
@ -202,7 +201,6 @@ SPAN_DECLARE(int) queue_read_byte(queue_state_t *s)
if (real_len < 1)
return -1;
/*endif*/
to_end = s->len - optr;
byte = s->data[optr];
if (++optr >= s->len)
optr = 0;

View File

@ -31,7 +31,6 @@
#endif
#include <stdlib.h>
#include <stdio.h>
#include <inttypes.h>
#if defined(HAVE_TGMATH_H)
#include <tgmath.h>
@ -648,9 +647,9 @@ SPAN_DECLARE(sig_tone_rx_state_t *) sig_tone_rx_init(sig_tone_rx_state_t *s, int
}
memset(s, 0, sizeof(*s));
#if !defined(SPANDSP_USE_FIXED_POINT)
for (i = 0; i < 3; i++)
for (j = 0; j < 2; j++)
{
for (j = 0; j < 2; j++)
for (i = 0; i < 3; i++)
{
s->tone[j].notch_z1[i] = 0.0f;
s->tone[j].notch_z2[i] = 0.0f;

View File

@ -107,19 +107,12 @@ typedef void (*put_bit_func_t)(void *user_data, int bit);
/*! Bit get function for data pumps */
typedef int (*get_bit_func_t)(void *user_data);
#define modem_rx_status_func_t modem_status_func_t
#define modem_tx_status_func_t modem_status_func_t
/*! Status change callback function for data pumps */
typedef void (*modem_status_func_t)(void *user_data, int status);
enum
{
/*! No parity bit should be used */
ASYNC_PARITY_NONE = 0,
/*! An even parity bit will exist, after the data bits */
ASYNC_PARITY_EVEN,
/*! An odd parity bit will exist, after the data bits */
ASYNC_PARITY_ODD
};
/*!
Asynchronous data transmit descriptor. This defines the state of a single
working instance of a byte to asynchronous serial converter, for use
@ -134,6 +127,16 @@ typedef struct async_tx_state_s async_tx_state_t;
*/
typedef struct async_rx_state_s async_rx_state_t;
enum
{
/*! No parity bit should be used */
ASYNC_PARITY_NONE = 0,
/*! An even parity bit will exist, after the data bits */
ASYNC_PARITY_EVEN,
/*! An odd parity bit will exist, after the data bits */
ASYNC_PARITY_ODD
};
#if defined(__cplusplus)
extern "C"
{

View File

@ -170,6 +170,14 @@ SPAN_DECLARE(void) dtmf_rx_parms(dtmf_rx_state_t *s,
\return The number of samples unprocessed. */
SPAN_DECLARE(int) dtmf_rx(dtmf_rx_state_t *s, const int16_t amp[], int samples);
/*! Fake processing of a missing block of received DTMF audio samples.
(e.g due to packet loss).
\brief Fake processing of a missing block of received DTMF audio samples.
\param s The DTMF receiver context.
\param len The number of samples to fake.
\return The number of samples unprocessed. */
SPAN_DECLARE(int) dtmf_rx_fillin(dtmf_rx_state_t *s, int samples);
/*! Get the status of DTMF detection during processing of the last audio
chunk.
\brief Get the status of DTMF detection during processing of the last

View File

@ -70,6 +70,8 @@
#include <spandsp/private/v29tx.h>
/*#include <spandsp/private/v32bis.h>*/
/*#include <spandsp/private/v34.h>*/
#include <spandsp/private/v42.h>
#include <spandsp/private/v42bis.h>
#include <spandsp/private/at_interpreter.h>
#include <spandsp/private/fax_modems.h>
#include <spandsp/private/timezone.h>
@ -90,8 +92,6 @@
#include <spandsp/private/t38_terminal.h>
#include <spandsp/private/t31.h>
#include <spandsp/private/v18.h>
#include <spandsp/private/v42.h>
#include <spandsp/private/v42bis.h>
#include <spandsp/private/adsi.h>
#endif

View File

@ -70,6 +70,13 @@ SPAN_DECLARE(void) fax_modems_set_tep_mode(fax_modems_state_t *s, int use_tep);
SPAN_DECLARE(int) fax_modems_restart(fax_modems_state_t *s);
/*! Get a pointer to the logging context associated with a FAX modems context.
\brief Get a pointer to the logging context associated with a FAX modems context.
\param s The FAX modems context.
\return A pointer to the logging context, or NULL.
*/
SPAN_DECLARE(logging_state_t *) fax_modems_get_logging_state(fax_modems_state_t *s);
SPAN_DECLARE(fax_modems_state_t *) fax_modems_init(fax_modems_state_t *s,
int use_tep,
hdlc_frame_handler_t hdlc_accept,

View File

@ -213,7 +213,7 @@ const int32_t line_model_d8_coeffs[] =
const int32_t line_model_d9_coeffs[] =
{
80, 31, 4, 42, 42, -61, -81, -64,
121, -102, -26, 1002, -9250, -22562, 39321, 35681,
-121, -102, -26, 1002, -9250, -22562, 39321, 35681,
-35289, 25312, -1457, -229, 15659, -6786, 16791, 3860,
2239, -28730, -11885, 33871, -176, -16421, 18173, -9669,
-10163, 9941, -19365, 3592, -5907, -10257, 5336, -12933,
@ -258,7 +258,7 @@ const float level_measurement_bp_coeffs[] =
};
/*!
The composite source signal "voiced" section from section C.1 of G.168.
The composite source signal "voiced" section from table C.1 of G.168.
*/
const int css_c1[] =
{
@ -282,7 +282,7 @@ const int css_c1[] =
};
/*!
The composite source signal "voiced" section from section C.3 of G.168.
The composite source signal "voiced" section from table C.3 of G.168.
*/
const int css_c3[] =
{

View File

@ -33,11 +33,8 @@
#if !defined(_SPANDSP_LOGGING_H_)
#define _SPANDSP_LOGGING_H_
/*! General logging function for spandsp logging. */
typedef void (*message_handler_func_t)(int level, const char *text);
/*! Error logging function for spandsp logging. */
typedef void (*error_handler_func_t)(const char *text);
/*! Logging function for spandsp logging. */
typedef void (*message_handler_func_t)(void *user_data, int level, const char *text);
/* Logging elements */
enum
@ -117,13 +114,9 @@ SPAN_DECLARE(int) span_log_set_sample_rate(logging_state_t *s, int samples_per_s
SPAN_DECLARE(int) span_log_bump_samples(logging_state_t *s, int samples);
SPAN_DECLARE(void) span_log_set_message_handler(logging_state_t *s, message_handler_func_t func);
SPAN_DECLARE(void) span_log_set_message_handler(logging_state_t *s, message_handler_func_t func, void *user_data);
SPAN_DECLARE(void) span_log_set_error_handler(logging_state_t *s, error_handler_func_t func);
SPAN_DECLARE(void) span_set_message_handler(message_handler_func_t func);
SPAN_DECLARE(void) span_set_error_handler(error_handler_func_t func);
SPAN_DECLARE(void) span_set_message_handler(message_handler_func_t func, void *user_data);
SPAN_DECLARE(logging_state_t *) span_log_init(logging_state_t *s, int level, const char *tag);

View File

@ -96,7 +96,7 @@ struct dtmf_rx_state_s
uint8_t in_digit;
/*! The current sample number within a processing block. */
int current_sample;
/*! Tone state duration */
int duration;

View File

@ -52,24 +52,27 @@ struct fax_modems_state_s
/*! \brief A V.21 FSK modem context used when receiving HDLC over V.21
messages. */
fsk_rx_state_t v21_rx;
/*! \brief A V.17 modem context used when sending FAXes at 7200bps, 9600bps
12000bps or 14400bps */
v17_tx_state_t v17_tx;
/*! \brief A V.29 modem context used when receiving FAXes at 7200bps, 9600bps
12000bps or 14400bps */
v17_rx_state_t v17_rx;
/*! \brief A V.29 modem context used when sending FAXes at 7200bps or
9600bps */
v29_tx_state_t v29_tx;
/*! \brief A V.29 modem context used when receiving FAXes at 7200bps or
9600bps */
v29_rx_state_t v29_rx;
/*! \brief A V.27ter modem context used when sending FAXes at 2400bps or
4800bps */
v27ter_tx_state_t v27ter_tx;
/*! \brief A V.27ter modem context used when receiving FAXes at 2400bps or
4800bps */
v27ter_rx_state_t v27ter_rx;
struct
{
/*! \brief A V.17 modem context used when sending FAXes at 7200bps, 9600bps
12000bps or 14400bps */
v17_tx_state_t v17_tx;
/*! \brief A V.29 modem context used when receiving FAXes at 7200bps, 9600bps
12000bps or 14400bps */
v17_rx_state_t v17_rx;
/*! \brief A V.29 modem context used when sending FAXes at 7200bps or
9600bps */
v29_tx_state_t v29_tx;
/*! \brief A V.29 modem context used when receiving FAXes at 7200bps or
9600bps */
v29_rx_state_t v29_rx;
/*! \brief A V.27ter modem context used when sending FAXes at 2400bps or
4800bps */
v27ter_tx_state_t v27ter_tx;
/*! \brief A V.27ter modem context used when receiving FAXes at 2400bps or
4800bps */
v27ter_rx_state_t v27ter_rx;
} fast_modems;
/*! \brief Used to insert timed silences. */
silence_gen_state_t silence_gen;
/*! \brief CED or CNG generator */
@ -79,9 +82,9 @@ struct fax_modems_state_s
/*! \brief */
dc_restore_state_t dc_restore;
/*! \brief The currently select receiver type */
/*! \brief The currently selected receiver type */
int current_rx_type;
/*! \brief The currently select transmitter type */
/*! \brief The currently selected transmitter type */
int current_tx_type;
/*! \brief TRUE if a carrier is present. Otherwise FALSE. */
@ -91,13 +94,13 @@ struct fax_modems_state_s
/*! \brief TRUE if an HDLC frame has been received correctly. */
int rx_frame_received;
/*! The current receive signal handler */
/*! \brief The current receive signal handler */
span_rx_handler_t *rx_handler;
/*! The current receive missing signal fill-in handler */
/*! \brief The current receive missing signal fill-in handler */
span_rx_fillin_handler_t *rx_fillin_handler;
void *rx_user_data;
/*! The current transmit signal handler */
/*! \brief The current transmit signal handler */
span_tx_handler_t *tx_handler;
void *tx_user_data;

View File

@ -39,7 +39,7 @@ struct logging_state_s
const char *protocol;
message_handler_func_t span_message;
error_handler_func_t span_error;
void *user_data;
};
#endif

View File

@ -95,16 +95,19 @@ struct t38_core_state_s
/*! \brief The fastest data rate supported by the T.38 channel. */
int fastest_image_data_rate;
/*! \brief Pace transmission */
int pace_transmission;
/*! \brief TRUE if IFP packet sequence numbers are relevant. For some transports, like TPKT
over TCP they are not relevent. */
int check_sequence_numbers;
/*! \brief The number of times each packet type will be sent (low byte). The
depth of redundancy (2nd byte). Higher numbers may increase reliability
for UDP transmission. Zero is valid for the indicator packet category,
to suppress all indicator packets (typicaly for TCP transmission). */
int category_control[5];
/*! \brief TRUE if IFP packet sequence numbers are relevant. For some transports, like TPKT
over TCP they are not relevent. */
int check_sequence_numbers;
/*! \brief The sequence number for the next packet to be transmitted */
int tx_seq_no;
/*! \brief The sequence number expected in the next received packet */

View File

@ -32,7 +32,7 @@ typedef struct
{
/*! \brief Internet Aware FAX mode bit mask. */
int iaf;
/*! \brief Required time between T.38 transmissions, in ms. */
/*! \brief Required time between T.38 transmissions, in milliseconds. */
int ms_per_tx_chunk;
/*! \brief Bit fields controlling the way data is packed into chunked for transmission. */
int chunking_modes;
@ -43,6 +43,9 @@ typedef struct
/*! \brief The current transmit step being timed */
int timed_step;
/*! \brief The timed step to go to when we reach idle from the current timed step */
int queued_timed_step;
/*! \brief TRUE is there has been some T.38 data missed (i.e. lost packets) in the current
reception period. */
int rx_data_missing;

View File

@ -59,7 +59,7 @@ typedef struct
const char *far_ident;
/*! \brief The FAX sub-address. */
const char *sub_address;
/*! \brief The FAX DCS information, as an ASCII string. */
/*! \brief The FAX DCS information, as an ASCII hex string. */
const char *dcs;
/*! \brief The first page to transfer. -1 to start at the beginning of the file. */

View File

@ -50,7 +50,7 @@ struct t4_state_s
in no header line. */
const char *header_info;
/*! \brief Optional per instance time zone for the FAX page header timestamp. */
tz_t *tz;
struct tz_s *tz;
/*! \brief The size of the compressed image on the line side, in bits. */
int line_image_size;

View File

@ -55,6 +55,8 @@ executive override tone, confirmation tone).
/*! Tone detection indication callback routine */
typedef void (*tone_report_func_t)(void *user_data, int code, int level, int delay);
typedef void (*tone_segment_func_t)(void *data, int f1, int f2, int duration);
typedef struct super_tone_rx_segment_s super_tone_rx_segment_t;
typedef struct super_tone_rx_descriptor_s super_tone_rx_descriptor_t;
@ -125,13 +127,24 @@ SPAN_DECLARE(int) super_tone_rx_release(super_tone_rx_state_t *s);
*/
SPAN_DECLARE(int) super_tone_rx_free(super_tone_rx_state_t *s);
/*! Define a callback routine to be called to report the valid detection or termination of
one of the monitored tones.
\param s The supervisory tone context.
\param callback The callback routine called to report the valid detection or termination of
one of the monitored tones.
\param user_data An opaque pointer passed when calling the callback routine.
*/
SPAN_DECLARE(void) super_tone_rx_tone_callback(super_tone_rx_state_t *s,
tone_report_func_t callback,
void *user_data);
/*! Define a callback routine to be called each time a tone pattern element is complete. This is
mostly used when analysing a tone.
\param s The supervisory tone context.
\param callback The callback routine.
*/
SPAN_DECLARE(void) super_tone_rx_segment_callback(super_tone_rx_state_t *s,
void (*callback)(void *data, int f1, int f2, int duration));
tone_segment_func_t callback);
/*! Apply supervisory tone detection processing to a block of audio samples.
\brief Apply supervisory tone detection processing to a block of audio samples.
@ -142,6 +155,14 @@ SPAN_DECLARE(void) super_tone_rx_segment_callback(super_tone_rx_state_t *s,
*/
SPAN_DECLARE(int) super_tone_rx(super_tone_rx_state_t *super, const int16_t amp[], int samples);
/*! Allow for a missing block of samples to a supervisory tone detector.
\brief Allow for a missing block of samples to a supervisory tone detector.
\param super The supervisory tone context.
\param samples The number of samples to allow for.
\return The number of samples processed.
*/
SPAN_DECLARE(int) super_tone_rx_fillin(super_tone_rx_state_t *s, int samples);
#if defined(__cplusplus)
}
#endif

View File

@ -36,15 +36,39 @@
???.
*/
/*! A table of the country names associated with each possible value of the T.35 country code
selector octet. */
extern const char *t35_country_codes[256];
#if defined(__cplusplus)
extern "C"
{
#endif
/*! Resolve a T.35 country code its probable likely real value, using heuristics to try to resolve issues
of broken bit order in the country code.
\brief Resolve a T.35 country code with bit reversal resolution.
\param country_code The country code.
\param country_code_extension The country code extension.
\return The true country code, or -1 for an invalid code.
*/
SPAN_DECLARE(int) t35_real_country_code(int country_code, int country_code_extension);
/*! Decode a T.35 country code to a country name, using heuristics to try to resolve issues of broken bit order
in the country code.
\brief Decode a T.35 country code to a country name, with bit reversal resolution.
\param country_code The country code.
\param country_code_extension The country code extension.
\return The country name, or NULL for an invalid country code.
*/
SPAN_DECLARE(const char *) t35_real_country_code_to_str(int country_code, int country_code_extension);
/*! Decode a T.35 country code to a country name.
\brief Decode a T.35 country code to a country name.
\param country_code The country code.
\param country_code_extension The country code extension.
\return The country name, or NULL for an invalid country code.
*/
SPAN_DECLARE(const char *) t35_country_code_to_str(int country_code, int country_code_extension);
SPAN_DECLARE(const char *) t35_vendor_to_str(const uint8_t *msg, int len);
/*! Decode an NSF field to try to determine the make and model of the
remote machine.
\brief Decode an NSF field.

View File

@ -155,7 +155,8 @@ enum t38_transport_types_e
{
T38_TRANSPORT_UDPTL = 0,
T38_TRANSPORT_RTP,
T38_TRANSPORT_TCP
T38_TRANSPORT_TCP,
T38_TRANSPORT_TCP_TPKT
};
/*! T.38 TCF management types */
@ -268,7 +269,7 @@ SPAN_DECLARE(int) t38_core_send_training_delay(t38_core_state_t *s, int indicato
\param field The message data content for the packet.
\param field_len The length of the message data, in bytes.
\param category The category of the packet being sent. This should be one of the values defined for t38_packet_categories_e.
\return ??? */
\return 0 for OK, else -1 */
SPAN_DECLARE(int) t38_core_send_data(t38_core_state_t *s, int data_type, int field_type, const uint8_t field[], int field_len, int category);
/*! \brief Send a data packet
@ -277,10 +278,11 @@ SPAN_DECLARE(int) t38_core_send_data(t38_core_state_t *s, int data_type, int fie
\param field The list of fields.
\param fields The number of fields in the list.
\param category The category of the packet being sent. This should be one of the values defined for t38_packet_categories_e.
\return ??? */
\return 0 for OK, else -1 */
SPAN_DECLARE(int) t38_core_send_data_multi_field(t38_core_state_t *s, int data_type, const t38_data_field_t field[], int fields, int category);
/*! \brief Process a received T.38 IFP packet.
/*! \brief Process a received T.38 IFP packet from an unreliable packet stream (e.g. UDPTL or RTP). This processing includes
packet sequence number checking, missing packet recovery, and skipping repeat packets.
\param s The T.38 context.
\param buf The packet contents.
\param len The length of the packet contents.
@ -288,6 +290,14 @@ SPAN_DECLARE(int) t38_core_send_data_multi_field(t38_core_state_t *s, int data_t
\return 0 for OK, else -1. */
SPAN_DECLARE_NONSTD(int) t38_core_rx_ifp_packet(t38_core_state_t *s, const uint8_t *buf, int len, uint16_t seq_no);
/*! \brief Process a received T.38 IFP packet from a reliable stream (e.g. TCP).
\param s The T.38 context.
\param buf The packet contents.
\param len The length of the packet contents.
\param seq_no The packet sequence number, used for logging purposes.
\return The length of the packet processed, or -1 if there is an error in the packet, or too few bytes of data to complete it. */
SPAN_DECLARE_NONSTD(int) t38_core_rx_ifp_stream(t38_core_state_t *s, const uint8_t *buf, int len, uint16_t log_seq_no);
/*! Set the method to be used for data rate management, as per the T.38 spec.
\param s The T.38 context.
\param method 1 for pass TCF across the T.38 link, 2 for handle TCF locally.
@ -339,6 +349,8 @@ SPAN_DECLARE(void) t38_set_max_datagram_size(t38_core_state_t *s, int max_datagr
information may be encoded in it, such as the redundancy depth for the particular packet category. */
SPAN_DECLARE(void) t38_set_redundancy_control(t38_core_state_t *s, int category, int setting);
SPAN_DECLARE(void) t38_set_pace_transmission(t38_core_state_t *s, int pace_transmission);
SPAN_DECLARE(void) t38_set_fastest_image_data_rate(t38_core_state_t *s, int max_rate);
SPAN_DECLARE(int) t38_get_fastest_image_data_rate(t38_core_state_t *s);

View File

@ -47,7 +47,10 @@ enum
T38_TERMINAL_OPTION_REGULAR_INDICATORS = 0x02,
/*! This option enables the regular repeat transmission of indicator signals for the
first 2s, during periods when no FAX signal transmission occurs. */
T38_TERMINAL_OPTION_2S_REPEATING_INDICATORS = 0x04
T38_TERMINAL_OPTION_2S_REPEATING_INDICATORS = 0x04,
/*! This option suppresses the transmission of indicators. This is usually used with
TCP/TPKT transmission of T.38 FAXes */
T38_TERMINAL_OPTION_NO_INDICATORS = 0x08
};
typedef struct t38_terminal_state_s t38_terminal_state_t;

View File

@ -39,6 +39,10 @@ for FAX transmission.
\section t4_page_sec_1 How does it work?
*/
/*! This function is a callback from the image decoders, to write the decoded bi-level image,
row by row. It is called for each row, with len set to the number of bytes per row. At the
end of the image it is called with len set to zero, to indicate the end of image condition.
\return 0 for OK, or non-zero for a problem that requires the image be interrupted. */
typedef int (*t4_row_write_handler_t)(void *user_data, const uint8_t buf[], size_t len);
/*! Supported compression modes. */
@ -60,12 +64,22 @@ typedef enum
T4_COMPRESSION_ITU_T43 = 6,
/*! T.45 run length colour compression */
T4_COMPRESSION_ITU_T45 = 7,
/*! T.81 + T.30 Annex E colour JPEG coding */
T4_COMPRESSION_ITU_T81 = 8,
/*! T.81 + T.30 Annex K colour sYCC-JPEG coding */
T4_COMPRESSION_ITU_SYCC_T81 = 9
/*! T.42 + T.81 + T.30 Annex E colour JPEG coding */
T4_COMPRESSION_ITU_T42 = 8,
/*! T.42 + T.81 + T.30 Annex K colour sYCC-JPEG coding */
T4_COMPRESSION_ITU_SYCC_T42 = 9
} t4_image_compression_t;
/*! Image type */
typedef enum
{
T4_IMAGE_TYPE_BILEVEL = 0,
T4_IMAGE_TYPE_GRAY_8BIT = 1,
T4_IMAGE_TYPE_GRAY_12BIT = 2,
T4_IMAGE_TYPE_COLOUR_8BIT = 3,
T4_IMAGE_TYPE_COLOUR_12BIT = 4
} t4_image_types_t;
/*! Supported X resolutions, in pixels per metre. */
typedef enum
{

View File

@ -28,12 +28,189 @@
#if !defined(_SPANDSP_T4_TX_H_)
#define _SPANDSP_T4_TX_H_
//#define SPANDSP_SUPPORT_TIFF_FX
/*! This function is a callback from the image decoders, to read the unencoded bi-level image,
row by row. It is called for each row, with len set to the number of bytes per row expected.
\return len for OK, or zero to indicate the end of the image data. */
typedef int (*t4_row_read_handler_t)(void *user_data, uint8_t buf[], size_t len);
#if defined(SPANDSP_SUPPORT_TIFF_FX)
/* TIFF-FX related extensions to the tag set supported by libtiff */
/*
Indexed(346) = 0, 1. SHORT
0: not a palette-color image.
1: palette-color image.
This field is used to indicate that each sample value is an index
into an array of color values specified in the image data stream.
Because the color map is embedded in the image data stream, the
ColorMap field is not used in Profile L. Lossless color fax
profile supports palette-color images with the ITULAB encoding.
The SamplesPerPixel value must be 1.
GlobalParametersIFD (400) IFD
An IFD containing global parameters. It is recommended that a TIFF
writer place this field in the first IFD, where a TIFF reader would
find it quickly.
Each field in the GlobalParametersIFD is a TIFF field that is legal
in any IFD. Required baseline fields should not be located in the
GlobalParametersIFD, but should be in each image IFD. If a conflict
exists between fields in the GlobalParametersIFD and in the image
IFDs, then the data in the image IFD shall prevail.
Among the GlobalParametersIFD entries is a new ProfileType field
which generally describes information in this IFD and in the TIFF
file.
ProfileType(401) LONG
The type of image data stored in this IFD.
0 = Unspecified
1 = Group 3 fax
No default
The following new global fields are defined in this document as IFD
entries for use with fax applications.
FaxProfile(402) = 0 - 6. BYTE
The profile that applies to this file; a profile is subset of the
full set of permitted fields and field values of TIFF for facsimile.
The currently defined values are:
0: does not conform to a profile defined for TIFF for facsimile
1: minimal black & white lossless, Profile S
2: extended black & white lossless, Profile F
3: lossless JBIG black & white, Profile J
4: lossy color and grayscale, Profile C
5: lossless color and grayscale, Profile L
6: Mixed Raster Content, Profile M
CodingMethods(403) LONG
This field indicates which coding methods are used in the file. A
bit value of 1 indicates which of the following coding methods is
used:
Bit 0: unspecified compression,
Bit 1: 1-dimensional coding, ITU-T Rec. T.4 (MH - Modified Huffman),
Bit 2: 2-dimensional coding, ITU-T Rec. T.4 (MR - Modified Read),
Bit 3: 2-dimensional coding, ITU-T Rec. T.6 (MMR - Modified MR),
Bit 4: ITU-T Rec. T.82 coding, using ITU-T Rec. T.85 (JBIG),
Bit 5: ITU-T Rec. T.81 (Baseline JPEG),
Bit 6: ITU-T Rec. T.82 coding, using ITU-T Rec. T.43 (JBIG color),
Bits 7-31: reserved for future use
Note: There is a limit of 32 compression types to identify standard
compression methods.
VersionYear(404) BYTE
Count: 4
The year of the standard specified by the FaxProfile field, given as
4 characters, e.g. '1997'; used in lossy and lossless color modes.
ModeNumber (405) BYTE
The mode of the standard specified by the FaxProfile field. A
value of 0 indicates Mode 1.0; used in Mixed Raster Content mode.
Decode(433) SRATIONAL
Count = 2 * SamplesPerPixel
Describes how to map image sample values into the range of values
appropriate for the current color space. In general, the values
are taken in pairs and specify the minimum and maximum output
value for each color component. For the base color fax profile,
Decode has a count of 6 values and maps the unsigned ITULAB-
encoded sample values (Lsample, asample, bsample) to signed L*a*b*
values, as follows:
L* = Decode[0] + Lsample x (Decode[1]-Decode[0])/(2^n -1)
a* = Decode[2] + asample x (Decode[3]-Decode[2])/(2^n -1)
b* = Decode[4] + bsample x (Decode[5]-Decode[4])/(2^n -1)
where Decode[0], Decode[2] and Decode[4] are the minimum values
for L*, a*, and b*; Decode[1], Decode[3] and Decode[5] are the
maximum values for L*, a*, and b*; and n is the BitsPerSample.
When n=8,=20 L*=Decode[0] when Lsample=0 and L*=Decode[1] when
Lsample=255.
ImageBaseColor(434) SHORT
Count = SamplesPerPixel
In areas of an image layer where no image data is available (i.e.,
where no strips are defined, or where the StripByteCounts entry for
a given strip is 0), the color specified by ImageBaseColor will be
used.
StripRowCounts(559) LONG
Count = number of strips.
The number of scanlines stored in a strip. Profile M allows each
fax strip to store a different number of scanlines. For strips
with more than one layer, the maximum strip size is either 256
scanlines or full page size. The 256 maximum SHOULD be used
unless the capability to receive longer strips has been
negotiated. This field replaces RowsPerStrip for IFDs with
variable-size strips. Only one of the two fields, StripRowCounts
and RowsPerStrip, may be used in an IFD.
ImageLayer(34732) LONG
Count = 2.
Image layers are defined such that layer 1 is the Background
layer, layer 3 is the Foreground layer, and layer 2 is the Mask
layer, which selects pixels from the Background and Foreground
layers. The ImageLayer tag contains two values, which describe
the layer to which the image belongs and the order in which it is
imaged.
ImageLayer[0] = 1, 2, 3.
1: Image is a Background image, i.e. the image that will appear
whenever the Mask contains a value of 0. Background images
typically contain low-resolution, continuous-tone imagery.
2: Image is the Mask layer. In MRC, if the Mask layer is present,
it must be the Primary IFD and be full page in extent.
3: Image is a Foreground image, i.e. the image that will appear
whenever the Mask contains a value of 1. The Foreground image
generally defines the color of text or lines but may also
contain high-resolution imagery.
ImageLayer[1]:
1: first image to be imaged in this layer
2: second image to be imaged in this layer
3: ...
*/
#define TIFFTAG_INDEXED 346
#define TIFFTAG_GLOBALPARAMETERSIFD 400
#define TIFFTAG_PROFILETYPE 401
#define PROFILETYPE_UNSPECIFIED 0
#define PROFILETYPE_G3_FAX 1
#define TIFFTAG_FAXPROFILE 402
#define FAXPROFILE_S 1
#define FAXPROFILE_F 2
#define FAXPROFILE_J 3
#define FAXPROFILE_C 4
#define FAXPROFILE_L 5
#define FAXPROFILE_M 6
#define TIFFTAG_CODINGMETHODS 403
#define CODINGMETHODS_T4_1D (1 << 1)
#define CODINGMETHODS_T4_2D (1 << 2)
#define CODINGMETHODS_T6 (1 << 3)
#define CODINGMETHODS_T85 (1 << 4)
#define CODINGMETHODS_T42 (1 << 5)
#define CODINGMETHODS_T43 (1 << 6)
#define TIFFTAG_VERSIONYEAR 404
#define TIFFTAG_MODENUMBER 405
#define TIFFTAG_DECODE 433
#define TIFFTAG_IMAGEBASECOLOR 434
#define TIFFTAG_T82OPTIONS 435
#define TIFFTAG_STRIPROWCOUNTS 559
#define TIFFTAG_IMAGELAYER 34732
#define COMPRESSION_T85 9
#define COMPRESSION_T43 10
#endif
#if defined(__cplusplus)
extern "C" {
#endif
#if defined(SPANDSP_SUPPORT_TIFF_FX)
/*! \brief Configure libtiff so it recognises the extended tag set for TIFF-FX. */
SPAN_DECLARE(void) TIFF_FX_init(void);
#endif
/*! \brief Prepare for transmission of a document.
\param s The T.4 context.
\param file The name of the file to be sent.

View File

@ -56,14 +56,13 @@
#include "spandsp/private/super_tone_rx.h"
#if defined(SPANDSP_USE_FIXED_POINT)
#define DETECTION_THRESHOLD 16439 /* -42dBm0 */
#define DETECTION_THRESHOLD 16439 /* -42dBm0 [((BINS*BINS*32768.0/(1.4142*128.0))*10^((-42 - DBM0_MAX_SINE_POWER)/20.0))^2] */
#define TONE_TWIST 4 /* 6dB */
#define TONE_TO_TOTAL_ENERGY 64 /* -3dB */
#else
#define DETECTION_THRESHOLD 2104205.6f /* -42dBm0 [(((128.0*32768.0/1.4142)*10^((-42 - DBM0_MAX_SINE_POWER)/20.0))^2)/128 => 2104205.6] */
#define DETECTION_THRESHOLD 2104205.6f /* -42dBm0 [((BINS*BINS*32768.0/1.4142)*10^((-42 - DBM0_MAX_SINE_POWER)/20.0))^2] */
#define TONE_TWIST 3.981f /* 6dB */
#define TONE_TO_TOTAL_ENERGY 1.995f /* 3dB */
#define DTMF_TO_TOTAL_ENERGY 64.152f /* -3dB [BINS*10^(-3/10.0)] */
#endif
static int add_super_tone_freq(super_tone_rx_descriptor_t *desc, int freq)
@ -237,8 +236,17 @@ SPAN_DECLARE(int) super_tone_rx_free_descriptor(super_tone_rx_descriptor_t *desc
}
/*- End of function --------------------------------------------------------*/
SPAN_DECLARE(void) super_tone_rx_tone_callback(super_tone_rx_state_t *s,
tone_report_func_t callback,
void *user_data)
{
s->tone_callback = callback;
s->callback_data = user_data;
}
/*- End of function --------------------------------------------------------*/
SPAN_DECLARE(void) super_tone_rx_segment_callback(super_tone_rx_state_t *s,
void (*callback)(void *data, int f1, int f2, int duration))
tone_segment_func_t callback)
{
s->segment_callback = callback;
}
@ -273,7 +281,11 @@ SPAN_DECLARE(super_tone_rx_state_t *) super_tone_rx_init(super_tone_rx_state_t *
if (desc)
s->desc = desc;
s->detected_tone = -1;
#if defined(SPANDSP_USE_FIXED_POINT)
s->energy = 0;
#else
s->energy = 0.0f;
#endif
for (i = 0; i < desc->monitored_frequencies; i++)
goertzel_init(&s->state[i], &s->desc->desc[i]);
return s;
@ -459,10 +471,21 @@ SPAN_DECLARE(int) super_tone_rx(super_tone_rx_state_t *s, const int16_t amp[], i
{
/* We have finished a Goertzel block. */
super_tone_chunk(s);
#if defined(SPANDSP_USE_FIXED_POINT)
s->energy = 0;
#else
s->energy = 0.0f;
#endif
}
}
return samples;
}
/*- End of function --------------------------------------------------------*/
SPAN_DECLARE(int) super_tone_rx_fillin(super_tone_rx_state_t *s, int samples)
{
/* TODO: Roll the detector forward without a state change */
return 0;
}
/*- End of function --------------------------------------------------------*/
/*- End of file ------------------------------------------------------------*/

View File

@ -1499,7 +1499,7 @@ static int build_dcs(t30_state_t *s)
}
if (bad != T30_ERR_OK)
{
s->current_status = bad;
t30_set_status(s, bad);
span_log(&s->logging, SPAN_LOG_FLOW, "Image resolution (%d x %d) not acceptable\n", s->x_resolution, s->y_resolution);
return -1;
}
@ -1548,7 +1548,7 @@ static int build_dcs(t30_state_t *s)
}
if (bad != T30_ERR_OK)
{
s->current_status = bad;
t30_set_status(s, bad);
span_log(&s->logging, SPAN_LOG_FLOW, "Image width (%d pixels) is not an acceptable FAX image width\n", s->image_width);
return -1;
}
@ -1590,7 +1590,7 @@ static int build_dcs(t30_state_t *s)
}
if (bad != T30_ERR_OK)
{
s->current_status = bad;
t30_set_status(s, bad);
span_log(&s->logging, SPAN_LOG_FLOW, "Image width (%d pixels) is not an acceptable FAX image width\n", s->image_width);
return -1;
}
@ -1699,7 +1699,7 @@ static void return_to_phase_b(t30_state_t *s, int with_fallback)
{
/* We have fallen back as far as we can go. Give up. */
s->current_fallback = 0;
s->current_status = T30_ERR_CANNOT_TRAIN;
t30_set_status(s, T30_ERR_CANNOT_TRAIN);
send_dcn(s);
}
else
@ -1929,7 +1929,7 @@ static int set_min_scan_time_code(t30_state_t *s)
case T4_Y_RESOLUTION_SUPERFINE:
if (!test_ctrl_bit(s->far_dis_dtc_frame, T30_DIS_BIT_200_400_CAPABLE))
{
s->current_status = T30_ERR_NORESSUPPORT;
t30_set_status(s, T30_ERR_NORESSUPPORT);
span_log(&s->logging, SPAN_LOG_FLOW, "Remote FAX does not support super-fine resolution.\n");
return -1;
}
@ -1938,7 +1938,7 @@ static int set_min_scan_time_code(t30_state_t *s)
case T4_Y_RESOLUTION_FINE:
if (!test_ctrl_bit(s->far_dis_dtc_frame, T30_DIS_BIT_200_200_CAPABLE))
{
s->current_status = T30_ERR_NORESSUPPORT;
t30_set_status(s, T30_ERR_NORESSUPPORT);
span_log(&s->logging, SPAN_LOG_FLOW, "Remote FAX does not support fine resolution.\n");
return -1;
}
@ -1969,7 +1969,7 @@ static int start_sending_document(t30_state_t *s)
if (t4_tx_init(&s->t4.tx, s->tx_file, s->tx_start_page, s->tx_stop_page) == NULL)
{
span_log(&s->logging, SPAN_LOG_WARNING, "Cannot open source TIFF file '%s'\n", s->tx_file);
s->current_status = T30_ERR_FILEERROR;
t30_set_status(s, T30_ERR_FILEERROR);
return -1;
}
s->operation_in_progress = OPERATION_IN_PROGRESS_T4_TX;
@ -2034,7 +2034,7 @@ static void unexpected_non_final_frame(t30_state_t *s, const uint8_t *msg, int l
{
span_log(&s->logging, SPAN_LOG_FLOW, "Unexpected %s frame in state %d\n", t30_frametype(msg[2]), s->state);
if (s->current_status == T30_ERR_OK)
s->current_status = T30_ERR_UNEXPECTED;
t30_set_status(s, T30_ERR_UNEXPECTED);
}
/*- End of function --------------------------------------------------------*/
@ -2042,7 +2042,7 @@ static void unexpected_final_frame(t30_state_t *s, const uint8_t *msg, int len)
{
span_log(&s->logging, SPAN_LOG_FLOW, "Unexpected %s frame in state %d\n", t30_frametype(msg[2]), s->state);
if (s->current_status == T30_ERR_OK)
s->current_status = T30_ERR_UNEXPECTED;
t30_set_status(s, T30_ERR_UNEXPECTED);
send_dcn(s);
}
/*- End of function --------------------------------------------------------*/
@ -2051,7 +2051,7 @@ static void unexpected_frame_length(t30_state_t *s, const uint8_t *msg, int len)
{
span_log(&s->logging, SPAN_LOG_FLOW, "Unexpected %s frame length - %d\n", t30_frametype(msg[0]), len);
if (s->current_status == T30_ERR_OK)
s->current_status = T30_ERR_UNEXPECTED;
t30_set_status(s, T30_ERR_UNEXPECTED);
send_dcn(s);
}
/*- End of function --------------------------------------------------------*/
@ -2153,7 +2153,7 @@ static int process_rx_dis_dtc(t30_state_t *s, const uint8_t *msg, int len)
default:
span_log(&s->logging, SPAN_LOG_FLOW, "Remote does not support a compatible modem\n");
/* We cannot talk to this machine! */
s->current_status = T30_ERR_INCOMPATIBLE;
t30_set_status(s, T30_ERR_INCOMPATIBLE);
return -1;
}
if (s->phase_b_handler)
@ -2162,7 +2162,7 @@ static int process_rx_dis_dtc(t30_state_t *s, const uint8_t *msg, int len)
if (new_status != T30_ERR_OK)
{
span_log(&s->logging, SPAN_LOG_FLOW, "Application rejected DIS/DTC - '%s'\n", t30_completion_code_to_str(new_status));
s->current_status = new_status;
t30_set_status(s, new_status);
/* TODO: If FNV is allowed, process it here */
send_dcn(s);
return -1;
@ -2230,7 +2230,7 @@ static int process_rx_dis_dtc(t30_state_t *s, const uint8_t *msg, int len)
if (!test_ctrl_bit(s->far_dis_dtc_frame, T30_DIS_BIT_READY_TO_RECEIVE_FAX_DOCUMENT))
{
span_log(&s->logging, SPAN_LOG_FLOW, "%s far end cannot receive\n", t30_frametype(msg[2]));
s->current_status = T30_ERR_RX_INCAPABLE;
t30_set_status(s, T30_ERR_RX_INCAPABLE);
send_dcn(s);
}
if (start_sending_document(s))
@ -2256,7 +2256,7 @@ static int process_rx_dis_dtc(t30_state_t *s, const uint8_t *msg, int len)
if (!test_ctrl_bit(s->far_dis_dtc_frame, T30_DIS_BIT_READY_TO_TRANSMIT_FAX_DOCUMENT))
{
span_log(&s->logging, SPAN_LOG_FLOW, "%s far end cannot transmit\n", t30_frametype(msg[2]));
s->current_status = T30_ERR_TX_INCAPABLE;
t30_set_status(s, T30_ERR_TX_INCAPABLE);
send_dcn(s);
return -1;
}
@ -2267,7 +2267,7 @@ static int process_rx_dis_dtc(t30_state_t *s, const uint8_t *msg, int len)
}
if (set_dis_or_dtc(s))
{
s->current_status = T30_ERR_INCOMPATIBLE;
t30_set_status(s, T30_ERR_INCOMPATIBLE);
send_dcn(s);
return -1;
}
@ -2404,7 +2404,7 @@ static int process_rx_dcs(t30_state_t *s, const uint8_t *msg, int len)
if (new_status != T30_ERR_OK)
{
span_log(&s->logging, SPAN_LOG_FLOW, "Application rejected DCS - '%s'\n", t30_completion_code_to_str(new_status));
s->current_status = new_status;
t30_set_status(s, new_status);
/* TODO: If FNV is allowed, process it here */
send_dcn(s);
return -1;
@ -2419,7 +2419,7 @@ static int process_rx_dcs(t30_state_t *s, const uint8_t *msg, int len)
if (s->rx_file[0] == '\0')
{
span_log(&s->logging, SPAN_LOG_FLOW, "No document to receive\n");
s->current_status = T30_ERR_FILEERROR;
t30_set_status(s, T30_ERR_FILEERROR);
send_dcn(s);
return -1;
}
@ -2428,7 +2428,7 @@ static int process_rx_dcs(t30_state_t *s, const uint8_t *msg, int len)
if (t4_rx_init(&s->t4.rx, s->rx_file, s->output_encoding) == NULL)
{
span_log(&s->logging, SPAN_LOG_WARNING, "Cannot open target TIFF file '%s'\n", s->rx_file);
s->current_status = T30_ERR_FILEERROR;
t30_set_status(s, T30_ERR_FILEERROR);
send_dcn(s);
return -1;
}
@ -2467,8 +2467,6 @@ static int send_response_to_pps(t30_state_t *s)
}
/*- End of function --------------------------------------------------------*/
#define VET_ALL_FCD_FRAMES
static int process_rx_pps(t30_state_t *s, const uint8_t *msg, int len)
{
int page;
@ -2478,11 +2476,8 @@ static int process_rx_pps(t30_state_t *s, const uint8_t *msg, int len)
int j;
int frame_no;
int first_bad_frame;
int image_ended;
#if defined(VET_ALL_FCD_FRAMES)
int first;
int expected_len;
#endif
if (len < 7)
{
@ -2557,7 +2552,7 @@ static int process_rx_pps(t30_state_t *s, const uint8_t *msg, int len)
else
{
/* Give up */
s->current_status = T30_ERR_RX_ECMPHD;
t30_set_status(s, T30_ERR_RX_ECMPHD);
send_dcn(s);
}
return 0;
@ -2565,10 +2560,8 @@ static int process_rx_pps(t30_state_t *s, const uint8_t *msg, int len)
/* Build a bit map of which frames we now have stored OK */
first_bad_frame = 256;
#if defined(VET_ALL_FCD_FRAMES)
first = TRUE;
expected_len = 256;
#endif
for (i = 0; i < 32; i++)
{
s->ecm_frame_map[i + 3] = 0;
@ -2578,14 +2571,26 @@ static int process_rx_pps(t30_state_t *s, const uint8_t *msg, int len)
#if defined(VET_ALL_FCD_FRAMES)
if (s->ecm_len[frame_no] >= 0)
{
/* The correct pattern of frame lengths is they will all be 64 or 256 octets long, except the
last one. The last one might the same length as all the others, or it might be exactly the
right length to contain the last chunk of the data. That is, some people pad at the end,
and some do not. */
/* Vet the frames which are present, to detect any with inappropriate lengths. This might seem
like overkill, as the frames must have had good CRCs to get this far. However, in the real
world there are systems, especially T.38 ones, which give bad frame lengths, and which screw
up communication unless you apply these checks. From experience, if you find a frame has a
suspect length, and demand retransmission, there is a good chance the new copy will be alright. */
if (frame_no < s->ecm_frames - 1)
{
/* Expect all frames, except the last one, to follow the length of the first one */
if (first)
{
/* Use the length of the first frame as our model for what the length should be */
if (s->ecm_len[frame_no] == 64)
expected_len = 64;
first = FALSE;
}
/* Check the length is consistent with the first frame */
if (s->ecm_len[frame_no] != expected_len)
{
span_log(&s->logging, SPAN_LOG_FLOW, "Bad length ECM frame - %d\n", s->ecm_len[frame_no]);
@ -2608,13 +2613,11 @@ static int process_rx_pps(t30_state_t *s, const uint8_t *msg, int len)
if (s->rx_ecm_block_ok)
{
span_log(&s->logging, SPAN_LOG_FLOW, "Partial page OK - committing block %d, %d frames\n", s->ecm_block, s->ecm_frames);
image_ended = FALSE;
for (i = 0; i < s->ecm_frames; i++)
{
if (t4_rx_put_chunk(&s->t4.rx, s->ecm_data[i], s->ecm_len[i]))
{
/* This is the end of the document */
image_ended = TRUE;
break;
}
}
@ -2776,7 +2779,7 @@ static void process_rx_fcd(t30_state_t *s, const uint8_t *msg, int len)
}
/* We have received something, so any missing carrier status is out of date */
if (s->current_status == T30_ERR_RX_NOCARRIER)
s->current_status = T30_ERR_OK;
t30_set_status(s, T30_ERR_OK);
break;
default:
unexpected_non_final_frame(s, msg, len);
@ -2797,7 +2800,7 @@ static void process_rx_rcp(t30_state_t *s, const uint8_t *msg, int len)
timer_t2_start(s);
/* We have received something, so any missing carrier status is out of date */
if (s->current_status == T30_ERR_RX_NOCARRIER)
s->current_status = T30_ERR_OK;
t30_set_status(s, T30_ERR_OK);
break;
case T30_STATE_F_POST_DOC_ECM:
/* Just ignore this. It must be an extra RCP. Several are usually sent, to maximise the chance
@ -2915,7 +2918,7 @@ static void process_state_answering(t30_state_t *s, const uint8_t *msg, int len)
process_rx_dcs(s, msg, len);
break;
case T30_DCN:
s->current_status = T30_ERR_TX_GOTDCN;
t30_set_status(s, T30_ERR_TX_GOTDCN);
disconnect(s);
break;
default:
@ -2983,7 +2986,7 @@ static void process_state_d(t30_state_t *s, const uint8_t *msg, int len)
switch (fcf)
{
case T30_DCN:
s->current_status = T30_ERR_TX_BADDCS;
t30_set_status(s, T30_ERR_TX_BADDCS);
disconnect(s);
break;
case T30_CRP:
@ -3009,7 +3012,7 @@ static void process_state_d_tcf(t30_state_t *s, const uint8_t *msg, int len)
switch (fcf)
{
case T30_DCN:
s->current_status = T30_ERR_TX_BADDCS;
t30_set_status(s, T30_ERR_TX_BADDCS);
disconnect(s);
break;
case T30_CRP:
@ -3059,7 +3062,7 @@ static void process_state_d_post_tcf(t30_state_t *s, const uint8_t *msg, int len
{
/* We have fallen back as far as we can go. Give up. */
s->current_fallback = 0;
s->current_status = T30_ERR_CANNOT_TRAIN;
t30_set_status(s, T30_ERR_CANNOT_TRAIN);
send_dcn(s);
break;
}
@ -3071,7 +3074,7 @@ static void process_state_d_post_tcf(t30_state_t *s, const uint8_t *msg, int len
if (++s->retries >= MAX_COMMAND_TRIES)
{
span_log(&s->logging, SPAN_LOG_FLOW, "Too many retries. Giving up.\n");
s->current_status = T30_ERR_RETRYDCN;
t30_set_status(s, T30_ERR_RETRYDCN);
send_dcn(s);
break;
}
@ -3081,7 +3084,7 @@ static void process_state_d_post_tcf(t30_state_t *s, const uint8_t *msg, int len
send_dcs_sequence(s, TRUE);
break;
case T30_DCN:
s->current_status = T30_ERR_TX_BADDCS;
t30_set_status(s, T30_ERR_TX_BADDCS);
disconnect(s);
break;
case T30_CRP:
@ -3234,7 +3237,7 @@ static void process_state_f_doc_non_ecm(t30_state_t *s, const uint8_t *msg, int
send_simple_frame(s, T30_RTN);
break;
case T30_DCN:
s->current_status = T30_ERR_RX_DCNDATA;
t30_set_status(s, T30_ERR_RX_DCNDATA);
disconnect(s);
break;
case T30_CRP:
@ -3245,7 +3248,7 @@ static void process_state_f_doc_non_ecm(t30_state_t *s, const uint8_t *msg, int
break;
default:
/* We don't know what to do with this. */
s->current_status = T30_ERR_RX_INVALCMD;
t30_set_status(s, T30_ERR_RX_INVALCMD);
unexpected_final_frame(s, msg, len);
break;
}
@ -3369,7 +3372,7 @@ static void process_state_f_post_doc_non_ecm(t30_state_t *s, const uint8_t *msg,
}
break;
case T30_DCN:
s->current_status = T30_ERR_RX_DCNFAX;
t30_set_status(s, T30_ERR_RX_DCNFAX);
disconnect(s);
break;
case T30_CRP:
@ -3380,7 +3383,7 @@ static void process_state_f_post_doc_non_ecm(t30_state_t *s, const uint8_t *msg,
break;
default:
/* We don't know what to do with this. */
s->current_status = T30_ERR_RX_INVALCMD;
t30_set_status(s, T30_ERR_RX_INVALCMD);
unexpected_final_frame(s, msg, len);
break;
}
@ -3453,7 +3456,7 @@ static void process_state_f_doc_and_post_doc_ecm(t30_state_t *s, const uint8_t *
case T30_RR:
break;
case T30_DCN:
s->current_status = T30_ERR_RX_DCNDATA;
t30_set_status(s, T30_ERR_RX_DCNDATA);
disconnect(s);
break;
case T30_CRP:
@ -3464,7 +3467,7 @@ static void process_state_f_doc_and_post_doc_ecm(t30_state_t *s, const uint8_t *
break;
default:
/* We don't know what to do with this. */
s->current_status = T30_ERR_RX_INVALCMD;
t30_set_status(s, T30_ERR_RX_INVALCMD);
unexpected_final_frame(s, msg, len);
break;
}
@ -3566,7 +3569,7 @@ static void process_state_r(t30_state_t *s, const uint8_t *msg, int len)
break;
case T30_DCN:
/* Received a DCN while waiting for a DIS */
s->current_status = T30_ERR_TX_GOTDCN;
t30_set_status(s, T30_ERR_TX_GOTDCN);
disconnect(s);
break;
case T30_CRP:
@ -3594,7 +3597,7 @@ static void process_state_t(t30_state_t *s, const uint8_t *msg, int len)
process_rx_dis_dtc(s, msg, len);
break;
case T30_DCN:
s->current_status = T30_ERR_RX_DCNWHY;
t30_set_status(s, T30_ERR_RX_DCNWHY);
disconnect(s);
break;
case T30_CRP:
@ -3606,7 +3609,7 @@ static void process_state_t(t30_state_t *s, const uint8_t *msg, int len)
default:
/* We don't know what to do with this. */
unexpected_final_frame(s, msg, len);
s->current_status = T30_ERR_TX_NODIS;
t30_set_status(s, T30_ERR_TX_NODIS);
break;
}
}
@ -3729,7 +3732,7 @@ static void process_state_ii_q(t30_state_t *s, const uint8_t *msg, int len)
{
/* We have fallen back as far as we can go. Give up. */
s->current_fallback = 0;
s->current_status = T30_ERR_CANNOT_TRAIN;
t30_set_status(s, T30_ERR_CANNOT_TRAIN);
send_dcn(s);
break;
}
@ -3790,7 +3793,7 @@ static void process_state_ii_q(t30_state_t *s, const uint8_t *msg, int len)
{
/* We have fallen back as far as we can go. Give up. */
s->current_fallback = 0;
s->current_status = T30_ERR_CANNOT_TRAIN;
t30_set_status(s, T30_ERR_CANNOT_TRAIN);
send_dcn(s);
break;
}
@ -3824,7 +3827,7 @@ static void process_state_ii_q(t30_state_t *s, const uint8_t *msg, int len)
{
/* We have fallen back as far as we can go. Give up. */
s->current_fallback = 0;
s->current_status = T30_ERR_CANNOT_TRAIN;
t30_set_status(s, T30_ERR_CANNOT_TRAIN);
send_dcn(s);
break;
}
@ -3847,10 +3850,10 @@ static void process_state_ii_q(t30_state_t *s, const uint8_t *msg, int len)
case T30_EOM:
case T30_EOS:
/* Unexpected DCN after EOM, EOS or MPS sequence */
s->current_status = T30_ERR_RX_DCNPHD;
t30_set_status(s, T30_ERR_RX_DCNPHD);
break;
default:
s->current_status = T30_ERR_TX_BADPG;
t30_set_status(s, T30_ERR_TX_BADPG);
break;
}
disconnect(s);
@ -3863,7 +3866,7 @@ static void process_state_ii_q(t30_state_t *s, const uint8_t *msg, int len)
break;
default:
/* We don't know what to do with this. */
s->current_status = T30_ERR_TX_INVALRSP;
t30_set_status(s, T30_ERR_TX_INVALRSP);
unexpected_final_frame(s, msg, len);
break;
}
@ -3968,7 +3971,7 @@ static void process_state_iii_q_rtn(t30_state_t *s, const uint8_t *msg, int len)
process_rx_fnv(s, msg, len);
break;
case T30_DCN:
s->current_status = T30_ERR_RX_DCNNORTN;
t30_set_status(s, T30_ERR_RX_DCNNORTN);
disconnect(s);
break;
default:
@ -4075,7 +4078,7 @@ static void process_state_iv_pps_null(t30_state_t *s, const uint8_t *msg, int le
send_rr(s);
break;
case T30_DCN:
s->current_status = T30_ERR_TX_BADPG;
t30_set_status(s, T30_ERR_TX_BADPG);
disconnect(s);
break;
case T30_CRP:
@ -4087,7 +4090,7 @@ static void process_state_iv_pps_null(t30_state_t *s, const uint8_t *msg, int le
default:
/* We don't know what to do with this. */
unexpected_final_frame(s, msg, len);
s->current_status = T30_ERR_TX_ECMPHD;
t30_set_status(s, T30_ERR_TX_ECMPHD);
break;
}
}
@ -4179,7 +4182,7 @@ static void process_state_iv_pps_q(t30_state_t *s, const uint8_t *msg, int len)
process_rx_ppr(s, msg, len);
break;
case T30_DCN:
s->current_status = T30_ERR_TX_BADPG;
t30_set_status(s, T30_ERR_TX_BADPG);
disconnect(s);
break;
case T30_CRP:
@ -4202,7 +4205,7 @@ static void process_state_iv_pps_q(t30_state_t *s, const uint8_t *msg, int len)
default:
/* We don't know what to do with this. */
unexpected_final_frame(s, msg, len);
s->current_status = T30_ERR_TX_ECMPHD;
t30_set_status(s, T30_ERR_TX_ECMPHD);
break;
}
}
@ -4291,7 +4294,7 @@ static void process_state_iv_pps_rnr(t30_state_t *s, const uint8_t *msg, int len
send_rr(s);
break;
case T30_DCN:
s->current_status = T30_ERR_RX_DCNRRD;
t30_set_status(s, T30_ERR_RX_DCNRRD);
disconnect(s);
break;
case T30_CRP:
@ -4365,7 +4368,7 @@ static void process_state_iv_eor(t30_state_t *s, const uint8_t *msg, int len)
break;
case T30_ERR:
/* TODO: Continue with the next message if MPS or EOM? */
s->current_status = T30_ERR_RETRYDCN;
t30_set_status(s, T30_ERR_RETRYDCN);
s->timer_t5 = 0;
send_dcn(s);
break;
@ -4410,12 +4413,12 @@ static void process_state_iv_eor_rnr(t30_state_t *s, const uint8_t *msg, int len
break;
case T30_ERR:
/* TODO: Continue with the next message if MPS or EOM? */
s->current_status = T30_ERR_RETRYDCN;
t30_set_status(s, T30_ERR_RETRYDCN);
s->timer_t5 = 0;
send_dcn(s);
break;
case T30_DCN:
s->current_status = T30_ERR_RX_DCNRRD;
t30_set_status(s, T30_ERR_RX_DCNRRD);
disconnect(s);
break;
case T30_CRP:
@ -4877,17 +4880,17 @@ static void repeat_last_command(t30_state_t *s)
{
case T30_STATE_D_POST_TCF:
/* Received no response to DCS or TCF */
s->current_status = T30_ERR_TX_PHBDEAD;
t30_set_status(s, T30_ERR_TX_PHBDEAD);
break;
case T30_STATE_II_Q:
case T30_STATE_IV_PPS_NULL:
case T30_STATE_IV_PPS_Q:
/* No response after sending a page */
s->current_status = T30_ERR_TX_PHDDEAD;
t30_set_status(s, T30_ERR_TX_PHDDEAD);
break;
default:
/* Disconnected after permitted retries */
s->current_status = T30_ERR_RETRYDCN;
t30_set_status(s, T30_ERR_RETRYDCN);
break;
}
send_dcn(s);
@ -5068,7 +5071,7 @@ static void timer_t2_t4_stop(t30_state_t *s)
static void timer_t0_expired(t30_state_t *s)
{
span_log(&s->logging, SPAN_LOG_FLOW, "T0 expired in state %d\n", s->state);
s->current_status = T30_ERR_T0_EXPIRED;
t30_set_status(s, T30_ERR_T0_EXPIRED);
/* Just end the call */
disconnect(s);
}
@ -5080,7 +5083,7 @@ static void timer_t1_expired(t30_state_t *s)
/* The initial connection establishment has timeout out. In other words, we
have been unable to communicate successfully with a remote machine.
It is time to abandon the call. */
s->current_status = T30_ERR_T1_EXPIRED;
t30_set_status(s, T30_ERR_T1_EXPIRED);
switch (s->state)
{
case T30_STATE_T:
@ -5133,33 +5136,33 @@ static void timer_t2_expired(t30_state_t *s)
case T30_STATE_F_DOC_ECM:
case T30_STATE_F_DOC_NON_ECM:
/* While waiting for FAX page */
s->current_status = T30_ERR_RX_T2EXPFAX;
t30_set_status(s, T30_ERR_RX_T2EXPFAX);
break;
case T30_STATE_F_POST_DOC_ECM:
case T30_STATE_F_POST_DOC_NON_ECM:
/* While waiting for next FAX page */
/* Figure 5-2b/T.30 and note 7 says we should allow 1 to 3 tries at this point.
The way we work now is effectively hard coding a 1 try limit */
s->current_status = T30_ERR_RX_T2EXPMPS;
t30_set_status(s, T30_ERR_RX_T2EXPMPS);
break;
#if 0
case ??????:
/* While waiting for DCN */
s->current_status = T30_ERR_RX_T2EXPDCN;
t30_set_status(s, T30_ERR_RX_T2EXPDCN);
break;
case ??????:
/* While waiting for phase D */
s->current_status = T30_ERR_RX_T2EXPD;
t30_set_status(s, T30_ERR_RX_T2EXPD);
break;
#endif
case T30_STATE_IV_PPS_RNR:
case T30_STATE_IV_EOR_RNR:
/* While waiting for RR command */
s->current_status = T30_ERR_RX_T2EXPRR;
t30_set_status(s, T30_ERR_RX_T2EXPRR);
break;
case T30_STATE_R:
/* While waiting for NSS, DCS or MCF */
s->current_status = T30_ERR_RX_T2EXP;
t30_set_status(s, T30_ERR_RX_T2EXP);
break;
case T30_STATE_F_FTT:
break;
@ -5172,7 +5175,7 @@ static void timer_t2_expired(t30_state_t *s)
static void timer_t1a_expired(t30_state_t *s)
{
span_log(&s->logging, SPAN_LOG_FLOW, "T1A expired in phase %s, state %d. An HDLC frame lasted too long.\n", phase_names[s->phase], s->state);
s->current_status = T30_ERR_HDLC_CARRIER;
t30_set_status(s, T30_ERR_HDLC_CARRIER);
disconnect(s);
}
/*- End of function --------------------------------------------------------*/
@ -5180,7 +5183,7 @@ static void timer_t1a_expired(t30_state_t *s)
static void timer_t2a_expired(t30_state_t *s)
{
span_log(&s->logging, SPAN_LOG_FLOW, "T2A expired in phase %s, state %d. An HDLC frame lasted too long.\n", phase_names[s->phase], s->state);
s->current_status = T30_ERR_HDLC_CARRIER;
t30_set_status(s, T30_ERR_HDLC_CARRIER);
disconnect(s);
}
/*- End of function --------------------------------------------------------*/
@ -5195,7 +5198,7 @@ static void timer_t2b_expired(t30_state_t *s)
static void timer_t3_expired(t30_state_t *s)
{
span_log(&s->logging, SPAN_LOG_FLOW, "T3 expired in phase %s, state %d\n", phase_names[s->phase], s->state);
s->current_status = T30_ERR_T3_EXPIRED;
t30_set_status(s, T30_ERR_T3_EXPIRED);
disconnect(s);
}
/*- End of function --------------------------------------------------------*/
@ -5219,7 +5222,7 @@ static void timer_t4_expired(t30_state_t *s)
static void timer_t4a_expired(t30_state_t *s)
{
span_log(&s->logging, SPAN_LOG_FLOW, "T4A expired in phase %s, state %d. An HDLC frame lasted too long.\n", phase_names[s->phase], s->state);
s->current_status = T30_ERR_HDLC_CARRIER;
t30_set_status(s, T30_ERR_HDLC_CARRIER);
disconnect(s);
}
/*- End of function --------------------------------------------------------*/
@ -5235,7 +5238,7 @@ static void timer_t5_expired(t30_state_t *s)
{
/* Give up waiting for the receiver to become ready in error correction mode */
span_log(&s->logging, SPAN_LOG_FLOW, "T5 expired in phase %s, state %d\n", phase_names[s->phase], s->state);
s->current_status = T30_ERR_TX_T5EXP;
t30_set_status(s, T30_ERR_TX_T5EXP);
}
/*- End of function --------------------------------------------------------*/
@ -5382,7 +5385,7 @@ static void t30_non_ecm_rx_status(void *user_data, int status)
case T30_STATE_F_POST_DOC_NON_ECM:
/* Page ended cleanly */
if (s->current_status == T30_ERR_RX_NOCARRIER)
s->current_status = T30_ERR_OK;
t30_set_status(s, T30_ERR_OK);
break;
default:
/* We should be receiving a document right now, but it did not end cleanly. */
@ -5395,12 +5398,12 @@ static void t30_non_ecm_rx_status(void *user_data, int status)
set_phase(s, T30_PHASE_D_RX);
timer_t2_start(s);
if (s->current_status == T30_ERR_RX_NOCARRIER)
s->current_status = T30_ERR_OK;
t30_set_status(s, T30_ERR_OK);
}
else
{
span_log(&s->logging, SPAN_LOG_WARNING, "Non-ECM carrier not found\n");
s->current_status = T30_ERR_RX_NOCARRIER;
t30_set_status(s, T30_ERR_RX_NOCARRIER);
}
break;
}
@ -5697,13 +5700,13 @@ static void t30_hdlc_rx_status(void *user_data, int status)
timer_t2_start(s);
/* We at least trained, so any missing carrier status is out of date */
if (s->current_status == T30_ERR_RX_NOCARRIER)
s->current_status = T30_ERR_OK;
t30_set_status(s, T30_ERR_OK);
}
else
{
/* Either there was no image carrier, or we failed to train to it. */
span_log(&s->logging, SPAN_LOG_WARNING, "ECM carrier not found\n");
s->current_status = T30_ERR_RX_NOCARRIER;
t30_set_status(s, T30_ERR_RX_NOCARRIER);
}
}
if (s->next_phase != T30_PHASE_IDLE)
@ -6235,7 +6238,7 @@ SPAN_DECLARE(void) t30_terminate(t30_state_t *s)
break;
default:
/* The call terminated prematurely. */
s->current_status = T30_ERR_CALLDROPPED;
t30_set_status(s, T30_ERR_CALLDROPPED);
break;
}
if (s->phase_e_handler)

View File

@ -750,7 +750,11 @@ SPAN_DECLARE(int) t30_set_supported_t30_features(t30_state_t *s, int supported_t
SPAN_DECLARE(void) t30_set_status(t30_state_t *s, int status)
{
s->current_status = status;
if (s->current_status != status)
{
span_log(&s->logging, SPAN_LOG_FLOW, "Status changing to '%s'\n", t30_completion_code_to_str(status));
s->current_status = status;
}
}
/*- End of function --------------------------------------------------------*/

View File

@ -1345,7 +1345,7 @@ static void hdlc_tx_underflow(void *user_data)
{
s->hdlc_tx.final = FALSE;
/* Schedule an orderly shutdown of the modem */
hdlc_tx_frame(&(s->audio.modems.hdlc_tx), NULL, 0);
hdlc_tx_frame(&s->audio.modems.hdlc_tx, NULL, 0);
}
else
{
@ -1542,9 +1542,9 @@ static void t31_v21_rx(t31_state_t *s)
s->hdlc_tx.final = FALSE;
s->hdlc_tx.len = 0;
s->dled = FALSE;
hdlc_rx_init(&(s->audio.modems.hdlc_rx), FALSE, TRUE, HDLC_FRAMING_OK_THRESHOLD, hdlc_accept_frame, s);
fsk_rx_init(&(s->audio.modems.v21_rx), &preset_fsk_specs[FSK_V21CH2], FSK_FRAME_MODE_SYNC, (put_bit_func_t) hdlc_rx_put_bit, &(s->audio.modems.hdlc_rx));
fsk_rx_signal_cutoff(&(s->audio.modems.v21_rx), -39.09f);
hdlc_rx_init(&s->audio.modems.hdlc_rx, FALSE, TRUE, HDLC_FRAMING_OK_THRESHOLD, hdlc_accept_frame, s);
fsk_rx_init(&s->audio.modems.v21_rx, &preset_fsk_specs[FSK_V21CH2], FSK_FRAME_MODE_SYNC, (put_bit_func_t) hdlc_rx_put_bit, &s->audio.modems.hdlc_rx);
fsk_rx_signal_cutoff(&s->audio.modems.v21_rx, -39.09f);
s->at_state.transmit = TRUE;
}
/*- End of function --------------------------------------------------------*/
@ -1678,8 +1678,8 @@ static int restart_modem(t31_state_t *s, int new_modem)
}
else
{
v17_tx_restart(&t->v17_tx, s->bit_rate, FALSE, s->short_train);
set_tx_handler(s, (span_tx_handler_t *) &v17_tx, &t->v17_tx);
v17_tx_restart(&t->fast_modems.v17_tx, s->bit_rate, FALSE, s->short_train);
set_tx_handler(s, (span_tx_handler_t *) &v17_tx, &t->fast_modems.v17_tx);
set_next_tx_handler(s, (span_tx_handler_t *) NULL, NULL);
}
s->tx.out_bytes = 0;
@ -1690,7 +1690,7 @@ static int restart_modem(t31_state_t *s, int new_modem)
if (!s->t38_mode)
{
set_rx_handler(s, (span_rx_handler_t *) &v17_v21_rx, (span_rx_fillin_handler_t *) &v17_v21_rx_fillin, s);
v17_rx_restart(&t->v17_rx, s->bit_rate, s->short_train);
v17_rx_restart(&t->fast_modems.v17_rx, s->bit_rate, s->short_train);
/* Allow for +FCERROR/+FRH:3 */
t31_v21_rx(s);
}
@ -1715,8 +1715,8 @@ static int restart_modem(t31_state_t *s, int new_modem)
}
else
{
v27ter_tx_restart(&t->v27ter_tx, s->bit_rate, FALSE);
set_tx_handler(s, (span_tx_handler_t *) &v27ter_tx, &t->v27ter_tx);
v27ter_tx_restart(&t->fast_modems.v27ter_tx, s->bit_rate, FALSE);
set_tx_handler(s, (span_tx_handler_t *) &v27ter_tx, &t->fast_modems.v27ter_tx);
set_next_tx_handler(s, (span_tx_handler_t *) NULL, NULL);
}
s->tx.out_bytes = 0;
@ -1727,7 +1727,7 @@ static int restart_modem(t31_state_t *s, int new_modem)
if (!s->t38_mode)
{
set_rx_handler(s, (span_rx_handler_t *) &v27ter_v21_rx, (span_rx_fillin_handler_t *) &v27ter_v21_rx_fillin, s);
v27ter_rx_restart(&t->v27ter_rx, s->bit_rate, FALSE);
v27ter_rx_restart(&t->fast_modems.v27ter_rx, s->bit_rate, FALSE);
/* Allow for +FCERROR/+FRH:3 */
t31_v21_rx(s);
}
@ -1752,8 +1752,8 @@ static int restart_modem(t31_state_t *s, int new_modem)
}
else
{
v29_tx_restart(&t->v29_tx, s->bit_rate, FALSE);
set_tx_handler(s, (span_tx_handler_t *) &v29_tx, &t->v29_tx);
v29_tx_restart(&t->fast_modems.v29_tx, s->bit_rate, FALSE);
set_tx_handler(s, (span_tx_handler_t *) &v29_tx, &t->fast_modems.v29_tx);
set_next_tx_handler(s, (span_tx_handler_t *) NULL, NULL);
}
s->tx.out_bytes = 0;
@ -1764,7 +1764,7 @@ static int restart_modem(t31_state_t *s, int new_modem)
if (!s->t38_mode)
{
set_rx_handler(s, (span_rx_handler_t *) &v29_v21_rx, (span_rx_fillin_handler_t *) &v29_v21_rx_fillin, s);
v29_rx_restart(&t->v29_rx, s->bit_rate, FALSE);
v29_rx_restart(&t->fast_modems.v29_rx, s->bit_rate, FALSE);
/* Allow for +FCERROR/+FRH:3 */
t31_v21_rx(s);
}
@ -1838,7 +1838,7 @@ static __inline__ void dle_unstuff_hdlc(t31_state_t *s, const char *stuffed, int
}
else
{
hdlc_tx_frame(&(s->audio.modems.hdlc_tx), s->hdlc_tx.buf, s->hdlc_tx.len);
hdlc_tx_frame(&s->audio.modems.hdlc_tx, s->hdlc_tx.buf, s->hdlc_tx.len);
s->hdlc_tx.len = 0;
}
}
@ -1929,7 +1929,7 @@ static int process_class1_cmd(at_state_t *t, void *user_data, int direction, int
if (s->t38_mode)
s->t38_fe.next_tx_samples = s->t38_fe.samples + ms_to_samples(val*10);
else
silence_gen_alter(&(s->audio.modems.silence_gen), ms_to_samples(val*10));
silence_gen_alter(&s->audio.modems.silence_gen, ms_to_samples(val*10));
s->at_state.transmit = TRUE;
}
else
@ -2162,8 +2162,8 @@ SPAN_DECLARE(int) t31_at_rx(t31_state_t *s, const char *t, int len)
if (s->tx.out_bytes)
{
/* Make room for new data in existing data buffer. */
s->tx.in_bytes = &(s->tx.data[s->tx.in_bytes]) - &(s->tx.data[s->tx.out_bytes]);
memmove(&(s->tx.data[0]), &(s->tx.data[s->tx.out_bytes]), s->tx.in_bytes);
s->tx.in_bytes = &s->tx.data[s->tx.in_bytes] - &s->tx.data[s->tx.out_bytes];
memmove(&s->tx.data[0], &s->tx.data[s->tx.out_bytes], s->tx.in_bytes);
s->tx.out_bytes = 0;
}
dle_unstuff(s, t, len);
@ -2233,7 +2233,7 @@ static int cng_rx(void *user_data, const int16_t amp[], int len)
}
else
{
fsk_rx(&(s->audio.modems.v21_rx), amp, len);
fsk_rx(&s->audio.modems.v21_rx, amp, len);
}
return 0;
}
@ -2246,13 +2246,13 @@ static int v17_v21_rx(void *user_data, const int16_t amp[], int len)
t = (t31_state_t *) user_data;
s = &t->audio.modems;
v17_rx(&s->v17_rx, amp, len);
v17_rx(&s->fast_modems.v17_rx, amp, len);
if (t->at_state.rx_trained)
{
/* The fast modem has trained, so we no longer need to run the slow
one in parallel. */
span_log(&t->logging, SPAN_LOG_FLOW, "Switching from V.17 + V.21 to V.17 (%.2fdBm0)\n", v17_rx_signal_power(&s->v17_rx));
set_rx_handler(t, (span_rx_handler_t *) &v17_rx, (span_rx_fillin_handler_t *) &v17_rx_fillin, &s->v17_rx);
span_log(&t->logging, SPAN_LOG_FLOW, "Switching from V.17 + V.21 to V.17 (%.2fdBm0)\n", v17_rx_signal_power(&s->fast_modems.v17_rx));
set_rx_handler(t, (span_rx_handler_t *) &v17_rx, (span_rx_fillin_handler_t *) &v17_rx_fillin, &s->fast_modems.v17_rx);
}
else
{
@ -2276,7 +2276,7 @@ static int v17_v21_rx_fillin(void *user_data, int len)
t = (t31_state_t *) user_data;
s = &t->audio.modems;
v17_rx_fillin(&s->v17_rx, len);
v17_rx_fillin(&s->fast_modems.v17_rx, len);
fsk_rx_fillin(&s->v21_rx, len);
return 0;
}
@ -2289,13 +2289,13 @@ static int v27ter_v21_rx(void *user_data, const int16_t amp[], int len)
t = (t31_state_t *) user_data;
s = &t->audio.modems;
v27ter_rx(&s->v27ter_rx, amp, len);
v27ter_rx(&s->fast_modems.v27ter_rx, amp, len);
if (t->at_state.rx_trained)
{
/* The fast modem has trained, so we no longer need to run the slow
one in parallel. */
span_log(&t->logging, SPAN_LOG_FLOW, "Switching from V.27ter + V.21 to V.27ter (%.2fdBm0)\n", v27ter_rx_signal_power(&s->v27ter_rx));
set_rx_handler(t, (span_rx_handler_t *) &v27ter_rx, (span_rx_fillin_handler_t *) &v27ter_rx_fillin, &s->v27ter_rx);
span_log(&t->logging, SPAN_LOG_FLOW, "Switching from V.27ter + V.21 to V.27ter (%.2fdBm0)\n", v27ter_rx_signal_power(&s->fast_modems.v27ter_rx));
set_rx_handler(t, (span_rx_handler_t *) &v27ter_rx, (span_rx_fillin_handler_t *) &v27ter_rx_fillin, &s->fast_modems.v27ter_rx);
}
else
{
@ -2319,7 +2319,7 @@ static int v27ter_v21_rx_fillin(void *user_data, int len)
t = (t31_state_t *) user_data;
s = &t->audio.modems;
v27ter_rx_fillin(&s->v27ter_rx, len);
v27ter_rx_fillin(&s->fast_modems.v27ter_rx, len);
fsk_rx_fillin(&s->v21_rx, len);
return 0;
}
@ -2332,13 +2332,13 @@ static int v29_v21_rx(void *user_data, const int16_t amp[], int len)
t = (t31_state_t *) user_data;
s = &t->audio.modems;
v29_rx(&s->v29_rx, amp, len);
v29_rx(&s->fast_modems.v29_rx, amp, len);
if (t->at_state.rx_trained)
{
/* The fast modem has trained, so we no longer need to run the slow
one in parallel. */
span_log(&s->logging, SPAN_LOG_FLOW, "Switching from V.29 + V.21 to V.29 (%.2fdBm0)\n", v29_rx_signal_power(&s->v29_rx));
set_rx_handler(t, (span_rx_handler_t *) &v29_rx, (span_rx_fillin_handler_t *) &v29_rx_fillin, &s->v29_rx);
span_log(&s->logging, SPAN_LOG_FLOW, "Switching from V.29 + V.21 to V.29 (%.2fdBm0)\n", v29_rx_signal_power(&s->fast_modems.v29_rx));
set_rx_handler(t, (span_rx_handler_t *) &v29_rx, (span_rx_fillin_handler_t *) &v29_rx_fillin, &s->fast_modems.v29_rx);
}
else
{
@ -2362,7 +2362,7 @@ static int v29_v21_rx_fillin(void *user_data, int len)
t = (t31_state_t *) user_data;
s = &t->audio.modems;
v29_rx_fillin(&s->v29_rx, len);
v29_rx_fillin(&s->fast_modems.v29_rx, len);
fsk_rx_fillin(&s->v21_rx, len);
return 0;
}
@ -2382,7 +2382,7 @@ SPAN_DECLARE_NONSTD(int) t31_rx(t31_state_t *s, int16_t amp[], int len)
for (i = 0; i < len; i++)
{
/* Clean up any DC influence. */
power = power_meter_update(&(s->audio.rx_power), amp[i] - s->audio.last_sample);
power = power_meter_update(&s->audio.rx_power, amp[i] - s->audio.last_sample);
s->audio.last_sample = amp[i];
if (power > s->audio.silence_threshold_power)
{
@ -2441,15 +2441,15 @@ SPAN_DECLARE_NONSTD(int) t31_rx_fillin(t31_state_t *s, int len)
break;
case FAX_MODEM_V27TER_RX:
/* TODO: what about FSK in the early stages */
len = v27ter_rx_fillin(&s->audio.modems.v27ter_rx, len);
len = v27ter_rx_fillin(&s->audio.modems.fast_modems.v27ter_rx, len);
break;
case FAX_MODEM_V29_RX:
/* TODO: what about FSK in the early stages */
len = v29_rx_fillin(&s->audio.modems.v29_rx, len);
len = v29_rx_fillin(&s->audio.modems.fast_modems.v29_rx, len);
break;
case FAX_MODEM_V17_RX:
/* TODO: what about FSK in the early stages */
len = v17_rx_fillin(&s->audio.modems.v17_rx, len);
len = v17_rx_fillin(&s->audio.modems.fast_modems.v17_rx, len);
break;
}
return 0;
@ -2465,7 +2465,7 @@ static int set_next_tx_type(t31_state_t *s)
return 0;
}
/* There is nothing else to change to, so use zero length silence */
silence_gen_alter(&(s->audio.modems.silence_gen), 0);
silence_gen_alter(&s->audio.modems.silence_gen, 0);
set_tx_handler(s, (span_tx_handler_t *) &silence_gen, &s->audio.modems.silence_gen);
set_next_tx_handler(s, (span_tx_handler_t *) NULL, NULL);
return -1;
@ -2582,18 +2582,8 @@ static int t31_t38_fe_init(t31_state_t *t,
t->hdlc_tx.ptr = 0;
hdlc_tx_init(&s->hdlc_tx_term,
FALSE,
1,
FALSE,
NULL,
NULL);
hdlc_rx_init(&s->hdlc_rx_term,
FALSE,
TRUE,
2,
NULL,
NULL);
hdlc_tx_init(&s->hdlc_tx_term, FALSE, 1, FALSE, NULL, NULL);
hdlc_rx_init(&s->hdlc_rx_term, FALSE, TRUE, 2, NULL, NULL);
return 0;
}
/*- End of function --------------------------------------------------------*/
@ -2650,14 +2640,10 @@ SPAN_DECLARE(t31_state_t *) t31_init(t31_state_t *s,
v8_parms.pstn_access = 0;
v8_parms.nsf = -1;
v8_parms.t66 = -1;
v8_init(&s->audio.v8,
FALSE,
&v8_parms,
v8_handler,
s);
v8_init(&s->audio.v8, FALSE, &v8_parms, v8_handler, s);
#endif
power_meter_init(&(s->audio.rx_power), 4);
power_meter_init(&s->audio.rx_power, 4);
s->audio.last_sample = 0;
s->audio.silence_threshold_power = power_meter_level_dbm0(-36);
s->at_state.rx_signal_present = FALSE;
@ -2682,9 +2668,7 @@ SPAN_DECLARE(t31_state_t *) t31_init(t31_state_t *s,
s->at_state.dte_inactivity_timeout = DEFAULT_DTE_TIMEOUT;
if (tx_t38_packet_handler)
{
t31_t38_fe_init(s,
tx_t38_packet_handler,
tx_t38_packet_user_data);
t31_t38_fe_init(s, tx_t38_packet_handler, tx_t38_packet_user_data);
t31_set_t38_config(s, FALSE);
}
s->t38_mode = FALSE;

File diff suppressed because it is too large Load Diff

View File

@ -81,13 +81,13 @@ static const struct
{ 215000, 1393000, 200000}, /* T38_IND_V17_12000_LONG_TRAINING */
{ 215000, 142000, 200000}, /* T38_IND_V17_14400_SHORT_TRAINING */
{ 215000, 1393000, 200000}, /* T38_IND_V17_14400_LONG_TRAINING */
{ 215000, 0, 0}, /* T38_IND_V8_ANSAM */
{ 215000, 0, 0}, /* T38_IND_V8_SIGNAL */
{ 215000, 0, 0}, /* T38_IND_V34_CNTL_CHANNEL_1200 */
{ 215000, 0, 0}, /* T38_IND_V34_PRI_CHANNEL */
{ 215000, 0, 0}, /* T38_IND_V34_CC_RETRAIN */
{ 215000, 0, 0}, /* T38_IND_V33_12000_TRAINING */
{ 215000, 0, 0} /* T38_IND_V33_14400_TRAINING */
{ 0, 0, 0}, /* T38_IND_V8_ANSAM */
{ 0, 0, 0}, /* T38_IND_V8_SIGNAL */
{ 0, 0, 200000}, /* T38_IND_V34_CNTL_CHANNEL_1200 */
{ 0, 0, 200000}, /* T38_IND_V34_PRI_CHANNEL */
{ 0, 0, 0}, /* T38_IND_V34_CC_RETRAIN */
{ 215000, 0, 200000}, /* T38_IND_V33_12000_TRAINING */
{ 215000, 0, 200000} /* T38_IND_V33_14400_TRAINING */
};
SPAN_DECLARE(const char *) t38_indicator_to_str(int indicator)
@ -325,15 +325,17 @@ static __inline__ int classify_seq_no_offset(int expected, int actual)
}
/*- End of function --------------------------------------------------------*/
SPAN_DECLARE_NONSTD(int) t38_core_rx_ifp_packet(t38_core_state_t *s, const uint8_t *buf, int len, uint16_t seq_no)
SPAN_DECLARE_NONSTD(int) t38_core_rx_ifp_stream(t38_core_state_t *s, const uint8_t *buf, int len, uint16_t log_seq_no)
{
int i;
int t30_indicator;
int t30_data;
int prev_ptr;
int ptr;
int other_half;
int numocts;
int log_seq_no;
int pkt_len;
int ret;
const uint8_t *msg;
unsigned int count;
unsigned int t30_field_type;
@ -342,18 +344,282 @@ SPAN_DECLARE_NONSTD(int) t38_core_rx_ifp_packet(t38_core_state_t *s, const uint8
uint8_t field_data_present;
char tag[20];
log_seq_no = (s->check_sequence_numbers) ? seq_no : s->rx_expected_seq_no;
if (span_log_test(&s->logging, SPAN_LOG_FLOW))
{
sprintf(tag, "Rx %5d: IFP", log_seq_no);
span_log_buf(&s->logging, SPAN_LOG_FLOW, tag, buf, len);
}
if (len < 1)
ptr = 0;
pkt_len = len;
switch (s->data_transport_protocol)
{
span_log(&s->logging, SPAN_LOG_PROTOCOL_WARNING, "Rx %5d: Bad packet length - %d\n", log_seq_no, len);
return -1;
case T38_TRANSPORT_TCP:
/* We don't know the actual packet length, so treat everythign we have as the packet */
ret = 0;
break;
case T38_TRANSPORT_TCP_TPKT:
if (len >= 4)
{
/* Version */
if (buf[0] != 3)
return -1;
/* Reserved */
if (buf[1] != 0)
return -1;
/* Packet length - this includes the length of the header itself */
pkt_len = (buf[2] << 8) | buf[3];
if (len < pkt_len)
return 0;
ptr = 4;
}
ret = -1;
break;
default:
/* We know the actual packet length, and its the exact length of what we were passed. */
ret = -1;
break;
}
if ((ptr + 1) > pkt_len)
return ret;
data_field_present = buf[ptr] & 0x80;
type = (buf[ptr] >> 6) & 1;
switch (type)
{
case T38_TYPE_OF_MSG_T30_INDICATOR:
/* Indicators should never have a data field */
if (data_field_present)
{
span_log(&s->logging, SPAN_LOG_PROTOCOL_WARNING, "Rx %5d: Data field with indicator\n", log_seq_no);
return -1;
}
/* Any received indicator should mean we no longer have a valid concept of "last received data/field type". */
s->current_rx_data_type = -1;
s->current_rx_field_type = -1;
if ((buf[ptr] & 0x20))
{
/* Extension */
if ((ptr + 2) > pkt_len)
return ret;
t30_indicator = T38_IND_V8_ANSAM + (((buf[ptr] << 2) & 0x3C) | ((buf[ptr + 1] >> 6) & 0x3));
if (t30_indicator > T38_IND_V33_14400_TRAINING)
{
span_log(&s->logging, SPAN_LOG_PROTOCOL_WARNING, "Rx %5d: Unknown indicator - %d\n", log_seq_no, t30_indicator);
return -1;
}
ptr += 2;
}
else
{
t30_indicator = (buf[ptr] >> 1) & 0xF;
ptr += 1;
}
span_log(&s->logging, SPAN_LOG_FLOW, "Rx %5d: indicator %s\n", log_seq_no, t38_indicator_to_str(t30_indicator));
s->rx_indicator_handler(s, s->rx_user_data, t30_indicator);
/* This must come after the indicator handler, so the handler routine sees the existing state of the
indicator. */
s->current_rx_indicator = t30_indicator;
break;
case T38_TYPE_OF_MSG_T30_DATA:
if ((buf[ptr] & 0x20))
{
/* Extension */
if ((ptr + 2) > pkt_len)
return ret;
t30_data = T38_DATA_V8 + (((buf[ptr] << 2) & 0x3C) | ((buf[ptr + 1] >> 6) & 0x3));
if (t30_data > T38_DATA_V33_14400)
{
span_log(&s->logging, SPAN_LOG_PROTOCOL_WARNING, "Rx %5d: Unknown data type - %d\n", log_seq_no, t30_data);
return -1;
}
ptr += 2;
}
else
{
t30_data = (buf[ptr] >> 1) & 0xF;
if (t30_data > T38_DATA_V17_14400)
{
span_log(&s->logging, SPAN_LOG_PROTOCOL_WARNING, "Rx %5d: Unknown data type - %d\n", log_seq_no, t30_data);
return -1;
}
ptr += 1;
}
if (!data_field_present)
{
/* This is kinda weird, but I guess if the length checks out we accept it. */
span_log(&s->logging, SPAN_LOG_PROTOCOL_WARNING, "Rx %5d: Data type with no data field\n", log_seq_no);
break;
}
if (ptr >= pkt_len)
return ret;
count = buf[ptr++];
//printf("Count is %d\n", count);
/* Do a dummy run through the fields to check we have a complete and uncorrupted packet. */
prev_ptr = ptr;
other_half = FALSE;
t30_field_type = 0;
for (i = 0; i < (int) count; i++)
{
if (ptr >= pkt_len)
return ret;
if (s->t38_version == 0)
{
/* The original version of T.38 with a typo in the ASN.1 spec. */
if (other_half)
{
/* The lack of a data field in the previous message means
we are currently in the middle of an octet. */
field_data_present = (buf[ptr] >> 3) & 1;
/* Decode field_type */
t30_field_type = buf[ptr] & 0x7;
ptr++;
other_half = FALSE;
}
else
{
field_data_present = (buf[ptr] >> 7) & 1;
/* Decode field_type */
t30_field_type = (buf[ptr] >> 4) & 0x7;
if (field_data_present)
ptr++;
else
other_half = TRUE;
}
if (t30_field_type > T38_FIELD_T4_NON_ECM_SIG_END)
{
span_log(&s->logging, SPAN_LOG_PROTOCOL_WARNING, "Rx %5d: Unknown field type - %d\n", log_seq_no, t30_field_type);
return -1;
}
}
else
{
field_data_present = (buf[ptr] >> 7) & 1;
/* Decode field_type */
if ((buf[ptr] & 0x40))
{
if ((ptr + 2) > pkt_len)
return ret;
t30_field_type = T38_FIELD_CM_MESSAGE + (((buf[ptr] << 2) & 0x3C) | ((buf[ptr + 1] >> 6) & 0x3));
if (t30_field_type > T38_FIELD_V34RATE)
{
span_log(&s->logging, SPAN_LOG_PROTOCOL_WARNING, "Rx %5d: Unknown field type - %d\n", log_seq_no, t30_field_type);
return -1;
}
ptr += 2;
}
else
{
t30_field_type = (buf[ptr++] >> 3) & 0x7;
}
}
/* Decode field_data */
if (field_data_present)
{
if ((ptr + 2) > pkt_len)
return ret;
numocts = ((buf[ptr] << 8) | buf[ptr + 1]) + 1;
msg = buf + ptr + 2;
ptr += numocts + 2;
}
else
{
numocts = 0;
msg = NULL;
}
if (ptr > pkt_len)
return ret;
}
/* Check if we finished mid byte in a version 0 packet. */
if (other_half)
ptr++;
if (ptr > pkt_len)
return ret;
/* Things look alright in the data, so lets run through the fields again, actually processing them.
There is no need to do all the error checking along the way on this pass. */
ptr = prev_ptr;
other_half = FALSE;
for (i = 0; i < (int) count; i++)
{
if (s->t38_version == 0)
{
/* The original version of T.38 with a typo in the ASN.1 spec. */
if (other_half)
{
/* The lack of a data field in the previous message means
we are currently in the middle of an octet. */
field_data_present = (buf[ptr] >> 3) & 1;
/* Decode field_type */
t30_field_type = buf[ptr] & 0x7;
ptr++;
other_half = FALSE;
}
else
{
field_data_present = (buf[ptr] >> 7) & 1;
/* Decode field_type */
t30_field_type = (buf[ptr] >> 4) & 0x7;
if (field_data_present)
ptr++;
else
other_half = TRUE;
}
}
else
{
field_data_present = (buf[ptr] >> 7) & 1;
/* Decode field_type */
if ((buf[ptr] & 0x40))
{
t30_field_type = T38_FIELD_CM_MESSAGE + (((buf[ptr] << 2) & 0x3C) | ((buf[ptr + 1] >> 6) & 0x3));
ptr += 2;
}
else
{
t30_field_type = (buf[ptr++] >> 3) & 0x7;
}
}
/* Decode field_data */
if (field_data_present)
{
numocts = ((buf[ptr] << 8) | buf[ptr + 1]) + 1;
msg = buf + ptr + 2;
ptr += numocts + 2;
}
else
{
numocts = 0;
msg = NULL;
}
span_log(&s->logging,
SPAN_LOG_FLOW,
"Rx %5d: (%d) data %s/%s + %d byte(s)\n",
log_seq_no,
i,
t38_data_type_to_str(t30_data),
t38_field_type_to_str(t30_field_type),
numocts);
s->rx_data_handler(s, s->rx_user_data, t30_data, t30_field_type, msg, numocts);
s->current_rx_data_type = t30_data;
s->current_rx_field_type = t30_field_type;
}
/* Check if we finished mid byte in a version 0 packet. */
if (other_half)
ptr++;
break;
}
if (ptr > pkt_len)
return ret;
return ptr;
}
/*- End of function --------------------------------------------------------*/
SPAN_DECLARE_NONSTD(int) t38_core_rx_ifp_packet(t38_core_state_t *s, const uint8_t *buf, int len, uint16_t seq_no)
{
int log_seq_no;
int ptr;
log_seq_no = (s->check_sequence_numbers) ? seq_no : s->rx_expected_seq_no;
if (s->check_sequence_numbers)
{
seq_no &= 0xFFFF;
@ -404,6 +670,11 @@ SPAN_DECLARE_NONSTD(int) t38_core_rx_ifp_packet(t38_core_state_t *s, const uint8
s->rx_expected_seq_no = seq_no;
}
}
if (len < 1)
{
span_log(&s->logging, SPAN_LOG_PROTOCOL_WARNING, "Rx %5d: Bad packet length - %d\n", log_seq_no, len);
return -1;
}
/* The sequence numbering is defined as rolling from 0xFFFF to 0x0000. Some implementations
of T.38 roll from 0xFFFF to 0x0001. Isn't standardisation a wonderful thing? The T.38
document specifies only a small fraction of what it should, yet then they actually nail
@ -414,201 +685,13 @@ SPAN_DECLARE_NONSTD(int) t38_core_rx_ifp_packet(t38_core_state_t *s, const uint8
luck a retry will ride over the problem. Rollovers don't occur that often. It takes quite
a few FAX pages to reach rollover. */
s->rx_expected_seq_no = (s->rx_expected_seq_no + 1) & 0xFFFF;
data_field_present = (buf[0] >> 7) & 1;
type = (buf[0] >> 6) & 1;
ptr = 0;
switch (type)
ptr = t38_core_rx_ifp_stream(s, buf, len, seq_no);
if (ptr != len)
{
case T38_TYPE_OF_MSG_T30_INDICATOR:
/* Indicators should never have a data field */
if (data_field_present)
{
span_log(&s->logging, SPAN_LOG_PROTOCOL_WARNING, "Rx %5d: Data field with indicator\n", log_seq_no);
return -1;
}
/* Any received indicator should mean we no longer have a valid concept of "last received data/field type". */
s->current_rx_data_type = -1;
s->current_rx_field_type = -1;
if ((buf[0] & 0x20))
{
/* Extension */
if (len != 2)
{
span_log(&s->logging, SPAN_LOG_PROTOCOL_WARNING, "Rx %5d: Invalid length for indicator (A)\n", log_seq_no);
return -1;
}
t30_indicator = T38_IND_V8_ANSAM + (((buf[0] << 2) & 0x3C) | ((buf[1] >> 6) & 0x3));
if (t30_indicator > T38_IND_V33_14400_TRAINING)
{
span_log(&s->logging, SPAN_LOG_PROTOCOL_WARNING, "Rx %5d: Unknown indicator - %d\n", log_seq_no, t30_indicator);
return -1;
}
}
else
{
if (len != 1)
{
span_log(&s->logging, SPAN_LOG_PROTOCOL_WARNING, "Rx %5d: Invalid length for indicator (B)\n", log_seq_no);
return -1;
}
t30_indicator = (buf[0] >> 1) & 0xF;
}
span_log(&s->logging, SPAN_LOG_FLOW, "Rx %5d: indicator %s\n", log_seq_no, t38_indicator_to_str(t30_indicator));
s->rx_indicator_handler(s, s->rx_user_data, t30_indicator);
/* This must come after the indicator handler, so the handler routine sees the existing state of the
indicator. */
s->current_rx_indicator = t30_indicator;
break;
case T38_TYPE_OF_MSG_T30_DATA:
if ((buf[0] & 0x20))
{
/* Extension */
if (len < 2)
{
span_log(&s->logging, SPAN_LOG_PROTOCOL_WARNING, "Rx %5d: Invalid length for data (A)\n", log_seq_no);
return -1;
}
t30_data = T38_DATA_V8 + (((buf[0] << 2) & 0x3C) | ((buf[1] >> 6) & 0x3));
if (t30_data > T38_DATA_V33_14400)
{
span_log(&s->logging, SPAN_LOG_PROTOCOL_WARNING, "Rx %5d: Unknown data type - %d\n", log_seq_no, t30_data);
return -1;
}
ptr = 2;
}
else
{
t30_data = (buf[0] >> 1) & 0xF;
if (t30_data > T38_DATA_V17_14400)
{
span_log(&s->logging, SPAN_LOG_PROTOCOL_WARNING, "Rx %5d: Unknown data type - %d\n", log_seq_no, t30_data);
return -1;
}
ptr = 1;
}
if (!data_field_present)
{
/* This is kinda weird, but I guess if the length checks out we accept it. */
span_log(&s->logging, SPAN_LOG_PROTOCOL_WARNING, "Rx %5d: Data type with no data field\n", log_seq_no);
if (ptr != len)
{
span_log(&s->logging, SPAN_LOG_PROTOCOL_WARNING, "Rx %5d: Invalid length for data (B)\n", log_seq_no);
return -1;
}
break;
}
if (ptr >= len)
{
span_log(&s->logging, SPAN_LOG_PROTOCOL_WARNING, "Rx %5d: Invalid length for data (C)\n", log_seq_no);
return -1;
}
count = buf[ptr++];
//printf("Count is %d\n", count);
other_half = FALSE;
t30_field_type = 0;
for (i = 0; i < (int) count; i++)
{
if (ptr >= len)
{
span_log(&s->logging, SPAN_LOG_PROTOCOL_WARNING, "Rx %5d: Invalid length for data (D)\n", log_seq_no);
return -1;
}
if (s->t38_version == 0)
{
/* The original version of T.38 with a typo in the ASN.1 spec. */
if (other_half)
{
/* The lack of a data field in the previous message means
we are currently in the middle of an octet. */
field_data_present = (buf[ptr] >> 3) & 1;
/* Decode field_type */
t30_field_type = buf[ptr] & 0x7;
ptr++;
other_half = FALSE;
}
else
{
field_data_present = (buf[ptr] >> 7) & 1;
/* Decode field_type */
t30_field_type = (buf[ptr] >> 4) & 0x7;
if (field_data_present)
ptr++;
else
other_half = TRUE;
}
if (t30_field_type > T38_FIELD_T4_NON_ECM_SIG_END)
{
span_log(&s->logging, SPAN_LOG_PROTOCOL_WARNING, "Rx %5d: Unknown field type - %d\n", log_seq_no, t30_field_type);
return -1;
}
}
else
{
field_data_present = (buf[ptr] >> 7) & 1;
/* Decode field_type */
if ((buf[ptr] & 0x40))
{
if (ptr > len - 2)
{
span_log(&s->logging, SPAN_LOG_PROTOCOL_WARNING, "Rx %5d: Invalid length for data (E)\n", log_seq_no);
return -1;
}
t30_field_type = T38_FIELD_CM_MESSAGE + (((buf[ptr] << 2) & 0x3C) | ((buf[ptr + 1] >> 6) & 0x3));
if (t30_field_type > T38_FIELD_V34RATE)
{
span_log(&s->logging, SPAN_LOG_PROTOCOL_WARNING, "Rx %5d: Unknown field type - %d\n", log_seq_no, t30_field_type);
return -1;
}
ptr += 2;
}
else
{
t30_field_type = (buf[ptr++] >> 3) & 0x7;
}
}
/* Decode field_data */
if (field_data_present)
{
if (ptr > len - 2)
{
span_log(&s->logging, SPAN_LOG_PROTOCOL_WARNING, "Rx %5d: Invalid length for data (F)\n", log_seq_no);
return -1;
}
numocts = ((buf[ptr] << 8) | buf[ptr + 1]) + 1;
msg = buf + ptr + 2;
ptr += numocts + 2;
}
else
{
numocts = 0;
msg = NULL;
}
if (ptr > len)
{
span_log(&s->logging, SPAN_LOG_PROTOCOL_WARNING, "Rx %5d: Invalid length for data (G)\n", log_seq_no);
return -1;
}
span_log(&s->logging,
SPAN_LOG_FLOW,
"Rx %5d: (%d) data %s/%s + %d byte(s)\n",
log_seq_no,
i,
t38_data_type_to_str(t30_data),
t38_field_type_to_str(t30_field_type),
numocts);
s->rx_data_handler(s, s->rx_user_data, t30_data, t30_field_type, msg, numocts);
s->current_rx_data_type = t30_data;
s->current_rx_field_type = t30_field_type;
}
if (ptr != len)
{
if (s->t38_version != 0 || ptr != (len - 1) || !other_half)
{
span_log(&s->logging, SPAN_LOG_PROTOCOL_WARNING, "Rx %5d: Invalid length for data (H) - %d %d\n", log_seq_no, ptr, len);
return -1;
}
}
break;
if (ptr >= 0)
span_log(&s->logging, SPAN_LOG_PROTOCOL_WARNING, "Rx %5d: Invalid length for packet - %d %d\n", log_seq_no, ptr, len);
return -1;
}
return 0;
}
@ -619,24 +702,37 @@ static int t38_encode_indicator(t38_core_state_t *s, uint8_t buf[], int indicato
int len;
/* Build the IFP packet */
len = 0;
if (s->data_transport_protocol == T38_TRANSPORT_TCP_TPKT)
len = 4;
/* Data field not present */
/* Indicator packet */
/* Type of indicator */
if (indicator <= T38_IND_V17_14400_LONG_TRAINING)
{
buf[0] = (uint8_t) (indicator << 1);
len = 1;
buf[len++] = (uint8_t) (indicator << 1);
}
else if (s->t38_version != 0 && indicator <= T38_IND_V33_14400_TRAINING)
{
buf[0] = (uint8_t) (0x20 | (((indicator - T38_IND_V8_ANSAM) & 0xF) >> 2));
buf[1] = (uint8_t) (((indicator - T38_IND_V8_ANSAM) << 6) & 0xFF);
len = 2;
buf[len++] = (uint8_t) (0x20 | (((indicator - T38_IND_V8_ANSAM) & 0xF) >> 2));
buf[len++] = (uint8_t) (((indicator - T38_IND_V8_ANSAM) << 6) & 0xFF);
}
else
{
len = -1;
}
if (s->data_transport_protocol == T38_TRANSPORT_TCP_TPKT)
{
/* Fill in the TPKT header (se RFC1006) */
/* Version */
buf[0] = 3;
/* Reserved */
buf[1] = 0;
/* Packet length - this includes the length of the header itself */
buf[2] = (len >> 8) & 0xFF;
buf[3] = len & 0xFF;
}
return len;
}
/*- End of function --------------------------------------------------------*/
@ -657,40 +753,31 @@ static int t38_encode_data(t38_core_state_t *s, uint8_t buf[], int data_type, co
char tag[20];
/* Build the IFP packet */
len = 0;
if (s->data_transport_protocol == T38_TRANSPORT_TCP_TPKT)
len = 4;
/* There seems no valid reason why a packet would ever be generated without a data field present */
data_field_present = TRUE;
data_field_present = (fields > 0) ? 0x80 : 0x00;
for (data_field_no = 0; data_field_no < fields; data_field_no++)
{
span_log(&s->logging,
SPAN_LOG_FLOW,
"Tx %5d: (%d) data %s/%s + %d byte(s)\n",
s->tx_seq_no,
data_field_no,
t38_data_type_to_str(data_type),
t38_field_type_to_str(field[data_field_no].field_type),
field[data_field_no].field_len);
}
data_field_no = 0;
len = 0;
/* Data field present */
/* Data packet */
/* Type of data */
if (data_type <= T38_DATA_V17_14400)
{
buf[len++] = (uint8_t) ((data_field_present << 7) | 0x40 | (data_type << 1));
buf[len++] = (uint8_t) (data_field_present | 0x40 | (data_type << 1));
}
else if (s->t38_version != 0 && data_type <= T38_DATA_V33_14400)
{
buf[len++] = (uint8_t) ((data_field_present << 7) | 0x60 | (((data_type - T38_DATA_V8) & 0xF) >> 2));
buf[len++] = (uint8_t) (data_field_present | 0x60 | (((data_type - T38_DATA_V8) & 0xF) >> 2));
buf[len++] = (uint8_t) (((data_type - T38_DATA_V8) << 6) & 0xFF);
}
else
{
return -1;
}
if (data_field_present)
{
encoded_len = 0;
@ -763,7 +850,31 @@ static int t38_encode_data(t38_core_state_t *s, uint8_t buf[], int data_type, co
data_field_no++;
}
}
while (fields != (int) encoded_len || fragment_len >= 16384);
while ((int) encoded_len != fields || fragment_len >= 16384);
}
for (data_field_no = 0; data_field_no < fields; data_field_no++)
{
span_log(&s->logging,
SPAN_LOG_FLOW,
"Tx %5d: (%d) data %s/%s + %d byte(s)\n",
s->tx_seq_no,
data_field_no,
t38_data_type_to_str(data_type),
t38_field_type_to_str(field[data_field_no].field_type),
field[data_field_no].field_len);
}
if (s->data_transport_protocol == T38_TRANSPORT_TCP_TPKT)
{
/* Fill in the TPKT header (se RFC1006) */
/* Version */
buf[0] = 3;
/* Reserved */
buf[1] = 0;
/* Packet length - this includes the length of the header itself */
buf[2] = (len >> 8) & 0xFF;
buf[3] = len & 0xFF;
}
if (span_log_test(&s->logging, SPAN_LOG_FLOW))
@ -801,13 +912,16 @@ SPAN_DECLARE(int) t38_core_send_indicator(t38_core_state_t *s, int indicator)
span_log(&s->logging, SPAN_LOG_FLOW, "Tx %5d: indicator %s\n", s->tx_seq_no, t38_indicator_to_str(indicator));
if (s->tx_packet_handler(s, s->tx_packet_user_data, buf, len, transmissions) < 0)
{
span_log(&s->logging, SPAN_LOG_PROTOCOL_WARNING, "Tx Packet Handler Failure\n");
span_log(&s->logging, SPAN_LOG_PROTOCOL_WARNING, "Tx packet handler failure\n");
return -1;
}
s->tx_seq_no = (s->tx_seq_no + 1) & 0xFFFF;
delay = modem_startup_time[indicator].training;
if (s->allow_for_tep)
delay += modem_startup_time[indicator].tep;
if (s->pace_transmission)
{
delay = modem_startup_time[indicator].training;
if (s->allow_for_tep)
delay += modem_startup_time[indicator].tep;
}
}
s->current_tx_indicator = indicator;
}
@ -817,13 +931,17 @@ SPAN_DECLARE(int) t38_core_send_indicator(t38_core_state_t *s, int indicator)
SPAN_DECLARE(int) t38_core_send_flags_delay(t38_core_state_t *s, int indicator)
{
return modem_startup_time[indicator].flags;
if (s->pace_transmission)
return modem_startup_time[indicator].flags;
return 0;
}
/*- End of function --------------------------------------------------------*/
SPAN_DECLARE(int) t38_core_send_training_delay(t38_core_state_t *s, int indicator)
{
return modem_startup_time[indicator].training;
if (s->pace_transmission)
return modem_startup_time[indicator].training;
return 0;
}
/*- End of function --------------------------------------------------------*/
@ -843,7 +961,7 @@ SPAN_DECLARE(int) t38_core_send_data(t38_core_state_t *s, int data_type, int fie
}
if (s->tx_packet_handler(s, s->tx_packet_user_data, buf, len, s->category_control[category]) < 0)
{
span_log(&s->logging, SPAN_LOG_PROTOCOL_WARNING, "Tx Packet Handler Failure\n");
span_log(&s->logging, SPAN_LOG_PROTOCOL_WARNING, "Tx packet handler failure\n");
return -1;
}
s->tx_seq_no = (s->tx_seq_no + 1) & 0xFFFF;
@ -863,7 +981,7 @@ SPAN_DECLARE(int) t38_core_send_data_multi_field(t38_core_state_t *s, int data_t
}
if (s->tx_packet_handler(s, s->tx_packet_user_data, buf, len, s->category_control[category]) < 0)
{
span_log(&s->logging, SPAN_LOG_PROTOCOL_WARNING, "Tx Packet Handler Failure\n");
span_log(&s->logging, SPAN_LOG_PROTOCOL_WARNING, "Tx packet handler failure\n");
return -1;
}
s->tx_seq_no = (s->tx_seq_no + 1) & 0xFFFF;
@ -925,6 +1043,12 @@ SPAN_DECLARE(void) t38_set_sequence_number_handling(t38_core_state_t *s, int che
}
/*- End of function --------------------------------------------------------*/
SPAN_DECLARE(void) t38_set_pace_transmission(t38_core_state_t *s, int pace_transmission)
{
s->pace_transmission = pace_transmission;
}
/*- End of function --------------------------------------------------------*/
SPAN_DECLARE(void) t38_set_tep_handling(t38_core_state_t *s, int allow_for_tep)
{
s->allow_for_tep = allow_for_tep;
@ -1003,6 +1127,7 @@ SPAN_DECLARE(t38_core_state_t *) t38_core_init(t38_core_state_t *s,
s->max_datagram_size = 100;
s->t38_version = 0;
s->check_sequence_numbers = TRUE;
s->pace_transmission = TRUE;
/* Set some defaults */
s->category_control[T38_PACKET_CATEGORY_INDICATOR] = 1;

View File

@ -159,14 +159,6 @@ enum
DISBIT8 = 0x80
};
enum
{
T38_NONE,
T38_V27TER_RX,
T38_V29_RX,
T38_V17_RX
};
enum
{
HDLC_FLAG_FINISHED = 0x01,
@ -256,7 +248,7 @@ static int v17_v21_rx_fillin(void *user_data, int len)
t = (t38_gateway_state_t *) user_data;
s = &t->audio.modems;
v17_rx_fillin(&s->v17_rx, len);
v17_rx_fillin(&s->fast_modems.v17_rx, len);
fsk_rx_fillin(&s->v21_rx, len);
return 0;
}
@ -269,13 +261,13 @@ static int v17_v21_rx(void *user_data, const int16_t amp[], int len)
t = (t38_gateway_state_t *) user_data;
s = &t->audio.modems;
v17_rx(&s->v17_rx, amp, len);
v17_rx(&s->fast_modems.v17_rx, amp, len);
if (s->rx_trained)
{
/* The fast modem has trained, so we no longer need to run the slow
one in parallel. */
span_log(&t->logging, SPAN_LOG_FLOW, "Switching from V.17 + V.21 to V.17 (%.2fdBm0)\n", v17_rx_signal_power(&s->v17_rx));
set_rx_handler(t, (span_rx_handler_t *) &v17_rx, (span_rx_fillin_handler_t *) &v17_rx_fillin, &s->v17_rx);
span_log(&t->logging, SPAN_LOG_FLOW, "Switching from V.17 + V.21 to V.17 (%.2fdBm0)\n", v17_rx_signal_power(&s->fast_modems.v17_rx));
set_rx_handler(t, (span_rx_handler_t *) &v17_rx, (span_rx_fillin_handler_t *) &v17_rx_fillin, &s->fast_modems.v17_rx);
}
else
{
@ -299,7 +291,7 @@ static int v27ter_v21_rx_fillin(void *user_data, int len)
t = (t38_gateway_state_t *) user_data;
s = &t->audio.modems;
v27ter_rx_fillin(&s->v27ter_rx, len);
v27ter_rx_fillin(&s->fast_modems.v27ter_rx, len);
fsk_rx_fillin(&s->v21_rx, len);
return 0;
}
@ -312,13 +304,13 @@ static int v27ter_v21_rx(void *user_data, const int16_t amp[], int len)
t = (t38_gateway_state_t *) user_data;
s = &t->audio.modems;
v27ter_rx(&s->v27ter_rx, amp, len);
v27ter_rx(&s->fast_modems.v27ter_rx, amp, len);
if (s->rx_trained)
{
/* The fast modem has trained, so we no longer need to run the slow
one in parallel. */
span_log(&t->logging, SPAN_LOG_FLOW, "Switching from V.27ter + V.21 to V.27ter (%.2fdBm0)\n", v27ter_rx_signal_power(&s->v27ter_rx));
set_rx_handler(t, (span_rx_handler_t *) &v27ter_rx, (span_rx_fillin_handler_t *) &v27ter_v21_rx_fillin, &s->v27ter_rx);
span_log(&t->logging, SPAN_LOG_FLOW, "Switching from V.27ter + V.21 to V.27ter (%.2fdBm0)\n", v27ter_rx_signal_power(&s->fast_modems.v27ter_rx));
set_rx_handler(t, (span_rx_handler_t *) &v27ter_rx, (span_rx_fillin_handler_t *) &v27ter_v21_rx_fillin, &s->fast_modems.v27ter_rx);
}
else
{
@ -342,7 +334,7 @@ static int v29_v21_rx_fillin(void *user_data, int len)
t = (t38_gateway_state_t *) user_data;
s = &t->audio.modems;
v29_rx_fillin(&s->v29_rx, len);
v29_rx_fillin(&s->fast_modems.v29_rx, len);
fsk_rx_fillin(&s->v21_rx, len);
return 0;
}
@ -355,13 +347,13 @@ static int v29_v21_rx(void *user_data, const int16_t amp[], int len)
t = (t38_gateway_state_t *) user_data;
s = &t->audio.modems;
v29_rx(&s->v29_rx, amp, len);
v29_rx(&s->fast_modems.v29_rx, amp, len);
if (s->rx_trained)
{
/* The fast modem has trained, so we no longer need to run the slow
one in parallel. */
span_log(&t->logging, SPAN_LOG_FLOW, "Switching from V.29 + V.21 to V.29 (%.2fdBm0)\n", v29_rx_signal_power(&s->v29_rx));
set_rx_handler(t, (span_rx_handler_t *) &v29_rx, (span_rx_fillin_handler_t *) &v29_rx_fillin, &s->v29_rx);
span_log(&t->logging, SPAN_LOG_FLOW, "Switching from V.29 + V.21 to V.29 (%.2fdBm0)\n", v29_rx_signal_power(&s->fast_modems.v29_rx));
set_rx_handler(t, (span_rx_handler_t *) &v29_rx, (span_rx_fillin_handler_t *) &v29_rx_fillin, &s->fast_modems.v29_rx);
}
else
{
@ -542,10 +534,10 @@ static int set_next_tx_type(t38_gateway_state_t *s)
}
/*endswitch*/
silence_gen_alter(&t->silence_gen, ms_to_samples(75));
v27ter_tx_restart(&t->v27ter_tx, t->tx_bit_rate, t->use_tep);
v27ter_tx_set_get_bit(&t->v27ter_tx, get_bit_func, get_bit_user_data);
v27ter_tx_restart(&t->fast_modems.v27ter_tx, t->tx_bit_rate, t->use_tep);
v27ter_tx_set_get_bit(&t->fast_modems.v27ter_tx, get_bit_func, get_bit_user_data);
set_tx_handler(s, (span_tx_handler_t *) &silence_gen, &t->silence_gen);
set_next_tx_handler(s, (span_tx_handler_t *) &v27ter_tx, &t->v27ter_tx);
set_next_tx_handler(s, (span_tx_handler_t *) &v27ter_tx, &t->fast_modems.v27ter_tx);
set_rx_active(s, TRUE);
break;
case T38_IND_V29_7200_TRAINING:
@ -561,10 +553,10 @@ static int set_next_tx_type(t38_gateway_state_t *s)
}
/*endswitch*/
silence_gen_alter(&t->silence_gen, ms_to_samples(75));
v29_tx_restart(&t->v29_tx, t->tx_bit_rate, t->use_tep);
v29_tx_set_get_bit(&t->v29_tx, get_bit_func, get_bit_user_data);
v29_tx_restart(&t->fast_modems.v29_tx, t->tx_bit_rate, t->use_tep);
v29_tx_set_get_bit(&t->fast_modems.v29_tx, get_bit_func, get_bit_user_data);
set_tx_handler(s, (span_tx_handler_t *) &silence_gen, &t->silence_gen);
set_next_tx_handler(s, (span_tx_handler_t *) &v29_tx, &t->v29_tx);
set_next_tx_handler(s, (span_tx_handler_t *) &v29_tx, &t->fast_modems.v29_tx);
set_rx_active(s, TRUE);
break;
case T38_IND_V17_7200_SHORT_TRAINING:
@ -609,10 +601,10 @@ static int set_next_tx_type(t38_gateway_state_t *s)
}
/*endswitch*/
silence_gen_alter(&t->silence_gen, ms_to_samples(75));
v17_tx_restart(&t->v17_tx, t->tx_bit_rate, t->use_tep, short_train);
v17_tx_set_get_bit(&t->v17_tx, get_bit_func, get_bit_user_data);
v17_tx_restart(&t->fast_modems.v17_tx, t->tx_bit_rate, t->use_tep, short_train);
v17_tx_set_get_bit(&t->fast_modems.v17_tx, get_bit_func, get_bit_user_data);
set_tx_handler(s, (span_tx_handler_t *) &silence_gen, &t->silence_gen);
set_next_tx_handler(s, (span_tx_handler_t *) &v17_tx, &t->v17_tx);
set_next_tx_handler(s, (span_tx_handler_t *) &v17_tx, &t->fast_modems.v17_tx);
set_rx_active(s, TRUE);
break;
case T38_IND_V8_ANSAM:
@ -811,15 +803,15 @@ static void monitor_control_messages(t38_gateway_state_t *s,
uint8_t dcs_code;
} modem_codes[] =
{
{14400, T38_V17_RX, DISBIT6},
{12000, T38_V17_RX, (DISBIT6 | DISBIT4)},
{ 9600, T38_V17_RX, (DISBIT6 | DISBIT3)},
{ 9600, T38_V29_RX, DISBIT3},
{ 7200, T38_V17_RX, (DISBIT6 | DISBIT4 | DISBIT3)},
{ 7200, T38_V29_RX, (DISBIT4 | DISBIT3)},
{ 4800, T38_V27TER_RX, DISBIT4},
{ 2400, T38_V27TER_RX, 0},
{ 0, T38_NONE, 0}
{14400, FAX_MODEM_V17_RX, DISBIT6},
{12000, FAX_MODEM_V17_RX, (DISBIT6 | DISBIT4)},
{ 9600, FAX_MODEM_V17_RX, (DISBIT6 | DISBIT3)},
{ 9600, FAX_MODEM_V29_RX, DISBIT3},
{ 7200, FAX_MODEM_V17_RX, (DISBIT6 | DISBIT4 | DISBIT3)},
{ 7200, FAX_MODEM_V29_RX, (DISBIT4 | DISBIT3)},
{ 4800, FAX_MODEM_V27TER_RX, DISBIT4},
{ 2400, FAX_MODEM_V27TER_RX, 0},
{ 0, FAX_MODEM_NONE, 0}
};
static const int minimum_scan_line_times[8] =
{
@ -873,7 +865,7 @@ static void monitor_control_messages(t38_gateway_state_t *s,
/* We need to check which modem type is about to be used, so we can start the
correct modem. */
s->core.fast_bit_rate = 0;
s->core.fast_rx_modem = T38_NONE;
s->core.fast_rx_modem = FAX_MODEM_NONE;
s->core.image_data_mode = FALSE;
s->core.short_train = FALSE;
if (from_modem)
@ -924,7 +916,7 @@ static void monitor_control_messages(t38_gateway_state_t *s,
/* If we are hitting one of these conditions, it will take another DCS/DTC to select
the fast modem again, so abandon our idea of it. */
s->core.fast_bit_rate = 0;
s->core.fast_rx_modem = T38_NONE;
s->core.fast_rx_modem = FAX_MODEM_NONE;
s->core.image_data_mode = FALSE;
s->core.short_train = FALSE;
#endif
@ -950,7 +942,7 @@ static void monitor_control_messages(t38_gateway_state_t *s,
/* If we are hitting one of these conditions, it will take another DCS/DTC to select
the fast modem again, so abandon our idea of it. */
s->core.fast_bit_rate = 0;
s->core.fast_rx_modem = T38_NONE;
s->core.fast_rx_modem = FAX_MODEM_NONE;
s->core.image_data_mode = FALSE;
s->core.short_train = FALSE;
#endif
@ -1609,7 +1601,7 @@ static int set_fast_packetisation(t38_gateway_state_t *s)
ind = T38_IND_NO_SIGNAL;
switch (s->core.fast_rx_active)
{
case T38_V17_RX:
case FAX_MODEM_V17_RX:
set_octets_per_data_packet(s, s->core.fast_bit_rate);
switch (s->core.fast_bit_rate)
{
@ -1633,7 +1625,7 @@ static int set_fast_packetisation(t38_gateway_state_t *s)
}
/*endswitch*/
break;
case T38_V27TER_RX:
case FAX_MODEM_V27TER_RX:
set_octets_per_data_packet(s, s->core.fast_bit_rate);
switch (s->core.fast_bit_rate)
{
@ -1649,7 +1641,7 @@ static int set_fast_packetisation(t38_gateway_state_t *s)
}
/*endswitch*/
break;
case T38_V29_RX:
case FAX_MODEM_V29_RX:
set_octets_per_data_packet(s, s->core.fast_bit_rate);
switch (s->core.fast_bit_rate)
{
@ -2174,27 +2166,27 @@ static int restart_rx_modem(t38_gateway_state_t *s)
s->core.to_t38.octets_per_data_packet = 1;
switch (s->core.fast_rx_modem)
{
case T38_V17_RX:
v17_rx_restart(&s->audio.modems.v17_rx, s->core.fast_bit_rate, s->core.short_train);
v17_rx_set_put_bit(&s->audio.modems.v17_rx, put_bit_func, put_bit_user_data);
case FAX_MODEM_V17_RX:
v17_rx_restart(&s->audio.modems.fast_modems.v17_rx, s->core.fast_bit_rate, s->core.short_train);
v17_rx_set_put_bit(&s->audio.modems.fast_modems.v17_rx, put_bit_func, put_bit_user_data);
set_rx_handler(s, &v17_v21_rx, &v17_v21_rx_fillin, s);
s->core.fast_rx_active = T38_V17_RX;
s->core.fast_rx_active = FAX_MODEM_V17_RX;
break;
case T38_V27TER_RX:
v27ter_rx_restart(&s->audio.modems.v27ter_rx, s->core.fast_bit_rate, FALSE);
v27ter_rx_set_put_bit(&s->audio.modems.v27ter_rx, put_bit_func, put_bit_user_data);
case FAX_MODEM_V27TER_RX:
v27ter_rx_restart(&s->audio.modems.fast_modems.v27ter_rx, s->core.fast_bit_rate, FALSE);
v27ter_rx_set_put_bit(&s->audio.modems.fast_modems.v27ter_rx, put_bit_func, put_bit_user_data);
set_rx_handler(s, &v27ter_v21_rx, &v27ter_v21_rx_fillin, s);
s->core.fast_rx_active = T38_V27TER_RX;
s->core.fast_rx_active = FAX_MODEM_V27TER_RX;
break;
case T38_V29_RX:
v29_rx_restart(&s->audio.modems.v29_rx, s->core.fast_bit_rate, FALSE);
v29_rx_set_put_bit(&s->audio.modems.v29_rx, put_bit_func, put_bit_user_data);
case FAX_MODEM_V29_RX:
v29_rx_restart(&s->audio.modems.fast_modems.v29_rx, s->core.fast_bit_rate, FALSE);
v29_rx_set_put_bit(&s->audio.modems.fast_modems.v29_rx, put_bit_func, put_bit_user_data);
set_rx_handler(s, &v29_v21_rx, &v29_v21_rx_fillin, s);
s->core.fast_rx_active = T38_V29_RX;
s->core.fast_rx_active = FAX_MODEM_V29_RX;
break;
default:
set_rx_handler(s, (span_rx_handler_t *) &fsk_rx, (span_rx_fillin_handler_t *) &fsk_rx_fillin, &(s->audio.modems.v21_rx));
s->core.fast_rx_active = T38_NONE;
s->core.fast_rx_active = FAX_MODEM_NONE;
break;
}
/*endswitch*/
@ -2426,7 +2418,7 @@ static int t38_gateway_audio_init(t38_gateway_state_t *s)
/* TODO: Don't use the very low cutoff levels we would like to. We get some quirks if we do.
We need to sort this out. */
fsk_rx_signal_cutoff(&s->audio.modems.v21_rx, -30.0f);
v29_rx_signal_cutoff(&s->audio.modems.v29_rx, -28.5f);
v29_rx_signal_cutoff(&s->audio.modems.fast_modems.v29_rx, -28.5f);
return 0;
}
/*- End of function --------------------------------------------------------*/

View File

@ -1305,19 +1305,31 @@ SPAN_DECLARE(void) t38_terminal_set_config(t38_terminal_state_t *s, int config)
if ((config & T38_TERMINAL_OPTION_NO_PACING))
{
/* Continuous streaming mode, as used for TPKT over TCP transport */
/* Inhibit indicator packets */
t38_set_redundancy_control(&s->t38_fe.t38, T38_PACKET_CATEGORY_INDICATOR, 0);
t38_set_pace_transmission(&s->t38_fe.t38, FALSE);
s->t38_fe.hdlc_tx.extra_bits = 0;
if ((config & T38_TERMINAL_OPTION_NO_INDICATORS))
t38_set_redundancy_control(&s->t38_fe.t38, T38_PACKET_CATEGORY_INDICATOR, 0);
else
t38_set_redundancy_control(&s->t38_fe.t38, T38_PACKET_CATEGORY_INDICATOR, 1);
/*endif*/
t38_set_redundancy_control(&s->t38_fe.t38, T38_PACKET_CATEGORY_CONTROL_DATA, 1);
t38_set_redundancy_control(&s->t38_fe.t38, T38_PACKET_CATEGORY_CONTROL_DATA_END, 1);
t38_set_redundancy_control(&s->t38_fe.t38, T38_PACKET_CATEGORY_IMAGE_DATA, 1);
t38_set_redundancy_control(&s->t38_fe.t38, T38_PACKET_CATEGORY_IMAGE_DATA_END, 1);
s->t38_fe.ms_per_tx_chunk = 0;
s->t38_fe.chunking_modes &= ~T38_CHUNKING_SEND_REGULAR_INDICATORS;
s->t38_fe.chunking_modes |= T38_CHUNKING_MERGE_FCS_WITH_DATA;
}
else
{
/* Paced streaming mode, as used for UDP transports */
t38_set_redundancy_control(&s->t38_fe.t38, T38_PACKET_CATEGORY_INDICATOR, INDICATOR_TX_COUNT);
t38_set_pace_transmission(&s->t38_fe.t38, TRUE);
s->t38_fe.hdlc_tx.extra_bits = 0;
if ((config & T38_TERMINAL_OPTION_NO_INDICATORS))
t38_set_redundancy_control(&s->t38_fe.t38, T38_PACKET_CATEGORY_INDICATOR, 0);
else
t38_set_redundancy_control(&s->t38_fe.t38, T38_PACKET_CATEGORY_INDICATOR, INDICATOR_TX_COUNT);
/*endif*/
t38_set_redundancy_control(&s->t38_fe.t38, T38_PACKET_CATEGORY_CONTROL_DATA, DATA_TX_COUNT);
t38_set_redundancy_control(&s->t38_fe.t38, T38_PACKET_CATEGORY_CONTROL_DATA_END, DATA_END_TX_COUNT);
t38_set_redundancy_control(&s->t38_fe.t38, T38_PACKET_CATEGORY_IMAGE_DATA, DATA_TX_COUNT);

View File

@ -143,6 +143,13 @@ static int set_tiff_directory_info(t4_state_t *s)
t = &s->tiff;
/* Prepare the directory entry fully before writing the image, or libtiff complains */
TIFFSetField(t->tiff_file, TIFFTAG_COMPRESSION, t->output_compression);
#if defined(SPANDSP_SUPPORT_TIFF_FX)
TIFFSetField(t->tiff_file, TIFFTAG_PROFILETYPE, PROFILETYPE_G3_FAX);
TIFFSetField(t->tiff_file, TIFFTAG_FAXPROFILE, FAXPROFILE_S);
TIFFSetField(t->tiff_file, TIFFTAG_CODINGMETHODS, CODINGMETHODS_T4_1D | CODINGMETHODS_T4_2D | CODINGMETHODS_T6);
TIFFSetField(t->tiff_file, TIFFTAG_VERSIONYEAR, "1998");
/* TIFFSetField(t->tiff_file, TIFFTAG_MODENUMBER, 0); */
#endif
if (t->output_compression == COMPRESSION_CCITT_T4)
{
TIFFSetField(t->tiff_file, TIFFTAG_T4OPTIONS, t->output_t4_options);
@ -1015,6 +1022,9 @@ SPAN_DECLARE(t4_state_t *) t4_rx_init(t4_state_t *s, const char *file, int outpu
return NULL;
}
memset(s, 0, sizeof(*s));
#if defined(SPANDSP_SUPPORT_TIFF_FX)
TIFF_FX_init();
#endif
span_log_init(&s->logging, SPAN_LOG_NONE, NULL);
span_log_set_protocol(&s->logging, "T.4");
s->rx = TRUE;
@ -1239,18 +1249,18 @@ SPAN_DECLARE(const char *) t4_encoding_to_str(int encoding)
return "T.4 2-D";
case T4_COMPRESSION_ITU_T6:
return "T.6";
case T4_COMPRESSION_ITU_T85:
return "T.85";
case T4_COMPRESSION_ITU_T85_L0:
return "T.85(L0)";
case T4_COMPRESSION_ITU_T42:
return "T.42";
case T4_COMPRESSION_ITU_SYCC_T42:
return "sYCC T.42";
case T4_COMPRESSION_ITU_T43:
return "T.43";
case T4_COMPRESSION_ITU_T45:
return "T.45";
case T4_COMPRESSION_ITU_T81:
return "T.81";
case T4_COMPRESSION_ITU_SYCC_T81:
return "sYCC T.81";
case T4_COMPRESSION_ITU_T85:
return "T.85";
case T4_COMPRESSION_ITU_T85_L0:
return "T.85(L0)";
}
return "???";
}

View File

@ -121,6 +121,52 @@ static void STATE_TRACE(const char *format, ...)
#define STATE_TRACE(...) /**/
#endif
#if defined(SPANDSP_SUPPORT_TIFF_FX)
/* TIFF-FX related extensions to the tag set supported by libtiff */
static const TIFFFieldInfo tiff_fx_tiff_field_info[] =
{
{TIFFTAG_INDEXED, 1, 1, TIFF_SHORT, FIELD_CUSTOM, FALSE, FALSE, (char *) "Indexed"},
{TIFFTAG_GLOBALPARAMETERSIFD, 1, 1, TIFF_LONG, FIELD_CUSTOM, FALSE, FALSE, (char *) "GlobalParametersIFD"},
{TIFFTAG_PROFILETYPE, 1, 1, TIFF_LONG, FIELD_CUSTOM, FALSE, FALSE, (char *) "ProfileType"},
{TIFFTAG_FAXPROFILE, 1, 1, TIFF_BYTE, FIELD_CUSTOM, FALSE, FALSE, (char *) "FaxProfile"},
{TIFFTAG_CODINGMETHODS, 1, 1, TIFF_LONG, FIELD_CUSTOM, FALSE, FALSE, (char *) "CodingMethods"},
{TIFFTAG_VERSIONYEAR, 4, 4, TIFF_BYTE, FIELD_CUSTOM, FALSE, FALSE, (char *) "VersionYear"},
{TIFFTAG_MODENUMBER, 1, 1, TIFF_BYTE, FIELD_CUSTOM, FALSE, FALSE, (char *) "ModeNumber"},
{TIFFTAG_DECODE, TIFF_VARIABLE, TIFF_VARIABLE, TIFF_SRATIONAL, FIELD_CUSTOM, FALSE, FALSE, (char *) "Decode"},
{TIFFTAG_IMAGEBASECOLOR, TIFF_SPP, TIFF_SPP, TIFF_SHORT, FIELD_CUSTOM, FALSE, FALSE, (char *) "ImageBaseColor"},
{TIFFTAG_T82OPTIONS, 1, 1, TIFF_LONG, FIELD_CUSTOM, FALSE, FALSE, (char *) "T82Options"},
{TIFFTAG_STRIPROWCOUNTS, TIFF_VARIABLE, TIFF_VARIABLE, TIFF_LONG, FIELD_CUSTOM, FALSE, TRUE, (char *) "StripRowCounts"},
{TIFFTAG_IMAGELAYER, 2, 2, TIFF_LONG, FIELD_CUSTOM, FALSE, FALSE, (char *) "ImageLayer"},
};
static TIFFExtendProc _ParentExtender = NULL;
static void TIFFFXDefaultDirectory(TIFF *tif)
{
/* Install the extended tag field info */
TIFFMergeFieldInfo(tif, tiff_fx_tiff_field_info, 11);
/* Since we may have overriddden another directory method, we call it now to
allow it to set up the rest of its own methods. */
if (_ParentExtender)
(*_ParentExtender)(tif);
}
/*- End of function --------------------------------------------------------*/
SPAN_DECLARE(void) TIFF_FX_init(void)
{
static int first_time = TRUE;
if (!first_time)
return;
first_time = FALSE;
/* Grab the inherited method and install */
_ParentExtender = TIFFSetTagExtender(TIFFFXDefaultDirectory);
}
/*- End of function --------------------------------------------------------*/
#endif
/*! T.4 run length table entry */
typedef struct
{

View File

@ -35,23 +35,26 @@
/* Make this file just disappear if we are not on an x86 machine */
#if defined(__i386__) // || defined(__x86_64__)
#define X86_EFLAGS_CF 0x00000001 /* Carry Flag */
#define X86_EFLAGS_PF 0x00000004 /* Parity Flag */
#define X86_EFLAGS_AF 0x00000010 /* Auxillary carry Flag */
#define X86_EFLAGS_ZF 0x00000040 /* Zero Flag */
#define X86_EFLAGS_SF 0x00000080 /* Sign Flag */
#define X86_EFLAGS_TF 0x00000100 /* Trap Flag */
#define X86_EFLAGS_IF 0x00000200 /* Interrupt Flag */
#define X86_EFLAGS_DF 0x00000400 /* Direction Flag */
#define X86_EFLAGS_OF 0x00000800 /* Overflow Flag */
#define X86_EFLAGS_IOPL 0x00003000 /* IOPL mask */
#define X86_EFLAGS_NT 0x00004000 /* Nested Task */
#define X86_EFLAGS_RF 0x00010000 /* Resume Flag */
#define X86_EFLAGS_VM 0x00020000 /* Virtual Mode */
#define X86_EFLAGS_AC 0x00040000 /* Alignment Check */
#define X86_EFLAGS_VIF 0x00080000 /* Virtual Interrupt Flag */
#define X86_EFLAGS_VIP 0x00100000 /* Virtual Interrupt Pending */
#define X86_EFLAGS_ID 0x00200000 /* CPUID detection flag */
enum
{
X86_EFLAGS_CF = 0x00000001, /* Carry Flag */
X86_EFLAGS_PF = 0x00000004, /* Parity Flag */
X86_EFLAGS_AF = 0x00000010, /* Auxillary carry Flag */
X86_EFLAGS_ZF = 0x00000040, /* Zero Flag */
X86_EFLAGS_SF = 0x00000080, /* Sign Flag */
X86_EFLAGS_TF = 0x00000100, /* Trap Flag */
X86_EFLAGS_IF = 0x00000200, /* Interrupt Flag */
X86_EFLAGS_DF = 0x00000400, /* Direction Flag */
X86_EFLAGS_OF = 0x00000800, /* Overflow Flag */
X86_EFLAGS_IOPL = 0x00003000, /* IOPL mask */
X86_EFLAGS_NT = 0x00004000, /* Nested Task */
X86_EFLAGS_RF = 0x00010000, /* Resume Flag */
X86_EFLAGS_VM = 0x00020000, /* Virtual Mode */
X86_EFLAGS_AC = 0x00040000, /* Alignment Check */
X86_EFLAGS_VIF = 0x00080000, /* Virtual Interrupt Flag */
X86_EFLAGS_VIP = 0x00100000, /* Virtual Interrupt Pending */
X86_EFLAGS_ID = 0x00200000 /* CPUID detection flag */
};
/* Standard macro to see if a specific flag is changeable */
static __inline__ int flag_is_changeable_p(uint32_t flag)

View File

@ -44,6 +44,9 @@
#include "spandsp/telephony.h"
#include "spandsp/logging.h"
#include "spandsp/fast_convert.h"
#include "spandsp/math_fixed.h"
#include "spandsp/saturated.h"
#include "spandsp/complex.h"
#include "spandsp/vector_float.h"
#include "spandsp/complex_vector_float.h"

View File

@ -24,18 +24,26 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#if !defined(FP_SCALE)
#if defined(SPANDSP_USE_FIXED_POINT)
#define FP_SCALE(x) ((int16_t) x)
#else
#define FP_SCALE(x) (x)
#endif
#endif
#if defined(SPANDSP_USE_FIXED_POINT)
static const complexi16_t v29_abab_constellation[6] =
#else
static const complexf_t v29_abab_constellation[6] =
#endif
{
{ 3, -3}, /* 315deg high 9600 */
{-3, 0}, /* 180deg low */
{ 1, -1}, /* 315deg low 7200 */
{-3, 0}, /* 180deg low */
{ 0, -3}, /* 270deg low 4800 */
{-3, 0} /* 180deg low */
{FP_SCALE( 3.0f), FP_SCALE(-3.0f)}, /* 315deg high 9600 */
{FP_SCALE(-3.0f), FP_SCALE( 0.0f)}, /* 180deg low */
{FP_SCALE( 1.0f), FP_SCALE(-1.0f)}, /* 315deg low 7200 */
{FP_SCALE(-3.0f), FP_SCALE( 0.0f)}, /* 180deg low */
{FP_SCALE( 0.0f), FP_SCALE(-3.0f)}, /* 270deg low 4800 */
{FP_SCALE(-3.0f), FP_SCALE( 0.0f)} /* 180deg low */
};
#if defined(SPANDSP_USE_FIXED_POINT)
@ -44,12 +52,12 @@ static const complexi16_t v29_cdcd_constellation[6] =
static const complexf_t v29_cdcd_constellation[6] =
#endif
{
{ 3, 0}, /* 0deg low 9600 */
{-3, 3}, /* 135deg high */
{ 3, 0}, /* 0deg low 7200 */
{-1, 1}, /* 135deg low */
{ 3, 0}, /* 0deg low 4800 */
{ 0, 3} /* 90deg low */
{FP_SCALE( 3.0f), FP_SCALE( 0.0f)}, /* 0deg low 9600 */
{FP_SCALE(-3.0f), FP_SCALE( 3.0f)}, /* 135deg high */
{FP_SCALE( 3.0f), FP_SCALE( 0.0f)}, /* 0deg low 7200 */
{FP_SCALE(-1.0f), FP_SCALE( 1.0f)}, /* 135deg low */
{FP_SCALE( 3.0f), FP_SCALE( 0.0f)}, /* 0deg low 4800 */
{FP_SCALE( 0.0f), FP_SCALE( 3.0f)} /* 90deg low */
};
#if defined(SPANDSP_USE_FIXED_POINT)
@ -58,22 +66,22 @@ static const complexi16_t v29_9600_constellation[16] =
static const complexf_t v29_9600_constellation[16] =
#endif
{
{ 3, 0}, /* 0deg low */
{ 1, 1}, /* 45deg low */
{ 0, 3}, /* 90deg low */
{-1, 1}, /* 135deg low */
{-3, 0}, /* 180deg low */
{-1, -1}, /* 225deg low */
{ 0, -3}, /* 270deg low */
{ 1, -1}, /* 315deg low */
{ 5, 0}, /* 0deg high */
{ 3, 3}, /* 45deg high */
{ 0, 5}, /* 90deg high */
{-3, 3}, /* 135deg high */
{-5, 0}, /* 180deg high */
{-3, -3}, /* 225deg high */
{ 0, -5}, /* 270deg high */
{ 3, -3} /* 315deg high */
{FP_SCALE( 3.0f), FP_SCALE( 0.0f)}, /* 0deg low */
{FP_SCALE( 1.0f), FP_SCALE( 1.0f)}, /* 45deg low */
{FP_SCALE( 0.0f), FP_SCALE( 3.0f)}, /* 90deg low */
{FP_SCALE(-1.0f), FP_SCALE( 1.0f)}, /* 135deg low */
{FP_SCALE(-3.0f), FP_SCALE( 0.0f)}, /* 180deg low */
{FP_SCALE(-1.0f), FP_SCALE(-1.0f)}, /* 225deg low */
{FP_SCALE( 0.0f), FP_SCALE(-3.0f)}, /* 270deg low */
{FP_SCALE( 1.0f), FP_SCALE(-1.0f)}, /* 315deg low */
{FP_SCALE( 5.0f), FP_SCALE( 0.0f)}, /* 0deg high */
{FP_SCALE( 3.0f), FP_SCALE( 3.0f)}, /* 45deg high */
{FP_SCALE( 0.0f), FP_SCALE( 5.0f)}, /* 90deg high */
{FP_SCALE(-3.0f), FP_SCALE( 3.0f)}, /* 135deg high */
{FP_SCALE(-5.0f), FP_SCALE( 0.0f)}, /* 180deg high */
{FP_SCALE(-3.0f), FP_SCALE(-3.0f)}, /* 225deg high */
{FP_SCALE( 0.0f), FP_SCALE(-5.0f)}, /* 270deg high */
{FP_SCALE( 3.0f), FP_SCALE(-3.0f)} /* 315deg high */
};
/*- End of file ------------------------------------------------------------*/

View File

@ -746,17 +746,14 @@ static int valid_data_state(v42_state_t *ss)
static void receive_information_frame(v42_state_t *ss, const uint8_t *frame, int len)
{
lapm_state_t *s;
int ret;
int n;
s = &ss->lapm;
if (!valid_data_state(ss))
return;
if (len > s->rx_n401 + 3)
return;
ret = 0;
/* Ack I frames: NR - 1 */
n = ack_info(ss, frame[2] >> 1);
ack_info(ss, frame[2] >> 1);
if (s->local_busy)
{
/* 8.4.7 */
@ -786,7 +783,6 @@ static void receive_information_frame(v42_state_t *ss, const uint8_t *frame, int
static void rx_supervisory_cmd_frame(v42_state_t *ss, const uint8_t *frame, int len)
{
lapm_state_t *s;
int n;
s = &ss->lapm;
/* If l->local_busy each RR,RNR,REJ with p=1 should be replied by RNR with f=1 (8.4.7) */
@ -794,20 +790,20 @@ static void rx_supervisory_cmd_frame(v42_state_t *ss, const uint8_t *frame, int
{
case LAPM_S_RR:
s->far_busy = FALSE;
n = ack_info(ss, frame[2] >> 1);
ack_info(ss, frame[2] >> 1);
/* If p = 1 may be used for status checking? */
tx_information_rr_rnr_response(ss, frame, len);
break;
case LAPM_S_RNR:
s->far_busy = TRUE;
n = ack_info(ss, frame[2] >> 1);
ack_info(ss, frame[2] >> 1);
/* If p = 1 may be used for status checking? */
if ((frame[2] & 0x1))
tx_supervisory_frame(s, s->rsp_addr, (s->local_busy) ? LAPM_S_RNR : LAPM_S_RR, 1);
break;
case LAPM_S_REJ:
s->far_busy = FALSE;
n = ack_info(ss, frame[2] >> 1);
ack_info(ss, frame[2] >> 1);
if (s->retry_count == 0)
{
t401_stop_t403_start(ss);
@ -827,7 +823,6 @@ static void rx_supervisory_cmd_frame(v42_state_t *ss, const uint8_t *frame, int
static void rx_supervisory_rsp_frame(v42_state_t *ss, const uint8_t *frame, int len)
{
lapm_state_t *s;
int n;
s = &ss->lapm;
if (s->retry_count == 0 && (frame[2] & 0x1))
@ -837,7 +832,7 @@ static void rx_supervisory_rsp_frame(v42_state_t *ss, const uint8_t *frame, int
{
case LAPM_S_RR:
s->far_busy = FALSE;
n = ack_info(ss, frame[2] >> 1);
ack_info(ss, frame[2] >> 1);
if (s->retry_count && (frame[2] & 0x1))
{
reject_info(s);
@ -846,7 +841,7 @@ static void rx_supervisory_rsp_frame(v42_state_t *ss, const uint8_t *frame, int
break;
case LAPM_S_RNR:
s->far_busy = TRUE;
n = ack_info(ss, frame[2] >> 1);
ack_info(ss, frame[2] >> 1);
if (s->retry_count && (frame[2] & 0x1))
{
reject_info(s);
@ -857,7 +852,7 @@ static void rx_supervisory_rsp_frame(v42_state_t *ss, const uint8_t *frame, int
break;
case LAPM_S_REJ:
s->far_busy = FALSE;
n = ack_info(ss, frame[2] >> 1);
ack_info(ss, frame[2] >> 1);
if (s->retry_count == 0 || (frame[2] & 0x1))
{
reject_info(s);

View File

@ -1011,9 +1011,9 @@ SPAN_DECLARE(int) v8_restart(v8_state_t *s, int calling_party, v8_parms_t *parms
s->modulation_bytes = 3;
s->ci_timer = 0;
if (calling_party)
s->calling_party = calling_party;
if (s->calling_party)
{
s->calling_party = TRUE;
s->state = V8_WAIT_1S;
s->negotiation_timer = ms_to_samples(1000);
s->ci_count = 0;
@ -1023,11 +1023,9 @@ SPAN_DECLARE(int) v8_restart(v8_state_t *s, int calling_party, v8_parms_t *parms
else
{
/* Send the ANSam or ANSam/ tone */
s->calling_party = FALSE;
modem_connect_tones_tx_init(&s->ansam_tx, s->parms.modem_connect_tone);
v8_decode_init(s);
s->state = V8_CM_WAIT;
v8_decode_init(s);
modem_connect_tones_tx_init(&s->ansam_tx, s->parms.modem_connect_tone);
s->negotiation_timer = ms_to_samples(200 + 5000);
s->modem_connect_tone_tx_on = ms_to_samples(75) + 1;
}

View File

@ -50,17 +50,16 @@ static int tests_failed = FALSE;
static int msg_step = 0;
static int msg2_step = 0;
static int error_step = 0;
static int msg_done = FALSE;
static int msg2_done = FALSE;
static int error_done = FALSE;
static void message_handler(int level, const char *text)
static void message_handler(void *user_data, int level, const char *text)
{
const char *ref[] =
{
"TAG Log with tag 1 2 3\n",
"Log with protocol 1 2 3\n",
"ERROR Log with severity log 1 2 3\n",
"FLOW NewTag Log with new tag 1 2 3\n",
"FLOW Protocol NewTag Log with protocol 1 2 3\n",
"FLOW Protocol NewTag Buf 00 01 02 03 04 05 06 07 08 09\n",
@ -78,6 +77,8 @@ static void message_handler(int level, const char *text)
""
};
if (ref[msg_step][0] == '\0')
return;
if (strcmp(ref[msg_step], text))
{
printf(">>>: %s", ref[msg_step]);
@ -89,7 +90,7 @@ static void message_handler(int level, const char *text)
}
/*- End of function --------------------------------------------------------*/
static void message_handler2(int level, const char *text)
static void message_handler2(void *user_data, int level, const char *text)
{
/* TODO: This doesn't check if the date/time field makes sense */
if (strcmp(" FLOW Protocol NewTag Date/time tagged log 1 2 3\n", text + 23))
@ -103,25 +104,6 @@ static void message_handler2(int level, const char *text)
}
/*- End of function --------------------------------------------------------*/
static void error_handler(const char *text)
{
const char *ref[] =
{
"ERROR Log with severity log 1 2 3\n",
""
};
if (strcmp(ref[error_step], text))
{
printf(">>>: %s", ref[error_step]);
tests_failed = TRUE;
}
if (ref[++error_step][0] == '\0')
error_done = TRUE;
printf("ERR: %s", text);
}
/*- End of function --------------------------------------------------------*/
int main(int argc, char *argv[])
{
logging_state_t log;
@ -143,8 +125,7 @@ int main(int argc, char *argv[])
fprintf(stderr, "Not logged.\n");
/* Now set a custom log handler */
span_log_set_message_handler(&log, &message_handler);
span_log_set_error_handler(&log, &error_handler);
span_log_set_message_handler(&log, &message_handler, NULL);
span_log_set_sample_rate(&log, 44100);
/* Try the different logging elements */
@ -176,7 +157,7 @@ int main(int argc, char *argv[])
fprintf(stderr, "Logged.\n");
else
fprintf(stderr, "Not logged.\n");
/* Test logging of buffer contents */
for (i = 0; i < 1000; i++)
buf[i] = i;
@ -199,7 +180,7 @@ int main(int argc, char *argv[])
break;
}
}
/* Check timestamping by samples */
span_log_set_level(&log, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_SHOW_TAG | SPAN_LOG_FLOW | SPAN_LOG_SHOW_SAMPLE_TIME);
for (i = 0; i < 10; i++)
@ -209,7 +190,7 @@ int main(int argc, char *argv[])
}
/* Check timestamping by current date and time */
span_log_set_message_handler(&log, &message_handler2);
span_log_set_message_handler(&log, &message_handler2, NULL);
span_log_set_level(&log, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_SHOW_TAG | SPAN_LOG_FLOW | SPAN_LOG_SHOW_DATE);
for (i = 0; i < 10; i++)
{
@ -218,13 +199,13 @@ int main(int argc, char *argv[])
delay.tv_nsec = 20000000;
nanosleep(&delay, NULL);
}
if (tests_failed || !msg_done || !error_done)
if (tests_failed || !msg_done)
{
printf("Tests failed - %d %d %d.\n", tests_failed, msg_done, error_done);
printf("Tests failed - %d %d.\n", tests_failed, msg_done);
return 2;
}
span_log_set_message_handler(&log, &message_handler);
span_log_set_message_handler(&log, &message_handler, NULL);
printf("Tests passed.\n");
return 0;

View File

@ -137,6 +137,6 @@ switch_status_t spandsp_fax_detect_session(switch_core_session_t *session,
int hits, const char *app, const char *data, switch_tone_detect_callback_t callback);
switch_status_t spandsp_fax_stop_detect_session(switch_core_session_t *session);
void spanfax_log_message(int level, const char *msg);
void spanfax_log_message(void *user_data, int level, const char *msg);
switch_status_t load_configuration(switch_bool_t reload);
void mod_spandsp_indicate_data(switch_core_session_t *session, switch_bool_t self, switch_bool_t on);

View File

@ -259,7 +259,7 @@ static void counter_increment(void)
switch_mutex_unlock(spandsp_globals.mutex);
}
void spanfax_log_message(int level, const char *msg)
void spanfax_log_message(void *user_data, int level, const char *msg)
{
int fs_log_level;
@ -713,8 +713,8 @@ static switch_status_t spanfax_init(pvt_t *pvt, transport_mode_t trans_mode)
fax_set_transmit_on_idle(fax, TRUE);
span_log_set_message_handler(&fax->logging, spanfax_log_message);
span_log_set_message_handler(&t30->logging, spanfax_log_message);
span_log_set_message_handler(&fax->logging, spanfax_log_message, NULL);
span_log_set_message_handler(&t30->logging, spanfax_log_message, NULL);
if (pvt->verbose) {
span_log_set_level(&fax->logging, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_FLOW);
@ -769,8 +769,8 @@ static switch_status_t spanfax_init(pvt_t *pvt, transport_mode_t trans_mode)
}
}
span_log_set_message_handler(&t38->logging, spanfax_log_message);
span_log_set_message_handler(&t30->logging, spanfax_log_message);
span_log_set_message_handler(&t38->logging, spanfax_log_message, NULL);
span_log_set_message_handler(&t30->logging, spanfax_log_message, NULL);
if (pvt->verbose) {
span_log_set_level(&t38->logging, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_FLOW);
@ -824,8 +824,8 @@ static switch_status_t spanfax_init(pvt_t *pvt, transport_mode_t trans_mode)
}
span_log_set_message_handler(&pvt->t38_gateway_state->logging, spanfax_log_message);
span_log_set_message_handler(&pvt->t38_core->logging, spanfax_log_message);
span_log_set_message_handler(&pvt->t38_gateway_state->logging, spanfax_log_message, NULL);
span_log_set_message_handler(&pvt->t38_core->logging, spanfax_log_message, NULL);
if (pvt->verbose) {
span_log_set_level(&pvt->t38_gateway_state->logging, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_FLOW);

View File

@ -346,15 +346,15 @@ switch_status_t modem_init(modem_t *modem, modem_control_handler_t control_handl
}
if (spandsp_globals.modem_verbose) {
span_log_set_message_handler(&modem->t31_state->logging, spanfax_log_message);
span_log_set_message_handler(&modem->t31_state->audio.modems.v17_rx.logging, spanfax_log_message);
span_log_set_message_handler(&modem->t31_state->audio.modems.v29_rx.logging, spanfax_log_message);
span_log_set_message_handler(&modem->t31_state->audio.modems.v27ter_rx.logging, spanfax_log_message);
span_log_set_message_handler(&modem->t31_state->logging, spanfax_log_message, NULL);
span_log_set_message_handler(&modem->t31_state->audio.modems.fast_modems.v17_rx.logging, spanfax_log_message, NULL);
span_log_set_message_handler(&modem->t31_state->audio.modems.fast_modems.v29_rx.logging, spanfax_log_message, NULL);
span_log_set_message_handler(&modem->t31_state->audio.modems.fast_modems.v27ter_rx.logging, spanfax_log_message, NULL);
modem->t31_state->logging.level = SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_FLOW;
modem->t31_state->audio.modems.v17_rx.logging.level = SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_FLOW;
modem->t31_state->audio.modems.v29_rx.logging.level = SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_FLOW;
modem->t31_state->audio.modems.v27ter_rx.logging.level = SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_FLOW;
modem->t31_state->audio.modems.fast_modems.v17_rx.logging.level = SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_FLOW;
modem->t31_state->audio.modems.fast_modems.v29_rx.logging.level = SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_FLOW;
modem->t31_state->audio.modems.fast_modems.v27ter_rx.logging.level = SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_FLOW;
}
modem->control_handler = control_handler;