diff --git a/libs/freetdm/src/ftdm_io.c b/libs/freetdm/src/ftdm_io.c index 58fa998390..650ef359d4 100644 --- a/libs/freetdm/src/ftdm_io.c +++ b/libs/freetdm/src/ftdm_io.c @@ -59,6 +59,8 @@ struct tm *localtime_r(const time_t *clock, struct tm *result); #define FTDM_HALF_DTMF_PAUSE 500 #define FTDM_FULL_DTMF_PAUSE 1000 +#define FTDM_CHANNEL_SW_DTMF_ALLOWED(ftdmchan) (!ftdm_channel_test_feature(ftdmchan, FTDM_CHANNEL_FEATURE_DTMF_DETECT) && !ftdm_test_flag(ftdmchan, FTDM_CHANNEL_SIG_DTMF_DETECTION)) + ftdm_time_t time_last_throttle_log = 0; ftdm_time_t time_current_throttle_log = 0; @@ -105,6 +107,7 @@ static val_str_t channel_flag_strs[] = { { "blocking", FTDM_CHANNEL_BLOCKING}, { "media", FTDM_CHANNEL_DIGITAL_MEDIA}, { "native-sigbridge", FTDM_CHANNEL_NATIVE_SIGBRIDGE}, + { "sig-dtmf-detection", FTDM_CHANNEL_SIG_DTMF_DETECTION}, { "invalid", FTDM_CHANNEL_MAX_FLAG}, }; @@ -3370,7 +3373,7 @@ FT_DECLARE(ftdm_status_t) ftdm_channel_command(ftdm_channel_t *ftdmchan, ftdm_co { /* if they don't have thier own, use ours */ if (FTDM_IS_VOICE_CHANNEL(ftdmchan)) { - if (!ftdm_channel_test_feature(ftdmchan, FTDM_CHANNEL_FEATURE_DTMF_DETECT)) { + if (FTDM_CHANNEL_SW_DTMF_ALLOWED(ftdmchan)) { teletone_dtmf_detect_init (&ftdmchan->dtmf_detect, ftdmchan->rate); ftdm_set_flag(ftdmchan, FTDM_CHANNEL_DTMF_DETECT); ftdm_set_flag(ftdmchan, FTDM_CHANNEL_SUPRESS_DTMF); @@ -3383,9 +3386,9 @@ FT_DECLARE(ftdm_status_t) ftdm_channel_command(ftdm_channel_t *ftdmchan, ftdm_co case FTDM_COMMAND_DISABLE_DTMF_DETECT: { if (FTDM_IS_VOICE_CHANNEL(ftdmchan)) { - if (!ftdm_channel_test_feature(ftdmchan, FTDM_CHANNEL_FEATURE_DTMF_DETECT)) { - teletone_dtmf_detect_init (&ftdmchan->dtmf_detect, ftdmchan->rate); - ftdm_clear_flag(ftdmchan, FTDM_CHANNEL_DTMF_DETECT); + if (FTDM_CHANNEL_SW_DTMF_ALLOWED(ftdmchan)) { + teletone_dtmf_detect_init (&ftdmchan->dtmf_detect, ftdmchan->rate); + ftdm_clear_flag(ftdmchan, FTDM_CHANNEL_DTMF_DETECT); ftdm_clear_flag(ftdmchan, FTDM_CHANNEL_SUPRESS_DTMF); ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Disabled software DTMF detector\n"); GOTO_STATUS(done, FTDM_SUCCESS); @@ -3461,8 +3464,11 @@ FT_DECLARE(ftdm_status_t) ftdm_channel_command(ftdm_channel_t *ftdmchan, ftdm_co break; case FTDM_COMMAND_SEND_DTMF: { - if (!ftdm_channel_test_feature(ftdmchan, FTDM_CHANNEL_FEATURE_DTMF_GENERATE)) { - char *digits = FTDM_COMMAND_OBJ_CHAR_P; + char *digits = FTDM_COMMAND_OBJ_CHAR_P; + if (ftdmchan->span->sig_send_dtmf) { + status = ftdmchan->span->sig_send_dtmf(ftdmchan, digits); + GOTO_STATUS(done, status); + } else if (!ftdm_channel_test_feature(ftdmchan, FTDM_CHANNEL_FEATURE_DTMF_GENERATE)) { if ((status = ftdmchan_activate_dtmf_buffer(ftdmchan)) != FTDM_SUCCESS) { GOTO_STATUS(done, status); @@ -3773,7 +3779,7 @@ FT_DECLARE(ftdm_status_t) ftdm_channel_queue_dtmf(ftdm_channel_t *ftdmchan, cons ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Queuing DTMF %s (debug = %d)\n", dtmf, ftdmchan->dtmfdbg.enabled); - if (ftdmchan->span->sig_dtmf && (ftdmchan->span->sig_dtmf(ftdmchan, dtmf) == FTDM_BREAK)) { + if (ftdmchan->span->sig_queue_dtmf && (ftdmchan->span->sig_queue_dtmf(ftdmchan, dtmf) == FTDM_BREAK)) { /* Signalling module wants to absorb this DTMF event */ return FTDM_SUCCESS; } @@ -4212,7 +4218,7 @@ FT_DECLARE(ftdm_status_t) ftdm_channel_process_media(ftdm_channel_t *ftdmchan, v } } - if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_DTMF_DETECT) && !ftdm_channel_test_feature(ftdmchan, FTDM_CHANNEL_FEATURE_DTMF_DETECT)) { + if (FTDM_CHANNEL_SW_DTMF_ALLOWED(ftdmchan) && ftdm_test_flag(ftdmchan, FTDM_CHANNEL_DTMF_DETECT)) { teletone_hit_type_t hit; char digit_char; uint32_t dur; diff --git a/libs/freetdm/src/ftmod/ftmod_gsm/ftmod_gsm.c b/libs/freetdm/src/ftmod/ftmod_gsm/ftmod_gsm.c index 689156919f..c89e3ae520 100755 --- a/libs/freetdm/src/ftmod/ftmod_gsm/ftmod_gsm.c +++ b/libs/freetdm/src/ftmod/ftmod_gsm/ftmod_gsm.c @@ -879,6 +879,30 @@ static ftdm_status_t init_wat_lib(void) return FTDM_SUCCESS; } +WAT_AT_CMD_RESPONSE_FUNC(on_dtmf_sent) +{ + ftdm_channel_t *ftdmchan = obj; + ftdm_span_t *span = ftdmchan->span; + int i = 0; + + if (success == WAT_TRUE) { + ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "DTMF successfully transmitted on span %s\n", span->name); + } else { + ftdm_log_chan(ftdmchan, FTDM_LOG_ERROR, "Command execution failed on span %s. Err: %s\n", span->name, error); + } + + for (i = 0; tokens[i]; i++) { + ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "%s\n", tokens[i]); + } + return i; +} + +static ftdm_status_t ftdm_gsm_send_dtmf(ftdm_channel_t *ftdmchan, const char* dtmf) +{ + ftdm_gsm_span_data_t *gsm_data = ftdmchan->span->signal_data; + wat_send_dtmf(ftdmchan->span->span_id, gsm_data->call_id, dtmf, on_dtmf_sent, ftdmchan); + return FTDM_SUCCESS; +} static FIO_CONFIGURE_SPAN_SIGNALING_FUNCTION(ftdm_gsm_configure_span_signaling) { @@ -956,9 +980,6 @@ static FIO_CONFIGURE_SPAN_SIGNALING_FUNCTION(ftdm_gsm_configure_span_signaling) gsm_data->dchan = dchan; gsm_data->bchan = bchan; - //sprintf(gsm_data->dchan->chan_name, "%s\t\n", "GSM dchan"); - //sprintf(gsm_data->bchan->chan_name, "%s\r\n", "GSM bchan"); - for (paramindex = 0; ftdm_parameters[paramindex].var; paramindex++) { var = ftdm_parameters[paramindex].var; val = ftdm_parameters[paramindex].val; @@ -984,7 +1005,6 @@ static FIO_CONFIGURE_SPAN_SIGNALING_FUNCTION(ftdm_gsm_configure_span_signaling) span_config.hardware_dtmf = WAT_FALSE; } ftdm_log(FTDM_LOG_DEBUG, "Configuring GSM span %s with hardware dtmf %s\n", span->name, val); - ftdm_channel_set_feature(gsm_data->bchan, FTDM_CHANNEL_FEATURE_DTMF_DETECT); } else { ftdm_log(FTDM_LOG_ERROR, "Ignoring unknown GSM parameter '%s'", var); } @@ -995,6 +1015,10 @@ static FIO_CONFIGURE_SPAN_SIGNALING_FUNCTION(ftdm_gsm_configure_span_signaling) span->stop = ftdm_gsm_stop; span->sig_read = NULL; span->sig_write = NULL; + if (span_config.hardware_dtmf == WAT_TRUE) { + span->sig_send_dtmf = ftdm_gsm_send_dtmf; + ftdm_set_flag(ftdmchan, FTDM_CHANNEL_SIG_DTMF_DETECTION); + } span->signal_cb = sig_cb; span->signal_type = FTDM_SIGTYPE_GSM; diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn.c b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn.c index c8b520783e..ed0a99dc95 100644 --- a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn.c +++ b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn.c @@ -1304,7 +1304,7 @@ static FIO_CONFIGURE_SPAN_SIGNALING_FUNCTION(ftdm_sangoma_isdn_span_config) span->indicate = ftdm_sangoma_isdn_indicate; span->channel_request = NULL; span->signal_cb = sig_cb; - span->sig_dtmf = ftdm_sangoma_isdn_dtmf; + span->sig_queue_dtmf = ftdm_sangoma_isdn_dtmf; span->get_channel_sig_status = ftdm_sangoma_isdn_get_chan_sig_status; span->set_channel_sig_status = ftdm_sangoma_isdn_set_chan_sig_status; span->get_span_sig_status = ftdm_sangoma_isdn_get_span_sig_status; diff --git a/libs/freetdm/src/include/private/ftdm_core.h b/libs/freetdm/src/include/private/ftdm_core.h index 728390dd54..f4a1fe4e29 100644 --- a/libs/freetdm/src/include/private/ftdm_core.h +++ b/libs/freetdm/src/include/private/ftdm_core.h @@ -513,7 +513,8 @@ struct ftdm_span { ftdm_span_stop_t stop; ftdm_channel_sig_read_t sig_read; ftdm_channel_sig_write_t sig_write; - ftdm_channel_sig_dtmf_t sig_dtmf; + ftdm_channel_sig_dtmf_t sig_queue_dtmf; + ftdm_channel_sig_dtmf_t sig_send_dtmf; ftdm_channel_state_processor_t state_processor; /*!< This guy is called whenever state processing is required */ void *io_data; /*!< Private I/O data per span. Do not touch unless you are an I/O module */ char *type; diff --git a/libs/freetdm/src/include/private/ftdm_types.h b/libs/freetdm/src/include/private/ftdm_types.h index 9e8aebe157..ee3406ea31 100755 --- a/libs/freetdm/src/include/private/ftdm_types.h +++ b/libs/freetdm/src/include/private/ftdm_types.h @@ -268,9 +268,11 @@ typedef enum { #define FTDM_CHANNEL_DIGITAL_MEDIA (1ULL << 36) /*!< Native signaling bridge is enabled */ #define FTDM_CHANNEL_NATIVE_SIGBRIDGE (1ULL << 37) +/*!< Native signaling DTMF detection */ +#define FTDM_CHANNEL_SIG_DTMF_DETECTION (1ULL << 38) /*!< This no more flags after this flag */ -#define FTDM_CHANNEL_MAX_FLAG (1ULL << 38) +#define FTDM_CHANNEL_MAX_FLAG (1ULL << 39) /*!