diff --git a/libs/spandsp/src/adsi.c b/libs/spandsp/src/adsi.c index 207c893e09..bbb4a71442 100644 --- a/libs/spandsp/src/adsi.c +++ b/libs/spandsp/src/adsi.c @@ -528,9 +528,11 @@ SPAN_DECLARE(void) adsi_tx_set_preamble(adsi_tx_state_t *s, } if (postamble_ones_len < 0) { +#if 0 if (s->standard == ADSI_STANDARD_JCLIP) s->postamble_ones_len = 5; else +#endif s->postamble_ones_len = 5; } else diff --git a/libs/spandsp/src/at_interpreter.c b/libs/spandsp/src/at_interpreter.c index bbb4a951ba..73625ef8d7 100644 --- a/libs/spandsp/src/at_interpreter.c +++ b/libs/spandsp/src/at_interpreter.c @@ -360,8 +360,11 @@ SPAN_DECLARE(void) at_display_call_info(at_state_t *s) while (call_id) { - snprintf(buf, sizeof(buf), "%s=%s", - call_id->id ? call_id->id : "NULL", call_id->value ? call_id->value : ""); + snprintf(buf, + sizeof(buf), + "%s=%s", + call_id->id ? call_id->id : "NULL", + call_id->value ? call_id->value : ""); at_put_response(s, buf); call_id = call_id->next; } @@ -845,7 +848,6 @@ static const char *at_cmd_D(at_state_t *s, const char *t) { int ok; char *u; - const char *w; char num[100 + 1]; char ch; @@ -858,7 +860,6 @@ static const char *at_cmd_D(at_state_t *s, const char *t) ok = FALSE; /* There are a numbers of options in a dial command string. Many are completely irrelevant in this application. */ - w = t; u = num; for ( ; (ch = *t); t++) { @@ -924,11 +925,13 @@ static const char *at_cmd_D(at_state_t *s, const char *t) case 'G': case 'g': /* GSM07.07 6.2 - Control the CUG supplementary service for this call */ + /* Uses index and info values set with command +CCUG. See +CCUG */ /* TODO: */ break; case 'I': case 'i': /* GSM07.07 6.2 - Override Calling Line Identification Restriction (CLIR) */ + /* I=invocation (restrict CLI presentation), i=suppression (allow CLI presentation). See +CLIR */ /* TODO: */ break; case ';': @@ -2326,6 +2329,10 @@ static const char *at_cmd_plus_CLIR(at_state_t *s, const char *t) { /* 3GPP TS 27.007 7.7 - Calling line identification restriction */ /* TODO: */ + /* Parameter sets the adjustment for outgoing calls: + 0 presentation indicator is used according to the subscription of the CLIR service + 1 CLIR invocation + 2 CLIR suppression */ t += 5; if (!parse_out(s, &t, NULL, 1, "+CLIR:", "")) return NULL; diff --git a/libs/spandsp/src/dds_int.c b/libs/spandsp/src/dds_int.c index df7a0a38cb..ad126f620a 100644 --- a/libs/spandsp/src/dds_int.c +++ b/libs/spandsp/src/dds_int.c @@ -42,146 +42,274 @@ #include "spandsp/complex.h" #include "spandsp/dds.h" -/* In a A-law or u-law channel, a 128 step sine table is adequate to keep the spectral +/* In a A-law or u-law channel, a fairly coarse step sine table is adequate to keep the spectral mess due to the DDS at a similar level to the spectral mess due to the A-law or u-law compression. */ -#define SLENK 7 +#define SLENK 8 #define DDS_STEPS (1 << SLENK) #define DDS_SHIFT (32 - 2 - SLENK) /* This is a simple set of direct digital synthesis (DDS) functions to generate sine - waves. This version uses a 128 entry sin/cos table to cover one quadrant. */ + waves. This version uses a 256 entry sin/cos table to cover one quadrant. */ static const int16_t sine_table[DDS_STEPS + 1] = { + 0, 201, + 402, 603, + 804, 1005, + 1206, 1407, + 1608, 1809, + 2009, 2210, + 2410, 2611, + 2811, 3012, + 3212, 3412, - 3812, - 4211, + 3612, + 3811, + 4011, + 4210, + 4410, 4609, + 4808, 5007, + 5205, 5404, + 5602, 5800, + 5998, 6195, + 6393, 6590, + 6786, 6983, - 7376, + 7179, + 7375, + 7571, 7767, + 7962, 8157, - 8546, + 8351, + 8545, + 8739, 8933, + 9126, 9319, + 9512, 9704, - 10088, + 9896, + 10087, + 10278, 10469, - 10850, + 10659, + 10849, + 11039, 11228, + 11417, 11605, + 11793, 11980, - 12354, + 12167, + 12353, + 12539, 12725, - 13095, - 13463, + 12910, + 13094, + 13279, + 13462, + 13645, 13828, - 14192, + 14010, + 14191, + 14372, 14553, + 14732, 14912, + 15090, 15269, - 15624, + 15446, + 15623, + 15800, 15976, - 16326, + 16151, + 16325, + 16499, 16673, + 16846, 17018, - 17361, + 17189, + 17360, + 17530, 17700, + 17869, 18037, - 18372, + 18204, + 18371, + 18537, 18703, + 18868, 19032, - 19358, - 19681, - 20001, - 20318, - 20632, - 20943, - 21251, - 21555, + 19195, + 19357, + 19519, + 19680, + 19841, + 20000, + 20159, + 20317, + 20475, + 20631, + 20787, + 20942, + 21096, + 21250, + 21403, + 21554, + 21705, 21856, + 22005, 22154, - 22449, - 22740, - 23028, - 23312, - 23593, + 22301, + 22448, + 22594, + 22739, + 22884, + 23027, + 23170, + 23311, + 23452, + 23592, + 23731, 23870, - 24144, - 24414, + 24007, + 24143, + 24279, + 24413, + 24547, 24680, - 24943, - 25202, - 25457, + 24811, + 24942, + 25072, + 25201, + 25329, + 25456, + 25582, 25708, - 25956, - 26199, - 26439, + 25832, + 25955, + 26077, + 26198, + 26319, + 26438, + 26556, 26674, - 26906, + 26790, + 26905, + 27019, 27133, - 27357, - 27576, - 27791, - 28002, - 28209, + 27245, + 27356, + 27466, + 27575, + 27683, + 27790, + 27896, + 28001, + 28105, + 28208, + 28310, 28411, - 28610, + 28510, + 28609, + 28706, 28803, - 28993, - 29178, - 29359, - 29535, - 29707, - 29875, - 30038, - 30196, - 30350, - 30499, - 30644, - 30784, - 30920, + 28898, + 28992, + 29085, + 29177, + 29268, + 29358, + 29447, + 29534, + 29621, + 29706, + 29791, + 29874, + 29956, + 30037, + 30117, + 30195, + 30273, + 30349, + 30424, + 30498, + 30571, + 30643, + 30714, + 30783, + 30852, + 30919, + 30985, 31050, - 31177, - 31298, - 31415, - 31527, - 31634, - 31737, - 31834, - 31927, - 32015, - 32099, - 32177, - 32251, - 32319, - 32383, - 32442, - 32496, - 32546, - 32590, - 32629, - 32664, - 32693, - 32718, - 32738, - 32753, - 32762, - 32767, + 31113, + 31176, + 31237, + 31297, + 31356, + 31414, + 31470, + 31526, + 31580, + 31633, + 31685, + 31736, + 31785, + 31833, + 31880, + 31926, + 31971, + 32014, + 32057, + 32098, + 32137, + 32176, + 32213, + 32250, + 32285, + 32318, + 32351, + 32382, + 32412, + 32441, + 32469, + 32495, + 32521, + 32545, + 32567, + 32589, + 32609, + 32628, + 32646, + 32663, + 32678, + 32692, + 32705, + 32717, + 32728, + 32737, + 32745, + 32752, + 32757, + 32761, + 32765, + 32766, 32767 }; diff --git a/libs/spandsp/src/dtmf.c b/libs/spandsp/src/dtmf.c index a0321c2030..35dc6c9dd1 100644 --- a/libs/spandsp/src/dtmf.c +++ b/libs/spandsp/src/dtmf.c @@ -224,11 +224,12 @@ SPAN_DECLARE(int) dtmf_rx(dtmf_rx_state_t *s, const int16_t amp[], int samples) total, row and coloumn power levels for detailed analysis of detection problems. */ span_log(&s->logging, SPAN_LOG_FLOW, - "Potentially '%c' - total %.2fdB, row %.2fdB, col %.2fdB - %s\n", + "Potentially '%c' - total %.2fdB, row %.2fdB, col %.2fdB, duration %d - %s\n", dtmf_positions[(best_row << 2) + best_col], log10f(s->energy)*10.0f - DTMF_POWER_OFFSET + DBM0_MAX_POWER, log10f(row_energy[best_row]/DTMF_TO_TOTAL_ENERGY)*10.0f - DTMF_POWER_OFFSET + DBM0_MAX_POWER, log10f(col_energy[best_col]/DTMF_TO_TOTAL_ENERGY)*10.0f - DTMF_POWER_OFFSET + DBM0_MAX_POWER, + s->duration, (hit) ? "hit" : "miss"); } } @@ -315,6 +316,28 @@ SPAN_DECLARE(int) dtmf_rx(dtmf_rx_state_t *s, const int16_t amp[], int samples) } /*- End of function --------------------------------------------------------*/ +SPAN_DECLARE(int) dtmf_rx_fillin(dtmf_rx_state_t *s, int samples) +{ + int i; + + /* Restart any Goertzel and energy gathering operation we might be in the middle of. */ + for (i = 0; i < 4; i++) + { + goertzel_reset(&s->row_out[i]); + goertzel_reset(&s->col_out[i]); + } +#if defined(SPANDSP_USE_FIXED_POINT) + s->energy = 0; +#else + s->energy = 0.0f; +#endif + s->current_sample = 0; + /* Don't update the hit detection. Pretend it never happened. */ + /* TODO: Surely we can be a cleverer than this. */ + return 0; +} +/*- End of function --------------------------------------------------------*/ + SPAN_DECLARE(int) dtmf_rx_status(dtmf_rx_state_t *s) { if (s->in_digit) diff --git a/libs/spandsp/src/fax.c b/libs/spandsp/src/fax.c index 422315f2d0..c5422e7a52 100644 --- a/libs/spandsp/src/fax.c +++ b/libs/spandsp/src/fax.c @@ -183,14 +183,14 @@ static void set_rx_handler(fax_state_t *s, } /*- End of function --------------------------------------------------------*/ -static void set_tx_handler(fax_state_t *s, span_tx_handler_t *handler, void *user_data) +static void fax_modems_set_tx_handler(fax_state_t *s, span_tx_handler_t *handler, void *user_data) { s->modems.tx_handler = handler; s->modems.tx_user_data = user_data; } /*- End of function --------------------------------------------------------*/ -static void set_next_tx_handler(fax_state_t *s, span_tx_handler_t *handler, void *user_data) +static void fax_modems_set_next_tx_handler(fax_state_t *s, span_tx_handler_t *handler, void *user_data) { s->modems.next_tx_handler = handler; s->modems.next_tx_user_data = user_data; @@ -204,13 +204,12 @@ static int v17_v21_rx(void *user_data, const int16_t amp[], int len) t = (fax_state_t *) user_data; s = &t->modems; - v17_rx(&s->v17_rx, amp, len); + v17_rx(&s->fast_modems.v17_rx, amp, len); if (t->t30.rx_trained) { - /* The fast modem has trained, so we no longer need to run the slow - one in parallel. */ - span_log(&t->logging, SPAN_LOG_FLOW, "Switching from V.17 + V.21 to V.17 (%.2fdBm0)\n", v17_rx_signal_power(&s->v17_rx)); - set_rx_handler(t, (span_rx_handler_t *) &v17_rx, (span_rx_fillin_handler_t *) &v17_rx_fillin, &s->v17_rx); + /* The fast modem has trained, so we no longer need to run the slow one in parallel. */ + span_log(&t->logging, SPAN_LOG_FLOW, "Switching from V.17 + V.21 to V.17 (%.2fdBm0)\n", v17_rx_signal_power(&s->fast_modems.v17_rx)); + set_rx_handler(t, (span_rx_handler_t *) &v17_rx, (span_rx_fillin_handler_t *) &v17_rx_fillin, &s->fast_modems.v17_rx); } else { @@ -234,7 +233,7 @@ static int v17_v21_rx_fillin(void *user_data, int len) t = (fax_state_t *) user_data; s = &t->modems; - v17_rx_fillin(&s->v17_rx, len); + v17_rx_fillin(&s->fast_modems.v17_rx, len); fsk_rx_fillin(&s->v21_rx, len); return 0; } @@ -247,13 +246,12 @@ static int v27ter_v21_rx(void *user_data, const int16_t amp[], int len) t = (fax_state_t *) user_data; s = &t->modems; - v27ter_rx(&s->v27ter_rx, amp, len); + v27ter_rx(&s->fast_modems.v27ter_rx, amp, len); if (t->t30.rx_trained) { - /* The fast modem has trained, so we no longer need to run the slow - one in parallel. */ - span_log(&t->logging, SPAN_LOG_FLOW, "Switching from V.27ter + V.21 to V.27ter (%.2fdBm0)\n", v27ter_rx_signal_power(&s->v27ter_rx)); - set_rx_handler(t, (span_rx_handler_t *) &v27ter_rx, (span_rx_fillin_handler_t *) &v27ter_rx_fillin, &s->v27ter_rx); + /* The fast modem has trained, so we no longer need to run the slow one in parallel. */ + span_log(&t->logging, SPAN_LOG_FLOW, "Switching from V.27ter + V.21 to V.27ter (%.2fdBm0)\n", v27ter_rx_signal_power(&s->fast_modems.v27ter_rx)); + set_rx_handler(t, (span_rx_handler_t *) &v27ter_rx, (span_rx_fillin_handler_t *) &v27ter_rx_fillin, &s->fast_modems.v27ter_rx); } else { @@ -277,7 +275,7 @@ static int v27ter_v21_rx_fillin(void *user_data, int len) t = (fax_state_t *) user_data; s = &t->modems; - v27ter_rx_fillin(&s->v27ter_rx, len); + v27ter_rx_fillin(&s->fast_modems.v27ter_rx, len); fsk_rx_fillin(&s->v21_rx, len); return 0; } @@ -290,13 +288,12 @@ static int v29_v21_rx(void *user_data, const int16_t amp[], int len) t = (fax_state_t *) user_data; s = &t->modems; - v29_rx(&s->v29_rx, amp, len); + v29_rx(&s->fast_modems.v29_rx, amp, len); if (t->t30.rx_trained) { - /* The fast modem has trained, so we no longer need to run the slow - one in parallel. */ - span_log(&t->logging, SPAN_LOG_FLOW, "Switching from V.29 + V.21 to V.29 (%.2fdBm0)\n", v29_rx_signal_power(&s->v29_rx)); - set_rx_handler(t, (span_rx_handler_t *) &v29_rx, (span_rx_fillin_handler_t *) &v29_rx_fillin, &s->v29_rx); + /* The fast modem has trained, so we no longer need to run the slow one in parallel. */ + span_log(&t->logging, SPAN_LOG_FLOW, "Switching from V.29 + V.21 to V.29 (%.2fdBm0)\n", v29_rx_signal_power(&s->fast_modems.v29_rx)); + set_rx_handler(t, (span_rx_handler_t *) &v29_rx, (span_rx_fillin_handler_t *) &v29_rx_fillin, &s->fast_modems.v29_rx); } else { @@ -320,7 +317,7 @@ static int v29_v21_rx_fillin(void *user_data, int len) t = (fax_state_t *) user_data; s = &t->modems; - v29_rx_fillin(&s->v29_rx, len); + v29_rx_fillin(&s->fast_modems.v29_rx, len); fsk_rx_fillin(&s->v21_rx, len); return 0; } @@ -377,14 +374,14 @@ static int set_next_tx_type(fax_state_t *s) t = &s->modems; if (t->next_tx_handler) { - set_tx_handler(s, t->next_tx_handler, t->next_tx_user_data); + fax_modems_set_tx_handler(s, t->next_tx_handler, t->next_tx_user_data); t->next_tx_handler = NULL; return 0; } /* If there is nothing else to change to, so use zero length silence */ silence_gen_alter(&t->silence_gen, 0); - set_tx_handler(s, (span_tx_handler_t *) &silence_gen, &t->silence_gen); - set_next_tx_handler(s, (span_tx_handler_t *) NULL, NULL); + fax_modems_set_tx_handler(s, (span_tx_handler_t *) &silence_gen, &t->silence_gen); + fax_modems_set_next_tx_handler(s, (span_tx_handler_t *) NULL, NULL); t->transmit = FALSE; return -1; } @@ -472,18 +469,18 @@ static void fax_set_rx_type(void *user_data, int type, int bit_rate, int short_t set_rx_handler(s, (span_rx_handler_t *) &fsk_rx, (span_rx_fillin_handler_t *) &fsk_rx_fillin, &t->v21_rx); break; case T30_MODEM_V27TER: - v27ter_rx_restart(&t->v27ter_rx, bit_rate, FALSE); - v27ter_rx_set_put_bit(&t->v27ter_rx, put_bit_func, put_bit_user_data); + v27ter_rx_restart(&t->fast_modems.v27ter_rx, bit_rate, FALSE); + v27ter_rx_set_put_bit(&t->fast_modems.v27ter_rx, put_bit_func, put_bit_user_data); set_rx_handler(s, &v27ter_v21_rx, &v27ter_v21_rx_fillin, s); break; case T30_MODEM_V29: - v29_rx_restart(&t->v29_rx, bit_rate, FALSE); - v29_rx_set_put_bit(&t->v29_rx, put_bit_func, put_bit_user_data); + v29_rx_restart(&t->fast_modems.v29_rx, bit_rate, FALSE); + v29_rx_set_put_bit(&t->fast_modems.v29_rx, put_bit_func, put_bit_user_data); set_rx_handler(s, &v29_v21_rx, &v29_v21_rx_fillin, s); break; case T30_MODEM_V17: - v17_rx_restart(&t->v17_rx, bit_rate, short_train); - v17_rx_set_put_bit(&t->v17_rx, put_bit_func, put_bit_user_data); + v17_rx_restart(&t->fast_modems.v17_rx, bit_rate, short_train); + v17_rx_set_put_bit(&t->fast_modems.v17_rx, put_bit_func, put_bit_user_data); set_rx_handler(s, &v17_v21_rx, &v17_v21_rx_fillin, s); break; case T30_MODEM_DONE: @@ -522,8 +519,8 @@ static void fax_set_tx_type(void *user_data, int type, int bit_rate, int short_t { case T30_MODEM_PAUSE: silence_gen_alter(&t->silence_gen, ms_to_samples(short_train)); - set_tx_handler(s, (span_tx_handler_t *) &silence_gen, &t->silence_gen); - set_next_tx_handler(s, (span_tx_handler_t *) NULL, NULL); + fax_modems_set_tx_handler(s, (span_tx_handler_t *) &silence_gen, &t->silence_gen); + fax_modems_set_next_tx_handler(s, (span_tx_handler_t *) NULL, NULL); t->transmit = TRUE; break; case T30_MODEM_CED: @@ -533,8 +530,8 @@ static void fax_set_tx_type(void *user_data, int type, int bit_rate, int short_t else tone = MODEM_CONNECT_TONES_FAX_CNG; modem_connect_tones_tx_init(&t->connect_tx, tone); - set_tx_handler(s, (span_tx_handler_t *) &modem_connect_tones_tx, &t->connect_tx); - set_next_tx_handler(s, (span_tx_handler_t *) NULL, NULL); + fax_modems_set_tx_handler(s, (span_tx_handler_t *) &modem_connect_tones_tx, &t->connect_tx); + fax_modems_set_next_tx_handler(s, (span_tx_handler_t *) NULL, NULL); t->transmit = TRUE; break; case T30_MODEM_V21: @@ -546,38 +543,38 @@ static void fax_set_tx_type(void *user_data, int type, int bit_rate, int short_t a 75ms gap before any V.21 transmission is harmless, adds little to the overall length of a call, and ensures the receiving end is ready. */ silence_gen_alter(&t->silence_gen, ms_to_samples(75)); - set_tx_handler(s, (span_tx_handler_t *) &silence_gen, &t->silence_gen); - set_next_tx_handler(s, (span_tx_handler_t *) &fsk_tx, &t->v21_tx); + fax_modems_set_tx_handler(s, (span_tx_handler_t *) &silence_gen, &t->silence_gen); + fax_modems_set_next_tx_handler(s, (span_tx_handler_t *) &fsk_tx, &t->v21_tx); t->transmit = TRUE; break; case T30_MODEM_V27TER: silence_gen_alter(&t->silence_gen, ms_to_samples(75)); /* For any fast modem, set 200ms of preamble flags */ hdlc_tx_flags(&t->hdlc_tx, bit_rate/(8*5)); - v27ter_tx_restart(&t->v27ter_tx, bit_rate, t->use_tep); - v27ter_tx_set_get_bit(&t->v27ter_tx, get_bit_func, get_bit_user_data); - set_tx_handler(s, (span_tx_handler_t *) &silence_gen, &t->silence_gen); - set_next_tx_handler(s, (span_tx_handler_t *) &v27ter_tx, &t->v27ter_tx); + v27ter_tx_restart(&t->fast_modems.v27ter_tx, bit_rate, t->use_tep); + v27ter_tx_set_get_bit(&t->fast_modems.v27ter_tx, get_bit_func, get_bit_user_data); + fax_modems_set_tx_handler(s, (span_tx_handler_t *) &silence_gen, &t->silence_gen); + fax_modems_set_next_tx_handler(s, (span_tx_handler_t *) &v27ter_tx, &t->fast_modems.v27ter_tx); t->transmit = TRUE; break; case T30_MODEM_V29: silence_gen_alter(&t->silence_gen, ms_to_samples(75)); /* For any fast modem, set 200ms of preamble flags */ hdlc_tx_flags(&t->hdlc_tx, bit_rate/(8*5)); - v29_tx_restart(&t->v29_tx, bit_rate, t->use_tep); - v29_tx_set_get_bit(&t->v29_tx, get_bit_func, get_bit_user_data); - set_tx_handler(s, (span_tx_handler_t *) &silence_gen, &t->silence_gen); - set_next_tx_handler(s, (span_tx_handler_t *) &v29_tx, &t->v29_tx); + v29_tx_restart(&t->fast_modems.v29_tx, bit_rate, t->use_tep); + v29_tx_set_get_bit(&t->fast_modems.v29_tx, get_bit_func, get_bit_user_data); + fax_modems_set_tx_handler(s, (span_tx_handler_t *) &silence_gen, &t->silence_gen); + fax_modems_set_next_tx_handler(s, (span_tx_handler_t *) &v29_tx, &t->fast_modems.v29_tx); t->transmit = TRUE; break; case T30_MODEM_V17: silence_gen_alter(&t->silence_gen, ms_to_samples(75)); /* For any fast modem, set 200ms of preamble flags */ hdlc_tx_flags(&t->hdlc_tx, bit_rate/(8*5)); - v17_tx_restart(&t->v17_tx, bit_rate, t->use_tep, short_train); - v17_tx_set_get_bit(&t->v17_tx, get_bit_func, get_bit_user_data); - set_tx_handler(s, (span_tx_handler_t *) &silence_gen, &t->silence_gen); - set_next_tx_handler(s, (span_tx_handler_t *) &v17_tx, &t->v17_tx); + v17_tx_restart(&t->fast_modems.v17_tx, bit_rate, t->use_tep, short_train); + v17_tx_set_get_bit(&t->fast_modems.v17_tx, get_bit_func, get_bit_user_data); + fax_modems_set_tx_handler(s, (span_tx_handler_t *) &silence_gen, &t->silence_gen); + fax_modems_set_next_tx_handler(s, (span_tx_handler_t *) &v17_tx, &t->fast_modems.v17_tx); t->transmit = TRUE; break; case T30_MODEM_DONE: @@ -585,8 +582,8 @@ static void fax_set_tx_type(void *user_data, int type, int bit_rate, int short_t /* Fall through */ default: silence_gen_alter(&t->silence_gen, 0); - set_tx_handler(s, (span_tx_handler_t *) &silence_gen, &t->silence_gen); - set_next_tx_handler(s, (span_tx_handler_t *) NULL, NULL); + fax_modems_set_tx_handler(s, (span_tx_handler_t *) &silence_gen, &t->silence_gen); + fax_modems_set_next_tx_handler(s, (span_tx_handler_t *) NULL, NULL); t->transmit = FALSE; break; } diff --git a/libs/spandsp/src/fax_modems.c b/libs/spandsp/src/fax_modems.c index 29392be1a4..cad8594592 100644 --- a/libs/spandsp/src/fax_modems.c +++ b/libs/spandsp/src/fax_modems.c @@ -91,7 +91,7 @@ SPAN_DECLARE_NONSTD(int) fax_modems_v17_v21_rx(void *user_data, const int16_t am fax_modems_state_t *s; s = (fax_modems_state_t *) user_data; - v17_rx(&s->v17_rx, amp, len); + v17_rx(&s->fast_modems.v17_rx, amp, len); fsk_rx(&s->v21_rx, amp, len); if (s->rx_frame_received) { @@ -111,7 +111,7 @@ SPAN_DECLARE_NONSTD(int) fax_modems_v17_v21_rx_fillin(void *user_data, int len) fax_modems_state_t *s; s = (fax_modems_state_t *) user_data; - v17_rx_fillin(&s->v17_rx, len); + v17_rx_fillin(&s->fast_modems.v17_rx, len); fsk_rx_fillin(&s->v21_rx, len); return 0; } @@ -122,7 +122,7 @@ SPAN_DECLARE_NONSTD(int) fax_modems_v27ter_v21_rx(void *user_data, const int16_t fax_modems_state_t *s; s = (fax_modems_state_t *) user_data; - v27ter_rx(&s->v27ter_rx, amp, len); + v27ter_rx(&s->fast_modems.v27ter_rx, amp, len); fsk_rx(&s->v21_rx, amp, len); if (s->rx_frame_received) { @@ -142,7 +142,7 @@ SPAN_DECLARE_NONSTD(int) fax_modems_v27ter_v21_rx_fillin(void *user_data, int le fax_modems_state_t *s; s = (fax_modems_state_t *) user_data; - v27ter_rx_fillin(&s->v27ter_rx, len); + v27ter_rx_fillin(&s->fast_modems.v27ter_rx, len); fsk_rx_fillin(&s->v21_rx, len); return 0; } @@ -153,7 +153,7 @@ SPAN_DECLARE_NONSTD(int) fax_modems_v29_v21_rx(void *user_data, const int16_t am fax_modems_state_t *s; s = (fax_modems_state_t *) user_data; - v29_rx(&s->v29_rx, amp, len); + v29_rx(&s->fast_modems.v29_rx, amp, len); fsk_rx(&s->v21_rx, amp, len); if (s->rx_frame_received) { @@ -173,7 +173,7 @@ SPAN_DECLARE_NONSTD(int) fax_modems_v29_v21_rx_fillin(void *user_data, int len) fax_modems_state_t *s; s = (fax_modems_state_t *) user_data; - v29_rx_fillin(&s->v29_rx, len); + v29_rx_fillin(&s->fast_modems.v29_rx, len); fsk_rx_fillin(&s->v21_rx, len); return 0; } @@ -195,10 +195,10 @@ static void v17_rx_status_handler(void *user_data, int status) switch (status) { case SIG_STATUS_TRAINING_SUCCEEDED: - span_log(&s->logging, SPAN_LOG_FLOW, "Switching to V.17 (%.2fdBm0)\n", v17_rx_signal_power(&s->v17_rx)); + span_log(&s->logging, SPAN_LOG_FLOW, "Switching to V.17 (%.2fdBm0)\n", v17_rx_signal_power(&s->fast_modems.v17_rx)); s->rx_handler = (span_rx_handler_t *) &v17_rx; s->rx_fillin_handler = (span_rx_fillin_handler_t *) &v17_rx_fillin; - s->rx_user_data = &s->v17_rx; + s->rx_user_data = &s->fast_modems.v17_rx; break; } } @@ -212,10 +212,10 @@ static void v27ter_rx_status_handler(void *user_data, int status) switch (status) { case SIG_STATUS_TRAINING_SUCCEEDED: - span_log(&s->logging, SPAN_LOG_FLOW, "Switching to V.27ter (%.2fdBm0)\n", v27ter_rx_signal_power(&s->v27ter_rx)); + span_log(&s->logging, SPAN_LOG_FLOW, "Switching to V.27ter (%.2fdBm0)\n", v27ter_rx_signal_power(&s->fast_modems.v27ter_rx)); s->rx_handler = (span_rx_handler_t *) &v27ter_rx; s->rx_fillin_handler = (span_rx_fillin_handler_t *) &v27ter_rx_fillin; - s->rx_user_data = &s->v27ter_rx; + s->rx_user_data = &s->fast_modems.v27ter_rx; break; } } @@ -229,10 +229,10 @@ static void v29_rx_status_handler(void *user_data, int status) switch (status) { case SIG_STATUS_TRAINING_SUCCEEDED: - span_log(&s->logging, SPAN_LOG_FLOW, "Switching to V.29 (%.2fdBm0)\n", v29_rx_signal_power(&s->v29_rx)); + span_log(&s->logging, SPAN_LOG_FLOW, "Switching to V.29 (%.2fdBm0)\n", v29_rx_signal_power(&s->fast_modems.v29_rx)); s->rx_handler = (span_rx_handler_t *) &v29_rx; s->rx_fillin_handler = (span_rx_fillin_handler_t *) &v29_rx_fillin; - s->rx_user_data = &s->v29_rx; + s->rx_user_data = &s->fast_modems.v29_rx; break; } } @@ -243,13 +243,13 @@ SPAN_DECLARE(void) fax_modems_start_rx_modem(fax_modems_state_t *s, int which) switch (which) { case FAX_MODEM_V17_RX: - v17_rx_set_modem_status_handler(&s->v17_rx, v17_rx_status_handler, s); + v17_rx_set_modem_status_handler(&s->fast_modems.v17_rx, v17_rx_status_handler, s); break; case FAX_MODEM_V27TER_RX: - v27ter_rx_set_modem_status_handler(&s->v27ter_rx, v27ter_rx_status_handler, s); + v27ter_rx_set_modem_status_handler(&s->fast_modems.v27ter_rx, v27ter_rx_status_handler, s); break; case FAX_MODEM_V29_RX: - v29_rx_set_modem_status_handler(&s->v29_rx, v29_rx_status_handler, s); + v29_rx_set_modem_status_handler(&s->fast_modems.v29_rx, v29_rx_status_handler, s); break; } fsk_rx_set_modem_status_handler(&s->v21_rx, v21_rx_status_handler, s); @@ -262,6 +262,12 @@ SPAN_DECLARE(void) fax_modems_set_tep_mode(fax_modems_state_t *s, int use_tep) } /*- End of function --------------------------------------------------------*/ +SPAN_DECLARE(logging_state_t *) fax_modems_get_logging_state(fax_modems_state_t *s) +{ + return &s->logging; +} +/*- End of function --------------------------------------------------------*/ + SPAN_DECLARE(int) fax_modems_restart(fax_modems_state_t *s) { return 0; @@ -290,13 +296,13 @@ SPAN_DECLARE(fax_modems_state_t *) fax_modems_init(fax_modems_state_t *s, fsk_rx_init(&s->v21_rx, &preset_fsk_specs[FSK_V21CH2], FSK_FRAME_MODE_SYNC, (put_bit_func_t) hdlc_rx_put_bit, &s->hdlc_rx); fsk_rx_signal_cutoff(&s->v21_rx, -39.09f); fsk_tx_init(&s->v21_tx, &preset_fsk_specs[FSK_V21CH2], (get_bit_func_t) hdlc_tx_get_bit, &s->hdlc_tx); - v17_rx_init(&s->v17_rx, 14400, non_ecm_put_bit, user_data); - v17_tx_init(&s->v17_tx, 14400, s->use_tep, non_ecm_get_bit, user_data); - v29_rx_init(&s->v29_rx, 9600, non_ecm_put_bit, user_data); - v29_rx_signal_cutoff(&s->v29_rx, -45.5f); - v29_tx_init(&s->v29_tx, 9600, s->use_tep, non_ecm_get_bit, user_data); - v27ter_rx_init(&s->v27ter_rx, 4800, non_ecm_put_bit, user_data); - v27ter_tx_init(&s->v27ter_tx, 4800, s->use_tep, non_ecm_get_bit, user_data); + v17_rx_init(&s->fast_modems.v17_rx, 14400, non_ecm_put_bit, user_data); + v17_tx_init(&s->fast_modems.v17_tx, 14400, s->use_tep, non_ecm_get_bit, user_data); + v29_rx_init(&s->fast_modems.v29_rx, 9600, non_ecm_put_bit, user_data); + v29_rx_signal_cutoff(&s->fast_modems.v29_rx, -45.5f); + v29_tx_init(&s->fast_modems.v29_tx, 9600, s->use_tep, non_ecm_get_bit, user_data); + v27ter_rx_init(&s->fast_modems.v27ter_rx, 4800, non_ecm_put_bit, user_data); + v27ter_tx_init(&s->fast_modems.v27ter_tx, 4800, s->use_tep, non_ecm_get_bit, user_data); silence_gen_init(&s->silence_gen, 0); modem_connect_tones_tx_init(&s->connect_tx, MODEM_CONNECT_TONES_FAX_CNG); if (tone_callback) diff --git a/libs/spandsp/src/logging.c b/libs/spandsp/src/logging.c index 726e7bd322..589a746106 100644 --- a/libs/spandsp/src/logging.c +++ b/libs/spandsp/src/logging.c @@ -46,10 +46,10 @@ #include "spandsp/private/logging.h" -static void default_message_handler(int level, const char *text); +static void default_message_handler(void *user_data, int level, const char *text); static message_handler_func_t __span_message = &default_message_handler; -static error_handler_func_t __span_error = NULL; +static void *__user_data = NULL; /* Note that this list *must* match the enum definition in logging.h */ static const char *severities[] = @@ -67,7 +67,7 @@ static const char *severities[] = "DEBUG 3" }; -static void default_message_handler(int level, const char *text) +static void default_message_handler(void *user_data, int level, const char *text) { fprintf(stderr, "%s", text); } @@ -138,14 +138,10 @@ SPAN_DECLARE(int) span_log(logging_state_t *s, int level, const char *format, .. } /*endif*/ len += vsnprintf(msg + len, 1024 - len, format, arg_ptr); - if (s->span_error && level == SPAN_LOG_ERROR) - s->span_error(msg); - else if (__span_error && level == SPAN_LOG_ERROR) - __span_error(msg); - else if (s->span_message) - s->span_message(level, msg); + if (s->span_message) + s->span_message(s->user_data, level, msg); else if (__span_message) - __span_message(level, msg); + __span_message(s->user_data, level, msg); /*endif*/ va_end(arg_ptr); return 1; @@ -215,27 +211,17 @@ SPAN_DECLARE(int) span_log_bump_samples(logging_state_t *s, int samples) } /*- End of function --------------------------------------------------------*/ -SPAN_DECLARE(void) span_log_set_message_handler(logging_state_t *s, message_handler_func_t func) +SPAN_DECLARE(void) span_log_set_message_handler(logging_state_t *s, message_handler_func_t func, void *user_data) { s->span_message = func; + s->user_data = user_data; } /*- End of function --------------------------------------------------------*/ -SPAN_DECLARE(void) span_log_set_error_handler(logging_state_t *s, error_handler_func_t func) -{ - s->span_error = func; -} -/*- End of function --------------------------------------------------------*/ - -SPAN_DECLARE(void) span_set_message_handler(message_handler_func_t func) +SPAN_DECLARE(void) span_set_message_handler(message_handler_func_t func, void *user_data) { __span_message = func; -} -/*- End of function --------------------------------------------------------*/ - -SPAN_DECLARE(void) span_set_error_handler(error_handler_func_t func) -{ - __span_error = func; + __user_data = user_data; } /*- End of function --------------------------------------------------------*/ @@ -246,7 +232,6 @@ SPAN_DECLARE(logging_state_t *) span_log_init(logging_state_t *s, int level, con if ((s = (logging_state_t *) malloc(sizeof(*s))) == NULL) return NULL; } - s->span_error = __span_error; s->span_message = __span_message; s->level = level; s->tag = tag; diff --git a/libs/spandsp/src/lpc10_analyse.c b/libs/spandsp/src/lpc10_analyse.c index 7c852c4e12..0e9341fa04 100644 --- a/libs/spandsp/src/lpc10_analyse.c +++ b/libs/spandsp/src/lpc10_analyse.c @@ -203,7 +203,6 @@ static void dynamic_pitch_tracking(lpc10_encode_state_t *s, { int32_t pbar; float sbar; - int32_t path[2]; int32_t i; int32_t j; float alpha; @@ -292,10 +291,7 @@ static void dynamic_pitch_tracking(lpc10_encode_state_t *s, /* TRACE: look back two frames to find minimum cost pitch estimate */ *pitch = *midx; for (i = 0, j = s->ipoint; i < 2; i++, j++) - { *pitch = s->p[j & 1][*pitch - 1]; - path[i] = *pitch; - } /* The following statement subtracts one from IPOINT, mod DEPTH. I */ /* think the author chose to add DEPTH-1, instead of subtracting 1, */ diff --git a/libs/spandsp/src/plc.c b/libs/spandsp/src/plc.c index 392a7b01a6..3d07417f68 100644 --- a/libs/spandsp/src/plc.c +++ b/libs/spandsp/src/plc.c @@ -165,10 +165,8 @@ SPAN_DECLARE(int) plc_fillin(plc_state_t *s, int16_t amp[], int len) float old_weight; float new_weight; float gain; - //int16_t *orig_amp; int orig_len; - //orig_amp = amp; orig_len = len; if (s->missing_samples == 0) { diff --git a/libs/spandsp/src/queue.c b/libs/spandsp/src/queue.c index 51774a1810..7430aa4100 100644 --- a/libs/spandsp/src/queue.c +++ b/libs/spandsp/src/queue.c @@ -188,7 +188,6 @@ SPAN_DECLARE(int) queue_read(queue_state_t *s, uint8_t *buf, int len) SPAN_DECLARE(int) queue_read_byte(queue_state_t *s) { int real_len; - int to_end; int iptr; int optr; int byte; @@ -202,7 +201,6 @@ SPAN_DECLARE(int) queue_read_byte(queue_state_t *s) if (real_len < 1) return -1; /*endif*/ - to_end = s->len - optr; byte = s->data[optr]; if (++optr >= s->len) optr = 0; diff --git a/libs/spandsp/src/sig_tone.c b/libs/spandsp/src/sig_tone.c index 99b0444023..6aaecdb211 100644 --- a/libs/spandsp/src/sig_tone.c +++ b/libs/spandsp/src/sig_tone.c @@ -31,7 +31,6 @@ #endif #include -#include #include #if defined(HAVE_TGMATH_H) #include @@ -648,9 +647,9 @@ SPAN_DECLARE(sig_tone_rx_state_t *) sig_tone_rx_init(sig_tone_rx_state_t *s, int } memset(s, 0, sizeof(*s)); #if !defined(SPANDSP_USE_FIXED_POINT) - for (i = 0; i < 3; i++) + for (j = 0; j < 2; j++) { - for (j = 0; j < 2; j++) + for (i = 0; i < 3; i++) { s->tone[j].notch_z1[i] = 0.0f; s->tone[j].notch_z2[i] = 0.0f; diff --git a/libs/spandsp/src/spandsp/async.h b/libs/spandsp/src/spandsp/async.h index e0124e55c2..4324264042 100644 --- a/libs/spandsp/src/spandsp/async.h +++ b/libs/spandsp/src/spandsp/async.h @@ -107,19 +107,12 @@ typedef void (*put_bit_func_t)(void *user_data, int bit); /*! Bit get function for data pumps */ typedef int (*get_bit_func_t)(void *user_data); +#define modem_rx_status_func_t modem_status_func_t +#define modem_tx_status_func_t modem_status_func_t + /*! Status change callback function for data pumps */ typedef void (*modem_status_func_t)(void *user_data, int status); -enum -{ - /*! No parity bit should be used */ - ASYNC_PARITY_NONE = 0, - /*! An even parity bit will exist, after the data bits */ - ASYNC_PARITY_EVEN, - /*! An odd parity bit will exist, after the data bits */ - ASYNC_PARITY_ODD -}; - /*! Asynchronous data transmit descriptor. This defines the state of a single working instance of a byte to asynchronous serial converter, for use @@ -134,6 +127,16 @@ typedef struct async_tx_state_s async_tx_state_t; */ typedef struct async_rx_state_s async_rx_state_t; +enum +{ + /*! No parity bit should be used */ + ASYNC_PARITY_NONE = 0, + /*! An even parity bit will exist, after the data bits */ + ASYNC_PARITY_EVEN, + /*! An odd parity bit will exist, after the data bits */ + ASYNC_PARITY_ODD +}; + #if defined(__cplusplus) extern "C" { diff --git a/libs/spandsp/src/spandsp/dtmf.h b/libs/spandsp/src/spandsp/dtmf.h index bca36cf015..161131355f 100644 --- a/libs/spandsp/src/spandsp/dtmf.h +++ b/libs/spandsp/src/spandsp/dtmf.h @@ -170,6 +170,14 @@ SPAN_DECLARE(void) dtmf_rx_parms(dtmf_rx_state_t *s, \return The number of samples unprocessed. */ SPAN_DECLARE(int) dtmf_rx(dtmf_rx_state_t *s, const int16_t amp[], int samples); +/*! Fake processing of a missing block of received DTMF audio samples. + (e.g due to packet loss). + \brief Fake processing of a missing block of received DTMF audio samples. + \param s The DTMF receiver context. + \param len The number of samples to fake. + \return The number of samples unprocessed. */ +SPAN_DECLARE(int) dtmf_rx_fillin(dtmf_rx_state_t *s, int samples); + /*! Get the status of DTMF detection during processing of the last audio chunk. \brief Get the status of DTMF detection during processing of the last diff --git a/libs/spandsp/src/spandsp/expose.h b/libs/spandsp/src/spandsp/expose.h index 6989a3faae..ac10084535 100644 --- a/libs/spandsp/src/spandsp/expose.h +++ b/libs/spandsp/src/spandsp/expose.h @@ -70,6 +70,8 @@ #include /*#include */ /*#include */ +#include +#include #include #include #include @@ -90,8 +92,6 @@ #include #include #include -#include -#include #include #endif diff --git a/libs/spandsp/src/spandsp/fax_modems.h b/libs/spandsp/src/spandsp/fax_modems.h index a3b5ef6f68..100e57eb5c 100644 --- a/libs/spandsp/src/spandsp/fax_modems.h +++ b/libs/spandsp/src/spandsp/fax_modems.h @@ -70,6 +70,13 @@ SPAN_DECLARE(void) fax_modems_set_tep_mode(fax_modems_state_t *s, int use_tep); SPAN_DECLARE(int) fax_modems_restart(fax_modems_state_t *s); +/*! Get a pointer to the logging context associated with a FAX modems context. + \brief Get a pointer to the logging context associated with a FAX modems context. + \param s The FAX modems context. + \return A pointer to the logging context, or NULL. +*/ +SPAN_DECLARE(logging_state_t *) fax_modems_get_logging_state(fax_modems_state_t *s); + SPAN_DECLARE(fax_modems_state_t *) fax_modems_init(fax_modems_state_t *s, int use_tep, hdlc_frame_handler_t hdlc_accept, diff --git a/libs/spandsp/src/spandsp/g168models.h b/libs/spandsp/src/spandsp/g168models.h index ff57491f0b..1bc728e300 100644 --- a/libs/spandsp/src/spandsp/g168models.h +++ b/libs/spandsp/src/spandsp/g168models.h @@ -213,7 +213,7 @@ const int32_t line_model_d8_coeffs[] = const int32_t line_model_d9_coeffs[] = { 80, 31, 4, 42, 42, -61, -81, -64, - 121, -102, -26, 1002, -9250, -22562, 39321, 35681, + -121, -102, -26, 1002, -9250, -22562, 39321, 35681, -35289, 25312, -1457, -229, 15659, -6786, 16791, 3860, 2239, -28730, -11885, 33871, -176, -16421, 18173, -9669, -10163, 9941, -19365, 3592, -5907, -10257, 5336, -12933, @@ -258,7 +258,7 @@ const float level_measurement_bp_coeffs[] = }; /*! - The composite source signal "voiced" section from section C.1 of G.168. + The composite source signal "voiced" section from table C.1 of G.168. */ const int css_c1[] = { @@ -282,7 +282,7 @@ const int css_c1[] = }; /*! - The composite source signal "voiced" section from section C.3 of G.168. + The composite source signal "voiced" section from table C.3 of G.168. */ const int css_c3[] = { diff --git a/libs/spandsp/src/spandsp/logging.h b/libs/spandsp/src/spandsp/logging.h index 0133b80926..2de8eb8767 100644 --- a/libs/spandsp/src/spandsp/logging.h +++ b/libs/spandsp/src/spandsp/logging.h @@ -33,11 +33,8 @@ #if !defined(_SPANDSP_LOGGING_H_) #define _SPANDSP_LOGGING_H_ -/*! General logging function for spandsp logging. */ -typedef void (*message_handler_func_t)(int level, const char *text); - -/*! Error logging function for spandsp logging. */ -typedef void (*error_handler_func_t)(const char *text); +/*! Logging function for spandsp logging. */ +typedef void (*message_handler_func_t)(void *user_data, int level, const char *text); /* Logging elements */ enum @@ -117,13 +114,9 @@ SPAN_DECLARE(int) span_log_set_sample_rate(logging_state_t *s, int samples_per_s SPAN_DECLARE(int) span_log_bump_samples(logging_state_t *s, int samples); -SPAN_DECLARE(void) span_log_set_message_handler(logging_state_t *s, message_handler_func_t func); +SPAN_DECLARE(void) span_log_set_message_handler(logging_state_t *s, message_handler_func_t func, void *user_data); -SPAN_DECLARE(void) span_log_set_error_handler(logging_state_t *s, error_handler_func_t func); - -SPAN_DECLARE(void) span_set_message_handler(message_handler_func_t func); - -SPAN_DECLARE(void) span_set_error_handler(error_handler_func_t func); +SPAN_DECLARE(void) span_set_message_handler(message_handler_func_t func, void *user_data); SPAN_DECLARE(logging_state_t *) span_log_init(logging_state_t *s, int level, const char *tag); diff --git a/libs/spandsp/src/spandsp/private/dtmf.h b/libs/spandsp/src/spandsp/private/dtmf.h index dc9c17bffc..e063470d78 100644 --- a/libs/spandsp/src/spandsp/private/dtmf.h +++ b/libs/spandsp/src/spandsp/private/dtmf.h @@ -96,7 +96,7 @@ struct dtmf_rx_state_s uint8_t in_digit; /*! The current sample number within a processing block. */ int current_sample; - + /*! Tone state duration */ int duration; diff --git a/libs/spandsp/src/spandsp/private/fax_modems.h b/libs/spandsp/src/spandsp/private/fax_modems.h index 67422bbe40..4250198ded 100644 --- a/libs/spandsp/src/spandsp/private/fax_modems.h +++ b/libs/spandsp/src/spandsp/private/fax_modems.h @@ -52,24 +52,27 @@ struct fax_modems_state_s /*! \brief A V.21 FSK modem context used when receiving HDLC over V.21 messages. */ fsk_rx_state_t v21_rx; - /*! \brief A V.17 modem context used when sending FAXes at 7200bps, 9600bps - 12000bps or 14400bps */ - v17_tx_state_t v17_tx; - /*! \brief A V.29 modem context used when receiving FAXes at 7200bps, 9600bps - 12000bps or 14400bps */ - v17_rx_state_t v17_rx; - /*! \brief A V.29 modem context used when sending FAXes at 7200bps or - 9600bps */ - v29_tx_state_t v29_tx; - /*! \brief A V.29 modem context used when receiving FAXes at 7200bps or - 9600bps */ - v29_rx_state_t v29_rx; - /*! \brief A V.27ter modem context used when sending FAXes at 2400bps or - 4800bps */ - v27ter_tx_state_t v27ter_tx; - /*! \brief A V.27ter modem context used when receiving FAXes at 2400bps or - 4800bps */ - v27ter_rx_state_t v27ter_rx; + struct + { + /*! \brief A V.17 modem context used when sending FAXes at 7200bps, 9600bps + 12000bps or 14400bps */ + v17_tx_state_t v17_tx; + /*! \brief A V.29 modem context used when receiving FAXes at 7200bps, 9600bps + 12000bps or 14400bps */ + v17_rx_state_t v17_rx; + /*! \brief A V.29 modem context used when sending FAXes at 7200bps or + 9600bps */ + v29_tx_state_t v29_tx; + /*! \brief A V.29 modem context used when receiving FAXes at 7200bps or + 9600bps */ + v29_rx_state_t v29_rx; + /*! \brief A V.27ter modem context used when sending FAXes at 2400bps or + 4800bps */ + v27ter_tx_state_t v27ter_tx; + /*! \brief A V.27ter modem context used when receiving FAXes at 2400bps or + 4800bps */ + v27ter_rx_state_t v27ter_rx; + } fast_modems; /*! \brief Used to insert timed silences. */ silence_gen_state_t silence_gen; /*! \brief CED or CNG generator */ @@ -79,9 +82,9 @@ struct fax_modems_state_s /*! \brief */ dc_restore_state_t dc_restore; - /*! \brief The currently select receiver type */ + /*! \brief The currently selected receiver type */ int current_rx_type; - /*! \brief The currently select transmitter type */ + /*! \brief The currently selected transmitter type */ int current_tx_type; /*! \brief TRUE if a carrier is present. Otherwise FALSE. */ @@ -91,13 +94,13 @@ struct fax_modems_state_s /*! \brief TRUE if an HDLC frame has been received correctly. */ int rx_frame_received; - /*! The current receive signal handler */ + /*! \brief The current receive signal handler */ span_rx_handler_t *rx_handler; - /*! The current receive missing signal fill-in handler */ + /*! \brief The current receive missing signal fill-in handler */ span_rx_fillin_handler_t *rx_fillin_handler; void *rx_user_data; - /*! The current transmit signal handler */ + /*! \brief The current transmit signal handler */ span_tx_handler_t *tx_handler; void *tx_user_data; diff --git a/libs/spandsp/src/spandsp/private/logging.h b/libs/spandsp/src/spandsp/private/logging.h index 0e59d267b3..fca1d257a9 100644 --- a/libs/spandsp/src/spandsp/private/logging.h +++ b/libs/spandsp/src/spandsp/private/logging.h @@ -39,7 +39,7 @@ struct logging_state_s const char *protocol; message_handler_func_t span_message; - error_handler_func_t span_error; + void *user_data; }; #endif diff --git a/libs/spandsp/src/spandsp/private/t38_core.h b/libs/spandsp/src/spandsp/private/t38_core.h index 8f71321dda..de0aac9d60 100644 --- a/libs/spandsp/src/spandsp/private/t38_core.h +++ b/libs/spandsp/src/spandsp/private/t38_core.h @@ -95,16 +95,19 @@ struct t38_core_state_s /*! \brief The fastest data rate supported by the T.38 channel. */ int fastest_image_data_rate; + /*! \brief Pace transmission */ + int pace_transmission; + + /*! \brief TRUE if IFP packet sequence numbers are relevant. For some transports, like TPKT + over TCP they are not relevent. */ + int check_sequence_numbers; + /*! \brief The number of times each packet type will be sent (low byte). The depth of redundancy (2nd byte). Higher numbers may increase reliability for UDP transmission. Zero is valid for the indicator packet category, to suppress all indicator packets (typicaly for TCP transmission). */ int category_control[5]; - /*! \brief TRUE if IFP packet sequence numbers are relevant. For some transports, like TPKT - over TCP they are not relevent. */ - int check_sequence_numbers; - /*! \brief The sequence number for the next packet to be transmitted */ int tx_seq_no; /*! \brief The sequence number expected in the next received packet */ diff --git a/libs/spandsp/src/spandsp/private/t38_terminal.h b/libs/spandsp/src/spandsp/private/t38_terminal.h index a78ec685f7..4cd47df85b 100644 --- a/libs/spandsp/src/spandsp/private/t38_terminal.h +++ b/libs/spandsp/src/spandsp/private/t38_terminal.h @@ -32,7 +32,7 @@ typedef struct { /*! \brief Internet Aware FAX mode bit mask. */ int iaf; - /*! \brief Required time between T.38 transmissions, in ms. */ + /*! \brief Required time between T.38 transmissions, in milliseconds. */ int ms_per_tx_chunk; /*! \brief Bit fields controlling the way data is packed into chunked for transmission. */ int chunking_modes; @@ -43,6 +43,9 @@ typedef struct /*! \brief The current transmit step being timed */ int timed_step; + /*! \brief The timed step to go to when we reach idle from the current timed step */ + int queued_timed_step; + /*! \brief TRUE is there has been some T.38 data missed (i.e. lost packets) in the current reception period. */ int rx_data_missing; diff --git a/libs/spandsp/src/spandsp/private/t4_rx.h b/libs/spandsp/src/spandsp/private/t4_rx.h index ba0d4ca74f..10ed0cf983 100644 --- a/libs/spandsp/src/spandsp/private/t4_rx.h +++ b/libs/spandsp/src/spandsp/private/t4_rx.h @@ -59,7 +59,7 @@ typedef struct const char *far_ident; /*! \brief The FAX sub-address. */ const char *sub_address; - /*! \brief The FAX DCS information, as an ASCII string. */ + /*! \brief The FAX DCS information, as an ASCII hex string. */ const char *dcs; /*! \brief The first page to transfer. -1 to start at the beginning of the file. */ diff --git a/libs/spandsp/src/spandsp/private/t4_tx.h b/libs/spandsp/src/spandsp/private/t4_tx.h index 9153b47e8b..d56c392afc 100644 --- a/libs/spandsp/src/spandsp/private/t4_tx.h +++ b/libs/spandsp/src/spandsp/private/t4_tx.h @@ -50,7 +50,7 @@ struct t4_state_s in no header line. */ const char *header_info; /*! \brief Optional per instance time zone for the FAX page header timestamp. */ - tz_t *tz; + struct tz_s *tz; /*! \brief The size of the compressed image on the line side, in bits. */ int line_image_size; diff --git a/libs/spandsp/src/spandsp/super_tone_rx.h b/libs/spandsp/src/spandsp/super_tone_rx.h index 702069856c..c819a4442d 100644 --- a/libs/spandsp/src/spandsp/super_tone_rx.h +++ b/libs/spandsp/src/spandsp/super_tone_rx.h @@ -55,6 +55,8 @@ executive override tone, confirmation tone). /*! Tone detection indication callback routine */ typedef void (*tone_report_func_t)(void *user_data, int code, int level, int delay); +typedef void (*tone_segment_func_t)(void *data, int f1, int f2, int duration); + typedef struct super_tone_rx_segment_s super_tone_rx_segment_t; typedef struct super_tone_rx_descriptor_s super_tone_rx_descriptor_t; @@ -125,13 +127,24 @@ SPAN_DECLARE(int) super_tone_rx_release(super_tone_rx_state_t *s); */ SPAN_DECLARE(int) super_tone_rx_free(super_tone_rx_state_t *s); +/*! Define a callback routine to be called to report the valid detection or termination of + one of the monitored tones. + \param s The supervisory tone context. + \param callback The callback routine called to report the valid detection or termination of + one of the monitored tones. + \param user_data An opaque pointer passed when calling the callback routine. +*/ +SPAN_DECLARE(void) super_tone_rx_tone_callback(super_tone_rx_state_t *s, + tone_report_func_t callback, + void *user_data); + /*! Define a callback routine to be called each time a tone pattern element is complete. This is mostly used when analysing a tone. \param s The supervisory tone context. \param callback The callback routine. */ SPAN_DECLARE(void) super_tone_rx_segment_callback(super_tone_rx_state_t *s, - void (*callback)(void *data, int f1, int f2, int duration)); + tone_segment_func_t callback); /*! Apply supervisory tone detection processing to a block of audio samples. \brief Apply supervisory tone detection processing to a block of audio samples. @@ -142,6 +155,14 @@ SPAN_DECLARE(void) super_tone_rx_segment_callback(super_tone_rx_state_t *s, */ SPAN_DECLARE(int) super_tone_rx(super_tone_rx_state_t *super, const int16_t amp[], int samples); +/*! Allow for a missing block of samples to a supervisory tone detector. + \brief Allow for a missing block of samples to a supervisory tone detector. + \param super The supervisory tone context. + \param samples The number of samples to allow for. + \return The number of samples processed. +*/ +SPAN_DECLARE(int) super_tone_rx_fillin(super_tone_rx_state_t *s, int samples); + #if defined(__cplusplus) } #endif diff --git a/libs/spandsp/src/spandsp/t35.h b/libs/spandsp/src/spandsp/t35.h index 553b6212e0..efd644b390 100644 --- a/libs/spandsp/src/spandsp/t35.h +++ b/libs/spandsp/src/spandsp/t35.h @@ -36,15 +36,39 @@ ???. */ -/*! A table of the country names associated with each possible value of the T.35 country code - selector octet. */ -extern const char *t35_country_codes[256]; - #if defined(__cplusplus) extern "C" { #endif +/*! Resolve a T.35 country code its probable likely real value, using heuristics to try to resolve issues + of broken bit order in the country code. + \brief Resolve a T.35 country code with bit reversal resolution. + \param country_code The country code. + \param country_code_extension The country code extension. + \return The true country code, or -1 for an invalid code. +*/ +SPAN_DECLARE(int) t35_real_country_code(int country_code, int country_code_extension); + +/*! Decode a T.35 country code to a country name, using heuristics to try to resolve issues of broken bit order + in the country code. + \brief Decode a T.35 country code to a country name, with bit reversal resolution. + \param country_code The country code. + \param country_code_extension The country code extension. + \return The country name, or NULL for an invalid country code. +*/ +SPAN_DECLARE(const char *) t35_real_country_code_to_str(int country_code, int country_code_extension); + +/*! Decode a T.35 country code to a country name. + \brief Decode a T.35 country code to a country name. + \param country_code The country code. + \param country_code_extension The country code extension. + \return The country name, or NULL for an invalid country code. +*/ +SPAN_DECLARE(const char *) t35_country_code_to_str(int country_code, int country_code_extension); + +SPAN_DECLARE(const char *) t35_vendor_to_str(const uint8_t *msg, int len); + /*! Decode an NSF field to try to determine the make and model of the remote machine. \brief Decode an NSF field. diff --git a/libs/spandsp/src/spandsp/t38_core.h b/libs/spandsp/src/spandsp/t38_core.h index 3d8e864513..cda7a19b52 100644 --- a/libs/spandsp/src/spandsp/t38_core.h +++ b/libs/spandsp/src/spandsp/t38_core.h @@ -155,7 +155,8 @@ enum t38_transport_types_e { T38_TRANSPORT_UDPTL = 0, T38_TRANSPORT_RTP, - T38_TRANSPORT_TCP + T38_TRANSPORT_TCP, + T38_TRANSPORT_TCP_TPKT }; /*! T.38 TCF management types */ @@ -268,7 +269,7 @@ SPAN_DECLARE(int) t38_core_send_training_delay(t38_core_state_t *s, int indicato \param field The message data content for the packet. \param field_len The length of the message data, in bytes. \param category The category of the packet being sent. This should be one of the values defined for t38_packet_categories_e. - \return ??? */ + \return 0 for OK, else -1 */ SPAN_DECLARE(int) t38_core_send_data(t38_core_state_t *s, int data_type, int field_type, const uint8_t field[], int field_len, int category); /*! \brief Send a data packet @@ -277,10 +278,11 @@ SPAN_DECLARE(int) t38_core_send_data(t38_core_state_t *s, int data_type, int fie \param field The list of fields. \param fields The number of fields in the list. \param category The category of the packet being sent. This should be one of the values defined for t38_packet_categories_e. - \return ??? */ + \return 0 for OK, else -1 */ SPAN_DECLARE(int) t38_core_send_data_multi_field(t38_core_state_t *s, int data_type, const t38_data_field_t field[], int fields, int category); -/*! \brief Process a received T.38 IFP packet. +/*! \brief Process a received T.38 IFP packet from an unreliable packet stream (e.g. UDPTL or RTP). This processing includes + packet sequence number checking, missing packet recovery, and skipping repeat packets. \param s The T.38 context. \param buf The packet contents. \param len The length of the packet contents. @@ -288,6 +290,14 @@ SPAN_DECLARE(int) t38_core_send_data_multi_field(t38_core_state_t *s, int data_t \return 0 for OK, else -1. */ SPAN_DECLARE_NONSTD(int) t38_core_rx_ifp_packet(t38_core_state_t *s, const uint8_t *buf, int len, uint16_t seq_no); +/*! \brief Process a received T.38 IFP packet from a reliable stream (e.g. TCP). + \param s The T.38 context. + \param buf The packet contents. + \param len The length of the packet contents. + \param seq_no The packet sequence number, used for logging purposes. + \return The length of the packet processed, or -1 if there is an error in the packet, or too few bytes of data to complete it. */ +SPAN_DECLARE_NONSTD(int) t38_core_rx_ifp_stream(t38_core_state_t *s, const uint8_t *buf, int len, uint16_t log_seq_no); + /*! Set the method to be used for data rate management, as per the T.38 spec. \param s The T.38 context. \param method 1 for pass TCF across the T.38 link, 2 for handle TCF locally. @@ -339,6 +349,8 @@ SPAN_DECLARE(void) t38_set_max_datagram_size(t38_core_state_t *s, int max_datagr information may be encoded in it, such as the redundancy depth for the particular packet category. */ SPAN_DECLARE(void) t38_set_redundancy_control(t38_core_state_t *s, int category, int setting); +SPAN_DECLARE(void) t38_set_pace_transmission(t38_core_state_t *s, int pace_transmission); + SPAN_DECLARE(void) t38_set_fastest_image_data_rate(t38_core_state_t *s, int max_rate); SPAN_DECLARE(int) t38_get_fastest_image_data_rate(t38_core_state_t *s); diff --git a/libs/spandsp/src/spandsp/t38_terminal.h b/libs/spandsp/src/spandsp/t38_terminal.h index c751b477da..2307f765f7 100644 --- a/libs/spandsp/src/spandsp/t38_terminal.h +++ b/libs/spandsp/src/spandsp/t38_terminal.h @@ -47,7 +47,10 @@ enum T38_TERMINAL_OPTION_REGULAR_INDICATORS = 0x02, /*! This option enables the regular repeat transmission of indicator signals for the first 2s, during periods when no FAX signal transmission occurs. */ - T38_TERMINAL_OPTION_2S_REPEATING_INDICATORS = 0x04 + T38_TERMINAL_OPTION_2S_REPEATING_INDICATORS = 0x04, + /*! This option suppresses the transmission of indicators. This is usually used with + TCP/TPKT transmission of T.38 FAXes */ + T38_TERMINAL_OPTION_NO_INDICATORS = 0x08 }; typedef struct t38_terminal_state_s t38_terminal_state_t; diff --git a/libs/spandsp/src/spandsp/t4_rx.h b/libs/spandsp/src/spandsp/t4_rx.h index b1b0a96e18..004c75c840 100644 --- a/libs/spandsp/src/spandsp/t4_rx.h +++ b/libs/spandsp/src/spandsp/t4_rx.h @@ -39,6 +39,10 @@ for FAX transmission. \section t4_page_sec_1 How does it work? */ +/*! This function is a callback from the image decoders, to write the decoded bi-level image, + row by row. It is called for each row, with len set to the number of bytes per row. At the + end of the image it is called with len set to zero, to indicate the end of image condition. + \return 0 for OK, or non-zero for a problem that requires the image be interrupted. */ typedef int (*t4_row_write_handler_t)(void *user_data, const uint8_t buf[], size_t len); /*! Supported compression modes. */ @@ -60,12 +64,22 @@ typedef enum T4_COMPRESSION_ITU_T43 = 6, /*! T.45 run length colour compression */ T4_COMPRESSION_ITU_T45 = 7, - /*! T.81 + T.30 Annex E colour JPEG coding */ - T4_COMPRESSION_ITU_T81 = 8, - /*! T.81 + T.30 Annex K colour sYCC-JPEG coding */ - T4_COMPRESSION_ITU_SYCC_T81 = 9 + /*! T.42 + T.81 + T.30 Annex E colour JPEG coding */ + T4_COMPRESSION_ITU_T42 = 8, + /*! T.42 + T.81 + T.30 Annex K colour sYCC-JPEG coding */ + T4_COMPRESSION_ITU_SYCC_T42 = 9 } t4_image_compression_t; +/*! Image type */ +typedef enum +{ + T4_IMAGE_TYPE_BILEVEL = 0, + T4_IMAGE_TYPE_GRAY_8BIT = 1, + T4_IMAGE_TYPE_GRAY_12BIT = 2, + T4_IMAGE_TYPE_COLOUR_8BIT = 3, + T4_IMAGE_TYPE_COLOUR_12BIT = 4 +} t4_image_types_t; + /*! Supported X resolutions, in pixels per metre. */ typedef enum { diff --git a/libs/spandsp/src/spandsp/t4_tx.h b/libs/spandsp/src/spandsp/t4_tx.h index 3985e28f63..6a10588e3e 100644 --- a/libs/spandsp/src/spandsp/t4_tx.h +++ b/libs/spandsp/src/spandsp/t4_tx.h @@ -28,12 +28,189 @@ #if !defined(_SPANDSP_T4_TX_H_) #define _SPANDSP_T4_TX_H_ +//#define SPANDSP_SUPPORT_TIFF_FX + +/*! This function is a callback from the image decoders, to read the unencoded bi-level image, + row by row. It is called for each row, with len set to the number of bytes per row expected. + \return len for OK, or zero to indicate the end of the image data. */ typedef int (*t4_row_read_handler_t)(void *user_data, uint8_t buf[], size_t len); +#if defined(SPANDSP_SUPPORT_TIFF_FX) +/* TIFF-FX related extensions to the tag set supported by libtiff */ + +/* +Indexed(346) = 0, 1. SHORT + 0: not a palette-color image. + 1: palette-color image. + This field is used to indicate that each sample value is an index + into an array of color values specified in the image data stream. + Because the color map is embedded in the image data stream, the + ColorMap field is not used in Profile L. Lossless color fax + profile supports palette-color images with the ITULAB encoding. + The SamplesPerPixel value must be 1. + +GlobalParametersIFD (400) IFD + An IFD containing global parameters. It is recommended that a TIFF + writer place this field in the first IFD, where a TIFF reader would + find it quickly. + + Each field in the GlobalParametersIFD is a TIFF field that is legal + in any IFD. Required baseline fields should not be located in the + GlobalParametersIFD, but should be in each image IFD. If a conflict + exists between fields in the GlobalParametersIFD and in the image + IFDs, then the data in the image IFD shall prevail. + + Among the GlobalParametersIFD entries is a new ProfileType field + which generally describes information in this IFD and in the TIFF + file. + +ProfileType(401) LONG + The type of image data stored in this IFD. + 0 = Unspecified + 1 = Group 3 fax + No default + + The following new global fields are defined in this document as IFD + entries for use with fax applications. + +FaxProfile(402) = 0 - 6. BYTE + The profile that applies to this file; a profile is subset of the + full set of permitted fields and field values of TIFF for facsimile. + The currently defined values are: + 0: does not conform to a profile defined for TIFF for facsimile + 1: minimal black & white lossless, Profile S + 2: extended black & white lossless, Profile F + 3: lossless JBIG black & white, Profile J + 4: lossy color and grayscale, Profile C + 5: lossless color and grayscale, Profile L + 6: Mixed Raster Content, Profile M + +CodingMethods(403) LONG + This field indicates which coding methods are used in the file. A + bit value of 1 indicates which of the following coding methods is + used: + Bit 0: unspecified compression, + Bit 1: 1-dimensional coding, ITU-T Rec. T.4 (MH - Modified Huffman), + Bit 2: 2-dimensional coding, ITU-T Rec. T.4 (MR - Modified Read), + Bit 3: 2-dimensional coding, ITU-T Rec. T.6 (MMR - Modified MR), + Bit 4: ITU-T Rec. T.82 coding, using ITU-T Rec. T.85 (JBIG), + Bit 5: ITU-T Rec. T.81 (Baseline JPEG), + Bit 6: ITU-T Rec. T.82 coding, using ITU-T Rec. T.43 (JBIG color), + Bits 7-31: reserved for future use + Note: There is a limit of 32 compression types to identify standard + compression methods. + +VersionYear(404) BYTE + Count: 4 + The year of the standard specified by the FaxProfile field, given as + 4 characters, e.g. '1997'; used in lossy and lossless color modes. + +ModeNumber (405) BYTE + The mode of the standard specified by the FaxProfile field. A + value of 0 indicates Mode 1.0; used in Mixed Raster Content mode. + +Decode(433) SRATIONAL + Count = 2 * SamplesPerPixel + Describes how to map image sample values into the range of values + appropriate for the current color space. In general, the values + are taken in pairs and specify the minimum and maximum output + value for each color component. For the base color fax profile, + Decode has a count of 6 values and maps the unsigned ITULAB- + encoded sample values (Lsample, asample, bsample) to signed L*a*b* + values, as follows: + L* = Decode[0] + Lsample x (Decode[1]-Decode[0])/(2^n -1) + a* = Decode[2] + asample x (Decode[3]-Decode[2])/(2^n -1) + b* = Decode[4] + bsample x (Decode[5]-Decode[4])/(2^n -1) + where Decode[0], Decode[2] and Decode[4] are the minimum values + for L*, a*, and b*; Decode[1], Decode[3] and Decode[5] are the + maximum values for L*, a*, and b*; and n is the BitsPerSample. + When n=8,=20 L*=Decode[0] when Lsample=0 and L*=Decode[1] when + Lsample=255. + +ImageBaseColor(434) SHORT + Count = SamplesPerPixel + In areas of an image layer where no image data is available (i.e., + where no strips are defined, or where the StripByteCounts entry for + a given strip is 0), the color specified by ImageBaseColor will be + used. + +StripRowCounts(559) LONG + Count = number of strips. + The number of scanlines stored in a strip. Profile M allows each + fax strip to store a different number of scanlines. For strips + with more than one layer, the maximum strip size is either 256 + scanlines or full page size. The 256 maximum SHOULD be used + unless the capability to receive longer strips has been + negotiated. This field replaces RowsPerStrip for IFDs with + variable-size strips. Only one of the two fields, StripRowCounts + and RowsPerStrip, may be used in an IFD. + +ImageLayer(34732) LONG + Count = 2. + Image layers are defined such that layer 1 is the Background + layer, layer 3 is the Foreground layer, and layer 2 is the Mask + layer, which selects pixels from the Background and Foreground + layers. The ImageLayer tag contains two values, which describe + the layer to which the image belongs and the order in which it is + imaged. + + ImageLayer[0] = 1, 2, 3. + 1: Image is a Background image, i.e. the image that will appear + whenever the Mask contains a value of 0. Background images + typically contain low-resolution, continuous-tone imagery. + 2: Image is the Mask layer. In MRC, if the Mask layer is present, + it must be the Primary IFD and be full page in extent. + 3: Image is a Foreground image, i.e. the image that will appear + whenever the Mask contains a value of 1. The Foreground image + generally defines the color of text or lines but may also + contain high-resolution imagery. + + ImageLayer[1]: + 1: first image to be imaged in this layer + 2: second image to be imaged in this layer + 3: ... +*/ + +#define TIFFTAG_INDEXED 346 +#define TIFFTAG_GLOBALPARAMETERSIFD 400 +#define TIFFTAG_PROFILETYPE 401 +#define PROFILETYPE_UNSPECIFIED 0 +#define PROFILETYPE_G3_FAX 1 +#define TIFFTAG_FAXPROFILE 402 +#define FAXPROFILE_S 1 +#define FAXPROFILE_F 2 +#define FAXPROFILE_J 3 +#define FAXPROFILE_C 4 +#define FAXPROFILE_L 5 +#define FAXPROFILE_M 6 +#define TIFFTAG_CODINGMETHODS 403 +#define CODINGMETHODS_T4_1D (1 << 1) +#define CODINGMETHODS_T4_2D (1 << 2) +#define CODINGMETHODS_T6 (1 << 3) +#define CODINGMETHODS_T85 (1 << 4) +#define CODINGMETHODS_T42 (1 << 5) +#define CODINGMETHODS_T43 (1 << 6) +#define TIFFTAG_VERSIONYEAR 404 +#define TIFFTAG_MODENUMBER 405 +#define TIFFTAG_DECODE 433 +#define TIFFTAG_IMAGEBASECOLOR 434 +#define TIFFTAG_T82OPTIONS 435 +#define TIFFTAG_STRIPROWCOUNTS 559 +#define TIFFTAG_IMAGELAYER 34732 + +#define COMPRESSION_T85 9 +#define COMPRESSION_T43 10 +#endif + #if defined(__cplusplus) extern "C" { #endif +#if defined(SPANDSP_SUPPORT_TIFF_FX) +/*! \brief Configure libtiff so it recognises the extended tag set for TIFF-FX. */ +SPAN_DECLARE(void) TIFF_FX_init(void); +#endif + /*! \brief Prepare for transmission of a document. \param s The T.4 context. \param file The name of the file to be sent. diff --git a/libs/spandsp/src/super_tone_rx.c b/libs/spandsp/src/super_tone_rx.c index 0ab84dab9b..87934669ab 100644 --- a/libs/spandsp/src/super_tone_rx.c +++ b/libs/spandsp/src/super_tone_rx.c @@ -56,14 +56,13 @@ #include "spandsp/private/super_tone_rx.h" #if defined(SPANDSP_USE_FIXED_POINT) -#define DETECTION_THRESHOLD 16439 /* -42dBm0 */ +#define DETECTION_THRESHOLD 16439 /* -42dBm0 [((BINS*BINS*32768.0/(1.4142*128.0))*10^((-42 - DBM0_MAX_SINE_POWER)/20.0))^2] */ #define TONE_TWIST 4 /* 6dB */ #define TONE_TO_TOTAL_ENERGY 64 /* -3dB */ #else -#define DETECTION_THRESHOLD 2104205.6f /* -42dBm0 [(((128.0*32768.0/1.4142)*10^((-42 - DBM0_MAX_SINE_POWER)/20.0))^2)/128 => 2104205.6] */ +#define DETECTION_THRESHOLD 2104205.6f /* -42dBm0 [((BINS*BINS*32768.0/1.4142)*10^((-42 - DBM0_MAX_SINE_POWER)/20.0))^2] */ #define TONE_TWIST 3.981f /* 6dB */ #define TONE_TO_TOTAL_ENERGY 1.995f /* 3dB */ -#define DTMF_TO_TOTAL_ENERGY 64.152f /* -3dB [BINS*10^(-3/10.0)] */ #endif static int add_super_tone_freq(super_tone_rx_descriptor_t *desc, int freq) @@ -237,8 +236,17 @@ SPAN_DECLARE(int) super_tone_rx_free_descriptor(super_tone_rx_descriptor_t *desc } /*- End of function --------------------------------------------------------*/ +SPAN_DECLARE(void) super_tone_rx_tone_callback(super_tone_rx_state_t *s, + tone_report_func_t callback, + void *user_data) +{ + s->tone_callback = callback; + s->callback_data = user_data; +} +/*- End of function --------------------------------------------------------*/ + SPAN_DECLARE(void) super_tone_rx_segment_callback(super_tone_rx_state_t *s, - void (*callback)(void *data, int f1, int f2, int duration)) + tone_segment_func_t callback) { s->segment_callback = callback; } @@ -273,7 +281,11 @@ SPAN_DECLARE(super_tone_rx_state_t *) super_tone_rx_init(super_tone_rx_state_t * if (desc) s->desc = desc; s->detected_tone = -1; +#if defined(SPANDSP_USE_FIXED_POINT) + s->energy = 0; +#else s->energy = 0.0f; +#endif for (i = 0; i < desc->monitored_frequencies; i++) goertzel_init(&s->state[i], &s->desc->desc[i]); return s; @@ -459,10 +471,21 @@ SPAN_DECLARE(int) super_tone_rx(super_tone_rx_state_t *s, const int16_t amp[], i { /* We have finished a Goertzel block. */ super_tone_chunk(s); +#if defined(SPANDSP_USE_FIXED_POINT) s->energy = 0; +#else + s->energy = 0.0f; +#endif } } return samples; } /*- End of function --------------------------------------------------------*/ + +SPAN_DECLARE(int) super_tone_rx_fillin(super_tone_rx_state_t *s, int samples) +{ + /* TODO: Roll the detector forward without a state change */ + return 0; +} +/*- End of function --------------------------------------------------------*/ /*- End of file ------------------------------------------------------------*/ diff --git a/libs/spandsp/src/t30.c b/libs/spandsp/src/t30.c index c301ceb0d4..68a5c901c3 100644 --- a/libs/spandsp/src/t30.c +++ b/libs/spandsp/src/t30.c @@ -1499,7 +1499,7 @@ static int build_dcs(t30_state_t *s) } if (bad != T30_ERR_OK) { - s->current_status = bad; + t30_set_status(s, bad); span_log(&s->logging, SPAN_LOG_FLOW, "Image resolution (%d x %d) not acceptable\n", s->x_resolution, s->y_resolution); return -1; } @@ -1548,7 +1548,7 @@ static int build_dcs(t30_state_t *s) } if (bad != T30_ERR_OK) { - s->current_status = bad; + t30_set_status(s, bad); span_log(&s->logging, SPAN_LOG_FLOW, "Image width (%d pixels) is not an acceptable FAX image width\n", s->image_width); return -1; } @@ -1590,7 +1590,7 @@ static int build_dcs(t30_state_t *s) } if (bad != T30_ERR_OK) { - s->current_status = bad; + t30_set_status(s, bad); span_log(&s->logging, SPAN_LOG_FLOW, "Image width (%d pixels) is not an acceptable FAX image width\n", s->image_width); return -1; } @@ -1699,7 +1699,7 @@ static void return_to_phase_b(t30_state_t *s, int with_fallback) { /* We have fallen back as far as we can go. Give up. */ s->current_fallback = 0; - s->current_status = T30_ERR_CANNOT_TRAIN; + t30_set_status(s, T30_ERR_CANNOT_TRAIN); send_dcn(s); } else @@ -1929,7 +1929,7 @@ static int set_min_scan_time_code(t30_state_t *s) case T4_Y_RESOLUTION_SUPERFINE: if (!test_ctrl_bit(s->far_dis_dtc_frame, T30_DIS_BIT_200_400_CAPABLE)) { - s->current_status = T30_ERR_NORESSUPPORT; + t30_set_status(s, T30_ERR_NORESSUPPORT); span_log(&s->logging, SPAN_LOG_FLOW, "Remote FAX does not support super-fine resolution.\n"); return -1; } @@ -1938,7 +1938,7 @@ static int set_min_scan_time_code(t30_state_t *s) case T4_Y_RESOLUTION_FINE: if (!test_ctrl_bit(s->far_dis_dtc_frame, T30_DIS_BIT_200_200_CAPABLE)) { - s->current_status = T30_ERR_NORESSUPPORT; + t30_set_status(s, T30_ERR_NORESSUPPORT); span_log(&s->logging, SPAN_LOG_FLOW, "Remote FAX does not support fine resolution.\n"); return -1; } @@ -1969,7 +1969,7 @@ static int start_sending_document(t30_state_t *s) if (t4_tx_init(&s->t4.tx, s->tx_file, s->tx_start_page, s->tx_stop_page) == NULL) { span_log(&s->logging, SPAN_LOG_WARNING, "Cannot open source TIFF file '%s'\n", s->tx_file); - s->current_status = T30_ERR_FILEERROR; + t30_set_status(s, T30_ERR_FILEERROR); return -1; } s->operation_in_progress = OPERATION_IN_PROGRESS_T4_TX; @@ -2034,7 +2034,7 @@ static void unexpected_non_final_frame(t30_state_t *s, const uint8_t *msg, int l { span_log(&s->logging, SPAN_LOG_FLOW, "Unexpected %s frame in state %d\n", t30_frametype(msg[2]), s->state); if (s->current_status == T30_ERR_OK) - s->current_status = T30_ERR_UNEXPECTED; + t30_set_status(s, T30_ERR_UNEXPECTED); } /*- End of function --------------------------------------------------------*/ @@ -2042,7 +2042,7 @@ static void unexpected_final_frame(t30_state_t *s, const uint8_t *msg, int len) { span_log(&s->logging, SPAN_LOG_FLOW, "Unexpected %s frame in state %d\n", t30_frametype(msg[2]), s->state); if (s->current_status == T30_ERR_OK) - s->current_status = T30_ERR_UNEXPECTED; + t30_set_status(s, T30_ERR_UNEXPECTED); send_dcn(s); } /*- End of function --------------------------------------------------------*/ @@ -2051,7 +2051,7 @@ static void unexpected_frame_length(t30_state_t *s, const uint8_t *msg, int len) { span_log(&s->logging, SPAN_LOG_FLOW, "Unexpected %s frame length - %d\n", t30_frametype(msg[0]), len); if (s->current_status == T30_ERR_OK) - s->current_status = T30_ERR_UNEXPECTED; + t30_set_status(s, T30_ERR_UNEXPECTED); send_dcn(s); } /*- End of function --------------------------------------------------------*/ @@ -2153,7 +2153,7 @@ static int process_rx_dis_dtc(t30_state_t *s, const uint8_t *msg, int len) default: span_log(&s->logging, SPAN_LOG_FLOW, "Remote does not support a compatible modem\n"); /* We cannot talk to this machine! */ - s->current_status = T30_ERR_INCOMPATIBLE; + t30_set_status(s, T30_ERR_INCOMPATIBLE); return -1; } if (s->phase_b_handler) @@ -2162,7 +2162,7 @@ static int process_rx_dis_dtc(t30_state_t *s, const uint8_t *msg, int len) if (new_status != T30_ERR_OK) { span_log(&s->logging, SPAN_LOG_FLOW, "Application rejected DIS/DTC - '%s'\n", t30_completion_code_to_str(new_status)); - s->current_status = new_status; + t30_set_status(s, new_status); /* TODO: If FNV is allowed, process it here */ send_dcn(s); return -1; @@ -2230,7 +2230,7 @@ static int process_rx_dis_dtc(t30_state_t *s, const uint8_t *msg, int len) if (!test_ctrl_bit(s->far_dis_dtc_frame, T30_DIS_BIT_READY_TO_RECEIVE_FAX_DOCUMENT)) { span_log(&s->logging, SPAN_LOG_FLOW, "%s far end cannot receive\n", t30_frametype(msg[2])); - s->current_status = T30_ERR_RX_INCAPABLE; + t30_set_status(s, T30_ERR_RX_INCAPABLE); send_dcn(s); } if (start_sending_document(s)) @@ -2256,7 +2256,7 @@ static int process_rx_dis_dtc(t30_state_t *s, const uint8_t *msg, int len) if (!test_ctrl_bit(s->far_dis_dtc_frame, T30_DIS_BIT_READY_TO_TRANSMIT_FAX_DOCUMENT)) { span_log(&s->logging, SPAN_LOG_FLOW, "%s far end cannot transmit\n", t30_frametype(msg[2])); - s->current_status = T30_ERR_TX_INCAPABLE; + t30_set_status(s, T30_ERR_TX_INCAPABLE); send_dcn(s); return -1; } @@ -2267,7 +2267,7 @@ static int process_rx_dis_dtc(t30_state_t *s, const uint8_t *msg, int len) } if (set_dis_or_dtc(s)) { - s->current_status = T30_ERR_INCOMPATIBLE; + t30_set_status(s, T30_ERR_INCOMPATIBLE); send_dcn(s); return -1; } @@ -2404,7 +2404,7 @@ static int process_rx_dcs(t30_state_t *s, const uint8_t *msg, int len) if (new_status != T30_ERR_OK) { span_log(&s->logging, SPAN_LOG_FLOW, "Application rejected DCS - '%s'\n", t30_completion_code_to_str(new_status)); - s->current_status = new_status; + t30_set_status(s, new_status); /* TODO: If FNV is allowed, process it here */ send_dcn(s); return -1; @@ -2419,7 +2419,7 @@ static int process_rx_dcs(t30_state_t *s, const uint8_t *msg, int len) if (s->rx_file[0] == '\0') { span_log(&s->logging, SPAN_LOG_FLOW, "No document to receive\n"); - s->current_status = T30_ERR_FILEERROR; + t30_set_status(s, T30_ERR_FILEERROR); send_dcn(s); return -1; } @@ -2428,7 +2428,7 @@ static int process_rx_dcs(t30_state_t *s, const uint8_t *msg, int len) if (t4_rx_init(&s->t4.rx, s->rx_file, s->output_encoding) == NULL) { span_log(&s->logging, SPAN_LOG_WARNING, "Cannot open target TIFF file '%s'\n", s->rx_file); - s->current_status = T30_ERR_FILEERROR; + t30_set_status(s, T30_ERR_FILEERROR); send_dcn(s); return -1; } @@ -2467,8 +2467,6 @@ static int send_response_to_pps(t30_state_t *s) } /*- End of function --------------------------------------------------------*/ -#define VET_ALL_FCD_FRAMES - static int process_rx_pps(t30_state_t *s, const uint8_t *msg, int len) { int page; @@ -2478,11 +2476,8 @@ static int process_rx_pps(t30_state_t *s, const uint8_t *msg, int len) int j; int frame_no; int first_bad_frame; - int image_ended; -#if defined(VET_ALL_FCD_FRAMES) int first; int expected_len; -#endif if (len < 7) { @@ -2557,7 +2552,7 @@ static int process_rx_pps(t30_state_t *s, const uint8_t *msg, int len) else { /* Give up */ - s->current_status = T30_ERR_RX_ECMPHD; + t30_set_status(s, T30_ERR_RX_ECMPHD); send_dcn(s); } return 0; @@ -2565,10 +2560,8 @@ static int process_rx_pps(t30_state_t *s, const uint8_t *msg, int len) /* Build a bit map of which frames we now have stored OK */ first_bad_frame = 256; -#if defined(VET_ALL_FCD_FRAMES) first = TRUE; expected_len = 256; -#endif for (i = 0; i < 32; i++) { s->ecm_frame_map[i + 3] = 0; @@ -2578,14 +2571,26 @@ static int process_rx_pps(t30_state_t *s, const uint8_t *msg, int len) #if defined(VET_ALL_FCD_FRAMES) if (s->ecm_len[frame_no] >= 0) { + /* The correct pattern of frame lengths is they will all be 64 or 256 octets long, except the + last one. The last one might the same length as all the others, or it might be exactly the + right length to contain the last chunk of the data. That is, some people pad at the end, + and some do not. */ + /* Vet the frames which are present, to detect any with inappropriate lengths. This might seem + like overkill, as the frames must have had good CRCs to get this far. However, in the real + world there are systems, especially T.38 ones, which give bad frame lengths, and which screw + up communication unless you apply these checks. From experience, if you find a frame has a + suspect length, and demand retransmission, there is a good chance the new copy will be alright. */ if (frame_no < s->ecm_frames - 1) { + /* Expect all frames, except the last one, to follow the length of the first one */ if (first) { + /* Use the length of the first frame as our model for what the length should be */ if (s->ecm_len[frame_no] == 64) expected_len = 64; first = FALSE; } + /* Check the length is consistent with the first frame */ if (s->ecm_len[frame_no] != expected_len) { span_log(&s->logging, SPAN_LOG_FLOW, "Bad length ECM frame - %d\n", s->ecm_len[frame_no]); @@ -2608,13 +2613,11 @@ static int process_rx_pps(t30_state_t *s, const uint8_t *msg, int len) if (s->rx_ecm_block_ok) { span_log(&s->logging, SPAN_LOG_FLOW, "Partial page OK - committing block %d, %d frames\n", s->ecm_block, s->ecm_frames); - image_ended = FALSE; for (i = 0; i < s->ecm_frames; i++) { if (t4_rx_put_chunk(&s->t4.rx, s->ecm_data[i], s->ecm_len[i])) { /* This is the end of the document */ - image_ended = TRUE; break; } } @@ -2776,7 +2779,7 @@ static void process_rx_fcd(t30_state_t *s, const uint8_t *msg, int len) } /* We have received something, so any missing carrier status is out of date */ if (s->current_status == T30_ERR_RX_NOCARRIER) - s->current_status = T30_ERR_OK; + t30_set_status(s, T30_ERR_OK); break; default: unexpected_non_final_frame(s, msg, len); @@ -2797,7 +2800,7 @@ static void process_rx_rcp(t30_state_t *s, const uint8_t *msg, int len) timer_t2_start(s); /* We have received something, so any missing carrier status is out of date */ if (s->current_status == T30_ERR_RX_NOCARRIER) - s->current_status = T30_ERR_OK; + t30_set_status(s, T30_ERR_OK); break; case T30_STATE_F_POST_DOC_ECM: /* Just ignore this. It must be an extra RCP. Several are usually sent, to maximise the chance @@ -2915,7 +2918,7 @@ static void process_state_answering(t30_state_t *s, const uint8_t *msg, int len) process_rx_dcs(s, msg, len); break; case T30_DCN: - s->current_status = T30_ERR_TX_GOTDCN; + t30_set_status(s, T30_ERR_TX_GOTDCN); disconnect(s); break; default: @@ -2983,7 +2986,7 @@ static void process_state_d(t30_state_t *s, const uint8_t *msg, int len) switch (fcf) { case T30_DCN: - s->current_status = T30_ERR_TX_BADDCS; + t30_set_status(s, T30_ERR_TX_BADDCS); disconnect(s); break; case T30_CRP: @@ -3009,7 +3012,7 @@ static void process_state_d_tcf(t30_state_t *s, const uint8_t *msg, int len) switch (fcf) { case T30_DCN: - s->current_status = T30_ERR_TX_BADDCS; + t30_set_status(s, T30_ERR_TX_BADDCS); disconnect(s); break; case T30_CRP: @@ -3059,7 +3062,7 @@ static void process_state_d_post_tcf(t30_state_t *s, const uint8_t *msg, int len { /* We have fallen back as far as we can go. Give up. */ s->current_fallback = 0; - s->current_status = T30_ERR_CANNOT_TRAIN; + t30_set_status(s, T30_ERR_CANNOT_TRAIN); send_dcn(s); break; } @@ -3071,7 +3074,7 @@ static void process_state_d_post_tcf(t30_state_t *s, const uint8_t *msg, int len if (++s->retries >= MAX_COMMAND_TRIES) { span_log(&s->logging, SPAN_LOG_FLOW, "Too many retries. Giving up.\n"); - s->current_status = T30_ERR_RETRYDCN; + t30_set_status(s, T30_ERR_RETRYDCN); send_dcn(s); break; } @@ -3081,7 +3084,7 @@ static void process_state_d_post_tcf(t30_state_t *s, const uint8_t *msg, int len send_dcs_sequence(s, TRUE); break; case T30_DCN: - s->current_status = T30_ERR_TX_BADDCS; + t30_set_status(s, T30_ERR_TX_BADDCS); disconnect(s); break; case T30_CRP: @@ -3234,7 +3237,7 @@ static void process_state_f_doc_non_ecm(t30_state_t *s, const uint8_t *msg, int send_simple_frame(s, T30_RTN); break; case T30_DCN: - s->current_status = T30_ERR_RX_DCNDATA; + t30_set_status(s, T30_ERR_RX_DCNDATA); disconnect(s); break; case T30_CRP: @@ -3245,7 +3248,7 @@ static void process_state_f_doc_non_ecm(t30_state_t *s, const uint8_t *msg, int break; default: /* We don't know what to do with this. */ - s->current_status = T30_ERR_RX_INVALCMD; + t30_set_status(s, T30_ERR_RX_INVALCMD); unexpected_final_frame(s, msg, len); break; } @@ -3369,7 +3372,7 @@ static void process_state_f_post_doc_non_ecm(t30_state_t *s, const uint8_t *msg, } break; case T30_DCN: - s->current_status = T30_ERR_RX_DCNFAX; + t30_set_status(s, T30_ERR_RX_DCNFAX); disconnect(s); break; case T30_CRP: @@ -3380,7 +3383,7 @@ static void process_state_f_post_doc_non_ecm(t30_state_t *s, const uint8_t *msg, break; default: /* We don't know what to do with this. */ - s->current_status = T30_ERR_RX_INVALCMD; + t30_set_status(s, T30_ERR_RX_INVALCMD); unexpected_final_frame(s, msg, len); break; } @@ -3453,7 +3456,7 @@ static void process_state_f_doc_and_post_doc_ecm(t30_state_t *s, const uint8_t * case T30_RR: break; case T30_DCN: - s->current_status = T30_ERR_RX_DCNDATA; + t30_set_status(s, T30_ERR_RX_DCNDATA); disconnect(s); break; case T30_CRP: @@ -3464,7 +3467,7 @@ static void process_state_f_doc_and_post_doc_ecm(t30_state_t *s, const uint8_t * break; default: /* We don't know what to do with this. */ - s->current_status = T30_ERR_RX_INVALCMD; + t30_set_status(s, T30_ERR_RX_INVALCMD); unexpected_final_frame(s, msg, len); break; } @@ -3566,7 +3569,7 @@ static void process_state_r(t30_state_t *s, const uint8_t *msg, int len) break; case T30_DCN: /* Received a DCN while waiting for a DIS */ - s->current_status = T30_ERR_TX_GOTDCN; + t30_set_status(s, T30_ERR_TX_GOTDCN); disconnect(s); break; case T30_CRP: @@ -3594,7 +3597,7 @@ static void process_state_t(t30_state_t *s, const uint8_t *msg, int len) process_rx_dis_dtc(s, msg, len); break; case T30_DCN: - s->current_status = T30_ERR_RX_DCNWHY; + t30_set_status(s, T30_ERR_RX_DCNWHY); disconnect(s); break; case T30_CRP: @@ -3606,7 +3609,7 @@ static void process_state_t(t30_state_t *s, const uint8_t *msg, int len) default: /* We don't know what to do with this. */ unexpected_final_frame(s, msg, len); - s->current_status = T30_ERR_TX_NODIS; + t30_set_status(s, T30_ERR_TX_NODIS); break; } } @@ -3729,7 +3732,7 @@ static void process_state_ii_q(t30_state_t *s, const uint8_t *msg, int len) { /* We have fallen back as far as we can go. Give up. */ s->current_fallback = 0; - s->current_status = T30_ERR_CANNOT_TRAIN; + t30_set_status(s, T30_ERR_CANNOT_TRAIN); send_dcn(s); break; } @@ -3790,7 +3793,7 @@ static void process_state_ii_q(t30_state_t *s, const uint8_t *msg, int len) { /* We have fallen back as far as we can go. Give up. */ s->current_fallback = 0; - s->current_status = T30_ERR_CANNOT_TRAIN; + t30_set_status(s, T30_ERR_CANNOT_TRAIN); send_dcn(s); break; } @@ -3824,7 +3827,7 @@ static void process_state_ii_q(t30_state_t *s, const uint8_t *msg, int len) { /* We have fallen back as far as we can go. Give up. */ s->current_fallback = 0; - s->current_status = T30_ERR_CANNOT_TRAIN; + t30_set_status(s, T30_ERR_CANNOT_TRAIN); send_dcn(s); break; } @@ -3847,10 +3850,10 @@ static void process_state_ii_q(t30_state_t *s, const uint8_t *msg, int len) case T30_EOM: case T30_EOS: /* Unexpected DCN after EOM, EOS or MPS sequence */ - s->current_status = T30_ERR_RX_DCNPHD; + t30_set_status(s, T30_ERR_RX_DCNPHD); break; default: - s->current_status = T30_ERR_TX_BADPG; + t30_set_status(s, T30_ERR_TX_BADPG); break; } disconnect(s); @@ -3863,7 +3866,7 @@ static void process_state_ii_q(t30_state_t *s, const uint8_t *msg, int len) break; default: /* We don't know what to do with this. */ - s->current_status = T30_ERR_TX_INVALRSP; + t30_set_status(s, T30_ERR_TX_INVALRSP); unexpected_final_frame(s, msg, len); break; } @@ -3968,7 +3971,7 @@ static void process_state_iii_q_rtn(t30_state_t *s, const uint8_t *msg, int len) process_rx_fnv(s, msg, len); break; case T30_DCN: - s->current_status = T30_ERR_RX_DCNNORTN; + t30_set_status(s, T30_ERR_RX_DCNNORTN); disconnect(s); break; default: @@ -4075,7 +4078,7 @@ static void process_state_iv_pps_null(t30_state_t *s, const uint8_t *msg, int le send_rr(s); break; case T30_DCN: - s->current_status = T30_ERR_TX_BADPG; + t30_set_status(s, T30_ERR_TX_BADPG); disconnect(s); break; case T30_CRP: @@ -4087,7 +4090,7 @@ static void process_state_iv_pps_null(t30_state_t *s, const uint8_t *msg, int le default: /* We don't know what to do with this. */ unexpected_final_frame(s, msg, len); - s->current_status = T30_ERR_TX_ECMPHD; + t30_set_status(s, T30_ERR_TX_ECMPHD); break; } } @@ -4179,7 +4182,7 @@ static void process_state_iv_pps_q(t30_state_t *s, const uint8_t *msg, int len) process_rx_ppr(s, msg, len); break; case T30_DCN: - s->current_status = T30_ERR_TX_BADPG; + t30_set_status(s, T30_ERR_TX_BADPG); disconnect(s); break; case T30_CRP: @@ -4202,7 +4205,7 @@ static void process_state_iv_pps_q(t30_state_t *s, const uint8_t *msg, int len) default: /* We don't know what to do with this. */ unexpected_final_frame(s, msg, len); - s->current_status = T30_ERR_TX_ECMPHD; + t30_set_status(s, T30_ERR_TX_ECMPHD); break; } } @@ -4291,7 +4294,7 @@ static void process_state_iv_pps_rnr(t30_state_t *s, const uint8_t *msg, int len send_rr(s); break; case T30_DCN: - s->current_status = T30_ERR_RX_DCNRRD; + t30_set_status(s, T30_ERR_RX_DCNRRD); disconnect(s); break; case T30_CRP: @@ -4365,7 +4368,7 @@ static void process_state_iv_eor(t30_state_t *s, const uint8_t *msg, int len) break; case T30_ERR: /* TODO: Continue with the next message if MPS or EOM? */ - s->current_status = T30_ERR_RETRYDCN; + t30_set_status(s, T30_ERR_RETRYDCN); s->timer_t5 = 0; send_dcn(s); break; @@ -4410,12 +4413,12 @@ static void process_state_iv_eor_rnr(t30_state_t *s, const uint8_t *msg, int len break; case T30_ERR: /* TODO: Continue with the next message if MPS or EOM? */ - s->current_status = T30_ERR_RETRYDCN; + t30_set_status(s, T30_ERR_RETRYDCN); s->timer_t5 = 0; send_dcn(s); break; case T30_DCN: - s->current_status = T30_ERR_RX_DCNRRD; + t30_set_status(s, T30_ERR_RX_DCNRRD); disconnect(s); break; case T30_CRP: @@ -4877,17 +4880,17 @@ static void repeat_last_command(t30_state_t *s) { case T30_STATE_D_POST_TCF: /* Received no response to DCS or TCF */ - s->current_status = T30_ERR_TX_PHBDEAD; + t30_set_status(s, T30_ERR_TX_PHBDEAD); break; case T30_STATE_II_Q: case T30_STATE_IV_PPS_NULL: case T30_STATE_IV_PPS_Q: /* No response after sending a page */ - s->current_status = T30_ERR_TX_PHDDEAD; + t30_set_status(s, T30_ERR_TX_PHDDEAD); break; default: /* Disconnected after permitted retries */ - s->current_status = T30_ERR_RETRYDCN; + t30_set_status(s, T30_ERR_RETRYDCN); break; } send_dcn(s); @@ -5068,7 +5071,7 @@ static void timer_t2_t4_stop(t30_state_t *s) static void timer_t0_expired(t30_state_t *s) { span_log(&s->logging, SPAN_LOG_FLOW, "T0 expired in state %d\n", s->state); - s->current_status = T30_ERR_T0_EXPIRED; + t30_set_status(s, T30_ERR_T0_EXPIRED); /* Just end the call */ disconnect(s); } @@ -5080,7 +5083,7 @@ static void timer_t1_expired(t30_state_t *s) /* The initial connection establishment has timeout out. In other words, we have been unable to communicate successfully with a remote machine. It is time to abandon the call. */ - s->current_status = T30_ERR_T1_EXPIRED; + t30_set_status(s, T30_ERR_T1_EXPIRED); switch (s->state) { case T30_STATE_T: @@ -5133,33 +5136,33 @@ static void timer_t2_expired(t30_state_t *s) case T30_STATE_F_DOC_ECM: case T30_STATE_F_DOC_NON_ECM: /* While waiting for FAX page */ - s->current_status = T30_ERR_RX_T2EXPFAX; + t30_set_status(s, T30_ERR_RX_T2EXPFAX); break; case T30_STATE_F_POST_DOC_ECM: case T30_STATE_F_POST_DOC_NON_ECM: /* While waiting for next FAX page */ /* Figure 5-2b/T.30 and note 7 says we should allow 1 to 3 tries at this point. The way we work now is effectively hard coding a 1 try limit */ - s->current_status = T30_ERR_RX_T2EXPMPS; + t30_set_status(s, T30_ERR_RX_T2EXPMPS); break; #if 0 case ??????: /* While waiting for DCN */ - s->current_status = T30_ERR_RX_T2EXPDCN; + t30_set_status(s, T30_ERR_RX_T2EXPDCN); break; case ??????: /* While waiting for phase D */ - s->current_status = T30_ERR_RX_T2EXPD; + t30_set_status(s, T30_ERR_RX_T2EXPD); break; #endif case T30_STATE_IV_PPS_RNR: case T30_STATE_IV_EOR_RNR: /* While waiting for RR command */ - s->current_status = T30_ERR_RX_T2EXPRR; + t30_set_status(s, T30_ERR_RX_T2EXPRR); break; case T30_STATE_R: /* While waiting for NSS, DCS or MCF */ - s->current_status = T30_ERR_RX_T2EXP; + t30_set_status(s, T30_ERR_RX_T2EXP); break; case T30_STATE_F_FTT: break; @@ -5172,7 +5175,7 @@ static void timer_t2_expired(t30_state_t *s) static void timer_t1a_expired(t30_state_t *s) { span_log(&s->logging, SPAN_LOG_FLOW, "T1A expired in phase %s, state %d. An HDLC frame lasted too long.\n", phase_names[s->phase], s->state); - s->current_status = T30_ERR_HDLC_CARRIER; + t30_set_status(s, T30_ERR_HDLC_CARRIER); disconnect(s); } /*- End of function --------------------------------------------------------*/ @@ -5180,7 +5183,7 @@ static void timer_t1a_expired(t30_state_t *s) static void timer_t2a_expired(t30_state_t *s) { span_log(&s->logging, SPAN_LOG_FLOW, "T2A expired in phase %s, state %d. An HDLC frame lasted too long.\n", phase_names[s->phase], s->state); - s->current_status = T30_ERR_HDLC_CARRIER; + t30_set_status(s, T30_ERR_HDLC_CARRIER); disconnect(s); } /*- End of function --------------------------------------------------------*/ @@ -5195,7 +5198,7 @@ static void timer_t2b_expired(t30_state_t *s) static void timer_t3_expired(t30_state_t *s) { span_log(&s->logging, SPAN_LOG_FLOW, "T3 expired in phase %s, state %d\n", phase_names[s->phase], s->state); - s->current_status = T30_ERR_T3_EXPIRED; + t30_set_status(s, T30_ERR_T3_EXPIRED); disconnect(s); } /*- End of function --------------------------------------------------------*/ @@ -5219,7 +5222,7 @@ static void timer_t4_expired(t30_state_t *s) static void timer_t4a_expired(t30_state_t *s) { span_log(&s->logging, SPAN_LOG_FLOW, "T4A expired in phase %s, state %d. An HDLC frame lasted too long.\n", phase_names[s->phase], s->state); - s->current_status = T30_ERR_HDLC_CARRIER; + t30_set_status(s, T30_ERR_HDLC_CARRIER); disconnect(s); } /*- End of function --------------------------------------------------------*/ @@ -5235,7 +5238,7 @@ static void timer_t5_expired(t30_state_t *s) { /* Give up waiting for the receiver to become ready in error correction mode */ span_log(&s->logging, SPAN_LOG_FLOW, "T5 expired in phase %s, state %d\n", phase_names[s->phase], s->state); - s->current_status = T30_ERR_TX_T5EXP; + t30_set_status(s, T30_ERR_TX_T5EXP); } /*- End of function --------------------------------------------------------*/ @@ -5382,7 +5385,7 @@ static void t30_non_ecm_rx_status(void *user_data, int status) case T30_STATE_F_POST_DOC_NON_ECM: /* Page ended cleanly */ if (s->current_status == T30_ERR_RX_NOCARRIER) - s->current_status = T30_ERR_OK; + t30_set_status(s, T30_ERR_OK); break; default: /* We should be receiving a document right now, but it did not end cleanly. */ @@ -5395,12 +5398,12 @@ static void t30_non_ecm_rx_status(void *user_data, int status) set_phase(s, T30_PHASE_D_RX); timer_t2_start(s); if (s->current_status == T30_ERR_RX_NOCARRIER) - s->current_status = T30_ERR_OK; + t30_set_status(s, T30_ERR_OK); } else { span_log(&s->logging, SPAN_LOG_WARNING, "Non-ECM carrier not found\n"); - s->current_status = T30_ERR_RX_NOCARRIER; + t30_set_status(s, T30_ERR_RX_NOCARRIER); } break; } @@ -5697,13 +5700,13 @@ static void t30_hdlc_rx_status(void *user_data, int status) timer_t2_start(s); /* We at least trained, so any missing carrier status is out of date */ if (s->current_status == T30_ERR_RX_NOCARRIER) - s->current_status = T30_ERR_OK; + t30_set_status(s, T30_ERR_OK); } else { /* Either there was no image carrier, or we failed to train to it. */ span_log(&s->logging, SPAN_LOG_WARNING, "ECM carrier not found\n"); - s->current_status = T30_ERR_RX_NOCARRIER; + t30_set_status(s, T30_ERR_RX_NOCARRIER); } } if (s->next_phase != T30_PHASE_IDLE) @@ -6235,7 +6238,7 @@ SPAN_DECLARE(void) t30_terminate(t30_state_t *s) break; default: /* The call terminated prematurely. */ - s->current_status = T30_ERR_CALLDROPPED; + t30_set_status(s, T30_ERR_CALLDROPPED); break; } if (s->phase_e_handler) diff --git a/libs/spandsp/src/t30_api.c b/libs/spandsp/src/t30_api.c index 707f5fe44e..8ba35e5732 100644 --- a/libs/spandsp/src/t30_api.c +++ b/libs/spandsp/src/t30_api.c @@ -750,7 +750,11 @@ SPAN_DECLARE(int) t30_set_supported_t30_features(t30_state_t *s, int supported_t SPAN_DECLARE(void) t30_set_status(t30_state_t *s, int status) { - s->current_status = status; + if (s->current_status != status) + { + span_log(&s->logging, SPAN_LOG_FLOW, "Status changing to '%s'\n", t30_completion_code_to_str(status)); + s->current_status = status; + } } /*- End of function --------------------------------------------------------*/ diff --git a/libs/spandsp/src/t31.c b/libs/spandsp/src/t31.c index 6839b0efcc..bc18a72e59 100644 --- a/libs/spandsp/src/t31.c +++ b/libs/spandsp/src/t31.c @@ -1345,7 +1345,7 @@ static void hdlc_tx_underflow(void *user_data) { s->hdlc_tx.final = FALSE; /* Schedule an orderly shutdown of the modem */ - hdlc_tx_frame(&(s->audio.modems.hdlc_tx), NULL, 0); + hdlc_tx_frame(&s->audio.modems.hdlc_tx, NULL, 0); } else { @@ -1542,9 +1542,9 @@ static void t31_v21_rx(t31_state_t *s) s->hdlc_tx.final = FALSE; s->hdlc_tx.len = 0; s->dled = FALSE; - hdlc_rx_init(&(s->audio.modems.hdlc_rx), FALSE, TRUE, HDLC_FRAMING_OK_THRESHOLD, hdlc_accept_frame, s); - fsk_rx_init(&(s->audio.modems.v21_rx), &preset_fsk_specs[FSK_V21CH2], FSK_FRAME_MODE_SYNC, (put_bit_func_t) hdlc_rx_put_bit, &(s->audio.modems.hdlc_rx)); - fsk_rx_signal_cutoff(&(s->audio.modems.v21_rx), -39.09f); + hdlc_rx_init(&s->audio.modems.hdlc_rx, FALSE, TRUE, HDLC_FRAMING_OK_THRESHOLD, hdlc_accept_frame, s); + fsk_rx_init(&s->audio.modems.v21_rx, &preset_fsk_specs[FSK_V21CH2], FSK_FRAME_MODE_SYNC, (put_bit_func_t) hdlc_rx_put_bit, &s->audio.modems.hdlc_rx); + fsk_rx_signal_cutoff(&s->audio.modems.v21_rx, -39.09f); s->at_state.transmit = TRUE; } /*- End of function --------------------------------------------------------*/ @@ -1678,8 +1678,8 @@ static int restart_modem(t31_state_t *s, int new_modem) } else { - v17_tx_restart(&t->v17_tx, s->bit_rate, FALSE, s->short_train); - set_tx_handler(s, (span_tx_handler_t *) &v17_tx, &t->v17_tx); + v17_tx_restart(&t->fast_modems.v17_tx, s->bit_rate, FALSE, s->short_train); + set_tx_handler(s, (span_tx_handler_t *) &v17_tx, &t->fast_modems.v17_tx); set_next_tx_handler(s, (span_tx_handler_t *) NULL, NULL); } s->tx.out_bytes = 0; @@ -1690,7 +1690,7 @@ static int restart_modem(t31_state_t *s, int new_modem) if (!s->t38_mode) { set_rx_handler(s, (span_rx_handler_t *) &v17_v21_rx, (span_rx_fillin_handler_t *) &v17_v21_rx_fillin, s); - v17_rx_restart(&t->v17_rx, s->bit_rate, s->short_train); + v17_rx_restart(&t->fast_modems.v17_rx, s->bit_rate, s->short_train); /* Allow for +FCERROR/+FRH:3 */ t31_v21_rx(s); } @@ -1715,8 +1715,8 @@ static int restart_modem(t31_state_t *s, int new_modem) } else { - v27ter_tx_restart(&t->v27ter_tx, s->bit_rate, FALSE); - set_tx_handler(s, (span_tx_handler_t *) &v27ter_tx, &t->v27ter_tx); + v27ter_tx_restart(&t->fast_modems.v27ter_tx, s->bit_rate, FALSE); + set_tx_handler(s, (span_tx_handler_t *) &v27ter_tx, &t->fast_modems.v27ter_tx); set_next_tx_handler(s, (span_tx_handler_t *) NULL, NULL); } s->tx.out_bytes = 0; @@ -1727,7 +1727,7 @@ static int restart_modem(t31_state_t *s, int new_modem) if (!s->t38_mode) { set_rx_handler(s, (span_rx_handler_t *) &v27ter_v21_rx, (span_rx_fillin_handler_t *) &v27ter_v21_rx_fillin, s); - v27ter_rx_restart(&t->v27ter_rx, s->bit_rate, FALSE); + v27ter_rx_restart(&t->fast_modems.v27ter_rx, s->bit_rate, FALSE); /* Allow for +FCERROR/+FRH:3 */ t31_v21_rx(s); } @@ -1752,8 +1752,8 @@ static int restart_modem(t31_state_t *s, int new_modem) } else { - v29_tx_restart(&t->v29_tx, s->bit_rate, FALSE); - set_tx_handler(s, (span_tx_handler_t *) &v29_tx, &t->v29_tx); + v29_tx_restart(&t->fast_modems.v29_tx, s->bit_rate, FALSE); + set_tx_handler(s, (span_tx_handler_t *) &v29_tx, &t->fast_modems.v29_tx); set_next_tx_handler(s, (span_tx_handler_t *) NULL, NULL); } s->tx.out_bytes = 0; @@ -1764,7 +1764,7 @@ static int restart_modem(t31_state_t *s, int new_modem) if (!s->t38_mode) { set_rx_handler(s, (span_rx_handler_t *) &v29_v21_rx, (span_rx_fillin_handler_t *) &v29_v21_rx_fillin, s); - v29_rx_restart(&t->v29_rx, s->bit_rate, FALSE); + v29_rx_restart(&t->fast_modems.v29_rx, s->bit_rate, FALSE); /* Allow for +FCERROR/+FRH:3 */ t31_v21_rx(s); } @@ -1838,7 +1838,7 @@ static __inline__ void dle_unstuff_hdlc(t31_state_t *s, const char *stuffed, int } else { - hdlc_tx_frame(&(s->audio.modems.hdlc_tx), s->hdlc_tx.buf, s->hdlc_tx.len); + hdlc_tx_frame(&s->audio.modems.hdlc_tx, s->hdlc_tx.buf, s->hdlc_tx.len); s->hdlc_tx.len = 0; } } @@ -1929,7 +1929,7 @@ static int process_class1_cmd(at_state_t *t, void *user_data, int direction, int if (s->t38_mode) s->t38_fe.next_tx_samples = s->t38_fe.samples + ms_to_samples(val*10); else - silence_gen_alter(&(s->audio.modems.silence_gen), ms_to_samples(val*10)); + silence_gen_alter(&s->audio.modems.silence_gen, ms_to_samples(val*10)); s->at_state.transmit = TRUE; } else @@ -2162,8 +2162,8 @@ SPAN_DECLARE(int) t31_at_rx(t31_state_t *s, const char *t, int len) if (s->tx.out_bytes) { /* Make room for new data in existing data buffer. */ - s->tx.in_bytes = &(s->tx.data[s->tx.in_bytes]) - &(s->tx.data[s->tx.out_bytes]); - memmove(&(s->tx.data[0]), &(s->tx.data[s->tx.out_bytes]), s->tx.in_bytes); + s->tx.in_bytes = &s->tx.data[s->tx.in_bytes] - &s->tx.data[s->tx.out_bytes]; + memmove(&s->tx.data[0], &s->tx.data[s->tx.out_bytes], s->tx.in_bytes); s->tx.out_bytes = 0; } dle_unstuff(s, t, len); @@ -2233,7 +2233,7 @@ static int cng_rx(void *user_data, const int16_t amp[], int len) } else { - fsk_rx(&(s->audio.modems.v21_rx), amp, len); + fsk_rx(&s->audio.modems.v21_rx, amp, len); } return 0; } @@ -2246,13 +2246,13 @@ static int v17_v21_rx(void *user_data, const int16_t amp[], int len) t = (t31_state_t *) user_data; s = &t->audio.modems; - v17_rx(&s->v17_rx, amp, len); + v17_rx(&s->fast_modems.v17_rx, amp, len); if (t->at_state.rx_trained) { /* The fast modem has trained, so we no longer need to run the slow one in parallel. */ - span_log(&t->logging, SPAN_LOG_FLOW, "Switching from V.17 + V.21 to V.17 (%.2fdBm0)\n", v17_rx_signal_power(&s->v17_rx)); - set_rx_handler(t, (span_rx_handler_t *) &v17_rx, (span_rx_fillin_handler_t *) &v17_rx_fillin, &s->v17_rx); + span_log(&t->logging, SPAN_LOG_FLOW, "Switching from V.17 + V.21 to V.17 (%.2fdBm0)\n", v17_rx_signal_power(&s->fast_modems.v17_rx)); + set_rx_handler(t, (span_rx_handler_t *) &v17_rx, (span_rx_fillin_handler_t *) &v17_rx_fillin, &s->fast_modems.v17_rx); } else { @@ -2276,7 +2276,7 @@ static int v17_v21_rx_fillin(void *user_data, int len) t = (t31_state_t *) user_data; s = &t->audio.modems; - v17_rx_fillin(&s->v17_rx, len); + v17_rx_fillin(&s->fast_modems.v17_rx, len); fsk_rx_fillin(&s->v21_rx, len); return 0; } @@ -2289,13 +2289,13 @@ static int v27ter_v21_rx(void *user_data, const int16_t amp[], int len) t = (t31_state_t *) user_data; s = &t->audio.modems; - v27ter_rx(&s->v27ter_rx, amp, len); + v27ter_rx(&s->fast_modems.v27ter_rx, amp, len); if (t->at_state.rx_trained) { /* The fast modem has trained, so we no longer need to run the slow one in parallel. */ - span_log(&t->logging, SPAN_LOG_FLOW, "Switching from V.27ter + V.21 to V.27ter (%.2fdBm0)\n", v27ter_rx_signal_power(&s->v27ter_rx)); - set_rx_handler(t, (span_rx_handler_t *) &v27ter_rx, (span_rx_fillin_handler_t *) &v27ter_rx_fillin, &s->v27ter_rx); + span_log(&t->logging, SPAN_LOG_FLOW, "Switching from V.27ter + V.21 to V.27ter (%.2fdBm0)\n", v27ter_rx_signal_power(&s->fast_modems.v27ter_rx)); + set_rx_handler(t, (span_rx_handler_t *) &v27ter_rx, (span_rx_fillin_handler_t *) &v27ter_rx_fillin, &s->fast_modems.v27ter_rx); } else { @@ -2319,7 +2319,7 @@ static int v27ter_v21_rx_fillin(void *user_data, int len) t = (t31_state_t *) user_data; s = &t->audio.modems; - v27ter_rx_fillin(&s->v27ter_rx, len); + v27ter_rx_fillin(&s->fast_modems.v27ter_rx, len); fsk_rx_fillin(&s->v21_rx, len); return 0; } @@ -2332,13 +2332,13 @@ static int v29_v21_rx(void *user_data, const int16_t amp[], int len) t = (t31_state_t *) user_data; s = &t->audio.modems; - v29_rx(&s->v29_rx, amp, len); + v29_rx(&s->fast_modems.v29_rx, amp, len); if (t->at_state.rx_trained) { /* The fast modem has trained, so we no longer need to run the slow one in parallel. */ - span_log(&s->logging, SPAN_LOG_FLOW, "Switching from V.29 + V.21 to V.29 (%.2fdBm0)\n", v29_rx_signal_power(&s->v29_rx)); - set_rx_handler(t, (span_rx_handler_t *) &v29_rx, (span_rx_fillin_handler_t *) &v29_rx_fillin, &s->v29_rx); + span_log(&s->logging, SPAN_LOG_FLOW, "Switching from V.29 + V.21 to V.29 (%.2fdBm0)\n", v29_rx_signal_power(&s->fast_modems.v29_rx)); + set_rx_handler(t, (span_rx_handler_t *) &v29_rx, (span_rx_fillin_handler_t *) &v29_rx_fillin, &s->fast_modems.v29_rx); } else { @@ -2362,7 +2362,7 @@ static int v29_v21_rx_fillin(void *user_data, int len) t = (t31_state_t *) user_data; s = &t->audio.modems; - v29_rx_fillin(&s->v29_rx, len); + v29_rx_fillin(&s->fast_modems.v29_rx, len); fsk_rx_fillin(&s->v21_rx, len); return 0; } @@ -2382,7 +2382,7 @@ SPAN_DECLARE_NONSTD(int) t31_rx(t31_state_t *s, int16_t amp[], int len) for (i = 0; i < len; i++) { /* Clean up any DC influence. */ - power = power_meter_update(&(s->audio.rx_power), amp[i] - s->audio.last_sample); + power = power_meter_update(&s->audio.rx_power, amp[i] - s->audio.last_sample); s->audio.last_sample = amp[i]; if (power > s->audio.silence_threshold_power) { @@ -2441,15 +2441,15 @@ SPAN_DECLARE_NONSTD(int) t31_rx_fillin(t31_state_t *s, int len) break; case FAX_MODEM_V27TER_RX: /* TODO: what about FSK in the early stages */ - len = v27ter_rx_fillin(&s->audio.modems.v27ter_rx, len); + len = v27ter_rx_fillin(&s->audio.modems.fast_modems.v27ter_rx, len); break; case FAX_MODEM_V29_RX: /* TODO: what about FSK in the early stages */ - len = v29_rx_fillin(&s->audio.modems.v29_rx, len); + len = v29_rx_fillin(&s->audio.modems.fast_modems.v29_rx, len); break; case FAX_MODEM_V17_RX: /* TODO: what about FSK in the early stages */ - len = v17_rx_fillin(&s->audio.modems.v17_rx, len); + len = v17_rx_fillin(&s->audio.modems.fast_modems.v17_rx, len); break; } return 0; @@ -2465,7 +2465,7 @@ static int set_next_tx_type(t31_state_t *s) return 0; } /* There is nothing else to change to, so use zero length silence */ - silence_gen_alter(&(s->audio.modems.silence_gen), 0); + silence_gen_alter(&s->audio.modems.silence_gen, 0); set_tx_handler(s, (span_tx_handler_t *) &silence_gen, &s->audio.modems.silence_gen); set_next_tx_handler(s, (span_tx_handler_t *) NULL, NULL); return -1; @@ -2582,18 +2582,8 @@ static int t31_t38_fe_init(t31_state_t *t, t->hdlc_tx.ptr = 0; - hdlc_tx_init(&s->hdlc_tx_term, - FALSE, - 1, - FALSE, - NULL, - NULL); - hdlc_rx_init(&s->hdlc_rx_term, - FALSE, - TRUE, - 2, - NULL, - NULL); + hdlc_tx_init(&s->hdlc_tx_term, FALSE, 1, FALSE, NULL, NULL); + hdlc_rx_init(&s->hdlc_rx_term, FALSE, TRUE, 2, NULL, NULL); return 0; } /*- End of function --------------------------------------------------------*/ @@ -2650,14 +2640,10 @@ SPAN_DECLARE(t31_state_t *) t31_init(t31_state_t *s, v8_parms.pstn_access = 0; v8_parms.nsf = -1; v8_parms.t66 = -1; - v8_init(&s->audio.v8, - FALSE, - &v8_parms, - v8_handler, - s); + v8_init(&s->audio.v8, FALSE, &v8_parms, v8_handler, s); #endif - power_meter_init(&(s->audio.rx_power), 4); + power_meter_init(&s->audio.rx_power, 4); s->audio.last_sample = 0; s->audio.silence_threshold_power = power_meter_level_dbm0(-36); s->at_state.rx_signal_present = FALSE; @@ -2682,9 +2668,7 @@ SPAN_DECLARE(t31_state_t *) t31_init(t31_state_t *s, s->at_state.dte_inactivity_timeout = DEFAULT_DTE_TIMEOUT; if (tx_t38_packet_handler) { - t31_t38_fe_init(s, - tx_t38_packet_handler, - tx_t38_packet_user_data); + t31_t38_fe_init(s, tx_t38_packet_handler, tx_t38_packet_user_data); t31_set_t38_config(s, FALSE); } s->t38_mode = FALSE; diff --git a/libs/spandsp/src/t35.c b/libs/spandsp/src/t35.c index 9d525b5e36..0dd2c89dfd 100644 --- a/libs/spandsp/src/t35.c +++ b/libs/spandsp/src/t35.c @@ -92,271 +92,21 @@ typedef struct const model_data_t *known_models; } nsf_data_t; -const char *t35_country_codes[256] = +/*! T.35 country codes */ +typedef struct { - "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)" -}; + /*! 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} }; @@ -371,7 +121,7 @@ static const model_data_t Brother[] = 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"}, @@ -520,389 +270,672 @@ static const model_data_t Muratec48[] = * 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}, - - /* 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}, - - /* France */ - {"\xBC\x53\x01", 3, "Minolta", FALSE, NULL}, - - /* 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}, - - /* 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}, - - /* 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\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} }; -#if 0 -SPAN_DECLARE(void) nsf_find_station_id(int reverse_order) +static const nsf_data_t vendor_20[] = { - const char *id = NULL; - int idSize = 0; - const char *maxId = NULL; - int maxIdSize = 0; - const char *p; + /* Germany */ + {"\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} +}; - /* Trying to find the longest printable ASCII sequence */ - for (p = (const char *) nsf + T35_VENDOR_ID_LEN, *end = p + nsf.length(); - p < end; - p++) +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 */ + {"\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 */ + {"\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 */ + {"\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} +}; + +static const country_code_t t35_country_codes[255] = +{ + {"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} +}; + +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 (maxIdSize >= min_id_size) + 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) { - stationId.resize(0); - const char *p; - int dir; - - if (reverseOrder) - { - p = maxId + maxIdSize - 1; - dir = -1; - } - else - { - p = maxId; - dir = 1; - } - for (int i = 0; i < maxIdSize; i++) - { - stationId.append(*p); - p += dir; - } - station_id_decoded = TRUE; + 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 ((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) + { + /* 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 --------------------------------------------------------*/ + +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) + { + return p; + } + } + 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 ------------------------------------------------------------*/ diff --git a/libs/spandsp/src/t38_core.c b/libs/spandsp/src/t38_core.c index 55b524af61..67a53ae707 100644 --- a/libs/spandsp/src/t38_core.c +++ b/libs/spandsp/src/t38_core.c @@ -81,13 +81,13 @@ static const struct { 215000, 1393000, 200000}, /* T38_IND_V17_12000_LONG_TRAINING */ { 215000, 142000, 200000}, /* T38_IND_V17_14400_SHORT_TRAINING */ { 215000, 1393000, 200000}, /* T38_IND_V17_14400_LONG_TRAINING */ - { 215000, 0, 0}, /* T38_IND_V8_ANSAM */ - { 215000, 0, 0}, /* T38_IND_V8_SIGNAL */ - { 215000, 0, 0}, /* T38_IND_V34_CNTL_CHANNEL_1200 */ - { 215000, 0, 0}, /* T38_IND_V34_PRI_CHANNEL */ - { 215000, 0, 0}, /* T38_IND_V34_CC_RETRAIN */ - { 215000, 0, 0}, /* T38_IND_V33_12000_TRAINING */ - { 215000, 0, 0} /* T38_IND_V33_14400_TRAINING */ + { 0, 0, 0}, /* T38_IND_V8_ANSAM */ + { 0, 0, 0}, /* T38_IND_V8_SIGNAL */ + { 0, 0, 200000}, /* T38_IND_V34_CNTL_CHANNEL_1200 */ + { 0, 0, 200000}, /* T38_IND_V34_PRI_CHANNEL */ + { 0, 0, 0}, /* T38_IND_V34_CC_RETRAIN */ + { 215000, 0, 200000}, /* T38_IND_V33_12000_TRAINING */ + { 215000, 0, 200000} /* T38_IND_V33_14400_TRAINING */ }; SPAN_DECLARE(const char *) t38_indicator_to_str(int indicator) @@ -325,15 +325,17 @@ static __inline__ int classify_seq_no_offset(int expected, int actual) } /*- End of function --------------------------------------------------------*/ -SPAN_DECLARE_NONSTD(int) t38_core_rx_ifp_packet(t38_core_state_t *s, const uint8_t *buf, int len, uint16_t seq_no) +SPAN_DECLARE_NONSTD(int) t38_core_rx_ifp_stream(t38_core_state_t *s, const uint8_t *buf, int len, uint16_t log_seq_no) { int i; int t30_indicator; int t30_data; + int prev_ptr; int ptr; int other_half; int numocts; - int log_seq_no; + int pkt_len; + int ret; const uint8_t *msg; unsigned int count; unsigned int t30_field_type; @@ -342,18 +344,282 @@ SPAN_DECLARE_NONSTD(int) t38_core_rx_ifp_packet(t38_core_state_t *s, const uint8 uint8_t field_data_present; char tag[20]; - log_seq_no = (s->check_sequence_numbers) ? seq_no : s->rx_expected_seq_no; - if (span_log_test(&s->logging, SPAN_LOG_FLOW)) { sprintf(tag, "Rx %5d: IFP", log_seq_no); span_log_buf(&s->logging, SPAN_LOG_FLOW, tag, buf, len); } - if (len < 1) + ptr = 0; + pkt_len = len; + switch (s->data_transport_protocol) { - span_log(&s->logging, SPAN_LOG_PROTOCOL_WARNING, "Rx %5d: Bad packet length - %d\n", log_seq_no, len); - return -1; + case T38_TRANSPORT_TCP: + /* We don't know the actual packet length, so treat everythign we have as the packet */ + ret = 0; + break; + case T38_TRANSPORT_TCP_TPKT: + if (len >= 4) + { + /* Version */ + if (buf[0] != 3) + return -1; + /* Reserved */ + if (buf[1] != 0) + return -1; + /* Packet length - this includes the length of the header itself */ + pkt_len = (buf[2] << 8) | buf[3]; + if (len < pkt_len) + return 0; + ptr = 4; + } + ret = -1; + break; + default: + /* We know the actual packet length, and its the exact length of what we were passed. */ + ret = -1; + break; } + if ((ptr + 1) > pkt_len) + return ret; + data_field_present = buf[ptr] & 0x80; + type = (buf[ptr] >> 6) & 1; + switch (type) + { + case T38_TYPE_OF_MSG_T30_INDICATOR: + /* Indicators should never have a data field */ + if (data_field_present) + { + span_log(&s->logging, SPAN_LOG_PROTOCOL_WARNING, "Rx %5d: Data field with indicator\n", log_seq_no); + return -1; + } + /* Any received indicator should mean we no longer have a valid concept of "last received data/field type". */ + s->current_rx_data_type = -1; + s->current_rx_field_type = -1; + if ((buf[ptr] & 0x20)) + { + /* Extension */ + if ((ptr + 2) > pkt_len) + return ret; + t30_indicator = T38_IND_V8_ANSAM + (((buf[ptr] << 2) & 0x3C) | ((buf[ptr + 1] >> 6) & 0x3)); + if (t30_indicator > T38_IND_V33_14400_TRAINING) + { + span_log(&s->logging, SPAN_LOG_PROTOCOL_WARNING, "Rx %5d: Unknown indicator - %d\n", log_seq_no, t30_indicator); + return -1; + } + ptr += 2; + } + else + { + t30_indicator = (buf[ptr] >> 1) & 0xF; + ptr += 1; + } + span_log(&s->logging, SPAN_LOG_FLOW, "Rx %5d: indicator %s\n", log_seq_no, t38_indicator_to_str(t30_indicator)); + s->rx_indicator_handler(s, s->rx_user_data, t30_indicator); + /* This must come after the indicator handler, so the handler routine sees the existing state of the + indicator. */ + s->current_rx_indicator = t30_indicator; + break; + case T38_TYPE_OF_MSG_T30_DATA: + if ((buf[ptr] & 0x20)) + { + /* Extension */ + if ((ptr + 2) > pkt_len) + return ret; + t30_data = T38_DATA_V8 + (((buf[ptr] << 2) & 0x3C) | ((buf[ptr + 1] >> 6) & 0x3)); + if (t30_data > T38_DATA_V33_14400) + { + span_log(&s->logging, SPAN_LOG_PROTOCOL_WARNING, "Rx %5d: Unknown data type - %d\n", log_seq_no, t30_data); + return -1; + } + ptr += 2; + } + else + { + t30_data = (buf[ptr] >> 1) & 0xF; + if (t30_data > T38_DATA_V17_14400) + { + span_log(&s->logging, SPAN_LOG_PROTOCOL_WARNING, "Rx %5d: Unknown data type - %d\n", log_seq_no, t30_data); + return -1; + } + ptr += 1; + } + if (!data_field_present) + { + /* This is kinda weird, but I guess if the length checks out we accept it. */ + span_log(&s->logging, SPAN_LOG_PROTOCOL_WARNING, "Rx %5d: Data type with no data field\n", log_seq_no); + break; + } + if (ptr >= pkt_len) + return ret; + count = buf[ptr++]; + //printf("Count is %d\n", count); + /* Do a dummy run through the fields to check we have a complete and uncorrupted packet. */ + prev_ptr = ptr; + other_half = FALSE; + t30_field_type = 0; + for (i = 0; i < (int) count; i++) + { + if (ptr >= pkt_len) + return ret; + if (s->t38_version == 0) + { + /* The original version of T.38 with a typo in the ASN.1 spec. */ + if (other_half) + { + /* The lack of a data field in the previous message means + we are currently in the middle of an octet. */ + field_data_present = (buf[ptr] >> 3) & 1; + /* Decode field_type */ + t30_field_type = buf[ptr] & 0x7; + ptr++; + other_half = FALSE; + } + else + { + field_data_present = (buf[ptr] >> 7) & 1; + /* Decode field_type */ + t30_field_type = (buf[ptr] >> 4) & 0x7; + if (field_data_present) + ptr++; + else + other_half = TRUE; + } + if (t30_field_type > T38_FIELD_T4_NON_ECM_SIG_END) + { + span_log(&s->logging, SPAN_LOG_PROTOCOL_WARNING, "Rx %5d: Unknown field type - %d\n", log_seq_no, t30_field_type); + return -1; + } + } + else + { + field_data_present = (buf[ptr] >> 7) & 1; + /* Decode field_type */ + if ((buf[ptr] & 0x40)) + { + if ((ptr + 2) > pkt_len) + return ret; + t30_field_type = T38_FIELD_CM_MESSAGE + (((buf[ptr] << 2) & 0x3C) | ((buf[ptr + 1] >> 6) & 0x3)); + if (t30_field_type > T38_FIELD_V34RATE) + { + span_log(&s->logging, SPAN_LOG_PROTOCOL_WARNING, "Rx %5d: Unknown field type - %d\n", log_seq_no, t30_field_type); + return -1; + } + ptr += 2; + } + else + { + t30_field_type = (buf[ptr++] >> 3) & 0x7; + } + } + /* Decode field_data */ + if (field_data_present) + { + if ((ptr + 2) > pkt_len) + return ret; + numocts = ((buf[ptr] << 8) | buf[ptr + 1]) + 1; + msg = buf + ptr + 2; + ptr += numocts + 2; + } + else + { + numocts = 0; + msg = NULL; + } + if (ptr > pkt_len) + return ret; + } + /* Check if we finished mid byte in a version 0 packet. */ + if (other_half) + ptr++; + if (ptr > pkt_len) + return ret; + + /* Things look alright in the data, so lets run through the fields again, actually processing them. + There is no need to do all the error checking along the way on this pass. */ + ptr = prev_ptr; + other_half = FALSE; + for (i = 0; i < (int) count; i++) + { + if (s->t38_version == 0) + { + /* The original version of T.38 with a typo in the ASN.1 spec. */ + if (other_half) + { + /* The lack of a data field in the previous message means + we are currently in the middle of an octet. */ + field_data_present = (buf[ptr] >> 3) & 1; + /* Decode field_type */ + t30_field_type = buf[ptr] & 0x7; + ptr++; + other_half = FALSE; + } + else + { + field_data_present = (buf[ptr] >> 7) & 1; + /* Decode field_type */ + t30_field_type = (buf[ptr] >> 4) & 0x7; + if (field_data_present) + ptr++; + else + other_half = TRUE; + } + } + else + { + field_data_present = (buf[ptr] >> 7) & 1; + /* Decode field_type */ + if ((buf[ptr] & 0x40)) + { + t30_field_type = T38_FIELD_CM_MESSAGE + (((buf[ptr] << 2) & 0x3C) | ((buf[ptr + 1] >> 6) & 0x3)); + ptr += 2; + } + else + { + t30_field_type = (buf[ptr++] >> 3) & 0x7; + } + } + /* Decode field_data */ + if (field_data_present) + { + numocts = ((buf[ptr] << 8) | buf[ptr + 1]) + 1; + msg = buf + ptr + 2; + ptr += numocts + 2; + } + else + { + numocts = 0; + msg = NULL; + } + span_log(&s->logging, + SPAN_LOG_FLOW, + "Rx %5d: (%d) data %s/%s + %d byte(s)\n", + log_seq_no, + i, + t38_data_type_to_str(t30_data), + t38_field_type_to_str(t30_field_type), + numocts); + s->rx_data_handler(s, s->rx_user_data, t30_data, t30_field_type, msg, numocts); + s->current_rx_data_type = t30_data; + s->current_rx_field_type = t30_field_type; + } + /* Check if we finished mid byte in a version 0 packet. */ + if (other_half) + ptr++; + break; + } + if (ptr > pkt_len) + return ret; + return ptr; +} +/*- End of function --------------------------------------------------------*/ + +SPAN_DECLARE_NONSTD(int) t38_core_rx_ifp_packet(t38_core_state_t *s, const uint8_t *buf, int len, uint16_t seq_no) +{ + int log_seq_no; + int ptr; + + log_seq_no = (s->check_sequence_numbers) ? seq_no : s->rx_expected_seq_no; + if (s->check_sequence_numbers) { seq_no &= 0xFFFF; @@ -404,6 +670,11 @@ SPAN_DECLARE_NONSTD(int) t38_core_rx_ifp_packet(t38_core_state_t *s, const uint8 s->rx_expected_seq_no = seq_no; } } + if (len < 1) + { + span_log(&s->logging, SPAN_LOG_PROTOCOL_WARNING, "Rx %5d: Bad packet length - %d\n", log_seq_no, len); + return -1; + } /* The sequence numbering is defined as rolling from 0xFFFF to 0x0000. Some implementations of T.38 roll from 0xFFFF to 0x0001. Isn't standardisation a wonderful thing? The T.38 document specifies only a small fraction of what it should, yet then they actually nail @@ -414,201 +685,13 @@ SPAN_DECLARE_NONSTD(int) t38_core_rx_ifp_packet(t38_core_state_t *s, const uint8 luck a retry will ride over the problem. Rollovers don't occur that often. It takes quite a few FAX pages to reach rollover. */ s->rx_expected_seq_no = (s->rx_expected_seq_no + 1) & 0xFFFF; - data_field_present = (buf[0] >> 7) & 1; - type = (buf[0] >> 6) & 1; - ptr = 0; - switch (type) + + ptr = t38_core_rx_ifp_stream(s, buf, len, seq_no); + if (ptr != len) { - case T38_TYPE_OF_MSG_T30_INDICATOR: - /* Indicators should never have a data field */ - if (data_field_present) - { - span_log(&s->logging, SPAN_LOG_PROTOCOL_WARNING, "Rx %5d: Data field with indicator\n", log_seq_no); - return -1; - } - /* Any received indicator should mean we no longer have a valid concept of "last received data/field type". */ - s->current_rx_data_type = -1; - s->current_rx_field_type = -1; - if ((buf[0] & 0x20)) - { - /* Extension */ - if (len != 2) - { - span_log(&s->logging, SPAN_LOG_PROTOCOL_WARNING, "Rx %5d: Invalid length for indicator (A)\n", log_seq_no); - return -1; - } - t30_indicator = T38_IND_V8_ANSAM + (((buf[0] << 2) & 0x3C) | ((buf[1] >> 6) & 0x3)); - if (t30_indicator > T38_IND_V33_14400_TRAINING) - { - span_log(&s->logging, SPAN_LOG_PROTOCOL_WARNING, "Rx %5d: Unknown indicator - %d\n", log_seq_no, t30_indicator); - return -1; - } - } - else - { - if (len != 1) - { - span_log(&s->logging, SPAN_LOG_PROTOCOL_WARNING, "Rx %5d: Invalid length for indicator (B)\n", log_seq_no); - return -1; - } - t30_indicator = (buf[0] >> 1) & 0xF; - } - span_log(&s->logging, SPAN_LOG_FLOW, "Rx %5d: indicator %s\n", log_seq_no, t38_indicator_to_str(t30_indicator)); - s->rx_indicator_handler(s, s->rx_user_data, t30_indicator); - /* This must come after the indicator handler, so the handler routine sees the existing state of the - indicator. */ - s->current_rx_indicator = t30_indicator; - break; - case T38_TYPE_OF_MSG_T30_DATA: - if ((buf[0] & 0x20)) - { - /* Extension */ - if (len < 2) - { - span_log(&s->logging, SPAN_LOG_PROTOCOL_WARNING, "Rx %5d: Invalid length for data (A)\n", log_seq_no); - return -1; - } - t30_data = T38_DATA_V8 + (((buf[0] << 2) & 0x3C) | ((buf[1] >> 6) & 0x3)); - if (t30_data > T38_DATA_V33_14400) - { - span_log(&s->logging, SPAN_LOG_PROTOCOL_WARNING, "Rx %5d: Unknown data type - %d\n", log_seq_no, t30_data); - return -1; - } - ptr = 2; - } - else - { - t30_data = (buf[0] >> 1) & 0xF; - if (t30_data > T38_DATA_V17_14400) - { - span_log(&s->logging, SPAN_LOG_PROTOCOL_WARNING, "Rx %5d: Unknown data type - %d\n", log_seq_no, t30_data); - return -1; - } - ptr = 1; - } - if (!data_field_present) - { - /* This is kinda weird, but I guess if the length checks out we accept it. */ - span_log(&s->logging, SPAN_LOG_PROTOCOL_WARNING, "Rx %5d: Data type with no data field\n", log_seq_no); - if (ptr != len) - { - span_log(&s->logging, SPAN_LOG_PROTOCOL_WARNING, "Rx %5d: Invalid length for data (B)\n", log_seq_no); - return -1; - } - break; - } - if (ptr >= len) - { - span_log(&s->logging, SPAN_LOG_PROTOCOL_WARNING, "Rx %5d: Invalid length for data (C)\n", log_seq_no); - return -1; - } - count = buf[ptr++]; - //printf("Count is %d\n", count); - other_half = FALSE; - t30_field_type = 0; - for (i = 0; i < (int) count; i++) - { - if (ptr >= len) - { - span_log(&s->logging, SPAN_LOG_PROTOCOL_WARNING, "Rx %5d: Invalid length for data (D)\n", log_seq_no); - return -1; - } - if (s->t38_version == 0) - { - /* The original version of T.38 with a typo in the ASN.1 spec. */ - if (other_half) - { - /* The lack of a data field in the previous message means - we are currently in the middle of an octet. */ - field_data_present = (buf[ptr] >> 3) & 1; - /* Decode field_type */ - t30_field_type = buf[ptr] & 0x7; - ptr++; - other_half = FALSE; - } - else - { - field_data_present = (buf[ptr] >> 7) & 1; - /* Decode field_type */ - t30_field_type = (buf[ptr] >> 4) & 0x7; - if (field_data_present) - ptr++; - else - other_half = TRUE; - } - if (t30_field_type > T38_FIELD_T4_NON_ECM_SIG_END) - { - span_log(&s->logging, SPAN_LOG_PROTOCOL_WARNING, "Rx %5d: Unknown field type - %d\n", log_seq_no, t30_field_type); - return -1; - } - } - else - { - field_data_present = (buf[ptr] >> 7) & 1; - /* Decode field_type */ - if ((buf[ptr] & 0x40)) - { - if (ptr > len - 2) - { - span_log(&s->logging, SPAN_LOG_PROTOCOL_WARNING, "Rx %5d: Invalid length for data (E)\n", log_seq_no); - return -1; - } - t30_field_type = T38_FIELD_CM_MESSAGE + (((buf[ptr] << 2) & 0x3C) | ((buf[ptr + 1] >> 6) & 0x3)); - if (t30_field_type > T38_FIELD_V34RATE) - { - span_log(&s->logging, SPAN_LOG_PROTOCOL_WARNING, "Rx %5d: Unknown field type - %d\n", log_seq_no, t30_field_type); - return -1; - } - ptr += 2; - } - else - { - t30_field_type = (buf[ptr++] >> 3) & 0x7; - } - } - /* Decode field_data */ - if (field_data_present) - { - if (ptr > len - 2) - { - span_log(&s->logging, SPAN_LOG_PROTOCOL_WARNING, "Rx %5d: Invalid length for data (F)\n", log_seq_no); - return -1; - } - numocts = ((buf[ptr] << 8) | buf[ptr + 1]) + 1; - msg = buf + ptr + 2; - ptr += numocts + 2; - } - else - { - numocts = 0; - msg = NULL; - } - if (ptr > len) - { - span_log(&s->logging, SPAN_LOG_PROTOCOL_WARNING, "Rx %5d: Invalid length for data (G)\n", log_seq_no); - return -1; - } - span_log(&s->logging, - SPAN_LOG_FLOW, - "Rx %5d: (%d) data %s/%s + %d byte(s)\n", - log_seq_no, - i, - t38_data_type_to_str(t30_data), - t38_field_type_to_str(t30_field_type), - numocts); - s->rx_data_handler(s, s->rx_user_data, t30_data, t30_field_type, msg, numocts); - s->current_rx_data_type = t30_data; - s->current_rx_field_type = t30_field_type; - } - if (ptr != len) - { - if (s->t38_version != 0 || ptr != (len - 1) || !other_half) - { - span_log(&s->logging, SPAN_LOG_PROTOCOL_WARNING, "Rx %5d: Invalid length for data (H) - %d %d\n", log_seq_no, ptr, len); - return -1; - } - } - break; + if (ptr >= 0) + span_log(&s->logging, SPAN_LOG_PROTOCOL_WARNING, "Rx %5d: Invalid length for packet - %d %d\n", log_seq_no, ptr, len); + return -1; } return 0; } @@ -619,24 +702,37 @@ static int t38_encode_indicator(t38_core_state_t *s, uint8_t buf[], int indicato int len; /* Build the IFP packet */ + len = 0; + if (s->data_transport_protocol == T38_TRANSPORT_TCP_TPKT) + len = 4; + /* Data field not present */ /* Indicator packet */ /* Type of indicator */ if (indicator <= T38_IND_V17_14400_LONG_TRAINING) { - buf[0] = (uint8_t) (indicator << 1); - len = 1; + buf[len++] = (uint8_t) (indicator << 1); } else if (s->t38_version != 0 && indicator <= T38_IND_V33_14400_TRAINING) { - buf[0] = (uint8_t) (0x20 | (((indicator - T38_IND_V8_ANSAM) & 0xF) >> 2)); - buf[1] = (uint8_t) (((indicator - T38_IND_V8_ANSAM) << 6) & 0xFF); - len = 2; + buf[len++] = (uint8_t) (0x20 | (((indicator - T38_IND_V8_ANSAM) & 0xF) >> 2)); + buf[len++] = (uint8_t) (((indicator - T38_IND_V8_ANSAM) << 6) & 0xFF); } else { len = -1; } + if (s->data_transport_protocol == T38_TRANSPORT_TCP_TPKT) + { + /* Fill in the TPKT header (se RFC1006) */ + /* Version */ + buf[0] = 3; + /* Reserved */ + buf[1] = 0; + /* Packet length - this includes the length of the header itself */ + buf[2] = (len >> 8) & 0xFF; + buf[3] = len & 0xFF; + } return len; } /*- End of function --------------------------------------------------------*/ @@ -657,40 +753,31 @@ static int t38_encode_data(t38_core_state_t *s, uint8_t buf[], int data_type, co char tag[20]; /* Build the IFP packet */ + len = 0; + if (s->data_transport_protocol == T38_TRANSPORT_TCP_TPKT) + len = 4; /* There seems no valid reason why a packet would ever be generated without a data field present */ - data_field_present = TRUE; + data_field_present = (fields > 0) ? 0x80 : 0x00; - for (data_field_no = 0; data_field_no < fields; data_field_no++) - { - span_log(&s->logging, - SPAN_LOG_FLOW, - "Tx %5d: (%d) data %s/%s + %d byte(s)\n", - s->tx_seq_no, - data_field_no, - t38_data_type_to_str(data_type), - t38_field_type_to_str(field[data_field_no].field_type), - field[data_field_no].field_len); - } - data_field_no = 0; - len = 0; /* Data field present */ /* Data packet */ /* Type of data */ if (data_type <= T38_DATA_V17_14400) { - buf[len++] = (uint8_t) ((data_field_present << 7) | 0x40 | (data_type << 1)); + buf[len++] = (uint8_t) (data_field_present | 0x40 | (data_type << 1)); } else if (s->t38_version != 0 && data_type <= T38_DATA_V33_14400) { - buf[len++] = (uint8_t) ((data_field_present << 7) | 0x60 | (((data_type - T38_DATA_V8) & 0xF) >> 2)); + buf[len++] = (uint8_t) (data_field_present | 0x60 | (((data_type - T38_DATA_V8) & 0xF) >> 2)); buf[len++] = (uint8_t) (((data_type - T38_DATA_V8) << 6) & 0xFF); } else { return -1; } + if (data_field_present) { encoded_len = 0; @@ -763,7 +850,31 @@ static int t38_encode_data(t38_core_state_t *s, uint8_t buf[], int data_type, co data_field_no++; } } - while (fields != (int) encoded_len || fragment_len >= 16384); + while ((int) encoded_len != fields || fragment_len >= 16384); + } + + for (data_field_no = 0; data_field_no < fields; data_field_no++) + { + span_log(&s->logging, + SPAN_LOG_FLOW, + "Tx %5d: (%d) data %s/%s + %d byte(s)\n", + s->tx_seq_no, + data_field_no, + t38_data_type_to_str(data_type), + t38_field_type_to_str(field[data_field_no].field_type), + field[data_field_no].field_len); + } + + if (s->data_transport_protocol == T38_TRANSPORT_TCP_TPKT) + { + /* Fill in the TPKT header (se RFC1006) */ + /* Version */ + buf[0] = 3; + /* Reserved */ + buf[1] = 0; + /* Packet length - this includes the length of the header itself */ + buf[2] = (len >> 8) & 0xFF; + buf[3] = len & 0xFF; } if (span_log_test(&s->logging, SPAN_LOG_FLOW)) @@ -801,13 +912,16 @@ SPAN_DECLARE(int) t38_core_send_indicator(t38_core_state_t *s, int indicator) span_log(&s->logging, SPAN_LOG_FLOW, "Tx %5d: indicator %s\n", s->tx_seq_no, t38_indicator_to_str(indicator)); if (s->tx_packet_handler(s, s->tx_packet_user_data, buf, len, transmissions) < 0) { - span_log(&s->logging, SPAN_LOG_PROTOCOL_WARNING, "Tx Packet Handler Failure\n"); + span_log(&s->logging, SPAN_LOG_PROTOCOL_WARNING, "Tx packet handler failure\n"); return -1; } s->tx_seq_no = (s->tx_seq_no + 1) & 0xFFFF; - delay = modem_startup_time[indicator].training; - if (s->allow_for_tep) - delay += modem_startup_time[indicator].tep; + if (s->pace_transmission) + { + delay = modem_startup_time[indicator].training; + if (s->allow_for_tep) + delay += modem_startup_time[indicator].tep; + } } s->current_tx_indicator = indicator; } @@ -817,13 +931,17 @@ SPAN_DECLARE(int) t38_core_send_indicator(t38_core_state_t *s, int indicator) SPAN_DECLARE(int) t38_core_send_flags_delay(t38_core_state_t *s, int indicator) { - return modem_startup_time[indicator].flags; + if (s->pace_transmission) + return modem_startup_time[indicator].flags; + return 0; } /*- End of function --------------------------------------------------------*/ SPAN_DECLARE(int) t38_core_send_training_delay(t38_core_state_t *s, int indicator) { - return modem_startup_time[indicator].training; + if (s->pace_transmission) + return modem_startup_time[indicator].training; + return 0; } /*- End of function --------------------------------------------------------*/ @@ -843,7 +961,7 @@ SPAN_DECLARE(int) t38_core_send_data(t38_core_state_t *s, int data_type, int fie } if (s->tx_packet_handler(s, s->tx_packet_user_data, buf, len, s->category_control[category]) < 0) { - span_log(&s->logging, SPAN_LOG_PROTOCOL_WARNING, "Tx Packet Handler Failure\n"); + span_log(&s->logging, SPAN_LOG_PROTOCOL_WARNING, "Tx packet handler failure\n"); return -1; } s->tx_seq_no = (s->tx_seq_no + 1) & 0xFFFF; @@ -863,7 +981,7 @@ SPAN_DECLARE(int) t38_core_send_data_multi_field(t38_core_state_t *s, int data_t } if (s->tx_packet_handler(s, s->tx_packet_user_data, buf, len, s->category_control[category]) < 0) { - span_log(&s->logging, SPAN_LOG_PROTOCOL_WARNING, "Tx Packet Handler Failure\n"); + span_log(&s->logging, SPAN_LOG_PROTOCOL_WARNING, "Tx packet handler failure\n"); return -1; } s->tx_seq_no = (s->tx_seq_no + 1) & 0xFFFF; @@ -925,6 +1043,12 @@ SPAN_DECLARE(void) t38_set_sequence_number_handling(t38_core_state_t *s, int che } /*- End of function --------------------------------------------------------*/ +SPAN_DECLARE(void) t38_set_pace_transmission(t38_core_state_t *s, int pace_transmission) +{ + s->pace_transmission = pace_transmission; +} +/*- End of function --------------------------------------------------------*/ + SPAN_DECLARE(void) t38_set_tep_handling(t38_core_state_t *s, int allow_for_tep) { s->allow_for_tep = allow_for_tep; @@ -1003,6 +1127,7 @@ SPAN_DECLARE(t38_core_state_t *) t38_core_init(t38_core_state_t *s, s->max_datagram_size = 100; s->t38_version = 0; s->check_sequence_numbers = TRUE; + s->pace_transmission = TRUE; /* Set some defaults */ s->category_control[T38_PACKET_CATEGORY_INDICATOR] = 1; diff --git a/libs/spandsp/src/t38_gateway.c b/libs/spandsp/src/t38_gateway.c index 0626ac4086..03552efc41 100644 --- a/libs/spandsp/src/t38_gateway.c +++ b/libs/spandsp/src/t38_gateway.c @@ -159,14 +159,6 @@ enum DISBIT8 = 0x80 }; -enum -{ - T38_NONE, - T38_V27TER_RX, - T38_V29_RX, - T38_V17_RX -}; - enum { HDLC_FLAG_FINISHED = 0x01, @@ -256,7 +248,7 @@ static int v17_v21_rx_fillin(void *user_data, int len) t = (t38_gateway_state_t *) user_data; s = &t->audio.modems; - v17_rx_fillin(&s->v17_rx, len); + v17_rx_fillin(&s->fast_modems.v17_rx, len); fsk_rx_fillin(&s->v21_rx, len); return 0; } @@ -269,13 +261,13 @@ static int v17_v21_rx(void *user_data, const int16_t amp[], int len) t = (t38_gateway_state_t *) user_data; s = &t->audio.modems; - v17_rx(&s->v17_rx, amp, len); + v17_rx(&s->fast_modems.v17_rx, amp, len); if (s->rx_trained) { /* The fast modem has trained, so we no longer need to run the slow one in parallel. */ - span_log(&t->logging, SPAN_LOG_FLOW, "Switching from V.17 + V.21 to V.17 (%.2fdBm0)\n", v17_rx_signal_power(&s->v17_rx)); - set_rx_handler(t, (span_rx_handler_t *) &v17_rx, (span_rx_fillin_handler_t *) &v17_rx_fillin, &s->v17_rx); + span_log(&t->logging, SPAN_LOG_FLOW, "Switching from V.17 + V.21 to V.17 (%.2fdBm0)\n", v17_rx_signal_power(&s->fast_modems.v17_rx)); + set_rx_handler(t, (span_rx_handler_t *) &v17_rx, (span_rx_fillin_handler_t *) &v17_rx_fillin, &s->fast_modems.v17_rx); } else { @@ -299,7 +291,7 @@ static int v27ter_v21_rx_fillin(void *user_data, int len) t = (t38_gateway_state_t *) user_data; s = &t->audio.modems; - v27ter_rx_fillin(&s->v27ter_rx, len); + v27ter_rx_fillin(&s->fast_modems.v27ter_rx, len); fsk_rx_fillin(&s->v21_rx, len); return 0; } @@ -312,13 +304,13 @@ static int v27ter_v21_rx(void *user_data, const int16_t amp[], int len) t = (t38_gateway_state_t *) user_data; s = &t->audio.modems; - v27ter_rx(&s->v27ter_rx, amp, len); + v27ter_rx(&s->fast_modems.v27ter_rx, amp, len); if (s->rx_trained) { /* The fast modem has trained, so we no longer need to run the slow one in parallel. */ - span_log(&t->logging, SPAN_LOG_FLOW, "Switching from V.27ter + V.21 to V.27ter (%.2fdBm0)\n", v27ter_rx_signal_power(&s->v27ter_rx)); - set_rx_handler(t, (span_rx_handler_t *) &v27ter_rx, (span_rx_fillin_handler_t *) &v27ter_v21_rx_fillin, &s->v27ter_rx); + span_log(&t->logging, SPAN_LOG_FLOW, "Switching from V.27ter + V.21 to V.27ter (%.2fdBm0)\n", v27ter_rx_signal_power(&s->fast_modems.v27ter_rx)); + set_rx_handler(t, (span_rx_handler_t *) &v27ter_rx, (span_rx_fillin_handler_t *) &v27ter_v21_rx_fillin, &s->fast_modems.v27ter_rx); } else { @@ -342,7 +334,7 @@ static int v29_v21_rx_fillin(void *user_data, int len) t = (t38_gateway_state_t *) user_data; s = &t->audio.modems; - v29_rx_fillin(&s->v29_rx, len); + v29_rx_fillin(&s->fast_modems.v29_rx, len); fsk_rx_fillin(&s->v21_rx, len); return 0; } @@ -355,13 +347,13 @@ static int v29_v21_rx(void *user_data, const int16_t amp[], int len) t = (t38_gateway_state_t *) user_data; s = &t->audio.modems; - v29_rx(&s->v29_rx, amp, len); + v29_rx(&s->fast_modems.v29_rx, amp, len); if (s->rx_trained) { /* The fast modem has trained, so we no longer need to run the slow one in parallel. */ - span_log(&t->logging, SPAN_LOG_FLOW, "Switching from V.29 + V.21 to V.29 (%.2fdBm0)\n", v29_rx_signal_power(&s->v29_rx)); - set_rx_handler(t, (span_rx_handler_t *) &v29_rx, (span_rx_fillin_handler_t *) &v29_rx_fillin, &s->v29_rx); + span_log(&t->logging, SPAN_LOG_FLOW, "Switching from V.29 + V.21 to V.29 (%.2fdBm0)\n", v29_rx_signal_power(&s->fast_modems.v29_rx)); + set_rx_handler(t, (span_rx_handler_t *) &v29_rx, (span_rx_fillin_handler_t *) &v29_rx_fillin, &s->fast_modems.v29_rx); } else { @@ -542,10 +534,10 @@ static int set_next_tx_type(t38_gateway_state_t *s) } /*endswitch*/ silence_gen_alter(&t->silence_gen, ms_to_samples(75)); - v27ter_tx_restart(&t->v27ter_tx, t->tx_bit_rate, t->use_tep); - v27ter_tx_set_get_bit(&t->v27ter_tx, get_bit_func, get_bit_user_data); + v27ter_tx_restart(&t->fast_modems.v27ter_tx, t->tx_bit_rate, t->use_tep); + v27ter_tx_set_get_bit(&t->fast_modems.v27ter_tx, get_bit_func, get_bit_user_data); set_tx_handler(s, (span_tx_handler_t *) &silence_gen, &t->silence_gen); - set_next_tx_handler(s, (span_tx_handler_t *) &v27ter_tx, &t->v27ter_tx); + set_next_tx_handler(s, (span_tx_handler_t *) &v27ter_tx, &t->fast_modems.v27ter_tx); set_rx_active(s, TRUE); break; case T38_IND_V29_7200_TRAINING: @@ -561,10 +553,10 @@ static int set_next_tx_type(t38_gateway_state_t *s) } /*endswitch*/ silence_gen_alter(&t->silence_gen, ms_to_samples(75)); - v29_tx_restart(&t->v29_tx, t->tx_bit_rate, t->use_tep); - v29_tx_set_get_bit(&t->v29_tx, get_bit_func, get_bit_user_data); + v29_tx_restart(&t->fast_modems.v29_tx, t->tx_bit_rate, t->use_tep); + v29_tx_set_get_bit(&t->fast_modems.v29_tx, get_bit_func, get_bit_user_data); set_tx_handler(s, (span_tx_handler_t *) &silence_gen, &t->silence_gen); - set_next_tx_handler(s, (span_tx_handler_t *) &v29_tx, &t->v29_tx); + set_next_tx_handler(s, (span_tx_handler_t *) &v29_tx, &t->fast_modems.v29_tx); set_rx_active(s, TRUE); break; case T38_IND_V17_7200_SHORT_TRAINING: @@ -609,10 +601,10 @@ static int set_next_tx_type(t38_gateway_state_t *s) } /*endswitch*/ silence_gen_alter(&t->silence_gen, ms_to_samples(75)); - v17_tx_restart(&t->v17_tx, t->tx_bit_rate, t->use_tep, short_train); - v17_tx_set_get_bit(&t->v17_tx, get_bit_func, get_bit_user_data); + v17_tx_restart(&t->fast_modems.v17_tx, t->tx_bit_rate, t->use_tep, short_train); + v17_tx_set_get_bit(&t->fast_modems.v17_tx, get_bit_func, get_bit_user_data); set_tx_handler(s, (span_tx_handler_t *) &silence_gen, &t->silence_gen); - set_next_tx_handler(s, (span_tx_handler_t *) &v17_tx, &t->v17_tx); + set_next_tx_handler(s, (span_tx_handler_t *) &v17_tx, &t->fast_modems.v17_tx); set_rx_active(s, TRUE); break; case T38_IND_V8_ANSAM: @@ -811,15 +803,15 @@ static void monitor_control_messages(t38_gateway_state_t *s, uint8_t dcs_code; } modem_codes[] = { - {14400, T38_V17_RX, DISBIT6}, - {12000, T38_V17_RX, (DISBIT6 | DISBIT4)}, - { 9600, T38_V17_RX, (DISBIT6 | DISBIT3)}, - { 9600, T38_V29_RX, DISBIT3}, - { 7200, T38_V17_RX, (DISBIT6 | DISBIT4 | DISBIT3)}, - { 7200, T38_V29_RX, (DISBIT4 | DISBIT3)}, - { 4800, T38_V27TER_RX, DISBIT4}, - { 2400, T38_V27TER_RX, 0}, - { 0, T38_NONE, 0} + {14400, FAX_MODEM_V17_RX, DISBIT6}, + {12000, FAX_MODEM_V17_RX, (DISBIT6 | DISBIT4)}, + { 9600, FAX_MODEM_V17_RX, (DISBIT6 | DISBIT3)}, + { 9600, FAX_MODEM_V29_RX, DISBIT3}, + { 7200, FAX_MODEM_V17_RX, (DISBIT6 | DISBIT4 | DISBIT3)}, + { 7200, FAX_MODEM_V29_RX, (DISBIT4 | DISBIT3)}, + { 4800, FAX_MODEM_V27TER_RX, DISBIT4}, + { 2400, FAX_MODEM_V27TER_RX, 0}, + { 0, FAX_MODEM_NONE, 0} }; static const int minimum_scan_line_times[8] = { @@ -873,7 +865,7 @@ static void monitor_control_messages(t38_gateway_state_t *s, /* We need to check which modem type is about to be used, so we can start the correct modem. */ s->core.fast_bit_rate = 0; - s->core.fast_rx_modem = T38_NONE; + s->core.fast_rx_modem = FAX_MODEM_NONE; s->core.image_data_mode = FALSE; s->core.short_train = FALSE; if (from_modem) @@ -924,7 +916,7 @@ static void monitor_control_messages(t38_gateway_state_t *s, /* If we are hitting one of these conditions, it will take another DCS/DTC to select the fast modem again, so abandon our idea of it. */ s->core.fast_bit_rate = 0; - s->core.fast_rx_modem = T38_NONE; + s->core.fast_rx_modem = FAX_MODEM_NONE; s->core.image_data_mode = FALSE; s->core.short_train = FALSE; #endif @@ -950,7 +942,7 @@ static void monitor_control_messages(t38_gateway_state_t *s, /* If we are hitting one of these conditions, it will take another DCS/DTC to select the fast modem again, so abandon our idea of it. */ s->core.fast_bit_rate = 0; - s->core.fast_rx_modem = T38_NONE; + s->core.fast_rx_modem = FAX_MODEM_NONE; s->core.image_data_mode = FALSE; s->core.short_train = FALSE; #endif @@ -1609,7 +1601,7 @@ static int set_fast_packetisation(t38_gateway_state_t *s) ind = T38_IND_NO_SIGNAL; switch (s->core.fast_rx_active) { - case T38_V17_RX: + case FAX_MODEM_V17_RX: set_octets_per_data_packet(s, s->core.fast_bit_rate); switch (s->core.fast_bit_rate) { @@ -1633,7 +1625,7 @@ static int set_fast_packetisation(t38_gateway_state_t *s) } /*endswitch*/ break; - case T38_V27TER_RX: + case FAX_MODEM_V27TER_RX: set_octets_per_data_packet(s, s->core.fast_bit_rate); switch (s->core.fast_bit_rate) { @@ -1649,7 +1641,7 @@ static int set_fast_packetisation(t38_gateway_state_t *s) } /*endswitch*/ break; - case T38_V29_RX: + case FAX_MODEM_V29_RX: set_octets_per_data_packet(s, s->core.fast_bit_rate); switch (s->core.fast_bit_rate) { @@ -2174,27 +2166,27 @@ static int restart_rx_modem(t38_gateway_state_t *s) s->core.to_t38.octets_per_data_packet = 1; switch (s->core.fast_rx_modem) { - case T38_V17_RX: - v17_rx_restart(&s->audio.modems.v17_rx, s->core.fast_bit_rate, s->core.short_train); - v17_rx_set_put_bit(&s->audio.modems.v17_rx, put_bit_func, put_bit_user_data); + case FAX_MODEM_V17_RX: + v17_rx_restart(&s->audio.modems.fast_modems.v17_rx, s->core.fast_bit_rate, s->core.short_train); + v17_rx_set_put_bit(&s->audio.modems.fast_modems.v17_rx, put_bit_func, put_bit_user_data); set_rx_handler(s, &v17_v21_rx, &v17_v21_rx_fillin, s); - s->core.fast_rx_active = T38_V17_RX; + s->core.fast_rx_active = FAX_MODEM_V17_RX; break; - case T38_V27TER_RX: - v27ter_rx_restart(&s->audio.modems.v27ter_rx, s->core.fast_bit_rate, FALSE); - v27ter_rx_set_put_bit(&s->audio.modems.v27ter_rx, put_bit_func, put_bit_user_data); + case FAX_MODEM_V27TER_RX: + v27ter_rx_restart(&s->audio.modems.fast_modems.v27ter_rx, s->core.fast_bit_rate, FALSE); + v27ter_rx_set_put_bit(&s->audio.modems.fast_modems.v27ter_rx, put_bit_func, put_bit_user_data); set_rx_handler(s, &v27ter_v21_rx, &v27ter_v21_rx_fillin, s); - s->core.fast_rx_active = T38_V27TER_RX; + s->core.fast_rx_active = FAX_MODEM_V27TER_RX; break; - case T38_V29_RX: - v29_rx_restart(&s->audio.modems.v29_rx, s->core.fast_bit_rate, FALSE); - v29_rx_set_put_bit(&s->audio.modems.v29_rx, put_bit_func, put_bit_user_data); + case FAX_MODEM_V29_RX: + v29_rx_restart(&s->audio.modems.fast_modems.v29_rx, s->core.fast_bit_rate, FALSE); + v29_rx_set_put_bit(&s->audio.modems.fast_modems.v29_rx, put_bit_func, put_bit_user_data); set_rx_handler(s, &v29_v21_rx, &v29_v21_rx_fillin, s); - s->core.fast_rx_active = T38_V29_RX; + s->core.fast_rx_active = FAX_MODEM_V29_RX; break; default: set_rx_handler(s, (span_rx_handler_t *) &fsk_rx, (span_rx_fillin_handler_t *) &fsk_rx_fillin, &(s->audio.modems.v21_rx)); - s->core.fast_rx_active = T38_NONE; + s->core.fast_rx_active = FAX_MODEM_NONE; break; } /*endswitch*/ @@ -2426,7 +2418,7 @@ static int t38_gateway_audio_init(t38_gateway_state_t *s) /* TODO: Don't use the very low cutoff levels we would like to. We get some quirks if we do. We need to sort this out. */ fsk_rx_signal_cutoff(&s->audio.modems.v21_rx, -30.0f); - v29_rx_signal_cutoff(&s->audio.modems.v29_rx, -28.5f); + v29_rx_signal_cutoff(&s->audio.modems.fast_modems.v29_rx, -28.5f); return 0; } /*- End of function --------------------------------------------------------*/ diff --git a/libs/spandsp/src/t38_terminal.c b/libs/spandsp/src/t38_terminal.c index 427997cac2..cf78c024cc 100644 --- a/libs/spandsp/src/t38_terminal.c +++ b/libs/spandsp/src/t38_terminal.c @@ -1305,19 +1305,31 @@ SPAN_DECLARE(void) t38_terminal_set_config(t38_terminal_state_t *s, int config) if ((config & T38_TERMINAL_OPTION_NO_PACING)) { /* Continuous streaming mode, as used for TPKT over TCP transport */ - /* Inhibit indicator packets */ - t38_set_redundancy_control(&s->t38_fe.t38, T38_PACKET_CATEGORY_INDICATOR, 0); + t38_set_pace_transmission(&s->t38_fe.t38, FALSE); + s->t38_fe.hdlc_tx.extra_bits = 0; + if ((config & T38_TERMINAL_OPTION_NO_INDICATORS)) + t38_set_redundancy_control(&s->t38_fe.t38, T38_PACKET_CATEGORY_INDICATOR, 0); + else + t38_set_redundancy_control(&s->t38_fe.t38, T38_PACKET_CATEGORY_INDICATOR, 1); + /*endif*/ t38_set_redundancy_control(&s->t38_fe.t38, T38_PACKET_CATEGORY_CONTROL_DATA, 1); t38_set_redundancy_control(&s->t38_fe.t38, T38_PACKET_CATEGORY_CONTROL_DATA_END, 1); t38_set_redundancy_control(&s->t38_fe.t38, T38_PACKET_CATEGORY_IMAGE_DATA, 1); t38_set_redundancy_control(&s->t38_fe.t38, T38_PACKET_CATEGORY_IMAGE_DATA_END, 1); s->t38_fe.ms_per_tx_chunk = 0; s->t38_fe.chunking_modes &= ~T38_CHUNKING_SEND_REGULAR_INDICATORS; + s->t38_fe.chunking_modes |= T38_CHUNKING_MERGE_FCS_WITH_DATA; } else { /* Paced streaming mode, as used for UDP transports */ - t38_set_redundancy_control(&s->t38_fe.t38, T38_PACKET_CATEGORY_INDICATOR, INDICATOR_TX_COUNT); + t38_set_pace_transmission(&s->t38_fe.t38, TRUE); + s->t38_fe.hdlc_tx.extra_bits = 0; + if ((config & T38_TERMINAL_OPTION_NO_INDICATORS)) + t38_set_redundancy_control(&s->t38_fe.t38, T38_PACKET_CATEGORY_INDICATOR, 0); + else + t38_set_redundancy_control(&s->t38_fe.t38, T38_PACKET_CATEGORY_INDICATOR, INDICATOR_TX_COUNT); + /*endif*/ t38_set_redundancy_control(&s->t38_fe.t38, T38_PACKET_CATEGORY_CONTROL_DATA, DATA_TX_COUNT); t38_set_redundancy_control(&s->t38_fe.t38, T38_PACKET_CATEGORY_CONTROL_DATA_END, DATA_END_TX_COUNT); t38_set_redundancy_control(&s->t38_fe.t38, T38_PACKET_CATEGORY_IMAGE_DATA, DATA_TX_COUNT); diff --git a/libs/spandsp/src/t4_rx.c b/libs/spandsp/src/t4_rx.c index bc3389d7b4..ccb78a7e55 100644 --- a/libs/spandsp/src/t4_rx.c +++ b/libs/spandsp/src/t4_rx.c @@ -143,6 +143,13 @@ static int set_tiff_directory_info(t4_state_t *s) t = &s->tiff; /* Prepare the directory entry fully before writing the image, or libtiff complains */ TIFFSetField(t->tiff_file, TIFFTAG_COMPRESSION, t->output_compression); +#if defined(SPANDSP_SUPPORT_TIFF_FX) + TIFFSetField(t->tiff_file, TIFFTAG_PROFILETYPE, PROFILETYPE_G3_FAX); + TIFFSetField(t->tiff_file, TIFFTAG_FAXPROFILE, FAXPROFILE_S); + TIFFSetField(t->tiff_file, TIFFTAG_CODINGMETHODS, CODINGMETHODS_T4_1D | CODINGMETHODS_T4_2D | CODINGMETHODS_T6); + TIFFSetField(t->tiff_file, TIFFTAG_VERSIONYEAR, "1998"); + /* TIFFSetField(t->tiff_file, TIFFTAG_MODENUMBER, 0); */ +#endif if (t->output_compression == COMPRESSION_CCITT_T4) { TIFFSetField(t->tiff_file, TIFFTAG_T4OPTIONS, t->output_t4_options); @@ -1015,6 +1022,9 @@ SPAN_DECLARE(t4_state_t *) t4_rx_init(t4_state_t *s, const char *file, int outpu return NULL; } memset(s, 0, sizeof(*s)); +#if defined(SPANDSP_SUPPORT_TIFF_FX) + TIFF_FX_init(); +#endif span_log_init(&s->logging, SPAN_LOG_NONE, NULL); span_log_set_protocol(&s->logging, "T.4"); s->rx = TRUE; @@ -1239,18 +1249,18 @@ SPAN_DECLARE(const char *) t4_encoding_to_str(int encoding) return "T.4 2-D"; case T4_COMPRESSION_ITU_T6: return "T.6"; - case T4_COMPRESSION_ITU_T85: - return "T.85"; - case T4_COMPRESSION_ITU_T85_L0: - return "T.85(L0)"; + case T4_COMPRESSION_ITU_T42: + return "T.42"; + case T4_COMPRESSION_ITU_SYCC_T42: + return "sYCC T.42"; case T4_COMPRESSION_ITU_T43: return "T.43"; case T4_COMPRESSION_ITU_T45: return "T.45"; - case T4_COMPRESSION_ITU_T81: - return "T.81"; - case T4_COMPRESSION_ITU_SYCC_T81: - return "sYCC T.81"; + case T4_COMPRESSION_ITU_T85: + return "T.85"; + case T4_COMPRESSION_ITU_T85_L0: + return "T.85(L0)"; } return "???"; } diff --git a/libs/spandsp/src/t4_tx.c b/libs/spandsp/src/t4_tx.c index 5d150348ba..1c9f9a2b5e 100644 --- a/libs/spandsp/src/t4_tx.c +++ b/libs/spandsp/src/t4_tx.c @@ -121,6 +121,52 @@ static void STATE_TRACE(const char *format, ...) #define STATE_TRACE(...) /**/ #endif +#if defined(SPANDSP_SUPPORT_TIFF_FX) +/* TIFF-FX related extensions to the tag set supported by libtiff */ +static const TIFFFieldInfo tiff_fx_tiff_field_info[] = +{ + {TIFFTAG_INDEXED, 1, 1, TIFF_SHORT, FIELD_CUSTOM, FALSE, FALSE, (char *) "Indexed"}, + {TIFFTAG_GLOBALPARAMETERSIFD, 1, 1, TIFF_LONG, FIELD_CUSTOM, FALSE, FALSE, (char *) "GlobalParametersIFD"}, + {TIFFTAG_PROFILETYPE, 1, 1, TIFF_LONG, FIELD_CUSTOM, FALSE, FALSE, (char *) "ProfileType"}, + {TIFFTAG_FAXPROFILE, 1, 1, TIFF_BYTE, FIELD_CUSTOM, FALSE, FALSE, (char *) "FaxProfile"}, + {TIFFTAG_CODINGMETHODS, 1, 1, TIFF_LONG, FIELD_CUSTOM, FALSE, FALSE, (char *) "CodingMethods"}, + {TIFFTAG_VERSIONYEAR, 4, 4, TIFF_BYTE, FIELD_CUSTOM, FALSE, FALSE, (char *) "VersionYear"}, + {TIFFTAG_MODENUMBER, 1, 1, TIFF_BYTE, FIELD_CUSTOM, FALSE, FALSE, (char *) "ModeNumber"}, + {TIFFTAG_DECODE, TIFF_VARIABLE, TIFF_VARIABLE, TIFF_SRATIONAL, FIELD_CUSTOM, FALSE, FALSE, (char *) "Decode"}, + {TIFFTAG_IMAGEBASECOLOR, TIFF_SPP, TIFF_SPP, TIFF_SHORT, FIELD_CUSTOM, FALSE, FALSE, (char *) "ImageBaseColor"}, + {TIFFTAG_T82OPTIONS, 1, 1, TIFF_LONG, FIELD_CUSTOM, FALSE, FALSE, (char *) "T82Options"}, + {TIFFTAG_STRIPROWCOUNTS, TIFF_VARIABLE, TIFF_VARIABLE, TIFF_LONG, FIELD_CUSTOM, FALSE, TRUE, (char *) "StripRowCounts"}, + {TIFFTAG_IMAGELAYER, 2, 2, TIFF_LONG, FIELD_CUSTOM, FALSE, FALSE, (char *) "ImageLayer"}, +}; + +static TIFFExtendProc _ParentExtender = NULL; + +static void TIFFFXDefaultDirectory(TIFF *tif) +{ + /* Install the extended tag field info */ + TIFFMergeFieldInfo(tif, tiff_fx_tiff_field_info, 11); + + /* Since we may have overriddden another directory method, we call it now to + allow it to set up the rest of its own methods. */ + if (_ParentExtender) + (*_ParentExtender)(tif); +} +/*- End of function --------------------------------------------------------*/ + +SPAN_DECLARE(void) TIFF_FX_init(void) +{ + static int first_time = TRUE; + + if (!first_time) + return; + first_time = FALSE; + + /* Grab the inherited method and install */ + _ParentExtender = TIFFSetTagExtender(TIFFFXDefaultDirectory); +} +/*- End of function --------------------------------------------------------*/ +#endif + /*! T.4 run length table entry */ typedef struct { diff --git a/libs/spandsp/src/testcpuid.c b/libs/spandsp/src/testcpuid.c index 98c46a0581..2344c59079 100644 --- a/libs/spandsp/src/testcpuid.c +++ b/libs/spandsp/src/testcpuid.c @@ -35,23 +35,26 @@ /* Make this file just disappear if we are not on an x86 machine */ #if defined(__i386__) // || defined(__x86_64__) -#define X86_EFLAGS_CF 0x00000001 /* Carry Flag */ -#define X86_EFLAGS_PF 0x00000004 /* Parity Flag */ -#define X86_EFLAGS_AF 0x00000010 /* Auxillary carry Flag */ -#define X86_EFLAGS_ZF 0x00000040 /* Zero Flag */ -#define X86_EFLAGS_SF 0x00000080 /* Sign Flag */ -#define X86_EFLAGS_TF 0x00000100 /* Trap Flag */ -#define X86_EFLAGS_IF 0x00000200 /* Interrupt Flag */ -#define X86_EFLAGS_DF 0x00000400 /* Direction Flag */ -#define X86_EFLAGS_OF 0x00000800 /* Overflow Flag */ -#define X86_EFLAGS_IOPL 0x00003000 /* IOPL mask */ -#define X86_EFLAGS_NT 0x00004000 /* Nested Task */ -#define X86_EFLAGS_RF 0x00010000 /* Resume Flag */ -#define X86_EFLAGS_VM 0x00020000 /* Virtual Mode */ -#define X86_EFLAGS_AC 0x00040000 /* Alignment Check */ -#define X86_EFLAGS_VIF 0x00080000 /* Virtual Interrupt Flag */ -#define X86_EFLAGS_VIP 0x00100000 /* Virtual Interrupt Pending */ -#define X86_EFLAGS_ID 0x00200000 /* CPUID detection flag */ +enum +{ + X86_EFLAGS_CF = 0x00000001, /* Carry Flag */ + X86_EFLAGS_PF = 0x00000004, /* Parity Flag */ + X86_EFLAGS_AF = 0x00000010, /* Auxillary carry Flag */ + X86_EFLAGS_ZF = 0x00000040, /* Zero Flag */ + X86_EFLAGS_SF = 0x00000080, /* Sign Flag */ + X86_EFLAGS_TF = 0x00000100, /* Trap Flag */ + X86_EFLAGS_IF = 0x00000200, /* Interrupt Flag */ + X86_EFLAGS_DF = 0x00000400, /* Direction Flag */ + X86_EFLAGS_OF = 0x00000800, /* Overflow Flag */ + X86_EFLAGS_IOPL = 0x00003000, /* IOPL mask */ + X86_EFLAGS_NT = 0x00004000, /* Nested Task */ + X86_EFLAGS_RF = 0x00010000, /* Resume Flag */ + X86_EFLAGS_VM = 0x00020000, /* Virtual Mode */ + X86_EFLAGS_AC = 0x00040000, /* Alignment Check */ + X86_EFLAGS_VIF = 0x00080000, /* Virtual Interrupt Flag */ + X86_EFLAGS_VIP = 0x00100000, /* Virtual Interrupt Pending */ + X86_EFLAGS_ID = 0x00200000 /* CPUID detection flag */ +}; /* Standard macro to see if a specific flag is changeable */ static __inline__ int flag_is_changeable_p(uint32_t flag) diff --git a/libs/spandsp/src/v29rx.c b/libs/spandsp/src/v29rx.c index a94af80574..db1a6c1253 100644 --- a/libs/spandsp/src/v29rx.c +++ b/libs/spandsp/src/v29rx.c @@ -44,6 +44,9 @@ #include "spandsp/telephony.h" #include "spandsp/logging.h" +#include "spandsp/fast_convert.h" +#include "spandsp/math_fixed.h" +#include "spandsp/saturated.h" #include "spandsp/complex.h" #include "spandsp/vector_float.h" #include "spandsp/complex_vector_float.h" diff --git a/libs/spandsp/src/v29tx_constellation_maps.h b/libs/spandsp/src/v29tx_constellation_maps.h index 01da53e71f..f141b336bb 100644 --- a/libs/spandsp/src/v29tx_constellation_maps.h +++ b/libs/spandsp/src/v29tx_constellation_maps.h @@ -24,18 +24,26 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ +#if !defined(FP_SCALE) +#if defined(SPANDSP_USE_FIXED_POINT) +#define FP_SCALE(x) ((int16_t) x) +#else +#define FP_SCALE(x) (x) +#endif +#endif + #if defined(SPANDSP_USE_FIXED_POINT) static const complexi16_t v29_abab_constellation[6] = #else static const complexf_t v29_abab_constellation[6] = #endif { - { 3, -3}, /* 315deg high 9600 */ - {-3, 0}, /* 180deg low */ - { 1, -1}, /* 315deg low 7200 */ - {-3, 0}, /* 180deg low */ - { 0, -3}, /* 270deg low 4800 */ - {-3, 0} /* 180deg low */ + {FP_SCALE( 3.0f), FP_SCALE(-3.0f)}, /* 315deg high 9600 */ + {FP_SCALE(-3.0f), FP_SCALE( 0.0f)}, /* 180deg low */ + {FP_SCALE( 1.0f), FP_SCALE(-1.0f)}, /* 315deg low 7200 */ + {FP_SCALE(-3.0f), FP_SCALE( 0.0f)}, /* 180deg low */ + {FP_SCALE( 0.0f), FP_SCALE(-3.0f)}, /* 270deg low 4800 */ + {FP_SCALE(-3.0f), FP_SCALE( 0.0f)} /* 180deg low */ }; #if defined(SPANDSP_USE_FIXED_POINT) @@ -44,12 +52,12 @@ static const complexi16_t v29_cdcd_constellation[6] = static const complexf_t v29_cdcd_constellation[6] = #endif { - { 3, 0}, /* 0deg low 9600 */ - {-3, 3}, /* 135deg high */ - { 3, 0}, /* 0deg low 7200 */ - {-1, 1}, /* 135deg low */ - { 3, 0}, /* 0deg low 4800 */ - { 0, 3} /* 90deg low */ + {FP_SCALE( 3.0f), FP_SCALE( 0.0f)}, /* 0deg low 9600 */ + {FP_SCALE(-3.0f), FP_SCALE( 3.0f)}, /* 135deg high */ + {FP_SCALE( 3.0f), FP_SCALE( 0.0f)}, /* 0deg low 7200 */ + {FP_SCALE(-1.0f), FP_SCALE( 1.0f)}, /* 135deg low */ + {FP_SCALE( 3.0f), FP_SCALE( 0.0f)}, /* 0deg low 4800 */ + {FP_SCALE( 0.0f), FP_SCALE( 3.0f)} /* 90deg low */ }; #if defined(SPANDSP_USE_FIXED_POINT) @@ -58,22 +66,22 @@ static const complexi16_t v29_9600_constellation[16] = static const complexf_t v29_9600_constellation[16] = #endif { - { 3, 0}, /* 0deg low */ - { 1, 1}, /* 45deg low */ - { 0, 3}, /* 90deg low */ - {-1, 1}, /* 135deg low */ - {-3, 0}, /* 180deg low */ - {-1, -1}, /* 225deg low */ - { 0, -3}, /* 270deg low */ - { 1, -1}, /* 315deg low */ - { 5, 0}, /* 0deg high */ - { 3, 3}, /* 45deg high */ - { 0, 5}, /* 90deg high */ - {-3, 3}, /* 135deg high */ - {-5, 0}, /* 180deg high */ - {-3, -3}, /* 225deg high */ - { 0, -5}, /* 270deg high */ - { 3, -3} /* 315deg high */ + {FP_SCALE( 3.0f), FP_SCALE( 0.0f)}, /* 0deg low */ + {FP_SCALE( 1.0f), FP_SCALE( 1.0f)}, /* 45deg low */ + {FP_SCALE( 0.0f), FP_SCALE( 3.0f)}, /* 90deg low */ + {FP_SCALE(-1.0f), FP_SCALE( 1.0f)}, /* 135deg low */ + {FP_SCALE(-3.0f), FP_SCALE( 0.0f)}, /* 180deg low */ + {FP_SCALE(-1.0f), FP_SCALE(-1.0f)}, /* 225deg low */ + {FP_SCALE( 0.0f), FP_SCALE(-3.0f)}, /* 270deg low */ + {FP_SCALE( 1.0f), FP_SCALE(-1.0f)}, /* 315deg low */ + {FP_SCALE( 5.0f), FP_SCALE( 0.0f)}, /* 0deg high */ + {FP_SCALE( 3.0f), FP_SCALE( 3.0f)}, /* 45deg high */ + {FP_SCALE( 0.0f), FP_SCALE( 5.0f)}, /* 90deg high */ + {FP_SCALE(-3.0f), FP_SCALE( 3.0f)}, /* 135deg high */ + {FP_SCALE(-5.0f), FP_SCALE( 0.0f)}, /* 180deg high */ + {FP_SCALE(-3.0f), FP_SCALE(-3.0f)}, /* 225deg high */ + {FP_SCALE( 0.0f), FP_SCALE(-5.0f)}, /* 270deg high */ + {FP_SCALE( 3.0f), FP_SCALE(-3.0f)} /* 315deg high */ }; /*- End of file ------------------------------------------------------------*/ diff --git a/libs/spandsp/src/v42.c b/libs/spandsp/src/v42.c index 729ab40cfe..d41e2d345e 100644 --- a/libs/spandsp/src/v42.c +++ b/libs/spandsp/src/v42.c @@ -746,17 +746,14 @@ static int valid_data_state(v42_state_t *ss) static void receive_information_frame(v42_state_t *ss, const uint8_t *frame, int len) { lapm_state_t *s; - int ret; - int n; s = &ss->lapm; if (!valid_data_state(ss)) return; if (len > s->rx_n401 + 3) return; - ret = 0; /* Ack I frames: NR - 1 */ - n = ack_info(ss, frame[2] >> 1); + ack_info(ss, frame[2] >> 1); if (s->local_busy) { /* 8.4.7 */ @@ -786,7 +783,6 @@ static void receive_information_frame(v42_state_t *ss, const uint8_t *frame, int static void rx_supervisory_cmd_frame(v42_state_t *ss, const uint8_t *frame, int len) { lapm_state_t *s; - int n; s = &ss->lapm; /* If l->local_busy each RR,RNR,REJ with p=1 should be replied by RNR with f=1 (8.4.7) */ @@ -794,20 +790,20 @@ static void rx_supervisory_cmd_frame(v42_state_t *ss, const uint8_t *frame, int { case LAPM_S_RR: s->far_busy = FALSE; - n = ack_info(ss, frame[2] >> 1); + ack_info(ss, frame[2] >> 1); /* If p = 1 may be used for status checking? */ tx_information_rr_rnr_response(ss, frame, len); break; case LAPM_S_RNR: s->far_busy = TRUE; - n = ack_info(ss, frame[2] >> 1); + ack_info(ss, frame[2] >> 1); /* If p = 1 may be used for status checking? */ if ((frame[2] & 0x1)) tx_supervisory_frame(s, s->rsp_addr, (s->local_busy) ? LAPM_S_RNR : LAPM_S_RR, 1); break; case LAPM_S_REJ: s->far_busy = FALSE; - n = ack_info(ss, frame[2] >> 1); + ack_info(ss, frame[2] >> 1); if (s->retry_count == 0) { t401_stop_t403_start(ss); @@ -827,7 +823,6 @@ static void rx_supervisory_cmd_frame(v42_state_t *ss, const uint8_t *frame, int static void rx_supervisory_rsp_frame(v42_state_t *ss, const uint8_t *frame, int len) { lapm_state_t *s; - int n; s = &ss->lapm; if (s->retry_count == 0 && (frame[2] & 0x1)) @@ -837,7 +832,7 @@ static void rx_supervisory_rsp_frame(v42_state_t *ss, const uint8_t *frame, int { case LAPM_S_RR: s->far_busy = FALSE; - n = ack_info(ss, frame[2] >> 1); + ack_info(ss, frame[2] >> 1); if (s->retry_count && (frame[2] & 0x1)) { reject_info(s); @@ -846,7 +841,7 @@ static void rx_supervisory_rsp_frame(v42_state_t *ss, const uint8_t *frame, int break; case LAPM_S_RNR: s->far_busy = TRUE; - n = ack_info(ss, frame[2] >> 1); + ack_info(ss, frame[2] >> 1); if (s->retry_count && (frame[2] & 0x1)) { reject_info(s); @@ -857,7 +852,7 @@ static void rx_supervisory_rsp_frame(v42_state_t *ss, const uint8_t *frame, int break; case LAPM_S_REJ: s->far_busy = FALSE; - n = ack_info(ss, frame[2] >> 1); + ack_info(ss, frame[2] >> 1); if (s->retry_count == 0 || (frame[2] & 0x1)) { reject_info(s); diff --git a/libs/spandsp/src/v8.c b/libs/spandsp/src/v8.c index 9893bacfd3..08a81dd780 100644 --- a/libs/spandsp/src/v8.c +++ b/libs/spandsp/src/v8.c @@ -1011,9 +1011,9 @@ SPAN_DECLARE(int) v8_restart(v8_state_t *s, int calling_party, v8_parms_t *parms s->modulation_bytes = 3; s->ci_timer = 0; - if (calling_party) + s->calling_party = calling_party; + if (s->calling_party) { - s->calling_party = TRUE; s->state = V8_WAIT_1S; s->negotiation_timer = ms_to_samples(1000); s->ci_count = 0; @@ -1023,11 +1023,9 @@ SPAN_DECLARE(int) v8_restart(v8_state_t *s, int calling_party, v8_parms_t *parms else { /* Send the ANSam or ANSam/ tone */ - s->calling_party = FALSE; - modem_connect_tones_tx_init(&s->ansam_tx, s->parms.modem_connect_tone); - - v8_decode_init(s); s->state = V8_CM_WAIT; + v8_decode_init(s); + modem_connect_tones_tx_init(&s->ansam_tx, s->parms.modem_connect_tone); s->negotiation_timer = ms_to_samples(200 + 5000); s->modem_connect_tone_tx_on = ms_to_samples(75) + 1; } diff --git a/libs/spandsp/tests/logging_tests.c b/libs/spandsp/tests/logging_tests.c index 2159b20f8e..f90aebc0b8 100644 --- a/libs/spandsp/tests/logging_tests.c +++ b/libs/spandsp/tests/logging_tests.c @@ -50,17 +50,16 @@ static int tests_failed = FALSE; static int msg_step = 0; static int msg2_step = 0; -static int error_step = 0; static int msg_done = FALSE; static int msg2_done = FALSE; -static int error_done = FALSE; -static void message_handler(int level, const char *text) +static void message_handler(void *user_data, int level, const char *text) { const char *ref[] = { "TAG Log with tag 1 2 3\n", "Log with protocol 1 2 3\n", + "ERROR Log with severity log 1 2 3\n", "FLOW NewTag Log with new tag 1 2 3\n", "FLOW Protocol NewTag Log with protocol 1 2 3\n", "FLOW Protocol NewTag Buf 00 01 02 03 04 05 06 07 08 09\n", @@ -78,6 +77,8 @@ static void message_handler(int level, const char *text) "" }; + if (ref[msg_step][0] == '\0') + return; if (strcmp(ref[msg_step], text)) { printf(">>>: %s", ref[msg_step]); @@ -89,7 +90,7 @@ static void message_handler(int level, const char *text) } /*- End of function --------------------------------------------------------*/ -static void message_handler2(int level, const char *text) +static void message_handler2(void *user_data, int level, const char *text) { /* TODO: This doesn't check if the date/time field makes sense */ if (strcmp(" FLOW Protocol NewTag Date/time tagged log 1 2 3\n", text + 23)) @@ -103,25 +104,6 @@ static void message_handler2(int level, const char *text) } /*- End of function --------------------------------------------------------*/ -static void error_handler(const char *text) -{ - const char *ref[] = - { - "ERROR Log with severity log 1 2 3\n", - "" - }; - - if (strcmp(ref[error_step], text)) - { - printf(">>>: %s", ref[error_step]); - tests_failed = TRUE; - } - if (ref[++error_step][0] == '\0') - error_done = TRUE; - printf("ERR: %s", text); -} -/*- End of function --------------------------------------------------------*/ - int main(int argc, char *argv[]) { logging_state_t log; @@ -143,8 +125,7 @@ int main(int argc, char *argv[]) fprintf(stderr, "Not logged.\n"); /* Now set a custom log handler */ - span_log_set_message_handler(&log, &message_handler); - span_log_set_error_handler(&log, &error_handler); + span_log_set_message_handler(&log, &message_handler, NULL); span_log_set_sample_rate(&log, 44100); /* Try the different logging elements */ @@ -176,7 +157,7 @@ int main(int argc, char *argv[]) fprintf(stderr, "Logged.\n"); else fprintf(stderr, "Not logged.\n"); - + /* Test logging of buffer contents */ for (i = 0; i < 1000; i++) buf[i] = i; @@ -199,7 +180,7 @@ int main(int argc, char *argv[]) break; } } - + /* Check timestamping by samples */ span_log_set_level(&log, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_SHOW_TAG | SPAN_LOG_FLOW | SPAN_LOG_SHOW_SAMPLE_TIME); for (i = 0; i < 10; i++) @@ -209,7 +190,7 @@ int main(int argc, char *argv[]) } /* Check timestamping by current date and time */ - span_log_set_message_handler(&log, &message_handler2); + span_log_set_message_handler(&log, &message_handler2, NULL); span_log_set_level(&log, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_SHOW_TAG | SPAN_LOG_FLOW | SPAN_LOG_SHOW_DATE); for (i = 0; i < 10; i++) { @@ -218,13 +199,13 @@ int main(int argc, char *argv[]) delay.tv_nsec = 20000000; nanosleep(&delay, NULL); } - if (tests_failed || !msg_done || !error_done) + if (tests_failed || !msg_done) { - printf("Tests failed - %d %d %d.\n", tests_failed, msg_done, error_done); + printf("Tests failed - %d %d.\n", tests_failed, msg_done); return 2; } - - span_log_set_message_handler(&log, &message_handler); + + span_log_set_message_handler(&log, &message_handler, NULL); printf("Tests passed.\n"); return 0; diff --git a/src/mod/applications/mod_spandsp/mod_spandsp.h b/src/mod/applications/mod_spandsp/mod_spandsp.h index 4acef0796c..3ba14bcd14 100644 --- a/src/mod/applications/mod_spandsp/mod_spandsp.h +++ b/src/mod/applications/mod_spandsp/mod_spandsp.h @@ -137,6 +137,6 @@ switch_status_t spandsp_fax_detect_session(switch_core_session_t *session, int hits, const char *app, const char *data, switch_tone_detect_callback_t callback); switch_status_t spandsp_fax_stop_detect_session(switch_core_session_t *session); -void spanfax_log_message(int level, const char *msg); +void spanfax_log_message(void *user_data, int level, const char *msg); switch_status_t load_configuration(switch_bool_t reload); void mod_spandsp_indicate_data(switch_core_session_t *session, switch_bool_t self, switch_bool_t on); diff --git a/src/mod/applications/mod_spandsp/mod_spandsp_fax.c b/src/mod/applications/mod_spandsp/mod_spandsp_fax.c index 7cb0982591..fab30f2bb8 100644 --- a/src/mod/applications/mod_spandsp/mod_spandsp_fax.c +++ b/src/mod/applications/mod_spandsp/mod_spandsp_fax.c @@ -259,7 +259,7 @@ static void counter_increment(void) switch_mutex_unlock(spandsp_globals.mutex); } -void spanfax_log_message(int level, const char *msg) +void spanfax_log_message(void *user_data, int level, const char *msg) { int fs_log_level; @@ -713,8 +713,8 @@ static switch_status_t spanfax_init(pvt_t *pvt, transport_mode_t trans_mode) fax_set_transmit_on_idle(fax, TRUE); - span_log_set_message_handler(&fax->logging, spanfax_log_message); - span_log_set_message_handler(&t30->logging, spanfax_log_message); + span_log_set_message_handler(&fax->logging, spanfax_log_message, NULL); + span_log_set_message_handler(&t30->logging, spanfax_log_message, NULL); if (pvt->verbose) { span_log_set_level(&fax->logging, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_FLOW); @@ -769,8 +769,8 @@ static switch_status_t spanfax_init(pvt_t *pvt, transport_mode_t trans_mode) } } - span_log_set_message_handler(&t38->logging, spanfax_log_message); - span_log_set_message_handler(&t30->logging, spanfax_log_message); + span_log_set_message_handler(&t38->logging, spanfax_log_message, NULL); + span_log_set_message_handler(&t30->logging, spanfax_log_message, NULL); if (pvt->verbose) { span_log_set_level(&t38->logging, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_FLOW); @@ -824,8 +824,8 @@ static switch_status_t spanfax_init(pvt_t *pvt, transport_mode_t trans_mode) } - span_log_set_message_handler(&pvt->t38_gateway_state->logging, spanfax_log_message); - span_log_set_message_handler(&pvt->t38_core->logging, spanfax_log_message); + span_log_set_message_handler(&pvt->t38_gateway_state->logging, spanfax_log_message, NULL); + span_log_set_message_handler(&pvt->t38_core->logging, spanfax_log_message, NULL); if (pvt->verbose) { span_log_set_level(&pvt->t38_gateway_state->logging, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_FLOW); diff --git a/src/mod/applications/mod_spandsp/mod_spandsp_modem.c b/src/mod/applications/mod_spandsp/mod_spandsp_modem.c index ff2442beda..9b8fa1e090 100644 --- a/src/mod/applications/mod_spandsp/mod_spandsp_modem.c +++ b/src/mod/applications/mod_spandsp/mod_spandsp_modem.c @@ -346,15 +346,15 @@ switch_status_t modem_init(modem_t *modem, modem_control_handler_t control_handl } if (spandsp_globals.modem_verbose) { - span_log_set_message_handler(&modem->t31_state->logging, spanfax_log_message); - span_log_set_message_handler(&modem->t31_state->audio.modems.v17_rx.logging, spanfax_log_message); - span_log_set_message_handler(&modem->t31_state->audio.modems.v29_rx.logging, spanfax_log_message); - span_log_set_message_handler(&modem->t31_state->audio.modems.v27ter_rx.logging, spanfax_log_message); + span_log_set_message_handler(&modem->t31_state->logging, spanfax_log_message, NULL); + span_log_set_message_handler(&modem->t31_state->audio.modems.fast_modems.v17_rx.logging, spanfax_log_message, NULL); + span_log_set_message_handler(&modem->t31_state->audio.modems.fast_modems.v29_rx.logging, spanfax_log_message, NULL); + span_log_set_message_handler(&modem->t31_state->audio.modems.fast_modems.v27ter_rx.logging, spanfax_log_message, NULL); modem->t31_state->logging.level = SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_FLOW; - modem->t31_state->audio.modems.v17_rx.logging.level = SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_FLOW; - modem->t31_state->audio.modems.v29_rx.logging.level = SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_FLOW; - modem->t31_state->audio.modems.v27ter_rx.logging.level = SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_FLOW; + modem->t31_state->audio.modems.fast_modems.v17_rx.logging.level = SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_FLOW; + modem->t31_state->audio.modems.fast_modems.v29_rx.logging.level = SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_FLOW; + modem->t31_state->audio.modems.fast_modems.v27ter_rx.logging.level = SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_FLOW; } modem->control_handler = control_handler;