# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-#
-# $Id: autogen.sh,v 1.1.1.1 2009/11/19 12:10:48 steveu Exp $
-#
UNAME=`uname`
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-#
-# $Id: regression_tests.sh.in,v 1.2 2009/11/20 13:12:24 steveu Exp $
-#
STDOUT_DEST=xyzzy
STDERR_DEST=xyzzy2
* You should have received a copy of the GNU Lesser General Public
* License along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- * $Id: timing.h,v 1.1.1.1 2009/11/19 12:10:48 steveu Exp $
*/
#if !defined(_TIMING_H_)
}
/*- End of function --------------------------------------------------------*/
-SPAN_DECLARE_NONSTD(void) async_rx_put_bit(void *user_data, int bit)
+SPAN_DECLARE(void) async_rx_put_bit(void *user_data, int bit)
{
async_rx_state_t *s;
}
/*- End of function --------------------------------------------------------*/
-SPAN_DECLARE_NONSTD(int) async_tx_get_bit(void *user_data)
+SPAN_DECLARE(int) async_tx_get_bit(void *user_data)
{
async_tx_state_t *s;
int bit;
}
/*- End of function --------------------------------------------------------*/
-SPAN_DECLARE_NONSTD(int) fax_rx(fax_state_t *s, int16_t *amp, int len)
+SPAN_DECLARE(int) fax_rx(fax_state_t *s, int16_t *amp, int len)
{
int i;
}
/*- End of function --------------------------------------------------------*/
-SPAN_DECLARE_NONSTD(int) fax_rx_fillin(fax_state_t *s, int len)
+SPAN_DECLARE(int) fax_rx_fillin(fax_state_t *s, int len)
{
/* To mitigate the effect of lost packets on a packet network we should
try to sustain the status quo. If there is no receive modem running, keep
}
/*- End of function --------------------------------------------------------*/
-SPAN_DECLARE_NONSTD(int) fax_tx(fax_state_t *s, int16_t *amp, int max_len)
+SPAN_DECLARE(int) fax_tx(fax_state_t *s, int16_t *amp, int max_len)
{
int len;
#if defined(LOG_FAX_AUDIO)
/*- End of function --------------------------------------------------------*/
//static void fax_modems_hdlc_accept(void *user_data, const uint8_t *msg, int len, int ok)
-SPAN_DECLARE_NONSTD(void) fax_modems_hdlc_accept(void *user_data, const uint8_t *msg, int len, int ok)
+SPAN_DECLARE(void) fax_modems_hdlc_accept(void *user_data, const uint8_t *msg, int len, int ok)
{
fax_modems_state_t *s;
}
/*- End of function --------------------------------------------------------*/
-SPAN_DECLARE_NONSTD(void) fax_modems_hdlc_tx_frame(void *user_data, const uint8_t *msg, int len)
+SPAN_DECLARE(void) fax_modems_hdlc_tx_frame(void *user_data, const uint8_t *msg, int len)
{
fax_modems_state_t *s;
}
/*- End of function --------------------------------------------------------*/
-SPAN_DECLARE_NONSTD(int) fax_modems_v17_v21_rx(void *user_data, const int16_t amp[], int len)
+SPAN_DECLARE(int) fax_modems_v17_v21_rx(void *user_data, const int16_t amp[], int len)
{
fax_modems_state_t *s;
}
/*- End of function --------------------------------------------------------*/
-SPAN_DECLARE_NONSTD(int) fax_modems_v17_v21_rx_fillin(void *user_data, int len)
+SPAN_DECLARE(int) fax_modems_v17_v21_rx_fillin(void *user_data, int len)
{
fax_modems_state_t *s;
}
/*- End of function --------------------------------------------------------*/
-SPAN_DECLARE_NONSTD(int) fax_modems_v27ter_v21_rx(void *user_data, const int16_t amp[], int len)
+SPAN_DECLARE(int) fax_modems_v27ter_v21_rx(void *user_data, const int16_t amp[], int len)
{
fax_modems_state_t *s;
}
/*- End of function --------------------------------------------------------*/
-SPAN_DECLARE_NONSTD(int) fax_modems_v27ter_v21_rx_fillin(void *user_data, int len)
+SPAN_DECLARE(int) fax_modems_v27ter_v21_rx_fillin(void *user_data, int len)
{
fax_modems_state_t *s;
}
/*- End of function --------------------------------------------------------*/
-SPAN_DECLARE_NONSTD(int) fax_modems_v29_v21_rx(void *user_data, const int16_t amp[], int len)
+SPAN_DECLARE(int) fax_modems_v29_v21_rx(void *user_data, const int16_t amp[], int len)
{
fax_modems_state_t *s;
}
/*- End of function --------------------------------------------------------*/
-SPAN_DECLARE_NONSTD(int) fax_modems_v29_v21_rx_fillin(void *user_data, int len)
+SPAN_DECLARE(int) fax_modems_v29_v21_rx_fillin(void *user_data, int len)
{
fax_modems_state_t *s;
}
/*- End of function --------------------------------------------------------*/
-SPAN_DECLARE_NONSTD(int) fsk_tx(fsk_tx_state_t *s, int16_t amp[], int len)
+SPAN_DECLARE(int) fsk_tx(fsk_tx_state_t *s, int16_t amp[], int len)
{
int sample;
int bit;
}
/*- End of function --------------------------------------------------------*/
-SPAN_DECLARE_NONSTD(int) fsk_rx(fsk_rx_state_t *s, const int16_t *amp, int len)
+SPAN_DECLARE(int) fsk_rx(fsk_rx_state_t *s, const int16_t *amp, int len)
{
int buf_ptr;
int baudstate;
}
/*- End of function --------------------------------------------------------*/
-SPAN_DECLARE_NONSTD(int) fsk_rx_fillin(fsk_rx_state_t *s, int len)
+SPAN_DECLARE(int) fsk_rx_fillin(fsk_rx_state_t *s, int len)
{
int buf_ptr;
int i;
}
/*- End of function --------------------------------------------------------*/
-SPAN_DECLARE_NONSTD(void) hdlc_rx_put_bit(hdlc_rx_state_t *s, int new_bit)
+SPAN_DECLARE(void) hdlc_rx_put_bit(hdlc_rx_state_t *s, int new_bit)
{
if (new_bit < 0)
{
}
/*- End of function --------------------------------------------------------*/
-SPAN_DECLARE_NONSTD(void) hdlc_rx_put_byte(hdlc_rx_state_t *s, int new_byte)
+SPAN_DECLARE(void) hdlc_rx_put_byte(hdlc_rx_state_t *s, int new_byte)
{
int i;
}
/*- End of function --------------------------------------------------------*/
-SPAN_DECLARE_NONSTD(void) hdlc_rx_put(hdlc_rx_state_t *s, const uint8_t buf[], int len)
+SPAN_DECLARE(void) hdlc_rx_put(hdlc_rx_state_t *s, const uint8_t buf[], int len)
{
int i;
}
/*- End of function --------------------------------------------------------*/
-SPAN_DECLARE_NONSTD(int) hdlc_tx_get_byte(hdlc_tx_state_t *s)
+SPAN_DECLARE(int) hdlc_tx_get_byte(hdlc_tx_state_t *s)
{
int i;
int byte_in_progress;
}
/*- End of function --------------------------------------------------------*/
-SPAN_DECLARE_NONSTD(int) hdlc_tx_get_bit(hdlc_tx_state_t *s)
+SPAN_DECLARE(int) hdlc_tx_get_bit(hdlc_tx_state_t *s)
{
int txbit;
}
/*- End of function --------------------------------------------------------*/
-SPAN_DECLARE_NONSTD(int) hdlc_tx_get(hdlc_tx_state_t *s, uint8_t buf[], size_t max_len)
+SPAN_DECLARE(int) hdlc_tx_get(hdlc_tx_state_t *s, uint8_t buf[], size_t max_len)
{
size_t i;
int x;
}
/*- End of function --------------------------------------------------------*/
-SPAN_DECLARE_NONSTD(int) modem_connect_tones_tx(modem_connect_tones_tx_state_t *s,
- int16_t amp[],
- int len)
+SPAN_DECLARE(int) modem_connect_tones_tx(modem_connect_tones_tx_state_t *s,
+ int16_t amp[],
+ int len)
{
int16_t mod;
int i;
}
/*- End of function --------------------------------------------------------*/
-SPAN_DECLARE_NONSTD(int) modem_connect_tones_rx(modem_connect_tones_rx_state_t *s,
- const int16_t amp[],
- int len)
+SPAN_DECLARE(int) modem_connect_tones_rx(modem_connect_tones_rx_state_t *s,
+ const int16_t amp[],
+ int len)
{
int i;
int16_t notched;
}
/*- End of function --------------------------------------------------------*/
-SPAN_DECLARE_NONSTD(int) modem_connect_tones_rx_fillin(modem_connect_tones_rx_state_t *s, int len)
+SPAN_DECLARE(int) modem_connect_tones_rx_fillin(modem_connect_tones_rx_state_t *s, int len)
{
return 0;
}
#include "spandsp/private/silence_gen.h"
-SPAN_DECLARE_NONSTD(int) silence_gen(silence_gen_state_t *s, int16_t *amp, int max_len)
+SPAN_DECLARE(int) silence_gen(silence_gen_state_t *s, int16_t *amp, int max_len)
{
if (s->remaining_samples != INT_MAX)
{
/* The following dummy routines, to absorb data, don't really have a proper home,
so they have been put here. */
-SPAN_DECLARE_NONSTD(int) span_dummy_rx(void *user_data, const int16_t amp[], int len)
+SPAN_DECLARE(int) span_dummy_rx(void *user_data, const int16_t amp[], int len)
{
return 0;
}
}
/*- End of function --------------------------------------------------------*/
-SPAN_DECLARE_NONSTD(int) span_dummy_rx_fillin(void *user_data, int len)
+SPAN_DECLARE(int) span_dummy_rx_fillin(void *user_data, int len)
{
return 0;
}
- SIG_STATUS_TRAINING_SUCCEEDED
- SIG_STATUS_TRAINING_FAILED
- SIG_STATUS_END_OF_DATA */
-SPAN_DECLARE_NONSTD(void) async_rx_put_bit(void *user_data, int bit);
+SPAN_DECLARE(void) async_rx_put_bit(void *user_data, int bit);
/*! Initialise an asynchronous data receiver context.
\brief Initialise an asynchronous data receiver context.
\brief Get the next bit of a transmitted serial bit stream.
\param user_data An opaque point which must point to a transmitter context.
\return the next bit, or PUTBIT_END_OF_DATA to indicate the data stream has ended. */
-SPAN_DECLARE_NONSTD(int) async_tx_get_bit(void *user_data);
+SPAN_DECLARE(int) async_tx_get_bit(void *user_data);
/*! Initialise an asynchronous data transmit context.
\brief Initialise an asynchronous data transmit context.
\return The number of samples unprocessed. This should only be non-zero if
the software has reached the end of the FAX call.
*/
-SPAN_DECLARE_NONSTD(int) fax_rx(fax_state_t *s, int16_t *amp, int len);
+SPAN_DECLARE(int) fax_rx(fax_state_t *s, int16_t *amp, int len);
/*! Apply fake T.30 receive processing when a block of audio samples is missing (e.g due
to packet loss).
\return The number of samples unprocessed. This should only be non-zero if
the software has reached the end of the FAX call.
*/
-SPAN_DECLARE_NONSTD(int) fax_rx_fillin(fax_state_t *s, int len);
+SPAN_DECLARE(int) fax_rx_fillin(fax_state_t *s, int len);
/*! Apply T.30 transmit processing to generate a block of audio samples.
\brief Apply T.30 transmit processing to generate a block of audio samples.
\return The number of samples actually generated. This will be zero when
there is nothing to send.
*/
-SPAN_DECLARE_NONSTD(int) fax_tx(fax_state_t *s, int16_t *amp, int max_len);
+SPAN_DECLARE(int) fax_tx(fax_state_t *s, int16_t *amp, int max_len);
/*! Select whether silent audio will be sent when FAX transmit is idle.
\brief Select whether silent audio will be sent when FAX transmit is idle.
#endif
/* TEMPORARY FUDGE */
-SPAN_DECLARE_NONSTD(void) fax_modems_hdlc_accept(void *user_data, const uint8_t *msg, int len, int ok);
+SPAN_DECLARE(void) fax_modems_hdlc_accept(void *user_data, const uint8_t *msg, int len, int ok);
/*! Convert a FAX modem type to a short text description.
\brief Convert a FAX modem type to a short text description.
SPAN_DECLARE(const char *) fax_modem_to_str(int modem);
/* N.B. the following are currently a work in progress */
-SPAN_DECLARE_NONSTD(int) fax_modems_v17_v21_rx(void *user_data, const int16_t amp[], int len);
-SPAN_DECLARE_NONSTD(int) fax_modems_v27ter_v21_rx(void *user_data, const int16_t amp[], int len);
-SPAN_DECLARE_NONSTD(int) fax_modems_v29_v21_rx(void *user_data, const int16_t amp[], int len);
-SPAN_DECLARE_NONSTD(int) fax_modems_v17_v21_rx_fillin(void *user_data, int len);
-SPAN_DECLARE_NONSTD(int) fax_modems_v27ter_v21_rx_fillin(void *user_data, int len);
-SPAN_DECLARE_NONSTD(int) fax_modems_v29_v21_rx_fillin(void *user_data, int len);
-
-SPAN_DECLARE_NONSTD(void) fax_modems_hdlc_tx_frame(void *user_data, const uint8_t *msg, int len);
+SPAN_DECLARE(int) fax_modems_v17_v21_rx(void *user_data, const int16_t amp[], int len);
+SPAN_DECLARE(int) fax_modems_v27ter_v21_rx(void *user_data, const int16_t amp[], int len);
+SPAN_DECLARE(int) fax_modems_v29_v21_rx(void *user_data, const int16_t amp[], int len);
+SPAN_DECLARE(int) fax_modems_v17_v21_rx_fillin(void *user_data, int len);
+SPAN_DECLARE(int) fax_modems_v27ter_v21_rx_fillin(void *user_data, int len);
+SPAN_DECLARE(int) fax_modems_v29_v21_rx_fillin(void *user_data, int len);
+
+SPAN_DECLARE(void) fax_modems_hdlc_tx_frame(void *user_data, const uint8_t *msg, int len);
SPAN_DECLARE(void) fax_modems_hdlc_tx_flags(fax_modems_state_t *s, int flags);
\param len The number of samples to be generated.
\return The number of samples actually generated.
*/
-SPAN_DECLARE_NONSTD(int) fsk_tx(fsk_tx_state_t *s, int16_t amp[], int len);
+SPAN_DECLARE(int) fsk_tx(fsk_tx_state_t *s, int16_t amp[], int len);
/*! Get the current received signal power.
\param s The modem context.
\param len The number of samples in the buffer.
\return The number of samples unprocessed.
*/
-SPAN_DECLARE_NONSTD(int) fsk_rx(fsk_rx_state_t *s, const int16_t *amp, int len);
+SPAN_DECLARE(int) fsk_rx(fsk_rx_state_t *s, const int16_t *amp, int len);
/*! Fake processing of a missing block of received FSK modem audio samples
(e.g due to packet loss).
\param len The number of samples to fake.
\return The number of samples unprocessed.
*/
-SPAN_DECLARE_NONSTD(int) fsk_rx_fillin(fsk_rx_state_t *s, int len);
+SPAN_DECLARE(int) fsk_rx_fillin(fsk_rx_state_t *s, int len);
SPAN_DECLARE(void) fsk_rx_set_put_bit(fsk_rx_state_t *s, put_bit_func_t put_bit, void *user_data);
\param s A pointer to an HDLC receiver context.
\param new_bit The bit.
*/
-SPAN_DECLARE_NONSTD(void) hdlc_rx_put_bit(hdlc_rx_state_t *s, int new_bit);
+SPAN_DECLARE(void) hdlc_rx_put_bit(hdlc_rx_state_t *s, int new_bit);
/*! \brief Put a byte of data to an HDLC receiver.
\param s A pointer to an HDLC receiver context.
\param new_byte The byte of data.
*/
-SPAN_DECLARE_NONSTD(void) hdlc_rx_put_byte(hdlc_rx_state_t *s, int new_byte);
+SPAN_DECLARE(void) hdlc_rx_put_byte(hdlc_rx_state_t *s, int new_byte);
/*! \brief Put a series of bytes of data to an HDLC receiver.
\param s A pointer to an HDLC receiver context.
\param buf The buffer of data.
\param len The length of the data in the buffer.
*/
-SPAN_DECLARE_NONSTD(void) hdlc_rx_put(hdlc_rx_state_t *s, const uint8_t buf[], int len);
+SPAN_DECLARE(void) hdlc_rx_put(hdlc_rx_state_t *s, const uint8_t buf[], int len);
/*! Initialise an HDLC transmitter context.
\brief Initialise an HDLC transmitter context.
\param s A pointer to an HDLC transmitter context.
\return The next bit for transmission.
*/
-SPAN_DECLARE_NONSTD(int) hdlc_tx_get_bit(hdlc_tx_state_t *s);
+SPAN_DECLARE(int) hdlc_tx_get_bit(hdlc_tx_state_t *s);
/*! \brief Get the next byte for transmission.
\param s A pointer to an HDLC transmitter context.
\return The next byte for transmission.
*/
-SPAN_DECLARE_NONSTD(int) hdlc_tx_get_byte(hdlc_tx_state_t *s);
+SPAN_DECLARE(int) hdlc_tx_get_byte(hdlc_tx_state_t *s);
/*! \brief Get the next sequence of bytes for transmission.
\param s A pointer to an HDLC transmitter context.
\param max_len The number of bytes to get.
\return The number of bytes actually got.
*/
-SPAN_DECLARE_NONSTD(int) hdlc_tx_get(hdlc_tx_state_t *s, uint8_t buf[], size_t max_len);
+SPAN_DECLARE(int) hdlc_tx_get(hdlc_tx_state_t *s, uint8_t buf[], size_t max_len);
#if defined(__cplusplus)
}
\param len The number of samples to generate.
\return The number of samples generated.
*/
-SPAN_DECLARE_NONSTD(int) modem_connect_tones_tx(modem_connect_tones_tx_state_t *s,
- int16_t amp[],
- int len);
+SPAN_DECLARE(int) modem_connect_tones_tx(modem_connect_tones_tx_state_t *s,
+ int16_t amp[],
+ int len);
/*! \brief Process a block of samples through an instance of the modem connect
tones detector.
\param len The number of samples in the array.
\return The number of unprocessed samples.
*/
-SPAN_DECLARE_NONSTD(int) modem_connect_tones_rx(modem_connect_tones_rx_state_t *s,
- const int16_t amp[],
- int len);
+SPAN_DECLARE(int) modem_connect_tones_rx(modem_connect_tones_rx_state_t *s,
+ const int16_t amp[],
+ int len);
/*! Fake processing of a missing block of received modem connect tone samples
(e.g due to packet loss).
\param len The number of samples to fake.
\return The number of samples unprocessed.
*/
-SPAN_DECLARE_NONSTD(int) modem_connect_tones_rx_fillin(modem_connect_tones_rx_state_t *s, int len);
+SPAN_DECLARE(int) modem_connect_tones_rx_fillin(modem_connect_tones_rx_state_t *s, int len);
/*! \brief Test if a modem_connect tone has been detected.
\param s The context.
\return The number of samples actually generated. This will be zero when
there is nothing to send.
*/
-SPAN_DECLARE_NONSTD(int) silence_gen(silence_gen_state_t *s, int16_t *amp, int max_len);
+SPAN_DECLARE(int) silence_gen(silence_gen_state_t *s, int16_t *amp, int max_len);
/*! Set a silence generator context to output continuous silence.
\brief Set a silence generator context to output continuous silence.
\param len The length of the signal buffer
\return 0.
*/
-SPAN_DECLARE_NONSTD(int) span_dummy_rx(void *user_data, const int16_t amp[], int len);
+SPAN_DECLARE(int) span_dummy_rx(void *user_data, const int16_t amp[], int len);
/*! A dummy routine to use as a signal modifier callback, when we aren't
really trying to process the signal. It just returns without affecting
\param len The length of the signal buffer
\return 0.
*/
-SPAN_DECLARE_NONSTD(int) span_dummy_rx_fillin(void *user_data, int len);
+SPAN_DECLARE(int) span_dummy_rx_fillin(void *user_data, int len);
#if defined(__cplusplus)
}
#if !defined(_STDBOOL_H)
#define _STDBOOL_H
+
#ifdef _MSC_VER
#pragma warning (disable: 4005)
#endif
+
#if !defined(__cplusplus)
#define _Bool int
-#define false 0
#define bool int
+#define false 0
#define true (!false)
#else
\brief Get a bit of received non-ECM image data.
\param user_data An opaque pointer, which must point to the T.30 context.
\return The next bit to transmit. */
-SPAN_DECLARE_NONSTD(int) t30_non_ecm_get_bit(void *user_data);
+SPAN_DECLARE(int) t30_non_ecm_get_bit(void *user_data);
/*! Get a chunk of received non-ECM image data.
\brief Get a bit of received non-ECM image data.
\brief Process a bit of received non-ECM image data
\param user_data An opaque pointer, which must point to the T.30 context.
\param bit The received bit. */
-SPAN_DECLARE_NONSTD(void) t30_non_ecm_put_bit(void *user_data, int bit);
+SPAN_DECLARE(void) t30_non_ecm_put_bit(void *user_data, int bit);
/*! Process a chunk of received non-ECM image data.
\brief Process a chunk of received non-ECM image data
\param msg The HDLC message.
\param len The length of the message, in octets.
\param ok True if the frame was received without error. */
-SPAN_DECLARE_NONSTD(void) t30_hdlc_accept(void *user_data, const uint8_t msg[], int len, int ok);
+SPAN_DECLARE(void) t30_hdlc_accept(void *user_data, const uint8_t msg[], int len, int ok);
/*! Report the passage of time to the T.30 engine.
\brief Report the passage of time to the T.30 engine.
\param amp The audio sample buffer.
\param len The number of samples in the buffer.
\return The number of samples unprocessed. */
-SPAN_DECLARE_NONSTD(int) t31_rx(t31_state_t *s, int16_t amp[], int len);
+SPAN_DECLARE(int) t31_rx(t31_state_t *s, int16_t amp[], int len);
/*! Fake processing of a missing block of received T.31 modem audio samples
(e.g due to packet loss).
\param s The T.31 modem context.
\param len The number of samples to fake.
\return The number of samples unprocessed. */
-SPAN_DECLARE_NONSTD(int) t31_rx_fillin(t31_state_t *s, int len);
+SPAN_DECLARE(int) t31_rx_fillin(t31_state_t *s, int len);
/*! Generate a block of T.31 modem audio samples.
\brief Generate a block of T.31 modem audio samples.
\param max_len The number of samples to be generated.
\return The number of samples actually generated.
*/
-SPAN_DECLARE_NONSTD(int) t31_tx(t31_state_t *s, int16_t amp[], int max_len);
+SPAN_DECLARE(int) t31_tx(t31_state_t *s, int16_t amp[], int max_len);
SPAN_DECLARE(int) t31_t38_send_timeout(t31_state_t *s, int samples);
\param len The length of the packet contents.
\param seq_no The packet sequence number.
\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);
+SPAN_DECLARE(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 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);
+SPAN_DECLARE(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 amp The audio sample buffer.
\param len The number of samples in the buffer.
\return The number of samples unprocessed. */
-SPAN_DECLARE_NONSTD(int) t38_gateway_rx(t38_gateway_state_t *s, int16_t amp[], int len);
+SPAN_DECLARE(int) t38_gateway_rx(t38_gateway_state_t *s, int16_t amp[], int len);
/*! Apply fake processing when a block of audio samples is missing (e.g due
to packet loss).
\return The number of samples unprocessed. This should only be non-zero if
the software has reached the end of the FAX call.
*/
-SPAN_DECLARE_NONSTD(int) t38_gateway_rx_fillin(t38_gateway_state_t *s, int len);
+SPAN_DECLARE(int) t38_gateway_rx_fillin(t38_gateway_state_t *s, int len);
/*! Generate a block of FAX audio samples.
\brief Generate a block of FAX audio samples.
\param max_len The number of samples to be generated.
\return The number of samples actually generated.
*/
-SPAN_DECLARE_NONSTD(int) t38_gateway_tx(t38_gateway_state_t *s, int16_t amp[], int max_len);
+SPAN_DECLARE(int) t38_gateway_tx(t38_gateway_state_t *s, int16_t amp[], int max_len);
/*! Control whether error correcting mode (ECM) is allowed.
\brief Control whether error correcting mode (ECM) is allowed.
/*! \brief Get the next bit of data from a T.38 rate adapting non-ECM buffer context.
\param user_data The buffer context, cast to a void pointer.
\return The next bit, or one of the values indicating a change of modem status. */
-SPAN_DECLARE_NONSTD(int) t38_non_ecm_buffer_get_bit(void *user_data);
+SPAN_DECLARE(int) t38_non_ecm_buffer_get_bit(void *user_data);
#if defined(__cplusplus)
}
#if defined(_M_IX86) || defined(_M_X64)
#if defined(LIBSPANDSP_EXPORTS)
-#define SPAN_DECLARE(type) __declspec(dllexport) type __stdcall
-#define SPAN_DECLARE_NONSTD(type) __declspec(dllexport) type __cdecl
+#define SPAN_DECLARE(type) __declspec(dllexport) type
#define SPAN_DECLARE_DATA __declspec(dllexport)
#else
-#define SPAN_DECLARE(type) __declspec(dllimport) type __stdcall
-#define SPAN_DECLARE_NONSTD(type) __declspec(dllimport) type __cdecl
+#define SPAN_DECLARE(type) __declspec(dllimport) type
#define SPAN_DECLARE_DATA __declspec(dllimport)
#endif
#elif defined(SPANDSP_USE_EXPORT_CAPABILITY) && (defined(__GNUC__) || defined(__SUNCC__))
#define SPAN_DECLARE(type) __attribute__((visibility("default"))) type
-#define SPAN_DECLARE_NONSTD(type) __attribute__((visibility("default"))) type
#define SPAN_DECLARE_DATA __attribute__((visibility("default")))
#else
#define SPAN_DECLARE(type) /**/ type
-#define SPAN_DECLARE_NONSTD(type) /**/ type
#define SPAN_DECLARE_DATA /**/
#endif
SPAN_DECLARE(void) tone_gen_descriptor_free(tone_gen_descriptor_t *s);
-SPAN_DECLARE_NONSTD(int) tone_gen(tone_gen_state_t *s, int16_t amp[], int max_samples);
+SPAN_DECLARE(int) tone_gen(tone_gen_state_t *s, int16_t amp[], int max_samples);
SPAN_DECLARE(tone_gen_state_t *) tone_gen_init(tone_gen_state_t *s, tone_gen_descriptor_t *t);
\param len The number of samples in the buffer.
\return The number of samples unprocessed.
*/
-SPAN_DECLARE_NONSTD(int) v17_rx(v17_rx_state_t *s, const int16_t amp[], int len);
+SPAN_DECLARE(int) v17_rx(v17_rx_state_t *s, const int16_t amp[], int len);
/*! Fake processing of a missing block of received V.17 modem audio samples.
(e.g due to packet loss).
\param len The number of samples to fake.
\return The number of samples unprocessed.
*/
-SPAN_DECLARE_NONSTD(int) v17_rx_fillin(v17_rx_state_t *s, int len);
+SPAN_DECLARE(int) v17_rx_fillin(v17_rx_state_t *s, int len);
/*! Get a snapshot of the current equalizer coefficients.
\brief Get a snapshot of the current equalizer coefficients.
\param len The number of samples to be generated.
\return The number of samples actually generated.
*/
-SPAN_DECLARE_NONSTD(int) v17_tx(v17_tx_state_t *s, int16_t amp[], int len);
+SPAN_DECLARE(int) v17_tx(v17_tx_state_t *s, int16_t amp[], int len);
#if defined(__cplusplus)
}
\param max_len The number of samples to be generated.
\return The number of samples actually generated.
*/
-SPAN_DECLARE_NONSTD(int) v18_tx(v18_state_t *s, int16_t amp[], int max_len);
+SPAN_DECLARE(int) v18_tx(v18_state_t *s, int16_t amp[], int max_len);
/*! Process a block of received V.18 audio samples.
\brief Process a block of received V.18 audio samples.
\param len The number of samples in the buffer.
\return The number of unprocessed samples.
*/
-SPAN_DECLARE_NONSTD(int) v18_rx(v18_state_t *s, const int16_t amp[], int len);
+SPAN_DECLARE(int) v18_rx(v18_state_t *s, const int16_t amp[], int len);
/*! Fake processing of a missing block of received V.18 audio samples.
(e.g due to packet loss).
\param len The number of samples to fake.
\return The number of unprocessed samples.
*/
-SPAN_DECLARE_NONSTD(int) v18_rx_fillin(v18_state_t *s, int len);
+SPAN_DECLARE(int) v18_rx_fillin(v18_state_t *s, int len);
/*! \brief Put a string to a V.18 context's input buffer.
\param s The V.18 context.
\param amp The audio sample buffer.
\param len The number of samples in the buffer.
\return The number of samples unprocessed. */
-SPAN_DECLARE_NONSTD(int) v22bis_rx(v22bis_state_t *s, const int16_t amp[], int len);
+SPAN_DECLARE(int) v22bis_rx(v22bis_state_t *s, const int16_t amp[], int len);
/*! Fake processing of a missing block of received V.22bis modem audio samples.
(e.g due to packet loss).
\param s The modem context.
\param len The number of samples to fake.
\return The number of samples unprocessed. */
-SPAN_DECLARE_NONSTD(int) v22bis_rx_fillin(v22bis_state_t *s, int len);
+SPAN_DECLARE(int) v22bis_rx_fillin(v22bis_state_t *s, int len);
/*! Get a snapshot of the current equalizer coefficients.
\brief Get a snapshot of the current equalizer coefficients.
\param amp The audio sample buffer.
\param len The number of samples to be generated.
\return The number of samples actually generated. */
-SPAN_DECLARE_NONSTD(int) v22bis_tx(v22bis_state_t *s, int16_t amp[], int len);
+SPAN_DECLARE(int) v22bis_tx(v22bis_state_t *s, int16_t amp[], int len);
/*! Adjust a V.22bis modem transmit context's power output.
\brief Adjust a V.22bis modem transmit context's output power.
\param len The number of samples in the buffer.
\return The number of samples unprocessed.
*/
-SPAN_DECLARE_NONSTD(int) v27ter_rx(v27ter_rx_state_t *s, const int16_t amp[], int len);
+SPAN_DECLARE(int) v27ter_rx(v27ter_rx_state_t *s, const int16_t amp[], int len);
/*! Fake processing of a missing block of received V.27ter modem audio samples.
(e.g due to packet loss).
\param len The number of samples to fake.
\return The number of samples unprocessed.
*/
-SPAN_DECLARE_NONSTD(int) v27ter_rx_fillin(v27ter_rx_state_t *s, int len);
+SPAN_DECLARE(int) v27ter_rx_fillin(v27ter_rx_state_t *s, int len);
/*! Get a snapshot of the current equalizer coefficients.
\brief Get a snapshot of the current equalizer coefficients.
\param len The number of samples to be generated.
\return The number of samples actually generated.
*/
-SPAN_DECLARE_NONSTD(int) v27ter_tx(v27ter_tx_state_t *s, int16_t amp[], int len);
+SPAN_DECLARE(int) v27ter_tx(v27ter_tx_state_t *s, int16_t amp[], int len);
#if defined(__cplusplus)
}
\param amp The audio sample buffer.
\param len The number of samples in the buffer.
\return The number of samples unprocessed. */
-SPAN_DECLARE_NONSTD(int) v29_rx(v29_rx_state_t *s, const int16_t amp[], int len);
+SPAN_DECLARE(int) v29_rx(v29_rx_state_t *s, const int16_t amp[], int len);
/*! Fake processing of a missing block of received V.29 modem audio samples.
(e.g due to packet loss).
\param s The modem context.
\param len The number of samples to fake.
\return The number of samples unprocessed. */
-SPAN_DECLARE_NONSTD(int) v29_rx_fillin(v29_rx_state_t *s, int len);
+SPAN_DECLARE(int) v29_rx_fillin(v29_rx_state_t *s, int len);
/*! Get a snapshot of the current equalizer coefficients.
\brief Get a snapshot of the current equalizer coefficients.
\param len The number of samples to be generated.
\return The number of samples actually generated.
*/
-SPAN_DECLARE_NONSTD(int) v29_tx(v29_tx_state_t *s, int16_t amp[], int len);
+SPAN_DECLARE(int) v29_tx(v29_tx_state_t *s, int16_t amp[], int len);
#if defined(__cplusplus)
}
SPAN_DECLARE(const char *) lapm_status_to_str(int status);
-SPAN_DECLARE_NONSTD(void) lapm_receive(void *user_data, const uint8_t *frame, int len, int ok);
+SPAN_DECLARE(void) lapm_receive(void *user_data, const uint8_t *frame, int len, int ok);
SPAN_DECLARE(void) v42_start(v42_state_t *s);
\param max_len The number of samples to be generated.
\return The number of samples actually generated.
*/
-SPAN_DECLARE_NONSTD(int) v8_tx(v8_state_t *s, int16_t *amp, int max_len);
+SPAN_DECLARE(int) v8_tx(v8_state_t *s, int16_t *amp, int max_len);
/*! Process a block of received V.8 audio samples.
\brief Process a block of received V.8 audio samples.
\param amp The audio sample buffer.
\param len The number of samples in the buffer.
*/
-SPAN_DECLARE_NONSTD(int) v8_rx(v8_state_t *s, const int16_t *amp, int len);
+SPAN_DECLARE(int) v8_rx(v8_state_t *s, const int16_t *amp, int len);
/*! Log the list of supported modulations.
\brief Log the list of supported modulations.
}
/*- End of function --------------------------------------------------------*/
-SPAN_DECLARE_NONSTD(void) t30_non_ecm_put_bit(void *user_data, int bit)
+SPAN_DECLARE(void) t30_non_ecm_put_bit(void *user_data, int bit)
{
t30_state_t *s;
int res;
}
/*- End of function --------------------------------------------------------*/
-SPAN_DECLARE_NONSTD(int) t30_non_ecm_get_bit(void *user_data)
+SPAN_DECLARE(int) t30_non_ecm_get_bit(void *user_data)
{
int bit;
t30_state_t *s;
}
/*- End of function --------------------------------------------------------*/
-SPAN_DECLARE_NONSTD(void) t30_hdlc_accept(void *user_data, const uint8_t *msg, int len, int ok)
+SPAN_DECLARE(void) t30_hdlc_accept(void *user_data, const uint8_t *msg, int len, int ok)
{
t30_state_t *s;
}
/*- End of function --------------------------------------------------------*/
-SPAN_DECLARE_NONSTD(int) t31_rx(t31_state_t *s, int16_t amp[], int len)
+SPAN_DECLARE(int) t31_rx(t31_state_t *s, int16_t amp[], int len)
{
int i;
int32_t power;
}
/*- End of function --------------------------------------------------------*/
-SPAN_DECLARE_NONSTD(int) t31_rx_fillin(t31_state_t *s, int len)
+SPAN_DECLARE(int) t31_rx_fillin(t31_state_t *s, int len)
{
/* To mitigate the effect of lost packets on a packet network we should
try to sustain the status quo. If there is no receive modem running, keep
}
/*- End of function --------------------------------------------------------*/
-SPAN_DECLARE_NONSTD(int) t31_tx(t31_state_t *s, int16_t amp[], int max_len)
+SPAN_DECLARE(int) t31_tx(t31_state_t *s, int16_t amp[], int max_len)
{
int len;
}
/*- End of function --------------------------------------------------------*/
-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)
+SPAN_DECLARE(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;
}
/*- 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(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;
}
/*- End of function --------------------------------------------------------*/
-SPAN_DECLARE_NONSTD(int) t38_gateway_rx(t38_gateway_state_t *s, int16_t amp[], int len)
+SPAN_DECLARE(int) t38_gateway_rx(t38_gateway_state_t *s, int16_t amp[], int len)
{
int i;
}
/*- End of function --------------------------------------------------------*/
-SPAN_DECLARE_NONSTD(int) t38_gateway_rx_fillin(t38_gateway_state_t *s, int len)
+SPAN_DECLARE(int) t38_gateway_rx_fillin(t38_gateway_state_t *s, int len)
{
/* To mitigate the effect of lost packets on a packet network we should
try to sustain the status quo. If there is no receive modem running, keep
}
/*- End of function --------------------------------------------------------*/
-SPAN_DECLARE_NONSTD(int) t38_gateway_tx(t38_gateway_state_t *s, int16_t amp[], int max_len)
+SPAN_DECLARE(int) t38_gateway_tx(t38_gateway_state_t *s, int16_t amp[], int max_len)
{
int len;
#if defined(LOG_FAX_AUDIO)
}
/*- End of function --------------------------------------------------------*/
-SPAN_DECLARE_NONSTD(int) t38_non_ecm_buffer_get_bit(void *user_data)
+SPAN_DECLARE(int) t38_non_ecm_buffer_get_bit(void *user_data)
{
t38_non_ecm_buffer_state_t *s;
int bit;
}
/*- End of function --------------------------------------------------------*/
-SPAN_DECLARE_NONSTD(int) tone_gen(tone_gen_state_t *s, int16_t amp[], int max_samples)
+SPAN_DECLARE(int) tone_gen(tone_gen_state_t *s, int16_t amp[], int max_samples)
{
int samples;
int limit;
}
/*- End of function --------------------------------------------------------*/
-SPAN_DECLARE_NONSTD(int) v17_rx(v17_rx_state_t *s, const int16_t amp[], int len)
+SPAN_DECLARE(int) v17_rx(v17_rx_state_t *s, const int16_t amp[], int len)
{
int i;
int step;
}
/*- End of function --------------------------------------------------------*/
-SPAN_DECLARE_NONSTD(int) v17_rx_fillin(v17_rx_state_t *s, int len)
+SPAN_DECLARE(int) v17_rx_fillin(v17_rx_state_t *s, int len)
{
int i;
}
/*- End of function --------------------------------------------------------*/
-SPAN_DECLARE_NONSTD(int) v17_tx(v17_tx_state_t *s, int16_t amp[], int len)
+SPAN_DECLARE(int) v17_tx(v17_tx_state_t *s, int16_t amp[], int len)
{
#if defined(SPANDSP_USE_FIXED_POINT)
complexi16_t v;
}
/*- End of function --------------------------------------------------------*/
-SPAN_DECLARE_NONSTD(int) v18_tx(v18_state_t *s, int16_t *amp, int max_len)
+SPAN_DECLARE(int) v18_tx(v18_state_t *s, int16_t *amp, int max_len)
{
int len;
int lenx;
}
/*- End of function --------------------------------------------------------*/
-SPAN_DECLARE_NONSTD(int) v18_rx(v18_state_t *s, const int16_t amp[], int len)
+SPAN_DECLARE(int) v18_rx(v18_state_t *s, const int16_t amp[], int len)
{
if (s->rx_suppression > 0)
{
}
/*- End of function --------------------------------------------------------*/
-SPAN_DECLARE_NONSTD(int) v18_rx_fillin(v18_state_t *s, int len)
+SPAN_DECLARE(int) v18_rx_fillin(v18_state_t *s, int len)
{
if (s->rx_suppression > 0)
{
}
/*- End of function --------------------------------------------------------*/
-SPAN_DECLARE_NONSTD(int) v22bis_rx(v22bis_state_t *s, const int16_t amp[], int len)
+SPAN_DECLARE(int) v22bis_rx(v22bis_state_t *s, const int16_t amp[], int len)
{
int i;
int step;
}
/*- End of function --------------------------------------------------------*/
-SPAN_DECLARE_NONSTD(int) v22bis_rx_fillin(v22bis_state_t *s, int len)
+SPAN_DECLARE(int) v22bis_rx_fillin(v22bis_state_t *s, int len)
{
int i;
}
/*- End of function --------------------------------------------------------*/
-SPAN_DECLARE_NONSTD(int) v22bis_tx(v22bis_state_t *s, int16_t amp[], int len)
+SPAN_DECLARE(int) v22bis_tx(v22bis_state_t *s, int16_t amp[], int len)
{
#if defined(SPANDSP_USE_FIXED_POINT)
complexi16_t v;
}
/*- End of function --------------------------------------------------------*/
-SPAN_DECLARE_NONSTD(int) v27ter_rx(v27ter_rx_state_t *s, const int16_t amp[], int len)
+SPAN_DECLARE(int) v27ter_rx(v27ter_rx_state_t *s, const int16_t amp[], int len)
{
int i;
int step;
}
/*- End of function --------------------------------------------------------*/
-SPAN_DECLARE_NONSTD(int) v27ter_rx_fillin(v27ter_rx_state_t *s, int len)
+SPAN_DECLARE(int) v27ter_rx_fillin(v27ter_rx_state_t *s, int len)
{
int i;
}
/*- End of function --------------------------------------------------------*/
-SPAN_DECLARE_NONSTD(int) v27ter_tx(v27ter_tx_state_t *s, int16_t amp[], int len)
+SPAN_DECLARE(int) v27ter_tx(v27ter_tx_state_t *s, int16_t amp[], int len)
{
#if defined(SPANDSP_USE_FIXED_POINT)
complexi16_t v;
}
/*- End of function --------------------------------------------------------*/
-SPAN_DECLARE_NONSTD(int) v29_rx(v29_rx_state_t *s, const int16_t amp[], int len)
+SPAN_DECLARE(int) v29_rx(v29_rx_state_t *s, const int16_t amp[], int len)
{
int i;
int step;
}
/*- End of function --------------------------------------------------------*/
-SPAN_DECLARE_NONSTD(int) v29_rx_fillin(v29_rx_state_t *s, int len)
+SPAN_DECLARE(int) v29_rx_fillin(v29_rx_state_t *s, int len)
{
int i;
}
/*- End of function --------------------------------------------------------*/
-SPAN_DECLARE_NONSTD(int) v29_tx(v29_tx_state_t *s, int16_t amp[], int len)
+SPAN_DECLARE(int) v29_tx(v29_tx_state_t *s, int16_t amp[], int len)
{
#if defined(SPANDSP_USE_FIXED_POINT)
complexi16_t v;
}
/*- End of function --------------------------------------------------------*/
-SPAN_DECLARE_NONSTD(void) lapm_receive(void *user_data, const uint8_t *frame, int len, int ok)
+SPAN_DECLARE(void) lapm_receive(void *user_data, const uint8_t *frame, int len, int ok)
{
lapm_state_t *s;
v42_state_t *ss;
}
/*- End of function --------------------------------------------------------*/
-SPAN_DECLARE_NONSTD(int) v8_tx(v8_state_t *s, int16_t *amp, int max_len)
+SPAN_DECLARE(int) v8_tx(v8_state_t *s, int16_t *amp, int max_len)
{
int len;
}
/*- End of function --------------------------------------------------------*/
-SPAN_DECLARE_NONSTD(int) v8_rx(v8_state_t *s, const int16_t *amp, int len)
+SPAN_DECLARE(int) v8_rx(v8_state_t *s, const int16_t *amp, int len)
{
int residual_samples;
int tone;
fax_decode_SOURCES = fax_decode.c
fax_decode_LDADD = $(LIBDIR) -lspandsp
-fax_tests_SOURCES = fax_tests.c fax_utils.c media_monitor.cpp
+fax_tests_SOURCES = fax_tests.c fax_utils.c media_monitor.cpp fax_tester.c
fax_tests_LDADD = -L$(top_builddir)/spandsp-sim -lspandsp-sim $(LIBDIR) -lspandsp
fsk_tests_SOURCES = fsk_tests.c
xmlChar *compression;
};
-static struct
+struct
{
const char *tag;
int code;
if (s->timer > s->timeout)
{
s->timeout = 0x7FFFFFFFFFFFFFFFLL;
- if (s->front_end_step_timeout_handler)
- s->front_end_step_timeout_handler(s, s->front_end_step_timeout_user_data);
+ span_log(&s->logging, SPAN_LOG_FLOW, "FAX tester step timed out\n");
+ printf("Test failed\n");
+ exit(2);
}
}
/*- End of function --------------------------------------------------------*/
static void front_end_step_complete(faxtester_state_t *s)
{
- if (s->front_end_step_complete_handler)
- s->front_end_step_complete_handler(s, s->front_end_step_complete_user_data);
+ while (faxtester_next_step(s) == 0)
+ ;
+ /*endwhile*/
+}
+/*- End of function --------------------------------------------------------*/
+
+static int faxtester_phase_b_handler(void *user_data, int result)
+{
+ int ch;
+ int status;
+ faxtester_state_t *s;
+ const char *u;
+
+ s = (faxtester_state_t *) user_data;
+ ch = s->far_tag;
+ status = T30_ERR_OK;
+ if ((u = t30_get_rx_ident(s->far_t30)))
+ {
+ printf("%c: Phase B: remote ident '%s'\n", ch, u);
+ if (s->expected_rx_info.ident[0] && strcmp(s->expected_rx_info.ident, u))
+ {
+ printf("%c: Phase B: remote ident incorrect! - expected '%s'\n", ch, s->expected_rx_info.ident);
+ status = T30_ERR_IDENT_UNACCEPTABLE;
+ }
+ }
+ else
+ {
+ if (s->expected_rx_info.ident[0])
+ {
+ printf("%c: Phase B: remote ident missing!\n", ch);
+ status = T30_ERR_IDENT_UNACCEPTABLE;
+ }
+ }
+ if ((u = t30_get_rx_sub_address(s->far_t30)))
+ {
+ printf("%c: Phase B: remote sub-address '%s'\n", ch, u);
+ if (s->expected_rx_info.sub_address[0] && strcmp(s->expected_rx_info.sub_address, u))
+ {
+ printf("%c: Phase B: remote sub-address incorrect! - expected '%s'\n", ch, s->expected_rx_info.sub_address);
+ status = T30_ERR_SUB_UNACCEPTABLE;
+ }
+ }
+ else
+ {
+ if (s->expected_rx_info.sub_address[0])
+ {
+ printf("%c: Phase B: remote sub-address missing!\n", ch);
+ status = T30_ERR_SUB_UNACCEPTABLE;
+ }
+ }
+ if ((u = t30_get_rx_polled_sub_address(s->far_t30)))
+ {
+ printf("%c: Phase B: remote polled sub-address '%s'\n", ch, u);
+ if (s->expected_rx_info.polled_sub_address[0] && strcmp(s->expected_rx_info.polled_sub_address, u))
+ {
+ printf("%c: Phase B: remote polled sub-address incorrect! - expected '%s'\n", ch, s->expected_rx_info.polled_sub_address);
+ status = T30_ERR_PSA_UNACCEPTABLE;
+ }
+ }
+ else
+ {
+ if (s->expected_rx_info.polled_sub_address[0])
+ {
+ printf("%c: Phase B: remote polled sub-address missing!\n", ch);
+ status = T30_ERR_PSA_UNACCEPTABLE;
+ }
+ }
+ if ((u = t30_get_rx_selective_polling_address(s->far_t30)))
+ {
+ printf("%c: Phase B: remote selective polling address '%s'\n", ch, u);
+ if (s->expected_rx_info.selective_polling_address[0] && strcmp(s->expected_rx_info.selective_polling_address, u))
+ {
+ printf("%c: Phase B: remote selective polling address incorrect! - expected '%s'\n", ch, s->expected_rx_info.selective_polling_address);
+ status = T30_ERR_SEP_UNACCEPTABLE;
+ }
+ }
+ else
+ {
+ if (s->expected_rx_info.selective_polling_address[0])
+ {
+ printf("%c: Phase B: remote selective polling address missing!\n", ch);
+ status = T30_ERR_SEP_UNACCEPTABLE;
+ }
+ }
+ if ((u = t30_get_rx_sender_ident(s->far_t30)))
+ {
+ printf("%c: Phase B: remote sender ident '%s'\n", ch, u);
+ if (s->expected_rx_info.sender_ident[0] && strcmp(s->expected_rx_info.sender_ident, u))
+ {
+ printf("%c: Phase B: remote sender ident incorrect! - expected '%s'\n", ch, s->expected_rx_info.sender_ident);
+ status = T30_ERR_SID_UNACCEPTABLE;
+ }
+ }
+ else
+ {
+ if (s->expected_rx_info.sender_ident[0])
+ {
+ printf("%c: Phase B: remote sender ident missing!\n", ch);
+ status = T30_ERR_SID_UNACCEPTABLE;
+ }
+ }
+ if ((u = t30_get_rx_password(s->far_t30)))
+ {
+ printf("%c: Phase B: remote password '%s'\n", ch, u);
+ if (s->expected_rx_info.password[0] && strcmp(s->expected_rx_info.password, u))
+ {
+ printf("%c: Phase B: remote password incorrect! - expected '%s'\n", ch, s->expected_rx_info.password);
+ status = T30_ERR_PWD_UNACCEPTABLE;
+ }
+ }
+ else
+ {
+ if (s->expected_rx_info.password[0])
+ {
+ printf("%c: Phase B: remote password missing!\n", ch);
+ status = T30_ERR_PWD_UNACCEPTABLE;
+ }
+ }
+ printf("%c: Phase B handler on channel %c - (0x%X) %s\n", ch, ch, result, t30_frametype(result));
+ return status;
+}
+/*- End of function --------------------------------------------------------*/
+
+static int faxtester_phase_d_handler(void *user_data, int result)
+{
+ int i;
+ int ch;
+ faxtester_state_t *s;
+ char tag[20];
+
+ s = (faxtester_state_t *) user_data;
+ ch = s->far_tag;
+ i = 0;
+ snprintf(tag, sizeof(tag), "%c: Phase D", ch);
+ printf("%c: Phase D handler on channel %c - (0x%X) %s\n", ch, ch, result, t30_frametype(result));
+ fax_log_page_transfer_statistics(s->far_t30, tag);
+ fax_log_tx_parameters(s->far_t30, tag);
+ fax_log_rx_parameters(s->far_t30, tag);
+
+ if (s->use_receiver_not_ready)
+ t30_set_receiver_not_ready(s->far_t30, 3);
+
+ if (s->test_local_interrupt)
+ {
+ if (i == 0)
+ {
+ printf("%c: Initiating interrupt request\n", ch);
+ t30_local_interrupt_request(s->far_t30, true);
+ }
+ else
+ {
+ switch (result)
+ {
+ case T30_PIP:
+ case T30_PRI_MPS:
+ case T30_PRI_EOM:
+ case T30_PRI_EOP:
+ printf("%c: Accepting interrupt request\n", ch);
+ t30_local_interrupt_request(s->far_t30, true);
+ break;
+ case T30_PIN:
+ break;
+ }
+ }
+ }
+ return T30_ERR_OK;
+}
+/*- End of function --------------------------------------------------------*/
+
+static void faxtester_phase_e_handler(void *user_data, int result)
+{
+ int ch;
+ faxtester_state_t *s;
+ char tag[20];
+
+ s = (faxtester_state_t *) user_data;
+ ch = s->far_tag;
+ snprintf(tag, sizeof(tag), "%c: Phase E", ch);
+ printf("%c: Phase E handler on channel %c - (%d) %s\n", ch, ch, result, t30_completion_code_to_str(result));
+ fax_log_final_transfer_statistics(s->far_t30, tag);
+ fax_log_tx_parameters(s->far_t30, tag);
+ fax_log_rx_parameters(s->far_t30, tag);
+}
+/*- End of function --------------------------------------------------------*/
+
+static void t30_real_time_frame_handler(void *user_data,
+ bool incoming,
+ const uint8_t *msg,
+ int len)
+{
+ if (msg == NULL)
+ {
+ }
+ else
+ {
+ fprintf(stderr,
+ "T.30: Real time frame handler - %s, %s, length = %d\n",
+ (incoming) ? "line->T.30" : "T.30->line",
+ t30_frametype(msg[2]),
+ len);
+ }
+}
+/*- End of function --------------------------------------------------------*/
+
+static int faxtester_document_handler(void *user_data, int event)
+{
+ int ch;
+ faxtester_state_t *s;
+ t30_state_t *t;
+
+ s = (faxtester_state_t *) user_data;
+ ch = s->far_tag;
+ t = s->far_t30;
+ fprintf(stderr, "%c: Document handler on channel %c - event %d\n", ch, ch, event);
+ if (s->next_tx_file[0])
+ {
+ t30_set_tx_file(t, s->next_tx_file, -1, -1);
+ s->next_tx_file[0] = '\0';
+ return true;
+ }
+ return false;
+}
+/*- End of function --------------------------------------------------------*/
+
+static void faxtester_real_time_frame_handler(faxtester_state_t *s,
+ int direction,
+ const uint8_t *msg,
+ int len)
+{
+ if (msg == NULL)
+ {
+ while (faxtester_next_step(s) == 0)
+ ;
+ /*endwhile*/
+ }
+ else
+ {
+ fprintf(stderr,
+ "TST: Real time frame handler - %s, %s, length = %d\n",
+ (direction) ? "line->tester" : "tester->line",
+ t30_frametype(msg[2]),
+ len);
+ if (direction && msg[1] == s->awaited[1])
+ {
+ if ((s->awaited_len >= 0 && len != abs(s->awaited_len))
+ ||
+ (s->awaited_len < 0 && len < abs(s->awaited_len))
+ ||
+ memcmp(msg, s->awaited, abs(s->awaited_len)) != 0)
+ {
+ span_log_buf(&s->logging, SPAN_LOG_FLOW, "Expected", s->awaited, abs(s->awaited_len));
+ span_log_buf(&s->logging, SPAN_LOG_FLOW, "Received", msg, len);
+ printf("Test failed\n");
+ exit(2);
+ }
+ }
+ if (msg[1] == s->awaited[1])
+ {
+ while (faxtester_next_step(s) == 0)
+ ;
+ /*endwhile*/
+ }
+ }
}
/*- End of function --------------------------------------------------------*/
}
/*- End of function --------------------------------------------------------*/
-void faxtester_set_non_ecm_image_buffer(faxtester_state_t *s, const uint8_t *buf, int len)
+static void faxtester_set_ecm_image_buffer(faxtester_state_t *s, int block, int frame_size, int crc_hit)
{
- s->image_ptr = 0;
- s->image_bit_ptr = 8;
- s->image_len = len;
- s->image_buffer = buf;
-}
-/*- End of function --------------------------------------------------------*/
-
-void faxtester_set_ecm_image_buffer(faxtester_state_t *s, const uint8_t *buf, int len, int block, int frame_size, int crc_hit)
-{
- int start;
-
- start = 256*frame_size*block;
- if (len > start + 256*frame_size)
- len = start + 256*frame_size;
+ s->image_ptr = 256*frame_size*block;
+ if (s->image_len > s->image_ptr + 256*frame_size)
+ s->image_len = s->image_ptr + 256*frame_size;
s->ecm_frame_size = frame_size;
- s->image_ptr = start;
s->image_bit_ptr = 8;
- s->image_len = len;
- s->image_buffer = buf;
s->corrupt_crc = crc_hit;
+ s->image_buffer = s->image;
+
/* Send the first frame */
hdlc_underflow_handler(s);
}
break;
case SIG_STATUS_CARRIER_DOWN:
if (s->modems.rx_trained)
- {
- if (s->real_time_frame_handler)
- s->real_time_frame_handler(s, s->real_time_frame_user_data, true, NULL, 0);
- }
+ faxtester_real_time_frame_handler(s, true, NULL, 0);
s->modems.rx_signal_present = false;
s->modems.rx_trained = false;
break;
return;
}
s = (faxtester_state_t *) user_data;
- if (s->real_time_frame_handler)
- s->real_time_frame_handler(s, s->real_time_frame_user_data, true, msg, len);
+ faxtester_real_time_frame_handler(s, true, msg, len);
}
/*- End of function --------------------------------------------------------*/
break;
case T30_MODEM_CED:
case T30_MODEM_CNG:
- tone = (type == T30_MODEM_CED) ? MODEM_CONNECT_TONES_FAX_CED : MODEM_CONNECT_TONES_FAX_CNG;
+ tone = (type == T30_MODEM_CED) ? FAX_MODEM_CED_TONE_TX : FAX_MODEM_CNG_TONE_TX;
fax_modems_start_slow_modem(t, tone);
s->transmit = true;
break;
}
/*- End of function --------------------------------------------------------*/
-void faxtester_set_real_time_frame_handler(faxtester_state_t *s, faxtester_real_time_frame_handler_t handler, void *user_data)
+static void corrupt_image(faxtester_state_t *s, const char *bad_rows)
+{
+ int i;
+ int j;
+ int k;
+ uint32_t bits;
+ uint32_t bitsx;
+ int list[1000];
+ int x;
+ int row;
+ const char *t;
+
+ /* Form the list of rows to be hit */
+ x = 0;
+ t = bad_rows;
+ while (*t)
+ {
+ while (isspace((int) *t))
+ t++;
+ if (sscanf(t, "%d", &list[x]) < 1)
+ break;
+ x++;
+ while (isdigit((int) *t))
+ t++;
+ if (*t == ',')
+ t++;
+ }
+
+ /* Go through the image, and corrupt the first bit of every listed row */
+ bits = 0x7FF;
+ bitsx = 0x7FF;
+ row = 0;
+ for (i = 0; i < s->image_len; i++)
+ {
+ bits ^= (s->image[i] << 11);
+ bitsx ^= (s->image[i] << 11);
+ for (j = 0; j < 8; j++)
+ {
+ if ((bits & 0xFFF) == 0x800)
+ {
+ /* We are at an EOL. Is this row in the list of rows to be corrupted? */
+ row++;
+ for (k = 0; k < x; k++)
+ {
+ if (list[k] == row)
+ {
+ /* Corrupt this row. TSB85 says to hit the first bit after the EOL */
+ bitsx ^= 0x1000;
+ }
+ }
+ }
+ bits >>= 1;
+ bitsx >>= 1;
+ }
+ s->image[i] = (bitsx >> 3) & 0xFF;
+ }
+ span_log(&s->logging, SPAN_LOG_FLOW, "%d rows found. %d corrupted\n", row, x);
+}
+/*- End of function --------------------------------------------------------*/
+
+static int string_to_msg(uint8_t msg[], uint8_t mask[], const char buf[])
+{
+ int i;
+ int x;
+ const char *t;
+
+ msg[0] = 0;
+ mask[0] = 0xFF;
+ i = 0;
+ t = (char *) buf;
+ while (*t)
+ {
+ /* Skip white space */
+ while (isspace((int) *t))
+ t++;
+ /* If we find ... we allow arbitrary additional info beyond this point in the message */
+ if (t[0] == '.' && t[1] == '.' && t[2] == '.')
+ {
+ return -i;
+ }
+ else if (isxdigit((int) *t))
+ {
+ for ( ; isxdigit((int) *t); t++)
+ {
+ x = *t;
+ if (x >= 'a')
+ x -= 0x20;
+ if (x >= 'A')
+ x -= ('A' - 10);
+ else
+ x -= '0';
+ msg[i] = (msg[i] << 4) | x;
+ }
+ mask[i] = 0xFF;
+ if (*t == '/')
+ {
+ /* There is a mask following the byte */
+ mask[i] = 0;
+ for (t++; isxdigit((int) *t); t++)
+ {
+ x = *t;
+ if (x >= 'a')
+ x -= 0x20;
+ if (x >= 'A')
+ x -= ('A' - 10);
+ else
+ x -= '0';
+ mask[i] = (mask[i] << 4) | x;
+ }
+ }
+ if (*t && !isspace((int) *t))
+ {
+ /* Bad string */
+ return 0;
+ }
+ i++;
+ }
+ }
+ return i;
+}
+/*- End of function --------------------------------------------------------*/
+
+void faxtester_set_flush_handler(faxtester_state_t *s, faxtester_flush_handler_t handler, void *user_data)
+{
+ s->flush_handler = handler;
+ s->flush_user_data = user_data;
+}
+/*- End of function --------------------------------------------------------*/
+
+static void fax_prepare(faxtester_state_t *s)
+{
+ if (s->far_fax)
+ {
+ fax_set_transmit_on_idle(s->far_fax, true);
+ fax_set_tep_mode(s->far_fax, true);
+ }
+#if 0
+ t30_set_tx_ident(s->far_t30, "1234567890");
+ t30_set_tx_sub_address(s->far_t30, "Sub-address");
+ t30_set_tx_sender_ident(s->far_t30, "Sender ID");
+ t30_set_tx_password(s->far_t30, "Password");
+ t30_set_tx_polled_sub_address(s->far_t30, "Polled sub-address");
+ t30_set_tx_selective_polling_address(s->far_t30, "Sel polling address");
+#endif
+ t30_set_tx_nsf(s->far_t30, (const uint8_t *) "\x50\x00\x00\x00Spandsp NSF\x00", 16);
+ //t30_set_tx_nss(s->far_t30, (const uint8_t *) "\x50\x00\x00\x00Spandsp NSS\x00", 16);
+ t30_set_tx_nsc(s->far_t30, (const uint8_t *) "\x50\x00\x00\x00Spandsp NSC\x00", 16);
+ t30_set_ecm_capability(s->far_t30, true);
+ t30_set_supported_t30_features(s->far_t30,
+ T30_SUPPORT_IDENTIFICATION
+ | T30_SUPPORT_SELECTIVE_POLLING
+ | T30_SUPPORT_SUB_ADDRESSING);
+ t30_set_supported_image_sizes(s->far_t30,
+ T4_SUPPORT_WIDTH_215MM
+ | T4_SUPPORT_WIDTH_255MM
+ | T4_SUPPORT_WIDTH_303MM
+ | T4_SUPPORT_LENGTH_US_LETTER
+ | T4_SUPPORT_LENGTH_US_LEGAL
+ | T4_SUPPORT_LENGTH_UNLIMITED);
+ t30_set_supported_bilevel_resolutions(s->far_t30,
+ T4_RESOLUTION_R8_STANDARD
+ | T4_RESOLUTION_R8_FINE
+ | T4_RESOLUTION_R8_SUPERFINE
+ | T4_RESOLUTION_R16_SUPERFINE
+ | T4_RESOLUTION_100_100
+ | T4_RESOLUTION_200_100
+ | T4_RESOLUTION_200_200
+ | T4_RESOLUTION_200_400
+ | T4_RESOLUTION_300_300
+ | T4_RESOLUTION_300_600
+ | T4_RESOLUTION_400_400
+ | T4_RESOLUTION_400_800
+ | T4_RESOLUTION_600_600
+ | T4_RESOLUTION_600_1200
+ | T4_RESOLUTION_1200_1200);
+ t30_set_supported_colour_resolutions(s->far_t30, 0);
+ t30_set_supported_modems(s->far_t30, T30_SUPPORT_V27TER | T30_SUPPORT_V29 | T30_SUPPORT_V17);
+ t30_set_supported_compressions(s->far_t30, T4_COMPRESSION_T4_1D | T4_COMPRESSION_T4_2D | T4_COMPRESSION_T6);
+ t30_set_phase_b_handler(s->far_t30, faxtester_phase_b_handler, (void *) s);
+ t30_set_phase_d_handler(s->far_t30, faxtester_phase_d_handler, (void *) s);
+ t30_set_phase_e_handler(s->far_t30, faxtester_phase_e_handler, (void *) s);
+ t30_set_real_time_frame_handler(s->far_t30, t30_real_time_frame_handler, (void *) s);
+ t30_set_document_handler(s->far_t30, faxtester_document_handler, (void *) s);
+}
+/*- End of function --------------------------------------------------------*/
+
+static void get_node_parms(struct xml_node_parms_s *parms, xmlNodePtr node)
+{
+ parms->dir = xmlGetProp(node, (const xmlChar *) "dir");
+ parms->type = xmlGetProp(node, (const xmlChar *) "type");
+ parms->modem = xmlGetProp(node, (const xmlChar *) "modem");
+ parms->value = xmlGetProp(node, (const xmlChar *) "value");
+ parms->tag = xmlGetProp(node, (const xmlChar *) "tag");
+ parms->bad_rows = xmlGetProp(node, (const xmlChar *) "bad_rows");
+ parms->crc_error = xmlGetProp(node, (const xmlChar *) "crc_error");
+ parms->pattern = xmlGetProp(node, (const xmlChar *) "pattern");
+ parms->timein = xmlGetProp(node, (const xmlChar *) "timein");
+ parms->timeout = xmlGetProp(node, (const xmlChar *) "timeout");
+ parms->min_bits = xmlGetProp(node, (const xmlChar *) "min_bits");
+ parms->frame_size = xmlGetProp(node, (const xmlChar *) "frame_size");
+ parms->block = xmlGetProp(node, (const xmlChar *) "block");
+ parms->compression = xmlGetProp(node, (const xmlChar *) "compression");
+}
+/*- End of function --------------------------------------------------------*/
+
+static void free_node_parms(struct xml_node_parms_s *parms)
+{
+ if (parms->dir)
+ xmlFree(parms->dir);
+ if (parms->type)
+ xmlFree(parms->type);
+ if (parms->modem)
+ xmlFree(parms->modem);
+ if (parms->value)
+ xmlFree(parms->value);
+ if (parms->tag)
+ xmlFree(parms->tag);
+ if (parms->bad_rows)
+ xmlFree(parms->bad_rows);
+ if (parms->crc_error)
+ xmlFree(parms->crc_error);
+ if (parms->pattern)
+ xmlFree(parms->pattern);
+ if (parms->timein)
+ xmlFree(parms->timein);
+ if (parms->timeout)
+ xmlFree(parms->timeout);
+ if (parms->min_bits)
+ xmlFree(parms->min_bits);
+ if (parms->frame_size)
+ xmlFree(parms->frame_size);
+ if (parms->block)
+ xmlFree(parms->block);
+ if (parms->compression)
+ xmlFree(parms->compression);
+}
+/*- End of function --------------------------------------------------------*/
+
+SPAN_DECLARE(int) faxtester_next_step(faxtester_state_t *s)
+{
+ int delay;
+ int flags;
+ struct xml_node_parms_s parms;
+ uint8_t buf[1000];
+ uint8_t mask[1000];
+ char path[1024];
+ int i;
+ int j;
+ int hdlc;
+ int short_train;
+ int min_row_bits;
+ int ecm_frame_size;
+ int ecm_block;
+ int compression_type;
+ xmlChar *min;
+ xmlChar *max;
+ t4_tx_state_t t4_tx_state;
+ t30_stats_t t30_stats;
+
+ s->test_for_call_clear = false;
+ if (s->cur == NULL)
+ {
+ if (!s->final_delayed)
+ {
+ /* Add a bit of waiting at the end, to ensure everything gets flushed through,
+ any timers can expire, etc. */
+ faxtester_set_timeout(s, -1);
+ faxtester_set_rx_type(s, T30_MODEM_NONE, 0, false, false);
+ faxtester_set_tx_type(s, T30_MODEM_PAUSE, 0, 120000, false);
+ s->final_delayed = true;
+ return 1;
+ }
+ /* Finished */
+ printf("Test passed\n");
+ exit(0);
+ }
+ for (;;)
+ {
+ if (s->cur == NULL)
+ {
+ if (s->repeat_parent == NULL)
+ {
+ /* Finished */
+ printf("Test passed\n");
+ exit(0);
+ }
+ if (++s->repeat_count > s->repeat_max)
+ {
+ /* Finished */
+ printf("Too many repeats\n");
+ printf("Test failed\n");
+ exit(0);
+ }
+ if (s->repeat_count < s->repeat_min)
+ {
+ s->cur = s->repeat_start;
+ }
+ else
+ {
+ s->cur = s->repeat_parent->next;
+ s->repeat_parent = NULL;
+ }
+ }
+ if (xmlStrcmp(s->cur->name, (const xmlChar *) "step") == 0)
+ {
+ break;
+ }
+ if (s->repeat_parent == NULL && xmlStrcmp(s->cur->name, (const xmlChar *) "repeat") == 0)
+ {
+ min = xmlGetProp(s->cur, (const xmlChar *) "min");
+ max = xmlGetProp(s->cur, (const xmlChar *) "max");
+ s->repeat_min = min ? atoi((const char *) min) : 0;
+ s->repeat_max = max ? atoi((const char *) max) : INT_MAX;
+ s->repeat_count = 0;
+ if (min)
+ xmlFree(min);
+ if (max)
+ xmlFree(max);
+ if (s->repeat_min > 0)
+ {
+ s->repeat_parent = s->cur;
+ s->repeat_start =
+ s->cur = s->cur->xmlChildrenNode;
+ continue;
+ }
+ }
+ s->cur = s->cur->next;
+ }
+
+ get_node_parms(&parms, s->cur);
+
+ s->cur = s->cur->next;
+
+ span_log(&s->logging,
+ SPAN_LOG_FLOW,
+ "Dir - %s, type - %s, modem - %s, value - %s, timein - %s, timeout - %s, tag - %s\n",
+ (parms.dir) ? (const char *) parms.dir : " ",
+ (parms.type) ? (const char *) parms.type : "",
+ (parms.modem) ? (const char *) parms.modem : "",
+ (parms.value) ? (const char *) parms.value : "",
+ (parms.timein) ? (const char *) parms.timein : "",
+ (parms.timeout) ? (const char *) parms.timeout : "",
+ (parms.tag) ? (const char *) parms.tag : "");
+ if (parms.type == NULL)
+ {
+ free_node_parms(&parms);
+ return 1;
+ }
+ s->timein_x = (parms.timein) ? atoi((const char *) parms.timein) : -1;
+ s->timeout_x = (parms.timeout) ? atoi((const char *) parms.timeout) : -1;
+
+ if (parms.dir && strcasecmp((const char *) parms.dir, "R") == 0)
+ {
+ /* Receive always has a timeout applied. */
+ if (s->timeout_x < 0)
+ s->timeout_x = 7000;
+ faxtester_set_timeout(s, s->timeout_x);
+ if (parms.modem)
+ {
+ hdlc = (strcasecmp((const char *) parms.type, "PREAMBLE") == 0);
+ short_train = (strcasecmp((const char *) parms.type, "TCF") != 0);
+ faxtester_set_tx_type(s, T30_MODEM_NONE, 0, false, false);
+ if (strcasecmp((const char *) parms.modem, "V.21") == 0)
+ {
+ faxtester_set_rx_type(s, T30_MODEM_V21, 300, false, true);
+ }
+ else if (strcasecmp((const char *) parms.modem, "V.17/14400") == 0)
+ {
+ faxtester_set_rx_type(s, T30_MODEM_V17, 14400, short_train, hdlc);
+ }
+ else if (strcasecmp((const char *) parms.modem, "V.17/12000") == 0)
+ {
+ faxtester_set_rx_type(s, T30_MODEM_V17, 12000, short_train, hdlc);
+ }
+ else if (strcasecmp((const char *) parms.modem, "V.17/9600") == 0)
+ {
+ faxtester_set_rx_type(s, T30_MODEM_V17, 9600, short_train, hdlc);
+ }
+ else if (strcasecmp((const char *) parms.modem, "V.17/7200") == 0)
+ {
+ faxtester_set_rx_type(s, T30_MODEM_V17, 7200, short_train, hdlc);
+ }
+ else if (strcasecmp((const char *) parms.modem, "V.29/9600") == 0)
+ {
+ faxtester_set_rx_type(s, T30_MODEM_V29, 9600, false, hdlc);
+ }
+ else if (strcasecmp((const char *) parms.modem, "V.29/7200") == 0)
+ {
+ faxtester_set_rx_type(s, T30_MODEM_V29, 7200, false, hdlc);
+ }
+ else if (strcasecmp((const char *) parms.modem, "V.27ter/4800") == 0)
+ {
+ faxtester_set_rx_type(s, T30_MODEM_V27TER, 4800, false, hdlc);
+ }
+ else if (strcasecmp((const char *) parms.modem, "V.27ter/2400") == 0)
+ {
+ faxtester_set_rx_type(s, T30_MODEM_V27TER, 2400, false, hdlc);
+ }
+ else
+ {
+ span_log(&s->logging, SPAN_LOG_FLOW, "Unrecognised modem\n");
+ }
+ }
+
+ if (strcasecmp((const char *) parms.type, "SET") == 0)
+ {
+ if (strcasecmp((const char *) parms.tag, "IDENT") == 0)
+ strcpy(s->expected_rx_info.ident, (const char *) parms.value);
+ else if (strcasecmp((const char *) parms.tag, "SUB") == 0)
+ strcpy(s->expected_rx_info.sub_address, (const char *) parms.value);
+ else if (strcasecmp((const char *) parms.tag, "SEP") == 0)
+ strcpy(s->expected_rx_info.selective_polling_address, (const char *) parms.value);
+ else if (strcasecmp((const char *) parms.tag, "PSA") == 0)
+ strcpy(s->expected_rx_info.polled_sub_address, (const char *) parms.value);
+ else if (strcasecmp((const char *) parms.tag, "SID") == 0)
+ strcpy(s->expected_rx_info.sender_ident, (const char *) parms.value);
+ else if (strcasecmp((const char *) parms.tag, "PWD") == 0)
+ strcpy(s->expected_rx_info.password, (const char *) parms.value);
+ free_node_parms(&parms);
+ return 0;
+ }
+ else if (strcasecmp((const char *) parms.type, "CNG") == 0)
+ {
+ /* Look for CNG */
+ faxtester_set_rx_type(s, T30_MODEM_CNG, 0, false, false);
+ faxtester_set_tx_type(s, T30_MODEM_NONE, 0, false, false);
+ }
+ else if (strcasecmp((const char *) parms.type, "CED") == 0)
+ {
+ /* Look for CED */
+ faxtester_set_rx_type(s, T30_MODEM_CED, 0, false, false);
+ faxtester_set_tx_type(s, T30_MODEM_NONE, 0, false, false);
+ }
+ else if (strcasecmp((const char *) parms.type, "HDLC") == 0)
+ {
+ i = string_to_msg(buf, mask, (const char *) parms.value);
+ bit_reverse(s->awaited, buf, abs(i));
+ s->awaited_len = i;
+ }
+ else if (strcasecmp((const char *) parms.type, "TCF") == 0)
+ {
+ }
+ else if (strcasecmp((const char *) parms.type, "MSG") == 0)
+ {
+ }
+ else if (strcasecmp((const char *) parms.type, "PP") == 0)
+ {
+ }
+ else if (strcasecmp((const char *) parms.type, "SILENCE") == 0)
+ {
+ faxtest_set_rx_silence(s);
+ }
+ else if (strcasecmp((const char *) parms.type, "CLEAR") == 0)
+ {
+ span_log(&s->logging, SPAN_LOG_FLOW, "Far end should drop the call\n");
+ s->test_for_call_clear = true;
+ s->call_clear_timer = 0;
+ }
+ else
+ {
+ span_log(&s->logging, SPAN_LOG_FLOW, "Unrecognised type '%s'\n", (const char *) parms.type);
+ free_node_parms(&parms);
+ return 0;
+ }
+ }
+ else
+ {
+ faxtester_set_timeout(s, s->timeout_x);
+ if (parms.modem)
+ {
+ hdlc = (strcasecmp((const char *) parms.type, "PREAMBLE") == 0);
+ short_train = (strcasecmp((const char *) parms.type, "TCF") != 0);
+ faxtester_set_rx_type(s, T30_MODEM_NONE, 0, false, false);
+ if (strcasecmp((const char *) parms.modem, "V.21") == 0)
+ {
+ faxtester_set_tx_type(s, T30_MODEM_V21, 300, false, true);
+ }
+ else if (strcasecmp((const char *) parms.modem, "V.17/14400") == 0)
+ {
+ faxtester_set_tx_type(s, T30_MODEM_V17, 14400, short_train, hdlc);
+ }
+ else if (strcasecmp((const char *) parms.modem, "V.17/12000") == 0)
+ {
+ faxtester_set_tx_type(s, T30_MODEM_V17, 12000, short_train, hdlc);
+ }
+ else if (strcasecmp((const char *) parms.modem, "V.17/9600") == 0)
+ {
+ faxtester_set_tx_type(s, T30_MODEM_V17, 9600, short_train, hdlc);
+ }
+ else if (strcasecmp((const char *) parms.modem, "V.17/7200") == 0)
+ {
+ faxtester_set_tx_type(s, T30_MODEM_V17, 7200, short_train, hdlc);
+ }
+ else if (strcasecmp((const char *) parms.modem, "V.29/9600") == 0)
+ {
+ faxtester_set_tx_type(s, T30_MODEM_V29, 9600, false, hdlc);
+ }
+ else if (strcasecmp((const char *) parms.modem, "V.29/7200") == 0)
+ {
+ faxtester_set_tx_type(s, T30_MODEM_V29, 7200, false, hdlc);
+ }
+ else if (strcasecmp((const char *) parms.modem, "V.27ter/4800") == 0)
+ {
+ faxtester_set_tx_type(s, T30_MODEM_V27TER, 4800, false, hdlc);
+ }
+ else if (strcasecmp((const char *) parms.modem, "V.27ter/2400") == 0)
+ {
+ faxtester_set_tx_type(s, T30_MODEM_V27TER, 2400, false, hdlc);
+ }
+ else
+ {
+ span_log(&s->logging, SPAN_LOG_FLOW, "Unrecognised modem\n");
+ }
+ }
+
+ if (strcasecmp((const char *) parms.type, "SET") == 0)
+ {
+ if (strcasecmp((const char *) parms.tag, "IDENT") == 0)
+ t30_set_tx_ident(s->far_t30, (const char *) parms.value);
+ else if (strcasecmp((const char *) parms.tag, "SUB") == 0)
+ t30_set_tx_sub_address(s->far_t30, (const char *) parms.value);
+ else if (strcasecmp((const char *) parms.tag, "SEP") == 0)
+ t30_set_tx_selective_polling_address(s->far_t30, (const char *) parms.value);
+ else if (strcasecmp((const char *) parms.tag, "PSA") == 0)
+ t30_set_tx_polled_sub_address(s->far_t30, (const char *) parms.value);
+ else if (strcasecmp((const char *) parms.tag, "SID") == 0)
+ t30_set_tx_sender_ident(s->far_t30, (const char *) parms.value);
+ else if (strcasecmp((const char *) parms.tag, "PWD") == 0)
+ t30_set_tx_password(s->far_t30, (const char *) parms.value);
+ else if (strcasecmp((const char *) parms.tag, "RXFILE") == 0)
+ {
+ if (parms.value)
+ t30_set_rx_file(s->far_t30, (const char *) parms.value, -1);
+ else
+ t30_set_rx_file(s->far_t30, output_tiff_file_name, -1);
+ }
+ else if (strcasecmp((const char *) parms.tag, "TXFILE") == 0)
+ {
+ sprintf(s->next_tx_file, "%s/%s", s->image_path, (const char *) parms.value);
+ printf("Push '%s'\n", s->next_tx_file);
+ }
+ free_node_parms(&parms);
+ return 0;
+ }
+ else if (strcasecmp((const char *) parms.type, "CALL") == 0)
+ {
+ if (s->far_fax)
+ fax_restart(s->far_fax, false);
+ else
+ t38_terminal_restart(s->far_t38, false);
+ fax_prepare(s);
+ s->next_tx_file[0] = '\0';
+ t30_set_rx_file(s->far_t30, output_tiff_file_name, -1);
+ /* Avoid libtiff 3.8.2 and earlier bug on complex 2D lines. */
+ t30_set_supported_output_compressions(s->far_t30, T4_COMPRESSION_T4_1D);
+ if (parms.value)
+ {
+ sprintf(path, "%s/%s", s->image_path, (const char *) parms.value);
+ t30_set_tx_file(s->far_t30, path, -1, -1);
+ }
+ free_node_parms(&parms);
+ return 0;
+ }
+ else if (strcasecmp((const char *) parms.type, "ANSWER") == 0)
+ {
+ if (s->far_fax)
+ fax_restart(s->far_fax, true);
+ else
+ t38_terminal_restart(s->far_t38, true);
+ fax_prepare(s);
+ s->next_tx_file[0] = '\0';
+ /* Avoid libtiff 3.8.2 and earlier bug on complex 2D lines. */
+ t30_set_supported_output_compressions(s->far_t30, T4_COMPRESSION_T4_1D);
+ if (parms.value)
+ {
+ sprintf(path, "%s/%s", s->image_path, (const char *) parms.value);
+ t30_set_tx_file(s->far_t30, path, -1, -1);
+ }
+ free_node_parms(&parms);
+ return 0;
+ }
+ else if (strcasecmp((const char *) parms.type, "CNG") == 0)
+ {
+ faxtester_set_rx_type(s, T30_MODEM_NONE, 0, false, false);
+ faxtester_set_tx_type(s, T30_MODEM_CNG, 0, false, false);
+ }
+ else if (strcasecmp((const char *) parms.type, "CED") == 0)
+ {
+ faxtester_set_rx_type(s, T30_MODEM_NONE, 0, false, false);
+ faxtester_set_tx_type(s, T30_MODEM_CED, 0, false, false);
+ }
+ else if (strcasecmp((const char *) parms.type, "WAIT") == 0)
+ {
+ delay = (parms.value) ? atoi((const char *) parms.value) : 1;
+ faxtester_set_rx_type(s, T30_MODEM_NONE, 0, false, false);
+ faxtester_set_tx_type(s, T30_MODEM_PAUSE, 0, delay, false);
+ }
+ else if (strcasecmp((const char *) parms.type, "PREAMBLE") == 0)
+ {
+ flags = (parms.value) ? atoi((const char *) parms.value) : 37;
+ faxtester_send_hdlc_flags(s, flags);
+ }
+ else if (strcasecmp((const char *) parms.type, "POSTAMBLE") == 0)
+ {
+ flags = (parms.value) ? atoi((const char *) parms.value) : 5;
+ faxtester_send_hdlc_flags(s, flags);
+ }
+ else if (strcasecmp((const char *) parms.type, "HDLC") == 0)
+ {
+ i = string_to_msg(buf, mask, (const char *) parms.value);
+ bit_reverse(buf, buf, abs(i));
+ if (parms.crc_error && strcasecmp((const char *) parms.crc_error, "0") == 0)
+ faxtester_send_hdlc_msg(s, buf, abs(i), false);
+ else
+ faxtester_send_hdlc_msg(s, buf, abs(i), true);
+ }
+ else if (strcasecmp((const char *) parms.type, "TCF") == 0)
+ {
+ i = (parms.value) ? atoi((const char *) parms.value) : 450;
+ if (parms.pattern)
+ {
+ /* TODO: implement proper patterns */
+ j = atoi((const char *) parms.pattern);
+ memset(s->image, 0x55, j);
+ if (i > j)
+ memset(s->image + j, 0, i - j);
+ }
+ else
+ {
+ memset(s->image, 0, i);
+ }
+ s->image_ptr = 0;
+ s->image_bit_ptr = 8;
+ s->image_buffer = s->image;
+ s->image_len = i;
+ }
+ else if (strcasecmp((const char *) parms.type, "MSG") == 0)
+ {
+ /* A non-ECM page */
+ min_row_bits = (parms.min_bits) ? atoi((const char *) parms.min_bits) : 0;
+ sprintf(path, "%s/%s", s->image_path, (const char *) parms.value);
+ if (t4_tx_init(&t4_tx_state, path, -1, -1) == NULL)
+ {
+ span_log(&s->logging, SPAN_LOG_FLOW, "Failed to init T.4 send\n");
+ printf("Test failed\n");
+ exit(2);
+ }
+ t4_tx_set_header_info(&t4_tx_state, NULL);
+ compression_type = T4_COMPRESSION_T4_1D;
+ if (parms.compression)
+ {
+ if (strcasecmp((const char *) parms.compression, "T.4 1D") == 0)
+ compression_type = T4_COMPRESSION_T4_1D;
+ else if (strcasecmp((const char *) parms.compression, "T.4 2D") == 0)
+ compression_type = T4_COMPRESSION_T4_2D;
+ else if (strcasecmp((const char *) parms.compression, "T.6") == 0)
+ compression_type = T4_COMPRESSION_T6;
+ else if (strcasecmp((const char *) parms.compression, "T.85") == 0)
+ compression_type = T4_COMPRESSION_T85;
+ }
+ if (t4_tx_set_tx_image_format(&t4_tx_state,
+ compression_type,
+ T4_SUPPORT_WIDTH_215MM
+ | T4_SUPPORT_LENGTH_US_LETTER
+ | T4_SUPPORT_LENGTH_US_LEGAL
+ | T4_SUPPORT_LENGTH_UNLIMITED,
+ T4_RESOLUTION_R8_STANDARD
+ | T4_RESOLUTION_R8_FINE
+ | T4_RESOLUTION_R8_SUPERFINE
+ | T4_RESOLUTION_R16_SUPERFINE
+ | T4_RESOLUTION_200_100
+ | T4_RESOLUTION_200_200
+ | T4_RESOLUTION_200_400
+ | T4_RESOLUTION_300_300
+ | T4_RESOLUTION_300_600
+ | T4_RESOLUTION_400_400
+ | T4_RESOLUTION_400_800
+ | T4_RESOLUTION_600_600
+ | T4_RESOLUTION_600_1200
+ | T4_RESOLUTION_1200_1200,
+ T4_RESOLUTION_100_100
+ | T4_RESOLUTION_200_200
+ | T4_RESOLUTION_300_300
+ | T4_RESOLUTION_400_400
+ | T4_RESOLUTION_600_600
+ | T4_RESOLUTION_1200_1200) < 0)
+ {
+ span_log(&s->logging, SPAN_LOG_FLOW, "Failed to set T.4 compression\n");
+ printf("Test failed\n");
+ exit(2);
+ }
+ t4_tx_set_min_bits_per_row(&t4_tx_state, min_row_bits);
+ if (t4_tx_start_page(&t4_tx_state))
+ {
+ span_log(&s->logging, SPAN_LOG_FLOW, "Failed to start T.4 send\n");
+ printf("Test failed\n");
+ exit(2);
+ }
+ s->image_len = t4_tx_get(&t4_tx_state, s->image, sizeof(s->image));
+ if (parms.bad_rows)
+ {
+ span_log(&s->logging, SPAN_LOG_FLOW, "We need to corrupt the image\n");
+ corrupt_image(s, (const char *) parms.bad_rows);
+ }
+ t4_tx_release(&t4_tx_state);
+ span_log(&s->logging, SPAN_LOG_FLOW, "Non-ECM image is %d bytes (min row bits %d)\n", s->image_len, min_row_bits);
+ s->image_ptr = 0;
+ s->image_bit_ptr = 8;
+ s->image_buffer = s->image;
+ }
+ else if (strcasecmp((const char *) parms.type, "PP") == 0)
+ {
+ min_row_bits = (parms.min_bits) ? atoi((const char *) parms.min_bits) : 0;
+ ecm_block = (parms.block) ? atoi((const char *) parms.block) : 0;
+ ecm_frame_size = (parms.frame_size) ? atoi((const char *) parms.frame_size) : 64;
+ i = (parms.crc_error) ? atoi((const char *) parms.crc_error) : -1;
+ sprintf(path, "%s/%s", s->image_path, (const char *) parms.value);
+ if (t4_tx_init(&t4_tx_state, path, -1, -1) == NULL)
+ {
+ span_log(&s->logging, SPAN_LOG_FLOW, "Failed to init T.4 send\n");
+ printf("Test failed\n");
+ exit(2);
+ }
+ t4_tx_set_header_info(&t4_tx_state, NULL);
+ compression_type = T4_COMPRESSION_T4_1D;
+ if (parms.compression)
+ {
+ if (strcasecmp((const char *) parms.compression, "T.4 1D") == 0)
+ compression_type = T4_COMPRESSION_T4_1D;
+ else if (strcasecmp((const char *) parms.compression, "T.4 2D") == 0)
+ compression_type = T4_COMPRESSION_T4_2D;
+ else if (strcasecmp((const char *) parms.compression, "T.6") == 0)
+ compression_type = T4_COMPRESSION_T6;
+ else if (strcasecmp((const char *) parms.compression, "T.85") == 0)
+ compression_type = T4_COMPRESSION_T85;
+ }
+ if (t4_tx_set_tx_image_format(&t4_tx_state,
+ compression_type,
+ T4_SUPPORT_WIDTH_215MM
+ | T4_SUPPORT_LENGTH_US_LETTER
+ | T4_SUPPORT_LENGTH_US_LEGAL
+ | T4_SUPPORT_LENGTH_UNLIMITED,
+ T4_RESOLUTION_R8_STANDARD
+ | T4_RESOLUTION_R8_FINE
+ | T4_RESOLUTION_R8_SUPERFINE
+ | T4_RESOLUTION_R16_SUPERFINE
+ | T4_RESOLUTION_200_100
+ | T4_RESOLUTION_200_200
+ | T4_RESOLUTION_200_400
+ | T4_RESOLUTION_300_300
+ | T4_RESOLUTION_300_600
+ | T4_RESOLUTION_400_400
+ | T4_RESOLUTION_400_800
+ | T4_RESOLUTION_600_600
+ | T4_RESOLUTION_600_1200
+ | T4_RESOLUTION_1200_1200,
+ T4_RESOLUTION_100_100
+ | T4_RESOLUTION_200_200
+ | T4_RESOLUTION_300_300
+ | T4_RESOLUTION_400_400
+ | T4_RESOLUTION_600_600
+ | T4_RESOLUTION_1200_1200) < 0)
+ {
+ span_log(&s->logging, SPAN_LOG_FLOW, "Failed to set T.4 compression\n");
+ printf("Test failed\n");
+ exit(2);
+ }
+ t4_tx_set_min_bits_per_row(&t4_tx_state, min_row_bits);
+ if (t4_tx_start_page(&t4_tx_state))
+ {
+ span_log(&s->logging, SPAN_LOG_FLOW, "Failed to start T.4 send\n");
+ printf("Test failed\n");
+ exit(2);
+ }
+ /*endif*/
+ s->image_len = t4_tx_get(&t4_tx_state, s->image, sizeof(s->image));
+ if (parms.bad_rows)
+ {
+ span_log(&s->logging, SPAN_LOG_FLOW, "We need to corrupt the image\n");
+ corrupt_image(s, (const char *) parms.bad_rows);
+ }
+ /*endif*/
+ t4_tx_release(&t4_tx_state);
+ span_log(&s->logging, SPAN_LOG_FLOW, "ECM image is %d bytes (min row bits %d)\n", s->image_len, min_row_bits);
+ faxtester_set_ecm_image_buffer(s, ecm_block, ecm_frame_size, i);
+ }
+ else if (strcasecmp((const char *) parms.type, "CLEAR") == 0)
+ {
+ span_log(&s->logging, SPAN_LOG_FLOW, "Time to drop the call\n");
+ t30_terminate(s->far_t30);
+ free_node_parms(&parms);
+ return 0;
+ }
+ else if (strcasecmp((const char *) parms.type, "STATUS") == 0)
+ {
+ if (parms.value)
+ {
+ for (i = 0; t30_status[i].code >= 0; i++)
+ {
+ if (strcmp(t30_status[i].tag, (const char *) parms.value) == 0)
+ break;
+ }
+ if (t30_status[i].code >= 0)
+ delay = t30_status[i].code;
+ else
+ delay = atoi((const char *) parms.value);
+ t30_get_transfer_statistics(s->far_t30, &t30_stats);
+ if (delay == t30_stats.current_status)
+ span_log(&s->logging, SPAN_LOG_FLOW, "Expected status (%s) found\n", t30_status[i].tag);
+ else
+ span_log(&s->logging, SPAN_LOG_FLOW, "Expected status %s, but found %s (%d)\n", t30_status[i].tag, t30_status[t30_stats.current_status].tag, t30_stats.current_status);
+ if (delay != t30_stats.current_status)
+ {
+ printf("Test failed\n");
+ exit(2);
+ }
+ }
+ free_node_parms(&parms);
+ return 0;
+ }
+ else
+ {
+ span_log(&s->logging, SPAN_LOG_FLOW, "Unrecognised type '%s'\n", (const char *) parms.type);
+ free_node_parms(&parms);
+ return 0;
+ }
+ /*endif*/
+ }
+ /*endif*/
+ free_node_parms(&parms);
+ return 1;
+}
+/*- End of function --------------------------------------------------------*/
+
+static int parse_config(faxtester_state_t *s, xmlNodePtr cur)
{
- s->real_time_frame_handler = handler;
- s->real_time_frame_user_data = user_data;
+ xmlChar *x;
+ xmlChar *y;
+
+ while (cur)
+ {
+ if (xmlStrcmp(cur->name, (const xmlChar *) "path") == 0)
+ {
+ x = NULL;
+ y = NULL;
+ if ((x = xmlGetProp(cur, (const xmlChar *) "type"))
+ &&
+ (y = xmlGetProp(cur, (const xmlChar *) "value")))
+ {
+ if (strcasecmp((const char *) x, "IMAGE") == 0)
+ {
+ span_log(&s->logging, SPAN_LOG_FLOW, "Found '%s' '%s'\n", (char *) x, (char *) y);
+ strcpy(s->image_path, (const char *) y);
+ }
+ /*endif*/
+ }
+ /*endif*/
+ if (x)
+ xmlFree(x);
+ /*endif*/
+ if (y)
+ xmlFree(y);
+ /*endif*/
+ }
+ /*endif*/
+ cur = cur->next;
+ }
+ /*endwhile*/
+ return -1;
+}
+/*- End of function --------------------------------------------------------*/
+
+static int parse_test_group(faxtester_state_t *s, xmlNodePtr cur, const char *test)
+{
+ xmlChar *x;
+
+ while (cur)
+ {
+ if (xmlStrcmp(cur->name, (const xmlChar *) "test") == 0)
+ {
+ if ((x = xmlGetProp(cur, (const xmlChar *) "name")))
+ {
+ if (xmlStrcmp(x, (const xmlChar *) test) == 0)
+ {
+ span_log(&s->logging, SPAN_LOG_FLOW, "Found '%s'\n", (char *) x);
+ s->cur = cur->xmlChildrenNode;
+ xmlFree(x);
+ return 0;
+ }
+ /*endif*/
+ xmlFree(x);
+ }
+ /*endif*/
+ }
+ /*endif*/
+ cur = cur->next;
+ }
+ /*endwhile*/
+ return -1;
}
/*- End of function --------------------------------------------------------*/
-void faxtester_set_front_end_step_complete_handler(faxtester_state_t *s, faxtester_front_end_step_complete_handler_t handler, void *user_data)
+static int get_test_set(faxtester_state_t *s, const char *test_file, const char *test)
{
- s->front_end_step_complete_handler = handler;
- s->front_end_step_complete_user_data = user_data;
+ xmlParserCtxtPtr ctxt;
+ xmlNodePtr cur;
+
+ if ((ctxt = xmlNewParserCtxt()) == NULL)
+ {
+ fprintf(stderr, "Failed to allocate XML parser context\n");
+ return -1;
+ }
+ /* parse the file, activating the DTD validation option */
+ if ((s->doc = xmlCtxtReadFile(ctxt, test_file, NULL, XML_PARSE_XINCLUDE | XML_PARSE_DTDVALID)) == NULL)
+ {
+ fprintf(stderr, "Failed to read the XML document\n");
+ return -1;
+ }
+ if (ctxt->valid == 0)
+ {
+ fprintf(stderr, "Failed to validate the XML document\n");
+ xmlFreeDoc(s->doc);
+ s->doc = NULL;
+ xmlFreeParserCtxt(ctxt);
+ return -1;
+ }
+ xmlFreeParserCtxt(ctxt);
+
+ /* Check the document is of the right kind */
+ if ((cur = xmlDocGetRootElement(s->doc)) == NULL)
+ {
+ xmlFreeDoc(s->doc);
+ s->doc = NULL;
+ fprintf(stderr, "Empty document\n");
+ return -1;
+ }
+ /*endif*/
+ if (xmlStrcmp(cur->name, (const xmlChar *) "fax-tests"))
+ {
+ xmlFreeDoc(s->doc);
+ s->doc = NULL;
+ fprintf(stderr, "Document of the wrong type, root node != fax-tests\n");
+ return -1;
+ }
+ /*endif*/
+ cur = cur->xmlChildrenNode;
+ while (cur && xmlIsBlankNode(cur))
+ cur = cur->next;
+ /*endwhile*/
+ if (cur == NULL)
+ {
+ fprintf(stderr, "XML test not found\n");
+ return -1;
+ }
+ /*endif*/
+ xmlCleanupParser();
+ while (cur)
+ {
+ if (xmlStrcmp(cur->name, (const xmlChar *) "config") == 0)
+ parse_config(s, cur->xmlChildrenNode);
+ /*endif*/
+ if (xmlStrcmp(cur->name, (const xmlChar *) "test-group") == 0)
+ {
+ if (parse_test_group(s, cur->xmlChildrenNode, test) == 0)
+ return 0;
+ /*endif*/
+ }
+ /*endif*/
+ cur = cur->next;
+ }
+ /*endwhile*/
+ fprintf(stderr, "XML test not found\n");
+ return -1;
}
/*- End of function --------------------------------------------------------*/
-void faxtester_set_front_end_step_timeout_handler(faxtester_state_t *s, faxtester_front_end_step_complete_handler_t handler, void *user_data)
+SPAN_DECLARE(logging_state_t *) faxtester_get_logging_state(faxtester_state_t *s)
{
- s->front_end_step_timeout_handler = handler;
- s->front_end_step_timeout_user_data = user_data;
+ return &s->logging;
}
/*- End of function --------------------------------------------------------*/
-faxtester_state_t *faxtester_init(faxtester_state_t *s, int calling_party)
+faxtester_state_t *faxtester_init(faxtester_state_t *s, const char *test_file, const char *test)
{
if (s == NULL)
{
if ((s = (faxtester_state_t *) malloc(sizeof(*s))) == NULL)
return NULL;
}
+ /*endif*/
memset(s, 0, sizeof(*s));
span_log_init(&s->logging, SPAN_LOG_NONE, NULL);
fax_modems_set_tep_mode(&s->modems, false);
fax_modems_set_rx_active(&s->modems, true);
faxtester_set_timeout(s, -1);
+ s->timein_x = -1;
+ s->timeout_x = -1;
faxtester_set_tx_type(s, T30_MODEM_NONE, 0, false, false);
-
+ strcpy(s->image_path, ".");
+ s->next_tx_file[0] = '\0';
+ if (get_test_set(s, test_file, test) < 0)
+ {
+ /* TODO: free the state, if it was allocated. */
+ return NULL;
+ }
+ /*endif*/
+ memset(&s->expected_rx_info, 0, sizeof(s->expected_rx_info));
return s;
}
/*- End of function --------------------------------------------------------*/
int faxtester_release(faxtester_state_t *s)
{
+ if (s->doc)
+ {
+ xmlFreeDoc(s->doc);
+ s->doc = NULL;
+ }
return 0;
}
/*- End of function --------------------------------------------------------*/
int faxtester_free(faxtester_state_t *s)
{
+ faxtester_release(s);
free(s);
return 0;
}
/*- End of function --------------------------------------------------------*/
-
-void faxtester_set_flush_handler(faxtester_state_t *s, faxtester_flush_handler_t handler, void *user_data)
-{
- s->flush_handler = handler;
- s->flush_user_data = user_data;
-}
-/*- End of function --------------------------------------------------------*/
/*- End of file ------------------------------------------------------------*/
typedef void (*faxtester_flush_handler_t)(faxtester_state_t *s, void *user_data, int which);
-/*!
- FAX tester real time frame handler.
- \brief FAX tester real time frame handler.
- \param s The FAX tester context.
- \param user_data An opaque pointer.
- \param direction True for incoming, false for outgoing.
- \param msg The HDLC message.
- \param len The length of the message.
-*/
-typedef void (*faxtester_real_time_frame_handler_t)(faxtester_state_t *s,
- void *user_data,
- int direction,
- const uint8_t *msg,
- int len);
-
-typedef void (*faxtester_front_end_step_complete_handler_t)(faxtester_state_t *s, void *user_data);
-
/*!
FAX tester descriptor.
*/
{
/*! \brief The far end FAX context */
fax_state_t *far_fax;
+ t38_terminal_state_t *far_t38;
+
+ int far_tag;
/*! \brief The far end T.38 terminal context */
t38_terminal_state_t *far_t38_fax;
+
+ t30_state_t *far_t30;
+
+ t30_exchanged_info_t expected_rx_info;
+
+ bool use_receiver_not_ready;
+ bool test_local_interrupt;
/*! \brief Path for the FAX image test files. */
char image_path[1024];
xmlDocPtr doc;
/*! \brief Pointer to our current step in the test. */
xmlNodePtr cur;
+
+ int repeat_min;
+ int repeat_max;
+ int repeat_count;
+ xmlNodePtr repeat_start;
+ xmlNodePtr repeat_parent;
faxtester_flush_handler_t flush_handler;
void *flush_user_data;
- /*! \brief A pointer to a callback routine to be called when frames are
- exchanged. */
- faxtester_real_time_frame_handler_t real_time_frame_handler;
- /*! \brief An opaque pointer supplied in real time frame callbacks. */
- void *real_time_frame_user_data;
-
- faxtester_front_end_step_complete_handler_t front_end_step_complete_handler;
- void *front_end_step_complete_user_data;
-
- faxtester_front_end_step_complete_handler_t front_end_step_timeout_handler;
- void *front_end_step_timeout_user_data;
-
const uint8_t *image_buffer;
int image_len;
int image_ptr;
int image_bit_ptr;
+ uint8_t image[1000000];
+
int ecm_frame_size;
int corrupt_crc;
*/
void faxtester_set_tep_mode(faxtester_state_t *s, int use_tep);
-void faxtester_set_real_time_frame_handler(faxtester_state_t *s, faxtester_real_time_frame_handler_t handler, void *user_data);
-
-void faxtester_set_front_end_step_complete_handler(faxtester_state_t *s, faxtester_front_end_step_complete_handler_t handler, void *user_data);
-
-void faxtester_set_front_end_step_timeout_handler(faxtester_state_t *s, faxtester_front_end_step_complete_handler_t handler, void *user_data);
-
void faxtester_set_timeout(faxtester_state_t *s, int timeout);
-void faxtester_set_non_ecm_image_buffer(faxtester_state_t *s, const uint8_t *buf, int len);
+SPAN_DECLARE(int) faxtester_next_step(faxtester_state_t *s);
-void faxtester_set_ecm_image_buffer(faxtester_state_t *s, const uint8_t *buf, int len, int block, int frame_size, int crc_hit);
+/*! Get the logging context associated with a FAX tester context.
+ \brief Get the logging context associated with a FAX tester context.
+ \param s The FAX tester context.
+ \return A pointer to the logging context */
+SPAN_DECLARE(logging_state_t *) faxtester_get_logging_state(faxtester_state_t *s);
-/*! Initialise a FAX context.
- \brief Initialise a FAX context.
+/*! Initialise a FAX tester context.
+ \brief Initialise a FAX tester context.
\param s The FAX tester context.
- \param calling_party true if the context is for a calling party. FALSE if the
- context is for an answering party.
+ \param test_file The name of the file of XML test scripts.
+ \param test The name of the XML script test.
\return A pointer to the FAX context, or NULL if there was a problem.
*/
-faxtester_state_t *faxtester_init(faxtester_state_t *s, int calling_party);
+faxtester_state_t *faxtester_init(faxtester_state_t *s, const char *test_file, const char *test);
/*! Release a FAX context.
\brief Release a FAX context.
#define INPUT_TIFF_FILE_NAME "../test-data/itu/fax/itutests.tif"
#define OUTPUT_TIFF_FILE_NAME "fax_tests.tif"
+#define INPUT_WAVE_FILE_NAME "fax_cap.wav"
#define OUTPUT_WAVE_FILE_NAME "fax_tests.wav"
enum
{
- AUDIO_FAX,
- T38_TERMINAL_FAX,
- T38_GATEWAY_FAX,
+ AUDIO_FAX = 1,
+ T38_FAX,
T31_AUDIO_FAX,
- T31_T38_TERMINAL_FAX,
- T31_T38_GATEWAY_FAX,
+ T31_T38_FAX,
TSB85_AUDIO_FAX,
- TSB85_T38_TERMINAL_FAX,
- TSB85_T38_GATEWAY_FAX
+ TSB85_T38_FAX,
+ REPLAY_AUDIO_FAX,
+ REPLAY_T38_FAX,
+ AUDIO_TO_T38_GATEWAY,
+ PASSTHROUGH,
+ AUDIO_CHAN,
+ T38_CHAN
};
-int mode[2] = {AUDIO_FAX, AUDIO_FAX};
+const char *output_tiff_file_name;
-t30_state_t *t30_state[2] = {NULL, NULL};
-fax_state_t *fax_state[2] = {NULL, NULL};
-t38_gateway_state_t *t38_gateway_state[2] = {NULL, NULL};
-t38_terminal_state_t *t38_state[2] = {NULL, NULL};
-t38_core_state_t *t38_core_state[2] = {NULL, NULL};
-faxtester_state_t *faxtester[2] = {NULL, NULL};
-g1050_state_t *g1050_path[2] = {NULL, NULL};
-awgn_state_t *awgn_state[2] = {NULL, NULL};
-int16_t audio_buffer[2*2][SAMPLES_PER_CHUNK];
+struct audio_buf_s
+{
+ int16_t amp[SAMPLES_PER_CHUNK];
+ int len;
+};
-int t38_subst_seq[2] = {0, 0};
+struct chain_element_s
+{
+ int node_type;
+ int left_chan_type;
+ int right_chan_type;
+ struct
+ {
+ fax_state_t *fax_state;
+ t38_terminal_state_t *t38_state;
+ faxtester_state_t *faxtester_state;
+ t38_gateway_state_t *t38_gateway_state;
+ SNDFILE *wave_handle;
+ } node;
+ struct
+ {
+ g1050_state_t *g1050_path;
+ both_ways_line_model_state_t *line_model;
+ struct audio_buf_s *audio_in_buf;
+ struct audio_buf_s *audio_out_buf;
+ } path;
+ t30_state_t *t30_state;
+ t38_core_state_t *t38_core_state;
+ int t38_subst_seq;
+ bool phase_e_reached;
+ bool completed;
+ bool succeeded;
+ t30_exchanged_info_t expected_rx_info;
+
+ awgn_state_t *awgn_state;
+
+ struct audio_buf_s audio_buf[2];
+
+ int peer;
+ int t38_peer;
+
+ char tag[10];
+};
-t30_exchanged_info_t expected_rx_info[2];
+struct chain_element_s chain[7];
+int chain_elements = 2;
+bool t38_simulate_incrementing_repeats = false;
bool use_receiver_not_ready = false;
bool test_local_interrupt = false;
double when = 0.0;
-bool phase_e_reached[2] = {false, false};
-bool completed[2] = {false, false};
-bool succeeded[2] = {false, false};
-
-bool t38_simulate_incrementing_repeats = false;
-
static int phase_b_handler(void *user_data, int result)
{
int i;
char tag[20];
const char *u;
const uint8_t *v;
+ t30_exchanged_info_t *info;
i = (int) (intptr_t) user_data;
- s = t30_state[i];
+ s = chain[i].t30_state;
ch = i + 'A';
+ info = &chain[i].expected_rx_info;
snprintf(tag, sizeof(tag), "%c: Phase B", ch);
printf("%c: Phase B handler - (0x%X) %s\n", ch, result, t30_frametype(result));
fax_log_rx_parameters(s, tag);
if ((u = t30_get_rx_ident(s)))
{
printf("%c: Phase B remote ident '%s'\n", ch, u);
- if (expected_rx_info[i].ident[0] && strcmp(expected_rx_info[i].ident, u))
+ if (info->ident[0] && strcmp(info->ident, u))
{
- printf("%c: Phase B: remote ident incorrect! - expected '%s'\n", ch, expected_rx_info[i].ident);
+ printf("%c: Phase B: remote ident incorrect! - expected '%s'\n", ch, info->ident);
status = T30_ERR_IDENT_UNACCEPTABLE;
}
}
else
{
- if (expected_rx_info[i].ident[0])
+ if (info->ident[0])
{
printf("%c: Phase B: remote ident missing!\n", ch);
status = T30_ERR_IDENT_UNACCEPTABLE;
if ((u = t30_get_rx_sub_address(s)))
{
printf("%c: Phase B: remote sub-address '%s'\n", ch, u);
- if (expected_rx_info[i].sub_address[0] && strcmp(expected_rx_info[i].sub_address, u))
+ if (info->sub_address[0] && strcmp(info->sub_address, u))
{
- printf("%c: Phase B: remote sub-address incorrect! - expected '%s'\n", ch, expected_rx_info[i].sub_address);
+ printf("%c: Phase B: remote sub-address incorrect! - expected '%s'\n", ch, info->sub_address);
status = T30_ERR_SUB_UNACCEPTABLE;
}
}
else
{
- if (expected_rx_info[i].sub_address[0])
+ if (info->sub_address[0])
{
printf("%c: Phase B: remote sub-address missing!\n", ch);
status = T30_ERR_SUB_UNACCEPTABLE;
if ((u = t30_get_rx_polled_sub_address(s)))
{
printf("%c: Phase B: remote polled sub-address '%s'\n", ch, u);
- if (expected_rx_info[i].polled_sub_address[0] && strcmp(expected_rx_info[i].polled_sub_address, u))
+ if (info->polled_sub_address[0] && strcmp(info->polled_sub_address, u))
{
- printf("%c: Phase B: remote polled sub-address incorrect! - expected '%s'\n", ch, expected_rx_info[i].polled_sub_address);
+ printf("%c: Phase B: remote polled sub-address incorrect! - expected '%s'\n", ch, info->polled_sub_address);
status = T30_ERR_PSA_UNACCEPTABLE;
}
}
else
{
- if (expected_rx_info[i].polled_sub_address[0])
+ if (info->polled_sub_address[0])
{
printf("%c: Phase B: remote polled sub-address missing!\n", ch);
status = T30_ERR_PSA_UNACCEPTABLE;
if ((u = t30_get_rx_selective_polling_address(s)))
{
printf("%c: Phase B: remote selective polling address '%s'\n", ch, u);
- if (expected_rx_info[i].selective_polling_address[0] && strcmp(expected_rx_info[i].selective_polling_address, u))
+ if (info->selective_polling_address[0] && strcmp(info->selective_polling_address, u))
{
- printf("%c: Phase B: remote selective polling address incorrect! - expected '%s'\n", ch, expected_rx_info[i].selective_polling_address);
+ printf("%c: Phase B: remote selective polling address incorrect! - expected '%s'\n", ch, info->selective_polling_address);
status = T30_ERR_SEP_UNACCEPTABLE;
}
}
else
{
- if (expected_rx_info[i].selective_polling_address[0])
+ if (info->selective_polling_address[0])
{
printf("%c: Phase B: remote selective polling address missing!\n", ch);
status = T30_ERR_SEP_UNACCEPTABLE;
if ((u = t30_get_rx_sender_ident(s)))
{
printf("%c: Phase B: remote sender ident '%s'\n", ch, u);
- if (expected_rx_info[i].sender_ident[0] && strcmp(expected_rx_info[i].sender_ident, u))
+ if (info->sender_ident[0] && strcmp(info->sender_ident, u))
{
- printf("%c: Phase B: remote sender ident incorrect! - expected '%s'\n", ch, expected_rx_info[i].sender_ident);
+ printf("%c: Phase B: remote sender ident incorrect! - expected '%s'\n", ch, info->sender_ident);
status = T30_ERR_SID_UNACCEPTABLE;
}
}
else
{
- if (expected_rx_info[i].sender_ident[0])
+ if (info->sender_ident[0])
{
printf("%c: Phase B: remote sender ident missing!\n", ch);
status = T30_ERR_SID_UNACCEPTABLE;
if ((u = t30_get_rx_password(s)))
{
printf("%c: Phase B: remote password '%s'\n", ch, u);
- if (expected_rx_info[i].password[0] && strcmp(expected_rx_info[i].password, u))
+ if (info->password[0] && strcmp(info->password, u))
{
- printf("%c: Phase B: remote password incorrect! - expected '%s'\n", ch, expected_rx_info[i].password);
+ printf("%c: Phase B: remote password incorrect! - expected '%s'\n", ch, info->password);
status = T30_ERR_PWD_UNACCEPTABLE;
}
}
else
{
- if (expected_rx_info[i].password[0])
+ if (info->password[0])
{
printf("%c: Phase B: remote password missing!\n", ch);
status = T30_ERR_PWD_UNACCEPTABLE;
if ((len = t30_get_rx_nsf(s, &v)))
{
printf("%c: Phase B: NSF %d bytes\n", ch, len);
- if (expected_rx_info[i].nsf_len && (expected_rx_info[i].nsf_len != len || memcmp(expected_rx_info[i].nsf, v, len)))
+ if (info->nsf_len && (info->nsf_len != len || memcmp(info->nsf, v, len)))
{
- printf("%c: Phase B: remote NSF incorrect! - expected %u bytes\n", ch, (unsigned int) expected_rx_info[i].nsf_len);
+ printf("%c: Phase B: remote NSF incorrect! - expected %u bytes\n", ch, (unsigned int) info->nsf_len);
}
}
else
{
- if (expected_rx_info[i].nsf_len)
+ if (info->nsf_len)
{
- printf("%c: Phase B: remote NSF missing! - expected %u bytes\n", ch, (unsigned int) expected_rx_info[i].nsf_len);
+ printf("%c: Phase B: remote NSF missing! - expected %u bytes\n", ch, (unsigned int) info->nsf_len);
}
}
if ((len = t30_get_rx_nsc(s, &v)))
{
printf("%c: Phase B: NSC %d bytes\n", ch, len);
- if (expected_rx_info[i].nsc_len && (expected_rx_info[i].nsc_len != len || memcmp(expected_rx_info[i].nsc, v, len)))
+ if (info->nsc_len && (info->nsc_len != len || memcmp(info->nsc, v, len)))
{
- printf("%c: Phase B: remote NSC incorrect! - expected %u bytes\n", ch, (unsigned int) expected_rx_info[i].nsc_len);
+ printf("%c: Phase B: remote NSC incorrect! - expected %u bytes\n", ch, (unsigned int) info->nsc_len);
}
}
else
{
- if (expected_rx_info[i].nsc_len)
+ if (info->nsc_len)
{
- printf("%c: Phase B: remote NSC missing! - expected %u bytes\n", ch, (unsigned int) expected_rx_info[i].nsc_len);
+ printf("%c: Phase B: remote NSC missing! - expected %u bytes\n", ch, (unsigned int) info->nsc_len);
}
}
if ((len = t30_get_rx_nss(s, &v)))
{
printf("%c: Phase B: NSS %d bytes\n", ch, len);
- if (expected_rx_info[i].nss_len && (expected_rx_info[i].nss_len != len || memcmp(expected_rx_info[i].nss, v, len)))
+ if (info->nss_len && (info->nss_len != len || memcmp(info->nss, v, len)))
{
- printf("%c: Phase B: remote NSS incorrect! - expected %u bytes\n", ch, (unsigned int) expected_rx_info[i].nss_len);
+ printf("%c: Phase B: remote NSS incorrect! - expected %u bytes\n", ch, (unsigned int) info->nss_len);
}
}
else
{
- if (expected_rx_info[i].nss_len)
+ if (info->nss_len)
{
- printf("%c: Phase B: remote NSS missing! - expected %u bytes\n", ch, (unsigned int) expected_rx_info[i].nsf_len);
+ printf("%c: Phase B: remote NSS missing! - expected %u bytes\n", ch, (unsigned int) info->nsf_len);
}
}
char tag[20];
i = (int) (intptr_t) user_data;
- s = t30_state[i];
+ s = chain[i].t30_state;
ch = i + 'A';
snprintf(tag, sizeof(tag), "%c: Phase D", ch);
printf("%c: Phase D handler - (0x%X) %s\n", ch, result, t30_frametype(result));
char tag[20];
i = (int) (intptr_t) user_data;
- s = t30_state[i];
+ s = chain[i].t30_state;
ch = i + 'A';
snprintf(tag, sizeof(tag), "%c: Phase E", ch);
printf("%c: Phase E handler - (%d) %s\n", ch, result, t30_completion_code_to_str(result));
fax_log_tx_parameters(s, tag);
fax_log_rx_parameters(s, tag);
t30_get_transfer_statistics(s, &t);
- succeeded[i] = (result == T30_ERR_OK);
- phase_e_reached[i] = true;
+ chain[i].succeeded = (result == T30_ERR_OK);
+ chain[i].phase_e_reached = true;
}
/*- End of function --------------------------------------------------------*/
-static void real_time_frame_handler(void *user_data,
- bool incoming,
- const uint8_t *msg,
- int len)
+static void real_time_t30_frame_handler(void *user_data,
+ bool incoming,
+ const uint8_t *msg,
+ int len)
{
int i;
int ch;
t30_set_phase_b_handler(t30, phase_b_handler, (void *) (intptr_t) chan);
t30_set_phase_d_handler(t30, phase_d_handler, (void *) (intptr_t) chan);
t30_set_phase_e_handler(t30, phase_e_handler, (void *) (intptr_t) chan);
- t30_set_real_time_frame_handler(t30, real_time_frame_handler, (void *) (intptr_t) chan);
+ t30_set_real_time_frame_handler(t30, real_time_t30_frame_handler, (void *) (intptr_t) chan);
t30_set_document_handler(t30, document_handler, (void *) (intptr_t) chan);
}
/*- End of function --------------------------------------------------------*/
{
for (i = 0; i < count; i++)
{
- span_log(&s->logging, SPAN_LOG_FLOW, "Send seq %d, len %d\n", t38_subst_seq[chan], len);
+ span_log(&s->logging, SPAN_LOG_FLOW, "Send seq %d, len %d\n", chain[chan].t38_subst_seq, len);
- if (g1050_put(g1050_path[chan], buf, len, t38_subst_seq[chan], when) < 0)
- printf("Lost packet %d\n", t38_subst_seq[chan]);
- t38_subst_seq[chan] = (t38_subst_seq[chan] + 1) & 0xFFFF;
+ if (g1050_put(chain[chan].path.g1050_path, buf, len, chain[chan].t38_subst_seq, when) < 0)
+ printf("Lost packet %d\n", chain[chan].t38_subst_seq);
+ chain[chan].t38_subst_seq = (chain[chan].t38_subst_seq + 1) & 0xFFFF;
}
}
else
for (i = 0; i < count; i++)
{
- if (g1050_put(g1050_path[chan], buf, len, s->tx_seq_no, when) < 0)
+ if (g1050_put(chain[chan].path.g1050_path, buf, len, s->tx_seq_no, when) < 0)
printf("Lost packet %d\n", s->tx_seq_no);
}
}
}
/*- End of function --------------------------------------------------------*/
+static void t33_tests(void)
+{
+ int n;
+ int item_no;
+ int type;
+ uint8_t num[21];
+ uint8_t new_t33[133];
+ /* These patterns are from the T.33 spec */
+ static const uint8_t *pkts[] =
+ {
+ (const uint8_t *) "#1234567890#1234",
+ (const uint8_t *) "1234#5678#8910",
+ (const uint8_t *) "#6174444100#1234#567",
+ (const uint8_t *) "1234#5678##2032223",
+ (const uint8_t *) "#2037445555##6446666",
+ (const uint8_t *) "#2037445555#1234##6446666#5678",
+ //(const uint8_t *) "#123456789012345678901#1234##6446666#5678",
+ (const uint8_t *) ""
+ };
+
+ printf("T.33 sub-address packing/unpacking tests\n");
+ for (n = 0; pkts[n][0]; n++)
+ {
+ new_t33[0] = '\0';
+ printf("'%s'\n", pkts[n]);
+ for (item_no = 0; item_no < 100; item_no++)
+ {
+ if ((type = t33_sub_address_extract_field(num, pkts[n], item_no)) <= 0)
+ {
+ if (type == T33_NONE)
+ break;
+ printf("Bad sub-address field\n");
+ exit(2);
+ }
+ switch (type)
+ {
+ case T33_SST:
+ printf("SST '%s'\n", num);
+ t33_sub_address_add_field(new_t33, num, type);
+ break;
+ case T33_EXT:
+ printf(" EXT '%s'\n", num);
+ t33_sub_address_add_field(new_t33, num, type);
+ break;
+ }
+ }
+ if (strcmp((const char *) pkts[n], (const char *) new_t33))
+ {
+ printf("Re-encode mismatch '%s' '%s'\n", pkts[n], new_t33);
+ exit(2);
+ }
+ }
+}
+/*- End of function --------------------------------------------------------*/
+
int main(int argc, char *argv[])
{
int16_t silence[SAMPLES_PER_CHUNK];
- int16_t t30_amp[2][SAMPLES_PER_CHUNK];
- int16_t t38_amp[2][SAMPLES_PER_CHUNK];
int16_t t38_amp_hist_a[8][SAMPLES_PER_CHUNK];
int16_t t38_amp_hist_b[8][SAMPLES_PER_CHUNK];
- int16_t out_amp[SAMPLES_PER_CHUNK*4];
- int16_t *fax_rx_buf[2];
- int16_t *fax_tx_buf[2];
- int16_t *t38_gateway_rx_buf[2];
- int16_t *t38_gateway_tx_buf[2];
- int t30_len[2];
- int t38_len[2];
+ int16_t audio_log[SAMPLES_PER_CHUNK*4];
int hist_ptr;
int log_audio;
int msg_len;
uint8_t msg[1024];
int outframes;
SNDFILE *wave_handle;
- SNDFILE *input_wave_handle;
bool use_ecm;
bool use_tep;
- int feedback_audio;
- int use_transmit_on_idle;
+ bool use_polled_mode;
+ bool use_transmit_on_idle;
+ bool feedback_audio;
int t38_version;
const char *input_tiff_file_name;
- const char *decode_file_name;
+ const char *replay_file_name;
int i;
int j;
+ int k;
int seq_no;
int g1050_model_no;
int g1050_speed_pattern_no;
int expected_pages;
char *page_header_info;
char *page_header_tz;
- const char *tag;
const char *xml_file_name;
+ const char *xml_test_name[2];
+ int xml_step;
char buf[132 + 1];
+ int line_model_no;
+ int channel_codec;
+ int rbs_pattern;
#if defined(ENABLE_GUI)
int use_gui;
#endif
use_ecm = false;
t38_version = 1;
input_tiff_file_name = INPUT_TIFF_FILE_NAME;
+ output_tiff_file_name = OUTPUT_TIFF_FILE_NAME;
t38_simulate_incrementing_repeats = false;
g1050_model_no = 0;
g1050_speed_pattern_no = 1;
use_tep = false;
feedback_audio = false;
use_transmit_on_idle = true;
+ use_polled_mode = false;
supported_modems = T30_SUPPORT_V27TER | T30_SUPPORT_V29 | T30_SUPPORT_V17;
page_header_info = NULL;
page_header_tz = NULL;
signal_level = 0;
noise_level = -99;
scan_line_time = 0;
- decode_file_name = NULL;
+ replay_file_name = INPUT_WAVE_FILE_NAME;
code_to_look_up = -1;
allowed_bilevel_resolutions[0] = 0;
allowed_bilevel_resolutions[1] = 0;
allowed = 0;
+ line_model_no = 0;
+ channel_codec = MUNGE_CODEC_NONE;
+ rbs_pattern = 0;
colour_enabled = false;
t37_like_output = false;
t38_transport = T38_TRANSPORT_UDPTL;
xml_file_name = "../spandsp/tsb85.xml";
- while ((opt = getopt(argc, argv, "7b:c:Cd:D:efFgH:i:Ilm:M:n:p:s:S:tT:u:v:x:z:")) != -1)
+ xml_test_name[0] = "MRGN01";
+ xml_test_name[1] = "MRGN01";
+ xml_step = 0;
+ while ((opt = getopt(argc, argv, "7b:c:Cd:D:efFgH:i:Ilm:M:n:p:Ps:S:tT:u:v:x:X:z:")) != -1)
{
switch (opt)
{
colour_enabled = true;
break;
case 'd':
- decode_file_name = optarg;
+ replay_file_name = optarg;
break;
case 'D':
drop_frame_rate =
noise_level = atoi(optarg);
break;
case 'p':
- for (i = 0; i < 2; i++)
+ /*
+ -p FAX-audio-FAX
+ -p FAX-T38-FAX
+ -p FAX-audio-T38gateway-T38-T38gateway-audio-FAX
+ -p FAX-T38-T38gateway-audio-T38gateway-T38-FAX
+ -p FAX-T38-T38gateway-audio-FAX
+ -p FAX-audio-T38gateway-T38-FAX
+ -p tester-audio-FAX
+ -p tester-T38-FAX
+ -p tester-audio-T38gateway-T38-T38gateway-audio-FAX
+ -p tester-T38-T38gateway-audio-T38gateway-T38-FAX
+ -p tester-T38-T38gateway-audio-FAX
+ -p tester-audio-T38gateway-T38-FAX
+ */
+ for (i = 0, chain_elements = 0, k = 0; chain_elements < 7; i++)
{
- switch (optarg[i])
+ if (optarg[i] != '-' && optarg[i] != '\0')
+ continue;
+ j = optarg[i];
+ optarg[i] = '\0';
+ if (strcmp(&optarg[k], "FAX") == 0)
{
- case 'A':
- mode[i] = AUDIO_FAX;
- break;
- case 'G':
- mode[i] = T38_GATEWAY_FAX;
- break;
- case 'T':
- mode[i] = T38_TERMINAL_FAX;
- break;
- default:
- fprintf(stderr, "Unknown FAX path element %c\n", optarg[i]);
+ chain[chain_elements++].node_type = AUDIO_FAX;
+ }
+ else if (strcmp(&optarg[k], "T38") == 0)
+ {
+ chain[chain_elements++].node_type = T38_FAX;
+ }
+ else if (strcmp(&optarg[k], "T31") == 0)
+ {
+ chain[chain_elements++].node_type = T31_AUDIO_FAX;
+ }
+ else if (strcmp(&optarg[k], "tester") == 0)
+ {
+ chain[chain_elements++].node_type = TSB85_AUDIO_FAX;
+ }
+ else if (strcmp(&optarg[k], "replay") == 0)
+ {
+ chain[chain_elements++].node_type = REPLAY_AUDIO_FAX;
+ }
+ else if (strcmp(&optarg[k], "T38gateway") == 0)
+ {
+ chain[chain_elements++].node_type = AUDIO_TO_T38_GATEWAY;
+ }
+ else if (strcmp(&optarg[k], "passthrough") == 0)
+ {
+ chain[chain_elements++].node_type = PASSTHROUGH;
+ }
+ else
+ {
+ fprintf(stderr, "Unknown FAX path element %s\n", &optarg[k]);
exit(2);
}
+ k = i + 1;
+ if (j == '\0')
+ break;
}
- if ((mode[0] == AUDIO_FAX && mode[1] != AUDIO_FAX)
+#if 0
+ if ((chain[0].node_type == AUDIO_FAX && chain[chain_elements - 1].node_type != AUDIO_FAX)
||
- (mode[0] != AUDIO_FAX && mode[1] == AUDIO_FAX))
+ (chain[0].node_type != AUDIO_FAX && chain[chain_elements - 1].node_type == AUDIO_FAX))
{
- fprintf(stderr, "Invalid FAX path %s\n", optarg);
+ fprintf(stderr, "Invalid FAX path\n");
exit(2);
}
+#endif
+ break;
+ case 'P':
+ use_polled_mode = true;
break;
case 's':
g1050_speed_pattern_no = atoi(optarg);
t38_version = atoi(optarg);
break;
case 'x':
+ xml_test_name[xml_step] = optarg;
+ xml_step ^= 1;
+ break;
+ case 'X':
xml_file_name = optarg;
break;
case 'z':
memset(silence, 0, sizeof(silence));
srand48(0x1234567);
+
+ memset(t38_amp_hist_a, 0, sizeof(t38_amp_hist_a));
+ memset(t38_amp_hist_b, 0, sizeof(t38_amp_hist_b));
+
/* Set up the nodes */
- input_wave_handle = NULL;
- if (mode[0] == T38_TERMINAL_FAX)
- {
- }
- else
- {
- if (decode_file_name)
- {
- if ((input_wave_handle = sf_open_telephony_read(decode_file_name, 1)) == NULL)
- {
- fprintf(stderr, " Cannot open audio file '%s'\n", decode_file_name);
- exit(2);
- }
- }
- }
+ chain[0].peer = chain_elements - 1;
+ chain[chain_elements - 1].peer = 0;
- for (i = 0; i < 2; i++)
+ for (i = 0; i < chain_elements; i++)
{
- tag = (i == 0) ? "A" : "B";
+ chain[i].tag[0] = i + 'A';
+ chain[i].tag[1] = '\0';
+
+ memset(&chain[i].audio_buf[0], 0, sizeof(chain[i].audio_buf[0]));
+ memset(&chain[i].audio_buf[1], 0, sizeof(chain[i].audio_buf[1]));
+ memset(&chain[i].expected_rx_info, 0, sizeof(chain[i].expected_rx_info));
- memset(&expected_rx_info[i], 0, sizeof(expected_rx_info[i]));
- switch (mode[i])
+ switch (chain[i].node_type)
{
- case T38_TERMINAL_FAX:
- if ((t38_state[i] = t38_terminal_init(NULL, (i == 0), tx_packet_handler, (void *) (intptr_t) i)) == NULL)
+ case AUDIO_FAX:
+ if ((chain[i].node.fax_state = fax_init(NULL, (i == 0))) == NULL)
{
- fprintf(stderr, "Cannot start the T.38 terminal instance\n");
+ fprintf(stderr, " Cannot start FAX instance\n");
exit(2);
}
- t30_state[i] = t38_terminal_get_t30_state(t38_state[i]);
- t38_core_state[i] = t38_terminal_get_t38_core_state(t38_state[i]);
+ chain[i].t30_state = fax_get_t30_state(chain[i].node.fax_state);
- logging = t38_terminal_get_logging_state(t38_state[i]);
+ logging = fax_get_logging_state(chain[i].node.fax_state);
span_log_set_level(logging, SPAN_LOG_DEBUG | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_SHOW_TAG | SPAN_LOG_SHOW_SAMPLE_TIME);
- span_log_set_tag(logging, tag);
+ span_log_set_tag(logging, chain[i].tag);
- logging = t38_core_get_logging_state(t38_core_state[i]);
+ logging = fax_modems_get_logging_state(&chain[i].node.fax_state->modems);
span_log_set_level(logging, SPAN_LOG_DEBUG | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_SHOW_TAG | SPAN_LOG_SHOW_SAMPLE_TIME);
- span_log_set_tag(logging, tag);
+ span_log_set_tag(logging, chain[i].tag);
- logging = t30_get_logging_state(t30_state[i]);
+ logging = t30_get_logging_state(chain[i].t30_state);
span_log_set_level(logging, SPAN_LOG_DEBUG | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_SHOW_TAG | SPAN_LOG_SHOW_SAMPLE_TIME);
- span_log_set_tag(logging, tag);
+ span_log_set_tag(logging, chain[i].tag);
+
+ set_t30_callbacks(chain[i].t30_state, i);
+
+ chain[i].path.audio_in_buf = &chain[i + ((i == 0) ? 1 : -1)].audio_buf[0];
+ chain[i].path.audio_out_buf = &chain[i].audio_buf[0];
+
+ chain[i].awgn_state = NULL;
+ signal_scaling = 1.0f;
+ if (noise_level > -99)
+ {
+ chain[i].awgn_state = awgn_init_dbm0(NULL, 1234567, noise_level);
+ signal_scaling = powf(10.0f, signal_level/20.0f);
+ printf("Signal scaling %f\n", signal_scaling);
+ }
break;
- case AUDIO_FAX:
- case T38_GATEWAY_FAX:
- if ((fax_state[i] = fax_init(NULL, (i == 0))) == NULL)
+ case T38_FAX:
+ if ((chain[i].node.t38_state = t38_terminal_init(NULL, (i == 0), tx_packet_handler, (void *) (intptr_t) i)) == NULL)
{
- fprintf(stderr, "Cannot start FAX instance\n");
+ fprintf(stderr, " Cannot start the T.38 terminal instance\n");
exit(2);
}
- t30_state[i] = fax_get_t30_state(fax_state[i]);
+ chain[i].t30_state = t38_terminal_get_t30_state(chain[i].node.t38_state);
+ chain[i].t38_core_state = t38_terminal_get_t38_core_state(chain[i].node.t38_state);
- logging = fax_get_logging_state(fax_state[i]);
+ logging = t38_terminal_get_logging_state(chain[i].node.t38_state);
span_log_set_level(logging, SPAN_LOG_DEBUG | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_SHOW_TAG | SPAN_LOG_SHOW_SAMPLE_TIME);
- span_log_set_tag(logging, tag);
+ span_log_set_tag(logging, chain[i].tag);
- logging = fax_modems_get_logging_state(&fax_state[i]->modems);
+ logging = t38_core_get_logging_state(chain[i].t38_core_state);
span_log_set_level(logging, SPAN_LOG_DEBUG | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_SHOW_TAG | SPAN_LOG_SHOW_SAMPLE_TIME);
- span_log_set_tag(logging, tag);
+ span_log_set_tag(logging, chain[i].tag);
- logging = t30_get_logging_state(t30_state[i]);
+ logging = t30_get_logging_state(chain[i].t30_state);
span_log_set_level(logging, SPAN_LOG_DEBUG | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_SHOW_TAG | SPAN_LOG_SHOW_SAMPLE_TIME);
- span_log_set_tag(logging, tag);
+ span_log_set_tag(logging, chain[i].tag);
- if (mode[i] == T38_GATEWAY_FAX)
+ set_t30_callbacks(chain[i].t30_state, i);
+
+ if (i == 0)
{
- if ((t38_gateway_state[i] = t38_gateway_init(NULL, tx_packet_handler, (void *) (intptr_t) i)) == NULL)
+ chain[i].t38_peer = i + 1;
+ }
+ else
+ {
+ switch (chain[i - 1].node_type)
{
- fprintf(stderr, "Cannot start the T.38 gateway instance\n");
- exit(2);
+ case T38_FAX:
+ case AUDIO_TO_T38_GATEWAY:
+ chain[i].t38_peer = i - 1;
+ break;
+ default:
+ chain[i].t38_peer = i + 1;
+ break;
}
- t38_core_state[i] = t38_gateway_get_t38_core_state(t38_gateway_state[i]);
-
- logging = t38_gateway_get_logging_state(t38_gateway_state[i]);
- span_log_set_level(logging, SPAN_LOG_DEBUG | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_SHOW_TAG | SPAN_LOG_SHOW_SAMPLE_TIME);
- span_log_set_tag(logging, tag);
+ }
+ break;
+ case T31_AUDIO_FAX:
+ break;
+ case T31_T38_FAX:
+ break;
+ case TSB85_AUDIO_FAX:
+ case TSB85_T38_FAX:
+ if ((chain[i].node.faxtester_state = faxtester_init(NULL, xml_file_name, xml_test_name[(i == 0) ? 0 : 1])) == NULL)
+ {
+ fprintf(stderr, " Cannot start FAX tester instance\n");
+ exit(2);
+ }
+ logging = faxtester_get_logging_state(chain[i].node.faxtester_state);
+ span_log_set_level(logging, SPAN_LOG_DEBUG | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_SHOW_TAG | SPAN_LOG_SHOW_SAMPLE_TIME);
+ span_log_set_tag(logging, chain[i].tag);
- logging = fax_modems_get_logging_state(&t38_gateway_state[i]->audio.modems);
- span_log_set_level(logging, SPAN_LOG_DEBUG | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_SHOW_TAG | SPAN_LOG_SHOW_SAMPLE_TIME);
- span_log_set_tag(logging, tag);
+ faxtester_set_transmit_on_idle(chain[i].node.faxtester_state, true);
- logging = t38_core_get_logging_state(t38_core_state[i]);
- span_log_set_level(logging, SPAN_LOG_DEBUG | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_SHOW_TAG | SPAN_LOG_SHOW_SAMPLE_TIME);
- span_log_set_tag(logging, tag);
+ chain[i].path.audio_in_buf = &chain[i + ((i == 0) ? 1 : -1)].audio_buf[0];
+ chain[i].path.audio_out_buf = &chain[i].audio_buf[0];
- fax_rx_buf[i] = t38_amp[i];
- fax_tx_buf[i] = t30_amp[i];
- t38_gateway_rx_buf[i] = t30_amp[i];
- t38_gateway_tx_buf[i] = t38_amp[i];
+ if (i == 0)
+ {
+ chain[i].t38_peer = i + 1;
}
else
{
- fax_rx_buf[i] = t30_amp[i];
- fax_tx_buf[i] = t30_amp[i ^ 1];
- t38_gateway_rx_buf[i] = NULL;
- t38_gateway_tx_buf[i] = NULL;
+ switch (chain[i - 1].node_type)
+ {
+ case T38_FAX:
+ case AUDIO_TO_T38_GATEWAY:
+ chain[i].t38_peer = i - 1;
+ break;
+ default:
+ chain[i].t38_peer = i + 1;
+ break;
+ }
}
- awgn_state[i] = NULL;
+
+ chain[i].awgn_state = NULL;
signal_scaling = 1.0f;
if (noise_level > -99)
{
- awgn_state[i] = awgn_init_dbm0(NULL, 1234567, noise_level);
+ chain[i].awgn_state = awgn_init_dbm0(NULL, 1234567, noise_level);
signal_scaling = powf(10.0f, signal_level/20.0f);
printf("Signal scaling %f\n", signal_scaling);
}
break;
- case T31_AUDIO_FAX:
- break;
- case T31_T38_TERMINAL_FAX:
- case T31_T38_GATEWAY_FAX:
- break;
- case TSB85_AUDIO_FAX:
- break;
- case TSB85_T38_TERMINAL_FAX:
- case TSB85_T38_GATEWAY_FAX:
+ case REPLAY_AUDIO_FAX:
+ if ((chain[i].node.wave_handle = sf_open_telephony_read(replay_file_name, 1)) == NULL)
+ {
+ fprintf(stderr, " Cannot open audio file '%s'\n", replay_file_name);
+ exit(2);
+ }
+
+ chain[i].path.audio_in_buf = &chain[i + ((i == 0) ? 1 : -1)].audio_buf[0];
+ chain[i].path.audio_out_buf = &chain[i].audio_buf[0];
break;
+ case AUDIO_TO_T38_GATEWAY:
+ if ((chain[i].node.t38_gateway_state = t38_gateway_init(NULL, tx_packet_handler, (void *) (intptr_t) i)) == NULL)
+ {
+ fprintf(stderr, " Cannot start T.38 gateway instance\n");
+ exit(2);
+ }
+ chain[i].t38_core_state = t38_gateway_get_t38_core_state(chain[i].node.t38_gateway_state);
+
+ logging = t38_gateway_get_logging_state(chain[i].node.t38_gateway_state);
+ span_log_set_level(logging, SPAN_LOG_DEBUG | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_SHOW_TAG | SPAN_LOG_SHOW_SAMPLE_TIME);
+ span_log_set_tag(logging, chain[i].tag);
+
+ logging = fax_modems_get_logging_state(&chain[i].node.t38_gateway_state->audio.modems);
+ span_log_set_level(logging, SPAN_LOG_DEBUG | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_SHOW_TAG | SPAN_LOG_SHOW_SAMPLE_TIME);
+ span_log_set_tag(logging, chain[i].tag);
+
+ logging = t38_core_get_logging_state(chain[i].t38_core_state);
+ span_log_set_level(logging, SPAN_LOG_DEBUG | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_SHOW_TAG | SPAN_LOG_SHOW_SAMPLE_TIME);
+ span_log_set_tag(logging, chain[i].tag);
+
+ t38_gateway_set_transmit_on_idle(chain[i].node.t38_gateway_state, use_transmit_on_idle);
+ t38_gateway_set_supported_modems(chain[i].node.t38_gateway_state, supported_modems);
+ //t38_gateway_set_nsx_suppression(chain[i].node.t38_state, NULL, 0, NULL, 0);
+ t38_gateway_set_fill_bit_removal(chain[i].node.t38_gateway_state, remove_fill_bits);
+ t38_gateway_set_real_time_frame_handler(chain[i].node.t38_gateway_state, real_time_gateway_frame_handler, (void *) (intptr_t) i);
+ t38_gateway_set_ecm_capability(chain[i].node.t38_gateway_state, use_ecm);
+ t38_set_t38_version(chain[i].t38_core_state, t38_version);
+
+ if (i == 0)
+ {
+ chain[i].t38_peer = i + 1;
+ chain[i].path.audio_in_buf = NULL;
+ }
+ else
+ {
+ switch (chain[i - 1].node_type)
+ {
+ case T38_FAX:
+ case AUDIO_TO_T38_GATEWAY:
+ chain[i].t38_peer = i - 1;
+ chain[i].path.audio_in_buf = &chain[i + 1].audio_buf[0];
+ break;
+ default:
+ chain[i].t38_peer = i + 1;
+ chain[i].path.audio_in_buf = &chain[i - 1].audio_buf[0];
+ break;
+ }
+ }
+
+ chain[i].path.audio_out_buf = &chain[i].audio_buf[0];
+
+ chain[i].awgn_state = NULL;
+ signal_scaling = 1.0f;
+ if (noise_level > -99)
+ {
+ chain[i].awgn_state = awgn_init_dbm0(NULL, 1234567, noise_level);
+ signal_scaling = powf(10.0f, signal_level/20.0f);
+ printf("Signal scaling %f\n", signal_scaling);
+ }
}
- set_t30_callbacks(t30_state[i], i);
- }
- /* Set up the channels */
- for (i = 0; i < 2; i++)
- {
- if ((g1050_path[i] = g1050_init(g1050_model_no, g1050_speed_pattern_no, 100, 33)) == NULL)
+ if ((chain[i].path.g1050_path = g1050_init(g1050_model_no, g1050_speed_pattern_no, 100, 33)) == NULL)
{
- fprintf(stderr, "Failed to start IP network path model\n");
+ fprintf(stderr, " Failed to start IP network path model\n");
exit(2);
}
- memset(audio_buffer[2*i], 0, SAMPLES_PER_CHUNK*sizeof(int16_t));
- memset(audio_buffer[2*i + 1], 0, SAMPLES_PER_CHUNK*sizeof(int16_t));
- memset(t30_amp[i], 0, sizeof(t30_amp[i]));
- memset(t38_amp[i], 0, sizeof(t38_amp[i]));
}
- memset(t38_amp_hist_a, 0, sizeof(t38_amp_hist_a));
- memset(t38_amp_hist_b, 0, sizeof(t38_amp_hist_b));
- for (i = 0; i < 2; i++)
+ for (i = 0; i < chain_elements; i++)
{
j = i + 1;
- sprintf(buf, "%d%d%d%d%d%d%d%d", j, j, j, j, j, j, j, j);
- t30_set_tx_ident(t30_state[i], buf);
- strcpy(expected_rx_info[i ^ 1].ident, buf);
- sprintf(buf, "Sub-address %d", j);
- t30_set_tx_sub_address(t30_state[i], buf);
- //strcpy(expected_rx_info[i ^ 1].sub_address, buf);
- sprintf(buf, "Sender ID %d", j);
- t30_set_tx_sender_ident(t30_state[i], buf);
- //strcpy(expected_rx_info[i ^ 1].sender_ident, buf);
- sprintf(buf, "Password %d", j);
- t30_set_tx_password(t30_state[i], buf);
- //strcpy(expected_rx_info[i ^ 1].password, buf);
- sprintf(buf, "Polled sub-add %d", j);
- t30_set_tx_polled_sub_address(t30_state[i], buf);
- //strcpy(expected_rx_info[i ^ 1].polled_sub_address, buf);
- sprintf(buf, "Select poll add %d", j);
- t30_set_tx_selective_polling_address(t30_state[i], buf);
- //strcpy(expected_rx_info[i ^ 1].selective_polling_address, buf);
- t30_set_tx_page_header_info(t30_state[i], page_header_info);
- if (page_header_tz)
- t30_set_tx_page_header_tz(t30_state[i], page_header_tz);
-
- if ((i & 1) == 1)
+ if (chain[i].t30_state)
{
- t30_set_tx_nsf(t30_state[i], (const uint8_t *) "\x50\x00\x00\x00Spandsp\x00", 12);
- expected_rx_info[i ^ 1].nsf = (uint8_t *) "\x50\x00\x00\x00Spandsp\x00";
- expected_rx_info[i ^ 1].nsf_len = 12;
- }
+ sprintf(buf, "%d%d%d%d%d%d%d%d", j, j, j, j, j, j, j, j);
+ t30_set_tx_ident(chain[i].t30_state, buf);
+ strcpy(chain[chain[i].peer].expected_rx_info.ident, buf);
+ sprintf(buf, "Sub-address %d", j);
+ t30_set_tx_sub_address(chain[i].t30_state, buf);
+ //strcpy(chain[chain[i].peer].expected_rx_info.sub_address, buf);
+ sprintf(buf, "Sender ID %d", j);
+ t30_set_tx_sender_ident(chain[i].t30_state, buf);
+ //strcpy(chain[chain[i].peer].expected_rx_info.sender_ident, buf);
+ sprintf(buf, "Password %d", j);
+ t30_set_tx_password(chain[i].t30_state, buf);
+ //strcpy(chain[chain[i].peer].expected_rx_info.password, buf);
+ sprintf(buf, "Polled sub-add %d", j);
+ t30_set_tx_polled_sub_address(chain[i].t30_state, buf);
+ //strcpy(chain[chain[i].peer].expected_rx_info.polled_sub_address, buf);
+ sprintf(buf, "Select poll add %d", j);
+ t30_set_tx_selective_polling_address(chain[i].t30_state, buf);
+ //strcpy(chain[chain[i].peer].expected_rx_info.selective_polling_address, buf);
+ t30_set_tx_page_header_info(chain[i].t30_state, page_header_info);
+ if (page_header_tz)
+ t30_set_tx_page_header_tz(chain[i].t30_state, page_header_tz);
+
+ if (i != 0)
+ {
+ t30_set_tx_nsf(chain[i].t30_state, (const uint8_t *) "\x50\x00\x00\x00Spandsp\x00", 12);
+ chain[chain[i].peer].expected_rx_info.nsf = (uint8_t *) "\x50\x00\x00\x00Spandsp\x00";
+ chain[chain[i].peer].expected_rx_info.nsf_len = 12;
+ }
- t30_set_supported_modems(t30_state[i], supported_modems);
- t30_set_supported_t30_features(t30_state[i],
- T30_SUPPORT_IDENTIFICATION
- | T30_SUPPORT_SELECTIVE_POLLING
- | T30_SUPPORT_SUB_ADDRESSING);
- t30_set_supported_image_sizes(t30_state[i],
- T4_SUPPORT_WIDTH_215MM
- | T4_SUPPORT_WIDTH_255MM
- | T4_SUPPORT_WIDTH_303MM
- | T4_SUPPORT_LENGTH_US_LETTER
- | T4_SUPPORT_LENGTH_US_LEGAL
- | T4_SUPPORT_LENGTH_UNLIMITED);
- switch (allowed_bilevel_resolutions[i])
- {
- case 0:
- /* Allow anything */
- t30_set_supported_bilevel_resolutions(t30_state[i],
- T4_RESOLUTION_R8_STANDARD
- | T4_RESOLUTION_R8_FINE
- | T4_RESOLUTION_R8_SUPERFINE
- | T4_RESOLUTION_R16_SUPERFINE
- | T4_RESOLUTION_200_100
- | T4_RESOLUTION_200_200
- | T4_RESOLUTION_200_400
- | T4_RESOLUTION_300_300
- | T4_RESOLUTION_300_600
- | T4_RESOLUTION_400_400
- | T4_RESOLUTION_400_800
- | T4_RESOLUTION_600_600
- | T4_RESOLUTION_600_1200
- | T4_RESOLUTION_1200_1200);
- break;
- case 1:
- /* Allow anything metric */
- t30_set_supported_bilevel_resolutions(t30_state[i],
- T4_RESOLUTION_R8_STANDARD
- | T4_RESOLUTION_R8_FINE
- | T4_RESOLUTION_R8_SUPERFINE
- | T4_RESOLUTION_R16_SUPERFINE);
- break;
- case 2:
- /* Allow anything inch based */
- t30_set_supported_bilevel_resolutions(t30_state[i],
- T4_RESOLUTION_200_100
- | T4_RESOLUTION_200_200
- | T4_RESOLUTION_200_400
- | T4_RESOLUTION_300_300
- | T4_RESOLUTION_300_600
- | T4_RESOLUTION_400_400
- | T4_RESOLUTION_400_800
- | T4_RESOLUTION_600_600
- | T4_RESOLUTION_600_1200
- | T4_RESOLUTION_1200_1200);
- break;
- case 3:
- /* Allow only restricted length resolution */
- t30_set_supported_bilevel_resolutions(t30_state[i],
- T4_RESOLUTION_R8_STANDARD
- | T4_RESOLUTION_R8_FINE
- | T4_RESOLUTION_200_100
- | T4_RESOLUTION_200_200);
- break;
- case 4:
- /* Allow only more restricted length resolution */
- t30_set_supported_bilevel_resolutions(t30_state[i],
- T4_RESOLUTION_R8_STANDARD
- | T4_RESOLUTION_200_100);
- break;
- }
- if (colour_enabled)
- {
- t30_set_supported_colour_resolutions(t30_state[i],
- T4_RESOLUTION_100_100
- | T4_RESOLUTION_200_200
- | T4_RESOLUTION_300_300
- | T4_RESOLUTION_400_400
- | T4_RESOLUTION_600_600
- | T4_RESOLUTION_1200_1200);
- }
- else
- {
- t30_set_supported_colour_resolutions(t30_state[i], 0);
- }
- if (t37_like_output)
- {
- t30_set_supported_output_compressions(t30_state[i],
- T4_COMPRESSION_T85
- | T4_COMPRESSION_T85_L0
- | T4_COMPRESSION_T6
- | T4_COMPRESSION_T42_T81);
- }
- else
- {
- t30_set_supported_output_compressions(t30_state[i],
- T4_COMPRESSION_T6
- | T4_COMPRESSION_JPEG);
- }
+ t30_set_supported_modems(chain[i].t30_state, supported_modems);
+ t30_set_supported_t30_features(chain[i].t30_state,
+ T30_SUPPORT_IDENTIFICATION
+ | T30_SUPPORT_SELECTIVE_POLLING
+ | T30_SUPPORT_SUB_ADDRESSING);
+ t30_set_supported_image_sizes(chain[i].t30_state,
+ T4_SUPPORT_WIDTH_215MM
+ | T4_SUPPORT_WIDTH_255MM
+ | T4_SUPPORT_WIDTH_303MM
+ | T4_SUPPORT_LENGTH_US_LETTER
+ | T4_SUPPORT_LENGTH_US_LEGAL
+ | T4_SUPPORT_LENGTH_UNLIMITED);
+ switch (allowed_bilevel_resolutions[(i == 0) ? 0 : 1])
+ {
+ case 0:
+ /* Allow anything */
+ t30_set_supported_bilevel_resolutions(chain[i].t30_state,
+ T4_RESOLUTION_R8_STANDARD
+ | T4_RESOLUTION_R8_FINE
+ | T4_RESOLUTION_R8_SUPERFINE
+ | T4_RESOLUTION_R16_SUPERFINE
+ | T4_RESOLUTION_200_100
+ | T4_RESOLUTION_200_200
+ | T4_RESOLUTION_200_400
+ | T4_RESOLUTION_300_300
+ | T4_RESOLUTION_300_600
+ | T4_RESOLUTION_400_400
+ | T4_RESOLUTION_400_800
+ | T4_RESOLUTION_600_600
+ | T4_RESOLUTION_600_1200
+ | T4_RESOLUTION_1200_1200);
+ break;
+ case 1:
+ /* Allow anything metric */
+ t30_set_supported_bilevel_resolutions(chain[i].t30_state,
+ T4_RESOLUTION_R8_STANDARD
+ | T4_RESOLUTION_R8_FINE
+ | T4_RESOLUTION_R8_SUPERFINE
+ | T4_RESOLUTION_R16_SUPERFINE);
+ break;
+ case 2:
+ /* Allow anything inch based */
+ t30_set_supported_bilevel_resolutions(chain[i].t30_state,
+ T4_RESOLUTION_200_100
+ | T4_RESOLUTION_200_200
+ | T4_RESOLUTION_200_400
+ | T4_RESOLUTION_300_300
+ | T4_RESOLUTION_300_600
+ | T4_RESOLUTION_400_400
+ | T4_RESOLUTION_400_800
+ | T4_RESOLUTION_600_600
+ | T4_RESOLUTION_600_1200
+ | T4_RESOLUTION_1200_1200);
+ break;
+ case 3:
+ /* Allow only restricted length resolution */
+ t30_set_supported_bilevel_resolutions(chain[i].t30_state,
+ T4_RESOLUTION_R8_STANDARD
+ | T4_RESOLUTION_R8_FINE
+ | T4_RESOLUTION_200_100
+ | T4_RESOLUTION_200_200);
+ break;
+ case 4:
+ /* Allow only more restricted length resolution */
+ t30_set_supported_bilevel_resolutions(chain[i].t30_state,
+ T4_RESOLUTION_R8_STANDARD
+ | T4_RESOLUTION_200_100);
+ break;
+ }
+ if (colour_enabled)
+ {
+ t30_set_supported_colour_resolutions(chain[i].t30_state,
+ T4_RESOLUTION_100_100
+ | T4_RESOLUTION_200_200
+ | T4_RESOLUTION_300_300
+ | T4_RESOLUTION_400_400
+ | T4_RESOLUTION_600_600
+ | T4_RESOLUTION_1200_1200);
+ }
+ else
+ {
+ t30_set_supported_colour_resolutions(chain[i].t30_state, 0);
+ }
+ if (t37_like_output)
+ {
+ t30_set_supported_output_compressions(chain[i].t30_state,
+ T4_COMPRESSION_T85
+ | T4_COMPRESSION_T85_L0
+ | T4_COMPRESSION_T6
+ | T4_COMPRESSION_T42_T81);
+ }
+ else
+ {
+ t30_set_supported_output_compressions(chain[i].t30_state,
+ T4_COMPRESSION_T6
+ | T4_COMPRESSION_JPEG);
+ }
- t30_set_ecm_capability(t30_state[i], use_ecm);
- t30_set_supported_compressions(t30_state[i],
- T4_COMPRESSION_T4_1D
- | T4_COMPRESSION_T4_2D
- | T4_COMPRESSION_T6
- | T4_COMPRESSION_T85
- | T4_COMPRESSION_T85_L0
- //| T4_COMPRESSION_T88
- | T4_COMPRESSION_T43
- | T4_COMPRESSION_T45
- | T4_COMPRESSION_T42_T81
- | T4_COMPRESSION_SYCC_T81
- | T4_COMPRESSION_GRAYSCALE
- | T4_COMPRESSION_COLOUR
- | T4_COMPRESSION_12BIT
- | T4_COMPRESSION_COLOUR_TO_GRAY
- | T4_COMPRESSION_GRAY_TO_BILEVEL
- | T4_COMPRESSION_COLOUR_TO_BILEVEL
- | T4_COMPRESSION_RESCALING
- | 0);
- t30_set_minimum_scan_line_time(t30_state[i], scan_line_time);
-
- if (mode[i] == T38_GATEWAY_FAX)
- {
- t38_gateway_set_transmit_on_idle(t38_gateway_state[i], use_transmit_on_idle);
- t38_gateway_set_supported_modems(t38_gateway_state[i], supported_modems);
- //t38_gateway_set_nsx_suppression(t38_state[i], NULL, 0, NULL, 0);
- t38_gateway_set_fill_bit_removal(t38_gateway_state[i], remove_fill_bits);
- t38_gateway_set_real_time_frame_handler(t38_gateway_state[i], real_time_gateway_frame_handler, (void *) (intptr_t) i);
- t38_gateway_set_ecm_capability(t38_gateway_state[i], use_ecm);
- }
- if (mode[i] != AUDIO_FAX)
- {
- t38_set_t38_version(t38_core_state[i], t38_version);
+ t30_set_ecm_capability(chain[i].t30_state, use_ecm);
+ t30_set_supported_compressions(chain[i].t30_state,
+ T4_COMPRESSION_T4_1D
+ | T4_COMPRESSION_T4_2D
+ | T4_COMPRESSION_T6
+ | T4_COMPRESSION_T85
+ | T4_COMPRESSION_T85_L0
+ //| T4_COMPRESSION_T88
+ | T4_COMPRESSION_T43
+ | T4_COMPRESSION_T45
+ | T4_COMPRESSION_T42_T81
+ | T4_COMPRESSION_SYCC_T81
+ | T4_COMPRESSION_GRAYSCALE
+ | T4_COMPRESSION_COLOUR
+ | T4_COMPRESSION_12BIT
+ | T4_COMPRESSION_COLOUR_TO_GRAY
+ | T4_COMPRESSION_GRAY_TO_BILEVEL
+ | T4_COMPRESSION_COLOUR_TO_BILEVEL
+ | T4_COMPRESSION_RESCALING
+ | 0);
+ t30_set_minimum_scan_line_time(chain[i].t30_state, scan_line_time);
}
- if (mode[i] == T38_TERMINAL_FAX)
+ switch (chain[i].node_type)
{
- //t30_set_iaf_mode(t30_state[i], T30_IAF_MODE_NO_FILL_BITS);
+ case AUDIO_FAX:
+ fax_set_transmit_on_idle(chain[i].node.fax_state, use_transmit_on_idle);
+ fax_set_tep_mode(chain[i].node.fax_state, use_tep);
+ break;
+ case T38_FAX:
+ t38_set_t38_version(chain[i].t38_core_state, t38_version);
+ //t30_set_iaf_mode(chain[i].t30_state, T30_IAF_MODE_NO_FILL_BITS);
switch (t38_transport)
{
case T38_TRANSPORT_UDPTL:
case T38_TRANSPORT_RTP:
- t38_terminal_set_fill_bit_removal(t38_state[i], remove_fill_bits);
- t38_terminal_set_tep_mode(t38_state[i], use_tep);
+ t38_terminal_set_fill_bit_removal(chain[i].node.t38_state, remove_fill_bits);
+ t38_terminal_set_tep_mode(chain[i].node.t38_state, use_tep);
break;
case T38_TRANSPORT_TCP:
case T38_TRANSPORT_TCP_TPKT:
- t38_terminal_set_fill_bit_removal(t38_state[i], true);
- t38_terminal_set_config(t38_state[i], T38_TERMINAL_OPTION_NO_PACING | T38_TERMINAL_OPTION_NO_INDICATORS);
- t38_terminal_set_tep_mode(t38_state[i], false);
+ t38_terminal_set_fill_bit_removal(chain[i].node.t38_state, true);
+ t38_terminal_set_config(chain[i].node.t38_state, T38_TERMINAL_OPTION_NO_PACING | T38_TERMINAL_OPTION_NO_INDICATORS);
+ t38_terminal_set_tep_mode(chain[i].node.t38_state, false);
break;
}
+ break;
}
- else
+ }
+
+ for (i = 0; i < chain_elements; i++)
+ {
+ switch (chain[i].node_type)
{
- fax_set_transmit_on_idle(fax_state[i], use_transmit_on_idle);
- fax_set_tep_mode(fax_state[i], use_tep);
+ case TSB85_AUDIO_FAX:
+ case TSB85_T38_FAX:
+ if (chain[chain[i].peer].node_type == AUDIO_FAX)
+ chain[i].node.faxtester_state->far_fax = chain[chain[i].peer].node.fax_state;
+ else
+ chain[i].node.faxtester_state->far_t38 = chain[chain[i].peer].node.t38_state;
+ chain[i].node.faxtester_state->far_t30 = chain[chain[i].peer].t30_state;
+ chain[i].node.faxtester_state->far_tag = chain[i].peer + 'A';
+
+ while (faxtester_next_step(chain[i].node.faxtester_state) == 0)
+ /*dummy loop*/;
+ /*endwhile*/
+ break;
+ case REPLAY_AUDIO_FAX:
+ break;
+ case PASSTHROUGH:
+ if (chain[i - 1].path.audio_in_buf == &chain[i].audio_buf[0])
+ chain[i - 1].path.audio_in_buf = &chain[i + 1].audio_buf[0];
+ if (chain[i + 1].path.audio_in_buf == &chain[i].audio_buf[0])
+ chain[i + 1].path.audio_in_buf = &chain[i - 1].audio_buf[0];
+ break;
}
}
- t30_set_tx_file(t30_state[0], input_tiff_file_name, start_page, end_page);
- t30_set_rx_file(t30_state[1], OUTPUT_TIFF_FILE_NAME, -1);
+ switch (chain[chain_elements - 1].node_type)
+ {
+ case AUDIO_FAX:
+ case T38_FAX:
+ k = (use_polled_mode) ? (chain_elements - 1) : 0;
+ if (chain[k].t30_state)
+ t30_set_tx_file(chain[k].t30_state, input_tiff_file_name, start_page, end_page);
+ break;
+ }
+ switch (chain[0].node_type)
+ {
+ case AUDIO_FAX:
+ case T38_FAX:
+ k = (use_polled_mode) ? 0 : (chain_elements - 1);
+ if (chain[k].t30_state)
+ t30_set_rx_file(chain[k].t30_state, output_tiff_file_name, -1);
+ break;
+ }
#if defined(ENABLE_GUI)
if (use_gui)
hist_ptr = 0;
for (;;)
{
- memset(out_amp, 0, sizeof(out_amp));
+ memset(audio_log, 0, sizeof(audio_log));
- for (i = 0; i < 2; i++)
+ for (i = 0; i < chain_elements; i++)
{
/* Update T.30 timing */
- logging = t30_get_logging_state(t30_state[i]);
- span_log_bump_samples(logging, SAMPLES_PER_CHUNK);
-
- if (mode[i] == T38_TERMINAL_FAX)
+ switch (chain[i].node_type)
{
- /* Update T.38 termination timing */
- logging = t38_terminal_get_logging_state(t38_state[i]);
+ case AUDIO_FAX:
+ /* Update timing */
+ logging = t30_get_logging_state(chain[i].t30_state);
span_log_bump_samples(logging, SAMPLES_PER_CHUNK);
- logging = t38_core_get_logging_state(t38_core_state[i]);
+ logging = fax_get_logging_state(chain[i].node.fax_state);
span_log_bump_samples(logging, SAMPLES_PER_CHUNK);
-
- completed[i] = t38_terminal_send_timeout(t38_state[i], SAMPLES_PER_CHUNK);
- }
- else
- {
- /* Update audio FAX timing */
- logging = fax_get_logging_state(fax_state[i]);
+ logging = fax_modems_get_logging_state(&chain[i].node.fax_state->modems);
span_log_bump_samples(logging, SAMPLES_PER_CHUNK);
+#if 0
+ /* Probe inside the modems to update their logs */
+ span_log_bump_samples(chain[i].node.fax_state->modems.v27ter_rx.logging, len);
+ span_log_bump_samples(chain[i].node.fax_state->modems.v29_rx.logging, len);
+ span_log_bump_samples(chain[i].node.fax_state->modems.v17_rx.logging, len);
+#endif
#if 0
/* Mute the signal */
- vec_zeroi16(fax_rx_buf[i], SAMPLES_PER_CHUNK);
+ vec_zeroi16(chain[i].path.audio_in_buf->amp, SAMPLES_PER_CHUNK);
+ chain[i].path.audio_in_buf->len = SAMPLES_PER_CHUNK;
#endif
- fax_rx(fax_state[i], fax_rx_buf[i], SAMPLES_PER_CHUNK);
- if (!t30_call_active(t30_state[i]))
+ if (log_audio)
{
- completed[i] = true;
- continue;
+ k = (i == 0) ? 0 : 2;
+ for (j = 0; j < chain[i].path.audio_in_buf->len; j++)
+ audio_log[4*j + k] = chain[i].path.audio_in_buf->amp[j];
}
-
- if (i == 0 && input_wave_handle)
+ fax_rx(chain[i].node.fax_state, chain[i].path.audio_in_buf->amp, chain[i].path.audio_in_buf->len);
+ if (!t30_call_active(chain[i].t30_state))
{
- t30_len[i] = sf_readf_short(input_wave_handle, fax_tx_buf[i], SAMPLES_PER_CHUNK);
- if (t30_len[i] == 0)
- break;
+ chain[i].completed = true;
+ continue;
}
- else
+
+ chain[i].path.audio_out_buf->len = fax_tx(chain[i].node.fax_state, chain[i].path.audio_out_buf->amp, SAMPLES_PER_CHUNK);
+ if (!use_transmit_on_idle)
{
- t30_len[i] = fax_tx(fax_state[i], fax_tx_buf[i], SAMPLES_PER_CHUNK);
- if (!use_transmit_on_idle)
+ /* The receive side always expects a full block of samples, but the
+ transmit side may not be sending any when it doesn't need to. We
+ may need to pad with some silence. */
+ if (chain[i].path.audio_out_buf->len < SAMPLES_PER_CHUNK)
{
- /* The receive side always expects a full block of samples, but the
- transmit side may not be sending any when it doesn't need to. We
- may need to pad with some silence. */
- if (t30_len[i] < SAMPLES_PER_CHUNK)
- {
- memset(t30_amp[i] + t30_len[i], 0, sizeof(int16_t)*(SAMPLES_PER_CHUNK - t30_len[i]));
- t30_len[i] = SAMPLES_PER_CHUNK;
- }
- }
- if (awgn_state[i])
- {
- for (j = 0; j < t30_len[i]; j++)
- fax_tx_buf[i][j] = ((int16_t) (fax_tx_buf[i][j]*signal_scaling)) + awgn(awgn_state[i]);
+ vec_zeroi16(&chain[i].path.audio_out_buf->amp[chain[i].path.audio_out_buf->len], SAMPLES_PER_CHUNK - chain[i].path.audio_out_buf->len);
+ chain[i].path.audio_out_buf->len = SAMPLES_PER_CHUNK;
}
}
+ if (chain[i].awgn_state)
+ {
+ for (j = 0; j < chain[i].path.audio_out_buf->len; j++)
+ chain[i].path.audio_out_buf->amp[j] = ((int16_t) (chain[i].path.audio_out_buf->amp[j]*signal_scaling)) + awgn(chain[i].awgn_state);
+ }
if (log_audio)
{
- for (j = 0; j < t30_len[i]; j++)
- out_amp[4*j + 2*i] = t30_amp[i][j];
+ k = (i == 0) ? 1 : 3;
+ for (j = 0; j < chain[i].path.audio_out_buf->len; j++)
+ audio_log[4*j + k] = chain[i].path.audio_out_buf->amp[j];
}
if (feedback_audio)
{
- for (j = 0; j < t30_len[i]; j++)
- t30_amp[i][j] += t38_amp_hist_a[hist_ptr][j] >> 1;
- memcpy(t38_amp_hist_a[hist_ptr], t38_amp[i], sizeof(int16_t)*SAMPLES_PER_CHUNK);
+ for (j = 0; j < chain[i].path.audio_out_buf->len; j++)
+ chain[i].path.audio_out_buf->amp[j] += t38_amp_hist_a[hist_ptr][j] >> 1;
+ memcpy(t38_amp_hist_a[hist_ptr], chain[i].path.audio_out_buf->amp, sizeof(int16_t)*SAMPLES_PER_CHUNK);
}
+ break;
+ case T38_FAX:
+ /* Update timing */
+ logging = t30_get_logging_state(chain[i].t30_state);
+ span_log_bump_samples(logging, SAMPLES_PER_CHUNK);
+ logging = t38_terminal_get_logging_state(chain[i].node.t38_state);
+ span_log_bump_samples(logging, SAMPLES_PER_CHUNK);
+ logging = t38_core_get_logging_state(chain[i].t38_core_state);
+ span_log_bump_samples(logging, SAMPLES_PER_CHUNK);
- if (mode[i] == T38_GATEWAY_FAX)
- {
- /* Update T.38 gateway timing */
- logging = t38_gateway_get_logging_state(t38_gateway_state[i]);
- span_log_bump_samples(logging, SAMPLES_PER_CHUNK);
- logging = t38_core_get_logging_state(t38_core_state[i]);
- span_log_bump_samples(logging, SAMPLES_PER_CHUNK);
+ chain[i].completed = t38_terminal_send_timeout(chain[i].node.t38_state, SAMPLES_PER_CHUNK);
- if (drop_frame_rate && --drop_frame == 0)
- {
- drop_frame = drop_frame_rate;
- if (t38_gateway_rx_fillin(t38_gateway_state[i], SAMPLES_PER_CHUNK))
- break;
- }
- else
- {
- if (t38_gateway_rx(t38_gateway_state[i], t38_gateway_rx_buf[i], SAMPLES_PER_CHUNK))
- break;
- }
+ while ((msg_len = g1050_get(chain[i].path.g1050_path, msg, 1024, when, &seq_no, &tx_when, &rx_when)) >= 0)
+ {
+#if defined(ENABLE_GUI)
+ if (use_gui)
+ media_monitor_rx(seq_no, tx_when, rx_when);
+#endif
+ t38_core_rx_ifp_packet(chain[chain[i].t38_peer].t38_core_state, msg, msg_len, seq_no);
+ }
+ break;
+ case TSB85_AUDIO_FAX:
+ /* Update timing */
+ logging = faxtester_get_logging_state(chain[i].node.faxtester_state);
+ span_log_bump_samples(logging, SAMPLES_PER_CHUNK);
+#if 0
+ /* Probe inside the modems to update their logs */
+ span_log_bump_samples(&chain[i].node.faxtester_state->modems.v27ter_rx.logging, len);
+ span_log_bump_samples(&chain[i].node.faxtester_state->modems.v29_rx.logging, len);
+ span_log_bump_samples(&chain[i].node.faxtester_state->modems.v17_rx.logging, len);
+#endif
- t38_len[i] = t38_gateway_tx(t38_gateway_state[i], t38_gateway_tx_buf[i], SAMPLES_PER_CHUNK);
- if (!use_transmit_on_idle)
+ if (log_audio)
+ {
+ k = (i == 0) ? 0 : 2;
+ for (j = 0; j < chain[i].path.audio_in_buf->len; j++)
+ audio_log[4*j + k] = chain[i].path.audio_in_buf->amp[j];
+ }
+ faxtester_rx(chain[i].node.faxtester_state, chain[i].path.audio_in_buf->amp, chain[i].path.audio_in_buf->len);
+ chain[i].path.audio_out_buf->len = faxtester_tx(chain[i].node.faxtester_state, chain[i].path.audio_out_buf->amp, SAMPLES_PER_CHUNK);
+ if (chain[i].path.audio_out_buf->len == 0)
+ break;
+ if (log_audio)
+ {
+ k = (i == 0) ? 1 : 3;
+ for (j = 0; j < chain[i].path.audio_out_buf->len; j++)
+ audio_log[4*j + k] = chain[i].path.audio_out_buf->amp[j];
+ }
+ if (chain[i].node.faxtester_state->test_for_call_clear && !chain[i].node.faxtester_state->far_end_cleared_call)
+ {
+ chain[i].node.faxtester_state->call_clear_timer += chain[i].path.audio_out_buf->len;
+ if (!t30_call_active(chain[i].node.faxtester_state->far_t30))
{
- if (t38_len[i] < SAMPLES_PER_CHUNK)
+ span_log(faxtester_get_logging_state(chain[i].node.faxtester_state),
+ SPAN_LOG_FLOW,
+ "Far end cleared after %dms (limits %dms to %dms)\n",
+ chain[i].node.faxtester_state->call_clear_timer/8,
+ chain[i].node.faxtester_state->timein_x,
+ chain[i].node.faxtester_state->timeout);
+ if (chain[i].node.faxtester_state->call_clear_timer/8 < chain[i].node.faxtester_state->timein_x || chain[i].node.faxtester_state->call_clear_timer/8 > chain[i].node.faxtester_state->timeout_x)
{
- memset(t38_amp[i] + t38_len[i], 0, sizeof(int16_t)*(SAMPLES_PER_CHUNK - t38_len[i]));
- t38_len[i] = SAMPLES_PER_CHUNK;
+ printf("Test failed\n");
+ exit(2);
}
+ span_log(faxtester_get_logging_state(chain[i].node.faxtester_state), SPAN_LOG_FLOW, "Clear time OK\n");
+ chain[i].node.faxtester_state->far_end_cleared_call = true;
+ chain[i].node.faxtester_state->test_for_call_clear = false;
+ while (faxtester_next_step(chain[i].node.faxtester_state) == 0)
+ /*dummy loop*/;
+ /*endwhile*/
}
- if (feedback_audio)
- {
- for (j = 0; j < t30_len[i]; j++)
- t30_amp[i][j] += t38_amp_hist_a[hist_ptr][j] >> 1;
- memcpy(t38_amp_hist_a[hist_ptr], t38_amp[i], sizeof(int16_t)*SAMPLES_PER_CHUNK);
- }
+ /*endif*/
+ }
+ /*endif*/
+ break;
+ case REPLAY_AUDIO_FAX:
+ chain[i].path.audio_out_buf->len = sf_readf_short(chain[i].node.wave_handle, chain[i].path.audio_out_buf->amp, SAMPLES_PER_CHUNK);
+ if (chain[i].path.audio_out_buf->len == 0)
+ break;
+ break;
+ case AUDIO_TO_T38_GATEWAY:
+ /* Update timing */
+ logging = t38_gateway_get_logging_state(chain[i].node.t38_gateway_state);
+ span_log_bump_samples(logging, SAMPLES_PER_CHUNK);
+ logging = t38_core_get_logging_state(chain[i].t38_core_state);
+ span_log_bump_samples(logging, SAMPLES_PER_CHUNK);
+#if 0
+ /* Probe inside the modems to update their logs */
+ span_log_bump_samples(&chain[i].node.t38_gateway_state->modems.v27ter_rx.logging, len);
+ span_log_bump_samples(&chain[i].node.t38_gateway_state->modems.v29_rx.logging, len);
+ span_log_bump_samples(&chain[i].node.t38_gateway_state->modems.v17_rx.logging, len);
+#endif
- if (log_audio)
+ if (drop_frame_rate && --drop_frame == 0)
+ {
+ drop_frame = drop_frame_rate;
+ if (t38_gateway_rx_fillin(chain[i].node.t38_gateway_state, SAMPLES_PER_CHUNK))
+ break;
+ }
+ else
+ {
+ if (t38_gateway_rx(chain[i].node.t38_gateway_state, chain[i].path.audio_in_buf->amp, chain[i].path.audio_in_buf->len))
+ break;
+ }
+
+ chain[i].path.audio_out_buf->len = t38_gateway_tx(chain[i].node.t38_gateway_state, chain[i].path.audio_out_buf->amp, SAMPLES_PER_CHUNK);
+ if (!use_transmit_on_idle)
+ {
+ if (chain[i].path.audio_out_buf->len < SAMPLES_PER_CHUNK)
{
- for (j = 0; j < t38_len[i]; j++)
- out_amp[4*j + 2*i + 1] = t38_amp[i][j];
+ vec_zeroi16(&chain[i].path.audio_out_buf->amp[chain[i].path.audio_out_buf->len], SAMPLES_PER_CHUNK - chain[i].path.audio_out_buf->len);
+ chain[i].path.audio_out_buf->len = SAMPLES_PER_CHUNK;
}
}
- }
- if (mode[i] != AUDIO_FAX)
- {
- while ((msg_len = g1050_get(g1050_path[i], msg, 1024, when, &seq_no, &tx_when, &rx_when)) >= 0)
+ if (feedback_audio)
+ {
+ for (j = 0; j < chain[i].path.audio_out_buf->len; j++)
+ chain[i].path.audio_out_buf->amp[j] += t38_amp_hist_a[hist_ptr][j] >> 1;
+ vec_movei16(t38_amp_hist_a[hist_ptr], chain[i].path.audio_out_buf->amp, SAMPLES_PER_CHUNK);
+ }
+
+#if 0
+ if (log_audio)
+ {
+ k = (i == 0) ? 1 : 3;
+ for (j = 0; j < chain[i].path.audio_out_buf->len; j++)
+ audio_log[4*j + k] = chain[i].path.audio_out_buf->amp[j];
+ }
+#endif
+ while ((msg_len = g1050_get(chain[i].path.g1050_path, msg, 1024, when, &seq_no, &tx_when, &rx_when)) >= 0)
{
#if defined(ENABLE_GUI)
if (use_gui)
media_monitor_rx(seq_no, tx_when, rx_when);
#endif
- t38_core_rx_ifp_packet(t38_core_state[i ^ 1], msg, msg_len, seq_no);
+ t38_core_rx_ifp_packet(chain[chain[i].t38_peer].t38_core_state, msg, msg_len, seq_no);
}
+ break;
}
}
if (log_audio)
{
- outframes = sf_writef_short(wave_handle, out_amp, SAMPLES_PER_CHUNK);
+ outframes = sf_writef_short(wave_handle, audio_log, SAMPLES_PER_CHUNK);
if (outframes != SAMPLES_PER_CHUNK)
break;
}
when += (float) SAMPLES_PER_CHUNK/(float) SAMPLE_RATE;
- if (completed[0] && completed[1])
+ if (chain[0].completed && chain[chain_elements - 1].completed)
break;
#if defined(ENABLE_GUI)
if (use_gui)
if (++hist_ptr > 3)
hist_ptr = 0;
}
- for (i = 0; i < 2; i++)
+
+ for (i = 0; i < chain_elements; i++)
{
- if (mode[i] == T38_GATEWAY_FAX)
+ switch (chain[i].node_type)
{
- t38_gateway_get_transfer_statistics(t38_gateway_state[i], &t38_stats);
+ case AUDIO_TO_T38_GATEWAY:
+ t38_gateway_get_transfer_statistics(chain[i].node.t38_gateway_state, &t38_stats);
printf("%c side exchanged %d pages at %dbps, in %s mode\n",
i + 'A',
t38_stats.pages_transferred,
t38_stats.bit_rate,
(t38_stats.error_correcting_mode) ? "ECM" : "non-ECM");
- }
- }
- if (input_wave_handle)
- {
- if (sf_close_telephony(input_wave_handle))
- {
- fprintf(stderr, " Cannot close audio file '%s'\n", decode_file_name);
- exit(2);
+ break;
}
}
if (log_audio)
if (start_page >= 0)
expected_pages -= start_page;
/* Check how many pages were transferred */
- for (i = 0; i < 2; i++)
+ for (j = 0; j < 2; j++)
{
- if (!phase_e_reached[i])
+ i = (j == 0) ? 0 : (chain_elements - 1);
+ if (!chain[i].phase_e_reached)
break;
- if (!succeeded[i])
+ if (!chain[i].succeeded)
break;
- t30_get_transfer_statistics(t30_state[i], &t30_stats);
- if (i & 1)
+
+ t30_get_transfer_statistics(chain[i].t30_state, &t30_stats);
+ if ((!use_polled_mode && i != 0) || (use_polled_mode && i == 0))
{
if (t30_stats.pages_tx != 0 || t30_stats.pages_rx != expected_pages)
break;
if (t30_stats.pages_tx != expected_pages || t30_stats.pages_rx != 0)
break;
}
- if (mode[i] == T38_TERMINAL_FAX)
- t38_terminal_free(t38_state[i]);
- else
- fax_free(fax_state[i]);
- if (mode[i] == T38_GATEWAY_FAX)
- t38_gateway_free(t38_gateway_state[i]);
- if (g1050_path[i])
+ }
+ for (i = 0; i < chain_elements; i++)
+ {
+ switch (chain[i].node_type)
+ {
+ case AUDIO_FAX:
+ fax_free(chain[i].node.fax_state);
+ break;
+ case T38_FAX:
+ t38_terminal_free(chain[i].node.t38_state);
+ break;
+ case TSB85_AUDIO_FAX:
+ case TSB85_T38_FAX:
+ faxtester_free(chain[i].node.faxtester_state);
+ break;
+ case REPLAY_AUDIO_FAX:
+ if (sf_close_telephony(chain[i].node.wave_handle))
+ {
+ fprintf(stderr, " Cannot close audio file '%s'\n", replay_file_name);
+ exit(2);
+ }
+ chain[i].node.wave_handle = NULL;
+ break;
+ case AUDIO_TO_T38_GATEWAY:
+ t38_gateway_free(chain[i].node.t38_gateway_state);
+ break;
+ }
+ if (chain[i].path.g1050_path)
{
- g1050_free(g1050_path[i]);
- g1050_path[i] = NULL;
+ g1050_free(chain[i].path.g1050_path);
+ chain[i].path.g1050_path = NULL;
}
}
- if (i < 2)
+ if (j < 2)
{
printf("Tests failed\n");
exit(2);
}
+ t33_tests();
printf("Tests passed\n");
return 0;
}
TIFFCMP=tiffcmp
# Colour/gray -> bilevel by not allowing ECM
-#for OPTS in "-p AA" "-p TT" "-p GG" "-p TG" "-p GT"
+#for OPTS in "-p FAX-FAX" "-p T38-T38" "-p FAX-T38gateway-T38gateway-FAX" "-p T38-T38gateway-FAX" "-p FAX-T38gateway-T38"
#do
# IN_FILE="${LOCALTESTS_DIR}/lenna-colour.tif"
# OUT_FILE="${LOCALTESTS_DIR}/lenna-colour-bilevel.tif"
#done
# Colour/gray -> colour/gray
-#for OPTS in "-p AA -C -e" "-p TT -C -e" "-p GG -C -e" "-p TG -C -e" "-p GT -C -e"
+#for OPTS in "-p FAX-FAX -C -e" "-p T38-T38 -C -e" "-p FAX-T38gateway-T38gateway-FAX -C -e" "-p T38-T38gateway-FAX -C -e" "-p FAX-T38gateway-T38 -C -e"
#do
# IN_FILE="${LOCALTESTS_DIR}/lenna-colour.tif"
# OUT_FILE="${LOCALTESTS_DIR}/lenna-colour-out.tif"
#done
# Bi-level tests with image squashing
-for OPTS in "-p AA" "-p AA -e" "-p TT" "-p TT -e" "-p GG" "-p GG -e" "-p TG" "-p TG -e" "-p GT" "-p GT -e"
+for OPTS in "-p FAX-FAX" "-p FAX-FAX -e" "-p T38-T38" "-p T38-T38 -e" "-p FAX-T38gateway-T38gateway-FAX" "-p FAX-T38gateway-T38gateway-FAX -e" "-p T38-T38gateway-FAX" "-p T38-T38gateway-FAX -e" "-p FAX-T38gateway-T38" "-p FAX-T38gateway-T38 -e"
do
IN_FILE="${ITUTESTS_DIR}/bilevel_R8_77_A4.tif"
OUT_FILE="${ITUTESTS_DIR}/bilevel_R8_77SQ_A4.tif"
done
# Bi-level tests
-for OPTS in "-p AA" "-p AA -e" "-p TT" "-p TT -e" "-p GG" "-p GG -e" "-p TG" "-p TG -e" "-p GT" "-p GT -e"
+for OPTS in "-p FAX-FAX" "-p FAX-FAX -e" "-p T38-T38" "-p T38-T38 -e" "-p FAX-T38gateway-T38gateway-FAX" "-p FAX-T38gateway-T38gateway-FAX -e" "-p T38-T38gateway-FAX" "-p T38-T38gateway-FAX -e" "-p FAX-T38gateway-T38" "-p FAX-T38gateway-T38 -e"
do
FILE="${ITUTESTS_DIR}/itutests.tif"
run_fax_test
typedef struct _ipv6_hdr
{
char dontcare[6];
- uint8_t nxt_header; /* we only need the next header, so we can determine, if the next header is UDP or not */
+ u_int8_t nxt_header; /* we only need the next header, so we can determine, if the next header is UDP or not */
char dontcare2[33];
} ipv6_hdr;
#endif
SNDFILE *out_handle;
-bool use_receiver_not_ready = false;
-bool test_local_interrupt = false;
-
const char *output_tiff_file_name;
bool log_audio = false;
-fax_state_t *fax;
-faxtester_state_t state;
-
-uint8_t image[1000000];
-
-uint8_t awaited[1000];
-int awaited_len = 0;
-
-char image_path[1024];
-
-t30_exchanged_info_t expected_rx_info;
-
-char next_tx_file[1000];
-
-static int timein_x = -1;
-static int timeout_x = -1;
-
-static int next_step(faxtester_state_t *s);
-
-static bool test_for_call_clear = false;
-static int call_clear_timer = 0;
-
-static bool far_end_cleared_call = false;
-
-struct
-{
- const char *tag;
- int code;
-} t30_status[] =
-{
- {"OK", T30_ERR_OK},
- {"CEDTONE", T30_ERR_CEDTONE},
- {"T0_EXPIRED", T30_ERR_T0_EXPIRED},
- {"T1_EXPIRED", T30_ERR_T1_EXPIRED},
- {"T3_EXPIRED", T30_ERR_T3_EXPIRED},
- {"HDLC_CARRIER", T30_ERR_HDLC_CARRIER},
- {"CANNOT_TRAIN", T30_ERR_CANNOT_TRAIN},
- {"OPER_INT_FAIL", T30_ERR_OPER_INT_FAIL},
- {"INCOMPATIBLE", T30_ERR_INCOMPATIBLE},
- {"RX_INCAPABLE", T30_ERR_RX_INCAPABLE},
- {"TX_INCAPABLE", T30_ERR_TX_INCAPABLE},
- {"NORESSUPPORT", T30_ERR_NORESSUPPORT},
- {"NOSIZESUPPORT", T30_ERR_NOSIZESUPPORT},
- {"UNEXPECTED", T30_ERR_UNEXPECTED},
- {"TX_BADDCS", T30_ERR_TX_BADDCS},
- {"TX_BADPG", T30_ERR_TX_BADPG},
- {"TX_ECMPHD", T30_ERR_TX_ECMPHD},
- {"TX_GOTDCN", T30_ERR_TX_GOTDCN},
- {"TX_INVALRSP", T30_ERR_TX_INVALRSP},
- {"TX_NODIS", T30_ERR_TX_NODIS},
- {"TX_PHBDEAD", T30_ERR_TX_PHBDEAD},
- {"TX_PHDDEAD", T30_ERR_TX_PHDDEAD},
- {"TX_T5EXP", T30_ERR_TX_T5EXP},
- {"RX_ECMPHD", T30_ERR_RX_ECMPHD},
- {"RX_GOTDCS", T30_ERR_RX_GOTDCS},
- {"RX_INVALCMD", T30_ERR_RX_INVALCMD},
- {"RX_NOCARRIER", T30_ERR_RX_NOCARRIER},
- {"RX_NOEOL", T30_ERR_RX_NOEOL},
- {"RX_NOFAX", T30_ERR_RX_NOFAX},
- {"RX_T2EXPDCN", T30_ERR_RX_T2EXPDCN},
- {"RX_T2EXPD", T30_ERR_RX_T2EXPD},
- {"RX_T2EXPFAX", T30_ERR_RX_T2EXPFAX},
- {"RX_T2EXPMPS", T30_ERR_RX_T2EXPMPS},
- {"RX_T2EXPRR", T30_ERR_RX_T2EXPRR},
- {"RX_T2EXP", T30_ERR_RX_T2EXP},
- {"RX_DCNWHY", T30_ERR_RX_DCNWHY},
- {"RX_DCNDATA", T30_ERR_RX_DCNDATA},
- {"RX_DCNFAX", T30_ERR_RX_DCNFAX},
- {"RX_DCNPHD", T30_ERR_RX_DCNPHD},
- {"RX_DCNRRD", T30_ERR_RX_DCNRRD},
- {"RX_DCNNORTN", T30_ERR_RX_DCNNORTN},
- {"FILEERROR", T30_ERR_FILEERROR},
- {"NOPAGE", T30_ERR_NOPAGE},
- {"BADTIFF", T30_ERR_BADTIFF},
- {"BADPAGE", T30_ERR_BADPAGE},
- {"BADTAG", T30_ERR_BADTAG},
- {"BADTIFFHDR", T30_ERR_BADTIFFHDR},
- {"NOMEM", T30_ERR_NOMEM},
- {"RETRYDCN", T30_ERR_RETRYDCN},
- {"CALLDROPPED", T30_ERR_CALLDROPPED},
- {"NOPOLL", T30_ERR_NOPOLL},
- {"IDENT_UNACCEPTABLE", T30_ERR_IDENT_UNACCEPTABLE},
- {"SUB_UNACCEPTABLE", T30_ERR_SUB_UNACCEPTABLE},
- {"SEP_UNACCEPTABLE", T30_ERR_SEP_UNACCEPTABLE},
- {"PSA_UNACCEPTABLE", T30_ERR_PSA_UNACCEPTABLE},
- {"SID_UNACCEPTABLE", T30_ERR_SID_UNACCEPTABLE},
- {"PWD_UNACCEPTABLE", T30_ERR_PWD_UNACCEPTABLE},
- {"TSA_UNACCEPTABLE", T30_ERR_TSA_UNACCEPTABLE},
- {"IRA_UNACCEPTABLE", T30_ERR_IRA_UNACCEPTABLE},
- {"CIA_UNACCEPTABLE", T30_ERR_CIA_UNACCEPTABLE},
- {"ISP_UNACCEPTABLE", T30_ERR_ISP_UNACCEPTABLE},
- {"CSA_UNACCEPTABLE", T30_ERR_CSA_UNACCEPTABLE},
- {NULL, -1}
-};
-
-static int phase_b_handler(void *user_data, int result)
-{
- int ch;
- int status;
- t30_state_t *s;
- const char *u;
-
- s = (t30_state_t *) user_data;
- ch = 'A';
- status = T30_ERR_OK;
- if ((u = t30_get_rx_ident(s)))
- {
- printf("%c: Phase B: remote ident '%s'\n", ch, u);
- if (expected_rx_info.ident[0] && strcmp(expected_rx_info.ident, u))
- {
- printf("%c: Phase B: remote ident incorrect! - expected '%s'\n", ch, expected_rx_info.ident);
- status = T30_ERR_IDENT_UNACCEPTABLE;
- }
- }
- else
- {
- if (expected_rx_info.ident[0])
- {
- printf("%c: Phase B: remote ident missing!\n", ch);
- status = T30_ERR_IDENT_UNACCEPTABLE;
- }
- }
- if ((u = t30_get_rx_sub_address(s)))
- {
- printf("%c: Phase B: remote sub-address '%s'\n", ch, u);
- if (expected_rx_info.sub_address[0] && strcmp(expected_rx_info.sub_address, u))
- {
- printf("%c: Phase B: remote sub-address incorrect! - expected '%s'\n", ch, expected_rx_info.sub_address);
- status = T30_ERR_SUB_UNACCEPTABLE;
- }
- }
- else
- {
- if (expected_rx_info.sub_address[0])
- {
- printf("%c: Phase B: remote sub-address missing!\n", ch);
- status = T30_ERR_SUB_UNACCEPTABLE;
- }
- }
- if ((u = t30_get_rx_polled_sub_address(s)))
- {
- printf("%c: Phase B: remote polled sub-address '%s'\n", ch, u);
- if (expected_rx_info.polled_sub_address[0] && strcmp(expected_rx_info.polled_sub_address, u))
- {
- printf("%c: Phase B: remote polled sub-address incorrect! - expected '%s'\n", ch, expected_rx_info.polled_sub_address);
- status = T30_ERR_PSA_UNACCEPTABLE;
- }
- }
- else
- {
- if (expected_rx_info.polled_sub_address[0])
- {
- printf("%c: Phase B: remote polled sub-address missing!\n", ch);
- status = T30_ERR_PSA_UNACCEPTABLE;
- }
- }
- if ((u = t30_get_rx_selective_polling_address(s)))
- {
- printf("%c: Phase B: remote selective polling address '%s'\n", ch, u);
- if (expected_rx_info.selective_polling_address[0] && strcmp(expected_rx_info.selective_polling_address, u))
- {
- printf("%c: Phase B: remote selective polling address incorrect! - expected '%s'\n", ch, expected_rx_info.selective_polling_address);
- status = T30_ERR_SEP_UNACCEPTABLE;
- }
- }
- else
- {
- if (expected_rx_info.selective_polling_address[0])
- {
- printf("%c: Phase B: remote selective polling address missing!\n", ch);
- status = T30_ERR_SEP_UNACCEPTABLE;
- }
- }
- if ((u = t30_get_rx_sender_ident(s)))
- {
- printf("%c: Phase B: remote sender ident '%s'\n", ch, u);
- if (expected_rx_info.sender_ident[0] && strcmp(expected_rx_info.sender_ident, u))
- {
- printf("%c: Phase B: remote sender ident incorrect! - expected '%s'\n", ch, expected_rx_info.sender_ident);
- status = T30_ERR_SID_UNACCEPTABLE;
- }
- }
- else
- {
- if (expected_rx_info.sender_ident[0])
- {
- printf("%c: Phase B: remote sender ident missing!\n", ch);
- status = T30_ERR_SID_UNACCEPTABLE;
- }
- }
- if ((u = t30_get_rx_password(s)))
- {
- printf("%c: Phase B: remote password '%s'\n", ch, u);
- if (expected_rx_info.password[0] && strcmp(expected_rx_info.password, u))
- {
- printf("%c: Phase B: remote password incorrect! - expected '%s'\n", ch, expected_rx_info.password);
- status = T30_ERR_PWD_UNACCEPTABLE;
- }
- }
- else
- {
- if (expected_rx_info.password[0])
- {
- printf("%c: Phase B: remote password missing!\n", ch);
- status = T30_ERR_PWD_UNACCEPTABLE;
- }
- }
- printf("%c: Phase B handler on channel %d - (0x%X) %s\n", ch, ch, result, t30_frametype(result));
- return status;
-}
-/*- End of function --------------------------------------------------------*/
-
-static int phase_d_handler(void *user_data, int result)
-{
- int i;
- int ch;
- t30_state_t *s;
- char tag[20];
-
- i = 0;
- s = (t30_state_t *) user_data;
- ch = i + 'A';
- snprintf(tag, sizeof(tag), "%c: Phase D", ch);
- printf("%c: Phase D handler on channel %c - (0x%X) %s\n", ch, ch, result, t30_frametype(result));
- fax_log_page_transfer_statistics(s, tag);
- fax_log_tx_parameters(s, tag);
- fax_log_rx_parameters(s, tag);
-
- if (use_receiver_not_ready)
- t30_set_receiver_not_ready(s, 3);
-
- if (test_local_interrupt)
- {
- if (i == 0)
- {
- printf("%c: Initiating interrupt request\n", ch);
- t30_local_interrupt_request(s, true);
- }
- else
- {
- switch (result)
- {
- case T30_PIP:
- case T30_PRI_MPS:
- case T30_PRI_EOM:
- case T30_PRI_EOP:
- printf("%c: Accepting interrupt request\n", ch);
- t30_local_interrupt_request(s, true);
- break;
- case T30_PIN:
- break;
- }
- }
- }
- return T30_ERR_OK;
-}
-/*- End of function --------------------------------------------------------*/
-
-static void phase_e_handler(void *user_data, int result)
-{
- int ch;
- t30_state_t *s;
- char tag[20];
-
- ch = 'A';
- s = (t30_state_t *) user_data;
- snprintf(tag, sizeof(tag), "%c: Phase E", ch);
- printf("%c: Phase E handler on channel %c - (%d) %s\n", ch, ch, result, t30_completion_code_to_str(result));
- fax_log_final_transfer_statistics(s, tag);
- fax_log_tx_parameters(s, tag);
- fax_log_rx_parameters(s, tag);
-}
-/*- End of function --------------------------------------------------------*/
-
-static void t30_real_time_frame_handler(void *user_data,
- bool incoming,
- const uint8_t *msg,
- int len)
-{
- if (msg == NULL)
- {
- }
- else
- {
- fprintf(stderr,
- "T.30: Real time frame handler - %s, %s, length = %d\n",
- (incoming) ? "line->T.30" : "T.30->line",
- t30_frametype(msg[2]),
- len);
- }
-}
-/*- End of function --------------------------------------------------------*/
-
-static int document_handler(void *user_data, int event)
-{
- int ch;
- t30_state_t *s;
-
- ch = 'A';
- s = (t30_state_t *) user_data;
- fprintf(stderr, "%c: Document handler on channel %c - event %d\n", ch, ch, event);
- if (next_tx_file[0])
- {
- t30_set_tx_file(s, next_tx_file, -1, -1);
- next_tx_file[0] = '\0';
- return true;
- }
- return false;
-}
-/*- End of function --------------------------------------------------------*/
-
-static void faxtester_real_time_frame_handler(faxtester_state_t *s,
- void *user_data,
- int direction,
- const uint8_t *msg,
- int len)
-{
- if (msg == NULL)
- {
- while (next_step(s) == 0)
- ;
- /*endwhile*/
- }
- else
- {
- fprintf(stderr,
- "TST: Real time frame handler - %s, %s, length = %d\n",
- (direction) ? "line->tester" : "tester->line",
- t30_frametype(msg[2]),
- len);
- if (direction && msg[1] == awaited[1])
- {
- if ((awaited_len >= 0 && len != abs(awaited_len))
- ||
- (awaited_len < 0 && len < abs(awaited_len))
- ||
- memcmp(msg, awaited, abs(awaited_len)) != 0)
- {
- span_log_buf(&s->logging, SPAN_LOG_FLOW, "Expected", awaited, abs(awaited_len));
- span_log_buf(&s->logging, SPAN_LOG_FLOW, "Received", msg, len);
- printf("Test failed\n");
- exit(2);
- }
- }
- if (msg[1] == awaited[1])
- {
- while (next_step(s) == 0)
- ;
- /*endwhile*/
- }
- }
-}
-/*- End of function --------------------------------------------------------*/
-
-static void faxtester_front_end_step_complete_handler(faxtester_state_t *s, void *user_data)
-{
- while (next_step(s) == 0)
- ;
- /*endwhile*/
-}
-/*- End of function --------------------------------------------------------*/
-
-static void faxtester_front_end_step_timeout_handler(faxtester_state_t *s, void *user_data)
-{
- span_log(&s->logging, SPAN_LOG_FLOW, "FAX tester step timed out\n");
- printf("Test failed\n");
- exit(2);
-}
-/*- End of function --------------------------------------------------------*/
-
-static void fax_prepare(void)
-{
- t30_state_t *t30;
- logging_state_t *logging;
-
- t30 = fax_get_t30_state(fax);
- fax_set_transmit_on_idle(fax, true);
- fax_set_tep_mode(fax, true);
-#if 0
- t30_set_tx_ident(t30, "1234567890");
- t30_set_tx_sub_address(t30, "Sub-address");
- t30_set_tx_sender_ident(t30, "Sender ID");
- t30_set_tx_password(t30, "Password");
- t30_set_tx_polled_sub_address(t30, "Polled sub-address");
- t30_set_tx_selective_polling_address(t30, "Sel polling address");
-#endif
- t30_set_tx_nsf(t30, (const uint8_t *) "\x50\x00\x00\x00Spandsp NSF\x00", 16);
- //t30_set_tx_nss(t30, (const uint8_t *) "\x50\x00\x00\x00Spandsp NSS\x00", 16);
- t30_set_tx_nsc(t30, (const uint8_t *) "\x50\x00\x00\x00Spandsp NSC\x00", 16);
- t30_set_ecm_capability(t30, true);
- t30_set_supported_t30_features(t30,
- T30_SUPPORT_IDENTIFICATION
- | T30_SUPPORT_SELECTIVE_POLLING
- | T30_SUPPORT_SUB_ADDRESSING);
- t30_set_supported_image_sizes(t30,
- T4_SUPPORT_WIDTH_215MM
- | T4_SUPPORT_WIDTH_255MM
- | T4_SUPPORT_WIDTH_303MM
- | T4_SUPPORT_LENGTH_US_LETTER
- | T4_SUPPORT_LENGTH_US_LEGAL
- | T4_SUPPORT_LENGTH_UNLIMITED);
- t30_set_supported_bilevel_resolutions(t30,
- T4_RESOLUTION_R8_STANDARD
- | T4_RESOLUTION_R8_FINE
- | T4_RESOLUTION_R8_SUPERFINE
- | T4_RESOLUTION_R16_SUPERFINE
- | T4_RESOLUTION_100_100
- | T4_RESOLUTION_200_100
- | T4_RESOLUTION_200_200
- | T4_RESOLUTION_200_400
- | T4_RESOLUTION_300_300
- | T4_RESOLUTION_300_600
- | T4_RESOLUTION_400_400
- | T4_RESOLUTION_400_800
- | T4_RESOLUTION_600_600
- | T4_RESOLUTION_600_1200
- | T4_RESOLUTION_1200_1200);
- t30_set_supported_colour_resolutions(t30, 0);
- t30_set_supported_modems(t30, T30_SUPPORT_V27TER | T30_SUPPORT_V29 | T30_SUPPORT_V17);
- t30_set_supported_compressions(t30, T4_COMPRESSION_T4_1D | T4_COMPRESSION_T4_2D | T4_COMPRESSION_T6);
- t30_set_phase_b_handler(t30, phase_b_handler, (void *) t30);
- t30_set_phase_d_handler(t30, phase_d_handler, (void *) t30);
- t30_set_phase_e_handler(t30, phase_e_handler, (void *) t30);
- t30_set_real_time_frame_handler(t30, t30_real_time_frame_handler, (void *) t30);
- t30_set_document_handler(t30, document_handler, (void *) t30);
-
- logging = fax_get_logging_state(fax);
- span_log_set_level(logging, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_SHOW_TAG | SPAN_LOG_SHOW_SAMPLE_TIME | SPAN_LOG_FLOW);
- span_log_set_tag(logging, "A");
-
- logging = t30_get_logging_state(t30);
- span_log_set_level(logging, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_SHOW_TAG | SPAN_LOG_SHOW_SAMPLE_TIME | SPAN_LOG_FLOW);
- span_log_set_tag(logging, "A");
-
-#if 0
- span_log_set_level(&fax.modems.v27ter_rx.logging, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_SHOW_TAG | SPAN_LOG_SHOW_SAMPLE_TIME | SPAN_LOG_FLOW);
- span_log_set_tag(&fax.modems.v27ter_rx.logging, "A");
- span_log_set_level(&fax.modems.v29_rx.logging, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_SHOW_TAG | SPAN_LOG_SHOW_SAMPLE_TIME | SPAN_LOG_FLOW);
- span_log_set_tag(&fax.modems.v29_rx.logging, "A");
- span_log_set_level(&fax.modems.v17_rx.logging, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_SHOW_TAG | SPAN_LOG_SHOW_SAMPLE_TIME | SPAN_LOG_FLOW);
- span_log_set_tag(&fax.modems.v17_rx.logging, "A");
-#endif
-}
-/*- End of function --------------------------------------------------------*/
-
-static int string_to_msg(uint8_t msg[], uint8_t mask[], const char buf[])
-{
- int i;
- int x;
- const char *t;
-
- msg[0] = 0;
- mask[0] = 0xFF;
- i = 0;
- t = (char *) buf;
- while (*t)
- {
- /* Skip white space */
- while (isspace((int) *t))
- t++;
- /* If we find ... we allow arbitrary addition info beyond this point in the message */
- if (t[0] == '.' && t[1] == '.' && t[2] == '.')
- {
- return -i;
- }
- else if (isxdigit((int) *t))
- {
- for ( ; isxdigit((int) *t); t++)
- {
- x = *t;
- if (x >= 'a')
- x -= 0x20;
- if (x >= 'A')
- x -= ('A' - 10);
- else
- x -= '0';
- msg[i] = (msg[i] << 4) | x;
- }
- mask[i] = 0xFF;
- if (*t == '/')
- {
- /* There is a mask following the byte */
- mask[i] = 0;
- for (t++; isxdigit((int) *t); t++)
- {
- x = *t;
- if (x >= 'a')
- x -= 0x20;
- if (x >= 'A')
- x -= ('A' - 10);
- else
- x -= '0';
- mask[i] = (mask[i] << 4) | x;
- }
- }
- if (*t && !isspace((int) *t))
- {
- /* Bad string */
- return 0;
- }
- i++;
- }
- }
- return i;
-}
-/*- End of function --------------------------------------------------------*/
-
-#if 0
-static void string_test2(const uint8_t msg[], int len)
-{
- int i;
-
- if (len > 0)
- {
- for (i = 0; i < len - 1; i++)
- printf("%02X ", msg[i]);
- printf("%02X", msg[i]);
- }
-}
-/*- End of function --------------------------------------------------------*/
-
-static void string_test3(const char buf[])
-{
- uint8_t msg[1000];
- uint8_t mask[1000];
- int len;
- int i;
-
- len = string_to_msg(msg, mask, buf);
- printf("Len = %d: ", len);
- string_test2(msg, abs(len));
- printf("/");
- string_test2(mask, abs(len));
- printf("\n");
-}
-/*- End of function --------------------------------------------------------*/
-
-static int string_test(void)
-{
- string_test3("FF C8 12 34 56 78");
- string_test3("FF C8 12/55 34 56/aA 78 ");
- string_test3("FF C8 12/55 34 56/aA 78 ...");
- string_test3("FF C8 12/55 34 56/aA 78...");
- string_test3("FF C8 12/55 34 56/aA 78 ... 99 88 77");
- exit(0);
-}
-/*- End of function --------------------------------------------------------*/
-#endif
-
-static void corrupt_image(faxtester_state_t *s, uint8_t image[], int len, const char *bad_rows)
-{
- int i;
- int j;
- int k;
- uint32_t bits;
- uint32_t bitsx;
- int list[1000];
- int x;
- int row;
- const char *t;
-
- /* Form the list of rows to be hit */
- x = 0;
- t = bad_rows;
- while (*t)
- {
- while (isspace((int) *t))
- t++;
- if (sscanf(t, "%d", &list[x]) < 1)
- break;
- x++;
- while (isdigit((int) *t))
- t++;
- if (*t == ',')
- t++;
- }
-
- /* Go through the image, and corrupt the first bit of every listed row */
- bits = 0x7FF;
- bitsx = 0x7FF;
- row = 0;
- for (i = 0; i < len; i++)
- {
- bits ^= (image[i] << 11);
- bitsx ^= (image[i] << 11);
- for (j = 0; j < 8; j++)
- {
- if ((bits & 0xFFF) == 0x800)
- {
- /* We are at an EOL. Is this row in the list of rows to be corrupted? */
- row++;
- for (k = 0; k < x; k++)
- {
- if (list[k] == row)
- {
- /* Corrupt this row. TSB85 says to hit the first bit after the EOL */
- bitsx ^= 0x1000;
- }
- }
- }
- bits >>= 1;
- bitsx >>= 1;
- }
- image[i] = (bitsx >> 3) & 0xFF;
- }
- span_log(&s->logging, SPAN_LOG_FLOW, "%d rows found. %d corrupted\n", row, x);
-}
-/*- End of function --------------------------------------------------------*/
-
-static int next_step(faxtester_state_t *s)
-{
- int delay;
- int flags;
- xmlChar *dir;
- xmlChar *type;
- xmlChar *modem;
- xmlChar *value;
- xmlChar *tag;
- xmlChar *bad_rows;
- xmlChar *crc_error;
- xmlChar *pattern;
- xmlChar *timein;
- xmlChar *timeout;
- xmlChar *min_bits;
- xmlChar *frame_size;
- xmlChar *block;
- xmlChar *compression;
- uint8_t buf[1000];
- uint8_t mask[1000];
- char path[1024];
- int i;
- int j;
- int hdlc;
- int short_train;
- int min_row_bits;
- int ecm_frame_size;
- int ecm_block;
- int compression_type;
- int len;
- t4_tx_state_t t4_tx_state;
- t30_state_t *t30;
- t30_stats_t t30_stats;
-
- test_for_call_clear = false;
- if (s->cur == NULL)
- {
- if (!s->final_delayed)
- {
- /* Add a bit of waiting at the end, to ensure everything gets flushed through,
- any timers can expire, etc. */
- faxtester_set_timeout(s, -1);
- faxtester_set_rx_type(s, T30_MODEM_NONE, 0, false, false);
- faxtester_set_tx_type(s, T30_MODEM_PAUSE, 0, 120000, false);
- s->final_delayed = true;
- return 1;
- }
- /* Finished */
- printf("Test passed\n");
- exit(0);
- }
- while (s->cur && xmlStrcmp(s->cur->name, (const xmlChar *) "step") != 0)
- s->cur = s->cur->next;
- if (s->cur == NULL)
- {
- /* Finished */
- printf("Test passed\n");
- exit(0);
- }
-
- dir = xmlGetProp(s->cur, (const xmlChar *) "dir");
- type = xmlGetProp(s->cur, (const xmlChar *) "type");
- modem = xmlGetProp(s->cur, (const xmlChar *) "modem");
- value = xmlGetProp(s->cur, (const xmlChar *) "value");
- tag = xmlGetProp(s->cur, (const xmlChar *) "tag");
- bad_rows = xmlGetProp(s->cur, (const xmlChar *) "bad_rows");
- crc_error = xmlGetProp(s->cur, (const xmlChar *) "crc_error");
- pattern = xmlGetProp(s->cur, (const xmlChar *) "pattern");
- timein = xmlGetProp(s->cur, (const xmlChar *) "timein");
- timeout = xmlGetProp(s->cur, (const xmlChar *) "timeout");
- min_bits = xmlGetProp(s->cur, (const xmlChar *) "min_bits");
- frame_size = xmlGetProp(s->cur, (const xmlChar *) "frame_size");
- block = xmlGetProp(s->cur, (const xmlChar *) "block");
- compression = xmlGetProp(s->cur, (const xmlChar *) "compression");
-
- s->cur = s->cur->next;
-
- span_log(&s->logging,
- SPAN_LOG_FLOW,
- "Dir - %s, type - %s, modem - %s, value - %s, timein - %s, timeout - %s, tag - %s\n",
- (dir) ? (const char *) dir : "",
- (type) ? (const char *) type : "",
- (modem) ? (const char *) modem : "",
- (value) ? (const char *) value : "",
- (timein) ? (const char *) timein : "",
- (timeout) ? (const char *) timeout : "",
- (tag) ? (const char *) tag : "");
- if (type == NULL)
- return 1;
- if (timein)
- timein_x = atoi((const char *) timein);
- else
- timein_x = -1;
- if (timeout)
- timeout_x = atoi((const char *) timeout);
- else
- timeout_x = -1;
-
- if (dir && strcasecmp((const char *) dir, "R") == 0)
- {
- /* Receive always has a timeout applied. */
- if (timeout_x < 0)
- timeout_x = 7000;
- faxtester_set_timeout(s, timeout_x);
- if (modem)
- {
- hdlc = (strcasecmp((const char *) type, "PREAMBLE") == 0);
- short_train = (strcasecmp((const char *) type, "TCF") != 0);
- faxtester_set_tx_type(s, T30_MODEM_NONE, 0, false, false);
- if (strcasecmp((const char *) modem, "V.21") == 0)
- {
- faxtester_set_rx_type(s, T30_MODEM_V21, 300, false, true);
- }
- else if (strcasecmp((const char *) modem, "V.17/14400") == 0)
- {
- faxtester_set_rx_type(s, T30_MODEM_V17, 14400, short_train, hdlc);
- }
- else if (strcasecmp((const char *) modem, "V.17/12000") == 0)
- {
- faxtester_set_rx_type(s, T30_MODEM_V17, 12000, short_train, hdlc);
- }
- else if (strcasecmp((const char *) modem, "V.17/9600") == 0)
- {
- faxtester_set_rx_type(s, T30_MODEM_V17, 9600, short_train, hdlc);
- }
- else if (strcasecmp((const char *) modem, "V.17/7200") == 0)
- {
- faxtester_set_rx_type(s, T30_MODEM_V17, 7200, short_train, hdlc);
- }
- else if (strcasecmp((const char *) modem, "V.29/9600") == 0)
- {
- faxtester_set_rx_type(s, T30_MODEM_V29, 9600, false, hdlc);
- }
- else if (strcasecmp((const char *) modem, "V.29/7200") == 0)
- {
- faxtester_set_rx_type(s, T30_MODEM_V29, 7200, false, hdlc);
- }
- else if (strcasecmp((const char *) modem, "V.27ter/4800") == 0)
- {
- faxtester_set_rx_type(s, T30_MODEM_V27TER, 4800, false, hdlc);
- }
- else if (strcasecmp((const char *) modem, "V.27ter/2400") == 0)
- {
- faxtester_set_rx_type(s, T30_MODEM_V27TER, 2400, false, hdlc);
- }
- else
- {
- span_log(&s->logging, SPAN_LOG_FLOW, "Unrecognised modem\n");
- }
- }
-
- if (strcasecmp((const char *) type, "SET") == 0)
- {
- if (strcasecmp((const char *) tag, "IDENT") == 0)
- strcpy(expected_rx_info.ident, (const char *) value);
- else if (strcasecmp((const char *) tag, "SUB") == 0)
- strcpy(expected_rx_info.sub_address, (const char *) value);
- else if (strcasecmp((const char *) tag, "SEP") == 0)
- strcpy(expected_rx_info.selective_polling_address, (const char *) value);
- else if (strcasecmp((const char *) tag, "PSA") == 0)
- strcpy(expected_rx_info.polled_sub_address, (const char *) value);
- else if (strcasecmp((const char *) tag, "SID") == 0)
- strcpy(expected_rx_info.sender_ident, (const char *) value);
- else if (strcasecmp((const char *) tag, "PWD") == 0)
- strcpy(expected_rx_info.password, (const char *) value);
- return 0;
- }
- else if (strcasecmp((const char *) type, "CNG") == 0)
- {
- /* Look for CNG */
- faxtester_set_rx_type(s, T30_MODEM_CNG, 0, false, false);
- faxtester_set_tx_type(s, T30_MODEM_NONE, 0, false, false);
- }
- else if (strcasecmp((const char *) type, "CED") == 0)
- {
- /* Look for CED */
- faxtester_set_rx_type(s, T30_MODEM_CED, 0, false, false);
- faxtester_set_tx_type(s, T30_MODEM_NONE, 0, false, false);
- }
- else if (strcasecmp((const char *) type, "HDLC") == 0)
- {
- i = string_to_msg(buf, mask, (const char *) value);
- bit_reverse(awaited, buf, abs(i));
- awaited_len = i;
- }
- else if (strcasecmp((const char *) type, "TCF") == 0)
- {
- }
- else if (strcasecmp((const char *) type, "MSG") == 0)
- {
- }
- else if (strcasecmp((const char *) type, "PP") == 0)
- {
- }
- else if (strcasecmp((const char *) type, "SILENCE") == 0)
- {
- faxtest_set_rx_silence(s);
- }
- else if (strcasecmp((const char *) type, "CLEAR") == 0)
- {
- span_log(&s->logging, SPAN_LOG_FLOW, "Far end should drop the call\n");
- test_for_call_clear = true;
- call_clear_timer = 0;
- }
- else
- {
- span_log(&s->logging, SPAN_LOG_FLOW, "Unrecognised type '%s'\n", (const char *) type);
- return 0;
- }
- }
- else
- {
- faxtester_set_timeout(s, timeout_x);
- if (modem)
- {
- hdlc = (strcasecmp((const char *) type, "PREAMBLE") == 0);
- short_train = (strcasecmp((const char *) type, "TCF") != 0);
- faxtester_set_rx_type(s, T30_MODEM_NONE, 0, false, false);
- if (strcasecmp((const char *) modem, "V.21") == 0)
- {
- faxtester_set_tx_type(s, T30_MODEM_V21, 300, false, true);
- }
- else if (strcasecmp((const char *) modem, "V.17/14400") == 0)
- {
- faxtester_set_tx_type(s, T30_MODEM_V17, 14400, short_train, hdlc);
- }
- else if (strcasecmp((const char *) modem, "V.17/12000") == 0)
- {
- faxtester_set_tx_type(s, T30_MODEM_V17, 12000, short_train, hdlc);
- }
- else if (strcasecmp((const char *) modem, "V.17/9600") == 0)
- {
- faxtester_set_tx_type(s, T30_MODEM_V17, 9600, short_train, hdlc);
- }
- else if (strcasecmp((const char *) modem, "V.17/7200") == 0)
- {
- faxtester_set_tx_type(s, T30_MODEM_V17, 7200, short_train, hdlc);
- }
- else if (strcasecmp((const char *) modem, "V.29/9600") == 0)
- {
- faxtester_set_tx_type(s, T30_MODEM_V29, 9600, false, hdlc);
- }
- else if (strcasecmp((const char *) modem, "V.29/7200") == 0)
- {
- faxtester_set_tx_type(s, T30_MODEM_V29, 7200, false, hdlc);
- }
- else if (strcasecmp((const char *) modem, "V.27ter/4800") == 0)
- {
- faxtester_set_tx_type(s, T30_MODEM_V27TER, 4800, false, hdlc);
- }
- else if (strcasecmp((const char *) modem, "V.27ter/2400") == 0)
- {
- faxtester_set_tx_type(s, T30_MODEM_V27TER, 2400, false, hdlc);
- }
- else
- {
- span_log(&s->logging, SPAN_LOG_FLOW, "Unrecognised modem\n");
- }
- }
-
- if (strcasecmp((const char *) type, "SET") == 0)
- {
- t30 = fax_get_t30_state(fax);
- if (strcasecmp((const char *) tag, "IDENT") == 0)
- t30_set_tx_ident(t30, (const char *) value);
- else if (strcasecmp((const char *) tag, "SUB") == 0)
- t30_set_tx_sub_address(t30, (const char *) value);
- else if (strcasecmp((const char *) tag, "SEP") == 0)
- t30_set_tx_selective_polling_address(t30, (const char *) value);
- else if (strcasecmp((const char *) tag, "PSA") == 0)
- t30_set_tx_polled_sub_address(t30, (const char *) value);
- else if (strcasecmp((const char *) tag, "SID") == 0)
- t30_set_tx_sender_ident(t30, (const char *) value);
- else if (strcasecmp((const char *) tag, "PWD") == 0)
- t30_set_tx_password(t30, (const char *) value);
- else if (strcasecmp((const char *) tag, "RXFILE") == 0)
- {
- if (value)
- t30_set_rx_file(t30, (const char *) value, -1);
- else
- t30_set_rx_file(t30, output_tiff_file_name, -1);
- }
- else if (strcasecmp((const char *) tag, "TXFILE") == 0)
- {
- sprintf(next_tx_file, "%s/%s", image_path, (const char *) value);
- printf("Push '%s'\n", next_tx_file);
- }
- return 0;
- }
- else if (strcasecmp((const char *) type, "CALL") == 0)
- {
- fax = fax_init(NULL, false);
- fax_prepare();
- next_tx_file[0] = '\0';
- t30 = fax_get_t30_state(fax);
- t30_set_rx_file(t30, output_tiff_file_name, -1);
- /* Avoid libtiff 3.8.2 and earlier bug on complex 2D lines. */
- t30_set_supported_output_compressions(t30, T4_COMPRESSION_T4_1D);
- if (value)
- {
- sprintf(path, "%s/%s", image_path, (const char *) value);
- t30_set_tx_file(t30, path, -1, -1);
- }
- return 0;
- }
- else if (strcasecmp((const char *) type, "ANSWER") == 0)
- {
- fax = fax_init(NULL, true);
- fax_prepare();
- next_tx_file[0] = '\0';
- t30 = fax_get_t30_state(fax);
- /* Avoid libtiff 3.8.2 and earlier bug on complex 2D lines. */
- t30_set_supported_output_compressions(t30, T4_COMPRESSION_T4_1D);
- if (value)
- {
- sprintf(path, "%s/%s", image_path, (const char *) value);
- t30_set_tx_file(t30, path, -1, -1);
- }
- return 0;
- }
- else if (strcasecmp((const char *) type, "CNG") == 0)
- {
- faxtester_set_rx_type(s, T30_MODEM_NONE, 0, false, false);
- faxtester_set_tx_type(s, T30_MODEM_CNG, 0, false, false);
- }
- else if (strcasecmp((const char *) type, "CED") == 0)
- {
- faxtester_set_rx_type(s, T30_MODEM_NONE, 0, false, false);
- faxtester_set_tx_type(s, T30_MODEM_CED, 0, false, false);
- }
- else if (strcasecmp((const char *) type, "WAIT") == 0)
- {
- delay = (value) ? atoi((const char *) value) : 1;
- faxtester_set_rx_type(s, T30_MODEM_NONE, 0, false, false);
- faxtester_set_tx_type(s, T30_MODEM_PAUSE, 0, delay, false);
- }
- else if (strcasecmp((const char *) type, "PREAMBLE") == 0)
- {
- flags = (value) ? atoi((const char *) value) : 37;
- faxtester_send_hdlc_flags(s, flags);
- }
- else if (strcasecmp((const char *) type, "POSTAMBLE") == 0)
- {
- flags = (value) ? atoi((const char *) value) : 5;
- faxtester_send_hdlc_flags(s, flags);
- }
- else if (strcasecmp((const char *) type, "HDLC") == 0)
- {
- i = string_to_msg(buf, mask, (const char *) value);
- bit_reverse(buf, buf, abs(i));
- if (crc_error && strcasecmp((const char *) crc_error, "0") == 0)
- faxtester_send_hdlc_msg(s, buf, abs(i), false);
- else
- faxtester_send_hdlc_msg(s, buf, abs(i), true);
- }
- else if (strcasecmp((const char *) type, "TCF") == 0)
- {
- if (value)
- i = atoi((const char *) value);
- else
- i = 450;
- if (pattern)
- {
- /* TODO: implement proper patterns */
- j = atoi((const char *) pattern);
- memset(image, 0x55, j);
- if (i > j)
- memset(image + j, 0, i - j);
- }
- else
- {
- memset(image, 0, i);
- }
- faxtester_set_non_ecm_image_buffer(s, image, i);
- }
- else if (strcasecmp((const char *) type, "MSG") == 0)
- {
- /* A non-ECM page */
- min_row_bits = (min_bits) ? atoi((const char *) min_bits) : 0;
- sprintf(path, "%s/%s", image_path, (const char *) value);
- if (t4_tx_init(&t4_tx_state, path, -1, -1) == NULL)
- {
- span_log(&s->logging, SPAN_LOG_FLOW, "Failed to init T.4 send\n");
- printf("Test failed\n");
- exit(2);
- }
- t4_tx_set_header_info(&t4_tx_state, NULL);
- compression_type = T4_COMPRESSION_T4_1D;
- if (compression)
- {
- if (strcasecmp((const char *) compression, "T.4 2D") == 0)
- compression_type = T4_COMPRESSION_T4_2D;
- else if (strcasecmp((const char *) compression, "T.6") == 0)
- compression_type = T4_COMPRESSION_T6;
- }
- if (t4_tx_set_tx_image_format(&t4_tx_state,
- compression_type,
- T4_SUPPORT_WIDTH_215MM
- | T4_SUPPORT_LENGTH_US_LETTER
- | T4_SUPPORT_LENGTH_US_LEGAL
- | T4_SUPPORT_LENGTH_UNLIMITED,
- T4_RESOLUTION_R8_STANDARD
- | T4_RESOLUTION_R8_FINE
- | T4_RESOLUTION_R8_SUPERFINE
- | T4_RESOLUTION_R16_SUPERFINE
- | T4_RESOLUTION_200_100
- | T4_RESOLUTION_200_200
- | T4_RESOLUTION_200_400
- | T4_RESOLUTION_300_300
- | T4_RESOLUTION_300_600
- | T4_RESOLUTION_400_400
- | T4_RESOLUTION_400_800
- | T4_RESOLUTION_600_600
- | T4_RESOLUTION_600_1200
- | T4_RESOLUTION_1200_1200,
- T4_RESOLUTION_100_100
- | T4_RESOLUTION_200_200
- | T4_RESOLUTION_300_300
- | T4_RESOLUTION_400_400
- | T4_RESOLUTION_600_600
- | T4_RESOLUTION_1200_1200) < 0)
- {
- span_log(&s->logging, SPAN_LOG_FLOW, "Failed to set T.4 compression\n");
- printf("Test failed\n");
- exit(2);
- }
- t4_tx_set_min_bits_per_row(&t4_tx_state, min_row_bits);
- if (t4_tx_start_page(&t4_tx_state))
- {
- span_log(&s->logging, SPAN_LOG_FLOW, "Failed to start T.4 send\n");
- printf("Test failed\n");
- exit(2);
- }
- len = t4_tx_get(&t4_tx_state, image, sizeof(image));
- if (bad_rows)
- {
- span_log(&s->logging, SPAN_LOG_FLOW, "We need to corrupt the image\n");
- corrupt_image(s, image, len, (const char *) bad_rows);
- }
- t4_tx_release(&t4_tx_state);
- span_log(&s->logging, SPAN_LOG_FLOW, "Non-ECM image is %d bytes (min row bits %d)\n", len, min_row_bits);
- faxtester_set_non_ecm_image_buffer(s, image, len);
- }
- else if (strcasecmp((const char *) type, "PP") == 0)
- {
- min_row_bits = (min_bits) ? atoi((const char *) min_bits) : 0;
- ecm_block = (block) ? atoi((const char *) block) : 0;
- ecm_frame_size = (frame_size) ? atoi((const char *) frame_size) : 64;
- i = (crc_error) ? atoi((const char *) crc_error) : -1;
- sprintf(path, "%s/%s", image_path, (const char *) value);
- if (t4_tx_init(&t4_tx_state, path, -1, -1) == NULL)
- {
- span_log(&s->logging, SPAN_LOG_FLOW, "Failed to init T.4 send\n");
- printf("Test failed\n");
- exit(2);
- }
- t4_tx_set_header_info(&t4_tx_state, NULL);
- compression_type = T4_COMPRESSION_T4_1D;
- if (compression)
- {
- if (strcasecmp((const char *) compression, "T.4 2D") == 0)
- compression_type = T4_COMPRESSION_T4_2D;
- else if (strcasecmp((const char *) compression, "T.6") == 0)
- compression_type = T4_COMPRESSION_T6;
- }
- if (t4_tx_set_tx_image_format(&t4_tx_state,
- compression_type,
- T4_SUPPORT_WIDTH_215MM
- | T4_SUPPORT_LENGTH_US_LETTER
- | T4_SUPPORT_LENGTH_US_LEGAL
- | T4_SUPPORT_LENGTH_UNLIMITED,
- T4_RESOLUTION_R8_STANDARD
- | T4_RESOLUTION_R8_FINE
- | T4_RESOLUTION_R8_SUPERFINE
- | T4_RESOLUTION_R16_SUPERFINE
- | T4_RESOLUTION_200_100
- | T4_RESOLUTION_200_200
- | T4_RESOLUTION_200_400
- | T4_RESOLUTION_300_300
- | T4_RESOLUTION_300_600
- | T4_RESOLUTION_400_400
- | T4_RESOLUTION_400_800
- | T4_RESOLUTION_600_600
- | T4_RESOLUTION_600_1200
- | T4_RESOLUTION_1200_1200,
- T4_RESOLUTION_100_100
- | T4_RESOLUTION_200_200
- | T4_RESOLUTION_300_300
- | T4_RESOLUTION_400_400
- | T4_RESOLUTION_600_600
- | T4_RESOLUTION_1200_1200) < 0)
- {
- span_log(&s->logging, SPAN_LOG_FLOW, "Failed to set T.4 compression\n");
- printf("Test failed\n");
- exit(2);
- }
- t4_tx_set_min_bits_per_row(&t4_tx_state, min_row_bits);
- if (t4_tx_start_page(&t4_tx_state))
- {
- span_log(&s->logging, SPAN_LOG_FLOW, "Failed to start T.4 send\n");
- printf("Test failed\n");
- exit(2);
- }
- /*endif*/
- len = t4_tx_get(&t4_tx_state, image, sizeof(image));
- if (bad_rows)
- {
- span_log(&s->logging, SPAN_LOG_FLOW, "We need to corrupt the image\n");
- corrupt_image(s, image, len, (const char *) bad_rows);
- }
- /*endif*/
- t4_tx_release(&t4_tx_state);
- span_log(&s->logging, SPAN_LOG_FLOW, "ECM image is %d bytes (min row bits %d)\n", len, min_row_bits);
- faxtester_set_ecm_image_buffer(s, image, len, ecm_block, ecm_frame_size, i);
- }
- else if (strcasecmp((const char *) type, "CLEAR") == 0)
- {
- span_log(&s->logging, SPAN_LOG_FLOW, "Time to drop the call\n");
- t30 = fax_get_t30_state(fax);
- t30_terminate(t30);
- return 0;
- }
- else if (strcasecmp((const char *) type, "STATUS") == 0)
- {
- if (value)
- {
- for (i = 0; t30_status[i].code >= 0; i++)
- {
- if (strcmp(t30_status[i].tag, (const char *) value) == 0)
- break;
- }
- if (t30_status[i].code >= 0)
- delay = t30_status[i].code;
- else
- delay = atoi((const char *) value);
- t30 = fax_get_t30_state(fax);
- t30_get_transfer_statistics(t30, &t30_stats);
- span_log(&s->logging, SPAN_LOG_FLOW, "Expect status %d. Got %d\n", delay, t30_stats.current_status);
- if (delay != t30_stats.current_status)
- {
- printf("Test failed\n");
- exit(2);
- }
- }
- return 0;
- }
- else
- {
- span_log(&s->logging, SPAN_LOG_FLOW, "Unrecognised type '%s'\n", (const char *) type);
- return 0;
- }
- /*endif*/
- }
- /*endif*/
- return 1;
-}
-/*- End of function --------------------------------------------------------*/
+faxtester_state_t *state;
static void exchange(faxtester_state_t *s)
{
total_audio_time = 0;
- faxtester_set_transmit_on_idle(&state, true);
- faxtester_set_real_time_frame_handler(&state, faxtester_real_time_frame_handler, NULL);
- faxtester_set_front_end_step_complete_handler(&state, faxtester_front_end_step_complete_handler, NULL);
- faxtester_set_front_end_step_timeout_handler(&state, faxtester_front_end_step_timeout_handler, NULL);
+ faxtester_set_transmit_on_idle(s, true);
- fax = fax_init(NULL, false);
- fax_prepare();
- next_tx_file[0] = '\0';
+ s->far_fax = fax_init(NULL, false);
+ s->far_t30 = fax_get_t30_state(s->far_fax);
+ s->far_tag = 'A';
+
+ if (s->far_fax)
+ logging = fax_get_logging_state(s->far_fax);
+ else
+ logging = t38_terminal_get_logging_state(s->far_t38);
+ span_log_set_level(logging, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_SHOW_TAG | SPAN_LOG_SHOW_SAMPLE_TIME | SPAN_LOG_FLOW);
+ span_log_set_tag(logging, "A");
- while (next_step(s) == 0)
+ logging = t30_get_logging_state(s->far_t30);
+ span_log_set_level(logging, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_SHOW_TAG | SPAN_LOG_SHOW_SAMPLE_TIME | SPAN_LOG_FLOW);
+ span_log_set_tag(logging, "A");
+
+#if 0
+ span_log_set_level(&fax.modems.v27ter_rx.logging, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_SHOW_TAG | SPAN_LOG_SHOW_SAMPLE_TIME | SPAN_LOG_FLOW);
+ span_log_set_tag(&fax.modems.v27ter_rx.logging, "A");
+ span_log_set_level(&fax.modems.v29_rx.logging, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_SHOW_TAG | SPAN_LOG_SHOW_SAMPLE_TIME | SPAN_LOG_FLOW);
+ span_log_set_tag(&fax.modems.v29_rx.logging, "A");
+ span_log_set_level(&fax.modems.v17_rx.logging, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_SHOW_TAG | SPAN_LOG_SHOW_SAMPLE_TIME | SPAN_LOG_FLOW);
+ span_log_set_tag(&fax.modems.v17_rx.logging, "A");
+#endif
+ while (faxtester_next_step(s) == 0)
;
/*endwhile*/
for (;;)
{
- len = fax_tx(fax, amp, SAMPLES_PER_CHUNK);
+ len = fax_tx(s->far_fax, amp, SAMPLES_PER_CHUNK);
faxtester_rx(s, amp, len);
if (log_audio)
{
total_audio_time += SAMPLES_PER_CHUNK;
- logging = t30_get_logging_state(fax_get_t30_state(fax));
+ logging = t30_get_logging_state(s->far_t30);
span_log_bump_samples(logging, len);
#if 0
span_log_bump_samples(&fax.modems.v27ter_rx.logging, len);
span_log_bump_samples(&fax.modems.v29_rx.logging, len);
span_log_bump_samples(&fax.modems.v17_rx.logging, len);
#endif
- logging = fax_get_logging_state(fax);
+ logging = fax_get_logging_state(s->far_fax);
span_log_bump_samples(logging, len);
- span_log_bump_samples(&s->logging, len);
+ logging = faxtester_get_logging_state(s);
+ span_log_bump_samples(logging, len);
len = faxtester_tx(s, amp, SAMPLES_PER_CHUNK);
- if (fax_rx(fax, amp, len))
+ if (fax_rx(s->far_fax, amp, len))
break;
/*endif*/
if (log_audio)
/*endif*/
}
/*endif*/
- if (test_for_call_clear && !far_end_cleared_call)
+ if (s->test_for_call_clear && !s->far_end_cleared_call)
{
- call_clear_timer += len;
- if (!t30_call_active(fax_get_t30_state(fax)))
+ s->call_clear_timer += len;
+ if (!t30_call_active(s->far_t30))
{
- span_log(&s->logging, SPAN_LOG_FLOW, "Far end cleared after %dms (limits %dms to %dms)\n", call_clear_timer/8, timein_x, timeout_x);
- if (call_clear_timer/8 < timein_x || call_clear_timer/8 > timeout_x)
+ span_log(faxtester_get_logging_state(s), SPAN_LOG_FLOW, "Far end cleared after %dms (limits %dms to %dms)\n", s->call_clear_timer/8, s->timein_x, s->timeout);
+ if (s->call_clear_timer/8 < s->timein_x || s->call_clear_timer/8 > s->timeout_x)
{
printf("Test failed\n");
exit(2);
}
- span_log(&s->logging, SPAN_LOG_FLOW, "Clear time OK\n");
- far_end_cleared_call = true;
- test_for_call_clear = false;
- while (next_step(s) == 0)
+ span_log(faxtester_get_logging_state(s), SPAN_LOG_FLOW, "Clear time OK\n");
+ s->far_end_cleared_call = true;
+ s->test_for_call_clear = false;
+ while (faxtester_next_step(s) == 0)
;
/*endwhile*/
}
}
/*- End of function --------------------------------------------------------*/
-static int parse_config(faxtester_state_t *s, xmlDocPtr doc, xmlNsPtr ns, xmlNodePtr cur)
-{
- xmlChar *x;
- xmlChar *y;
-
- while (cur)
- {
- if (xmlStrcmp(cur->name, (const xmlChar *) "path") == 0)
- {
- if ((x = xmlGetProp(cur, (const xmlChar *) "type"))
- &&
- (y = xmlGetProp(cur, (const xmlChar *) "value")))
- {
- if (strcasecmp((const char *) x, "IMAGE") == 0)
- {
- span_log(&s->logging, SPAN_LOG_FLOW, "Found '%s' '%s'\n", (char *) x, (char *) y);
- strcpy(image_path, (const char *) y);
- }
- /*endif*/
- }
- /*endif*/
- }
- /*endif*/
- cur = cur->next;
- }
- /*endwhile*/
- return -1;
-}
-/*- End of function --------------------------------------------------------*/
-
-static int parse_test_group(faxtester_state_t *s, xmlDocPtr doc, xmlNsPtr ns, xmlNodePtr cur, const char *test)
-{
- xmlChar *x;
-
- while (cur)
- {
- if (xmlStrcmp(cur->name, (const xmlChar *) "test") == 0)
- {
- if ((x = xmlGetProp(cur, (const xmlChar *) "name")))
- {
- if (xmlStrcmp(x, (const xmlChar *) test) == 0)
- {
- span_log(&s->logging, SPAN_LOG_FLOW, "Found '%s'\n", (char *) x);
- s->cur = cur->xmlChildrenNode;
- return 0;
- }
- /*endif*/
- }
- /*endif*/
- }
- /*endif*/
- cur = cur->next;
- }
- /*endwhile*/
- return -1;
-}
-/*- End of function --------------------------------------------------------*/
-
-static int get_test_set(faxtester_state_t *s, const char *test_file, const char *test)
-{
- xmlParserCtxtPtr ctxt;
- xmlNsPtr ns;
- xmlNodePtr cur;
-
- ns = NULL;
- xmlKeepBlanksDefault(0);
- xmlCleanupParser();
-
- if ((ctxt = xmlNewParserCtxt()) == NULL)
- {
- fprintf(stderr, "Failed to allocate parser context\n");
- printf("Test failed\n");
- exit(2);
- }
- /* parse the file, activating the DTD validation option */
- if ((s->doc = xmlCtxtReadFile(ctxt, test_file, NULL, XML_PARSE_XINCLUDE | XML_PARSE_DTDVALID)) == NULL)
- {
- fprintf(stderr, "Failed to read the XML document\n");
- printf("Test failed\n");
- exit(2);
- }
- if (ctxt->valid == 0)
- {
- fprintf(stderr, "Failed to validate the XML document\n");
- xmlFreeDoc(s->doc);
- xmlFreeParserCtxt(ctxt);
- printf("Test failed\n");
- exit(2);
- }
- xmlFreeParserCtxt(ctxt);
-
- /* Check the document is of the right kind */
- if ((cur = xmlDocGetRootElement(s->doc)) == NULL)
- {
- xmlFreeDoc(s->doc);
- fprintf(stderr, "Empty document\n");
- printf("Test failed\n");
- exit(2);
- }
- /*endif*/
- if (xmlStrcmp(cur->name, (const xmlChar *) "fax-tests"))
- {
- xmlFreeDoc(s->doc);
- fprintf(stderr, "Document of the wrong type, root node != fax-tests");
- printf("Test failed\n");
- exit(2);
- }
- /*endif*/
- cur = cur->xmlChildrenNode;
- while (cur && xmlIsBlankNode(cur))
- cur = cur->next;
- /*endwhile*/
- if (cur == NULL)
- {
- printf("Test failed\n");
- exit(2);
- }
- /*endif*/
- while (cur)
- {
- if (xmlStrcmp(cur->name, (const xmlChar *) "config") == 0)
- {
- parse_config(s, s->doc, ns, cur->xmlChildrenNode);
- }
- /*endif*/
- if (xmlStrcmp(cur->name, (const xmlChar *) "test-group") == 0)
- {
- if (parse_test_group(s, s->doc, ns, cur->xmlChildrenNode, test) == 0)
- {
- /* We found the test we want, so run it. */
- exchange(s);
- break;
- }
- /*endif*/
- }
- /*endif*/
- cur = cur->next;
- }
- /*endwhile*/
- xmlFreeDoc(s->doc);
- return 0;
-}
-/*- End of function --------------------------------------------------------*/
-
int main(int argc, char *argv[])
{
const char *xml_file_name;
const char *test_name;
+ logging_state_t *logging;
int opt;
#if 0
if (argc > 0)
test_name = argv[0];
- strcpy(image_path, ".");
- faxtester_init(&state, true);
- memset(&expected_rx_info, 0, sizeof(expected_rx_info));
- span_log_set_level(&state.logging, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_SHOW_TAG | SPAN_LOG_SHOW_SAMPLE_TIME | SPAN_LOG_FLOW);
- span_log_set_tag(&state.logging, "B");
- get_test_set(&state, xml_file_name, test_name);
- faxtester_release(&state);
+ if ((state = faxtester_init(NULL, xml_file_name, test_name)) == NULL)
+ {
+ fprintf(stderr, "Cannot start FAX tester instance\n");
+ printf("Test failed\n");
+ exit(2);
+ }
+ logging = faxtester_get_logging_state(state);
+ span_log_set_level(logging, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_SHOW_TAG | SPAN_LOG_SHOW_SAMPLE_TIME | SPAN_LOG_FLOW);
+ span_log_set_tag(logging, "B");
+ /* We found the test we want, so run it. */
+ exchange(state);
+ faxtester_free(state);
printf("Done\n");
return 0;
}
+++ /dev/null
-alsa_nogsmlib_nocplusplus
\ No newline at end of file