}
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
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;
}
{
int ok;
char *u;
- const char *w;
char num[100 + 1];
char ch;
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++)
{
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 ';':
{
/* 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;
#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
};
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");
}
}
}
/*- 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)
}
/*- 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;
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
{
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;
}
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
{
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;
}
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
{
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;
}
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;
}
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:
{
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:
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:
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:
/* 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;
}
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)
{
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;
}
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)
{
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;
}
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)
{
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;
}
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;
}
}
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;
}
}
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;
}
}
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);
}
/*- 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;
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)
#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[] =
"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);
}
}
/*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;
}
/*- 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 --------------------------------------------------------*/
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;
{
int32_t pbar;
float sbar;
- int32_t path[2];
int32_t i;
int32_t j;
float alpha;
/* 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, */
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)
{
SPAN_DECLARE(int) queue_read_byte(queue_state_t *s)
{
int real_len;
- int to_end;
int iptr;
int optr;
int byte;
if (real_len < 1)
return -1;
/*endif*/
- to_end = s->len - optr;
byte = s->data[optr];
if (++optr >= s->len)
optr = 0;
#endif
#include <stdlib.h>
-#include <stdio.h>
#include <inttypes.h>
#if defined(HAVE_TGMATH_H)
#include <tgmath.h>
}
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;
/*! 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
*/
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"
{
\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
#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>
#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
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,
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,
};
/*!
- 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[] =
{
};
/*!
- 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[] =
{
#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
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_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_log_set_message_handler(logging_state_t *s, message_handler_func_t func, void *user_data);
-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);
uint8_t in_digit;
/*! The current sample number within a processing block. */
int current_sample;
-
+
/*! Tone state duration */
int duration;
/*! \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 */
/*! \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. */
/*! \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;
const char *protocol;
message_handler_func_t span_message;
- error_handler_func_t span_error;
+ void *user_data;
};
#endif
/*! \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 */
{
/*! \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;
/*! \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;
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. */
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;
/*! 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;
*/
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.
*/
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
???.
*/
-/*! 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.
{
T38_TRANSPORT_UDPTL = 0,
T38_TRANSPORT_RTP,
- T38_TRANSPORT_TCP
+ T38_TRANSPORT_TCP,
+ T38_TRANSPORT_TCP_TPKT
};
/*! T.38 TCF management types */
\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
\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.
\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.
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);
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;
\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. */
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
{
#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.
#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)
}
/*- 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;
}
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;
{
/* 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 ------------------------------------------------------------*/
}
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;
}
}
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;
}
}
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;
}
{
/* 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
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;
}
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;
}
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;
{
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 --------------------------------------------------------*/
{
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 --------------------------------------------------------*/
{
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 --------------------------------------------------------*/
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)
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;
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))
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;
}
}
if (set_dis_or_dtc(s))
{
- s->current_status = T30_ERR_INCOMPATIBLE;
+ t30_set_status(s, T30_ERR_INCOMPATIBLE);
send_dcn(s);
return -1;
}
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;
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;
}
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;
}
}
/*- 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;
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)
{
else
{
/* Give up */
- s->current_status = T30_ERR_RX_ECMPHD;
+ t30_set_status(s, T30_ERR_RX_ECMPHD);
send_dcn(s);
}
return 0;
/* 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;
#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]);
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;
}
}
}
/* 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);
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
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:
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:
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:
{
/* 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;
}
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;
}
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:
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:
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;
}
}
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:
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;
}
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:
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;
}
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:
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:
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;
}
}
{
/* 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;
}
{
/* 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;
}
{
/* 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;
}
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);
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;
}
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:
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:
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;
}
}
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:
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;
}
}
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:
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;
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:
{
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);
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);
}
/* 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:
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;
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 --------------------------------------------------------*/
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 --------------------------------------------------------*/
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 --------------------------------------------------------*/
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 --------------------------------------------------------*/
{
/* 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 --------------------------------------------------------*/
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. */
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;
}
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)
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)
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 --------------------------------------------------------*/
{
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
{
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 --------------------------------------------------------*/
}
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;
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);
}
}
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;
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);
}
}
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;
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);
}
}
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;
}
}
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
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);
}
else
{
- fsk_rx(&(s->audio.modems.v21_rx), amp, len);
+ fsk_rx(&s->audio.modems.v21_rx, amp, len);
}
return 0;
}
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
{
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;
}
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
{
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;
}
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
{
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;
}
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)
{
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;
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;
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 --------------------------------------------------------*/
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;
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;
const model_data_t *known_models;
} nsf_data_t;
-const char *t35_country_codes[256] =
-{
- "Japan", /* 0x00 */
- "Albania",
- "Algeria",
- "American Samoa",
- "Germany",
- "Anguilla",
- "Antigua and Barbuda",
- "Argentina",
- "Ascension (see S. Helena)",
- "Australia",
- "Austria",
- "Bahamas",
- "Bahrain",
- "Bangladesh",
- "Barbados",
- "Belgium",
- "Belize",
- "Benin (Republic of)",
- "Bermudas",
- "Bhutan (Kingdom of)",
- "Bolivia",
- "Botswana",
- "Brazil",
- "British Antarctic Territory",
- "British Indian Ocean Territory",
- "British Virgin Islands",
- "Brunei Darussalam",
- "Bulgaria",
- "Myanmar (Union of)",
- "Burundi",
- "Byelorussia",
- "Cameroon",
- "Canada", /* 0x20 */
- "Cape Verde",
- "Cayman Islands",
- "Central African Republic",
- "Chad",
- "Chile",
- "China",
- "Colombia",
- "Comoros",
- "Congo",
- "Cook Islands",
- "Costa Rica",
- "Cuba",
- "Cyprus",
- "Czech and Slovak Federal Republic",
- "Cambodia",
- "Democratic People's Republic of Korea",
- "Denmark",
- "Djibouti",
- "Dominican Republic",
- "Dominica",
- "Ecuador",
- "Egypt",
- "El Salvador",
- "Equatorial Guinea",
- "Ethiopia",
- "Falkland Islands",
- "Fiji",
- "Finland",
- "France",
- "French Polynesia",
- "French Southern and Antarctic Lands",
- "Gabon", /* 0x40 */
- "Gambia",
- "Germany (Federal Republic of)",
- "Angola",
- "Ghana",
- "Gibraltar",
- "Greece",
- "Grenada",
- "Guam",
- "Guatemala",
- "Guernsey",
- "Guinea",
- "Guinea-Bissau",
- "Guayana",
- "Haiti",
- "Honduras",
- "Hong Kong",
- "Hungary (Republic of)",
- "Iceland",
- "India",
- "Indonesia",
- "Iran (Islamic Republic of)",
- "Iraq",
- "Ireland",
- "Israel",
- "Italy",
- "Cote d'Ivoire",
- "Jamaica",
- "Afghanistan",
- "Jersey",
- "Jordan",
- "Kenya",
- "Kiribati", /* 0x60 */
- "Korea (Republic of)",
- "Kuwait",
- "Lao (People's Democratic Republic)",
- "Lebanon",
- "Lesotho",
- "Liberia",
- "Libya",
- "Liechtenstein",
- "Luxembourg",
- "Macau",
- "Madagascar",
- "Malaysia",
- "Malawi",
- "Maldives",
- "Mali",
- "Malta",
- "Mauritania",
- "Mauritius",
- "Mexico",
- "Monaco",
- "Mongolia",
- "Montserrat",
- "Morocco",
- "Mozambique",
- "Nauru",
- "Nepal",
- "Netherlands",
- "Netherlands Antilles",
- "New Caledonia",
- "New Zealand",
- "Nicaragua",
- "Niger", /* 0x80 */
- "Nigeria",
- "Norway",
- "Oman",
- "Pakistan",
- "Panama",
- "Papua New Guinea",
- "Paraguay",
- "Peru",
- "Philippines",
- "Poland (Republic of)",
- "Portugal",
- "Puerto Rico",
- "Qatar",
- "Romania",
- "Rwanda",
- "Saint Kitts and Nevis",
- "Saint Croix",
- "Saint Helena and Ascension",
- "Saint Lucia",
- "San Marino",
- "Saint Thomas",
- "Sao Tome and Principe",
- "Saint Vincent and the Grenadines",
- "Saudi Arabia",
- "Senegal",
- "Seychelles",
- "Sierra Leone",
- "Singapore",
- "Solomon Islands",
- "Somalia",
- "South Africa",
- "Spain", /* 0xA0 */
- "Sri Lanka",
- "Sudan",
- "Suriname",
- "Swaziland",
- "Sweden",
- "Switzerland",
- "Syria",
- "Tanzania",
- "Thailand",
- "Togo",
- "Tonga",
- "Trinidad and Tobago",
- "Tunisia",
- "Turkey",
- "Turks and Caicos Islands",
- "Tuvalu",
- "Uganda",
- "Ukraine",
- "United Arab Emirates",
- "United Kingdom",
- "United States",
- "Burkina Faso",
- "Uruguay",
- "U.S.S.R.",
- "Vanuatu",
- "Vatican City State",
- "Venezuela",
- "Viet Nam",
- "Wallis and Futuna",
- "Western Samoa",
- "Yemen (Republic of)",
- "Yemen (Republic of)", /* 0xC0 */
- "Yugoslavia",
- "Zaire",
- "Zambia",
- "Zimbabwe"
- "Slovakia",
- "Slovenia",
- "(available)",
- "(available)",
- "(available)",
- "(available)",
- "(available)",
- "(available)",
- "(available)",
- "(available)",
- "(available)",
- "(available)", /* 0xD0 */
- "(available)",
- "(available)",
- "(available)",
- "(available)",
- "(available)",
- "(available)",
- "(available)",
- "(available)",
- "(available)",
- "(available)",
- "(available)",
- "(available)",
- "(available)",
- "(available)",
- "(available)",
- "(available)", /* 0xE0 */
- "(available)",
- "(available)",
- "(available)",
- "(available)",
- "(available)",
- "(available)",
- "(available)",
- "(available)",
- "(available)",
- "(available)",
- "(available)",
- "(available)",
- "(available)",
- "(available)",
- "(available)",
- "(available)", /* 0xF0 */
- "(available)",
- "(available)",
- "(available)",
- "(available)",
- "(available)",
- "(available)",
- "Lithuania",
- "Latvia",
- "Estonia",
- "US Virgin Islands",
- "(available)",
- "(available)",
- "(Universal)",
- "Taiwan",
- "(extension)"
-};
+/*! T.35 country codes */
+typedef struct
+{
+ /*! The country's name */
+ const char *name;
+ /*! A pointer to a list of known vendors from this country */
+ const nsf_data_t *vendors;
+} country_code_t;
static const model_data_t Canon[] =
{
{5, "\x80\x00\x80\x48\x00", "Faxphone B640"},
{5, "\x80\x00\x80\x49\x10", "Fax B100"},
{5, "\x80\x00\x8A\x49\x10", "Laser Class 9000 Series"},
+ {5, "\x80\x00\x8A\x48\x00", "Laser Class 2060"},
{0, NULL, NULL}
};
static const model_data_t Panasonic0E[] =
{
{10, "\x00\x00\x00\x96\x0F\x01\x02\x00\x10\x05\x02\x95\xC8\x08\x01\x49\x02\x41\x53\x54\x47", "KX-F90"},
- {10, "\x00\x00\x00\x96\x0F\x01\x03\x00\x10\x05\x02\x95\xC8\x08\x01\x49\x02 \x03", "KX-F230 or KX-FT21 or ..."},
+ {10, "\x00\x00\x00\x96\x0F\x01\x03\x00\x10\x05\x02\x95\xC8\x08\x01\x49\x02\x03", "KX-F230 or KX-FT21 or ..."},
{10, "\x00\x00\x00\x16\x0F\x01\x03\x00\x10\x05\x02\x95\xC8\x08", "KX-F780"},
{10, "\x00\x00\x00\x16\x0F\x01\x03\x00\x10\x00\x02\x95\x80\x08\x75\xB5", "KX-M260"},
{10, "\x00\x00\x00\x16\x0F\x01\x02\x00\x10\x05\x02\x85\xC8\x08\xAD", "KX-F2050BS"},
* table must be verified and corrected against actual real-world
* results.
*/
-static const nsf_data_t known_nsf[] =
+static const nsf_data_t vendor_00[] =
{
/* Japan */
- {"\x00\x00\x00", 3, "Unknown - indeterminate", TRUE, NULL},
- {"\x00\x00\x01", 3, "Anjitsu", FALSE, NULL},
- {"\x00\x00\x02", 3, "Nippon Telephone", FALSE, NULL},
- {"\x00\x00\x05", 3, "Mitsuba Electric", FALSE, NULL},
- {"\x00\x00\x06", 3, "Master Net", FALSE, NULL},
- {"\x00\x00\x09", 3, "Xerox/Toshiba", TRUE, Xerox},
- {"\x00\x00\x0A", 3, "Kokusai", FALSE, NULL},
- {"\x00\x00\x0D", 3, "Logic System International", FALSE, NULL},
- {"\x00\x00\x0E", 3, "Panasonic", FALSE, Panasonic0E},
- {"\x00\x00\x11", 3, "Canon", FALSE, Canon},
- {"\x00\x00\x15", 3, "Toyotsushen Machinery", FALSE, NULL},
- {"\x00\x00\x16", 3, "System House Mind", FALSE, NULL},
- {"\x00\x00\x19", 3, "Xerox", TRUE, NULL},
- {"\x00\x00\x1D", 3, "Hitachi Software", FALSE, NULL},
- {"\x00\x00\x21", 3, "OKI Electric/Lanier", TRUE, NULL},
- {"\x00\x00\x25", 3, "Ricoh", TRUE, Ricoh},
- {"\x00\x00\x26", 3, "Konica", FALSE, NULL},
- {"\x00\x00\x29", 3, "Japan Wireless", FALSE, NULL},
- {"\x00\x00\x2D", 3, "Sony", FALSE, NULL},
- {"\x00\x00\x31", 3, "Sharp/Olivetti", FALSE, Sharp},
- {"\x00\x00\x35", 3, "Kogyu", FALSE, NULL},
- {"\x00\x00\x36", 3, "Japan Telecom", FALSE, NULL},
- {"\x00\x00\x3D", 3, "IBM Japan", FALSE, NULL},
- {"\x00\x00\x39", 3, "Panasonic", FALSE, NULL},
- {"\x00\x00\x41", 3, "Swasaki Communication", FALSE, NULL},
- {"\x00\x00\x45", 3, "Muratec", FALSE, Muratec45},
- {"\x00\x00\x46", 3, "Pheonix", FALSE, NULL},
- {"\x00\x00\x48", 3, "Muratec", FALSE, Muratec48}, // not registered
- {"\x00\x00\x49", 3, "Japan Electric", FALSE, NULL},
- {"\x00\x00\x4D", 3, "Okura Electric", FALSE, NULL},
- {"\x00\x00\x51", 3, "Sanyo", FALSE, Sanyo},
- {"\x00\x00\x55", 3, "unknown - Japan 55", FALSE, NULL},
- {"\x00\x00\x56", 3, "Brother", FALSE, Brother},
- {"\x00\x00\x59", 3, "Fujitsu", FALSE, NULL},
- {"\x00\x00\x5D", 3, "Kuoni", FALSE, NULL},
- {"\x00\x00\x61", 3, "Casio", FALSE, NULL},
- {"\x00\x00\x65", 3, "Tateishi Electric", FALSE, NULL},
- {"\x00\x00\x66", 3, "Utax/Mita", TRUE, NULL},
- {"\x00\x00\x69", 3, "Hitachi Production", FALSE, NULL},
- {"\x00\x00\x6D", 3, "Hitachi Telecom", FALSE, NULL},
- {"\x00\x00\x71", 3, "Tamura Electric Works", FALSE, NULL},
- {"\x00\x00\x75", 3, "Tokyo Electric Corp.", FALSE, NULL},
- {"\x00\x00\x76", 3, "Advance", FALSE, NULL},
- {"\x00\x00\x79", 3, "Panasonic", FALSE, Panasonic79},
- {"\x00\x00\x7D", 3, "Seiko", FALSE, NULL},
- {"\x00\x08\x00", 3, "Daiko", FALSE, NULL},
- {"\x00\x10\x00", 3, "Funai Electric", FALSE, NULL},
- {"\x00\x20\x00", 3, "Eagle System", FALSE, NULL},
- {"\x00\x30\x00", 3, "Nippon Business Systems", FALSE, NULL},
- {"\x00\x40\x00", 3, "Comtron", FALSE, NULL},
- {"\x00\x48\x00", 3, "Cosmo Consulting", FALSE, NULL},
- {"\x00\x50\x00", 3, "Orion Electric", FALSE, NULL},
- {"\x00\x60\x00", 3, "Nagano Nippon", FALSE, NULL},
- {"\x00\x70\x00", 3, "Kyocera", FALSE, NULL},
- {"\x00\x80\x00", 3, "Kanda Networks", FALSE, NULL},
- {"\x00\x88\x00", 3, "Soft Front", FALSE, NULL},
- {"\x00\x90\x00", 3, "Arctic", FALSE, NULL},
- {"\x00\xA0\x00", 3, "Nakushima", FALSE, NULL},
- {"\x00\xB0\x00", 3, "Minolta", FALSE, NULL},
- {"\x00\xC0\x00", 3, "Tohoku Pioneer", FALSE, NULL},
- {"\x00\xD0\x00", 3, "USC", FALSE, NULL},
- {"\x00\xE0\x00", 3, "Hiboshi", FALSE, NULL},
- {"\x00\xF0\x00", 3, "Sumitomo Electric", FALSE, NULL},
+ {"\x00\x00", 2, "Unknown - indeterminate", TRUE, NULL},
+ {"\x00\x01", 2, "Anritsu", FALSE, NULL},
+ {"\x00\x02", 2, "Nippon Telephone", FALSE, NULL},
+ {"\x00\x05", 2, "Mitsuba Electric", FALSE, NULL},
+ {"\x00\x06", 2, "Master Net", FALSE, NULL},
+ {"\x00\x09", 2, "Xerox/Toshiba", TRUE, Xerox},
+ {"\x00\x0A", 2, "Kokusai", FALSE, NULL},
+ {"\x00\x0D", 2, "Logic System International", FALSE, NULL},
+ {"\x00\x0E", 2, "Panasonic", FALSE, Panasonic0E},
+ {"\x00\x11", 2, "Canon", FALSE, Canon},
+ {"\x00\x15", 2, "Toyotsushen Machinery", FALSE, NULL},
+ {"\x00\x16", 2, "System House Mind", FALSE, NULL},
+ {"\x00\x19", 2, "Xerox", TRUE, NULL},
+ {"\x00\x1D", 2, "Hitachi Software", FALSE, NULL},
+ {"\x00\x21", 2, "OKI Electric/Lanier", TRUE, NULL},
+ {"\x00\x25", 2, "Ricoh", TRUE, Ricoh},
+ {"\x00\x26", 2, "Konica", FALSE, NULL},
+ {"\x00\x29", 2, "Japan Wireless", FALSE, NULL},
+ {"\x00\x2D", 2, "Sony", FALSE, NULL},
+ {"\x00\x31", 2, "Sharp/Olivetti", FALSE, Sharp},
+ {"\x00\x35", 2, "Kogyu", FALSE, NULL},
+ {"\x00\x36", 2, "Japan Telecom", FALSE, NULL},
+ {"\x00\x3D", 2, "IBM Japan", FALSE, NULL},
+ {"\x00\x39", 2, "Panasonic", FALSE, NULL},
+ {"\x00\x41", 2, "Swasaki Communication", FALSE, NULL},
+ {"\x00\x45", 2, "Muratec", FALSE, Muratec45},
+ {"\x00\x46", 2, "Pheonix", FALSE, NULL},
+ {"\x00\x48", 2, "Muratec", FALSE, Muratec48}, /* Not registered */
+ {"\x00\x49", 2, "Japan Electric", FALSE, NULL},
+ {"\x00\x4D", 2, "Okura Electric", FALSE, NULL},
+ {"\x00\x51", 2, "Sanyo", FALSE, Sanyo},
+ {"\x00\x55", 2, "Unknown - Japan 55", FALSE, NULL},
+ {"\x00\x56", 2, "Brother", FALSE, Brother},
+ {"\x00\x59", 2, "Fujitsu", FALSE, NULL},
+ {"\x00\x5D", 2, "Kuoni", FALSE, NULL},
+ {"\x00\x61", 2, "Casio", FALSE, NULL},
+ {"\x00\x65", 2, "Tateishi Electric", FALSE, NULL},
+ {"\x00\x66", 2, "Utax/Mita", TRUE, NULL},
+ {"\x00\x69", 2, "Hitachi Production", FALSE, NULL},
+ {"\x00\x6D", 2, "Hitachi Telecom", FALSE, NULL},
+ {"\x00\x71", 2, "Tamura Electric Works", FALSE, NULL},
+ {"\x00\x75", 2, "Tokyo Electric Corp.", FALSE, NULL},
+ {"\x00\x76", 2, "Advance", FALSE, NULL},
+ {"\x00\x79", 2, "Panasonic", FALSE, Panasonic79},
+ {"\x00\x7D", 2, "Seiko", FALSE, NULL},
+ {"\x08\x00", 2, "Daiko", FALSE, NULL},
+ {"\x10\x00", 2, "Funai Electric", FALSE, NULL},
+ {"\x20\x00", 2, "Eagle System", FALSE, NULL},
+ {"\x30\x00", 2, "Nippon Business Systems", FALSE, NULL},
+ {"\x40\x00", 2, "Comtron", FALSE, NULL},
+ {"\x48\x00", 2, "Cosmo Consulting", FALSE, NULL},
+ {"\x50\x00", 2, "Orion Electric", FALSE, NULL},
+ {"\x60\x00", 2, "Nagano Nippon", FALSE, NULL},
+ {"\x70\x00", 2, "Kyocera", FALSE, NULL},
+ {"\x80\x00", 2, "Kanda Networks", FALSE, NULL},
+ {"\x88\x00", 2, "Soft Front", FALSE, NULL},
+ {"\x90\x00", 2, "Arctic", FALSE, NULL},
+ {"\xA0\x00", 2, "Nakushima", FALSE, NULL},
+ {"\xB0\x00", 2, "Minolta", FALSE, NULL},
+ {"\xC0\x00", 2, "Tohoku Pioneer", FALSE, NULL},
+ {"\xD0\x00", 2, "USC", FALSE, NULL},
+ {"\xE0\x00", 2, "Hiboshi", FALSE, NULL},
+ {"\xF0\x00", 2, "Sumitomo Electric", FALSE, NULL},
+ {NULL, 0, NULL, FALSE, NULL}
+};
+static const nsf_data_t vendor_20[] =
+{
/* Germany */
- {"\x20\x09", 2, "ITK Institut für Telekommunikation GmbH & Co KG", FALSE, NULL},
- {"\x20\x11", 2, "Dr. Neuhaus Mikroelektronik", FALSE, NULL},
- {"\x20\x21", 2, "ITO Communication", FALSE, NULL},
- {"\x20\x31", 2, "mbp Kommunikationssysteme GmbH", FALSE, NULL},
- {"\x20\x41", 2, "Siemens", FALSE, NULL},
- {"\x20\x42", 2, "Deutsche Telekom AG", FALSE, NULL},
- {"\x20\x51", 2, "mps Software", FALSE, NULL},
- {"\x20\x61", 2, "Hauni Elektronik", FALSE, NULL},
- {"\x20\x71", 2, "Digitronic computersysteme gmbh", FALSE, NULL},
- {"\x20\x81\x00", 3, "Innovaphone GmbH", FALSE, NULL},
- {"\x20\x81\x40", 3, "TEDAS Gesellschaft für Telekommunikations-, Daten- und Audiosysteme mbH", FALSE, NULL},
- {"\x20\x81\x80", 3, "AVM Audiovisuelles Marketing und Computersysteme GmbH", FALSE, NULL},
- {"\x20\x81\xC0", 3, "EICON Technology Research GmbH", FALSE, NULL},
- {"\x20\xB1", 2, "Schneider Rundfunkwerke AG", FALSE, NULL},
- {"\x20\xC2", 2, "Deutsche Telekom AG", FALSE, NULL},
- {"\x20\xD1", 2, "Ferrari electronik GmbH", FALSE, NULL},
- {"\x20\xF1", 2, "DeTeWe - Deutsche Telephonwerke AG & Co", FALSE, NULL},
- {"\x20\xFF", 2, "Germany Regional Code", FALSE, NULL},
-
- /* China */
- {"\x64\x00\x00", 3, "unknown - China 00 00", FALSE, NULL},
- {"\x64\x01\x00", 3, "unknown - China 01 00", FALSE, NULL},
- {"\x64\x01\x01", 3, "unknown - China 01 01", FALSE, NULL},
- {"\x64\x01\x02", 3, "unknown - China 01 02", FALSE, NULL},
+ {"\x09", 1, "ITK Institut für Telekommunikation GmbH & Co KG", FALSE, NULL},
+ {"\x11", 1, "Dr. Neuhaus Mikroelektronik", FALSE, NULL},
+ {"\x21", 1, "ITO Communication", FALSE, NULL},
+ {"\x31", 1, "mbp Kommunikationssysteme GmbH", FALSE, NULL},
+ {"\x41", 1, "Siemens", FALSE, NULL},
+ {"\x42", 1, "Deutsche Telekom AG", FALSE, NULL},
+ {"\x51", 1, "mps Software", FALSE, NULL},
+ {"\x61", 1, "Hauni Elektronik", FALSE, NULL},
+ {"\x71", 1, "Digitronic computersysteme gmbh", FALSE, NULL},
+ {"\x81\x00", 2, "Innovaphone GmbH", FALSE, NULL},
+ {"\x81\x40", 2, "TEDAS Gesellschaft für Telekommunikations-, Daten- und Audiosysteme mbH", FALSE, NULL},
+ {"\x81\x80", 2, "AVM Audiovisuelles Marketing und Computersysteme GmbH", FALSE, NULL},
+ {"\x81\xC0", 2, "EICON Technology Research GmbH", FALSE, NULL},
+ {"\xB1", 1, "Schneider Rundfunkwerke AG", FALSE, NULL},
+ {"\xC2", 1, "Deutsche Telekom AG", FALSE, NULL},
+ {"\xD1", 1, "Ferrari electronik GmbH", FALSE, NULL},
+ {"\xF1", 1, "DeTeWe - Deutsche Telephonwerke AG & Co", FALSE, NULL},
+ {"\xFF", 1, "Germany Regional Code", FALSE, NULL},
+ {NULL, 0, NULL, FALSE, NULL}
+};
- /* France */
- {"\xBC\x53\x01", 3, "Minolta", FALSE, NULL},
+static const nsf_data_t vendor_64[] =
+{
+ /* China (not Lebanon) */
+ {"\x00\x00", 2, "Unknown - China 00 00", FALSE, NULL},
+ {"\x01\x00", 2, "Unknown - China 01 00", FALSE, NULL},
+ {"\x01\x01", 2, "Unknown - China 01 01", FALSE, NULL},
+ {"\x01\x02", 2, "Unknown - China 01 02", FALSE, NULL},
+ {NULL, 0, NULL, FALSE, NULL}
+};
+static const nsf_data_t vendor_61[] =
+{
/* Korea */
- {"\x86\x00\x02", 3, "unknown - Korea 02", FALSE, NULL},
- {"\x86\x00\x06", 3, "unknown - Korea 06", FALSE, NULL},
- {"\x86\x00\x08", 3, "unknown - Korea 08", FALSE, NULL},
- {"\x86\x00\x0A", 3, "unknown - Korea 0A", FALSE, NULL},
- {"\x86\x00\x0E", 3, "unknown - Korea 0E", FALSE, NULL},
- {"\x86\x00\x10", 3, "Samsung", FALSE, NULL},
- {"\x86\x00\x11", 3, "unknown - Korea 11", FALSE, NULL},
- {"\x86\x00\x16", 3, "Samsung", FALSE, Samsung16},
- {"\x86\x00\x1A", 3, "unknown - Korea 1A", FALSE, NULL},
- {"\x86\x00\x40", 3, "unknown - Korea 40", FALSE, NULL},
- {"\x86\x00\x48", 3, "unknown - Korea 48", FALSE, NULL},
- {"\x86\x00\x52", 3, "unknown - Korea 52", FALSE, NULL},
- {"\x86\x00\x5A", 3, "Samsung", FALSE, Samsung5A},
- {"\x86\x00\x5E", 3, "unknown - Korea 5E", FALSE, NULL},
- {"\x86\x00\x66", 3, "unknown - Korea 66", FALSE, NULL},
- {"\x86\x00\x6E", 3, "unknown - Korea 6E", FALSE, NULL},
- {"\x86\x00\x82", 3, "unknown - Korea 82", FALSE, NULL},
- {"\x86\x00\x88", 3, "unknown - Korea 88", FALSE, NULL},
- {"\x86\x00\x8A", 3, "unknown - Korea 8A", FALSE, NULL},
- {"\x86\x00\x8C", 3, "Samsung", FALSE, Samsung8C},
- {"\x86\x00\x92", 3, "unknown - Korea 92", FALSE, NULL},
- {"\x86\x00\x98", 3, "Samsung", FALSE, NULL},
- {"\x86\x00\xA2", 3, "Samsung", FALSE, SamsungA2},
- {"\x86\x00\xA4", 3, "unknown - Korea A4", FALSE, NULL},
- {"\x86\x00\xC2", 3, "Samsung", FALSE, NULL},
- {"\x86\x00\xC9", 3, "unknown - Korea C9", FALSE, NULL},
- {"\x86\x00\xCC", 3, "unknown - Korea CC", FALSE, NULL},
- {"\x86\x00\xD2", 3, "unknown - Korea D2", FALSE, NULL},
- {"\x86\x00\xDA", 3, "Xerox", FALSE, XeroxDA},
- {"\x86\x00\xE2", 3, "unknown - Korea E2", FALSE, NULL},
- {"\x86\x00\xEC", 3, "unknown - Korea EC", FALSE, NULL},
- {"\x86\x00\xEE", 3, "unknown - Korea EE", FALSE, NULL},
+ {"\x00\x7A", 2, "Xerox", FALSE, NULL},
+ {NULL, 0, NULL, FALSE, NULL}
+};
+static const nsf_data_t vendor_86[] =
+{
+ /* Korea (not Papua New Guinea) */
+ {"\x00\x02", 2, "Unknown - Korea 02", FALSE, NULL},
+ {"\x00\x06", 2, "Unknown - Korea 06", FALSE, NULL},
+ {"\x00\x08", 2, "Unknown - Korea 08", FALSE, NULL},
+ {"\x00\x0A", 2, "Unknown - Korea 0A", FALSE, NULL},
+ {"\x00\x0E", 2, "Unknown - Korea 0E", FALSE, NULL},
+ {"\x00\x10", 2, "Samsung", FALSE, NULL},
+ {"\x00\x11", 2, "Unknown - Korea 11", FALSE, NULL},
+ {"\x00\x16", 2, "Samsung", FALSE, Samsung16},
+ {"\x00\x1A", 2, "Unknown - Korea 1A", FALSE, NULL},
+ {"\x00\x40", 2, "Unknown - Korea 40", FALSE, NULL},
+ {"\x00\x48", 2, "Unknown - Korea 48", FALSE, NULL},
+ {"\x00\x52", 2, "Unknown - Korea 52", FALSE, NULL},
+ {"\x00\x5A", 2, "Samsung", FALSE, Samsung5A},
+ {"\x00\x5E", 2, "Unknown - Korea 5E", FALSE, NULL},
+ {"\x00\x66", 2, "Unknown - Korea 66", FALSE, NULL},
+ {"\x00\x6E", 2, "Unknown - Korea 6E", FALSE, NULL},
+ {"\x00\x82", 2, "Unknown - Korea 82", FALSE, NULL},
+ {"\x00\x88", 2, "Unknown - Korea 88", FALSE, NULL},
+ {"\x00\x8A", 2, "Unknown - Korea 8A", FALSE, NULL},
+ {"\x00\x8C", 2, "Samsung", FALSE, Samsung8C},
+ {"\x00\x92", 2, "Unknown - Korea 92", FALSE, NULL},
+ {"\x00\x98", 2, "Samsung", FALSE, NULL},
+ {"\x00\xA2", 2, "Samsung", FALSE, SamsungA2},
+ {"\x00\xA4", 2, "Unknown - Korea A4", FALSE, NULL},
+ {"\x00\xC2", 2, "Samsung", FALSE, NULL},
+ {"\x00\xC9", 2, "Unknown - Korea C9", FALSE, NULL},
+ {"\x00\xCC", 2, "Unknown - Korea CC", FALSE, NULL},
+ {"\x00\xD2", 2, "Unknown - Korea D2", FALSE, NULL},
+ {"\x00\xDA", 2, "Xerox", FALSE, XeroxDA},
+ {"\x00\xE2", 2, "Unknown - Korea E2", FALSE, NULL},
+ {"\x00\xEC", 2, "Unknown - Korea EC", FALSE, NULL},
+ {"\x00\xEE", 2, "Unknown - Korea EE", FALSE, NULL},
+ {NULL, 0, NULL, FALSE, NULL}
+};
+
+static const nsf_data_t vendor_bc[] =
+{
+ /* France */
+ {"\x53\x01", 2, "Minolta", FALSE, NULL},
+ {NULL, 0, NULL, FALSE, NULL}
+};
+
+static const nsf_data_t vendor_ad[] =
+{
+ /* United States (not Tunisia) */
+ {"\x00\x00", 2, "Pitney Bowes", FALSE, PitneyBowes},
+ {"\x00\x0C", 2, "Dialogic", FALSE, NULL},
+ {"\x00\x15", 2, "Lexmark", FALSE, Lexmark},
+ {"\x00\x16", 2, "JetFax", FALSE, JetFax},
+ {"\x00\x24", 2, "Octel", FALSE, NULL},
+ {"\x00\x36", 2, "HP", FALSE, HP},
+ {"\x00\x42", 2, "FaxTalk", FALSE, NULL},
+ {"\x00\x44", 2, NULL, TRUE, NULL},
+ {"\x00\x46", 2, "BrookTrout", FALSE, NULL},
+ {"\x00\x51", 2, "Telogy Networks", FALSE, NULL},
+ {"\x00\x55", 2, "HylaFAX", FALSE, NULL},
+ {"\x00\x5C", 2, "IBM", FALSE, NULL},
+ {"\x00\x98", 2, "Unknown - USA 98", TRUE, NULL},
+ {NULL, 0, NULL, FALSE, NULL}
+};
+
+static const nsf_data_t vendor_b4[] =
+{
/* United Kingdom */
- {"\xB4\x00\xB0", 3, "DCE", FALSE, NULL},
- {"\xB4\x00\xB1", 3, "Hasler", FALSE, NULL},
- {"\xB4\x00\xB2", 3, "Interquad", FALSE, NULL},
- {"\xB4\x00\xB3", 3, "Comwave", FALSE, NULL},
- {"\xB4\x00\xB4", 3, "Iconographic", FALSE, NULL},
- {"\xB4\x00\xB5", 3, "Wordcraft", FALSE, NULL},
- {"\xB4\x00\xB6", 3, "Acorn", FALSE, NULL},
+ {"\x00\xB0", 2, "DCE", FALSE, NULL},
+ {"\x00\xB1", 2, "Hasler", FALSE, NULL},
+ {"\x00\xB2", 2, "Interquad", FALSE, NULL},
+ {"\x00\xB3", 2, "Comwave", FALSE, NULL},
+ {"\x00\xB4", 2, "Iconographic", FALSE, NULL},
+ {"\x00\xB5", 2, "Wordcraft", FALSE, NULL},
+ {"\x00\xB6", 2, "Acorn", FALSE, NULL},
+ {NULL, 0, NULL, FALSE, NULL}
+};
+static const nsf_data_t vendor_b5[] =
+{
/* United States */
- {"\xAD\x00\x00", 3, "Pitney Bowes", FALSE, PitneyBowes},
- {"\xAD\x00\x0C", 3, "Dialogic", FALSE, NULL},
- {"\xAD\x00\x15", 3, "Lexmark", FALSE, Lexmark},
- {"\xAD\x00\x16", 3, "JetFax", FALSE, JetFax},
- {"\xAD\x00\x24", 3, "Octel", FALSE, NULL},
- {"\xAD\x00\x36", 3, "HP", FALSE, HP},
- {"\xAD\x00\x42", 3, "FaxTalk", FALSE, NULL},
- {"\xAD\x00\x44", 3, NULL, TRUE, NULL},
- {"\xAD\x00\x46", 3, "BrookTrout", FALSE, NULL},
- {"\xAD\x00\x51", 3, "Telogy Networks", FALSE, NULL},
- {"\xAD\x00\x55", 3, "HylaFAX", FALSE, NULL},
- {"\xAD\x00\x5C", 3, "IBM", FALSE, NULL},
- {"\xAD\x00\x98", 3, "unknown - USA 98", TRUE, NULL},
- {"\xB5\x00\x01", 3, "Picturetel", FALSE, NULL},
- {"\xB5\x00\x20", 3, "Conexant", FALSE, NULL},
- {"\xB5\x00\x22", 3, "Comsat", FALSE, NULL},
- {"\xB5\x00\x24", 3, "Octel", FALSE, NULL},
- {"\xB5\x00\x26", 3, "ROLM", FALSE, NULL},
- {"\xB5\x00\x28", 3, "SOFNET", FALSE, NULL},
- {"\xB5\x00\x29", 3, "TIA TR-29 Committee", FALSE, NULL},
- {"\xB5\x00\x2A", 3, "STF Tech", FALSE, NULL},
- {"\xB5\x00\x2C", 3, "HKB", FALSE, NULL},
- {"\xB5\x00\x2E", 3, "Delrina", FALSE, NULL},
- {"\xB5\x00\x30", 3, "Dialogic", FALSE, NULL},
- {"\xB5\x00\x32", 3, "Applied Synergy", FALSE, NULL},
- {"\xB5\x00\x34", 3, "Syncro Development", FALSE, NULL},
- {"\xB5\x00\x36", 3, "Genoa", FALSE, NULL},
- {"\xB5\x00\x38", 3, "Texas Instruments", FALSE, NULL},
- {"\xB5\x00\x3A", 3, "IBM", FALSE, NULL},
- {"\xB5\x00\x3C", 3, "ViaSat", FALSE, NULL},
- {"\xB5\x00\x3E", 3, "Ericsson", FALSE, NULL},
- {"\xB5\x00\x42", 3, "Bogosian", FALSE, NULL},
- {"\xB5\x00\x44", 3, "Adobe", FALSE, NULL},
- {"\xB5\x00\x46", 3, "Fremont Communications", FALSE, NULL},
- {"\xB5\x00\x48", 3, "Hayes", FALSE, NULL},
- {"\xB5\x00\x4A", 3, "Lucent", FALSE, NULL},
- {"\xB5\x00\x4C", 3, "Data Race", FALSE, NULL},
- {"\xB5\x00\x4E", 3, "TRW", FALSE, NULL},
- {"\xB5\x00\x52", 3, "Audiofax", FALSE, NULL},
- {"\xB5\x00\x54", 3, "Computer Automation", FALSE, NULL},
- {"\xB5\x00\x56", 3, "Serca", FALSE, NULL},
- {"\xB5\x00\x58", 3, "Octocom", FALSE, NULL},
- {"\xB5\x00\x5C", 3, "Power Solutions", FALSE, NULL},
- {"\xB5\x00\x5A", 3, "Digital Sound", FALSE, NULL},
- {"\xB5\x00\x5E", 3, "Pacific Data", FALSE, NULL},
- {"\xB5\x00\x60", 3, "Commetrex", FALSE, NULL},
- {"\xB5\x00\x62", 3, "BrookTrout", FALSE, NULL},
- {"\xB5\x00\x64", 3, "Gammalink", FALSE, NULL},
- {"\xB5\x00\x66", 3, "Castelle", FALSE, NULL},
- {"\xB5\x00\x68", 3, "Hybrid Fax", FALSE, NULL},
- {"\xB5\x00\x6A", 3, "Omnifax", FALSE, NULL},
- {"\xB5\x00\x6C", 3, "HP", FALSE, NULL},
- {"\xB5\x00\x6E", 3, "Microsoft", FALSE, NULL},
- {"\xB5\x00\x72", 3, "Speaking Devices", FALSE, NULL},
- {"\xB5\x00\x74", 3, "Compaq", FALSE, NULL},
-/*
- {"\xB5\x00\x76", 3, "Trust - Cryptek", FALSE, NULL}, // collision with Microsoft
-*/
- {"\xB5\x00\x76", 3, "Microsoft", FALSE, NULL}, // uses LSB for country but MSB for manufacturer
- {"\xB5\x00\x78", 3, "Cylink", FALSE, NULL},
- {"\xB5\x00\x7A", 3, "Pitney Bowes", FALSE, NULL},
- {"\xB5\x00\x7C", 3, "Digiboard", FALSE, NULL},
- {"\xB5\x00\x7E", 3, "Codex", FALSE, NULL},
- {"\xB5\x00\x82", 3, "Wang Labs", FALSE, NULL},
- {"\xB5\x00\x84", 3, "Netexpress Communications", FALSE, NULL},
- {"\xB5\x00\x86", 3, "Cable-Sat", FALSE, NULL},
- {"\xB5\x00\x88", 3, "MFPA", FALSE, NULL},
- {"\xB5\x00\x8A", 3, "Telogy Networks", FALSE, NULL},
- {"\xB5\x00\x8E", 3, "Telecom Multimedia Systems", FALSE, NULL},
- {"\xB5\x00\x8C", 3, "AT&T", FALSE, NULL},
- {"\xB5\x00\x92", 3, "Nuera", FALSE, NULL},
- {"\xB5\x00\x94", 3, "K56flex", FALSE, NULL},
- {"\xB5\x00\x96", 3, "MiBridge", FALSE, NULL},
- {"\xB5\x00\x98", 3, "Xerox", FALSE, NULL},
- {"\xB5\x00\x9A", 3, "Fujitsu", FALSE, NULL},
- {"\xB5\x00\x9B", 3, "Fujitsu", FALSE, NULL},
- {"\xB5\x00\x9C", 3, "Natural Microsystems", FALSE, NULL},
- {"\xB5\x00\x9E", 3, "CopyTele", FALSE, NULL},
- {"\xB5\x00\xA2", 3, "Murata", FALSE, NULL},
- {"\xB5\x00\xA4", 3, "Lanier", FALSE, NULL},
- {"\xB5\x00\xA6", 3, "Qualcomm", FALSE, NULL},
- {"\xB5\x00\xAA", 3, "HylaFAX", FALSE, NULL}, // we did it backwards for a while
+ {"\x00\x01", 2, "Picturetel", FALSE, NULL},
+ {"\x00\x20", 2, "Conexant", FALSE, NULL},
+ {"\x00\x22", 2, "Comsat", FALSE, NULL},
+ {"\x00\x24", 2, "Octel", FALSE, NULL},
+ {"\x00\x26", 2, "ROLM", FALSE, NULL},
+ {"\x00\x28", 2, "SOFNET", FALSE, NULL},
+ {"\x00\x29", 2, "TIA TR-29 Committee", FALSE, NULL},
+ {"\x00\x2A", 2, "STF Tech", FALSE, NULL},
+ {"\x00\x2C", 2, "HKB", FALSE, NULL},
+ {"\x00\x2E", 2, "Delrina", FALSE, NULL},
+ {"\x00\x30", 2, "Dialogic", FALSE, NULL},
+ {"\x00\x32", 2, "Applied Synergy", FALSE, NULL},
+ {"\x00\x34", 2, "Syncro Development", FALSE, NULL},
+ {"\x00\x36", 2, "Genoa", FALSE, NULL},
+ {"\x00\x38", 2, "Texas Instruments", FALSE, NULL},
+ {"\x00\x3A", 2, "IBM", FALSE, NULL},
+ {"\x00\x3C", 2, "ViaSat", FALSE, NULL},
+ {"\x00\x3E", 2, "Ericsson", FALSE, NULL},
+ {"\x00\x42", 2, "Bogosian", FALSE, NULL},
+ {"\x00\x44", 2, "Adobe", FALSE, NULL},
+ {"\x00\x46", 2, "Fremont Communications", FALSE, NULL},
+ {"\x00\x48", 2, "Hayes", FALSE, NULL},
+ {"\x00\x4A", 2, "Lucent", FALSE, NULL},
+ {"\x00\x4C", 2, "Data Race", FALSE, NULL},
+ {"\x00\x4E", 2, "TRW", FALSE, NULL},
+ {"\x00\x52", 2, "Audiofax", FALSE, NULL},
+ {"\x00\x54", 2, "Computer Automation", FALSE, NULL},
+ {"\x00\x56", 2, "Serca", FALSE, NULL},
+ {"\x00\x58", 2, "Octocom", FALSE, NULL},
+ {"\x00\x5C", 2, "Power Solutions", FALSE, NULL},
+ {"\x00\x5A", 2, "Digital Sound", FALSE, NULL},
+ {"\x00\x5E", 2, "Pacific Data", FALSE, NULL},
+ {"\x00\x60", 2, "Commetrex", FALSE, NULL},
+ {"\x00\x62", 2, "BrookTrout", FALSE, NULL},
+ {"\x00\x64", 2, "Gammalink", FALSE, NULL},
+ {"\x00\x66", 2, "Castelle", FALSE, NULL},
+ {"\x00\x68", 2, "Hybrid Fax", FALSE, NULL},
+ {"\x00\x6A", 2, "Omnifax", FALSE, NULL},
+ {"\x00\x6C", 2, "HP", FALSE, NULL},
+ {"\x00\x6E", 2, "Microsoft", FALSE, NULL},
+ {"\x00\x72", 2, "Speaking Devices", FALSE, NULL},
+ {"\x00\x74", 2, "Compaq", FALSE, NULL},
+ {"\x00\x76", 2, "Microsoft", FALSE, NULL}, /* uses LSB for country but MSB for manufacturer */
+ {"\x00\x78", 2, "Cylink", FALSE, NULL},
+ {"\x00\x7A", 2, "Pitney Bowes", FALSE, NULL},
+ {"\x00\x7C", 2, "Digiboard", FALSE, NULL},
+ {"\x00\x7E", 2, "Codex", FALSE, NULL},
+ {"\x00\x82", 2, "Wang Labs", FALSE, NULL},
+ {"\x00\x84", 2, "Netexpress Communications", FALSE, NULL},
+ {"\x00\x86", 2, "Cable-Sat", FALSE, NULL},
+ {"\x00\x88", 2, "MFPA", FALSE, NULL},
+ {"\x00\x8A", 2, "Telogy Networks", FALSE, NULL},
+ {"\x00\x8E", 2, "Telecom Multimedia Systems", FALSE, NULL},
+ {"\x00\x8C", 2, "AT&T", FALSE, NULL},
+ {"\x00\x92", 2, "Nuera", FALSE, NULL},
+ {"\x00\x94", 2, "K56flex", FALSE, NULL},
+ {"\x00\x96", 2, "MiBridge", FALSE, NULL},
+ {"\x00\x98", 2, "Xerox", FALSE, NULL},
+ {"\x00\x9A", 2, "Fujitsu", FALSE, NULL},
+ {"\x00\x9B", 2, "Fujitsu", FALSE, NULL},
+ {"\x00\x9C", 2, "Natural Microsystems", FALSE, NULL},
+ {"\x00\x9E", 2, "CopyTele", FALSE, NULL},
+ {"\x00\xA2", 2, "Murata", FALSE, NULL},
+ {"\x00\xA4", 2, "Lanier", FALSE, NULL},
+ {"\x00\xA6", 2, "Qualcomm", FALSE, NULL},
+ {"\x00\xAA", 2, "HylaFAX", FALSE, NULL},
{NULL, 0, NULL, FALSE, NULL}
};
-#if 0
-SPAN_DECLARE(void) nsf_find_station_id(int reverse_order)
+static const country_code_t t35_country_codes[255] =
{
- const char *id = NULL;
- int idSize = 0;
- const char *maxId = NULL;
- int maxIdSize = 0;
- const char *p;
+ {"Japan", vendor_00}, /* 0x00 */
+ {"Albania", NULL},
+ {"Algeria", NULL},
+ {"American Samoa", NULL},
+ {"Germany", NULL},
+ {"Anguilla", NULL},
+ {"Antigua and Barbuda", NULL},
+ {"Argentina", NULL},
+ {"Ascension (see S. Helena)", NULL},
+ {"Australia", NULL},
+ {"Austria", NULL},
+ {"Bahamas", NULL},
+ {"Bahrain", NULL},
+ {"Bangladesh", NULL},
+ {"Barbados", NULL},
+ {"Belgium", NULL},
+ {"Belize", NULL}, /* 0x10 */
+ {"Benin (Republic of)", NULL},
+ {"Bermudas", NULL},
+ {"Bhutan (Kingdom of)", NULL},
+ {"Bolivia", NULL},
+ {"Botswana", NULL},
+ {"Brazil", NULL},
+ {"British Antarctic Territory", NULL},
+ {"British Indian Ocean Territory", NULL},
+ {"British Virgin Islands", NULL},
+ {"Brunei Darussalam", NULL},
+ {"Bulgaria", NULL},
+ {"Myanmar (Union of)", NULL},
+ {"Burundi", NULL},
+ {"Byelorussia", NULL},
+ {"Cameroon", NULL},
+ {"Canada", vendor_20}, /* 0x20 */
+ {"Cape Verde", NULL},
+ {"Cayman Islands", NULL},
+ {"Central African Republic", NULL},
+ {"Chad", NULL},
+ {"Chile", NULL},
+ {"China", NULL},
+ {"Colombia", NULL},
+ {"Comoros", NULL},
+ {"Congo", NULL},
+ {"Cook Islands", NULL},
+ {"Costa Rica", NULL},
+ {"Cuba", NULL},
+ {"Cyprus", NULL},
+ {"Czech and Slovak Federal Republic", NULL}, /* 0x30 */
+ {"Cambodia", NULL},
+ {"Democratic People's Republic of Korea", NULL},
+ {"Denmark", NULL},
+ {"Djibouti", NULL},
+ {"Dominican Republic", NULL},
+ {"Dominica", NULL},
+ {"Ecuador", NULL},
+ {"Egypt", NULL},
+ {"El Salvador", NULL},
+ {"Equatorial Guinea", NULL},
+ {"Ethiopia", NULL},
+ {"Falkland Islands", NULL},
+ {"Fiji", NULL},
+ {"Finland", NULL},
+ {"France", NULL},
+ {"French Polynesia", NULL},
+ {"French Southern and Antarctic Lands", NULL},
+ {"Gabon", NULL}, /* 0x40 */
+ {"Gambia", NULL},
+ {"Germany (Federal Republic of)", NULL},
+ {"Angola", NULL},
+ {"Ghana", NULL},
+ {"Gibraltar", NULL},
+ {"Greece", NULL},
+ {"Grenada", NULL},
+ {"Guam", NULL},
+ {"Guatemala", NULL},
+ {"Guernsey", NULL},
+ {"Guinea", NULL},
+ {"Guinea-Bissau", NULL},
+ {"Guayana", NULL},
+ {"Haiti", NULL},
+ {"Honduras", NULL},
+ {"Hong Kong", NULL}, /* 0x50 */
+ {"Hungary (Republic of)", NULL},
+ {"Iceland", NULL},
+ {"India", NULL},
+ {"Indonesia", NULL},
+ {"Iran (Islamic Republic of)", NULL},
+ {"Iraq", NULL},
+ {"Ireland", NULL},
+ {"Israel", NULL},
+ {"Italy", NULL},
+ {"Cote d'Ivoire", NULL},
+ {"Jamaica", NULL},
+ {"Afghanistan", NULL},
+ {"Jersey", NULL},
+ {"Jordan", NULL},
+ {"Kenya", NULL},
+ {"Kiribati", NULL}, /* 0x60 */
+ {"Korea (Republic of)", vendor_61},
+ {"Kuwait", NULL},
+ {"Lao (People's Democratic Republic)", NULL},
+ {"Lebanon", vendor_64},
+ {"Lesotho", NULL},
+ {"Liberia", NULL},
+ {"Libya", NULL},
+ {"Liechtenstein", NULL},
+ {"Luxembourg", NULL},
+ {"Macau", NULL},
+ {"Madagascar", NULL},
+ {"Malaysia", NULL},
+ {"Malawi", NULL},
+ {"Maldives", NULL},
+ {"Mali", NULL},
+ {"Malta", NULL}, /* 0x70 */
+ {"Mauritania", NULL},
+ {"Mauritius", NULL},
+ {"Mexico", NULL},
+ {"Monaco", NULL},
+ {"Mongolia", NULL},
+ {"Montserrat", NULL},
+ {"Morocco", NULL},
+ {"Mozambique", NULL},
+ {"Nauru", NULL},
+ {"Nepal", NULL},
+ {"Netherlands", NULL},
+ {"Netherlands Antilles", NULL},
+ {"New Caledonia", NULL},
+ {"New Zealand", NULL},
+ {"Nicaragua", NULL},
+ {"Niger", NULL}, /* 0x80 */
+ {"Nigeria", NULL},
+ {"Norway", NULL},
+ {"Oman", NULL},
+ {"Pakistan", NULL},
+ {"Panama", NULL},
+ {"Papua New Guinea", vendor_86},
+ {"Paraguay", NULL},
+ {"Peru", NULL},
+ {"Philippines", NULL},
+ {"Poland (Republic of)", NULL},
+ {"Portugal", NULL},
+ {"Puerto Rico", NULL},
+ {"Qatar", NULL},
+ {"Romania", NULL},
+ {"Rwanda", NULL},
+ {"Saint Kitts and Nevis", NULL}, /* 0x90 */
+ {"Saint Croix", NULL},
+ {"Saint Helena and Ascension", NULL},
+ {"Saint Lucia", NULL},
+ {"San Marino", NULL},
+ {"Saint Thomas", NULL},
+ {"Sao Tome and Principe", NULL},
+ {"Saint Vincent and the Grenadines", NULL},
+ {"Saudi Arabia", NULL},
+ {"Senegal", NULL},
+ {"Seychelles", NULL},
+ {"Sierra Leone", NULL},
+ {"Singapore", NULL},
+ {"Solomon Islands", NULL},
+ {"Somalia", NULL},
+ {"South Africa", NULL},
+ {"Spain", NULL}, /* 0xA0 */
+ {"Sri Lanka", NULL},
+ {"Sudan", NULL},
+ {"Suriname", NULL},
+ {"Swaziland", NULL},
+ {"Sweden", NULL},
+ {"Switzerland", NULL},
+ {"Syria", NULL},
+ {"Tanzania", NULL},
+ {"Thailand", NULL},
+ {"Togo", NULL},
+ {"Tonga", NULL},
+ {"Trinidad and Tobago", NULL},
+ {"Tunisia", vendor_ad},
+ {"Turkey", NULL},
+ {"Turks and Caicos Islands", NULL},
+ {"Tuvalu", NULL}, /* 0xB0 */
+ {"Uganda", NULL},
+ {"Ukraine", NULL},
+ {"United Arab Emirates", NULL},
+ {"United Kingdom", vendor_b4},
+ {"United States", vendor_b5},
+ {"Burkina Faso", NULL},
+ {"Uruguay", NULL},
+ {"U.S.S.R.", NULL},
+ {"Vanuatu", NULL},
+ {"Vatican City State", NULL},
+ {"Venezuela", NULL},
+ {"Viet Nam", NULL},
+ {"Wallis and Futuna", NULL},
+ {"Western Samoa", NULL},
+ {"Yemen (Republic of)", NULL},
+ {"Yemen (Republic of)", NULL}, /* 0xC0 */
+ {"Yugoslavia", NULL},
+ {"Zaire", NULL},
+ {"Zambia", NULL},
+ {"Zimbabwe", NULL},
+ {"Slovakia", NULL},
+ {"Slovenia", NULL},
+ {NULL, NULL},
+ {NULL, NULL},
+ {NULL, NULL},
+ {NULL, NULL},
+ {NULL, NULL},
+ {NULL, NULL},
+ {NULL, NULL},
+ {NULL, NULL},
+ {NULL, NULL},
+ {NULL, NULL}, /* 0xD0 */
+ {NULL, NULL},
+ {NULL, NULL},
+ {NULL, NULL},
+ {NULL, NULL},
+ {NULL, NULL},
+ {NULL, NULL},
+ {NULL, NULL},
+ {NULL, NULL},
+ {NULL, NULL},
+ {NULL, NULL},
+ {NULL, NULL},
+ {NULL, NULL},
+ {NULL, NULL},
+ {NULL, NULL},
+ {NULL, NULL},
+ {NULL, NULL}, /* 0xE0 */
+ {NULL, NULL},
+ {NULL, NULL},
+ {NULL, NULL},
+ {NULL, NULL},
+ {NULL, NULL},
+ {NULL, NULL},
+ {NULL, NULL},
+ {NULL, NULL},
+ {NULL, NULL},
+ {NULL, NULL},
+ {NULL, NULL},
+ {NULL, NULL},
+ {NULL, NULL},
+ {NULL, NULL},
+ {NULL, NULL},
+ {NULL, NULL}, /* 0xF0 */
+ {NULL, NULL},
+ {NULL, NULL},
+ {NULL, NULL},
+ {NULL, NULL},
+ {NULL, NULL},
+ {NULL, NULL},
+ {"Lithuania", NULL},
+ {"Latvia", NULL},
+ {"Estonia", NULL},
+ {"US Virgin Islands", NULL},
+ {NULL, NULL},
+ {NULL, NULL},
+ {"(Universal)", NULL},
+ {"Taiwan", NULL}
+};
- /* Trying to find the longest printable ASCII sequence */
- for (p = (const char *) nsf + T35_VENDOR_ID_LEN, *end = p + nsf.length();
- p < end;
- p++)
+SPAN_DECLARE(int) t35_real_country_code(int country_code, int country_code_extension)
+{
+ if (country_code < 0 || country_code > 0xFF)
+ return -1;
+ if (country_code == 0xFF)
{
- if (isprint(*p))
- {
- if (!idSize++)
- id = p;
- if (idSize > maxIdSize)
- {
- max_id = id;
- max_id_size = idSize;
- }
- }
- else
- {
- id = NULL;
- id_size = 0;
- }
+ /* The extension code gives us the country. */
+ /* Right now there are no extension codes defined by the ITU */
+ return -1;
}
+ /* We need to apply realism over accuracy, though it blocks out some countries.
+ It is very rare to find a machine from any country but the following:
- /* Minimum acceptable id length */
- const int MinIdSize = 4;
+ Japan 0x00 (no confusion)
+ Germany 0x04 (0x20) (Canada/Germany confusion)
+ China 0x26 (0x64) (China/Lebanon confusion)
+ Korea 0x61 (0x86) (Korea/Papua New Guinea confusion)
+ UK 0xB4 (0x2D) (UK/Cyprus confusion)
+ USA 0xB5 (0xAD) (USA/Tunisia confusion)
+ France 0x3D (0xBC) (France/Vietnam confusion)
+
+ If we force the most likely of the two possible countries (forward or bit reversed),
+ the only mixup with any realistic probability is the Canada/Germany confusion. We
+ will just live with this, and force the more likely countries. */
+ switch (country_code)
+ {
+ case 0x20:
+ /* Force Germany */
+ case 0x2D:
+ /* Force UK */
+ case 0x64:
+ /* Force China */
+ case 0x86:
+ /* Force Korea */
+ case 0xAD:
+ /* Force USA */
+ case 0xBC:
+ /* Force France */
+ country_code = bit_reverse8(country_code);
+ break;
+ }
+ /* Try the country code at face value, then bit reversed */
+ if (t35_country_codes[country_code].name)
+ return country_code;
+ /* If the country code is missing, its most likely the country code is reversed. */
+ country_code = bit_reverse8(country_code);
+ if (t35_country_codes[country_code].name)
+ return country_code;
+ return -1;
+}
+/*- End of function --------------------------------------------------------*/
+
+SPAN_DECLARE(const char *) t35_real_country_code_to_str(int country_code, int country_code_extension)
+{
+ int real_code;
- if (maxIdSize >= min_id_size)
+ if ((real_code = t35_real_country_code(country_code, country_code_extension)) >= 0)
+ return t35_country_codes[real_code].name;
+ return NULL;
+}
+/*- End of function --------------------------------------------------------*/
+
+SPAN_DECLARE(const char *) t35_country_code_to_str(int country_code, int country_code_extension)
+{
+ if (country_code < 0 || country_code > 0xFF)
+ return NULL;
+ if (country_code == 0xFF)
{
- stationId.resize(0);
- const char *p;
- int dir;
+ /* The extension code gives us the country. */
+ /* Right now there are no extension codes defined by the ITU */
+ return NULL;
+ }
+
+ return t35_country_codes[country_code].name;
+}
+/*- End of function --------------------------------------------------------*/
- if (reverseOrder)
- {
- p = maxId + maxIdSize - 1;
- dir = -1;
- }
- else
- {
- p = maxId;
- dir = 1;
- }
- for (int i = 0; i < maxIdSize; i++)
+static const nsf_data_t *find_vendor(const uint8_t *msg, int len)
+{
+ const nsf_data_t *vendors;
+ const nsf_data_t *p;
+ int real_country_code;
+
+ if (msg[0] < 0 || msg[0] > 0xFF)
+ return NULL;
+ if (msg[0] == 0xFF)
+ {
+ /* The extension code gives us the country. */
+ /* Right now there are no extension codes defined by the ITU */
+ return NULL;
+ }
+ if ((real_country_code = t35_real_country_code(msg[0], msg[1])) < 0)
+ return NULL;
+ if ((vendors = t35_country_codes[msg[0]].vendors) == NULL)
+ return NULL;
+ for (p = vendors; p->vendor_id; p++)
+ {
+ if (len >= p->vendor_id_len
+ &&
+ memcmp(p->vendor_id, &msg[1], p->vendor_id_len) == 0)
{
- stationId.append(*p);
- p += dir;
+ return p;
}
- station_id_decoded = TRUE;
}
+ return NULL;
+}
+/*- End of function --------------------------------------------------------*/
+
+SPAN_DECLARE(const char *) t35_vendor_to_str(const uint8_t *msg, int len)
+{
+ const nsf_data_t *p;
+
+ if ((p = find_vendor(msg, len)) == NULL)
+ return NULL;
+ return p->vendor_name;
}
/*- End of function --------------------------------------------------------*/
-#endif
SPAN_DECLARE(int) t35_decode(const uint8_t *msg, int len, const char **country, const char **vendor, const char **model)
{
- int vendor_decoded;
const nsf_data_t *p;
const model_data_t *pp;
- vendor_decoded = FALSE;
if (country)
- *country = NULL;
+ *country = t35_real_country_code_to_str(msg[0], msg[1]);
if (vendor)
*vendor = NULL;
if (model)
*model = NULL;
- if (country)
- {
- /* We need to apply realism over accuracy, though it blocks out some countries.
- It is very rare to find a machine from any country but the following:
-
- Japan 0x00 (no confusion)
- Germany 0x04 (0x20) (Canada/Germany confusion)
- China 0x26 (0x64) (China/Lebanon confusion)
- Korea 0x61 (0x86) (Korea/Papua New Guinea confusion)
- UK 0xB4 (0x2D) (UK/Cyprus confusion)
- USA 0xB5 (0xAD) (USA/Tunisia confusion)
- France 0x3D (0xBC) (France/Vietnam confusion)
-
- If we force the most likely of the two possible countries (forward or bit reversed),
- the only mixup with any realistic probability is the Canada/Germany confusion. We
- will just live with this, and force the more likely countries. */
- switch (msg[0])
- {
- case 0x20:
- /* Force Germany */
- *country = t35_country_codes[0x04];
- break;
- case 0x64:
- /* Force China */
- *country = t35_country_codes[0x26];
- break;
- case 0x86:
- /* Force Korea */
- *country = t35_country_codes[0x61];
- break;
- case 0x2D:
- /* Force UK */
- *country = t35_country_codes[0xB4];
- break;
- case 0xAD:
- /* Force USA */
- *country = t35_country_codes[0xB5];
- break;
- case 0xBC:
- /* Force France */
- *country = t35_country_codes[0x3D];
- break;
- default:
- /* Try the country code at face value, then bit reversed */
- if (t35_country_codes[msg[0]])
- *country = t35_country_codes[msg[0]];
- else if (t35_country_codes[bit_reverse8(msg[0])])
- *country = t35_country_codes[bit_reverse8(msg[0])];
- break;
- }
- }
- for (p = known_nsf; p->vendor_id; p++)
+
+ if ((p = find_vendor(msg, len)) == NULL)
+ return FALSE;
+ if (vendor)
+ *vendor = p->vendor_name;
+ if (model && p->known_models)
{
- if (len >= p->vendor_id_len
- &&
- memcmp(p->vendor_id, msg, p->vendor_id_len) == 0)
+ for (pp = p->known_models; pp->model_id; pp++)
{
- if (p->vendor_name && vendor)
- *vendor = p->vendor_name;
- if (p->known_models && model)
+ if (len == 1 + p->vendor_id_len + pp->model_id_size
+ &&
+ memcmp(&msg[1 + p->vendor_id_len], pp->model_id, pp->model_id_size) == 0)
{
- for (pp = p->known_models; pp->model_id; pp++)
- {
- if (len == p->vendor_id_len + pp->model_id_size
- &&
- memcmp(pp->model_id, &msg[p->vendor_id_len], pp->model_id_size) == 0)
- {
- *model = pp->model_name;
- break;
- }
- }
+ *model = pp->model_name;
+ break;
}
-#if 0
- findStationId(p->inverse_station_id_order);
-#endif
- vendor_decoded = TRUE;
- break;
}
}
-#if 0
- if (!vendor_found())
- find_station_id(0);
-#endif
- return vendor_decoded;
+ return TRUE;
}
/*- End of function --------------------------------------------------------*/
/*- End of file ------------------------------------------------------------*/
{ 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)
}
/*- 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;
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)
- {
- span_log(&s->logging, SPAN_LOG_PROTOCOL_WARNING, "Rx %5d: Bad packet length - %d\n", log_seq_no, len);
- return -1;
- }
- if (s->check_sequence_numbers)
+ ptr = 0;
+ pkt_len = len;
+ switch (s->data_transport_protocol)
{
- seq_no &= 0xFFFF;
- if (seq_no != s->rx_expected_seq_no)
+ 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)
{
- /* An expected value of -1 indicates this is the first received packet, and will accept
- anything for that. We can't assume they will start from zero, even though they should. */
- if (s->rx_expected_seq_no != -1)
- {
- /* We have a packet with a serial number that is not in sequence. The cause could be:
- - 1. a repeat copy of a recent packet. Many T.38 implementations can preduce quite a lot of these.
- - 2. a late packet, whose point in the sequence we have already passed.
- - 3. the result of a hop in the sequence numbers cause by something weird from the other
- end. Stream switching might cause this
- - 4. missing packets.
-
- In cases 1 and 2 we need to drop this packet. In case 2 it might make sense to try to do
- something with it in the terminal case. Currently we don't. For gateway operation it will be
- too late to do anything useful.
- */
- if (((seq_no + 1) & 0xFFFF) == s->rx_expected_seq_no)
- {
- /* Assume this is truly a repeat packet, and don't bother checking its contents. */
- span_log(&s->logging, SPAN_LOG_FLOW, "Rx %5d: Repeat packet number\n", log_seq_no);
- return 0;
- }
- /* Distinguish between a little bit out of sequence, and a huge hop. */
- switch (classify_seq_no_offset(s->rx_expected_seq_no, seq_no))
- {
- case -1:
- /* This packet is in the near past, so its late. */
- span_log(&s->logging, SPAN_LOG_FLOW, "Rx %5d: Late packet - expected %d\n", log_seq_no, s->rx_expected_seq_no);
- return 0;
- case 1:
- /* This packet is in the near future, so some packets have been lost */
- span_log(&s->logging, SPAN_LOG_FLOW, "Rx %5d: Missing from %d\n", log_seq_no, s->rx_expected_seq_no);
- s->rx_missing_handler(s, s->rx_user_data, s->rx_expected_seq_no, seq_no);
- s->missing_packets += (seq_no - s->rx_expected_seq_no);
- break;
- default:
- /* The sequence has jumped wildly */
- span_log(&s->logging, SPAN_LOG_FLOW, "Rx %5d: Sequence restart\n", log_seq_no);
- s->rx_missing_handler(s, s->rx_user_data, -1, -1);
- s->missing_packets++;
- break;
- }
- }
- s->rx_expected_seq_no = seq_no;
+ /* 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;
}
- /* 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
- something properly, people ignore it. Developers in this industry truly deserves the ****
- **** **** **** **** **** documents they have to live with. Anyway, when the far end has a
- broken rollover behaviour we will get a hiccup at the rollover point. Don't worry too
- much. We will just treat the message in progress as one with some missing data. With any
- 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;
+ 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:
/* 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))
+ if ((buf[ptr] & 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 ((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
{
- 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;
+ 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);
s->current_rx_indicator = t30_indicator;
break;
case T38_TYPE_OF_MSG_T30_DATA:
- if ((buf[0] & 0x20))
+ if ((buf[ptr] & 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 ((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;
+ ptr += 2;
}
else
{
- t30_data = (buf[0] >> 1) & 0xF;
+ 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;
+ 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;
- }
+ 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 >= len)
- {
- span_log(&s->logging, SPAN_LOG_PROTOCOL_WARNING, "Rx %5d: Invalid length for data (D)\n", log_seq_no);
- return -1;
- }
+ 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. */
/* 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;
- }
+ 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)
{
/* 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;
- }
+ if ((ptr + 2) > pkt_len)
+ return ret;
numocts = ((buf[ptr] << 8) | buf[ptr + 1]) + 1;
msg = buf + ptr + 2;
ptr += numocts + 2;
numocts = 0;
msg = NULL;
}
- if (ptr > len)
+ 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)
{
- span_log(&s->logging, SPAN_LOG_PROTOCOL_WARNING, "Rx %5d: Invalid length for data (G)\n", log_seq_no);
- return -1;
+ /* 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,
s->current_rx_data_type = t30_data;
s->current_rx_field_type = t30_field_type;
}
- if (ptr != len)
+ /* 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;
+ if (seq_no != s->rx_expected_seq_no)
{
- if (s->t38_version != 0 || ptr != (len - 1) || !other_half)
+ /* An expected value of -1 indicates this is the first received packet, and will accept
+ anything for that. We can't assume they will start from zero, even though they should. */
+ if (s->rx_expected_seq_no != -1)
{
- 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;
+ /* We have a packet with a serial number that is not in sequence. The cause could be:
+ - 1. a repeat copy of a recent packet. Many T.38 implementations can preduce quite a lot of these.
+ - 2. a late packet, whose point in the sequence we have already passed.
+ - 3. the result of a hop in the sequence numbers cause by something weird from the other
+ end. Stream switching might cause this
+ - 4. missing packets.
+
+ In cases 1 and 2 we need to drop this packet. In case 2 it might make sense to try to do
+ something with it in the terminal case. Currently we don't. For gateway operation it will be
+ too late to do anything useful.
+ */
+ if (((seq_no + 1) & 0xFFFF) == s->rx_expected_seq_no)
+ {
+ /* Assume this is truly a repeat packet, and don't bother checking its contents. */
+ span_log(&s->logging, SPAN_LOG_FLOW, "Rx %5d: Repeat packet number\n", log_seq_no);
+ return 0;
+ }
+ /* Distinguish between a little bit out of sequence, and a huge hop. */
+ switch (classify_seq_no_offset(s->rx_expected_seq_no, seq_no))
+ {
+ case -1:
+ /* This packet is in the near past, so its late. */
+ span_log(&s->logging, SPAN_LOG_FLOW, "Rx %5d: Late packet - expected %d\n", log_seq_no, s->rx_expected_seq_no);
+ return 0;
+ case 1:
+ /* This packet is in the near future, so some packets have been lost */
+ span_log(&s->logging, SPAN_LOG_FLOW, "Rx %5d: Missing from %d\n", log_seq_no, s->rx_expected_seq_no);
+ s->rx_missing_handler(s, s->rx_user_data, s->rx_expected_seq_no, seq_no);
+ s->missing_packets += (seq_no - s->rx_expected_seq_no);
+ break;
+ default:
+ /* The sequence has jumped wildly */
+ span_log(&s->logging, SPAN_LOG_FLOW, "Rx %5d: Sequence restart\n", log_seq_no);
+ s->rx_missing_handler(s, s->rx_user_data, -1, -1);
+ s->missing_packets++;
+ break;
+ }
}
+ s->rx_expected_seq_no = seq_no;
}
- break;
+ }
+ 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
+ something properly, people ignore it. Developers in this industry truly deserves the ****
+ **** **** **** **** **** documents they have to live with. Anyway, when the far end has a
+ broken rollover behaviour we will get a hiccup at the rollover point. Don't worry too
+ much. We will just treat the message in progress as one with some missing data. With any
+ 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;
+
+ ptr = t38_core_rx_ifp_stream(s, buf, len, seq_no);
+ if (ptr != len)
+ {
+ 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;
}
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 --------------------------------------------------------*/
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;
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))
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;
}
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 --------------------------------------------------------*/
}
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;
}
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;
}
/*- 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;
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;
DISBIT8 = 0x80
};
-enum
-{
- T38_NONE,
- T38_V27TER_RX,
- T38_V29_RX,
- T38_V17_RX
-};
-
enum
{
HDLC_FLAG_FINISHED = 0x01,
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;
}
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
{
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;
}
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
{
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;
}
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
{
}
/*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:
}
/*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:
}
/*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:
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] =
{
/* 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)
/* 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
/* 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
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)
{
}
/*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)
{
}
/*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)
{
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*/
/* 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 --------------------------------------------------------*/
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);
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);
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;
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 "???";
}
#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
{
/* 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)
#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"
* 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)
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)
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 ------------------------------------------------------------*/
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 */
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) */
{
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);
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))
{
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);
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);
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);
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;
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;
}
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",
""
};
+ if (ref[msg_step][0] == '\0')
+ return;
if (strcmp(ref[msg_step], text))
{
printf(">>>: %s", ref[msg_step]);
}
/*- 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))
}
/*- 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;
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 */
fprintf(stderr, "Logged.\n");
else
fprintf(stderr, "Not logged.\n");
-
+
/* Test logging of buffer contents */
for (i = 0; i < 1000; i++)
buf[i] = i;
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++)
}
/* 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++)
{
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;
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);
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;
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);
}
}
- 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);
}
- 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);
}
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;