freetdm: ISDN - Fix for not waking up the line on power-saving lines

This commit is contained in:
David Yat Sin 2010-11-09 16:34:34 -05:00
parent adc26e6316
commit a0b164c132
11 changed files with 145 additions and 35 deletions

View File

@ -1751,7 +1751,7 @@ FT_DECLARE(ftdm_status_t) ftdm_channel_open_chan(ftdm_channel_t *ftdmchan)
goto done; goto done;
} }
if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_IN_ALARM)) { if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_IN_ALARM) && !ftdm_test_flag(ftdmchan->span, FTDM_SPAN_PWR_SAVING)) {
snprintf(ftdmchan->last_error, sizeof(ftdmchan->last_error), "%s", "Channel is alarmed\n"); snprintf(ftdmchan->last_error, sizeof(ftdmchan->last_error), "%s", "Channel is alarmed\n");
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_WARNING, "Cannot open channel when is alarmed\n"); ftdm_log_chan_msg(ftdmchan, FTDM_LOG_WARNING, "Cannot open channel when is alarmed\n");
goto done; goto done;
@ -3927,6 +3927,11 @@ static ftdm_status_t ftdm_set_channels_alarms(ftdm_span_t *span, int currindex)
ftdm_log(FTDM_LOG_ERROR, "%d:%d: Failed to get alarms\n", span->channels[chan_index]->physical_span_id, span->channels[chan_index]->physical_chan_id); ftdm_log(FTDM_LOG_ERROR, "%d:%d: Failed to get alarms\n", span->channels[chan_index]->physical_span_id, span->channels[chan_index]->physical_chan_id);
return FTDM_FAIL; return FTDM_FAIL;
} }
if (span->channels[chan_index]->alarm_flags) {
ftdm_set_flag_locked(span->channels[chan_index], FTDM_CHANNEL_IN_ALARM);
} else {
ftdm_clear_flag_locked(span->channels[chan_index], FTDM_CHANNEL_IN_ALARM);
}
} }
return FTDM_SUCCESS; return FTDM_SUCCESS;
} }

View File

@ -53,7 +53,6 @@
//#define IODEBUG //#define IODEBUG
/* helper macros */ /* helper macros */
#define FTDM_SPAN_IS_BRI(x) ((x)->trunk_type == FTDM_TRUNK_BRI || (x)->trunk_type == FTDM_TRUNK_BRI_PTMP)
#define FTDM_SPAN_IS_NT(x) (((ftdm_isdn_data_t *)(x)->signal_data)->mode == Q921_NT) #define FTDM_SPAN_IS_NT(x) (((ftdm_isdn_data_t *)(x)->signal_data)->mode == Q921_NT)

View File

@ -47,6 +47,7 @@ static ftdm_status_t ftdm_sangoma_isdn_start(ftdm_span_t *span);
ftdm_channel_t* ftdm_sangoma_isdn_process_event_states(ftdm_span_t *span, sngisdn_event_data_t *sngisdn_event); ftdm_channel_t* ftdm_sangoma_isdn_process_event_states(ftdm_span_t *span, sngisdn_event_data_t *sngisdn_event);
static void ftdm_sangoma_isdn_advance_chan_states(ftdm_channel_t *ftdmchan); static void ftdm_sangoma_isdn_advance_chan_states(ftdm_channel_t *ftdmchan);
static void ftdm_sangoma_isdn_poll_events(ftdm_span_t *span);
static void ftdm_sangoma_isdn_process_state_change(ftdm_channel_t *ftdmchan); static void ftdm_sangoma_isdn_process_state_change(ftdm_channel_t *ftdmchan);
static void ftdm_sangoma_isdn_process_stack_event (ftdm_span_t *span, sngisdn_event_data_t *sngisdn_event); static void ftdm_sangoma_isdn_process_stack_event (ftdm_span_t *span, sngisdn_event_data_t *sngisdn_event);
@ -238,6 +239,50 @@ static __inline__ void ftdm_sangoma_isdn_advance_chan_states(ftdm_channel_t *ftd
} }
} }
static void ftdm_sangoma_isdn_poll_events(ftdm_span_t *span)
{
ftdm_status_t ret_status;
ftdm_channel_t *ftdmchan;
ftdm_iterator_t *chaniter = NULL;
ftdm_iterator_t *curr = NULL;
ret_status = ftdm_span_poll_event(span, 0, NULL);
switch(ret_status) {
case FTDM_SUCCESS:
{
ftdm_event_t *event;
while (ftdm_span_next_event(span, &event) == FTDM_SUCCESS) {
if (FTDM_SPAN_IS_BRI(span)) {
switch (event->enum_id) {
/* Check if the span woke up from power-saving mode */
case FTDM_OOB_ALARM_CLEAR:
{
chaniter = ftdm_span_get_chan_iterator(span, NULL);
for (curr = chaniter; curr; curr = ftdm_iterator_next(curr)) {
ftdmchan = (ftdm_channel_t*)ftdm_iterator_current(curr);
sngisdn_chan_data_t *sngisdn_info = ftdmchan->call_data;
if (ftdm_test_flag(sngisdn_info, FLAG_ACTIVATING)) {
ftdm_clear_flag(sngisdn_info, FLAG_ACTIVATING);
sngisdn_snd_setup((ftdm_channel_t*)ftdmchan);
}
}
ftdm_iterator_free(chaniter);
}
}
}
}
}
break;
case FTDM_TIMEOUT:
/* No events pending */
break;
default:
ftdm_log(FTDM_LOG_WARNING, "%s:Failed to poll span event\n", span->name);
}
}
static void *ftdm_sangoma_isdn_run(ftdm_thread_t *me, void *obj) static void *ftdm_sangoma_isdn_run(ftdm_thread_t *me, void *obj)
{ {
ftdm_interrupt_t *ftdm_sangoma_isdn_int[2]; ftdm_interrupt_t *ftdm_sangoma_isdn_int[2];
@ -300,21 +345,8 @@ static void *ftdm_sangoma_isdn_run(ftdm_thread_t *me, void *obj)
} }
/* Poll for events, e.g HW DTMF */ /* Poll for events, e.g HW DTMF */
ret_status = ftdm_span_poll_event(span, 0, NULL); ftdm_sangoma_isdn_poll_events(span);
switch(ret_status) {
case FTDM_SUCCESS:
{
ftdm_event_t *event;
while (ftdm_span_next_event(span, &event) == FTDM_SUCCESS);
}
break;
case FTDM_TIMEOUT:
/* No events pending */
break;
default:
ftdm_log(FTDM_LOG_WARNING, "%s:Failed to poll span event\n", span->name);
}
if (ftdm_sched_get_time_to_next_timer(signal_data->sched, &sleep) == FTDM_SUCCESS) { if (ftdm_sched_get_time_to_next_timer(signal_data->sched, &sleep) == FTDM_SUCCESS) {
if (sleep < 0 || sleep > SNGISDN_EVENT_POLL_RATE) { if (sleep < 0 || sleep > SNGISDN_EVENT_POLL_RATE) {
sleep = SNGISDN_EVENT_POLL_RATE; sleep = SNGISDN_EVENT_POLL_RATE;
@ -498,8 +530,20 @@ static void ftdm_sangoma_isdn_process_state_change(ftdm_channel_t *ftdmchan)
} }
break; break;
case FTDM_CHANNEL_STATE_DIALING: /* outgoing call request */ case FTDM_CHANNEL_STATE_DIALING: /* outgoing call request */
{ {
sngisdn_snd_setup(ftdmchan); if (FTDM_SPAN_IS_BRI(ftdmchan->span) &&
ftdm_test_flag(ftdmchan, FTDM_CHANNEL_IN_ALARM) &&
ftdm_test_flag(ftdmchan->span, FTDM_SPAN_PWR_SAVING)) {
sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*) ftdmchan->span->signal_data;
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Requesting Line activation\n");
sngisdn_set_flag(sngisdn_info, FLAG_ACTIVATING);
sng_isdn_wake_up_phy(ftdmchan->span);
ftdm_sched_timer(signal_data->sched, "timer_t3", signal_data->timer_t3*1000, sngisdn_t3_timeout, (void*) sngisdn_info, NULL);
} else {
sngisdn_snd_setup(ftdmchan);
}
} }
break; break;
case FTDM_CHANNEL_STATE_PROGRESS: case FTDM_CHANNEL_STATE_PROGRESS:
@ -856,8 +900,7 @@ static FIO_CONFIGURE_SPAN_SIGNALING_FUNCTION(ftdm_sangoma_isdn_span_config)
if (span->trunk_type == FTDM_TRUNK_BRI_PTMP || if (span->trunk_type == FTDM_TRUNK_BRI_PTMP ||
span->trunk_type == FTDM_TRUNK_BRI) { span->trunk_type == FTDM_TRUNK_BRI) {
ftdm_set_flag(span, FTDM_SPAN_USE_AV_RATE);
sng_isdn_set_avail_rate(span, SNGISDN_AVAIL_PWR_SAVING); sng_isdn_set_avail_rate(span, SNGISDN_AVAIL_PWR_SAVING);
} }
@ -914,7 +957,7 @@ static FIO_SIG_LOAD_FUNCTION(ftdm_sangoma_isdn_init)
/* initalize sng_isdn library */ /* initalize sng_isdn library */
ftdm_assert_return(!sng_isdn_init(&g_sngisdn_event_interface), FTDM_FAIL, "Failed to initialize stack\n"); ftdm_assert_return(!sng_isdn_init(&g_sngisdn_event_interface), FTDM_FAIL, "Failed to initialize stack\n");
return FTDM_SUCCESS; return FTDM_SUCCESS;
} }

View File

@ -74,6 +74,7 @@ typedef enum {
FLAG_DELAYED_REL = (1 << 7), FLAG_DELAYED_REL = (1 << 7),
FLAG_SENT_PROCEED = (1 << 8), FLAG_SENT_PROCEED = (1 << 8),
FLAG_SEND_DISC = (1 << 9), FLAG_SEND_DISC = (1 << 9),
FLAG_ACTIVATING = (1 << 10), /* Used for BRI only, flag is set after we request line CONNECTED */
} sngisdn_flag_t; } sngisdn_flag_t;
@ -181,6 +182,7 @@ typedef struct sngisdn_span_data {
uint8_t facility; uint8_t facility;
int8_t facility_timeout; int8_t facility_timeout;
uint8_t num_local_numbers; uint8_t num_local_numbers;
uint8_t timer_t3;
char* local_numbers[SNGISDN_NUM_LOCAL_NUMBERS]; char* local_numbers[SNGISDN_NUM_LOCAL_NUMBERS];
ftdm_sched_t *sched; ftdm_sched_t *sched;
ftdm_queue_t *event_queue; ftdm_queue_t *event_queue;
@ -368,11 +370,13 @@ void sngisdn_delayed_release(void* p_sngisdn_info);
void sngisdn_delayed_connect(void* p_sngisdn_info); void sngisdn_delayed_connect(void* p_sngisdn_info);
void sngisdn_delayed_disconnect(void* p_sngisdn_info); void sngisdn_delayed_disconnect(void* p_sngisdn_info);
void sngisdn_facility_timeout(void* p_sngisdn_info); void sngisdn_facility_timeout(void* p_sngisdn_info);
void sngisdn_t3_timeout(void* p_sngisdn_info);
/* Stack management functions */ /* Stack management functions */
ftdm_status_t sng_isdn_stack_cfg(ftdm_span_t *span); ftdm_status_t sng_isdn_stack_cfg(ftdm_span_t *span);
ftdm_status_t sng_isdn_stack_start(ftdm_span_t *span); ftdm_status_t sng_isdn_stack_start(ftdm_span_t *span);
ftdm_status_t sng_isdn_stack_stop(ftdm_span_t *span); ftdm_status_t sng_isdn_stack_stop(ftdm_span_t *span);
ftdm_status_t sng_isdn_wake_up_phy(ftdm_span_t *span);
void sngisdn_print_phy_stats(ftdm_stream_handle_t *stream, ftdm_span_t *span); void sngisdn_print_phy_stats(ftdm_stream_handle_t *stream, ftdm_span_t *span);
void sngisdn_print_spans(ftdm_stream_handle_t *stream); void sngisdn_print_spans(ftdm_stream_handle_t *stream);

View File

@ -98,6 +98,8 @@ ftdm_status_t parse_switchtype(const char* switch_name, ftdm_span_t *span)
ftdm_log(FTDM_LOG_ERROR, "%s:Unsupported switchtype %s for trunktype:%s\n", span->name, switch_name, ftdm_trunk_type2str(span->trunk_type)); ftdm_log(FTDM_LOG_ERROR, "%s:Unsupported switchtype %s for trunktype:%s\n", span->name, switch_name, ftdm_trunk_type2str(span->trunk_type));
return FTDM_FAIL; return FTDM_FAIL;
} }
ftdm_set_flag(span, FTDM_SPAN_USE_AV_RATE);
ftdm_set_flag(span, FTDM_SPAN_PWR_SAVING);
/* can be > 1 for some BRI variants */ /* can be > 1 for some BRI variants */
break; break;
default: default:
@ -179,6 +181,7 @@ ftdm_status_t ftmod_isdn_parse_cfg(ftdm_conf_parameter_t *ftdm_parameters, ftdm_
signal_data->min_digits = 8; signal_data->min_digits = 8;
signal_data->overlap_dial = SNGISDN_OPT_DEFAULT; signal_data->overlap_dial = SNGISDN_OPT_DEFAULT;
signal_data->setup_arb = SNGISDN_OPT_DEFAULT; signal_data->setup_arb = SNGISDN_OPT_DEFAULT;
signal_data->timer_t3 = 8;
signal_data->link_id = span->span_id; signal_data->link_id = span->span_id;
span->default_caller_data.bearer_capability = IN_ITC_SPEECH; span->default_caller_data.bearer_capability = IN_ITC_SPEECH;
@ -189,6 +192,7 @@ ftdm_status_t ftmod_isdn_parse_cfg(ftdm_conf_parameter_t *ftdm_parameters, ftdm_
if (span->trunk_type == FTDM_TRUNK_BRI || if (span->trunk_type == FTDM_TRUNK_BRI ||
span->trunk_type == FTDM_TRUNK_BRI_PTMP) { span->trunk_type == FTDM_TRUNK_BRI_PTMP) {
ftdm_span_set_npi("unknown", &span->default_caller_data.dnis.plan); ftdm_span_set_npi("unknown", &span->default_caller_data.dnis.plan);
ftdm_span_set_ton("unknown", &span->default_caller_data.dnis.type); ftdm_span_set_ton("unknown", &span->default_caller_data.dnis.type);
ftdm_span_set_npi("unknown", &span->default_caller_data.cid_num.plan); ftdm_span_set_npi("unknown", &span->default_caller_data.cid_num.plan);

View File

@ -113,6 +113,40 @@ ftdm_status_t sng_isdn_stack_stop(ftdm_span_t *span)
} }
ftdm_status_t sng_isdn_wake_up_phy(ftdm_span_t *span)
{
L1Mngmt cntrl;
Pst pst;
sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*)span->signal_data;
/* initalize the post structure */
stack_pst_init(&pst);
/* insert the destination Entity */
pst.dstEnt = ENTL1;
/* initalize the control structure */
memset(&cntrl, 0, sizeof(cntrl));
/* initalize the control header */
stack_hdr_init(&cntrl.hdr);
cntrl.hdr.msgType = TCNTRL; /* configuration */
cntrl.hdr.entId.ent = ENTL1; /* entity */
cntrl.hdr.entId.inst = S_INST; /* instance */
cntrl.hdr.elmId.elmnt = STTSAP; /* SAP Specific cntrl */
cntrl.t.cntrl.action = AENA;
cntrl.t.cntrl.subAction = SAELMNT;
cntrl.t.cntrl.sapId = signal_data->link_id;
if (sng_isdn_phy_cntrl(&pst, &cntrl)) {
return FTDM_FAIL;
}
return FTDM_SUCCESS;
}
ftdm_status_t sng_isdn_activate_phy(ftdm_span_t *span) ftdm_status_t sng_isdn_activate_phy(ftdm_span_t *span)
{ {

View File

@ -38,13 +38,6 @@ extern ftdm_status_t cpy_calling_num_from_user(CgPtyNmb *cgPtyNmb, ftdm_caller_d
extern ftdm_status_t cpy_called_num_from_user(CdPtyNmb *cdPtyNmb, ftdm_caller_data_t *ftdm); extern ftdm_status_t cpy_called_num_from_user(CdPtyNmb *cdPtyNmb, ftdm_caller_data_t *ftdm);
extern ftdm_status_t cpy_calling_name_from_user(ConEvnt *conEvnt, ftdm_channel_t *ftdmchan); extern ftdm_status_t cpy_calling_name_from_user(ConEvnt *conEvnt, ftdm_channel_t *ftdmchan);
void sngisdn_snd_setup(ftdm_channel_t *ftdmchan);
void sngisdn_snd_proceed(ftdm_channel_t *ftdmchan);
void sngisdn_snd_progress(ftdm_channel_t *ftdmchan);
void sngisdn_snd_connect(ftdm_channel_t *ftdmchan);
void sngisdn_snd_disconnect(ftdm_channel_t *ftdmchan);
void sngisdn_snd_release(ftdm_channel_t *ftdmchan, uint8_t glare);
void sngisdn_snd_setup(ftdm_channel_t *ftdmchan) void sngisdn_snd_setup(ftdm_channel_t *ftdmchan)
{ {

View File

@ -382,6 +382,28 @@ ftdm_status_t cpy_calling_name_from_user(ConEvnt *conEvnt, ftdm_channel_t *ftdmc
return FTDM_SUCCESS; return FTDM_SUCCESS;
} }
void sngisdn_t3_timeout(void* p_sngisdn_info)
{
sngisdn_chan_data_t *sngisdn_info = (sngisdn_chan_data_t*)p_sngisdn_info;
ftdm_channel_t *ftdmchan = sngisdn_info->ftdmchan;
sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*) ftdmchan->span->signal_data;
ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Timer T3 expired (suId:%d suInstId:%u spInstId:%u)\n",
signal_data->cc_id, sngisdn_info->glare.spInstId, sngisdn_info->glare.suInstId);
ftdm_mutex_lock(ftdmchan->mutex);
if (ftdm_test_flag(sngisdn_info, FLAG_ACTIVATING)){
/* PHY layer timed-out, need to clear the call */
ftdm_log_chan(ftdmchan, FTDM_LOG_INFO, "Failed to Wake-Up line (suId:%d suInstId:%u spInstId:%u)\n",
signal_data->cc_id, sngisdn_info->glare.spInstId, sngisdn_info->glare.suInstId);
ftdmchan->caller_data.hangup_cause = FTDM_CAUSE_NO_ROUTE_DESTINATION;
ftdm_clear_flag(sngisdn_info, FLAG_ACTIVATING);
ftdm_set_flag(sngisdn_info, FLAG_LOCAL_ABORT);
ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_TERMINATING);
}
ftdm_mutex_unlock(ftdmchan->mutex);
}
void sngisdn_delayed_release(void* p_sngisdn_info) void sngisdn_delayed_release(void* p_sngisdn_info)
{ {
sngisdn_chan_data_t *sngisdn_info = (sngisdn_chan_data_t*)p_sngisdn_info; sngisdn_chan_data_t *sngisdn_info = (sngisdn_chan_data_t*)p_sngisdn_info;

View File

@ -1011,13 +1011,15 @@ static FIO_GET_ALARMS_FUNCTION(wanpipe_get_alarms)
} }
alarms = tdm_api.wp_tdm_cmd.fe_alarms; alarms = tdm_api.wp_tdm_cmd.fe_alarms;
#endif #endif
#if 1 #ifdef WIN32
/* DAVIDY - Temporary fix: in the current trunk of libsangoma, for BRI, /* Temporary fix: in the current trunk of libsangoma, for BRI,
WAN_TE_BIT_ALARM_RED bit is set if the card is in disconnected state, but this has WAN_TE_BIT_ALARM_RED bit is set if the card is in disconnected state, but this has
not been ported to Windows-libsangoma yet */ not been ported to Windows-libsangoma yet */
if (alarms) { if (FTDM_SPAN_IS_BRI(ftdmchan->span)) {
ftdmchan->alarm_flags |= FTDM_ALARM_RED; if (alarms) {
alarms = 0; ftdmchan->alarm_flags |= FTDM_ALARM_RED;
alarms = 0;
}
} }
#endif #endif
@ -1027,6 +1029,7 @@ static FIO_GET_ALARMS_FUNCTION(wanpipe_get_alarms)
ftdmchan->alarm_flags |= FTDM_ALARM_RED; ftdmchan->alarm_flags |= FTDM_ALARM_RED;
alarms &= ~WAN_TE_BIT_ALARM_RED; alarms &= ~WAN_TE_BIT_ALARM_RED;
} }
if (alarms & WAN_TE_BIT_ALARM_AIS) { if (alarms & WAN_TE_BIT_ALARM_AIS) {
ftdmchan->alarm_flags |= FTDM_ALARM_BLUE; ftdmchan->alarm_flags |= FTDM_ALARM_BLUE;

View File

@ -222,6 +222,8 @@ extern "C" {
#define ftdm_is_dtmf(key) ((key > 47 && key < 58) || (key > 64 && key < 69) || (key > 96 && key < 101) || key == 35 || key == 42 || key == 87 || key == 119) #define ftdm_is_dtmf(key) ((key > 47 && key < 58) || (key > 64 && key < 69) || (key > 96 && key < 101) || key == 35 || key == 42 || key == 87 || key == 119)
#define FTDM_SPAN_IS_BRI(x) ((x)->trunk_type == FTDM_TRUNK_BRI || (x)->trunk_type == FTDM_TRUNK_BRI_PTMP)
/*! /*!
\brief Copy flags from one arbitrary object to another \brief Copy flags from one arbitrary object to another
\command dest the object to copy the flags to \command dest the object to copy the flags to

View File

@ -176,10 +176,11 @@ typedef enum {
FTDM_SPAN_USE_CHAN_QUEUE = (1 << 6), FTDM_SPAN_USE_CHAN_QUEUE = (1 << 6),
FTDM_SPAN_SUGGEST_CHAN_ID = (1 << 7), FTDM_SPAN_SUGGEST_CHAN_ID = (1 << 7),
FTDM_SPAN_USE_AV_RATE = (1 << 8), FTDM_SPAN_USE_AV_RATE = (1 << 8),
FTDM_SPAN_PWR_SAVING = (1 << 9),
/* If you use this flag, you MUST call ftdm_span_trigger_signals to deliver the user signals /* If you use this flag, you MUST call ftdm_span_trigger_signals to deliver the user signals
* after having called ftdm_send_span_signal(), which with this flag it will just enqueue the signal * after having called ftdm_send_span_signal(), which with this flag it will just enqueue the signal
* for later delivery */ * for later delivery */
FTDM_SPAN_USE_SIGNALS_QUEUE = (1 << 9), FTDM_SPAN_USE_SIGNALS_QUEUE = (1 << 10),
} ftdm_span_flag_t; } ftdm_span_flag_t;
/*! \brief Channel supported features */ /*! \brief Channel supported features */