]> git.ipfire.org Git - thirdparty/freeswitch.git/commitdiff
Chnaged T.30 x-rex, y-res, width vetting to be more rigorous.
authorSteve Underwood <steveu@coppice.org>
Sat, 9 Mar 2013 14:19:47 +0000 (22:19 +0800)
committerSteve Underwood <steveu@coppice.org>
Sat, 9 Mar 2013 14:19:47 +0000 (22:19 +0800)
Various little tweaks to spandsp

17 files changed:
libs/spandsp/src/ademco_contactid.c
libs/spandsp/src/adsi.c
libs/spandsp/src/async.c
libs/spandsp/src/dtmf.c
libs/spandsp/src/fsk.c
libs/spandsp/src/spandsp/async.h
libs/spandsp/src/spandsp/dtmf.h
libs/spandsp/src/spandsp/private/async.h
libs/spandsp/src/spandsp/private/dtmf.h
libs/spandsp/src/spandsp/private/t38_gateway.h
libs/spandsp/src/spandsp/private/v22bis.h
libs/spandsp/src/spandsp/saturated.h
libs/spandsp/src/spandsp/v18.h
libs/spandsp/src/spandsp/v42.h
libs/spandsp/src/t30.c
libs/spandsp/src/v18.c
libs/spandsp/src/v42.c

index 39ce670bde13fe9072061e1ed126851574653e53..6862567184ab3569a266ff780c6428609dc762e3 100644 (file)
@@ -84,7 +84,7 @@ Receiver now waits
 
 Sender waits 250-300ms after end of 2300Hz tone
 
-Send ACCT MT QXYZ GG CCC
+Send ACCT MT QXYZ GG CCC S
 
 ACCT = 4 digit account code (0-9, B-F)
 MT = 2 digit message type (18 preferred, 98 optional)
@@ -124,6 +124,74 @@ If kissoff doesn't start within 1.25s of the end of the DTMF, repeat the DTMF me
 Receiver sends 750-1000ms of 1400Hz as the kissoff tone
 
 Sender shall make 4 attempts before giving up. One successful kissoff resets the attempt counter
+
+
+Ademco Express 4/1
+
+    ACCT MT C
+
+ACCT = 4 digit account code (0-9, B-F)
+MT = 2 digit message type (17)
+C = alarm code
+S = 1 digit hex checksum
+
+Ademco Express 4/2
+
+    ACCT MT C Z S
+
+ACCT = 4 digit account code (0-9, B-F)
+MT = 2 digit message type (27)
+C = 1 digit alarm code
+Z = 1 digit zone or user number
+S = 1 digit hex checksum
+
+Ademco High speed
+
+    ACCT MT PPPPPPPP X S
+
+ACCT = 4 digit account code (0-9, B-F)
+MT = 2 digit message type (55)
+PPPPPPPP = 8 digit status of each zone
+X = 1 digit type of information in the PPPPPPPP field
+S = 1 digit hex checksum
+
+Each P digit contains one of the following values:
+        1  new alarm
+        2  new opening
+        3  new restore
+        4  new closing
+        5  normal
+        6  outstanding
+The X field contains one of the following values:
+        0  AlarmNet messages
+        1  ambush or duress
+        2  opening by user (the first P field contains the user number)
+        3  bypass (the P fields indicate which zones are bypassed)
+        4  closing by user (the first P field contain the user number)
+        5  trouble (the P fields contain which zones are in trouble)
+        6  system trouble
+        7  normal message (the P fields indicate zone status)
+        8  low battery (the P fields indicate zone status)
+        9  test (the P fields indicate zone status)
+
+Ademco Super fast
+
+    ACCT MT PPPPPPPP X S
+
+ACCT = 4 digit account code (0-9, B-F)
+MT = 2 digit message type (56)
+
+There are versions somewhat like the above, with 8, 16 or 24 'P' digits,
+and no message type
+    ACCT PPPPPPPP X
+    ACCT PPPPPPPPPPPPPPPP X
+    ACCT PPPPPPPPPPPPPPPPPPPPPPPP X
+
+ACCT = 4 digit account code (0-9, B-F)
+PPPPPPPP = 8, 16 or 24 digit status of each zone
+X = 1 digit status of the communicator
+S = 1 digit hex checksum
+
 */
 
 struct ademco_code_s
@@ -1040,7 +1108,7 @@ SPAN_DECLARE(ademco_contactid_sender_state_t *) ademco_contactid_sender_init(ade
 
     s->step = 0;
     s->remaining_samples = ms_to_samples(100);
-    dtmf_tx_init(&s->dtmf);
+    dtmf_tx_init(&s->dtmf, NULL, NULL);
     /* The specified timing is 50-60ms on, 50-60ms off */
     dtmf_tx_set_timing(&s->dtmf, 55, 55);
     return s;
index 54d4137682a328cb7a069aad28a109be5c910b0e..647bf371ab5482118fca4e0cfe40e1f90662d10b 100644 (file)
@@ -373,19 +373,19 @@ static void start_tx(adsi_tx_state_t *s)
     switch (s->standard)
     {
     case ADSI_STANDARD_CLASS:
-        fsk_tx_init(&(s->fsktx), &preset_fsk_specs[FSK_BELL202], adsi_tx_get_bit, s);
+        fsk_tx_init(&s->fsktx, &preset_fsk_specs[FSK_BELL202], adsi_tx_get_bit, s);
         break;
     case ADSI_STANDARD_CLIP:
     case ADSI_STANDARD_ACLIP:
     case ADSI_STANDARD_JCLIP:
-        fsk_tx_init(&(s->fsktx), &preset_fsk_specs[FSK_V23CH1], adsi_tx_get_bit, s);
+        fsk_tx_init(&s->fsktx, &preset_fsk_specs[FSK_V23CH1], adsi_tx_get_bit, s);
         break;
     case ADSI_STANDARD_CLIP_DTMF:
-        dtmf_tx_init(&(s->dtmftx));
+        dtmf_tx_init(&s->dtmftx, NULL, NULL);
         break;
     case ADSI_STANDARD_TDD:
-        fsk_tx_init(&(s->fsktx), &preset_fsk_specs[FSK_WEITBRECHT], async_tx_get_bit, &(s->asynctx));
-        async_tx_init(&(s->asynctx), 5, ASYNC_PARITY_NONE, 2, FALSE, adsi_tdd_get_async_byte, s);
+        fsk_tx_init(&s->fsktx, &preset_fsk_specs[FSK_WEITBRECHT], async_tx_get_bit, &s->asynctx);
+        async_tx_init(&s->asynctx, 5, ASYNC_PARITY_NONE, 2, FALSE, adsi_tdd_get_async_byte, s);
         /* Schedule an explicit shift at the start of baudot transmission */
         s->baudot_shift = 2;
         break;
@@ -403,10 +403,10 @@ SPAN_DECLARE(int) adsi_rx(adsi_rx_state_t *s, const int16_t amp[], int len)
         s->in_progress -= len;
         if (s->in_progress <= 0)
             s->msg_len = 0;
-        dtmf_rx(&(s->dtmfrx), amp, len);
+        dtmf_rx(&s->dtmfrx, amp, len);
         break;
     default:
-        fsk_rx(&(s->fskrx), amp, len);
+        fsk_rx(&s->fskrx, amp, len);
         break;
     }
     return 0;
@@ -435,20 +435,20 @@ SPAN_DECLARE(adsi_rx_state_t *) adsi_rx_init(adsi_rx_state_t *s,
     switch (standard)
     {
     case ADSI_STANDARD_CLASS:
-        fsk_rx_init(&(s->fskrx), &preset_fsk_specs[FSK_BELL202], FSK_FRAME_MODE_ASYNC, adsi_rx_put_bit, s);
+        fsk_rx_init(&s->fskrx, &preset_fsk_specs[FSK_BELL202], FSK_FRAME_MODE_ASYNC, adsi_rx_put_bit, s);
         break;
     case ADSI_STANDARD_CLIP:
     case ADSI_STANDARD_ACLIP:
     case ADSI_STANDARD_JCLIP:
-        fsk_rx_init(&(s->fskrx), &preset_fsk_specs[FSK_V23CH1], FSK_FRAME_MODE_ASYNC, adsi_rx_put_bit, s);
+        fsk_rx_init(&s->fskrx, &preset_fsk_specs[FSK_V23CH1], FSK_FRAME_MODE_ASYNC, adsi_rx_put_bit, s);
         break;
     case ADSI_STANDARD_CLIP_DTMF:
-        dtmf_rx_init(&(s->dtmfrx), adsi_rx_dtmf, s);
+        dtmf_rx_init(&s->dtmfrx, adsi_rx_dtmf, s);
         break;
     case ADSI_STANDARD_TDD:
         /* TDD uses 5 bit data, no parity and 1.5 stop bits. We scan for the first stop bit, and
            ride over the fraction. */
-        fsk_rx_init(&(s->fskrx), &preset_fsk_specs[FSK_WEITBRECHT], FSK_FRAME_MODE_5N1_FRAMES, adsi_tdd_put_async_byte, s);
+        fsk_rx_init(&s->fskrx, &preset_fsk_specs[FSK_WEITBRECHT], FSK_FRAME_MODE_5N1_FRAMES, adsi_tdd_put_async_byte, s);
         break;
     }
     s->standard = standard;
@@ -475,19 +475,19 @@ SPAN_DECLARE(int) adsi_tx(adsi_tx_state_t *s, int16_t amp[], int max_len)
     int len;
     int lenx;
 
-    len = tone_gen(&(s->alert_tone_gen), amp, max_len);
+    len = tone_gen(&s->alert_tone_gen, amp, max_len);
     if (s->tx_signal_on)
     {
         switch (s->standard)
         {
         case ADSI_STANDARD_CLIP_DTMF:
             if (len < max_len)
-                len += dtmf_tx(&(s->dtmftx), amp, max_len - len);
+                len += dtmf_tx(&s->dtmftx, amp, max_len - len);
             break;
         default:
             if (len < max_len)
             {
-                if ((lenx = fsk_tx(&(s->fsktx), amp + len, max_len - len)) <= 0)
+                if ((lenx = fsk_tx(&s->fsktx, amp + len, max_len - len)) <= 0)
                     s->tx_signal_on = FALSE;
                 len += lenx;
             }
@@ -500,7 +500,7 @@ SPAN_DECLARE(int) adsi_tx(adsi_tx_state_t *s, int16_t amp[], int max_len)
 
 SPAN_DECLARE(void) adsi_tx_send_alert_tone(adsi_tx_state_t *s)
 {
-    tone_gen_init(&(s->alert_tone_gen), &(s->alert_tone_desc));
+    tone_gen_init(&s->alert_tone_gen, &s->alert_tone_desc);
 }
 /*- End of function --------------------------------------------------------*/
 
@@ -583,7 +583,7 @@ SPAN_DECLARE(int) adsi_tx_put_message(adsi_tx_state_t *s, const uint8_t *msg, in
     case ADSI_STANDARD_CLIP_DTMF:
         if (len >= 128)
             return -1;
-        len -= (int) dtmf_tx_put(&(s->dtmftx), (char *) msg, len);
+        len -= (int) dtmf_tx_put(&s->dtmftx, (char *) msg, len);
         break;
     case ADSI_STANDARD_JCLIP:
         if (len > 128 - 9)
@@ -662,7 +662,7 @@ SPAN_DECLARE(adsi_tx_state_t *) adsi_tx_init(adsi_tx_state_t *s, int standard)
             return NULL;
     }
     memset(s, 0, sizeof(*s));
-    tone_gen_descriptor_init(&(s->alert_tone_desc),
+    tone_gen_descriptor_init(&s->alert_tone_desc,
                              2130,
                              -13,
                              2750,
index 1bfa65d9103d4a1ab4730745aaf82e1e21632744..49e25fde2359e8650dbbd62d2977ea027ca935b2 100644 (file)
@@ -35,6 +35,7 @@
 #include <assert.h>
 
 #include "spandsp/telephony.h"
+#include "spandsp/bit_operations.h"
 #include "spandsp/async.h"
 
 #include "spandsp/private/async.h"
@@ -75,55 +76,13 @@ SPAN_DECLARE(const char *) signal_status_to_str(int status)
         return "Link disconnected";
     case SIG_STATUS_LINK_ERROR:
         return "Link error";
+    case SIG_STATUS_LINK_IDLE:
+        return "Link idle";
     }
     return "???";
 }
 /*- End of function --------------------------------------------------------*/
 
-SPAN_DECLARE(async_rx_state_t *) async_rx_init(async_rx_state_t *s,
-                                               int data_bits,
-                                               int parity,
-                                               int stop_bits,
-                                               int use_v14,
-                                               put_byte_func_t put_byte,
-                                               void *user_data)
-{
-    if (s == NULL)
-    {
-        if ((s = (async_rx_state_t *) malloc(sizeof(*s))) == NULL)
-            return NULL;
-    }
-    s->data_bits = data_bits;
-    s->parity = parity;
-    s->stop_bits = stop_bits;
-    s->use_v14 = use_v14;
-
-    s->put_byte = put_byte;
-    s->user_data = user_data;
-
-    s->byte_in_progress = 0;
-    s->bitpos = 0;
-    s->parity_bit = 0;
-
-    s->parity_errors = 0;
-    s->framing_errors = 0;
-    return s;
-}
-/*- End of function --------------------------------------------------------*/
-
-SPAN_DECLARE(int) async_rx_release(async_rx_state_t *s)
-{
-    return 0;
-}
-/*- End of function --------------------------------------------------------*/
-
-SPAN_DECLARE(int) async_rx_free(async_rx_state_t *s)
-{
-    free(s);
-    return 0;
-}
-/*- End of function --------------------------------------------------------*/
-
 SPAN_DECLARE_NONSTD(void) async_rx_put_bit(void *user_data, int bit)
 {
     async_rx_state_t *s;
@@ -205,45 +164,44 @@ SPAN_DECLARE_NONSTD(void) async_rx_put_bit(void *user_data, int bit)
 }
 /*- End of function --------------------------------------------------------*/
 
-SPAN_DECLARE(async_tx_state_t *) async_tx_init(async_tx_state_t *s,
+SPAN_DECLARE(async_rx_state_t *) async_rx_init(async_rx_state_t *s,
                                                int data_bits,
                                                int parity,
                                                int stop_bits,
                                                int use_v14,
-                                               get_byte_func_t get_byte,
+                                               put_byte_func_t put_byte,
                                                void *user_data)
 {
     if (s == NULL)
     {
-        if ((s = (async_tx_state_t *) malloc(sizeof(*s))) == NULL)
+        if ((s = (async_rx_state_t *) malloc(sizeof(*s))) == NULL)
             return NULL;
     }
-    /* We have a use_v14 parameter for completeness, but right now V.14 only
-       applies to the receive side. We are unlikely to have an application where
-       flow control does not exist, so V.14 stuffing is not needed. */
     s->data_bits = data_bits;
     s->parity = parity;
     s->stop_bits = stop_bits;
-    if (parity != ASYNC_PARITY_NONE)
-        s->stop_bits++;
-        
-    s->get_byte = get_byte;
+    s->use_v14 = use_v14;
+
+    s->put_byte = put_byte;
     s->user_data = user_data;
 
     s->byte_in_progress = 0;
     s->bitpos = 0;
     s->parity_bit = 0;
+
+    s->parity_errors = 0;
+    s->framing_errors = 0;
     return s;
 }
 /*- End of function --------------------------------------------------------*/
 
-SPAN_DECLARE(int) async_tx_release(async_tx_state_t *s)
+SPAN_DECLARE(int) async_rx_release(async_rx_state_t *s)
 {
     return 0;
 }
 /*- End of function --------------------------------------------------------*/
 
-SPAN_DECLARE(int) async_tx_free(async_tx_state_t *s)
+SPAN_DECLARE(int) async_rx_free(async_rx_state_t *s)
 {
     free(s);
     return 0;
@@ -295,4 +253,56 @@ SPAN_DECLARE_NONSTD(int) async_tx_get_bit(void *user_data)
     return bit;
 }
 /*- End of function --------------------------------------------------------*/
+
+SPAN_DECLARE(void) async_tx_presend_bits(async_tx_state_t *s, int bits)
+{
+    s->presend_bits = bits;
+}
+/*- End of function --------------------------------------------------------*/
+
+SPAN_DECLARE(async_tx_state_t *) async_tx_init(async_tx_state_t *s,
+                                               int data_bits,
+                                               int parity,
+                                               int stop_bits,
+                                               int use_v14,
+                                               get_byte_func_t get_byte,
+                                               void *user_data)
+{
+    if (s == NULL)
+    {
+        if ((s = (async_tx_state_t *) malloc(sizeof(*s))) == NULL)
+            return NULL;
+    }
+    /* We have a use_v14 parameter for completeness, but right now V.14 only
+       applies to the receive side. We are unlikely to have an application where
+       flow control does not exist, so V.14 stuffing is not needed. */
+    s->data_bits = data_bits;
+    s->parity = parity;
+    s->stop_bits = stop_bits;
+    if (parity != ASYNC_PARITY_NONE)
+        s->stop_bits++;
+        
+    s->get_byte = get_byte;
+    s->user_data = user_data;
+
+    s->byte_in_progress = 0;
+    s->bitpos = 0;
+    s->parity_bit = 0;
+    s->presend_bits = 0;
+    return s;
+}
+/*- End of function --------------------------------------------------------*/
+
+SPAN_DECLARE(int) async_tx_release(async_tx_state_t *s)
+{
+    return 0;
+}
+/*- End of function --------------------------------------------------------*/
+
+SPAN_DECLARE(int) async_tx_free(async_tx_state_t *s)
+{
+    free(s);
+    return 0;
+}
+/*- End of function --------------------------------------------------------*/
 /*- End of file ------------------------------------------------------------*/
index ee61f0095cf56443e218fb08d1460f8e40cce82b..196e3d3eca39c4d149d5e67d246af6d30edf7e0c 100644 (file)
@@ -508,21 +508,31 @@ SPAN_DECLARE(int) dtmf_tx(dtmf_tx_state_t *s, int16_t amp[], int max_samples)
     if (s->tones.current_section >= 0)
     {
         /* Deal with the fragment left over from last time */
-        len = tone_gen(&(s->tones), amp, max_samples);
+        len = tone_gen(&s->tones, amp, max_samples);
     }
-    while (len < max_samples  &&  (digit = queue_read_byte(&s->queue.queue)) >= 0)
+
+    while (len < max_samples)
     {
         /* Step to the next digit */
+        if ((digit = queue_read_byte(&s->queue.queue)) < 0)
+        {
+            /* See if we can get some more digits */
+            if (s->callback == NULL)
+                break;
+            s->callback(s->callback_data);
+            if ((digit = queue_read_byte(&s->queue.queue)) < 0)
+                break;
+        }
         if (digit == 0)
             continue;
         if ((cp = strchr(dtmf_positions, digit)) == NULL)
             continue;
-        tone_gen_init(&(s->tones), &dtmf_digit_tones[cp - dtmf_positions]);
+        tone_gen_init(&s->tones, &dtmf_digit_tones[cp - dtmf_positions]);
         s->tones.tone[0].gain = s->low_level;
         s->tones.tone[1].gain = s->high_level;
         s->tones.duration[0] = s->on_time;
         s->tones.duration[1] = s->off_time;
-        len += tone_gen(&(s->tones), amp + len, max_samples - len);
+        len += tone_gen(&s->tones, amp + len, max_samples - len);
     }
     return len;
 }
@@ -562,7 +572,9 @@ SPAN_DECLARE(void) dtmf_tx_set_timing(dtmf_tx_state_t *s, int on_time, int off_t
 }
 /*- End of function --------------------------------------------------------*/
 
-SPAN_DECLARE(dtmf_tx_state_t *) dtmf_tx_init(dtmf_tx_state_t *s)
+SPAN_DECLARE(dtmf_tx_state_t *) dtmf_tx_init(dtmf_tx_state_t *s,
+                                             digits_tx_callback_t callback,
+                                             void *user_data)
 {
     if (s == NULL)
     {
@@ -572,7 +584,9 @@ SPAN_DECLARE(dtmf_tx_state_t *) dtmf_tx_init(dtmf_tx_state_t *s)
     memset(s, 0, sizeof(*s));
     if (!dtmf_tx_inited)
         dtmf_tx_initialise();
-    tone_gen_init(&(s->tones), &dtmf_digit_tones[0]);
+    s->callback = callback;
+    s->callback_data = user_data;
+    tone_gen_init(&s->tones, &dtmf_digit_tones[0]);
     dtmf_tx_set_level(s, DEFAULT_DTMF_TX_LEVEL, 0);
     dtmf_tx_set_timing(s, -1, -1);
     queue_init(&s->queue.queue, MAX_DTMF_DIGITS, QUEUE_READ_ATOMIC | QUEUE_WRITE_ATOMIC);
index 3f53aa7bc802a5fc52453093385a17e473b0c162..d95f7574689044ab0e43399fcbc2cd689323017b 100644 (file)
@@ -117,7 +117,7 @@ const fsk_spec_t preset_fsk_specs[] =
          4545
     },
     {
-        "Weitbrecht 50",    /* Used for Internatioal TDD (Telecoms Device for the Deaf) */
+        "Weitbrecht 50",    /* Used for international TDD (Telecoms Device for the Deaf) */
         1600 + 200,
         1600 - 200,
         -14,
index 8d643dd720a28f00749e35ec741c58405732d998..1b22cd5caf91d557318047cae7403df17ed2f567 100644 (file)
@@ -86,7 +86,9 @@ enum
     /*! \brief The link protocol (e.g. V.42) has disconnected. */
     SIG_STATUS_LINK_DISCONNECTED = -15,
     /*! \brief An error has occurred in the link protocol (e.g. V.42). */
-    SIG_STATUS_LINK_ERROR = -16
+    SIG_STATUS_LINK_ERROR = -16,
+    /*! \brief Keep the link in an idle state, as there is nothing to send. */
+    SIG_STATUS_LINK_IDLE = -17
 };
 
 /*! Message put function for data pumps */
@@ -145,27 +147,44 @@ extern "C"
     \return A pointer to the description. */
 SPAN_DECLARE(const char *) signal_status_to_str(int status);
 
-/*! Initialise an asynchronous data transmit context.
-    \brief Initialise an asynchronous data transmit context.
-    \param s The transmitter context.
-    \param data_bits The number of data bit.
+/*! Accept a bit from a received serial bit stream
+    \brief Accept a bit from a received serial bit stream
+    \param user_data An opaque point which must point to a receiver context.
+    \param bit The new bit. Some special values are supported for this field.
+        - SIG_STATUS_CARRIER_UP
+        - SIG_STATUS_CARRIER_DOWN
+        - 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);
+
+/*! Initialise an asynchronous data receiver context.
+    \brief Initialise an asynchronous data receiver context.
+    \param s The receiver context.
+    \param data_bits The number of data bits.
     \param parity_bits The type of parity.
     \param stop_bits The number of stop bits.
     \param use_v14 TRUE if V.14 rate adaption processing should be used.
-    \param get_byte The callback routine used to get the data to be transmitted.
+    \param put_byte The callback routine used to put the received data.
     \param user_data An opaque pointer.
     \return A pointer to the initialised context, or NULL if there was a problem. */
-SPAN_DECLARE(async_tx_state_t *) async_tx_init(async_tx_state_t *s,
+SPAN_DECLARE(async_rx_state_t *) async_rx_init(async_rx_state_t *s,
                                                int data_bits,
                                                int parity_bits,
                                                int stop_bits,
                                                int use_v14,
-                                               get_byte_func_t get_byte,
+                                               put_byte_func_t put_byte,
                                                void *user_data);
 
-SPAN_DECLARE(int) async_tx_release(async_tx_state_t *s);
+SPAN_DECLARE(int) async_rx_release(async_rx_state_t *s);
 
-SPAN_DECLARE(int) async_tx_free(async_tx_state_t *s);
+SPAN_DECLARE(int) async_rx_free(async_rx_state_t *s);
+
+/*! Set a minimum number of bit times of stop bit state before character transmission commences.
+    \brief Set a minimum number of bit times of stop bit state before character transmission commences.
+    \param user_data An opaque point which must point to a transmitter context.
+    \param the number of bits. */
+SPAN_DECLARE(void) async_tx_presend_bits(async_tx_state_t *s, int bits);
 
 /*! Get the next bit of a transmitted serial bit stream.
     \brief Get the next bit of a transmitted serial bit stream.
@@ -173,38 +192,27 @@ SPAN_DECLARE(int) async_tx_free(async_tx_state_t *s);
     \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);
 
-/*! Initialise an asynchronous data receiver context.
-    \brief Initialise an asynchronous data receiver context.
-    \param s The receiver context.
-    \param data_bits The number of data bits.
+/*! Initialise an asynchronous data transmit context.
+    \brief Initialise an asynchronous data transmit context.
+    \param s The transmitter context.
+    \param data_bits The number of data bit.
     \param parity_bits The type of parity.
     \param stop_bits The number of stop bits.
     \param use_v14 TRUE if V.14 rate adaption processing should be used.
-    \param put_byte The callback routine used to put the received data.
+    \param get_byte The callback routine used to get the data to be transmitted.
     \param user_data An opaque pointer.
     \return A pointer to the initialised context, or NULL if there was a problem. */
-SPAN_DECLARE(async_rx_state_t *) async_rx_init(async_rx_state_t *s,
+SPAN_DECLARE(async_tx_state_t *) async_tx_init(async_tx_state_t *s,
                                                int data_bits,
                                                int parity_bits,
                                                int stop_bits,
                                                int use_v14,
-                                               put_byte_func_t put_byte,
+                                               get_byte_func_t get_byte,
                                                void *user_data);
 
-SPAN_DECLARE(int) async_rx_release(async_rx_state_t *s);
-
-SPAN_DECLARE(int) async_rx_free(async_rx_state_t *s);
+SPAN_DECLARE(int) async_tx_release(async_tx_state_t *s);
 
-/*! Accept a bit from a received serial bit stream
-    \brief Accept a bit from a received serial bit stream
-    \param user_data An opaque point which must point to a receiver context.
-    \param bit The new bit. Some special values are supported for this field.
-        - SIG_STATUS_CARRIER_UP
-        - SIG_STATUS_CARRIER_DOWN
-        - 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(int) async_tx_free(async_tx_state_t *s);
 
 #if defined(__cplusplus)
 }
index a9aeb64ef9a4ecdfb8072aef2a40d21fd6ce7e11..58ea779088cf1833c9f28b5ab57e5f2be491ca8f 100644 (file)
@@ -74,6 +74,7 @@ repertoire of 16 DTMF dual tones.
 #define MAX_DTMF_DIGITS 128
 
 typedef void (*digits_rx_callback_t)(void *user_data, const char *digits, int len);
+typedef void (*digits_tx_callback_t)(void *user_data);
 
 /*!
     DTMF generator state descriptor. This defines the state of a single
@@ -122,8 +123,13 @@ SPAN_DECLARE(void) dtmf_tx_set_timing(dtmf_tx_state_t *s, int on_time, int off_t
 
 /*! \brief Initialise a DTMF tone generator context.
     \param s The DTMF generator context.
+    \param callback An optional callback routine, used to get more digits.
+    \param user_data An opaque pointer which is associated with the context,
+           and supplied in callbacks.
     \return A pointer to the DTMF generator context. */
-SPAN_DECLARE(dtmf_tx_state_t *) dtmf_tx_init(dtmf_tx_state_t *s);
+SPAN_DECLARE(dtmf_tx_state_t *) dtmf_tx_init(dtmf_tx_state_t *s,
+                                             digits_tx_callback_t callback,
+                                             void *user_data);
 
 /*! \brief Release a DTMF tone generator context.
     \param s The DTMF tone generator context.
index 715d659d9e0c927d24206781402f63c0fdbf7a1d..7354aaf96701a618789aec8dded8619914230c3b 100644 (file)
@@ -43,9 +43,11 @@ struct async_tx_state_s
     get_byte_func_t get_byte;
     /*! \brief An opaque pointer passed when calling get_byte. */
     void *user_data;
+    /*! \brief The minimum number of stop bits to send before character transmission begins. */
+    int presend_bits;
 
     /*! \brief A current, partially transmitted, character. */
-    unsigned int byte_in_progress;
+    int32_t byte_in_progress;
     /*! \brief The current bit position within a partially transmitted character. */
     int bitpos;
     /*! \brief Parity bit. */
@@ -73,7 +75,7 @@ struct async_rx_state_s
     void *user_data;
 
     /*! \brief A current, partially complete, character. */
-    unsigned int byte_in_progress;
+    int32_t byte_in_progress;
     /*! \brief The current bit position within a partially complete character. */
     int bitpos;
     /*! \brief Parity bit. */
index e063470d78a40b5be7019568b00f6cc35a9886db..eae20ad4d541b5ef49b3575a769cd8c78ddf883b 100644 (file)
 */
 struct dtmf_tx_state_s
 {
+    /*! Optional callback funcion to get more digits. */
+    digits_tx_callback_t callback;
+    /*! An opaque pointer passed to the callback function. */
+    void *callback_data;
     tone_gen_state_t tones;
     float low_level;
     float high_level;
index 075a9b221c9925c357c641d317b4e868df935ea2..e8e74c2af93d61b4d70444b30dce796f59cac0f9 100644 (file)
@@ -66,6 +66,10 @@ typedef struct
 {
     /*! \brief The FAX modem set for the audio side fo the gateway. */
     fax_modems_state_t modems;
+    /*! \brief CED detector */
+    modem_connect_tones_rx_state_t connect_rx_ced;
+    /*! \brief CNG detector */
+    modem_connect_tones_rx_state_t connect_rx_cng;
 } t38_gateway_audio_state_t;
 
 /*!
index b601b0c02db456173e0a1d9c6257882e0d050861..5a03cb79f81e2cf6ee3770c4a81425b720824e94 100644 (file)
@@ -138,7 +138,7 @@ struct v22bis_state_s
         int constellation_state;
 
 #if defined(SPANDSP_USE_FIXED_POINT)
-        /*! \brief The scaling factor accessed by the AGC algorithm. */
+        /*! \brief The scaling factor assessed by the AGC algorithm. */
         int16_t agc_scaling;
         /*! \brief The root raised cosine (RRC) pulse shaping filter buffer. */
         int16_t rrc_filter[V22BIS_RX_FILTER_STEPS];
@@ -158,7 +158,7 @@ struct v22bis_state_s
         /*! \brief The integral part of the carrier tracking filter. */
         int32_t carrier_track_i;
 #else
-        /*! \brief The scaling factor accessed by the AGC algorithm. */
+        /*! \brief The scaling factor assessed by the AGC algorithm. */
         float agc_scaling;
         /*! \brief The root raised cosine (RRC) pulse shaping filter buffer. */
         float rrc_filter[V22BIS_RX_FILTER_STEPS];
index 8c159fee3aa59bb9c0a0c10cefdbeadc06fede34..fcefbe96ab7a87540f7364cd7cceeaa49e8a7a99 100644 (file)
@@ -363,16 +363,24 @@ static __inline__ int32_t saturated_sub32(int32_t a, int32_t b)
 
 static __inline__ int16_t saturated_mul16(int16_t a, int16_t b)
 {
-    if (a == INT16_MIN  &&  b == INT16_MIN)
+    int32_t product;
+
+    product = (int32_t) a*b;
+    if (product == 0x40000000)
         return INT16_MAX;
     /*endif*/
-    return (int16_t) (((int32_t) a*(int32_t) b) >> 15);
+    return product >> 15;
 }
 /*- End of function --------------------------------------------------------*/
 
 static __inline__ int32_t saturated_mul16_32(int16_t a, int16_t b)
 {
-    return ((int32_t) a*(int32_t) b) << 1;
+    int32_t product;
+
+    product = (int32_t) a*b;
+    if (product == 0x40000000)
+        return INT32_MAX;
+    return product << 1;
 }
 /*- End of function --------------------------------------------------------*/
 
index bc73c7e619c05bbc30a31d0568c4142248c00bc0..08219ec0be486e3b52344ad06028f5041071b3a4 100644 (file)
@@ -140,9 +140,19 @@ SPAN_DECLARE_NONSTD(int) v18_tx(v18_state_t *s, int16_t amp[], int max_len);
     \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 unprocessed samples.
 */
 SPAN_DECLARE_NONSTD(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).
+    \brief Fake processing of a missing block of received V.18 audio samples.
+    \param s The V.18 context.
+    \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);
+
 /*! \brief Put a string to a V.18 context's input buffer.
     \param s The V.18 context.
     \param msg The string to be added.
index bdd34e86f13c098ff8ddbbafc723212540e75630..5ab26262dd6c1c7ff06fe741de3f109f1b7020d2 100644 (file)
@@ -100,12 +100,12 @@ SPAN_DECLARE(void) v42_restart(v42_state_t *s);
 /*! Release a V.42 context.
     \param s The V.42 context.
     \return 0 if OK */
-SPAN_DECLARE(void) v42_release(v42_state_t *s);
+SPAN_DECLARE(int) v42_release(v42_state_t *s);
 
 /*! Free a V.42 context.
     \param s The V.42 context.
     \return 0 if OK */
-SPAN_DECLARE(void) v42_free(v42_state_t *s);
+SPAN_DECLARE(int) v42_free(v42_state_t *s);
 
 #if defined(__cplusplus)
 }
index 38f160d7ff51b3ad96f323c06352e65a812ff1df..5c495dbb81b50ca3efc9db9f5f4f178688585d11 100644 (file)
@@ -1406,7 +1406,7 @@ static int build_dcs(t30_state_t *s)
     /* We have a file to send, so tell the far end to go into receive mode. */
     set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_RECEIVE_FAX_DOCUMENT);
     /* Set the Y resolution bits */
-    bad = T30_ERR_OK;
+    bad = T30_ERR_NORESSUPPORT;
     row_squashing_ratio = 1;
     switch (s->y_resolution)
     {
@@ -1414,19 +1414,18 @@ static int build_dcs(t30_state_t *s)
         switch (s->x_resolution)
         {
         case T4_X_RESOLUTION_600:
-            if (!(s->supported_resolutions & T30_SUPPORT_600_1200_RESOLUTION))
-                bad = T30_ERR_NORESSUPPORT;
-            else
+            if ((s->supported_resolutions & T30_SUPPORT_600_1200_RESOLUTION)  &&  test_ctrl_bit(s->far_dis_dtc_frame, T30_DIS_BIT_600_1200_CAPABLE))
+            {
                 set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_600_1200);
+                bad = T30_ERR_OK;
+            }
             break;
         case T4_X_RESOLUTION_1200:
-            if (!(s->supported_resolutions & T30_SUPPORT_1200_1200_RESOLUTION))
-                bad = T30_ERR_NORESSUPPORT;
-            else
+            if ((s->supported_resolutions & T30_SUPPORT_1200_1200_RESOLUTION)  &&  test_ctrl_bit(s->far_dis_dtc_frame, T30_DIS_BIT_1200_1200_CAPABLE))
+            {
                 set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_1200_1200);
-            break;
-        default:
-            bad = T30_ERR_NORESSUPPORT;
+                bad = T30_ERR_OK;
+            }
             break;
         }
         break;
@@ -1434,13 +1433,11 @@ static int build_dcs(t30_state_t *s)
         switch (s->x_resolution)
         {
         case T4_X_RESOLUTION_R16:
-            if (!(s->supported_resolutions & T30_SUPPORT_400_800_RESOLUTION))
-                bad = T30_ERR_NORESSUPPORT;
-            else
+            if ((s->supported_resolutions & T30_SUPPORT_400_800_RESOLUTION)  &&  test_ctrl_bit(s->far_dis_dtc_frame, T30_DIS_BIT_400_800_CAPABLE))
+            {
                 set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_400_800);
-            break;
-        default:
-            bad = T30_ERR_NORESSUPPORT;
+                bad = T30_ERR_OK;
+            }
             break;
         }
         break;
@@ -1448,19 +1445,18 @@ static int build_dcs(t30_state_t *s)
         switch (s->x_resolution)
         {
         case T4_X_RESOLUTION_300:
-            if (!(s->supported_resolutions & T30_SUPPORT_300_600_RESOLUTION))
-                bad = T30_ERR_NORESSUPPORT;
-            else
+            if ((s->supported_resolutions & T30_SUPPORT_300_600_RESOLUTION)  &&  test_ctrl_bit(s->far_dis_dtc_frame, T30_DIS_BIT_300_600_CAPABLE))
+            {
                 set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_300_600);
+                bad = T30_ERR_OK;
+            }
             break;
         case T4_X_RESOLUTION_600:
-            if (!(s->supported_resolutions & T30_SUPPORT_600_600_RESOLUTION))
-                bad = T30_ERR_NORESSUPPORT;
-            else
+            if ((s->supported_resolutions & T30_SUPPORT_600_600_RESOLUTION)  &&  test_ctrl_bit(s->far_dis_dtc_frame, T30_DIS_BIT_600_600_CAPABLE))
+            {
                 set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_600_600);
-            break;
-        default:
-            bad = T30_ERR_NORESSUPPORT;
+                bad = T30_ERR_OK;
+            }
             break;
         }
         break;
@@ -1468,45 +1464,40 @@ static int build_dcs(t30_state_t *s)
         switch (s->x_resolution)
         {
         case T4_X_RESOLUTION_300:
-            if (!(s->supported_resolutions & T30_SUPPORT_300_300_RESOLUTION))
-                bad = T30_ERR_NORESSUPPORT;
-            else
+            if ((s->supported_resolutions & T30_SUPPORT_300_300_RESOLUTION)  &&  test_ctrl_bit(s->far_dis_dtc_frame, T30_DIS_BIT_300_300_CAPABLE))
+            {
                 set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_300_300);
-            break;
-        default:
-            bad = T30_ERR_NORESSUPPORT;
+                bad = T30_ERR_OK;
+            }
             break;
         }
         break;
     case T4_Y_RESOLUTION_SUPERFINE:
         if ((s->supported_resolutions & T30_SUPPORT_SUPERFINE_RESOLUTION))
         {
-            switch (s->x_resolution)
+            if (s->x_resolution == T4_X_RESOLUTION_R16  &&  test_ctrl_bit(s->far_dis_dtc_frame, T30_DIS_BIT_400_400_CAPABLE))
             {
-            case T4_X_RESOLUTION_R8:
-                set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_200_400);
-                break;
-            case T4_X_RESOLUTION_R16:
                 set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_400_400);
+                bad = T30_ERR_OK;
                 break;
-            default:
-                bad = T30_ERR_NORESSUPPORT;
+            }
+            if (s->x_resolution == T4_X_RESOLUTION_R8  &&  test_ctrl_bit(s->far_dis_dtc_frame, T30_DIS_BIT_200_400_CAPABLE))
+            {
+                set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_200_400);
+                bad = T30_ERR_OK;
                 break;
             }
-            break;
         }
         row_squashing_ratio <<= 1;
         /* Fall through */
     case T4_Y_RESOLUTION_FINE:
-        if ((s->supported_resolutions & T30_SUPPORT_FINE_RESOLUTION))
+        if ((s->supported_resolutions & T30_SUPPORT_FINE_RESOLUTION)  &&  test_ctrl_bit(s->far_dis_dtc_frame, T30_DIS_BIT_200_200_CAPABLE))
         {
             switch (s->x_resolution)
             {
             case T4_X_RESOLUTION_R8:
                 set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_200_200);
-                break;
-            default:
-                bad = T30_ERR_NORESSUPPORT;
+                bad = T30_ERR_OK;
                 break;
             }
             break;
@@ -1519,9 +1510,7 @@ static int build_dcs(t30_state_t *s)
         {
         case T4_X_RESOLUTION_R8:
             /* No bits to set for this */
-            break;
-        default:
-            bad = T30_ERR_NORESSUPPORT;
+            bad = T30_ERR_OK;
             break;
         }
         break;
@@ -1533,97 +1522,89 @@ static int build_dcs(t30_state_t *s)
         span_log(&s->logging, SPAN_LOG_FLOW, "Image resolution (%d x %d) not acceptable\n", s->x_resolution, s->y_resolution);
         return -1;
     }
-    /* Deal with the image width. The X resolution will fall in line with any valid width. */
+
+    /* Deal with the image width. */
     /* Low (R4) res widths are not supported in recent versions of T.30 */
     bad = T30_ERR_OK;
     /* The following treats a width field of 11 like 10, which does what note 6 of Table 2/T.30
        says we should do with the invalid value 11. */
-    switch (s->image_width)
+    if (((s->image_width == T4_WIDTH_R8_A4)  &&  (s->x_resolution == T4_X_RESOLUTION_R8))
+        ||
+        ((s->image_width == T4_WIDTH_300_A4)  &&  (s->x_resolution == T4_X_RESOLUTION_300))
+        ||
+        ((s->image_width == T4_WIDTH_R16_A4)  &&  (s->x_resolution == T4_X_RESOLUTION_R16))
+        ||
+        ((s->image_width == T4_WIDTH_600_A4)  &&  (s->x_resolution == T4_X_RESOLUTION_600))
+        ||
+        ((s->image_width == T4_WIDTH_1200_A4)  &&  (s->x_resolution == T4_X_RESOLUTION_1200)))
     {
-    case T4_WIDTH_R8_A4:
-    case T4_WIDTH_300_A4:
-    case T4_WIDTH_R16_A4:
-    case T4_WIDTH_600_A4:
-    case T4_WIDTH_1200_A4:
+        span_log(&s->logging, SPAN_LOG_FLOW, "Image width is A4 0x%x 0x%x\n", s->image_width, s->x_resolution);
         /* No width related bits need to be set. */
-        break;
-    case T4_WIDTH_R8_B4:
-    case T4_WIDTH_300_B4:
-    case T4_WIDTH_R16_B4:
-    case T4_WIDTH_600_B4:
-    case T4_WIDTH_1200_B4:
-        if ((s->far_dis_dtc_frame[5] & (DISBIT2 | DISBIT1)) < 1)
-            bad = T30_ERR_NOSIZESUPPORT;
-        else if (!(s->supported_image_sizes & T30_SUPPORT_255MM_WIDTH))
-            bad = T30_ERR_NOSIZESUPPORT;
-        else
+    }
+    else if (((s->image_width == T4_WIDTH_R8_B4)  &&  (s->x_resolution == T4_X_RESOLUTION_R8))
+            ||
+            ((s->image_width == T4_WIDTH_300_B4)  &&  (s->x_resolution == T4_X_RESOLUTION_300))
+            ||
+            ((s->image_width == T4_WIDTH_R16_B4)  &&  (s->x_resolution == T4_X_RESOLUTION_R16))
+            ||
+            ((s->image_width == T4_WIDTH_600_B4)  &&  (s->x_resolution == T4_X_RESOLUTION_600))
+            ||
+            ((s->image_width == T4_WIDTH_1200_B4)  &&  (s->x_resolution == T4_X_RESOLUTION_1200)))
+    {
+        if (((s->far_dis_dtc_frame[5] & (DISBIT2 | DISBIT1)) >= 1)
+            &&
+            (s->supported_image_sizes & T30_SUPPORT_255MM_WIDTH))
+        {
+            span_log(&s->logging, SPAN_LOG_FLOW, "Image width is B4\n");
             set_ctrl_bit(s->dcs_frame, 17);
-        break;
-    case T4_WIDTH_R8_A3:
-    case T4_WIDTH_300_A3:
-    case T4_WIDTH_R16_A3:
-    case T4_WIDTH_600_A3:
-    case T4_WIDTH_1200_A3:
-        if ((s->far_dis_dtc_frame[5] & (DISBIT2 | DISBIT1)) < 2)
-            bad = T30_ERR_NOSIZESUPPORT;
-        else if (!(s->supported_image_sizes & T30_SUPPORT_303MM_WIDTH))    
-            bad = T30_ERR_NOSIZESUPPORT;
+        }
         else
-            set_ctrl_bit(s->dcs_frame, 18);
-        break;
-    default:
-        /* T.30 does not support this width */
-        bad = T30_ERR_NOSIZESUPPORT;
-        break;
+        {
+            /* We do not support this width and resolution combination */
+            bad = T30_ERR_NOSIZESUPPORT;
+        }
     }
-    if (bad != T30_ERR_OK)
+    else if (((s->image_width == T4_WIDTH_R8_A3)  &&  (s->x_resolution == T4_X_RESOLUTION_R8))
+            ||
+            ((s->image_width == T4_WIDTH_300_A3)  &&  (s->x_resolution == T4_X_RESOLUTION_300))
+            ||
+            ((s->image_width == T4_WIDTH_R16_A3)  &&  (s->x_resolution == T4_X_RESOLUTION_R16))
+            ||
+            ((s->image_width == T4_WIDTH_600_A3)  &&  (s->x_resolution == T4_X_RESOLUTION_600))
+            ||
+            ((s->image_width == T4_WIDTH_1200_A3)  &&  (s->x_resolution == T4_X_RESOLUTION_1200)))
     {
-        t30_set_status(s, bad);
-        span_log(&s->logging, SPAN_LOG_FLOW, "Image width (%d pixels) is not an acceptable FAX image width\n", s->image_width);
-        return -1;
+        if (((s->far_dis_dtc_frame[5] & (DISBIT2 | DISBIT1)) >= 2)
+            &&
+            (s->supported_image_sizes & T30_SUPPORT_303MM_WIDTH))
+        {
+            span_log(&s->logging, SPAN_LOG_FLOW, "Image width is A3\n");
+            set_ctrl_bit(s->dcs_frame, 18);
+        }
+        else
+        {
+            /* We do not support this width and resolution combination */
+            bad = T30_ERR_NOSIZESUPPORT;
+        }
     }
-    switch (s->image_width)
+    else
     {
-    case T4_WIDTH_R8_A4:
-    case T4_WIDTH_R8_B4:
-    case T4_WIDTH_R8_A3:
-        /* These are always OK */
-        break;
-    case T4_WIDTH_300_A4:
-    case T4_WIDTH_300_B4:
-    case T4_WIDTH_300_A3:
-        if (!test_ctrl_bit(s->far_dis_dtc_frame, T30_DIS_BIT_300_300_CAPABLE)  &&  !test_ctrl_bit(s->far_dis_dtc_frame, T30_DIS_BIT_300_600_CAPABLE))
-            bad = T30_ERR_NOSIZESUPPORT;
-        break;
-    case T4_WIDTH_R16_A4:
-    case T4_WIDTH_R16_B4:
-    case T4_WIDTH_R16_A3:
-        if (!test_ctrl_bit(s->far_dis_dtc_frame, T30_DIS_BIT_400_400_CAPABLE))
-            bad = T30_ERR_NOSIZESUPPORT;
-        break;
-    case T4_WIDTH_600_A4:
-    case T4_WIDTH_600_B4:
-    case T4_WIDTH_600_A3:
-        if (!test_ctrl_bit(s->far_dis_dtc_frame, T30_DIS_BIT_600_600_CAPABLE)  &&  !test_ctrl_bit(s->far_dis_dtc_frame, T30_DIS_BIT_600_1200_CAPABLE))
-            bad = T30_ERR_NOSIZESUPPORT;
-        break;
-    case T4_WIDTH_1200_A4:
-    case T4_WIDTH_1200_B4:
-    case T4_WIDTH_1200_A3:
-        if (!test_ctrl_bit(s->far_dis_dtc_frame, T30_DIS_BIT_1200_1200_CAPABLE))
-            bad = T30_ERR_NOSIZESUPPORT;
-        break;
-    default:
-        /* T.30 does not support this width */
+        /* We do not support this width and resolution combination */
         bad = T30_ERR_NOSIZESUPPORT;
-        break;
     }
+
     if (bad != T30_ERR_OK)
     {
         t30_set_status(s, bad);
-        span_log(&s->logging, SPAN_LOG_FLOW, "Image width (%d pixels) is not an acceptable FAX image width\n", s->image_width);
+        span_log(&s->logging,
+                 SPAN_LOG_FLOW,
+                 "Image width (%d pixels) and resolution (%d x %d) is not an acceptable\n",
+                 s->image_width,
+                 s->x_resolution,
+                 s->y_resolution);
         return -1;
     }
+
     /* Deal with the image length */
     /* If the other end supports unlimited length, then use that. Otherwise, if the other end supports
        B4 use that, as its longer than the default A4 length. */
@@ -2004,6 +1985,7 @@ static int start_sending_document(t30_state_t *s)
 
     if (tx_start_page(s))
         return -1;
+
     s->x_resolution = t4_tx_get_x_resolution(&s->t4.tx);
     s->y_resolution = t4_tx_get_y_resolution(&s->t4.tx);
     s->image_width = t4_tx_get_image_width(&s->t4.tx);
@@ -2337,6 +2319,7 @@ static int process_rx_dcs(t30_state_t *s, const uint8_t *msg, int len)
     };
     uint8_t dcs_frame[T30_MAX_DIS_DTC_DCS_LEN];
     int i;
+    int x;
     int new_status;
 
     t30_decode_dis_dtc_dcs(s, msg, len);
@@ -2368,46 +2351,104 @@ static int process_rx_dcs(t30_state_t *s, const uint8_t *msg, int len)
 
     s->octets_per_ecm_frame = test_ctrl_bit(dcs_frame, T30_DCS_BIT_64_OCTET_ECM_FRAMES)  ?  256  :  64;
 
+    s->x_resolution = -1;
+    s->y_resolution = -1;
+    x = -1;
     if (test_ctrl_bit(dcs_frame, T30_DCS_BIT_1200_1200))
-        s->x_resolution = T4_X_RESOLUTION_1200;
-    else if (test_ctrl_bit(dcs_frame, T30_DCS_BIT_600_600)  ||  test_ctrl_bit(dcs_frame, T30_DCS_BIT_600_1200))
-        s->x_resolution = T4_X_RESOLUTION_600;
-    else if (test_ctrl_bit(dcs_frame, T30_DCS_BIT_400_400)  ||  test_ctrl_bit(dcs_frame, T30_DCS_BIT_400_800))
-        s->x_resolution = T4_X_RESOLUTION_R16;
-    else if (test_ctrl_bit(dcs_frame, T30_DCS_BIT_300_300)  ||  test_ctrl_bit(dcs_frame, T30_DCS_BIT_300_600))
-        s->x_resolution = T4_X_RESOLUTION_300;
-    else
-        s->x_resolution = T4_X_RESOLUTION_R8;
-
-    if (test_ctrl_bit(dcs_frame, T30_DCS_BIT_1200_1200)  ||  test_ctrl_bit(dcs_frame, T30_DCS_BIT_600_1200))
-        s->y_resolution = T4_Y_RESOLUTION_1200;
+    {
+        if ((s->supported_resolutions & T30_SUPPORT_1200_1200_RESOLUTION))
+        {
+            s->x_resolution = T4_X_RESOLUTION_1200;
+            s->y_resolution = T4_Y_RESOLUTION_1200;
+            x = 5;
+        }
+    }
+    else if (test_ctrl_bit(dcs_frame, T30_DCS_BIT_600_1200))
+    {
+        if ((s->supported_resolutions & T30_SUPPORT_600_1200_RESOLUTION))
+        {
+            s->x_resolution = T4_X_RESOLUTION_600;
+            s->y_resolution = T4_Y_RESOLUTION_1200;
+            x = 4;
+        }
+    }
+    else if (test_ctrl_bit(dcs_frame, T30_DCS_BIT_600_600))
+    {
+        if ((s->supported_resolutions & T30_SUPPORT_600_600_RESOLUTION))
+        {
+            s->x_resolution = T4_X_RESOLUTION_600;
+            s->y_resolution = T4_Y_RESOLUTION_600;
+            x = 4;
+        }
+    }
     else if (test_ctrl_bit(dcs_frame, T30_DCS_BIT_400_800))
-        s->y_resolution = T4_Y_RESOLUTION_800;
-    else if (test_ctrl_bit(dcs_frame, T30_DCS_BIT_600_600)  ||  test_ctrl_bit(dcs_frame, T30_DCS_BIT_300_600))
-        s->y_resolution = T4_Y_RESOLUTION_600;
-    else if (test_ctrl_bit(dcs_frame, T30_DCS_BIT_200_400)  ||  test_ctrl_bit(dcs_frame, T30_DCS_BIT_400_400))
-        s->y_resolution = T4_Y_RESOLUTION_SUPERFINE;
+    {
+        if ((s->supported_resolutions & T30_SUPPORT_400_800_RESOLUTION))
+        {
+            s->x_resolution = T4_X_RESOLUTION_R16;
+            s->y_resolution = T4_Y_RESOLUTION_800;
+            x = 3;
+        }
+    }
+    else if (test_ctrl_bit(dcs_frame, T30_DCS_BIT_400_400))
+    {
+        if ((s->supported_resolutions & T30_SUPPORT_400_400_RESOLUTION))
+        {
+            s->x_resolution = T4_X_RESOLUTION_R16;
+            s->y_resolution = T4_Y_RESOLUTION_SUPERFINE;
+            x = 3;
+        }
+    }
+    else if (test_ctrl_bit(dcs_frame, T30_DCS_BIT_300_600))
+    {
+        if ((s->supported_resolutions & T30_SUPPORT_300_600_RESOLUTION))
+        {
+            s->x_resolution = T4_X_RESOLUTION_300;
+            s->y_resolution = T4_Y_RESOLUTION_600;
+            x = 2;
+        }
+    }
     else if (test_ctrl_bit(dcs_frame, T30_DCS_BIT_300_300))
-        s->y_resolution = T4_Y_RESOLUTION_300;
+    {
+        if ((s->supported_resolutions & T30_SUPPORT_300_300_RESOLUTION))
+        {
+            s->x_resolution = T4_X_RESOLUTION_300;
+            s->y_resolution = T4_Y_RESOLUTION_300;
+            x = 2;
+        }
+    }
+    else if (test_ctrl_bit(dcs_frame, T30_DCS_BIT_200_400))
+    {
+        if ((s->supported_resolutions & T30_SUPPORT_SUPERFINE_RESOLUTION))
+        {
+            s->x_resolution = T4_X_RESOLUTION_R8;
+            s->y_resolution = T4_Y_RESOLUTION_SUPERFINE;
+            x = 1;
+        }
+    }
     else if (test_ctrl_bit(dcs_frame, T30_DCS_BIT_200_200))
-        s->y_resolution = T4_Y_RESOLUTION_FINE;
+    {
+        if ((s->supported_resolutions & T30_SUPPORT_FINE_RESOLUTION))
+        {
+            s->x_resolution = T4_X_RESOLUTION_R8;
+            s->y_resolution = T4_Y_RESOLUTION_FINE;
+            x = 1;
+        }
+    }
     else
+    {
+        s->x_resolution = T4_X_RESOLUTION_R8;
         s->y_resolution = T4_Y_RESOLUTION_STANDARD;
+        x = 1;
+    }
 
-    if (s->x_resolution == T4_X_RESOLUTION_1200)
-        i = 5;
-    else if (s->x_resolution == T4_X_RESOLUTION_600)
-        i = 4;
-    else if (s->x_resolution == T4_X_RESOLUTION_R16)
-        i = 3;
-    else if (s->x_resolution == T4_X_RESOLUTION_300)
-        i = 2;
-    else if (s->x_resolution == T4_X_RESOLUTION_R4)
-        i = 0;
-    else
-        i = 1;
+    if (x < 0)
+    {
+        t30_set_status(s, T30_ERR_NORESSUPPORT);
+        return -1;
+    }
 
-    s->image_width = widths[i][dcs_frame[5] & (DISBIT2 | DISBIT1)];
+    s->image_width = widths[x][dcs_frame[5] & (DISBIT2 | DISBIT1)];
 
     /* Check which compression the far end has decided to use. */
 #if defined(SPANDSP_SUPPORT_T42)
index 639ae0770c0eb2d03a525b9f138604f5667a29e1..e1cfdc005a0854c4bb60d2798330b1785cb921dc 100644 (file)
@@ -387,9 +387,9 @@ static int cmp(const void *s, const void *t)
 SPAN_DECLARE(int) v18_encode_dtmf(v18_state_t *s, char dtmf[], const char msg[])
 {
     const char *t;
-    char *u;
     const char *v;
-    
+    char *u;
+
     t = msg;
     u = dtmf;
     while (*t)
@@ -685,7 +685,8 @@ static void v18_tdd_put_async_byte(void *user_data, int byte)
             {
                 /* Whatever we have to date constitutes the message */
                 s->rx_msg[s->rx_msg_len] = '\0';
-                s->put_msg(s->user_data, s->rx_msg, s->rx_msg_len);
+                if (s->put_msg)
+                    s->put_msg(s->user_data, s->rx_msg, s->rx_msg_len);
                 s->rx_msg_len = 0;
             }
             break;
@@ -701,7 +702,8 @@ static void v18_tdd_put_async_byte(void *user_data, int byte)
     if (s->rx_msg_len >= 256)
     {
         s->rx_msg[s->rx_msg_len] = '\0';
-        s->put_msg(s->user_data, s->rx_msg, s->rx_msg_len);
+        if (s->put_msg)
+            s->put_msg(s->user_data, s->rx_msg, s->rx_msg_len);
         s->rx_msg_len = 0;
     }
 }
@@ -815,6 +817,33 @@ SPAN_DECLARE(int) v18_put(v18_state_t *s, const char msg[], int len)
 }
 /*- End of function --------------------------------------------------------*/
 
+SPAN_DECLARE(const char *) v18_mode_to_str(int mode)
+{
+    switch (mode & 0xFF)
+    {
+    case V18_MODE_NONE:
+        return "None";
+    case V18_MODE_5BIT_45:
+        return "Weitbrecht TDD (45.45bps)";
+    case V18_MODE_5BIT_50:
+        return "Weitbrecht TDD (50bps)";
+    case V18_MODE_DTMF:
+        return "DTMF";
+    case V18_MODE_EDT:
+        return "EDT";
+    case V18_MODE_BELL103:
+        return "Bell 103";
+    case V18_MODE_V23VIDEOTEX:
+        return "Videotex";
+    case V18_MODE_V21TEXTPHONE:
+        return "V.21";
+    case V18_MODE_V18TEXTPHONE:
+        return "V.18 text telephone";
+    }
+    return "???";
+}
+/*- End of function --------------------------------------------------------*/
+
 SPAN_DECLARE(logging_state_t *) v18_get_logging_state(v18_state_t *s)
 {
     return &s->logging;
@@ -863,7 +892,7 @@ SPAN_DECLARE(v18_state_t *) v18_init(v18_state_t *s,
         s->repeat_shifts = mode & 0x100;
         break;
     case V18_MODE_DTMF:
-        dtmf_tx_init(&s->dtmftx);
+        dtmf_tx_init(&s->dtmftx, NULL, NULL);
         dtmf_rx_init(&s->dtmfrx, v18_rx_dtmf, s);
         break;
     case V18_MODE_EDT:
@@ -909,31 +938,4 @@ SPAN_DECLARE(int) v18_free(v18_state_t *s)
     return 0;
 }
 /*- End of function --------------------------------------------------------*/
-
-SPAN_DECLARE(const char *) v18_mode_to_str(int mode)
-{
-    switch (mode & 0xFF)
-    {
-    case V18_MODE_NONE:
-        return "None";
-    case V18_MODE_5BIT_45:
-        return "Weitbrecht TDD (45.45bps)";
-    case V18_MODE_5BIT_50:
-        return "Weitbrecht TDD (50bps)";
-    case V18_MODE_DTMF:
-        return "DTMF";
-    case V18_MODE_EDT:
-        return "EDT";
-    case V18_MODE_BELL103:
-        return "Bell 103";
-    case V18_MODE_V23VIDEOTEX:
-        return "Videotex";
-    case V18_MODE_V21TEXTPHONE:
-        return "V.21";
-    case V18_MODE_V18TEXTPHONE:
-        return "V.18 text telephone";
-    }
-    return "???";
-}
-/*- End of function --------------------------------------------------------*/
 /*- End of file ------------------------------------------------------------*/
index eec5a8709983563299b4432ffb024b224ec997d7..3e73d67c27aeb7f2927656a21cdb822f0592fab1 100644 (file)
@@ -1554,16 +1554,18 @@ SPAN_DECLARE(v42_state_t *) v42_init(v42_state_t *ss,
 }
 /*- End of function --------------------------------------------------------*/
 
-SPAN_DECLARE(void) v42_release(v42_state_t *s)
+SPAN_DECLARE(int) v42_release(v42_state_t *s)
 {
     reset_lapm(s);
+    return 0;
 }
 /*- End of function --------------------------------------------------------*/
 
-SPAN_DECLARE(void) v42_free(v42_state_t *s)
+SPAN_DECLARE(int) v42_free(v42_state_t *s)
 {
     v42_release(s);
     free(s);
+    return 0;
 }
 /*- End of function --------------------------------------------------------*/
 /*- End of file ------------------------------------------------------------*/