diff --git a/libs/freetdm/mod_freetdm/mod_freetdm.c b/libs/freetdm/mod_freetdm/mod_freetdm.c index 55f899e5c0..56eebd7dd5 100755 --- a/libs/freetdm/mod_freetdm/mod_freetdm.c +++ b/libs/freetdm/mod_freetdm/mod_freetdm.c @@ -3413,9 +3413,9 @@ static switch_status_t load_config(void) boost_span = boost_spans[i]; ftdm_log(FTDM_LOG_DEBUG, "Starting boost span %d\n", ftdm_span_get_id(boost_span)); if (ftdm_span_start(boost_span) == FTDM_FAIL) { - ftdm_log(FTDM_LOG_ERROR, "Error starting boost FreeTDM span %d, error: %s\n", - ftdm_span_get_id(boost_span), ftdm_span_get_last_error(boost_span)); - continue; + ftdm_log(FTDM_LOG_ERROR, "Error starting boost FreeTDM span %d, error: %s\n", + ftdm_span_get_id(boost_span), ftdm_span_get_last_error(boost_span)); + continue; } } diff --git a/libs/freetdm/src/ftdm_call_utils.c b/libs/freetdm/src/ftdm_call_utils.c index 4d7317ab22..d91b3bc9e2 100644 --- a/libs/freetdm/src/ftdm_call_utils.c +++ b/libs/freetdm/src/ftdm_call_utils.c @@ -78,6 +78,37 @@ FT_DECLARE(ftdm_status_t) ftdm_span_set_ton(const char *ton_string, uint8_t *tar return FTDM_SUCCESS; } +FT_DECLARE(ftdm_status_t) ftdm_span_set_bearer_capability(const char *bc_string, ftdm_bearer_cap_t *target) +{ + if (!strcasecmp(bc_string, "speech")) { + *target = FTDM_BEARER_CAP_SPEECH; + } else if (!strcasecmp(bc_string, "unrestricted-digital")) { + *target = FTDM_BEARER_CAP_64K_UNRESTRICTED; + } else if (!strcasecmp(bc_string, "3.1Khz")) { + *target = FTDM_BEARER_CAP_3_1KHZ_AUDIO; + } else { + ftdm_log(FTDM_LOG_WARNING, "Unsupported Bearer Capability value (%s)\n", bc_string); + return FTDM_FAIL; + } + return FTDM_SUCCESS; +} + +FT_DECLARE(ftdm_status_t) ftdm_span_set_bearer_layer1(const char *bc_string, ftdm_user_layer1_prot_t *target) +{ + if (!strcasecmp(bc_string, "v110")) { + *target = FTDM_USER_LAYER1_PROT_V110; + } else if (!strcasecmp(bc_string, "ulaw")) { + *target = FTDM_USER_LAYER1_PROT_ULAW; + } else if (!strcasecmp(bc_string, "alaw")) { + *target =FTDM_USER_LAYER1_PROT_ALAW ; + } else { + ftdm_log(FTDM_LOG_WARNING, "Unsupported Bearer Layer1 Prot value (%s)\n", bc_string); + return FTDM_FAIL; + } + return FTDM_SUCCESS; +} + + FT_DECLARE(ftdm_status_t) ftdm_is_number(char *number) { if (!number) { diff --git a/libs/freetdm/src/ftdm_io.c b/libs/freetdm/src/ftdm_io.c index ca00cdc9cd..fc32a0ff0f 100644 --- a/libs/freetdm/src/ftdm_io.c +++ b/libs/freetdm/src/ftdm_io.c @@ -293,6 +293,14 @@ static ftdm_status_t ftdm_set_caller_data(ftdm_span_t *span, ftdm_caller_data_t caller_data->rdnis.type = span->default_caller_data.rdnis.type; } + if (caller_data->bearer_capability == FTDM_INVALID_INT_PARM) { + caller_data->bearer_capability = span->default_caller_data.bearer_capability; + } + + if (caller_data->bearer_layer1 == FTDM_INVALID_INT_PARM) { + caller_data->bearer_layer1 = span->default_caller_data.bearer_layer1; + } + if (FTDM_FAIL == ftdm_is_number(caller_data->cid_num.digits)) { ftdm_log(FTDM_LOG_DEBUG, "dropping caller id number %s since we only accept digits\n", caller_data->cid_num.digits); caller_data->cid_num.digits[0] = '\0'; 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 ef440634c8..9ffd7097a3 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 @@ -281,8 +281,8 @@ static void *ftdm_sangoma_isdn_run(ftdm_thread_t *me, void *obj) while ((sngisdn_event = ftdm_queue_dequeue(signal_data->event_queue))) { ftdm_sangoma_isdn_process_stack_event(span, sngisdn_event); ftdm_safe_free(sngisdn_event); - } - ftdm_span_trigger_signals(span); + } + ftdm_span_trigger_signals(span); break; case FTDM_TIMEOUT: /* twiddle */ diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn.h b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn.h index 932db0e89e..3f63fbc1d4 100644 --- a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn.h +++ b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn.h @@ -320,6 +320,11 @@ void sngisdn_rcv_cc_ind(CcMngmt *status); void sngisdn_rcv_sng_log(uint8_t level, char *fmt,...); void sngisdn_rcv_sng_assert(char *message); +uint8_t sngisdn_get_infoTranCap_from_stack(ftdm_bearer_cap_t bearer_capability); +uint8_t sngisdn_get_usrInfoLyr1Prot_from_stack(ftdm_user_layer1_prot_t layer1_prot); +ftdm_bearer_cap_t sngisdn_get_infoTranCap_from_user(uint8_t bearer_capability); +ftdm_user_layer1_prot_t sngisdn_get_usrInfoLyr1Prot_from_user(uint8_t layer1_prot); + static __inline__ uint32_t sngisdn_test_flag(sngisdn_chan_data_t *sngisdn_info, sngisdn_flag_t flag) { return (uint32_t) sngisdn_info->flags & flag; diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_cfg.c b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_cfg.c index 6124070cad..ec44142303 100644 --- a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_cfg.c +++ b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_cfg.c @@ -163,6 +163,11 @@ ftdm_status_t ftmod_isdn_parse_cfg(ftdm_conf_parameter_t *ftdm_parameters, ftdm_ signal_data->overlap_dial = SNGISDN_OPT_DEFAULT; signal_data->setup_arb = SNGISDN_OPT_DEFAULT; + span->default_caller_data.bearer_capability = IN_ITC_SPEECH; + + /* Cannot set default bearer_layer1 yet, as we do not know the switchtype */ + span->default_caller_data.bearer_layer1 = FTDM_INVALID_INT_PARM; + if (span->trunk_type == FTDM_TRUNK_BRI || span->trunk_type == FTDM_TRUNK_BRI_PTMP) { @@ -240,6 +245,10 @@ ftdm_status_t ftmod_isdn_parse_cfg(ftdm_conf_parameter_t *ftdm_parameters, ftdm_ ftdm_span_set_ton(val, &span->default_caller_data.rdnis.type); } else if (!strcasecmp(var, "outbound-rdnis-npi")) { ftdm_span_set_npi(val, &span->default_caller_data.rdnis.plan); + } else if (!strcasecmp(var, "outbound-bearer_cap")) { + ftdm_span_set_bearer_capability(val, &span->default_caller_data.bearer_capability); + } else if (!strcasecmp(var, "outbound-bearer_layer1")) { + ftdm_span_set_bearer_layer1(val, &span->default_caller_data.bearer_layer1); } else { ftdm_log(FTDM_LOG_WARNING, "Ignoring unknown parameter %s\n", ftdm_parameters[paramindex].var); } @@ -253,6 +262,14 @@ ftdm_status_t ftmod_isdn_parse_cfg(ftdm_conf_parameter_t *ftdm_parameters, ftdm_ ftdm_log(FTDM_LOG_ERROR, "%s: signalling not specified", span->name); return FTDM_FAIL; } + + if (span->default_caller_data.bearer_layer1 == FTDM_INVALID_INT_PARM) { + if (signal_data->switchtype == SNGISDN_SWITCH_EUROISDN) { + span->default_caller_data.bearer_layer1 = IN_UIL1_G711ULAW; + } else { + span->default_caller_data.bearer_layer1 = IN_UIL1_G711ALAW; + } + } return FTDM_SUCCESS; } diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_hndl.c b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_hndl.c index 2520a3d9c3..c3d97e5c5c 100644 --- a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_hndl.c +++ b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_hndl.c @@ -34,10 +34,10 @@ #include "ftmod_sangoma_isdn.h" -extern ftdm_status_t cpy_calling_num_from_sngisdn(ftdm_caller_data_t *ftdm, CgPtyNmb *cgPtyNmb); -extern ftdm_status_t cpy_called_num_from_sngisdn(ftdm_caller_data_t *ftdm, CdPtyNmb *cdPtyNmb); -extern ftdm_status_t cpy_redir_num_from_sngisdn(ftdm_caller_data_t *ftdm, RedirNmb *redirNmb); -extern ftdm_status_t cpy_calling_name_from_sngisdn(ftdm_caller_data_t *ftdm, Display *display); +extern ftdm_status_t cpy_calling_num_from_stack(ftdm_caller_data_t *ftdm, CgPtyNmb *cgPtyNmb); +extern ftdm_status_t cpy_called_num_from_stack(ftdm_caller_data_t *ftdm, CdPtyNmb *cdPtyNmb); +extern ftdm_status_t cpy_redir_num_from_stack(ftdm_caller_data_t *ftdm, RedirNmb *redirNmb); +extern ftdm_status_t cpy_calling_name_from_stack(ftdm_caller_data_t *ftdm, Display *display); /* Remote side transmit a SETUP */ void sngisdn_process_con_ind (sngisdn_event_data_t *sngisdn_event) @@ -78,7 +78,7 @@ void sngisdn_process_con_ind (sngisdn_event_data_t *sngisdn_event) } sngisdn_info->suInstId = get_unique_suInstId(suId); - sngisdn_info->spInstId = spInstId; + sngisdn_info->spInstId = spInstId; /* If this is a glared call that was previously saved, we moved all the info to the current call, so clear the glared saved data */ @@ -87,10 +87,7 @@ void sngisdn_process_con_ind (sngisdn_event_data_t *sngisdn_event) clear_call_glare_data(sngisdn_info); } - ftdm_assert(g_sngisdn_data.ccs[suId].active_spInstIds[spInstId] == NULL, "Con Ind on busy spInstId"); - ftdm_mutex_lock(g_sngisdn_data.ccs[suId].mutex); - g_sngisdn_data.ccs[suId].active_spInstIds[spInstId] = sngisdn_info; g_sngisdn_data.ccs[suId].active_suInstIds[sngisdn_info->suInstId] = sngisdn_info; ftdm_mutex_unlock(g_sngisdn_data.ccs[suId].mutex); @@ -110,11 +107,15 @@ void sngisdn_process_con_ind (sngisdn_event_data_t *sngisdn_event) break; } /* Fill in call information */ - cpy_calling_num_from_sngisdn(&ftdmchan->caller_data, &conEvnt->cgPtyNmb); - cpy_called_num_from_sngisdn(&ftdmchan->caller_data, &conEvnt->cdPtyNmb); - cpy_calling_name_from_sngisdn(&ftdmchan->caller_data, &conEvnt->display); + cpy_calling_num_from_stack(&ftdmchan->caller_data, &conEvnt->cgPtyNmb); + cpy_called_num_from_stack(&ftdmchan->caller_data, &conEvnt->cdPtyNmb); + cpy_calling_name_from_stack(&ftdmchan->caller_data, &conEvnt->display); + + if (conEvnt->bearCap[0].eh.pres) { + ftdmchan->caller_data.bearer_layer1 = sngisdn_get_infoTranCap_from_stack(conEvnt->bearCap[0].usrInfoLyr1Prot.val); + ftdmchan->caller_data.bearer_capability = sngisdn_get_infoTranCap_from_stack(conEvnt->bearCap[0].infoTranCap.val); + } - if (signal_data->switchtype == SNGISDN_SWITCH_NI2) { if (conEvnt->shift11.eh.pres && conEvnt->ni2OctStr.eh.pres) { if (conEvnt->ni2OctStr.str.len == 4 && conEvnt->ni2OctStr.str.val[0] == 0x37) { @@ -156,7 +157,7 @@ void sngisdn_process_con_ind (sngisdn_event_data_t *sngisdn_event) break; case FTDM_CHANNEL_STATE_TERMINATING: ftdm_log_chan_msg(ftdmchan, FTDM_LOG_INFO, "Processing SETUP in TERMINATING state, saving SETUP info for later processing\n"); - ftdm_assert(!sngisdn_test_flag(sngisdn_info, FLAG_GLARE), "Trying to save GLARE info, but we already had a glare"); + ftdm_assert(!sngisdn_test_flag(sngisdn_info, FLAG_GLARE), "Trying to save GLARE info, but we already had a glare\n"); sngisdn_set_flag(sngisdn_info, FLAG_GLARE); @@ -168,11 +169,6 @@ void sngisdn_process_con_ind (sngisdn_event_data_t *sngisdn_event) sngisdn_info->glare.dChan = dChan; sngisdn_info->glare.ces = ces; - /* We need to register the spInstId in case we get a release for that call while it is still stored in sngisdn_info->glare */ - ftdm_mutex_lock(g_sngisdn_data.ccs[suId].mutex); - g_sngisdn_data.ccs[suId].active_spInstIds[spInstId] = sngisdn_info; - ftdm_mutex_unlock(g_sngisdn_data.ccs[suId].mutex); - break; case FTDM_CHANNEL_STATE_DIALING: /* glare */ if (signal_data->signalling == SNGISDN_SIGNALING_NET) { @@ -184,11 +180,6 @@ void sngisdn_process_con_ind (sngisdn_event_data_t *sngisdn_event) sngisdn_info->glare.suInstId = get_unique_suInstId(suId); sngisdn_info->glare.spInstId = spInstId; - ftdm_mutex_lock(g_sngisdn_data.ccs[suId].mutex); - g_sngisdn_data.ccs[suId].active_spInstIds[spInstId] = sngisdn_info; - g_sngisdn_data.ccs[suId].active_suInstIds[sngisdn_info->suInstId] = sngisdn_info; - ftdm_mutex_unlock(g_sngisdn_data.ccs[suId].mutex); - sngisdn_info->glare.dChan = dChan; sngisdn_info->glare.ces = ces; ftdmchan->caller_data.hangup_cause = 0x2C; /* Channel requested not available */ @@ -208,10 +199,6 @@ void sngisdn_process_con_ind (sngisdn_event_data_t *sngisdn_event) sngisdn_info->glare.dChan = dChan; sngisdn_info->glare.ces = ces; - /* We need to register the spInstId in case we get a release for that call while it is still stored in sngisdn_info->glare */ - ftdm_mutex_lock(g_sngisdn_data.ccs[suId].mutex); - g_sngisdn_data.ccs[suId].active_spInstIds[spInstId] = sngisdn_info; - ftdm_mutex_unlock(g_sngisdn_data.ccs[suId].mutex); ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_TERMINATING); } break; @@ -241,13 +228,6 @@ void sngisdn_process_con_cfm (sngisdn_event_data_t *sngisdn_event) ftdm_assert(!ftdm_test_flag(ftdmchan, FTDM_CHANNEL_STATE_CHANGE), "State change flag pending\n"); ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Processing CONNECT/CONNECT ACK (suId:%u suInstId:%u spInstId:%u ces:%d)\n", suId, suInstId, spInstId, ces); - - if (!sngisdn_info->spInstId) { - ftdm_mutex_lock(g_sngisdn_data.ccs[suId].mutex); - sngisdn_info->spInstId = spInstId; - g_sngisdn_data.ccs[suId].active_spInstIds[spInstId] = sngisdn_info; - ftdm_mutex_unlock(g_sngisdn_data.ccs[suId].mutex); - } if (ftdmchan->span->trunk_type == FTDM_TRUNK_BRI_PTMP && ((sngisdn_span_data_t*)ftdmchan->span->signal_data)->signalling == SNGISDN_SIGNALING_NET) { @@ -311,13 +291,6 @@ void sngisdn_process_cnst_ind (sngisdn_event_data_t *sngisdn_event) CnStEvnt *cnStEvnt = &sngisdn_event->event.cnStEvnt; - if (!sngisdn_info->spInstId) { - ftdm_mutex_lock(g_sngisdn_data.ccs[suId].mutex); - sngisdn_info->spInstId = spInstId; - g_sngisdn_data.ccs[suId].active_spInstIds[spInstId] = sngisdn_info; - ftdm_mutex_unlock(g_sngisdn_data.ccs[suId].mutex); - } - ftdm_assert(!ftdm_test_flag(ftdmchan, FTDM_CHANNEL_STATE_CHANGE), "State change flag pending\n"); ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Processing %s (suId:%u suInstId:%u spInstId:%u ces:%d)\n", @@ -370,7 +343,7 @@ void sngisdn_process_cnst_ind (sngisdn_event_data_t *sngisdn_event) ftdm_size_t min_digits = ((sngisdn_span_data_t*)ftdmchan->span->signal_data)->min_digits; ftdm_size_t num_digits; - cpy_called_num_from_sngisdn(&ftdmchan->caller_data, &cnStEvnt->cdPtyNmb); + cpy_called_num_from_stack(&ftdmchan->caller_data, &cnStEvnt->cdPtyNmb); num_digits = strlen(ftdmchan->caller_data.dnis.digits); if (cnStEvnt->sndCmplt.eh.pres || num_digits >= min_digits) { @@ -414,13 +387,6 @@ void sngisdn_process_disc_ind (sngisdn_event_data_t *sngisdn_event) DiscEvnt *discEvnt = &sngisdn_event->event.discEvnt; - if (!sngisdn_info->spInstId) { - ftdm_mutex_lock(g_sngisdn_data.ccs[suId].mutex); - sngisdn_info->spInstId = spInstId; - g_sngisdn_data.ccs[suId].active_spInstIds[spInstId] = sngisdn_info; - ftdm_mutex_unlock(g_sngisdn_data.ccs[suId].mutex); - } - ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Processing DISCONNECT (suId:%u suInstId:%u spInstId:%u)\n", suId, suInstId, spInstId); ftdm_assert(!ftdm_test_flag(ftdmchan, FTDM_CHANNEL_STATE_CHANGE), "State change flag pending\n"); @@ -686,7 +652,6 @@ void sngisdn_process_fac_ind (sngisdn_event_data_t *sngisdn_event) switch (ftdmchan->state) { case FTDM_CHANNEL_STATE_GET_CALLERID: /* Update the caller ID Name */ -#if 1 if (facEvnt->facElmt.facStr.pres) { uint8_t facility_str[255]; memcpy(facility_str, (uint8_t*)&facEvnt->facElmt.facStr.val, facEvnt->facElmt.facStr.len); @@ -694,9 +659,7 @@ void sngisdn_process_fac_ind (sngisdn_event_data_t *sngisdn_event) if (sng_isdn_retrieve_facility_caller_name(facility_str, facEvnt->facElmt.facStr.len, retrieved_str) != FTDM_SUCCESS) { ftdm_log_chan_msg(ftdmchan, FTDM_LOG_WARNING, "Failed to retrieve Caller Name from Facility IE\n"); } - ftdm_log_chan(ftdmchan, FTDM_LOG_WARNING, "DYDBG Name is:%s\n", retrieved_str); } -#endif ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_RING); break; @@ -876,6 +839,7 @@ void sngisdn_process_sta_cfm (sngisdn_event_data_t *sngisdn_event) case 9: switch (ftdmchan->state) { case FTDM_CHANNEL_STATE_PROGRESS: + case FTDM_CHANNEL_STATE_PROGRESS_MEDIA: /* Do nothing */ break; default: diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_out.c b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_out.c index 8247735cb9..6e8e0e81fd 100644 --- a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_out.c +++ b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_out.c @@ -34,9 +34,9 @@ #include "ftmod_sangoma_isdn.h" -extern ftdm_status_t cpy_calling_num_to_sngisdn(CgPtyNmb *cgPtyNmb, ftdm_caller_data_t *ftdm); -extern ftdm_status_t cpy_called_num_to_sngisdn(CdPtyNmb *cdPtyNmb, ftdm_caller_data_t *ftdm); -extern ftdm_status_t cpy_calling_name_to_sngisdn(ConEvnt *conEvnt, ftdm_channel_t *ftdmchan); +extern ftdm_status_t cpy_calling_num_from_user(CgPtyNmb *cgPtyNmb, ftdm_caller_data_t *ftdm); +extern ftdm_status_t cpy_called_num_from_user(CdPtyNmb *cdPtyNmb, ftdm_caller_data_t *ftdm); +extern ftdm_status_t cpy_calling_name_from_user(ConEvnt *conEvnt, ftdm_channel_t *ftdmchan); void sngisdn_snd_setup(ftdm_channel_t *ftdmchan); void sngisdn_snd_proceed(ftdm_channel_t *ftdmchan); @@ -62,11 +62,10 @@ void sngisdn_snd_setup(ftdm_channel_t *ftdmchan) ftdm_mutex_unlock(g_sngisdn_data.ccs[signal_data->cc_id].mutex); memset(&conEvnt, 0, sizeof(conEvnt)); - + conEvnt.bearCap[0].eh.pres = PRSNT_NODEF; conEvnt.bearCap[0].infoTranCap.pres = PRSNT_NODEF; - - conEvnt.bearCap[0].infoTranCap.val = IN_ITC_SPEECH; + conEvnt.bearCap[0].infoTranCap.val = sngisdn_get_infoTranCap_from_user(ftdmchan->caller_data.bearer_capability); conEvnt.bearCap[0].codeStand0.pres = PRSNT_NODEF; conEvnt.bearCap[0].codeStand0.val = IN_CSTD_CCITT; @@ -96,14 +95,21 @@ void sngisdn_snd_setup(ftdm_channel_t *ftdmchan) conEvnt.chanId.infoChanSel.val = ftdmchan->physical_chan_id; } else { /* PRI only params */ - - if (signal_data->switchtype == SNGISDN_SWITCH_EUROISDN) { - conEvnt.bearCap[0].usrInfoLyr1Prot.pres = PRSNT_NODEF; + conEvnt.bearCap[0].usrInfoLyr1Prot.pres = PRSNT_NODEF; + conEvnt.bearCap[0].usrInfoLyr1Prot.val = sngisdn_get_usrInfoLyr1Prot_from_user(ftdmchan->caller_data.bearer_layer1); + + if (signal_data->switchtype == SNGISDN_SWITCH_EUROISDN && + conEvnt.bearCap[0].usrInfoLyr1Prot.val == IN_UIL1_G711ULAW) { + + /* We are bridging a call from T1 */ conEvnt.bearCap[0].usrInfoLyr1Prot.val = IN_UIL1_G711ALAW; - } else { - conEvnt.bearCap[0].usrInfoLyr1Prot.pres = PRSNT_NODEF; + + } else if (conEvnt.bearCap[0].usrInfoLyr1Prot.val == IN_UIL1_G711ALAW) { + + /* We are bridging a call from E1 */ conEvnt.bearCap[0].usrInfoLyr1Prot.val = IN_UIL1_G711ULAW; } + conEvnt.bearCap[0].lyr1Ident.pres = PRSNT_NODEF; conEvnt.bearCap[0].lyr1Ident.val = IN_L1_IDENT; @@ -138,9 +144,9 @@ void sngisdn_snd_setup(ftdm_channel_t *ftdmchan) sngisdn_info->ces = CES_MNGMNT; } - cpy_called_num_to_sngisdn(&conEvnt.cdPtyNmb, &ftdmchan->caller_data); - cpy_calling_num_to_sngisdn(&conEvnt.cgPtyNmb, &ftdmchan->caller_data); - cpy_calling_name_to_sngisdn(&conEvnt, ftdmchan); + cpy_called_num_from_user(&conEvnt.cdPtyNmb, &ftdmchan->caller_data); + cpy_calling_num_from_user(&conEvnt.cgPtyNmb, &ftdmchan->caller_data); + cpy_calling_name_from_user(&conEvnt, ftdmchan); ftdm_log_chan(ftdmchan, FTDM_LOG_INFO, "Sending SETUP (suId:%d suInstId:%u spInstId:%u dchan:%d ces:%d)\n", signal_data->cc_id, sngisdn_info->suInstId, sngisdn_info->spInstId, signal_data->dchan_id, sngisdn_info->ces); @@ -277,7 +283,7 @@ void sngisdn_snd_proceed(ftdm_channel_t *ftdmchan) sngisdn_chan_data_t *sngisdn_info = (sngisdn_chan_data_t*) ftdmchan->call_data; sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*) ftdmchan->span->signal_data; - if (!sngisdn_info->suInstId || !sngisdn_info->spInstId) { + if (!sngisdn_info->suInstId || !sngisdn_info->spInstId) { ftdm_log_chan(ftdmchan, FTDM_LOG_ERROR, "Sending PROGRESS, but no call data, aborting (suId:%d suInstId:%u spInstId:%u)\n", signal_data->cc_id, sngisdn_info->suInstId, sngisdn_info->spInstId); sngisdn_set_flag(sngisdn_info, FLAG_LOCAL_ABORT); ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_TERMINATING); diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_rcv.c b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_rcv.c index 1c49674eeb..29cfb2330e 100644 --- a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_rcv.c +++ b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_rcv.c @@ -87,11 +87,14 @@ void sngisdn_rcv_con_ind (int16_t suId, uint32_t suInstId, uint32_t spInstId, Co sngisdn_event->event_id = SNGISDN_EVENT_CON_IND; sngisdn_event->sngisdn_info = sngisdn_info; sngisdn_event->suId = suId; - sngisdn_event->suInstId = suInstId; sngisdn_event->spInstId = spInstId; sngisdn_event->dChan = dChan; sngisdn_event->ces = ces; + ftdm_mutex_lock(g_sngisdn_data.ccs[suId].mutex); + g_sngisdn_data.ccs[suId].active_spInstIds[spInstId] = sngisdn_info; + ftdm_mutex_unlock(g_sngisdn_data.ccs[suId].mutex); + memcpy(&sngisdn_event->event.conEvnt, conEvnt, sizeof(*conEvnt)); ftdm_queue_enqueue(((sngisdn_span_data_t*)sngisdn_info->ftdmchan->span->signal_data)->event_queue, sngisdn_event); @@ -113,6 +116,14 @@ void sngisdn_rcv_con_cfm (int16_t suId, uint32_t suInstId, uint32_t spInstId, Cn return; } + if (!sngisdn_info->spInstId) { + ftdm_mutex_lock(g_sngisdn_data.ccs[suId].mutex); + sngisdn_info->spInstId = spInstId; + g_sngisdn_data.ccs[suId].active_spInstIds[spInstId] = sngisdn_info; + ftdm_mutex_unlock(g_sngisdn_data.ccs[suId].mutex); + } + + ftdm_log_chan(sngisdn_info->ftdmchan, FTDM_LOG_INFO, "Received CONNECT/CONNECT ACK (suId:%u suInstId:%u spInstId:%u ces:%d)\n", suId, suInstId, spInstId, ces); sngisdn_event = ftdm_malloc(sizeof(*sngisdn_event)); @@ -126,7 +137,6 @@ void sngisdn_rcv_con_cfm (int16_t suId, uint32_t suInstId, uint32_t spInstId, Cn sngisdn_event->spInstId = spInstId; sngisdn_event->dChan = dChan; sngisdn_event->ces = ces; - memcpy(&sngisdn_event->event.cnStEvnt, cnStEvnt, sizeof(*cnStEvnt)); ftdm_queue_enqueue(((sngisdn_span_data_t*)sngisdn_info->ftdmchan->span->signal_data)->event_queue, sngisdn_event); @@ -148,6 +158,13 @@ void sngisdn_rcv_cnst_ind (int16_t suId, uint32_t suInstId, uint32_t spInstId, C return; } + if (!sngisdn_info->spInstId) { + ftdm_mutex_lock(g_sngisdn_data.ccs[suId].mutex); + sngisdn_info->spInstId = spInstId; + g_sngisdn_data.ccs[suId].active_spInstIds[spInstId] = sngisdn_info; + ftdm_mutex_unlock(g_sngisdn_data.ccs[suId].mutex); + } + ftdm_log_chan(sngisdn_info->ftdmchan, FTDM_LOG_INFO, "Received %s (suId:%u suInstId:%u spInstId:%u ces:%d)\n", (evntType == MI_ALERTING)?"ALERT": (evntType == MI_CALLPROC)?"PROCEED": @@ -187,9 +204,17 @@ void sngisdn_rcv_disc_ind (int16_t suId, uint32_t suInstId, uint32_t spInstId, D !(suInstId && get_ftdmchan_by_suInstId(suId, suInstId, &sngisdn_info) == FTDM_SUCCESS)) { ftdm_log(FTDM_LOG_CRIT, "Could not find matching call suId:%u suInstId:%u spInstId:%u\n", suId, suInstId, spInstId); + ftdm_assert(0, "Inconsistent call states\n"); return; } + if (!sngisdn_info->spInstId) { + ftdm_mutex_lock(g_sngisdn_data.ccs[suId].mutex); + sngisdn_info->spInstId = spInstId; + g_sngisdn_data.ccs[suId].active_spInstIds[spInstId] = sngisdn_info; + ftdm_mutex_unlock(g_sngisdn_data.ccs[suId].mutex); + } + ftdm_log_chan(sngisdn_info->ftdmchan, FTDM_LOG_INFO, "Received DISCONNECT (suId:%u suInstId:%u spInstId:%u)\n", suId, suInstId, spInstId); sngisdn_event = ftdm_malloc(sizeof(*sngisdn_event)); @@ -219,6 +244,7 @@ void sngisdn_rcv_rel_ind (int16_t suId, uint32_t suInstId, uint32_t spInstId, Re !(suInstId && get_ftdmchan_by_suInstId(suId, suInstId, &sngisdn_info) == FTDM_SUCCESS)) { ftdm_log(FTDM_LOG_CRIT, "Could not find matching call suId:%u suInstId:%u spInstId:%u\n", suId, suInstId, spInstId); + ftdm_assert(0, "Inconsistent call states\n"); return; } @@ -250,7 +276,7 @@ void sngisdn_rcv_dat_ind (int16_t suId, uint32_t suInstId, uint32_t spInstId, In !(suInstId && get_ftdmchan_by_suInstId(suId, suInstId, &sngisdn_info) == FTDM_SUCCESS)) { ftdm_log(FTDM_LOG_CRIT, "Could not find matching call suId:%u suInstId:%u spInstId:%u\n", suId, suInstId, spInstId); - + ftdm_assert(0, "Inconsistent call states\n"); return; } @@ -282,7 +308,7 @@ void sngisdn_rcv_sshl_ind (int16_t suId, uint32_t suInstId, uint32_t spInstId, S !(suInstId && get_ftdmchan_by_suInstId(suId, suInstId, &sngisdn_info) == FTDM_SUCCESS)) { ftdm_log(FTDM_LOG_CRIT, "Could not find matching call suId:%u suInstId:%u spInstId:%u\n", suId, suInstId, spInstId); - + ftdm_assert(0, "Inconsistent call states\n"); return; } @@ -315,7 +341,7 @@ void sngisdn_rcv_sshl_cfm (int16_t suId, uint32_t suInstId, uint32_t spInstId, S !(suInstId && get_ftdmchan_by_suInstId(suId, suInstId, &sngisdn_info) == FTDM_SUCCESS)) { ftdm_log(FTDM_LOG_CRIT, "Could not find matching call suId:%u suInstId:%u spInstId:%u\n", suId, suInstId, spInstId); - + ftdm_assert(0, "Inconsistent call states\n"); return; } @@ -347,7 +373,7 @@ void sngisdn_rcv_rmrt_ind (int16_t suId, uint32_t suInstId, uint32_t spInstId, R !(suInstId && get_ftdmchan_by_suInstId(suId, suInstId, &sngisdn_info) == FTDM_SUCCESS)) { ftdm_log(FTDM_LOG_CRIT, "Could not find matching call suId:%u suInstId:%u spInstId:%u\n", suId, suInstId, spInstId); - + ftdm_assert(0, "Inconsistent call states\n"); return; } @@ -380,7 +406,7 @@ void sngisdn_rcv_rmrt_cfm (int16_t suId, uint32_t suInstId, uint32_t spInstId, R !(suInstId && get_ftdmchan_by_suInstId(suId, suInstId, &sngisdn_info) == FTDM_SUCCESS)) { ftdm_log(FTDM_LOG_CRIT, "Could not find matching call suId:%u suInstId:%u spInstId:%u\n", suId, suInstId, spInstId); - + ftdm_assert(0, "Inconsistent call states\n"); return; } @@ -413,7 +439,7 @@ void sngisdn_rcv_flc_ind (int16_t suId, uint32_t suInstId, uint32_t spInstId, St !(suInstId && get_ftdmchan_by_suInstId(suId, suInstId, &sngisdn_info) == FTDM_SUCCESS)) { ftdm_log(FTDM_LOG_CRIT, "Could not find matching call suId:%u suInstId:%u spInstId:%u\n", suId, suInstId, spInstId); - + ftdm_assert(0, "Inconsistent call states\n"); return; } @@ -446,7 +472,7 @@ void sngisdn_rcv_fac_ind (int16_t suId, uint32_t suInstId, uint32_t spInstId, Fa !(suInstId && get_ftdmchan_by_suInstId(suId, suInstId, &sngisdn_info) == FTDM_SUCCESS)) { ftdm_log(FTDM_LOG_CRIT, "Could not find matching call suId:%u suInstId:%u spInstId:%u\n", suId, suInstId, spInstId); - + ftdm_assert(0, "Inconsistent call states\n"); return; } @@ -479,7 +505,7 @@ void sngisdn_rcv_sta_cfm (int16_t suId, uint32_t suInstId, uint32_t spInstId, St !(suInstId && get_ftdmchan_by_suInstId(suId, suInstId, &sngisdn_info) == FTDM_SUCCESS)) { ftdm_log(FTDM_LOG_CRIT, "Could not find matching call suId:%u suInstId:%u spInstId:%u\n", suId, suInstId, spInstId); - + ftdm_assert(0, "Inconsistent call states\n"); return; } @@ -641,7 +667,10 @@ void sngisdn_rcv_q921_ind(BdMngmt *status) } } } - ftdm_assert(ftdmspan != NULL, "Received q921 status on unconfigured span\n"); + if (ftdmspan == NULL) { + ftdm_log(FTDM_LOG_WARNING, "Received q921 status on unconfigured span (lnkNmb:%d)\n", status->t.usta.lnkNmb); + return; + } switch (status->t.usta.alarm.category) { case (LCM_CATEGORY_INTERFACE): diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_support.c b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_support.c index f910eb31eb..29e7994c87 100644 --- a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_support.c +++ b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_support.c @@ -34,15 +34,15 @@ #include "ftmod_sangoma_isdn.h" -ftdm_status_t cpy_calling_num_from_sngisdn(ftdm_caller_data_t *ftdm, CgPtyNmb *cgPtyNmb); -ftdm_status_t cpy_called_num_from_sngisdn(ftdm_caller_data_t *ftdm, CdPtyNmb *cdPtyNmb); -ftdm_status_t cpy_redir_num_from_sngisdn(ftdm_caller_data_t *ftdm, RedirNmb *redirNmb); -ftdm_status_t cpy_calling_name_from_sngisdn(ftdm_caller_data_t *ftdm, Display *display); +ftdm_status_t cpy_calling_num_from_stack(ftdm_caller_data_t *ftdm, CgPtyNmb *cgPtyNmb); +ftdm_status_t cpy_called_num_from_stack(ftdm_caller_data_t *ftdm, CdPtyNmb *cdPtyNmb); +ftdm_status_t cpy_redir_num_from_stack(ftdm_caller_data_t *ftdm, RedirNmb *redirNmb); +ftdm_status_t cpy_calling_name_from_stack(ftdm_caller_data_t *ftdm, Display *display); -ftdm_status_t cpy_calling_num_to_sngisdn(CgPtyNmb *cgPtyNmb, ftdm_caller_data_t *ftdm); -ftdm_status_t cpy_called_num_to_sngisdn(CdPtyNmb *cdPtyNmb, ftdm_caller_data_t *ftdm); -ftdm_status_t cpy_redir_num_to_sngisdn(RedirNmb *redirNmb, ftdm_caller_data_t *ftdm); -ftdm_status_t cpy_calling_name_to_sngisdn(ConEvnt *conEvnt, ftdm_channel_t *ftdmchan); +ftdm_status_t cpy_calling_num_from_user(CgPtyNmb *cgPtyNmb, ftdm_caller_data_t *ftdm); +ftdm_status_t cpy_called_num_from_user(CdPtyNmb *cdPtyNmb, ftdm_caller_data_t *ftdm); +ftdm_status_t cpy_redir_num_from_user(RedirNmb *redirNmb, ftdm_caller_data_t *ftdm); +ftdm_status_t cpy_calling_name_from_user(ConEvnt *conEvnt, ftdm_channel_t *ftdmchan); ftdm_status_t sngisdn_check_free_ids(void); @@ -146,7 +146,7 @@ ftdm_status_t sng_isdn_set_avail_rate(ftdm_span_t *ftdmspan, sngisdn_avail_t ava return FTDM_SUCCESS; } -ftdm_status_t cpy_calling_num_from_sngisdn(ftdm_caller_data_t *ftdm, CgPtyNmb *cgPtyNmb) +ftdm_status_t cpy_calling_num_from_stack(ftdm_caller_data_t *ftdm, CgPtyNmb *cgPtyNmb) { if (cgPtyNmb->eh.pres != PRSNT_NODEF) { return FTDM_FAIL; @@ -173,7 +173,7 @@ ftdm_status_t cpy_calling_num_from_sngisdn(ftdm_caller_data_t *ftdm, CgPtyNmb *c return FTDM_SUCCESS; } -ftdm_status_t cpy_called_num_from_sngisdn(ftdm_caller_data_t *ftdm, CdPtyNmb *cdPtyNmb) +ftdm_status_t cpy_called_num_from_stack(ftdm_caller_data_t *ftdm, CdPtyNmb *cdPtyNmb) { if (cdPtyNmb->eh.pres != PRSNT_NODEF) { return FTDM_FAIL; @@ -195,7 +195,7 @@ ftdm_status_t cpy_called_num_from_sngisdn(ftdm_caller_data_t *ftdm, CdPtyNmb *cd return FTDM_SUCCESS; } -ftdm_status_t cpy_redir_num_from_sngisdn(ftdm_caller_data_t *ftdm, RedirNmb *redirNmb) +ftdm_status_t cpy_redir_num_from_stack(ftdm_caller_data_t *ftdm, RedirNmb *redirNmb) { if (redirNmb->eh.pres != PRSNT_NODEF) { return FTDM_FAIL; @@ -215,7 +215,7 @@ ftdm_status_t cpy_redir_num_from_sngisdn(ftdm_caller_data_t *ftdm, RedirNmb *red return FTDM_SUCCESS; } -ftdm_status_t cpy_calling_name_from_sngisdn(ftdm_caller_data_t *ftdm, Display *display) +ftdm_status_t cpy_calling_name_from_stack(ftdm_caller_data_t *ftdm, Display *display) { if (display->eh.pres != PRSNT_NODEF) { return FTDM_FAIL; @@ -228,7 +228,7 @@ ftdm_status_t cpy_calling_name_from_sngisdn(ftdm_caller_data_t *ftdm, Display *d return FTDM_SUCCESS; } -ftdm_status_t cpy_calling_num_to_sngisdn(CgPtyNmb *cgPtyNmb, ftdm_caller_data_t *ftdm) +ftdm_status_t cpy_calling_num_from_user(CgPtyNmb *cgPtyNmb, ftdm_caller_data_t *ftdm) { uint8_t len = strlen(ftdm->cid_num.digits); if (!len) { @@ -256,7 +256,7 @@ ftdm_status_t cpy_calling_num_to_sngisdn(CgPtyNmb *cgPtyNmb, ftdm_caller_data_t return FTDM_SUCCESS; } -ftdm_status_t cpy_called_num_to_sngisdn(CdPtyNmb *cdPtyNmb, ftdm_caller_data_t *ftdm) +ftdm_status_t cpy_called_num_from_user(CdPtyNmb *cdPtyNmb, ftdm_caller_data_t *ftdm) { uint8_t len = strlen(ftdm->dnis.digits); if (!len) { @@ -286,7 +286,7 @@ ftdm_status_t cpy_called_num_to_sngisdn(CdPtyNmb *cdPtyNmb, ftdm_caller_data_t * return FTDM_SUCCESS; } -ftdm_status_t cpy_redir_num_to_sngisdn(RedirNmb *redirNmb, ftdm_caller_data_t *ftdm) +ftdm_status_t cpy_redir_num_from_user(RedirNmb *redirNmb, ftdm_caller_data_t *ftdm) { uint8_t len = strlen(ftdm->rdnis.digits); if (!len) { @@ -318,7 +318,7 @@ ftdm_status_t cpy_redir_num_to_sngisdn(RedirNmb *redirNmb, ftdm_caller_data_t *f } -ftdm_status_t cpy_calling_name_to_sngisdn(ConEvnt *conEvnt, ftdm_channel_t *ftdmchan) +ftdm_status_t cpy_calling_name_from_user(ConEvnt *conEvnt, ftdm_channel_t *ftdmchan) { uint8_t len; ftdm_caller_data_t *ftdm = &ftdmchan->caller_data; @@ -385,13 +385,7 @@ void sngisdn_delayed_release(void* p_sngisdn_info) signal_data->cc_id, sngisdn_info->glare.spInstId, sngisdn_info->glare.suInstId); sngisdn_snd_release(ftdmchan, 1); -#if 1 /* TODO: Confirm this */ clear_call_glare_data(sngisdn_info); -#else - g_sngisdn_data.ccs[signal_data->cc_id].active_spInstIds[sngisdn_info->glare.spInstId] = NULL; - g_sngisdn_data.ccs[signal_data->cc_id].active_suInstIds[sngisdn_info->glare.suInstId] = NULL; -#endif - } else { ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Call was already released (suId:%d suInstId:%u spInstId:%u)\n", signal_data->cc_id, sngisdn_info->glare.spInstId, sngisdn_info->glare.suInstId); @@ -473,6 +467,72 @@ void get_memory_info(void) return; } +uint8_t sngisdn_get_infoTranCap_from_stack(ftdm_bearer_cap_t bearer_capability) +{ + switch(bearer_capability) { + case FTDM_BEARER_CAP_SPEECH: + return IN_ITC_SPEECH; + + case FTDM_BEARER_CAP_64K_UNRESTRICTED: + return IN_ITC_UNRDIG; + + case FTDM_BEARER_CAP_3_1KHZ_AUDIO: + return IN_ITC_A31KHZ; + + /* Do not put a default case here, so we can see compile warnings if we have unhandled cases */ + } + return FTDM_BEARER_CAP_SPEECH; +} + +uint8_t sngisdn_get_usrInfoLyr1Prot_from_stack(ftdm_user_layer1_prot_t layer1_prot) +{ + switch(layer1_prot) { + case FTDM_USER_LAYER1_PROT_V110: + return IN_UIL1_CCITTV110; + + case FTDM_USER_LAYER1_PROT_ULAW: + return IN_UIL1_G711ULAW; + + case FTDM_USER_LAYER1_PROT_ALAW: + return IN_UIL1_G711ALAW; + + /* Do not put a default case here, so we can see compile warnings if we have unhandled cases */ + } + return IN_UIL1_G711ULAW; +} + +ftdm_bearer_cap_t sngisdn_get_infoTranCap_from_user(uint8_t bearer_capability) +{ + switch(bearer_capability) { + case IN_ITC_SPEECH: + return FTDM_BEARER_CAP_SPEECH; + + case IN_ITC_UNRDIG: + return FTDM_BEARER_CAP_64K_UNRESTRICTED; + + case IN_ITC_A31KHZ: + return FTDM_BEARER_CAP_3_1KHZ_AUDIO; + + default: + return FTDM_BEARER_CAP_SPEECH; + } + return FTDM_BEARER_CAP_SPEECH; +} + +ftdm_user_layer1_prot_t sngisdn_get_usrInfoLyr1Prot_from_user(uint8_t layer1_prot) +{ + switch(layer1_prot) { + case IN_UIL1_CCITTV110: + return FTDM_USER_LAYER1_PROT_V110; + case IN_UIL1_G711ULAW: + return FTDM_USER_LAYER1_PROT_ULAW; + case IN_UIL1_G711ALAW: + return IN_UIL1_G711ALAW; + default: + return FTDM_USER_LAYER1_PROT_ULAW; + } + return FTDM_USER_LAYER1_PROT_ULAW; +} /* For Emacs: * Local Variables: diff --git a/libs/freetdm/src/include/freetdm.h b/libs/freetdm/src/include/freetdm.h index 7501bb4977..0437e02e51 100644 --- a/libs/freetdm/src/include/freetdm.h +++ b/libs/freetdm/src/include/freetdm.h @@ -60,6 +60,8 @@ /*! \brief Max number of groups */ #define FTDM_MAX_GROUPS_INTERFACE FTDM_MAX_SPANS_INTERFACE +#define FTDM_INVALID_INT_PARM 0xFF + /*! \brief FreeTDM APIs possible return codes */ typedef enum { FTDM_SUCCESS, /*!< Success */ @@ -208,6 +210,7 @@ typedef struct ftdm_queue_handler { ftdm_queue_destroy_func_t destroy; } ftdm_queue_handler_t; + /*! \brief Type Of Number (TON) */ typedef enum { FTDM_TON_UNKNOWN = 0, diff --git a/libs/freetdm/src/include/private/ftdm_call_utils.h b/libs/freetdm/src/include/private/ftdm_call_utils.h index 57f2f4b133..782abde927 100644 --- a/libs/freetdm/src/include/private/ftdm_call_utils.h +++ b/libs/freetdm/src/include/private/ftdm_call_utils.h @@ -39,6 +39,8 @@ FT_DECLARE(ftdm_status_t) ftdm_span_set_npi(const char *npi_string, uint8_t *target); FT_DECLARE(ftdm_status_t) ftdm_span_set_ton(const char *ton_string, uint8_t *target); +FT_DECLARE(ftdm_status_t) ftdm_span_set_bearer_capability(const char *bc_string, ftdm_bearer_cap_t *target); +FT_DECLARE(ftdm_status_t) ftdm_span_set_bearer_layer1(const char *bc_string, ftdm_user_layer1_prot_t *target); FT_DECLARE(ftdm_status_t) ftdm_is_number(char *number); #endif /* __FTDM_CALL_UTILS_H__ */