From 27096d4512ef6bf21403aa0f466908d940db0078 Mon Sep 17 00:00:00 2001 From: David Yat Sin Date: Tue, 28 Sep 2010 13:55:46 -0400 Subject: [PATCH] Support for enabling/disabling HWEC based on call bearer_cap --- libs/freetdm/src/ftdm_io.c | 54 ++++++++++++++++--- .../src/ftmod/ftmod_wanpipe/ftmod_wanpipe.c | 38 ++++++++++++- libs/freetdm/src/include/private/ftdm_types.h | 2 + 3 files changed, 86 insertions(+), 8 deletions(-) diff --git a/libs/freetdm/src/ftdm_io.c b/libs/freetdm/src/ftdm_io.c index 79d55c4d16..df139c548e 100644 --- a/libs/freetdm/src/ftdm_io.c +++ b/libs/freetdm/src/ftdm_io.c @@ -244,6 +244,39 @@ static __inline__ void ftdm_std_free(void *pool, void *ptr) free(ptr); } +static void ftdm_set_echocancel_call_begin(ftdm_channel_t *chan) +{ + ftdm_caller_data_t *caller_data = ftdm_channel_get_caller_data(chan); + if (ftdm_channel_test_feature(chan, FTDM_CHANNEL_FEATURE_HWEC)) { + if (ftdm_channel_test_feature(chan, FTDM_CHANNEL_FEATURE_HWEC_DISABLED_ON_IDLE)) { + if (caller_data->bearer_capability != FTDM_BEARER_CAP_64K_UNRESTRICTED) { + ftdm_channel_command(chan, FTDM_COMMAND_ENABLE_ECHOCANCEL, NULL); + } + } else { + if (caller_data->bearer_capability == FTDM_BEARER_CAP_64K_UNRESTRICTED) { + ftdm_channel_command(chan, FTDM_COMMAND_DISABLE_ECHOCANCEL, NULL); + } + } + } +} + +static void ftdm_set_echocancel_call_end(ftdm_channel_t *chan) +{ + ftdm_caller_data_t *caller_data = ftdm_channel_get_caller_data(chan); + if (ftdm_channel_test_feature(chan, FTDM_CHANNEL_FEATURE_HWEC)) { + if (ftdm_channel_test_feature(chan, FTDM_CHANNEL_FEATURE_HWEC_DISABLED_ON_IDLE)) { + if (caller_data->bearer_capability != FTDM_BEARER_CAP_64K_UNRESTRICTED) { + ftdm_channel_command(chan, FTDM_COMMAND_DISABLE_ECHOCANCEL, NULL); + } + } else { + if (caller_data->bearer_capability == FTDM_BEARER_CAP_64K_UNRESTRICTED) { + ftdm_channel_command(chan, FTDM_COMMAND_ENABLE_ECHOCANCEL, NULL); + } + } + } +} + + FT_DECLARE_DATA ftdm_memory_handler_t g_ftdm_mem_handler = { /*.pool =*/ NULL, @@ -2008,6 +2041,9 @@ done: static ftdm_status_t call_hangup(ftdm_channel_t *chan, const char *file, const char *func, int line) { ftdm_set_flag(chan, FTDM_CHANNEL_USER_HANGUP); + + ftdm_set_echocancel_call_end(chan); + if (chan->state != FTDM_CHANNEL_STATE_DOWN) { if (chan->state == FTDM_CHANNEL_STATE_HANGUP) { /* make user's life easier, and just ignore double hangup requests */ @@ -2173,10 +2209,12 @@ done: FT_DECLARE(ftdm_status_t) _ftdm_channel_call_place(const char *file, const char *func, int line, ftdm_channel_t *ftdmchan) { ftdm_status_t status = FTDM_FAIL; - + ftdm_assert_return(ftdmchan != NULL, FTDM_FAIL, "null channel"); ftdm_assert_return(ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OUTBOUND), FTDM_FAIL, "Call place, but outbound flag not set\n"); + ftdm_set_echocancel_call_begin(ftdmchan); + ftdm_channel_lock(ftdmchan); if (ftdmchan->span->outgoing_call) { @@ -4740,11 +4778,15 @@ FT_DECLARE(ftdm_status_t) ftdm_span_send_signal(ftdm_span_t *span, ftdm_sigmsg_t break; case FTDM_SIGEVENT_START: - /* when cleaning up the public API I added this because mod_freetdm.c on_fxs_signal was - * doing it during SIGEVENT_START, but now that flags are private they can't, wonder if - * is needed at all? - * */ - ftdm_clear_flag(sigmsg->channel, FTDM_CHANNEL_HOLD); + { + ftdm_set_echocancel_call_begin(sigmsg->channel); + + /* when cleaning up the public API I added this because mod_freetdm.c on_fxs_signal was + * doing it during SIGEVENT_START, but now that flags are private they can't, wonder if + * is needed at all? + * */ + ftdm_clear_flag(sigmsg->channel, FTDM_CHANNEL_HOLD); + } break; case FTDM_SIGEVENT_STOP: diff --git a/libs/freetdm/src/ftmod/ftmod_wanpipe/ftmod_wanpipe.c b/libs/freetdm/src/ftmod/ftmod_wanpipe/ftmod_wanpipe.c index be99f94aff..23463e9088 100644 --- a/libs/freetdm/src/ftmod/ftmod_wanpipe/ftmod_wanpipe.c +++ b/libs/freetdm/src/ftmod/ftmod_wanpipe/ftmod_wanpipe.c @@ -280,6 +280,25 @@ static unsigned wp_open_range(ftdm_span_t *span, unsigned spanno, unsigned start ftdm_channel_set_feature(chan, FTDM_CHANNEL_FEATURE_DTMF_DETECT); dtmf = "hardware"; } + + err = sangoma_tdm_get_hw_ec(chan->sockfd, &tdm_api); + if (err > 0) { + ftdm_channel_set_feature(chan, FTDM_CHANNEL_FEATURE_HWEC); + } + +#ifdef WP_API_FEATURE_HWEC_PERSIST + err = sangoma_tdm_get_hwec_persist_status(chan->sockfd, &tdm_api); + if (err == 0) { + ftdm_channel_set_feature(chan, FTDM_CHANNEL_FEATURE_HWEC_DISABLED_ON_IDLE); + } +#else + if (span->trunk_type == FTDM_TRUNK_BRI || span->trunk_type == FTDM_TRUNK_BRI_PTMP) { + ftdm_log(FTDM_LOG_WARNING, "WP_API_FEATURE_HWEC_PERSIST feature is not supported \ + with your version of libsangoma, you should update your Wanpipe drivers\n"); + + } +#endif + } #ifdef LIBSANGOMA_VERSION @@ -598,18 +617,33 @@ static FIO_COMMAND_FUNCTION(wanpipe_command) break; case FTDM_COMMAND_ENABLE_ECHOCANCEL: { +#ifdef WP_API_FEATURE_EC_CHAN_STAT + err=sangoma_tdm_get_hwec_chan_status(ftdmchan->sockfd, &tdm_api); + if (err > 0) { + /* Hardware echo canceller already enabled */ + err = 0; + break; + } +#endif err=sangoma_tdm_enable_hwec(ftdmchan->sockfd, &tdm_api); if (err) { - snprintf(ftdmchan->last_error, sizeof(ftdmchan->last_error), "HWEC Enable Failed"); + snprintf(ftdmchan->last_error, sizeof(ftdmchan->last_error), "HWEC Enable Failed"); return FTDM_FAIL; } } break; case FTDM_COMMAND_DISABLE_ECHOCANCEL: { +#ifdef WP_API_FEATURE_EC_CHAN_STAT + err=sangoma_tdm_get_hwec_chan_status(ftdmchan->sockfd, &tdm_api); + if (!err) { + /* Hardware echo canceller already disabled */ + break; + } +#endif err=sangoma_tdm_disable_hwec(ftdmchan->sockfd, &tdm_api); if (err) { - snprintf(ftdmchan->last_error, sizeof(ftdmchan->last_error), "HWEC Disable Failed"); + snprintf(ftdmchan->last_error, sizeof(ftdmchan->last_error), "HWEC Disable Failed"); return FTDM_FAIL; } } diff --git a/libs/freetdm/src/include/private/ftdm_types.h b/libs/freetdm/src/include/private/ftdm_types.h index d0d19e5a55..016fd31c43 100644 --- a/libs/freetdm/src/include/private/ftdm_types.h +++ b/libs/freetdm/src/include/private/ftdm_types.h @@ -191,6 +191,8 @@ typedef enum { FTDM_CHANNEL_FEATURE_CALLERID = (1 << 4), /*!< Channel can detect caller id (read-only) */ FTDM_CHANNEL_FEATURE_PROGRESS = (1 << 5), /*!< Channel can detect inband progress (read-only) */ FTDM_CHANNEL_FEATURE_CALLWAITING = (1 << 6), /*!< Channel will allow call waiting (ie: FXS devices) (read/write) */ + FTDM_CHANNEL_FEATURE_HWEC = (1<<7), /*!< Channel has a hardware echo canceller */ + FTDM_CHANNEL_FEATURE_HWEC_DISABLED_ON_IDLE = (1<<8), /*!< hardware echo canceller is disabled when there are no calls on this channel */ } ftdm_channel_feature_t; typedef enum {