]> git.ipfire.org Git - thirdparty/freeswitch.git/commitdiff
FreeTDM - ISDN fix for BRI lines with Q.921 layer going idle
authorDavid Yat Sin <dyatsin@sangoma.com>
Tue, 3 Apr 2012 20:48:14 +0000 (16:48 -0400)
committerDavid Yat Sin <dyatsin@sangoma.com>
Tue, 3 Apr 2012 20:48:14 +0000 (16:48 -0400)
libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn.c
libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_cntrl.c
libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_cfg.c
libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_hndl.c
libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_out.c
libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_rcv.c
libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_trace.c

index e6740c2dddec7922c307db7c404a3540b75fb2cc..e3af9d9b98bc7d85b7f27211a779130a2c480e66 100644 (file)
@@ -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);
                        }
index 668b63006cdacc573299acff4f8cb9316506a008..15def40218e8436989c384156c41e502f95cb6ba 100644 (file)
@@ -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;
 }
 
index 2a225140198beae9fe29b9fa3bae031c88ccfd8f..55a156c5624e61fe836166b7a762406b641235ba 100644 (file)
@@ -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 */
index 76641f3893570d0a35fa2f87c7737897facdbc47..0a340683595ff0776a1f98d0b43bae78319db22c 100644 (file)
@@ -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);
-               }
-       } 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));
+                       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_iterator_free(chaniter);
        }
 
        ftdm_log(FTDM_LOG_DEBUG, "Processing RESTART CFM (suId:%u dChan:%d ces:%d type:%d)\n", suId, dChan, ces, evntType);
index 076cb54a6114577137be9d0410086d7ba91f0274..f52833363481ae43fac208e3987ccae2c1c0f72c 100644 (file)
@@ -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;
index 72b6def4ae8c93bd760b1d8bd3bd993adc305955..c45bbf0874e0fbafec5c09723b65cdd5a14d2e16 100644 (file)
@@ -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",
index 52c4f4d321278f4c043dd441d77e05666ecd4aca..56797fbf9cac0d3ed88938154bdd1d73130f5335 100644 (file)
@@ -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);