]> git.ipfire.org Git - thirdparty/freeswitch.git/commitdiff
Various small cleanups in spandsp
authorSteve Underwood <steveu@x240.coppice.org>
Wed, 7 May 2014 05:11:53 +0000 (13:11 +0800)
committerSteve Underwood <steveu@x240.coppice.org>
Wed, 7 May 2014 05:11:53 +0000 (13:11 +0800)
14 files changed:
libs/spandsp/configure.ac
libs/spandsp/src/Makefile.am
libs/spandsp/src/spandsp.h.in
libs/spandsp/src/spandsp/expose.h
libs/spandsp/src/v27ter_tx.c
libs/spandsp/src/v8.c
libs/spandsp/tests/Makefile.am
libs/spandsp/tests/data_modems_tests.c [new file with mode: 0644]
libs/spandsp/tests/dummy_modems_tests.c [new file with mode: 0644]
libs/spandsp/tests/fax_tests.c
libs/spandsp/tests/socket_harness.c [new file with mode: 0644]
libs/spandsp/tests/socket_harness.h [new file with mode: 0644]
libs/spandsp/unpack_gsm0610_data.sh
libs/spandsp/yum-prepare.sh

index 19005f9965839407e0cb6ba55a7b3c688017bd11..ad5ecf148dfc167cdb0fc88e4aa1e019d0ddafb2 100644 (file)
@@ -202,6 +202,18 @@ AC_CHECK_HEADERS([stdlib.h])
 AC_CHECK_HEADERS([string.h])
 AC_CHECK_HEADERS([strings.h])
 AC_CHECK_HEADERS([malloc.h])
+AC_CHECK_HEADERS([math.h], [INSERT_MATH_HEADER="#include <math.h>"])
+AC_CHECK_HEADERS([float.h])
+AC_CHECK_HEADERS([fcntl.h])
+AC_CHECK_HEADERS([sys/time.h])
+AC_CHECK_HEADERS([sys/select.h])
+AC_CHECK_HEADERS([sys/ioctl.h])
+AC_CHECK_HEADERS([sys/fcntl.h])
+AC_CHECK_HEADERS([sndfile.h])
+AC_CHECK_HEADERS([fenv.h])
+AC_CHECK_HEADERS([fftw3.h], , [AC_CHECK_HEADERS([fftw.h])])
+AC_CHECK_HEADERS([pcap.h])
+AC_CHECK_HEADERS([pthread.h])
 
 case "$host" in
     *dragonfly*)
@@ -215,18 +227,6 @@ case "$host" in
     ;;
 esac
 
-AC_CHECK_HEADERS([math.h], [INSERT_MATH_HEADER="#include <math.h>"])
-AC_CHECK_HEADERS([float.h])
-AC_CHECK_HEADERS([fcntl.h])
-AC_CHECK_HEADERS([sys/time.h])
-AC_CHECK_HEADERS([sys/select.h])
-AC_CHECK_HEADERS([sys/ioctl.h])
-AC_CHECK_HEADERS([sys/fcntl.h])
-AC_CHECK_HEADERS([sndfile.h])
-AC_CHECK_HEADERS([fenv.h])
-AC_CHECK_HEADERS([fftw3.h], , [AC_CHECK_HEADERS([fftw.h])])
-AC_CHECK_HEADERS([pcap.h])
-AC_CHECK_HEADERS([pthread.h])
 if test "${build}" == "${host}"
 then
     AC_CHECK_HEADERS([X11/X.h])
index 46347fe00ab02d1229b73dc58196cedc71a25eea..6a80d13c169406b0ab0f8a732b7612a24d51f644 100644 (file)
@@ -110,6 +110,7 @@ libspandsp_la_SOURCES = ademco_contactid.c \
                         complex_vector_float.c \
                         complex_vector_int.c \
                         crc.c \
+                        data_modems.c \
                         dds_float.c \
                         dds_int.c \
                         dtmf.c \
@@ -210,6 +211,7 @@ nobase_include_HEADERS = spandsp/ademco_contactid.h \
                          spandsp/complex_filters.h \
                          spandsp/complex_vector_float.h \
                          spandsp/complex_vector_int.h \
+                         spandsp/data_modems.h \
                          spandsp/dc_restore.h \
                          spandsp/dds.h \
                          spandsp/dtmf.h \
@@ -292,6 +294,7 @@ nobase_include_HEADERS = spandsp/ademco_contactid.h \
                          spandsp/private/bell_r2_mf.h \
                          spandsp/private/bert.h \
                          spandsp/private/bitstream.h \
+                         spandsp/private/data_modems.h \
                          spandsp/private/dtmf.h \
                          spandsp/private/echo.h \
                          spandsp/private/fax.h \
index 747f4a432f411e9a022c3c4b4398616a0faef3d3..7ec041f195e913193c368ecc2a6acf6fb95bd8de 100644 (file)
 #include <spandsp/t30_logging.h>
 #include <spandsp/t35.h>
 #include <spandsp/at_interpreter.h>
+#include <spandsp/data_modems.h>
 #include <spandsp/fax_modems.h>
 #include <spandsp/fax.h>
 #include <spandsp/t38_core.h>
index b65a21f1b9b689ec5e7d64cd36d0800434db8603..d9811b4caa4b7287fb3308e50791550c22a33cc8 100644 (file)
@@ -82,7 +82,7 @@
 #include <spandsp/private/v42.h>
 #include <spandsp/private/v42bis.h>
 #include <spandsp/private/at_interpreter.h>
-//#include <spandsp/private/data_modems.h>
+#include <spandsp/private/data_modems.h>
 #include <spandsp/private/fax_modems.h>
 #include <spandsp/private/timezone.h>
 #include <spandsp/private/image_translate.h>
index 5065c004bef9ab56303235fa8c3ac7384009486e..f6b69917bbc80d58ff711cc738ad552c2164675e 100644 (file)
@@ -65,7 +65,7 @@
 #include "spandsp/private/v27ter_tx.h"
 
 #if defined(SPANDSP_USE_FIXED_POINT)
-#define FP_SCALE                        FP_Q6_10
+#define FP_SCALE(x)                     FP_Q6_10(x)
 #else
 #define FP_SCALE(x)                     (x)
 #endif
index 464d90b0fefc065c3733ec27e78db67a62b5e254..5052e45d68d44b5ec20f6eecd3935485bdee949c 100644 (file)
@@ -70,7 +70,7 @@
 
 enum
 {
-    V8_WAIT_1S,         /* Start point when sending CI */
+    V8_WAIT_1S = 0,     /* Start point when sending CI */
     V8_AWAIT_ANSAM,     /* Start point when sending initial silence */
     V8_CI_ON,
     V8_CI_OFF,
@@ -539,16 +539,16 @@ static void put_bit(void *user_data, int bit)
                 switch (s->preamble_type)
                 {
                 case V8_SYNC_CI:
-                    tag = "CI: ";
+                    tag = ">CI: ";
                     break;
                 case V8_SYNC_CM_JM:
-                    tag = (s->calling_party)  ?  "JM: "  :  "CM: ";
+                    tag = (s->calling_party)  ?  ">JM: "  :  ">CM: ";
                     break;
                 case V8_SYNC_V92:
-                    tag = "V92: ";
+                    tag = ">V.92: ";
                     break;
                 default:
-                    tag = "??: ";
+                    tag = ">??: ";
                     break;
                 }
                 span_log_buf(&s->logging, SPAN_LOG_FLOW, tag, s->rx_data, s->rx_data_ptr);
@@ -639,20 +639,26 @@ static void v8_put_preamble(v8_state_t *s)
 }
 /*- End of function --------------------------------------------------------*/
 
-static void v8_put_byte(v8_state_t *s, int data)
+static void v8_put_bytes(v8_state_t *s, uint8_t buf[], int len)
 {
     int i;
+    int j;
+    uint8_t byte;
     uint8_t bits[10];
 
     /* Insert start & stop bits */
-    bits[0] = 0;
-    for (i = 1;  i < 9;  i++)
+    for (i = 0;  i < len;  i++)
     {
-        bits[i] = (uint8_t) (data & 1);
-        data >>= 1;
+        bits[0] = 0;
+        byte = buf[i];
+        for (j = 1;  j < 9;  j++)
+        {
+            bits[j] = byte & 1;
+            byte >>= 1;
+        }
+        bits[9] = 1;
+        queue_write(s->tx_queue, bits, 10);
     }
-    bits[9] = 1;
-    queue_write(s->tx_queue, bits, 10);
 }
 /*- End of function --------------------------------------------------------*/
 
@@ -661,12 +667,15 @@ static void send_cm_jm(v8_state_t *s)
     int val;
     unsigned int offered_modulations;
     int bytes;
+    uint8_t buf[10];
+    int ptr;
 
     /* Send a CM, or a JM as appropriate */
     v8_put_preamble(s);
-    v8_put_byte(s, V8_CM_JM_SYNC_OCTET);
+    ptr = 0;
+    buf[ptr++] = V8_CM_JM_SYNC_OCTET;
     /* Data call */
-    v8_put_byte(s, (s->result.call_function << 5) | V8_CALL_FUNCTION_TAG);
+    buf[ptr++] = (s->result.call_function << 5) | V8_CALL_FUNCTION_TAG;
 
     /* Supported modulations */
     offered_modulations = s->result.modulations;
@@ -676,7 +685,9 @@ static void send_cm_jm(v8_state_t *s)
         val |= 0x20;
     if (offered_modulations & V8_MOD_V34)
         val |= 0x40;
-    v8_put_byte(s, val);
+    if (offered_modulations & V8_MOD_V34HDX)
+        val |= 0x80;
+    buf[ptr++] = val;
     if (++bytes < s->modulation_bytes)
     {
         val = 0x10;
@@ -690,7 +701,7 @@ static void send_cm_jm(v8_state_t *s)
             val |= 0x40;
         if (offered_modulations & V8_MOD_V27TER)
             val |= 0x80;
-        v8_put_byte(s, val);
+        buf[ptr++] = val;
     }
     if (++bytes < s->modulation_bytes)
     {
@@ -705,19 +716,21 @@ static void send_cm_jm(v8_state_t *s)
             val |= 0x40;
         if (offered_modulations & V8_MOD_V21)
             val |= 0x80;
-        v8_put_byte(s, val);
+        buf[ptr++] = val;
     }
 
     if (s->parms.protocol)
-        v8_put_byte(s, (s->parms.protocol << 5) | V8_PROTOCOLS_TAG);
+        buf[ptr++] = (s->parms.protocol << 5) | V8_PROTOCOLS_TAG;
     if (s->parms.pstn_access)
-        v8_put_byte(s, (s->parms.pstn_access << 5) | V8_PSTN_ACCESS_TAG);
+        buf[ptr++] = (s->parms.pstn_access << 5) | V8_PSTN_ACCESS_TAG;
     if (s->parms.pcm_modem_availability)
-        v8_put_byte(s, (s->parms.pcm_modem_availability << 5) | V8_PCM_MODEM_AVAILABILITY_TAG);
+        buf[ptr++] = (s->parms.pcm_modem_availability << 5) | V8_PCM_MODEM_AVAILABILITY_TAG;
     if (s->parms.t66 >= 0)
-        v8_put_byte(s, (s->parms.t66 << 5) | V8_T66_TAG);
+        buf[ptr++] = (s->parms.t66 << 5) | V8_T66_TAG;
     /* No NSF */
-    //v8_put_byte(s, (0 << 5) | V8_NSF_TAG);
+    //buf[ptr++] = (0 << 5) | V8_NSF_TAG;
+    span_log_buf(&s->logging, SPAN_LOG_FLOW, (s->calling_party)  ?  "<CM: "  :  "<JM: ", &buf[1], ptr - 1);
+    v8_put_bytes(s, buf, ptr);
 }
 /*- End of function --------------------------------------------------------*/
 
@@ -729,7 +742,15 @@ SPAN_DECLARE_NONSTD(int) v8_tx(v8_state_t *s, int16_t *amp, int max_len)
     len = 0;
     if (s->modem_connect_tone_tx_on)
     {
-        if (s->modem_connect_tone_tx_on > ms_to_samples(75))
+        if (s->modem_connect_tone_tx_on == (ms_to_samples(75) + 2))
+        {
+            if (s->fsk_tx_on)
+            {
+                /* The initial silence is over */
+                s->modem_connect_tone_tx_on = 0;
+            }
+        }
+        else if (s->modem_connect_tone_tx_on == (ms_to_samples(75) + 1))
         {
             /* Send the ANSam tone */
             len = modem_connect_tones_tx(&s->ansam_tx, amp, max_len);
@@ -752,14 +773,19 @@ SPAN_DECLARE_NONSTD(int) v8_tx(v8_state_t *s, int16_t *amp, int max_len)
     }
     if (s->fsk_tx_on  &&  len < max_len)
     {
-        max_len -= len;
-        len = fsk_tx(&s->v21tx, amp + len, max_len);
+        len += fsk_tx(&s->v21tx, &amp[len], max_len - len);
         if (len < max_len)
         {
-            span_log(&s->logging, SPAN_LOG_FLOW, "FSK ends\n");
+            span_log(&s->logging, SPAN_LOG_FLOW, "FSK ends (%d/%d) %d %d\n", len, max_len, s->fsk_tx_on, s->state);
             s->fsk_tx_on = false;
+            //s->state = V8_PARKED;
         }
     }
+    if (s->state != V8_PARKED  &&  len < max_len)
+    {
+        vec_zeroi16(&amp[len], max_len - len);
+        len = max_len;
+    }
     return len;
 }
 /*- End of function --------------------------------------------------------*/
@@ -767,6 +793,7 @@ SPAN_DECLARE_NONSTD(int) v8_tx(v8_state_t *s, int16_t *amp, int max_len)
 static void send_v92(v8_state_t *s)
 {
     int i;
+    uint8_t buf[2];
 
     if (s->result.v92 >= 0)
     {
@@ -774,8 +801,10 @@ static void send_v92(v8_state_t *s)
         for (i = 0;  i < 2;  i++)
         {
             v8_put_preamble(s);
-            v8_put_byte(s, V8_V92_SYNC_OCTET);
-            v8_put_byte(s, s->result.v92);
+            buf[0] = V8_V92_SYNC_OCTET;
+            buf[1] = s->result.v92;
+            span_log_buf(&s->logging, SPAN_LOG_FLOW, "<V.92: ", &buf[1], 1);
+            v8_put_bytes(s, buf, 2);
         }
     }
 }
@@ -784,13 +813,16 @@ static void send_v92(v8_state_t *s)
 static void send_ci(v8_state_t *s)
 {
     int i;
+    uint8_t buf[2];
 
     /* Send 4 CI packets in a burst (the spec says at least 3) */
     for (i = 0;  i < 4;  i++)
     {
         v8_put_preamble(s);
-        v8_put_byte(s, V8_CI_SYNC_OCTET);
-        v8_put_byte(s, (s->result.call_function << 5) | V8_CALL_FUNCTION_TAG);
+        buf[0] = V8_CI_SYNC_OCTET;
+        buf[1] = (s->result.call_function << 5) | V8_CALL_FUNCTION_TAG;
+        span_log_buf(&s->logging, SPAN_LOG_FLOW, "<CI: ", &buf[1], 1);
+        v8_put_bytes(s, buf, 2);
     }
 }
 /*- End of function --------------------------------------------------------*/
@@ -822,9 +854,9 @@ static void handle_modem_connect_tone(v8_state_t *s, int tone)
 
 SPAN_DECLARE_NONSTD(int) v8_rx(v8_state_t *s, const int16_t *amp, int len)
 {
-    int i;
     int residual_samples;
     int tone;
+    uint8_t buf[3];
 
     //span_log(&s->logging, SPAN_LOG_FLOW, "v8_rx state %d\n", s->state);
     residual_samples = 0;
@@ -911,8 +943,9 @@ SPAN_DECLARE_NONSTD(int) v8_rx(v8_state_t *s, const int16_t *amp, int len)
             /* Now JM has been detected, we send CJ and wait for 75 ms
                before finishing the V.8 analysis. */
             fsk_tx_restart(&s->v21tx, &preset_fsk_specs[FSK_V21CH1]);
-            for (i = 0;  i < 3;  i++)
-                v8_put_byte(s, 0);
+            memset(buf, 0, 3);
+            v8_put_bytes(s, buf, 3);
+            span_log_buf(&s->logging, SPAN_LOG_FLOW, "<CJ: ", &buf[1], 2);
             s->state = V8_CJ_ON;
             s->fsk_tx_on = true;
             break;
@@ -1060,6 +1093,7 @@ SPAN_DECLARE(int) v8_restart(v8_state_t *s, bool calling_party, v8_parms_t *parm
         }
         modem_connect_tones_rx_init(&s->ansam_rx, MODEM_CONNECT_TONES_ANS_PR, NULL, NULL);
         fsk_tx_init(&s->v21tx, &preset_fsk_specs[FSK_V21CH1], get_bit, s);
+        s->modem_connect_tone_tx_on = ms_to_samples(75) + 2;
     }
     else
     {
index 7149900a903a979e95afaf08e0798162ed43bd14..47ee06aec363af784db705d6e3552812de3c3880 100644 (file)
@@ -73,10 +73,12 @@ noinst_PROGRAMS =   ademco_contactid_tests \
                     complex_vector_float_tests \
                     complex_vector_int_tests \
                     crc_tests \
+                    data_modems_tests \
                     dc_restore_tests \
                     dds_tests \
                     dtmf_rx_tests \
                     dtmf_tx_tests \
+                    dummy_modems_tests \
                     echo_tests \
                     fax_decode \
                     fax_tests \
@@ -151,6 +153,7 @@ noinst_HEADERS =    echo_monitor.h \
                     modem_monitor.h \
                     pcap_parse.h \
                     pseudo_terminals.h \
+                    socket_harness.h \
                     udptl.h
 
 ademco_contactid_tests_SOURCES = ademco_contactid_tests.c
@@ -198,6 +201,9 @@ complex_vector_int_tests_LDADD = $(LIBDIR) -lspandsp
 crc_tests_SOURCES = crc_tests.c
 crc_tests_LDADD = $(LIBDIR) -lspandsp
 
+data_modems_tests_SOURCES = data_modems_tests.c media_monitor.cpp
+data_modems_tests_LDADD = -L$(top_builddir)/spandsp-sim -lspandsp-sim $(LIBDIR) -lspandsp
+
 dc_restore_tests_SOURCES = dc_restore_tests.c
 dc_restore_tests_LDADD = $(LIBDIR) -lspandsp
 
@@ -210,6 +216,9 @@ dtmf_rx_tests_LDADD = -L$(top_builddir)/spandsp-sim -lspandsp-sim $(LIBDIR) -lsp
 dtmf_tx_tests_SOURCES = dtmf_tx_tests.c
 dtmf_tx_tests_LDADD = -L$(top_builddir)/spandsp-sim -lspandsp-sim $(LIBDIR) -lspandsp
 
+dummy_modems_tests_SOURCES = dummy_modems_tests.c media_monitor.cpp socket_harness.c pseudo_terminals.c
+dummy_modems_tests_LDADD = -L$(top_builddir)/spandsp-sim -lspandsp-sim $(LIBDIR) -lspandsp -lutil
+
 echo_tests_SOURCES = echo_tests.c echo_monitor.cpp
 echo_tests_LDADD = -L$(top_builddir)/spandsp-sim -lspandsp-sim $(LIBDIR) -lspandsp
 
diff --git a/libs/spandsp/tests/data_modems_tests.c b/libs/spandsp/tests/data_modems_tests.c
new file mode 100644 (file)
index 0000000..86bd085
--- /dev/null
@@ -0,0 +1,312 @@
+/*
+ * SpanDSP - a series of DSP components for telephony
+ *
+ * data_modems_tests.c - Tests for data_modems.
+ *
+ * Written by Steve Underwood <steveu@coppice.org>
+ *
+ * Copyright (C) 2011 Steve Underwood
+ *
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2, as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * 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.
+ */
+
+/*! \file */
+
+/*! \page data_modems_tests_page Data modems tests
+\section data_modems_tests_page_sec_1 What does it do?
+*/
+
+#if defined(HAVE_CONFIG_H)
+#include "config.h"
+#endif
+
+#if defined(HAVE_FL_FL_H)  &&  defined(HAVE_FL_FL_CARTESIAN_H)  &&  defined(HAVE_FL_FL_AUDIO_METER_H)
+#define ENABLE_GUI
+#endif
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <string.h>
+#include <assert.h>
+#include <sndfile.h>
+
+#include "spandsp.h"
+#include "spandsp-sim.h"
+
+#if defined(ENABLE_GUI)
+#include "media_monitor.h"
+#endif
+
+#define INPUT_FILE_NAME         "../test-data/itu/fax/itu1.tif"
+#define OUTPUT_FILE_NAME        "t31.tif"
+#define OUTPUT_WAVE_FILE_NAME   "data_modems.wav"
+
+#define SAMPLES_PER_CHUNK 160
+
+struct command_response_s
+{
+    const char *command;
+    int len_command;
+    const char *response;
+    int len_response;
+};
+
+char *decode_test_file = NULL;
+int countdown = 0;
+int command_response_test_step = -1;
+char response_buf[1000];
+int response_buf_ptr = 0;
+bool answered = false;
+bool done = false;
+bool sequence_terminated = false;
+
+data_modems_state_t *data_modems_state[2];
+
+static void reporter(void *user_data, int reason, bert_results_t *results)
+{
+    int channel;
+
+    channel = (int) (intptr_t) user_data;
+    switch (reason)
+    {
+    case BERT_REPORT_SYNCED:
+        fprintf(stderr, "%d: BERT report synced\n", channel);
+        break;
+    case BERT_REPORT_UNSYNCED:
+        fprintf(stderr, "%d: BERT report unsync'ed\n", channel);
+        break;
+    case BERT_REPORT_REGULAR:
+        fprintf(stderr, "%d: BERT report regular - %d bits, %d bad bits, %d resyncs\n", channel, results->total_bits, results->bad_bits, results->resyncs);
+        break;
+    case BERT_REPORT_GT_10_2:
+        fprintf(stderr, "%d: BERT report > 1 in 10^2\n", channel);
+        break;
+    case BERT_REPORT_LT_10_2:
+        fprintf(stderr, "%d: BERT report < 1 in 10^2\n", channel);
+        break;
+    case BERT_REPORT_LT_10_3:
+        fprintf(stderr, "%d: BERT report < 1 in 10^3\n", channel);
+        break;
+    case BERT_REPORT_LT_10_4:
+        fprintf(stderr, "%d: BERT report < 1 in 10^4\n", channel);
+        break;
+    case BERT_REPORT_LT_10_5:
+        fprintf(stderr, "%d: BERT report < 1 in 10^5\n", channel);
+        break;
+    case BERT_REPORT_LT_10_6:
+        fprintf(stderr, "%d: BERT report < 1 in 10^6\n", channel);
+        break;
+    case BERT_REPORT_LT_10_7:
+        fprintf(stderr, "%d: BERT report < 1 in 10^7\n", channel);
+        break;
+    default:
+        fprintf(stderr, "%d: BERT report reason %d\n", channel, reason);
+        break;
+    }
+}
+/*- End of function --------------------------------------------------------*/
+
+static int get_msg(void *user_data, uint8_t msg[], int len)
+{
+    return 0;
+}
+/*- End of function --------------------------------------------------------*/
+
+static void put_msg(void *user_data, const uint8_t msg[], int len)
+{
+    if (len < 0)
+        printf("Status %s\n", signal_status_to_str(len));
+}
+/*- End of function --------------------------------------------------------*/
+
+static int modem_tests(int use_gui, int log_audio, int test_sending)
+{
+    int mdm_len;
+    int16_t mdm_amp[SAMPLES_PER_CHUNK];
+    //int use_tep;
+    //logging_state_t *logging;
+    int outframes;
+    int16_t silence[SAMPLES_PER_CHUNK];
+    int16_t out_amp[2*SAMPLES_PER_CHUNK];
+    SNDFILE *wave_handle;
+    SNDFILE *in_handle;
+    int i;
+    int k;
+    int calling_party;
+    logging_state_t *logging;
+    bert_state_t *bert[2];
+
+    /* Test a pair of modems against each other */
+
+    /* Set up the test environment */
+    //use_tep = false;
+
+    wave_handle = NULL;
+    if (log_audio)
+    {
+        if ((wave_handle = sf_open_telephony_write(OUTPUT_WAVE_FILE_NAME, 2)) == NULL)
+        {
+            fprintf(stderr, "    Cannot create audio file '%s'\n", OUTPUT_WAVE_FILE_NAME);
+            exit(2);
+        }
+    }
+
+    in_handle = NULL;
+    if (decode_test_file)
+    {
+        if ((in_handle = sf_open_telephony_read(decode_test_file, 1)) == NULL)
+        {
+            fprintf(stderr, "    Cannot create audio file '%s'\n", decode_test_file);
+            exit(2);
+        }
+    }
+
+    memset(silence, 0, sizeof(silence));
+    memset(mdm_amp, 0, sizeof(mdm_amp));
+    mdm_len = 0;
+
+    /* Now set up and run the modems */
+    calling_party = true;
+    for (i = 0;  i < 2;  i++)
+    {
+        bert[i] = bert_init(NULL, 1000000, BERT_PATTERN_ITU_O152_11, 2400, 20);
+        bert_set_report(bert[i], 100000, reporter, (void *) (intptr_t) i);
+        if ((data_modems_state[i] = data_modems_init(NULL,
+                                                     calling_party,
+                                                     put_msg,
+                                                     get_msg,
+                                                     NULL)) == NULL)
+        {
+            fprintf(stderr, "    Cannot start the data modem\n");
+            exit(2);
+        }
+        logging = data_modems_get_logging_state(data_modems_state[i]);
+        span_log_set_level(logging, SPAN_LOG_DEBUG | SPAN_LOG_SHOW_TAG | SPAN_LOG_SHOW_SAMPLE_TIME);
+        span_log_set_tag(logging, "Modem");
+        calling_party = false;
+    }
+
+#if defined(ENABLE_GUI)
+    if (use_gui)
+        start_media_monitor();
+#endif
+    while (!done)
+    {
+        for (i = 0;  i < 2;  i++)
+        {
+            /* 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. */
+            mdm_len = data_modems_tx(data_modems_state[i], mdm_amp, SAMPLES_PER_CHUNK);
+            if (mdm_len < SAMPLES_PER_CHUNK)
+            {
+                vec_zeroi16(mdm_amp + mdm_len, SAMPLES_PER_CHUNK - mdm_len);
+                mdm_len = SAMPLES_PER_CHUNK;
+            }
+            if (log_audio)
+            {
+                for (k = 0;  k < mdm_len;  k++)
+                    out_amp[2*k + i] = mdm_amp[k];
+            }
+            if (data_modems_rx(data_modems_state[i ^ 1], mdm_amp, mdm_len))
+                break;
+        }
+
+        if (log_audio)
+        {
+            outframes = sf_writef_short(wave_handle, out_amp, SAMPLES_PER_CHUNK);
+            if (outframes != SAMPLES_PER_CHUNK)
+                break;
+        }
+    }
+
+    if (decode_test_file)
+    {
+        if (sf_close_telephony(in_handle))
+        {
+            fprintf(stderr, "    Cannot close audio file '%s'\n", decode_test_file);
+            exit(2);
+        }
+    }
+    if (log_audio)
+    {
+        if (sf_close_telephony(wave_handle))
+        {
+            fprintf(stderr, "    Cannot close audio file '%s'\n", OUTPUT_WAVE_FILE_NAME);
+            exit(2);
+        }
+    }
+
+    if (!done  ||  !sequence_terminated)
+    {
+        printf("Tests failed\n");
+        return 2;
+    }
+
+    return 0;
+}
+/*- End of function --------------------------------------------------------*/
+
+int main(int argc, char *argv[])
+{
+    int log_audio;
+    int test_sending;
+    int use_gui;
+    int opt;
+
+    decode_test_file = NULL;
+    log_audio = false;
+    test_sending = false;
+    use_gui = false;
+    while ((opt = getopt(argc, argv, "d:glrs")) != -1)
+    {
+        switch (opt)
+        {
+        case 'd':
+            decode_test_file = optarg;
+            break;
+        case 'g':
+#if defined(ENABLE_GUI)
+            use_gui = true;
+#else
+            fprintf(stderr, "Graphical monitoring not available\n");
+            exit(2);
+#endif
+            break;
+        case 'l':
+            log_audio = true;
+            break;
+        case 'r':
+            test_sending = false;
+            break;
+        case 's':
+            test_sending = true;
+            break;
+        default:
+            //usage();
+            exit(2);
+            break;
+        }
+    }
+
+    modem_tests(use_gui, log_audio, test_sending);
+    printf("Tests passed\n");
+    return 0;
+}
+/*- End of function --------------------------------------------------------*/
+/*- End of file ------------------------------------------------------------*/
diff --git a/libs/spandsp/tests/dummy_modems_tests.c b/libs/spandsp/tests/dummy_modems_tests.c
new file mode 100644 (file)
index 0000000..c836f96
--- /dev/null
@@ -0,0 +1,253 @@
+/*
+ * SpanDSP - a series of DSP components for telephony
+ *
+ * dummy_modems_tests.c - Tests for data_modems connected together by sockets.
+ *
+ * Written by Steve Underwood <steveu@coppice.org>
+ *
+ * Copyright (C) 2011 Steve Underwood
+ *
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2, as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * 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.
+ */
+
+/*! \file */
+
+/*! \page dummy_modems_tests_page Dummy data modems tests
+\section dummy_modems_tests_page_sec_1 What does it do?
+*/
+
+#if defined(HAVE_CONFIG_H)
+#include "config.h"
+#endif
+
+#if defined(HAVE_FL_FL_H)  &&  defined(HAVE_FL_FL_CARTESIAN_H)  &&  defined(HAVE_FL_FL_AUDIO_METER_H)
+#define ENABLE_GUI
+#endif
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <string.h>
+#include <assert.h>
+#include <termios.h>
+#include <sndfile.h>
+
+//#define SPANDSP_EXPOSE_INTERNAL_STRUCTURES
+
+#include "spandsp.h"
+#include "spandsp-sim.h"
+
+#include "pseudo_terminals.h"
+#include "socket_harness.h"
+
+#if defined(ENABLE_GUI)
+#include "media_monitor.h"
+#endif
+
+#define OUTPUT_WAVE_FILE_NAME   "dummy_modems.wav"
+
+#define SAMPLES_PER_CHUNK 160
+
+SNDFILE *wave_handle = NULL;
+int16_t wave_buffer[4096];
+
+data_modems_state_t *data_modem_state;
+
+static int get_msg(void *user_data, uint8_t msg[], int len)
+{
+    return 0;
+}
+/*- End of function --------------------------------------------------------*/
+
+static void put_msg(void *user_data, const uint8_t msg[], int len)
+{
+    if (len < 0)
+        printf("Status %s\n", signal_status_to_str(len));
+    else
+        printf("Put %d '%s'\n", len, msg);
+}
+/*- End of function --------------------------------------------------------*/
+
+static void terminal_callback(void *user_data, const uint8_t msg[], int len)
+{
+    printf("terminal callback %d\n", len);
+}
+/*- End of function --------------------------------------------------------*/
+
+static int termios_callback(void *user_data, struct termios *termios)
+{
+    printf("termios callback\n");
+    return 0;
+}
+/*- End of function --------------------------------------------------------*/
+
+static void hangup_callback(void *user_data, int status)
+{
+}
+/*- End of function --------------------------------------------------------*/
+
+static int terminal_free_space_callback(void *user_data)
+{
+    return 42;
+}
+/*- End of function --------------------------------------------------------*/
+
+static int rx_callback(void *user_data, const int16_t amp[], int samples)
+{
+    int i;
+    int out_samples;
+
+    out_samples = data_modems_rx((data_modems_state_t *) user_data, amp, samples);
+    if (wave_handle)
+    {
+        for (i = 0;  i < samples;  i++)
+            wave_buffer[2*i] = amp[i];
+    }
+    return out_samples;
+}
+/*- End of function --------------------------------------------------------*/
+
+static int rx_fillin_callback(void *user_data, int samples)
+{
+    return data_modems_rx_fillin((data_modems_state_t *) user_data, samples);
+}
+/*- End of function --------------------------------------------------------*/
+
+static int tx_callback(void *user_data, int16_t amp[], int samples)
+{
+    int i;
+    int out_samples;
+
+    out_samples = data_modems_tx((data_modems_state_t *) user_data, amp, samples);
+    if (wave_handle)
+    {
+        if (out_samples < samples)
+            memset(&amp[out_samples], 0, (samples - out_samples)*2);
+        for (i = 0;  i < samples;  i++)
+            wave_buffer[2*i + 1] = amp[i];
+        sf_writef_short(wave_handle, wave_buffer, samples);
+    }
+    return samples;
+}
+/*- End of function --------------------------------------------------------*/
+
+static int modem_tests(int use_gui, int log_audio, bool calling_party)
+{
+    logging_state_t *logging;
+    socket_harness_state_t *s;
+
+    /* Now set up and run the modems */
+    if ((data_modem_state = data_modems_init(NULL,
+                                             calling_party,
+                                             put_msg,
+                                             get_msg,
+                                             NULL)) == NULL)
+    {
+        fprintf(stderr, "    Cannot start the data modem\n");
+        exit(2);
+    }
+    logging = data_modems_get_logging_state(data_modem_state);
+    span_log_set_level(logging, SPAN_LOG_DEBUG | SPAN_LOG_SHOW_TAG | SPAN_LOG_SHOW_DATE);
+    span_log_set_tag(logging, "Modem");
+
+    if ((s = socket_harness_init(NULL,
+                                 "/tmp/modemsocket",
+                                 "modemA",
+                                 calling_party,
+                                 terminal_callback,
+                                 termios_callback,
+                                 hangup_callback,
+                                 terminal_free_space_callback,
+                                 rx_callback,
+                                 rx_fillin_callback,
+                                 tx_callback,
+                                 data_modem_state)) == NULL)
+    {
+        fprintf(stderr, "    Cannot start the socket harness\n");
+        exit(2);
+    }
+
+    wave_handle = NULL;
+    if (log_audio)
+    {
+        if ((wave_handle = sf_open_telephony_write(OUTPUT_WAVE_FILE_NAME, 2)) == NULL)
+        {
+            fprintf(stderr, "    Cannot create audio file '%s'\n", OUTPUT_WAVE_FILE_NAME);
+            exit(2);
+        }
+    }
+
+    socket_harness_run(s);
+
+    if (log_audio)
+    {
+        if (sf_close_telephony(wave_handle))
+        {
+            fprintf(stderr, "    Cannot close audio file '%s'\n", OUTPUT_WAVE_FILE_NAME);
+            exit(2);
+        }
+    }
+
+    return 0;
+}
+/*- End of function --------------------------------------------------------*/
+
+int main(int argc, char *argv[])
+{
+    int log_audio;
+    int use_gui;
+    int opt;
+    bool calling_party;
+
+    log_audio = false;
+    calling_party = false;
+    use_gui = false;
+    while ((opt = getopt(argc, argv, "acgl")) != -1)
+    {
+        switch (opt)
+        {
+        case 'a':
+            calling_party = false;
+            break;
+        case 'c':
+            calling_party = true;
+            break;
+        case 'g':
+#if defined(ENABLE_GUI)
+            use_gui = true;
+#else
+            fprintf(stderr, "Graphical monitoring not available\n");
+            exit(2);
+#endif
+            break;
+        case 'l':
+            log_audio = true;
+            break;
+        default:
+            //usage();
+            exit(2);
+            break;
+        }
+    }
+
+    if (modem_tests(use_gui, log_audio, calling_party))
+        exit(2);
+    printf("Tests passed\n");
+    return 0;
+}
+/*- End of function --------------------------------------------------------*/
+/*- End of file ------------------------------------------------------------*/
index 955d4b7d256f443222258bcfd5f65a1f8a62d869..96105edcaeef3830c97baff797c6e954b7ec1c89 100644 (file)
 \section fax_tests_page_sec_1 What does it do?
 These tests exercise the following FAX to FAX paths:
 
-         +--Modems-+-----------TDM/RTP-----------+-Modems--+
-         |          \                           /          |
-         |           \                         /           |
-T.30 <---+      T.38 gateway            T.38 gateway       +--->T.30
-         |             \                     /             |
-         |              \                   /              |
-         +---T.38---+----+----UDPTL/RTP----+----+---T.38---+
-                     \                         /
-                      +----------TCP----------+
+TSB85 <-----------+                                     +-----------> TSB85
+                   \                                   /
+ T.31 <-----------+ \                                 / +-----------> T.31
+                   \ \                               / /
+          +--Modems-+-+-----------TDM/RTP-----------+-+-Modems--+
+          |            \                           /            |
+          |             \                         /             |
+ T.30 <---+        T.38 gateway            T.38 gateway         +---> T.30
+          |               \                     /               |
+          |                \                   /                |
+          +---T.38---+-+----+----UDPTL/RTP----+----+ +---T.38---+
+                    / / \                         / \ \
+ T.31 <------------/ /   +----------TCP----------+   \ +------------> T.31
+                    /                                 \
+TSB85 <------------+                                   +------------> TSB85
 
 T.30<->Modems<-------------------------TDM/RTP------------------------->Modems<->T.30
 T.30<->Modems<-TDM/RTP->T.38 gateway<-UDPTL/RTP->T.38 gateway<-TDM/RTP->Modems<->T.30
@@ -45,6 +51,7 @@ T.30<->Modems<-TDM/RTP->T.38 gateway<-UDPTL/RTP-------------------------->T.38<-
 T.30<->T.38<--------------------------UDPTL/RTP->T.38 gateway<-TDM/RTP->Modems<->T.30
 T.30<->T.38<--------------------------UDPTL/RTP-------------------------->T.38<->T.30
 
+The T.31 and TSB85 parts are incomplete right now.
 */
 
 #if defined(HAVE_CONFIG_H)
@@ -520,6 +527,7 @@ int main(int argc, char *argv[])
     char *page_header_info;
     char *page_header_tz;
     const char *tag;
+    const char *xml_file_name;
     char buf[132 + 1];
 #if defined(ENABLE_GUI)
     int use_gui;
@@ -557,7 +565,8 @@ int main(int argc, char *argv[])
     colour_enabled = false;
     t37_like_output = false;
     t38_transport = T38_TRANSPORT_UDPTL;
-    while ((opt = getopt(argc, argv, "7b:c:Cd:D:efFgH:i:Ilm:M:n:p:s:S:tT:u:v:z:")) != -1)
+    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)
     {
         switch (opt)
         {
@@ -682,6 +691,9 @@ int main(int argc, char *argv[])
         case 'v':
             t38_version = atoi(optarg);
             break;
+        case 'x':
+            xml_file_name = optarg;
+            break;
         case 'z':
             page_header_tz = optarg;
             break;
@@ -736,8 +748,9 @@ int main(int argc, char *argv[])
         tag = (i == 0)  ?  "A"  :  "B";
 
         memset(&expected_rx_info[i], 0, sizeof(expected_rx_info[i]));
-        if (mode[i] == T38_TERMINAL_FAX)
+        switch (mode[i])
         {
+        case T38_TERMINAL_FAX:
             if ((t38_state[i] = t38_terminal_init(NULL, (i == 0), tx_packet_handler, (void *) (intptr_t) i)) == NULL)
             {
                 fprintf(stderr, "Cannot start the T.38 terminal instance\n");
@@ -757,9 +770,9 @@ int main(int argc, char *argv[])
             logging = t30_get_logging_state(t30_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);
-        }
-        else
-        {
+            break;
+        case AUDIO_FAX:
+        case T38_GATEWAY_FAX:
             if ((fax_state[i] = fax_init(NULL, (i == 0))) == NULL)
             {
                 fprintf(stderr, "Cannot start FAX instance\n");
@@ -783,7 +796,7 @@ int main(int argc, char *argv[])
             {
                 if ((t38_gateway_state[i] = t38_gateway_init(NULL, tx_packet_handler, (void *) (intptr_t) i)) == NULL)
                 {
-                    fprintf(stderr, "Cannot start the T.38 gateway instancel\n");
+                    fprintf(stderr, "Cannot start the T.38 gateway instance\n");
                     exit(2);
                 }
                 t38_core_state[i] = t38_gateway_get_t38_core_state(t38_gateway_state[i]);
@@ -820,6 +833,17 @@ int main(int argc, char *argv[])
                 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:
+            break;
         }
         set_t30_callbacks(t30_state[i], i);
     }
diff --git a/libs/spandsp/tests/socket_harness.c b/libs/spandsp/tests/socket_harness.c
new file mode 100644 (file)
index 0000000..71b22b9
--- /dev/null
@@ -0,0 +1,346 @@
+/*
+ * SpanDSP - a series of DSP components for telephony
+ *
+ * socket_harness.c
+ *
+ * Written by Steve Underwood <steveu@coppice.org>
+ *
+ * Copyright (C) 2007 Steve Underwood
+ *
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2, as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * 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.
+ */
+
+
+/*! \page bitstream_tests_page Bitstream tests
+\section bitstream_tests_page_sec_1 What does it do?
+
+\section bitstream_tests_page_sec_2 How is it used?
+*/
+
+#if defined(HAVE_CONFIG_H)
+#include "config.h"
+#endif
+
+#define _GNU_SOURCE
+
+#include <inttypes.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <fcntl.h>
+#include <string.h>
+#include <assert.h>
+#include <unistd.h>
+#include <signal.h>
+#include <termios.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <sys/ioctl.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <netinet/in.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+
+#define SPANDSP_EXPOSE_INTERNAL_STRUCTURES
+
+#include "spandsp.h"
+
+#include "pseudo_terminals.h"
+#include "socket_harness.h"
+
+//#define SIMULATE_RING 1
+
+#define CLOSE_COUNT_MAX 100
+
+/* static data */
+static int16_t inbuf[4096];
+static int16_t outbuf[4096];
+
+static volatile sig_atomic_t keep_running = true;
+
+static void log_signal(int signum)
+{
+    fprintf(stderr, "Signal %d: mark termination.\n", signum);
+    keep_running = false;
+    exit(2);
+}
+/*- End of function --------------------------------------------------------*/
+
+int socket_harness_run(socket_harness_state_t *s)
+{
+    struct timeval tmo;
+    fd_set rset;
+    fd_set eset;
+    struct termios termios;
+    int max_fd;
+    int count;
+    int samples;
+    int tx_samples;
+    int ret;
+
+    while (keep_running)
+    {
+        //if (s->modem->event)
+        //    modem_event(s->modem);
+#ifdef SIMULATE_RING
+        tmo.tv_sec = 0;
+        tmo.tv_usec= 1000000/RING_HZ;
+#else
+        tmo.tv_sec = 1;
+        tmo.tv_usec= 0;
+#endif
+        max_fd = 0;
+        FD_ZERO(&rset);
+        FD_ZERO(&eset);
+        FD_SET(s->audio_fd, &rset);
+        FD_SET(s->audio_fd, &eset);
+        FD_SET(s->pty_fd, &rset);
+        FD_SET(s->pty_fd, &eset);
+        if (s->audio_fd > max_fd)
+            max_fd = s->audio_fd;
+        if (s->pty_fd > max_fd)
+            max_fd = s->pty_fd;
+        if (s->pty_closed  &&  s->close_count)
+        {
+            if (!s->started  ||  s->close_count++ > CLOSE_COUNT_MAX)
+                s->close_count = 0;
+        }
+        else if (s->terminal_free_space_callback(s->user_data))
+        {
+            FD_SET(s->pty_fd, &rset);
+            if (s->pty_fd > max_fd)
+                max_fd = s->pty_fd;
+        }
+        if ((ret = select(max_fd + 1, &rset, NULL, &eset, &tmo)) < 0)
+        {
+            if (errno == EINTR)
+                continue;
+            fprintf(stderr, "Error: select: %s\n", strerror(errno));
+            return ret;
+        }
+
+        if (ret == 0)
+        {
+            /* Timeout */
+#ifdef SIMULATE_RING
+            if (!modem->modem->started)
+            {
+                rcount++;
+                if (rcount <= RING_ON)
+                    modem_ring(modem->modem);
+                else if (rcount > RING_OFF)
+                    rcount = 0;
+            }
+#endif
+            continue;
+        }
+
+        if (FD_ISSET(s->audio_fd, &rset))
+        {
+            if ((count = read(s->audio_fd, inbuf, sizeof(inbuf)/2)) < 0)
+            {
+                if (errno != EAGAIN)
+                {
+                    fprintf(stderr, "Error: audio read: %s\n", strerror(errno));
+                    return -1;
+                }
+                count = 0;
+            }
+            if (count == 0)
+            {
+                fprintf(stderr, "Audio socket closed\n");
+                return 0;
+            }
+            samples = count/2;
+            usleep(125*samples);
+
+            s->rx_callback(s->user_data, inbuf, samples);
+            tx_samples = s->tx_callback(s->user_data, outbuf, samples);
+            if (tx_samples < samples)
+                memset(&outbuf[tx_samples], 0, (samples - tx_samples)*2);
+
+            if ((count = write(s->audio_fd, outbuf, samples*2)) < 0)
+            {
+                if (errno != EAGAIN)
+                {
+                    fprintf(stderr, "Error: audio write: %s\n", strerror(errno));
+                    return -1;
+                }
+                /* TODO: */
+            }
+            if (count != samples*2)
+                fprintf(stderr, "audio write = %d\n", count);
+        }
+
+        if (FD_ISSET(s->pty_fd, &rset))
+        {
+            /* Check termios */
+            tcgetattr(s->pty_fd, &termios);
+            if (memcmp(&termios, &s->termios, sizeof(termios)))
+                s->termios_callback(s->user_data, &termios);
+            /* Read data */
+            if ((count = s->terminal_free_space_callback(s->user_data)))
+            {
+                if (count > sizeof(inbuf))
+                    count = sizeof(inbuf);
+                if ((count = read(s->pty_fd, inbuf, count)) < 0)
+                {
+                    if (errno == EAGAIN)
+                    {
+                        fprintf(stderr, "pty read, errno = EAGAIN\n");
+                    }
+                    else
+                    {
+                        if (errno == EIO)
+                        {
+                            if (!s->pty_closed)
+                            {
+                                fprintf(stderr, "pty closed.\n");
+                                s->pty_closed = 1;
+                                if ((termios.c_cflag & HUPCL))
+                                    s->hangup_callback(s->user_data, 0);
+                            }
+                            s->close_count = 1;
+                        }
+                        else
+                        {
+                            fprintf(stderr, "Error: pty read: %s\n", strerror(errno));
+                            return -1;
+                        }
+                    }
+                }
+                else
+                {
+                    if (count == 0)
+                        fprintf(stderr, "pty read = 0\n");
+                    s->pty_closed = false;
+                    s->terminal_callback(s->user_data, (uint8_t *) inbuf, count);
+                }
+            }
+        }
+    }
+
+    return 0;
+}
+/*- End of function --------------------------------------------------------*/
+
+socket_harness_state_t *socket_harness_init(socket_harness_state_t *s,
+                                            const char *socket_name,
+                                            const char *tag,
+                                            int caller,
+                                            put_msg_func_t terminal_callback,
+                                            termio_update_func_t termios_callback,
+                                            modem_status_func_t hangup_callback,
+                                            put_msg_free_space_func_t terminal_free_space_callback,
+                                            span_rx_handler_t rx_callback,
+                                            span_rx_fillin_handler_t rx_fillin_callback,
+                                            span_tx_handler_t tx_callback,
+                                            void *user_data)
+{
+    int sockfd;
+    int listensockfd;
+    struct sockaddr_un serv_addr;
+    struct sockaddr_un cli_addr;
+    socklen_t servlen;
+    socklen_t clilen;
+
+    if ((sockfd = socket(AF_UNIX, SOCK_STREAM, 0)) < 0)
+    {
+        fprintf(stderr, "Socket failed - errno = %d\n", errno);
+        return NULL;
+    }
+
+    if (s == NULL)
+    {
+        if ((s = (socket_harness_state_t *) malloc(sizeof(*s))) == NULL)
+            return NULL;
+    }
+    memset(s, 0, sizeof(*s));
+
+    signal(SIGINT, log_signal);
+    signal(SIGTERM, log_signal);
+
+    s->terminal_callback = terminal_callback;
+    s->termios_callback = termios_callback;
+    s->hangup_callback = hangup_callback;
+    s->terminal_free_space_callback = terminal_free_space_callback;
+
+    s->rx_callback = rx_callback;
+    s->rx_fillin_callback = rx_fillin_callback;
+    s->tx_callback = tx_callback;
+
+    s->user_data = user_data;
+
+    memset((char *) &serv_addr, 0, sizeof(serv_addr));
+    serv_addr.sun_family = AF_UNIX;
+    /* This is a generic Unix domain socket. */
+    strcpy(serv_addr.sun_path, socket_name);
+    printf("Creating socket '%s'\n", serv_addr.sun_path);
+    servlen = strlen(serv_addr.sun_path) + sizeof(serv_addr.sun_family) + 1;
+    if (caller)
+    {
+        fprintf(stderr, "Connecting to '%s'\n", serv_addr.sun_path);
+        if (connect(sockfd, (struct sockaddr *) &serv_addr, servlen) < 0)
+        {
+            fprintf(stderr, "Connect failed - errno = %d\n", errno);
+            exit(2);
+        }
+        fprintf(stderr, "Connected to '%s'\n", serv_addr.sun_path);
+    }
+    else
+    {
+        fprintf(stderr, "Listening to '%s'\n", serv_addr.sun_path);
+        listensockfd = sockfd;
+        /* The file may or may not exist. Just try to delete it anyway. */
+        unlink(serv_addr.sun_path);
+        if (bind(listensockfd, (struct sockaddr *) &serv_addr, servlen) < 0)
+        {
+            fprintf(stderr, "Bind failed - errno = %d\n", errno);
+            exit(2);
+        }
+        listen(listensockfd, 5);
+        clilen = sizeof(cli_addr);
+        if ((sockfd = accept(listensockfd, (struct sockaddr *) &cli_addr, &clilen)) < 0)
+        {
+            fprintf(stderr, "Accept failed - errno = %d", errno);
+            exit(2);
+        }
+        fprintf(stderr, "Accepted on '%s'\n", serv_addr.sun_path);
+    }
+    if (pseudo_terminal_create(&s->modem))
+    {
+        fprintf(stderr, "Failed to create pseudo TTY\n");
+        exit(2);
+    }
+    s->audio_fd = sockfd;
+    s->pty_fd = s->modem.master;
+    return s;
+}
+/*- End of function --------------------------------------------------------*/
+
+int socket_harness_release(socket_harness_state_t *s)
+{
+    return 0;
+}
+/*- End of function --------------------------------------------------------*/
+
+int socket_harness_free(socket_harness_state_t *s)
+{
+    free(s);
+    return 0;
+}
+/*- End of function --------------------------------------------------------*/
+/*- End of file ------------------------------------------------------------*/
diff --git a/libs/spandsp/tests/socket_harness.h b/libs/spandsp/tests/socket_harness.h
new file mode 100644 (file)
index 0000000..9b05d5c
--- /dev/null
@@ -0,0 +1,73 @@
+/*
+ * SpanDSP - a series of DSP components for telephony
+ *
+ * socket_harness.h
+ *
+ * Written by Steve Underwood <steveu@coppice.org>
+ *
+ * Copyright (C) 2012 Steve Underwood
+ *
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2, as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * 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.
+ */
+
+typedef int (*termio_update_func_t)(void *user_data, struct termios *termios);
+
+typedef int (*put_msg_free_space_func_t)(void *user_data);
+
+typedef struct socket_harness_state_s
+{
+    void *user_data;
+
+    put_msg_func_t terminal_callback;
+    termio_update_func_t termios_callback;
+    modem_status_func_t hangup_callback;
+    put_msg_free_space_func_t terminal_free_space_callback;
+
+    span_rx_handler_t rx_callback;
+    span_rx_fillin_handler_t rx_fillin_callback;
+    span_tx_handler_t tx_callback;
+
+    int audio_fd;
+    int pty_fd;
+    logging_state_t logging;
+    struct termios termios;
+
+    unsigned int delay;
+    unsigned int started;
+    unsigned pty_closed;
+    unsigned close_count;
+    
+    modem_t modem;
+} socket_harness_state_t;
+
+int socket_harness_run(socket_harness_state_t *s);
+
+socket_harness_state_t *socket_harness_init(socket_harness_state_t *s,
+                                            const char *socket_name,
+                                            const char *tag,
+                                            int caller,
+                                            put_msg_func_t terminal_callback,
+                                            termio_update_func_t termios_callback,
+                                            modem_status_func_t hangup_callback,
+                                            put_msg_free_space_func_t terminal_free_space_callback,
+                                            span_rx_handler_t rx_callback,
+                                            span_rx_fillin_handler_t rx_fillin_callback,
+                                            span_tx_handler_t tx_callback,
+                                            void *user_data);
+
+int socket_harness_release(socket_harness_state_t *s);
+
+int socket_harness_free(socket_harness_state_t *s);
index 482334c79e74498db8b609ade45e8f4dc2ec4954..cba7349dea23e9012b75eaf430cac78d78dd96a7 100755 (executable)
@@ -53,7 +53,7 @@ else
     cd gsm0610
 fi
 
-if [ $1x =  --no-exe-runx ]
+if [ $1x == --no-exe-runx ]
 then
     # Run the .exe files, which should be here
     ./FR_A.EXE
@@ -77,7 +77,7 @@ rm -rf READ_FRA.TXT
 rm -rf ACTION
 rm -rf unpacked
 
-if [ $1x =  --no-exex ]
+if [ $1x == --no-exex ]
 then
     # We need to prepare the .exe files to be run separately
     rm -rf *.INP
index e41200482bf56b3888ce190513055f90657db0ea..bcdb01e8cb4139c68840e9d58516fd83a4db8e07 100644 (file)
@@ -1,5 +1,4 @@
-:
-
+#!/bin/sh
 #
 # Install the things which need adding to a fresh Fedora or Centos install to make it ready to build
 # spandsp and its test suite
@@ -19,7 +18,7 @@ yum install fftw-devel \
             sox \
             gcc-c++ \
             libtool \
-            autconf \
+            autoconf \
             automake \
             m4 \
             netpbm \