diff --git a/libs/freetdm/src/ftdm_io.c b/libs/freetdm/src/ftdm_io.c index f02c9c48db..1ede703a41 100644 --- a/libs/freetdm/src/ftdm_io.c +++ b/libs/freetdm/src/ftdm_io.c @@ -1751,7 +1751,7 @@ FT_DECLARE(ftdm_status_t) ftdm_channel_open_chan(ftdm_channel_t *ftdmchan) goto done; } - if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_IN_ALARM)) { + if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_IN_ALARM) && !ftdm_test_flag(ftdmchan->span, FTDM_SPAN_PWR_SAVING)) { snprintf(ftdmchan->last_error, sizeof(ftdmchan->last_error), "%s", "Channel is alarmed\n"); ftdm_log_chan_msg(ftdmchan, FTDM_LOG_WARNING, "Cannot open channel when is alarmed\n"); goto done; @@ -3927,6 +3927,11 @@ static ftdm_status_t ftdm_set_channels_alarms(ftdm_span_t *span, int currindex) ftdm_log(FTDM_LOG_ERROR, "%d:%d: Failed to get alarms\n", span->channels[chan_index]->physical_span_id, span->channels[chan_index]->physical_chan_id); return FTDM_FAIL; } + if (span->channels[chan_index]->alarm_flags) { + ftdm_set_flag_locked(span->channels[chan_index], FTDM_CHANNEL_IN_ALARM); + } else { + ftdm_clear_flag_locked(span->channels[chan_index], FTDM_CHANNEL_IN_ALARM); + } } return FTDM_SUCCESS; } diff --git a/libs/freetdm/src/ftmod/ftmod_isdn/ftmod_isdn.c b/libs/freetdm/src/ftmod/ftmod_isdn/ftmod_isdn.c index 65c9dfc11f..d64e711e73 100644 --- a/libs/freetdm/src/ftmod/ftmod_isdn/ftmod_isdn.c +++ b/libs/freetdm/src/ftmod/ftmod_isdn/ftmod_isdn.c @@ -53,7 +53,6 @@ //#define IODEBUG /* helper macros */ -#define FTDM_SPAN_IS_BRI(x) ((x)->trunk_type == FTDM_TRUNK_BRI || (x)->trunk_type == FTDM_TRUNK_BRI_PTMP) #define FTDM_SPAN_IS_NT(x) (((ftdm_isdn_data_t *)(x)->signal_data)->mode == Q921_NT) 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 22c89cb920..39231a0f39 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 @@ -47,6 +47,7 @@ static ftdm_status_t ftdm_sangoma_isdn_start(ftdm_span_t *span); ftdm_channel_t* ftdm_sangoma_isdn_process_event_states(ftdm_span_t *span, sngisdn_event_data_t *sngisdn_event); static void ftdm_sangoma_isdn_advance_chan_states(ftdm_channel_t *ftdmchan); +static void ftdm_sangoma_isdn_poll_events(ftdm_span_t *span); static void ftdm_sangoma_isdn_process_state_change(ftdm_channel_t *ftdmchan); static void ftdm_sangoma_isdn_process_stack_event (ftdm_span_t *span, sngisdn_event_data_t *sngisdn_event); @@ -238,6 +239,50 @@ static __inline__ void ftdm_sangoma_isdn_advance_chan_states(ftdm_channel_t *ftd } } +static void ftdm_sangoma_isdn_poll_events(ftdm_span_t *span) +{ + ftdm_status_t ret_status; + ftdm_channel_t *ftdmchan; + ftdm_iterator_t *chaniter = NULL; + ftdm_iterator_t *curr = NULL; + + ret_status = ftdm_span_poll_event(span, 0, NULL); + switch(ret_status) { + case FTDM_SUCCESS: + { + ftdm_event_t *event; + while (ftdm_span_next_event(span, &event) == FTDM_SUCCESS) { + + if (FTDM_SPAN_IS_BRI(span)) { + switch (event->enum_id) { + /* Check if the span woke up from power-saving mode */ + case FTDM_OOB_ALARM_CLEAR: + { + chaniter = ftdm_span_get_chan_iterator(span, NULL); + for (curr = chaniter; curr; curr = ftdm_iterator_next(curr)) { + ftdmchan = (ftdm_channel_t*)ftdm_iterator_current(curr); + sngisdn_chan_data_t *sngisdn_info = ftdmchan->call_data; + + if (ftdm_test_flag(sngisdn_info, FLAG_ACTIVATING)) { + ftdm_clear_flag(sngisdn_info, FLAG_ACTIVATING); + sngisdn_snd_setup((ftdm_channel_t*)ftdmchan); + } + } + ftdm_iterator_free(chaniter); + } + } + } + } + } + break; + case FTDM_TIMEOUT: + /* No events pending */ + break; + default: + ftdm_log(FTDM_LOG_WARNING, "%s:Failed to poll span event\n", span->name); + } +} + static void *ftdm_sangoma_isdn_run(ftdm_thread_t *me, void *obj) { ftdm_interrupt_t *ftdm_sangoma_isdn_int[2]; @@ -300,21 +345,8 @@ static void *ftdm_sangoma_isdn_run(ftdm_thread_t *me, void *obj) } /* Poll for events, e.g HW DTMF */ - ret_status = ftdm_span_poll_event(span, 0, NULL); - switch(ret_status) { - case FTDM_SUCCESS: - { - ftdm_event_t *event; - while (ftdm_span_next_event(span, &event) == FTDM_SUCCESS); - } - break; - case FTDM_TIMEOUT: - /* No events pending */ - break; - default: - ftdm_log(FTDM_LOG_WARNING, "%s:Failed to poll span event\n", span->name); - } - + ftdm_sangoma_isdn_poll_events(span); + if (ftdm_sched_get_time_to_next_timer(signal_data->sched, &sleep) == FTDM_SUCCESS) { if (sleep < 0 || sleep > SNGISDN_EVENT_POLL_RATE) { sleep = SNGISDN_EVENT_POLL_RATE; @@ -498,8 +530,20 @@ static void ftdm_sangoma_isdn_process_state_change(ftdm_channel_t *ftdmchan) } break; case FTDM_CHANNEL_STATE_DIALING: /* outgoing call request */ - { - sngisdn_snd_setup(ftdmchan); + { + if (FTDM_SPAN_IS_BRI(ftdmchan->span) && + ftdm_test_flag(ftdmchan, FTDM_CHANNEL_IN_ALARM) && + ftdm_test_flag(ftdmchan->span, FTDM_SPAN_PWR_SAVING)) { + + sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*) ftdmchan->span->signal_data; + + ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Requesting Line activation\n"); + sngisdn_set_flag(sngisdn_info, FLAG_ACTIVATING); + sng_isdn_wake_up_phy(ftdmchan->span); + ftdm_sched_timer(signal_data->sched, "timer_t3", signal_data->timer_t3*1000, sngisdn_t3_timeout, (void*) sngisdn_info, NULL); + } else { + sngisdn_snd_setup(ftdmchan); + } } break; case FTDM_CHANNEL_STATE_PROGRESS: @@ -856,8 +900,7 @@ static FIO_CONFIGURE_SPAN_SIGNALING_FUNCTION(ftdm_sangoma_isdn_span_config) if (span->trunk_type == FTDM_TRUNK_BRI_PTMP || span->trunk_type == FTDM_TRUNK_BRI) { - - ftdm_set_flag(span, FTDM_SPAN_USE_AV_RATE); + sng_isdn_set_avail_rate(span, SNGISDN_AVAIL_PWR_SAVING); } @@ -914,7 +957,7 @@ static FIO_SIG_LOAD_FUNCTION(ftdm_sangoma_isdn_init) /* initalize sng_isdn library */ - ftdm_assert_return(!sng_isdn_init(&g_sngisdn_event_interface), FTDM_FAIL, "Failed to initialize stack\n"); + ftdm_assert_return(!sng_isdn_init(&g_sngisdn_event_interface), FTDM_FAIL, "Failed to initialize stack\n"); return FTDM_SUCCESS; } 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 e84392e22a..a3d48a8e11 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 @@ -74,6 +74,7 @@ typedef enum { FLAG_DELAYED_REL = (1 << 7), FLAG_SENT_PROCEED = (1 << 8), FLAG_SEND_DISC = (1 << 9), + FLAG_ACTIVATING = (1 << 10), /* Used for BRI only, flag is set after we request line CONNECTED */ } sngisdn_flag_t; @@ -181,6 +182,7 @@ typedef struct sngisdn_span_data { uint8_t facility; int8_t facility_timeout; uint8_t num_local_numbers; + uint8_t timer_t3; char* local_numbers[SNGISDN_NUM_LOCAL_NUMBERS]; ftdm_sched_t *sched; ftdm_queue_t *event_queue; @@ -368,11 +370,13 @@ void sngisdn_delayed_release(void* p_sngisdn_info); void sngisdn_delayed_connect(void* p_sngisdn_info); void sngisdn_delayed_disconnect(void* p_sngisdn_info); void sngisdn_facility_timeout(void* p_sngisdn_info); +void sngisdn_t3_timeout(void* p_sngisdn_info); /* Stack management functions */ ftdm_status_t sng_isdn_stack_cfg(ftdm_span_t *span); ftdm_status_t sng_isdn_stack_start(ftdm_span_t *span); ftdm_status_t sng_isdn_stack_stop(ftdm_span_t *span); +ftdm_status_t sng_isdn_wake_up_phy(ftdm_span_t *span); void sngisdn_print_phy_stats(ftdm_stream_handle_t *stream, ftdm_span_t *span); void sngisdn_print_spans(ftdm_stream_handle_t *stream); 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 64d7a2403f..18ca9c38dd 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 @@ -98,6 +98,8 @@ ftdm_status_t parse_switchtype(const char* switch_name, ftdm_span_t *span) ftdm_log(FTDM_LOG_ERROR, "%s:Unsupported switchtype %s for trunktype:%s\n", span->name, switch_name, ftdm_trunk_type2str(span->trunk_type)); return FTDM_FAIL; } + ftdm_set_flag(span, FTDM_SPAN_USE_AV_RATE); + ftdm_set_flag(span, FTDM_SPAN_PWR_SAVING); /* can be > 1 for some BRI variants */ break; default: @@ -179,6 +181,7 @@ ftdm_status_t ftmod_isdn_parse_cfg(ftdm_conf_parameter_t *ftdm_parameters, ftdm_ signal_data->min_digits = 8; signal_data->overlap_dial = SNGISDN_OPT_DEFAULT; signal_data->setup_arb = SNGISDN_OPT_DEFAULT; + signal_data->timer_t3 = 8; signal_data->link_id = span->span_id; span->default_caller_data.bearer_capability = IN_ITC_SPEECH; @@ -189,6 +192,7 @@ ftdm_status_t ftmod_isdn_parse_cfg(ftdm_conf_parameter_t *ftdm_parameters, ftdm_ if (span->trunk_type == FTDM_TRUNK_BRI || span->trunk_type == FTDM_TRUNK_BRI_PTMP) { + ftdm_span_set_npi("unknown", &span->default_caller_data.dnis.plan); ftdm_span_set_ton("unknown", &span->default_caller_data.dnis.type); ftdm_span_set_npi("unknown", &span->default_caller_data.cid_num.plan); diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_cntrl.c b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_cntrl.c index 27c16c2a51..bfc00d07ba 100644 --- a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_cntrl.c +++ b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_cntrl.c @@ -113,6 +113,40 @@ ftdm_status_t sng_isdn_stack_stop(ftdm_span_t *span) } +ftdm_status_t sng_isdn_wake_up_phy(ftdm_span_t *span) +{ + L1Mngmt cntrl; + Pst pst; + + sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*)span->signal_data; + + /* initalize the post structure */ + stack_pst_init(&pst); + + /* insert the destination Entity */ + pst.dstEnt = ENTL1; + + /* initalize the control structure */ + memset(&cntrl, 0, sizeof(cntrl)); + + /* initalize the control header */ + stack_hdr_init(&cntrl.hdr); + + cntrl.hdr.msgType = TCNTRL; /* configuration */ + cntrl.hdr.entId.ent = ENTL1; /* entity */ + cntrl.hdr.entId.inst = S_INST; /* instance */ + cntrl.hdr.elmId.elmnt = STTSAP; /* SAP Specific cntrl */ + + cntrl.t.cntrl.action = AENA; + cntrl.t.cntrl.subAction = SAELMNT; + cntrl.t.cntrl.sapId = signal_data->link_id; + + if (sng_isdn_phy_cntrl(&pst, &cntrl)) { + return FTDM_FAIL; + } + return FTDM_SUCCESS; +} + ftdm_status_t sng_isdn_activate_phy(ftdm_span_t *span) { 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 3284d54165..425c281a94 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 @@ -38,13 +38,6 @@ extern ftdm_status_t cpy_calling_num_from_user(CgPtyNmb *cgPtyNmb, ftdm_caller_d 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); -void sngisdn_snd_progress(ftdm_channel_t *ftdmchan); -void sngisdn_snd_connect(ftdm_channel_t *ftdmchan); -void sngisdn_snd_disconnect(ftdm_channel_t *ftdmchan); -void sngisdn_snd_release(ftdm_channel_t *ftdmchan, uint8_t glare); - void sngisdn_snd_setup(ftdm_channel_t *ftdmchan) { 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 f54f7db61c..5987823283 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 @@ -382,6 +382,28 @@ ftdm_status_t cpy_calling_name_from_user(ConEvnt *conEvnt, ftdm_channel_t *ftdmc return FTDM_SUCCESS; } +void sngisdn_t3_timeout(void* p_sngisdn_info) +{ + sngisdn_chan_data_t *sngisdn_info = (sngisdn_chan_data_t*)p_sngisdn_info; + ftdm_channel_t *ftdmchan = sngisdn_info->ftdmchan; + sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*) ftdmchan->span->signal_data; + + ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Timer T3 expired (suId:%d suInstId:%u spInstId:%u)\n", + signal_data->cc_id, sngisdn_info->glare.spInstId, sngisdn_info->glare.suInstId); + ftdm_mutex_lock(ftdmchan->mutex); + if (ftdm_test_flag(sngisdn_info, FLAG_ACTIVATING)){ + /* PHY layer timed-out, need to clear the call */ + ftdm_log_chan(ftdmchan, FTDM_LOG_INFO, "Failed to Wake-Up line (suId:%d suInstId:%u spInstId:%u)\n", + signal_data->cc_id, sngisdn_info->glare.spInstId, sngisdn_info->glare.suInstId); + + ftdmchan->caller_data.hangup_cause = FTDM_CAUSE_NO_ROUTE_DESTINATION; + ftdm_clear_flag(sngisdn_info, FLAG_ACTIVATING); + ftdm_set_flag(sngisdn_info, FLAG_LOCAL_ABORT); + ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_TERMINATING); + } + ftdm_mutex_unlock(ftdmchan->mutex); +} + void sngisdn_delayed_release(void* p_sngisdn_info) { sngisdn_chan_data_t *sngisdn_info = (sngisdn_chan_data_t*)p_sngisdn_info; diff --git a/libs/freetdm/src/ftmod/ftmod_wanpipe/ftmod_wanpipe.c b/libs/freetdm/src/ftmod/ftmod_wanpipe/ftmod_wanpipe.c index e2d85f7ea1..b95b34d2d2 100644 --- a/libs/freetdm/src/ftmod/ftmod_wanpipe/ftmod_wanpipe.c +++ b/libs/freetdm/src/ftmod/ftmod_wanpipe/ftmod_wanpipe.c @@ -1011,13 +1011,15 @@ static FIO_GET_ALARMS_FUNCTION(wanpipe_get_alarms) } alarms = tdm_api.wp_tdm_cmd.fe_alarms; #endif -#if 1 - /* DAVIDY - Temporary fix: in the current trunk of libsangoma, for BRI, +#ifdef WIN32 + /* Temporary fix: in the current trunk of libsangoma, for BRI, WAN_TE_BIT_ALARM_RED bit is set if the card is in disconnected state, but this has not been ported to Windows-libsangoma yet */ - if (alarms) { - ftdmchan->alarm_flags |= FTDM_ALARM_RED; - alarms = 0; + if (FTDM_SPAN_IS_BRI(ftdmchan->span)) { + if (alarms) { + ftdmchan->alarm_flags |= FTDM_ALARM_RED; + alarms = 0; + } } #endif @@ -1027,6 +1029,7 @@ static FIO_GET_ALARMS_FUNCTION(wanpipe_get_alarms) ftdmchan->alarm_flags |= FTDM_ALARM_RED; alarms &= ~WAN_TE_BIT_ALARM_RED; } + if (alarms & WAN_TE_BIT_ALARM_AIS) { ftdmchan->alarm_flags |= FTDM_ALARM_BLUE; diff --git a/libs/freetdm/src/include/private/ftdm_core.h b/libs/freetdm/src/include/private/ftdm_core.h index 8bdbdd60f8..dbf108020b 100644 --- a/libs/freetdm/src/include/private/ftdm_core.h +++ b/libs/freetdm/src/include/private/ftdm_core.h @@ -222,6 +222,8 @@ extern "C" { #define ftdm_is_dtmf(key) ((key > 47 && key < 58) || (key > 64 && key < 69) || (key > 96 && key < 101) || key == 35 || key == 42 || key == 87 || key == 119) +#define FTDM_SPAN_IS_BRI(x) ((x)->trunk_type == FTDM_TRUNK_BRI || (x)->trunk_type == FTDM_TRUNK_BRI_PTMP) + /*! \brief Copy flags from one arbitrary object to another \command dest the object to copy the flags to diff --git a/libs/freetdm/src/include/private/ftdm_types.h b/libs/freetdm/src/include/private/ftdm_types.h index bddefd9be6..78ac8f63eb 100644 --- a/libs/freetdm/src/include/private/ftdm_types.h +++ b/libs/freetdm/src/include/private/ftdm_types.h @@ -176,10 +176,11 @@ typedef enum { FTDM_SPAN_USE_CHAN_QUEUE = (1 << 6), FTDM_SPAN_SUGGEST_CHAN_ID = (1 << 7), FTDM_SPAN_USE_AV_RATE = (1 << 8), + FTDM_SPAN_PWR_SAVING = (1 << 9), /* If you use this flag, you MUST call ftdm_span_trigger_signals to deliver the user signals * after having called ftdm_send_span_signal(), which with this flag it will just enqueue the signal * for later delivery */ - FTDM_SPAN_USE_SIGNALS_QUEUE = (1 << 9), + FTDM_SPAN_USE_SIGNALS_QUEUE = (1 << 10), } ftdm_span_flag_t; /*! \brief Channel supported features */