]> git.ipfire.org Git - thirdparty/freeswitch.git/commitdiff
Fix for NFAS when one of the d-channels are down
authorDavid Yat Sin <dyatsin@sangoma.com>
Thu, 7 Jun 2012 00:41:48 +0000 (20:41 -0400)
committerDavid Yat Sin <dyatsin@sangoma.com>
Thu, 7 Jun 2012 00:41:48 +0000 (20:41 -0400)
libs/freetdm/mod_freetdm/mod_freetdm.c
libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn.c
libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn.h
libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_cfg.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_cntrl.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_support.c

index 8b0acc3aef391de90b78c3dfc4d87fabaedb49c0..a2dacafd43bbb343e2ca698b5fc2cdf76ace0241 100755 (executable)
@@ -1884,10 +1884,8 @@ static FIO_SIGNAL_CB_FUNCTION(on_common_signal)
                                return FTDM_FAIL;
                        }
                        if (sigmsg->event_id == FTDM_SIGEVENT_ALARM_CLEAR) {
-                               ftdm_log(FTDM_LOG_NOTICE, "Alarm cleared on channel %d:%d\n", spanid, chanid);
                                switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "condition", "ftdm-alarm-clear");
                        } else {
-                               ftdm_log(FTDM_LOG_NOTICE, "Alarm raised on channel %d:%d\n", spanid, chanid);
                                switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "condition", "ftdm-alarm-trap");
                        }
                }
@@ -2489,7 +2487,7 @@ static FIO_SIGNAL_CB_FUNCTION(on_clear_channel_signal)
                break;  
        case FTDM_SIGEVENT_SIGSTATUS_CHANGED:
                {       
-                       ftdm_signaling_status_t sigstatus = sigmsg->ev_data.sigstatus.status;
+                       ftdm_signaling_status_t sigstatus = sigmsg->ev_data.sigstatus.status;   
                        switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "%d:%d signalling changed to :%s\n",
                                        spanid, chanid, ftdm_signaling_status2str(sigstatus));
                }
index e3af9d9b98bc7d85b7f27211a779130a2c480e66..0f9a63fde2eb71c56dc2c10a86b5437ed14758de 100644 (file)
@@ -281,8 +281,8 @@ ftdm_state_map_t sangoma_isdn_state_map = {
 static void ftdm_sangoma_isdn_process_phy_events(ftdm_span_t *span, ftdm_oob_event_t event)
 {
        sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*) span->signal_data;
-       sngisdn_snd_event(signal_data->dchan, event);
-       
+       sngisdn_snd_event(signal_data, event);
+
        switch (event) {
                /* Check if the span woke up from power-saving mode */
                case FTDM_OOB_ALARM_CLEAR:
@@ -354,7 +354,6 @@ static void *ftdm_sangoma_isdn_io_run(ftdm_thread_t *me, void *obj)
        short *poll_events = ftdm_malloc(sizeof(short) * span->chan_count);
 
        /* Initialize the d-channel */
-       ftdm_assert(((sngisdn_span_data_t*)span->signal_data)->dchan, "Span does not have a dchannel");
        chaniter = ftdm_span_get_chan_iterator(span, NULL);
        if (!chaniter) {
                ftdm_log(FTDM_LOG_CRIT, "Failed to allocate channel iterator for span %s!\n", span->name);
@@ -1039,21 +1038,11 @@ static ftdm_status_t ftdm_sangoma_isdn_dtmf(ftdm_channel_t *ftdmchan, const char
        return FTDM_SUCCESS;
 }
 
-static ftdm_status_t ftdm_sangoma_isdn_start(ftdm_span_t *span)
+static ftdm_status_t ftdm_sangoma_isdn_perform_start(ftdm_span_t *span)
 {
        sngisdn_span_data_t *signal_data = span->signal_data;
 
-       ftdm_log(FTDM_LOG_INFO,"Starting span %s:%u.\n",span->name,span->span_id);
-       
-       ftdm_channel_set_feature(((sngisdn_span_data_t*)span->signal_data)->dchan, FTDM_CHANNEL_FEATURE_IO_STATS);
-       ftdm_channel_open_chan(((sngisdn_span_data_t*)span->signal_data)->dchan);
-       ftdm_sangoma_isdn_dchan_set_queue_size(((sngisdn_span_data_t*)span->signal_data)->dchan);       
-
-       if (sngisdn_stack_start(span) != FTDM_SUCCESS) {
-               ftdm_log(FTDM_LOG_CRIT, "Failed to start span %s\n", span->name);
-               return FTDM_FAIL;
-       }
-
+       ftdm_log(FTDM_LOG_DEBUG, "Actually starting span:%s\n", span->name);
        /* clear the monitor thread stop flag */
        ftdm_clear_flag(span, FTDM_SPAN_STOP_THREAD);
        ftdm_clear_flag(span, FTDM_SPAN_IN_THREAD);
@@ -1085,12 +1074,64 @@ static ftdm_status_t ftdm_sangoma_isdn_start(ftdm_span_t *span)
        if (signal_data->restart_timeout) {
                ftdm_log(FTDM_LOG_DEBUG, "%s:Scheduling Restart timeout\n", signal_data->ftdm_span->name);
                ftdm_sched_timer(signal_data->sched, "restart_timeout", signal_data->restart_timeout,
-                                                       sngisdn_restart_timeout, (void*) signal_data, &signal_data->timers[SNGISDN_SPAN_TIMER_RESTART]);
+                                               sngisdn_restart_timeout, (void*) signal_data, &signal_data->timers[SNGISDN_SPAN_TIMER_RESTART]);
        }
+
        ftdm_log(FTDM_LOG_DEBUG,"Finished starting span %s\n", span->name);
        return FTDM_SUCCESS;
 }
 
+
+static ftdm_status_t ftdm_sangoma_isdn_start(ftdm_span_t *span)
+{
+       sngisdn_span_data_t *signal_data = span->signal_data;
+
+       ftdm_log(FTDM_LOG_INFO,"Starting span %s:%u.\n",span->name,span->span_id);
+
+       if (signal_data->dchan) {
+               ftdm_channel_set_feature(signal_data->dchan, FTDM_CHANNEL_FEATURE_IO_STATS);
+               ftdm_channel_open_chan(signal_data->dchan);
+               ftdm_sangoma_isdn_dchan_set_queue_size(signal_data->dchan);
+       }
+
+       if (signal_data->nfas.trunk) {
+               if (signal_data->nfas.trunk->num_spans == signal_data->nfas.trunk->num_spans_configured) {
+                       int i;
+                       ftdm_log(FTDM_LOG_DEBUG, "Starting span for all spans within trunkgroup:%s\n", signal_data->nfas.trunk->name);
+
+                       sngisdn_stack_start(signal_data->nfas.trunk->dchan->ftdm_span);
+                       ftdm_sangoma_isdn_perform_start(signal_data->nfas.trunk->dchan->ftdm_span);
+
+                       if (signal_data->nfas.trunk->backup) {
+                               sngisdn_stack_start(signal_data->nfas.trunk->backup->ftdm_span);
+                               ftdm_sangoma_isdn_perform_start(signal_data->nfas.trunk->backup->ftdm_span);
+                       }
+                       
+                       for (i = 0; i < signal_data->nfas.trunk->num_spans; i++) {
+                               if (signal_data->nfas.trunk->spans[i] &&
+                                       signal_data->nfas.trunk->spans[i]->nfas.sigchan == SNGISDN_NFAS_DCHAN_NONE) {
+                                       sngisdn_stack_start(signal_data->nfas.trunk->spans[i]->ftdm_span);
+                                       ftdm_sangoma_isdn_perform_start(signal_data->nfas.trunk->spans[i]->ftdm_span);
+                               }
+                       }
+
+                       return FTDM_SUCCESS;
+               } else {
+                       ftdm_log(FTDM_LOG_DEBUG, "Delaying span start until all spans within trunkgroup are started: %s\n", signal_data->nfas.trunk->name);
+                       return FTDM_SUCCESS;
+               }
+       }
+
+       if (sngisdn_stack_start(span) != FTDM_SUCCESS) {
+               ftdm_log(FTDM_LOG_CRIT, "Failed to start span %s\n", span->name);
+               return FTDM_FAIL;
+       }
+
+       ftdm_sangoma_isdn_perform_start(span);
+       
+       return FTDM_SUCCESS;
+}
+
 static ftdm_status_t ftdm_sangoma_isdn_stop(ftdm_span_t *span)
 {      
        ftdm_iterator_t *chaniter = NULL;
@@ -1138,13 +1179,13 @@ static FIO_CONFIGURE_SPAN_SIGNALING_FUNCTION(ftdm_sangoma_isdn_span_config)
        ftdm_iterator_t *chaniter = NULL;
        ftdm_iterator_t *curr = NULL;
 
-       sngisdn_span_data_t *span_data;
+       sngisdn_span_data_t *signal_data;
        
        ftdm_log(FTDM_LOG_INFO, "Configuring ftmod_sangoma_isdn span = %s\n", span->name);      
 
-       span_data = ftdm_calloc(1, sizeof(sngisdn_span_data_t));
-       span_data->ftdm_span = span;
-       span->signal_data = span_data;
+       signal_data = ftdm_calloc(1, sizeof(sngisdn_span_data_t));
+       signal_data->ftdm_span = span;
+       span->signal_data = signal_data;
        
        chaniter = ftdm_span_get_chan_iterator(span, NULL);
        for (curr = chaniter; curr; curr = ftdm_iterator_next(curr)) {
@@ -1160,79 +1201,98 @@ static FIO_CONFIGURE_SPAN_SIGNALING_FUNCTION(ftdm_sangoma_isdn_span_config)
                return FTDM_FAIL;
        }
 
-       if (sngisdn_stack_cfg(span) != FTDM_SUCCESS) {
+       if (signal_data->nfas.trunk) {
+               if (signal_data->nfas.trunk->num_spans == ++signal_data->nfas.trunk->num_spans_configured) {
+                       int i;
+                       ftdm_log(FTDM_LOG_DEBUG, "Starting stack configuration for all spans within trunkgroup:%s\n", signal_data->nfas.trunk->name);
+
+                       sngisdn_stack_cfg(signal_data->nfas.trunk->dchan->ftdm_span);
+                       if (signal_data->nfas.trunk->backup) {
+                               sngisdn_stack_cfg(signal_data->nfas.trunk->backup->ftdm_span);
+                       }
+                       
+                       for (i = 0; i < signal_data->nfas.trunk->num_spans; i++) {
+                               if (signal_data->nfas.trunk->spans[i] &&
+                                       signal_data->nfas.trunk->spans[i]->nfas.sigchan == SNGISDN_NFAS_DCHAN_NONE) {
+                                       sngisdn_stack_cfg(signal_data->nfas.trunk->spans[i]->ftdm_span);
+                               }
+                       }
+               } else {
+                       ftdm_log(FTDM_LOG_DEBUG, "Delaying span stack configuration until all spans within trunkgroup are started:%s\n", signal_data->nfas.trunk->name);
+               }
+       } else if (sngisdn_stack_cfg(span) != FTDM_SUCCESS) {
                ftdm_log(FTDM_LOG_CRIT, "Sangoma ISDN Stack configuration failed\n");
                return FTDM_FAIL;
        }
 
-       if (span_data->cid_name_method == SNGISDN_CID_NAME_AUTO) {
-               switch (span_data->switchtype) {
+       if (signal_data->cid_name_method == SNGISDN_CID_NAME_AUTO) {
+               switch (signal_data->switchtype) {
                        case SNGISDN_SWITCH_EUROISDN:
                                if (FTDM_SPAN_IS_BRI(span)) {
-                                       span_data->cid_name_method = SNGISDN_CID_NAME_USR_USR_IE;
+                                       signal_data->cid_name_method = SNGISDN_CID_NAME_USR_USR_IE;
                                } else {
-                                       span_data->cid_name_method = SNGISDN_CID_NAME_DISPLAY_IE;
+                                       signal_data->cid_name_method = SNGISDN_CID_NAME_DISPLAY_IE;
                                }
                                break;
                        case SNGISDN_SWITCH_DMS100:
-                               span_data->cid_name_method = SNGISDN_CID_NAME_DISPLAY_IE;
+                               signal_data->cid_name_method = SNGISDN_CID_NAME_DISPLAY_IE;
                                break;
                        case SNGISDN_SWITCH_NI2:
                        case SNGISDN_SWITCH_5ESS:
                        case SNGISDN_SWITCH_4ESS:
-                               span_data->cid_name_method = SNGISDN_CID_NAME_FACILITY_IE;
+                               signal_data->cid_name_method = SNGISDN_CID_NAME_FACILITY_IE;
                                break;
                        default:
                                break;
                }
        }
 
-       if (span_data->send_cid_name == SNGISDN_OPT_DEFAULT) {
-               switch (span_data->switchtype) {
+       if (signal_data->send_cid_name == SNGISDN_OPT_DEFAULT) {
+               switch (signal_data->switchtype) {
                        case SNGISDN_SWITCH_EUROISDN:
 #ifdef SNGISDN_SUPPORT_CALLING_NAME_IN_FACILITY
                        case SNGISDN_SWITCH_NI2:
                        case SNGISDN_SWITCH_5ESS:
                        case SNGISDN_SWITCH_4ESS:
 #endif
-                               if (span_data->signalling == SNGISDN_SIGNALING_NET) {
-                                       span_data->send_cid_name = SNGISDN_OPT_TRUE;
+                               if (signal_data->signalling == SNGISDN_SIGNALING_NET) {
+                                       signal_data->send_cid_name = SNGISDN_OPT_TRUE;
                                } else {
-                                       span_data->send_cid_name = SNGISDN_OPT_FALSE;
+                                       signal_data->send_cid_name = SNGISDN_OPT_FALSE;
                                }
                                break;
                        case SNGISDN_SWITCH_DMS100:
-                               span_data->send_cid_name = SNGISDN_OPT_TRUE;
+                               signal_data->send_cid_name = SNGISDN_OPT_TRUE;
                                break;
 #ifndef SNGISDN_SUPPORT_CALLING_NAME_IN_FACILITY
                        case SNGISDN_SWITCH_NI2:
                        case SNGISDN_SWITCH_5ESS:
                        case SNGISDN_SWITCH_4ESS:
-                               span_data->send_cid_name = SNGISDN_OPT_FALSE;
+                               signal_data->send_cid_name = SNGISDN_OPT_FALSE;
                                break;
 #endif
                        default:
-                               span_data->send_cid_name = SNGISDN_OPT_FALSE;
+                               signal_data->send_cid_name = SNGISDN_OPT_FALSE;
                                break;
                }
-       } else if (span_data->send_cid_name == SNGISDN_OPT_TRUE) {
-               switch (span_data->switchtype) {
+       } else if (signal_data->send_cid_name == SNGISDN_OPT_TRUE) {
+               switch (signal_data->switchtype) {
                        case SNGISDN_SWITCH_NI2:
                        case SNGISDN_SWITCH_5ESS:
                        case SNGISDN_SWITCH_4ESS:
 #ifndef SNGISDN_SUPPORT_CALLING_NAME_IN_FACILITY
                                ftdm_log(FTDM_LOG_WARNING, "Sending Calling Name in Facility IE not supported, please update your libsng_isdn library\n");
-                               span_data->send_cid_name = SNGISDN_OPT_FALSE;
+                               signal_data->send_cid_name = SNGISDN_OPT_FALSE;
 #endif
                                break;
                        case SNGISDN_SWITCH_INSNET: /* Don't know how to transmit caller ID name on INSNET */
                        case SNGISDN_SWITCH_QSIG: /* It seems like QSIG does not support Caller ID */
-                               span_data->send_cid_name = SNGISDN_OPT_FALSE;
+                               signal_data->send_cid_name = SNGISDN_OPT_FALSE;
                                break;
                        case SNGISDN_SWITCH_EUROISDN:
                                break;
                        default:
-                               span_data->send_cid_name = SNGISDN_OPT_FALSE;
+                               signal_data->send_cid_name = SNGISDN_OPT_FALSE;
                                break;
                }
        }
index 92054b88694e23544fa67e6ca1e68bfe015270e1..0034add1539617ec4486be6cb94984219df916a0 100644 (file)
@@ -58,7 +58,8 @@
 /* Theoretical limit for MAX_SPANS_PER_NFAS_LINK is 31,
    but set to 8 for now to save some memory */
 
-#define MAX_SPANS_PER_NFAS_LINK                8 
+#define MAX_SPANS_PER_NFAS_LINK                16
+#define MAX_NFAS_GROUPS                                16
 #define NUM_E1_CHANNELS_PER_SPAN       32
 #define NUM_T1_CHANNELS_PER_SPAN       24
 #define NUM_BRI_CHANNELS_PER_SPAN      2
@@ -66,6 +67,9 @@
 #define SNGISDN_EVENT_POLL_RATE                100
 #define SNGISDN_NUM_LOCAL_NUMBERS      8
 #define SNGISDN_DCHAN_QUEUE_LEN                200
+#define MAX_NFAS_GROUP_NAME                    50
+
+#define NSG
 
 #ifndef MI_NOTIFY
 #define MI_NOTIFY 0x14
@@ -242,16 +246,25 @@ typedef struct sngisdn_chan_data {
        ftdm_size_t                             raw_data_len;
 } sngisdn_chan_data_t;
 
+struct sngisdn_nfas_data;
+typedef struct sngisdn_nfas_data sngisdn_nfas_data_t;
+
+typedef enum {
+       SNGISDN_NFAS_DCHAN_NONE,
+       SNGISDN_NFAS_DCHAN_PRIMARY,
+       SNGISDN_NFAS_DCHAN_BACKUP,
+} sngisdn_nfas_sigchan_t;
+
 /* Span specific data */
 typedef struct sngisdn_span_data {
        ftdm_span_t             *ftdm_span;
        ftdm_channel_t  *dchan;
        uint8_t                 link_id;
        uint8_t                 switchtype;
-       uint8_t                 signalling;                     /* SNGISDN_SIGNALING_CPE or SNGISDN_SIGNALING_NET */
+       uint8_t                 signalling;             /* SNGISDN_SIGNALING_CPE or SNGISDN_SIGNALING_NET */
        uint8_t                 cc_id;
-       uint8_t                 dchan_id;
-       uint8_t                 span_id;
+       ftdm_signaling_status_t         sigstatus;
+
        uint8_t                 tei;
        uint8_t                 min_digits;
        uint8_t                 trace_flags;            /* TODO change to bit map of sngisdn_tracetype_t */
@@ -274,7 +287,7 @@ typedef struct sngisdn_span_data {
        uint8_t                 restart_timeout;
        uint8_t                 force_sending_complete;
        uint8_t                 cid_name_method;
-       uint8_t                 send_cid_name;
+       uint8_t                 send_cid_name;  
 
        int32_t                 timer_t301;
        int32_t                 timer_t302;
@@ -292,11 +305,20 @@ typedef struct sngisdn_span_data {
        int32_t                 timer_t318;
        int32_t                 timer_t319;
        int32_t                 timer_t322;
-       
+
        char*                   local_numbers[SNGISDN_NUM_LOCAL_NUMBERS];
        ftdm_timer_id_t timers[SNGISDN_NUM_SPAN_TIMERS];
        ftdm_sched_t    *sched;
        ftdm_queue_t    *event_queue;
+
+       struct nfas_info {
+               sngisdn_nfas_data_t *trunk;
+               sngisdn_nfas_sigchan_t sigchan;
+               uint8_t interface_id;
+       } nfas;
+
+       uint32_t num_chans;
+       sngisdn_chan_data_t *channels[NUM_E1_CHANNELS_PER_SPAN];
 } sngisdn_span_data_t;
 
 typedef struct sngisdn_event_data {
@@ -331,19 +353,18 @@ typedef struct sngisdn_event_data {
        
 } sngisdn_event_data_t;
 
-/* dchan_data can have more than 1 span when running NFAS */
-typedef struct sngisdn_dchan_data {
-       uint8_t                         num_spans;
-       sngisdn_span_data_t     *spans[MAX_L1_LINKS+1];
-       uint16_t                        num_chans;
-       /* worst case for number of channel is when using NFAS, and NFAS is only used on T1,
-               so we can use MAX_SPANS_PER_NFAS_LINK*NUM_T1_CHANNELS_PER_SPAN instead of
-               MAX_SPANS_PER_NFAS_LINK*NUM_E1_CHANNELS_PER_SPAN
-       */
-       /* Never seen NFAS on E1 yet, so use NUM_T1_CHANNELS_PER_SPAN */
-       /* b-channels are arranged by physical id's not logical */
-       sngisdn_chan_data_t *channels[MAX_SPANS_PER_NFAS_LINK*NUM_T1_CHANNELS_PER_SPAN];
-}sngisdn_dchan_data_t;
+struct sngisdn_nfas_data {
+       char name[MAX_NFAS_GROUP_NAME];
+
+       char dchan_span_name[20];
+       sngisdn_span_data_t *dchan;     /* Span that contains primary d-channel */
+
+       char backup_span_name[20];
+       sngisdn_span_data_t *backup; /* Span that contains backup d-channel */
+       uint8_t num_spans;                      /* Number of spans within this NFAS */
+       uint8_t num_spans_configured;
+       sngisdn_span_data_t     *spans[MAX_SPANS_PER_NFAS_LINK+1]; //indexed by logical span id
+};
 
 typedef struct sngisdn_cc {
        /* TODO: use flags instead of config_done and activation_done */
@@ -360,10 +381,10 @@ typedef struct sngisdn_cc {
 /* Global sngisdn data */
 typedef struct ftdm_sngisdn_data {
        uint8_t gen_config_done;
-       uint8_t num_cc;                                         /* 1 ent per switchtype */
-       struct sngisdn_cc ccs[MAX_VARIANTS+1];
-       uint8_t num_dchan;
-       sngisdn_dchan_data_t dchans[MAX_L1_LINKS+1];
+       uint8_t num_cc;                                         /* 1 ent per switchtype */      
+       struct sngisdn_cc ccs[MAX_VARIANTS+1];  
+       uint8_t num_nfas;
+       sngisdn_nfas_data_t nfass[MAX_NFAS_GROUPS+1];
        sngisdn_span_data_t *spans[MAX_L1_LINKS+1]; /* spans are indexed by link_id */
 
 #ifdef SANGOMA_ISDN_CHAN_ID_INVERT_BIT
@@ -424,7 +445,7 @@ void sngisdn_snd_info_req(ftdm_channel_t *ftdmchan);
 void sngisdn_snd_status_enq(ftdm_channel_t *ftdmchan);
 void sngisdn_snd_restart(ftdm_channel_t *ftdmchan);
 void sngisdn_snd_data(ftdm_channel_t *dchan, uint8_t *data, ftdm_size_t len);
-void sngisdn_snd_event(ftdm_channel_t *dchan, ftdm_oob_event_t event);
+void sngisdn_snd_event(sngisdn_span_data_t *signal_data, ftdm_oob_event_t event);
 
 /* Inbound Call Control functions */
 void sngisdn_rcv_con_ind(int16_t suId, uint32_t suInstId, uint32_t spInstId, ConEvnt *conEvnt, int16_t dChan, uint8_t ces);
@@ -553,6 +574,7 @@ static __inline__ void sngisdn_set_flag(sngisdn_chan_data_t *sngisdn_info, sngis
 void handle_sng_log(uint8_t level, char *fmt,...);
 void sngisdn_delayed_setup(void* p_sngisdn_info);
 void sngisdn_delayed_release(void* p_sngisdn_info);
+void sngisdn_delayed_release_nfas(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);
@@ -564,6 +586,7 @@ ftdm_status_t sngisdn_stack_cfg(ftdm_span_t *span);
 ftdm_status_t sngisdn_stack_start(ftdm_span_t *span);
 ftdm_status_t sngisdn_stack_stop(ftdm_span_t *span);
 ftdm_status_t sngisdn_wake_up_phy(ftdm_span_t *span);
+sngisdn_span_data_t *sngisdn_dchan(sngisdn_span_data_t *signal_data);
 
 ftdm_status_t sngisdn_show_l1_stats(ftdm_stream_handle_t *stream, ftdm_span_t *span);
 ftdm_status_t sngisdn_show_spans(ftdm_stream_handle_t *stream);
index ba05d9b4a42aa420c10f0e62da11b4aaaf6dff59..45c6c9cc1794815e3b3a7a9f1fb8721910bb8012 100644 (file)
@@ -37,6 +37,7 @@
 static ftdm_status_t parse_timer(const char* val, int32_t *target);
 static ftdm_status_t parse_switchtype(const char* switch_name, ftdm_span_t *span);
 static ftdm_status_t parse_signalling(const char* signalling, ftdm_span_t *span);
+static ftdm_status_t parse_trunkgroup(const char *_trunkgroup);
 static ftdm_status_t add_local_number(const char* val, ftdm_span_t *span);
 static ftdm_status_t parse_yesno(const char* var, const char* val, uint8_t *target);
 static ftdm_status_t set_switchtype_defaults(ftdm_span_t *span);
@@ -81,7 +82,7 @@ static ftdm_status_t parse_switchtype(const char* switch_name, ftdm_span_t *span
        unsigned i;
        ftdm_iterator_t *chaniter = NULL;
        ftdm_iterator_t *curr = NULL;   
-       sngisdn_dchan_data_t *dchan_data;
+       //sngisdn_dchan_data_t *dchan_data;
        sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*) span->signal_data;
        
        switch(span->trunk_type) {
@@ -133,13 +134,15 @@ static ftdm_status_t parse_switchtype(const char* switch_name, ftdm_span_t *span
                        ftdm_log(FTDM_LOG_ERROR, "%s:Unsupported trunktype:%s\n", span->name, switch_name, ftdm_trunk_type2str(span->trunk_type));
                        return FTDM_FAIL;
        }
+
        /* see if we have profile with this switch_type already */
-       for (i=1; i <= g_sngisdn_data.num_cc; i++) {
+       for (i = 1; i <= g_sngisdn_data.num_cc; i++) {
                if (g_sngisdn_data.ccs[i].switchtype == signal_data->switchtype &&
                        g_sngisdn_data.ccs[i].trunktype == span->trunk_type) {
                        break;
                }
        }
+
        /* need to create a new switch_type */
        if (i > g_sngisdn_data.num_cc) {
                g_sngisdn_data.num_cc++;
@@ -151,20 +154,9 @@ static ftdm_status_t parse_switchtype(const char* switch_name, ftdm_span_t *span
        /* add this span to its ent_cc */
        signal_data->cc_id = i;
 
-       /* create a new dchan */ /* for NFAS - no-dchan on b-channels-only links */
-       g_sngisdn_data.num_dchan++;
-       signal_data->dchan_id = g_sngisdn_data.num_dchan;
-
-       dchan_data = &g_sngisdn_data.dchans[signal_data->dchan_id];
-       dchan_data->num_spans++;
-
-       signal_data->span_id = dchan_data->num_spans;
-       dchan_data->spans[signal_data->span_id] = signal_data;
-
        g_sngisdn_data.spans[signal_data->link_id] = signal_data;
        
-       ftdm_log(FTDM_LOG_DEBUG, "%s: cc_id:%d dchan_id:%d span_id:%d link_id:%d\n", span->name, signal_data->cc_id, signal_data->dchan_id, signal_data->span_id, signal_data->link_id);
-
+       ftdm_log(FTDM_LOG_DEBUG, "%s: cc_id:%d link_id:%d\n", span->name, signal_data->cc_id, signal_data->link_id);
        
        chaniter = ftdm_span_get_chan_iterator(span, NULL);
        for (curr = chaniter; curr; curr = ftdm_iterator_next(curr)) {
@@ -175,17 +167,16 @@ static ftdm_status_t parse_switchtype(const char* switch_name, ftdm_span_t *span
                        signal_data->dchan = ftdmchan;
                } else {
                        /* Add the channels to the span */
-                       /* NFAS is not supported on E1, so span_id will always be 1 for E1 so this will work for E1 as well */
-                       chan_id = ((signal_data->span_id-1)*NUM_T1_CHANNELS_PER_SPAN)+ftdmchan->physical_chan_id;
-                       dchan_data->channels[chan_id] = (sngisdn_chan_data_t*)ftdmchan->call_data;
-                       dchan_data->num_chans++;
+                       chan_id = ftdmchan->physical_chan_id;
+                       signal_data->channels[chan_id] = (sngisdn_chan_data_t*)ftdmchan->call_data;
+                       signal_data->num_chans++;
                }
        }
        ftdm_iterator_free(chaniter);
        return FTDM_SUCCESS;
 }
 
-static ftdm_status_t parse_signalling(const charsignalling, ftdm_span_t *span)
+static ftdm_status_t parse_signalling(const char *signalling, ftdm_span_t *span)
 {
        sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*) span->signal_data;
        if (!strcasecmp(signalling, "net") ||
@@ -205,6 +196,146 @@ static ftdm_status_t parse_signalling(const char* signalling, ftdm_span_t *span)
        return FTDM_SUCCESS;
 }
 
+static ftdm_status_t parse_spanmap(const char *_spanmap, ftdm_span_t *span)
+{
+       int i;
+       char *p, *name, *spanmap;
+       uint8_t logical_span_id = 0;
+       ftdm_status_t ret = FTDM_SUCCESS;
+       sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*) span->signal_data;
+
+       spanmap = ftdm_strdup(_spanmap);
+
+       p = name = NULL;
+
+       i = 0;
+       for (p = strtok(spanmap, ","); p; p = strtok(NULL, ",")) {
+               while (*p == ' ') {
+                       p++;
+               }
+               switch(i++) {
+                       case 0:
+                               name = ftdm_strdup(p);
+                               break;
+                       case 1:
+                               logical_span_id = atoi(p);
+                               break;
+               }
+       }
+
+       if (!name || logical_span_id < 0) {
+               ftdm_log(FTDM_LOG_ERROR, "Invalid spanmap syntax %s\n", _spanmap);
+               ret = FTDM_FAIL;
+               goto done;
+       }
+
+       for (i = 0; i < g_sngisdn_data.num_nfas; i++) {
+               if (!ftdm_strlen_zero(g_sngisdn_data.nfass[i].name) &&
+                       !strcasecmp(g_sngisdn_data.nfass[i].name, name)) {
+
+                       signal_data->nfas.trunk = &g_sngisdn_data.nfass[i];
+                       break;
+               }
+       }
+
+       if (!signal_data->nfas.trunk) {
+               ftdm_log(FTDM_LOG_ERROR, "Could not find trunkgroup with name %s\n", name);
+               ret = FTDM_FAIL;
+               goto done;
+       }
+
+       if (signal_data->nfas.trunk->spans[logical_span_id]) {
+               ftdm_log(FTDM_LOG_ERROR, "trunkgroup:%s already had a span with logical span id:%d\n", name, logical_span_id);
+       } else {
+               signal_data->nfas.trunk->spans[logical_span_id] = signal_data;
+               signal_data->nfas.interface_id = logical_span_id;
+       }
+
+       if (!strcasecmp(signal_data->ftdm_span->name, signal_data->nfas.trunk->dchan_span_name)) {
+
+               signal_data->nfas.sigchan = SNGISDN_NFAS_DCHAN_PRIMARY;
+               signal_data->nfas.trunk->dchan = signal_data;
+       }
+
+       if (!strcasecmp(signal_data->ftdm_span->name, signal_data->nfas.trunk->backup_span_name)) {
+
+               signal_data->nfas.sigchan = SNGISDN_NFAS_DCHAN_BACKUP;
+               signal_data->nfas.trunk->backup = signal_data;
+       }
+
+done:
+       ftdm_safe_free(spanmap);
+       ftdm_safe_free(name);
+       return ret;
+}
+
+static ftdm_status_t parse_trunkgroup(const char *_trunkgroup)
+{
+       int i;
+       char *p, *name, *dchan_span, *backup_span, *trunkgroup;
+       uint8_t num_spans;
+       ftdm_status_t ret = FTDM_SUCCESS;
+
+       trunkgroup =  ftdm_strdup(_trunkgroup);
+
+       p = name = dchan_span = backup_span = NULL;
+
+       /* format: name, num_chans, dchan_span, [backup_span] */
+
+       i = 0;
+       for (p = strtok(trunkgroup, ","); p; p = strtok(NULL, ",")) {
+               while (*p == ' ') {
+                       p++;
+               }
+               switch(i++) {
+                       case 0:
+                               name = ftdm_strdup(p);
+                               break;
+                       case 1:
+                               num_spans = atoi(p);
+                               break;
+                       case 2:
+                               dchan_span = ftdm_strdup(p);
+                               break;
+                       case 3:
+                               backup_span = ftdm_strdup(p);
+               }
+       }
+
+       if (!name || !dchan_span || num_spans <= 0) {
+               ftdm_log(FTDM_LOG_ERROR, "Invalid parameters for trunkgroup:%s\n", _trunkgroup);
+               ret = FTDM_FAIL;
+               goto done;
+       }
+
+       for (i = 0; i < g_sngisdn_data.num_nfas; i++) {
+               if (!ftdm_strlen_zero(g_sngisdn_data.nfass[i].name) &&
+                   !strcasecmp(g_sngisdn_data.nfass[i].name, name)) {
+
+                       /* We already configured this trunkgroup */
+                       goto done;
+               }
+       }
+
+       /* Trunk group was not found, need to configure it */
+       strncpy(g_sngisdn_data.nfass[i].name, name, sizeof(g_sngisdn_data.nfass[i].name));
+       g_sngisdn_data.nfass[i].num_spans = num_spans;
+       strncpy(g_sngisdn_data.nfass[i].dchan_span_name, dchan_span, sizeof(g_sngisdn_data.nfass[i].dchan_span_name));
+
+       if (backup_span) {
+               strncpy(g_sngisdn_data.nfass[i].backup_span_name, backup_span, sizeof(g_sngisdn_data.nfass[i].backup_span_name));
+       }
+       
+
+       g_sngisdn_data.num_nfas++;
+done:
+       ftdm_safe_free(trunkgroup);
+       ftdm_safe_free(name);
+       ftdm_safe_free(dchan_span);
+       ftdm_safe_free(backup_span);
+       return FTDM_SUCCESS;
+}
+
 static ftdm_status_t parse_early_media(const char* opt, ftdm_span_t *span)
 {
        sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*) span->signal_data;
@@ -314,6 +445,19 @@ ftdm_status_t ftmod_isdn_parse_cfg(ftdm_conf_parameter_t *ftdm_parameters, ftdm_
        /* Cannot set default bearer_layer1 yet, as we do not know the switchtype */
        span->default_caller_data.bearer_layer1 = FTDM_INVALID_INT_PARM;
 
+       /* Find out if NFAS is enabled first */
+       for (paramindex = 0; ftdm_parameters[paramindex].var; paramindex++) {
+               ftdm_log(FTDM_LOG_DEBUG, "Sangoma ISDN key=value, %s=%s\n", ftdm_parameters[paramindex].var, ftdm_parameters[paramindex].val);
+               var = ftdm_parameters[paramindex].var;
+               val = ftdm_parameters[paramindex].val;
+
+               if (!strcasecmp(var, "trunkgroup")) {
+                       if (parse_trunkgroup(val) != FTDM_SUCCESS) {
+                               return FTDM_FAIL;
+                       }
+               }
+       }
+
        for (paramindex = 0; ftdm_parameters[paramindex].var; paramindex++) {
                ftdm_log(FTDM_LOG_DEBUG, "Sangoma ISDN key=value, %s=%s\n", ftdm_parameters[paramindex].var, ftdm_parameters[paramindex].val);
                var = ftdm_parameters[paramindex].var;
@@ -331,6 +475,10 @@ ftdm_status_t ftmod_isdn_parse_cfg(ftdm_conf_parameter_t *ftdm_parameters, ftdm_
                        if (parse_signalling(val, span) != FTDM_SUCCESS) {
                                return FTDM_FAIL;
                        }
+               } else if (!strcasecmp(var, "spanmap")) {
+                       if (parse_spanmap(val, span) != FTDM_SUCCESS) {
+                               return FTDM_FAIL;
+                       }
                } else if (!strcasecmp(var, "tei")) {
                        uint8_t tei = atoi(val);
                        if (tei > 127) {
@@ -465,6 +613,8 @@ ftdm_status_t ftmod_isdn_parse_cfg(ftdm_conf_parameter_t *ftdm_parameters, ftdm_
                        parse_timer(val, &signal_data->timer_t319);
                } else if (!strcasecmp(var, "timer-t322")) {
                        parse_timer(val, &signal_data->timer_t322);
+               } else if (!strcasecmp(var, "trunkgroup")) {
+                       /* Do nothing, we already parsed this parameter */
                } else {
                        ftdm_log(FTDM_LOG_WARNING, "Ignoring unknown parameter %s\n", ftdm_parameters[paramindex].var);
                }
index 15def40218e8436989c384156c41e502f95cb6ba..754aff11870a52e18b7bde8eeb269b9db06dbdf9 100644 (file)
@@ -40,6 +40,8 @@ void sngisdn_set_chan_sig_status(ftdm_channel_t *ftdmchan, ftdm_signaling_status
 void sngisdn_set_chan_sig_status(ftdm_channel_t *ftdmchan, ftdm_signaling_status_t status)
 {
        ftdm_sigmsg_t sig;
+       sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*)ftdmchan->span->signal_data;
+       
        ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Signalling link status changed to %s\n", ftdm_signaling_status2str(status));
 
        memset(&sig, 0, sizeof(sig));
@@ -52,7 +54,6 @@ void sngisdn_set_chan_sig_status(ftdm_channel_t *ftdmchan, ftdm_signaling_status
 
        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);
 
@@ -67,6 +68,7 @@ void sngisdn_set_span_sig_status(ftdm_span_t *span, ftdm_signaling_status_t stat
        ftdm_iterator_t *chaniter = NULL;
        ftdm_iterator_t *curr = NULL;
 
+       ((sngisdn_span_data_t*)span->signal_data)->sigstatus = status;
 
        chaniter = ftdm_span_get_chan_iterator(span, NULL);
        for (curr = chaniter; curr; curr = ftdm_iterator_next(curr)) {
index 55a156c5624e61fe836166b7a762406b641235ba..b96a8012432e6c44c7f71d37afc7f44a21aa56db 100644 (file)
@@ -62,6 +62,8 @@ ftdm_status_t sngisdn_stack_cfg(ftdm_span_t *span)
 {
        sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*)span->signal_data;
 
+       ftdm_log(FTDM_LOG_DEBUG, "Starting stack configuration for span:%s\n", span->name);
+       
        if (!g_sngisdn_data.gen_config_done) {
                g_sngisdn_data.gen_config_done = 1;
                ftdm_log(FTDM_LOG_DEBUG, "Starting general stack configuration\n");
@@ -91,33 +93,33 @@ ftdm_status_t sngisdn_stack_cfg(ftdm_span_t *span)
                ftdm_log(FTDM_LOG_INFO, "General stack configuration done\n");
        }
 
-       /* TODO: for NFAS, should only call these function for spans with d-chans */
-       if (sngisdn_stack_cfg_phy_psap(span) != FTDM_SUCCESS) {
-               ftdm_log(FTDM_LOG_ERROR, "%s:phy_psap configuration failed\n", span->name);
-               return FTDM_FAIL;
-       }
-       ftdm_log(FTDM_LOG_DEBUG, "%s:phy_psap configuration done\n", span->name);
-
-       if (sngisdn_stack_cfg_q921_msap(span) != FTDM_SUCCESS) {
-               ftdm_log(FTDM_LOG_ERROR, "%s:q921_msap configuration failed\n", span->name);
-               return FTDM_FAIL;
-       }
-       ftdm_log(FTDM_LOG_DEBUG, "%s:q921_msap configuration done\n", span->name);
+       if (signal_data->dchan) {
+               if (sngisdn_stack_cfg_phy_psap(span) != FTDM_SUCCESS) {
+                       ftdm_log(FTDM_LOG_ERROR, "%s:phy_psap configuration failed\n", span->name);
+                       return FTDM_FAIL;
+               }
+               ftdm_log(FTDM_LOG_DEBUG, "%s:phy_psap configuration done\n", span->name);
 
-       if (sngisdn_stack_cfg_q921_dlsap(span, 0) != FTDM_SUCCESS) {
-               ftdm_log(FTDM_LOG_ERROR, "%s:q921_dlsap configuration failed\n", span->name);
-               return FTDM_FAIL;
-       }
-       ftdm_log(FTDM_LOG_DEBUG, "%s:q921_dlsap configuration done\n", span->name);
+               if (sngisdn_stack_cfg_q921_msap(span) != FTDM_SUCCESS) {
+                       ftdm_log(FTDM_LOG_ERROR, "%s:q921_msap configuration failed\n", span->name);
+                       return FTDM_FAIL;
+               }
+               ftdm_log(FTDM_LOG_DEBUG, "%s:q921_msap configuration done\n", span->name);
 
-       if (span->trunk_type == FTDM_TRUNK_BRI_PTMP) {
-               if (sngisdn_stack_cfg_q921_dlsap(span, 1) != FTDM_SUCCESS) {
-                       ftdm_log(FTDM_LOG_ERROR, "%s:q921_dlsap management configuration failed\n", span->name);
+               if (sngisdn_stack_cfg_q921_dlsap(span, 0) != FTDM_SUCCESS) {
+                       ftdm_log(FTDM_LOG_ERROR, "%s:q921_dlsap configuration failed\n", span->name);
                        return FTDM_FAIL;
                }
-               ftdm_log(FTDM_LOG_DEBUG, "%s:q921_dlsap management configuration done\n", span->name);
+               ftdm_log(FTDM_LOG_DEBUG, "%s:q921_dlsap configuration done\n", span->name);
+
+               if (span->trunk_type == FTDM_TRUNK_BRI_PTMP) {
+                       if (sngisdn_stack_cfg_q921_dlsap(span, 1) != FTDM_SUCCESS) {
+                               ftdm_log(FTDM_LOG_ERROR, "%s:q921_dlsap management configuration failed\n", span->name);
+                               return FTDM_FAIL;
+                       }
+                       ftdm_log(FTDM_LOG_DEBUG, "%s:q921_dlsap management configuration done\n", span->name);
+               }
        }
-       
 
        if (sngisdn_stack_cfg_q931_dlsap(span) != FTDM_SUCCESS) {
                ftdm_log(FTDM_LOG_ERROR, "%s:q931_dlsap configuration failed\n", span->name);
@@ -125,11 +127,13 @@ ftdm_status_t sngisdn_stack_cfg(ftdm_span_t *span)
        }
        ftdm_log(FTDM_LOG_DEBUG, "%s:q931_dlsap configuration done\n", span->name);
 
-       if (sngisdn_stack_cfg_q931_lce(span) != FTDM_SUCCESS) {
-               ftdm_log(FTDM_LOG_ERROR, "%s:q931_lce configuration failed\n", span->name);
-               return FTDM_FAIL;
+       if (signal_data->dchan) {
+               if (sngisdn_stack_cfg_q931_lce(span) != FTDM_SUCCESS) {
+                       ftdm_log(FTDM_LOG_ERROR, "%s:q931_lce configuration failed\n", span->name);
+                       return FTDM_FAIL;
+               }
+               ftdm_log(FTDM_LOG_DEBUG, "%s:q931_lce configuration done\n", span->name);
        }
-       ftdm_log(FTDM_LOG_DEBUG, "%s:q931_lce configuration done\n", span->name);
 
        if (!g_sngisdn_data.ccs[signal_data->cc_id].config_done) {
                g_sngisdn_data.ccs[signal_data->cc_id].config_done = 1;
@@ -216,7 +220,7 @@ ftdm_status_t sngisdn_stack_cfg_phy_psap(ftdm_span_t *span)
        cfg.hdr.entId.inst  = S_INST;
        cfg.hdr.elmId.elmnt = STPSAP;
 
-       cfg.hdr.elmId.elmntInst1    = signal_data->dchan_id;
+       cfg.hdr.elmId.elmntInst1    = signal_data->link_id;
 
        if (!signal_data->dchan) {
                ftdm_log(FTDM_LOG_ERROR, "%s:No d-channels specified\n", span->name);
@@ -242,7 +246,7 @@ ftdm_status_t sngisdn_stack_cfg_phy_psap(ftdm_span_t *span)
                        return FTDM_FAIL;
        }
 
-       cfg.t.cfg.s.l1PSAP.spId         = signal_data->dchan_id;
+       cfg.t.cfg.s.l1PSAP.spId         = signal_data->link_id;
 
        if (sng_isdn_phy_config(&pst, &cfg)) {
                return FTDM_FAIL;
@@ -316,7 +320,7 @@ ftdm_status_t sngisdn_stack_cfg_q921_msap(ftdm_span_t *span)
        cfg.hdr.entId.inst  = S_INST;
        cfg.hdr.elmId.elmnt = STMSAP;
 
-       cfg.t.cfg.s.bdMSAP.lnkNmb      = signal_data->dchan_id;
+       cfg.t.cfg.s.bdMSAP.lnkNmb      = signal_data->link_id;
 
        cfg.t.cfg.s.bdMSAP.maxOutsFrms = 24;            /* MAC window */
        cfg.t.cfg.s.bdMSAP.tQUpperTrs  = 32;           /* Tx Queue Upper Threshold */
@@ -409,7 +413,7 @@ ftdm_status_t sngisdn_stack_cfg_q921_dlsap(ftdm_span_t *span, uint8_t management
        cfg.hdr.entId.inst  = S_INST;
        cfg.hdr.elmId.elmnt = STDLSAP;
 
-       cfg.t.cfg.s.bdDLSAP.lnkNmb              = signal_data->dchan_id;
+       cfg.t.cfg.s.bdDLSAP.lnkNmb              = signal_data->link_id;
 
        cfg.t.cfg.s.bdDLSAP.n201                = 1028;                 /* n201 */
        if (span->trunk_type == FTDM_TRUNK_BRI_PTMP ||
@@ -614,8 +618,8 @@ ftdm_status_t sngisdn_stack_cfg_q931_dlsap(ftdm_span_t *span)
 
        cfg.hdr.response.selector=0;
 
-       cfg.t.cfg.s.inDLSAP.sapId = signal_data->dchan_id;
-       cfg.t.cfg.s.inDLSAP.spId = signal_data->dchan_id;
+       cfg.t.cfg.s.inDLSAP.sapId = signal_data->link_id;
+       cfg.t.cfg.s.inDLSAP.spId = signal_data->link_id;
 
        cfg.t.cfg.s.inDLSAP.swtch = sng_isdn_stack_switchtype(signal_data->switchtype);
 
@@ -630,11 +634,9 @@ ftdm_status_t sngisdn_stack_cfg_q931_dlsap(ftdm_span_t *span)
        } else {
                cfg.t.cfg.s.inDLSAP.facilityHandling = 0;
        }
-
-       /* TODO : NFAS configuration */
-       cfg.t.cfg.s.inDLSAP.nfasInt = FALSE; /* pass this later */
-
-       if (!cfg.t.cfg.s.inDLSAP.nfasInt) {
+       
+       if (!signal_data->nfas.trunk) {
+               cfg.t.cfg.s.inDLSAP.nfasInt = FALSE;
                cfg.t.cfg.s.inDLSAP.intId = 0;
                cfg.t.cfg.s.inDLSAP.sigInt = 0;
                cfg.t.cfg.s.inDLSAP.bupInt = 0;
@@ -645,19 +647,55 @@ ftdm_status_t sngisdn_stack_cfg_q931_dlsap(ftdm_span_t *span)
                        cfg.t.cfg.s.inDLSAP.ctldInt[i] = IN_INT_NOT_CFGD;
 
        } else {
-               /* Need to get these parameters from NFAS */
-               cfg.t.cfg.s.inDLSAP.intId = 0;
-               cfg.t.cfg.s.inDLSAP.sigInt = 0;
-               cfg.t.cfg.s.inDLSAP.bupInt = 1;
-               cfg.t.cfg.s.inDLSAP.nmbNfasInt = 2;
-               cfg.t.cfg.s.inDLSAP.buIntPr = 1;
+               cfg.t.cfg.s.inDLSAP.nfasInt = TRUE;
+               cfg.t.cfg.s.inDLSAP.intId = signal_data->nfas.interface_id;
 
                for (i = 0; i < IN_MAX_NMB_INTRFS; i++)
                        cfg.t.cfg.s.inDLSAP.ctldInt[i] = IN_INT_NOT_CFGD;
 
-               /* For primary and backup interfaces, need to initialize this array */
-               cfg.t.cfg.s.inDLSAP.ctldInt[0] = 0; /* This is primary if for NFAS */
-               cfg.t.cfg.s.inDLSAP.ctldInt[1] = 1;
+               switch (signal_data->nfas.sigchan) {
+                       case SNGISDN_NFAS_DCHAN_PRIMARY:
+                               cfg.t.cfg.s.inDLSAP.sigInt = signal_data->nfas.trunk->dchan->link_id;
+                               cfg.t.cfg.s.inDLSAP.nmbNfasInt = signal_data->nfas.trunk->num_spans;
+
+                               if (signal_data->nfas.trunk->backup) {
+                                       cfg.t.cfg.s.inDLSAP.buIntPr = TRUE;
+                                       cfg.t.cfg.s.inDLSAP.bupInt = signal_data->nfas.trunk->backup->link_id;
+                               } else {
+                                       cfg.t.cfg.s.inDLSAP.buIntPr = FALSE;
+                               }
+
+                               for (i = 0; i < MAX_SPANS_PER_NFAS_LINK; i++) {
+                                       if (signal_data->nfas.trunk->spans[i]) {
+                                               cfg.t.cfg.s.inDLSAP.ctldInt[i] = signal_data->nfas.trunk->spans[i]->link_id;
+                                       }
+                               }
+                               
+                               break;
+                       case SNGISDN_NFAS_DCHAN_BACKUP:
+                               cfg.t.cfg.s.inDLSAP.sigInt = signal_data->nfas.trunk->dchan->link_id;
+                               cfg.t.cfg.s.inDLSAP.nmbNfasInt = signal_data->nfas.trunk->num_spans;
+
+                               if (signal_data->nfas.trunk->backup) {
+                                       cfg.t.cfg.s.inDLSAP.buIntPr = TRUE;
+                                       cfg.t.cfg.s.inDLSAP.bupInt = signal_data->nfas.trunk->backup->link_id;
+                               } else {
+                                       cfg.t.cfg.s.inDLSAP.buIntPr = FALSE;
+                               }
+
+                               for (i = 0; i < MAX_SPANS_PER_NFAS_LINK; i++) {
+                                       if (signal_data->nfas.trunk->spans[i]) {
+                                               cfg.t.cfg.s.inDLSAP.ctldInt[i] = signal_data->nfas.trunk->spans[i]->link_id;
+                                       }
+                               }
+                               
+                               break;
+                       case SNGISDN_NFAS_DCHAN_NONE:
+                               cfg.t.cfg.s.inDLSAP.sigInt = signal_data->nfas.trunk->dchan->link_id;
+                               cfg.t.cfg.s.inDLSAP.nmbNfasInt = 0;
+
+                               break;
+               }
        }
 
        cfg.t.cfg.s.inDLSAP.numRstInd = 255;
@@ -903,13 +941,27 @@ ftdm_status_t sngisdn_stack_cfg_q931_dlsap(ftdm_span_t *span)
                        break;
                case FTDM_TRUNK_T1:
                case FTDM_TRUNK_J1:
-                               /* if NFAS, could be 0 if no signalling */
-                       cfg.t.cfg.s.inDLSAP.dChannelNum = 24;
-                       cfg.t.cfg.s.inDLSAP.nmbBearChan = NUM_T1_CHANNELS_PER_SPAN;
-                       cfg.t.cfg.s.inDLSAP.firstBChanNum = 1;
+                       /* if NFAS, could be 0 if no signalling */
                        cfg.t.cfg.s.inDLSAP.callRefLen = 2;
                        cfg.t.cfg.s.inDLSAP.teiAlloc = IN_STATIC;
                        cfg.t.cfg.s.inDLSAP.intCfg = IN_INTCFG_PTPT;
+                       cfg.t.cfg.s.inDLSAP.firstBChanNum = 1;
+                       
+                       if (signal_data->nfas.trunk) {
+                               if (signal_data->nfas.sigchan ==  SNGISDN_NFAS_DCHAN_PRIMARY ||
+                                       signal_data->nfas.sigchan ==  SNGISDN_NFAS_DCHAN_BACKUP) {
+
+                                       cfg.t.cfg.s.inDLSAP.dChannelNum = 24;
+                                       cfg.t.cfg.s.inDLSAP.nmbBearChan = NUM_T1_CHANNELS_PER_SPAN - 1;
+                               } else {
+                                       cfg.t.cfg.s.inDLSAP.dChannelNum = 0;
+                                       cfg.t.cfg.s.inDLSAP.nmbBearChan = NUM_T1_CHANNELS_PER_SPAN;
+                               }
+                       } else {
+                               cfg.t.cfg.s.inDLSAP.dChannelNum = 24;
+                               cfg.t.cfg.s.inDLSAP.nmbBearChan = NUM_T1_CHANNELS_PER_SPAN;
+                               cfg.t.cfg.s.inDLSAP.firstBChanNum = 1;
+                       }
                        break;
                case FTDM_TRUNK_BRI:
                        cfg.t.cfg.s.inDLSAP.dChannelNum = 0; /* Unused for BRI */
@@ -969,7 +1021,7 @@ ftdm_status_t sngisdn_stack_cfg_q931_lce(ftdm_span_t *span)
 
        cfg.hdr.response.selector=0;
 
-       cfg.t.cfg.s.inLCe.sapId = signal_data->dchan_id;
+       cfg.t.cfg.s.inLCe.sapId = signal_data->link_id;
 
        cfg.t.cfg.s.inLCe.lnkUpDwnInd = TRUE;
 
@@ -990,13 +1042,13 @@ ftdm_status_t sngisdn_stack_cfg_q931_lce(ftdm_span_t *span)
        cfg.t.cfg.s.inLCe.t314.enb = FALSE; /* if segmentation enabled, set to TRUE */
        cfg.t.cfg.s.inLCe.t314.val = 35;
 
-       cfg.t.cfg.s.inLCe.t332i.enb = FALSE; /* set to TRUE for NFAS */
-
-#ifdef NFAS
-       cfg.t.cfg.s.inLCe.t332i.val = 35;
-#else
-       cfg.t.cfg.s.inLCe.t332i.val = 0;
-#endif
+       if (signal_data->nfas.trunk) {
+               cfg.t.cfg.s.inLCe.t332i.enb = TRUE;
+               cfg.t.cfg.s.inLCe.t332i.val = 35;
+       } else {
+               cfg.t.cfg.s.inLCe.t332i.enb = FALSE;
+               cfg.t.cfg.s.inLCe.t332i.val = 35;
+       }
 
 #if (ISDN_NI1 || ISDN_NT || ISDN_ATT)
        cfg.t.cfg.s.inLCe.tSpid.enb = TRUE;
index 2023f4c54c04c3eaa307604570d31c652f15071d..1cc23ddb8d52aa40ca4c0188f8e62b6e803ce61e 100644 (file)
@@ -55,10 +55,12 @@ ftdm_status_t sngisdn_stack_start(ftdm_span_t *span)
 {
        sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*)span->signal_data;
 
-       
-       if (sngisdn_cntrl_q921(span, ABND_ENA, NOTUSED) != FTDM_SUCCESS) {
-               ftdm_log(FTDM_LOG_CRIT, "%s:Failed to activate stack q921\n", span->name);
-               return FTDM_FAIL;
+       if (signal_data->dchan) {               
+               if (sngisdn_cntrl_q921(span, ABND_ENA, NOTUSED) != FTDM_SUCCESS) {
+                       ftdm_log(FTDM_LOG_CRIT, "%s:Failed to activate stack q921\n", span->name);
+                       return FTDM_FAIL;
+               }
+               ftdm_log(FTDM_LOG_DEBUG, "%s:Stack q921 activated\n", span->name);
        }
 
        /* Try to find an alternative for this */
@@ -67,8 +69,7 @@ ftdm_status_t sngisdn_stack_start(ftdm_span_t *span)
        LdUiDatConReq when activated, and this requires the Mac SAP to be already
        bound first */
        ftdm_sleep(500); 
-       
-       ftdm_log(FTDM_LOG_DEBUG, "%s:Stack q921 activated\n", span->name);
+               
        if (!g_sngisdn_data.ccs[signal_data->cc_id].activation_done) {
                g_sngisdn_data.ccs[signal_data->cc_id].activation_done = 1;
                if (sngisdn_activate_cc(span) != FTDM_SUCCESS) {
@@ -78,7 +79,6 @@ ftdm_status_t sngisdn_stack_start(ftdm_span_t *span)
                ftdm_log(FTDM_LOG_DEBUG, "%s:Stack CC activated\n", span->name);
        }
 
-       
        if (sngisdn_cntrl_q931(span, ABND_ENA, SAELMNT) != FTDM_SUCCESS) {
                ftdm_log(FTDM_LOG_CRIT, "%s:Failed to activate stack q931\n", span->name);
                return FTDM_FAIL;
@@ -91,7 +91,11 @@ ftdm_status_t sngisdn_stack_start(ftdm_span_t *span)
 
 ftdm_status_t sngisdn_stack_stop(ftdm_span_t *span)
 {
+       sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*)span->signal_data;
        /* Stop L1 first, so we do not receive any more frames */
+       if (!signal_data->dchan) {
+               return FTDM_SUCCESS;
+       }
        if (sngisdn_deactivate_phy(span) != FTDM_SUCCESS) {
                ftdm_log(FTDM_LOG_CRIT, "%s:Failed to deactivate stack phy\n", span->name);
                return FTDM_FAIL;
@@ -147,7 +151,7 @@ ftdm_status_t sngisdn_deactivate_phy(ftdm_span_t *span)
        cntrl.t.cntrl.action = AUBND_DIS;
        cntrl.t.cntrl.subAction = SAELMNT;
 
-       cntrl.t.cntrl.sapId = signal_data->dchan_id;
+       cntrl.t.cntrl.sapId = signal_data->link_id;
        
        if (sng_isdn_phy_cntrl(&pst, &cntrl)) {
                return FTDM_FAIL;
@@ -182,7 +186,7 @@ ftdm_status_t sngisdn_wake_up_phy(ftdm_span_t *span)
        cntrl.t.cntrl.action = AENA;
        cntrl.t.cntrl.subAction = SAELMNT;
 
-       cntrl.t.cntrl.sapId = signal_data->dchan_id;
+       cntrl.t.cntrl.sapId = signal_data->link_id;
        
        if (sng_isdn_phy_cntrl(&pst, &cntrl)) {
                return FTDM_FAIL;
@@ -226,33 +230,34 @@ ftdm_status_t sngisdn_activate_cc(ftdm_span_t *span)
 
 ftdm_status_t sngisdn_activate_trace(ftdm_span_t *span, sngisdn_tracetype_t trace_opt)
 {
-       sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*)span->signal_data;
+       sngisdn_span_data_t *signal_data = sngisdn_dchan((sngisdn_span_data_t*)span->signal_data);
+
        switch (trace_opt) {
                case SNGISDN_TRACE_DISABLE:
                        if (sngisdn_test_trace_flag(signal_data, SNGISDN_TRACE_Q921)) {
-                               ftdm_log(FTDM_LOG_INFO, "s%d Disabling q921 trace\n", signal_data->link_id);
+                               ftdm_log(FTDM_LOG_INFO, "%s:Disabling q921 trace\n", signal_data->ftdm_span->name);
                                sngisdn_clear_trace_flag(signal_data, SNGISDN_TRACE_Q921);
                                
-                               if (sngisdn_cntrl_q921(span, ADISIMM, SATRC) != FTDM_SUCCESS) {
-                                       ftdm_log(FTDM_LOG_ERROR, "s%d Failed to disable q921 trace\n");
+                               if (sngisdn_cntrl_q921(signal_data->ftdm_span, ADISIMM, SATRC) != FTDM_SUCCESS) {
+                                       ftdm_log(FTDM_LOG_INFO, "%s:Failed to disable q921 trace\n", signal_data->ftdm_span->name);
                                }
                        }
                        if (sngisdn_test_trace_flag(signal_data, SNGISDN_TRACE_Q931)) {
-                               ftdm_log(FTDM_LOG_INFO, "s%d Disabling q931 trace\n", signal_data->link_id);
+                               ftdm_log(FTDM_LOG_INFO, "%s:Disabling q921 trace\n", signal_data->ftdm_span->name);
                                sngisdn_clear_trace_flag(signal_data, SNGISDN_TRACE_Q931);
 
-                               if (sngisdn_cntrl_q931(span, ADISIMM, SATRC) != FTDM_SUCCESS) {
-                                       ftdm_log(FTDM_LOG_ERROR, "s%d Failed to disable q931 trace\n");
+                               if (sngisdn_cntrl_q931(signal_data->ftdm_span, ADISIMM, SATRC) != FTDM_SUCCESS) {
+                                       ftdm_log(FTDM_LOG_INFO, "%s:Failed to disable q921 trace\n", signal_data->ftdm_span->name);
                                }
                        }
                        break;
                case SNGISDN_TRACE_Q921:
                        if (!sngisdn_test_trace_flag(signal_data, SNGISDN_TRACE_Q921)) {
-                               ftdm_log(FTDM_LOG_INFO, "s%d Enabling q921 trace\n", signal_data->link_id);
+                               ftdm_log(FTDM_LOG_INFO, "%s:Enabling q921 trace\n", signal_data->ftdm_span->name);
                                sngisdn_set_trace_flag(signal_data, SNGISDN_TRACE_Q921);
 
-                               if (sngisdn_cntrl_q921(span, AENA, SATRC) != FTDM_SUCCESS) {
-                                       ftdm_log(FTDM_LOG_ERROR, "s%d Failed to enable q921 trace\n");
+                               if (sngisdn_cntrl_q921(signal_data->ftdm_span, AENA, SATRC) != FTDM_SUCCESS) {
+                                       ftdm_log(FTDM_LOG_INFO, "%s:Failed to enable q921 trace\n", signal_data->ftdm_span->name);
                                }
                        }
                        break;
@@ -261,8 +266,8 @@ ftdm_status_t sngisdn_activate_trace(ftdm_span_t *span, sngisdn_tracetype_t trac
                                ftdm_log(FTDM_LOG_INFO, "s%d Enabling q931 trace\n", signal_data->link_id);
                                sngisdn_set_trace_flag(signal_data, SNGISDN_TRACE_Q931);
                                
-                               if (sngisdn_cntrl_q931(span, AENA, SATRC) != FTDM_SUCCESS) {
-                                       ftdm_log(FTDM_LOG_ERROR, "s%d Failed to enable q931 trace\n");
+                               if (sngisdn_cntrl_q931(signal_data->ftdm_span, AENA, SATRC) != FTDM_SUCCESS) {
+                                       ftdm_log(FTDM_LOG_INFO, "%s:Failed to enable q931 trace\n", signal_data->ftdm_span->name);
                                }
                        }
                        break;
@@ -301,7 +306,7 @@ ftdm_status_t sngisdn_cntrl_q931(ftdm_span_t *span, uint8_t action, uint8_t suba
                cntrl.t.cntrl.trcLen = -1; /* Trace the entire message buffer */
        }
 
-       cntrl.t.cntrl.sapId = signal_data->dchan_id;
+       cntrl.t.cntrl.sapId = signal_data->link_id;
        cntrl.t.cntrl.ces = 0;
 
        if(sng_isdn_q931_cntrl(&pst, &cntrl)) {
@@ -342,11 +347,11 @@ ftdm_status_t sngisdn_cntrl_q921(ftdm_span_t *span, uint8_t action, uint8_t suba
        cntrl.t.cntrl.subAction    = subaction;
 
 #if (SMBD_LMINT3 || BD_LMINT3)
-       cntrl.t.cntrl.lnkNmb       = signal_data->dchan_id;
+       cntrl.t.cntrl.lnkNmb       = signal_data->link_id;
        cntrl.t.cntrl.sapi         = NOTUSED;
        cntrl.t.cntrl.tei          = NOTUSED;
 #else /* _LMINT3 */
-       cntrl.hdr.elmId.elmntInst1 = signal_data->dchan_id;
+       cntrl.hdr.elmId.elmntInst1 = signal_data->link_id;
        cntrl.hdr.elmId.elmntInst2 = NOTUSED;
        cntrl.hdr.elmId.elmntInst3 = NOTUSED;
 #endif /* _LMINT3 */
index 0a340683595ff0776a1f98d0b43bae78319db22c..15bff0390e37688dcc150a9ff05ce77b29c20d88 100644 (file)
@@ -58,6 +58,19 @@ void sngisdn_process_con_ind (sngisdn_event_data_t *sngisdn_event)
                
        switch (ftdmchan->state) {
                case FTDM_CHANNEL_STATE_DOWN: /* Proper state to receive a SETUP */
+                       if (signal_data->nfas.trunk) {
+                               ftdm_alarm_flag_t alarmflag = 0;
+
+                               ftdm_channel_get_alarms(ftdmchan, &alarmflag);
+                               if (alarmflag) {
+                                       ftdm_log_chan_msg(ftdmchan, FTDM_LOG_INFO, "Received SETUP but channel has physical layer alarm - rejecting\n");
+                                       
+                                       ftdmchan->caller_data.hangup_cause = 0x2C; /* Channel requested not available */
+                                       ftdm_sched_timer(signal_data->sched, "delayed_release", 1, sngisdn_delayed_release, (void*) sngisdn_info, NULL);
+                                       break;
+                               }
+                       }
+
                        if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_INUSE) ||
                                ftdm_channel_open_chan(ftdmchan) != FTDM_SUCCESS) {
 
@@ -1177,13 +1190,13 @@ void sngisdn_process_rst_cfm (sngisdn_event_data_t *sngisdn_event)
        uint8_t chan_no = 0;
        Rst *rstEvnt = &sngisdn_event->event.rstEvnt;   
        
-       sngisdn_span_data_t     *signal_data = g_sngisdn_data.dchans[dChan].spans[1];
+       sngisdn_span_data_t     *signal_data = g_sngisdn_data.spans[dChan];
        if (!signal_data) {
                ftdm_log(FTDM_LOG_CRIT, "Received RESTART CFM on unconfigured span (suId:%d)\n", suId);
                return;
        }
-       
-       if (rstEvnt->rstInd.eh.pres == PRSNT_NODEF && rstEvnt->rstInd.rstClass.pres == PRSNT_NODEF) {                   
+
+       if (rstEvnt->rstInd.eh.pres == PRSNT_NODEF && rstEvnt->rstInd.rstClass.pres == PRSNT_NODEF) {
                switch(rstEvnt->rstInd.rstClass.val) {
                        case IN_CL_INDCHAN: /* Indicated b-channel */
                                if (rstEvnt->chanId.eh.pres) {
@@ -1196,6 +1209,16 @@ void sngisdn_process_rst_cfm (sngisdn_event_data_t *sngisdn_event)
                                                        chan_no = rstEvnt->chanId.chanNmbSlotMap.val[0];
                                                }
                                        }
+
+                                       if (signal_data->nfas.trunk) {
+                                               if (!rstEvnt->chanId.intIdent.pres) {
+                                                       ftdm_log(FTDM_LOG_CRIT, "Failed to determine interface from RESTART\n");
+                                                       return;
+                                               } else if (signal_data->nfas.interface_id != rstEvnt->chanId.intIdent.val) {
+                                                       /* This RESTART is for another interface */
+                                                       return;
+                                               }
+                                       }
                                }
                                if (!chan_no) {
                                        ftdm_log(FTDM_LOG_CRIT, "Failed to determine channel from RESTART\n");
@@ -1258,10 +1281,7 @@ void sngisdn_process_rst_ind (sngisdn_event_data_t *sngisdn_event)
 
        rstEvnt = &sngisdn_event->event.rstEvnt;
 
-       /* TODO: readjust this when NFAS is implemented as signal_data will not always be the first
-        * span for that d-channel */
-
-       signal_data = g_sngisdn_data.dchans[dChan].spans[1];
+       signal_data = g_sngisdn_data.spans[dChan];
 
        if (!signal_data) {
                ftdm_log(FTDM_LOG_CRIT, "Received RESTART IND on unconfigured span (suId:%d)\n", suId);
@@ -1292,6 +1312,16 @@ void sngisdn_process_rst_ind (sngisdn_event_data_t *sngisdn_event)
                                                        chan_no = rstEvnt->chanId.chanNmbSlotMap.val[0];
                                                }
                                        }
+
+                                       if (signal_data->nfas.trunk) {
+                                               if (!rstEvnt->chanId.intIdent.pres) {
+                                                       ftdm_log(FTDM_LOG_CRIT, "Failed to determine interface from RESTART\n");
+                                                       return;
+                                               } else if (signal_data->nfas.interface_id != rstEvnt->chanId.intIdent.val) {
+                                                       /* This RESTART is for another interface */
+                                                       return;
+                                               }
+                                       }
                                }
                                if (!chan_no) {
                                        ftdm_log(FTDM_LOG_CRIT, "Failed to determine channel from RESTART\n");
@@ -1300,7 +1330,7 @@ void sngisdn_process_rst_ind (sngisdn_event_data_t *sngisdn_event)
                                break;
                        case IN_CL_SNGINT: /* Single interface */
                        case IN_CL_ALLINT: /* All interfaces */
-                               /* In case restart class indicates all interfaces, we will duplicate
+                               /* In case restart class indicates all interfaces, we will duplicated
                                                this event on each span associated to this d-channel in sngisdn_rcv_rst_cfm,
                                                so treat it as a single interface anyway */
                                chan_no = 0;
index f52833363481ae43fac208e3987ccae2c1c0f72c..20b0c86ca9ce41913672a372dd6d31c0f445f2dd 100644 (file)
 
 void sngisdn_snd_setup(ftdm_channel_t *ftdmchan)
 {
-       ConEvnt conEvnt;        
+       ConEvnt conEvnt;
        sngisdn_chan_data_t *sngisdn_info = ftdmchan->call_data;
        sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*) ftdmchan->span->signal_data;
-       ftdm_sngisdn_progind_t prog_ind = {SNGISDN_PROGIND_LOC_USER, SNGISDN_PROGIND_DESCR_INVALID};
+       ftdm_sngisdn_progind_t prog_ind = {SNGISDN_PROGIND_LOC_USER, SNGISDN_PROGIND_DESCR_INVALID};    
 
        ftdm_assert((!sngisdn_info->suInstId && !sngisdn_info->spInstId), "Trying to call out, but call data was not cleared\n");
        
@@ -75,9 +75,9 @@ void sngisdn_snd_setup(ftdm_channel_t *ftdmchan)
        set_facility_ie(ftdmchan, &conEvnt.facilityStr);
        set_prog_ind_ie(ftdmchan, &conEvnt.progInd, prog_ind);
 
-       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);
+       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, sngisdn_dchan(signal_data)->link_id, sngisdn_info->ces);
 
-       if (sng_isdn_con_request(signal_data->cc_id, sngisdn_info->suInstId, &conEvnt, signal_data->dchan_id, sngisdn_info->ces)) {
+       if (sng_isdn_con_request(signal_data->cc_id, sngisdn_info->suInstId, &conEvnt, sngisdn_dchan(signal_data)->link_id, sngisdn_info->ces)) {
                ftdm_log_chan_msg(ftdmchan, FTDM_LOG_CRIT, "stack refused SETUP request\n");
        }
 
@@ -103,9 +103,9 @@ void sngisdn_snd_setup_ack(ftdm_channel_t *ftdmchan)
 
 
 
-       ftdm_log_chan(ftdmchan, FTDM_LOG_INFO, "Sending SETUP ACK (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);
+       ftdm_log_chan(ftdmchan, FTDM_LOG_INFO, "Sending SETUP ACK (suId:%d suInstId:%u spInstId:%u dchan:%d ces:%d)\n", signal_data->cc_id, sngisdn_info->suInstId, sngisdn_info->spInstId, sngisdn_dchan(signal_data)->link_id, sngisdn_info->ces);
 
-       if(sng_isdn_con_status(signal_data->cc_id, sngisdn_info->suInstId, sngisdn_info->spInstId, &cnStEvnt, MI_SETUPACK, signal_data->dchan_id, sngisdn_info->ces)) {
+       if(sng_isdn_con_status(signal_data->cc_id, sngisdn_info->suInstId, sngisdn_info->spInstId, &cnStEvnt, MI_SETUPACK, sngisdn_dchan(signal_data)->link_id, sngisdn_info->ces)) {
                ftdm_log_chan_msg(ftdmchan, FTDM_LOG_CRIT,      "stack refused SETUP ACK request\n");
        }
        return;
@@ -135,9 +135,9 @@ void sngisdn_snd_con_complete(ftdm_channel_t *ftdmchan)
                set_chan_id_ie(ftdmchan, &cnStEvnt.chanId);
        }
 
-       ftdm_log_chan(ftdmchan, FTDM_LOG_INFO, "Sending CONNECT COMPL (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);
+       ftdm_log_chan(ftdmchan, FTDM_LOG_INFO, "Sending CONNECT COMPL (suId:%d suInstId:%u spInstId:%u dchan:%d ces:%d)\n", signal_data->cc_id, sngisdn_info->suInstId, sngisdn_info->spInstId, sngisdn_dchan(signal_data)->link_id, sngisdn_info->ces);
 
-       if(sng_isdn_con_comp(signal_data->cc_id, sngisdn_info->suInstId, sngisdn_info->spInstId, &cnStEvnt, signal_data->dchan_id, sngisdn_info->ces)) {
+       if(sng_isdn_con_comp(signal_data->cc_id, sngisdn_info->suInstId, sngisdn_info->spInstId, &cnStEvnt, sngisdn_dchan(signal_data)->link_id, sngisdn_info->ces)) {
                ftdm_log_chan_msg(ftdmchan, FTDM_LOG_CRIT,      "stack refused CONNECT ACK request\n");
        }
        return;
@@ -171,9 +171,9 @@ void sngisdn_snd_proceed(ftdm_channel_t *ftdmchan, ftdm_sngisdn_progind_t prog_i
        set_prog_ind_ie(ftdmchan, &cnStEvnt.progInd, prog_ind);
        set_facility_ie(ftdmchan, &cnStEvnt.facilityStr);
 
-       ftdm_log_chan(ftdmchan, FTDM_LOG_INFO, "Sending PROCEED (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);
+       ftdm_log_chan(ftdmchan, FTDM_LOG_INFO, "Sending PROCEED (suId:%d suInstId:%u spInstId:%u dchan:%d ces:%d)\n", signal_data->cc_id, sngisdn_info->suInstId, sngisdn_info->spInstId, sngisdn_dchan(signal_data)->link_id, sngisdn_info->ces);
 
-       if(sng_isdn_con_status(signal_data->cc_id, sngisdn_info->suInstId, sngisdn_info->spInstId, &cnStEvnt, MI_CALLPROC, signal_data->dchan_id, sngisdn_info->ces)) {
+       if(sng_isdn_con_status(signal_data->cc_id, sngisdn_info->suInstId, sngisdn_info->spInstId, &cnStEvnt, MI_CALLPROC, sngisdn_dchan(signal_data)->link_id, sngisdn_info->ces)) {
                ftdm_log_chan_msg(ftdmchan, FTDM_LOG_CRIT,      "stack refused PROCEED request\n");
        }
        return;
@@ -203,8 +203,8 @@ void sngisdn_snd_progress(ftdm_channel_t *ftdmchan, ftdm_sngisdn_progind_t prog_
        set_prog_ind_ie(ftdmchan, &cnStEvnt.progInd, prog_ind);
        set_facility_ie(ftdmchan, &cnStEvnt.facilityStr);
 
-       ftdm_log_chan(ftdmchan, FTDM_LOG_INFO, "Sending PROGRESS (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);
-       if(sng_isdn_con_status(signal_data->cc_id, sngisdn_info->suInstId, sngisdn_info->spInstId,&cnStEvnt, MI_PROGRESS, signal_data->dchan_id, sngisdn_info->ces)) {
+       ftdm_log_chan(ftdmchan, FTDM_LOG_INFO, "Sending PROGRESS (suId:%d suInstId:%u spInstId:%u dchan:%d ces:%d)\n", signal_data->cc_id, sngisdn_info->suInstId, sngisdn_info->spInstId, sngisdn_dchan(signal_data)->link_id, sngisdn_info->ces);
+       if(sng_isdn_con_status(signal_data->cc_id, sngisdn_info->suInstId, sngisdn_info->spInstId,&cnStEvnt, MI_PROGRESS, sngisdn_dchan(signal_data)->link_id, sngisdn_info->ces)) {
                ftdm_log_chan_msg(ftdmchan, FTDM_LOG_CRIT,      "stack refused PROGRESS request\n");
        }
        return;
@@ -229,9 +229,9 @@ void sngisdn_snd_alert(ftdm_channel_t *ftdmchan, ftdm_sngisdn_progind_t prog_ind
        set_prog_ind_ie(ftdmchan, &cnStEvnt.progInd, prog_ind);
        set_facility_ie(ftdmchan, &cnStEvnt.facilityStr);
 
-       ftdm_log_chan(ftdmchan, FTDM_LOG_INFO, "Sending ALERT (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);
+       ftdm_log_chan(ftdmchan, FTDM_LOG_INFO, "Sending ALERT (suId:%d suInstId:%u spInstId:%u dchan:%d ces:%d)\n", signal_data->cc_id, sngisdn_info->suInstId, sngisdn_info->spInstId, sngisdn_dchan(signal_data)->link_id, sngisdn_info->ces);
 
-       if(sng_isdn_con_status(signal_data->cc_id, sngisdn_info->suInstId, sngisdn_info->spInstId,&cnStEvnt, MI_ALERTING, signal_data->dchan_id, sngisdn_info->ces)) {
+       if(sng_isdn_con_status(signal_data->cc_id, sngisdn_info->suInstId, sngisdn_info->spInstId,&cnStEvnt, MI_ALERTING, sngisdn_dchan(signal_data)->link_id, sngisdn_info->ces)) {
                ftdm_log_chan_msg(ftdmchan, FTDM_LOG_CRIT,      "stack refused ALERT request\n");
        }
        return;
@@ -265,8 +265,8 @@ void sngisdn_snd_connect(ftdm_channel_t *ftdmchan)
        set_prog_ind_ie(ftdmchan, &cnStEvnt.progInd, prog_ind);
        set_facility_ie(ftdmchan, &cnStEvnt.facilityStr);
 
-       ftdm_log_chan(ftdmchan, FTDM_LOG_INFO, "Sending CONNECT (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);
-       if (sng_isdn_con_response(signal_data->cc_id, sngisdn_info->suInstId, sngisdn_info->spInstId, &cnStEvnt, signal_data->dchan_id, sngisdn_info->ces)) {
+       ftdm_log_chan(ftdmchan, FTDM_LOG_INFO, "Sending CONNECT (suId:%d suInstId:%u spInstId:%u dchan:%d ces:%d)\n", signal_data->cc_id, sngisdn_info->suInstId, sngisdn_info->spInstId, sngisdn_dchan(signal_data)->link_id, sngisdn_info->ces);
+       if (sng_isdn_con_response(signal_data->cc_id, sngisdn_info->suInstId, sngisdn_info->spInstId, &cnStEvnt, sngisdn_dchan(signal_data)->link_id, sngisdn_info->ces)) {
                ftdm_log_chan_msg(ftdmchan, FTDM_LOG_CRIT, "stack refused CONNECT request\n");
        }
        return;
@@ -297,9 +297,9 @@ void sngisdn_snd_fac_req(ftdm_channel_t *ftdmchan)
        facEvnt.facElmt.facStr.val[1] = (uint8_t)facEvnt.facElmt.facStr.len;
        facEvnt.facElmt.facStr.len +=2; /* Need to include the size of identifier + len */
 
-       ftdm_log_chan(ftdmchan, FTDM_LOG_INFO, "Sending FACILITY (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);
+       ftdm_log_chan(ftdmchan, FTDM_LOG_INFO, "Sending FACILITY (suId:%d suInstId:%u spInstId:%u dchan:%d ces:%d)\n", signal_data->cc_id, sngisdn_info->suInstId, sngisdn_info->spInstId, sngisdn_dchan(signal_data)->link_id, sngisdn_info->ces);
 
-       if (sng_isdn_facility_request(signal_data->cc_id, sngisdn_info->suInstId, sngisdn_info->spInstId, &facEvnt, MI_FACIL, signal_data->dchan_id, sngisdn_info->ces)) {
+       if (sng_isdn_facility_request(signal_data->cc_id, sngisdn_info->suInstId, sngisdn_info->spInstId, &facEvnt, MI_FACIL, sngisdn_dchan(signal_data)->link_id, sngisdn_info->ces)) {
                ftdm_log_chan_msg(ftdmchan, FTDM_LOG_CRIT,      "stack refused FACILITY request\n");
        }
        return;
@@ -322,9 +322,9 @@ void sngisdn_snd_info_req(ftdm_channel_t *ftdmchan)
 
        memset(&cnStEvnt, 0, sizeof(cnStEvnt));
 
-       ftdm_log_chan(ftdmchan, FTDM_LOG_INFO, "Sending INFO REQ (suId:%d dchan:%d ces:%d)\n", signal_data->cc_id, signal_data->dchan_id, sngisdn_info->ces);
+       ftdm_log_chan(ftdmchan, FTDM_LOG_INFO, "Sending INFO REQ (suId:%d dchan:%d ces:%d)\n", signal_data->cc_id, sngisdn_dchan(signal_data)->link_id, sngisdn_info->ces);
 
-       if (sng_isdn_con_status(signal_data->cc_id, 0, 0, &cnStEvnt, MI_INFO, signal_data->dchan_id, sngisdn_info->ces)) {
+       if (sng_isdn_con_status(signal_data->cc_id, 0, 0, &cnStEvnt, MI_INFO, sngisdn_dchan(signal_data)->link_id, sngisdn_info->ces)) {
                ftdm_log_chan_msg(ftdmchan, FTDM_LOG_CRIT,      "stack refused INFO request\n");
        }
        return;
@@ -348,9 +348,9 @@ void sngisdn_snd_notify_req(ftdm_channel_t *ftdmchan)
 
        set_not_ind_ie(ftdmchan, &cnStEvnt.notInd);
 
-       ftdm_log_chan(ftdmchan, FTDM_LOG_INFO, "Sending NOTIFY (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);
+       ftdm_log_chan(ftdmchan, FTDM_LOG_INFO, "Sending NOTIFY (suId:%d suInstId:%u spInstId:%u dchan:%d ces:%d)\n", signal_data->cc_id, sngisdn_info->suInstId, sngisdn_info->spInstId, sngisdn_dchan(signal_data)->link_id, sngisdn_info->ces);
 
-       if(sng_isdn_con_status(signal_data->cc_id, sngisdn_info->suInstId, sngisdn_info->spInstId,&cnStEvnt, MI_NOTIFY, signal_data->dchan_id, sngisdn_info->ces)) {
+       if(sng_isdn_con_status(signal_data->cc_id, sngisdn_info->suInstId, sngisdn_info->spInstId,&cnStEvnt, MI_NOTIFY, sngisdn_dchan(signal_data)->link_id, sngisdn_info->ces)) {
                ftdm_log_chan_msg(ftdmchan, FTDM_LOG_CRIT,      "stack refused NOTIFY request\n");
        }
        return;
@@ -368,7 +368,7 @@ void sngisdn_snd_status_enq(ftdm_channel_t *ftdmchan)
 
        memset(&staEvnt, 0, sizeof(StaEvnt));
        
-       ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Sending Status ENQ on suId:%d suInstId:%u spInstId:%d dchan:%d ces:%d\n", signal_data->cc_id, sngisdn_info->suInstId, sngisdn_info->spInstId, signal_data->dchan_id, sngisdn_info->ces);
+       ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Sending Status ENQ on suId:%d suInstId:%u spInstId:%d dchan:%d ces:%d\n", signal_data->cc_id, sngisdn_info->suInstId, sngisdn_info->spInstId, sngisdn_dchan(signal_data)->link_id, sngisdn_info->ces);
        if (sng_isdn_status_request(signal_data->cc_id, sngisdn_info->suInstId, sngisdn_info->spInstId, &staEvnt, MI_STATENQ)) {
                ftdm_log_chan_msg(ftdmchan, FTDM_LOG_CRIT,      "stack refused Status ENQ request\n");
        }
@@ -468,9 +468,9 @@ void sngisdn_snd_restart(ftdm_channel_t *ftdmchan)
        set_chan_id_ie(ftdmchan, &rstEvnt.chanId);
        set_restart_ind_ie(ftdmchan, &rstEvnt.rstInd);
        
-       ftdm_log_chan(ftdmchan, FTDM_LOG_INFO, "Sending RESTART (suId:%d dchan:%d ces:%d)\n", signal_data->cc_id, signal_data->dchan_id, CES_MNGMNT);
+       ftdm_log_chan(ftdmchan, FTDM_LOG_INFO, "Sending RESTART (suId:%d dchan:%d ces:%d)\n", signal_data->cc_id, sngisdn_dchan(signal_data)->link_id, CES_MNGMNT);
 
-       if (sng_isdn_restart_request(signal_data->cc_id, &rstEvnt, signal_data->dchan_id, CES_MNGMNT, IN_SND_RST)) {
+       if (sng_isdn_restart_request(signal_data->cc_id, &rstEvnt, sngisdn_dchan(signal_data)->link_id, CES_MNGMNT, IN_SND_RST)) {
                ftdm_log_chan_msg(ftdmchan, FTDM_LOG_CRIT, "stack refused RESTART request\n");
        }
        return;
@@ -535,25 +535,26 @@ void sngisdn_snd_data(ftdm_channel_t *dchan, uint8_t *data, ftdm_size_t len)
                ftdm_log_chan(dchan, FTDM_LOG_CRIT, "\nL1 RX [%s] flags:%x\n", string, l1_frame.flags);
        }
 #endif
-       sng_isdn_data_ind(signal_data->dchan_id, &l1_frame);
+       sng_isdn_data_ind(signal_data->link_id, &l1_frame);
 }
 
-void sngisdn_snd_event(ftdm_channel_t *dchan, ftdm_oob_event_t event)
+void sngisdn_snd_event(sngisdn_span_data_t *signal_data, ftdm_oob_event_t event)
 {
        sng_l1_event_t l1_event;
-       sngisdn_span_data_t *signal_data = NULL;
+
+       if (!signal_data->dchan) {
+               return;
+       }
        memset(&l1_event, 0, sizeof(l1_event));
-       
-       
-       signal_data = (sngisdn_span_data_t*) dchan->span->signal_data;
+
        switch(event) {
                case FTDM_OOB_ALARM_CLEAR:
                        l1_event.type = SNG_L1EVENT_ALARM_OFF;
-                       sng_isdn_event_ind(signal_data->dchan_id, &l1_event);
+                       sng_isdn_event_ind(signal_data->link_id, &l1_event);
                        break;
                case FTDM_OOB_ALARM_TRAP:
                        l1_event.type = SNG_L1EVENT_ALARM_ON;
-                       sng_isdn_event_ind(signal_data->dchan_id, &l1_event);
+                       sng_isdn_event_ind(signal_data->link_id, &l1_event);
                        break;
                default:
                        /* We do not care about the other OOB events for now */
index c45bbf0874e0fbafec5c09723b65cdd5a14d2e16..17e8d54084aaf47879bd77e4c189bb83484245b7 100644 (file)
  */
 
 #include "ftmod_sangoma_isdn.h"
+//static void sngisdn_rcv_q931_ind_span(sngisdn_span_data_t *signal_data, InMngmt *status);
 
 void sngisdn_rcv_con_ind (int16_t suId, uint32_t suInstId, uint32_t spInstId, ConEvnt *conEvnt, int16_t dChan, uint8_t ces)
 {
        uint8_t bchan_no = 0;
+       int8_t interface_id = -1; /* Specifies which interface for NFAS */
        sngisdn_chan_data_t *sngisdn_info = NULL;
        sngisdn_event_data_t *sngisdn_event = NULL;
 
        ISDN_FUNC_TRACE_ENTER(__FUNCTION__);
 
        ftdm_assert(g_sngisdn_data.ccs[suId].activation_done != 0, "Con Ind on unconfigured cc\n");
-       ftdm_assert(g_sngisdn_data.dchans[dChan].num_spans != 0, "Con Ind on unconfigured dchan\n");
+       ftdm_assert(g_sngisdn_data.spans[dChan], "Con Ind on unconfigured dchan\n");
                
        if (conEvnt->chanId.eh.pres != PRSNT_NODEF) {
                /* TODO: Implement me */
@@ -58,19 +60,38 @@ void sngisdn_rcv_con_ind (int16_t suId, uint32_t suInstId, uint32_t spInstId, Co
                bchan_no = conEvnt->chanId.infoChanSel.val;
        }
 
+       if (conEvnt->chanId.intIdent.pres) {
+               interface_id = conEvnt->chanId.intIdent.val;
+       }
+
        if (!bchan_no) {
                ftdm_log(FTDM_LOG_ERROR, "Failed to obtain b-channel number from SETUP message\n");
                ISDN_FUNC_TRACE_EXIT(__FUNCTION__);
                return;
        }
 
-       if (g_sngisdn_data.dchans[dChan].channels[bchan_no] == NULL) {
-               ftdm_log(FTDM_LOG_ERROR, "Incoming call on unconfigured b-channel:%d\n", bchan_no);
-               ISDN_FUNC_TRACE_EXIT(__FUNCTION__);
-               return;
+       if (g_sngisdn_data.spans[dChan]->nfas.trunk) {
+               if (interface_id < 0) {
+                       ftdm_log(FTDM_LOG_ERROR, "Interface ID not present on NFAS interface\n");
+                       ISDN_FUNC_TRACE_EXIT(__FUNCTION__);
+                       return;
+               } else if (!g_sngisdn_data.spans[dChan]->nfas.trunk->spans[interface_id]) {
+                       ftdm_log(FTDM_LOG_ERROR, "NFAS group:%s does not have logical interface %d\n", g_sngisdn_data.spans[dChan]->nfas.trunk->name, interface_id);
+                       ISDN_FUNC_TRACE_EXIT(__FUNCTION__);
+                       return;
+               } else {
+                       sngisdn_info = g_sngisdn_data.spans[dChan]->nfas.trunk->spans[interface_id]->channels[bchan_no];
+               }
+       } else {
+               if (g_sngisdn_data.spans[dChan]->channels[bchan_no] == NULL) {
+                       ftdm_log(FTDM_LOG_ERROR, "Incoming call on unconfigured b-channel:%d\n", bchan_no);
+                       ISDN_FUNC_TRACE_EXIT(__FUNCTION__);
+                       return;
+               }
+               
+               sngisdn_info = g_sngisdn_data.spans[dChan]->channels[bchan_no];
        }
-
-       sngisdn_info = g_sngisdn_data.dchans[dChan].channels[bchan_no];
+       
 
        ftdm_log_chan(sngisdn_info->ftdmchan, FTDM_LOG_INFO, "Received SETUP (suId:%u suInstId:%u spInstId:%u)\n", suId, suInstId, spInstId);
        
@@ -103,7 +124,7 @@ void sngisdn_rcv_con_cfm (int16_t suId, uint32_t suInstId, uint32_t spInstId, Cn
        ISDN_FUNC_TRACE_ENTER(__FUNCTION__);
 
        ftdm_assert(g_sngisdn_data.ccs[suId].activation_done != 0, "Con Cfm on unconfigured cc\n");
-       ftdm_assert(g_sngisdn_data.dchans[dChan].num_spans != 0, "Con Cfm on unconfigured dchan\n");
+       ftdm_assert(g_sngisdn_data.spans[dChan] != 0, "Con Cfm on unconfigured dchan\n");
 
        if (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);
@@ -147,7 +168,7 @@ void sngisdn_rcv_cnst_ind (int16_t suId, uint32_t suInstId, uint32_t spInstId, C
        ISDN_FUNC_TRACE_ENTER(__FUNCTION__);
 
        ftdm_assert(g_sngisdn_data.ccs[suId].activation_done != 0, "Cnst Ind on unconfigured cc\n");
-       ftdm_assert(g_sngisdn_data.dchans[dChan].num_spans != 0, "Cnst Ind on unconfigured dchan\n");
+       ftdm_assert(g_sngisdn_data.spans[dChan] != 0, "Cnst Ind on unconfigured dchan\n");
 
        if (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);
@@ -537,37 +558,41 @@ void sngisdn_rcv_sta_cfm (int16_t suId, uint32_t suInstId, uint32_t spInstId, St
 
 void sngisdn_rcv_srv_ind (int16_t suId, Srv *srvEvnt, int16_t dChan, uint8_t ces)
 {
-       unsigned i;
+       
        sngisdn_span_data_t     *signal_data;
        sngisdn_event_data_t *sngisdn_event = NULL;
 
        ISDN_FUNC_TRACE_ENTER(__FUNCTION__);
 
        ftdm_log(FTDM_LOG_INFO, "Received SERVICE IND (dChan:%d ces:%u)\n", dChan, ces);
-       
-       /* Enqueue the event to each span within the dChan */
-       for(i=1; i<=g_sngisdn_data.dchans[dChan].num_spans; i++) {
-               signal_data = g_sngisdn_data.dchans[dChan].spans[i];
-               sngisdn_event = ftdm_malloc(sizeof(*sngisdn_event));
-               ftdm_assert(sngisdn_event != NULL, "Failed to allocate memory\n");
-               memset(sngisdn_event, 0, sizeof(*sngisdn_event));
-
-               sngisdn_event->event_id = SNGISDN_EVENT_SRV_IND;                
-               sngisdn_event->suId = suId;
-               sngisdn_event->dChan = dChan;
-               sngisdn_event->ces = ces;
-               sngisdn_event->signal_data = signal_data;
-               
-               memcpy(&sngisdn_event->event.srvEvnt, srvEvnt, sizeof(*srvEvnt));
-               ftdm_queue_enqueue((signal_data)->event_queue, sngisdn_event);
+
+       signal_data = g_sngisdn_data.spans[dChan];
+
+       if (signal_data->nfas.trunk) {
+               unsigned i;
+               for (i = 0; i < signal_data->nfas.trunk->num_spans; i++) {
+                       sngisdn_span_data_t     *my_signal_data = signal_data->nfas.trunk->spans[i];
+
+                       sngisdn_event = ftdm_malloc(sizeof(*sngisdn_event));
+                       ftdm_assert(sngisdn_event != NULL, "Failed to allocate memory\n");
+                       memset(sngisdn_event, 0, sizeof(*sngisdn_event));
+                       sngisdn_event->event_id = SNGISDN_EVENT_SRV_IND;
+                       sngisdn_event->suId = suId;
+                       sngisdn_event->dChan = dChan;
+                       sngisdn_event->ces = ces;
+                       sngisdn_event->signal_data = my_signal_data;
+                       memcpy(&sngisdn_event->event.srvEvnt, srvEvnt, sizeof(*srvEvnt));
+                       ftdm_queue_enqueue(my_signal_data->event_queue, sngisdn_event);
+               }
+       } else {
+               ftdm_queue_enqueue(signal_data->event_queue, sngisdn_event);
        }
        ISDN_FUNC_TRACE_EXIT(__FUNCTION__);
 }
 
 
 void sngisdn_rcv_srv_cfm (int16_t suId, Srv *srvEvnt, int16_t dChan, uint8_t ces)
-{
-       unsigned i;
+{      
        sngisdn_span_data_t     *signal_data = NULL;
        sngisdn_event_data_t *sngisdn_event = NULL;
 
@@ -575,59 +600,65 @@ void sngisdn_rcv_srv_cfm (int16_t suId, Srv *srvEvnt, int16_t dChan, uint8_t ces
 
        ftdm_log(FTDM_LOG_INFO, "Received SERVICE CFM (dChan:%d ces:%u)\n", dChan, ces);
 
-       /* Enqueue the event to each span within the dChan */
-       for(i=1; i<=g_sngisdn_data.dchans[dChan].num_spans; i++) {
-               signal_data = g_sngisdn_data.dchans[dChan].spans[i];
-               sngisdn_event = ftdm_malloc(sizeof(*sngisdn_event));
-               ftdm_assert(sngisdn_event != NULL, "Failed to allocate memory\n");
-               memset(sngisdn_event, 0, sizeof(*sngisdn_event));
-
-               sngisdn_event->event_id = SNGISDN_EVENT_SRV_CFM;                
-               sngisdn_event->suId = suId;
-               sngisdn_event->dChan = dChan;
-               sngisdn_event->ces = ces;
-               sngisdn_event->signal_data = signal_data;
-
-               memcpy(&sngisdn_event->event.srvEvnt, srvEvnt, sizeof(*srvEvnt));
-               ftdm_queue_enqueue((signal_data)->event_queue, sngisdn_event);
+       signal_data = g_sngisdn_data.spans[dChan];
+
+       if (signal_data->nfas.trunk) {
+               unsigned i;
+               for (i = 0; i < signal_data->nfas.trunk->num_spans; i++) {
+                       sngisdn_span_data_t     *my_signal_data = signal_data->nfas.trunk->spans[i];
+
+                       sngisdn_event = ftdm_malloc(sizeof(*sngisdn_event));
+                       ftdm_assert(sngisdn_event != NULL, "Failed to allocate memory\n");
+                       memset(sngisdn_event, 0, sizeof(*sngisdn_event));
+                       sngisdn_event->event_id = SNGISDN_EVENT_SRV_CFM;
+                       sngisdn_event->suId = suId;
+                       sngisdn_event->dChan = dChan;
+                       sngisdn_event->ces = ces;
+                       sngisdn_event->signal_data = my_signal_data;
+                       memcpy(&sngisdn_event->event.srvEvnt, srvEvnt, sizeof(*srvEvnt));
+                       ftdm_queue_enqueue(my_signal_data->event_queue, sngisdn_event);
+               }
+       } else {
+               ftdm_queue_enqueue(signal_data->event_queue, sngisdn_event);
        }
        ISDN_FUNC_TRACE_EXIT(__FUNCTION__);
 }
 
 void sngisdn_rcv_rst_ind (int16_t suId, Rst *rstEvnt, int16_t dChan, uint8_t ces, uint8_t evntType)
-{
-       unsigned i;
+{      
        sngisdn_span_data_t     *signal_data = NULL;
        sngisdn_event_data_t *sngisdn_event = NULL;
 
        ISDN_FUNC_TRACE_ENTER(__FUNCTION__);
 
        ftdm_log(FTDM_LOG_INFO, "Received RESTART IND (dChan:%d ces:%u type:%u)\n", dChan, ces, evntType);
-       
-       /* Enqueue the event to each span within the dChan */
-       for(i=1; i<=g_sngisdn_data.dchans[dChan].num_spans; i++) {
-               signal_data = g_sngisdn_data.dchans[dChan].spans[i];
-
-               sngisdn_event = ftdm_malloc(sizeof(*sngisdn_event));
-               ftdm_assert(sngisdn_event != NULL, "Failed to allocate memory\n");
-               memset(sngisdn_event, 0, sizeof(*sngisdn_event));
-
-               sngisdn_event->event_id = SNGISDN_EVENT_RST_IND;
-               sngisdn_event->suId = suId;
-               sngisdn_event->dChan = dChan;
-               sngisdn_event->ces = ces;
-               sngisdn_event->evntType = evntType;
-               sngisdn_event->signal_data = signal_data;
-
-               memcpy(&sngisdn_event->event.rstEvnt, rstEvnt, sizeof(*rstEvnt));
+
+       signal_data = g_sngisdn_data.spans[dChan];
+
+       if (signal_data->nfas.trunk) {
+               unsigned i;
+               for (i = 0; i < signal_data->nfas.trunk->num_spans; i++) {
+                       sngisdn_span_data_t     *my_signal_data = signal_data->nfas.trunk->spans[i];
+
+                       sngisdn_event = ftdm_malloc(sizeof(*sngisdn_event));
+                       ftdm_assert(sngisdn_event != NULL, "Failed to allocate memory\n");
+                       memset(sngisdn_event, 0, sizeof(*sngisdn_event));
+                       sngisdn_event->event_id = SNGISDN_EVENT_RST_IND;
+                       sngisdn_event->suId = suId;
+                       sngisdn_event->dChan = dChan;
+                       sngisdn_event->ces = ces;
+                       sngisdn_event->signal_data = my_signal_data;
+                       memcpy(&sngisdn_event->event.rstEvnt, rstEvnt, sizeof(*rstEvnt));
+                       ftdm_queue_enqueue(my_signal_data->event_queue, sngisdn_event);
+               }
+       } else {
                ftdm_queue_enqueue(signal_data->event_queue, sngisdn_event);
        }
        ISDN_FUNC_TRACE_EXIT(__FUNCTION__);
 }
 
 void sngisdn_rcv_rst_cfm (int16_t suId, Rst *rstEvnt, int16_t dChan, uint8_t ces, uint8_t evntType)
-{
-       unsigned i;
+{      
        sngisdn_span_data_t     *signal_data;
        sngisdn_event_data_t *sngisdn_event = NULL;
 
@@ -636,22 +667,26 @@ void sngisdn_rcv_rst_cfm (int16_t suId, Rst *rstEvnt, int16_t dChan, uint8_t ces
 
        ftdm_log(FTDM_LOG_INFO, "Received RESTART CFM (dChan:%d ces:%u type:%u)\n", dChan, ces, evntType);
 
-       /* Enqueue the event to each span within the dChan */
-       for(i=1; i<=g_sngisdn_data.dchans[dChan].num_spans; i++) {
-               signal_data = g_sngisdn_data.dchans[dChan].spans[i];
-               sngisdn_event = ftdm_malloc(sizeof(*sngisdn_event));
-               ftdm_assert(sngisdn_event != NULL, "Failed to allocate memory\n");
-               memset(sngisdn_event, 0, sizeof(*sngisdn_event));
-
-               sngisdn_event->event_id = SNGISDN_EVENT_RST_CFM;
-               sngisdn_event->suId = suId;
-               sngisdn_event->dChan = dChan;
-               sngisdn_event->ces = ces;
-               sngisdn_event->evntType = evntType;
-               sngisdn_event->signal_data = signal_data;
-
-               memcpy(&sngisdn_event->event.rstEvnt, rstEvnt, sizeof(*rstEvnt));
-               ftdm_queue_enqueue((signal_data)->event_queue, sngisdn_event);
+       signal_data = g_sngisdn_data.spans[dChan];
+
+       if (signal_data->nfas.trunk) {
+               unsigned i;
+               for (i = 0; i < signal_data->nfas.trunk->num_spans; i++) {
+                       sngisdn_span_data_t     *my_signal_data = signal_data->nfas.trunk->spans[i];
+
+                       sngisdn_event = ftdm_malloc(sizeof(*sngisdn_event));
+                       ftdm_assert(sngisdn_event != NULL, "Failed to allocate memory\n");
+                       memset(sngisdn_event, 0, sizeof(*sngisdn_event));
+                       sngisdn_event->event_id = SNGISDN_EVENT_RST_CFM;
+                       sngisdn_event->suId = suId;
+                       sngisdn_event->dChan = dChan;
+                       sngisdn_event->ces = ces;
+                       sngisdn_event->signal_data = my_signal_data;
+                       memcpy(&sngisdn_event->event.rstEvnt, rstEvnt, sizeof(*rstEvnt));
+                       ftdm_queue_enqueue(my_signal_data->event_queue, sngisdn_event);
+               }
+       } else {
+               ftdm_queue_enqueue(signal_data->event_queue, sngisdn_event);
        }
        ISDN_FUNC_TRACE_EXIT(__FUNCTION__);
 }
@@ -660,7 +695,7 @@ void sngisdn_rcv_rst_cfm (int16_t suId, Rst *rstEvnt, int16_t dChan, uint8_t ces
 void sngisdn_rcv_phy_ind(SuId suId, Reason reason)
 {
        if (reason != LL1_REASON_CON_REQ_FAIL) {
-               ftdm_log(FTDM_LOG_INFO, "[SNGISDN PHY] D-chan %d : %s\n", suId, DECODE_LL1_REASON(reason));
+               ftdm_log(FTDM_LOG_DEBUG, "[SNGISDN PHY] D-chan %d : %s\n", suId, DECODE_LL1_REASON(reason));
        }
     return;
 } 
@@ -669,7 +704,7 @@ void sngisdn_rcv_q921_ind(BdMngmt *status)
 {      
        ftdm_span_t *ftdmspan;
 
-       sngisdn_span_data_t     *signal_data = g_sngisdn_data.dchans[status->t.usta.lnkNmb].spans[1];
+       sngisdn_span_data_t     *signal_data = g_sngisdn_data.spans[status->t.usta.lnkNmb];
        
        if (!signal_data) {
                ftdm_log(FTDM_LOG_INFO, "Received q921 status on unconfigured span (lnkNmb:%d)\n", status->t.usta.lnkNmb);
@@ -722,8 +757,43 @@ void sngisdn_rcv_q921_ind(BdMngmt *status)
        }
     return;
 }
+
+#if 0
+static void sngisdn_rcv_q931_ind_span(sngisdn_span_data_t *signal_data, InMngmt *status)
+{
+       ftdm_span_t *ftdmspan =  signal_data->ftdm_span;
+       uint32_t chan_no = status->t.usta.evntParm[2];
+                               
+       if (!signal_data) {
+               ftdm_log(FTDM_LOG_INFO, "Received q931 status on unconfigured span (lnkNmb:%d)\n", status->t.usta.suId);
+               return;
+       }
+
+       ftdm_log(FTDM_LOG_INFO, "[SNGISDN Q931] s%d: %s: %s(%d): %s(%d)\n",
+                        status->t.usta.suId,
+       DECODE_LCM_CATEGORY(status->t.usta.alarm.category),
+                                               DECODE_LCM_EVENT(status->t.usta.alarm.event), status->t.usta.alarm.event,
+                                                                                DECODE_LCM_CAUSE(status->t.usta.alarm.cause), status->t.usta.alarm.cause);
+
+       if (chan_no) {
+               ftdm_channel_t *ftdmchan = ftdm_span_get_channel(ftdmspan, chan_no);
+               if (ftdmchan) {
+                       sngisdn_set_chan_sig_status(ftdmchan, (status->t.usta.alarm.event == LCM_EVENT_UP) ? FTDM_SIG_STATE_UP : FTDM_SIG_STATE_DOWN);
+                       sngisdn_set_chan_avail_rate(ftdmchan, (status->t.usta.alarm.event == LCM_EVENT_UP) ? SNGISDN_AVAIL_UP: SNGISDN_AVAIL_PWR_SAVING);
+               } else {
+                       ftdm_log(FTDM_LOG_CRIT, "stack alarm event on invalid channel :%d\n", chan_no);
+               }
+       } else {
+               sngisdn_set_span_sig_status(ftdmspan, (status->t.usta.alarm.event == LCM_EVENT_UP) ? FTDM_SIG_STATE_UP : FTDM_SIG_STATE_DOWN);
+               sngisdn_set_span_avail_rate(ftdmspan, (status->t.usta.alarm.event == LCM_EVENT_UP) ? SNGISDN_AVAIL_UP: SNGISDN_AVAIL_PWR_SAVING);
+       }
+}
+#endif
+
 void sngisdn_rcv_q931_ind(InMngmt *status)
-{      
+{
+       sngisdn_span_data_t     *signal_data = NULL;
+       ftdm_span_t *ftdmspan = NULL;
 #ifndef WIN32
        if (status->t.usta.alarm.cause == 287) {
                sngisdn_get_memory_info();
@@ -731,47 +801,53 @@ void sngisdn_rcv_q931_ind(InMngmt *status)
        }
 #endif
 
+       signal_data = g_sngisdn_data.spans[status->t.usta.suId];
+       if (!signal_data) {
+               ftdm_log(FTDM_LOG_INFO, "Received q931 status on unconfigured span (lnkNmb:%d)\n", status->t.usta.suId);
+               return;
+       }
+
+       ftdmspan =  signal_data->ftdm_span;
+
        switch (status->t.usta.alarm.event) {
                case LCM_EVENT_UP:
                case LCM_EVENT_DOWN:
                {
-                       ftdm_span_t *ftdmspan;
-                       sngisdn_span_data_t     *signal_data = g_sngisdn_data.dchans[status->t.usta.suId].spans[1];
-                       if (!signal_data) {
-                               ftdm_log(FTDM_LOG_INFO, "Received q931 status on unconfigured span (lnkNmb:%d)\n", status->t.usta.suId);
-                               return;
+                       int i;
+                       sngisdn_nfas_data_t *nfas_data = NULL;
+                       ftdm_log(FTDM_LOG_INFO, "[SNGISDN Q931] s%d: %s: %s(%d): %s(%d)\n",
+                                                                               status->t.usta.suId,
+                                                                               DECODE_LCM_CATEGORY(status->t.usta.alarm.category),
+                                                                               DECODE_LCM_EVENT(status->t.usta.alarm.event), status->t.usta.alarm.event,
+                                                                               DECODE_LCM_CAUSE(status->t.usta.alarm.cause), status->t.usta.alarm.cause);
+
+                       nfas_data = signal_data->nfas.trunk;
+
+                       if (nfas_data && status->t.usta.alarm.event == LCM_EVENT_UP) {
+                               for (i = 0; i < ftdm_array_len(nfas_data->spans); i++) {
+                                       if (nfas_data->spans[i] && nfas_data->spans[i]->nfas.sigchan == SNGISDN_NFAS_DCHAN_NONE) {
+
+                                               sngisdn_set_span_sig_status(nfas_data->spans[i]->ftdm_span, FTDM_SIG_STATE_UP);
+                                               sngisdn_set_span_avail_rate(nfas_data->spans[i]->ftdm_span, SNGISDN_AVAIL_UP);
+                                       }
+                               }
                        }
-                       ftdmspan = signal_data->ftdm_span;
                        
-                       if (status->t.usta.alarm.event == LCM_EVENT_UP) {
-                               uint32_t chan_no = status->t.usta.evntParm[2];
-                               ftdm_log(FTDM_LOG_INFO, "[SNGISDN Q931] s%d: %s: %s(%d): %s(%d)\n",
-                                                status->t.usta.suId,
-                                                               DECODE_LCM_CATEGORY(status->t.usta.alarm.category),
-                                                               DECODE_LCM_EVENT(status->t.usta.alarm.event), status->t.usta.alarm.event,
-                                                               DECODE_LCM_CAUSE(status->t.usta.alarm.cause), status->t.usta.alarm.cause);
-
-                               if (chan_no) {
-                                       ftdm_channel_t *ftdmchan = ftdm_span_get_channel(ftdmspan, chan_no);
-                                       if (ftdmchan) {
-                                               sngisdn_set_chan_sig_status(ftdmchan, FTDM_SIG_STATE_UP);
-                                               sngisdn_set_chan_avail_rate(ftdmchan, SNGISDN_AVAIL_UP);
-                                       } else {
-                                               ftdm_log(FTDM_LOG_CRIT, "stack alarm event on invalid channel :%d\n", chan_no);
+                       sngisdn_set_span_sig_status(ftdmspan, (status->t.usta.alarm.event == LCM_EVENT_UP) ? FTDM_SIG_STATE_UP : FTDM_SIG_STATE_DOWN);
+                       sngisdn_set_span_avail_rate(ftdmspan, (status->t.usta.alarm.event == LCM_EVENT_UP) ? SNGISDN_AVAIL_UP: SNGISDN_AVAIL_PWR_SAVING);
+
+                       if (nfas_data && status->t.usta.alarm.event == LCM_EVENT_DOWN) {
+                               if (nfas_data->dchan->sigstatus == FTDM_SIG_STATE_DOWN &&
+                                  (nfas_data->backup && nfas_data->backup->sigstatus == FTDM_SIG_STATE_DOWN)) {
+
+                                       for (i = 0; i < ftdm_array_len(nfas_data->spans); i++) {
+                                               if (nfas_data->spans[i] && nfas_data->spans[i]->nfas.sigchan == SNGISDN_NFAS_DCHAN_NONE) {
+
+                                                       sngisdn_set_span_sig_status(nfas_data->spans[i]->ftdm_span, FTDM_SIG_STATE_DOWN);
+                                                       sngisdn_set_span_avail_rate(nfas_data->spans[i]->ftdm_span, SNGISDN_AVAIL_PWR_SAVING);
+                                               }
                                        }
-                               } else {
-                                       sngisdn_set_span_sig_status(ftdmspan, FTDM_SIG_STATE_UP);
-                                       sngisdn_set_span_avail_rate(ftdmspan, SNGISDN_AVAIL_UP);
                                }
-                       } else {
-                               ftdm_log(FTDM_LOG_WARNING, "[SNGISDN Q931] s%d: %s: %s(%d): %s(%d)\n",
-                                                               status->t.usta.suId,
-                                                               DECODE_LCM_CATEGORY(status->t.usta.alarm.category),
-                                                               DECODE_LCM_EVENT(status->t.usta.alarm.event), status->t.usta.alarm.event,
-                                                               DECODE_LCM_CAUSE(status->t.usta.alarm.cause), status->t.usta.alarm.cause);
-                               
-                               sngisdn_set_span_sig_status(ftdmspan, FTDM_SIG_STATE_DOWN);
-                               sngisdn_set_span_avail_rate(ftdmspan, SNGISDN_AVAIL_PWR_SAVING);
                        }
                }
                break;
@@ -805,7 +881,7 @@ void sngisdn_rcv_q931_trace(InMngmt *trc, Buffer *mBuf)
        ftdm_trace_dir_t dir;
        uint8_t tdata[1000];
 
-       sngisdn_span_data_t     *signal_data = g_sngisdn_data.dchans[trc->t.trc.suId].spans[1];
+       sngisdn_span_data_t     *signal_data = g_sngisdn_data.spans[trc->t.trc.suId];
 
        ftdm_assert(mBuf != NULLP, "Received a Q931 trace with no buffer");
        mlen = ((SsMsgInfo*)(mBuf->b_rptr))->len;
@@ -851,7 +927,7 @@ void sngisdn_rcv_q921_trace(BdMngmt *trc, Buffer *mBuf)
        ftdm_trace_dir_t dir;
        uint8_t tdata[1000];
 
-       sngisdn_span_data_t     *signal_data = g_sngisdn_data.dchans[trc->t.trc.lnkNmb].spans[1];
+       sngisdn_span_data_t     *signal_data = g_sngisdn_data.spans[trc->t.trc.lnkNmb];
 
        if (trc->t.trc.evnt == TL2TMR) {
                return;
@@ -900,7 +976,7 @@ int16_t sngisdn_rcv_l1_data_req(uint16_t spId, sng_l1_frame_t *l1_frame)
 {
        ftdm_status_t status;
        ftdm_wait_flag_t flags = FTDM_WRITE;
-       sngisdn_span_data_t     *signal_data = g_sngisdn_data.dchans[spId].spans[1];
+       sngisdn_span_data_t     *signal_data = g_sngisdn_data.spans[spId];
        ftdm_size_t length = l1_frame->len;
 
        ftdm_assert(signal_data, "Received Data request on unconfigured span\n");
@@ -952,7 +1028,7 @@ int16_t sngisdn_rcv_l1_data_req(uint16_t spId, sng_l1_frame_t *l1_frame)
 
 int16_t sngisdn_rcv_l1_cmd_req(uint16_t spId, sng_l1_cmd_t *l1_cmd)
 {
-       sngisdn_span_data_t     *signal_data = g_sngisdn_data.dchans[spId].spans[1];
+       sngisdn_span_data_t     *signal_data = g_sngisdn_data.spans[spId];
        ftdm_assert(signal_data, "Received Data request on unconfigured span\n");
        
        switch(l1_cmd->type) {
index 254b3abbfbbd1144c7002a0ba4addc85eb2b2f2d..737805c0cd84d61d8ab7b357e8736ef44f7d5c21 100644 (file)
@@ -1061,11 +1061,12 @@ ftdm_status_t set_cause_ie(ftdm_channel_t *ftdmchan, CauseDgn *causeDgn)
 
 ftdm_status_t set_chan_id_ie(ftdm_channel_t *ftdmchan, ChanId *chanId)
 {
+       sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*) ftdmchan->span->signal_data;
        sngisdn_chan_data_t *sngisdn_info = (sngisdn_chan_data_t*)ftdmchan->call_data;
        if (!ftdmchan) {
                return FTDM_SUCCESS;
        }
-
+       
        ftdm_set_flag(sngisdn_info, FLAG_SENT_CHAN_ID);
 
        chanId->eh.pres = PRSNT_NODEF;
@@ -1084,6 +1085,12 @@ ftdm_status_t set_chan_id_ie(ftdm_channel_t *ftdmchan, ChanId *chanId)
                chanId->infoChanSel.pres = PRSNT_NODEF;
                chanId->infoChanSel.val = ftdmchan->physical_chan_id;
        } else {
+               if (signal_data->nfas.trunk) {
+                       chanId->intIdentPres.val = IN_IIP_EXPLICIT;
+                       chanId->intIdent.pres = PRSNT_NODEF;
+                       chanId->intIdent.val = signal_data->nfas.interface_id;
+               }
+
                chanId->intType.pres = PRSNT_NODEF;
                chanId->intType.val = IN_IT_OTHER;
                chanId->infoChanSel.pres = PRSNT_NODEF;
@@ -1098,6 +1105,7 @@ ftdm_status_t set_chan_id_ie(ftdm_channel_t *ftdmchan, ChanId *chanId)
                chanId->chanNmbSlotMap.len = 1;
                chanId->chanNmbSlotMap.val[0] = ftdmchan->physical_chan_id;
        }
+       
        return FTDM_SUCCESS;
 }
 
@@ -1217,6 +1225,23 @@ void sngisdn_delayed_setup(void *p_sngisdn_info)
        return;
 }
 
+void sngisdn_delayed_release_nfas(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_mutex_lock(ftdmchan->mutex);
+       
+       ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Sending delayed RELEASE (suId:%d suInstId:%u spInstId:%u)\n",
+                                       signal_data->cc_id, sngisdn_info->spInstId, sngisdn_info->suInstId);
+
+       sngisdn_snd_release(ftdmchan, 0);
+
+       ftdm_mutex_unlock(ftdmchan->mutex);
+       return;
+}
+
 void sngisdn_delayed_release(void *p_sngisdn_info)
 {
        sngisdn_chan_data_t *sngisdn_info = (sngisdn_chan_data_t*)p_sngisdn_info;       
@@ -1413,7 +1438,7 @@ ftdm_status_t sngisdn_show_l1_stats(ftdm_stream_handle_t *stream, ftdm_span_t *s
        sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*)span->signal_data;
 
        memset(&sts, 0, sizeof(sts));
-       sng_isdn_phy_stats(signal_data->link_id , &sts);
+       sng_isdn_phy_stats(sngisdn_dchan(signal_data)->link_id , &sts);
 
        stream->write_function(stream, "\n---------------------------------------------------------------------\n");
        stream->write_function(stream, "   Span:%s", span->name);
@@ -1548,6 +1573,14 @@ void sngisdn_send_signal(sngisdn_chan_data_t *sngisdn_info, ftdm_signal_event_t
        ftdm_span_send_signal(ftdmchan->span, &sigev);
 }
 
+sngisdn_span_data_t *sngisdn_dchan(sngisdn_span_data_t *signal_data)
+{
+       if (!signal_data->nfas.trunk) {
+               return signal_data;
+       }
+       return signal_data->nfas.trunk->dchan;
+}
+
 
 /* For Emacs:
  * Local Variables: