Added sangoma_isdn
This commit is contained in:
parent
53761efdf6
commit
c943e641d5
|
@ -257,6 +257,25 @@ ftmod_sangoma_ss7_la_LDFLAGS = -module -avoid-version -lsng_ss7
|
|||
ftmod_sangoma_ss7_la_LIBADD = $(MYLIB)
|
||||
endif
|
||||
|
||||
if SNGISDN
|
||||
ftmod_sangoma_isdn_la_SOURCES = $(SRC)/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn.c \
|
||||
$(SRC)/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_cfg.c \
|
||||
$(SRC)/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_cntrl.c \
|
||||
$(SRC)/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_trace.c \
|
||||
$(SRC)/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_support.c \
|
||||
$(SRC)/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_cntrl.c \
|
||||
$(SRC)/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_cfg.c \
|
||||
$(SRC)/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_in.c \
|
||||
$(SRC)/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_out.c
|
||||
|
||||
|
||||
ftmod_sangoma_isdn_la_CFLAGS = $(AM_CFLAGS) $(MY_CFLAGS)
|
||||
ftmod_sangoma_isdn_la_LDFLAGS = -module -avoid-version -lsng_isdn
|
||||
ftmod_sangoma_isdn_la_LIBADD = $(MYLIB)
|
||||
endif
|
||||
|
||||
|
||||
|
||||
if OPENR2
|
||||
ftmod_r2_la_SOURCES = $(SRC)/ftmod/ftmod_r2/ftmod_r2.c
|
||||
ftmod_r2_la_CFLAGS = $(AM_CFLAGS) $(MY_CFLAGS)
|
||||
|
@ -264,7 +283,6 @@ ftmod_r2_la_LDFLAGS = -module -avoid-version -lopenr2
|
|||
ftmod_r2_la_LIBADD = $(MYLIB)
|
||||
endif
|
||||
|
||||
|
||||
dox doxygen:
|
||||
cd docs && doxygen $(FT_SRCDIR)/docs/Doxygen.conf
|
||||
|
||||
|
|
|
@ -173,6 +173,9 @@ AM_CONDITIONAL([LIBPRI],[test "${enable_libpri}" = "yes"])
|
|||
AC_CHECK_LIB([sng_ss7], [sng_isup_init], [have_sng_ss7="yes"])
|
||||
AM_CONDITIONAL([SNGSS7],[test "${have_sng_ss7}" = "yes"])
|
||||
|
||||
AC_CHECK_LIB([sng_isdn], [sng_isdn_init], [have_sng_isdn="yes"])
|
||||
AM_CONDITIONAL([SNGISDN],[test "${have_sng_isdn}" = "yes"])
|
||||
|
||||
AC_CHECK_LIB([openr2], [openr2_context_set_io_type], [have_openr2="yes"])
|
||||
AM_CONDITIONAL([OPENR2],[test "${have_openr2}" = "yes"])
|
||||
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,259 @@
|
|||
/*
|
||||
* Copyright (c) 2010, Sangoma Technologies
|
||||
* David Yat Sin <davidy@sangoma.com>
|
||||
* Moises Silva <moy@sangoma.com>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* * Neither the name of the original author; nor the names of any contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
|
||||
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#ifndef __FTMOD_SNG_ISDN_H__
|
||||
#define __FTMOD_SNG_ISDN_H__
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdint.h>
|
||||
#include <unistd.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#include "private/ftdm_core.h"
|
||||
|
||||
#include <sng_isdn.h>
|
||||
|
||||
#define MAX_SPANS_PER_NFAS_LINK 8 /* TODO: Confirm this value */
|
||||
#define NUM_E1_CHANNELS_PER_SPAN 32
|
||||
#define NUM_T1_CHANNELS_PER_SPAN 24
|
||||
#define NUM_BRI_CHANNELS_PER_SPAN 2
|
||||
|
||||
/* Should never have DEBUG_MODE defined when used in production */
|
||||
#if 0
|
||||
#undef DEBUG_MODE
|
||||
#define FORCE_SEFGAULT
|
||||
#else
|
||||
#define DEBUG_MODE
|
||||
#define FORCE_SEGFAULT *(int *) 0 = 0;
|
||||
#endif
|
||||
|
||||
/* TODO: rename all *_cc_* to *_an_* */
|
||||
|
||||
typedef struct sngisdn_glare_data {
|
||||
int16_t suId;
|
||||
uint32_t suInstId;
|
||||
uint32_t spInstId;
|
||||
int16_t dChan;
|
||||
ConEvnt setup;
|
||||
uint8_t ces;
|
||||
}sngisdn_glare_data_t;
|
||||
|
||||
|
||||
/* Channel specific data */
|
||||
typedef struct sngisdn_chan_data {
|
||||
ftdm_channel_t *ftdmchan;
|
||||
uint32_t flags;
|
||||
uint8_t ces; /* not used for now */
|
||||
uint8_t dchan_id;
|
||||
uint32_t suInstId; /* instance ID generated locally */
|
||||
uint32_t spInstId; /* instance ID generated by stack */
|
||||
|
||||
uint8_t globalFlg;
|
||||
sngisdn_glare_data_t glare;
|
||||
} sngisdn_chan_data_t;
|
||||
|
||||
/* Span specific data */
|
||||
typedef struct sngisdn_span_data {
|
||||
ftdm_span_t *ftdm_span;
|
||||
uint8_t link_id;
|
||||
uint8_t switchtype;
|
||||
uint8_t signalling; /* SNGISDN_SIGNALING_CPE or SNGISDN_SIGNALING_NET */
|
||||
uint8_t cc_id;
|
||||
uint8_t dchan_id;
|
||||
uint8_t span_id;
|
||||
uint8_t tei;
|
||||
uint8_t keep_link_up;
|
||||
uint8_t trace_flags;
|
||||
} sngisdn_span_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;
|
||||
|
||||
typedef struct sngisdn_cc {
|
||||
/* TODO: use flags instead of config_done and activation_done */
|
||||
uint8_t config_done;
|
||||
uint8_t activation_done;
|
||||
uint8_t switchtype;
|
||||
ftdm_trunk_type_t trunktype;
|
||||
uint32_t last_suInstId;
|
||||
ftdm_mutex_t *request_mutex;
|
||||
sngisdn_chan_data_t *active_spInstIds[MAX_INSTID];
|
||||
sngisdn_chan_data_t *active_suInstIds[MAX_INSTID];
|
||||
}sngisdn_cc_t;
|
||||
|
||||
/* 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];
|
||||
}ftdm_sngisdn_data_t;
|
||||
|
||||
typedef enum {
|
||||
FLAG_RESET_RX = (1 << 0),
|
||||
FLAG_RESET_TX = (1 << 1),
|
||||
FLAG_REMOTE_REL = (1 << 2),
|
||||
FLAG_LOCAL_REL = (1 << 3),
|
||||
FLAG_REMOTE_ABORT = (1 << 4),
|
||||
FLAG_LOCAL_ABORT = (1 << 4),
|
||||
FLAG_GLARE = (1 << 5),
|
||||
FLAG_INFID_RESUME = (1 << 17),
|
||||
FLAG_INFID_PAUSED = (1 << 18),
|
||||
FLAG_CKT_MN_BLOCK_RX = (1 << 19),
|
||||
FLAG_CKT_MN_BLOCK_TX = (1 << 20),
|
||||
FLAG_CKT_MN_UNBLK_RX = (1 << 21),
|
||||
FLAG_CKT_MN_UNBLK_TX = (1 << 22),
|
||||
FLAG_GRP_HW_BLOCK_RX = (1 << 23),
|
||||
FLAG_GRP_HW_BLOCK_TX = (1 << 24),
|
||||
FLAG_GRP_MN_BLOCK_RX = (1 << 25),
|
||||
FLAG_GRP_MN_BLOCK_TX = (1 << 28),
|
||||
FLAG_GRP_HW_UNBLK_RX = (1 << 27),
|
||||
FLAG_GRP_HW_UNBLK_TX = (1 << 28),
|
||||
FLAG_GRP_MN_UNBLK_RX = (1 << 29),
|
||||
FLAG_GRP_MN_UNBLK_TX = (1 << 30)
|
||||
} sngisdn_flag_t;
|
||||
|
||||
|
||||
typedef enum {
|
||||
SNGISDN_SWITCH_INVALID = 0, /* invalid */
|
||||
SNGISDN_SWITCH_NI2 , /* national isdn-2 */
|
||||
SNGISDN_SWITCH_5ESS, /* att 5ess */
|
||||
SNGISDN_SWITCH_4ESS, /* att 4ess */
|
||||
SNGISDN_SWITCH_DMS100, /* nt dms100 */
|
||||
SNGISDN_SWITCH_EUROISDN,/* etsi */
|
||||
SNGISDN_SWITCH_QSIG, /* etsi qsig */
|
||||
SNGISDN_SWITCH_INSNET, /* int - net */
|
||||
} sngisdn_switchtype_t;
|
||||
|
||||
typedef enum {
|
||||
SNGISDN_SIGNALING_INVALID = 0, /* invalid */
|
||||
SNGISDN_SIGNALING_CPE , /* customer side emulation */
|
||||
SNGISDN_SIGNALING_NET, /* network side emulation */
|
||||
} sngisdn_signalingtype_t;
|
||||
|
||||
typedef enum {
|
||||
SNGISDN_TRACE_DISABLE = 0,
|
||||
SNGISDN_TRACE_Q921 = 1,
|
||||
SNGISDN_TRACE_Q931 = 2,
|
||||
} sngisdn_tracetype_t;
|
||||
|
||||
|
||||
#define sngisdn_set_flag(obj, flag) ((obj)->flags |= (flag))
|
||||
#define sngisdn_clear_flag(obj, flag) ((obj)->flags &= ~(flag))
|
||||
#define sngisdn_test_flag(obj, flag) ((obj)->flags & flag)
|
||||
|
||||
#define sngisdn_set_trace_flag(obj, flag) ((obj)->trace_flags |= (flag))
|
||||
#define sngisdn_clear_trace_flag(obj, flag) ((obj)->trace_flags &= ~(flag))
|
||||
#define sngisdn_test_trace_flag(obj, flag) ((obj)->trace_flags & flag)
|
||||
|
||||
/* TODO implement these 2 functions */
|
||||
#define ISDN_FUNC_TRACE_ENTER(a)
|
||||
#define ISDN_FUNC_TRACE_EXIT(a)
|
||||
|
||||
/* Configuration functions */
|
||||
ftdm_status_t ftmod_isdn_parse_cfg(ftdm_conf_parameter_t *ftdm_parameters, ftdm_span_t *span);
|
||||
|
||||
/* Support functions */
|
||||
uint32_t get_unique_suInstId(uint8_t cc_id);
|
||||
void clear_call_data(sngisdn_chan_data_t *sngisdn_info);
|
||||
void stack_hdr_init(Header *hdr);
|
||||
void stack_pst_init(Pst *pst);
|
||||
ftdm_status_t get_ftdmchan_by_spInstId(uint8_t cc_id, uint32_t spInstId, sngisdn_chan_data_t **sngisdn_data);
|
||||
ftdm_status_t get_ftdmchan_by_suInstId(uint8_t cc_id, uint32_t suInstId, sngisdn_chan_data_t **sngisdn_data);
|
||||
|
||||
ftdm_status_t check_for_state_change(ftdm_channel_t *ftdmchan);
|
||||
|
||||
/* Outbound Call Control functions */
|
||||
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_alert(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);
|
||||
void sngisdn_snd_reset(ftdm_channel_t *ftdmchan);
|
||||
void sngisdn_snd_con_complete(ftdm_channel_t *ftdmchan);
|
||||
|
||||
/* Inbound Call Control functions */
|
||||
void sngisdn_rcv_con_ind (signed short suId, uint32_t suInstId, uint32_t spInstId, ConEvnt *conEvnt, signed short dChan, uint8_t ces);
|
||||
void sngisdn_rcv_con_cfm (signed short suId, uint32_t suInstId, uint32_t spInstId, CnStEvnt *cnStEvnt, signed short dChan, uint8_t ces);
|
||||
void sngisdn_rcv_cnst_ind (signed short suId, uint32_t suInstId, uint32_t spInstId, CnStEvnt *cnStEvnt, uint8_t evntType, signed short dChan, uint8_t ces);
|
||||
void sngisdn_rcv_disc_ind (signed short suId, uint32_t suInstId, uint32_t spInstId, DiscEvnt *discEvnt);
|
||||
void sngisdn_rcv_rel_ind (signed short suId, uint32_t suInstId, uint32_t spInstId, RelEvnt *relEvnt);
|
||||
void sngisdn_rcv_dat_ind (signed short suId, uint32_t suInstId, uint32_t spInstId, InfoEvnt *infoEvnt);
|
||||
void sngisdn_rcv_sshl_ind (signed short suId, uint32_t suInstId, uint32_t spInstId, SsHlEvnt *ssHlEvnt, uint8_t action);
|
||||
void sngisdn_rcv_sshl_cfm (signed short suId, uint32_t suInstId, uint32_t spInstId, SsHlEvnt *ssHlEvnt, uint8_t action);
|
||||
void sngisdn_rcv_rmrt_ind (signed short suId, uint32_t suInstId, uint32_t spInstId, RmRtEvnt *rmRtEvnt, uint8_t action);
|
||||
void sngisdn_rcv_rmrt_cfm (signed short suId, uint32_t suInstId, uint32_t spInstId, RmRtEvnt *rmRtEvnt, uint8_t action);
|
||||
void sngisdn_rcv_flc_ind (signed short suId, uint32_t suInstId, uint32_t spInstId, StaEvnt *staEvnt);
|
||||
void sngisdn_rcv_fac_ind (signed short suId, uint32_t suInstId, uint32_t spInstId, FacEvnt *facEvnt, uint8_t evntType, signed short dChan, uint8_t ces);
|
||||
void sngisdn_rcv_sta_cfm ( signed short suId, uint32_t suInstId, uint32_t spInstId, StaEvnt *staEvnt);
|
||||
void sngisdn_rcv_srv_ind ( signed short suId, Srv *srvEvnt, signed short dChan, uint8_t ces);
|
||||
void sngisdn_rcv_srv_cfm ( signed short suId, Srv *srvEvnt, signed short dChan, uint8_t ces);
|
||||
void sngisdn_rcv_rst_cfm ( signed short suId, Rst *rstEvnt, signed short dChan, uint8_t ces, uint8_t evtType);
|
||||
void sngisdn_rcv_rst_ind ( signed short suId, Rst *rstEvnt, signed short dChan, uint8_t ces, uint8_t evtType);
|
||||
|
||||
|
||||
void sngisdn_rcv_phy_ind(SuId suId, Reason reason);
|
||||
void sngisdn_rcv_q921_ind(BdMngmt *status);
|
||||
void sngisdn_rcv_q921_trace(BdMngmt *trc, Buffer *mBuf);
|
||||
void sngisdn_rcv_q931_ind(InMngmt *status);
|
||||
void sngisdn_rcv_q931_trace(InMngmt *trc, Buffer *mBuf);
|
||||
void sngisdn_rcv_cc_ind(CcMngmt *status);
|
||||
void sngisdn_rcv_sng_log(uint8_t level, char *fmt,...);
|
||||
|
||||
void handle_sng_log(uint8_t level, char *fmt,...);
|
||||
void sngisdn_set_span_sig_status(ftdm_span_t *ftdmspan, ftdm_signaling_status_t status);
|
||||
|
||||
/* Stack management functions */
|
||||
ftdm_status_t sng_isdn_stack_cfg(ftdm_span_t *span);
|
||||
ftdm_status_t sng_isdn_stack_activate(ftdm_span_t *span);
|
||||
|
||||
|
||||
#endif /* __FTMOD_SNG_ISDN_H__ */
|
||||
|
|
@ -0,0 +1,219 @@
|
|||
/*
|
||||
* Copyright (c) 2010, Sangoma Technologies
|
||||
* David Yat Sin <davidy@sangoma.com>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* * Neither the name of the original author; nor the names of any contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
|
||||
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
******************************************************************************/
|
||||
|
||||
#include "ftmod_sangoma_isdn.h"
|
||||
|
||||
ftdm_status_t parse_switchtype(const char* switch_name, ftdm_span_t *span);
|
||||
ftdm_status_t parse_signalling(const char* signalling, ftdm_span_t *span);
|
||||
|
||||
extern ftdm_sngisdn_data_t g_sngisdn_data;
|
||||
|
||||
ftdm_status_t parse_switchtype(const char* switch_name, ftdm_span_t *span)
|
||||
{
|
||||
unsigned i;
|
||||
|
||||
sngisdn_dchan_data_t *dchan_data;
|
||||
sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*) span->signal_data;
|
||||
switch(span->trunk_type) {
|
||||
case FTDM_TRUNK_T1:
|
||||
if (!strcasecmp(switch_name, "ni2")) {
|
||||
signal_data->switchtype = SNGISDN_SWITCH_NI2;
|
||||
} else if (!strcasecmp(switch_name, "5ess")) {
|
||||
signal_data->switchtype = SNGISDN_SWITCH_5ESS;
|
||||
} else if (!strcasecmp(switch_name, "4ess")) {
|
||||
signal_data->switchtype = SNGISDN_SWITCH_4ESS;
|
||||
} else if (!strcasecmp(switch_name, "dms100")) {
|
||||
signal_data->switchtype = SNGISDN_SWITCH_DMS100;
|
||||
} else {
|
||||
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;
|
||||
}
|
||||
break;
|
||||
case FTDM_TRUNK_E1:
|
||||
if (!strcasecmp(switch_name, "euroisdn") || strcasecmp(switch_name, "etsi")) {
|
||||
signal_data->switchtype = SNGISDN_SWITCH_EUROISDN;
|
||||
} else if (!strcasecmp(switch_name, "qsig")) {
|
||||
signal_data->switchtype = SNGISDN_SWITCH_QSIG;
|
||||
} else {
|
||||
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;
|
||||
}
|
||||
break;
|
||||
case FTDM_TRUNK_BRI:
|
||||
case FTDM_TRUNK_BRI_PTMP:
|
||||
if (!strcasecmp(switch_name, "euroisdn") ||
|
||||
!strcasecmp(switch_name, "etsi")) {
|
||||
signal_data->switchtype = SNGISDN_SWITCH_EUROISDN;
|
||||
} else if (!strcasecmp(switch_name, "insnet") ||
|
||||
!strcasecmp(switch_name, "ntt")) {
|
||||
signal_data->switchtype = SNGISDN_SWITCH_INSNET;
|
||||
} else {
|
||||
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;
|
||||
}
|
||||
/* can be > 1 for some BRI variants */
|
||||
break;
|
||||
default:
|
||||
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++) {
|
||||
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++;
|
||||
g_sngisdn_data.ccs[i].switchtype = signal_data->switchtype;
|
||||
g_sngisdn_data.ccs[i].trunktype = span->trunk_type;
|
||||
ftdm_log(FTDM_LOG_DEBUG, "%s: New switchtype:%s cc_id:%u\n", span->name, switch_name, i);
|
||||
}
|
||||
|
||||
/* 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;
|
||||
|
||||
ftdm_log(FTDM_LOG_DEBUG, "%s: cc_id:%d dchan_id:%d span_id:%d\n", span->name, signal_data->cc_id, signal_data->dchan_id, signal_data->span_id);
|
||||
|
||||
/* Add the channels to the span */
|
||||
for (i=1;i<=span->chan_count;i++) {
|
||||
unsigned chan_id;
|
||||
ftdm_channel_t *ftdmchan = span->channels[i];
|
||||
/* 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++;
|
||||
}
|
||||
return FTDM_SUCCESS;
|
||||
}
|
||||
|
||||
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") ||
|
||||
!strcasecmp(signalling, "pri_net")||
|
||||
!strcasecmp(signalling, "bri_net")) {
|
||||
|
||||
signal_data->signalling = SNGISDN_SIGNALING_NET;
|
||||
} else if (!strcasecmp(signalling, "cpe") ||
|
||||
!strcasecmp(signalling, "pri_cpe")||
|
||||
!strcasecmp(signalling, "bri_cpe")) {
|
||||
|
||||
signal_data->signalling = SNGISDN_SIGNALING_CPE;
|
||||
} else {
|
||||
ftdm_log(FTDM_LOG_ERROR, "Unsupported signalling %s\n", signalling);
|
||||
return FTDM_FAIL;
|
||||
}
|
||||
return FTDM_SUCCESS;
|
||||
}
|
||||
|
||||
ftdm_status_t ftmod_isdn_parse_cfg(ftdm_conf_parameter_t *ftdm_parameters, ftdm_span_t *span)
|
||||
{
|
||||
unsigned paramindex;
|
||||
const char *var, *val;
|
||||
sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*) span->signal_data;
|
||||
/* Set defaults here */
|
||||
signal_data->keep_link_up = 1;
|
||||
signal_data->tei = 0;
|
||||
|
||||
|
||||
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, "switchtype")) {
|
||||
if (parse_switchtype(val, span) != FTDM_SUCCESS) {
|
||||
return FTDM_FAIL;
|
||||
}
|
||||
} else if (!strcasecmp(var, "signalling")) {
|
||||
if (parse_signalling(val, span) != FTDM_SUCCESS) {
|
||||
return FTDM_FAIL;
|
||||
}
|
||||
} else if (!strcasecmp(var, "tei")) {
|
||||
uint8_t tei = atoi(val);
|
||||
if (tei > 127) {
|
||||
ftdm_log(FTDM_LOG_ERROR, "Invalid TEI %d, valid values are (0-127)", tei);
|
||||
return FTDM_FAIL;
|
||||
}
|
||||
signal_data->tei = tei;
|
||||
} else if (!strcasecmp(var, "keep_link_up")) {
|
||||
if (!strcasecmp(val, "yes")) {
|
||||
signal_data->keep_link_up = 1;
|
||||
} else if (!strcasecmp(val, "no")) {
|
||||
signal_data->keep_link_up = 0;
|
||||
} else {
|
||||
ftdm_log(FTDM_LOG_ERROR, "Invalid keep_link_up value, valid values are (yes/no)");
|
||||
return FTDM_FAIL;
|
||||
}
|
||||
} else {
|
||||
ftdm_log(FTDM_LOG_WARNING, "Ignoring unknown parameter %s\n", ftdm_parameters[paramindex].var);
|
||||
}
|
||||
}
|
||||
signal_data->link_id = span->span_id;
|
||||
if (signal_data->switchtype == SNGISDN_SWITCH_INVALID) {
|
||||
ftdm_log(FTDM_LOG_ERROR, "%s: switchtype not specified", span->name);
|
||||
return FTDM_FAIL;
|
||||
}
|
||||
if (signal_data->signalling == SNGISDN_SIGNALING_INVALID) {
|
||||
ftdm_log(FTDM_LOG_ERROR, "%s: signalling not specified", span->name);
|
||||
return FTDM_FAIL;
|
||||
}
|
||||
return FTDM_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
/******************************************************************************/
|
||||
/* For Emacs:
|
||||
* Local Variables:
|
||||
* mode:c
|
||||
* indent-tabs-mode:t
|
||||
* tab-width:4
|
||||
* c-basic-offset:4
|
||||
* End:
|
||||
* For VIM:
|
||||
* vim:set softtabstop=4 shiftwidth=4 tabstop=4:
|
||||
*/
|
|
@ -0,0 +1,85 @@
|
|||
/*
|
||||
* Copyright (c) 2010, Sangoma Technologies
|
||||
* David Yat Sin <davidy@sangoma.com>
|
||||
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* * Neither the name of the original author; nor the names of any contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
|
||||
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
******************************************************************************/
|
||||
|
||||
#include "ftmod_sangoma_isdn.h"
|
||||
|
||||
|
||||
void sngisdn_set_chan_sig_status(ftdm_channel_t *ftdmchan, ftdm_signaling_status_t status);
|
||||
|
||||
void sngisdn_set_chan_sig_status(ftdm_channel_t *ftdmchan, ftdm_signaling_status_t status)
|
||||
{
|
||||
ftdm_sigmsg_t sig;
|
||||
ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Signalling link status changed to %s\n", ftdm_signaling_status2str(status));
|
||||
|
||||
memset(&sig, 0, sizeof(sig));
|
||||
sig.chan_id = ftdmchan->chan_id;
|
||||
sig.span_id = ftdmchan->span_id;
|
||||
sig.channel = ftdmchan;
|
||||
sig.event_id = FTDM_SIGEVENT_SIGSTATUS_CHANGED;
|
||||
sig.raw_data = &status;
|
||||
ftdm_span_send_signal(ftdmchan->span, &sig);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void sngisdn_set_span_sig_status(ftdm_span_t *ftdmspan, ftdm_signaling_status_t status)
|
||||
{
|
||||
unsigned i;
|
||||
/* TODO: use channel iterator once it is implemented */
|
||||
|
||||
for (i=1;i<=ftdmspan->chan_count;i++) {
|
||||
sngisdn_set_chan_sig_status(ftdmspan->channels[i], status);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/* For Emacs:
|
||||
* Local Variables:
|
||||
* mode:c
|
||||
* indent-tabs-mode:t
|
||||
* tab-width:4
|
||||
* c-basic-offset:4
|
||||
* End:
|
||||
* For VIM:
|
||||
* vim:set softtabstop=4 shiftwidth=4 tabstop=4:
|
||||
*/
|
||||
|
||||
/******************************************************************************/
|
||||
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,316 @@
|
|||
/*
|
||||
* Copyright (c) 2010, Sangoma Technologies
|
||||
* David Yat Sin <davidy@sangoma.com>
|
||||
* Moises Silva <moy@sangoma.com>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* * Neither the name of the original author; nor the names of any contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
|
||||
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "ftmod_sangoma_isdn.h"
|
||||
|
||||
void stack_resp_hdr_init(Header *hdr);
|
||||
|
||||
ftdm_status_t sng_isdn_cntrl_phy(ftdm_span_t *span);
|
||||
ftdm_status_t sng_isdn_cntrl_q921(ftdm_span_t *span);
|
||||
ftdm_status_t sng_isdn_cntrl_q931(ftdm_span_t *span);
|
||||
ftdm_status_t sng_isdn_cntrl_cc(ftdm_span_t *span);
|
||||
ftdm_status_t sng_isdn_cntrl_trace(ftdm_span_t *span, sngisdn_tracetype_t trace_opt);
|
||||
|
||||
ftdm_status_t sng_isdn_cntrl_q931(ftdm_span_t *span, uint8_t action, uint8_t subaction);
|
||||
ftdm_status_t sng_isdn_cntrl_q921(ftdm_span_t *span, uint8_t action, uint8_t subaction);
|
||||
|
||||
extern ftdm_sngisdn_data_t g_sngisdn_data;
|
||||
|
||||
|
||||
ftdm_status_t sng_isdn_stack_activate(ftdm_span_t *span)
|
||||
{
|
||||
sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*)span->signal_data;
|
||||
|
||||
if (sng_isdn_cntrl_q921(span) != 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);
|
||||
if (!g_sngisdn_data.ccs[signal_data->cc_id].activation_done) {
|
||||
g_sngisdn_data.ccs[signal_data->cc_id].activation_done = 1;
|
||||
if (sng_isdn_cntrl_cc(span) != FTDM_SUCCESS) {
|
||||
ftdm_log(FTDM_LOG_CRIT, "%s:Failed to activate stack CC\n", span->name);
|
||||
return FTDM_FAIL;
|
||||
}
|
||||
ftdm_log(FTDM_LOG_DEBUG, "%s:Stack CC activated\n", span->name);
|
||||
}
|
||||
|
||||
if (sng_isdn_cntrl_q931(span) != FTDM_SUCCESS) {
|
||||
ftdm_log(FTDM_LOG_CRIT, "%s:Failed to activate stack q931\n", span->name);
|
||||
return FTDM_FAIL;
|
||||
}
|
||||
ftdm_log(FTDM_LOG_DEBUG, "%s:Stack q931 activated\n", span->name);
|
||||
|
||||
ftdm_log(FTDM_LOG_INFO, "%s:Stack activated\n",span->name);
|
||||
return FTDM_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
ftdm_status_t sng_isdn_cntrl_phy(ftdm_span_t *span)
|
||||
{
|
||||
L1Mngmt cntrl;
|
||||
Pst pst;
|
||||
|
||||
ftdm_log(FTDM_LOG_ERROR, "%s:PHY control not implemented\n", span->name);
|
||||
return FTDM_SUCCESS;
|
||||
/* TODO: phy cntrl not implemented yet */
|
||||
|
||||
sng_isdn_phy_cntrl(&pst, &cntrl);
|
||||
return FTDM_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
ftdm_status_t sng_isdn_cntrl_q921(ftdm_span_t *span)
|
||||
{
|
||||
ftdm_status_t status;
|
||||
status = sng_isdn_cntrl_q921(span, ABND_ENA, NOTUSED);
|
||||
|
||||
/* Try to find an alternative for this */
|
||||
/* LAPD will call LdUiDatBndCfm before it received a LdLiMacBndCfm from L1,
|
||||
so we need to give some time before activating q931, as q931 will send a
|
||||
LdUiDatConReq when activated, and this requires the Mac SAP to be already
|
||||
bound first */
|
||||
|
||||
if (status == FTDM_SUCCESS) {
|
||||
ftdm_sleep(500);
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
ftdm_status_t sng_isdn_cntrl_q931(ftdm_span_t *span)
|
||||
{
|
||||
/* TODO: remove this function later, just call sng_isdn_cntrl_q931 directly */
|
||||
return sng_isdn_cntrl_q931(span, ABND_ENA, SAELMNT);
|
||||
}
|
||||
|
||||
ftdm_status_t sng_isdn_cntrl_cc(ftdm_span_t *span)
|
||||
{
|
||||
CcMngmt 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 = ENTCC;
|
||||
|
||||
/* 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 = ENTCC; /* entity */
|
||||
cntrl.hdr.entId.inst = S_INST; /* instance */
|
||||
cntrl.hdr.elmId.elmnt = STTSAP; /* physical sap */
|
||||
|
||||
cntrl.t.cntrl.action = ABND_ENA;
|
||||
cntrl.t.cntrl.subAction = SAELMNT;
|
||||
|
||||
cntrl.t.cntrl.sapId = signal_data->cc_id;
|
||||
if (sng_isdn_cc_cntrl(&pst, &cntrl)) {
|
||||
return FTDM_FAIL;
|
||||
}
|
||||
return FTDM_SUCCESS;
|
||||
}
|
||||
|
||||
ftdm_status_t sng_isdn_cntrl_trace(ftdm_span_t *span, sngisdn_tracetype_t trace_opt)
|
||||
{
|
||||
sngisdn_span_data_t *signal_data = (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);
|
||||
sngisdn_clear_trace_flag(signal_data, SNGISDN_TRACE_Q921);
|
||||
|
||||
if (sng_isdn_cntrl_q921(span, ADISIMM, SAELMNT) != FTDM_SUCCESS) {
|
||||
ftdm_log(FTDM_LOG_ERROR, "s%d Failed to disable q921 trace\n");
|
||||
}
|
||||
}
|
||||
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);
|
||||
sngisdn_clear_trace_flag(signal_data, SNGISDN_TRACE_Q931);
|
||||
|
||||
if (sng_isdn_cntrl_q931(span, ADISIMM, SATRC) != FTDM_SUCCESS) {
|
||||
ftdm_log(FTDM_LOG_ERROR, "s%d Failed to disable q931 trace\n");
|
||||
}
|
||||
}
|
||||
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);
|
||||
sngisdn_set_trace_flag(signal_data, SNGISDN_TRACE_Q921);
|
||||
|
||||
if (sng_isdn_cntrl_q921(span, AENA, SATRC) != FTDM_SUCCESS) {
|
||||
ftdm_log(FTDM_LOG_ERROR, "s%d Failed to enable q921 trace\n");
|
||||
}
|
||||
}
|
||||
break;
|
||||
case SNGISDN_TRACE_Q931:
|
||||
if (!sngisdn_test_trace_flag(signal_data, SNGISDN_TRACE_Q931)) {
|
||||
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 (sng_isdn_cntrl_q931(span, AENA, SATRC) != FTDM_SUCCESS) {
|
||||
ftdm_log(FTDM_LOG_ERROR, "s%d Failed to enable q931 trace\n");
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
return FTDM_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
ftdm_status_t sng_isdn_cntrl_q931(ftdm_span_t *span, uint8_t action, uint8_t subaction)
|
||||
{
|
||||
InMngmt 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 = ENTIN;
|
||||
|
||||
/* 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 = ENTIN; /* entity */
|
||||
cntrl.hdr.entId.inst = S_INST; /* instance */
|
||||
cntrl.hdr.elmId.elmnt = STDLSAP; /* physical sap */
|
||||
|
||||
cntrl.t.cntrl.action = action;
|
||||
cntrl.t.cntrl.subAction = subaction;
|
||||
|
||||
if (action == AENA && subaction == SATRC) {
|
||||
cntrl.t.cntrl.trcLen = -1; /* Trace the entire message buffer */
|
||||
}
|
||||
cntrl.t.cntrl.sapId = signal_data->link_id;
|
||||
cntrl.t.cntrl.ces = 0;
|
||||
|
||||
if(sng_isdn_q931_cntrl(&pst, &cntrl)) {
|
||||
return FTDM_FAIL;
|
||||
}
|
||||
return FTDM_SUCCESS;
|
||||
|
||||
}
|
||||
|
||||
ftdm_status_t sng_isdn_cntrl_q921(ftdm_span_t *span, uint8_t action, uint8_t subaction)
|
||||
{
|
||||
BdMngmt 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 = ENTLD;
|
||||
|
||||
/* initalize the control structure */
|
||||
memset(&cntrl, 0, sizeof(cntrl));
|
||||
|
||||
/* initalize the control header */
|
||||
stack_hdr_init(&cntrl.hdr);
|
||||
/* build control request */
|
||||
cntrl.hdr.msgType = TCNTRL;
|
||||
cntrl.hdr.entId.ent = ENTLD;
|
||||
cntrl.hdr.entId.inst = S_INST;
|
||||
|
||||
#if (SMBD_LMINT3 || BD_LMINT3)
|
||||
stack_resp_hdr_init(&cntrl.hdr);
|
||||
#endif /* _LMINT3 */
|
||||
|
||||
cntrl.hdr.elmId.elmnt = STMSAP;
|
||||
cntrl.t.cntrl.action = action;
|
||||
cntrl.t.cntrl.subAction = subaction;
|
||||
|
||||
#if (SMBD_LMINT3 || BD_LMINT3)
|
||||
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->link_id;
|
||||
cntrl.hdr.elmId.elmntInst2 = NOTUSED;
|
||||
cntrl.hdr.elmId.elmntInst3 = NOTUSED;
|
||||
#endif /* _LMINT3 */
|
||||
|
||||
cntrl.t.cntrl.logInt = NOTUSED;
|
||||
cntrl.t.cntrl.trcLen = NOTUSED;
|
||||
if (action == AENA && subaction == SATRC) {
|
||||
cntrl.t.cntrl.trcLen = -1; /* Trace the entire message buffer */
|
||||
}
|
||||
|
||||
SGetDateTime(&(cntrl.t.cntrl.dt));
|
||||
if(sng_isdn_q921_cntrl(&pst, &cntrl)) {
|
||||
return FTDM_FAIL;
|
||||
}
|
||||
|
||||
return FTDM_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
void stack_resp_hdr_init(Header *hdr)
|
||||
{
|
||||
hdr->response.selector = 0;
|
||||
hdr->response.mem.region = RTESPEC;
|
||||
hdr->response.mem.pool = S_POOL;
|
||||
hdr->response.prior = PRIOR0;
|
||||
hdr->response.route = RTESPEC;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
/* For Emacs:
|
||||
* Local Variables:
|
||||
* mode:c
|
||||
* indent-tabs-mode:t
|
||||
* tab-width:4
|
||||
* c-basic-offset:4
|
||||
* End:
|
||||
* For VIM:
|
||||
* vim:set softtabstop=4 shiftwidth=4 tabstop=4:
|
||||
*/
|
||||
|
||||
/******************************************************************************/
|
|
@ -0,0 +1,935 @@
|
|||
/*
|
||||
* Copyright (c) 2010, Sangoma Technologies
|
||||
* David Yat Sin <davidy@sangoma.com>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* * Neither the name of the original author; nor the names of any contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
|
||||
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "ftmod_sangoma_isdn.h"
|
||||
|
||||
extern ftdm_status_t cpy_calling_num_from_sngisdn(ftdm_caller_data_t *ftdm, CgPtyNmb *cgPtyNmb);
|
||||
extern ftdm_status_t cpy_called_num_from_sngisdn(ftdm_caller_data_t *ftdm, CdPtyNmb *cdPtyNmb);
|
||||
extern ftdm_status_t cpy_called_name_from_sngisdn(ftdm_caller_data_t *ftdm, CgPtyNmb *cgPtyNmb);
|
||||
extern ftdm_status_t cpy_calling_name_from_sngisdn(ftdm_caller_data_t *ftdm, ConEvnt *conEvnt);
|
||||
extern void sngisdn_trace_q921(char* str, uint8_t* data, uint32_t data_len);
|
||||
extern void sngisdn_trace_q931(char* str, uint8_t* data, uint32_t data_len);
|
||||
extern void get_memory_info(void);
|
||||
|
||||
extern ftdm_sngisdn_data_t g_sngisdn_data;
|
||||
|
||||
#define MAX_DECODE_STR_LEN 2000
|
||||
|
||||
/* Remote side transmit a SETUP */
|
||||
void sngisdn_rcv_con_ind (int16_t suId, uint32_t suInstId, uint32_t spInstId, ConEvnt *conEvnt, int16_t dChan, uint8_t ces)
|
||||
{
|
||||
ISDN_FUNC_TRACE_ENTER(__FUNCTION__);
|
||||
uint8_t bchan_no = 0;
|
||||
sngisdn_chan_data_t *sngisdn_info;
|
||||
ftdm_channel_t *ftdmchan;
|
||||
/*sngisdn_span_data_t *span_info;*/
|
||||
|
||||
ftdm_log(FTDM_LOG_DEBUG, "%s suId:%d suInstId:%d spInstId:%d dChan:%d ces:%d\n", __FUNCTION__, suId, suInstId, spInstId, dChan, ces);
|
||||
|
||||
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.ccs[suId].active_spInstIds[spInstId] == NULL, "Con Ind on busy spInstId");
|
||||
|
||||
if (conEvnt->chanId.eh.pres != PRSNT_NODEF) {
|
||||
/* TODO: Implement me */
|
||||
ftdm_log(FTDM_LOG_ERROR, "Incoming call without Channel Id not supported yet\n");
|
||||
ISDN_FUNC_TRACE_EXIT(__FUNCTION__);
|
||||
return;
|
||||
}
|
||||
|
||||
if (conEvnt->chanId.chanNmbSlotMap.pres) {
|
||||
bchan_no = conEvnt->chanId.chanNmbSlotMap.val[0];
|
||||
} else if (conEvnt->chanId.infoChanSel.pres) {
|
||||
bchan_no = conEvnt->chanId.infoChanSel.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;
|
||||
}
|
||||
|
||||
sngisdn_info = g_sngisdn_data.dchans[dChan].channels[bchan_no];
|
||||
ftdmchan = sngisdn_info->ftdmchan;
|
||||
ftdm_mutex_lock(ftdmchan->mutex);
|
||||
|
||||
/* check if there is a pending state change, give it a bit to clear */
|
||||
if (check_for_state_change(ftdmchan) != FTDM_SUCCESS) {
|
||||
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_CRIT, "Failed to wait for pending state change\n");
|
||||
ftdm_mutex_unlock(ftdmchan->mutex);
|
||||
ISDN_FUNC_TRACE_EXIT(__FUNCTION__);
|
||||
return;
|
||||
}
|
||||
|
||||
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_INFO, "Received SETUP\n");
|
||||
switch (ftdmchan->state){
|
||||
case FTDM_CHANNEL_STATE_DOWN: /* Proper state to receive a SETUP */
|
||||
sngisdn_info->suInstId = get_unique_suInstId(suId);
|
||||
sngisdn_info->spInstId = spInstId;
|
||||
g_sngisdn_data.ccs[suId].active_spInstIds[spInstId] = sngisdn_info;
|
||||
g_sngisdn_data.ccs[suId].active_suInstIds[sngisdn_info->suInstId] = sngisdn_info;
|
||||
|
||||
/* try to open the channel */
|
||||
if (ftdm_channel_open_chan(ftdmchan) != FTDM_SUCCESS) {
|
||||
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_CRIT, "Failed to open channel");
|
||||
sngisdn_set_flag(sngisdn_info, FLAG_LOCAL_REL);
|
||||
ftdmchan->caller_data.hangup_cause = FTDM_CAUSE_NORMAL_TEMPORARY_FAILURE;
|
||||
ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_CANCEL);
|
||||
} else {
|
||||
/* Fill in call information */
|
||||
cpy_calling_num_from_sngisdn(&ftdmchan->caller_data, &conEvnt->cgPtyNmb);
|
||||
cpy_called_num_from_sngisdn(&ftdmchan->caller_data, &conEvnt->cdPtyNmb);
|
||||
cpy_calling_name_from_sngisdn(&ftdmchan->caller_data, conEvnt);
|
||||
|
||||
/* Get ani2 */
|
||||
#if 0
|
||||
/* TODO: confirm that this works in the field */
|
||||
if (conEvnt->niOperSysAcc.eh.pres) {
|
||||
if (conEvnt->niOperSysAcc.typeAcc.pres) {
|
||||
ftdmchan->caller_data.aniII = (uint8_t)conEvnt->niOperSysAcc.typeAcc.val;
|
||||
ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Received ANI: type of access:%x", conEvnt->niOperSysAcc.typeAcc.val);
|
||||
}
|
||||
if (conEvnt->niOperSysAcc.typeServ.pres) {
|
||||
ftdmchan->caller_data.aniII = (uint8_t)conEvnt->niOperSysAcc.typeServ.val;
|
||||
ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Received ANI: type of service:%x", conEvnt->niOperSysAcc.typeServ.val);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/* set the state of the channel to collecting...the rest is done by the chan monitor */
|
||||
ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_COLLECT);
|
||||
|
||||
}
|
||||
break;
|
||||
case FTDM_CHANNEL_STATE_DIALING: /* glare */
|
||||
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_WARNING, "Received SETUP in DIALING state, glare, queueing incoming call\n");
|
||||
/* the flag the channel as having a collision */
|
||||
sngisdn_set_flag(sngisdn_info, FLAG_GLARE);
|
||||
|
||||
/* save the SETUP for processing once the channel has gone to DOWN */
|
||||
memcpy(&sngisdn_info->glare.setup, conEvnt, sizeof(*conEvnt));
|
||||
sngisdn_info->glare.suId = suId;
|
||||
sngisdn_info->glare.suInstId = suInstId;
|
||||
sngisdn_info->glare.spInstId = spInstId;
|
||||
sngisdn_info->glare.dChan = dChan;
|
||||
sngisdn_info->glare.ces = ces;
|
||||
break;
|
||||
default:
|
||||
ftdm_log_chan(ftdmchan, FTDM_LOG_CRIT, "Received SETUP in an invalid state (%s)\n", ftdm_channel_state2str(ftdmchan->state));
|
||||
break;
|
||||
}
|
||||
ftdm_mutex_unlock(ftdmchan->mutex);
|
||||
ISDN_FUNC_TRACE_EXIT(__FUNCTION__);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Remote side transmit a CONNECT or CONNECT ACK */
|
||||
void sngisdn_rcv_con_cfm (int16_t suId, uint32_t suInstId, uint32_t spInstId, CnStEvnt *cnStEvnt, int16_t dChan, uint8_t ces)
|
||||
{
|
||||
ISDN_FUNC_TRACE_ENTER(__FUNCTION__);
|
||||
sngisdn_chan_data_t *sngisdn_info;
|
||||
ftdm_channel_t *ftdmchan;
|
||||
|
||||
ftdm_log(FTDM_LOG_DEBUG, "%s suId:%d suInstId:%d spInstId:%d dChan:%d ces:%d\n", __FUNCTION__, suId, suInstId, spInstId, dChan, ces);
|
||||
|
||||
|
||||
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");
|
||||
|
||||
if (get_ftdmchan_by_suInstId(suId, suInstId, &sngisdn_info) != FTDM_SUCCESS) {
|
||||
ftdm_log(FTDM_LOG_CRIT, "Could not find matching call suId:%d suInstId:%d spInstId:%d\n", suId, suInstId, spInstId);
|
||||
ISDN_FUNC_TRACE_EXIT(__FUNCTION__);
|
||||
return;
|
||||
}
|
||||
|
||||
ftdmchan = (ftdm_channel_t*)sngisdn_info->ftdmchan;
|
||||
|
||||
if (!sngisdn_info->spInstId) {
|
||||
sngisdn_info->spInstId = spInstId;
|
||||
g_sngisdn_data.ccs[suId].active_spInstIds[spInstId] = sngisdn_info;
|
||||
}
|
||||
|
||||
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_INFO, "Received CONNECT/CONNECT ACK\n");
|
||||
ftdm_mutex_lock(ftdmchan->mutex);
|
||||
|
||||
/* check if there is a pending state change, give it a bit to clear */
|
||||
if (check_for_state_change(ftdmchan) != FTDM_SUCCESS) {
|
||||
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_CRIT, "Failed to wait for pending state change\n");
|
||||
ftdm_mutex_unlock(ftdmchan->mutex);
|
||||
ISDN_FUNC_TRACE_EXIT(__FUNCTION__);
|
||||
return;
|
||||
}
|
||||
|
||||
if (ftdmchan->span->trunk_type == FTDM_TRUNK_BRI_PTMP &&
|
||||
((sngisdn_span_data_t*)ftdmchan->span->signal_data)->signalling == SNGISDN_SIGNALING_NET) {
|
||||
|
||||
if(sngisdn_info->ces == CES_MNGMNT) {
|
||||
/* We assign the call to the first TE */
|
||||
sngisdn_info->ces = ces;
|
||||
} else {
|
||||
/* We already assigned this call, do nothing */
|
||||
ftdm_mutex_unlock(ftdmchan->mutex);
|
||||
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Call already assigned, ignoring connect\n");
|
||||
ISDN_FUNC_TRACE_EXIT(__FUNCTION__);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OUTBOUND)) {
|
||||
switch(ftdmchan->state) {
|
||||
case FTDM_CHANNEL_STATE_PROGRESS:
|
||||
case FTDM_CHANNEL_STATE_PROGRESS_MEDIA:
|
||||
case FTDM_CHANNEL_STATE_DIALING:
|
||||
ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_UP);
|
||||
break;
|
||||
default:
|
||||
ftdm_log_chan(ftdmchan, FTDM_LOG_CRIT, "Received CONNECT/CONNECT ACK in an invalid state (%s)\n",
|
||||
ftdm_channel_state2str(ftdmchan->state));
|
||||
|
||||
ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_RESTART);
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
switch(ftdmchan->state) {
|
||||
case FTDM_CHANNEL_STATE_UP:
|
||||
/* This is the only valid state we should get a CONNECT ACK on */
|
||||
/* do nothing */
|
||||
break;
|
||||
default:
|
||||
ftdm_log_chan(ftdmchan, FTDM_LOG_CRIT, "Received CONNECT/CONNECT ACK in an invalid state (%s)\n", ftdm_channel_state2str(ftdmchan->state));
|
||||
ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_RESTART);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
ftdm_mutex_unlock(ftdmchan->mutex);
|
||||
ISDN_FUNC_TRACE_EXIT(__FUNCTION__);
|
||||
return;
|
||||
}
|
||||
|
||||
void sngisdn_rcv_cnst_ind (int16_t suId, uint32_t suInstId, uint32_t spInstId, CnStEvnt *cnStEvnt, uint8_t evntType, int16_t dChan, uint8_t ces)
|
||||
{
|
||||
ISDN_FUNC_TRACE_ENTER(__FUNCTION__);
|
||||
sngisdn_chan_data_t *sngisdn_info;
|
||||
ftdm_channel_t *ftdmchan;
|
||||
|
||||
ftdm_log(FTDM_LOG_DEBUG, "%s suId:%d suInstId:%d spInstId:%d dChan:%d ces:%d\n", __FUNCTION__, suId, suInstId, spInstId, dChan, ces);
|
||||
|
||||
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");
|
||||
|
||||
if (get_ftdmchan_by_suInstId(suId, suInstId, &sngisdn_info) != FTDM_SUCCESS) {
|
||||
ftdm_log(FTDM_LOG_CRIT, "Could not find matching call suId:%d suInstId:%d spInstId:%d\n", suId, suInstId, spInstId);
|
||||
ISDN_FUNC_TRACE_EXIT(__FUNCTION__);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!sngisdn_info->spInstId) {
|
||||
sngisdn_info->spInstId = spInstId;
|
||||
g_sngisdn_data.ccs[suId].active_spInstIds[spInstId] = sngisdn_info;
|
||||
}
|
||||
|
||||
ftdmchan = (ftdm_channel_t*)sngisdn_info->ftdmchan;
|
||||
ftdm_log_chan(ftdmchan, FTDM_LOG_INFO, "Received %s\n",
|
||||
(evntType == MI_ALERTING)?"ALERT":
|
||||
(evntType == MI_CALLPROC)?"PROCEED":
|
||||
(evntType == MI_PROGRESS)?"PROGRESS":"UNKNOWN");
|
||||
ftdm_mutex_lock(ftdmchan->mutex);
|
||||
|
||||
/* check if there is a pending state change, give it a bit to clear */
|
||||
if (check_for_state_change(ftdmchan) != FTDM_SUCCESS) {
|
||||
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_CRIT, "Failed to wait for pending state change\n");
|
||||
ftdm_mutex_unlock(ftdmchan->mutex);
|
||||
ISDN_FUNC_TRACE_EXIT(__FUNCTION__);
|
||||
return;
|
||||
}
|
||||
|
||||
switch(ftdmchan->state) {
|
||||
case FTDM_CHANNEL_STATE_DIALING:
|
||||
if (evntType == MI_PROGRESS) {
|
||||
ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_PROGRESS_MEDIA);
|
||||
} else {
|
||||
ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_PROGRESS);
|
||||
}
|
||||
break;
|
||||
case FTDM_CHANNEL_STATE_PROGRESS:
|
||||
if (evntType == MI_PROGRESS) {
|
||||
ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_PROGRESS_MEDIA);
|
||||
}
|
||||
break;
|
||||
case FTDM_CHANNEL_STATE_PROGRESS_MEDIA:
|
||||
/* Do nothing */
|
||||
break;
|
||||
default:
|
||||
ftdm_log_chan(ftdmchan, FTDM_LOG_CRIT, "Received ALERT/PROCEED/PROGRESS in an invalid state (%s)\n",
|
||||
ftdm_channel_state2str(ftdmchan->state));
|
||||
|
||||
ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_RESTART);
|
||||
break;
|
||||
}
|
||||
|
||||
ftdm_mutex_unlock(ftdmchan->mutex);
|
||||
ISDN_FUNC_TRACE_EXIT(__FUNCTION__);
|
||||
return;
|
||||
}
|
||||
|
||||
void sngisdn_rcv_disc_ind (int16_t suId, uint32_t suInstId, uint32_t spInstId, DiscEvnt *discEvnt)
|
||||
{
|
||||
ISDN_FUNC_TRACE_ENTER(__FUNCTION__);
|
||||
sngisdn_chan_data_t *sngisdn_info;
|
||||
ftdm_channel_t *ftdmchan = NULL;
|
||||
|
||||
ftdm_log(FTDM_LOG_DEBUG, "%s suId:%d suInstId:%d spInstId:%d\n", __FUNCTION__, suId, suInstId, spInstId);
|
||||
|
||||
ftdm_assert(spInstId != 0, "Received DISCONNECT with invalid id");
|
||||
|
||||
if (spInstId && get_ftdmchan_by_spInstId(suId, spInstId, &sngisdn_info) == FTDM_SUCCESS) {
|
||||
ftdmchan = (ftdm_channel_t*)sngisdn_info->ftdmchan;
|
||||
} else if (suInstId && get_ftdmchan_by_suInstId(suId, suInstId, &sngisdn_info) == FTDM_SUCCESS) {
|
||||
ftdmchan = (ftdm_channel_t*)sngisdn_info->ftdmchan;
|
||||
} else {
|
||||
ftdm_log(FTDM_LOG_CRIT, "Could not find matching call suId:%d suInstId:%d spInstId:%d\n", suId, suInstId, spInstId);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!sngisdn_info->spInstId) {
|
||||
sngisdn_info->spInstId = spInstId;
|
||||
g_sngisdn_data.ccs[suId].active_spInstIds[spInstId] = sngisdn_info;
|
||||
}
|
||||
|
||||
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_INFO, "Received DISCONNECT\n");
|
||||
ftdm_mutex_lock(ftdmchan->mutex);
|
||||
/* check if there is a pending state change, give it a bit to clear */
|
||||
if (check_for_state_change(ftdmchan) != FTDM_SUCCESS) {
|
||||
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_CRIT, "Failed to wait for pending state change\n");
|
||||
ftdm_mutex_unlock(ftdmchan->mutex);
|
||||
ISDN_FUNC_TRACE_EXIT(__FUNCTION__);
|
||||
return;
|
||||
}
|
||||
|
||||
switch (ftdmchan->state) {
|
||||
case FTDM_CHANNEL_STATE_RING:
|
||||
case FTDM_CHANNEL_STATE_DIALING:
|
||||
case FTDM_CHANNEL_STATE_PROGRESS:
|
||||
case FTDM_CHANNEL_STATE_PROGRESS_MEDIA:
|
||||
case FTDM_CHANNEL_STATE_COLLECT:
|
||||
case FTDM_CHANNEL_STATE_UP:
|
||||
if (discEvnt->causeDgn[0].eh.pres && discEvnt->causeDgn[0].causeVal.pres) {
|
||||
ftdmchan->caller_data.hangup_cause = discEvnt->causeDgn[0].causeVal.val;
|
||||
} else {
|
||||
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_WARNING, "DISCONNECT did not have a cause code\n");
|
||||
ftdmchan->caller_data.hangup_cause = 0;
|
||||
}
|
||||
sngisdn_set_flag(sngisdn_info, FLAG_REMOTE_REL);
|
||||
ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_TERMINATING);
|
||||
break;
|
||||
default:
|
||||
ftdm_log_chan(ftdmchan, FTDM_LOG_CRIT, "Received DISCONNECT in an invalid state (%s)\n",
|
||||
ftdm_channel_state2str(ftdmchan->state));
|
||||
/* start reset procedure */
|
||||
ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_RESTART);
|
||||
break;
|
||||
}
|
||||
|
||||
ftdm_mutex_unlock(ftdmchan->mutex);
|
||||
ISDN_FUNC_TRACE_EXIT(__FUNCTION__);
|
||||
return;
|
||||
}
|
||||
|
||||
void sngisdn_rcv_rel_ind (int16_t suId, uint32_t suInstId, uint32_t spInstId, RelEvnt *relEvnt)
|
||||
{
|
||||
ISDN_FUNC_TRACE_ENTER(__FUNCTION__);
|
||||
ftdm_log(FTDM_LOG_DEBUG, "%s suId:%d suInstId:%d spInstId:%d\n", __FUNCTION__, suId, suInstId, spInstId);
|
||||
|
||||
sngisdn_chan_data_t *sngisdn_info ;
|
||||
ftdm_channel_t *ftdmchan = NULL;
|
||||
|
||||
/* get the ftdmchan and ss7_chan_data from the circuit */
|
||||
if (suInstId && (get_ftdmchan_by_suInstId(suId, suInstId, &sngisdn_info) == FTDM_SUCCESS)) {
|
||||
ftdmchan = sngisdn_info->ftdmchan;
|
||||
} else if (spInstId && (get_ftdmchan_by_spInstId(suId, spInstId, &sngisdn_info) == FTDM_SUCCESS)) {
|
||||
ftdmchan = sngisdn_info->ftdmchan;
|
||||
}
|
||||
|
||||
if (ftdmchan == NULL) {
|
||||
ftdm_log(FTDM_LOG_CRIT, "Failed to find matching channel suId:%d suInstId:%d spInstId:%d\n", suId, suInstId, spInstId);
|
||||
ISDN_FUNC_TRACE_EXIT(__FUNCTION__);
|
||||
return;
|
||||
}
|
||||
|
||||
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_INFO, "Received RELEASE/RELEASE COMPLETE\n");
|
||||
/* now that we have the right channel...put a lock on it so no-one else can use it */
|
||||
ftdm_mutex_lock(ftdmchan->mutex);
|
||||
|
||||
/* check if there is a pending state change, give it a bit to clear */
|
||||
if (check_for_state_change(ftdmchan)) {
|
||||
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_CRIT, "Failed to wait for pending state change\n");
|
||||
ftdm_mutex_unlock(ftdmchan->mutex);
|
||||
ISDN_FUNC_TRACE_EXIT(__FUNCTION__);
|
||||
return;
|
||||
};
|
||||
|
||||
/* check whether the ftdm channel is in a state to accept a call */
|
||||
switch (ftdmchan->state) {
|
||||
case FTDM_CHANNEL_STATE_HANGUP_COMPLETE:
|
||||
/* go to DOWN */
|
||||
ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_DOWN);
|
||||
break;
|
||||
case FTDM_CHANNEL_STATE_DOWN:
|
||||
/* do nothing, just drop the message */
|
||||
break;
|
||||
case FTDM_CHANNEL_STATE_PROGRESS:
|
||||
case FTDM_CHANNEL_STATE_PROGRESS_MEDIA:
|
||||
/* Remote side sent a SETUP, then a RELEASE COMPLETE to abort call - this is an abort */
|
||||
sngisdn_set_flag(sngisdn_info, FLAG_REMOTE_ABORT);
|
||||
ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_TERMINATING);
|
||||
break;
|
||||
case FTDM_CHANNEL_STATE_DIALING:
|
||||
/* Remote side rejected our SETUP message on outbound call */
|
||||
sngisdn_set_flag(sngisdn_info, FLAG_REMOTE_ABORT);
|
||||
ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_TERMINATING);
|
||||
break;
|
||||
case FTDM_CHANNEL_STATE_UP:
|
||||
sngisdn_set_flag(sngisdn_info, FLAG_REMOTE_ABORT);
|
||||
ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_TERMINATING);
|
||||
break;
|
||||
default:
|
||||
/* Should just stop the call...but a reset is easier for now (since it does hangup the call) */
|
||||
ftdm_log_chan(ftdmchan, FTDM_LOG_CRIT, "Received RELEASE in an invalid state (%s)\n",
|
||||
ftdm_channel_state2str(ftdmchan->state));
|
||||
|
||||
/* go to RESTART */
|
||||
ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_RESTART);
|
||||
|
||||
break;
|
||||
/**************************************************************************/
|
||||
}
|
||||
|
||||
/* unlock the channel */
|
||||
ftdm_mutex_unlock(ftdmchan->mutex);
|
||||
|
||||
ISDN_FUNC_TRACE_EXIT(__FUNCTION__);
|
||||
return;
|
||||
}
|
||||
|
||||
void sngisdn_rcv_dat_ind (int16_t suId, uint32_t suInstId, uint32_t spInstId, InfoEvnt *infoEvnt)
|
||||
{
|
||||
ISDN_FUNC_TRACE_ENTER(__FUNCTION__);
|
||||
ftdm_log(FTDM_LOG_INFO, "Received DATA IND suId:%d suInstId:%d spInstId:%d\n", suId, suInstId, spInstId);
|
||||
ISDN_FUNC_TRACE_EXIT(__FUNCTION__);
|
||||
return;
|
||||
}
|
||||
|
||||
void sngisdn_rcv_sshl_ind (int16_t suId, uint32_t suInstId, uint32_t spInstId, SsHlEvnt *ssHlEvnt, uint8_t action)
|
||||
{
|
||||
ISDN_FUNC_TRACE_ENTER(__FUNCTION__);
|
||||
ftdm_log(FTDM_LOG_INFO, "Received SSHL IND suId:%d suInstId:%d spInstId:%d\n", suId, suInstId, spInstId);
|
||||
ISDN_FUNC_TRACE_EXIT(__FUNCTION__);
|
||||
return;
|
||||
}
|
||||
|
||||
void sngisdn_rcv_sshl_cfm (int16_t suId, uint32_t suInstId, uint32_t spInstId, SsHlEvnt *ssHlEvnt, uint8_t action)
|
||||
{
|
||||
ISDN_FUNC_TRACE_ENTER(__FUNCTION__);
|
||||
ftdm_log(FTDM_LOG_INFO, "Received SSHL CFM suId:%d suInstId:%d spInstId:%d\n", suId, suInstId, spInstId);
|
||||
ISDN_FUNC_TRACE_EXIT(__FUNCTION__);
|
||||
return;
|
||||
}
|
||||
|
||||
void sngisdn_rcv_rmrt_ind (int16_t suId, uint32_t suInstId, uint32_t spInstId, RmRtEvnt *rmRtEvnt, uint8_t action)
|
||||
{
|
||||
ISDN_FUNC_TRACE_ENTER(__FUNCTION__);
|
||||
ftdm_log(FTDM_LOG_INFO, "Received RESUME/RETRIEVE ind suId:%d suInstId:%d spInstId:%d\n", suId, suInstId, spInstId);
|
||||
ISDN_FUNC_TRACE_EXIT(__FUNCTION__);
|
||||
return;
|
||||
}
|
||||
|
||||
void sngisdn_rcv_rmrt_cfm (int16_t suId, uint32_t suInstId, uint32_t spInstId, RmRtEvnt *rmRtEvnt, uint8_t action)
|
||||
{
|
||||
ISDN_FUNC_TRACE_ENTER(__FUNCTION__);
|
||||
ftdm_log(FTDM_LOG_INFO, "Received RESUME/RETRIEVE CFM suId:%d suInstId:%d spInstId:%d\n", suId, suInstId, spInstId);
|
||||
ISDN_FUNC_TRACE_EXIT(__FUNCTION__);
|
||||
return;
|
||||
}
|
||||
|
||||
void sngisdn_rcv_flc_ind (int16_t suId, uint32_t suInstId, uint32_t spInstId, StaEvnt *staEvnt)
|
||||
{
|
||||
ISDN_FUNC_TRACE_ENTER(__FUNCTION__);
|
||||
ftdm_log(FTDM_LOG_INFO, "Received FLOW CONTROL IND suId:%d suInstId:%d spInstId:%d\n", suId, suInstId, spInstId);
|
||||
ISDN_FUNC_TRACE_EXIT(__FUNCTION__);
|
||||
return;
|
||||
}
|
||||
|
||||
void sngisdn_rcv_fac_ind (int16_t suId, uint32_t suInstId, uint32_t spInstId, FacEvnt *facEvnt, uint8_t evntType, int16_t dChan, uint8_t ces)
|
||||
{
|
||||
ISDN_FUNC_TRACE_ENTER(__FUNCTION__);
|
||||
ftdm_log(FTDM_LOG_INFO, "Received FACILITY IND suId:%d suInstId:%d spInstId:%d\n", suId, suInstId, spInstId);
|
||||
ISDN_FUNC_TRACE_EXIT(__FUNCTION__);
|
||||
return;
|
||||
}
|
||||
|
||||
void sngisdn_rcv_sta_cfm ( int16_t suId, uint32_t suInstId, uint32_t spInstId, StaEvnt *staEvnt)
|
||||
{
|
||||
ISDN_FUNC_TRACE_ENTER(__FUNCTION__);
|
||||
ftdm_log(FTDM_LOG_DEBUG, "%s suId:%d suInstId:%d spInstId:%d\n", __FUNCTION__, suId, suInstId, spInstId);
|
||||
|
||||
sngisdn_chan_data_t *sngisdn_info ;
|
||||
ftdm_channel_t *ftdmchan = NULL;
|
||||
uint8_t call_state = 0;
|
||||
|
||||
if (staEvnt->callSte.eh.pres && staEvnt->callSte.callGlblSte.pres) {
|
||||
call_state = staEvnt->callSte.callGlblSte.val;
|
||||
}
|
||||
|
||||
/* get the ftdmchan and ss7_chan_data from the circuit */
|
||||
if (suInstId && (get_ftdmchan_by_suInstId(suId, suInstId, &sngisdn_info) == FTDM_SUCCESS)) {
|
||||
ftdmchan = sngisdn_info->ftdmchan;
|
||||
} else if (spInstId && (get_ftdmchan_by_spInstId(suId, spInstId, &sngisdn_info) == FTDM_SUCCESS)) {
|
||||
ftdmchan = sngisdn_info->ftdmchan;
|
||||
}
|
||||
|
||||
if (ftdmchan == NULL) {
|
||||
ftdm_log(FTDM_LOG_CRIT, "Failed to find matching channel suId:%d suInstId:%d spInstId:%d\n", suId, suInstId, spInstId);
|
||||
ISDN_FUNC_TRACE_EXIT(__FUNCTION__);
|
||||
return;
|
||||
}
|
||||
|
||||
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_INFO, "Received STATUS CONFIRM\n");
|
||||
/* now that we have the right channel...put a lock on it so no-one else can use it */
|
||||
ftdm_mutex_lock(ftdmchan->mutex);
|
||||
|
||||
/* check if there is a pending state change, give it a bit to clear */
|
||||
if (check_for_state_change(ftdmchan)) {
|
||||
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_CRIT, "Failed to wait for pending state change\n");
|
||||
ftdm_mutex_unlock(ftdmchan->mutex);
|
||||
ISDN_FUNC_TRACE_EXIT(__FUNCTION__);
|
||||
return;
|
||||
};
|
||||
|
||||
if (staEvnt->causeDgn[0].eh.pres && staEvnt->causeDgn[0].causeVal.pres) {
|
||||
if (staEvnt->causeDgn[0].causeVal.val != 30) {
|
||||
|
||||
if (staEvnt->callSte.eh.pres && staEvnt->callSte.callGlblSte.pres) {
|
||||
call_state = staEvnt->callSte.callGlblSte.val;
|
||||
/* Section 4.3.30 from INT Interface - Service Definition */
|
||||
ftdmchan->caller_data.hangup_cause = staEvnt->causeDgn[0].causeVal.val;
|
||||
|
||||
|
||||
/* There is incompatibility between local and remote side call states some Q931 msgs probably got lost - initiate disconnect */
|
||||
ftdm_log_chan(ftdmchan, FTDM_LOG_WARNING, "Incompatible call states detected, remote side indicated state:%d our state:%s cause:%d\n", call_state, ftdm_channel_state2str(ftdmchan->state), staEvnt->causeDgn[0].causeVal.val);
|
||||
|
||||
switch(call_state) {
|
||||
/* Sere ITU-T Q931 for definition of call states */
|
||||
case 0: /* Remote switch thinks there are no calls on this channel */
|
||||
switch (ftdmchan->state) {
|
||||
case FTDM_CHANNEL_STATE_COLLECT:
|
||||
case FTDM_CHANNEL_STATE_DIALING:
|
||||
sngisdn_set_flag(sngisdn_info, FLAG_REMOTE_ABORT);
|
||||
ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_TERMINATING);
|
||||
break;
|
||||
case FTDM_CHANNEL_STATE_TERMINATING:
|
||||
/* We are in the process of clearing local states,
|
||||
just make sure we will not send any messages to remote switch */
|
||||
sngisdn_set_flag(sngisdn_info, FLAG_REMOTE_ABORT);
|
||||
break;
|
||||
case FTDM_CHANNEL_STATE_HANGUP:
|
||||
/* This cannot happen, state_advance always sets
|
||||
ftdmchan to STATE_HANGUP_COMPLETE when in STATE_HANGUP
|
||||
and we called check_for_state_change earlier so something is very wrong here!!! */
|
||||
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_CRIT, "How can we we in FTDM_CHANNEL_STATE_HANGUP after checking for state change?\n");
|
||||
ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_RESTART);
|
||||
break;
|
||||
case FTDM_CHANNEL_STATE_HANGUP_COMPLETE:
|
||||
/* We were waiting for remote switch to send RELEASE COMPLETE
|
||||
but this will not happen, so just clear local state */
|
||||
ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_DOWN);
|
||||
break;
|
||||
case FTDM_CHANNEL_STATE_DOWN:
|
||||
/* If our local state is down as well, then there is nothing to do */
|
||||
break;
|
||||
default:
|
||||
ftdm_log_chan(ftdmchan, FTDM_LOG_CRIT, "Don't know how to handle incompatible state. remote call state:%d our state:%s\n", call_state, ftdm_channel_state2str(ftdmchan->state));
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 8: /* Remote switch is in "Connect Request state" */
|
||||
switch (ftdmchan->state) {
|
||||
case FTDM_CHANNEL_STATE_UP:
|
||||
/* This is ok. We sent a Connect, and we are waiting for a connect ack */
|
||||
/* Do nothing */
|
||||
break;
|
||||
case FTDM_CHANNEL_STATE_HANGUP_COMPLETE:
|
||||
/* We hung up locally, but remote switch doesn't know send disconnect again*/
|
||||
sngisdn_snd_disconnect(ftdmchan);
|
||||
break;
|
||||
default:
|
||||
ftdm_log_chan(ftdmchan, FTDM_LOG_CRIT, "Don't know how to handle incompatible state. remote call state:%d our state:%s\n", call_state, ftdm_channel_state2str(ftdmchan->state));
|
||||
break;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
ftdm_log_chan(ftdmchan, FTDM_LOG_CRIT, "Don't know how to handle incompatible state. remote call state:%d our state:%s\n", call_state, ftdm_channel_state2str(ftdmchan->state));
|
||||
ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_RESTART);
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
ftdmchan->caller_data.hangup_cause = staEvnt->causeDgn[0].causeVal.val;
|
||||
/* We could not extract the call state */
|
||||
ftdm_log_chan(ftdmchan, FTDM_LOG_CRIT, "Incompatible call states detected, but could not determine call (cause:%d)\n", ftdmchan->caller_data.hangup_cause);
|
||||
ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_RESTART);
|
||||
}
|
||||
|
||||
}
|
||||
/**************************************************************************/
|
||||
}
|
||||
|
||||
/* unlock the channel */
|
||||
ftdm_mutex_unlock(ftdmchan->mutex);
|
||||
|
||||
ISDN_FUNC_TRACE_EXIT(__FUNCTION__);
|
||||
return;
|
||||
}
|
||||
|
||||
void sngisdn_rcv_srv_ind ( int16_t suId, Srv *srvEvnt, int16_t dChan, uint8_t ces)
|
||||
{
|
||||
ISDN_FUNC_TRACE_ENTER(__FUNCTION__);
|
||||
ftdm_log(FTDM_LOG_INFO, "Received SERVICE IND suId:%d dChan:%d ces:%d\n", suId, dChan, ces);
|
||||
ISDN_FUNC_TRACE_EXIT(__FUNCTION__);
|
||||
return;
|
||||
}
|
||||
|
||||
void sngisdn_rcv_srv_cfm ( int16_t suId, Srv *srvEvnt, int16_t dChan, uint8_t ces)
|
||||
{
|
||||
ISDN_FUNC_TRACE_ENTER(__FUNCTION__);
|
||||
ftdm_log(FTDM_LOG_INFO, "Received SERVICE CFM suId:%d dChan:%d ces:%d\n", suId, dChan, ces);
|
||||
ISDN_FUNC_TRACE_EXIT(__FUNCTION__);
|
||||
return;
|
||||
}
|
||||
|
||||
void sngisdn_rcv_rst_ind (int16_t suId, Rst *rstEvnt, int16_t dChan, uint8_t ces, uint8_t evtType)
|
||||
{
|
||||
ISDN_FUNC_TRACE_ENTER(__FUNCTION__);
|
||||
ftdm_log(FTDM_LOG_INFO, "Received RESTART IND suId:%d dChan:%d ces:%d\n", suId, dChan, ces);
|
||||
ISDN_FUNC_TRACE_EXIT(__FUNCTION__);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void sngisdn_rcv_rst_cfm ( int16_t suId, Rst *rstEvnt, int16_t dChan, uint8_t ces, uint8_t evtType)
|
||||
{
|
||||
ISDN_FUNC_TRACE_ENTER(__FUNCTION__);
|
||||
ftdm_log(FTDM_LOG_INFO, "Received RESTART CFM suId:%d dChan:%d ces:%d\n", suId, dChan, ces);
|
||||
ISDN_FUNC_TRACE_EXIT(__FUNCTION__);
|
||||
return;
|
||||
}
|
||||
|
||||
void sngisdn_rcv_phy_ind(SuId suId, Reason reason)
|
||||
{
|
||||
ISDN_FUNC_TRACE_ENTER(__FUNCTION__);
|
||||
ftdm_log(FTDM_LOG_INFO, "[SNGISDN PHY] D-chan %d : %s\n", suId, DECODE_LL1_REASON(reason));
|
||||
ISDN_FUNC_TRACE_EXIT(__FUNCTION__);
|
||||
return;
|
||||
}
|
||||
|
||||
void sngisdn_rcv_q921_ind(BdMngmt *status)
|
||||
{
|
||||
ISDN_FUNC_TRACE_ENTER(__FUNCTION__);
|
||||
|
||||
unsigned j,k;
|
||||
ftdm_span_t *ftdmspan = NULL;
|
||||
|
||||
for(j=1;j<=g_sngisdn_data.num_dchan;j++) {
|
||||
for(k=1;k<=g_sngisdn_data.dchans[j].num_spans;k++) {
|
||||
if (g_sngisdn_data.dchans[j].spans[k]->link_id == status->t.usta.lnkNmb) {
|
||||
ftdmspan = (ftdm_span_t*)g_sngisdn_data.dchans[j].spans[k]->ftdm_span;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (ftdmspan == NULL) {
|
||||
ftdm_log(FTDM_LOG_CRIT, "Received q921 status on unconfigured span\n", status->t.usta.lnkNmb);
|
||||
#ifdef DEBUG_MODE
|
||||
FORCE_SEGFAULT
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
|
||||
switch (status->t.usta.alarm.category) {
|
||||
case (LCM_CATEGORY_INTERFACE):
|
||||
ftdm_log(FTDM_LOG_INFO, "[SNGISDN Q921] %s: %s: %s(%d): %s(%d)\n",
|
||||
ftdmspan->name,
|
||||
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);
|
||||
break;
|
||||
default:
|
||||
ftdm_log(FTDM_LOG_INFO, "[SNGISDN Q921] %s: %s: %s(%d): %s(%d)\n",
|
||||
ftdmspan->name,
|
||||
DECODE_LCM_CATEGORY(status->t.usta.alarm.category),
|
||||
DECODE_LLD_EVENT(status->t.usta.alarm.event), status->t.usta.alarm.event,
|
||||
DECODE_LLD_CAUSE(status->t.usta.alarm.cause), status->t.usta.alarm.cause);
|
||||
break;
|
||||
}
|
||||
|
||||
ISDN_FUNC_TRACE_EXIT(__FUNCTION__)
|
||||
return;
|
||||
}
|
||||
void sngisdn_rcv_q931_ind(InMngmt *status)
|
||||
{
|
||||
ISDN_FUNC_TRACE_ENTER(__FUNCTION__);
|
||||
|
||||
|
||||
|
||||
ftdm_span_t *ftdmspan = NULL;
|
||||
|
||||
if (status->t.usta.alarm.cause == 287) {
|
||||
get_memory_info();
|
||||
return;
|
||||
}
|
||||
|
||||
switch (status->t.usta.alarm.category) {
|
||||
case (LCM_CATEGORY_INTERFACE):
|
||||
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);
|
||||
|
||||
/* clean this up later */
|
||||
|
||||
switch (status->t.usta.alarm.event) {
|
||||
case LCM_EVENT_UP:
|
||||
case LCM_EVENT_DOWN:
|
||||
{
|
||||
unsigned j,k;
|
||||
for(j=1;j<=g_sngisdn_data.num_dchan;j++) {
|
||||
for(k=1;k<=g_sngisdn_data.dchans[j].num_spans;k++) {
|
||||
if (g_sngisdn_data.dchans[j].spans[k]->link_id == status->t.usta.suId) {
|
||||
ftdmspan = (ftdm_span_t*)g_sngisdn_data.dchans[j].spans[k]->ftdm_span;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (ftdmspan == NULL) {
|
||||
ftdm_log(FTDM_LOG_CRIT, "Received q931 LCM EVENT on unconfigured span (suId:%d)\n", status->t.usta.suId);
|
||||
return;
|
||||
}
|
||||
|
||||
sngisdn_set_span_sig_status(ftdmspan, (status->t.usta.alarm.event == LCM_EVENT_UP)?FTDM_SIG_STATE_UP:FTDM_SIG_STATE_DOWN);
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
ftdm_log(FTDM_LOG_DEBUG, "[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);
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
ISDN_FUNC_TRACE_EXIT(__FUNCTION__);
|
||||
return;
|
||||
}
|
||||
|
||||
void sngisdn_rcv_cc_ind(CcMngmt *status)
|
||||
{
|
||||
ISDN_FUNC_TRACE_ENTER(__FUNCTION__);
|
||||
ftdm_log(FTDM_LOG_INFO, "RECEIVED %s\n", __FUNCTION__);
|
||||
ISDN_FUNC_TRACE_EXIT(__FUNCTION__);
|
||||
return;
|
||||
}
|
||||
|
||||
#define Q931_TRC_EVENT(event) (event == TL3PKTTX)?"TX": \
|
||||
(event == TL3PKTRX)?"RX":"UNKNOWN"
|
||||
|
||||
void sngisdn_rcv_q931_trace(InMngmt *trc, Buffer *mBuf)
|
||||
{
|
||||
MsgLen mlen;
|
||||
MsgLen i;
|
||||
int16_t j;
|
||||
Buffer *tmp;
|
||||
Data *cptr;
|
||||
uint8_t data;
|
||||
uint8_t tdata[1000];
|
||||
char *data_str = ftdm_calloc(1,MAX_DECODE_STR_LEN); /* TODO Find a proper size */
|
||||
|
||||
ftdm_assert(mBuf != NULLP, "Received a Q931 trace with no buffer");
|
||||
mlen = ((SsMsgInfo*)(mBuf->b_rptr))->len;
|
||||
|
||||
if (mlen != 0) {
|
||||
tmp = mBuf->b_cont;
|
||||
cptr = tmp->b_rptr;
|
||||
data = *cptr++;
|
||||
i = 0;
|
||||
|
||||
for(j=0;j<mlen;j++) {
|
||||
tdata[j]= data;
|
||||
|
||||
if (cptr == tmp->b_wptr) {
|
||||
tmp = tmp->b_cont;
|
||||
if (tmp) cptr = tmp->b_rptr;
|
||||
}
|
||||
data = *cptr++;
|
||||
}
|
||||
|
||||
sngisdn_trace_q931(data_str, tdata, mlen);
|
||||
ftdm_log(FTDM_LOG_INFO, "[SNGISDN Q931] FRAME %s:%s\n", Q931_TRC_EVENT(trc->t.trc.evnt), data_str);
|
||||
}
|
||||
|
||||
ftdm_safe_free(data_str);
|
||||
/* We do not need to free mBuf in this case because stack does it */
|
||||
/* SPutMsg(mBuf); */
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
#define Q921_TRC_EVENT(event) (event == TL2FRMRX)?"RX": \
|
||||
(event == TL2FRMTX)?"TX": \
|
||||
(event == TL2TMR)?"TMR EXPIRED":"UNKNOWN"
|
||||
|
||||
void sngisdn_rcv_q921_trace(BdMngmt *trc, Buffer *mBuf)
|
||||
{
|
||||
MsgLen mlen;
|
||||
MsgLen i;
|
||||
int16_t j;
|
||||
Buffer *tmp;
|
||||
Data *cptr;
|
||||
uint8_t data;
|
||||
uint8_t tdata[16];
|
||||
char *data_str = ftdm_calloc(1,200); /* TODO Find a proper size */
|
||||
|
||||
|
||||
if (trc->t.trc.evnt == TL2TMR) {
|
||||
goto end_of_trace;
|
||||
}
|
||||
|
||||
ftdm_assert(mBuf != NULLP, "Received a Q921 trace with no buffer");
|
||||
mlen = ((SsMsgInfo*)(mBuf->b_rptr))->len;
|
||||
|
||||
if (mlen != 0) {
|
||||
tmp = mBuf->b_cont;
|
||||
cptr = tmp->b_rptr;
|
||||
data = *cptr++;
|
||||
i = 0;
|
||||
while (i < mlen) {
|
||||
j = 0;
|
||||
for(j=0;j<16;j++) {
|
||||
if (i<mlen) {
|
||||
tdata[j]= data;
|
||||
|
||||
if (cptr == tmp->b_wptr) {
|
||||
tmp = tmp->b_cont;
|
||||
if (tmp) cptr = tmp->b_rptr;
|
||||
}
|
||||
i++;
|
||||
if (i<mlen) data = *cptr++;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
sngisdn_trace_q921(data_str, tdata, mlen);
|
||||
ftdm_log(FTDM_LOG_INFO, "[SNGISDN Q921] FRAME %s:%s\n", Q921_TRC_EVENT(trc->t.trc.evnt), data_str);
|
||||
}
|
||||
end_of_trace:
|
||||
ftdm_safe_free(data_str);
|
||||
SPutMsg(mBuf);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void sngisdn_rcv_sng_log(uint8_t level, char *fmt,...)
|
||||
{
|
||||
char *data;
|
||||
int ret;
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, fmt);
|
||||
ret = ftdm_vasprintf(&data, fmt, ap);
|
||||
if (ret == -1) {
|
||||
return;
|
||||
}
|
||||
|
||||
switch (level) {
|
||||
case SNG_LOGLEVEL_DEBUG:
|
||||
ftdm_log(FTDM_LOG_DEBUG, "sng_isdn->%s", data);
|
||||
break;
|
||||
case SNG_LOGLEVEL_WARN:
|
||||
ftdm_log(FTDM_LOG_INFO, "sng_isdn->%s", data);
|
||||
break;
|
||||
case SNG_LOGLEVEL_INFO:
|
||||
ftdm_log(FTDM_LOG_INFO, "sng_isdn->%s", data);
|
||||
break;
|
||||
case SNG_LOGLEVEL_STATS:
|
||||
ftdm_log(FTDM_LOG_INFO, "sng_isdn->%s", data);
|
||||
break;
|
||||
case SNG_LOGLEVEL_ERROR:
|
||||
ftdm_log(FTDM_LOG_ERROR, "sng_isdn->%s", data);
|
||||
#ifdef DEBUG_MODE
|
||||
FORCE_SEGFAULT
|
||||
#endif
|
||||
break;
|
||||
case SNG_LOGLEVEL_CRIT:
|
||||
ftdm_log(FTDM_LOG_CRIT, "sng_isdn->%s", data);
|
||||
#ifdef DEBUG_MODE
|
||||
FORCE_SEGFAULT
|
||||
#endif
|
||||
break;
|
||||
default:
|
||||
ftdm_log(FTDM_LOG_INFO, "sng_isdn->%s", data);
|
||||
break;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/* For Emacs:
|
||||
* Local Variables:
|
||||
* mode:c
|
||||
* indent-tabs-mode:t
|
||||
* tab-width:4
|
||||
* c-basic-offset:4
|
||||
* End:
|
||||
* For VIM:
|
||||
* vim:set softtabstop=4 shiftwidth=4 tabstop=4:
|
||||
*/
|
||||
|
||||
/******************************************************************************/
|
|
@ -0,0 +1,433 @@
|
|||
/*
|
||||
* Copyright (c) 2010, Sangoma Technologies
|
||||
* David Yat Sin <davidy@sangoma.com>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* * Neither the name of the original author; nor the names of any contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
|
||||
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "ftmod_sangoma_isdn.h"
|
||||
|
||||
extern ftdm_status_t cpy_calling_num_to_sngisdn(CgPtyNmb *cgPtyNmb, ftdm_caller_data_t *ftdm);
|
||||
extern ftdm_status_t cpy_called_num_to_sngisdn(CdPtyNmb *cdPtyNmb, ftdm_caller_data_t *ftdm);
|
||||
extern ftdm_status_t cpy_calling_name_to_sngisdn(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);
|
||||
|
||||
|
||||
void sngisdn_snd_setup(ftdm_channel_t *ftdmchan)
|
||||
{
|
||||
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_log_chan_msg(ftdmchan, FTDM_LOG_INFO, "Sending SETUP\n");
|
||||
|
||||
sngisdn_info->suInstId = get_unique_suInstId(signal_data->cc_id);
|
||||
sngisdn_info->spInstId = 0;
|
||||
|
||||
memset(&conEvnt, 0, sizeof(conEvnt));
|
||||
|
||||
conEvnt.bearCap[0].eh.pres = PRSNT_NODEF;
|
||||
conEvnt.bearCap[0].infoTranCap.pres = PRSNT_NODEF;
|
||||
|
||||
conEvnt.bearCap[0].infoTranCap.val = IN_ITC_SPEECH;
|
||||
|
||||
conEvnt.bearCap[0].codeStand0.pres = PRSNT_NODEF;
|
||||
conEvnt.bearCap[0].codeStand0.val = IN_CSTD_CCITT;
|
||||
conEvnt.bearCap[0].infoTranRate0.pres = PRSNT_NODEF;
|
||||
conEvnt.bearCap[0].infoTranRate0.val = IN_ITR_64KBIT;
|
||||
conEvnt.bearCap[0].tranMode.pres = PRSNT_NODEF;
|
||||
conEvnt.bearCap[0].tranMode.val = IN_TM_CIRCUIT;
|
||||
|
||||
conEvnt.chanId.eh.pres = PRSNT_NODEF;
|
||||
conEvnt.chanId.prefExc.pres = PRSNT_NODEF;
|
||||
conEvnt.chanId.prefExc.val = IN_PE_EXCLSVE;
|
||||
conEvnt.chanId.dChanInd.pres = PRSNT_NODEF;
|
||||
conEvnt.chanId.dChanInd.val = IN_DSI_NOTDCHAN;
|
||||
conEvnt.chanId.intIdentPres.pres = PRSNT_NODEF;
|
||||
conEvnt.chanId.intIdentPres.val = IN_IIP_IMPLICIT;
|
||||
conEvnt.chanId.intIdent.pres = NOTPRSNT;
|
||||
|
||||
if (ftdmchan->span->trunk_type == FTDM_TRUNK_BRI ||
|
||||
ftdmchan->span->trunk_type == FTDM_TRUNK_BRI_PTMP) {
|
||||
/* Trillium stack rejests lyr1Ident on BRI, but Netbricks always sends it.
|
||||
Check with Trillium if this ever causes calls to fail in the field */
|
||||
|
||||
/* BRI only params */
|
||||
conEvnt.chanId.intType.pres = PRSNT_NODEF;
|
||||
conEvnt.chanId.intType.val = IN_IT_BASIC;
|
||||
conEvnt.chanId.infoChanSel.pres = PRSNT_NODEF;
|
||||
conEvnt.chanId.infoChanSel.val = ftdmchan->physical_chan_id;
|
||||
} else {
|
||||
/* PRI only params */
|
||||
if (signal_data->switchtype == SNGISDN_SWITCH_EUROISDN) {
|
||||
conEvnt.bearCap[0].usrInfoLyr1Prot.pres = PRSNT_NODEF;
|
||||
conEvnt.bearCap[0].usrInfoLyr1Prot.val = IN_UIL1_G711ULAW;
|
||||
} else {
|
||||
conEvnt.bearCap[0].usrInfoLyr1Prot.pres = PRSNT_NODEF;
|
||||
conEvnt.bearCap[0].usrInfoLyr1Prot.val = IN_UIL1_G711ALAW;
|
||||
}
|
||||
conEvnt.bearCap[0].lyr1Ident.pres = PRSNT_NODEF;
|
||||
conEvnt.bearCap[0].lyr1Ident.val = IN_L1_IDENT;
|
||||
|
||||
conEvnt.chanId.intType.pres = PRSNT_NODEF;
|
||||
conEvnt.chanId.intType.val = IN_IT_OTHER;
|
||||
conEvnt.chanId.chanMapType.pres = PRSNT_NODEF;
|
||||
conEvnt.chanId.chanMapType.val = IN_CMT_BCHAN;
|
||||
conEvnt.chanId.nmbMap.pres = PRSNT_NODEF;
|
||||
conEvnt.chanId.nmbMap.val = IN_NM_CHNNMB;
|
||||
conEvnt.chanId.codeStand1.pres = PRSNT_NODEF;
|
||||
conEvnt.chanId.codeStand1.val = IN_CSTD_CCITT;
|
||||
conEvnt.chanId.chanNmbSlotMap.pres = PRSNT_NODEF;
|
||||
conEvnt.chanId.chanNmbSlotMap.len = 1;
|
||||
conEvnt.chanId.chanNmbSlotMap.val[0] = ftdmchan->physical_chan_id;
|
||||
}
|
||||
|
||||
conEvnt.progInd.eh.pres = PRSNT_NODEF;
|
||||
conEvnt.progInd.location.pres = PRSNT_NODEF;
|
||||
conEvnt.progInd.location.val = IN_LOC_USER;
|
||||
conEvnt.progInd.codeStand0.pres = PRSNT_NODEF;
|
||||
conEvnt.progInd.codeStand0.val = IN_CSTD_CCITT;
|
||||
conEvnt.progInd.progDesc.pres = PRSNT_NODEF;
|
||||
conEvnt.progInd.progDesc.val = IN_PD_NOTETEISDN; /* Not end-to-end ISDN */
|
||||
|
||||
if (signal_data->switchtype == SNGISDN_SWITCH_EUROISDN) {
|
||||
conEvnt.sndCmplt.eh.pres = PRSNT_NODEF;
|
||||
}
|
||||
if (ftdmchan->span->trunk_type == FTDM_TRUNK_BRI_PTMP &&
|
||||
signal_data->signalling == SNGISDN_SIGNALING_NET) {
|
||||
sngisdn_info->ces = CES_MNGMNT;
|
||||
}
|
||||
|
||||
cpy_calling_num_to_sngisdn(&conEvnt.cgPtyNmb, &ftdmchan->caller_data);
|
||||
cpy_called_num_to_sngisdn(&conEvnt.cdPtyNmb, &ftdmchan->caller_data);
|
||||
cpy_calling_name_to_sngisdn(&conEvnt, ftdmchan);
|
||||
|
||||
ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Sending con request on suId:%d suInstId:%u spInstId:%u\n", signal_data->cc_id, sngisdn_info->suInstId, sngisdn_info->spInstId);
|
||||
|
||||
if (sng_isdn_con_request(signal_data->cc_id, sngisdn_info->suInstId, &conEvnt, signal_data->dchan_id, sngisdn_info->ces)) {
|
||||
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_CRIT, "stack refused SETUP request\n");
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/* Used only for BRI PTMP */
|
||||
void sngisdn_snd_con_complete(ftdm_channel_t *ftdmchan)
|
||||
{
|
||||
CnStEvnt cnStEvnt;
|
||||
|
||||
sngisdn_chan_data_t *sngisdn_info = (sngisdn_chan_data_t*) ftdmchan->call_data;
|
||||
sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*) ftdmchan->span->signal_data;
|
||||
|
||||
memset(&cnStEvnt, 0, sizeof(cnStEvnt));
|
||||
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_INFO, "Sending CONNECT ACK\n");
|
||||
|
||||
cnStEvnt.chanId.eh.pres = PRSNT_NODEF;
|
||||
cnStEvnt.chanId.prefExc.pres = PRSNT_NODEF;
|
||||
cnStEvnt.chanId.prefExc.val = IN_PE_EXCLSVE;
|
||||
cnStEvnt.chanId.dChanInd.pres = PRSNT_NODEF;
|
||||
cnStEvnt.chanId.dChanInd.val = IN_DSI_NOTDCHAN;
|
||||
cnStEvnt.chanId.intIdentPres.pres = PRSNT_NODEF;
|
||||
cnStEvnt.chanId.intIdentPres.val = IN_IIP_IMPLICIT;
|
||||
|
||||
if (ftdmchan->span->trunk_type == FTDM_TRUNK_BRI ||
|
||||
ftdmchan->span->trunk_type == FTDM_TRUNK_BRI_PTMP) {
|
||||
|
||||
/* BRI only params */
|
||||
cnStEvnt.chanId.intType.pres = PRSNT_NODEF;
|
||||
cnStEvnt.chanId.intType.val = IN_IT_BASIC;
|
||||
cnStEvnt.chanId.infoChanSel.pres = PRSNT_NODEF;
|
||||
cnStEvnt.chanId.infoChanSel.val = ftdmchan->physical_chan_id;
|
||||
} else {
|
||||
cnStEvnt.chanId.intType.pres = PRSNT_NODEF;
|
||||
cnStEvnt.chanId.intType.val = IN_IT_OTHER;
|
||||
cnStEvnt.chanId.infoChanSel.pres = PRSNT_NODEF;
|
||||
cnStEvnt.chanId.infoChanSel.val = IN_ICS_B1CHAN;
|
||||
cnStEvnt.chanId.chanMapType.pres = PRSNT_NODEF;
|
||||
cnStEvnt.chanId.chanMapType.val = IN_CMT_BCHAN;
|
||||
cnStEvnt.chanId.nmbMap.pres = PRSNT_NODEF;
|
||||
cnStEvnt.chanId.nmbMap.val = IN_NM_CHNNMB;
|
||||
cnStEvnt.chanId.codeStand1.pres = PRSNT_NODEF;
|
||||
cnStEvnt.chanId.codeStand1.val = IN_CSTD_CCITT;
|
||||
cnStEvnt.chanId.chanNmbSlotMap.pres = PRSNT_NODEF;
|
||||
cnStEvnt.chanId.chanNmbSlotMap.len = 1;
|
||||
cnStEvnt.chanId.chanNmbSlotMap.val[0] = ftdmchan->physical_chan_id;
|
||||
}
|
||||
|
||||
|
||||
ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Sending connect ACK on suId:%d suInstId:%u spInstId:%u ces:%d\n", signal_data->cc_id, sngisdn_info->suInstId, sngisdn_info->spInstId, 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)) {
|
||||
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_CRIT, "stack refused CONNECT ACK request\n");
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void sngisdn_snd_proceed(ftdm_channel_t *ftdmchan)
|
||||
{
|
||||
CnStEvnt cnStEvnt;
|
||||
|
||||
sngisdn_chan_data_t *sngisdn_info = (sngisdn_chan_data_t*) ftdmchan->call_data;
|
||||
sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*) ftdmchan->span->signal_data;
|
||||
|
||||
memset(&cnStEvnt, 0, sizeof(cnStEvnt));
|
||||
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_INFO, "Sending PROCEED\n");
|
||||
|
||||
cnStEvnt.chanId.eh.pres = PRSNT_NODEF;
|
||||
cnStEvnt.chanId.prefExc.pres = PRSNT_NODEF;
|
||||
cnStEvnt.chanId.prefExc.val = IN_PE_EXCLSVE;
|
||||
cnStEvnt.chanId.dChanInd.pres = PRSNT_NODEF;
|
||||
cnStEvnt.chanId.dChanInd.val = IN_DSI_NOTDCHAN;
|
||||
cnStEvnt.chanId.intIdentPres.pres = PRSNT_NODEF;
|
||||
cnStEvnt.chanId.intIdentPres.val = IN_IIP_IMPLICIT;
|
||||
|
||||
if (ftdmchan->span->trunk_type == FTDM_TRUNK_BRI ||
|
||||
ftdmchan->span->trunk_type == FTDM_TRUNK_BRI_PTMP) {
|
||||
|
||||
/* BRI only params */
|
||||
cnStEvnt.chanId.intType.pres = PRSNT_NODEF;
|
||||
cnStEvnt.chanId.intType.val = IN_IT_BASIC;
|
||||
cnStEvnt.chanId.infoChanSel.pres = PRSNT_NODEF;
|
||||
cnStEvnt.chanId.infoChanSel.val = ftdmchan->physical_chan_id;
|
||||
} else {
|
||||
cnStEvnt.chanId.intType.pres = PRSNT_NODEF;
|
||||
cnStEvnt.chanId.intType.val = IN_IT_OTHER;
|
||||
cnStEvnt.chanId.infoChanSel.pres = PRSNT_NODEF;
|
||||
cnStEvnt.chanId.infoChanSel.val = IN_ICS_B1CHAN;
|
||||
cnStEvnt.chanId.chanMapType.pres = PRSNT_NODEF;
|
||||
cnStEvnt.chanId.chanMapType.val = IN_CMT_BCHAN;
|
||||
cnStEvnt.chanId.nmbMap.pres = PRSNT_NODEF;
|
||||
cnStEvnt.chanId.nmbMap.val = IN_NM_CHNNMB;
|
||||
cnStEvnt.chanId.codeStand1.pres = PRSNT_NODEF;
|
||||
cnStEvnt.chanId.codeStand1.val = IN_CSTD_CCITT;
|
||||
cnStEvnt.chanId.chanNmbSlotMap.pres = PRSNT_NODEF;
|
||||
cnStEvnt.chanId.chanNmbSlotMap.len = 1;
|
||||
cnStEvnt.chanId.chanNmbSlotMap.val[0] = ftdmchan->physical_chan_id;
|
||||
}
|
||||
|
||||
|
||||
ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Sending con status on suId:%d suInstId:%u spInstId:%u\n", signal_data->cc_id, sngisdn_info->suInstId, sngisdn_info->spInstId);
|
||||
|
||||
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)) {
|
||||
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_CRIT, "stack refused PROCEED request\n");
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
void sngisdn_snd_progress(ftdm_channel_t *ftdmchan)
|
||||
{
|
||||
CnStEvnt cnStEvnt;
|
||||
|
||||
sngisdn_chan_data_t *sngisdn_info = (sngisdn_chan_data_t*) ftdmchan->call_data;
|
||||
sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*) ftdmchan->span->signal_data;
|
||||
|
||||
memset(&cnStEvnt, 0, sizeof(cnStEvnt));
|
||||
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_INFO, "Sending PROGRESS\n");
|
||||
|
||||
|
||||
cnStEvnt.progInd.eh.pres = PRSNT_NODEF;
|
||||
cnStEvnt.progInd.location.pres = PRSNT_NODEF;
|
||||
cnStEvnt.progInd.location.val = IN_LOC_USER;
|
||||
cnStEvnt.progInd.codeStand0.pres = PRSNT_NODEF;
|
||||
cnStEvnt.progInd.codeStand0.val = IN_CSTD_CCITT;
|
||||
cnStEvnt.progInd.progDesc.pres = PRSNT_NODEF;
|
||||
cnStEvnt.progInd.progDesc.val = IN_PD_NOTETEISDN;
|
||||
|
||||
ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Sending con status on suId:%d suInstId:%u spInstId:%u\n", signal_data->cc_id, sngisdn_info->suInstId, sngisdn_info->spInstId);
|
||||
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_msg(ftdmchan, FTDM_LOG_CRIT, "stack refused PROGRESS request\n");
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
void sngisdn_snd_alert(ftdm_channel_t *ftdmchan)
|
||||
{
|
||||
CnStEvnt cnStEvnt;
|
||||
|
||||
sngisdn_chan_data_t *sngisdn_info = (sngisdn_chan_data_t*) ftdmchan->call_data;
|
||||
sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*) ftdmchan->span->signal_data;
|
||||
|
||||
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_INFO, "Sending ALERT\n");
|
||||
|
||||
memset(&cnStEvnt, 0, sizeof(cnStEvnt));
|
||||
|
||||
cnStEvnt.progInd.eh.pres = PRSNT_NODEF;
|
||||
cnStEvnt.progInd.location.pres = PRSNT_NODEF;
|
||||
cnStEvnt.progInd.location.val = IN_LOC_USER;
|
||||
cnStEvnt.progInd.codeStand0.pres = PRSNT_NODEF;
|
||||
cnStEvnt.progInd.codeStand0.val = IN_CSTD_CCITT;
|
||||
cnStEvnt.progInd.progDesc.pres = PRSNT_NODEF;
|
||||
cnStEvnt.progInd.progDesc.val = IN_PD_NOTETEISDN;
|
||||
|
||||
ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Sending con status on suId:%d suInstId:%u spInstId:%u\n", signal_data->cc_id, sngisdn_info->suInstId, sngisdn_info->spInstId);
|
||||
|
||||
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)) {
|
||||
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_CRIT, "stack refused ALERT request\n");
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
void sngisdn_snd_connect(ftdm_channel_t *ftdmchan)
|
||||
{
|
||||
CnStEvnt cnStEvnt;
|
||||
|
||||
sngisdn_chan_data_t *sngisdn_info = (sngisdn_chan_data_t*) ftdmchan->call_data;
|
||||
sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*) ftdmchan->span->signal_data;
|
||||
|
||||
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_INFO, "Sending CONNECT\n");
|
||||
|
||||
memset(&cnStEvnt, 0, sizeof(cnStEvnt));
|
||||
|
||||
|
||||
cnStEvnt.chanId.eh.pres = PRSNT_NODEF;
|
||||
cnStEvnt.chanId.prefExc.pres = PRSNT_NODEF;
|
||||
cnStEvnt.chanId.prefExc.val = IN_PE_EXCLSVE;
|
||||
cnStEvnt.chanId.dChanInd.pres = PRSNT_NODEF;
|
||||
cnStEvnt.chanId.dChanInd.val = IN_DSI_NOTDCHAN;
|
||||
cnStEvnt.chanId.intIdentPres.pres = PRSNT_NODEF;
|
||||
cnStEvnt.chanId.intIdentPres.val = IN_IIP_IMPLICIT;
|
||||
|
||||
if (ftdmchan->span->trunk_type == FTDM_TRUNK_BRI ||
|
||||
ftdmchan->span->trunk_type == FTDM_TRUNK_BRI_PTMP) {
|
||||
|
||||
/* BRI only params */
|
||||
cnStEvnt.chanId.intType.pres = PRSNT_NODEF;
|
||||
cnStEvnt.chanId.intType.val = IN_IT_BASIC;
|
||||
cnStEvnt.chanId.infoChanSel.pres = PRSNT_NODEF;
|
||||
cnStEvnt.chanId.infoChanSel.val = ftdmchan->physical_chan_id;
|
||||
} else {
|
||||
cnStEvnt.chanId.intType.pres = PRSNT_NODEF;
|
||||
cnStEvnt.chanId.intType.val = IN_IT_OTHER;
|
||||
cnStEvnt.chanId.infoChanSel.pres = PRSNT_NODEF;
|
||||
cnStEvnt.chanId.infoChanSel.val = IN_ICS_B1CHAN;
|
||||
cnStEvnt.chanId.chanMapType.pres = PRSNT_NODEF;
|
||||
cnStEvnt.chanId.chanMapType.val = IN_CMT_BCHAN;
|
||||
cnStEvnt.chanId.nmbMap.pres = PRSNT_NODEF;
|
||||
cnStEvnt.chanId.nmbMap.val = IN_NM_CHNNMB;
|
||||
cnStEvnt.chanId.codeStand1.pres = PRSNT_NODEF;
|
||||
cnStEvnt.chanId.codeStand1.val = IN_CSTD_CCITT;
|
||||
cnStEvnt.chanId.chanNmbSlotMap.pres = PRSNT_NODEF;
|
||||
cnStEvnt.chanId.chanNmbSlotMap.len = 1;
|
||||
cnStEvnt.chanId.chanNmbSlotMap.val[0] = ftdmchan->physical_chan_id;
|
||||
}
|
||||
|
||||
ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Sending con response on suId:%d suInstId:%u spInstId:%u\n", signal_data->cc_id, sngisdn_info->suInstId, sngisdn_info->spInstId);
|
||||
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_msg(ftdmchan, FTDM_LOG_CRIT, "stack refused CONNECT request\n");
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
void sngisdn_snd_disconnect(ftdm_channel_t *ftdmchan)
|
||||
{
|
||||
DiscEvnt discEvnt;
|
||||
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_INFO, "Sending DISCONNECT\n");
|
||||
|
||||
sngisdn_chan_data_t *sngisdn_info = (sngisdn_chan_data_t*) ftdmchan->call_data;
|
||||
sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*) ftdmchan->span->signal_data;
|
||||
|
||||
memset(&discEvnt, 0, sizeof(discEvnt));
|
||||
|
||||
/* Fill discEvnt here */
|
||||
discEvnt.causeDgn[0].eh.pres = PRSNT_NODEF;
|
||||
discEvnt.causeDgn[0].location.pres = PRSNT_NODEF;
|
||||
discEvnt.causeDgn[0].location.val = IN_LOC_PRIVNETLU;
|
||||
discEvnt.causeDgn[0].codeStand3.pres = PRSNT_NODEF;
|
||||
discEvnt.causeDgn[0].codeStand3.val = IN_CSTD_CCITT;
|
||||
discEvnt.causeDgn[0].causeVal.pres = PRSNT_NODEF;
|
||||
discEvnt.causeDgn[0].causeVal.val = ftdmchan->caller_data.hangup_cause;
|
||||
discEvnt.causeDgn[0].recommend.pres = NOTPRSNT;
|
||||
discEvnt.causeDgn[0].dgnVal.pres = NOTPRSNT;
|
||||
|
||||
ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Sending disc request on suId:%d suInstId:%u spInstId:%u\n", signal_data->cc_id, sngisdn_info->suInstId, sngisdn_info->spInstId);
|
||||
if (sng_isdn_disc_request(signal_data->cc_id, sngisdn_info->suInstId, sngisdn_info->spInstId, &discEvnt)) {
|
||||
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_CRIT, "stack refused DISCONNECT request\n");
|
||||
}
|
||||
return;
|
||||
}
|
||||
void sngisdn_snd_release(ftdm_channel_t *ftdmchan)
|
||||
{
|
||||
RelEvnt relEvnt;
|
||||
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_INFO, "Sending RELEASE/RELEASE COMPLETE\n");
|
||||
|
||||
sngisdn_chan_data_t *sngisdn_info = (sngisdn_chan_data_t*) ftdmchan->call_data;
|
||||
sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*) ftdmchan->span->signal_data;
|
||||
|
||||
memset(&relEvnt, 0, sizeof(relEvnt));
|
||||
|
||||
/* Fill discEvnt here */
|
||||
relEvnt.causeDgn[0].eh.pres = PRSNT_NODEF;
|
||||
relEvnt.causeDgn[0].location.pres = PRSNT_NODEF;
|
||||
relEvnt.causeDgn[0].location.val = IN_LOC_PRIVNETLU;
|
||||
relEvnt.causeDgn[0].codeStand3.pres = PRSNT_NODEF;
|
||||
relEvnt.causeDgn[0].codeStand3.val = IN_CSTD_CCITT;
|
||||
|
||||
relEvnt.causeDgn[0].causeVal.pres = PRSNT_NODEF;
|
||||
relEvnt.causeDgn[0].causeVal.val = ftdmchan->caller_data.hangup_cause;
|
||||
relEvnt.causeDgn[0].recommend.pres = NOTPRSNT;
|
||||
relEvnt.causeDgn[0].dgnVal.pres = NOTPRSNT;
|
||||
|
||||
ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Sending release request on suId:%d suInstId:%u spInstId:%u\n", signal_data->cc_id, sngisdn_info->suInstId, sngisdn_info->spInstId);
|
||||
|
||||
if (sng_isdn_release_request(signal_data->cc_id, sngisdn_info->suInstId, sngisdn_info->spInstId, &relEvnt)) {
|
||||
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_CRIT, "stack refused RELEASE/RELEASE COMPLETE request\n");
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void sngisdn_snd_reset(ftdm_channel_t *ftdmchan)
|
||||
{
|
||||
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_INFO, "Sending RESET\n");
|
||||
ftdm_log_chan(ftdmchan, FTDM_LOG_CRIT, "%s not implemented\n", __FUNCTION__);
|
||||
/* TODO: implement me */
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* For Emacs:
|
||||
* Local Variables:
|
||||
* mode:c
|
||||
* indent-tabs-mode:t
|
||||
* tab-width:4
|
||||
* c-basic-offset:4
|
||||
* End:
|
||||
* For VIM:
|
||||
* vim:set softtabstop=4 shiftwidth=4 tabstop=4:
|
||||
*/
|
||||
|
||||
/******************************************************************************/
|
|
@ -0,0 +1,353 @@
|
|||
/*
|
||||
* Copyright (c) 2010, Sangoma Technologies
|
||||
* David Yat Sin <davidy@sangoma.com>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* * Neither the name of the original author; nor the names of any contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
|
||||
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "ftmod_sangoma_isdn.h"
|
||||
|
||||
ftdm_status_t cpy_calling_num_from_sngisdn(ftdm_caller_data_t *ftdm, CgPtyNmb *cgPtyNmb);
|
||||
ftdm_status_t cpy_called_num_from_sngisdn(ftdm_caller_data_t *ftdm, CdPtyNmb *cdPtyNmb);
|
||||
ftdm_status_t cpy_redir_num_from_sngisdn(ftdm_caller_data_t *ftdm, RedirNmb *redirNmb);
|
||||
ftdm_status_t cpy_calling_name_from_sngisdn(ftdm_caller_data_t *ftdm, ConEvnt *conEvnt);
|
||||
|
||||
ftdm_status_t cpy_calling_num_to_sngisdn(CgPtyNmb *cgPtyNmb, ftdm_caller_data_t *ftdm);
|
||||
ftdm_status_t cpy_called_num_to_sngisdn(CdPtyNmb *cdPtyNmb, ftdm_caller_data_t *ftdm);
|
||||
ftdm_status_t cpy_redir_num_to_sngisdn(RedirNmb *redirNmb, ftdm_caller_data_t *ftdm);
|
||||
ftdm_status_t cpy_calling_name_to_sngisdn(ConEvnt *conEvnt, ftdm_channel_t *ftdmchan);
|
||||
|
||||
extern ftdm_sngisdn_data_t g_sngisdn_data;
|
||||
void get_memory_info(void);
|
||||
|
||||
void clear_call_data(sngisdn_chan_data_t *sngisdn_info)
|
||||
{
|
||||
uint32_t cc_id = ((sngisdn_span_data_t*)sngisdn_info->ftdmchan->span->signal_data)->cc_id;
|
||||
|
||||
g_sngisdn_data.ccs[cc_id].active_spInstIds[sngisdn_info->spInstId]=NULL;
|
||||
g_sngisdn_data.ccs[cc_id].active_suInstIds[sngisdn_info->suInstId]=NULL;
|
||||
|
||||
sngisdn_info->suInstId = 0;
|
||||
sngisdn_info->spInstId = 0;
|
||||
sngisdn_info->globalFlg = 0;
|
||||
sngisdn_info->flags = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
uint32_t get_unique_suInstId(uint8_t cc_id)
|
||||
{
|
||||
uint32_t suInstId;
|
||||
ftdm_mutex_lock(g_sngisdn_data.ccs[cc_id].request_mutex);
|
||||
suInstId = g_sngisdn_data.ccs[cc_id].last_suInstId;
|
||||
|
||||
while(1) {
|
||||
if (++suInstId == MAX_INSTID) {
|
||||
suInstId = 1;
|
||||
}
|
||||
if (g_sngisdn_data.ccs[cc_id].active_suInstIds[suInstId] == NULL) {
|
||||
g_sngisdn_data.ccs[cc_id].last_suInstId = suInstId;
|
||||
ftdm_mutex_unlock(g_sngisdn_data.ccs[cc_id].request_mutex);
|
||||
return suInstId;
|
||||
}
|
||||
}
|
||||
/* Should never reach here */
|
||||
ftdm_mutex_unlock(g_sngisdn_data.ccs[cc_id].request_mutex);
|
||||
return 0;
|
||||
}
|
||||
|
||||
ftdm_status_t get_ftdmchan_by_suInstId(uint8_t cc_id, uint32_t suInstId, sngisdn_chan_data_t **sngisdn_data)
|
||||
{
|
||||
ftdm_assert_return(g_sngisdn_data.ccs[cc_id].activation_done, FTDM_FAIL, "Trying to find call on unconfigured CC\n");
|
||||
|
||||
if (g_sngisdn_data.ccs[cc_id].active_suInstIds[suInstId] == NULL) {
|
||||
return FTDM_FAIL;
|
||||
}
|
||||
*sngisdn_data = g_sngisdn_data.ccs[cc_id].active_suInstIds[suInstId];
|
||||
return FTDM_SUCCESS;
|
||||
}
|
||||
|
||||
ftdm_status_t get_ftdmchan_by_spInstId(uint8_t cc_id, uint32_t spInstId, sngisdn_chan_data_t **sngisdn_data)
|
||||
{
|
||||
ftdm_assert_return(g_sngisdn_data.ccs[cc_id].activation_done, FTDM_FAIL, "Trying to find call on unconfigured CC\n");
|
||||
|
||||
if (g_sngisdn_data.ccs[cc_id].active_spInstIds[spInstId] == NULL) {
|
||||
return FTDM_FAIL;
|
||||
}
|
||||
*sngisdn_data = g_sngisdn_data.ccs[cc_id].active_spInstIds[spInstId];
|
||||
return FTDM_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
ftdm_status_t cpy_calling_num_from_sngisdn(ftdm_caller_data_t *ftdm, CgPtyNmb *cgPtyNmb)
|
||||
{
|
||||
if (cgPtyNmb->eh.pres != PRSNT_NODEF) {
|
||||
return FTDM_FAIL;
|
||||
}
|
||||
|
||||
if (cgPtyNmb->screenInd.pres == PRSNT_NODEF) {
|
||||
ftdm->screen = cgPtyNmb->screenInd.val;
|
||||
}
|
||||
|
||||
if (cgPtyNmb->presInd0.pres == PRSNT_NODEF) {
|
||||
ftdm->pres = cgPtyNmb->presInd0.val;
|
||||
}
|
||||
|
||||
if (cgPtyNmb->nmbPlanId.pres == PRSNT_NODEF) {
|
||||
ftdm->cid_num.plan = cgPtyNmb->nmbPlanId.val;
|
||||
}
|
||||
if (cgPtyNmb->typeNmb1.pres == PRSNT_NODEF) {
|
||||
ftdm->cid_num.type = cgPtyNmb->typeNmb1.val;
|
||||
}
|
||||
|
||||
if (cgPtyNmb->nmbDigits.pres == PRSNT_NODEF) {
|
||||
ftdm_copy_string(ftdm->cid_num.digits, (const char*)cgPtyNmb->nmbDigits.val, cgPtyNmb->nmbDigits.len+1);
|
||||
}
|
||||
return FTDM_SUCCESS;
|
||||
}
|
||||
|
||||
ftdm_status_t cpy_called_num_from_sngisdn(ftdm_caller_data_t *ftdm, CdPtyNmb *cdPtyNmb)
|
||||
{
|
||||
if (cdPtyNmb->eh.pres != PRSNT_NODEF) {
|
||||
return FTDM_FAIL;
|
||||
}
|
||||
|
||||
if (cdPtyNmb->nmbPlanId.pres == PRSNT_NODEF) {
|
||||
ftdm->cid_num.plan = cdPtyNmb->nmbPlanId.val;
|
||||
}
|
||||
|
||||
if (cdPtyNmb->typeNmb0.pres == PRSNT_NODEF) {
|
||||
ftdm->cid_num.type = cdPtyNmb->typeNmb0.val;
|
||||
}
|
||||
|
||||
if (cdPtyNmb->nmbDigits.pres == PRSNT_NODEF) {
|
||||
ftdm_copy_string(ftdm->dnis.digits, (const char*)cdPtyNmb->nmbDigits.val, cdPtyNmb->nmbDigits.len+1);
|
||||
}
|
||||
return FTDM_SUCCESS;
|
||||
}
|
||||
|
||||
ftdm_status_t cpy_redir_num_from_sngisdn(ftdm_caller_data_t *ftdm, RedirNmb *redirNmb)
|
||||
{
|
||||
if (redirNmb->eh.pres != PRSNT_NODEF) {
|
||||
return FTDM_FAIL;
|
||||
}
|
||||
|
||||
if (redirNmb->nmbPlanId.pres == PRSNT_NODEF) {
|
||||
ftdm->rdnis.plan = redirNmb->nmbPlanId.val;
|
||||
}
|
||||
|
||||
if (redirNmb->typeNmb.pres == PRSNT_NODEF) {
|
||||
ftdm->rdnis.type = redirNmb->typeNmb.val;
|
||||
}
|
||||
|
||||
if (redirNmb->nmbDigits.pres == PRSNT_NODEF) {
|
||||
ftdm_copy_string(ftdm->rdnis.digits, (const char*)redirNmb->nmbDigits.val, redirNmb->nmbDigits.len+1);
|
||||
}
|
||||
return FTDM_SUCCESS;
|
||||
}
|
||||
|
||||
ftdm_status_t cpy_calling_name_from_sngisdn(ftdm_caller_data_t *ftdm, ConEvnt *conEvnt)
|
||||
{
|
||||
if (conEvnt->display.eh.pres && conEvnt->display.dispInfo.pres == PRSNT_NODEF) {
|
||||
ftdm_copy_string(ftdm->cid_name, (const char*)conEvnt->display.dispInfo.val, conEvnt->display.dispInfo.len+1);
|
||||
}
|
||||
|
||||
/* TODO check if caller name is contained in a Facility IE */
|
||||
return FTDM_SUCCESS;
|
||||
}
|
||||
|
||||
ftdm_status_t cpy_calling_num_to_sngisdn(CgPtyNmb *cgPtyNmb, ftdm_caller_data_t *ftdm)
|
||||
{
|
||||
uint8_t len = strlen(ftdm->cid_num.digits);
|
||||
if (!len) {
|
||||
return FTDM_SUCCESS;
|
||||
}
|
||||
cgPtyNmb->eh.pres = PRSNT_NODEF;
|
||||
|
||||
cgPtyNmb->screenInd.pres = PRSNT_NODEF;
|
||||
cgPtyNmb->screenInd.val = ftdm->screen;
|
||||
|
||||
cgPtyNmb->presInd0.pres = PRSNT_NODEF;
|
||||
cgPtyNmb->presInd0.val = ftdm->pres;
|
||||
|
||||
cgPtyNmb->nmbPlanId.pres = PRSNT_NODEF;
|
||||
cgPtyNmb->nmbPlanId.val = ftdm->cid_num.plan;
|
||||
|
||||
cgPtyNmb->typeNmb1.pres = PRSNT_NODEF;
|
||||
cgPtyNmb->typeNmb1.val = ftdm->cid_num.type;
|
||||
|
||||
cgPtyNmb->nmbDigits.pres = PRSNT_NODEF;
|
||||
cgPtyNmb->nmbDigits.len = len;
|
||||
|
||||
memcpy(cgPtyNmb->nmbDigits.val, ftdm->cid_num.digits, len);
|
||||
|
||||
return FTDM_SUCCESS;
|
||||
}
|
||||
|
||||
ftdm_status_t cpy_called_num_to_sngisdn(CdPtyNmb *cdPtyNmb, ftdm_caller_data_t *ftdm)
|
||||
{
|
||||
uint8_t len = strlen(ftdm->dnis.digits);
|
||||
if (!len) {
|
||||
return FTDM_SUCCESS;
|
||||
}
|
||||
cdPtyNmb->eh.pres = PRSNT_NODEF;
|
||||
|
||||
cdPtyNmb->nmbPlanId.pres = PRSNT_NODEF;
|
||||
cdPtyNmb->nmbPlanId.val = ftdm->dnis.plan;
|
||||
|
||||
cdPtyNmb->typeNmb0.pres = PRSNT_NODEF;
|
||||
cdPtyNmb->typeNmb0.val = ftdm->dnis.type;
|
||||
|
||||
cdPtyNmb->nmbDigits.pres = PRSNT_NODEF;
|
||||
cdPtyNmb->nmbDigits.len = len;
|
||||
|
||||
memcpy(cdPtyNmb->nmbDigits.val, ftdm->dnis.digits, len);
|
||||
return FTDM_SUCCESS;
|
||||
}
|
||||
|
||||
ftdm_status_t cpy_redir_num_to_sngisdn(RedirNmb *redirNmb, ftdm_caller_data_t *ftdm)
|
||||
{
|
||||
uint8_t len = strlen(ftdm->rdnis.digits);
|
||||
if (!len) {
|
||||
return FTDM_SUCCESS;
|
||||
}
|
||||
|
||||
redirNmb->eh.pres = PRSNT_NODEF;
|
||||
|
||||
redirNmb->nmbPlanId.pres = PRSNT_NODEF;
|
||||
redirNmb->nmbPlanId.val = ftdm->rdnis.plan;
|
||||
|
||||
redirNmb->typeNmb.pres = PRSNT_NODEF;
|
||||
redirNmb->typeNmb.val = ftdm->rdnis.type;
|
||||
|
||||
redirNmb->nmbDigits.pres = PRSNT_NODEF;
|
||||
redirNmb->nmbDigits.len = len;
|
||||
|
||||
memcpy(redirNmb->nmbDigits.val, ftdm->rdnis.digits, len);
|
||||
|
||||
return FTDM_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
ftdm_status_t cpy_calling_name_to_sngisdn(ConEvnt *conEvnt, ftdm_channel_t *ftdmchan)
|
||||
{
|
||||
uint8_t len;
|
||||
ftdm_caller_data_t *ftdm = &ftdmchan->caller_data;
|
||||
/* sngisdn_chan_data_t *sngisdn_info = ftdmchan->call_data; */
|
||||
sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*) ftdmchan->span->signal_data;
|
||||
|
||||
len = strlen(ftdm->cid_name);
|
||||
if (!len) {
|
||||
return FTDM_SUCCESS;
|
||||
}
|
||||
|
||||
if (ftdmchan->span->trunk_type == FTDM_TRUNK_BRI ||
|
||||
ftdmchan->span->trunk_type == FTDM_TRUNK_BRI_PTMP) {
|
||||
|
||||
conEvnt->usrUsr.eh.pres = PRSNT_NODEF;
|
||||
conEvnt->usrUsr.protocolDisc.pres = PRSNT_NODEF;
|
||||
conEvnt->usrUsr.protocolDisc.val = PD_IA5; /* IA5 chars */
|
||||
conEvnt->usrUsr.usrInfo.pres = PRSNT_NODEF;
|
||||
conEvnt->usrUsr.usrInfo.len = len;
|
||||
/* in sangoma_brid we used to send usr-usr info as <cid_name>!<calling_number>,
|
||||
change to previous style if current one does not work */
|
||||
memcpy(conEvnt->usrUsr.usrInfo.val, ftdm->cid_name, len);
|
||||
} else {
|
||||
switch (signal_data->switchtype) {
|
||||
case SNGISDN_SWITCH_NI2:
|
||||
/* TODO: Need to send the caller ID as a facility IE */
|
||||
|
||||
break;
|
||||
case SNGISDN_SWITCH_EUROISDN:
|
||||
if (signal_data->signalling != SNGISDN_SIGNALING_NET) {
|
||||
break;
|
||||
}
|
||||
/* follow through */
|
||||
case SNGISDN_SWITCH_5ESS:
|
||||
case SNGISDN_SWITCH_4ESS:
|
||||
case SNGISDN_SWITCH_DMS100:
|
||||
conEvnt->display.eh.pres = PRSNT_NODEF;
|
||||
conEvnt->display.dispInfo.pres = PRSNT_NODEF;
|
||||
conEvnt->display.dispInfo.len = len;
|
||||
memcpy(conEvnt->display.dispInfo.val, ftdm->cid_name, len);
|
||||
break;
|
||||
case SNGISDN_SWITCH_QSIG:
|
||||
/* It seems like QSIG does not support Caller ID Name */
|
||||
break;
|
||||
case SNGISDN_SWITCH_INSNET:
|
||||
/* Don't know how to transmit caller ID name on INSNET */
|
||||
break;
|
||||
}
|
||||
}
|
||||
return FTDM_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
|
||||
ftdm_status_t check_for_state_change(ftdm_channel_t *ftdmchan)
|
||||
{
|
||||
|
||||
#if 0
|
||||
ftdm_log_chan_msg(ftdmchan, "Checking for pending state change\n");
|
||||
#endif
|
||||
/* check to see if there are any pending state changes on the channel and give them a sec to happen*/
|
||||
ftdm_wait_for_flag_cleared(ftdmchan, FTDM_CHANNEL_STATE_CHANGE, 5000);
|
||||
|
||||
/* check the flag to confirm it is clear now */
|
||||
if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_STATE_CHANGE)) {
|
||||
/* the flag is still up...so we have a problem */
|
||||
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_ERROR, "FTDM_CHANNEL_STATE_CHANGE set for over 500ms\n");
|
||||
|
||||
/* move the state of the channel to RESTART to force a reset */
|
||||
ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_RESTART);
|
||||
|
||||
return FTDM_FAIL;
|
||||
}
|
||||
return FTDM_SUCCESS;
|
||||
}
|
||||
|
||||
void get_memory_info(void)
|
||||
{
|
||||
U32 availmen = 0;
|
||||
SRegInfoShow(S_REG, &availmen);
|
||||
return;
|
||||
}
|
||||
|
||||
/* For Emacs:
|
||||
* Local Variables:
|
||||
* mode:c
|
||||
* indent-tabs-mode:t
|
||||
* tab-width:4
|
||||
* c-basic-offset:4
|
||||
* End:
|
||||
* For VIM:
|
||||
* vim:set softtabstop=4 shiftwidth=4 tabstop=4:
|
||||
*/
|
||||
|
||||
/******************************************************************************/
|
|
@ -0,0 +1,661 @@
|
|||
/*
|
||||
* Copyright (c) 2010, Sangoma Technologies
|
||||
* David Yat Sin <davidy@sangoma.com>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* * Neither the name of the original author; nor the names of any contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
|
||||
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "ftmod_sangoma_isdn.h"
|
||||
#include "ftmod_sangoma_isdn_trace.h"
|
||||
|
||||
#define OCTET(x) (ieData[x-1] & 0xFF)
|
||||
|
||||
void print_hex_dump(char* str, uint32_t *str_len, uint8_t* data, uint32_t index_start, uint32_t index_end);
|
||||
void sngisdn_trace_q921(char* str, uint8_t* data, uint32_t data_len);
|
||||
void sngisdn_trace_q931(char* str, uint8_t* data, uint32_t data_len);
|
||||
uint32_t sngisdn_decode_ie(char *str, uint32_t *str_len, uint8_t current_codeset, uint8_t *data, uint16_t index_start);
|
||||
|
||||
uint8_t get_bits(uint8_t octet, uint8_t bitLo, uint8_t bitHi);
|
||||
char* get_code_2_str(int code, struct code2str *pCodeTable);
|
||||
|
||||
char* get_code_2_str(int code, struct code2str *pCodeTable)
|
||||
{
|
||||
struct code2str* pCode2txt;
|
||||
pCode2txt = pCodeTable;
|
||||
while(pCode2txt) {
|
||||
if(pCode2txt->code >= 0) {
|
||||
if (pCode2txt->code == code) {
|
||||
return pCode2txt->text;
|
||||
}
|
||||
pCode2txt++;
|
||||
} else {
|
||||
/* This is the default value from the table */
|
||||
return pCode2txt->text;
|
||||
}
|
||||
}
|
||||
return (char*)"unknown";
|
||||
}
|
||||
|
||||
|
||||
uint8_t get_bits(uint8_t octet, uint8_t bitLo, uint8_t bitHi)
|
||||
{
|
||||
if (!bitLo || !bitHi) {
|
||||
return 0;
|
||||
}
|
||||
if (bitLo > bitHi) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
bitLo--;
|
||||
bitHi--;
|
||||
|
||||
switch(bitHi - bitLo) {
|
||||
case 0:
|
||||
return (octet >> bitLo) & 0x01;
|
||||
case 1:
|
||||
return (octet >> bitLo) & 0x03;
|
||||
case 2:
|
||||
return (octet >> bitLo) & 0x07;
|
||||
case 3:
|
||||
return (octet >> bitLo) & 0x0F;
|
||||
case 4:
|
||||
return (octet >> bitLo) & 0x1F;
|
||||
case 5:
|
||||
return (octet >> bitLo) & 0x3F;
|
||||
case 6:
|
||||
return (octet >> bitLo) & 0x7F;
|
||||
case 7:
|
||||
return (octet >> bitLo) & 0xFF;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void sngisdn_trace_q921(char* str, uint8_t* data, uint32_t data_len)
|
||||
{
|
||||
int str_len;
|
||||
int i;
|
||||
uint8_t sapi, cr, ea, tei, ns, nr, pf, p, cmd;
|
||||
uint8_t frame_format = 0;
|
||||
|
||||
str_len = 0;
|
||||
|
||||
if(data_len >= 2) {
|
||||
switch ((int)data[2] & 0x03) {
|
||||
case 0: case 2:
|
||||
frame_format = I_FRAME;
|
||||
break;
|
||||
case 1:
|
||||
frame_format = S_FRAME;
|
||||
break;
|
||||
case 3:
|
||||
frame_format = U_FRAME;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
str_len+= sprintf(&str[str_len], " format: %s\n",
|
||||
get_code_2_str(frame_format, dcodQ921FrameFormatTable));
|
||||
|
||||
for(i=0; i < data_len; i++) {
|
||||
switch(i) {
|
||||
case 0: // Octet 2
|
||||
sapi = (uint8_t)((data[i]>>2) & 0x3F);
|
||||
cr = (uint8_t)((data[i]>>1) & 0x1);
|
||||
ea = (uint8_t)(data[i] & 0x1);
|
||||
str_len+= sprintf(&str[str_len], " sapi: %03d c/r: %01d ea: %01d\n", sapi, cr, ea);
|
||||
break;
|
||||
case 1:
|
||||
tei = (uint8_t)((data[i]>>1) & 0x7F);
|
||||
ea = (uint8_t)(data[i] & 0x1);
|
||||
str_len+= sprintf(&str[str_len], " tei: %03d ea: %01d\n", tei, ea);
|
||||
break;
|
||||
case 2:
|
||||
switch(frame_format) {
|
||||
case I_FRAME:
|
||||
ns = (uint8_t)((data[i]>>1) & 0x7F);
|
||||
nr = (uint8_t)((data[i+1]>>1) & 0x7F);
|
||||
p = (uint8_t)(data[i+1] & 0x01);
|
||||
str_len+= sprintf(&str[str_len], " n(s): %03d\n n(r): %03d p: %01d\n", ns, nr, p);
|
||||
break;
|
||||
case S_FRAME:
|
||||
nr = (uint8_t)((data[i+1]>>1) & 0x7F);
|
||||
pf = (uint8_t)(data[i+1] & 0x01);
|
||||
str_len+= sprintf(&str[str_len], " n(r): %03d p/f: %01d\n", nr, pf);
|
||||
|
||||
cmd = (uint8_t)((data[i]>>2) & 0x03);
|
||||
str_len+= sprintf(&str[str_len], " cmd: %s\n", get_code_2_str(cmd, dcodQ921SupervisoryCmdTable));
|
||||
|
||||
break;
|
||||
case U_FRAME:
|
||||
pf = (uint8_t)((data[i]>>4) & 0x01);
|
||||
str_len+= sprintf(&str[str_len], " p/f: %01d\n", pf);
|
||||
|
||||
cmd = (uint8_t)((data[i]>>2) & 0x03);
|
||||
cmd |= (uint8_t)((data[i]>>5) & 0x07);
|
||||
|
||||
str_len+= sprintf(&str[str_len], " cmd: %s\n", get_code_2_str(cmd, dcodQ921UnnumberedCmdTable));
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
void sngisdn_trace_q931(char* str, uint8_t* data, uint32_t data_len)
|
||||
{
|
||||
uint32_t str_len;
|
||||
uint8_t prot_disc, callRefFlag;
|
||||
uint16_t lenCallRef, c, i;
|
||||
uint8_t current_codeset = 0;
|
||||
|
||||
str_len = 0;
|
||||
|
||||
/* Decode Protocol Discrimator */
|
||||
prot_disc = (uint8_t)data[0];
|
||||
str_len += sprintf(&str[str_len], " Prot Disc:%s (0x%02x)\n", get_code_2_str(prot_disc, dcodQ931ProtDiscTable), prot_disc);
|
||||
|
||||
|
||||
|
||||
|
||||
/* Decode Call Reference */
|
||||
lenCallRef = (uint8_t) (data[1] & 0x0F);
|
||||
|
||||
str_len += sprintf(&str[str_len], " Call Ref:");
|
||||
c=2;
|
||||
callRefFlag = get_bits(data[c], 8,8);
|
||||
for(i=0; i<(2*lenCallRef);i++) {
|
||||
if(i==0) {
|
||||
str_len += sprintf(&str[str_len], "%s%s",
|
||||
get_code_2_str((uint8_t)(data[c] & 0x70), dcodQ931CallRefHiTable),
|
||||
get_code_2_str((uint8_t)(data[c] & 0x0F), dcodQ931CallRefLoTable));
|
||||
} else {
|
||||
str_len += sprintf(&str[str_len], "%s%s",
|
||||
get_code_2_str((uint8_t)(data[c] & 0xF0), dcodQ931CallRefHiTable),
|
||||
get_code_2_str((uint8_t)(data[c] & 0x0F), dcodQ931CallRefLoTable));
|
||||
}
|
||||
|
||||
i=i+1;
|
||||
c=c+1;
|
||||
}
|
||||
str_len += sprintf(&str[str_len], " (%s side)\n", callRefFlag?"Destination":"Origination");
|
||||
|
||||
/* Decode message type */
|
||||
str_len+= sprintf(&str[str_len], " Type:%s (0x%x)\n", get_code_2_str((int)(data[2+lenCallRef] & 0xFF), dcodQ931MsgTypeTable), (int)(data[2+lenCallRef] & 0xFF));
|
||||
|
||||
/* go through rest of data and look for important info */
|
||||
for(i=3+lenCallRef; i < data_len; i++) {
|
||||
switch (data[i] & 0xF8) {
|
||||
case Q931_LOCKING_SHIFT:
|
||||
current_codeset = (data[i] & 0x7);
|
||||
str_len+= sprintf(&str[str_len], "Codeset shift to %d (locking)\n", current_codeset);
|
||||
continue;
|
||||
case Q931_NON_LOCKING_SHIFT:
|
||||
current_codeset = (data[i] & 0x7);
|
||||
str_len+= sprintf(&str[str_len], "Codeset shift to %d (non-locking)\n", current_codeset);
|
||||
continue;
|
||||
}
|
||||
i+= sngisdn_decode_ie(str, &str_len, current_codeset, data, i);
|
||||
}
|
||||
print_hex_dump(str, &str_len, (uint8_t*) data, 0, data_len);
|
||||
return;
|
||||
}
|
||||
|
||||
uint32_t sngisdn_decode_ie(char *str, uint32_t *str_len, uint8_t current_codeset, uint8_t *data, uint16_t index_start)
|
||||
{
|
||||
unsigned char* ieData;
|
||||
uint8_t ieId;
|
||||
uint32_t len = 0;
|
||||
int index_end;
|
||||
|
||||
ieData = (unsigned char*) &data[index_start];
|
||||
|
||||
ieId = OCTET(1);
|
||||
len = OCTET(2);
|
||||
index_end = index_start+len+1;
|
||||
|
||||
*str_len += sprintf(&str[*str_len], " %s:", get_code_2_str(data[index_start], dcodQ931IEIDTable));
|
||||
switch(ieId) {
|
||||
case PROT_Q931_IE_BEARER_CAP:
|
||||
{
|
||||
uint8_t codingStandard, infTransferCap, transferMode, infTransferRate, usrL1Prot;
|
||||
|
||||
codingStandard = get_bits(OCTET(3),6,7);
|
||||
infTransferCap = get_bits(OCTET(3),1,5);
|
||||
transferMode = get_bits(OCTET(4),6,7);
|
||||
infTransferRate = get_bits(OCTET(4),1,5);
|
||||
usrL1Prot = get_bits(OCTET(5),1,5);
|
||||
|
||||
*str_len+= sprintf(&str[*str_len], "Coding:%s(%d) TransferCap:%s(%d) TransferRate:%s(%d) L1Prot:%s(%d)\n",
|
||||
get_code_2_str(codingStandard, dcodQ931BcCodingStandardTable), codingStandard,
|
||||
get_code_2_str(infTransferCap, dcodQ931BcInfTransferCapTable), infTransferCap,
|
||||
get_code_2_str(infTransferRate, dcodQ931BcInfTransferRateTable), infTransferRate,
|
||||
get_code_2_str(usrL1Prot, dcodQ931BcusrL1ProtTable), usrL1Prot);
|
||||
}
|
||||
break;
|
||||
case PROT_Q931_IE_CAUSE:
|
||||
{
|
||||
uint8_t codingStandard, location, cause,diagOct = 5;
|
||||
codingStandard = get_bits(OCTET(3),6,7);
|
||||
location = get_bits(OCTET(3),1,4);
|
||||
|
||||
cause = get_bits(OCTET(4),1,7);
|
||||
|
||||
*str_len+= sprintf(&str[*str_len], "coding:%s(%d) location:%s(%d) val:%s(%d)\n",
|
||||
get_code_2_str(codingStandard, dcodQ931BcCodingStandardTable), codingStandard,
|
||||
get_code_2_str(location,dcodQ931IelocationTable), location,
|
||||
get_code_2_str(cause, dcodQ931CauseCodeTable),
|
||||
cause);
|
||||
switch(cause) {
|
||||
case PROT_Q931_RELEASE_CAUSE_IE_NOT_EXIST:
|
||||
while(diagOct++ < len) {
|
||||
*str_len+= sprintf(&str[*str_len], " %d:IE %s(0x%02x)\n",
|
||||
diagOct,
|
||||
get_code_2_str(OCTET(diagOct), dcodQ931IEIDTable),
|
||||
OCTET(diagOct));
|
||||
}
|
||||
break;
|
||||
case PROT_Q931_RELEASE_CAUSE_WRONG_CALL_STATE:
|
||||
while(diagOct++ < len) {
|
||||
*str_len+= sprintf(&str[*str_len], " %d:Message %s(0x%02x)\n",
|
||||
diagOct,
|
||||
get_code_2_str(OCTET(diagOct), dcodQ931MsgTypeTable),
|
||||
OCTET(diagOct));
|
||||
}
|
||||
break;
|
||||
case PROT_Q931_RECOVERY_ON_TIMER_EXPIRE:
|
||||
*str_len+= sprintf(&str[*str_len], " Timer T\n");
|
||||
while(diagOct++ < len) {
|
||||
if(OCTET(diagOct) >= ' ' && OCTET(diagOct) < 0x7f) {
|
||||
*str_len+= sprintf(&str[*str_len], "%c", OCTET(diagOct));
|
||||
} else {
|
||||
*str_len+= sprintf(&str[*str_len], ".");
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
while(diagOct++ < len) {
|
||||
*str_len+= sprintf(&str[*str_len], " %d: 0x%02x\n",
|
||||
diagOct,
|
||||
OCTET(diagOct));
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case PROT_Q931_IE_CHANNEL_ID:
|
||||
{
|
||||
uint8_t infoChannelSelection=0;
|
||||
uint8_t prefExclusive=0;
|
||||
uint8_t ifaceIdPresent=0;
|
||||
uint8_t ifaceIdentifier = 0; /* octet_3_1 */
|
||||
uint8_t chanType=0, numberMap=0, codingStandard=0;
|
||||
uint8_t channelNo = 0;
|
||||
|
||||
infoChannelSelection = get_bits(OCTET(3),1,2);
|
||||
prefExclusive = get_bits(OCTET(3),4,4);
|
||||
ifaceIdPresent = get_bits(OCTET(3),7,7);
|
||||
|
||||
if (ifaceIdPresent) {
|
||||
ifaceIdentifier= get_bits(OCTET(4),1,7);
|
||||
chanType = get_bits(OCTET(5),1,4);
|
||||
numberMap = get_bits(OCTET(5),5,5);
|
||||
codingStandard = get_bits(OCTET(5),6,7);
|
||||
channelNo = get_bits(OCTET(6),1,7);
|
||||
} else {
|
||||
chanType = get_bits(OCTET(4),1,4);
|
||||
numberMap = get_bits(OCTET(4),5,5);
|
||||
codingStandard = get_bits(OCTET(4),6,7);
|
||||
channelNo = get_bits(OCTET(5),1,7);
|
||||
}
|
||||
|
||||
if (numberMap) {
|
||||
*str_len+= sprintf(&str[*str_len], " MAP\n");
|
||||
} else {
|
||||
*str_len+= sprintf(&str[*str_len], "No:%d ", channelNo);
|
||||
}
|
||||
|
||||
*str_len+= sprintf(&str[*str_len], "Type:%s(%d) %s ", get_code_2_str(chanType,dcodQ931ChanTypeTable), chanType, (numberMap)? "Map":"");
|
||||
*str_len+= sprintf(&str[*str_len], "%s/%s \n",
|
||||
(prefExclusive)? "Exclusive":"Preferred",
|
||||
(ifaceIdPresent)? "Explicit":"Implicit");
|
||||
}
|
||||
break;
|
||||
case PROT_Q931_IE_CALLING_PARTY_NUMBER:
|
||||
{
|
||||
uint8_t plan, type, screening = 0, presentation = 0, callingNumOct, j;
|
||||
uint8_t screeningEnabled = 0, presentationEnabled = 0;
|
||||
char callingNumDigits[32];
|
||||
memset(callingNumDigits, 0, sizeof(callingNumDigits));
|
||||
|
||||
plan = get_bits(OCTET(3),1,4);
|
||||
type = get_bits(OCTET(3),5,7);
|
||||
|
||||
if(!get_bits(OCTET(3),8,8)) {
|
||||
screening = get_bits(OCTET(4),1,2);
|
||||
presentation = get_bits(OCTET(4),6,7);
|
||||
screeningEnabled = 1;
|
||||
presentationEnabled = 1;
|
||||
callingNumOct = 4;
|
||||
} else {
|
||||
callingNumOct = 3;
|
||||
}
|
||||
if(len >= sizeof(callingNumDigits)) {
|
||||
len = sizeof(callingNumDigits)-1;
|
||||
}
|
||||
j = 0;
|
||||
while(callingNumOct++ <= len+1) {
|
||||
callingNumDigits[j++]=ia5[get_bits(OCTET(callingNumOct),1,4)][get_bits(OCTET(callingNumOct),5,8)];
|
||||
}
|
||||
callingNumDigits[j]='\0';
|
||||
*str_len+= sprintf(&str[*str_len], "%s(l:%d) plan:%s(%d) type:%s(%d)",
|
||||
|
||||
callingNumDigits, j,
|
||||
get_code_2_str(plan, dcodQ931NumberingPlanTable), plan,
|
||||
get_code_2_str(type, dcodQ931TypeofNumberTable), type);
|
||||
|
||||
if (presentationEnabled||screeningEnabled) {
|
||||
*str_len+= sprintf(&str[*str_len], "scr:%s(%d) pres:%s(%d)\n",
|
||||
get_code_2_str(screening, dcodQ931ScreeningTable), screening,
|
||||
get_code_2_str(presentation, dcodQ931PresentationTable), presentation);
|
||||
} else {
|
||||
*str_len+= sprintf(&str[*str_len], "\n");
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case PROT_Q931_IE_CALLED_PARTY_NUMBER:
|
||||
{
|
||||
uint8_t plan, type, calledNumOct,j;
|
||||
char calledNumDigits[32];
|
||||
memset(calledNumDigits, 0, sizeof(calledNumDigits));
|
||||
plan = get_bits(OCTET(3),1,4);
|
||||
type = get_bits(OCTET(3),5,7);
|
||||
|
||||
if(len >= sizeof(calledNumDigits)) {
|
||||
len = sizeof(calledNumDigits)-1;
|
||||
}
|
||||
calledNumOct = 3;
|
||||
j = 0;
|
||||
while(calledNumOct++ <= len+1) {
|
||||
calledNumDigits[j++]=ia5[get_bits(OCTET(calledNumOct),1,4)][get_bits(OCTET(calledNumOct),5,8)];
|
||||
}
|
||||
calledNumDigits[j]='\0';
|
||||
*str_len+= sprintf(&str[*str_len], "%s(l:%d) plan:%s(%d) type:%s(%d)\n",
|
||||
calledNumDigits, j,
|
||||
get_code_2_str(plan, dcodQ931NumberingPlanTable), plan,
|
||||
get_code_2_str(type, dcodQ931TypeofNumberTable), type);
|
||||
}
|
||||
break;
|
||||
case PROT_Q931_IE_REDIRECTING_NUMBER: //rdnis
|
||||
{
|
||||
uint8_t plan, type, screening = 0, presentation = 0, reason = 0, rdnisOct,j;
|
||||
uint8_t screeningEnabled = 0, presentationEnabled = 0, reasonEnabled = 0;
|
||||
char rdnis_string[32];
|
||||
memset(rdnis_string, 0, sizeof(rdnis_string));
|
||||
rdnisOct = 5;
|
||||
plan = get_bits(OCTET(3),1,4);
|
||||
type = get_bits(OCTET(3),5,7);
|
||||
|
||||
if(!get_bits(OCTET(3),8,8)) { //Oct 3a exists
|
||||
rdnisOct++;
|
||||
screening = get_bits(OCTET(4),1,2);
|
||||
presentation = get_bits(OCTET(4),6,7);
|
||||
screeningEnabled = 1;
|
||||
presentationEnabled = 1;
|
||||
if (!get_bits(OCTET(4),8,8)) { //Oct 3b exists
|
||||
rdnisOct++;
|
||||
reason = get_bits(OCTET(5),1,4);
|
||||
reasonEnabled = 1;
|
||||
}
|
||||
}
|
||||
|
||||
if(len >= sizeof(rdnis_string)) {
|
||||
len = sizeof(rdnis_string)-1;
|
||||
}
|
||||
|
||||
j = 0;
|
||||
while(rdnisOct++ <= len+1) {
|
||||
rdnis_string[j++]=ia5[get_bits(OCTET(rdnisOct),1,4)][get_bits(OCTET(rdnisOct),5,8)];
|
||||
}
|
||||
|
||||
rdnis_string[j]='\0';
|
||||
*str_len+= sprintf(&str[*str_len], "%s(l:%d) plan:%s(%d) type:%s(%d)",
|
||||
rdnis_string, j,
|
||||
get_code_2_str(plan, dcodQ931NumberingPlanTable), plan,
|
||||
get_code_2_str(type, dcodQ931TypeofNumberTable), type);
|
||||
|
||||
if(presentationEnabled || screeningEnabled) {
|
||||
*str_len+= sprintf(&str[*str_len], "scr:%s(%d) pres:%s(%d)",
|
||||
get_code_2_str(screening, dcodQ931ScreeningTable), screening,
|
||||
get_code_2_str(presentation, dcodQ931PresentationTable), presentation);
|
||||
}
|
||||
|
||||
if(reasonEnabled) {
|
||||
*str_len+= sprintf(&str[*str_len], "reason:%s(%d)",
|
||||
get_code_2_str(reason, dcodQ931ReasonTable), reason);
|
||||
}
|
||||
*str_len+= sprintf(&str[*str_len], "\n");
|
||||
}
|
||||
break;
|
||||
case PROT_Q931_IE_USER_USER:
|
||||
{
|
||||
uint8_t protDiscr = 0x00, j, uui_stringOct;
|
||||
char uui_string[32];
|
||||
memset(uui_string, 0, sizeof(uui_string));
|
||||
protDiscr = OCTET(3);
|
||||
uui_stringOct = 3;
|
||||
if (protDiscr != 0x04) { /* Non-IA5 */
|
||||
*str_len+= sprintf(&str[*str_len], "%s (0x%02x)\n",
|
||||
get_code_2_str(protDiscr, dcodQ931UuiProtDiscrTable), protDiscr);
|
||||
} else {
|
||||
j = 0;
|
||||
|
||||
if(len >= sizeof(uui_string)) {
|
||||
len = sizeof(uui_string)-1;
|
||||
}
|
||||
while(uui_stringOct++ <= len+1) {
|
||||
uui_string[j++]=ia5[get_bits(OCTET(uui_stringOct),1,4)][get_bits(OCTET(uui_stringOct),5,8)];
|
||||
}
|
||||
uui_string[j]='\0';
|
||||
*str_len+= sprintf(&str[*str_len], " %s (0x%02x) <%s>\n",
|
||||
get_code_2_str(protDiscr, dcodQ931UuiProtDiscrTable), protDiscr,
|
||||
uui_string);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case PROT_Q931_IE_DISPLAY:
|
||||
{
|
||||
uint8_t displayStrOct=2, j;
|
||||
char displayStr[82];
|
||||
memset(displayStr, 0, sizeof(displayStr));
|
||||
|
||||
if(get_bits(OCTET(3),8,8)) {
|
||||
displayStrOct++;
|
||||
}
|
||||
j = 0;
|
||||
if(len >= sizeof(displayStr)) {
|
||||
len = sizeof(displayStr)-1;
|
||||
}
|
||||
while(displayStrOct++ <= len+1) {
|
||||
displayStr[j++]=ia5[get_bits(OCTET(displayStrOct),1,4)][get_bits(OCTET(displayStrOct),5,8)];
|
||||
}
|
||||
displayStr[j]='\0';
|
||||
*str_len+= sprintf(&str[*str_len], "%s(l:%d)\n",
|
||||
displayStr, len);
|
||||
}
|
||||
break;
|
||||
case PROT_Q931_IE_RESTART_IND:
|
||||
{
|
||||
uint8_t indClass;
|
||||
indClass = get_bits(OCTET(3),1,3);
|
||||
*str_len+= sprintf(&str[*str_len], "class:%s(%d)\n",
|
||||
get_code_2_str(indClass,dcodQ931RestartIndClassTable), indClass);
|
||||
}
|
||||
break;
|
||||
case PROT_Q931_IE_PROGRESS_IND:
|
||||
{
|
||||
uint8_t codingStandard, location, progressDescr;
|
||||
codingStandard = get_bits(OCTET(3),6,7);
|
||||
location = get_bits(OCTET(3),1,4);
|
||||
progressDescr = get_bits(OCTET(4),1,7);
|
||||
*str_len+= sprintf(&str[*str_len], "coding:%s(%d) location:%s(%d) descr:%s(%d)\n",
|
||||
get_code_2_str(codingStandard,dcodQ931BcCodingStandardTable), codingStandard,
|
||||
get_code_2_str(location,dcodQ931IelocationTable), location,
|
||||
get_code_2_str(progressDescr,dcodQ931IeprogressDescrTable), progressDescr);
|
||||
}
|
||||
break;
|
||||
case PROT_Q931_IE_KEYPAD_FACILITY:
|
||||
{
|
||||
uint8_t keypadFacilityStrOct = 3, j;
|
||||
char keypadFacilityStr[82];
|
||||
memset(keypadFacilityStr, 0, sizeof(keypadFacilityStr));
|
||||
|
||||
j = 0;
|
||||
if(len >= sizeof(keypadFacilityStr)) {
|
||||
len = sizeof(keypadFacilityStr)-1;
|
||||
}
|
||||
while(keypadFacilityStrOct++ < len+1) {
|
||||
keypadFacilityStr[j++]=ia5[get_bits(OCTET(keypadFacilityStrOct),1,4)][get_bits(OCTET(keypadFacilityStrOct),5,8)];
|
||||
}
|
||||
keypadFacilityStr[j]='\0';
|
||||
*str_len+= sprintf(&str[*str_len], " digits:%s(l:%d)\n",
|
||||
keypadFacilityStr, len);
|
||||
}
|
||||
break;
|
||||
case PROT_Q931_IE_FACILITY:
|
||||
{
|
||||
uint8_t protProfile;
|
||||
protProfile = get_bits(OCTET(3),1,5);
|
||||
*str_len+= sprintf(&str[*str_len], "Prot profile:%s(%d)\n",
|
||||
get_code_2_str(protProfile,dcodQ931IeFacilityProtProfileTable), protProfile);
|
||||
}
|
||||
break;
|
||||
case PROT_Q931_IE_GENERIC_DIGITS:
|
||||
{
|
||||
uint8_t encoding,type;
|
||||
int value = 0;
|
||||
|
||||
encoding = get_bits(OCTET(3),6,8);
|
||||
type = get_bits(OCTET(3),1,5);
|
||||
|
||||
*str_len+= sprintf(&str[*str_len], "encoding:%s(%d) type:%s(%d) ",
|
||||
get_code_2_str(encoding,dcodQ931GenDigitsEncodingTable), encoding,
|
||||
get_code_2_str(encoding,dcodQ931GenDigitsTypeTable), type);
|
||||
|
||||
if (len > 1) {
|
||||
uint32_t j=0;
|
||||
|
||||
while(++j < len) {
|
||||
switch(encoding) {
|
||||
case 0: /* BCD even */
|
||||
case 1: /* BCD odd */
|
||||
{
|
||||
uint8_t byte = OCTET(j+3);
|
||||
value = (get_bits(byte,1,4)*10) + get_bits(byte,5,8) + (value*10);
|
||||
}
|
||||
break;
|
||||
case 2: /* IA 5 */
|
||||
value = value*10 + OCTET(j+3)-'0';
|
||||
*str_len+= sprintf(&str[*str_len], "%c", OCTET(j+3));
|
||||
break;
|
||||
case 3:
|
||||
/* Don't know how to decode binary encoding yet */
|
||||
*str_len+= sprintf(&str[*str_len], "Binary encoded");
|
||||
break;
|
||||
}
|
||||
}
|
||||
*str_len+= sprintf(&str[*str_len], " ");
|
||||
switch(type) {
|
||||
case 4: /* info digits */
|
||||
*str_len+= sprintf(&str[*str_len], "ani2:%s(%d)", get_code_2_str(value,dcodQ931LineInfoTable), value);
|
||||
break;
|
||||
case 5: /* Callid */
|
||||
*str_len+= sprintf(&str[*str_len], "Caller ID not implemented\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
*str_len+= sprintf(&str[*str_len], "\n");
|
||||
print_hex_dump(str, str_len, (uint8_t*) data, index_start, index_end);
|
||||
}
|
||||
break;
|
||||
case PROT_Q931_IE_SENDING_COMPLETE:
|
||||
/* No need to decode sending complete IE, as no additional info is available except that sending is done */
|
||||
break;
|
||||
case PROT_Q931_IE_CALLED_PARTY_SUBADDRESS:
|
||||
case PROT_Q931_IE_REDIRECTION_NUMBER:
|
||||
case PROT_Q931_IE_NOTIFICATION_IND:
|
||||
case PROT_Q931_IE_DATE_TIME:
|
||||
case PROT_Q931_IE_INFORMATION_REQUEST:
|
||||
case PROT_Q931_IE_SIGNAL:
|
||||
case PROT_Q931_IE_SWITCHOOK:
|
||||
case PROT_Q931_IE_FEATURE_ACT:
|
||||
case PROT_Q931_IE_FEATURE_IND:
|
||||
case PROT_Q931_IE_INFORMATION_RATE:
|
||||
case PROT_Q931_IE_END_TO_END_TRANSIT_DELAY:
|
||||
case PROT_Q931_IE_TRANSIT_DELAY_SELECT_IND:
|
||||
case PROT_Q931_IE_PACKET_LAYER_BINARY_PARAMS:
|
||||
case PROT_Q931_IE_PACKET_LAYER_WINDOW_SIZE:
|
||||
case PROT_Q931_IE_PACKET_LAYER_SIZE:
|
||||
case PROT_Q931_IE_TRANSIT_NETWORK_SELECTION:
|
||||
case PROT_Q931_IE_LOW_LAYER_COMPAT:
|
||||
case PROT_Q931_IE_HIGH_LAYER_COMPAT:
|
||||
case PROT_Q931_IE_ESCAPE_FOR_EXTENSION:
|
||||
case PROT_Q931_IE_CALL_IDENTITY:
|
||||
case PROT_Q931_IE_CALL_STATE:
|
||||
case PROT_Q931_IE_SEGMENTED_MESSAGE:
|
||||
case PROT_Q931_IE_NETWORK_SPF_FACILITY:
|
||||
case PROT_Q931_IE_CALLING_PARTY_SUBADDRESS:
|
||||
default:
|
||||
{
|
||||
*str_len += sprintf(&str[*str_len], "Undecoded");
|
||||
print_hex_dump((char*)str, str_len, data, index_start, index_end);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return len+1;
|
||||
}
|
||||
|
||||
void print_hex_dump(char* str, uint32_t *str_len, uint8_t* data, uint32_t index_start, uint32_t index_end)
|
||||
{
|
||||
int k;
|
||||
*str_len += sprintf(&str[*str_len], " [ ");
|
||||
for(k=index_start; k <= index_end; k++) {
|
||||
if (k && !(k%32)) {
|
||||
*str_len += sprintf(&str[*str_len], "\n ");
|
||||
}
|
||||
*str_len += sprintf(&str[*str_len], "%02x ", data[k]);
|
||||
}
|
||||
*str_len += sprintf(&str[*str_len], "]\n");
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,540 @@
|
|||
/*
|
||||
* Copyright (c) 2010, Sangoma Technologies
|
||||
* David Yat Sin <davidy@sangoma.com>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* * Neither the name of the original author; nor the names of any contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
|
||||
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#ifndef __FTMOD_SANGOMA_ISDN_TRACE_H__
|
||||
#define __FTMOD_SANGOMA_ISDN_TRACE_H__
|
||||
|
||||
#define MX_CODE_TXT_LEN 70
|
||||
#define Q931_LOCKING_SHIFT 0x90
|
||||
#define Q931_NON_LOCKING_SHIFT 0x98
|
||||
|
||||
#define PROT_Q931_RELEASE_CAUSE_MISDIALED_TRUNK_PREFIX 5
|
||||
#define PROT_Q931_RELEASE_CAUSE_INVALID_NUMBER_FORMAT 28
|
||||
#define PROT_Q931_RELEASE_CAUSE_NO_CHAN_AVAIL 34
|
||||
#define PROT_Q931_RELEASE_CAUSE_DEST_OUT_OF_ORDER 27
|
||||
#define PROT_Q931_RELEASE_CAUSE_IE_NOT_EXIST 99
|
||||
#define PROT_Q931_RECOVERY_ON_TIMER_EXPIRE 102
|
||||
#define PROT_Q931_RELEASE_CAUSE_WRONG_CALL_STATE 101
|
||||
|
||||
|
||||
#define PROT_Q931_IE_SEGMENTED_MESSAGE 0x00
|
||||
#define PROT_Q931_IE_BEARER_CAP 0x04
|
||||
#define PROT_Q931_IE_CAUSE 0x08
|
||||
#define PROT_Q931_IE_CALL_IDENTITY 0x10
|
||||
#define PROT_Q931_IE_CALL_STATE 0x14
|
||||
#define PROT_Q931_IE_CHANNEL_ID 0x18
|
||||
#define PROT_Q931_IE_FACILITY 0x1c
|
||||
#define PROT_Q931_IE_PROGRESS_IND 0x1e
|
||||
#define PROT_Q931_IE_NETWORK_SPF_FACILITY 0x20
|
||||
#define PROT_Q931_IE_NOTIFICATION_IND 0x27
|
||||
#define PROT_Q931_IE_DISPLAY 0x28
|
||||
#define PROT_Q931_IE_DATE_TIME 0x29
|
||||
#define PROT_Q931_IE_KEYPAD_FACILITY 0x2c
|
||||
#define PROT_Q931_IE_INFORMATION_REQUEST 0x32
|
||||
#define PROT_Q931_IE_SIGNAL 0x34
|
||||
#define PROT_Q931_IE_SWITCHOOK 0x36
|
||||
#define PROT_Q931_IE_GENERIC_DIGITS 0x37
|
||||
#define PROT_Q931_IE_FEATURE_ACT 0x38
|
||||
#define PROT_Q931_IE_FEATURE_IND 0x39
|
||||
#define PROT_Q931_IE_INFORMATION_RATE 0x40
|
||||
#define PROT_Q931_IE_END_TO_END_TRANSIT_DELAY 0x42
|
||||
#define PROT_Q931_IE_TRANSIT_DELAY_SELECT_IND 0x43
|
||||
#define PROT_Q931_IE_PACKET_LAYER_BINARY_PARAMS 0x44
|
||||
#define PROT_Q931_IE_PACKET_LAYER_WINDOW_SIZE 0x45
|
||||
#define PROT_Q931_IE_PACKET_LAYER_SIZE 0x46
|
||||
#define PROT_Q931_IE_CALLING_PARTY_NUMBER 0x6c
|
||||
#define PROT_Q931_IE_CALLING_PARTY_SUBADDRESS 0x6d
|
||||
#define PROT_Q931_IE_CALLED_PARTY_NUMBER 0x70
|
||||
#define PROT_Q931_IE_CALLED_PARTY_SUBADDRESS 0x71
|
||||
#define PROT_Q931_IE_REDIRECTING_NUMBER 0x74
|
||||
#define PROT_Q931_IE_REDIRECTION_NUMBER 0x76
|
||||
#define PROT_Q931_IE_TRANSIT_NETWORK_SELECTION 0x78
|
||||
#define PROT_Q931_IE_RESTART_IND 0x79
|
||||
#define PROT_Q931_IE_LOW_LAYER_COMPAT 0x7c
|
||||
#define PROT_Q931_IE_HIGH_LAYER_COMPAT 0x7d
|
||||
#define PROT_Q931_IE_USER_USER 0x7e
|
||||
#define PROT_Q931_IE_SENDING_COMPLETE 0xa1
|
||||
#define PROT_Q931_IE_ESCAPE_FOR_EXTENSION 0x7f
|
||||
#define PROT_Q931_IE_SENDING_COMPLETE 0xa1
|
||||
|
||||
#define NULL_CHAR 0
|
||||
|
||||
|
||||
struct code2str
|
||||
{
|
||||
int code;
|
||||
char text[MX_CODE_TXT_LEN];
|
||||
};
|
||||
|
||||
enum {
|
||||
I_FRAME = 1, /* Information frame */
|
||||
S_FRAME, /* Supervisory frame */
|
||||
U_FRAME, /* Unnumbered frame */
|
||||
};
|
||||
|
||||
char ia5[16][8]={{NULL_CHAR,NULL_CHAR,' ','0','@','P','`','p'},
|
||||
{NULL_CHAR,NULL_CHAR,'!','1','A','Q','a','q'},
|
||||
{NULL_CHAR,NULL_CHAR,'"','2','B','R','b','r'},
|
||||
{NULL_CHAR,NULL_CHAR,'#','3','C','S','c','s'},
|
||||
{NULL_CHAR,NULL_CHAR,'$','4','D','T','d','t'},
|
||||
{NULL_CHAR,NULL_CHAR,'%','5','E','U','e','u'},
|
||||
{NULL_CHAR,NULL_CHAR,'&','6','F','V','f','v'},
|
||||
{NULL_CHAR,NULL_CHAR,'\'','7','G','W','g','w'},
|
||||
{NULL_CHAR,NULL_CHAR,'(','8','H','X','h','x'},
|
||||
{NULL_CHAR,NULL_CHAR,')','9','I','Y','i','y'},
|
||||
{NULL_CHAR,NULL_CHAR,'*',':','J','Z','j','z'},
|
||||
{NULL_CHAR,NULL_CHAR,'+',';','K','[','k','{'},
|
||||
{NULL_CHAR,NULL_CHAR,',','<','L','\\','l','|'},
|
||||
{NULL_CHAR,NULL_CHAR,'-','=','M',']','m','}'},
|
||||
{NULL_CHAR,NULL_CHAR,'.','>','N','^','n','~'},
|
||||
{NULL_CHAR,NULL_CHAR,'/','?','O','_','o',NULL_CHAR}};
|
||||
|
||||
/* Based on Table 4 - pg 15 of Q.921 Recommendation */
|
||||
struct code2str dcodQ921FrameFormatTable[] = {
|
||||
{I_FRAME, "Information"},
|
||||
{S_FRAME, "Supervisory"},
|
||||
{U_FRAME, "Unnumbered"},
|
||||
{-1, "?"},
|
||||
};
|
||||
|
||||
|
||||
/* Based on Table 5 - pg 15 of Q.921 Recommendation */
|
||||
struct code2str dcodQ921SupervisoryCmdTable[] = {
|
||||
{0, "RR - receive ready"},
|
||||
{1, "RNR - receive not ready"},
|
||||
{2, "REJ - reject"},
|
||||
{-1, "Unknown"},
|
||||
};
|
||||
|
||||
/* Based on Table 5 - pg 15 of Q.921 Recommendation */
|
||||
struct code2str dcodQ921UnnumberedCmdTable[] = {
|
||||
{0x0F, "SABME - set async balanced mode extended"},
|
||||
{0x03, "DM - disconnected mode"},
|
||||
{0x00, "UI - unnumbered information"},
|
||||
{0x08, "DISC - disconnect"},
|
||||
{0x0C, "UA - unnumbered acknowledgement"},
|
||||
{0x11, "FRMR - frame reject"},
|
||||
{0x17, "XID - Exchange Identification)"},
|
||||
{-1, "Unknown"},
|
||||
};
|
||||
|
||||
struct code2str dcodQ931ProtDiscTable[] = {
|
||||
{0x08, "Q.931/I.451"},
|
||||
{0x09, "Q.2931"},
|
||||
{-1, "Unknown"},
|
||||
};
|
||||
|
||||
struct code2str dcodQ931CallRefHiTable[] = {
|
||||
{0, "0"},
|
||||
{16, "1"},
|
||||
{32, "2"},
|
||||
{48, "3"},
|
||||
{64, "4"},
|
||||
{80, "5"},
|
||||
{96, "6"},
|
||||
{112, "7"},
|
||||
{128, "8"},
|
||||
{144, "9"},
|
||||
{160, "A"},
|
||||
{176, "B"},
|
||||
{192, "C"},
|
||||
{208, "D"},
|
||||
{224, "E"},
|
||||
{240, "F"},
|
||||
{-1,"?"},
|
||||
};
|
||||
|
||||
struct code2str dcodQ931CallRefLoTable[] = {
|
||||
{0, "0"},
|
||||
{1, "1"},
|
||||
{2, "2"},
|
||||
{3, "3"},
|
||||
{4, "4"},
|
||||
{5, "5"},
|
||||
{6, "6"},
|
||||
{7, "7"},
|
||||
{8, "8"},
|
||||
{9, "9"},
|
||||
{10, "A"},
|
||||
{11, "B"},
|
||||
{12, "C"},
|
||||
{13, "D"},
|
||||
{14, "E"},
|
||||
{15, "F"},
|
||||
{-1,"?"},
|
||||
};
|
||||
|
||||
struct code2str dcodQ931MsgTypeTable[] = {
|
||||
{1, "Alerting"},
|
||||
{2, "Call Proceeding"},
|
||||
{3, "Progress"},
|
||||
{5, "Setup"},
|
||||
{7, "Connect"},
|
||||
{13, "Setup Ack"},
|
||||
{15, "Connect Ack"},
|
||||
{32, "User Info"},
|
||||
{33, "Suspend Rej"},
|
||||
{34, "Resume Rej"},
|
||||
{37, "Suspend"},
|
||||
{38, "Resume"},
|
||||
{45, "Suspend Ack"},
|
||||
{46, "Resume Ack"},
|
||||
{69, "Disconnect"},
|
||||
{70, "Restart"},
|
||||
{77, "Release"},
|
||||
{78, "Release Ack"},
|
||||
{90, "Release Compl"},
|
||||
{96, "Segment"},
|
||||
{98, "Facility"},
|
||||
{110, "Notify"},
|
||||
{117, "Status Enquiry"},
|
||||
{121, "Congest Cntrl"},
|
||||
{123, "Information"},
|
||||
{125, "Status"},
|
||||
{-1, "Unknown"},
|
||||
};
|
||||
|
||||
struct code2str dcodQ931CauseCodeTable[] = {
|
||||
{1, "Unallocated (unassigned) number"},
|
||||
{2, "No route to specified network"},
|
||||
{3, "No route to destination"},
|
||||
{4, "Send special information tone"},
|
||||
{5, "Misdialed trunk prefix"},
|
||||
{6, "Channel Unacceptable"},
|
||||
{7, "Call awarded and channel established"},
|
||||
{8, "Pre-emption"},
|
||||
{9, "Pre-emption-circuit reserved"},
|
||||
{16, "Normal call clearing"},
|
||||
{17, "User Busy"},
|
||||
{18, "No User Responding"},
|
||||
{19, "No Answer from User"},
|
||||
{20, "Subscriber Absent"},
|
||||
{21, "Call Rejected"},
|
||||
{22, "Number Changed"},
|
||||
{26, "Non-Selected User Clearing"},
|
||||
{27, "Destination Out-of-Order"},
|
||||
{28, "Invalid Number Format"},
|
||||
{29, "Facility Rejected"},
|
||||
{30, "Response to Status Enquiry"},
|
||||
{31, "Normal, Unspecified"},
|
||||
{34, "No Circuit/Channel Available"},
|
||||
{38, "Network Out-of-Order"},
|
||||
{39, "Permanent Frame Mode OOS"},
|
||||
{40, "Permanent Frame Mode Operational"},
|
||||
{41, "Temporary Failure"},
|
||||
{42, "Switching Equipment Congestion"},
|
||||
{43, "Access Information Discarded"},
|
||||
{44, "Requested Circuit/Channel not available"},
|
||||
{47, "Resource Unavailable, Unspecified"},
|
||||
{49, "Quality of Service not available"},
|
||||
{50, "Requested facility not subscribed"},
|
||||
{53, "Outgoing calls barred within CUG"},
|
||||
{55, "Incoming calls barred within CUG"},
|
||||
{57, "Bearer capability not authorized"},
|
||||
{58, "Bearer capability not presently available"},
|
||||
{62, "Inconsistency in access inf and subscriber"},
|
||||
{63, "Service or Option not available"},
|
||||
{65, "Bearer capability not implemented"},
|
||||
{66, "Channel type not implemented"},
|
||||
{69, "Requested facility not implemented"},
|
||||
{70, "Only restricted digital BC available"},
|
||||
{79, "Service or option not implemented"},
|
||||
{81, "Invalid call reference value"},
|
||||
{82, "Identified channel does not exist"},
|
||||
{83, "Suspended call exists"},
|
||||
{84, "Call identity in use"},
|
||||
{85, "No call suspended"},
|
||||
{86, "Call already cleared"},
|
||||
{87, "User not member of CUG"},
|
||||
{88, "Incompatible destination"},
|
||||
{90, "Non existent CUG"},
|
||||
{91, "Invalid transit network selection"},
|
||||
{95, "Invalid message, unspecified"},
|
||||
{96, "Mandatory IE missing"},
|
||||
{97, "Message type non-existent, not implemented"},
|
||||
{98, "Message not compatible with call state"},
|
||||
{99, "An IE or parameter does not exist"},
|
||||
{100, "Invalid IE contents"},
|
||||
{101, "Message not compatible with call state"},
|
||||
{102, "Recovery on timer expired"},
|
||||
{103, "Parameter non-existent, not impl"},
|
||||
{110, "Message with unrecognized parameter"},
|
||||
{111, "Protocol error, unspecified"},
|
||||
{127, "Interworking, unspecified"},
|
||||
{-1, "Unknown"},
|
||||
};
|
||||
|
||||
struct code2str dcodQ931IEIDTable[] = {
|
||||
{PROT_Q931_IE_SEGMENTED_MESSAGE, "Segmented Message"},
|
||||
{PROT_Q931_IE_BEARER_CAP, "Bearer Capability"},
|
||||
{PROT_Q931_IE_CAUSE, "Cause"},
|
||||
{PROT_Q931_IE_CALL_IDENTITY, "Call Identity"},
|
||||
{PROT_Q931_IE_CALL_STATE, "Call State"},
|
||||
{PROT_Q931_IE_CHANNEL_ID, "Channel Id"},
|
||||
{PROT_Q931_IE_FACILITY, "Facility"},
|
||||
{PROT_Q931_IE_PROGRESS_IND, "Progress Indicator"},
|
||||
{PROT_Q931_IE_NETWORK_SPF_FACILITY, "Network Specific Facilities"},
|
||||
{PROT_Q931_IE_NOTIFICATION_IND, "Notification Indicator"},
|
||||
{PROT_Q931_IE_DISPLAY, "Display"},
|
||||
{PROT_Q931_IE_DATE_TIME, "Date/Time"},
|
||||
{PROT_Q931_IE_KEYPAD_FACILITY, "Keypad Facility"},
|
||||
{PROT_Q931_IE_INFORMATION_REQUEST, "Information Request"},
|
||||
{PROT_Q931_IE_SIGNAL, "Signal"},
|
||||
{PROT_Q931_IE_SWITCHOOK, "Switchhook"},
|
||||
{PROT_Q931_IE_GENERIC_DIGITS, "Generic Digits"},
|
||||
{PROT_Q931_IE_FEATURE_ACT, "Feature Activation"},
|
||||
{PROT_Q931_IE_FEATURE_IND, "Feature Indication"},
|
||||
{PROT_Q931_IE_INFORMATION_RATE, "Information Rate"},
|
||||
{PROT_Q931_IE_END_TO_END_TRANSIT_DELAY, "End-to-end Transit Delay"},
|
||||
{PROT_Q931_IE_TRANSIT_DELAY_SELECT_IND, "Transit Delay Selection and Indication"},
|
||||
{PROT_Q931_IE_PACKET_LAYER_BINARY_PARAMS, "Packet layer binary parameters"},
|
||||
{PROT_Q931_IE_PACKET_LAYER_WINDOW_SIZE, "Packet layer Window Size"},
|
||||
{PROT_Q931_IE_PACKET_LAYER_SIZE, "Packet layer Size"},
|
||||
{PROT_Q931_IE_CALLING_PARTY_NUMBER, "Calling Party Number"},
|
||||
{PROT_Q931_IE_CALLING_PARTY_SUBADDRESS, "Calling Party Subaddress"},
|
||||
{PROT_Q931_IE_CALLED_PARTY_NUMBER, "Called Party Number"},
|
||||
{PROT_Q931_IE_CALLED_PARTY_SUBADDRESS, "Called Party Subaddress"},
|
||||
{PROT_Q931_IE_REDIRECTING_NUMBER, "Redirecting Number"},
|
||||
{PROT_Q931_IE_REDIRECTION_NUMBER, "Redirection Number"},
|
||||
{PROT_Q931_IE_TRANSIT_NETWORK_SELECTION, "Transit Network Selection"},
|
||||
{PROT_Q931_IE_RESTART_IND, "Restart Indicator"},
|
||||
{PROT_Q931_IE_LOW_LAYER_COMPAT, "Low-Layer Compatibility"},
|
||||
{PROT_Q931_IE_HIGH_LAYER_COMPAT, "High-Layer Compatibility"},
|
||||
{PROT_Q931_IE_USER_USER, "User-User"},
|
||||
{PROT_Q931_IE_SENDING_COMPLETE, "Sending complete"},
|
||||
{PROT_Q931_IE_ESCAPE_FOR_EXTENSION, "Escape for extension"},
|
||||
{-1,"Unknown"},
|
||||
};
|
||||
|
||||
struct code2str dcodQ931NumberingPlanTable[] = {
|
||||
{0, "unknown"},
|
||||
{1, "isdn"},
|
||||
{3, "data"},
|
||||
{4, "telex"},
|
||||
{8, "national"},
|
||||
{9, "private"},
|
||||
{15, "reserved"},
|
||||
{-1, "invalid"},
|
||||
};
|
||||
|
||||
struct code2str dcodQ931TypeofNumberTable[] = {
|
||||
{0, "unknown"},
|
||||
{1, "international"},
|
||||
{2, "national"},
|
||||
{3, "network spf"},
|
||||
{4, "subscriber"},
|
||||
{6, "abbreviated"},
|
||||
{7, "reserved"},
|
||||
{-1, "invalid" },
|
||||
};
|
||||
|
||||
struct code2str dcodQ931PresentationTable[] = {
|
||||
{0, "allowed"},
|
||||
{1, "restricted"},
|
||||
{2, "not available"},
|
||||
{-1, "invalid" },
|
||||
};
|
||||
|
||||
struct code2str dcodQ931ScreeningTable[] = {
|
||||
{0, "user, not screened"},
|
||||
{1, "user, passed"},
|
||||
{2, "user, failed"},
|
||||
{3, "network, provided"},
|
||||
{-1, "invalid" },
|
||||
};
|
||||
|
||||
struct code2str dcodQ931ReasonTable[] = {
|
||||
{0x0, "Unknown"},
|
||||
{0x1, "Call forwarding busy"},
|
||||
{0x2, "Call forwarding no reply"},
|
||||
{0x4, "Call deflection"},
|
||||
{0x9, "Called DTE out of order"},
|
||||
{0xA, "Call forwarding by the called DTE"},
|
||||
{0xF, "Call forwarding unconditional"},
|
||||
{-1, "reserved" },
|
||||
};
|
||||
|
||||
struct code2str dcodQ931BcCodingStandardTable[] = {
|
||||
{0x0, "ITU-T"},
|
||||
{0x1, "ISO/IEC"},
|
||||
{0x2, "National"},
|
||||
{0x3, "Defined standard"},
|
||||
{-1, "unknown"},
|
||||
};
|
||||
|
||||
struct code2str dcodQ931BcInfTransferCapTable[] = {
|
||||
{0x00, "Speech"},
|
||||
{0x08, "Unrestricted digital"},
|
||||
{0x09, "Restricted digital"},
|
||||
{0x10, "3.1Khz audio"},
|
||||
{0x11, "Unrestricted digital w/ tones"},
|
||||
{0x18, "Video"},
|
||||
{-1, "reserved"},
|
||||
};
|
||||
|
||||
struct code2str dcodQ931BcInfTransferRateTable[] = {
|
||||
{0x00, "n/a"}, /* for packet-mode calls */
|
||||
{0x10, "64 Kbit/s"},
|
||||
{0x11, "2x64 Kbit/s"},
|
||||
{0x13, "384 Kbit/s"},
|
||||
{0x15, "1536 Kbit/s"},
|
||||
{0x17, "1920 Kbit/s"},
|
||||
{0x18, "Multirate"},
|
||||
{-1, "reserved"},
|
||||
};
|
||||
|
||||
|
||||
struct code2str dcodQ931BcusrL1ProtTable[] = {
|
||||
{0x01, "ITU-T rate/V.110/I.460/X.30"},
|
||||
{0x02, "G.711 u-Law"},
|
||||
{0x03, "G.711 A-Law"},
|
||||
{0x04, "G.721/I.460"},
|
||||
{0x05, "H.221/H.242"},
|
||||
{0x06, "H.223/H.245"},
|
||||
{0x07, "Non-ITU-T rate"},
|
||||
{0x08, "V.120"},
|
||||
{0x09, "X.31 HDLC"},
|
||||
{-1, "reserved"},
|
||||
};
|
||||
|
||||
struct code2str dcodQ931UuiProtDiscrTable[] = {
|
||||
{0x00, "User-specific"},
|
||||
{0x01, "OSI high layer prot"},
|
||||
{0x02, "Recommendation X.244"},
|
||||
{0x03, "System management"},
|
||||
{0x04, "IA5 Chars"},
|
||||
{0x05, "X.208/X.209"},
|
||||
{0x07, "V.120"},
|
||||
{0x08, "Q.931/I.451"},
|
||||
{0x10, "X.25"},
|
||||
{-1,"reserved"},
|
||||
};
|
||||
|
||||
struct code2str dcodQ931ChanTypeTable[] = {
|
||||
{0x3,"B-chans"},
|
||||
{0x6,"H0-chans"},
|
||||
{0x8,"H11-chans"},
|
||||
{0x9,"H12-chans"},
|
||||
{-1,"reserved"},
|
||||
};
|
||||
|
||||
struct code2str dcodQ931RestartIndClassTable[] = {
|
||||
{0x0 ,"Indicated in channel IE"},
|
||||
{0x6 ,"Single interface"},
|
||||
{0x7 ,"All interfaces"},
|
||||
{-1, "reserved"},
|
||||
};
|
||||
|
||||
struct code2str dcodQ931IelocationTable[] = {
|
||||
{0x0, "User"},
|
||||
{0x1, "Private network, local user"},
|
||||
{0x2, "Public network, local user"},
|
||||
{0x3, "Transit network"},
|
||||
{0x4, "Public network, remote user"},
|
||||
{0x5, "Private network, remote user"},
|
||||
{0xA, "Beyond interworking point"},
|
||||
{-1, "reserved"},
|
||||
};
|
||||
|
||||
struct code2str dcodQ931IeprogressDescrTable[] = {
|
||||
{0x01, "Further info maybe available"},
|
||||
{0x02, "Destination is non-ISDN"},
|
||||
{0x03, "Origination address is non-ISDN"},
|
||||
{0x04, "Call returned to ISDN"},
|
||||
{0x08, "In-band data ready"},
|
||||
{-1, "reserved"},
|
||||
};
|
||||
|
||||
struct code2str dcodQ931IeFacilityProtProfileTable[] = {
|
||||
{0x11, "Remote Operations Protocol"},
|
||||
{0x12, "CMIP Protocol"},
|
||||
{0x13, "ACSE Protocol"},
|
||||
{0x16, "GAT Protocol"},
|
||||
{0x1F, "Networking Extensions"},
|
||||
{-1, "reserved"},
|
||||
};
|
||||
|
||||
//from www.voip-info.org/wiki/ANI2 - NANPA
|
||||
struct code2str dcodQ931LineInfoTable[] = {
|
||||
{0, "Plain Old Telephone Service(POTS)" },
|
||||
{1, "Multiparty line"},
|
||||
{2, "ANI Failure"},
|
||||
{6, "Station Level Rating"},
|
||||
{7, "Special Operator Handling Required"},
|
||||
{20, "Automatic Identified Outward Dialing (AIOD)"},
|
||||
{23, "Coin or Non-coin"},
|
||||
{24, "Toll free service, POTS originated for non-pay station"},
|
||||
{25, "Toll free service, POTS originated for pay station"},
|
||||
{27, "Pay station with coin control"},
|
||||
{29, "Prison-Inmate service"},
|
||||
{30, "Intercept - blank"},
|
||||
{31, "Intercept - trouble"},
|
||||
{32, "Intercept - regular"},
|
||||
{34, "Telco operator handled call"},
|
||||
{52, "Outward Wide Area Telecommunications Service(OUTWATS)"},
|
||||
{60, "TRS call - from unrestricted line"},
|
||||
{61, "Cellular-Wireless PCS Type 1"},
|
||||
{62, "Cellular-Wireless PCS Type 2"},
|
||||
{63, "Cellular-Wireless PCS Type Roaming"},
|
||||
{66, "TRS call - from hotel/motel"},
|
||||
{67, "TRS call - from restricted line"},
|
||||
{70, "Line connected to pay station"},
|
||||
{93, "Private virtual network call"},
|
||||
{-1, "Unassigned"},
|
||||
};
|
||||
|
||||
|
||||
struct code2str dcodQ931GenDigitsEncodingTable[] = {
|
||||
{0, "BCD even"},
|
||||
{1, "BCD odd"},
|
||||
{2, "IA5"},
|
||||
{3, "Binary"},
|
||||
{-1, "Invalid"},
|
||||
};
|
||||
|
||||
|
||||
struct code2str dcodQ931GenDigitsTypeTable[] = {
|
||||
{ 0, "Account Code"},
|
||||
{ 1, "Auth Code"},
|
||||
{ 2, "Customer ID" },
|
||||
{ 3, "Universal Access"},
|
||||
{ 4, "Info Digits"},
|
||||
{ 5, "Callid"},
|
||||
{ 6, "Opart"},
|
||||
{ 7, "TCN"},
|
||||
{ 9, "Adin"},
|
||||
{-1, "Invalid"},
|
||||
};
|
||||
|
||||
#endif /* __FTMOD_SANGOMA_ISDN_TRACE_H__ */
|
||||
|
Loading…
Reference in New Issue