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 e6740c2ddd..e3af9d9b98 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 @@ -682,16 +682,26 @@ static ftdm_status_t ftdm_sangoma_isdn_process_state_change(ftdm_channel_t *ftdm break; case FTDM_CHANNEL_STATE_DIALING: /* outgoing call request */ { - 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); - ftdm_sangoma_isdn_wakeup_phy(ftdmchan); - ftdm_sched_timer(signal_data->sched, "timer_t3", signal_data->timer_t3*1000, sngisdn_t3_timeout, (void*) sngisdn_info, NULL); + if (FTDM_SPAN_IS_BRI(ftdmchan->span) && ftdm_test_flag(ftdmchan->span, FTDM_SPAN_PWR_SAVING)) { + ftdm_signaling_status_t sigstatus; + ftdm_span_get_sig_status(ftdmchan->span, &sigstatus); + if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_IN_ALARM)) { + sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*)ftdmchan->span->signal_data; + + ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Requesting Physical Line activation\n"); + sngisdn_set_flag(sngisdn_info, FLAG_ACTIVATING); + ftdm_sangoma_isdn_wakeup_phy(ftdmchan); + ftdm_sched_timer(signal_data->sched, "timer_t3", signal_data->timer_t3*1000, sngisdn_t3_timeout, (void*) sngisdn_info, NULL); + } else if (sigstatus == FTDM_SIG_STATE_DOWN) { + sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*)ftdmchan->span->signal_data; + + ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Requesting Q.921 Line activation\n"); + sngisdn_set_flag(sngisdn_info, FLAG_ACTIVATING); + sngisdn_snd_info_req(ftdmchan); + 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); + } } else { sngisdn_snd_setup(ftdmchan); } diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_cntrl.c b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_cntrl.c index 668b63006c..15def40218 100644 --- a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_cntrl.c +++ b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_cntrl.c @@ -49,6 +49,16 @@ void sngisdn_set_chan_sig_status(ftdm_channel_t *ftdmchan, ftdm_signaling_status sig.event_id = FTDM_SIGEVENT_SIGSTATUS_CHANGED; sig.ev_data.sigstatus.status = status; ftdm_span_send_signal(ftdmchan->span, &sig); + + if (FTDM_SPAN_IS_BRI(ftdmchan->span)) { + sngisdn_chan_data_t *sngisdn_info = ftdmchan->call_data; + sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*)ftdmchan->span->signal_data; + if (ftdm_test_flag(sngisdn_info, FLAG_ACTIVATING)) { + ftdm_clear_flag(sngisdn_info, FLAG_ACTIVATING); + + ftdm_sched_timer(signal_data->sched, "delayed_setup", 1000, sngisdn_delayed_setup, (void*) sngisdn_info, NULL); + } + } return; } diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_cfg.c b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_cfg.c index 2a22514019..55a156c562 100644 --- a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_cfg.c +++ b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_cfg.c @@ -972,8 +972,19 @@ ftdm_status_t sngisdn_stack_cfg_q931_lce(ftdm_span_t *span) cfg.t.cfg.s.inLCe.sapId = signal_data->dchan_id; cfg.t.cfg.s.inLCe.lnkUpDwnInd = TRUE; - cfg.t.cfg.s.inLCe.tCon.enb = TRUE; - cfg.t.cfg.s.inLCe.tCon.val = 35; + + if (FTDM_SPAN_IS_BRI(span)) { + /* tCon Timer causes unwanted hangup on BRI links + where the Q.921 link goes into disconnected + state when idle. */ + + cfg.t.cfg.s.inLCe.tCon.enb = FALSE; + cfg.t.cfg.s.inLCe.tCon.val = 0; + } else { + cfg.t.cfg.s.inLCe.tCon.enb = TRUE; + cfg.t.cfg.s.inLCe.tCon.val = 35; + } + cfg.t.cfg.s.inLCe.tDisc.enb = TRUE; cfg.t.cfg.s.inLCe.tDisc.val = 35; cfg.t.cfg.s.inLCe.t314.enb = FALSE; /* if segmentation enabled, set to TRUE */ 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 76641f3893..0a34068359 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 @@ -1169,12 +1169,13 @@ static ftdm_status_t sngisdn_bring_down(ftdm_channel_t *ftdmchan) void sngisdn_process_rst_cfm (sngisdn_event_data_t *sngisdn_event) { + ftdm_signaling_status_t sigstatus; int16_t suId = sngisdn_event->suId; int16_t dChan = sngisdn_event->dChan; uint8_t ces = sngisdn_event->ces; uint8_t evntType = sngisdn_event->evntType; uint8_t chan_no = 0; - Rst *rstEvnt = &sngisdn_event->event.rstEvnt; + Rst *rstEvnt = &sngisdn_event->event.rstEvnt; sngisdn_span_data_t *signal_data = g_sngisdn_data.dchans[dChan].spans[1]; if (!signal_data) { @@ -1213,23 +1214,26 @@ void sngisdn_process_rst_cfm (sngisdn_event_data_t *sngisdn_event) return; } } + + ftdm_span_get_sig_status(signal_data->ftdm_span, &sigstatus); + if (sigstatus == FTDM_SIG_STATE_DOWN) { + if (chan_no) { /* For a single channel */ + if (chan_no > ftdm_span_get_chan_count(signal_data->ftdm_span)) { + ftdm_log(FTDM_LOG_CRIT, "Received RESTART on invalid channel:%d\n", chan_no); + } else { + ftdm_channel_t *ftdmchan = ftdm_span_get_channel(signal_data->ftdm_span, chan_no); + sngisdn_bring_down(ftdmchan); + } + } else { /* for all channels */ + ftdm_iterator_t *chaniter = NULL; + ftdm_iterator_t *curr = NULL; - if (chan_no) { /* For a single channel */ - if (chan_no > ftdm_span_get_chan_count(signal_data->ftdm_span)) { - ftdm_log(FTDM_LOG_CRIT, "Received RESTART on invalid channel:%d\n", chan_no); - } else { - ftdm_channel_t *ftdmchan = ftdm_span_get_channel(signal_data->ftdm_span, chan_no); - sngisdn_bring_down(ftdmchan); + chaniter = ftdm_span_get_chan_iterator(signal_data->ftdm_span, NULL); + for (curr = chaniter; curr; curr = ftdm_iterator_next(curr)) { + sngisdn_bring_down((ftdm_channel_t*)ftdm_iterator_current(curr)); + } + ftdm_iterator_free(chaniter); } - } else { /* for all channels */ - ftdm_iterator_t *chaniter = NULL; - ftdm_iterator_t *curr = NULL; - - chaniter = ftdm_span_get_chan_iterator(signal_data->ftdm_span, NULL); - for (curr = chaniter; curr; curr = ftdm_iterator_next(curr)) { - sngisdn_bring_down((ftdm_channel_t*)ftdm_iterator_current(curr)); - } - ftdm_iterator_free(chaniter); } ftdm_log(FTDM_LOG_DEBUG, "Processing RESTART CFM (suId:%u dChan:%d ces:%d type:%d)\n", suId, dChan, ces, evntType); 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 076cb54a61..f528333634 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 @@ -305,6 +305,7 @@ void sngisdn_snd_fac_req(ftdm_channel_t *ftdmchan) return; } +/* This is used to request Q.921 to initiate link establishment */ void sngisdn_snd_info_req(ftdm_channel_t *ftdmchan) { CnStEvnt cnStEvnt; 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 72b6def4ae..c45bbf0874 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 @@ -689,6 +689,17 @@ void sngisdn_rcv_q921_ind(BdMngmt *status) DECODE_LCM_CATEGORY(status->t.usta.alarm.category), DECODE_LLD_EVENT(status->t.usta.alarm.event), status->t.usta.alarm.event, DECODE_LLD_CAUSE(status->t.usta.alarm.cause), status->t.usta.alarm.cause); + + if (FTDM_SPAN_IS_BRI(ftdmspan) && (status->t.usta.alarm.event == PROT_ST_DN)) { + /* Q.921 link is down - This is a line where the Q.921 stops transmitting + after the line goes idle. + + Do not drop current calls, but set sigstatus do down so that we + can try to re-initialize link before trying new outbound calls */ + + sngisdn_set_span_sig_status(ftdmspan, FTDM_SIG_STATE_DOWN); + sngisdn_set_span_avail_rate(ftdmspan, SNGISDN_AVAIL_PWR_SAVING); + } break; default: ftdm_log(FTDM_LOG_INFO, "[SNGISDN Q921] %s: %s: %s(%d): %s(%d)\n", diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_trace.c b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_trace.c index 52c4f4d321..56797fbf9c 100644 --- a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_trace.c +++ b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_trace.c @@ -112,7 +112,7 @@ uint8_t get_bits(uint8_t octet, uint8_t bitLo, uint8_t bitHi) void sngisdn_trace_interpreted_q921(sngisdn_span_data_t *signal_data, ftdm_trace_dir_t dir, uint8_t *data, uint32_t data_len) { - char *data_str = ftdm_calloc(1,200); /* TODO Find a proper size */ + char *data_str = ftdm_calloc(1,500); /* TODO Find a proper size */ sngisdn_decode_q921(data_str, data, data_len); ftdm_log(FTDM_LOG_DEBUG, "[SNGISDN Q921] %s FRAME %s:\n%s\n", signal_data->ftdm_span->name, ftdm_trace_dir2str(dir), data_str); ftdm_safe_free(data_str);