Exemple #1
0
static int test_hdlc_crc_error_handling(void)
{
    int i;
    int j;
    int nextbyte;
    int corrupt;

    printf("Testing CRC error handling using CRC-16 (bit by bit)\n");
    frame_len_errors = 0;
    frame_data_errors = 0;
    hdlc_tx_init(&tx, FALSE, 2, FALSE, underflow_handler, NULL);
    hdlc_rx_init(&rx, FALSE, TRUE, 5, frame_handler, NULL);
    underflow_reported = FALSE;
    framing_ok_reported = FALSE;
    framing_ok_reports = 0;

    hdlc_tx_flags(&tx, 10);
    /* Don't push an initial message so we should get an underflow after the preamble. */
    /* Lie for the first message, as there isn't really one */
    frame_handled = TRUE;
    frame_failed = FALSE;
    frames_sent = 0;
    bytes_sent = 0;
    ref_len = 100;
    corrupt = FALSE;
    for (i = 0;  i < 8*1000000;  i++)
    {
        nextbyte = hdlc_tx_get_bit(&tx);
        hdlc_rx_put_bit(&rx, nextbyte);
        if (framing_ok_reported)
        {
            printf("Framing OK reported at bit %d (%d)\n", i, framing_ok_reports);
            framing_ok_reported = FALSE;
        }
        if (underflow_reported)
        {
            underflow_reported = FALSE;
            for (j = 0;  j < 20;  j++)
            {
                nextbyte = hdlc_tx_get_bit(&tx);
                hdlc_rx_put_bit(&rx, nextbyte);
                if (framing_ok_reported)
                {
                    printf("Framing OK reported at bit %d (%d) - %d\n", i, framing_ok_reports, frame_handled);
                    framing_ok_reported = FALSE;
                }
            }
            if (ref_len)
            {
                frames_sent++;
                bytes_sent += ref_len;
            }
            if (!frame_handled)
            {
                if (!corrupt)
                {
                    printf("Frame not received when it should be correct.\n");
                    return -1;
                }
            }
            else
            {
                if (corrupt)
                {
                    printf("Frame received when it should be corrupt.\n");
                    return -1;
                }
            }
            ref_len = cook_up_msg(buf);
            hdlc_tx_frame(&tx, buf, ref_len);
            if ((corrupt = rand() & 1))
                hdlc_tx_corrupt_frame(&tx);
            frame_handled = FALSE;
        }
    }

    printf("Tests passed.\n");
    return 0;
}
Exemple #2
0
static int test_hdlc_octet_count_handling(void)
{
    int i;
    int j;
    int nextbyte;

    printf("Testing the octet_counting handling using CRC-16 (bit by bit)\n");
    frame_len_errors = 0;
    frame_data_errors = 0;
    hdlc_tx_init(&tx, FALSE, 2, FALSE, underflow_handler, NULL);
    hdlc_rx_init(&rx, FALSE, TRUE, 0, frame_handler, NULL);
    //hdlc_rx_set_max_frame_len(&rx, 50);
    hdlc_rx_set_octet_counting_report_interval(&rx, 16);
    underflow_reported = FALSE;
    framing_ok_reported = FALSE;
    framing_ok_reports = 0;

    hdlc_tx_flags(&tx, 10);
    /* Don't push an initial message so we should get an underflow after the preamble. */
    /* Lie for the first message, as there isn't really one */
    frame_handled = TRUE;
    frame_failed = FALSE;
    frames_sent = 0;
    bytes_sent = 0;
    ref_len = 0;
    for (i = 0;  i < 8*1000000;  i++)
    {
        nextbyte = hdlc_tx_get_bit(&tx);
        hdlc_rx_put_bit(&rx, nextbyte);
        if (framing_ok_reported)
        {
            printf("Framing OK reported at bit %d (%d)\n", i, framing_ok_reports);
            framing_ok_reported = FALSE;
        }
        if (underflow_reported)
        {
            underflow_reported = FALSE;
            for (j = 0;  j < 20;  j++)
            {
                nextbyte = hdlc_tx_get_bit(&tx);
                hdlc_rx_put_bit(&rx, nextbyte);
                if (framing_ok_reported)
                {
                    printf("Framing OK reported at bit %d (%d) - %d\n", i, framing_ok_reports, frame_handled);
                    framing_ok_reported = FALSE;
                }
            }
            if (ref_len)
            {
                frames_sent++;
                bytes_sent += ref_len;
            }
            if (!frame_handled)
            {
                if (frame_failed)
                    printf("Frame failed.\n");
                printf("Frame not received.\n");
                return -1;
            }
            ref_len = cook_up_msg(buf);
            hdlc_tx_frame(&tx, buf, ref_len);
            hdlc_tx_abort(&tx);
            //hdlc_tx_corrupt_frame(&tx);
            frame_handled = FALSE;
        }
    }

    printf("Tests passed.\n");
    return 0;
}
Exemple #3
0
static int test_hdlc_frame_length_error_handling(void)
{
    int i;
    int j;
    int nextbyte;

    printf("Testing frame length error handling using CRC-16 (bit by bit)\n");
    frame_len_errors = 0;
    frame_data_errors = 0;
    hdlc_tx_init(&tx, FALSE, 2, FALSE, underflow_handler, NULL);
    hdlc_rx_init(&rx, FALSE, TRUE, 5, frame_handler, NULL);
    hdlc_rx_set_max_frame_len(&rx, 100);
    underflow_reported = FALSE;
    framing_ok_reported = FALSE;
    framing_ok_reports = 0;

    hdlc_tx_flags(&tx, 10);
    /* Don't push an initial message so we should get an underflow after the preamble. */
    /* Lie for the first message, as there isn't really one */
    frame_handled = TRUE;
    frame_failed = FALSE;
    frames_sent = 0;
    bytes_sent = 0;
    ref_len = 0;
    for (i = 0;  i < 8*1000000;  i++)
    {
        nextbyte = hdlc_tx_get_bit(&tx);
        hdlc_rx_put_bit(&rx, nextbyte);
        if (framing_ok_reported)
        {
            printf("Framing OK reported at bit %d (%d)\n", i, framing_ok_reports);
            framing_ok_reported = FALSE;
        }
        if (underflow_reported)
        {
            underflow_reported = FALSE;
            for (j = 0;  j < 20;  j++)
            {
                nextbyte = hdlc_tx_get_bit(&tx);
                hdlc_rx_put_bit(&rx, nextbyte);
                if (framing_ok_reported)
                {
                    printf("Framing OK reported at bit %d (%d) - %d\n", i, framing_ok_reports, frame_handled);
                    framing_ok_reported = FALSE;
                }
            }
            if (ref_len)
            {
                frames_sent++;
                bytes_sent += ref_len;
            }
            if (!frame_handled)
            {
                /* We should get a failure when the length reaches 101 */
                if (ref_len == 101)
                {
                    printf("Tests passed.\n");
                    return 0;
                }
                if (frame_failed)
                    printf("Frame failed.\n");
                printf("Frame not received at length %d.\n", ref_len);
                return -1;
            }
            else
            {
                /* We should get a failure when the length reaches 101 */
                if (ref_len > 100)
                {
                    printf("Tests failed.\n");
                    return -1;
                }
            }
            ref_len++;
            hdlc_tx_frame(&tx, buf, ref_len);
            frame_handled = FALSE;
        }
    }
    /* We shouldn't reach here */
    printf("Tests failed.\n");
    return -1;
}
Exemple #4
0
static int test_hdlc_modes(void)
{
    int i;
    int j;
    int len;
    int nextbyte;
    int progress;
    int progress_delay;
    uint8_t bufx[100];

    /* Try sending HDLC messages with CRC-16 */
    printf("Testing with CRC-16 (byte by byte)\n");
    frame_len_errors = 0;
    frame_data_errors = 0;
    hdlc_tx_init(&tx, FALSE, 1, FALSE, underflow_handler, NULL);
    hdlc_rx_init(&rx, FALSE, FALSE, 5, frame_handler, NULL);
    underflow_reported = FALSE;

    start = rdtscll();
    hdlc_tx_flags(&tx, 40);
    /* Push an initial message so we should NOT get an underflow after the preamble. */
    ref_len = cook_up_msg(buf);
    hdlc_tx_frame(&tx, buf, ref_len);
    frame_handled = FALSE;
    frame_failed = FALSE;
    frames_sent = 0;
    bytes_sent = 0;
    for (i = 0;  i < 1000000;  i++)
    {
        nextbyte = hdlc_tx_get_byte(&tx);
        hdlc_rx_put_byte(&rx, nextbyte);
        if (underflow_reported)
        {
            underflow_reported = FALSE;
            nextbyte = hdlc_tx_get_byte(&tx);
            hdlc_rx_put_byte(&rx, nextbyte);
            frames_sent++;
            bytes_sent += ref_len;
            if (!frame_handled)
            {
                printf("Frame not received.\n");
                return -1;
            }
            ref_len = cook_up_msg(buf);
            hdlc_tx_frame(&tx, buf, ref_len);
            frame_handled = FALSE;
        }
    }
    end = rdtscll();
    check_result();

    /* Now try sending HDLC messages with CRC-16 */
    printf("Testing with CRC-16 (chunk by chunk)\n");
    frame_len_errors = 0;
    frame_data_errors = 0;
    hdlc_tx_init(&tx, FALSE, 1, FALSE, underflow_handler, NULL);
    hdlc_rx_init(&rx, FALSE, FALSE, 5, frame_handler, NULL);
    underflow_reported = FALSE;

    start = rdtscll();
    hdlc_tx_flags(&tx, 40);
    /* Push an initial message so we should NOT get an underflow after the preamble. */
    ref_len = cook_up_msg(buf);
    hdlc_tx_frame(&tx, buf, ref_len);
    frame_handled = FALSE;
    frame_failed = FALSE;
    frames_sent = 0;
    bytes_sent = 0;
    for (i = 0;  i < 10000;  i++)
    {
        len = hdlc_tx_get(&tx, bufx, 100);
        hdlc_rx_put(&rx, bufx, len);
        if (underflow_reported)
        {
            underflow_reported = FALSE;
            len = hdlc_tx_get(&tx, bufx, 100);
            hdlc_rx_put(&rx, bufx, len);
            frames_sent++;
            bytes_sent += ref_len;
            if (!frame_handled)
            {
                printf("Frame not received.\n");
                return -1;
            }
            ref_len = cook_up_msg(buf);
            hdlc_tx_frame(&tx, buf, ref_len);
            frame_handled = FALSE;
        }
    }
    end = rdtscll();
    check_result();

    /* Now try sending HDLC messages with CRC-16 bit by bit */
    printf("Testing with CRC-16 (bit by bit)\n");
    frame_len_errors = 0;
    frame_data_errors = 0;
    hdlc_tx_init(&tx, FALSE, 2, FALSE, underflow_handler, NULL);
    hdlc_rx_init(&rx, FALSE, FALSE, 5, frame_handler, NULL);
    underflow_reported = FALSE;

    start = rdtscll();
    hdlc_tx_flags(&tx, 40);
    /* Don't push an initial message so we should get an underflow after the preamble. */
    /* Lie for the first message, as there isn't really one */
    frame_handled = TRUE;
    frame_failed = FALSE;
    frames_sent = 0;
    bytes_sent = 0;
    ref_len = 0;
    for (i = 0;  i < 8*1000000;  i++)
    {
        nextbyte = hdlc_tx_get_bit(&tx);
        hdlc_rx_put_bit(&rx, nextbyte);
        if (underflow_reported)
        {
            underflow_reported = FALSE;
            for (j = 0;  j < 20;  j++)
            {
                nextbyte = hdlc_tx_get_bit(&tx);
                hdlc_rx_put_bit(&rx, nextbyte);
            }
            if (ref_len)
            {
                frames_sent++;
                bytes_sent += ref_len;
            }
            if (!frame_handled)
            {
                printf("Frame not received.\n");
                return -1;
            }
            ref_len = cook_up_msg(buf);
            hdlc_tx_frame(&tx, buf, ref_len);
            frame_handled = FALSE;
        }
    }
    end = rdtscll();
    check_result();

    /* Now try sending HDLC messages with CRC-32 */
    printf("Testing with CRC-32 (byte by byte)\n");
    frame_len_errors = 0;
    frame_data_errors = 0;
    hdlc_tx_init(&tx, TRUE, 1, FALSE, underflow_handler, NULL);
    hdlc_rx_init(&rx, TRUE, FALSE, 1, frame_handler, NULL);
    underflow_reported = FALSE;

    start = rdtscll();
    hdlc_tx_flags(&tx, 40);
    /* Don't push an initial message so we should get an underflow after the preamble. */
    /* Lie for the first message, as there isn't really one */
    frame_handled = TRUE;
    frame_failed = FALSE;
    frames_sent = 0;
    bytes_sent = 0;
    ref_len = 0;
    for (i = 0;  i < 1000000;  i++)
    {
        nextbyte = hdlc_tx_get_byte(&tx);
        hdlc_rx_put_byte(&rx, nextbyte);
        if (underflow_reported)
        {
            underflow_reported = FALSE;
            nextbyte = hdlc_tx_get_byte(&tx);
            hdlc_rx_put_byte(&rx, nextbyte);
            if (ref_len)
            {
                frames_sent++;
                bytes_sent += ref_len;
            }
            if (!frame_handled)
            {
                printf("Frame not received.\n");
                return -1;
            }
            ref_len = cook_up_msg(buf);
            hdlc_tx_frame(&tx, buf, ref_len);
            frame_handled = FALSE;
        }
    }
    end = rdtscll();
    check_result();

    /* Now try progressive mode with CRC-16 */
    printf("Testing progressive mode with CRC-16 (byte by byte)\n");
    frame_len_errors = 0;
    frame_data_errors = 0;
    hdlc_tx_init(&tx, TRUE, 1, TRUE, underflow_handler, NULL);
    hdlc_rx_init(&rx, TRUE, FALSE, 1, frame_handler, NULL);
    underflow_reported = FALSE;

    start = rdtscll();
    hdlc_tx_flags(&tx, 40);
    /* Don't push an initial message so we should get an underflow after the preamble. */
    /* Lie for the first message, as there isn't really one */
    frame_handled = TRUE;
    frame_failed = FALSE;
    progress = 9999;
    progress_delay = 9999;
    frames_sent = 0;
    bytes_sent = 0;
    ref_len = 0;
    for (i = 0;  i < 1000000;  i++)
    {
        nextbyte = hdlc_tx_get_byte(&tx);
        hdlc_rx_put_byte(&rx, nextbyte);
        if (underflow_reported)
        {
            underflow_reported = FALSE;
            nextbyte = hdlc_tx_get_byte(&tx);
            hdlc_rx_put_byte(&rx, nextbyte);
            if (ref_len)
            {
                frames_sent++;
                bytes_sent += ref_len;
            }
            if (!frame_handled)
            {
                printf("Frame not received.\n");
                return -1;
            }
            ref_len = cook_up_msg(buf);
            hdlc_tx_frame(&tx, buf, 10);
            progress = 10;
            progress_delay = 8;
            frame_handled = FALSE;
        }
        if (progress < ref_len  &&  progress_delay-- <= 0)
        {
            if (hdlc_tx_frame(&tx, buf + progress, (progress + 10 <= ref_len)  ?  10  :  ref_len - progress) < 0)
            {
                printf("Failed to add progressively\n");
                return -1;
            }
            progress += 10;
            progress_delay = 8;
        }
    }
    end = rdtscll();
    check_result();

    printf("Tests passed.\n");
    return 0;
}
Exemple #5
0
SPAN_DECLARE(void) fax_modems_hdlc_tx_flags(fax_modems_state_t *s, int flags)
{
    hdlc_tx_flags(&s->hdlc_tx, flags);
}
Exemple #6
0
static void fax_set_tx_type(void *user_data, int type, int bit_rate, int short_train, int use_hdlc)
{
    fax_state_t *s;
    get_bit_func_t get_bit_func;
    void *get_bit_user_data;
    fax_modems_state_t *t;
    int tone;

    s = (fax_state_t *) user_data;
    t = &s->modems;
    span_log(&s->logging, SPAN_LOG_FLOW, "Set tx type %d\n", type);
    if (t->current_tx_type == type)
        return;
    if (use_hdlc)
    {
        get_bit_func = (get_bit_func_t) hdlc_tx_get_bit;
        get_bit_user_data = (void *) &t->hdlc_tx;
    }
    else
    {
        get_bit_func = t30_non_ecm_get_bit;
        get_bit_user_data = (void *) &s->t30;
    }
    switch (type)
    {
    case T30_MODEM_PAUSE:
        silence_gen_alter(&t->silence_gen, ms_to_samples(short_train));
        set_tx_handler(s, (span_tx_handler_t *) &silence_gen, &t->silence_gen);
        set_next_tx_handler(s, (span_tx_handler_t *) NULL, NULL);
        t->transmit = TRUE;
        break;
    case T30_MODEM_CED:
    case T30_MODEM_CNG:
        if (type == T30_MODEM_CED)
            tone = MODEM_CONNECT_TONES_FAX_CED;
        else
            tone = MODEM_CONNECT_TONES_FAX_CNG;
        modem_connect_tones_tx_init(&t->connect_tx, tone);
        set_tx_handler(s, (span_tx_handler_t *) &modem_connect_tones_tx, &t->connect_tx);
        set_next_tx_handler(s, (span_tx_handler_t *) NULL, NULL);
        t->transmit = TRUE;
        break;
    case T30_MODEM_V21:
        fsk_tx_init(&t->v21_tx, &preset_fsk_specs[FSK_V21CH2], get_bit_func, get_bit_user_data);
        /* The spec says 1s +-15% of preamble. So, the minimum is 32 octets. */
        hdlc_tx_flags(&t->hdlc_tx, 32);
        /* Pause before switching from phase C, as per T.30 5.3.2.2. If we omit this, the receiver
           might not see the carrier fall between the high speed and low speed sections. In practice,
           a 75ms gap before any V.21 transmission is harmless, adds little to the overall length of
           a call, and ensures the receiving end is ready. */
        silence_gen_alter(&t->silence_gen, ms_to_samples(75));
        set_tx_handler(s, (span_tx_handler_t *) &silence_gen, &t->silence_gen);
        set_next_tx_handler(s, (span_tx_handler_t *) &fsk_tx, &t->v21_tx);
        t->transmit = TRUE;
        break;
    case T30_MODEM_V27TER:
        silence_gen_alter(&t->silence_gen, ms_to_samples(75));
        /* For any fast modem, set 200ms of preamble flags */
        hdlc_tx_flags(&t->hdlc_tx, bit_rate/(8*5));
        v27ter_tx_restart(&t->v27ter_tx, bit_rate, t->use_tep);
        v27ter_tx_set_get_bit(&t->v27ter_tx, get_bit_func, get_bit_user_data);
        set_tx_handler(s, (span_tx_handler_t *) &silence_gen, &t->silence_gen);
        set_next_tx_handler(s, (span_tx_handler_t *) &v27ter_tx, &t->v27ter_tx);
        t->transmit = TRUE;
        break;
    case T30_MODEM_V29:
        silence_gen_alter(&t->silence_gen, ms_to_samples(75));
        /* For any fast modem, set 200ms of preamble flags */
        hdlc_tx_flags(&t->hdlc_tx, bit_rate/(8*5));
        v29_tx_restart(&t->v29_tx, bit_rate, t->use_tep);
        v29_tx_set_get_bit(&t->v29_tx, get_bit_func, get_bit_user_data);
        set_tx_handler(s, (span_tx_handler_t *) &silence_gen, &t->silence_gen);
        set_next_tx_handler(s, (span_tx_handler_t *) &v29_tx, &t->v29_tx);
        t->transmit = TRUE;
        break;
    case T30_MODEM_V17:
        silence_gen_alter(&t->silence_gen, ms_to_samples(75));
        /* For any fast modem, set 200ms of preamble flags */
        hdlc_tx_flags(&t->hdlc_tx, bit_rate/(8*5));
        v17_tx_restart(&t->v17_tx, bit_rate, t->use_tep, short_train);
        v17_tx_set_get_bit(&t->v17_tx, get_bit_func, get_bit_user_data);
        set_tx_handler(s, (span_tx_handler_t *) &silence_gen, &t->silence_gen);
        set_next_tx_handler(s, (span_tx_handler_t *) &v17_tx, &t->v17_tx);
        t->transmit = TRUE;
        break;
    case T30_MODEM_DONE:
        span_log(&s->logging, SPAN_LOG_FLOW, "FAX exchange complete\n");
        /* Fall through */
    default:
        silence_gen_alter(&t->silence_gen, 0);
        set_tx_handler(s, (span_tx_handler_t *) &silence_gen, &t->silence_gen);
        set_next_tx_handler(s, (span_tx_handler_t *) NULL, NULL);
        t->transmit = FALSE;
        break;
    }
    t->tx_bit_rate = bit_rate;
    t->current_tx_type = type;
}
Exemple #7
0
static void fax_set_tx_type(void *user_data, int type, int short_train, int use_hdlc)
{
    fax_state_t *s;
    tone_gen_descriptor_t tone_desc;
    get_bit_func_t get_bit_func;
    void *get_bit_user_data;

    s = (fax_state_t *) user_data;
    span_log(&s->logging, SPAN_LOG_FLOW, "Set tx type %d\n", type);
    if (s->current_tx_type == type)
        return;
    s->first_tx_hdlc_frame = TRUE;
    if (use_hdlc)
    {
        get_bit_func = (get_bit_func_t) hdlc_tx_get_bit;
        get_bit_user_data = (void *) &(s->hdlctx);
    }
    else
    {
        get_bit_func = t30_non_ecm_get_bit;
        get_bit_user_data = (void *) &(s->t30_state);
    }
    switch (type)
    {
    case T30_MODEM_PAUSE:
        silence_gen_alter(&(s->silence_gen), ms_to_samples(short_train));
        s->tx_handler = (span_tx_handler_t *) &silence_gen;
        s->tx_user_data = &(s->silence_gen);
        s->next_tx_handler = NULL;
        s->transmit = TRUE;
        break;
    case T30_MODEM_CNG:
        /* 0.5s of 1100Hz+-38Hz + 3.0s of silence repeating. Timing +-15% */
        make_tone_gen_descriptor(&tone_desc,
                                 1100,
                                 -11,
                                 0,
                                 0,
                                 500,
                                 3000,
                                 0,
                                 0,
                                 TRUE);
        tone_gen_init(&(s->tone_gen), &tone_desc);
        s->tx_handler = (span_tx_handler_t *) &tone_gen;
        s->tx_user_data = &(s->tone_gen);
        s->next_tx_handler = NULL;
        s->transmit = TRUE;
        break;
    case T30_MODEM_CED:
        /* 0.2s of silence, then 2.6s to 4s of 2100Hz+-15Hz tone, then 75ms of silence. The 75ms of silence
           will be inserted by the pre V.21 pause we use for any switch to V.21. */
        silence_gen_alter(&(s->silence_gen), ms_to_samples(200));
        make_tone_gen_descriptor(&tone_desc,
                                 2100,
                                 -11,
                                 0,
                                 0,
                                 2600,
                                 0,
                                 0,
                                 0,
                                 FALSE);
        tone_gen_init(&(s->tone_gen), &tone_desc);
        s->tx_handler = (span_tx_handler_t *) &silence_gen;
        s->tx_user_data = &(s->silence_gen);
        s->next_tx_handler = (span_tx_handler_t *) &tone_gen;
        s->next_tx_user_data = &(s->tone_gen);
        s->transmit = TRUE;
        break;
    case T30_MODEM_V21:
        fsk_tx_init(&(s->v21tx), &preset_fsk_specs[FSK_V21CH2], get_bit_func, get_bit_user_data);
        /* The spec says 1s +-15% of preamble. So, the minimum is 32 octets. */
        hdlc_tx_flags(&(s->hdlctx), 32);
        /* Pause before switching from phase C, as per T.30 5.3.2.2. If we omit this, the receiver
           might not see the carrier fall between the high speed and low speed sections. In practice,
           a 75ms gap before any V.21 transmission is harmless, adds little to the overall length of
           a call, and ensures the receiving end is ready. */
        silence_gen_alter(&(s->silence_gen), ms_to_samples(75));
        s->tx_handler = (span_tx_handler_t *) &silence_gen;
        s->tx_user_data = &(s->silence_gen);
        s->next_tx_handler = (span_tx_handler_t *) &fsk_tx;
        s->next_tx_user_data = &(s->v21tx);
        s->transmit = TRUE;
        break;
    case T30_MODEM_V27TER_2400:
        silence_gen_alter(&(s->silence_gen), ms_to_samples(75));
        v27ter_tx_restart(&(s->v27ter_tx), 2400, s->use_tep);
        v27ter_tx_set_get_bit(&(s->v27ter_tx), get_bit_func, get_bit_user_data);
        s->tx_handler = (span_tx_handler_t *) &silence_gen;
        s->tx_user_data = &(s->silence_gen);
        s->next_tx_handler = (span_tx_handler_t *) &v27ter_tx;
        s->next_tx_user_data = &(s->v27ter_tx);
        hdlc_tx_flags(&(s->hdlctx), 60);
        s->transmit = TRUE;
        break;
    case T30_MODEM_V27TER_4800:
        silence_gen_alter(&(s->silence_gen), ms_to_samples(75));
        v27ter_tx_restart(&(s->v27ter_tx), 4800, s->use_tep);
        v27ter_tx_set_get_bit(&(s->v27ter_tx), get_bit_func, get_bit_user_data);
        s->tx_handler = (span_tx_handler_t *) &silence_gen;
        s->tx_user_data = &(s->silence_gen);
        s->next_tx_handler = (span_tx_handler_t *) &v27ter_tx;
        s->next_tx_user_data = &(s->v27ter_tx);
        hdlc_tx_flags(&(s->hdlctx), 120);
        s->transmit = TRUE;
        break;
    case T30_MODEM_V29_7200:
        silence_gen_alter(&(s->silence_gen), ms_to_samples(75));
        v29_tx_restart(&(s->v29tx), 7200, s->use_tep);
        v29_tx_set_get_bit(&(s->v29tx), get_bit_func, get_bit_user_data);
        s->tx_handler = (span_tx_handler_t *) &silence_gen;
        s->tx_user_data = &(s->silence_gen);
        s->next_tx_handler = (span_tx_handler_t *) &v29_tx;
        s->next_tx_user_data = &(s->v29tx);
        hdlc_tx_flags(&(s->hdlctx), 180);
        s->transmit = TRUE;
        break;
    case T30_MODEM_V29_9600:
        silence_gen_alter(&(s->silence_gen), ms_to_samples(75));
        v29_tx_restart(&(s->v29tx), 9600, s->use_tep);
        v29_tx_set_get_bit(&(s->v29tx), get_bit_func, get_bit_user_data);
        s->tx_handler = (span_tx_handler_t *) &silence_gen;
        s->tx_user_data = &(s->silence_gen);
        s->next_tx_handler = (span_tx_handler_t *) &v29_tx;
        s->next_tx_user_data = &(s->v29tx);
        hdlc_tx_flags(&(s->hdlctx), 240);
        s->transmit = TRUE;
        break;
    case T30_MODEM_V17_7200:
        silence_gen_alter(&(s->silence_gen), ms_to_samples(75));
        v17_tx_restart(&(s->v17tx), 7200, s->use_tep, short_train);
        v17_tx_set_get_bit(&(s->v17tx), get_bit_func, get_bit_user_data);
        s->tx_handler = (span_tx_handler_t *) &silence_gen;
        s->tx_user_data = &(s->silence_gen);
        s->next_tx_handler = (span_tx_handler_t *) &v17_tx;
        s->next_tx_user_data = &(s->v17tx);
        hdlc_tx_flags(&(s->hdlctx), 180);
        s->transmit = TRUE;
        break;
    case T30_MODEM_V17_9600:
        silence_gen_alter(&(s->silence_gen), ms_to_samples(75));
        v17_tx_restart(&(s->v17tx), 9600, s->use_tep, short_train);
        v17_tx_set_get_bit(&(s->v17tx), get_bit_func, get_bit_user_data);
        s->tx_handler = (span_tx_handler_t *) &silence_gen;
        s->tx_user_data = &(s->silence_gen);
        s->next_tx_handler = (span_tx_handler_t *) &v17_tx;
        s->next_tx_user_data = &(s->v17tx);
        hdlc_tx_flags(&(s->hdlctx), 240);
        s->transmit = TRUE;
        break;
    case T30_MODEM_V17_12000:
        silence_gen_alter(&(s->silence_gen), ms_to_samples(75));
        v17_tx_restart(&(s->v17tx), 12000, s->use_tep, short_train);
        v17_tx_set_get_bit(&(s->v17tx), get_bit_func, get_bit_user_data);
        s->tx_handler = (span_tx_handler_t *) &silence_gen;
        s->tx_user_data = &(s->silence_gen);
        s->next_tx_handler = (span_tx_handler_t *) &v17_tx;
        s->next_tx_user_data = &(s->v17tx);
        hdlc_tx_flags(&(s->hdlctx), 300);
        s->transmit = TRUE;
        break;
    case T30_MODEM_V17_14400:
        silence_gen_alter(&(s->silence_gen), ms_to_samples(75));
        v17_tx_restart(&(s->v17tx), 14400, s->use_tep, short_train);
        v17_tx_set_get_bit(&(s->v17tx), get_bit_func, get_bit_user_data);
        s->tx_handler = (span_tx_handler_t *) &silence_gen;
        s->tx_user_data = &(s->silence_gen);
        s->next_tx_handler = (span_tx_handler_t *) &v17_tx;
        s->next_tx_user_data = &(s->v17tx);
        hdlc_tx_flags(&(s->hdlctx), 360);
        s->transmit = TRUE;
        break;
    case T30_MODEM_DONE:
        span_log(&s->logging, SPAN_LOG_FLOW, "FAX exchange complete\n");
        /* Fall through */
    default:
        silence_gen_alter(&(s->silence_gen), 0);
        s->tx_handler = (span_tx_handler_t *) &silence_gen;
        s->tx_user_data = &(s->silence_gen);
        s->next_tx_handler = NULL;
        s->transmit = FALSE;
        break;
    }
    s->current_tx_type = type;
}