2001-10-09 02:06:21 +00:00
/*
* Asterisk - - A telephony toolkit for Linux .
*
2003-02-24 06:00:18 +00:00
* Zaptel Pseudo TDM interface
2001-10-09 02:06:21 +00:00
*
2005-01-21 07:06:25 +00:00
* Copyright ( C ) 2003 - 2005 , Digium , Inc .
2001-10-09 02:06:21 +00:00
*
2003-02-24 06:00:18 +00:00
* Mark Spencer < markster @ digium . com >
2001-10-09 02:06:21 +00:00
*
* This program is free software , distributed under the terms of
* the GNU General Public License
*/
# include <stdio.h>
# include <string.h>
# include <sys/signal.h>
# include <errno.h>
# include <stdlib.h>
2005-05-04 04:35:27 +00:00
# if !defined(SOLARIS) && !defined(__FreeBSD__)
2003-02-07 19:23:19 +00:00
# include <stdint.h>
2004-12-14 23:36:30 +00:00
# endif
2001-10-09 02:06:21 +00:00
# include <unistd.h>
# include <sys/ioctl.h>
2004-06-04 15:44:14 +00:00
# ifdef __linux__
2001-10-09 02:06:21 +00:00
# include <linux/zaptel.h>
2004-06-04 15:44:14 +00:00
# else
# include <zaptel.h>
# endif /* __linux__ */
2001-10-09 02:06:21 +00:00
# include <math.h>
# include <tonezone.h>
2003-02-07 19:23:19 +00:00
# include <ctype.h>
2001-10-09 02:06:21 +00:00
# ifdef ZAPATA_PRI
# include <libpri.h>
2005-07-12 02:33:57 +00:00
# ifndef PRI_CALLINGPLANANI
2004-10-28 21:42:39 +00:00
# error "You need newer libpri"
# endif
2001-10-09 02:06:21 +00:00
# endif
2003-02-07 19:23:19 +00:00
# ifdef ZAPATA_R2
# include <libmfcr2.h>
# endif
2001-10-09 02:06:21 +00:00
2005-04-21 06:02:45 +00:00
# include "asterisk.h"
2002-03-08 23:48:42 +00:00
2005-06-06 22:12:19 +00:00
ASTERISK_FILE_VERSION ( __FILE__ , " $Revision$ " )
2005-06-06 21:09:59 +00:00
# include "asterisk/lock.h"
# include "asterisk/channel.h"
# include "asterisk/config.h"
# include "asterisk/logger.h"
# include "asterisk/module.h"
# include "asterisk/pbx.h"
# include "asterisk/options.h"
# include "asterisk/file.h"
# include "asterisk/ulaw.h"
# include "asterisk/alaw.h"
# include "asterisk/callerid.h"
# include "asterisk/adsi.h"
# include "asterisk/cli.h"
# include "asterisk/cdr.h"
# include "asterisk/features.h"
# include "asterisk/musiconhold.h"
# include "asterisk/say.h"
# include "asterisk/tdd.h"
# include "asterisk/app.h"
# include "asterisk/dsp.h"
# include "asterisk/astdb.h"
# include "asterisk/manager.h"
# include "asterisk/causes.h"
# include "asterisk/term.h"
# include "asterisk/utils.h"
# include "asterisk/transcap.h"
2004-04-26 12:30:28 +00:00
# ifndef ZT_SIG_EM_E1
# error "Your zaptel is too old. please cvs update"
# endif
2001-10-09 02:06:21 +00:00
2005-05-02 20:16:21 +00:00
# ifndef ZT_TONEDETECT
/* Work around older code with no tone detect */
# define ZT_EVENT_DTMFDOWN 0
# define ZT_EVENT_DTMFUP 0
# endif
2002-06-24 17:59:56 +00:00
/*
* Define ZHONE_HACK to cause us to go off hook and then back on hook when
* the user hangs up to reset the state machine so ring works properly .
* This is used to be able to support kewlstart by putting the zhone in
* groundstart mode since their forward disconnect supervision is entirely
* broken even though their documentation says it isn ' t and their support
* is entirely unwilling to provide any assistance with their channel banks
* even though their web site says they support their products for life .
*/
2003-02-07 19:23:19 +00:00
/* #define ZHONE_HACK */
2002-06-24 17:59:56 +00:00
2004-09-04 15:00:05 +00:00
/*
* Define if you want to check the hook state for an FXO ( FXS signalled ) interface
* before dialing on it . Certain FXO interfaces always think they ' re out of
* service with this method however .
*/
/* #define ZAP_CHECK_HOOKSTATE */
2003-04-15 17:09:34 +00:00
/* Typically, how many rings before we should send Caller*ID */
# define DEFAULT_CIDRINGS 1
2002-06-24 17:59:56 +00:00
# define CHANNEL_PSEUDO -12
2003-02-07 19:23:19 +00:00
# define AST_LAW(p) (((p)->law == ZT_LAW_ALAW) ? AST_FORMAT_ALAW : AST_FORMAT_ULAW)
2005-07-19 13:30:37 +00:00
/* Signaling types that need to use MF detection should be placed in this macro */
# define NEED_MFDETECT(p) (((p)->sig == SIG_FEATDMF) || ((p)->sig == SIG_FEATDMF_TA) || ((p)->sig == SIG_E911) || ((p)->sig == SIG_FEATB))
2005-03-04 06:47:24 +00:00
static const char desc [ ] = " Zapata Telephony "
2001-10-09 02:06:21 +00:00
# ifdef ZAPATA_PRI
2003-02-07 19:23:19 +00:00
" w/PRI "
# endif
# ifdef ZAPATA_R2
" w/R2 "
# endif
;
2005-03-04 06:47:24 +00:00
static const char tdesc [ ] = " Zapata Telephony Driver "
2003-02-07 19:23:19 +00:00
# ifdef ZAPATA_PRI
" w/PRI "
# endif
# ifdef ZAPATA_R2
" w/R2 "
2001-10-09 02:06:21 +00:00
# endif
2003-02-07 19:23:19 +00:00
;
2005-03-04 06:47:24 +00:00
static const char type [ ] = " Zap " ;
static const char config [ ] = " zapata.conf " ;
2001-10-09 02:06:21 +00:00
# define SIG_EM ZT_SIG_EM
2004-04-16 18:00:00 +00:00
# define SIG_EMWINK (0x100000 | ZT_SIG_EM)
# define SIG_FEATD (0x200000 | ZT_SIG_EM)
# define SIG_FEATDMF (0x400000 | ZT_SIG_EM)
# define SIG_FEATB (0x800000 | ZT_SIG_EM)
# define SIG_E911 (0x1000000 | ZT_SIG_EM)
2005-04-22 19:10:35 +00:00
# define SIG_FEATDMF_TA (0x2000000 | ZT_SIG_EM)
2001-10-09 02:06:21 +00:00
# define SIG_FXSLS ZT_SIG_FXSLS
# define SIG_FXSGS ZT_SIG_FXSGS
# define SIG_FXSKS ZT_SIG_FXSKS
# define SIG_FXOLS ZT_SIG_FXOLS
# define SIG_FXOGS ZT_SIG_FXOGS
# define SIG_FXOKS ZT_SIG_FXOKS
# define SIG_PRI ZT_SIG_CLEAR
2003-02-07 19:23:19 +00:00
# define SIG_R2 ZT_SIG_CAS
2003-03-17 18:11:33 +00:00
# define SIG_SF ZT_SIG_SF
2004-04-16 18:00:00 +00:00
# define SIG_SFWINK (0x100000 | ZT_SIG_SF)
# define SIG_SF_FEATD (0x200000 | ZT_SIG_SF)
# define SIG_SF_FEATDMF (0x400000 | ZT_SIG_SF)
# define SIG_SF_FEATB (0x800000 | ZT_SIG_SF)
# define SIG_EM_E1 ZT_SIG_EM_E1
2004-06-05 06:54:52 +00:00
# define SIG_GR303FXOKS (0x100000 | ZT_SIG_FXOKS)
2004-06-29 11:45:51 +00:00
# define SIG_GR303FXSKS (0x200000 | ZT_SIG_FXSKS)
2001-10-09 02:06:21 +00:00
2005-02-04 06:12:32 +00:00
# define NUM_SPANS 32
# define NUM_DCHANS 4 /* No more than 4 d-channels */
# define MAX_CHANNELS 672 /* No more than a DS3 per trunk group */
2002-06-24 17:59:56 +00:00
# define CHAN_PSEUDO -2
2001-10-09 02:06:21 +00:00
2004-06-07 03:39:18 +00:00
# define DCHAN_PROVISIONED (1 << 0)
# define DCHAN_NOTINALARM (1 << 1)
# define DCHAN_UP (1 << 2)
# define DCHAN_AVAILABLE (DCHAN_PROVISIONED | DCHAN_NOTINALARM | DCHAN_UP)
2004-12-15 19:59:53 +00:00
static int cur_emdigitwait = 250 ; /* Wait time in ms for digits on EM channel */
2005-07-10 23:49:57 +00:00
static char context [ AST_MAX_CONTEXT ] = " default " ;
2004-10-02 00:58:31 +00:00
static char cid_num [ 256 ] = " " ;
static char cid_name [ 256 ] = " " ;
2005-04-22 19:10:35 +00:00
static char defaultcic [ 64 ] = " " ;
static char defaultozz [ 64 ] = " " ;
2001-10-09 02:06:21 +00:00
static char language [ MAX_LANGUAGE ] = " " ;
2005-07-05 17:16:17 +00:00
static char musicclass [ MAX_MUSICCLASS ] = " " ;
2004-03-28 02:53:04 +00:00
static char progzone [ 10 ] = " " ;
2001-10-09 02:06:21 +00:00
2004-01-12 04:28:00 +00:00
static int usedistinctiveringdetection = 0 ;
2005-06-23 14:51:52 +00:00
static int transfertobusy = 1 ;
2001-10-09 02:06:21 +00:00
static int use_callerid = 1 ;
2004-09-19 16:17:18 +00:00
static int cid_signalling = CID_SIG_BELL ;
static int cid_start = CID_START_RING ;
2003-12-18 16:01:08 +00:00
static int zaptrcallerid = 0 ;
2001-10-09 02:06:21 +00:00
static int cur_signalling = - 1 ;
2005-01-15 21:51:38 +00:00
static ast_group_t cur_group = 0 ;
static ast_group_t cur_callergroup = 0 ;
static ast_group_t cur_pickupgroup = 0 ;
2003-02-07 19:23:19 +00:00
static int relaxdtmf = 0 ;
2001-10-09 02:06:21 +00:00
static int immediate = 0 ;
static int stripmsd = 0 ;
static int callwaiting = 0 ;
static int callwaitingcallerid = 0 ;
static int hidecallerid = 0 ;
2003-09-05 04:00:57 +00:00
static int restrictcid = 0 ;
2003-10-01 15:59:26 +00:00
static int use_callingpres = 0 ;
2003-02-07 19:23:19 +00:00
static int callreturn = 0 ;
2001-10-09 02:06:21 +00:00
static int threewaycalling = 0 ;
static int transfer = 0 ;
2004-12-09 22:39:14 +00:00
static int canpark = 0 ;
2002-03-08 23:48:42 +00:00
static int cancallforward = 0 ;
2001-10-09 02:06:21 +00:00
static float rxgain = 0.0 ;
static float txgain = 0.0 ;
2004-02-15 07:35:32 +00:00
static int tonezone = - 1 ;
2001-10-09 02:06:21 +00:00
static int echocancel ;
2003-10-27 17:16:08 +00:00
static int echotraining ;
2004-09-13 23:07:50 +00:00
static int pulse ;
2002-09-10 04:45:51 +00:00
static int echocanbridged = 0 ;
2003-02-07 19:23:19 +00:00
static int busydetect = 0 ;
2003-03-06 06:00:17 +00:00
static int busycount = 3 ;
2005-08-08 00:08:48 +00:00
static int busy_tonelength = 0 ;
static int busy_quietlength = 0 ;
2003-03-06 06:00:17 +00:00
2003-02-07 19:23:19 +00:00
static int callprogress = 0 ;
2005-05-25 17:18:05 +00:00
static char accountcode [ AST_MAX_ACCOUNT_CODE ] = " " ;
2001-12-29 18:04:21 +00:00
2002-03-08 23:48:42 +00:00
static char mailbox [ AST_MAX_EXTENSION ] ;
2001-12-29 18:04:21 +00:00
static int amaflags = 0 ;
static int adsi = 0 ;
2003-10-24 18:22:45 +00:00
static int numbufs = 4 ;
2004-03-24 08:36:36 +00:00
static int cur_prewink = - 1 ;
static int cur_preflash = - 1 ;
static int cur_wink = - 1 ;
static int cur_flash = - 1 ;
static int cur_start = - 1 ;
static int cur_rxwink = - 1 ;
static int cur_rxflash = - 1 ;
static int cur_debounce = - 1 ;
2004-08-31 13:47:23 +00:00
static int priindication_oob = 0 ;
2002-06-24 17:59:56 +00:00
# ifdef ZAPATA_PRI
static int minunused = 2 ;
static int minidle = 0 ;
static char idleext [ AST_MAX_EXTENSION ] ;
static char idledial [ AST_MAX_EXTENSION ] ;
2003-05-19 23:33:41 +00:00
static int overlapdial = 0 ;
2005-05-12 15:05:25 +00:00
static int facilityenable = 0 ;
2005-02-04 06:12:32 +00:00
static char internationalprefix [ 10 ] = " " ;
static char nationalprefix [ 10 ] = " " ;
static char localprefix [ 20 ] = " " ;
static char privateprefix [ 20 ] = " " ;
static char unknownprefix [ 20 ] = " " ;
static long resetinterval = 3600 ; /* How often (in seconds) to reset unused channels. Default 1 hour. */
2004-06-06 01:54:22 +00:00
static struct ast_channel inuse = { " GR-303InUse " } ;
2004-10-02 15:04:38 +00:00
# ifdef PRI_GETSET_TIMERS
2004-10-02 15:01:37 +00:00
static int pritimers [ PRI_MAX_TIMERS ] ;
2002-06-24 17:59:56 +00:00
# endif
2005-05-25 10:57:15 +00:00
static int pridebugfd = - 1 ;
static char pridebugfilename [ 1024 ] = " " ;
2004-10-02 15:04:38 +00:00
# endif
2002-06-24 17:59:56 +00:00
2001-10-09 02:06:21 +00:00
/* Wait up to 16 seconds for first digit (FXO logic) */
static int firstdigittimeout = 16000 ;
/* How long to wait for following digits (FXO logic) */
static int gendigittimeout = 8000 ;
2003-02-07 19:23:19 +00:00
/* How long to wait for an extra digit, if there is an ambiguous match */
static int matchdigittimeout = 3000 ;
2001-10-09 02:06:21 +00:00
static int usecnt = 0 ;
2004-06-09 01:45:08 +00:00
AST_MUTEX_DEFINE_STATIC ( usecnt_lock ) ;
2001-10-09 02:06:21 +00:00
/* Protect the interface list (of zt_pvt's) */
2004-06-09 01:45:08 +00:00
AST_MUTEX_DEFINE_STATIC ( iflock ) ;
2001-10-09 02:06:21 +00:00
2005-04-22 19:10:35 +00:00
2004-04-25 22:37:09 +00:00
static int ifcount = 0 ;
2005-08-29 21:18:20 +00:00
# ifdef ZAPATA_PRI
2005-04-22 19:10:35 +00:00
AST_MUTEX_DEFINE_STATIC ( pridebugfdlock ) ;
2005-08-29 21:18:20 +00:00
# endif
2005-04-22 19:10:35 +00:00
2005-02-08 07:49:40 +00:00
/* Whether we answer on a Polarity Switch event */
static int answeronpolarityswitch = 0 ;
2004-11-17 06:18:33 +00:00
/* Whether we hang up on a Polarity Switch event */
static int hanguponpolarityswitch = 0 ;
/* How long (ms) to ignore Polarity Switch events after we answer a call */
static int polarityonanswerdelay = 600 ;
2004-12-28 21:32:25 +00:00
/* When to send the CallerID signals (rings) */
static int sendcalleridafter = DEFAULT_CIDRINGS ;
2001-10-09 02:06:21 +00:00
/* Protect the monitoring thread, so only one process can kill or start it, and not
when it ' s doing something critical . */
2004-06-09 01:45:08 +00:00
AST_MUTEX_DEFINE_STATIC ( monlock ) ;
2001-10-09 02:06:21 +00:00
/* This is the thread for the monitor which checks for input on the channels
which are not currently in use . */
2004-03-15 07:51:22 +00:00
static pthread_t monitor_thread = AST_PTHREADT_NULL ;
2001-10-09 02:06:21 +00:00
static int restart_monitor ( void ) ;
2005-08-09 01:59:59 +00:00
static enum ast_bridge_result zt_bridge ( struct ast_channel * c0 , struct ast_channel * c1 , int flags , struct ast_frame * * fo , struct ast_channel * * rc ) ;
2001-10-09 02:06:21 +00:00
2005-03-28 20:48:24 +00:00
static int zt_sendtext ( struct ast_channel * c , const char * text ) ;
2001-12-29 18:04:21 +00:00
2001-10-09 02:06:21 +00:00
static inline int zt_get_event ( int fd )
{
/* Avoid the silly zt_getevent which ignores a bunch of events */
int j ;
if ( ioctl ( fd , ZT_GETEVENT , & j ) = = - 1 ) return - 1 ;
return j ;
}
static inline int zt_wait_event ( int fd )
{
/* Avoid the silly zt_waitevent which ignores a bunch of events */
int i , j = 0 ;
i = ZT_IOMUX_SIGEVENT ;
if ( ioctl ( fd , ZT_IOMUX , & i ) = = - 1 ) return - 1 ;
if ( ioctl ( fd , ZT_GETEVENT , & j ) = = - 1 ) return - 1 ;
return j ;
}
2003-02-07 19:23:19 +00:00
/* Chunk size to read -- we use 20ms chunks to make things happy. */
# define READ_SIZE 160
2001-10-09 02:06:21 +00:00
# define MASK_AVAIL (1 << 0) /* Channel available for PRI use */
# define MASK_INUSE (1 << 1) /* Channel currently in use */
# define CALLWAITING_SILENT_SAMPLES ( (300 * 8) / READ_SIZE) /* 300 ms */
# define CALLWAITING_REPEAT_SAMPLES ( (10000 * 8) / READ_SIZE) /* 300 ms */
2003-02-07 19:23:19 +00:00
# define CIDCW_EXPIRE_SAMPLES ( (500 * 8) / READ_SIZE) /* 500 ms */
2003-04-11 04:31:33 +00:00
# define MIN_MS_SINCE_FLASH ( (2000) ) /* 2000 ms */
2003-02-07 19:23:19 +00:00
# define RINGT ( (8000 * 8) / READ_SIZE)
2001-10-09 02:06:21 +00:00
struct zt_pvt ;
2003-02-07 19:23:19 +00:00
# ifdef ZAPATA_R2
static int r2prot = - 1 ;
# endif
2001-10-09 02:06:21 +00:00
# ifdef ZAPATA_PRI
2004-06-05 06:54:52 +00:00
2005-05-24 15:30:10 +00:00
# define PVT_TO_CHANNEL(p) (((p)->prioffset) | ((p)->logicalspan << 8) | (p->pri->mastertrunkgroup ? 0x10000 : 0))
2004-06-05 06:54:52 +00:00
# define PRI_CHANNEL(p) ((p) & 0xff)
# define PRI_SPAN(p) (((p) >> 8) & 0xff)
2005-05-20 19:09:21 +00:00
# define PRI_EXPLICIT(p) (((p) >> 16) & 0x01)
2004-06-05 06:54:52 +00:00
2001-10-09 02:06:21 +00:00
struct zt_pri {
2005-02-04 06:12:32 +00:00
pthread_t master ; /* Thread of master */
ast_mutex_t lock ; /* Mutex */
2005-06-07 21:13:35 +00:00
char idleext [ AST_MAX_EXTENSION ] ; /* Where to idle extra calls */
2005-07-10 23:49:57 +00:00
char idlecontext [ AST_MAX_CONTEXT ] ; /* What context to use for idle */
2005-06-07 21:13:35 +00:00
char idledial [ AST_MAX_EXTENSION ] ; /* What to dial before dumping */
2005-02-04 06:12:32 +00:00
int minunused ; /* Min # of channels to keep empty */
int minidle ; /* Min # of "idling" calls to keep active */
int nodetype ; /* Node type */
int switchtype ; /* Type of switch to emulate */
2005-06-07 21:13:35 +00:00
int nsf ; /* Network-Specific Facilities */
2005-02-04 06:12:32 +00:00
int dialplan ; /* Dialing plan */
int localdialplan ; /* Local dialing plan */
2005-06-07 21:13:35 +00:00
char internationalprefix [ 10 ] ; /* country access code ('00' for european dialplans) */
char nationalprefix [ 10 ] ; /* area access code ('0' for european dialplans) */
char localprefix [ 20 ] ; /* area access code + area code ('0'+area code for european dialplans) */
char privateprefix [ 20 ] ; /* for private dialplans */
char unknownprefix [ 20 ] ; /* for unknown dialplans */
int dchannels [ NUM_DCHANS ] ; /* What channel are the dchannels on */
2005-02-04 06:12:32 +00:00
int trunkgroup ; /* What our trunkgroup is */
2005-06-07 21:13:35 +00:00
int mastertrunkgroup ; /* What trunk group is our master */
2005-02-04 06:12:32 +00:00
int prilogicalspan ; /* Logical span number within trunk group */
int numchans ; /* Num of channels we represent */
int overlapdial ; /* In overlap dialing mode */
2005-05-12 15:05:25 +00:00
int facilityenable ; /* Enable facility IEs */
2005-06-07 21:13:35 +00:00
struct pri * dchans [ NUM_DCHANS ] ; /* Actual d-channels */
int dchanavail [ NUM_DCHANS ] ; /* Whether each channel is available */
2005-02-04 06:12:32 +00:00
struct pri * pri ; /* Currently active D-channel */
2001-10-09 02:06:21 +00:00
int debug ;
2005-06-07 21:13:35 +00:00
int fds [ NUM_DCHANS ] ; /* FD's for d-channels */
2001-10-09 02:06:21 +00:00
int offset ;
int span ;
2002-06-24 17:59:56 +00:00
int resetting ;
2004-06-05 06:54:52 +00:00
int resetpos ;
2005-02-04 06:12:32 +00:00
time_t lastreset ; /* time when unused channels were last reset */
long resetinterval ; /* Interval (in seconds) for resetting unused channels */
2005-06-07 21:13:35 +00:00
struct zt_pvt * pvts [ MAX_CHANNELS ] ; /* Member channel pvt structs */
struct zt_pvt * crvs ; /* Member CRV structs */
struct zt_pvt * crvend ; /* Pointer to end of CRV structs */
2001-10-09 02:06:21 +00:00
} ;
static struct zt_pri pris [ NUM_SPANS ] ;
static int pritype = PRI_CPE ;
#if 0
2001-12-29 18:04:21 +00:00
# define DEFAULT_PRI_DEBUG (PRI_DEBUG_Q931_DUMP | PRI_DEBUG_Q921_DUMP | PRI_DEBUG_Q921_RAW | PRI_DEBUG_Q921_STATE)
2001-10-09 02:06:21 +00:00
# else
# define DEFAULT_PRI_DEBUG 0
# endif
static inline void pri_rel ( struct zt_pri * pri )
{
2003-08-13 15:25:16 +00:00
ast_mutex_unlock ( & pri - > lock ) ;
2001-10-09 02:06:21 +00:00
}
static int switchtype = PRI_SWITCH_NI2 ;
2004-06-26 05:20:42 +00:00
static int nsf = PRI_NSF_NONE ;
2003-02-07 19:23:19 +00:00
static int dialplan = PRI_NATIONAL_ISDN + 1 ;
2004-07-17 01:30:43 +00:00
static int localdialplan = PRI_NATIONAL_ISDN + 1 ;
2001-10-09 02:06:21 +00:00
2004-06-06 01:54:22 +00:00
# else
/* Shut up the compiler */
struct zt_pri ;
2001-10-09 02:06:21 +00:00
# endif
2003-02-07 19:23:19 +00:00
# define SUB_REAL 0 /* Active call */
# define SUB_CALLWAIT 1 /* Call-Waiting call on hold */
# define SUB_THREEWAY 2 /* Three-way call */
2005-02-08 07:49:40 +00:00
/* Polarity states */
# define POLARITY_IDLE 0
# define POLARITY_REV 1
2004-01-12 04:28:00 +00:00
static struct zt_distRings drings ;
struct distRingData {
int ring [ 3 ] ;
} ;
struct ringContextData {
2005-07-10 23:49:57 +00:00
char contextData [ AST_MAX_CONTEXT ] ;
2004-01-12 04:28:00 +00:00
} ;
struct zt_distRings {
struct distRingData ringnum [ 3 ] ;
struct ringContextData ringContext [ 3 ] ;
} ;
2003-02-07 19:23:19 +00:00
static char * subnames [ ] = {
" Real " ,
" Callwait " ,
" Threeway "
} ;
struct zt_subchannel {
int zfd ;
struct ast_channel * owner ;
int chan ;
short buffer [ AST_FRIENDLY_OFFSET / 2 + READ_SIZE ] ;
struct ast_frame f ; /* One frame for each channel. How did this ever work before? */
2005-06-07 21:13:35 +00:00
unsigned int needringing : 1 ;
unsigned int needbusy : 1 ;
unsigned int needcongestion : 1 ;
unsigned int needcallerid : 1 ;
unsigned int needanswer : 1 ;
unsigned int needflash : 1 ;
unsigned int linear : 1 ;
unsigned int inthreeway : 1 ;
2003-08-23 17:49:54 +00:00
ZT_CONFINFO curconf ;
2003-02-07 19:23:19 +00:00
} ;
# define CONF_USER_REAL (1 << 0)
# define CONF_USER_THIRDCALL (1 << 1)
# define MAX_SLAVES 4
2001-10-09 02:06:21 +00:00
static struct zt_pvt {
2003-08-13 15:25:16 +00:00
ast_mutex_t lock ;
2005-06-07 21:13:35 +00:00
struct ast_channel * owner ; /* Our current active owner (if applicable) */
/* Up to three channels can be associated with this call */
2001-10-09 02:06:21 +00:00
2005-06-07 21:13:35 +00:00
struct zt_subchannel sub_unused ; /* Just a safety precaution */
struct zt_subchannel subs [ 3 ] ; /* Sub-channels */
struct zt_confinfo saveconf ; /* Saved conference info */
2003-02-07 19:23:19 +00:00
2005-06-07 21:13:35 +00:00
struct zt_pvt * slaves [ MAX_SLAVES ] ; /* Slave to us (follows our conferencing) */
struct zt_pvt * master ; /* Master to us (we follow their conferencing) */
int inconference ; /* If our real should be in the conference */
2001-10-09 02:06:21 +00:00
int sig ; /* Signalling style */
2005-06-07 21:13:35 +00:00
int radio ; /* radio type */
2001-10-09 02:06:21 +00:00
float rxgain ;
float txgain ;
2005-06-07 21:13:35 +00:00
int tonezone ; /* tone zone for this chan, or -1 for default */
struct zt_pvt * next ; /* Next channel in list */
struct zt_pvt * prev ; /* Prev channel in list */
/* flags */
unsigned int adsi : 1 ;
unsigned int answeronpolarityswitch : 1 ;
unsigned int busydetect : 1 ;
unsigned int callreturn : 1 ;
unsigned int callwaiting : 1 ;
unsigned int callwaitingcallerid : 1 ;
unsigned int cancallforward : 1 ;
unsigned int canpark : 1 ;
unsigned int confirmanswer : 1 ; /* Wait for '#' to confirm answer */
unsigned int destroy : 1 ;
unsigned int didtdd : 1 ; /* flag to say its done it once */
unsigned int dialednone : 1 ;
unsigned int dialing : 1 ;
unsigned int digital : 1 ;
unsigned int dnd : 1 ;
unsigned int echobreak : 1 ;
unsigned int echocanbridged : 1 ;
unsigned int echocanon : 1 ;
unsigned int faxhandled : 1 ; /* Has a fax tone already been handled? */
unsigned int firstradio : 1 ;
unsigned int hanguponpolarityswitch : 1 ;
2005-07-21 15:06:50 +00:00
unsigned int hardwaredtmf : 1 ;
2005-06-07 21:13:35 +00:00
unsigned int hidecallerid ;
unsigned int ignoredtmf : 1 ;
unsigned int immediate : 1 ; /* Answer before getting digits? */
unsigned int inalarm : 1 ;
unsigned int mate : 1 ; /* flag to say its in MATE mode */
unsigned int outgoing : 1 ;
unsigned int overlapdial : 1 ;
unsigned int permcallwaiting : 1 ;
unsigned int permhidecallerid : 1 ; /* Whether to hide our outgoing caller ID or not */
unsigned int priindication_oob : 1 ;
unsigned int pulse : 1 ;
unsigned int pulsedial : 1 ; /* whether a pulse dial phone is detected */
unsigned int restrictcid : 1 ; /* Whether restrict the callerid -> only send ANI */
unsigned int threewaycalling : 1 ;
unsigned int transfer : 1 ;
unsigned int use_callerid : 1 ; /* Whether or not to use caller id on this channel */
unsigned int use_callingpres : 1 ; /* Whether to use the callingpres the calling switch sends */
unsigned int usedistinctiveringdetection : 1 ;
unsigned int zaptrcallerid : 1 ; /* should we use the callerid from incoming call on zap transfer or not */
2005-06-23 14:51:52 +00:00
unsigned int transfertobusy : 1 ; /* allow flash-transfers to busy channels */
2005-06-07 21:13:35 +00:00
# if defined(ZAPATA_PRI)
unsigned int alerting : 1 ;
unsigned int alreadyhungup : 1 ;
unsigned int isidlecall : 1 ;
unsigned int resetting : 1 ;
unsigned int setup_ack : 1 ;
# endif
# if defined(ZAPATA_R2)
unsigned int hasr2call : 1 ;
unsigned int r2blocked : 1 ;
unsigned int sigchecked : 1 ;
# endif
2004-01-12 04:28:00 +00:00
struct zt_distRings drings ;
2005-07-10 23:49:57 +00:00
char context [ AST_MAX_CONTEXT ] ;
char defcontext [ AST_MAX_CONTEXT ] ;
2001-10-09 02:06:21 +00:00
char exten [ AST_MAX_EXTENSION ] ;
char language [ MAX_LANGUAGE ] ;
2005-07-05 17:16:17 +00:00
char musicclass [ MAX_MUSICCLASS ] ;
2005-07-12 02:33:57 +00:00
# ifdef PRI_ANI
char cid_ani [ AST_MAX_EXTENSION ] ;
# endif
2004-10-02 00:58:31 +00:00
char cid_num [ AST_MAX_EXTENSION ] ;
2005-06-07 21:13:35 +00:00
int cid_ton ; /* Type Of Number (TON) */
2004-10-02 00:58:31 +00:00
char cid_name [ AST_MAX_EXTENSION ] ;
char lastcid_num [ AST_MAX_EXTENSION ] ;
char lastcid_name [ AST_MAX_EXTENSION ] ;
2005-06-07 21:13:35 +00:00
char * origcid_num ; /* malloced original callerid */
char * origcid_name ; /* malloced original callerid */
2004-10-02 00:58:31 +00:00
char callwait_num [ AST_MAX_EXTENSION ] ;
char callwait_name [ AST_MAX_EXTENSION ] ;
2003-02-07 19:23:19 +00:00
char rdnis [ AST_MAX_EXTENSION ] ;
2003-09-04 18:55:35 +00:00
char dnid [ AST_MAX_EXTENSION ] ;
2003-04-09 04:00:43 +00:00
unsigned int group ;
2001-12-29 18:04:21 +00:00
int law ;
2003-02-07 19:23:19 +00:00
int confno ; /* Our conference */
2005-06-07 21:13:35 +00:00
int confusers ; /* Who is using our conference */
int propconfno ; /* Propagated conference number */
2005-01-15 21:51:38 +00:00
ast_group_t callgroup ;
ast_group_t pickupgroup ;
2005-06-07 21:13:35 +00:00
int channel ; /* Channel Number or CRV */
2001-10-09 02:06:21 +00:00
int span ; /* Span number */
2005-06-07 21:13:35 +00:00
time_t guardtime ; /* Must wait this much time before using for new call */
int cid_signalling ; /* CID signalling type bell202 or v23 */
int cid_start ; /* CID start indicator, polarity or ring */
int callingpres ; /* The value of callling presentation that we're going to use when placing a PRI call */
int callwaitingrepeat ; /* How many samples to wait before repeating call waiting */
int cidcwexpire ; /* When to expire our muting for CID/CW */
2001-10-09 02:06:21 +00:00
unsigned char * cidspill ;
int cidpos ;
int cidlen ;
int ringt ;
int stripmsd ;
int callwaitcas ;
int callwaitrings ;
int echocancel ;
2003-10-27 17:16:08 +00:00
int echotraining ;
2004-06-23 22:00:04 +00:00
char echorest [ 20 ] ;
2003-03-06 06:00:17 +00:00
int busycount ;
2005-08-08 00:08:48 +00:00
int busy_tonelength ;
int busy_quietlength ;
2003-02-07 19:23:19 +00:00
int callprogress ;
2005-06-07 21:13:35 +00:00
struct timeval flashtime ; /* Last flash-hook time */
2003-02-07 19:23:19 +00:00
struct ast_dsp * dsp ;
2001-10-09 02:06:21 +00:00
int cref ; /* Call reference number */
ZT_DIAL_OPERATION dop ;
2005-06-07 21:13:35 +00:00
int whichwink ; /* SIG_FEATDMF_TA Which wink are we on? */
2005-04-22 19:10:35 +00:00
char finaldial [ 64 ] ;
2005-05-25 17:18:05 +00:00
char accountcode [ AST_MAX_ACCOUNT_CODE ] ; /* Account code */
2005-06-07 21:13:35 +00:00
int amaflags ; /* AMA Flags */
struct tdd_state * tdd ; /* TDD flag */
2002-03-08 23:48:42 +00:00
char call_forward [ AST_MAX_EXTENSION ] ;
char mailbox [ AST_MAX_EXTENSION ] ;
2004-01-16 23:40:37 +00:00
char dialdest [ 256 ] ;
2003-02-07 19:23:19 +00:00
int onhooktime ;
int msgstate ;
2005-06-07 21:13:35 +00:00
int distinctivering ; /* Which distinctivering to use */
int cidrings ; /* Which ring to deliver CID on */
int dtmfrelax ; /* whether to run in relaxed DTMF mode */
2003-11-12 00:13:22 +00:00
int fake_event ;
2004-12-15 19:59:53 +00:00
int emdigitwait ;
2004-11-17 06:18:33 +00:00
int polarityonanswerdelay ;
struct timeval polaritydelaytv ;
2004-12-28 21:32:25 +00:00
int sendcalleridafter ;
2001-10-09 02:06:21 +00:00
# ifdef ZAPATA_PRI
struct zt_pri * pri ;
2004-06-06 01:54:22 +00:00
struct zt_pvt * bearer ;
struct zt_pvt * realcall ;
2001-10-09 02:06:21 +00:00
q931_call * call ;
2003-02-07 19:23:19 +00:00
int prioffset ;
2004-06-06 22:51:37 +00:00
int logicalspan ;
2003-04-18 15:55:50 +00:00
int proceeding ;
2005-01-21 04:48:15 +00:00
int dsp_features ;
2003-02-07 19:23:19 +00:00
# endif
# ifdef ZAPATA_R2
int r2prot ;
mfcr2_t * r2 ;
2001-10-09 02:06:21 +00:00
# endif
2005-02-08 07:49:40 +00:00
int polarity ;
2005-06-07 21:13:35 +00:00
2003-08-07 03:48:00 +00:00
} * iflist = NULL , * ifend = NULL ;
2001-10-09 02:06:21 +00:00
2005-03-04 06:47:24 +00:00
static struct ast_channel * zt_request ( const char * type , int format , void * data , int * cause ) ;
static int zt_digit ( struct ast_channel * ast , char digit ) ;
2005-03-28 20:48:24 +00:00
static int zt_sendtext ( struct ast_channel * c , const char * text ) ;
2005-03-04 06:47:24 +00:00
static int zt_call ( struct ast_channel * ast , char * rdest , int timeout ) ;
static int zt_hangup ( struct ast_channel * ast ) ;
static int zt_answer ( struct ast_channel * ast ) ;
struct ast_frame * zt_read ( struct ast_channel * ast ) ;
static int zt_write ( struct ast_channel * ast , struct ast_frame * frame ) ;
struct ast_frame * zt_exception ( struct ast_channel * ast ) ;
static int zt_indicate ( struct ast_channel * chan , int condition ) ;
static int zt_fixup ( struct ast_channel * oldchan , struct ast_channel * newchan ) ;
static int zt_setoption ( struct ast_channel * chan , int option , void * data , int datalen ) ;
static const struct ast_channel_tech zap_tech = {
. type = type ,
. description = tdesc ,
. capabilities = AST_FORMAT_SLINEAR | AST_FORMAT_ULAW ,
. requester = zt_request ,
. send_digit = zt_digit ,
. send_text = zt_sendtext ,
. call = zt_call ,
. hangup = zt_hangup ,
. answer = zt_answer ,
. read = zt_read ,
. write = zt_write ,
. bridge = zt_bridge ,
. exception = zt_exception ,
. indicate = zt_indicate ,
. fixup = zt_fixup ,
. setoption = zt_setoption ,
} ;
2004-07-16 22:15:30 +00:00
# ifdef ZAPATA_PRI
# define GET_CHANNEL(p) ((p)->bearer ? (p)->bearer->channel : p->channel)
# else
# define GET_CHANNEL(p) ((p)->channel)
# endif
2003-11-07 16:55:13 +00:00
struct zt_pvt * round_robin [ 32 ] ;
2003-04-22 18:47:49 +00:00
# ifdef ZAPATA_PRI
static inline int pri_grab ( struct zt_pvt * pvt , struct zt_pri * pri )
{
int res ;
/* Grab the lock first */
do {
2003-08-13 15:25:16 +00:00
res = ast_mutex_trylock ( & pri - > lock ) ;
2003-04-22 18:47:49 +00:00
if ( res ) {
2003-08-13 15:25:16 +00:00
ast_mutex_unlock ( & pvt - > lock ) ;
2003-04-22 18:47:49 +00:00
/* Release the lock and try again */
usleep ( 1 ) ;
2003-08-13 15:25:16 +00:00
ast_mutex_lock ( & pvt - > lock ) ;
2003-04-22 18:47:49 +00:00
}
} while ( res ) ;
2004-04-25 22:37:09 +00:00
/* Then break the poll */
2003-04-22 18:47:49 +00:00
pthread_kill ( pri - > master , SIGURG ) ;
return 0 ;
}
# endif
2004-02-23 05:02:24 +00:00
# define NUM_CADENCE_MAX 25
static int num_cadence = 4 ;
static int user_has_defined_cadences = 0 ;
static struct zt_ring_cadence cadences [ NUM_CADENCE_MAX ] = {
2002-06-24 17:59:56 +00:00
{ { 125 , 125 , 2000 , 4000 } } , /* Quick chirp followed by normal ring */
{ { 250 , 250 , 500 , 1000 , 250 , 250 , 500 , 4000 } } , /* British style ring */
{ { 125 , 125 , 125 , 125 , 125 , 4000 } } , /* Three short bursts */
{ { 1000 , 500 , 2500 , 5000 } } , /* Long ring */
} ;
2004-01-12 04:28:00 +00:00
int receivedRingT ; /* Used to find out what ringtone we are on */
2004-02-23 05:02:24 +00:00
/* cidrings says in which pause to transmit the cid information, where the first pause
* is 1 , the second pause is 2 and so on .
*/
2004-01-12 04:28:00 +00:00
2004-02-23 05:02:24 +00:00
static int cidrings [ NUM_CADENCE_MAX ] = {
2002-06-24 17:59:56 +00:00
2 , /* Right after first long ring */
4 , /* Right after long part */
3 , /* After third chirp */
2 , /* Second spell */
} ;
2001-10-09 02:06:21 +00:00
# define ISTRUNK(p) ((p->sig == SIG_FXSLS) || (p->sig == SIG_FXSKS) || \
2003-02-07 19:23:19 +00:00
( p - > sig = = SIG_FXSGS ) | | ( p - > sig = = SIG_PRI ) )
2001-10-09 02:06:21 +00:00
2004-04-16 18:00:00 +00:00
# define CANBUSYDETECT(p) (ISTRUNK(p) || (p->sig & (SIG_EM | SIG_EM_E1 | SIG_SF)) /* || (p->sig & __ZT_SIG_FXO) */ )
# define CANPROGRESSDETECT(p) (ISTRUNK(p) || (p->sig & (SIG_EM | SIG_EM_E1 | SIG_SF)) /* || (p->sig & __ZT_SIG_FXO) */ )
2001-10-09 02:06:21 +00:00
2003-02-07 19:23:19 +00:00
static int zt_get_index ( struct ast_channel * ast , struct zt_pvt * p , int nullok )
2001-10-09 02:06:21 +00:00
{
int res ;
2003-02-07 19:23:19 +00:00
if ( p - > subs [ 0 ] . owner = = ast )
res = 0 ;
else if ( p - > subs [ 1 ] . owner = = ast )
res = 1 ;
else if ( p - > subs [ 2 ] . owner = = ast )
res = 2 ;
else {
res = - 1 ;
if ( ! nullok )
ast_log ( LOG_WARNING , " Unable to get index, and nullok is not asserted \n " ) ;
}
return res ;
}
2004-09-10 18:47:13 +00:00
# ifdef ZAPATA_PRI
static void wakeup_sub ( struct zt_pvt * p , int a , struct zt_pri * pri )
# else
static void wakeup_sub ( struct zt_pvt * p , int a , void * pri )
# endif
2004-04-22 16:02:56 +00:00
{
struct ast_frame null = { AST_FRAME_NULL , } ;
2004-09-10 18:47:13 +00:00
# ifdef ZAPATA_PRI
if ( pri )
ast_mutex_unlock ( & pri - > lock ) ;
# endif
2004-04-22 16:02:56 +00:00
for ( ; ; ) {
if ( p - > subs [ a ] . owner ) {
if ( ast_mutex_trylock ( & p - > subs [ a ] . owner - > lock ) ) {
ast_mutex_unlock ( & p - > lock ) ;
usleep ( 1 ) ;
ast_mutex_lock ( & p - > lock ) ;
} else {
ast_queue_frame ( p - > subs [ a ] . owner , & null ) ;
ast_mutex_unlock ( & p - > subs [ a ] . owner - > lock ) ;
2004-04-22 18:41:11 +00:00
break ;
2004-04-22 16:02:56 +00:00
}
} else
break ;
}
2004-09-10 18:47:13 +00:00
# ifdef ZAPATA_PRI
if ( pri )
ast_mutex_lock ( & pri - > lock ) ;
# endif
2004-04-22 16:02:56 +00:00
}
2004-09-10 18:47:13 +00:00
# ifdef ZAPATA_PRI
static void zap_queue_frame ( struct zt_pvt * p , struct ast_frame * f , struct zt_pri * pri )
# else
static void zap_queue_frame ( struct zt_pvt * p , struct ast_frame * f , void * pri )
# endif
2004-06-14 21:18:52 +00:00
{
2004-09-10 18:47:13 +00:00
/* We must unlock the PRI to avoid the possibility of a deadlock */
# ifdef ZAPATA_PRI
if ( pri )
ast_mutex_unlock ( & pri - > lock ) ;
# endif
2004-06-14 21:18:52 +00:00
for ( ; ; ) {
if ( p - > owner ) {
if ( ast_mutex_trylock ( & p - > owner - > lock ) ) {
ast_mutex_unlock ( & p - > lock ) ;
usleep ( 1 ) ;
ast_mutex_lock ( & p - > lock ) ;
} else {
ast_queue_frame ( p - > owner , f ) ;
ast_mutex_unlock ( & p - > owner - > lock ) ;
break ;
}
} else
break ;
}
2004-09-10 18:47:13 +00:00
# ifdef ZAPATA_PRI
if ( pri )
ast_mutex_lock ( & pri - > lock ) ;
# endif
2004-06-14 21:18:52 +00:00
}
2005-02-25 17:32:37 +00:00
static int restore_gains ( struct zt_pvt * p ) ;
2003-02-07 19:23:19 +00:00
static void swap_subs ( struct zt_pvt * p , int a , int b )
{
int tchan ;
int tinthreeway ;
struct ast_channel * towner ;
ast_log ( LOG_DEBUG , " Swapping %d and %d \n " , a , b ) ;
tchan = p - > subs [ a ] . chan ;
towner = p - > subs [ a ] . owner ;
tinthreeway = p - > subs [ a ] . inthreeway ;
p - > subs [ a ] . chan = p - > subs [ b ] . chan ;
p - > subs [ a ] . owner = p - > subs [ b ] . owner ;
p - > subs [ a ] . inthreeway = p - > subs [ b ] . inthreeway ;
p - > subs [ b ] . chan = tchan ;
p - > subs [ b ] . owner = towner ;
p - > subs [ b ] . inthreeway = tinthreeway ;
2004-04-22 16:02:56 +00:00
if ( p - > subs [ a ] . owner )
2003-02-07 19:23:19 +00:00
p - > subs [ a ] . owner - > fds [ 0 ] = p - > subs [ a ] . zfd ;
2004-04-22 16:02:56 +00:00
if ( p - > subs [ b ] . owner )
2003-02-07 19:23:19 +00:00
p - > subs [ b ] . owner - > fds [ 0 ] = p - > subs [ b ] . zfd ;
2004-09-10 18:47:13 +00:00
wakeup_sub ( p , a , NULL ) ;
wakeup_sub ( p , b , NULL ) ;
2003-02-07 19:23:19 +00:00
}
static int zt_open ( char * fn )
{
int fd ;
int isnum ;
int chan = 0 ;
int bs ;
int x ;
isnum = 1 ;
for ( x = 0 ; x < strlen ( fn ) ; x + + ) {
if ( ! isdigit ( fn [ x ] ) ) {
isnum = 0 ;
break ;
}
}
if ( isnum ) {
chan = atoi ( fn ) ;
if ( chan < 1 ) {
ast_log ( LOG_WARNING , " Invalid channel number '%s' \n " , fn ) ;
return - 1 ;
}
fn = " /dev/zap/channel " ;
2001-10-09 02:06:21 +00:00
}
2003-02-07 19:23:19 +00:00
fd = open ( fn , O_RDWR | O_NONBLOCK ) ;
if ( fd < 0 ) {
ast_log ( LOG_WARNING , " Unable to open '%s': %s \n " , fn , strerror ( errno ) ) ;
2001-10-09 02:06:21 +00:00
return - 1 ;
2003-02-07 19:23:19 +00:00
}
if ( chan ) {
if ( ioctl ( fd , ZT_SPECIFY , & chan ) ) {
x = errno ;
close ( fd ) ;
errno = x ;
ast_log ( LOG_WARNING , " Unable to specify channel %d: %s \n " , chan , strerror ( errno ) ) ;
2001-10-09 02:06:21 +00:00
return - 1 ;
}
}
2003-02-07 19:23:19 +00:00
bs = READ_SIZE ;
if ( ioctl ( fd , ZT_SET_BLOCKSIZE , & bs ) = = - 1 ) return - 1 ;
return fd ;
}
static void zt_close ( int fd )
{
2004-10-23 22:00:40 +00:00
if ( fd > 0 )
close ( fd ) ;
2003-02-07 19:23:19 +00:00
}
int zt_setlinear ( int zfd , int linear )
{
int res ;
res = ioctl ( zfd , ZT_SETLINEAR , & linear ) ;
if ( res )
return res ;
2001-10-09 02:06:21 +00:00
return 0 ;
}
2003-02-07 19:23:19 +00:00
int zt_setlaw ( int zfd , int law )
2001-10-09 02:06:21 +00:00
{
2003-02-07 19:23:19 +00:00
int res ;
res = ioctl ( zfd , ZT_SETLAW , & law ) ;
if ( res )
return res ;
return 0 ;
}
static int alloc_sub ( struct zt_pvt * p , int x )
{
ZT_BUFFERINFO bi ;
int res ;
if ( p - > subs [ x ] . zfd < 0 ) {
p - > subs [ x ] . zfd = zt_open ( " /dev/zap/pseudo " ) ;
if ( p - > subs [ x ] . zfd > - 1 ) {
res = ioctl ( p - > subs [ x ] . zfd , ZT_GET_BUFINFO , & bi ) ;
if ( ! res ) {
bi . txbufpolicy = ZT_POLICY_IMMEDIATE ;
bi . rxbufpolicy = ZT_POLICY_IMMEDIATE ;
2003-10-24 18:22:45 +00:00
bi . numbufs = numbufs ;
2003-02-07 19:23:19 +00:00
res = ioctl ( p - > subs [ x ] . zfd , ZT_SET_BUFINFO , & bi ) ;
if ( res < 0 ) {
ast_log ( LOG_WARNING , " Unable to set buffer policy on channel %d \n " , x ) ;
}
} else
ast_log ( LOG_WARNING , " Unable to check buffer policy on channel %d \n " , x ) ;
if ( ioctl ( p - > subs [ x ] . zfd , ZT_CHANNO , & p - > subs [ x ] . chan ) = = 1 ) {
ast_log ( LOG_WARNING , " Unable to get channel number for pseudo channel on FD %d \n " , p - > subs [ x ] . zfd ) ;
zt_close ( p - > subs [ x ] . zfd ) ;
p - > subs [ x ] . zfd = - 1 ;
return - 1 ;
}
if ( option_debug )
ast_log ( LOG_DEBUG , " Allocated %s subchannel on FD %d channel %d \n " , subnames [ x ] , p - > subs [ x ] . zfd , p - > subs [ x ] . chan ) ;
return 0 ;
} else
ast_log ( LOG_WARNING , " Unable to open pseudo channel: %s \n " , strerror ( errno ) ) ;
return - 1 ;
}
ast_log ( LOG_WARNING , " %s subchannel of %d already in use \n " , subnames [ x ] , p - > channel ) ;
return - 1 ;
}
static int unalloc_sub ( struct zt_pvt * p , int x )
{
if ( ! x ) {
ast_log ( LOG_WARNING , " Trying to unalloc the real channel %d?!? \n " , p - > channel ) ;
return - 1 ;
}
ast_log ( LOG_DEBUG , " Released sub %d of channel %d \n " , x , p - > channel ) ;
if ( p - > subs [ x ] . zfd > - 1 ) {
zt_close ( p - > subs [ x ] . zfd ) ;
}
p - > subs [ x ] . zfd = - 1 ;
p - > subs [ x ] . linear = 0 ;
p - > subs [ x ] . chan = 0 ;
p - > subs [ x ] . owner = NULL ;
p - > subs [ x ] . inthreeway = 0 ;
2005-02-08 07:49:40 +00:00
p - > polarity = POLARITY_IDLE ;
2003-08-23 17:49:54 +00:00
memset ( & p - > subs [ x ] . curconf , 0 , sizeof ( p - > subs [ x ] . curconf ) ) ;
2001-10-09 02:06:21 +00:00
return 0 ;
}
static int zt_digit ( struct ast_channel * ast , char digit )
{
ZT_DIAL_OPERATION zo ;
struct zt_pvt * p ;
2003-02-07 19:23:19 +00:00
int res = 0 ;
int index ;
2005-03-04 06:47:24 +00:00
p = ast - > tech_pvt ;
2004-06-20 14:07:44 +00:00
ast_mutex_lock ( & p - > lock ) ;
2003-02-07 19:23:19 +00:00
index = zt_get_index ( ast , p , 0 ) ;
2004-12-11 23:00:20 +00:00
if ( ( index = = SUB_REAL ) & & p - > owner ) {
2003-03-25 19:08:46 +00:00
# ifdef ZAPATA_PRI
2004-06-20 06:53:53 +00:00
if ( p - > sig = = SIG_PRI & & ast - > _state = = AST_STATE_DIALING & & ( p - > proceeding < 2 ) ) {
if ( p - > setup_ack ) {
if ( ! pri_grab ( p , p - > pri ) ) {
pri_information ( p - > pri - > pri , p - > call , digit ) ;
pri_rel ( p - > pri ) ;
} else
ast_log ( LOG_WARNING , " Unable to grab PRI on span %d \n " , p - > span ) ;
} else if ( strlen ( p - > dialdest ) < sizeof ( p - > dialdest ) - 1 ) {
ast_log ( LOG_DEBUG , " Queueing digit '%c' since setup_ack not yet received \n " , digit ) ;
res = strlen ( p - > dialdest ) ;
p - > dialdest [ res + + ] = digit ;
p - > dialdest [ res ] = ' \0 ' ;
}
2003-03-24 22:12:11 +00:00
} else {
2003-03-25 19:08:46 +00:00
# else
{
# endif
2003-03-24 22:12:11 +00:00
zo . op = ZT_DIAL_OP_APPEND ;
zo . dialstr [ 0 ] = ' T ' ;
zo . dialstr [ 1 ] = digit ;
zo . dialstr [ 2 ] = 0 ;
if ( ( res = ioctl ( p - > subs [ SUB_REAL ] . zfd , ZT_DIAL , & zo ) ) )
ast_log ( LOG_WARNING , " Couldn't dial digit %c \n " , digit ) ;
else
p - > dialing = 1 ;
}
2003-02-07 19:23:19 +00:00
}
2004-06-20 14:07:44 +00:00
ast_mutex_unlock ( & p - > lock ) ;
2001-10-09 02:06:21 +00:00
return res ;
}
static char * events [ ] = {
2005-02-04 06:12:32 +00:00
" No event " ,
" On hook " ,
" Ring/Answered " ,
" Wink/Flash " ,
" Alarm " ,
" No more alarm " ,
2001-10-09 02:06:21 +00:00
" HDLC Abort " ,
" HDLC Overrun " ,
" HDLC Bad FCS " ,
" Dial Complete " ,
" Ringer On " ,
" Ringer Off " ,
2003-02-07 19:23:19 +00:00
" Hook Transition Complete " ,
" Bits Changed " ,
2005-02-04 06:12:32 +00:00
" Pulse Start " ,
2004-09-19 16:17:18 +00:00
" Timer Expired " ,
" Timer Ping " ,
2005-02-04 06:12:32 +00:00
" Polarity Reversal "
2001-10-09 02:06:21 +00:00
} ;
2003-02-28 06:00:18 +00:00
static struct {
int alarm ;
char * name ;
} alarms [ ] = {
{ ZT_ALARM_RED , " Red Alarm " } ,
{ ZT_ALARM_YELLOW , " Yellow Alarm " } ,
{ ZT_ALARM_BLUE , " Blue Alarm " } ,
{ ZT_ALARM_RECOVER , " Recovering " } ,
{ ZT_ALARM_LOOPBACK , " Loopback " } ,
{ ZT_ALARM_NOTOPEN , " Not Open " } ,
{ ZT_ALARM_NONE , " None " } ,
} ;
static char * alarm2str ( int alarm )
{
int x ;
for ( x = 0 ; x < sizeof ( alarms ) / sizeof ( alarms [ 0 ] ) ; x + + ) {
if ( alarms [ x ] . alarm & alarm )
return alarms [ x ] . name ;
}
return alarm ? " Unknown Alarm " : " No Alarm " ;
}
2001-10-09 02:06:21 +00:00
static char * event2str ( int event )
{
static char buf [ 256 ] ;
2004-09-19 16:17:18 +00:00
if ( ( event < 18 ) & & ( event > - 1 ) )
2001-10-09 02:06:21 +00:00
return events [ event ] ;
2004-07-16 04:40:54 +00:00
sprintf ( buf , " Event %d " , event ) ; /* safe */
2001-10-09 02:06:21 +00:00
return buf ;
}
2005-03-05 02:08:37 +00:00
# ifdef ZAPATA_PRI
2005-03-03 17:00:57 +00:00
static char * dialplan2str ( int dialplan )
{
if ( dialplan = = - 1 ) {
return ( " Dynamically set dialplan in ISDN " ) ;
}
return ( pri_plan2str ( dialplan ) ) ;
}
2005-03-05 02:08:37 +00:00
# endif
2005-03-03 17:00:57 +00:00
2003-02-07 19:23:19 +00:00
# ifdef ZAPATA_R2
static int str2r2prot ( char * swtype )
{
if ( ! strcasecmp ( swtype , " ar " ) )
return MFCR2_PROT_ARGENTINA ;
/*endif*/
if ( ! strcasecmp ( swtype , " cn " ) )
return MFCR2_PROT_CHINA ;
/*endif*/
if ( ! strcasecmp ( swtype , " kr " ) )
return MFCR2_PROT_KOREA ;
/*endif*/
return - 1 ;
}
# endif
2005-03-17 23:12:15 +00:00
static char * zap_sig2str ( int sig )
2001-10-09 02:06:21 +00:00
{
static char buf [ 256 ] ;
switch ( sig ) {
case SIG_EM :
return " E & M Immediate " ;
case SIG_EMWINK :
return " E & M Wink " ;
2004-04-16 18:00:00 +00:00
case SIG_EM_E1 :
return " E & M E1 " ;
2001-10-09 02:06:21 +00:00
case SIG_FEATD :
2002-06-24 17:59:56 +00:00
return " Feature Group D (DTMF) " ;
case SIG_FEATDMF :
return " Feature Group D (MF) " ;
2005-04-22 19:10:35 +00:00
case SIG_FEATDMF_TA :
return " Feature Groud D (MF) Tandem Access " ;
2002-06-24 17:59:56 +00:00
case SIG_FEATB :
return " Feature Group B (MF) " ;
2004-01-16 23:40:37 +00:00
case SIG_E911 :
return " E911 (MF) " ;
2001-10-09 02:06:21 +00:00
case SIG_FXSLS :
return " FXS Loopstart " ;
case SIG_FXSGS :
return " FXS Groundstart " ;
case SIG_FXSKS :
return " FXS Kewlstart " ;
case SIG_FXOLS :
return " FXO Loopstart " ;
case SIG_FXOGS :
return " FXO Groundstart " ;
case SIG_FXOKS :
return " FXO Kewlstart " ;
case SIG_PRI :
return " PRI Signalling " ;
2003-02-07 19:23:19 +00:00
case SIG_R2 :
return " R2 Signalling " ;
2003-03-17 18:11:33 +00:00
case SIG_SF :
2003-03-17 20:04:36 +00:00
return " SF (Tone) Signalling Immediate " ;
case SIG_SFWINK :
return " SF (Tone) Signalling Wink " ;
case SIG_SF_FEATD :
return " SF (Tone) Signalling with Feature Group D (DTMF) " ;
case SIG_SF_FEATDMF :
2004-01-16 23:40:37 +00:00
return " SF (Tone) Signalling with Feature Group D (MF) " ;
2003-03-17 20:04:36 +00:00
case SIG_SF_FEATB :
return " SF (Tone) Signalling with Feature Group B (MF) " ;
2004-06-05 06:54:52 +00:00
case SIG_GR303FXOKS :
return " GR-303 Signalling with FXOKS " ;
2004-06-29 11:45:51 +00:00
case SIG_GR303FXSKS :
return " GR-303 Signalling with FXSKS " ;
2002-06-24 17:59:56 +00:00
case 0 :
return " Pseudo Signalling " ;
2001-10-09 02:06:21 +00:00
default :
2002-06-24 17:59:56 +00:00
snprintf ( buf , sizeof ( buf ) , " Unknown signalling %d " , sig ) ;
2001-10-09 02:06:21 +00:00
return buf ;
}
}
2005-03-17 23:12:15 +00:00
# define sig2str zap_sig2str
2003-08-23 17:49:54 +00:00
static int conf_add ( struct zt_pvt * p , struct zt_subchannel * c , int index , int slavechannel )
2001-10-09 02:06:21 +00:00
{
2003-02-07 19:23:19 +00:00
/* If the conference already exists, and we're already in it
don ' t bother doing anything */
ZT_CONFINFO zi ;
2003-08-23 17:49:54 +00:00
memset ( & zi , 0 , sizeof ( zi ) ) ;
zi . chan = 0 ;
if ( slavechannel > 0 ) {
/* If we have only one slave, do a digital mon */
zi . confmode = ZT_CONF_DIGITALMON ;
zi . confno = slavechannel ;
} else {
if ( ! index ) {
/* Real-side and pseudo-side both participate in conference */
zi . confmode = ZT_CONF_REALANDPSEUDO | ZT_CONF_TALKER | ZT_CONF_LISTENER |
ZT_CONF_PSEUDO_TALKER | ZT_CONF_PSEUDO_LISTENER ;
} else
zi . confmode = ZT_CONF_CONF | ZT_CONF_TALKER | ZT_CONF_LISTENER ;
zi . confno = p - > confno ;
2003-02-07 19:23:19 +00:00
}
2003-08-23 17:49:54 +00:00
if ( ( zi . confno = = c - > curconf . confno ) & & ( zi . confmode = = c - > curconf . confmode ) )
return 0 ;
2003-02-07 19:23:19 +00:00
if ( c - > zfd < 0 )
return 0 ;
if ( ioctl ( c - > zfd , ZT_SETCONF , & zi ) ) {
2003-08-23 17:49:54 +00:00
ast_log ( LOG_WARNING , " Failed to add %d to conference %d/%d \n " , c - > zfd , zi . confmode , zi . confno ) ;
2001-10-09 02:06:21 +00:00
return - 1 ;
}
2003-08-23 17:49:54 +00:00
if ( slavechannel < 1 ) {
p - > confno = zi . confno ;
}
memcpy ( & c - > curconf , & zi , sizeof ( c - > curconf ) ) ;
ast_log ( LOG_DEBUG , " Added %d to conference %d/%d \n " , c - > zfd , c - > curconf . confmode , c - > curconf . confno ) ;
2001-10-09 02:06:21 +00:00
return 0 ;
}
2003-08-23 17:49:54 +00:00
static int isourconf ( struct zt_pvt * p , struct zt_subchannel * c )
{
/* If they're listening to our channel, they're ours */
if ( ( p - > channel = = c - > curconf . confno ) & & ( c - > curconf . confmode = = ZT_CONF_DIGITALMON ) )
return 1 ;
/* If they're a talker on our (allocated) conference, they're ours */
if ( ( p - > confno > 0 ) & & ( p - > confno = = c - > curconf . confno ) & & ( c - > curconf . confmode & ZT_CONF_TALKER ) )
return 1 ;
return 0 ;
}
static int conf_del ( struct zt_pvt * p , struct zt_subchannel * c , int index )
2001-10-09 02:06:21 +00:00
{
2003-02-07 19:23:19 +00:00
ZT_CONFINFO zi ;
2003-08-23 17:49:54 +00:00
if ( /* Can't delete if there's no zfd */
2003-02-07 19:23:19 +00:00
( c - > zfd < 0 ) | |
/* Don't delete from the conference if it's not our conference */
2003-08-23 17:49:54 +00:00
! isourconf ( p , c )
2003-02-07 19:23:19 +00:00
/* Don't delete if we don't think it's conferenced at all (implied) */
) return 0 ;
memset ( & zi , 0 , sizeof ( zi ) ) ;
zi . chan = 0 ;
zi . confno = 0 ;
zi . confmode = 0 ;
if ( ioctl ( c - > zfd , ZT_SETCONF , & zi ) ) {
2003-08-23 17:49:54 +00:00
ast_log ( LOG_WARNING , " Failed to drop %d from conference %d/%d \n " , c - > zfd , c - > curconf . confmode , c - > curconf . confno ) ;
2003-02-07 19:23:19 +00:00
return - 1 ;
}
2003-08-23 17:49:54 +00:00
ast_log ( LOG_DEBUG , " Removed %d from conference %d/%d \n " , c - > zfd , c - > curconf . confmode , c - > curconf . confno ) ;
memcpy ( & c - > curconf , & zi , sizeof ( c - > curconf ) ) ;
2003-02-07 19:23:19 +00:00
return 0 ;
2001-10-09 02:06:21 +00:00
}
2003-08-23 17:49:54 +00:00
static int isslavenative ( struct zt_pvt * p , struct zt_pvt * * out )
{
int x ;
int useslavenative ;
struct zt_pvt * slave = NULL ;
/* Start out optimistic */
useslavenative = 1 ;
/* Update conference state in a stateless fashion */
for ( x = 0 ; x < 3 ; x + + ) {
/* Any three-way calling makes slave native mode *definitely* out
of the question */
if ( ( p - > subs [ x ] . zfd > - 1 ) & & p - > subs [ x ] . inthreeway )
useslavenative = 0 ;
}
/* If we don't have any 3-way calls, check to see if we have
precisely one slave */
if ( useslavenative ) {
for ( x = 0 ; x < MAX_SLAVES ; x + + ) {
if ( p - > slaves [ x ] ) {
if ( slave ) {
/* Whoops already have a slave! No
slave native and stop right away */
slave = NULL ;
useslavenative = 0 ;
break ;
} else {
/* We have one slave so far */
slave = p - > slaves [ x ] ;
}
}
}
}
/* If no slave, slave native definitely out */
if ( ! slave )
useslavenative = 0 ;
else if ( slave - > law ! = p - > law ) {
useslavenative = 0 ;
slave = NULL ;
}
if ( out )
* out = slave ;
return useslavenative ;
}
2004-07-30 20:23:06 +00:00
static int reset_conf ( struct zt_pvt * p )
{
ZT_CONFINFO zi ;
2004-08-01 02:39:32 +00:00
memset ( & zi , 0 , sizeof ( zi ) ) ;
2004-07-30 20:23:06 +00:00
p - > confno = - 1 ;
2004-12-13 15:11:36 +00:00
memset ( & p - > subs [ SUB_REAL ] . curconf , 0 , sizeof ( p - > subs [ SUB_REAL ] . curconf ) ) ;
2004-07-30 20:23:06 +00:00
if ( p - > subs [ SUB_REAL ] . zfd > - 1 ) {
if ( ioctl ( p - > subs [ SUB_REAL ] . zfd , ZT_SETCONF , & zi ) )
ast_log ( LOG_WARNING , " Failed to reset conferencing on channel %d! \n " , p - > channel ) ;
}
return 0 ;
}
2003-02-07 19:23:19 +00:00
static int update_conf ( struct zt_pvt * p )
2001-10-09 02:06:21 +00:00
{
2003-02-07 19:23:19 +00:00
int needconf = 0 ;
int x ;
2003-08-23 17:49:54 +00:00
int useslavenative ;
struct zt_pvt * slave = NULL ;
useslavenative = isslavenative ( p , & slave ) ;
2003-02-07 19:23:19 +00:00
/* Start with the obvious, general stuff */
for ( x = 0 ; x < 3 ; x + + ) {
2003-08-23 17:49:54 +00:00
/* Look for three way calls */
2003-02-07 19:23:19 +00:00
if ( ( p - > subs [ x ] . zfd > - 1 ) & & p - > subs [ x ] . inthreeway ) {
2003-08-23 17:49:54 +00:00
conf_add ( p , & p - > subs [ x ] , x , 0 ) ;
2003-02-07 19:23:19 +00:00
needconf + + ;
} else {
2003-08-23 17:49:54 +00:00
conf_del ( p , & p - > subs [ x ] , x ) ;
2003-02-07 19:23:19 +00:00
}
2001-10-09 02:06:21 +00:00
}
2003-08-23 17:49:54 +00:00
/* If we have a slave, add him to our conference now. or DAX
if this is slave native */
2003-02-07 19:23:19 +00:00
for ( x = 0 ; x < MAX_SLAVES ; x + + ) {
if ( p - > slaves [ x ] ) {
2003-08-23 17:49:54 +00:00
if ( useslavenative )
2004-07-16 22:15:30 +00:00
conf_add ( p , & p - > slaves [ x ] - > subs [ SUB_REAL ] , SUB_REAL , GET_CHANNEL ( p ) ) ;
2003-08-23 17:49:54 +00:00
else {
conf_add ( p , & p - > slaves [ x ] - > subs [ SUB_REAL ] , SUB_REAL , 0 ) ;
needconf + + ;
}
2003-02-07 19:23:19 +00:00
}
}
/* If we're supposed to be in there, do so now */
if ( p - > inconference & & ! p - > subs [ SUB_REAL ] . inthreeway ) {
2003-08-23 17:49:54 +00:00
if ( useslavenative )
2004-07-16 22:15:30 +00:00
conf_add ( p , & p - > subs [ SUB_REAL ] , SUB_REAL , GET_CHANNEL ( slave ) ) ;
2003-08-23 17:49:54 +00:00
else {
conf_add ( p , & p - > subs [ SUB_REAL ] , SUB_REAL , 0 ) ;
needconf + + ;
}
2003-02-07 19:23:19 +00:00
}
/* If we have a master, add ourselves to his conference */
2003-08-23 17:49:54 +00:00
if ( p - > master ) {
if ( isslavenative ( p - > master , NULL ) ) {
2004-07-16 22:15:30 +00:00
conf_add ( p - > master , & p - > subs [ SUB_REAL ] , SUB_REAL , GET_CHANNEL ( p - > master ) ) ;
2003-08-23 17:49:54 +00:00
} else {
conf_add ( p - > master , & p - > subs [ SUB_REAL ] , SUB_REAL , 0 ) ;
}
}
2003-02-07 19:23:19 +00:00
if ( ! needconf ) {
/* Nobody is left (or should be left) in our conference.
Kill it . */
p - > confno = - 1 ;
}
ast_log ( LOG_DEBUG , " Updated conferencing on %d, with %d conference users \n " , p - > channel , needconf ) ;
2001-10-09 02:06:21 +00:00
return 0 ;
}
static void zt_enable_ec ( struct zt_pvt * p )
{
int x ;
int res ;
2004-11-07 16:21:01 +00:00
if ( ! p )
return ;
2003-02-07 19:23:19 +00:00
if ( p - > echocanon ) {
ast_log ( LOG_DEBUG , " Echo cancellation already on \n " ) ;
return ;
}
2004-11-07 16:21:01 +00:00
if ( p - > digital ) {
ast_log ( LOG_DEBUG , " Echo cancellation isn't required on digital connection \n " ) ;
return ;
}
if ( p - > echocancel ) {
2003-05-19 23:33:41 +00:00
if ( p - > sig = = SIG_PRI ) {
x = 1 ;
res = ioctl ( p - > subs [ SUB_REAL ] . zfd , ZT_AUDIOMODE , & x ) ;
if ( res )
ast_log ( LOG_WARNING , " Unable to enable echo cancellation on channel %d \n " , p - > channel ) ;
}
2002-03-08 23:48:42 +00:00
x = p - > echocancel ;
2003-02-07 19:23:19 +00:00
res = ioctl ( p - > subs [ SUB_REAL ] . zfd , ZT_ECHOCANCEL , & x ) ;
2001-10-09 02:06:21 +00:00
if ( res )
ast_log ( LOG_WARNING , " Unable to enable echo cancellation on channel %d \n " , p - > channel ) ;
2003-02-07 19:23:19 +00:00
else {
p - > echocanon = 1 ;
2001-10-09 02:06:21 +00:00
ast_log ( LOG_DEBUG , " Enabled echo cancellation on channel %d \n " , p - > channel ) ;
2003-02-07 19:23:19 +00:00
}
2002-03-08 23:48:42 +00:00
} else
2004-11-01 01:44:11 +00:00
ast_log ( LOG_DEBUG , " No echo cancellation requested \n " ) ;
2001-10-09 02:06:21 +00:00
}
2003-10-27 17:16:08 +00:00
static void zt_train_ec ( struct zt_pvt * p )
{
int x ;
int res ;
if ( p & & p - > echocancel & & p - > echotraining ) {
2004-06-23 22:00:04 +00:00
x = p - > echotraining ;
2003-10-27 17:16:08 +00:00
res = ioctl ( p - > subs [ SUB_REAL ] . zfd , ZT_ECHOTRAIN , & x ) ;
if ( res )
ast_log ( LOG_WARNING , " Unable to request echo training on channel %d \n " , p - > channel ) ;
else {
ast_log ( LOG_DEBUG , " Engaged echo training on channel %d \n " , p - > channel ) ;
}
} else
ast_log ( LOG_DEBUG , " No echo training requested \n " ) ;
}
2001-10-09 02:06:21 +00:00
static void zt_disable_ec ( struct zt_pvt * p )
{
int x ;
int res ;
if ( p - > echocancel ) {
x = 0 ;
2003-02-07 19:23:19 +00:00
res = ioctl ( p - > subs [ SUB_REAL ] . zfd , ZT_ECHOCANCEL , & x ) ;
2001-10-09 02:06:21 +00:00
if ( res )
ast_log ( LOG_WARNING , " Unable to disable echo cancellation on channel %d \n " , p - > channel ) ;
else
ast_log ( LOG_DEBUG , " disabled echo cancellation on channel %d \n " , p - > channel ) ;
}
2003-02-07 19:23:19 +00:00
p - > echocanon = 0 ;
2001-10-09 02:06:21 +00:00
}
2003-02-07 19:23:19 +00:00
int set_actual_gain ( int fd , int chan , float rxgain , float txgain , int law )
2001-10-09 02:06:21 +00:00
{
struct zt_gains g ;
float ltxgain ;
float lrxgain ;
int j , k ;
g . chan = chan ;
2003-03-20 16:58:45 +00:00
if ( ( rxgain ! = 0.0 ) | | ( txgain ! = 0.0 ) ) {
/* caluculate linear value of tx gain */
ltxgain = pow ( 10.0 , txgain / 20.0 ) ;
/* caluculate linear value of rx gain */
lrxgain = pow ( 10.0 , rxgain / 20.0 ) ;
if ( law = = ZT_LAW_ALAW ) {
for ( j = 0 ; j < 256 ; j + + ) {
k = ( int ) ( ( ( float ) AST_ALAW ( j ) ) * lrxgain ) ;
if ( k > 32767 ) k = 32767 ;
if ( k < - 32767 ) k = - 32767 ;
g . rxgain [ j ] = AST_LIN2A ( k ) ;
k = ( int ) ( ( ( float ) AST_ALAW ( j ) ) * ltxgain ) ;
if ( k > 32767 ) k = 32767 ;
if ( k < - 32767 ) k = - 32767 ;
g . txgain [ j ] = AST_LIN2A ( k ) ;
}
} else {
for ( j = 0 ; j < 256 ; j + + ) {
k = ( int ) ( ( ( float ) AST_MULAW ( j ) ) * lrxgain ) ;
if ( k > 32767 ) k = 32767 ;
if ( k < - 32767 ) k = - 32767 ;
g . rxgain [ j ] = AST_LIN2MU ( k ) ;
k = ( int ) ( ( ( float ) AST_MULAW ( j ) ) * ltxgain ) ;
if ( k > 32767 ) k = 32767 ;
if ( k < - 32767 ) k = - 32767 ;
g . txgain [ j ] = AST_LIN2MU ( k ) ;
}
2003-02-07 19:23:19 +00:00
}
} else {
for ( j = 0 ; j < 256 ; j + + ) {
2003-03-20 16:58:45 +00:00
g . rxgain [ j ] = j ;
g . txgain [ j ] = j ;
2003-02-07 19:23:19 +00:00
}
2001-10-09 02:06:21 +00:00
}
2003-03-20 16:58:45 +00:00
2001-10-09 02:06:21 +00:00
/* set 'em */
return ( ioctl ( fd , ZT_SETGAINS , & g ) ) ;
}
static inline int zt_set_hook ( int fd , int hs )
{
int x , res ;
x = hs ;
res = ioctl ( fd , ZT_HOOK , & x ) ;
if ( res < 0 )
2003-02-07 19:23:19 +00:00
{
if ( errno = = EINPROGRESS ) return 0 ;
2001-10-09 02:06:21 +00:00
ast_log ( LOG_WARNING , " zt hook failed: %s \n " , strerror ( errno ) ) ;
2003-02-07 19:23:19 +00:00
}
return res ;
}
static inline int zt_confmute ( struct zt_pvt * p , int muted )
{
2003-05-19 23:33:41 +00:00
int x , y , res ;
2003-02-07 19:23:19 +00:00
x = muted ;
2003-05-19 23:33:41 +00:00
if ( p - > sig = = SIG_PRI ) {
y = 1 ;
res = ioctl ( p - > subs [ SUB_REAL ] . zfd , ZT_AUDIOMODE , & y ) ;
if ( res )
ast_log ( LOG_WARNING , " Unable to set audio mode on '%d' \n " , p - > channel ) ;
}
2003-02-07 19:23:19 +00:00
res = ioctl ( p - > subs [ SUB_REAL ] . zfd , ZT_CONFMUTE , & x ) ;
if ( res < 0 )
ast_log ( LOG_WARNING , " zt confmute(%d) failed on channel %d: %s \n " , muted , p - > channel , strerror ( errno ) ) ;
2001-10-09 02:06:21 +00:00
return res ;
}
static int save_conference ( struct zt_pvt * p )
{
struct zt_confinfo c ;
int res ;
2003-02-07 19:23:19 +00:00
if ( p - > saveconf . confmode ) {
2001-10-09 02:06:21 +00:00
ast_log ( LOG_WARNING , " Can't save conference -- already in use \n " ) ;
return - 1 ;
}
2003-02-07 19:23:19 +00:00
p - > saveconf . chan = 0 ;
res = ioctl ( p - > subs [ SUB_REAL ] . zfd , ZT_GETCONF , & p - > saveconf ) ;
2001-10-09 02:06:21 +00:00
if ( res ) {
ast_log ( LOG_WARNING , " Unable to get conference info: %s \n " , strerror ( errno ) ) ;
2003-02-07 19:23:19 +00:00
p - > saveconf . confmode = 0 ;
2001-10-09 02:06:21 +00:00
return - 1 ;
}
c . chan = 0 ;
c . confno = 0 ;
c . confmode = ZT_CONF_NORMAL ;
2003-02-07 19:23:19 +00:00
res = ioctl ( p - > subs [ SUB_REAL ] . zfd , ZT_SETCONF , & c ) ;
2001-10-09 02:06:21 +00:00
if ( res ) {
ast_log ( LOG_WARNING , " Unable to set conference info: %s \n " , strerror ( errno ) ) ;
return - 1 ;
}
if ( option_debug )
ast_log ( LOG_DEBUG , " Disabled conferencing \n " ) ;
return 0 ;
}
static int restore_conference ( struct zt_pvt * p )
{
int res ;
2003-02-07 19:23:19 +00:00
if ( p - > saveconf . confmode ) {
res = ioctl ( p - > subs [ SUB_REAL ] . zfd , ZT_SETCONF , & p - > saveconf ) ;
p - > saveconf . confmode = 0 ;
2001-10-09 02:06:21 +00:00
if ( res ) {
ast_log ( LOG_WARNING , " Unable to restore conference info: %s \n " , strerror ( errno ) ) ;
return - 1 ;
}
}
if ( option_debug )
ast_log ( LOG_DEBUG , " Restored conferencing \n " ) ;
return 0 ;
}
static int send_callerid ( struct zt_pvt * p ) ;
int send_cwcidspill ( struct zt_pvt * p )
{
p - > callwaitcas = 0 ;
2003-02-07 19:23:19 +00:00
p - > cidcwexpire = 0 ;
2001-10-09 02:06:21 +00:00
p - > cidspill = malloc ( MAX_CALLERID_SIZE ) ;
if ( p - > cidspill ) {
memset ( p - > cidspill , 0x7f , MAX_CALLERID_SIZE ) ;
2004-10-02 00:58:31 +00:00
p - > cidlen = ast_callerid_callwaiting_generate ( p - > cidspill , p - > callwait_name , p - > callwait_num , AST_LAW ( p ) ) ;
2001-10-09 02:06:21 +00:00
/* Make sure we account for the end */
p - > cidlen + = READ_SIZE * 4 ;
p - > cidpos = 0 ;
send_callerid ( p ) ;
if ( option_verbose > 2 )
2004-10-02 00:58:31 +00:00
ast_verbose ( VERBOSE_PREFIX_3 " CPE supports Call Waiting Caller*ID. Sending '%s/%s' \n " , p - > callwait_name , p - > callwait_num ) ;
2001-10-09 02:06:21 +00:00
} else return - 1 ;
return 0 ;
}
2002-03-08 23:48:42 +00:00
static int has_voicemail ( struct zt_pvt * p )
{
2004-10-03 21:18:27 +00:00
return ast_app_has_voicemail ( p - > mailbox , NULL ) ;
2002-03-08 23:48:42 +00:00
}
2001-10-09 02:06:21 +00:00
static int send_callerid ( struct zt_pvt * p )
{
/* Assumes spill in p->cidspill, p->cidlen in length and we're p->cidpos into it */
int res ;
2003-02-07 19:23:19 +00:00
/* Take out of linear mode if necessary */
if ( p - > subs [ SUB_REAL ] . linear ) {
p - > subs [ SUB_REAL ] . linear = 0 ;
zt_setlinear ( p - > subs [ SUB_REAL ] . zfd , 0 ) ;
}
2001-10-09 02:06:21 +00:00
while ( p - > cidpos < p - > cidlen ) {
2003-02-07 19:23:19 +00:00
res = write ( p - > subs [ SUB_REAL ] . zfd , p - > cidspill + p - > cidpos , p - > cidlen - p - > cidpos ) ;
2001-10-09 02:06:21 +00:00
if ( res < 0 ) {
if ( errno = = EAGAIN )
return 0 ;
else {
ast_log ( LOG_WARNING , " write failed: %s \n " , strerror ( errno ) ) ;
return - 1 ;
}
}
if ( ! res )
return 0 ;
p - > cidpos + = res ;
}
free ( p - > cidspill ) ;
2003-02-07 19:23:19 +00:00
p - > cidspill = NULL ;
2001-10-09 02:06:21 +00:00
if ( p - > callwaitcas ) {
2003-02-07 19:23:19 +00:00
/* Wait for CID/CW to expire */
p - > cidcwexpire = CIDCW_EXPIRE_SAMPLES ;
2001-10-09 02:06:21 +00:00
} else
restore_conference ( p ) ;
return 0 ;
}
static int zt_callwait ( struct ast_channel * ast )
{
2005-03-04 06:47:24 +00:00
struct zt_pvt * p = ast - > tech_pvt ;
2001-10-09 02:06:21 +00:00
p - > callwaitingrepeat = CALLWAITING_REPEAT_SAMPLES ;
if ( p - > cidspill ) {
ast_log ( LOG_WARNING , " Spill already exists?!? \n " ) ;
free ( p - > cidspill ) ;
}
p - > cidspill = malloc ( 2400 /* SAS */ + 680 /* CAS */ + READ_SIZE * 4 ) ;
if ( p - > cidspill ) {
save_conference ( p ) ;
/* Silence */
memset ( p - > cidspill , 0x7f , 2400 + 600 + READ_SIZE * 4 ) ;
if ( ! p - > callwaitrings & & p - > callwaitingcallerid ) {
2003-02-07 19:23:19 +00:00
ast_gen_cas ( p - > cidspill , 1 , 2400 + 680 , AST_LAW ( p ) ) ;
2001-10-09 02:06:21 +00:00
p - > callwaitcas = 1 ;
p - > cidlen = 2400 + 680 + READ_SIZE * 4 ;
} else {
2003-02-07 19:23:19 +00:00
ast_gen_cas ( p - > cidspill , 1 , 2400 , AST_LAW ( p ) ) ;
2001-10-09 02:06:21 +00:00
p - > callwaitcas = 0 ;
p - > cidlen = 2400 + READ_SIZE * 4 ;
}
p - > cidpos = 0 ;
send_callerid ( p ) ;
} else {
ast_log ( LOG_WARNING , " Unable to create SAS/CAS spill \n " ) ;
return - 1 ;
}
return 0 ;
}
2003-02-07 19:23:19 +00:00
static int zt_call ( struct ast_channel * ast , char * rdest , int timeout )
2001-10-09 02:06:21 +00:00
{
2005-03-04 06:47:24 +00:00
struct zt_pvt * p = ast - > tech_pvt ;
2001-10-09 02:06:21 +00:00
int x , res , index ;
char * c , * n , * l ;
2003-11-04 02:40:09 +00:00
# ifdef ZAPATA_PRI
2004-07-19 16:00:40 +00:00
char * s = NULL ;
2003-11-04 02:40:09 +00:00
# endif
2004-01-16 23:40:37 +00:00
char dest [ 256 ] ; /* must be same length as p->dialdest */
2004-05-07 21:22:46 +00:00
ast_mutex_lock ( & p - > lock ) ;
2005-05-15 23:26:45 +00:00
ast_copy_string ( dest , rdest , sizeof ( dest ) ) ;
ast_copy_string ( p - > dialdest , rdest , sizeof ( p - > dialdest ) ) ;
2004-06-23 03:16:58 +00:00
if ( ( ast - > _state = = AST_STATE_BUSY ) ) {
2004-06-23 03:19:32 +00:00
p - > subs [ SUB_REAL ] . needbusy = 1 ;
2004-06-23 03:16:58 +00:00
ast_mutex_unlock ( & p - > lock ) ;
return 0 ;
}
2002-09-10 04:45:51 +00:00
if ( ( ast - > _state ! = AST_STATE_DOWN ) & & ( ast - > _state ! = AST_STATE_RESERVED ) ) {
2001-10-09 02:06:21 +00:00
ast_log ( LOG_WARNING , " zt_call called on %s, neither down nor reserved \n " , ast - > name ) ;
2004-05-07 21:22:46 +00:00
ast_mutex_unlock ( & p - > lock ) ;
2001-10-09 02:06:21 +00:00
return - 1 ;
}
2001-12-29 18:04:21 +00:00
p - > dialednone = 0 ;
2003-02-07 19:23:19 +00:00
if ( p - > radio ) /* if a radio channel, up immediately */
{
/* Special pseudo -- automatically up */
ast_setstate ( ast , AST_STATE_UP ) ;
2004-05-07 21:22:46 +00:00
ast_mutex_unlock ( & p - > lock ) ;
2003-02-07 19:23:19 +00:00
return 0 ;
}
x = ZT_FLUSH_READ | ZT_FLUSH_WRITE ;
res = ioctl ( p - > subs [ SUB_REAL ] . zfd , ZT_FLUSH , & x ) ;
if ( res )
ast_log ( LOG_WARNING , " Unable to flush input on channel %d \n " , p - > channel ) ;
p - > outgoing = 1 ;
2003-10-22 04:04:59 +00:00
set_actual_gain ( p - > subs [ SUB_REAL ] . zfd , 0 , p - > rxgain , p - > txgain , p - > law ) ;
2001-10-09 02:06:21 +00:00
switch ( p - > sig ) {
case SIG_FXOLS :
case SIG_FXOGS :
case SIG_FXOKS :
if ( p - > owner = = ast ) {
/* Normal ring, on hook */
2002-09-10 04:45:51 +00:00
/* Don't send audio while on hook, until the call is answered */
p - > dialing = 1 ;
2001-10-09 02:06:21 +00:00
if ( p - > use_callerid ) {
/* Generate the Caller-ID spill if desired */
if ( p - > cidspill ) {
ast_log ( LOG_WARNING , " cidspill already exists?? \n " ) ;
free ( p - > cidspill ) ;
}
p - > cidspill = malloc ( MAX_CALLERID_SIZE ) ;
p - > callwaitcas = 0 ;
if ( p - > cidspill ) {
2004-10-02 00:58:31 +00:00
p - > cidlen = ast_callerid_generate ( p - > cidspill , ast - > cid . cid_name , ast - > cid . cid_num , AST_LAW ( p ) ) ;
2001-10-09 02:06:21 +00:00
p - > cidpos = 0 ;
send_callerid ( p ) ;
} else
ast_log ( LOG_WARNING , " Unable to generate CallerID spill \n " ) ;
}
2004-04-25 22:37:09 +00:00
/* Choose proper cadence */
2004-02-23 05:02:24 +00:00
if ( ( p - > distinctivering > 0 ) & & ( p - > distinctivering < = num_cadence ) ) {
2003-02-07 19:23:19 +00:00
if ( ioctl ( p - > subs [ SUB_REAL ] . zfd , ZT_SETCADENCE , & cadences [ p - > distinctivering - 1 ] ) )
2002-06-24 17:59:56 +00:00
ast_log ( LOG_WARNING , " Unable to set distinctive ring cadence %d on '%s' \n " , p - > distinctivering , ast - > name ) ;
p - > cidrings = cidrings [ p - > distinctivering - 1 ] ;
} else {
2003-02-07 19:23:19 +00:00
if ( ioctl ( p - > subs [ SUB_REAL ] . zfd , ZT_SETCADENCE , NULL ) )
2002-06-24 17:59:56 +00:00
ast_log ( LOG_WARNING , " Unable to reset default ring on '%s' \n " , ast - > name ) ;
2004-12-28 21:32:25 +00:00
p - > cidrings = p - > sendcalleridafter ;
2002-06-24 17:59:56 +00:00
}
2003-04-10 21:14:54 +00:00
/* nick@dccinc.com 4/3/03 mods to allow for deferred dialing */
c = strchr ( dest , ' / ' ) ;
if ( c )
2004-06-02 16:13:25 +00:00
c + + ;
2003-04-10 21:14:54 +00:00
if ( c & & ( strlen ( c ) < p - > stripmsd ) ) {
2004-06-02 16:13:25 +00:00
ast_log ( LOG_WARNING , " Number '%s' is shorter than stripmsd (%d) \n " , c , p - > stripmsd ) ;
c = NULL ;
2003-04-10 21:14:54 +00:00
}
if ( c ) {
p - > dop . op = ZT_DIAL_OP_REPLACE ;
2003-04-11 18:03:59 +00:00
snprintf ( p - > dop . dialstr , sizeof ( p - > dop . dialstr ) , " Tw%s " , c ) ;
2003-04-10 21:14:54 +00:00
ast_log ( LOG_DEBUG , " FXO: setup deferred dialstring: %s \n " , c ) ;
} else {
2004-07-16 04:40:54 +00:00
p - > dop . dialstr [ 0 ] = ' \0 ' ;
2003-04-10 21:14:54 +00:00
}
2001-10-09 02:06:21 +00:00
x = ZT_RING ;
2003-02-07 19:23:19 +00:00
if ( ioctl ( p - > subs [ SUB_REAL ] . zfd , ZT_HOOK , & x ) & & ( errno ! = EINPROGRESS ) ) {
2001-10-09 02:06:21 +00:00
ast_log ( LOG_WARNING , " Unable to ring phone: %s \n " , strerror ( errno ) ) ;
2004-05-07 21:22:46 +00:00
ast_mutex_unlock ( & p - > lock ) ;
2001-10-09 02:06:21 +00:00
return - 1 ;
}
p - > dialing = 1 ;
} else {
/* Call waiting call */
p - > callwaitrings = 0 ;
2004-10-02 00:58:31 +00:00
if ( ast - > cid . cid_num )
2005-05-15 23:26:45 +00:00
ast_copy_string ( p - > callwait_num , ast - > cid . cid_num , sizeof ( p - > callwait_num ) ) ;
2001-10-09 02:06:21 +00:00
else
2004-10-02 00:58:31 +00:00
p - > callwait_num [ 0 ] = ' \0 ' ;
if ( ast - > cid . cid_name )
2005-05-15 23:26:45 +00:00
ast_copy_string ( p - > callwait_name , ast - > cid . cid_name , sizeof ( p - > callwait_name ) ) ;
2004-10-02 00:58:31 +00:00
else
p - > callwait_name [ 0 ] = ' \0 ' ;
2001-10-09 02:06:21 +00:00
/* Call waiting tone instead */
2004-05-07 21:22:46 +00:00
if ( zt_callwait ( ast ) ) {
ast_mutex_unlock ( & p - > lock ) ;
2001-10-09 02:06:21 +00:00
return - 1 ;
2004-05-07 21:22:46 +00:00
}
2003-02-07 19:23:19 +00:00
/* Make ring-back */
if ( tone_zone_play_tone ( p - > subs [ SUB_CALLWAIT ] . zfd , ZT_TONE_RINGTONE ) )
ast_log ( LOG_WARNING , " Unable to generate call-wait ring-back on channel %s \n " , ast - > name ) ;
2001-10-09 02:06:21 +00:00
}
2004-10-02 00:58:31 +00:00
n = ast - > cid . cid_name ;
l = ast - > cid . cid_num ;
2003-02-07 19:23:19 +00:00
if ( l )
2005-05-15 23:26:45 +00:00
ast_copy_string ( p - > lastcid_num , l , sizeof ( p - > lastcid_num ) ) ;
2004-10-02 00:58:31 +00:00
else
p - > lastcid_num [ 0 ] = ' \0 ' ;
if ( n )
2005-05-15 23:26:45 +00:00
ast_copy_string ( p - > lastcid_name , n , sizeof ( p - > lastcid_name ) ) ;
2003-02-07 19:23:19 +00:00
else
2004-10-02 00:58:31 +00:00
p - > lastcid_name [ 0 ] = ' \0 ' ;
2002-09-10 04:45:51 +00:00
ast_setstate ( ast , AST_STATE_RINGING ) ;
2001-10-09 02:06:21 +00:00
index = zt_get_index ( ast , p , 0 ) ;
if ( index > - 1 ) {
2003-02-07 19:23:19 +00:00
p - > subs [ index ] . needringing = 1 ;
2001-10-09 02:06:21 +00:00
}
break ;
case SIG_FXSLS :
case SIG_FXSGS :
case SIG_FXSKS :
case SIG_EMWINK :
case SIG_EM :
2004-04-16 18:00:00 +00:00
case SIG_EM_E1 :
2001-10-09 02:06:21 +00:00
case SIG_FEATD :
2002-06-24 17:59:56 +00:00
case SIG_FEATDMF :
2004-01-16 23:40:37 +00:00
case SIG_E911 :
2002-06-24 17:59:56 +00:00
case SIG_FEATB :
2003-03-17 20:04:36 +00:00
case SIG_SFWINK :
case SIG_SF :
case SIG_SF_FEATD :
case SIG_SF_FEATDMF :
2005-04-22 19:10:35 +00:00
case SIG_FEATDMF_TA :
2003-03-17 20:04:36 +00:00
case SIG_SF_FEATB :
2001-10-09 02:06:21 +00:00
c = strchr ( dest , ' / ' ) ;
if ( c )
c + + ;
else
2004-04-19 22:55:35 +00:00
c = " " ;
2001-10-09 02:06:21 +00:00
if ( strlen ( c ) < p - > stripmsd ) {
ast_log ( LOG_WARNING , " Number '%s' is shorter than stripmsd (%d) \n " , c , p - > stripmsd ) ;
2004-05-07 21:22:46 +00:00
ast_mutex_unlock ( & p - > lock ) ;
2001-10-09 02:06:21 +00:00
return - 1 ;
}
2004-07-19 05:00:05 +00:00
# ifdef ZAPATA_PRI
2004-07-19 02:18:11 +00:00
/* Start the trunk, if not GR-303 */
if ( ! p - > pri ) {
2004-07-19 05:00:05 +00:00
# endif
2004-07-19 02:18:11 +00:00
x = ZT_START ;
res = ioctl ( p - > subs [ SUB_REAL ] . zfd , ZT_HOOK , & x ) ;
if ( res < 0 ) {
if ( errno ! = EINPROGRESS ) {
ast_log ( LOG_WARNING , " Unable to start channel: %s \n " , strerror ( errno ) ) ;
ast_mutex_unlock ( & p - > lock ) ;
return - 1 ;
}
2001-10-09 02:06:21 +00:00
}
2004-07-19 05:00:05 +00:00
# ifdef ZAPATA_PRI
2001-10-09 02:06:21 +00:00
}
2004-07-19 05:00:05 +00:00
# endif
2001-10-09 02:06:21 +00:00
ast_log ( LOG_DEBUG , " Dialing '%s' \n " , c ) ;
p - > dop . op = ZT_DIAL_OP_REPLACE ;
if ( p - > sig = = SIG_FEATD ) {
2004-10-02 00:58:31 +00:00
l = ast - > cid . cid_num ;
2001-10-09 02:06:21 +00:00
if ( l )
snprintf ( p - > dop . dialstr , sizeof ( p - > dop . dialstr ) , " T*%s*%s* " , l , c + p - > stripmsd ) ;
else
snprintf ( p - > dop . dialstr , sizeof ( p - > dop . dialstr ) , " T**%s* " , c + p - > stripmsd ) ;
2002-06-24 17:59:56 +00:00
} else
if ( p - > sig = = SIG_FEATDMF ) {
2004-10-02 00:58:31 +00:00
l = ast - > cid . cid_num ;
2002-06-24 17:59:56 +00:00
if ( l )
snprintf ( p - > dop . dialstr , sizeof ( p - > dop . dialstr ) , " M*00%s#*%s# " , l , c + p - > stripmsd ) ;
else
snprintf ( p - > dop . dialstr , sizeof ( p - > dop . dialstr ) , " M*02#*%s# " , c + p - > stripmsd ) ;
} else
2005-04-22 19:10:35 +00:00
if ( p - > sig = = SIG_FEATDMF_TA ) {
char * cic = NULL , * ozz = NULL ;
/* If you have to go through a Tandem Access point you need to use this */
ozz = pbx_builtin_getvar_helper ( p - > owner , " FEATDMF_OZZ " ) ;
if ( ! ozz )
ozz = defaultozz ;
cic = pbx_builtin_getvar_helper ( p - > owner , " FEATDMF_CIC " ) ;
if ( ! cic )
cic = defaultcic ;
if ( ! ozz | | ! cic ) {
ast_log ( LOG_WARNING , " Unable to dial channel of type feature group D MF tandem access without CIC or OZZ set \n " ) ;
ast_mutex_unlock ( & p - > lock ) ;
return - 1 ;
}
snprintf ( p - > dop . dialstr , sizeof ( p - > dop . dialstr ) , " M*%s%s# " , ozz , cic ) ;
snprintf ( p - > finaldial , sizeof ( p - > finaldial ) , " M*%s# " , c + p - > stripmsd ) ;
p - > whichwink = 0 ;
} else
2004-01-16 23:40:37 +00:00
if ( p - > sig = = SIG_E911 ) {
2005-05-15 23:26:45 +00:00
ast_copy_string ( p - > dop . dialstr , " M*911# " , sizeof ( p - > dop . dialstr ) ) ;
2004-01-16 23:40:37 +00:00
} else
2002-06-24 17:59:56 +00:00
if ( p - > sig = = SIG_FEATB ) {
snprintf ( p - > dop . dialstr , sizeof ( p - > dop . dialstr ) , " M*%s# " , c + p - > stripmsd ) ;
2001-10-09 02:06:21 +00:00
} else
2004-09-13 23:07:50 +00:00
if ( p - > pulse )
snprintf ( p - > dop . dialstr , sizeof ( p - > dop . dialstr ) , " P%sw " , c + p - > stripmsd ) ;
else
2003-11-05 22:32:20 +00:00
snprintf ( p - > dop . dialstr , sizeof ( p - > dop . dialstr ) , " T%sw " , c + p - > stripmsd ) ;
2004-08-20 21:07:10 +00:00
if ( p - > echotraining & & ( strlen ( p - > dop . dialstr ) > 4 ) ) {
2004-06-23 22:00:04 +00:00
memset ( p - > echorest , ' w ' , sizeof ( p - > echorest ) - 1 ) ;
strcpy ( p - > echorest + ( p - > echotraining / 400 ) + 1 , p - > dop . dialstr + strlen ( p - > dop . dialstr ) - 2 ) ;
2004-07-16 04:40:54 +00:00
p - > echorest [ sizeof ( p - > echorest ) - 1 ] = ' \0 ' ;
2003-11-05 22:32:20 +00:00
p - > echobreak = 1 ;
p - > dop . dialstr [ strlen ( p - > dop . dialstr ) - 2 ] = ' \0 ' ;
} else
p - > echobreak = 0 ;
2001-10-09 02:06:21 +00:00
if ( ! res ) {
2003-02-07 19:23:19 +00:00
if ( ioctl ( p - > subs [ SUB_REAL ] . zfd , ZT_DIAL , & p - > dop ) ) {
2001-10-09 02:06:21 +00:00
x = ZT_ONHOOK ;
2003-02-07 19:23:19 +00:00
ioctl ( p - > subs [ SUB_REAL ] . zfd , ZT_HOOK , & x ) ;
2001-10-09 02:06:21 +00:00
ast_log ( LOG_WARNING , " Dialing failed on channel %d: %s \n " , p - > channel , strerror ( errno ) ) ;
2004-05-07 21:22:46 +00:00
ast_mutex_unlock ( & p - > lock ) ;
2001-10-09 02:06:21 +00:00
return - 1 ;
}
} else
ast_log ( LOG_DEBUG , " Deferring dialing... \n " ) ;
p - > dialing = 1 ;
2001-12-29 18:04:21 +00:00
if ( strlen ( c + p - > stripmsd ) < 1 ) p - > dialednone = 1 ;
2002-09-10 04:45:51 +00:00
ast_setstate ( ast , AST_STATE_DIALING ) ;
2001-10-09 02:06:21 +00:00
break ;
2004-06-06 01:54:22 +00:00
case 0 :
/* Special pseudo -- automatically up*/
ast_setstate ( ast , AST_STATE_UP ) ;
break ;
2001-10-09 02:06:21 +00:00
case SIG_PRI :
2004-06-20 06:53:53 +00:00
/* We'll get it in a moment -- but use dialdest to store pre-setup_ack digits */
2004-07-16 04:40:54 +00:00
p - > dialdest [ 0 ] = ' \0 ' ;
2004-06-06 01:54:22 +00:00
break ;
default :
ast_log ( LOG_DEBUG , " not yet implemented \n " ) ;
ast_mutex_unlock ( & p - > lock ) ;
return - 1 ;
}
# ifdef ZAPATA_PRI
if ( p - > pri ) {
2004-06-16 15:34:21 +00:00
struct pri_sr * sr ;
2005-03-03 17:00:57 +00:00
int pridialplan ;
int dp_strip ;
int prilocaldialplan ;
int ldp_strip ;
2001-10-09 02:06:21 +00:00
c = strchr ( dest , ' / ' ) ;
if ( c )
c + + ;
else
c = dest ;
2004-10-02 00:58:31 +00:00
if ( ! p - > hidecallerid ) {
l = ast - > cid . cid_num ;
n = ast - > cid . cid_name ;
} else {
2001-10-09 02:06:21 +00:00
l = NULL ;
2004-10-02 00:58:31 +00:00
n = NULL ;
}
2001-10-09 02:06:21 +00:00
if ( strlen ( c ) < p - > stripmsd ) {
ast_log ( LOG_WARNING , " Number '%s' is shorter than stripmsd (%d) \n " , c , p - > stripmsd ) ;
2004-05-07 21:22:46 +00:00
ast_mutex_unlock ( & p - > lock ) ;
2001-10-09 02:06:21 +00:00
return - 1 ;
}
2004-07-19 02:18:11 +00:00
if ( p - > sig ! = SIG_FXSKS ) {
p - > dop . op = ZT_DIAL_OP_REPLACE ;
s = strchr ( c + p - > stripmsd , ' w ' ) ;
if ( s ) {
2005-04-06 19:17:21 +00:00
if ( strlen ( s ) > 1 )
2004-07-19 02:18:11 +00:00
snprintf ( p - > dop . dialstr , sizeof ( p - > dop . dialstr ) , " T%s " , s ) ;
else
p - > dop . dialstr [ 0 ] = ' \0 ' ;
* s = ' \0 ' ;
2005-04-06 19:17:21 +00:00
s + + ;
2004-07-19 02:18:11 +00:00
} else {
2004-07-16 04:40:54 +00:00
p - > dop . dialstr [ 0 ] = ' \0 ' ;
2004-07-19 02:18:11 +00:00
}
2003-02-07 19:23:19 +00:00
}
2004-05-07 21:22:46 +00:00
if ( pri_grab ( p , p - > pri ) ) {
ast_log ( LOG_WARNING , " Failed to grab PRI! \n " ) ;
2004-05-08 14:24:58 +00:00
ast_mutex_unlock ( & p - > lock ) ;
2004-05-07 21:22:46 +00:00
return - 1 ;
}
2003-03-16 06:00:11 +00:00
if ( ! ( p - > call = pri_new_call ( p - > pri - > pri ) ) ) {
ast_log ( LOG_WARNING , " Unable to create call on channel %d \n " , p - > channel ) ;
2004-05-07 21:22:46 +00:00
pri_rel ( p - > pri ) ;
ast_mutex_unlock ( & p - > lock ) ;
2003-03-16 06:00:11 +00:00
return - 1 ;
}
2004-06-16 15:34:21 +00:00
if ( ! ( sr = pri_sr_new ( ) ) ) {
ast_log ( LOG_WARNING , " Failed to allocate setup request channel %d \n " , p - > channel ) ;
pri_rel ( p - > pri ) ;
ast_mutex_unlock ( & p - > lock ) ;
}
2004-07-19 02:18:11 +00:00
if ( p - > bearer | | ( p - > sig = = SIG_FXSKS ) ) {
if ( p - > bearer ) {
ast_log ( LOG_DEBUG , " Oooh, I have a bearer on %d (%d:%d) \n " , PVT_TO_CHANNEL ( p - > bearer ) , p - > bearer - > logicalspan , p - > bearer - > channel ) ;
p - > bearer - > call = p - > call ;
} else
ast_log ( LOG_DEBUG , " I'm being setup with no bearer right now... \n " ) ;
2004-06-06 01:54:22 +00:00
pri_set_crv ( p - > pri - > pri , p - > call , p - > channel , 0 ) ;
}
2005-04-01 17:00:50 +00:00
p - > digital = IS_DIGITAL ( ast - > transfercapability ) ;
2004-06-16 15:34:21 +00:00
pri_sr_set_channel ( sr , p - > bearer ? PVT_TO_CHANNEL ( p - > bearer ) : PVT_TO_CHANNEL ( p ) ,
p - > pri - > nodetype = = PRI_NETWORK ? 0 : 1 , 1 ) ;
2005-04-01 17:00:50 +00:00
pri_sr_set_bearer ( sr , p - > digital ? PRI_TRANS_CAP_DIGITAL : ast - > transfercapability ,
2004-06-16 15:34:21 +00:00
( p - > digital ? - 1 :
( ( p - > law = = ZT_LAW_ALAW ) ? PRI_LAYER_1_ALAW : PRI_LAYER_1_ULAW ) ) ) ;
2005-05-12 15:05:25 +00:00
if ( p - > pri - > facilityenable )
pri_facility_enable ( p - > pri - > pri ) ;
2005-04-01 17:00:50 +00:00
if ( option_verbose > 2 )
ast_verbose ( VERBOSE_PREFIX_3 " Requested transfer capability: 0x%.2x - %s \n " , ast - > transfercapability , ast_transfercapability2str ( ast - > transfercapability ) ) ;
dp_strip = 0 ;
2005-03-03 17:00:57 +00:00
pridialplan = p - > pri - > dialplan - 1 ;
if ( pridialplan = = - 2 ) { /* compute dynamically */
if ( strncmp ( c + p - > stripmsd , p - > pri - > internationalprefix , strlen ( p - > pri - > internationalprefix ) ) = = 0 ) {
dp_strip = strlen ( p - > pri - > internationalprefix ) ;
pridialplan = PRI_INTERNATIONAL_ISDN ;
} else if ( strncmp ( c + p - > stripmsd , p - > pri - > nationalprefix , strlen ( p - > pri - > nationalprefix ) ) = = 0 ) {
dp_strip = strlen ( p - > pri - > nationalprefix ) ;
pridialplan = PRI_NATIONAL_ISDN ;
} else {
pridialplan = PRI_LOCAL_ISDN ;
}
}
2005-08-07 04:56:39 +00:00
pri_sr_set_called ( sr , c + p - > stripmsd + dp_strip , pridialplan , ( s & & * s ) ? 1 : 0 ) ;
2005-03-03 17:00:57 +00:00
ldp_strip = 0 ;
prilocaldialplan = p - > pri - > localdialplan - 1 ;
if ( ( l ! = NULL ) & & ( prilocaldialplan = = - 2 ) ) { /* compute dynamically */
if ( strncmp ( l , p - > pri - > internationalprefix , strlen ( p - > pri - > internationalprefix ) ) = = 0 ) {
ldp_strip = strlen ( p - > pri - > internationalprefix ) ;
prilocaldialplan = PRI_INTERNATIONAL_ISDN ;
} else if ( strncmp ( l , p - > pri - > nationalprefix , strlen ( p - > pri - > nationalprefix ) ) = = 0 ) {
ldp_strip = strlen ( p - > pri - > nationalprefix ) ;
prilocaldialplan = PRI_NATIONAL_ISDN ;
} else {
prilocaldialplan = PRI_LOCAL_ISDN ;
}
}
pri_sr_set_caller ( sr , l ? ( l + ldp_strip ) : NULL , n , prilocaldialplan ,
2004-10-02 00:58:31 +00:00
l ? ( p - > use_callingpres ? ast - > cid . cid_pres : PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN ) :
2004-06-16 15:34:21 +00:00
PRES_NUMBER_NOT_AVAILABLE ) ;
2004-10-31 23:34:22 +00:00
pri_sr_set_redirecting ( sr , ast - > cid . cid_rdnis , p - > pri - > localdialplan - 1 , PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN , PRI_REDIR_UNCONDITIONAL ) ;
2004-06-16 15:34:21 +00:00
if ( pri_setup ( p - > pri - > pri , p - > call , sr ) ) {
2005-03-03 17:00:57 +00:00
ast_log ( LOG_WARNING , " Unable to setup call to %s (using %s) \n " ,
c + p - > stripmsd + dp_strip , dialplan2str ( p - > pri - > dialplan ) ) ;
2004-05-07 21:22:46 +00:00
pri_rel ( p - > pri ) ;
ast_mutex_unlock ( & p - > lock ) ;
2004-06-16 15:34:21 +00:00
pri_sr_free ( sr ) ;
2001-10-09 02:06:21 +00:00
return - 1 ;
}
2004-06-16 15:34:21 +00:00
pri_sr_free ( sr ) ;
2003-02-07 19:23:19 +00:00
ast_setstate ( ast , AST_STATE_DIALING ) ;
2004-05-07 21:22:46 +00:00
pri_rel ( p - > pri ) ;
2001-10-09 02:06:21 +00:00
}
2004-06-06 01:54:22 +00:00
# endif
2004-05-07 21:22:46 +00:00
ast_mutex_unlock ( & p - > lock ) ;
2001-10-09 02:06:21 +00:00
return 0 ;
}
2004-06-22 17:42:14 +00:00
static void destroy_zt_pvt ( struct zt_pvt * * pvt )
{
struct zt_pvt * p = * pvt ;
2004-10-31 23:17:11 +00:00
/* Remove channel from the list */
if ( p - > prev )
p - > prev - > next = p - > next ;
if ( p - > next )
p - > next - > prev = p - > prev ;
2004-06-22 17:42:14 +00:00
ast_mutex_destroy ( & p - > lock ) ;
free ( p ) ;
* pvt = NULL ;
}
2001-10-09 02:06:21 +00:00
static int destroy_channel ( struct zt_pvt * prev , struct zt_pvt * cur , int now )
{
int owned = 0 ;
int i = 0 ;
if ( ! now ) {
if ( cur - > owner ) {
owned = 1 ;
}
for ( i = 0 ; i < 3 ; i + + ) {
2003-02-07 19:23:19 +00:00
if ( cur - > subs [ i ] . owner ) {
2001-10-09 02:06:21 +00:00
owned = 1 ;
}
}
if ( ! owned ) {
if ( prev ) {
prev - > next = cur - > next ;
2003-08-07 03:48:00 +00:00
if ( prev - > next )
prev - > next - > prev = prev ;
else
ifend = prev ;
2001-10-09 02:06:21 +00:00
} else {
iflist = cur - > next ;
2003-08-07 03:48:00 +00:00
if ( iflist )
iflist - > prev = NULL ;
else
ifend = NULL ;
2001-10-09 02:06:21 +00:00
}
2003-02-07 19:23:19 +00:00
if ( cur - > subs [ SUB_REAL ] . zfd > - 1 ) {
zt_close ( cur - > subs [ SUB_REAL ] . zfd ) ;
2001-10-09 02:06:21 +00:00
}
2004-06-22 17:42:14 +00:00
destroy_zt_pvt ( & cur ) ;
2001-10-09 02:06:21 +00:00
}
} else {
if ( prev ) {
prev - > next = cur - > next ;
2003-08-07 03:48:00 +00:00
if ( prev - > next )
prev - > next - > prev = prev ;
else
ifend = prev ;
2001-10-09 02:06:21 +00:00
} else {
iflist = cur - > next ;
2003-08-07 03:48:00 +00:00
if ( iflist )
iflist - > prev = NULL ;
else
ifend = NULL ;
2001-10-09 02:06:21 +00:00
}
2003-02-07 19:23:19 +00:00
if ( cur - > subs [ SUB_REAL ] . zfd > - 1 ) {
zt_close ( cur - > subs [ SUB_REAL ] . zfd ) ;
2001-10-09 02:06:21 +00:00
}
2004-06-22 17:42:14 +00:00
destroy_zt_pvt ( & cur ) ;
2001-10-09 02:06:21 +00:00
}
return 0 ;
}
2004-06-06 01:54:22 +00:00
# ifdef ZAPATA_PRI
2004-06-07 03:39:18 +00:00
int pri_is_up ( struct zt_pri * pri )
{
int x ;
for ( x = 0 ; x < NUM_DCHANS ; x + + ) {
if ( pri - > dchanavail [ x ] = = DCHAN_AVAILABLE )
return 1 ;
}
return 0 ;
}
2004-06-06 01:54:22 +00:00
int pri_assign_bearer ( struct zt_pvt * crv , struct zt_pri * pri , struct zt_pvt * bearer )
{
bearer - > owner = & inuse ;
2004-12-13 15:11:36 +00:00
bearer - > realcall = crv ;
2004-06-06 01:54:22 +00:00
crv - > subs [ SUB_REAL ] . zfd = bearer - > subs [ SUB_REAL ] . zfd ;
2004-07-19 02:18:11 +00:00
if ( crv - > subs [ SUB_REAL ] . owner )
crv - > subs [ SUB_REAL ] . owner - > fds [ 0 ] = crv - > subs [ SUB_REAL ] . zfd ;
2004-06-06 01:54:22 +00:00
crv - > bearer = bearer ;
crv - > call = bearer - > call ;
crv - > pri = pri ;
return 0 ;
}
2004-06-07 03:39:18 +00:00
static char * pri_order ( int level )
{
switch ( level ) {
case 0 :
return " Primary " ;
case 1 :
return " Secondary " ;
case 2 :
return " Tertiary " ;
case 3 :
return " Quaternary " ;
default :
return " <Unknown> " ;
}
}
2005-05-20 19:09:21 +00:00
/* Returns fd of the active dchan */
int pri_active_dchan_fd ( struct zt_pri * pri )
{
int x = - 1 ;
2005-05-24 15:30:10 +00:00
for ( x = 0 ; x < NUM_DCHANS ; x + + ) {
2005-05-20 19:09:21 +00:00
if ( ( pri - > dchans [ x ] = = pri - > pri ) )
break ;
2005-05-24 15:30:10 +00:00
}
2005-05-20 19:09:21 +00:00
return pri - > fds [ x ] ;
}
2004-06-07 03:39:18 +00:00
int pri_find_dchan ( struct zt_pri * pri )
{
int oldslot = - 1 ;
struct pri * old ;
int newslot = - 1 ;
int x ;
old = pri - > pri ;
for ( x = 0 ; x < NUM_DCHANS ; x + + ) {
if ( ( pri - > dchanavail [ x ] = = DCHAN_AVAILABLE ) & & ( newslot < 0 ) )
newslot = x ;
if ( pri - > dchans [ x ] = = old ) {
oldslot = x ;
}
}
if ( newslot < 0 ) {
2004-06-16 21:26:53 +00:00
newslot = 0 ;
2005-08-19 04:23:23 +00:00
ast_log ( LOG_WARNING , " No D-channels available! Using Primary channel %d as D-channel anyway! \n " ,
2004-06-07 03:39:18 +00:00
pri - > dchannels [ newslot ] ) ;
}
if ( old & & ( oldslot ! = newslot ) )
ast_log ( LOG_NOTICE , " Switching from from d-channel %d to channel %d! \n " ,
pri - > dchannels [ oldslot ] , pri - > dchannels [ newslot ] ) ;
pri - > pri = pri - > dchans [ newslot ] ;
return 0 ;
}
2004-06-06 01:54:22 +00:00
# endif
2001-10-09 02:06:21 +00:00
static int zt_hangup ( struct ast_channel * ast )
{
int res ;
2001-12-29 18:04:21 +00:00
int index , x , law ;
2005-02-25 17:32:37 +00:00
/*static int restore_gains(struct zt_pvt *p);*/
2005-03-04 06:47:24 +00:00
struct zt_pvt * p = ast - > tech_pvt ;
2001-10-09 02:06:21 +00:00
struct zt_pvt * tmp = NULL ;
struct zt_pvt * prev = NULL ;
ZT_PARAMS par ;
if ( option_debug )
ast_log ( LOG_DEBUG , " zt_hangup(%s) \n " , ast - > name ) ;
2005-03-04 06:47:24 +00:00
if ( ! ast - > tech_pvt ) {
2001-10-09 02:06:21 +00:00
ast_log ( LOG_WARNING , " Asked to hangup channel not connected \n " ) ;
return 0 ;
}
2003-03-19 16:44:19 +00:00
2003-08-13 15:25:16 +00:00
ast_mutex_lock ( & p - > lock ) ;
2003-03-19 16:44:19 +00:00
2001-10-09 02:06:21 +00:00
index = zt_get_index ( ast , p , 1 ) ;
2003-03-26 00:35:52 +00:00
if ( p - > sig = = SIG_PRI ) {
2003-05-19 23:33:41 +00:00
x = 1 ;
2003-03-26 00:35:52 +00:00
ast_channel_setoption ( ast , AST_OPTION_AUDIO_MODE , & x , sizeof ( char ) , 0 ) ;
}
2003-03-23 18:55:52 +00:00
2003-05-19 23:33:41 +00:00
x = 0 ;
zt_confmute ( p , 0 ) ;
2001-10-09 02:06:21 +00:00
restore_gains ( p ) ;
2004-10-02 00:58:31 +00:00
if ( p - > origcid_num ) {
2005-05-15 23:26:45 +00:00
ast_copy_string ( p - > cid_num , p - > origcid_num , sizeof ( p - > cid_num ) ) ;
2004-10-02 00:58:31 +00:00
free ( p - > origcid_num ) ;
p - > origcid_num = NULL ;
}
if ( p - > origcid_name ) {
2005-05-15 23:26:45 +00:00
ast_copy_string ( p - > cid_name , p - > origcid_name , sizeof ( p - > cid_name ) ) ;
2004-10-02 00:58:31 +00:00
free ( p - > origcid_name ) ;
p - > origcid_name = NULL ;
2003-12-17 23:39:16 +00:00
}
2003-04-24 20:13:23 +00:00
if ( p - > dsp )
ast_dsp_digitmode ( p - > dsp , DSP_DIGITMODE_DTMF | p - > dtmfrelax ) ;
2004-03-10 09:11:05 +00:00
if ( p - > exten )
2004-07-16 04:40:54 +00:00
p - > exten [ 0 ] = ' \0 ' ;
2003-02-07 19:23:19 +00:00
ast_log ( LOG_DEBUG , " Hangup: channel: %d index = %d, normal = %d, callwait = %d, thirdcall = %d \n " ,
p - > channel , index , p - > subs [ SUB_REAL ] . zfd , p - > subs [ SUB_CALLWAIT ] . zfd , p - > subs [ SUB_THREEWAY ] . zfd ) ;
2001-10-09 02:06:21 +00:00
p - > ignoredtmf = 0 ;
if ( index > - 1 ) {
/* Real channel, do some fixup */
2003-02-07 19:23:19 +00:00
p - > subs [ index ] . owner = NULL ;
p - > subs [ index ] . needanswer = 0 ;
2004-11-03 22:37:55 +00:00
p - > subs [ index ] . needflash = 0 ;
2003-02-07 19:23:19 +00:00
p - > subs [ index ] . needringing = 0 ;
2004-01-31 18:46:59 +00:00
p - > subs [ index ] . needbusy = 0 ;
p - > subs [ index ] . needcongestion = 0 ;
2003-02-07 19:23:19 +00:00
p - > subs [ index ] . linear = 0 ;
p - > subs [ index ] . needcallerid = 0 ;
2005-02-08 07:49:40 +00:00
p - > polarity = POLARITY_IDLE ;
2003-02-07 19:23:19 +00:00
zt_setlinear ( p - > subs [ index ] . zfd , 0 ) ;
if ( index = = SUB_REAL ) {
if ( ( p - > subs [ SUB_CALLWAIT ] . zfd > - 1 ) & & ( p - > subs [ SUB_THREEWAY ] . zfd > - 1 ) ) {
ast_log ( LOG_DEBUG , " Normal call hung up with both three way call and a call waiting call in place? \n " ) ;
if ( p - > subs [ SUB_CALLWAIT ] . inthreeway ) {
/* We had flipped over to answer a callwait and now it's gone */
ast_log ( LOG_DEBUG , " We were flipped over to the callwait, moving back and unowning. \n " ) ;
/* Move to the call-wait, but un-own us until they flip back. */
swap_subs ( p , SUB_CALLWAIT , SUB_REAL ) ;
unalloc_sub ( p , SUB_CALLWAIT ) ;
p - > owner = NULL ;
} else {
/* The three way hung up, but we still have a call wait */
ast_log ( LOG_DEBUG , " We were in the threeway and have a callwait still. Ditching the threeway. \n " ) ;
swap_subs ( p , SUB_THREEWAY , SUB_REAL ) ;
unalloc_sub ( p , SUB_THREEWAY ) ;
if ( p - > subs [ SUB_REAL ] . inthreeway ) {
/* This was part of a three way call. Immediately make way for
another call */
ast_log ( LOG_DEBUG , " Call was complete, setting owner to former third call \n " ) ;
p - > owner = p - > subs [ SUB_REAL ] . owner ;
} else {
/* This call hasn't been completed yet... Set owner to NULL */
ast_log ( LOG_DEBUG , " Call was incomplete, setting owner to NULL \n " ) ;
p - > owner = NULL ;
}
p - > subs [ SUB_REAL ] . inthreeway = 0 ;
}
} else if ( p - > subs [ SUB_CALLWAIT ] . zfd > - 1 ) {
/* Move to the call-wait and switch back to them. */
swap_subs ( p , SUB_CALLWAIT , SUB_REAL ) ;
unalloc_sub ( p , SUB_CALLWAIT ) ;
p - > owner = p - > subs [ SUB_REAL ] . owner ;
2004-03-16 23:42:41 +00:00
if ( p - > owner - > _state ! = AST_STATE_UP )
p - > subs [ SUB_REAL ] . needanswer = 1 ;
2004-10-23 12:19:47 +00:00
if ( ast_bridged_channel ( p - > subs [ SUB_REAL ] . owner ) )
ast_moh_stop ( ast_bridged_channel ( p - > subs [ SUB_REAL ] . owner ) ) ;
2003-02-07 19:23:19 +00:00
} else if ( p - > subs [ SUB_THREEWAY ] . zfd > - 1 ) {
swap_subs ( p , SUB_THREEWAY , SUB_REAL ) ;
unalloc_sub ( p , SUB_THREEWAY ) ;
if ( p - > subs [ SUB_REAL ] . inthreeway ) {
/* This was part of a three way call. Immediately make way for
another call */
ast_log ( LOG_DEBUG , " Call was complete, setting owner to former third call \n " ) ;
p - > owner = p - > subs [ SUB_REAL ] . owner ;
} else {
/* This call hasn't been completed yet... Set owner to NULL */
ast_log ( LOG_DEBUG , " Call was incomplete, setting owner to NULL \n " ) ;
p - > owner = NULL ;
}
p - > subs [ SUB_REAL ] . inthreeway = 0 ;
}
} else if ( index = = SUB_CALLWAIT ) {
/* Ditch the holding callwait call, and immediately make it availabe */
if ( p - > subs [ SUB_CALLWAIT ] . inthreeway ) {
/* This is actually part of a three way, placed on hold. Place the third part
on music on hold now */
2004-10-23 12:19:47 +00:00
if ( p - > subs [ SUB_THREEWAY ] . owner & & ast_bridged_channel ( p - > subs [ SUB_THREEWAY ] . owner ) )
ast_moh_start ( ast_bridged_channel ( p - > subs [ SUB_THREEWAY ] . owner ) , NULL ) ;
2003-02-07 19:23:19 +00:00
p - > subs [ SUB_THREEWAY ] . inthreeway = 0 ;
/* Make it the call wait now */
swap_subs ( p , SUB_CALLWAIT , SUB_THREEWAY ) ;
unalloc_sub ( p , SUB_THREEWAY ) ;
} else
unalloc_sub ( p , SUB_CALLWAIT ) ;
} else if ( index = = SUB_THREEWAY ) {
if ( p - > subs [ SUB_CALLWAIT ] . inthreeway ) {
/* The other party of the three way call is currently in a call-wait state.
Start music on hold for them , and take the main guy out of the third call */
2004-10-23 12:19:47 +00:00
if ( p - > subs [ SUB_CALLWAIT ] . owner & & ast_bridged_channel ( p - > subs [ SUB_CALLWAIT ] . owner ) )
ast_moh_start ( ast_bridged_channel ( p - > subs [ SUB_CALLWAIT ] . owner ) , NULL ) ;
2003-02-07 19:23:19 +00:00
p - > subs [ SUB_CALLWAIT ] . inthreeway = 0 ;
2001-10-09 02:06:21 +00:00
}
2003-02-07 19:23:19 +00:00
p - > subs [ SUB_REAL ] . inthreeway = 0 ;
2001-10-09 02:06:21 +00:00
/* If this was part of a three way call index, let us make
another three way call */
2003-02-07 19:23:19 +00:00
unalloc_sub ( p , SUB_THREEWAY ) ;
2001-10-09 02:06:21 +00:00
} else {
/* This wasn't any sort of call, but how are we an index? */
ast_log ( LOG_WARNING , " Index found but not any type of call? \n " ) ;
}
}
2002-06-24 17:59:56 +00:00
2003-02-07 19:23:19 +00:00
if ( ! p - > subs [ SUB_REAL ] . owner & & ! p - > subs [ SUB_CALLWAIT ] . owner & & ! p - > subs [ SUB_THREEWAY ] . owner ) {
2001-10-09 02:06:21 +00:00
p - > owner = NULL ;
p - > ringt = 0 ;
2002-06-24 17:59:56 +00:00
p - > distinctivering = 0 ;
p - > confirmanswer = 0 ;
p - > cidrings = 1 ;
2003-02-07 19:23:19 +00:00
p - > outgoing = 0 ;
p - > digital = 0 ;
p - > faxhandled = 0 ;
p - > pulsedial = 0 ;
p - > onhooktime = time ( NULL ) ;
2004-06-05 07:01:23 +00:00
# ifdef ZAPATA_PRI
2003-04-18 15:55:50 +00:00
p - > proceeding = 0 ;
2005-04-05 19:40:37 +00:00
p - > alerting = 0 ;
2003-05-19 23:33:41 +00:00
p - > setup_ack = 0 ;
2004-06-05 07:01:23 +00:00
# endif
2003-02-07 19:23:19 +00:00
if ( p - > dsp ) {
ast_dsp_free ( p - > dsp ) ;
p - > dsp = NULL ;
}
2003-05-19 23:33:41 +00:00
2001-12-29 18:04:21 +00:00
law = ZT_LAW_DEFAULT ;
2003-02-07 19:23:19 +00:00
res = ioctl ( p - > subs [ SUB_REAL ] . zfd , ZT_SETLAW , & law ) ;
2001-12-29 18:04:21 +00:00
if ( res < 0 )
ast_log ( LOG_WARNING , " Unable to set law on channel %d to default \n " , p - > channel ) ;
2001-10-09 02:06:21 +00:00
/* Perform low level hangup if no owner left */
# ifdef ZAPATA_PRI
2004-06-06 01:54:22 +00:00
if ( p - > pri ) {
/* Make sure we have a call (or REALLY have a call in the case of a PRI) */
if ( p - > call & & ( ! p - > bearer | | ( p - > bearer - > call = = p - > call ) ) ) {
2003-04-22 18:47:49 +00:00
if ( ! pri_grab ( p , p - > pri ) ) {
2003-08-07 00:47:27 +00:00
if ( p - > alreadyhungup ) {
2004-06-06 01:54:22 +00:00
ast_log ( LOG_DEBUG , " Already hungup... Calling hangup once, and clearing call \n " ) ;
2003-08-07 00:47:27 +00:00
pri_hangup ( p - > pri - > pri , p - > call , - 1 ) ;
p - > call = NULL ;
2004-06-06 01:54:22 +00:00
if ( p - > bearer )
p - > bearer - > call = NULL ;
2003-08-07 00:47:27 +00:00
} else {
2003-11-05 16:48:38 +00:00
char * cause = pbx_builtin_getvar_helper ( ast , " PRI_CAUSE " ) ;
2004-08-12 22:09:18 +00:00
int icause = ast - > hangupcause ? ast - > hangupcause : - 1 ;
2004-06-06 01:54:22 +00:00
ast_log ( LOG_DEBUG , " Not yet hungup... Calling hangup once with icause, and clearing call \n " ) ;
2003-08-07 00:47:27 +00:00
p - > alreadyhungup = 1 ;
2004-06-06 01:54:22 +00:00
if ( p - > bearer )
p - > bearer - > alreadyhungup = 1 ;
2003-11-05 16:48:38 +00:00
if ( cause ) {
if ( atoi ( cause ) )
icause = atoi ( cause ) ;
}
pri_hangup ( p - > pri - > pri , p - > call , icause ) ;
2003-08-07 00:47:27 +00:00
}
2001-10-09 02:06:21 +00:00
if ( res < 0 )
ast_log ( LOG_WARNING , " pri_disconnect failed \n " ) ;
pri_rel ( p - > pri ) ;
} else {
ast_log ( LOG_WARNING , " Unable to grab PRI on span %d \n " , p - > span ) ;
res = - 1 ;
}
2004-06-06 01:54:22 +00:00
} else {
if ( p - > bearer )
ast_log ( LOG_DEBUG , " Bearer call is %p, while ours is still %p \n " , p - > bearer - > call , p - > call ) ;
p - > call = NULL ;
2001-10-09 02:06:21 +00:00
res = 0 ;
2004-06-06 01:54:22 +00:00
}
}
2001-10-09 02:06:21 +00:00
# endif
2003-02-07 19:23:19 +00:00
# ifdef ZAPATA_R2
if ( p - > sig = = SIG_R2 ) {
if ( p - > hasr2call ) {
mfcr2_DropCall ( p - > r2 , NULL , UC_NORMAL_CLEARING ) ;
p - > hasr2call = 0 ;
res = 0 ;
} else
res = 0 ;
2004-06-06 01:54:22 +00:00
}
2003-02-07 19:23:19 +00:00
# endif
2004-06-06 01:54:22 +00:00
if ( p - > sig & & ( p - > sig ! = SIG_PRI ) & & ( p - > sig ! = SIG_R2 ) )
2003-02-07 19:23:19 +00:00
res = zt_set_hook ( p - > subs [ SUB_REAL ] . zfd , ZT_ONHOOK ) ;
2001-10-09 02:06:21 +00:00
if ( res < 0 ) {
ast_log ( LOG_WARNING , " Unable to hangup line %s \n " , ast - > name ) ;
}
switch ( p - > sig ) {
case SIG_FXOGS :
case SIG_FXOLS :
case SIG_FXOKS :
2003-02-07 19:23:19 +00:00
res = ioctl ( p - > subs [ SUB_REAL ] . zfd , ZT_GET_PARAMS , & par ) ;
2001-10-09 02:06:21 +00:00
if ( ! res ) {
#if 0
ast_log ( LOG_DEBUG , " Hanging up channel %d, offhook = %d \n " , p - > channel , par . rxisoffhook ) ;
# endif
/* If they're off hook, try playing congestion */
2004-08-21 21:41:54 +00:00
if ( ( par . rxisoffhook ) & & ( ! p - > radio ) )
2003-02-07 19:23:19 +00:00
tone_zone_play_tone ( p - > subs [ SUB_REAL ] . zfd , ZT_TONE_CONGESTION ) ;
2001-10-09 02:06:21 +00:00
else
2003-02-07 19:23:19 +00:00
tone_zone_play_tone ( p - > subs [ SUB_REAL ] . zfd , - 1 ) ;
2001-10-09 02:06:21 +00:00
}
break ;
2004-05-15 22:50:51 +00:00
case SIG_FXSGS :
case SIG_FXSLS :
case SIG_FXSKS :
2004-09-11 13:37:36 +00:00
/* Make sure we're not made available for at least two seconds assuming
we were actually used for an inbound or outbound call . */
if ( ast - > _state ! = AST_STATE_RESERVED ) {
time ( & p - > guardtime ) ;
p - > guardtime + = 2 ;
}
2004-05-15 22:50:51 +00:00
break ;
2001-10-09 02:06:21 +00:00
default :
2003-02-07 19:23:19 +00:00
tone_zone_play_tone ( p - > subs [ SUB_REAL ] . zfd , - 1 ) ;
2001-10-09 02:06:21 +00:00
}
if ( p - > cidspill )
free ( p - > cidspill ) ;
2002-06-24 17:59:56 +00:00
if ( p - > sig )
zt_disable_ec ( p ) ;
2001-10-09 02:06:21 +00:00
x = 0 ;
ast_channel_setoption ( ast , AST_OPTION_TONE_VERIFY , & x , sizeof ( char ) , 0 ) ;
2001-12-29 18:04:21 +00:00
ast_channel_setoption ( ast , AST_OPTION_TDD , & x , sizeof ( char ) , 0 ) ;
p - > didtdd = 0 ;
2001-10-09 02:06:21 +00:00
p - > cidspill = NULL ;
p - > callwaitcas = 0 ;
p - > callwaiting = p - > permcallwaiting ;
p - > hidecallerid = p - > permhidecallerid ;
p - > dialing = 0 ;
2004-07-16 04:40:54 +00:00
p - > rdnis [ 0 ] = ' \0 ' ;
2003-02-07 19:23:19 +00:00
update_conf ( p ) ;
2004-07-30 20:23:06 +00:00
reset_conf ( p ) ;
2003-05-19 23:33:41 +00:00
/* Restore data mode */
if ( p - > sig = = SIG_PRI ) {
x = 0 ;
ast_channel_setoption ( ast , AST_OPTION_AUDIO_MODE , & x , sizeof ( char ) , 0 ) ;
}
2004-06-06 01:54:22 +00:00
# ifdef ZAPATA_PRI
if ( p - > bearer ) {
ast_log ( LOG_DEBUG , " Freeing up bearer channel %d \n " , p - > bearer - > channel ) ;
/* Free up the bearer channel as well, and
don ' t use its file descriptor anymore */
2004-07-29 04:26:42 +00:00
update_conf ( p - > bearer ) ;
2004-07-30 20:23:06 +00:00
reset_conf ( p - > bearer ) ;
2004-06-06 01:54:22 +00:00
p - > bearer - > owner = NULL ;
2004-12-13 15:11:36 +00:00
p - > bearer - > realcall = NULL ;
2004-06-06 01:54:22 +00:00
p - > bearer = NULL ;
p - > subs [ SUB_REAL ] . zfd = - 1 ;
p - > pri = NULL ;
}
# endif
2001-10-09 02:06:21 +00:00
restart_monitor ( ) ;
}
2002-06-24 17:59:56 +00:00
2001-10-09 02:06:21 +00:00
p - > callwaitingrepeat = 0 ;
2003-02-07 19:23:19 +00:00
p - > cidcwexpire = 0 ;
2005-03-04 06:47:24 +00:00
ast - > tech_pvt = NULL ;
2003-08-13 15:25:16 +00:00
ast_mutex_unlock ( & p - > lock ) ;
ast_mutex_lock ( & usecnt_lock ) ;
2001-10-09 02:06:21 +00:00
usecnt - - ;
if ( usecnt < 0 )
ast_log ( LOG_WARNING , " Usecnt < 0??? \n " ) ;
2003-08-13 15:25:16 +00:00
ast_mutex_unlock ( & usecnt_lock ) ;
2001-10-09 02:06:21 +00:00
ast_update_use_count ( ) ;
if ( option_verbose > 2 )
ast_verbose ( VERBOSE_PREFIX_3 " Hungup '%s' \n " , ast - > name ) ;
2003-08-13 15:25:16 +00:00
ast_mutex_lock ( & iflock ) ;
2001-10-09 02:06:21 +00:00
tmp = iflist ;
prev = NULL ;
if ( p - > destroy ) {
while ( tmp ) {
2002-06-24 17:59:56 +00:00
if ( tmp = = p ) {
2001-10-09 02:06:21 +00:00
destroy_channel ( prev , tmp , 0 ) ;
break ;
} else {
prev = tmp ;
tmp = tmp - > next ;
}
}
}
2003-08-13 15:25:16 +00:00
ast_mutex_unlock ( & iflock ) ;
2001-10-09 02:06:21 +00:00
return 0 ;
}
static int zt_answer ( struct ast_channel * ast )
{
2005-03-04 06:47:24 +00:00
struct zt_pvt * p = ast - > tech_pvt ;
2001-10-09 02:06:21 +00:00
int res = 0 ;
2003-02-07 19:23:19 +00:00
int index ;
int oldstate = ast - > _state ;
2002-09-10 04:45:51 +00:00
ast_setstate ( ast , AST_STATE_UP ) ;
2003-08-13 15:25:16 +00:00
ast_mutex_lock ( & p - > lock ) ;
2003-02-07 19:23:19 +00:00
index = zt_get_index ( ast , p , 0 ) ;
if ( index < 0 )
index = SUB_REAL ;
/* nothing to do if a radio channel */
2003-04-22 18:47:49 +00:00
if ( p - > radio ) {
2003-08-13 15:25:16 +00:00
ast_mutex_unlock ( & p - > lock ) ;
2003-02-07 19:23:19 +00:00
return 0 ;
2003-04-22 18:47:49 +00:00
}
2001-10-09 02:06:21 +00:00
switch ( p - > sig ) {
case SIG_FXSLS :
case SIG_FXSGS :
case SIG_FXSKS :
p - > ringt = 0 ;
/* Fall through */
case SIG_EM :
2004-04-16 18:00:00 +00:00
case SIG_EM_E1 :
2001-10-09 02:06:21 +00:00
case SIG_EMWINK :
case SIG_FEATD :
2002-06-24 17:59:56 +00:00
case SIG_FEATDMF :
2004-01-16 23:40:37 +00:00
case SIG_E911 :
2002-06-24 17:59:56 +00:00
case SIG_FEATB :
2003-03-17 20:04:36 +00:00
case SIG_SF :
case SIG_SFWINK :
case SIG_SF_FEATD :
case SIG_SF_FEATDMF :
case SIG_SF_FEATB :
2001-10-09 02:06:21 +00:00
case SIG_FXOLS :
case SIG_FXOGS :
case SIG_FXOKS :
/* Pick up the line */
ast_log ( LOG_DEBUG , " Took %s off hook \n " , ast - > name ) ;
2004-11-17 06:18:33 +00:00
if ( p - > hanguponpolarityswitch ) {
gettimeofday ( & p - > polaritydelaytv , NULL ) ;
}
2003-02-07 19:23:19 +00:00
res = zt_set_hook ( p - > subs [ SUB_REAL ] . zfd , ZT_OFFHOOK ) ;
tone_zone_play_tone ( p - > subs [ index ] . zfd , - 1 ) ;
2001-10-09 02:06:21 +00:00
p - > dialing = 0 ;
2003-02-07 19:23:19 +00:00
if ( ( index = = SUB_REAL ) & & p - > subs [ SUB_THREEWAY ] . inthreeway ) {
if ( oldstate = = AST_STATE_RINGING ) {
ast_log ( LOG_DEBUG , " Finally swapping real and threeway \n " ) ;
tone_zone_play_tone ( p - > subs [ SUB_THREEWAY ] . zfd , - 1 ) ;
swap_subs ( p , SUB_THREEWAY , SUB_REAL ) ;
p - > owner = p - > subs [ SUB_REAL ] . owner ;
}
}
2004-01-26 16:39:34 +00:00
if ( p - > sig & __ZT_SIG_FXS ) {
zt_enable_ec ( p ) ;
zt_train_ec ( p ) ;
}
2001-10-09 02:06:21 +00:00
break ;
# ifdef ZAPATA_PRI
case SIG_PRI :
/* Send a pri acknowledge */
2003-04-22 18:47:49 +00:00
if ( ! pri_grab ( p , p - > pri ) ) {
2004-06-14 21:18:52 +00:00
p - > proceeding = 2 ;
2005-03-27 22:48:55 +00:00
res = pri_answer ( p - > pri - > pri , p - > call , 0 , ! p - > digital ) ;
2001-10-09 02:06:21 +00:00
pri_rel ( p - > pri ) ;
} else {
ast_log ( LOG_WARNING , " Unable to grab PRI on span %d \n " , p - > span ) ;
res = - 1 ;
}
break ;
2003-02-07 19:23:19 +00:00
# endif
# ifdef ZAPATA_R2
case SIG_R2 :
res = mfcr2_AnswerCall ( p - > r2 , NULL ) ;
if ( res )
ast_log ( LOG_WARNING , " R2 Answer call failed :( on %s \n " , ast - > name ) ;
break ;
# endif
case 0 :
2003-08-13 15:25:16 +00:00
ast_mutex_unlock ( & p - > lock ) ;
2003-02-07 19:23:19 +00:00
return 0 ;
2001-10-09 02:06:21 +00:00
default :
ast_log ( LOG_WARNING , " Don't know how to answer signalling %d (channel %d) \n " , p - > sig , p - > channel ) ;
2003-04-22 18:47:49 +00:00
res = - 1 ;
2001-10-09 02:06:21 +00:00
}
2003-08-13 15:25:16 +00:00
ast_mutex_unlock ( & p - > lock ) ;
2001-10-09 02:06:21 +00:00
return res ;
}
static int zt_setoption ( struct ast_channel * chan , int option , void * data , int datalen )
{
char * cp ;
2003-02-07 19:23:19 +00:00
int x ;
2001-10-09 02:06:21 +00:00
2005-03-04 06:47:24 +00:00
struct zt_pvt * p = chan - > tech_pvt ;
2001-10-09 02:06:21 +00:00
2001-12-29 18:04:21 +00:00
2003-03-23 17:14:29 +00:00
if ( ( option ! = AST_OPTION_TONE_VERIFY ) & & ( option ! = AST_OPTION_AUDIO_MODE ) & &
2003-02-07 19:23:19 +00:00
( option ! = AST_OPTION_TDD ) & & ( option ! = AST_OPTION_RELAXDTMF ) )
2001-10-09 02:06:21 +00:00
{
errno = ENOSYS ;
return - 1 ;
}
cp = ( char * ) data ;
if ( ( ! cp ) | | ( datalen < 1 ) )
{
errno = EINVAL ;
return - 1 ;
}
2001-12-29 18:04:21 +00:00
switch ( option ) {
case AST_OPTION_TONE_VERIFY :
2003-02-07 19:23:19 +00:00
if ( ! p - > dsp )
break ;
2001-12-29 18:04:21 +00:00
switch ( * cp ) {
case 1 :
2003-02-07 19:23:19 +00:00
ast_log ( LOG_DEBUG , " Set option TONE VERIFY, mode: MUTECONF(1) on %s \n " , chan - > name ) ;
ast_dsp_digitmode ( p - > dsp , DSP_DIGITMODE_MUTECONF | p - > dtmfrelax ) ; /* set mute mode if desired */
2001-12-29 18:04:21 +00:00
break ;
case 2 :
2003-02-07 19:23:19 +00:00
ast_log ( LOG_DEBUG , " Set option TONE VERIFY, mode: MUTECONF/MAX(2) on %s \n " , chan - > name ) ;
ast_dsp_digitmode ( p - > dsp , DSP_DIGITMODE_MUTECONF | DSP_DIGITMODE_MUTEMAX | p - > dtmfrelax ) ; /* set mute mode if desired */
2001-12-29 18:04:21 +00:00
break ;
default :
2003-02-07 19:23:19 +00:00
ast_log ( LOG_DEBUG , " Set option TONE VERIFY, mode: OFF(0) on %s \n " , chan - > name ) ;
ast_dsp_digitmode ( p - > dsp , DSP_DIGITMODE_DTMF | p - > dtmfrelax ) ; /* set mute mode if desired */
2001-12-29 18:04:21 +00:00
break ;
}
2001-10-09 02:06:21 +00:00
break ;
2001-12-29 18:04:21 +00:00
case AST_OPTION_TDD : /* turn on or off TDD */
if ( ! * cp ) { /* turn it off */
ast_log ( LOG_DEBUG , " Set option TDD MODE, value: OFF(0) on %s \n " , chan - > name ) ;
if ( p - > tdd ) tdd_free ( p - > tdd ) ;
p - > tdd = 0 ;
2002-06-24 17:59:56 +00:00
p - > mate = 0 ;
2001-12-29 18:04:21 +00:00
break ;
}
2002-06-24 17:59:56 +00:00
if ( * cp = = 2 )
ast_log ( LOG_DEBUG , " Set option TDD MODE, value: MATE(2) on %s \n " , chan - > name ) ;
else ast_log ( LOG_DEBUG , " Set option TDD MODE, value: ON(1) on % s \ n " ,chan->name) ;
p - > mate = 0 ;
zt_disable_ec ( p ) ;
2001-12-29 18:04:21 +00:00
/* otherwise, turn it on */
if ( ! p - > didtdd ) { /* if havent done it yet */
unsigned char mybuf [ 41000 ] , * buf ;
int size , res , fd , len ;
2003-02-07 19:23:19 +00:00
int index ;
2004-04-25 22:37:09 +00:00
struct pollfd fds [ 1 ] ;
2001-12-29 18:04:21 +00:00
buf = mybuf ;
memset ( buf , 0x7f , sizeof ( mybuf ) ) ; /* set to silence */
ast_tdd_gen_ecdisa ( buf + 16000 , 16000 ) ; /* put in tone */
len = 40000 ;
2003-02-07 19:23:19 +00:00
index = zt_get_index ( chan , p , 0 ) ;
if ( index < 0 ) {
ast_log ( LOG_WARNING , " No index in TDD? \n " ) ;
return - 1 ;
}
fd = p - > subs [ index ] . zfd ;
2001-12-29 18:04:21 +00:00
while ( len ) {
if ( ast_check_hangup ( chan ) ) return - 1 ;
size = len ;
if ( size > READ_SIZE )
size = READ_SIZE ;
2004-04-25 22:37:09 +00:00
fds [ 0 ] . fd = fd ;
fds [ 0 ] . events = POLLPRI | POLLOUT ;
res = poll ( fds , 1 , - 1 ) ;
2001-12-29 18:04:21 +00:00
if ( ! res ) {
2004-04-25 22:37:09 +00:00
ast_log ( LOG_DEBUG , " poll (for write) ret. 0 on channel %d \n " , p - > channel ) ;
2001-12-29 18:04:21 +00:00
continue ;
}
/* if got exception */
2004-04-25 22:37:09 +00:00
if ( fds [ 0 ] . revents & POLLPRI ) return - 1 ;
if ( ! ( fds [ 0 ] . revents & POLLOUT ) ) {
2001-12-29 18:04:21 +00:00
ast_log ( LOG_DEBUG , " write fd not ready on channel %d \n " , p - > channel ) ;
continue ;
}
res = write ( fd , buf , size ) ;
if ( res ! = size ) {
if ( res = = - 1 ) return - 1 ;
ast_log ( LOG_DEBUG , " Write returned %d (%s) on channel %d \n " , res , strerror ( errno ) , p - > channel ) ;
break ;
}
len - = size ;
buf + = size ;
}
p - > didtdd = 1 ; /* set to have done it now */
}
2002-06-24 17:59:56 +00:00
if ( * cp = = 2 ) { /* Mate mode */
if ( p - > tdd ) tdd_free ( p - > tdd ) ;
p - > tdd = 0 ;
p - > mate = 1 ;
break ;
}
2001-12-29 18:04:21 +00:00
if ( ! p - > tdd ) { /* if we dont have one yet */
p - > tdd = tdd_new ( ) ; /* allocate one */
}
2001-10-09 02:06:21 +00:00
break ;
2003-02-07 19:23:19 +00:00
case AST_OPTION_RELAXDTMF : /* Relax DTMF decoding (or not) */
2005-07-19 13:30:37 +00:00
if ( ! p - > dsp )
break ;
2003-02-07 19:23:19 +00:00
if ( ! * cp )
{
ast_log ( LOG_DEBUG , " Set option RELAX DTMF, value: OFF(0) on %s \n " , chan - > name ) ;
x = 0 ;
}
else
{
ast_log ( LOG_DEBUG , " Set option RELAX DTMF, value: ON(1) on %s \n " , chan - > name ) ;
x = 1 ;
}
ast_dsp_digitmode ( p - > dsp , x ? DSP_DIGITMODE_RELAXDTMF : DSP_DIGITMODE_DTMF | p - > dtmfrelax ) ;
break ;
2003-03-23 17:14:29 +00:00
case AST_OPTION_AUDIO_MODE : /* Set AUDIO mode (or not) */
if ( ! * cp )
{
ast_log ( LOG_DEBUG , " Set option AUDIO MODE, value: OFF(0) on %s \n " , chan - > name ) ;
x = 0 ;
2003-03-23 18:55:52 +00:00
zt_disable_ec ( p ) ;
2003-03-23 17:14:29 +00:00
}
else
{
ast_log ( LOG_DEBUG , " Set option AUDIO MODE, value: ON(1) on %s \n " , chan - > name ) ;
x = 1 ;
}
if ( ioctl ( p - > subs [ SUB_REAL ] . zfd , ZT_AUDIOMODE , & x ) = = - 1 )
2003-03-26 00:25:09 +00:00
ast_log ( LOG_WARNING , " Unable to set audio mode on channel %d to %d \n " , p - > channel , x ) ;
2003-03-23 17:14:29 +00:00
break ;
2001-10-09 02:06:21 +00:00
}
errno = 0 ;
return 0 ;
}
2004-02-20 21:23:22 +00:00
static void zt_unlink ( struct zt_pvt * slave , struct zt_pvt * master , int needlock )
2003-02-07 19:23:19 +00:00
{
/* Unlink a specific slave or all slaves/masters from a given master */
int x ;
int hasslaves ;
if ( ! master )
return ;
2004-02-20 21:23:22 +00:00
if ( needlock ) {
ast_mutex_lock ( & master - > lock ) ;
if ( slave ) {
while ( ast_mutex_trylock ( & slave - > lock ) ) {
ast_mutex_unlock ( & master - > lock ) ;
usleep ( 1 ) ;
ast_mutex_lock ( & master - > lock ) ;
}
}
}
2003-02-07 19:23:19 +00:00
hasslaves = 0 ;
for ( x = 0 ; x < MAX_SLAVES ; x + + ) {
if ( master - > slaves [ x ] ) {
if ( ! slave | | ( master - > slaves [ x ] = = slave ) ) {
/* Take slave out of the conference */
ast_log ( LOG_DEBUG , " Unlinking slave %d from %d \n " , master - > slaves [ x ] - > channel , master - > channel ) ;
2003-08-23 17:49:54 +00:00
conf_del ( master , & master - > slaves [ x ] - > subs [ SUB_REAL ] , SUB_REAL ) ;
conf_del ( master - > slaves [ x ] , & master - > subs [ SUB_REAL ] , SUB_REAL ) ;
2003-02-07 19:23:19 +00:00
master - > slaves [ x ] - > master = NULL ;
master - > slaves [ x ] = NULL ;
} else
hasslaves = 1 ;
}
if ( ! hasslaves )
master - > inconference = 0 ;
}
if ( ! slave ) {
if ( master - > master ) {
/* Take master out of the conference */
2003-08-23 17:49:54 +00:00
conf_del ( master - > master , & master - > subs [ SUB_REAL ] , SUB_REAL ) ;
conf_del ( master , & master - > master - > subs [ SUB_REAL ] , SUB_REAL ) ;
2003-02-07 19:23:19 +00:00
hasslaves = 0 ;
for ( x = 0 ; x < MAX_SLAVES ; x + + ) {
if ( master - > master - > slaves [ x ] = = master )
master - > master - > slaves [ x ] = NULL ;
else if ( master - > master - > slaves [ x ] )
hasslaves = 1 ;
}
if ( ! hasslaves )
master - > master - > inconference = 0 ;
}
master - > master = NULL ;
}
update_conf ( master ) ;
2004-02-20 21:23:22 +00:00
if ( needlock ) {
if ( slave )
ast_mutex_unlock ( & slave - > lock ) ;
ast_mutex_unlock ( & master - > lock ) ;
}
2003-02-07 19:23:19 +00:00
}
static void zt_link ( struct zt_pvt * slave , struct zt_pvt * master ) {
int x ;
if ( ! slave | | ! master ) {
ast_log ( LOG_WARNING , " Tried to link to/from NULL?? \n " ) ;
return ;
}
for ( x = 0 ; x < MAX_SLAVES ; x + + ) {
if ( ! master - > slaves [ x ] ) {
master - > slaves [ x ] = slave ;
break ;
}
}
if ( x > = MAX_SLAVES ) {
ast_log ( LOG_WARNING , " Replacing slave %d with new slave, %d \n " , master - > slaves [ MAX_SLAVES - 1 ] - > channel , slave - > channel ) ;
master - > slaves [ MAX_SLAVES - 1 ] = slave ;
}
if ( slave - > master )
ast_log ( LOG_WARNING , " Replacing master %d with new master, %d \n " , slave - > master - > channel , master - > channel ) ;
slave - > master = master ;
ast_log ( LOG_DEBUG , " Making %d slave to master %d at %d \n " , slave - > channel , master - > channel , x ) ;
}
2005-08-09 01:59:59 +00:00
static void disable_dtmf_detect ( struct zt_pvt * p )
2001-10-09 02:06:21 +00:00
{
2005-08-09 01:59:59 +00:00
int val ;
p - > ignoredtmf = 1 ;
# ifdef ZT_TONEDETECT
val = 0 ;
ioctl ( p - > subs [ SUB_REAL ] . zfd , ZT_TONEDETECT , & val ) ;
# endif
}
static void enable_dtmf_detect ( struct zt_pvt * p )
{
int val ;
p - > ignoredtmf = 0 ;
# ifdef ZT_TONEDETECT
val = ZT_TONEDETECT_ON | ZT_TONEDETECT_MUTE ;
ioctl ( p - > subs [ SUB_REAL ] . zfd , ZT_TONEDETECT , & val ) ;
# endif
}
static enum ast_bridge_result zt_bridge ( struct ast_channel * c0 , struct ast_channel * c1 , int flags , struct ast_frame * * fo , struct ast_channel * * rc )
{
struct ast_channel * who ;
2003-02-07 19:23:19 +00:00
struct zt_pvt * p0 , * p1 , * op0 , * op1 ;
2005-08-09 01:59:59 +00:00
struct zt_pvt * master = NULL , * slave = NULL ;
2001-10-09 02:06:21 +00:00
struct ast_frame * f ;
2003-02-07 19:23:19 +00:00
int to ;
int inconf = 0 ;
2005-08-09 01:59:59 +00:00
int nothingok = 1 ;
int ofd0 , ofd1 ;
int oi0 , oi1 , i0 = - 1 , i1 = - 1 , t0 , t1 ;
int os0 = - 1 , os1 = - 1 ;
struct ast_channel * oc0 , * oc1 ;
enum ast_bridge_result res ;
2005-03-02 16:09:27 +00:00
# ifdef PRI_2BCT
int triedtopribridge = 0 ;
q931_call * q931c0 = NULL , * q931c1 = NULL ;
# endif
2005-08-09 01:59:59 +00:00
/* For now, don't attempt to native bridge if either channel needs DTMF detection.
There is code below to handle it properly until DTMF is actually seen ,
but due to currently unresolved issues it ' s ignored . . .
*/
2003-02-07 19:23:19 +00:00
2001-10-09 02:06:21 +00:00
if ( flags & ( AST_BRIDGE_DTMF_CHANNEL_0 | AST_BRIDGE_DTMF_CHANNEL_1 ) )
2005-08-09 01:59:59 +00:00
return AST_BRIDGE_FAILED_NOWARN ;
2003-08-13 15:25:16 +00:00
ast_mutex_lock ( & c0 - > lock ) ;
ast_mutex_lock ( & c1 - > lock ) ;
2003-12-01 23:59:28 +00:00
2005-03-04 06:47:24 +00:00
p0 = c0 - > tech_pvt ;
p1 = c1 - > tech_pvt ;
2003-12-01 23:59:28 +00:00
/* cant do pseudo-channels here */
if ( ! p0 | | ( ! p0 - > sig ) | | ! p1 | | ( ! p1 - > sig ) ) {
ast_mutex_unlock ( & c0 - > lock ) ;
ast_mutex_unlock ( & c1 - > lock ) ;
2005-08-09 01:59:59 +00:00
return AST_BRIDGE_FAILED_NOWARN ;
2003-12-01 23:59:28 +00:00
}
2005-08-09 01:59:59 +00:00
oi0 = zt_get_index ( c0 , p0 , 0 ) ;
oi1 = zt_get_index ( c1 , p1 , 0 ) ;
if ( ( oi0 < 0 ) | | ( oi1 < 0 ) ) {
2004-03-22 22:48:59 +00:00
ast_mutex_unlock ( & c0 - > lock ) ;
ast_mutex_unlock ( & c1 - > lock ) ;
2005-08-09 01:59:59 +00:00
return AST_BRIDGE_FAILED ;
2004-03-22 22:48:59 +00:00
}
2003-02-07 19:23:19 +00:00
2005-08-09 01:59:59 +00:00
op0 = p0 = c0 - > tech_pvt ;
op1 = p1 = c1 - > tech_pvt ;
ofd0 = c0 - > fds [ 0 ] ;
ofd1 = c1 - > fds [ 0 ] ;
oc0 = p0 - > owner ;
oc1 = p1 - > owner ;
2003-02-07 19:23:19 +00:00
2003-08-13 15:25:16 +00:00
ast_mutex_lock ( & p0 - > lock ) ;
if ( ast_mutex_trylock ( & p1 - > lock ) ) {
2003-02-07 19:23:19 +00:00
/* Don't block, due to potential for deadlock */
2003-08-13 15:25:16 +00:00
ast_mutex_unlock ( & p0 - > lock ) ;
ast_mutex_unlock ( & c0 - > lock ) ;
ast_mutex_unlock ( & c1 - > lock ) ;
2003-02-07 19:23:19 +00:00
ast_log ( LOG_NOTICE , " Avoiding deadlock... \n " ) ;
2005-08-09 01:59:59 +00:00
return AST_BRIDGE_RETRY ;
2001-10-09 02:06:21 +00:00
}
2005-08-09 01:59:59 +00:00
if ( ( oi0 = = SUB_REAL ) & & ( oi1 = = SUB_REAL ) ) {
if ( p0 - > owner & & p1 - > owner ) {
2003-02-07 19:23:19 +00:00
/* If we don't have a call-wait in a 3-way, and we aren't in a 3-way, we can be master */
if ( ! p0 - > subs [ SUB_CALLWAIT ] . inthreeway & & ! p1 - > subs [ SUB_REAL ] . inthreeway ) {
master = p0 ;
slave = p1 ;
inconf = 1 ;
} else if ( ! p1 - > subs [ SUB_CALLWAIT ] . inthreeway & & ! p0 - > subs [ SUB_REAL ] . inthreeway ) {
master = p1 ;
slave = p0 ;
inconf = 1 ;
} else {
ast_log ( LOG_WARNING , " Huh? Both calls are callwaits or 3-ways? That's clever...? \n " ) ;
2005-08-09 01:59:59 +00:00
ast_log ( LOG_WARNING , " p0: chan %d/%d/CW%d/3W%d, p1: chan %d/%d/CW%d/3W%d \n " ,
p0 - > channel ,
oi0 , ( p0 - > subs [ SUB_CALLWAIT ] . zfd > - 1 ) ? 1 : 0 ,
p0 - > subs [ SUB_REAL ] . inthreeway , p0 - > channel ,
oi0 , ( p1 - > subs [ SUB_CALLWAIT ] . zfd > - 1 ) ? 1 : 0 ,
p1 - > subs [ SUB_REAL ] . inthreeway ) ;
2003-02-07 19:23:19 +00:00
}
2005-08-09 01:59:59 +00:00
nothingok = 0 ;
2003-02-07 19:23:19 +00:00
}
2005-08-09 01:59:59 +00:00
} else if ( ( oi0 = = SUB_REAL ) & & ( oi1 = = SUB_THREEWAY ) ) {
2003-02-07 19:23:19 +00:00
if ( p1 - > subs [ SUB_THREEWAY ] . inthreeway ) {
master = p1 ;
slave = p0 ;
2005-08-09 01:59:59 +00:00
nothingok = 0 ;
2003-02-07 19:23:19 +00:00
}
2005-08-09 01:59:59 +00:00
} else if ( ( oi0 = = SUB_THREEWAY ) & & ( oi1 = = SUB_REAL ) ) {
2003-02-07 19:23:19 +00:00
if ( p0 - > subs [ SUB_THREEWAY ] . inthreeway ) {
master = p0 ;
slave = p1 ;
2005-08-09 01:59:59 +00:00
nothingok = 0 ;
2003-02-07 19:23:19 +00:00
}
2005-08-09 01:59:59 +00:00
} else if ( ( oi0 = = SUB_REAL ) & & ( oi1 = = SUB_CALLWAIT ) ) {
2003-02-07 19:23:19 +00:00
/* We have a real and a call wait. If we're in a three way call, put us in it, otherwise,
don ' t put us in anything */
if ( p1 - > subs [ SUB_CALLWAIT ] . inthreeway ) {
master = p1 ;
slave = p0 ;
2005-08-09 01:59:59 +00:00
nothingok = 0 ;
2003-02-07 19:23:19 +00:00
}
2005-08-09 01:59:59 +00:00
} else if ( ( oi0 = = SUB_CALLWAIT ) & & ( oi1 = = SUB_REAL ) ) {
2003-02-07 19:23:19 +00:00
/* Same as previous */
if ( p0 - > subs [ SUB_CALLWAIT ] . inthreeway ) {
master = p0 ;
slave = p1 ;
2005-08-09 01:59:59 +00:00
nothingok = 0 ;
2003-02-07 19:23:19 +00:00
}
}
ast_log ( LOG_DEBUG , " master: %d, slave: %d, nothingok: %d \n " ,
master ? master - > channel : 0 , slave ? slave - > channel : 0 , nothingok ) ;
if ( master & & slave ) {
/* Stop any tones, or play ringtone as appropriate. If they're bridged
in an active threeway call with a channel that is ringing , we should
indicate ringing . */
if ( ( oi1 = = SUB_THREEWAY ) & &
2005-08-09 01:59:59 +00:00
p1 - > subs [ SUB_THREEWAY ] . inthreeway & &
p1 - > subs [ SUB_REAL ] . owner & &
p1 - > subs [ SUB_REAL ] . inthreeway & &
( p1 - > subs [ SUB_REAL ] . owner - > _state = = AST_STATE_RINGING ) ) {
ast_log ( LOG_DEBUG , " Playing ringback on %s since %s is in a ringing three-way \n " , c0 - > name , c1 - > name ) ;
tone_zone_play_tone ( p0 - > subs [ oi0 ] . zfd , ZT_TONE_RINGTONE ) ;
os1 = p1 - > subs [ SUB_REAL ] . owner - > _state ;
} else {
ast_log ( LOG_DEBUG , " Stopping tones on %d/%d talking to %d/%d \n " , p0 - > channel , oi0 , p1 - > channel , oi1 ) ;
tone_zone_play_tone ( p0 - > subs [ oi0 ] . zfd , - 1 ) ;
}
if ( ( oi0 = = SUB_THREEWAY ) & &
p0 - > subs [ SUB_THREEWAY ] . inthreeway & &
p0 - > subs [ SUB_REAL ] . owner & &
p0 - > subs [ SUB_REAL ] . inthreeway & &
( p0 - > subs [ SUB_REAL ] . owner - > _state = = AST_STATE_RINGING ) ) {
ast_log ( LOG_DEBUG , " Playing ringback on %s since %s is in a ringing three-way \n " , c1 - > name , c0 - > name ) ;
tone_zone_play_tone ( p1 - > subs [ oi1 ] . zfd , ZT_TONE_RINGTONE ) ;
os0 = p0 - > subs [ SUB_REAL ] . owner - > _state ;
2003-02-07 19:23:19 +00:00
} else {
2005-08-09 01:59:59 +00:00
ast_log ( LOG_DEBUG , " Stopping tones on %d/%d talking to %d/%d \n " , p1 - > channel , oi1 , p0 - > channel , oi0 ) ;
tone_zone_play_tone ( p1 - > subs [ oi0 ] . zfd , - 1 ) ;
2003-02-07 19:23:19 +00:00
}
2005-08-09 01:59:59 +00:00
if ( ( oi0 = = SUB_REAL ) & & ( oi1 = = SUB_REAL ) ) {
2003-02-07 19:23:19 +00:00
if ( ! p0 - > echocanbridged | | ! p1 - > echocanbridged ) {
/* Disable echo cancellation if appropriate */
zt_disable_ec ( p0 ) ;
zt_disable_ec ( p1 ) ;
}
}
zt_link ( slave , master ) ;
master - > inconference = inconf ;
} else if ( ! nothingok )
2005-08-09 01:59:59 +00:00
ast_log ( LOG_WARNING , " Can't link %d/%s with %d/%s \n " , p0 - > channel , subnames [ oi0 ] , p1 - > channel , subnames [ oi1 ] ) ;
2003-02-07 19:23:19 +00:00
update_conf ( p0 ) ;
update_conf ( p1 ) ;
2005-08-09 01:59:59 +00:00
t0 = p0 - > subs [ SUB_REAL ] . inthreeway ;
t1 = p1 - > subs [ SUB_REAL ] . inthreeway ;
2003-02-07 19:23:19 +00:00
2003-08-13 15:25:16 +00:00
ast_mutex_unlock ( & p0 - > lock ) ;
ast_mutex_unlock ( & p1 - > lock ) ;
2001-10-09 02:06:21 +00:00
2003-08-13 15:25:16 +00:00
ast_mutex_unlock ( & c0 - > lock ) ;
ast_mutex_unlock ( & c1 - > lock ) ;
2003-02-07 19:23:19 +00:00
/* Native bridge failed */
if ( ( ! master | | ! slave ) & & ! nothingok ) {
2005-08-09 01:59:59 +00:00
zt_enable_ec ( p0 ) ;
zt_enable_ec ( p1 ) ;
return AST_BRIDGE_FAILED ;
2003-02-07 19:23:19 +00:00
}
2005-08-09 01:59:59 +00:00
if ( ! ( flags & AST_BRIDGE_DTMF_CHANNEL_0 ) )
disable_dtmf_detect ( op0 ) ;
if ( ! ( flags & AST_BRIDGE_DTMF_CHANNEL_1 ) )
disable_dtmf_detect ( op1 ) ;
2001-10-09 02:06:21 +00:00
for ( ; ; ) {
2005-08-09 01:59:59 +00:00
struct ast_channel * c0_priority [ 2 ] = { c0 , c1 } ;
struct ast_channel * c1_priority [ 2 ] = { c1 , c0 } ;
int priority = 0 ;
2003-02-07 19:23:19 +00:00
/* Here's our main loop... Start by locking things, looking for private parts,
and then balking if anything is wrong */
2003-08-13 15:25:16 +00:00
ast_mutex_lock ( & c0 - > lock ) ;
ast_mutex_lock ( & c1 - > lock ) ;
2005-03-04 06:47:24 +00:00
p0 = c0 - > tech_pvt ;
p1 = c1 - > tech_pvt ;
2005-03-02 16:09:27 +00:00
2003-02-07 19:23:19 +00:00
if ( op0 = = p0 )
2005-08-09 01:59:59 +00:00
i0 = zt_get_index ( c0 , p0 , 1 ) ;
2003-02-07 19:23:19 +00:00
if ( op1 = = p1 )
2005-08-09 01:59:59 +00:00
i1 = zt_get_index ( c1 , p1 , 1 ) ;
2003-08-13 15:25:16 +00:00
ast_mutex_unlock ( & c0 - > lock ) ;
ast_mutex_unlock ( & c1 - > lock ) ;
2005-08-09 01:59:59 +00:00
if ( ( op0 ! = p0 ) | |
( op1 ! = p1 ) | |
( ofd0 ! = c0 - > fds [ 0 ] ) | |
( ofd1 ! = c1 - > fds [ 0 ] ) | |
( p0 - > subs [ SUB_REAL ] . owner & & ( os0 > - 1 ) & & ( os0 ! = p0 - > subs [ SUB_REAL ] . owner - > _state ) ) | |
( p1 - > subs [ SUB_REAL ] . owner & & ( os1 > - 1 ) & & ( os1 ! = p1 - > subs [ SUB_REAL ] . owner - > _state ) ) | |
( oc0 ! = p0 - > owner ) | |
( oc1 ! = p1 - > owner ) | |
( t0 ! = p0 - > subs [ SUB_REAL ] . inthreeway ) | |
( t1 ! = p1 - > subs [ SUB_REAL ] . inthreeway ) | |
( oi0 ! = i0 ) | |
( oi1 ! = i0 ) ) {
2003-02-07 19:23:19 +00:00
ast_log ( LOG_DEBUG , " Something changed out on %d/%d to %d/%d, returning -3 to restart \n " ,
2005-08-09 01:59:59 +00:00
op0 - > channel , oi0 , op1 - > channel , oi1 ) ;
res = AST_BRIDGE_RETRY ;
goto return_from_bridge ;
2001-10-09 02:06:21 +00:00
}
2005-08-15 14:57:58 +00:00
# ifdef PRI_2BCT
q931c0 = p0 - > call ;
q931c1 = p1 - > call ;
if ( p0 - > transfer & & p1 - > transfer
& & q931c0 & & q931c1
& & ! triedtopribridge ) {
pri_channel_bridge ( q931c0 , q931c1 ) ;
triedtopribridge = 1 ;
}
# endif
2003-02-07 19:23:19 +00:00
to = - 1 ;
2005-08-09 01:59:59 +00:00
who = ast_waitfor_n ( priority ? c0_priority : c1_priority , 2 , & to ) ;
2001-10-09 02:06:21 +00:00
if ( ! who ) {
2003-02-07 19:23:19 +00:00
ast_log ( LOG_DEBUG , " Ooh, empty read... \n " ) ;
2001-10-09 02:06:21 +00:00
continue ;
}
f = ast_read ( who ) ;
2005-08-09 01:59:59 +00:00
if ( ! f | | ( f - > frametype = = AST_FRAME_CONTROL ) ) {
2004-11-03 22:37:55 +00:00
* fo = f ;
* rc = who ;
2005-08-09 01:59:59 +00:00
res = AST_BRIDGE_COMPLETE ;
goto return_from_bridge ;
2004-11-03 22:37:55 +00:00
}
2003-02-07 19:23:19 +00:00
if ( f - > frametype = = AST_FRAME_DTMF ) {
2005-08-09 01:59:59 +00:00
if ( ( who = = c0 ) & & p0 - > pulsedial ) {
2003-02-07 19:23:19 +00:00
ast_write ( c1 , f ) ;
2005-08-09 01:59:59 +00:00
} else if ( p1 - > pulsedial ) {
2003-02-07 19:23:19 +00:00
ast_write ( c0 , f ) ;
2005-08-09 01:59:59 +00:00
} else {
* fo = f ;
* rc = who ;
res = AST_BRIDGE_COMPLETE ;
goto return_from_bridge ;
2001-10-09 02:06:21 +00:00
}
2003-02-07 19:23:19 +00:00
}
ast_frfree ( f ) ;
2005-08-09 01:59:59 +00:00
2001-10-09 02:06:21 +00:00
/* Swap who gets priority */
2005-08-09 01:59:59 +00:00
priority = ! priority ;
2001-10-09 02:06:21 +00:00
}
2005-08-09 01:59:59 +00:00
return_from_bridge :
if ( op0 = = p0 )
zt_enable_ec ( p0 ) ;
if ( op1 = = p1 )
zt_enable_ec ( p1 ) ;
if ( ! ( flags & AST_BRIDGE_DTMF_CHANNEL_0 ) )
enable_dtmf_detect ( op0 ) ;
if ( ! ( flags & AST_BRIDGE_DTMF_CHANNEL_1 ) )
enable_dtmf_detect ( op1 ) ;
zt_unlink ( slave , master , 1 ) ;
return res ;
2001-10-09 02:06:21 +00:00
}
2004-04-06 22:17:32 +00:00
static int zt_fixup ( struct ast_channel * oldchan , struct ast_channel * newchan )
2001-10-09 02:06:21 +00:00
{
2005-03-04 06:47:24 +00:00
struct zt_pvt * p = newchan - > tech_pvt ;
2001-10-09 02:06:21 +00:00
int x ;
2004-04-06 22:17:32 +00:00
ast_mutex_lock ( & p - > lock ) ;
2001-10-09 02:06:21 +00:00
ast_log ( LOG_DEBUG , " New owner for channel %d is %s \n " , p - > channel , newchan - > name ) ;
2004-06-06 01:54:22 +00:00
if ( p - > owner = = oldchan ) {
2003-02-07 19:23:19 +00:00
p - > owner = newchan ;
2004-06-06 01:54:22 +00:00
}
2001-10-09 02:06:21 +00:00
for ( x = 0 ; x < 3 ; x + + )
2003-02-07 19:23:19 +00:00
if ( p - > subs [ x ] . owner = = oldchan ) {
if ( ! x )
2004-02-20 21:23:22 +00:00
zt_unlink ( NULL , p , 0 ) ;
2003-02-07 19:23:19 +00:00
p - > subs [ x ] . owner = newchan ;
}
2002-09-10 04:45:51 +00:00
if ( newchan - > _state = = AST_STATE_RINGING )
2001-10-09 02:06:21 +00:00
zt_indicate ( newchan , AST_CONTROL_RINGING ) ;
2003-02-07 19:23:19 +00:00
update_conf ( p ) ;
2004-04-06 22:17:32 +00:00
ast_mutex_unlock ( & p - > lock ) ;
2001-10-09 02:06:21 +00:00
return 0 ;
}
static int zt_ring_phone ( struct zt_pvt * p )
{
int x ;
int res ;
/* Make sure our transmit state is on hook */
x = 0 ;
x = ZT_ONHOOK ;
2003-02-07 19:23:19 +00:00
res = ioctl ( p - > subs [ SUB_REAL ] . zfd , ZT_HOOK , & x ) ;
2001-10-09 02:06:21 +00:00
do {
x = ZT_RING ;
2003-02-07 19:23:19 +00:00
res = ioctl ( p - > subs [ SUB_REAL ] . zfd , ZT_HOOK , & x ) ;
2001-10-09 02:06:21 +00:00
#if 0
printf ( " Res: %d, error: %s \n " , res , strerror ( errno ) ) ;
# endif
if ( res ) {
switch ( errno ) {
case EBUSY :
case EINTR :
/* Wait just in case */
usleep ( 10000 ) ;
continue ;
case EINPROGRESS :
res = 0 ;
break ;
default :
ast_log ( LOG_WARNING , " Couldn't ring the phone: %s \n " , strerror ( errno ) ) ;
res = 0 ;
}
}
} while ( res ) ;
return res ;
}
static void * ss_thread ( void * data ) ;
2003-11-21 18:38:42 +00:00
static struct ast_channel * zt_new ( struct zt_pvt * , int , int , int , int , int ) ;
2001-10-09 02:06:21 +00:00
static int attempt_transfer ( struct zt_pvt * p )
{
/* In order to transfer, we need at least one of the channels to
actually be in a call bridge . We can ' t conference two applications
together ( but then , why would we want to ? ) */
2004-10-23 12:19:47 +00:00
if ( ast_bridged_channel ( p - > subs [ SUB_REAL ] . owner ) ) {
2003-02-07 19:23:19 +00:00
/* The three-way person we're about to transfer to could still be in MOH, so
stop if now if appropriate */
2004-10-23 12:19:47 +00:00
if ( ast_bridged_channel ( p - > subs [ SUB_THREEWAY ] . owner ) )
ast_moh_stop ( ast_bridged_channel ( p - > subs [ SUB_THREEWAY ] . owner ) ) ;
2003-02-07 19:23:19 +00:00
if ( p - > subs [ SUB_THREEWAY ] . owner - > _state = = AST_STATE_RINGING ) {
2004-10-23 12:19:47 +00:00
ast_indicate ( ast_bridged_channel ( p - > subs [ SUB_REAL ] . owner ) , AST_CONTROL_RINGING ) ;
2003-02-07 19:23:19 +00:00
}
2004-10-03 19:59:46 +00:00
if ( p - > subs [ SUB_REAL ] . owner - > cdr ) {
/* Move CDR from second channel to current one */
p - > subs [ SUB_THREEWAY ] . owner - > cdr =
ast_cdr_append ( p - > subs [ SUB_THREEWAY ] . owner - > cdr , p - > subs [ SUB_REAL ] . owner - > cdr ) ;
p - > subs [ SUB_REAL ] . owner - > cdr = NULL ;
}
2004-10-23 12:19:47 +00:00
if ( ast_bridged_channel ( p - > subs [ SUB_REAL ] . owner ) - > cdr ) {
2004-10-03 19:59:46 +00:00
/* Move CDR from second channel's bridge to current one */
p - > subs [ SUB_THREEWAY ] . owner - > cdr =
2004-10-23 12:19:47 +00:00
ast_cdr_append ( p - > subs [ SUB_THREEWAY ] . owner - > cdr , ast_bridged_channel ( p - > subs [ SUB_REAL ] . owner ) - > cdr ) ;
ast_bridged_channel ( p - > subs [ SUB_REAL ] . owner ) - > cdr = NULL ;
2004-10-03 19:59:46 +00:00
}
2004-10-23 12:19:47 +00:00
if ( ast_channel_masquerade ( p - > subs [ SUB_THREEWAY ] . owner , ast_bridged_channel ( p - > subs [ SUB_REAL ] . owner ) ) ) {
2001-10-09 02:06:21 +00:00
ast_log ( LOG_WARNING , " Unable to masquerade %s as %s \n " ,
2004-10-23 12:19:47 +00:00
ast_bridged_channel ( p - > subs [ SUB_REAL ] . owner ) - > name , p - > subs [ SUB_THREEWAY ] . owner - > name ) ;
2001-10-09 02:06:21 +00:00
return - 1 ;
}
2004-07-24 23:53:02 +00:00
/* Orphan the channel after releasing the lock */
ast_mutex_unlock ( & p - > subs [ SUB_THREEWAY ] . owner - > lock ) ;
2003-02-07 19:23:19 +00:00
unalloc_sub ( p , SUB_THREEWAY ) ;
2004-10-23 12:19:47 +00:00
} else if ( ast_bridged_channel ( p - > subs [ SUB_THREEWAY ] . owner ) ) {
2003-02-07 19:23:19 +00:00
if ( p - > subs [ SUB_REAL ] . owner - > _state = = AST_STATE_RINGING ) {
2004-10-23 12:19:47 +00:00
ast_indicate ( ast_bridged_channel ( p - > subs [ SUB_THREEWAY ] . owner ) , AST_CONTROL_RINGING ) ;
2003-02-07 19:23:19 +00:00
}
2004-10-23 12:19:47 +00:00
ast_moh_stop ( ast_bridged_channel ( p - > subs [ SUB_THREEWAY ] . owner ) ) ;
2004-10-03 19:59:46 +00:00
if ( p - > subs [ SUB_THREEWAY ] . owner - > cdr ) {
/* Move CDR from second channel to current one */
p - > subs [ SUB_REAL ] . owner - > cdr =
ast_cdr_append ( p - > subs [ SUB_REAL ] . owner - > cdr , p - > subs [ SUB_THREEWAY ] . owner - > cdr ) ;
p - > subs [ SUB_THREEWAY ] . owner - > cdr = NULL ;
}
2004-10-23 12:19:47 +00:00
if ( ast_bridged_channel ( p - > subs [ SUB_THREEWAY ] . owner ) - > cdr ) {
2004-10-03 19:59:46 +00:00
/* Move CDR from second channel's bridge to current one */
p - > subs [ SUB_REAL ] . owner - > cdr =
2004-10-23 12:19:47 +00:00
ast_cdr_append ( p - > subs [ SUB_REAL ] . owner - > cdr , ast_bridged_channel ( p - > subs [ SUB_THREEWAY ] . owner ) - > cdr ) ;
ast_bridged_channel ( p - > subs [ SUB_THREEWAY ] . owner ) - > cdr = NULL ;
2004-10-03 19:59:46 +00:00
}
2004-10-23 12:19:47 +00:00
if ( ast_channel_masquerade ( p - > subs [ SUB_REAL ] . owner , ast_bridged_channel ( p - > subs [ SUB_THREEWAY ] . owner ) ) ) {
2001-10-09 02:06:21 +00:00
ast_log ( LOG_WARNING , " Unable to masquerade %s as %s \n " ,
2004-10-23 12:19:47 +00:00
ast_bridged_channel ( p - > subs [ SUB_THREEWAY ] . owner ) - > name , p - > subs [ SUB_REAL ] . owner - > name ) ;
2001-10-09 02:06:21 +00:00
return - 1 ;
}
2004-07-27 00:53:09 +00:00
/* Three-way is now the REAL */
2004-07-26 13:38:47 +00:00
swap_subs ( p , SUB_THREEWAY , SUB_REAL ) ;
2004-07-27 00:53:09 +00:00
ast_mutex_unlock ( & p - > subs [ SUB_REAL ] . owner - > lock ) ;
2003-02-07 19:23:19 +00:00
unalloc_sub ( p , SUB_THREEWAY ) ;
/* Tell the caller not to hangup */
return 1 ;
2001-10-09 02:06:21 +00:00
} else {
ast_log ( LOG_DEBUG , " Neither %s nor %s are in a bridge, nothing to transfer \n " ,
2003-02-07 19:23:19 +00:00
p - > subs [ SUB_REAL ] . owner - > name , p - > subs [ SUB_THREEWAY ] . owner - > name ) ;
p - > subs [ SUB_THREEWAY ] . owner - > _softhangup | = AST_SOFTHANGUP_DEV ;
2005-08-11 16:43:36 +00:00
return - 1 ;
2001-10-09 02:06:21 +00:00
}
return 0 ;
}
2003-02-07 19:23:19 +00:00
# ifdef ZAPATA_R2
static struct ast_frame * handle_r2_event ( struct zt_pvt * p , mfcr2_event_t * e , int index )
{
struct ast_frame * f ;
f = & p - > subs [ index ] . f ;
if ( ! p - > r2 ) {
ast_log ( LOG_WARNING , " Huh? No R2 structure :( \n " ) ;
return NULL ;
}
switch ( e - > e ) {
case MFCR2_EVENT_BLOCKED :
if ( option_verbose > 2 )
ast_verbose ( VERBOSE_PREFIX_3 " Channel %d blocked \n " , p - > channel ) ;
break ;
case MFCR2_EVENT_UNBLOCKED :
if ( option_verbose > 2 )
ast_verbose ( VERBOSE_PREFIX_3 " Channel %d unblocked \n " , p - > channel ) ;
break ;
case MFCR2_EVENT_CONFIG_ERR :
if ( option_verbose > 2 )
ast_verbose ( VERBOSE_PREFIX_3 " Config error on channel %d \n " , p - > channel ) ;
break ;
case MFCR2_EVENT_RING :
if ( option_verbose > 2 )
ast_verbose ( VERBOSE_PREFIX_3 " Ring on channel %d \n " , p - > channel ) ;
break ;
case MFCR2_EVENT_HANGUP :
if ( option_verbose > 2 )
ast_verbose ( VERBOSE_PREFIX_3 " Hangup on channel %d \n " , p - > channel ) ;
break ;
case MFCR2_EVENT_RINGING :
if ( option_verbose > 2 )
ast_verbose ( VERBOSE_PREFIX_3 " Ringing on channel %d \n " , p - > channel ) ;
break ;
case MFCR2_EVENT_ANSWER :
if ( option_verbose > 2 )
ast_verbose ( VERBOSE_PREFIX_3 " Answer on channel %d \n " , p - > channel ) ;
break ;
case MFCR2_EVENT_HANGUP_ACK :
if ( option_verbose > 2 )
ast_verbose ( VERBOSE_PREFIX_3 " Hangup ACK on channel %d \n " , p - > channel ) ;
break ;
case MFCR2_EVENT_IDLE :
if ( option_verbose > 2 )
ast_verbose ( VERBOSE_PREFIX_3 " Idle on channel %d \n " , p - > channel ) ;
break ;
default :
ast_log ( LOG_WARNING , " Unknown MFC/R2 event %d \n " , e - > e ) ;
break ;
}
return f ;
}
static mfcr2_event_t * r2_get_event_bits ( struct zt_pvt * p )
{
int x ;
int res ;
mfcr2_event_t * e ;
res = ioctl ( p - > subs [ SUB_REAL ] . zfd , ZT_GETRXBITS , & x ) ;
if ( res ) {
ast_log ( LOG_WARNING , " Unable to check received bits \n " ) ;
return NULL ;
}
if ( ! p - > r2 ) {
ast_log ( LOG_WARNING , " Odd, no R2 structure on channel %d \n " , p - > channel ) ;
return NULL ;
}
e = mfcr2_cas_signaling_event ( p - > r2 , x ) ;
return e ;
}
# endif
2003-02-24 06:00:18 +00:00
static int check_for_conference ( struct zt_pvt * p )
{
ZT_CONFINFO ci ;
/* Fine if we already have a master, etc */
if ( p - > master | | ( p - > confno > - 1 ) )
return 0 ;
memset ( & ci , 0 , sizeof ( ci ) ) ;
if ( ioctl ( p - > subs [ SUB_REAL ] . zfd , ZT_GETCONF , & ci ) ) {
ast_log ( LOG_WARNING , " Failed to get conference info on channel %d \n " , p - > channel ) ;
return 0 ;
}
/* If we have no master and don't have a confno, then
if we ' re in a conference , it ' s probably a MeetMe room or
some such , so don ' t let us 3 - way out ! */
2003-08-23 17:49:54 +00:00
if ( ( p - > subs [ SUB_REAL ] . curconf . confno ! = ci . confno ) | | ( p - > subs [ SUB_REAL ] . curconf . confmode ! = ci . confmode ) ) {
2003-02-24 06:00:18 +00:00
if ( option_verbose > 2 )
ast_verbose ( VERBOSE_PREFIX_3 " Avoiding 3-way call when in an external conference \n " ) ;
return 1 ;
}
return 0 ;
}
2003-02-28 06:00:18 +00:00
static int get_alarms ( struct zt_pvt * p )
{
int res ;
ZT_SPANINFO zi ;
memset ( & zi , 0 , sizeof ( zi ) ) ;
zi . spanno = p - > span ;
res = ioctl ( p - > subs [ SUB_REAL ] . zfd , ZT_SPANSTAT , & zi ) ;
if ( res < 0 ) {
ast_log ( LOG_WARNING , " Unable to determine alarm on channel %d \n " , p - > channel ) ;
return 0 ;
}
return zi . alarms ;
}
2003-02-24 06:00:18 +00:00
2003-02-07 19:23:19 +00:00
static struct ast_frame * zt_handle_event ( struct ast_channel * ast )
2001-10-09 02:06:21 +00:00
{
int res , x ;
int index ;
2004-01-16 23:40:37 +00:00
char * c ;
2005-03-04 06:47:24 +00:00
struct zt_pvt * p = ast - > tech_pvt ;
2001-10-09 02:06:21 +00:00
pthread_t threadid ;
pthread_attr_t attr ;
struct ast_channel * chan ;
2005-07-15 16:03:02 +00:00
2001-10-09 02:06:21 +00:00
pthread_attr_init ( & attr ) ;
pthread_attr_setdetachstate ( & attr , PTHREAD_CREATE_DETACHED ) ;
2005-07-15 16:03:02 +00:00
2001-10-09 02:06:21 +00:00
index = zt_get_index ( ast , p , 0 ) ;
2003-02-07 19:23:19 +00:00
p - > subs [ index ] . f . frametype = AST_FRAME_NULL ;
p - > subs [ index ] . f . datalen = 0 ;
p - > subs [ index ] . f . samples = 0 ;
p - > subs [ index ] . f . mallocd = 0 ;
p - > subs [ index ] . f . offset = 0 ;
p - > subs [ index ] . f . src = " zt_handle_event " ;
p - > subs [ index ] . f . data = NULL ;
2001-10-09 02:06:21 +00:00
if ( index < 0 )
2003-02-07 19:23:19 +00:00
return & p - > subs [ index ] . f ;
2003-11-12 00:13:22 +00:00
if ( p - > fake_event ) {
res = p - > fake_event ;
p - > fake_event = 0 ;
} else
res = zt_get_event ( p - > subs [ index ] . zfd ) ;
2005-07-15 16:03:02 +00:00
2001-10-09 02:06:21 +00:00
ast_log ( LOG_DEBUG , " Got event %s(%d) on channel %d (index %d) \n " , event2str ( res ) , res , p - > channel , index ) ;
2005-07-15 16:03:02 +00:00
2005-05-02 20:16:21 +00:00
if ( res & ( ZT_EVENT_PULSEDIGIT | ZT_EVENT_DTMFUP ) ) {
2003-02-07 19:23:19 +00:00
if ( res & ZT_EVENT_PULSEDIGIT )
p - > pulsedial = 1 ;
else
p - > pulsedial = 0 ;
2005-08-16 16:12:22 +00:00
ast_log ( LOG_DEBUG , " Detected %sdigit '%c' \n " , p - > pulsedial ? " pulse " : " " , res & 0xff ) ;
2005-08-17 17:52:14 +00:00
# ifdef ZAPATA_PRI
2005-08-16 16:12:22 +00:00
if ( ( p - > proceeding < 2 ) & & p - > sig = = SIG_PRI & & p - > pri & & p - > pri - > overlapdial ) {
p - > subs [ index ] . f . frametype = AST_FRAME_NULL ;
p - > subs [ index ] . f . subclass = 0 ;
} else {
2005-08-17 17:52:14 +00:00
# endif
2005-08-16 16:12:22 +00:00
p - > subs [ index ] . f . frametype = AST_FRAME_DTMF ;
p - > subs [ index ] . f . subclass = res & 0xff ;
2005-08-17 17:52:14 +00:00
# ifdef ZAPATA_PRI
2005-08-16 16:12:22 +00:00
}
2005-08-17 17:52:14 +00:00
# endif
2005-05-02 20:16:21 +00:00
/* Unmute conference, return the captured digit */
zt_confmute ( p , 0 ) ;
return & p - > subs [ index ] . f ;
}
2005-07-15 16:03:02 +00:00
2005-05-02 20:16:21 +00:00
if ( res & ZT_EVENT_DTMFDOWN ) {
ast_log ( LOG_DEBUG , " DTMF Down '%c' \n " , res & 0xff ) ;
p - > subs [ index ] . f . frametype = AST_FRAME_NULL ;
p - > subs [ index ] . f . subclass = 0 ;
zt_confmute ( p , 1 ) ;
/* Mute conference, return null frame */
2003-02-07 19:23:19 +00:00
return & p - > subs [ index ] . f ;
}
2005-07-15 16:03:02 +00:00
2001-10-09 02:06:21 +00:00
switch ( res ) {
2003-02-07 19:23:19 +00:00
case ZT_EVENT_BITSCHANGED :
if ( p - > sig = = SIG_R2 ) {
# ifdef ZAPATA_R2
struct ast_frame * f = & p - > subs [ index ] . f ;
mfcr2_event_t * e ;
e = r2_get_event_bits ( p ) ;
if ( e )
f = handle_r2_event ( p , e , index ) ;
return f ;
# else
break ;
# endif
}
ast_log ( LOG_WARNING , " Recieved bits changed on %s signalling? \n " , sig2str ( p - > sig ) ) ;
case ZT_EVENT_PULSE_START :
/* Stop tone if there's a pulse start and the PBX isn't started */
if ( ! ast - > pbx )
tone_zone_play_tone ( p - > subs [ index ] . zfd , - 1 ) ;
break ;
2001-10-09 02:06:21 +00:00
case ZT_EVENT_DIALCOMPLETE :
if ( p - > inalarm ) break ;
2003-02-07 19:23:19 +00:00
if ( p - > radio ) break ;
if ( ioctl ( p - > subs [ index ] . zfd , ZT_DIALING , & x ) = = - 1 ) {
2001-10-09 02:06:21 +00:00
ast_log ( LOG_DEBUG , " ZT_DIALING ioctl failed on %s \n " , ast - > name ) ;
return NULL ;
}
2001-12-29 18:04:21 +00:00
if ( ! x ) { /* if not still dialing in driver */
2001-10-09 02:06:21 +00:00
zt_enable_ec ( p ) ;
2003-11-05 22:32:20 +00:00
if ( p - > echobreak ) {
2003-12-02 23:09:04 +00:00
zt_train_ec ( p ) ;
2005-05-15 23:26:45 +00:00
ast_copy_string ( p - > dop . dialstr , p - > echorest , sizeof ( p - > dop . dialstr ) ) ;
2003-11-05 22:32:20 +00:00
p - > dop . op = ZT_DIAL_OP_REPLACE ;
res = ioctl ( p - > subs [ SUB_REAL ] . zfd , ZT_DIAL , & p - > dop ) ;
p - > echobreak = 0 ;
} else {
p - > dialing = 0 ;
2004-01-16 23:40:37 +00:00
if ( p - > sig = = SIG_E911 ) {
/* if thru with dialing after offhook */
if ( ast - > _state = = AST_STATE_DIALING_OFFHOOK ) {
ast_setstate ( ast , AST_STATE_UP ) ;
p - > subs [ index ] . f . frametype = AST_FRAME_CONTROL ;
p - > subs [ index ] . f . subclass = AST_CONTROL_ANSWER ;
break ;
} else { /* if to state wait for offhook to dial rest */
/* we now wait for off hook */
ast_setstate ( ast , AST_STATE_DIALING_OFFHOOK ) ;
}
}
2003-11-05 22:32:20 +00:00
if ( ast - > _state = = AST_STATE_DIALING ) {
2004-06-25 21:17:08 +00:00
if ( ( p - > callprogress & 1 ) & & CANPROGRESSDETECT ( p ) & & p - > dsp & & p - > outgoing ) {
2003-11-05 22:32:20 +00:00
ast_log ( LOG_DEBUG , " Done dialing, but waiting for progress detection before doing more... \n " ) ;
2004-04-16 18:00:00 +00:00
} else if ( p - > confirmanswer | | ( ! p - > dialednone & & ( ( p - > sig = = SIG_EM ) | | ( p - > sig = = SIG_EM_E1 ) | | ( p - > sig = = SIG_EMWINK ) | | ( p - > sig = = SIG_FEATD ) | | ( p - > sig = = SIG_FEATDMF ) | | ( p - > sig = = SIG_E911 ) | | ( p - > sig = = SIG_FEATB ) | | ( p - > sig = = SIG_SF ) | | ( p - > sig = = SIG_SFWINK ) | | ( p - > sig = = SIG_SF_FEATD ) | | ( p - > sig = = SIG_SF_FEATDMF ) | | ( p - > sig = = SIG_SF_FEATB ) ) ) ) {
2003-11-05 22:32:20 +00:00
ast_setstate ( ast , AST_STATE_RINGING ) ;
2005-02-08 07:49:40 +00:00
} else if ( ! p - > answeronpolarityswitch ) {
2003-11-05 22:32:20 +00:00
ast_setstate ( ast , AST_STATE_UP ) ;
p - > subs [ index ] . f . frametype = AST_FRAME_CONTROL ;
p - > subs [ index ] . f . subclass = AST_CONTROL_ANSWER ;
}
2001-12-29 18:04:21 +00:00
}
2001-10-09 02:06:21 +00:00
}
}
break ;
case ZT_EVENT_ALARM :
2003-08-13 21:06:00 +00:00
# ifdef ZAPATA_PRI
2003-08-25 20:39:07 +00:00
if ( p - > call ) {
2003-08-25 21:17:38 +00:00
if ( p - > pri & & p - > pri - > pri ) {
2004-06-06 23:26:29 +00:00
if ( ! pri_grab ( p , p - > pri ) ) {
pri_hangup ( p - > pri - > pri , p - > call , - 1 ) ;
pri_destroycall ( p - > pri - > pri , p - > call ) ;
pri_rel ( p - > pri ) ;
} else
ast_log ( LOG_WARNING , " Failed to grab PRI! \n " ) ;
2003-08-25 21:17:38 +00:00
} else
2003-08-25 20:39:07 +00:00
ast_log ( LOG_WARNING , " The PRI Call have not been destroyed \n " ) ;
}
2003-08-25 21:17:38 +00:00
if ( p - > owner )
p - > owner - > _softhangup | = AST_SOFTHANGUP_DEV ;
2003-08-12 20:27:53 +00:00
p - > call = NULL ;
2004-06-06 23:26:29 +00:00
if ( p - > bearer )
p - > bearer - > inalarm = 1 ;
else
2003-08-12 20:27:53 +00:00
# endif
2001-10-09 02:06:21 +00:00
p - > inalarm = 1 ;
2003-02-28 06:00:18 +00:00
res = get_alarms ( p ) ;
ast_log ( LOG_WARNING , " Detected alarm on channel %d: %s \n " , p - > channel , alarm2str ( res ) ) ;
2003-08-18 14:20:12 +00:00
manager_event ( EVENT_FLAG_SYSTEM , " Alarm " ,
2003-08-18 14:19:15 +00:00
" Alarm: %s \r \n "
" Channel: %d \r \n " ,
alarm2str ( res ) , p - > channel ) ;
2001-10-09 02:06:21 +00:00
/* fall through intentionally */
case ZT_EVENT_ONHOOK :
2003-02-07 19:23:19 +00:00
if ( p - > radio )
{
p - > subs [ index ] . f . frametype = AST_FRAME_CONTROL ;
p - > subs [ index ] . f . subclass = AST_CONTROL_RADIO_UNKEY ;
break ;
}
2001-10-09 02:06:21 +00:00
switch ( p - > sig ) {
case SIG_FXOLS :
case SIG_FXOGS :
case SIG_FXOKS :
2003-02-07 19:23:19 +00:00
p - > onhooktime = time ( NULL ) ;
p - > msgstate = - 1 ;
2001-10-09 02:06:21 +00:00
/* Check for some special conditions regarding call waiting */
2003-02-07 19:23:19 +00:00
if ( index = = SUB_REAL ) {
2001-10-09 02:06:21 +00:00
/* The normal line was hung up */
2003-02-07 19:23:19 +00:00
if ( p - > subs [ SUB_CALLWAIT ] . owner ) {
/* There's a call waiting call, so ring the phone, but make it unowned in the mean time */
swap_subs ( p , SUB_CALLWAIT , SUB_REAL ) ;
2001-10-09 02:06:21 +00:00
if ( option_verbose > 2 )
2003-02-07 19:23:19 +00:00
ast_verbose ( VERBOSE_PREFIX_3 " Channel %d still has (callwait) call, ringing phone \n " , p - > channel ) ;
unalloc_sub ( p , SUB_CALLWAIT ) ;
#if 0
p - > subs [ index ] . needanswer = 0 ;
p - > subs [ index ] . needringing = 0 ;
# endif
2001-10-09 02:06:21 +00:00
p - > callwaitingrepeat = 0 ;
2003-02-07 19:23:19 +00:00
p - > cidcwexpire = 0 ;
p - > owner = NULL ;
2004-06-26 18:38:19 +00:00
/* Don't start streaming audio yet if the incoming call isn't up yet */
if ( p - > subs [ SUB_REAL ] . owner - > _state ! = AST_STATE_UP )
p - > dialing = 1 ;
2001-10-09 02:06:21 +00:00
zt_ring_phone ( p ) ;
2003-02-07 19:23:19 +00:00
} else if ( p - > subs [ SUB_THREEWAY ] . owner ) {
2003-03-21 16:26:50 +00:00
unsigned int mssinceflash ;
2004-07-24 23:38:23 +00:00
/* Here we have to retain the lock on both the main channel, the 3-way channel, and
the private structure - - not especially easy or clean */
while ( p - > subs [ SUB_THREEWAY ] . owner & & ast_mutex_trylock ( & p - > subs [ SUB_THREEWAY ] . owner - > lock ) ) {
/* Yuck, didn't get the lock on the 3-way, gotta release everything and re-grab! */
ast_mutex_unlock ( & p - > lock ) ;
ast_mutex_unlock ( & ast - > lock ) ;
usleep ( 1 ) ;
/* We can grab ast and p in that order, without worry. We should make sure
nothing seriously bad has happened though like some sort of bizarre double
masquerade ! */
ast_mutex_lock ( & ast - > lock ) ;
ast_mutex_lock ( & p - > lock ) ;
if ( p - > owner ! = ast ) {
ast_log ( LOG_WARNING , " This isn't good... \n " ) ;
return NULL ;
}
}
2004-07-24 23:45:37 +00:00
if ( ! p - > subs [ SUB_THREEWAY ] . owner ) {
2004-07-24 23:38:23 +00:00
ast_log ( LOG_NOTICE , " Whoa, threeway disappeared kinda randomly. \n " ) ;
return NULL ;
}
2005-07-15 23:00:47 +00:00
mssinceflash = ast_tvdiff_ms ( ast_tvnow ( ) , p - > flashtime ) ;
2003-04-11 04:31:33 +00:00
ast_log ( LOG_DEBUG , " Last flash was %d ms ago \n " , mssinceflash ) ;
2003-03-21 16:26:50 +00:00
if ( mssinceflash < MIN_MS_SINCE_FLASH ) {
/* It hasn't been long enough since the last flashook. This is probably a bounce on
hanging up . Hangup both channels now */
2003-04-11 04:31:33 +00:00
if ( p - > subs [ SUB_THREEWAY ] . owner )
2004-04-06 22:17:32 +00:00
ast_queue_hangup ( p - > subs [ SUB_THREEWAY ] . owner ) ;
2003-03-21 16:26:50 +00:00
p - > subs [ SUB_THREEWAY ] . owner - > _softhangup | = AST_SOFTHANGUP_DEV ;
ast_log ( LOG_DEBUG , " Looks like a bounced flash, hanging up both calls on %d \n " , p - > channel ) ;
2004-07-24 23:38:23 +00:00
ast_mutex_unlock ( & p - > subs [ SUB_THREEWAY ] . owner - > lock ) ;
2005-07-15 16:03:02 +00:00
} else if ( ( ast - > pbx ) | | ( ast - > _state = = AST_STATE_UP ) ) {
2003-02-07 19:23:19 +00:00
if ( p - > transfer ) {
/* In any case this isn't a threeway call anymore */
p - > subs [ SUB_REAL ] . inthreeway = 0 ;
p - > subs [ SUB_THREEWAY ] . inthreeway = 0 ;
2005-07-15 16:03:02 +00:00
/* Only attempt transfer if the phone is ringing; why transfer to busy tone eh? */
if ( ! p - > transfertobusy & & ast - > _state = = AST_STATE_BUSY ) {
2005-06-23 14:51:52 +00:00
ast_mutex_unlock ( & p - > subs [ SUB_THREEWAY ] . owner - > lock ) ;
/* Swap subs and dis-own channel */
swap_subs ( p , SUB_THREEWAY , SUB_REAL ) ;
p - > owner = NULL ;
/* Ring the phone */
zt_ring_phone ( p ) ;
} else {
2005-07-15 16:03:02 +00:00
if ( ( res = attempt_transfer ( p ) ) < 0 ) {
2005-06-09 22:23:21 +00:00
p - > subs [ SUB_THREEWAY ] . owner - > _softhangup | = AST_SOFTHANGUP_DEV ;
2005-07-15 16:03:02 +00:00
if ( p - > subs [ SUB_THREEWAY ] . owner )
ast_mutex_unlock ( & p - > subs [ SUB_THREEWAY ] . owner - > lock ) ;
} else if ( res ) {
2005-06-09 22:23:21 +00:00
/* Don't actually hang up at this point */
if ( p - > subs [ SUB_THREEWAY ] . owner )
ast_mutex_unlock ( & p - > subs [ SUB_THREEWAY ] . owner - > lock ) ;
break ;
}
2003-02-07 19:23:19 +00:00
}
2005-07-15 16:03:02 +00:00
} else {
2003-02-07 19:23:19 +00:00
p - > subs [ SUB_THREEWAY ] . owner - > _softhangup | = AST_SOFTHANGUP_DEV ;
2005-07-15 16:03:02 +00:00
if ( p - > subs [ SUB_THREEWAY ] . owner )
ast_mutex_unlock ( & p - > subs [ SUB_THREEWAY ] . owner - > lock ) ;
}
2003-02-07 19:23:19 +00:00
} else {
2004-07-24 23:38:23 +00:00
ast_mutex_unlock ( & p - > subs [ SUB_THREEWAY ] . owner - > lock ) ;
2003-02-07 19:23:19 +00:00
/* Swap subs and dis-own channel */
swap_subs ( p , SUB_THREEWAY , SUB_REAL ) ;
p - > owner = NULL ;
/* Ring the phone */
zt_ring_phone ( p ) ;
2001-10-09 02:06:21 +00:00
}
}
2003-02-07 19:23:19 +00:00
} else {
ast_log ( LOG_WARNING , " Got a hangup and my index is %d? \n " , index ) ;
2001-10-09 02:06:21 +00:00
}
/* Fall through */
default :
zt_disable_ec ( p ) ;
return NULL ;
}
break ;
case ZT_EVENT_RINGOFFHOOK :
if ( p - > inalarm ) break ;
2003-02-07 19:23:19 +00:00
if ( p - > radio )
{
p - > subs [ index ] . f . frametype = AST_FRAME_CONTROL ;
p - > subs [ index ] . f . subclass = AST_CONTROL_RADIO_KEY ;
break ;
}
2004-01-16 23:40:37 +00:00
/* for E911, its supposed to wait for offhook then dial
the second half of the dial string */
if ( ( p - > sig = = SIG_E911 ) & & ( ast - > _state = = AST_STATE_DIALING_OFFHOOK ) ) {
c = strchr ( p - > dialdest , ' / ' ) ;
if ( c )
c + + ;
else
c = p - > dialdest ;
if ( * c ) snprintf ( p - > dop . dialstr , sizeof ( p - > dop . dialstr ) , " M*0%s# " , c ) ;
2005-05-15 23:26:45 +00:00
else ast_copy_string ( p - > dop . dialstr , " M*2# " , sizeof ( p - > dop . dialstr ) ) ;
2004-01-16 23:40:37 +00:00
if ( strlen ( p - > dop . dialstr ) > 4 ) {
2004-06-23 22:00:04 +00:00
memset ( p - > echorest , ' w ' , sizeof ( p - > echorest ) - 1 ) ;
2004-06-23 22:01:46 +00:00
strcpy ( p - > echorest + ( p - > echotraining / 401 ) + 1 , p - > dop . dialstr + strlen ( p - > dop . dialstr ) - 2 ) ;
2004-07-16 04:40:54 +00:00
p - > echorest [ sizeof ( p - > echorest ) - 1 ] = ' \0 ' ;
2004-01-16 23:40:37 +00:00
p - > echobreak = 1 ;
p - > dop . dialstr [ strlen ( p - > dop . dialstr ) - 2 ] = ' \0 ' ;
} else
p - > echobreak = 0 ;
if ( ioctl ( p - > subs [ SUB_REAL ] . zfd , ZT_DIAL , & p - > dop ) ) {
x = ZT_ONHOOK ;
ioctl ( p - > subs [ SUB_REAL ] . zfd , ZT_HOOK , & x ) ;
ast_log ( LOG_WARNING , " Dialing failed on channel %d: %s \n " , p - > channel , strerror ( errno ) ) ;
return NULL ;
}
p - > dialing = 1 ;
return & p - > subs [ index ] . f ;
}
2001-10-09 02:06:21 +00:00
switch ( p - > sig ) {
case SIG_FXOLS :
case SIG_FXOGS :
case SIG_FXOKS :
2002-09-10 04:45:51 +00:00
switch ( ast - > _state ) {
2001-10-09 02:06:21 +00:00
case AST_STATE_RINGING :
zt_enable_ec ( p ) ;
2003-10-27 17:16:08 +00:00
zt_train_ec ( p ) ;
2003-02-07 19:23:19 +00:00
p - > subs [ index ] . f . frametype = AST_FRAME_CONTROL ;
p - > subs [ index ] . f . subclass = AST_CONTROL_ANSWER ;
2001-10-09 02:06:21 +00:00
/* Make sure it stops ringing */
2003-02-07 19:23:19 +00:00
zt_set_hook ( p - > subs [ index ] . zfd , ZT_OFFHOOK ) ;
2001-10-09 02:06:21 +00:00
ast_log ( LOG_DEBUG , " channel %d answered \n " , p - > channel ) ;
if ( p - > cidspill ) {
/* Cancel any running CallerID spill */
free ( p - > cidspill ) ;
p - > cidspill = NULL ;
}
p - > dialing = 0 ;
2003-02-07 19:23:19 +00:00
p - > callwaitcas = 0 ;
2002-06-24 17:59:56 +00:00
if ( p - > confirmanswer ) {
2004-04-25 22:37:09 +00:00
/* Ignore answer if "confirm answer" is enabled */
2003-02-07 19:23:19 +00:00
p - > subs [ index ] . f . frametype = AST_FRAME_NULL ;
p - > subs [ index ] . f . subclass = 0 ;
2004-05-05 04:23:18 +00:00
} else if ( ! ast_strlen_zero ( p - > dop . dialstr ) ) {
2003-04-10 21:14:54 +00:00
/* nick@dccinc.com 4/3/03 - fxo should be able to do deferred dialing */
res = ioctl ( p - > subs [ SUB_REAL ] . zfd , ZT_DIAL , & p - > dop ) ;
if ( res < 0 ) {
2004-06-02 16:13:25 +00:00
ast_log ( LOG_WARNING , " Unable to initiate dialing on trunk channel %d \n " , p - > channel ) ;
p - > dop . dialstr [ 0 ] = ' \0 ' ;
return NULL ;
2003-04-11 18:03:59 +00:00
} else {
2004-06-02 16:13:25 +00:00
ast_log ( LOG_DEBUG , " Sent FXO deferred digit string: %s \n " , p - > dop . dialstr ) ;
p - > subs [ index ] . f . frametype = AST_FRAME_NULL ;
p - > subs [ index ] . f . subclass = 0 ;
p - > dialing = 1 ;
2003-04-11 18:03:59 +00:00
}
2003-04-10 21:14:54 +00:00
p - > dop . dialstr [ 0 ] = ' \0 ' ;
2004-06-02 16:13:25 +00:00
ast_setstate ( ast , AST_STATE_DIALING ) ;
2003-04-11 18:03:59 +00:00
} else
2004-06-02 16:13:25 +00:00
ast_setstate ( ast , AST_STATE_UP ) ;
2003-02-07 19:23:19 +00:00
return & p - > subs [ index ] . f ;
2001-10-09 02:06:21 +00:00
case AST_STATE_DOWN :
2002-09-10 04:45:51 +00:00
ast_setstate ( ast , AST_STATE_RING ) ;
2001-10-09 02:06:21 +00:00
ast - > rings = 1 ;
2003-02-07 19:23:19 +00:00
p - > subs [ index ] . f . frametype = AST_FRAME_CONTROL ;
p - > subs [ index ] . f . subclass = AST_CONTROL_OFFHOOK ;
2001-10-09 02:06:21 +00:00
ast_log ( LOG_DEBUG , " channel %d picked up \n " , p - > channel ) ;
2003-02-07 19:23:19 +00:00
return & p - > subs [ index ] . f ;
2001-10-09 02:06:21 +00:00
case AST_STATE_UP :
/* Make sure it stops ringing */
2003-02-07 19:23:19 +00:00
zt_set_hook ( p - > subs [ index ] . zfd , ZT_OFFHOOK ) ;
2001-10-09 02:06:21 +00:00
/* Okay -- probably call waiting*/
2004-10-23 12:19:47 +00:00
if ( ast_bridged_channel ( p - > owner ) )
ast_moh_stop ( ast_bridged_channel ( p - > owner ) ) ;
2001-10-09 02:06:21 +00:00
break ;
2004-06-05 06:54:52 +00:00
case AST_STATE_RESERVED :
/* Start up dialtone */
if ( has_voicemail ( p ) )
res = tone_zone_play_tone ( p - > subs [ SUB_REAL ] . zfd , ZT_TONE_STUTTER ) ;
else
res = tone_zone_play_tone ( p - > subs [ SUB_REAL ] . zfd , ZT_TONE_DIALTONE ) ;
break ;
2001-10-09 02:06:21 +00:00
default :
2002-09-10 04:45:51 +00:00
ast_log ( LOG_WARNING , " FXO phone off hook in weird state %d?? \n " , ast - > _state ) ;
2001-10-09 02:06:21 +00:00
}
break ;
case SIG_FXSLS :
case SIG_FXSGS :
case SIG_FXSKS :
2002-09-10 04:45:51 +00:00
if ( ast - > _state = = AST_STATE_RING ) {
2001-10-09 02:06:21 +00:00
p - > ringt = RINGT ;
}
2005-02-08 07:49:40 +00:00
/* If we get a ring then we cannot be in
* reversed polarity . So we reset to idle */
ast_log ( LOG_DEBUG , " Setting IDLE polarity due "
" to ring. Old polarity was %d \n " ,
p - > polarity ) ;
p - > polarity = POLARITY_IDLE ;
2001-10-09 02:06:21 +00:00
/* Fall through */
case SIG_EM :
2004-04-16 18:00:00 +00:00
case SIG_EM_E1 :
2001-10-09 02:06:21 +00:00
case SIG_EMWINK :
case SIG_FEATD :
2002-06-24 17:59:56 +00:00
case SIG_FEATDMF :
2005-04-22 19:10:35 +00:00
case SIG_FEATDMF_TA :
2004-01-16 23:40:37 +00:00
case SIG_E911 :
2002-06-24 17:59:56 +00:00
case SIG_FEATB :
2003-03-17 20:04:36 +00:00
case SIG_SF :
case SIG_SFWINK :
case SIG_SF_FEATD :
case SIG_SF_FEATDMF :
case SIG_SF_FEATB :
2004-09-19 16:17:18 +00:00
if ( ast - > _state = = AST_STATE_PRERING )
ast_setstate ( ast , AST_STATE_RING ) ;
2003-05-26 23:10:08 +00:00
if ( ( ast - > _state = = AST_STATE_DOWN ) | | ( ast - > _state = = AST_STATE_RING ) ) {
2001-10-09 02:06:21 +00:00
if ( option_debug )
ast_log ( LOG_DEBUG , " Ring detected \n " ) ;
2003-02-07 19:23:19 +00:00
p - > subs [ index ] . f . frametype = AST_FRAME_CONTROL ;
p - > subs [ index ] . f . subclass = AST_CONTROL_RING ;
2003-04-11 03:03:41 +00:00
} else if ( p - > outgoing & & ( ( ast - > _state = = AST_STATE_RINGING ) | | ( ast - > _state = = AST_STATE_DIALING ) ) ) {
2001-10-09 02:06:21 +00:00
if ( option_debug )
ast_log ( LOG_DEBUG , " Line answered \n " ) ;
2002-06-24 17:59:56 +00:00
if ( p - > confirmanswer ) {
2003-02-07 19:23:19 +00:00
p - > subs [ index ] . f . frametype = AST_FRAME_NULL ;
p - > subs [ index ] . f . subclass = 0 ;
2002-06-24 17:59:56 +00:00
} else {
2003-02-07 19:23:19 +00:00
p - > subs [ index ] . f . frametype = AST_FRAME_CONTROL ;
p - > subs [ index ] . f . subclass = AST_CONTROL_ANSWER ;
2002-09-10 04:45:51 +00:00
ast_setstate ( ast , AST_STATE_UP ) ;
2002-06-24 17:59:56 +00:00
}
2002-09-10 04:45:51 +00:00
} else if ( ast - > _state ! = AST_STATE_RING )
ast_log ( LOG_WARNING , " Ring/Off-hook in strange state %d on channel %d \n " , ast - > _state , p - > channel ) ;
2001-10-09 02:06:21 +00:00
break ;
default :
ast_log ( LOG_WARNING , " Don't know how to handle ring/off hoook for signalling %d \n " , p - > sig ) ;
}
break ;
case ZT_EVENT_RINGEROFF :
if ( p - > inalarm ) break ;
2003-02-07 19:23:19 +00:00
if ( p - > radio ) break ;
2001-10-09 02:06:21 +00:00
ast - > rings + + ;
2002-06-24 17:59:56 +00:00
if ( ( ast - > rings > p - > cidrings ) & & ( p - > cidspill ) ) {
2001-10-09 02:06:21 +00:00
ast_log ( LOG_WARNING , " Didn't finish Caller-ID spill. Cancelling. \n " ) ;
free ( p - > cidspill ) ;
p - > cidspill = NULL ;
p - > callwaitcas = 0 ;
}
2003-02-07 19:23:19 +00:00
p - > subs [ index ] . f . frametype = AST_FRAME_CONTROL ;
p - > subs [ index ] . f . subclass = AST_CONTROL_RINGING ;
2001-10-09 02:06:21 +00:00
break ;
case ZT_EVENT_RINGERON :
break ;
case ZT_EVENT_NOALARM :
p - > inalarm = 0 ;
2004-06-06 23:26:29 +00:00
# ifdef ZAPATA_PRI
/* Extremely unlikely but just in case */
if ( p - > bearer )
p - > bearer - > inalarm = 1 ;
# endif
2003-02-28 06:00:18 +00:00
ast_log ( LOG_NOTICE , " Alarm cleared on channel %d \n " , p - > channel ) ;
2003-08-18 14:20:12 +00:00
manager_event ( EVENT_FLAG_SYSTEM , " AlarmClear " ,
2003-08-18 14:19:15 +00:00
" Channel: %d \r \n " , p - > channel ) ;
2001-10-09 02:06:21 +00:00
break ;
case ZT_EVENT_WINKFLASH :
if ( p - > inalarm ) break ;
2003-02-07 19:23:19 +00:00
if ( p - > radio ) break ;
2003-03-21 16:26:50 +00:00
/* Remember last time we got a flash-hook */
gettimeofday ( & p - > flashtime , NULL ) ;
2001-10-09 02:06:21 +00:00
switch ( p - > sig ) {
case SIG_FXOLS :
case SIG_FXOGS :
case SIG_FXOKS :
ast_log ( LOG_DEBUG , " Winkflash, index: %d, normal: %d, callwait: %d, thirdcall: %d \n " ,
2003-02-07 19:23:19 +00:00
index , p - > subs [ SUB_REAL ] . zfd , p - > subs [ SUB_CALLWAIT ] . zfd , p - > subs [ SUB_THREEWAY ] . zfd ) ;
p - > callwaitcas = 0 ;
2005-07-15 16:03:02 +00:00
if ( index ! = SUB_REAL ) {
ast_log ( LOG_WARNING , " Got flash hook with index %d on channel %d?!? \n " , index , p - > channel ) ;
goto winkflashdone ;
}
if ( p - > subs [ SUB_CALLWAIT ] . owner ) {
/* Swap to call-wait */
swap_subs ( p , SUB_REAL , SUB_CALLWAIT ) ;
tone_zone_play_tone ( p - > subs [ SUB_REAL ] . zfd , - 1 ) ;
p - > owner = p - > subs [ SUB_REAL ] . owner ;
ast_log ( LOG_DEBUG , " Making %s the new owner \n " , p - > owner - > name ) ;
if ( p - > owner - > _state = = AST_STATE_RINGING ) {
ast_setstate ( p - > owner , AST_STATE_UP ) ;
p - > subs [ SUB_REAL ] . needanswer = 1 ;
}
p - > callwaitingrepeat = 0 ;
p - > cidcwexpire = 0 ;
/* Start music on hold if appropriate */
if ( ! p - > subs [ SUB_CALLWAIT ] . inthreeway & & ast_bridged_channel ( p - > subs [ SUB_CALLWAIT ] . owner ) )
ast_moh_start ( ast_bridged_channel ( p - > subs [ SUB_CALLWAIT ] . owner ) , NULL ) ;
if ( ast_bridged_channel ( p - > subs [ SUB_REAL ] . owner ) )
ast_moh_stop ( ast_bridged_channel ( p - > subs [ SUB_REAL ] . owner ) ) ;
} else if ( ! p - > subs [ SUB_THREEWAY ] . owner ) {
char cid_num [ 256 ] ;
char cid_name [ 256 ] ;
if ( ! p - > threewaycalling ) {
/* Just send a flash if no 3-way calling */
p - > subs [ SUB_REAL ] . needflash = 1 ;
goto winkflashdone ;
} else if ( ! check_for_conference ( p ) ) {
if ( p - > zaptrcallerid & & p - > owner ) {
if ( p - > owner - > cid . cid_num )
ast_copy_string ( cid_num , p - > owner - > cid . cid_num , sizeof ( cid_num ) ) ;
if ( p - > owner - > cid . cid_name )
ast_copy_string ( cid_name , p - > owner - > cid . cid_name , sizeof ( cid_name ) ) ;
2001-10-09 02:06:21 +00:00
}
2005-07-15 16:03:02 +00:00
/* XXX This section needs much more error checking!!! XXX */
/* Start a 3-way call if feasible */
if ( ! ( ( ast - > pbx ) | |
( ast - > _state = = AST_STATE_UP ) | |
( ast - > _state = = AST_STATE_RING ) ) ) {
ast_log ( LOG_DEBUG , " Flash when call not up or ringing \n " ) ;
goto winkflashdone ;
}
if ( alloc_sub ( p , SUB_THREEWAY ) ) {
ast_log ( LOG_WARNING , " Unable to allocate three-way subchannel \n " ) ;
goto winkflashdone ;
2001-10-09 02:06:21 +00:00
}
2005-07-15 16:03:02 +00:00
/* Make new channel */
chan = zt_new ( p , AST_STATE_RESERVED , 0 , SUB_THREEWAY , 0 , 0 ) ;
if ( p - > zaptrcallerid ) {
if ( ! p - > origcid_num )
p - > origcid_num = strdup ( p - > cid_num ) ;
if ( ! p - > origcid_name )
p - > origcid_name = strdup ( p - > cid_name ) ;
ast_copy_string ( p - > cid_num , cid_num , sizeof ( p - > cid_num ) ) ;
ast_copy_string ( p - > cid_name , cid_name , sizeof ( p - > cid_name ) ) ;
}
/* Swap things around between the three-way and real call */
swap_subs ( p , SUB_THREEWAY , SUB_REAL ) ;
/* Disable echo canceller for better dialing */
zt_disable_ec ( p ) ;
res = tone_zone_play_tone ( p - > subs [ SUB_REAL ] . zfd , ZT_TONE_DIALRECALL ) ;
if ( res )
ast_log ( LOG_WARNING , " Unable to start dial recall tone on channel %d \n " , p - > channel ) ;
p - > owner = chan ;
if ( ! chan ) {
ast_log ( LOG_WARNING , " Cannot allocate new structure on channel %d \n " , p - > channel ) ;
} else if ( ast_pthread_create ( & threadid , & attr , ss_thread , chan ) ) {
ast_log ( LOG_WARNING , " Unable to start simple switch on channel %d \n " , p - > channel ) ;
res = tone_zone_play_tone ( p - > subs [ SUB_REAL ] . zfd , ZT_TONE_CONGESTION ) ;
zt_enable_ec ( p ) ;
ast_hangup ( chan ) ;
} else {
if ( option_verbose > 2 )
ast_verbose ( VERBOSE_PREFIX_3 " Started three way call on channel %d \n " , p - > channel ) ;
/* Start music on hold if appropriate */
if ( ast_bridged_channel ( p - > subs [ SUB_THREEWAY ] . owner ) )
ast_moh_start ( ast_bridged_channel ( p - > subs [ SUB_THREEWAY ] . owner ) , NULL ) ;
}
}
} else {
/* Already have a 3 way call */
if ( p - > subs [ SUB_THREEWAY ] . inthreeway ) {
/* Call is already up, drop the last person */
if ( option_debug )
ast_log ( LOG_DEBUG , " Got flash with three way call up, dropping last call on %d \n " , p - > channel ) ;
/* If the primary call isn't answered yet, use it */
if ( ( p - > subs [ SUB_REAL ] . owner - > _state ! = AST_STATE_UP ) & & ( p - > subs [ SUB_THREEWAY ] . owner - > _state = = AST_STATE_UP ) ) {
/* Swap back -- we're dropping the real 3-way that isn't finished yet*/
swap_subs ( p , SUB_THREEWAY , SUB_REAL ) ;
p - > owner = p - > subs [ SUB_REAL ] . owner ;
}
/* Drop the last call and stop the conference */
if ( option_verbose > 2 )
ast_verbose ( VERBOSE_PREFIX_3 " Dropping three-way call on %s \n " , p - > subs [ SUB_THREEWAY ] . owner - > name ) ;
p - > subs [ SUB_THREEWAY ] . owner - > _softhangup | = AST_SOFTHANGUP_DEV ;
p - > subs [ SUB_REAL ] . inthreeway = 0 ;
p - > subs [ SUB_THREEWAY ] . inthreeway = 0 ;
2001-10-09 02:06:21 +00:00
} else {
2005-07-15 16:03:02 +00:00
/* Lets see what we're up to */
if ( ( ( ast - > pbx ) | | ( ast - > _state = = AST_STATE_UP ) ) & &
( p - > transfertobusy | | ( ast - > _state ! = AST_STATE_BUSY ) ) ) {
int otherindex = SUB_THREEWAY ;
if ( option_verbose > 2 )
ast_verbose ( VERBOSE_PREFIX_3 " Building conference on call on %s and %s \n " , p - > subs [ SUB_THREEWAY ] . owner - > name , p - > subs [ SUB_REAL ] . owner - > name ) ;
/* Put them in the threeway, and flip */
p - > subs [ SUB_THREEWAY ] . inthreeway = 1 ;
p - > subs [ SUB_REAL ] . inthreeway = 1 ;
if ( ast - > _state = = AST_STATE_UP ) {
2003-02-07 19:23:19 +00:00
swap_subs ( p , SUB_THREEWAY , SUB_REAL ) ;
2005-07-15 16:03:02 +00:00
otherindex = SUB_REAL ;
2003-02-07 19:23:19 +00:00
}
2005-07-15 16:03:02 +00:00
if ( p - > subs [ otherindex ] . owner & & ast_bridged_channel ( p - > subs [ otherindex ] . owner ) )
ast_moh_stop ( ast_bridged_channel ( p - > subs [ otherindex ] . owner ) ) ;
p - > owner = p - > subs [ SUB_REAL ] . owner ;
if ( ast - > _state = = AST_STATE_RINGING ) {
ast_log ( LOG_DEBUG , " Enabling ringtone on real and threeway \n " ) ;
res = tone_zone_play_tone ( p - > subs [ SUB_REAL ] . zfd , ZT_TONE_RINGTONE ) ;
res = tone_zone_play_tone ( p - > subs [ SUB_THREEWAY ] . zfd , ZT_TONE_RINGTONE ) ;
}
} else {
2003-02-07 19:23:19 +00:00
if ( option_verbose > 2 )
2005-07-15 16:03:02 +00:00
ast_verbose ( VERBOSE_PREFIX_3 " Dumping incomplete call on on %s \n " , p - > subs [ SUB_THREEWAY ] . owner - > name ) ;
swap_subs ( p , SUB_THREEWAY , SUB_REAL ) ;
2003-02-07 19:23:19 +00:00
p - > subs [ SUB_THREEWAY ] . owner - > _softhangup | = AST_SOFTHANGUP_DEV ;
2005-07-15 16:03:02 +00:00
p - > owner = p - > subs [ SUB_REAL ] . owner ;
if ( p - > subs [ SUB_REAL ] . owner & & ast_bridged_channel ( p - > subs [ SUB_REAL ] . owner ) )
ast_moh_stop ( ast_bridged_channel ( p - > subs [ SUB_REAL ] . owner ) ) ;
zt_enable_ec ( p ) ;
2001-10-09 02:06:21 +00:00
}
2005-07-15 16:03:02 +00:00
2001-10-09 02:06:21 +00:00
}
}
2005-07-15 16:03:02 +00:00
winkflashdone :
2003-02-07 19:23:19 +00:00
update_conf ( p ) ;
2001-10-09 02:06:21 +00:00
break ;
case SIG_EM :
2004-04-16 18:00:00 +00:00
case SIG_EM_E1 :
2001-10-09 02:06:21 +00:00
case SIG_EMWINK :
case SIG_FEATD :
2003-03-17 20:04:36 +00:00
case SIG_SF :
case SIG_SFWINK :
case SIG_SF_FEATD :
2001-10-09 02:06:21 +00:00
case SIG_FXSLS :
case SIG_FXSGS :
if ( p - > dialing )
ast_log ( LOG_DEBUG , " Ignoring wink on channel %d \n " , p - > channel ) ;
else
2002-09-10 04:45:51 +00:00
ast_log ( LOG_DEBUG , " Got wink in weird state %d on channel %d \n " , ast - > _state , p - > channel ) ;
2001-10-09 02:06:21 +00:00
break ;
2005-04-22 19:10:35 +00:00
case SIG_FEATDMF_TA :
switch ( p - > whichwink ) {
case 0 :
ast_log ( LOG_DEBUG , " ANI2 set to '%d' and ANI is '%s' \n " , p - > owner - > cid . cid_ani2 , p - > owner - > cid . cid_ani ) ;
snprintf ( p - > dop . dialstr , sizeof ( p - > dop . dialstr ) , " M*%d%s# " , p - > owner - > cid . cid_ani2 , p - > owner - > cid . cid_ani ) ;
break ;
case 1 :
2005-05-15 23:26:45 +00:00
ast_copy_string ( p - > dop . dialstr , p - > finaldial , sizeof ( p - > dop . dialstr ) ) ;
2005-04-22 19:10:35 +00:00
break ;
case 2 :
ast_log ( LOG_WARNING , " Received unexpected wink on channel of type SIG_FEATDMF_TA \n " ) ;
return NULL ;
}
p - > whichwink + + ;
/* Fall through */
2002-06-24 17:59:56 +00:00
case SIG_FEATDMF :
2004-01-16 23:40:37 +00:00
case SIG_E911 :
2002-06-24 17:59:56 +00:00
case SIG_FEATB :
2003-03-17 20:04:36 +00:00
case SIG_SF_FEATDMF :
case SIG_SF_FEATB :
2002-06-24 17:59:56 +00:00
/* FGD MF *Must* wait for wink */
2004-05-05 04:23:18 +00:00
if ( ! ast_strlen_zero ( p - > dop . dialstr ) )
2003-05-19 23:43:44 +00:00
res = ioctl ( p - > subs [ SUB_REAL ] . zfd , ZT_DIAL , & p - > dop ) ;
else if ( res < 0 ) {
2002-06-24 17:59:56 +00:00
ast_log ( LOG_WARNING , " Unable to initiate dialing on trunk channel %d \n " , p - > channel ) ;
p - > dop . dialstr [ 0 ] = ' \0 ' ;
return NULL ;
} else
ast_log ( LOG_DEBUG , " Sent deferred digit string: %s \n " , p - > dop . dialstr ) ;
p - > dop . dialstr [ 0 ] = ' \0 ' ;
break ;
2001-10-09 02:06:21 +00:00
default :
ast_log ( LOG_WARNING , " Don't know how to handle ring/off hoook for signalling %d \n " , p - > sig ) ;
}
break ;
case ZT_EVENT_HOOKCOMPLETE :
if ( p - > inalarm ) break ;
2003-02-07 19:23:19 +00:00
if ( p - > radio ) break ;
2001-10-09 02:06:21 +00:00
switch ( p - > sig ) {
case SIG_FXSLS : /* only interesting for FXS */
case SIG_FXSGS :
case SIG_FXSKS :
case SIG_EM :
2004-04-16 18:00:00 +00:00
case SIG_EM_E1 :
2001-10-09 02:06:21 +00:00
case SIG_EMWINK :
2001-12-29 18:04:21 +00:00
case SIG_FEATD :
2003-03-17 20:04:36 +00:00
case SIG_SF :
case SIG_SFWINK :
case SIG_SF_FEATD :
2004-05-05 04:23:18 +00:00
if ( ! ast_strlen_zero ( p - > dop . dialstr ) )
2003-05-19 23:49:15 +00:00
res = ioctl ( p - > subs [ SUB_REAL ] . zfd , ZT_DIAL , & p - > dop ) ;
else if ( res < 0 ) {
2001-10-09 02:06:21 +00:00
ast_log ( LOG_WARNING , " Unable to initiate dialing on trunk channel %d \n " , p - > channel ) ;
p - > dop . dialstr [ 0 ] = ' \0 ' ;
return NULL ;
} else
ast_log ( LOG_DEBUG , " Sent deferred digit string: %s \n " , p - > dop . dialstr ) ;
p - > dop . dialstr [ 0 ] = ' \0 ' ;
2003-05-19 23:33:41 +00:00
p - > dop . op = ZT_DIAL_OP_REPLACE ;
2001-10-09 02:06:21 +00:00
break ;
2002-06-24 17:59:56 +00:00
case SIG_FEATDMF :
2004-01-16 23:40:37 +00:00
case SIG_E911 :
2002-06-24 17:59:56 +00:00
case SIG_FEATB :
2003-03-17 20:04:36 +00:00
case SIG_SF_FEATDMF :
case SIG_SF_FEATB :
2002-06-24 17:59:56 +00:00
ast_log ( LOG_DEBUG , " Got hook complete in MF FGD, waiting for wink now on channel %d \n " , p - > channel ) ;
break ;
2001-10-09 02:06:21 +00:00
default :
break ;
}
break ;
2004-11-17 06:18:33 +00:00
case ZT_EVENT_POLARITY :
/*
* If we get a Polarity Switch event , check to see
2005-02-08 07:49:40 +00:00
* if we should change the polarity state and
* mark the channel as UP or if this is an indication
* of remote end disconnect .
2004-11-17 06:18:33 +00:00
*/
2005-02-08 07:49:40 +00:00
if ( p - > polarity = = POLARITY_IDLE ) {
p - > polarity = POLARITY_REV ;
if ( p - > answeronpolarityswitch & &
( ( ast - > _state = = AST_STATE_DIALING ) | |
( ast - > _state = = AST_STATE_RINGING ) ) ) {
ast_log ( LOG_DEBUG , " Answering on polarity switch! \n " ) ;
ast_setstate ( p - > owner , AST_STATE_UP ) ;
} else
ast_log ( LOG_DEBUG , " Ignore switch to REVERSED Polarity on channel %d, state %d \n " , p - > channel , ast - > _state ) ;
} else if ( p - > hanguponpolarityswitch & &
2004-11-17 06:18:33 +00:00
( p - > polarityonanswerdelay > 0 ) & &
2005-02-08 07:49:40 +00:00
( p - > polarity = = POLARITY_REV ) & &
2004-11-17 06:18:33 +00:00
( ast - > _state = = AST_STATE_UP ) ) {
2005-07-15 23:00:47 +00:00
if ( ast_tvdiff_ms ( ast_tvnow ( ) , p - > polaritydelaytv ) > p - > polarityonanswerdelay ) {
2004-11-17 06:18:33 +00:00
ast_log ( LOG_DEBUG , " Hangup due to Reverse Polarity on channel %d \n " , p - > channel ) ;
ast_softhangup ( p - > owner , AST_SOFTHANGUP_EXPLICIT ) ;
2005-02-08 07:49:40 +00:00
p - > polarity = POLARITY_IDLE ;
2004-11-17 06:18:33 +00:00
} else {
ast_log ( LOG_DEBUG , " Ignore Reverse Polarity (too close to answer event) on channel %d, state %d \n " , p - > channel , ast - > _state ) ;
}
} else {
2005-02-08 07:49:40 +00:00
p - > polarity = POLARITY_IDLE ;
ast_log ( LOG_DEBUG , " Ignore switch to IDLE Polarity on channel %d, state %d \n " , p - > channel , ast - > _state ) ;
2004-11-17 06:18:33 +00:00
}
break ;
2001-10-09 02:06:21 +00:00
default :
ast_log ( LOG_DEBUG , " Dunno what to do with event %d on channel %d \n " , res , p - > channel ) ;
}
2003-02-07 19:23:19 +00:00
return & p - > subs [ index ] . f ;
2001-10-09 02:06:21 +00:00
}
2003-12-11 16:36:33 +00:00
2003-12-11 20:55:26 +00:00
static struct ast_frame * __zt_exception ( struct ast_channel * ast )
2001-10-09 02:06:21 +00:00
{
2005-03-04 06:47:24 +00:00
struct zt_pvt * p = ast - > tech_pvt ;
2001-10-09 02:06:21 +00:00
int res ;
int usedindex = - 1 ;
int index ;
2003-05-19 23:33:41 +00:00
struct ast_frame * f ;
2003-02-07 19:23:19 +00:00
2001-10-09 02:06:21 +00:00
index = zt_get_index ( ast , p , 1 ) ;
2003-02-07 19:23:19 +00:00
p - > subs [ index ] . f . frametype = AST_FRAME_NULL ;
p - > subs [ index ] . f . datalen = 0 ;
p - > subs [ index ] . f . samples = 0 ;
p - > subs [ index ] . f . mallocd = 0 ;
p - > subs [ index ] . f . offset = 0 ;
p - > subs [ index ] . f . subclass = 0 ;
2005-07-15 23:00:47 +00:00
p - > subs [ index ] . f . delivery = ast_tv ( 0 , 0 ) ;
2003-02-07 19:23:19 +00:00
p - > subs [ index ] . f . src = " zt_exception " ;
p - > subs [ index ] . f . data = NULL ;
if ( ( ! p - > owner ) & & ( ! p - > radio ) ) {
2001-10-09 02:06:21 +00:00
/* If nobody owns us, absorb the event appropriately, otherwise
we loop indefinitely . This occurs when , during call waiting , the
other end hangs up our channel so that it no longer exists , but we
have neither FLASH ' d nor ONHOOK ' d to signify our desire to
change to the other channel . */
2003-11-12 00:13:22 +00:00
if ( p - > fake_event ) {
res = p - > fake_event ;
p - > fake_event = 0 ;
} else
res = zt_get_event ( p - > subs [ SUB_REAL ] . zfd ) ;
2003-02-07 19:23:19 +00:00
/* Switch to real if there is one and this isn't something really silly... */
if ( ( res ! = ZT_EVENT_RINGEROFF ) & & ( res ! = ZT_EVENT_RINGERON ) & &
( res ! = ZT_EVENT_HOOKCOMPLETE ) ) {
ast_log ( LOG_DEBUG , " Restoring owner of channel %d on event %d \n " , p - > channel , res ) ;
p - > owner = p - > subs [ SUB_REAL ] . owner ;
2004-10-23 12:19:47 +00:00
if ( p - > owner & & ast_bridged_channel ( p - > owner ) )
ast_moh_stop ( ast_bridged_channel ( p - > owner ) ) ;
2001-10-09 02:06:21 +00:00
}
switch ( res ) {
case ZT_EVENT_ONHOOK :
zt_disable_ec ( p ) ;
if ( p - > owner ) {
if ( option_verbose > 2 )
ast_verbose ( VERBOSE_PREFIX_3 " Channel %s still has call, ringing phone \n " , p - > owner - > name ) ;
zt_ring_phone ( p ) ;
p - > callwaitingrepeat = 0 ;
2003-02-07 19:23:19 +00:00
p - > cidcwexpire = 0 ;
2001-10-09 02:06:21 +00:00
} else
ast_log ( LOG_WARNING , " Absorbed on hook, but nobody is left!?!? \n " ) ;
2003-02-07 19:23:19 +00:00
update_conf ( p ) ;
break ;
case ZT_EVENT_RINGOFFHOOK :
zt_set_hook ( p - > subs [ SUB_REAL ] . zfd , ZT_OFFHOOK ) ;
if ( p - > owner & & ( p - > owner - > _state = = AST_STATE_RINGING ) ) {
p - > subs [ SUB_REAL ] . needanswer = 1 ;
2004-06-26 18:38:19 +00:00
p - > dialing = 0 ;
2003-02-07 19:23:19 +00:00
}
break ;
case ZT_EVENT_HOOKCOMPLETE :
case ZT_EVENT_RINGERON :
case ZT_EVENT_RINGEROFF :
/* Do nothing */
2001-10-09 02:06:21 +00:00
break ;
case ZT_EVENT_WINKFLASH :
2003-03-21 16:26:50 +00:00
gettimeofday ( & p - > flashtime , NULL ) ;
2001-10-09 02:06:21 +00:00
if ( p - > owner ) {
if ( option_verbose > 2 )
ast_verbose ( VERBOSE_PREFIX_3 " Channel %d flashed to other channel %s \n " , p - > channel , p - > owner - > name ) ;
2003-02-07 19:23:19 +00:00
if ( p - > owner - > _state ! = AST_STATE_UP ) {
/* Answer if necessary */
usedindex = zt_get_index ( p - > owner , p , 0 ) ;
if ( usedindex > - 1 ) {
p - > subs [ usedindex ] . needanswer = 1 ;
}
2002-09-10 04:45:51 +00:00
ast_setstate ( p - > owner , AST_STATE_UP ) ;
2001-10-09 02:06:21 +00:00
}
p - > callwaitingrepeat = 0 ;
2003-02-07 19:23:19 +00:00
p - > cidcwexpire = 0 ;
2004-10-23 12:19:47 +00:00
if ( ast_bridged_channel ( p - > owner ) )
ast_moh_stop ( ast_bridged_channel ( p - > owner ) ) ;
2001-10-09 02:06:21 +00:00
} else
ast_log ( LOG_WARNING , " Absorbed on hook, but nobody is left!?!? \n " ) ;
2003-02-07 19:23:19 +00:00
update_conf ( p ) ;
2001-10-09 02:06:21 +00:00
break ;
default :
ast_log ( LOG_WARNING , " Don't know how to absorb event %s \n " , event2str ( res ) ) ;
}
2003-05-19 23:33:41 +00:00
f = & p - > subs [ index ] . f ;
return f ;
2001-10-09 02:06:21 +00:00
}
2003-02-07 19:23:19 +00:00
if ( ! p - > radio ) ast_log ( LOG_DEBUG , " Exception on %d, channel %d \n " , ast - > fds [ 0 ] , p - > channel ) ;
2001-10-09 02:06:21 +00:00
/* If it's not us, return NULL immediately */
2003-02-07 19:23:19 +00:00
if ( ast ! = p - > owner ) {
ast_log ( LOG_WARNING , " We're %s, not %s \n " , ast - > name , p - > owner - > name ) ;
2003-05-19 23:33:41 +00:00
f = & p - > subs [ index ] . f ;
return f ;
2003-02-07 19:23:19 +00:00
}
2003-05-19 23:33:41 +00:00
f = zt_handle_event ( ast ) ;
2003-12-11 20:55:26 +00:00
return f ;
}
struct ast_frame * zt_exception ( struct ast_channel * ast )
{
2005-03-04 06:47:24 +00:00
struct zt_pvt * p = ast - > tech_pvt ;
2003-12-11 20:55:26 +00:00
struct ast_frame * f ;
ast_mutex_lock ( & p - > lock ) ;
f = __zt_exception ( ast ) ;
2003-08-13 15:25:16 +00:00
ast_mutex_unlock ( & p - > lock ) ;
2003-05-19 23:33:41 +00:00
return f ;
2001-10-09 02:06:21 +00:00
}
struct ast_frame * zt_read ( struct ast_channel * ast )
{
2005-03-04 06:47:24 +00:00
struct zt_pvt * p = ast - > tech_pvt ;
2001-12-29 18:04:21 +00:00
int res ;
2001-10-09 02:06:21 +00:00
int index ;
2001-12-29 18:04:21 +00:00
void * readbuf ;
2003-02-07 19:23:19 +00:00
struct ast_frame * f ;
2001-10-09 02:06:21 +00:00
2003-02-07 19:23:19 +00:00
2003-08-13 15:25:16 +00:00
ast_mutex_lock ( & p - > lock ) ;
2001-10-09 02:06:21 +00:00
index = zt_get_index ( ast , p , 0 ) ;
2004-07-27 02:19:52 +00:00
/* Hang up if we don't really exist */
if ( index < 0 ) {
ast_log ( LOG_WARNING , " We dont exist? \n " ) ;
ast_mutex_unlock ( & p - > lock ) ;
return NULL ;
}
2004-08-21 21:41:54 +00:00
if ( p - > radio & & p - > inalarm ) return NULL ;
2003-02-07 19:23:19 +00:00
p - > subs [ index ] . f . frametype = AST_FRAME_NULL ;
p - > subs [ index ] . f . datalen = 0 ;
p - > subs [ index ] . f . samples = 0 ;
p - > subs [ index ] . f . mallocd = 0 ;
p - > subs [ index ] . f . offset = 0 ;
p - > subs [ index ] . f . subclass = 0 ;
2005-07-15 23:00:47 +00:00
p - > subs [ index ] . f . delivery = ast_tv ( 0 , 0 ) ;
2003-02-07 19:23:19 +00:00
p - > subs [ index ] . f . src = " zt_read " ;
p - > subs [ index ] . f . data = NULL ;
2001-10-09 02:06:21 +00:00
2003-02-07 19:23:19 +00:00
/* make sure it sends initial key state as first frame */
if ( p - > radio & & ( ! p - > firstradio ) )
{
ZT_PARAMS ps ;
ps . channo = p - > channel ;
2004-03-11 18:00:08 +00:00
if ( ioctl ( p - > subs [ SUB_REAL ] . zfd , ZT_GET_PARAMS , & ps ) < 0 ) {
ast_mutex_unlock ( & p - > lock ) ;
2003-02-07 19:23:19 +00:00
return NULL ;
2004-03-11 18:00:08 +00:00
}
2003-02-07 19:23:19 +00:00
p - > firstradio = 1 ;
p - > subs [ index ] . f . frametype = AST_FRAME_CONTROL ;
if ( ps . rxisoffhook )
{
p - > subs [ index ] . f . subclass = AST_CONTROL_RADIO_KEY ;
}
else
{
p - > subs [ index ] . f . subclass = AST_CONTROL_RADIO_UNKEY ;
}
2003-08-13 15:25:16 +00:00
ast_mutex_unlock ( & p - > lock ) ;
2003-02-07 19:23:19 +00:00
return & p - > subs [ index ] . f ;
}
2001-10-09 02:06:21 +00:00
if ( p - > ringt = = 1 ) {
2003-08-13 15:25:16 +00:00
ast_mutex_unlock ( & p - > lock ) ;
2001-10-09 02:06:21 +00:00
return NULL ;
}
else if ( p - > ringt > 0 )
p - > ringt - - ;
2003-02-07 19:23:19 +00:00
if ( p - > subs [ index ] . needringing ) {
2001-10-09 02:06:21 +00:00
/* Send ringing frame if requested */
2003-02-07 19:23:19 +00:00
p - > subs [ index ] . needringing = 0 ;
p - > subs [ index ] . f . frametype = AST_FRAME_CONTROL ;
p - > subs [ index ] . f . subclass = AST_CONTROL_RINGING ;
2002-09-10 04:45:51 +00:00
ast_setstate ( ast , AST_STATE_RINGING ) ;
2003-08-13 15:25:16 +00:00
ast_mutex_unlock ( & p - > lock ) ;
2003-02-07 19:23:19 +00:00
return & p - > subs [ index ] . f ;
2002-06-24 17:59:56 +00:00
}
2001-10-09 02:06:21 +00:00
2004-01-31 18:46:59 +00:00
if ( p - > subs [ index ] . needbusy ) {
2004-04-22 05:24:50 +00:00
/* Send busy frame if requested */
2004-01-31 18:46:59 +00:00
p - > subs [ index ] . needbusy = 0 ;
p - > subs [ index ] . f . frametype = AST_FRAME_CONTROL ;
p - > subs [ index ] . f . subclass = AST_CONTROL_BUSY ;
ast_mutex_unlock ( & p - > lock ) ;
return & p - > subs [ index ] . f ;
}
if ( p - > subs [ index ] . needcongestion ) {
2004-04-22 05:24:50 +00:00
/* Send congestion frame if requested */
2004-01-31 18:46:59 +00:00
p - > subs [ index ] . needcongestion = 0 ;
p - > subs [ index ] . f . frametype = AST_FRAME_CONTROL ;
p - > subs [ index ] . f . subclass = AST_CONTROL_CONGESTION ;
ast_mutex_unlock ( & p - > lock ) ;
return & p - > subs [ index ] . f ;
}
2003-02-07 19:23:19 +00:00
if ( p - > subs [ index ] . needcallerid ) {
2004-10-02 00:58:31 +00:00
ast_set_callerid ( ast , ! ast_strlen_zero ( p - > lastcid_num ) ? p - > lastcid_num : NULL ,
! ast_strlen_zero ( p - > lastcid_name ) ? p - > lastcid_name : NULL ,
! ast_strlen_zero ( p - > lastcid_num ) ? p - > lastcid_num : NULL
) ;
2003-02-07 19:23:19 +00:00
p - > subs [ index ] . needcallerid = 0 ;
2001-10-09 02:06:21 +00:00
}
2003-02-07 19:23:19 +00:00
if ( p - > subs [ index ] . needanswer ) {
2004-04-22 05:24:50 +00:00
/* Send answer frame if requested */
2003-02-07 19:23:19 +00:00
p - > subs [ index ] . needanswer = 0 ;
p - > subs [ index ] . f . frametype = AST_FRAME_CONTROL ;
p - > subs [ index ] . f . subclass = AST_CONTROL_ANSWER ;
2003-08-13 15:25:16 +00:00
ast_mutex_unlock ( & p - > lock ) ;
2003-02-07 19:23:19 +00:00
return & p - > subs [ index ] . f ;
}
2001-10-09 02:06:21 +00:00
2004-11-03 22:37:55 +00:00
if ( p - > subs [ index ] . needflash ) {
/* Send answer frame if requested */
p - > subs [ index ] . needflash = 0 ;
p - > subs [ index ] . f . frametype = AST_FRAME_CONTROL ;
p - > subs [ index ] . f . subclass = AST_CONTROL_FLASH ;
ast_mutex_unlock ( & p - > lock ) ;
return & p - > subs [ index ] . f ;
}
2005-03-04 06:47:24 +00:00
if ( ast - > rawreadformat = = AST_FORMAT_SLINEAR ) {
2003-02-07 19:23:19 +00:00
if ( ! p - > subs [ index ] . linear ) {
p - > subs [ index ] . linear = 1 ;
res = zt_setlinear ( p - > subs [ index ] . zfd , p - > subs [ index ] . linear ) ;
2001-12-29 18:04:21 +00:00
if ( res )
2003-02-07 19:23:19 +00:00
ast_log ( LOG_WARNING , " Unable to set channel %d (index %d) to linear mode. \n " , p - > channel , index ) ;
2001-12-29 18:04:21 +00:00
}
2005-03-04 06:47:24 +00:00
} else if ( ( ast - > rawreadformat = = AST_FORMAT_ULAW ) | |
( ast - > rawreadformat = = AST_FORMAT_ALAW ) ) {
2003-02-07 19:23:19 +00:00
if ( p - > subs [ index ] . linear ) {
p - > subs [ index ] . linear = 0 ;
res = zt_setlinear ( p - > subs [ index ] . zfd , p - > subs [ index ] . linear ) ;
2001-12-29 18:04:21 +00:00
if ( res )
2005-06-07 21:13:35 +00:00
ast_log ( LOG_WARNING , " Unable to set channel %d (index %d) to companded mode. \n " , p - > channel , index ) ;
2001-12-29 18:04:21 +00:00
}
2001-10-09 02:06:21 +00:00
} else {
2005-03-04 06:47:24 +00:00
ast_log ( LOG_WARNING , " Don't know how to read frames in format %s \n " , ast_getformatname ( ast - > rawreadformat ) ) ;
2003-08-13 15:25:16 +00:00
ast_mutex_unlock ( & p - > lock ) ;
2001-10-09 02:06:21 +00:00
return NULL ;
}
2003-02-07 19:23:19 +00:00
readbuf = ( ( unsigned char * ) p - > subs [ index ] . buffer ) + AST_FRIENDLY_OFFSET ;
2001-10-09 02:06:21 +00:00
CHECK_BLOCKING ( ast ) ;
2003-02-07 19:23:19 +00:00
res = read ( p - > subs [ index ] . zfd , readbuf , p - > subs [ index ] . linear ? READ_SIZE * 2 : READ_SIZE ) ;
2004-12-07 20:38:43 +00:00
ast_clear_flag ( ast , AST_FLAG_BLOCKING ) ;
2001-10-09 02:06:21 +00:00
/* Check for hangup */
if ( res < 0 ) {
2003-10-14 09:56:46 +00:00
f = NULL ;
2003-02-07 19:23:19 +00:00
if ( res = = - 1 ) {
if ( errno = = EAGAIN ) {
/* Return "NULL" frame if there is nobody there */
2003-08-13 15:25:16 +00:00
ast_mutex_unlock ( & p - > lock ) ;
2003-02-07 19:23:19 +00:00
return & p - > subs [ index ] . f ;
2003-10-14 09:56:46 +00:00
} else if ( errno = = ELAST ) {
2003-12-11 20:55:26 +00:00
f = __zt_exception ( ast ) ;
2003-02-07 19:23:19 +00:00
} else
ast_log ( LOG_WARNING , " zt_rec: %s \n " , strerror ( errno ) ) ;
}
2003-08-13 15:25:16 +00:00
ast_mutex_unlock ( & p - > lock ) ;
2003-10-14 09:56:46 +00:00
return f ;
2001-10-09 02:06:21 +00:00
}
2003-02-07 19:23:19 +00:00
if ( res ! = ( p - > subs [ index ] . linear ? READ_SIZE * 2 : READ_SIZE ) ) {
ast_log ( LOG_DEBUG , " Short read (%d/%d), must be an event... \n " , res , p - > subs [ index ] . linear ? READ_SIZE * 2 : READ_SIZE ) ;
2003-12-11 20:55:26 +00:00
f = __zt_exception ( ast ) ;
2003-08-13 15:25:16 +00:00
ast_mutex_unlock ( & p - > lock ) ;
2003-05-19 23:33:41 +00:00
return f ;
2001-10-09 02:06:21 +00:00
}
2001-12-29 18:04:21 +00:00
if ( p - > tdd ) { /* if in TDD mode, see if we receive that */
int c ;
c = tdd_feed ( p - > tdd , readbuf , READ_SIZE ) ;
if ( c < 0 ) {
ast_log ( LOG_DEBUG , " tdd_feed failed \n " ) ;
2004-03-11 18:00:08 +00:00
ast_mutex_unlock ( & p - > lock ) ;
2001-12-29 18:04:21 +00:00
return NULL ;
}
if ( c ) { /* if a char to return */
2003-02-07 19:23:19 +00:00
p - > subs [ index ] . f . subclass = 0 ;
p - > subs [ index ] . f . frametype = AST_FRAME_TEXT ;
p - > subs [ index ] . f . mallocd = 0 ;
p - > subs [ index ] . f . offset = AST_FRIENDLY_OFFSET ;
p - > subs [ index ] . f . data = p - > subs [ index ] . buffer + AST_FRIENDLY_OFFSET ;
p - > subs [ index ] . f . datalen = 1 ;
* ( ( char * ) p - > subs [ index ] . f . data ) = c ;
2003-08-13 15:25:16 +00:00
ast_mutex_unlock ( & p - > lock ) ;
2003-02-07 19:23:19 +00:00
return & p - > subs [ index ] . f ;
2001-12-29 18:04:21 +00:00
}
}
2001-10-09 02:06:21 +00:00
if ( p - > callwaitingrepeat )
p - > callwaitingrepeat - - ;
2003-02-07 19:23:19 +00:00
if ( p - > cidcwexpire )
p - > cidcwexpire - - ;
2001-10-09 02:06:21 +00:00
/* Repeat callwaiting */
if ( p - > callwaitingrepeat = = 1 ) {
p - > callwaitrings + + ;
zt_callwait ( ast ) ;
}
2003-02-07 19:23:19 +00:00
/* Expire CID/CW */
if ( p - > cidcwexpire = = 1 ) {
if ( option_verbose > 2 )
ast_verbose ( VERBOSE_PREFIX_3 " CPE does not support Call Waiting Caller*ID. \n " ) ;
restore_conference ( p ) ;
}
if ( p - > subs [ index ] . linear ) {
p - > subs [ index ] . f . datalen = READ_SIZE * 2 ;
2001-10-09 02:06:21 +00:00
} else
2003-02-07 19:23:19 +00:00
p - > subs [ index ] . f . datalen = READ_SIZE ;
2001-10-09 02:06:21 +00:00
/* Handle CallerID Transmission */
2003-02-07 19:23:19 +00:00
if ( ( p - > owner = = ast ) & & p - > cidspill & & ( ( ast - > _state = = AST_STATE_UP ) | | ( ast - > rings = = p - > cidrings ) ) ) {
2001-10-09 02:06:21 +00:00
send_callerid ( p ) ;
2002-06-24 17:59:56 +00:00
}
2001-10-09 02:06:21 +00:00
2003-02-07 19:23:19 +00:00
p - > subs [ index ] . f . frametype = AST_FRAME_VOICE ;
2005-03-04 06:47:24 +00:00
p - > subs [ index ] . f . subclass = ast - > rawreadformat ;
2003-02-07 19:23:19 +00:00
p - > subs [ index ] . f . samples = READ_SIZE ;
p - > subs [ index ] . f . mallocd = 0 ;
p - > subs [ index ] . f . offset = AST_FRIENDLY_OFFSET ;
p - > subs [ index ] . f . data = p - > subs [ index ] . buffer + AST_FRIENDLY_OFFSET / 2 ;
2001-10-09 02:06:21 +00:00
#if 0
2003-02-07 19:23:19 +00:00
ast_log ( LOG_DEBUG , " Read %d of voice on %s \n " , p - > subs [ index ] . f . datalen , ast - > name ) ;
2001-10-09 02:06:21 +00:00
# endif
2003-02-07 19:23:19 +00:00
if ( p - > dialing | | /* Transmitting something */
( index & & ( ast - > _state ! = AST_STATE_UP ) ) | | /* Three-way or callwait that isn't up */
( ( index = = SUB_CALLWAIT ) & & ! p - > subs [ SUB_CALLWAIT ] . inthreeway ) /* Inactive and non-confed call-wait */
) {
/* Whoops, we're still dialing, or in a state where we shouldn't transmit....
don ' t send anything */
p - > subs [ index ] . f . frametype = AST_FRAME_NULL ;
p - > subs [ index ] . f . subclass = 0 ;
p - > subs [ index ] . f . samples = 0 ;
p - > subs [ index ] . f . mallocd = 0 ;
p - > subs [ index ] . f . offset = 0 ;
p - > subs [ index ] . f . data = NULL ;
p - > subs [ index ] . f . datalen = 0 ;
}
2003-07-02 21:56:03 +00:00
if ( p - > dsp & & ( ! p - > ignoredtmf | | p - > callwaitcas | | p - > busydetect | | p - > callprogress ) & & ! index ) {
2003-02-07 19:23:19 +00:00
/* Perform busy detection. etc on the zap line */
2004-04-06 22:17:32 +00:00
f = ast_dsp_process ( ast , p - > dsp , & p - > subs [ index ] . f ) ;
2003-02-07 19:23:19 +00:00
if ( f ) {
if ( ( f - > frametype = = AST_FRAME_CONTROL ) & & ( f - > subclass = = AST_CONTROL_BUSY ) ) {
if ( ( ast - > _state = = AST_STATE_UP ) & & ! p - > outgoing ) {
/* Treat this as a "hangup" instead of a "busy" on the assumption that
a busy */
f = NULL ;
}
} else if ( f - > frametype = = AST_FRAME_DTMF ) {
2004-04-10 03:46:59 +00:00
# ifdef ZAPATA_PRI
2004-06-14 21:18:52 +00:00
if ( ( p - > proceeding < 2 ) & & p - > sig = = SIG_PRI & & p - > pri & & p - > pri - > overlapdial ) {
2004-04-09 16:33:37 +00:00
/* Don't accept in-band DTMF when in overlap dial mode */
f - > frametype = AST_FRAME_NULL ;
f - > subclass = 0 ;
}
2004-04-10 03:46:59 +00:00
# endif
2003-02-07 19:23:19 +00:00
/* DSP clears us of being pulse */
p - > pulsedial = 0 ;
}
}
} else
f = & p - > subs [ index ] . f ;
if ( f & & ( f - > frametype = = AST_FRAME_DTMF ) ) {
ast_log ( LOG_DEBUG , " DTMF digit: %c on %s \n " , f - > subclass , ast - > name ) ;
if ( p - > confirmanswer ) {
ast_log ( LOG_DEBUG , " Confirm answer on %s! \n " , ast - > name ) ;
/* Upon receiving a DTMF digit, consider this an answer confirmation instead
of a DTMF digit */
p - > subs [ index ] . f . frametype = AST_FRAME_CONTROL ;
p - > subs [ index ] . f . subclass = AST_CONTROL_ANSWER ;
f = & p - > subs [ index ] . f ;
2005-04-27 01:59:00 +00:00
/* Reset confirmanswer so DTMF's will behave properly for the duration of the call */
p - > confirmanswer = 0 ;
2003-02-07 19:23:19 +00:00
} else if ( p - > callwaitcas ) {
if ( ( f - > subclass = = ' A ' ) | | ( f - > subclass = = ' D ' ) ) {
ast_log ( LOG_DEBUG , " Got some DTMF, but it's for the CAS \n " ) ;
if ( p - > cidspill )
free ( p - > cidspill ) ;
send_cwcidspill ( p ) ;
}
2003-07-02 21:49:42 +00:00
if ( ( f - > subclass ! = ' m ' ) & & ( f - > subclass ! = ' u ' ) )
p - > callwaitcas = 0 ;
2003-02-07 19:23:19 +00:00
p - > subs [ index ] . f . frametype = AST_FRAME_NULL ;
p - > subs [ index ] . f . subclass = 0 ;
f = & p - > subs [ index ] . f ;
} else if ( f - > subclass = = ' f ' ) {
/* Fax tone -- Handle and return NULL */
if ( ! p - > faxhandled ) {
p - > faxhandled + + ;
if ( strcmp ( ast - > exten , " fax " ) ) {
2005-06-06 03:18:51 +00:00
const char * target_context = ast_strlen_zero ( ast - > macrocontext ) ? ast - > context : ast - > macrocontext ;
if ( ast_exists_extension ( ast , target_context , " fax " , 1 , ast - > cid . cid_num ) ) {
2003-02-07 19:23:19 +00:00
if ( option_verbose > 2 )
ast_verbose ( VERBOSE_PREFIX_3 " Redirecting %s to fax extension \n " , ast - > name ) ;
2003-05-29 20:18:45 +00:00
/* Save the DID/DNIS when we transfer the fax call to a "fax" extension */
2005-06-06 03:18:51 +00:00
pbx_builtin_setvar_helper ( ast , " FAXEXTEN " , ast - > exten ) ;
if ( ast_async_goto ( ast , target_context , " fax " , 1 ) )
ast_log ( LOG_WARNING , " Failed to async goto '%s' into fax of '%s' \n " , ast - > name , target_context ) ;
2003-02-07 19:23:19 +00:00
} else
ast_log ( LOG_NOTICE , " Fax detected, but no fax extension \n " ) ;
} else
ast_log ( LOG_DEBUG , " Already in a fax extension, not redirecting \n " ) ;
} else
ast_log ( LOG_DEBUG , " Fax already handled \n " ) ;
zt_confmute ( p , 0 ) ;
p - > subs [ index ] . f . frametype = AST_FRAME_NULL ;
p - > subs [ index ] . f . subclass = 0 ;
f = & p - > subs [ index ] . f ;
} else if ( f - > subclass = = ' m ' ) {
/* Confmute request */
zt_confmute ( p , 1 ) ;
p - > subs [ index ] . f . frametype = AST_FRAME_NULL ;
p - > subs [ index ] . f . subclass = 0 ;
f = & p - > subs [ index ] . f ;
} else if ( f - > subclass = = ' u ' ) {
/* Unmute */
zt_confmute ( p , 0 ) ;
p - > subs [ index ] . f . frametype = AST_FRAME_NULL ;
p - > subs [ index ] . f . subclass = 0 ;
f = & p - > subs [ index ] . f ;
} else
zt_confmute ( p , 0 ) ;
}
2004-06-26 18:38:19 +00:00
2003-11-12 00:13:22 +00:00
/* If we have a fake_event, trigger exception to handle it */
if ( p - > fake_event )
2004-12-07 20:38:43 +00:00
ast_set_flag ( ast , AST_FLAG_EXCEPTION ) ;
2004-06-26 18:38:19 +00:00
2003-08-13 15:25:16 +00:00
ast_mutex_unlock ( & p - > lock ) ;
2003-02-07 19:23:19 +00:00
return f ;
2001-10-09 02:06:21 +00:00
}
2003-02-07 19:23:19 +00:00
static int my_zt_write ( struct zt_pvt * p , unsigned char * buf , int len , int index , int linear )
2001-10-09 02:06:21 +00:00
{
int sent = 0 ;
int size ;
int res ;
int fd ;
2003-02-07 19:23:19 +00:00
fd = p - > subs [ index ] . zfd ;
2001-10-09 02:06:21 +00:00
while ( len ) {
size = len ;
2003-02-07 19:23:19 +00:00
if ( size > ( linear ? READ_SIZE * 2 : READ_SIZE ) )
size = ( linear ? READ_SIZE * 2 : READ_SIZE ) ;
2001-10-09 02:06:21 +00:00
res = write ( fd , buf , size ) ;
if ( res ! = size ) {
2005-05-10 04:26:34 +00:00
if ( option_debug )
ast_log ( LOG_DEBUG , " Write returned %d (%s) on channel %d \n " , res , strerror ( errno ) , p - > channel ) ;
2001-10-09 02:06:21 +00:00
return sent ;
}
len - = size ;
buf + = size ;
}
return sent ;
}
static int zt_write ( struct ast_channel * ast , struct ast_frame * frame )
{
2005-03-04 06:47:24 +00:00
struct zt_pvt * p = ast - > tech_pvt ;
2001-10-09 02:06:21 +00:00
int res ;
unsigned char outbuf [ 4096 ] ;
2003-02-07 19:23:19 +00:00
int index ;
index = zt_get_index ( ast , p , 0 ) ;
if ( index < 0 ) {
ast_log ( LOG_WARNING , " %s doesn't really exist? \n " , ast - > name ) ;
return - 1 ;
2001-10-09 02:06:21 +00:00
}
2004-06-05 06:54:52 +00:00
2005-03-27 22:48:55 +00:00
#if 0
2004-06-05 06:54:52 +00:00
# ifdef ZAPATA_PRI
2004-06-18 15:24:29 +00:00
ast_mutex_lock ( & p - > lock ) ;
2004-05-22 19:05:53 +00:00
if ( ! p - > proceeding & & p - > sig = = SIG_PRI & & p - > pri & & ! p - > outgoing ) {
2004-05-19 15:00:14 +00:00
if ( p - > pri - > pri ) {
if ( ! pri_grab ( p , p - > pri ) ) {
2005-03-27 22:48:55 +00:00
pri_progress ( p - > pri - > pri , p - > call , PVT_TO_CHANNEL ( p ) , ! p - > digital ) ;
2004-05-19 15:00:14 +00:00
pri_rel ( p - > pri ) ;
} else
ast_log ( LOG_WARNING , " Unable to grab PRI on span %d \n " , p - > span ) ;
}
p - > proceeding = 1 ;
}
2004-06-18 15:24:29 +00:00
ast_mutex_unlock ( & p - > lock ) ;
2005-03-27 22:48:55 +00:00
# endif
2004-05-19 15:00:14 +00:00
# endif
2001-10-09 02:06:21 +00:00
/* Write a frame of (presumably voice) data */
if ( frame - > frametype ! = AST_FRAME_VOICE ) {
2002-06-24 17:59:56 +00:00
if ( frame - > frametype ! = AST_FRAME_IMAGE )
ast_log ( LOG_WARNING , " Don't know what to do with frame type '%d' \n " , frame - > frametype ) ;
return 0 ;
2001-10-09 02:06:21 +00:00
}
2001-12-29 18:04:21 +00:00
if ( ( frame - > subclass ! = AST_FORMAT_SLINEAR ) & &
( frame - > subclass ! = AST_FORMAT_ULAW ) & &
( frame - > subclass ! = AST_FORMAT_ALAW ) ) {
2001-10-09 02:06:21 +00:00
ast_log ( LOG_WARNING , " Cannot handle frames in %d format \n " , frame - > subclass ) ;
return - 1 ;
}
if ( p - > dialing ) {
if ( option_debug )
ast_log ( LOG_DEBUG , " Dropping frame since I'm still dialing on %s... \n " , ast - > name ) ;
return 0 ;
}
2005-01-28 05:19:06 +00:00
if ( ! p - > owner ) {
if ( option_debug )
ast_log ( LOG_DEBUG , " Dropping frame since there is no active owner on %s... \n " , ast - > name ) ;
return 0 ;
}
2001-10-09 02:06:21 +00:00
if ( p - > cidspill ) {
if ( option_debug )
ast_log ( LOG_DEBUG , " Dropping frame since I've still got a callerid spill \n " ) ;
return 0 ;
}
/* Return if it's not valid data */
if ( ! frame - > data | | ! frame - > datalen )
return 0 ;
if ( frame - > datalen > sizeof ( outbuf ) * 2 ) {
ast_log ( LOG_WARNING , " Frame too large \n " ) ;
return 0 ;
}
2003-02-07 19:23:19 +00:00
2001-10-09 02:06:21 +00:00
if ( frame - > subclass = = AST_FORMAT_SLINEAR ) {
2003-02-07 19:23:19 +00:00
if ( ! p - > subs [ index ] . linear ) {
p - > subs [ index ] . linear = 1 ;
res = zt_setlinear ( p - > subs [ index ] . zfd , p - > subs [ index ] . linear ) ;
if ( res )
ast_log ( LOG_WARNING , " Unable to set linear mode on channel %d \n " , p - > channel ) ;
2001-12-29 18:04:21 +00:00
}
2003-02-07 19:23:19 +00:00
res = my_zt_write ( p , ( unsigned char * ) frame - > data , frame - > datalen , index , 1 ) ;
2001-10-09 02:06:21 +00:00
} else {
2001-12-29 18:04:21 +00:00
/* x-law already */
2003-02-07 19:23:19 +00:00
if ( p - > subs [ index ] . linear ) {
p - > subs [ index ] . linear = 0 ;
res = zt_setlinear ( p - > subs [ index ] . zfd , p - > subs [ index ] . linear ) ;
if ( res )
ast_log ( LOG_WARNING , " Unable to set companded mode on channel %d \n " , p - > channel ) ;
2001-12-29 18:04:21 +00:00
}
2003-02-07 19:23:19 +00:00
res = my_zt_write ( p , ( unsigned char * ) frame - > data , frame - > datalen , index , 0 ) ;
2001-10-09 02:06:21 +00:00
}
if ( res < 0 ) {
ast_log ( LOG_WARNING , " write failed: %s \n " , strerror ( errno ) ) ;
return - 1 ;
2001-12-29 18:04:21 +00:00
}
2001-10-09 02:06:21 +00:00
return 0 ;
}
static int zt_indicate ( struct ast_channel * chan , int condition )
{
2005-03-04 06:47:24 +00:00
struct zt_pvt * p = chan - > tech_pvt ;
2001-10-09 02:06:21 +00:00
int res = - 1 ;
2004-04-12 22:00:12 +00:00
int index ;
2004-11-03 22:37:55 +00:00
int func = ZT_FLASH ;
2004-04-12 22:00:12 +00:00
ast_mutex_lock ( & p - > lock ) ;
index = zt_get_index ( chan , p , 0 ) ;
2004-11-01 01:44:11 +00:00
ast_log ( LOG_DEBUG , " Requested indication %d on channel %s \n " , condition , chan - > name ) ;
2003-02-07 19:23:19 +00:00
if ( index = = SUB_REAL ) {
switch ( condition ) {
case AST_CONTROL_BUSY :
2004-08-31 13:47:23 +00:00
# ifdef ZAPATA_PRI
2004-09-13 22:14:34 +00:00
if ( p - > priindication_oob & & p - > sig = = SIG_PRI ) {
chan - > hangupcause = AST_CAUSE_USER_BUSY ;
chan - > _softhangup | = AST_SOFTHANGUP_DEV ;
2004-09-14 12:36:14 +00:00
res = 0 ;
2004-11-13 23:56:50 +00:00
} else if ( ! p - > proceeding & & p - > sig = = SIG_PRI & & p - > pri & & ! p - > outgoing ) {
if ( p - > pri - > pri ) {
if ( ! pri_grab ( p , p - > pri ) ) {
pri_progress ( p - > pri - > pri , p - > call , PVT_TO_CHANNEL ( p ) , 1 ) ;
pri_rel ( p - > pri ) ;
}
else
ast_log ( LOG_WARNING , " Unable to grab PRI on span %d \n " , p - > span ) ;
}
p - > proceeding = 1 ;
res = tone_zone_play_tone ( p - > subs [ index ] . zfd , ZT_TONE_BUSY ) ;
2004-09-13 22:14:34 +00:00
} else
2004-08-31 13:47:23 +00:00
# endif
res = tone_zone_play_tone ( p - > subs [ index ] . zfd , ZT_TONE_BUSY ) ;
2003-02-07 19:23:19 +00:00
break ;
case AST_CONTROL_RINGING :
2004-04-28 04:26:26 +00:00
# ifdef ZAPATA_PRI
2005-04-05 19:40:37 +00:00
if ( ( ! p - > alerting ) & & p - > sig = = SIG_PRI & & p - > pri & & ! p - > outgoing & & ( chan - > _state ! = AST_STATE_UP ) ) {
2004-04-27 21:50:24 +00:00
if ( p - > pri - > pri ) {
if ( ! pri_grab ( p , p - > pri ) ) {
2005-03-27 22:48:55 +00:00
pri_acknowledge ( p - > pri - > pri , p - > call , PVT_TO_CHANNEL ( p ) , ! p - > digital ) ;
2004-04-27 21:50:24 +00:00
pri_rel ( p - > pri ) ;
}
else
ast_log ( LOG_WARNING , " Unable to grab PRI on span %d \n " , p - > span ) ;
}
2005-04-05 19:40:37 +00:00
p - > alerting = 1 ;
2004-04-27 21:50:24 +00:00
}
2004-04-28 04:26:26 +00:00
# endif
2003-02-07 19:23:19 +00:00
res = tone_zone_play_tone ( p - > subs [ index ] . zfd , ZT_TONE_RINGTONE ) ;
if ( chan - > _state ! = AST_STATE_UP ) {
if ( ( chan - > _state ! = AST_STATE_RING ) | |
( ( p - > sig ! = SIG_FXSKS ) & &
( p - > sig ! = SIG_FXSLS ) & &
( p - > sig ! = SIG_FXSGS ) ) )
ast_setstate ( chan , AST_STATE_RINGING ) ;
}
2004-05-28 02:02:33 +00:00
break ;
2004-06-14 21:18:52 +00:00
case AST_CONTROL_PROCEEDING :
ast_log ( LOG_DEBUG , " Received AST_CONTROL_PROCEEDING on %s \n " , chan - > name ) ;
# ifdef ZAPATA_PRI
if ( ( p - > proceeding < 2 ) & & p - > sig = = SIG_PRI & & p - > pri & & ! p - > outgoing ) {
if ( p - > pri - > pri ) {
if ( ! pri_grab ( p , p - > pri ) ) {
2005-03-27 22:48:55 +00:00
pri_proceeding ( p - > pri - > pri , p - > call , PVT_TO_CHANNEL ( p ) , ! p - > digital ) ;
2004-06-14 21:18:52 +00:00
pri_rel ( p - > pri ) ;
}
else
ast_log ( LOG_WARNING , " Unable to grab PRI on span %d \n " , p - > span ) ;
}
p - > proceeding = 2 ;
}
# endif
/* don't continue in ast_indicate */
res = 0 ;
break ;
2003-05-19 23:33:41 +00:00
case AST_CONTROL_PROGRESS :
ast_log ( LOG_DEBUG , " Received AST_CONTROL_PROGRESS on %s \n " , chan - > name ) ;
# ifdef ZAPATA_PRI
2005-03-27 22:48:55 +00:00
p - > digital = 0 ; /* Digital-only calls isn't allows any inband progress messages */
2004-05-22 19:05:53 +00:00
if ( ! p - > proceeding & & p - > sig = = SIG_PRI & & p - > pri & & ! p - > outgoing ) {
2003-05-19 23:33:41 +00:00
if ( p - > pri - > pri ) {
if ( ! pri_grab ( p , p - > pri ) ) {
2004-06-05 06:54:52 +00:00
pri_progress ( p - > pri - > pri , p - > call , PVT_TO_CHANNEL ( p ) , 1 ) ;
2003-05-19 23:33:41 +00:00
pri_rel ( p - > pri ) ;
}
else
ast_log ( LOG_WARNING , " Unable to grab PRI on span %d \n " , p - > span ) ;
}
p - > proceeding = 1 ;
}
# endif
/* don't continue in ast_indicate */
res = 0 ;
2003-02-07 19:23:19 +00:00
break ;
case AST_CONTROL_CONGESTION :
2004-05-20 07:57:19 +00:00
chan - > hangupcause = AST_CAUSE_CONGESTION ;
2004-08-31 13:47:23 +00:00
# ifdef ZAPATA_PRI
2004-09-13 22:14:34 +00:00
if ( p - > priindication_oob & & p - > sig = = SIG_PRI ) {
chan - > hangupcause = AST_CAUSE_SWITCH_CONGESTION ;
chan - > _softhangup | = AST_SOFTHANGUP_DEV ;
2004-09-14 12:36:14 +00:00
res = 0 ;
2004-11-13 23:56:50 +00:00
} else if ( ! p - > proceeding & & p - > sig = = SIG_PRI & & p - > pri & & ! p - > outgoing ) {
2005-01-18 11:37:08 +00:00
if ( p - > pri ) {
2004-11-13 23:56:50 +00:00
if ( ! pri_grab ( p , p - > pri ) ) {
pri_progress ( p - > pri - > pri , p - > call , PVT_TO_CHANNEL ( p ) , 1 ) ;
pri_rel ( p - > pri ) ;
2005-01-18 11:37:08 +00:00
} else
2004-11-13 23:56:50 +00:00
ast_log ( LOG_WARNING , " Unable to grab PRI on span %d \n " , p - > span ) ;
}
p - > proceeding = 1 ;
res = tone_zone_play_tone ( p - > subs [ index ] . zfd , ZT_TONE_CONGESTION ) ;
2004-09-13 22:14:34 +00:00
} else
2004-08-31 13:47:23 +00:00
# endif
res = tone_zone_play_tone ( p - > subs [ index ] . zfd , ZT_TONE_CONGESTION ) ;
2003-02-07 19:23:19 +00:00
break ;
2005-01-17 12:37:55 +00:00
# ifdef ZAPATA_PRI
case AST_CONTROL_HOLD :
2005-01-18 11:37:08 +00:00
if ( p - > pri ) {
if ( ! pri_grab ( p , p - > pri ) ) {
res = pri_notify ( p - > pri - > pri , p - > call , p - > prioffset , PRI_NOTIFY_REMOTE_HOLD ) ;
pri_rel ( p - > pri ) ;
} else
ast_log ( LOG_WARNING , " Unable to grab PRI on span %d \n " , p - > span ) ;
}
2005-01-17 12:37:55 +00:00
break ;
case AST_CONTROL_UNHOLD :
2005-01-18 11:37:08 +00:00
if ( p - > pri ) {
if ( ! pri_grab ( p , p - > pri ) ) {
res = pri_notify ( p - > pri - > pri , p - > call , p - > prioffset , PRI_NOTIFY_REMOTE_RETRIEVAL ) ;
pri_rel ( p - > pri ) ;
} else
ast_log ( LOG_WARNING , " Unable to grab PRI on span %d \n " , p - > span ) ;
}
2005-01-17 12:37:55 +00:00
break ;
# endif
2003-02-07 19:23:19 +00:00
case AST_CONTROL_RADIO_KEY :
if ( p - > radio )
res = zt_set_hook ( p - > subs [ index ] . zfd , ZT_OFFHOOK ) ;
res = 0 ;
break ;
case AST_CONTROL_RADIO_UNKEY :
if ( p - > radio )
res = zt_set_hook ( p - > subs [ index ] . zfd , ZT_RINGOFF ) ;
res = 0 ;
break ;
2004-11-03 22:37:55 +00:00
case AST_CONTROL_FLASH :
/* flash hookswitch */
if ( ISTRUNK ( p ) & & ( p - > sig ! = SIG_PRI ) ) {
/* Clear out the dial buffer */
p - > dop . dialstr [ 0 ] = ' \0 ' ;
if ( ( ioctl ( p - > subs [ SUB_REAL ] . zfd , ZT_HOOK , & func ) = = - 1 ) & & ( errno ! = EINPROGRESS ) ) {
ast_log ( LOG_WARNING , " Unable to flash external trunk on channel %s: %s \n " ,
chan - > name , strerror ( errno ) ) ;
} else
res = 0 ;
} else
res = 0 ;
break ;
2003-02-07 19:23:19 +00:00
case - 1 :
res = tone_zone_play_tone ( p - > subs [ index ] . zfd , - 1 ) ;
break ;
default :
ast_log ( LOG_WARNING , " Don't know how to set condition %d on channel %s \n " , condition , chan - > name ) ;
2001-10-09 02:06:21 +00:00
}
2003-02-07 19:23:19 +00:00
} else
res = 0 ;
2004-04-12 22:00:12 +00:00
ast_mutex_unlock ( & p - > lock ) ;
2001-10-09 02:06:21 +00:00
return res ;
}
2005-04-01 17:00:50 +00:00
static struct ast_channel * zt_new ( struct zt_pvt * i , int state , int startpbx , int index , int law , int transfercapability )
2001-10-09 02:06:21 +00:00
{
struct ast_channel * tmp ;
2001-12-29 18:04:21 +00:00
int deflaw ;
int res ;
2003-02-07 19:23:19 +00:00
int x , y ;
int features ;
2001-12-29 18:04:21 +00:00
ZT_PARAMS ps ;
2004-12-01 18:44:52 +00:00
if ( i - > subs [ index ] . owner ) {
ast_log ( LOG_WARNING , " Channel %d already has a %s call \n " , i - > channel , subnames [ index ] ) ;
return NULL ;
}
2002-06-24 17:59:56 +00:00
tmp = ast_channel_alloc ( 0 ) ;
2001-10-09 02:06:21 +00:00
if ( tmp ) {
2005-03-04 06:47:24 +00:00
tmp - > tech = & zap_tech ;
2001-12-29 18:04:21 +00:00
ps . channo = i - > channel ;
2003-02-07 19:23:19 +00:00
res = ioctl ( i - > subs [ SUB_REAL ] . zfd , ZT_GET_PARAMS , & ps ) ;
2001-12-29 18:04:21 +00:00
if ( res ) {
ast_log ( LOG_WARNING , " Unable to get parameters, assuming MULAW \n " ) ;
ps . curlaw = ZT_LAW_MULAW ;
}
if ( ps . curlaw = = ZT_LAW_ALAW )
deflaw = AST_FORMAT_ALAW ;
else
deflaw = AST_FORMAT_ULAW ;
2003-02-07 19:23:19 +00:00
if ( law ) {
if ( law = = ZT_LAW_ALAW )
deflaw = AST_FORMAT_ALAW ;
else
deflaw = AST_FORMAT_ULAW ;
}
y = 1 ;
do {
2004-06-06 03:32:55 +00:00
# ifdef ZAPATA_PRI
2004-07-19 02:18:11 +00:00
if ( i - > bearer | | ( i - > pri & & ( i - > sig = = SIG_FXSKS ) ) )
2004-06-06 01:54:22 +00:00
snprintf ( tmp - > name , sizeof ( tmp - > name ) , " Zap/%d:%d-%d " , i - > pri - > trunkgroup , i - > channel , y ) ;
else
2004-06-06 03:32:55 +00:00
# endif
if ( i - > channel = = CHAN_PSEUDO )
snprintf ( tmp - > name , sizeof ( tmp - > name ) , " Zap/pseudo-%d " , rand ( ) ) ;
else
2004-06-06 01:54:22 +00:00
snprintf ( tmp - > name , sizeof ( tmp - > name ) , " Zap/%d-%d " , i - > channel , y ) ;
2003-02-07 19:23:19 +00:00
for ( x = 0 ; x < 3 ; x + + ) {
if ( ( index ! = x ) & & i - > subs [ x ] . owner & & ! strcasecmp ( tmp - > name , i - > subs [ x ] . owner - > name ) )
break ;
}
y + + ;
} while ( x < 3 ) ;
2001-10-09 02:06:21 +00:00
tmp - > type = type ;
2003-02-07 19:23:19 +00:00
tmp - > fds [ 0 ] = i - > subs [ index ] . zfd ;
2001-12-29 18:04:21 +00:00
tmp - > nativeformats = AST_FORMAT_SLINEAR | deflaw ;
2001-10-09 02:06:21 +00:00
/* Start out assuming ulaw since it's smaller :) */
2005-03-04 06:47:24 +00:00
tmp - > rawreadformat = deflaw ;
2001-12-29 18:04:21 +00:00
tmp - > readformat = deflaw ;
2005-03-04 06:47:24 +00:00
tmp - > rawwriteformat = deflaw ;
2001-12-29 18:04:21 +00:00
tmp - > writeformat = deflaw ;
2003-02-07 19:23:19 +00:00
i - > subs [ index ] . linear = 0 ;
zt_setlinear ( i - > subs [ index ] . zfd , i - > subs [ index ] . linear ) ;
features = 0 ;
if ( i - > busydetect & & CANBUSYDETECT ( i ) ) {
features | = DSP_FEATURE_BUSY_DETECT ;
}
2004-06-07 23:38:39 +00:00
if ( ( i - > callprogress & 1 ) & & CANPROGRESSDETECT ( i ) ) {
2003-02-07 19:23:19 +00:00
features | = DSP_FEATURE_CALL_PROGRESS ;
}
2004-06-08 22:34:25 +00:00
if ( ( ! i - > outgoing & & ( i - > callprogress & 4 ) ) | |
( i - > outgoing & & ( i - > callprogress & 2 ) ) ) {
2004-06-07 23:38:39 +00:00
features | = DSP_FEATURE_FAX_DETECT ;
}
2005-05-02 20:16:21 +00:00
# ifdef ZT_TONEDETECT
x = ZT_TONEDETECT_ON | ZT_TONEDETECT_MUTE ;
2005-07-21 15:06:50 +00:00
if ( ioctl ( i - > subs [ index ] . zfd , ZT_TONEDETECT , & x ) ) {
2005-05-02 20:16:21 +00:00
# endif
2005-07-21 15:06:50 +00:00
i - > hardwaredtmf = 0 ;
2005-05-02 20:16:21 +00:00
features | = DSP_FEATURE_DTMF_DETECT ;
2005-07-21 15:06:50 +00:00
# ifdef ZT_TONEDETECT
} else if ( NEED_MFDETECT ( i ) ) {
i - > hardwaredtmf = 1 ;
features | = DSP_FEATURE_DTMF_DETECT ;
}
# endif
2003-02-07 19:23:19 +00:00
if ( features ) {
if ( i - > dsp ) {
ast_log ( LOG_DEBUG , " Already have a dsp on %s? \n " , tmp - > name ) ;
} else {
i - > dsp = ast_dsp_new ( ) ;
if ( i - > dsp ) {
2005-01-21 04:48:15 +00:00
# ifdef ZAPATA_PRI
/* We cannot do progress detection until receives PROGRESS message */
if ( i - > outgoing & & ( i - > sig = = SIG_PRI ) ) {
/* Remember requested DSP features, don't treat
talking as ANSWER */
i - > dsp_features = features & ~ DSP_PROGRESS_TALK ;
features = 0 ;
}
# endif
2003-02-07 19:23:19 +00:00
ast_dsp_set_features ( i - > dsp , features ) ;
ast_dsp_digitmode ( i - > dsp , DSP_DIGITMODE_DTMF | i - > dtmfrelax ) ;
2004-05-05 04:23:18 +00:00
if ( ! ast_strlen_zero ( progzone ) )
2004-03-28 02:53:04 +00:00
ast_dsp_set_call_progress_zone ( i - > dsp , progzone ) ;
2003-03-06 06:00:17 +00:00
if ( i - > busydetect & & CANBUSYDETECT ( i ) ) {
ast_dsp_set_busy_count ( i - > dsp , i - > busycount ) ;
2005-08-08 00:08:48 +00:00
ast_dsp_set_busy_pattern ( i - > dsp , i - > busy_tonelength , i - > busy_quietlength ) ;
2005-07-19 13:30:37 +00:00
}
2003-02-07 19:23:19 +00:00
}
}
}
2001-10-09 02:06:21 +00:00
if ( state = = AST_STATE_RING )
tmp - > rings = 1 ;
2005-03-04 06:47:24 +00:00
tmp - > tech_pvt = i ;
2003-04-09 04:00:43 +00:00
if ( ( i - > sig = = SIG_FXOKS ) | | ( i - > sig = = SIG_FXOGS ) | | ( i - > sig = = SIG_FXOLS ) ) {
/* Only FXO signalled stuff can be picked up */
tmp - > callgroup = i - > callgroup ;
tmp - > pickupgroup = i - > pickupgroup ;
}
2004-05-05 04:23:18 +00:00
if ( ! ast_strlen_zero ( i - > language ) )
2005-05-15 23:26:45 +00:00
ast_copy_string ( tmp - > language , i - > language , sizeof ( tmp - > language ) ) ;
2004-05-05 04:23:18 +00:00
if ( ! ast_strlen_zero ( i - > musicclass ) )
2005-05-15 23:26:45 +00:00
ast_copy_string ( tmp - > musicclass , i - > musicclass , sizeof ( tmp - > musicclass ) ) ;
2001-10-09 02:06:21 +00:00
if ( ! i - > owner )
i - > owner = tmp ;
2004-05-05 04:23:18 +00:00
if ( ! ast_strlen_zero ( i - > accountcode ) )
2005-05-15 23:26:45 +00:00
ast_copy_string ( tmp - > accountcode , i - > accountcode , sizeof ( tmp - > accountcode ) ) ;
2001-12-29 18:04:21 +00:00
if ( i - > amaflags )
tmp - > amaflags = i - > amaflags ;
2003-02-07 19:23:19 +00:00
i - > subs [ index ] . owner = tmp ;
2005-05-15 23:26:45 +00:00
ast_copy_string ( tmp - > context , i - > context , sizeof ( tmp - > context ) ) ;
2002-03-08 23:48:42 +00:00
/* Copy call forward info */
2005-05-15 23:26:45 +00:00
ast_copy_string ( tmp - > call_forward , i - > call_forward , sizeof ( tmp - > call_forward ) ) ;
2001-12-29 18:04:21 +00:00
/* If we've been told "no ADSI" then enforce it */
if ( ! i - > adsi )
tmp - > adsicpe = AST_ADSI_UNAVAILABLE ;
2004-05-05 04:23:18 +00:00
if ( ! ast_strlen_zero ( i - > exten ) )
2005-05-15 23:26:45 +00:00
ast_copy_string ( tmp - > exten , i - > exten , sizeof ( tmp - > exten ) ) ;
2004-05-05 04:23:18 +00:00
if ( ! ast_strlen_zero ( i - > rdnis ) )
2004-10-02 00:58:31 +00:00
tmp - > cid . cid_rdnis = strdup ( i - > rdnis ) ;
2004-05-05 04:23:18 +00:00
if ( ! ast_strlen_zero ( i - > dnid ) )
2004-10-02 00:58:31 +00:00
tmp - > cid . cid_dnid = strdup ( i - > dnid ) ;
2005-01-05 22:40:42 +00:00
2005-07-12 02:33:57 +00:00
# ifdef PRI_ANI
ast_set_callerid ( tmp , i - > cid_num , i - > cid_name , ast_strlen_zero ( i - > cid_ani ) ? i - > cid_num : i - > cid_ani ) ;
# else
2005-01-05 22:40:42 +00:00
ast_set_callerid ( tmp , i - > cid_num , i - > cid_name , i - > cid_num ) ;
2005-07-12 02:33:57 +00:00
# endif
2004-10-02 00:58:31 +00:00
tmp - > cid . cid_pres = i - > callingpres ;
2005-02-04 06:12:32 +00:00
tmp - > cid . cid_ton = i - > cid_ton ;
2002-06-24 17:59:56 +00:00
# ifdef ZAPATA_PRI
2005-04-01 17:00:50 +00:00
tmp - > transfercapability = transfercapability ;
pbx_builtin_setvar_helper ( tmp , " TRANSFERCAPABILITY " , ast_transfercapability2str ( transfercapability ) ) ;
if ( transfercapability & PRI_TRANS_CAP_DIGITAL ) {
i - > digital = 1 ;
}
2002-06-24 17:59:56 +00:00
/* Assume calls are not idle calls unless we're told differently */
i - > isidlecall = 0 ;
2003-08-08 04:20:54 +00:00
i - > alreadyhungup = 0 ;
2002-06-24 17:59:56 +00:00
# endif
2003-11-21 18:24:49 +00:00
/* clear the fake event in case we posted one before we had ast_chanenl */
i - > fake_event = 0 ;
2003-02-12 13:59:15 +00:00
/* Assure there is no confmute on this channel */
zt_confmute ( i , 0 ) ;
2004-04-28 13:53:01 +00:00
ast_setstate ( tmp , state ) ;
ast_mutex_lock ( & usecnt_lock ) ;
usecnt + + ;
ast_mutex_unlock ( & usecnt_lock ) ;
ast_update_use_count ( ) ;
2001-10-09 02:06:21 +00:00
if ( startpbx ) {
if ( ast_pbx_start ( tmp ) ) {
ast_log ( LOG_WARNING , " Unable to start PBX on %s \n " , tmp - > name ) ;
ast_hangup ( tmp ) ;
tmp = NULL ;
}
}
} else
ast_log ( LOG_WARNING , " Unable to allocate channel structure \n " ) ;
return tmp ;
}
static int bump_gains ( struct zt_pvt * p )
{
int res ;
/* Bump receive gain by 9.0db */
2003-02-07 19:23:19 +00:00
res = set_actual_gain ( p - > subs [ SUB_REAL ] . zfd , 0 , p - > rxgain + 5.0 , p - > txgain , p - > law ) ;
2001-10-09 02:06:21 +00:00
if ( res ) {
ast_log ( LOG_WARNING , " Unable to bump gain \n " ) ;
return - 1 ;
}
return 0 ;
}
static int restore_gains ( struct zt_pvt * p )
{
int res ;
/* Bump receive gain by 9.0db */
2003-02-07 19:23:19 +00:00
res = set_actual_gain ( p - > subs [ SUB_REAL ] . zfd , 0 , p - > rxgain , p - > txgain , p - > law ) ;
2001-10-09 02:06:21 +00:00
if ( res ) {
ast_log ( LOG_WARNING , " Unable to restore gains: %s \n " , strerror ( errno ) ) ;
return - 1 ;
}
return 0 ;
}
2003-02-07 19:23:19 +00:00
static int my_getsigstr ( struct ast_channel * chan , char * str , char term , int ms )
{
char c ;
* str = 0 ; /* start with empty output buffer */
for ( ; ; )
{
/* Wait for the first digit (up to specified ms). */
c = ast_waitfordigit ( chan , ms ) ;
/* if timeout, hangup or error, return as such */
if ( c < 1 ) return ( c ) ;
* str + + = c ;
* str = 0 ;
if ( c = = term ) return ( 1 ) ;
}
}
2003-05-29 16:03:53 +00:00
static int zt_wink ( struct zt_pvt * p , int index )
{
int j ;
zt_set_hook ( p - > subs [ index ] . zfd , ZT_WINK ) ;
for ( ; ; )
{
/* set bits of interest */
j = ZT_IOMUX_SIGEVENT ;
/* wait for some happening */
if ( ioctl ( p - > subs [ index ] . zfd , ZT_IOMUX , & j ) = = - 1 ) return ( - 1 ) ;
/* exit loop if we have it */
if ( j & ZT_IOMUX_SIGEVENT ) break ;
}
/* get the event info */
if ( ioctl ( p - > subs [ index ] . zfd , ZT_GETEVENT , & j ) = = - 1 ) return ( - 1 ) ;
return 0 ;
}
2001-10-09 02:06:21 +00:00
static void * ss_thread ( void * data )
{
struct ast_channel * chan = data ;
2005-03-04 06:47:24 +00:00
struct zt_pvt * p = chan - > tech_pvt ;
2003-09-26 22:31:19 +00:00
char exten [ AST_MAX_EXTENSION ] = " " ;
char exten2 [ AST_MAX_EXTENSION ] = " " ;
2001-10-09 02:06:21 +00:00
unsigned char buf [ 256 ] ;
2004-09-19 16:17:18 +00:00
char dtmfcid [ 300 ] ;
2003-02-07 19:23:19 +00:00
char dtmfbuf [ 300 ] ;
2001-10-09 02:06:21 +00:00
struct callerid_state * cs ;
char * name = NULL , * number = NULL ;
2004-01-12 04:28:00 +00:00
int distMatches ;
int curRingData [ 3 ] ;
int receivedRingT ;
int counter1 ;
int counter ;
2004-11-22 18:59:19 +00:00
int samples = 0 ;
2004-01-12 04:28:00 +00:00
2001-10-09 02:06:21 +00:00
int flags ;
2003-05-29 16:03:53 +00:00
int i ;
2001-10-09 02:06:21 +00:00
int timeout ;
2002-03-08 23:48:42 +00:00
int getforward = 0 ;
2001-10-09 02:06:21 +00:00
char * s1 , * s2 ;
int len = 0 ;
int res ;
2003-02-07 19:23:19 +00:00
int index ;
2001-10-09 02:06:21 +00:00
if ( option_verbose > 2 )
ast_verbose ( VERBOSE_PREFIX_3 " Starting simple switch on '%s' \n " , chan - > name ) ;
2003-02-07 19:23:19 +00:00
index = zt_get_index ( chan , p , 1 ) ;
if ( index < 0 ) {
ast_log ( LOG_WARNING , " Huh? \n " ) ;
ast_hangup ( chan ) ;
return NULL ;
}
if ( p - > dsp )
ast_dsp_digitreset ( p - > dsp ) ;
2001-10-09 02:06:21 +00:00
switch ( p - > sig ) {
2004-05-02 03:39:17 +00:00
# ifdef ZAPATA_PRI
case SIG_PRI :
/* Now loop looking for an extension */
2005-05-15 23:26:45 +00:00
ast_copy_string ( exten , p - > exten , sizeof ( exten ) ) ;
2004-05-02 03:39:17 +00:00
len = strlen ( exten ) ;
res = 0 ;
2004-10-02 00:58:31 +00:00
while ( ( len < AST_MAX_EXTENSION - 1 ) & & ast_matchmore_extension ( chan , chan - > context , exten , 1 , p - > cid_num ) ) {
2004-06-13 07:25:27 +00:00
if ( len & & ! ast_ignore_pattern ( chan - > context , exten ) )
tone_zone_play_tone ( p - > subs [ index ] . zfd , - 1 ) ;
else
tone_zone_play_tone ( p - > subs [ index ] . zfd , ZT_TONE_DIALTONE ) ;
2004-10-02 00:58:31 +00:00
if ( ast_exists_extension ( chan , chan - > context , exten , 1 , p - > cid_num ) )
2004-05-02 03:39:17 +00:00
timeout = matchdigittimeout ;
else
timeout = gendigittimeout ;
res = ast_waitfordigit ( chan , timeout ) ;
if ( res < 0 ) {
ast_log ( LOG_DEBUG , " waitfordigit returned < 0... \n " ) ;
ast_hangup ( chan ) ;
return NULL ;
} else if ( res ) {
exten [ len + + ] = res ;
} else
break ;
}
2005-06-09 22:34:29 +00:00
/* if no extension was received ('unspecified') on overlap call, use the 's' extension */
if ( ast_strlen_zero ( exten ) ) {
if ( option_verbose > 2 )
ast_verbose ( VERBOSE_PREFIX_3 " Going to extension s|1 because of empty extension received on overlap call \n " ) ;
exten [ 0 ] = ' s ' ;
exten [ 1 ] = ' \0 ' ;
}
2004-06-13 07:25:27 +00:00
tone_zone_play_tone ( p - > subs [ index ] . zfd , - 1 ) ;
2004-10-02 00:58:31 +00:00
if ( ast_exists_extension ( chan , chan - > context , exten , 1 , p - > cid_num ) ) {
2004-05-02 03:39:17 +00:00
/* Start the real PBX */
2005-05-15 23:26:45 +00:00
ast_copy_string ( chan - > exten , exten , sizeof ( chan - > exten ) ) ;
2005-07-19 13:30:37 +00:00
if ( p - > dsp ) ast_dsp_digitreset ( p - > dsp ) ;
2004-06-13 07:16:00 +00:00
ast_setstate ( chan , AST_STATE_RING ) ;
2004-05-02 03:39:17 +00:00
res = ast_pbx_run ( chan ) ;
if ( res ) {
ast_log ( LOG_WARNING , " PBX exited non-zero! \n " ) ;
}
} else {
ast_log ( LOG_DEBUG , " No such possible extension '%s' in context '%s' \n " , exten , chan - > context ) ;
chan - > hangupcause = AST_CAUSE_UNALLOCATED ;
ast_hangup ( chan ) ;
}
return NULL ;
break ;
# endif
2001-10-09 02:06:21 +00:00
case SIG_FEATD :
2002-06-24 17:59:56 +00:00
case SIG_FEATDMF :
2004-01-16 23:40:37 +00:00
case SIG_E911 :
2002-06-24 17:59:56 +00:00
case SIG_FEATB :
2001-10-09 02:06:21 +00:00
case SIG_EMWINK :
2003-03-17 20:04:36 +00:00
case SIG_SF_FEATD :
case SIG_SF_FEATDMF :
case SIG_SF_FEATB :
case SIG_SFWINK :
2003-05-29 16:03:53 +00:00
if ( zt_wink ( p , index ) )
return NULL ;
2001-10-09 02:06:21 +00:00
/* Fall through */
case SIG_EM :
2004-04-16 18:00:00 +00:00
case SIG_EM_E1 :
2003-03-17 20:04:36 +00:00
case SIG_SF :
2003-02-07 19:23:19 +00:00
res = tone_zone_play_tone ( p - > subs [ index ] . zfd , - 1 ) ;
if ( p - > dsp )
ast_dsp_digitreset ( p - > dsp ) ;
2002-06-24 17:59:56 +00:00
/* set digit mode appropriately */
2003-02-07 19:23:19 +00:00
if ( p - > dsp ) {
2005-07-19 13:30:37 +00:00
if ( NEED_MFDETECT ( p ) )
2003-02-07 19:23:19 +00:00
ast_dsp_digitmode ( p - > dsp , DSP_DIGITMODE_MF | p - > dtmfrelax ) ;
else
ast_dsp_digitmode ( p - > dsp , DSP_DIGITMODE_DTMF | p - > dtmfrelax ) ;
}
2003-05-19 23:33:41 +00:00
dtmfbuf [ 0 ] = 0 ;
/* Wait for the first digit only if immediate=no */
2003-08-15 22:07:15 +00:00
if ( ! p - > immediate )
2003-05-19 23:33:41 +00:00
/* Wait for the first digit (up to 5 seconds). */
res = ast_waitfordigit ( chan , 5000 ) ;
else res = 0 ;
2003-02-07 19:23:19 +00:00
if ( res > 0 ) {
/* save first char */
dtmfbuf [ 0 ] = res ;
2002-06-24 17:59:56 +00:00
switch ( p - > sig )
{
case SIG_FEATD :
2003-03-17 20:04:36 +00:00
case SIG_SF_FEATD :
2003-02-07 19:23:19 +00:00
res = my_getsigstr ( chan , dtmfbuf + 1 , ' * ' , 3000 ) ;
2002-06-24 17:59:56 +00:00
if ( res > 0 )
2003-02-07 19:23:19 +00:00
res = my_getsigstr ( chan , dtmfbuf + strlen ( dtmfbuf ) , ' * ' , 3000 ) ;
2005-07-19 13:30:37 +00:00
if ( ( res < 1 ) & & ( p - > dsp ) ) ast_dsp_digitreset ( p - > dsp ) ;
2002-06-24 17:59:56 +00:00
break ;
case SIG_FEATDMF :
2004-01-16 23:40:37 +00:00
case SIG_E911 :
2003-03-17 20:04:36 +00:00
case SIG_SF_FEATDMF :
2003-02-07 19:23:19 +00:00
res = my_getsigstr ( chan , dtmfbuf + 1 , ' # ' , 3000 ) ;
2004-01-16 23:40:37 +00:00
if ( res > 0 ) {
/* if E911, take off hook */
if ( p - > sig = = SIG_E911 ) {
zt_set_hook ( p - > subs [ SUB_REAL ] . zfd , ZT_OFFHOOK ) ;
}
2003-02-07 19:23:19 +00:00
res = my_getsigstr ( chan , dtmfbuf + strlen ( dtmfbuf ) , ' # ' , 3000 ) ;
2004-01-16 23:40:37 +00:00
}
2005-07-19 13:30:37 +00:00
if ( ( res < 1 ) & & ( p - > dsp ) ) ast_dsp_digitreset ( p - > dsp ) ;
2002-06-24 17:59:56 +00:00
break ;
case SIG_FEATB :
2003-03-17 20:04:36 +00:00
case SIG_SF_FEATB :
2003-02-07 19:23:19 +00:00
res = my_getsigstr ( chan , dtmfbuf + 1 , ' # ' , 3000 ) ;
2005-07-19 13:30:37 +00:00
if ( ( res < 1 ) & & ( p - > dsp ) ) ast_dsp_digitreset ( p - > dsp ) ;
2002-06-24 17:59:56 +00:00
break ;
default :
/* If we got it, get the rest */
2004-12-15 19:59:53 +00:00
res = my_getsigstr ( chan , dtmfbuf + 1 , ' ' , p - > emdigitwait ) ;
2002-06-24 17:59:56 +00:00
break ;
}
2001-10-09 02:06:21 +00:00
}
if ( res = = - 1 ) {
ast_log ( LOG_WARNING , " getdtmf on channel %d: %s \n " , p - > channel , strerror ( errno ) ) ;
ast_hangup ( chan ) ;
return NULL ;
} else if ( res < 0 ) {
ast_log ( LOG_DEBUG , " Got hung up before digits finished \n " ) ;
ast_hangup ( chan ) ;
return NULL ;
}
2005-05-15 23:26:45 +00:00
ast_copy_string ( exten , dtmfbuf , sizeof ( exten ) ) ;
2004-05-05 04:23:18 +00:00
if ( ast_strlen_zero ( exten ) )
2005-05-15 23:26:45 +00:00
ast_copy_string ( exten , " s " , sizeof ( exten ) ) ;
2004-08-30 05:07:27 +00:00
if ( p - > sig = = SIG_FEATD | | p - > sig = = SIG_EMWINK ) {
/* Look for Feature Group D on all E&M Wink and Feature Group D trunks */
2001-10-09 02:06:21 +00:00
if ( exten [ 0 ] = = ' * ' ) {
2003-02-07 19:23:19 +00:00
char * stringp = NULL ;
2005-05-15 23:26:45 +00:00
ast_copy_string ( exten2 , exten , sizeof ( exten2 ) ) ;
2001-10-09 02:06:21 +00:00
/* Parse out extension and callerid */
2003-02-07 19:23:19 +00:00
stringp = exten2 + 1 ;
s1 = strsep ( & stringp , " * " ) ;
s2 = strsep ( & stringp , " * " ) ;
2001-10-09 02:06:21 +00:00
if ( s2 ) {
2004-10-02 00:58:31 +00:00
if ( ! ast_strlen_zero ( p - > cid_num ) )
2005-01-05 22:40:42 +00:00
ast_set_callerid ( chan , p - > cid_num , NULL , p - > cid_num ) ;
2001-10-09 02:06:21 +00:00
else
2005-01-05 22:40:42 +00:00
ast_set_callerid ( chan , s1 , NULL , s1 ) ;
2005-05-15 23:26:45 +00:00
ast_copy_string ( exten , s2 , sizeof ( exten ) ) ;
2001-10-09 02:06:21 +00:00
} else
2005-05-15 23:26:45 +00:00
ast_copy_string ( exten , s1 , sizeof ( exten ) ) ;
2004-08-30 05:07:27 +00:00
} else if ( p - > sig = = SIG_FEATD )
2001-10-09 02:06:21 +00:00
ast_log ( LOG_WARNING , " Got a non-Feature Group D input on channel %d. Assuming E&M Wink instead \n " , p - > channel ) ;
}
2002-06-24 17:59:56 +00:00
if ( p - > sig = = SIG_FEATDMF ) {
if ( exten [ 0 ] = = ' * ' ) {
2003-02-07 19:23:19 +00:00
char * stringp = NULL ;
2005-05-15 23:26:45 +00:00
ast_copy_string ( exten2 , exten , sizeof ( exten2 ) ) ;
2002-06-24 17:59:56 +00:00
/* Parse out extension and callerid */
2003-02-07 19:23:19 +00:00
stringp = exten2 + 1 ;
s1 = strsep ( & stringp , " # " ) ;
s2 = strsep ( & stringp , " # " ) ;
2002-06-24 17:59:56 +00:00
if ( s2 ) {
2004-10-02 00:58:31 +00:00
if ( ! ast_strlen_zero ( p - > cid_num ) )
2005-01-05 22:40:42 +00:00
ast_set_callerid ( chan , p - > cid_num , NULL , p - > cid_num ) ;
2002-06-24 17:59:56 +00:00
else
2005-01-05 22:40:42 +00:00
if ( * ( s1 + 2 ) )
ast_set_callerid ( chan , s1 + 2 , NULL , s1 + 2 ) ;
2005-05-15 23:26:45 +00:00
ast_copy_string ( exten , s2 + 1 , sizeof ( exten ) ) ;
2002-06-24 17:59:56 +00:00
} else
2005-05-15 23:26:45 +00:00
ast_copy_string ( exten , s1 + 2 , sizeof ( exten ) ) ;
2002-06-24 17:59:56 +00:00
} else
ast_log ( LOG_WARNING , " Got a non-Feature Group D input on channel %d. Assuming E&M Wink instead \n " , p - > channel ) ;
}
2004-01-16 23:40:37 +00:00
if ( p - > sig = = SIG_E911 ) {
if ( exten [ 0 ] = = ' * ' ) {
char * stringp = NULL ;
2005-05-15 23:26:45 +00:00
ast_copy_string ( exten2 , exten , sizeof ( exten2 ) ) ;
2004-01-16 23:40:37 +00:00
/* Parse out extension and callerid */
stringp = exten2 + 1 ;
s1 = strsep ( & stringp , " # " ) ;
s2 = strsep ( & stringp , " # " ) ;
if ( s2 & & ( * ( s2 + 1 ) = = ' 0 ' ) ) {
2005-01-05 22:40:42 +00:00
if ( * ( s2 + 2 ) )
ast_set_callerid ( chan , s2 + 2 , NULL , s2 + 2 ) ;
}
2005-05-15 23:26:45 +00:00
if ( s1 ) ast_copy_string ( exten , s1 , sizeof ( exten ) ) ;
else ast_copy_string ( exten , " 911 " , sizeof ( exten ) ) ;
2004-10-02 00:58:31 +00:00
printf ( " E911: exten: %s, ANI: %s \n " , exten , chan - > cid . cid_ani ) ;
2004-01-16 23:40:37 +00:00
} else
ast_log ( LOG_WARNING , " Got a non-E911 input on channel %d. Assuming E&M Wink instead \n " , p - > channel ) ;
}
2002-06-24 17:59:56 +00:00
if ( p - > sig = = SIG_FEATB ) {
if ( exten [ 0 ] = = ' * ' ) {
2003-02-07 19:23:19 +00:00
char * stringp = NULL ;
2005-05-15 23:26:45 +00:00
ast_copy_string ( exten2 , exten , sizeof ( exten2 ) ) ;
2002-06-24 17:59:56 +00:00
/* Parse out extension and callerid */
2003-02-07 19:23:19 +00:00
stringp = exten2 + 1 ;
s1 = strsep ( & stringp , " # " ) ;
2005-05-15 23:26:45 +00:00
ast_copy_string ( exten , exten2 + 1 , sizeof ( exten ) ) ;
2002-06-24 17:59:56 +00:00
} else
ast_log ( LOG_WARNING , " Got a non-Feature Group B input on channel %d. Assuming E&M Wink instead \n " , p - > channel ) ;
}
2003-05-29 16:03:53 +00:00
if ( p - > sig = = SIG_FEATDMF ) {
zt_wink ( p , index ) ;
}
2001-10-09 02:06:21 +00:00
zt_enable_ec ( p ) ;
2005-07-21 15:06:50 +00:00
if ( NEED_MFDETECT ( p ) ) {
if ( p - > dsp ) {
if ( ! p - > hardwaredtmf )
ast_dsp_digitmode ( p - > dsp , DSP_DIGITMODE_DTMF | p - > dtmfrelax ) ;
else {
ast_dsp_free ( p - > dsp ) ;
p - > dsp = NULL ;
}
}
}
2004-10-02 00:58:31 +00:00
if ( ast_exists_extension ( chan , chan - > context , exten , 1 , chan - > cid . cid_num ) ) {
2005-05-15 23:26:45 +00:00
ast_copy_string ( chan - > exten , exten , sizeof ( chan - > exten ) ) ;
2005-07-19 13:30:37 +00:00
if ( p - > dsp ) ast_dsp_digitreset ( p - > dsp ) ;
2001-10-09 02:06:21 +00:00
res = ast_pbx_run ( chan ) ;
if ( res ) {
ast_log ( LOG_WARNING , " PBX exited non-zero \n " ) ;
2003-02-07 19:23:19 +00:00
res = tone_zone_play_tone ( p - > subs [ index ] . zfd , ZT_TONE_CONGESTION ) ;
2001-10-09 02:06:21 +00:00
}
return NULL ;
} else {
if ( option_verbose > 2 )
ast_verbose ( VERBOSE_PREFIX_2 " Unknown extension '%s' in context '%s' requested \n " , exten , chan - > context ) ;
sleep ( 2 ) ;
2003-02-07 19:23:19 +00:00
res = tone_zone_play_tone ( p - > subs [ index ] . zfd , ZT_TONE_INFO ) ;
2001-10-09 02:06:21 +00:00
if ( res < 0 )
ast_log ( LOG_WARNING , " Unable to start special tone on %d \n " , p - > channel ) ;
else
sleep ( 1 ) ;
res = ast_streamfile ( chan , " ss-noservice " , chan - > language ) ;
if ( res > = 0 )
ast_waitstream ( chan , " " ) ;
2003-02-07 19:23:19 +00:00
res = tone_zone_play_tone ( p - > subs [ index ] . zfd , ZT_TONE_CONGESTION ) ;
2001-10-09 02:06:21 +00:00
ast_hangup ( chan ) ;
return NULL ;
}
break ;
case SIG_FXOLS :
case SIG_FXOGS :
case SIG_FXOKS :
/* Read the first digit */
timeout = firstdigittimeout ;
2003-02-13 06:00:14 +00:00
/* If starting a threeway call, never timeout on the first digit so someone
can use flash - hook as a " hold " feature */
if ( p - > subs [ SUB_THREEWAY ] . owner )
timeout = 999999 ;
2001-10-09 02:06:21 +00:00
while ( len < AST_MAX_EXTENSION - 1 ) {
2004-09-02 03:32:07 +00:00
/* Read digit unless it's supposed to be immediate, in which case the
only answer is ' s ' */
if ( p - > immediate )
res = ' s ' ;
else
res = ast_waitfordigit ( chan , timeout ) ;
2003-02-07 19:23:19 +00:00
timeout = 0 ;
if ( res < 0 ) {
ast_log ( LOG_DEBUG , " waitfordigit returned < 0... \n " ) ;
res = tone_zone_play_tone ( p - > subs [ index ] . zfd , - 1 ) ;
2001-10-09 02:06:21 +00:00
ast_hangup ( chan ) ;
return NULL ;
2003-02-07 19:23:19 +00:00
} else if ( res ) {
2001-10-09 02:06:21 +00:00
exten [ len + + ] = res ;
2004-07-19 05:00:05 +00:00
exten [ len ] = ' \0 ' ;
2001-10-09 02:06:21 +00:00
}
if ( ! ast_ignore_pattern ( chan - > context , exten ) )
2003-02-07 19:23:19 +00:00
tone_zone_play_tone ( p - > subs [ index ] . zfd , - 1 ) ;
else
tone_zone_play_tone ( p - > subs [ index ] . zfd , ZT_TONE_DIALTONE ) ;
2004-10-02 00:58:31 +00:00
if ( ast_exists_extension ( chan , chan - > context , exten , 1 , p - > cid_num ) & & strcmp ( exten , ast_parking_ext ( ) ) ) {
if ( ! res | | ! ast_matchmore_extension ( chan , chan - > context , exten , 1 , p - > cid_num ) ) {
2003-02-07 19:23:19 +00:00
if ( getforward ) {
/* Record this as the forwarding extension */
2005-05-15 23:26:45 +00:00
ast_copy_string ( p - > call_forward , exten , sizeof ( p - > call_forward ) ) ;
2003-02-07 19:23:19 +00:00
if ( option_verbose > 2 )
ast_verbose ( VERBOSE_PREFIX_3 " Setting call forward to '%s' on channel %d \n " , p - > call_forward , p - > channel ) ;
res = tone_zone_play_tone ( p - > subs [ index ] . zfd , ZT_TONE_DIALRECALL ) ;
if ( res )
break ;
usleep ( 500000 ) ;
res = tone_zone_play_tone ( p - > subs [ index ] . zfd , - 1 ) ;
sleep ( 1 ) ;
memset ( exten , 0 , sizeof ( exten ) ) ;
res = tone_zone_play_tone ( p - > subs [ index ] . zfd , ZT_TONE_DIALTONE ) ;
len = 0 ;
getforward = 0 ;
} else {
res = tone_zone_play_tone ( p - > subs [ index ] . zfd , - 1 ) ;
2005-05-15 23:26:45 +00:00
ast_copy_string ( chan - > exten , exten , sizeof ( chan - > exten ) ) ;
2004-10-02 00:58:31 +00:00
if ( ! ast_strlen_zero ( p - > cid_num ) ) {
if ( ! p - > hidecallerid )
2005-01-05 22:40:42 +00:00
ast_set_callerid ( chan , p - > cid_num , NULL , p - > cid_num ) ;
else
ast_set_callerid ( chan , NULL , NULL , p - > cid_num ) ;
2004-10-02 00:58:31 +00:00
}
if ( ! ast_strlen_zero ( p - > cid_name ) ) {
2003-02-07 19:23:19 +00:00
if ( ! p - > hidecallerid )
2005-01-05 22:40:42 +00:00
ast_set_callerid ( chan , NULL , p - > cid_name , NULL ) ;
2003-02-07 19:23:19 +00:00
}
ast_setstate ( chan , AST_STATE_RING ) ;
zt_enable_ec ( p ) ;
res = ast_pbx_run ( chan ) ;
if ( res ) {
ast_log ( LOG_WARNING , " PBX exited non-zero \n " ) ;
res = tone_zone_play_tone ( p - > subs [ index ] . zfd , ZT_TONE_CONGESTION ) ;
}
return NULL ;
2002-03-08 23:48:42 +00:00
}
2003-02-07 19:23:19 +00:00
} else {
/* It's a match, but they just typed a digit, and there is an ambiguous match,
so just set the timeout to matchdigittimeout and wait some more */
timeout = matchdigittimeout ;
2001-12-29 18:04:21 +00:00
}
2003-02-07 19:23:19 +00:00
} else if ( res = = 0 ) {
ast_log ( LOG_DEBUG , " not enough digits (and no ambiguous match)... \n " ) ;
res = tone_zone_play_tone ( p - > subs [ index ] . zfd , ZT_TONE_CONGESTION ) ;
zt_wait_event ( p - > subs [ index ] . zfd ) ;
ast_hangup ( chan ) ;
return NULL ;
2001-10-09 02:06:21 +00:00
} else if ( p - > callwaiting & & ! strcmp ( exten , " *70 " ) ) {
if ( option_verbose > 2 )
ast_verbose ( VERBOSE_PREFIX_3 " Disabling call waiting on %s \n " , chan - > name ) ;
/* Disable call waiting if enabled */
p - > callwaiting = 0 ;
2003-02-07 19:23:19 +00:00
res = tone_zone_play_tone ( p - > subs [ index ] . zfd , ZT_TONE_DIALRECALL ) ;
2001-10-09 02:06:21 +00:00
if ( res ) {
ast_log ( LOG_WARNING , " Unable to do dial recall on channel %s: %s \n " ,
chan - > name , strerror ( errno ) ) ;
}
len = 0 ;
2003-02-07 19:23:19 +00:00
ioctl ( p - > subs [ index ] . zfd , ZT_CONFDIAG , & len ) ;
2001-10-09 02:06:21 +00:00
memset ( exten , 0 , sizeof ( exten ) ) ;
timeout = firstdigittimeout ;
2003-04-09 04:00:43 +00:00
} else if ( ! strcmp ( exten , ast_pickup_ext ( ) ) ) {
2001-10-09 02:06:21 +00:00
/* Scan all channels and see if any there
* ringing channqels with that have call groups
* that equal this channels pickup group
*/
2003-04-09 04:00:43 +00:00
if ( index = = SUB_REAL ) {
/* Switch us from Third call to Call Wait */
if ( p - > subs [ SUB_THREEWAY ] . owner ) {
/* If you make a threeway call and the *8# a call, it should actually
look like a callwait */
alloc_sub ( p , SUB_CALLWAIT ) ;
swap_subs ( p , SUB_CALLWAIT , SUB_THREEWAY ) ;
unalloc_sub ( p , SUB_THREEWAY ) ;
}
zt_enable_ec ( p ) ;
if ( ast_pickup_call ( chan ) ) {
ast_log ( LOG_DEBUG , " No call pickup possible... \n " ) ;
res = tone_zone_play_tone ( p - > subs [ index ] . zfd , ZT_TONE_CONGESTION ) ;
zt_wait_event ( p - > subs [ index ] . zfd ) ;
2001-10-09 02:06:21 +00:00
}
2003-04-09 04:00:43 +00:00
ast_hangup ( chan ) ;
return NULL ;
} else {
ast_log ( LOG_WARNING , " Huh? Got *8# on call not on real \n " ) ;
ast_hangup ( chan ) ;
return NULL ;
2001-10-09 02:06:21 +00:00
}
2003-04-09 04:00:43 +00:00
2001-10-09 02:06:21 +00:00
} else if ( ! p - > hidecallerid & & ! strcmp ( exten , " *67 " ) ) {
if ( option_verbose > 2 )
ast_verbose ( VERBOSE_PREFIX_3 " Disabling Caller*ID on %s \n " , chan - > name ) ;
/* Disable Caller*ID if enabled */
p - > hidecallerid = 1 ;
2004-10-02 00:58:31 +00:00
if ( chan - > cid . cid_num )
free ( chan - > cid . cid_num ) ;
chan - > cid . cid_num = NULL ;
if ( chan - > cid . cid_name )
free ( chan - > cid . cid_name ) ;
chan - > cid . cid_name = NULL ;
2003-02-07 19:23:19 +00:00
res = tone_zone_play_tone ( p - > subs [ index ] . zfd , ZT_TONE_DIALRECALL ) ;
2001-10-09 02:06:21 +00:00
if ( res ) {
ast_log ( LOG_WARNING , " Unable to do dial recall on channel %s: %s \n " ,
chan - > name , strerror ( errno ) ) ;
}
len = 0 ;
memset ( exten , 0 , sizeof ( exten ) ) ;
timeout = firstdigittimeout ;
2003-02-07 19:23:19 +00:00
} else if ( p - > callreturn & & ! strcmp ( exten , " *69 " ) ) {
res = 0 ;
2004-10-02 00:58:31 +00:00
if ( ! ast_strlen_zero ( p - > lastcid_num ) ) {
res = ast_say_digit_str ( chan , p - > lastcid_num , " " , chan - > language ) ;
2003-02-07 19:23:19 +00:00
}
if ( ! res )
res = tone_zone_play_tone ( p - > subs [ index ] . zfd , ZT_TONE_DIALRECALL ) ;
break ;
2002-09-10 04:45:51 +00:00
} else if ( ! strcmp ( exten , " *78 " ) ) {
/* Do not disturb */
2005-04-27 04:03:49 +00:00
if ( option_verbose > 2 ) {
2002-09-10 04:45:51 +00:00
ast_verbose ( VERBOSE_PREFIX_3 " Enabled DND on channel %d \n " , p - > channel ) ;
2005-04-27 04:03:49 +00:00
manager_event ( EVENT_FLAG_SYSTEM , " DNDState " ,
" Channel: Zap/%d \r \n "
" Status: enabled \r \n " , p - > channel ) ;
}
2003-02-07 19:23:19 +00:00
res = tone_zone_play_tone ( p - > subs [ index ] . zfd , ZT_TONE_DIALRECALL ) ;
2002-09-10 04:45:51 +00:00
p - > dnd = 1 ;
getforward = 0 ;
memset ( exten , 0 , sizeof ( exten ) ) ;
len = 0 ;
} else if ( ! strcmp ( exten , " *79 " ) ) {
/* Do not disturb */
2005-04-27 04:03:49 +00:00
if ( option_verbose > 2 ) {
2002-09-10 04:45:51 +00:00
ast_verbose ( VERBOSE_PREFIX_3 " Disabled DND on channel %d \n " , p - > channel ) ;
2005-04-27 04:03:49 +00:00
manager_event ( EVENT_FLAG_SYSTEM , " DNDState " ,
" Channel: Zap/%d \r \n "
" Status: disabled \r \n " , p - > channel ) ;
}
2003-02-07 19:23:19 +00:00
res = tone_zone_play_tone ( p - > subs [ index ] . zfd , ZT_TONE_DIALRECALL ) ;
2002-09-10 04:45:51 +00:00
p - > dnd = 0 ;
getforward = 0 ;
memset ( exten , 0 , sizeof ( exten ) ) ;
len = 0 ;
2002-03-08 23:48:42 +00:00
} else if ( p - > cancallforward & & ! strcmp ( exten , " *72 " ) ) {
2003-02-07 19:23:19 +00:00
res = tone_zone_play_tone ( p - > subs [ index ] . zfd , ZT_TONE_DIALRECALL ) ;
2002-03-08 23:48:42 +00:00
getforward = 1 ;
memset ( exten , 0 , sizeof ( exten ) ) ;
len = 0 ;
} else if ( p - > cancallforward & & ! strcmp ( exten , " *73 " ) ) {
if ( option_verbose > 2 )
ast_verbose ( VERBOSE_PREFIX_3 " Cancelling call forwarding on channel %d \n " , p - > channel ) ;
2003-02-07 19:23:19 +00:00
res = tone_zone_play_tone ( p - > subs [ index ] . zfd , ZT_TONE_DIALRECALL ) ;
2002-03-08 23:48:42 +00:00
memset ( p - > call_forward , 0 , sizeof ( p - > call_forward ) ) ;
getforward = 0 ;
memset ( exten , 0 , sizeof ( exten ) ) ;
len = 0 ;
2004-12-09 22:39:14 +00:00
} else if ( ( p - > transfer | | p - > canpark ) & & ! strcmp ( exten , ast_parking_ext ( ) ) & &
2003-02-07 19:23:19 +00:00
p - > subs [ SUB_THREEWAY ] . owner & &
2004-10-23 12:19:47 +00:00
ast_bridged_channel ( p - > subs [ SUB_THREEWAY ] . owner ) ) {
2001-12-29 18:04:21 +00:00
/* This is a three way call, the main call being a real channel,
and we ' re parking the first call . */
2004-10-23 12:19:47 +00:00
ast_masq_park_call ( ast_bridged_channel ( p - > subs [ SUB_THREEWAY ] . owner ) , chan , 0 , NULL ) ;
2001-12-29 18:04:21 +00:00
if ( option_verbose > 2 )
ast_verbose ( VERBOSE_PREFIX_3 " Parking call to '%s' \n " , chan - > name ) ;
break ;
2004-10-02 00:58:31 +00:00
} else if ( ! ast_strlen_zero ( p - > lastcid_num ) & & ! strcmp ( exten , " *60 " ) ) {
2003-03-06 06:00:17 +00:00
if ( option_verbose > 2 )
2004-10-02 00:58:31 +00:00
ast_verbose ( VERBOSE_PREFIX_3 " Blacklisting number %s \n " , p - > lastcid_num ) ;
res = ast_db_put ( " blacklist " , p - > lastcid_num , " 1 " ) ;
2003-03-06 06:00:17 +00:00
if ( ! res ) {
res = tone_zone_play_tone ( p - > subs [ index ] . zfd , ZT_TONE_DIALRECALL ) ;
memset ( exten , 0 , sizeof ( exten ) ) ;
len = 0 ;
}
2001-10-09 02:06:21 +00:00
} else if ( p - > hidecallerid & & ! strcmp ( exten , " *82 " ) ) {
if ( option_verbose > 2 )
ast_verbose ( VERBOSE_PREFIX_3 " Enabling Caller*ID on %s \n " , chan - > name ) ;
/* Enable Caller*ID if enabled */
p - > hidecallerid = 0 ;
2004-10-02 00:58:31 +00:00
if ( chan - > cid . cid_num )
free ( chan - > cid . cid_num ) ;
chan - > cid . cid_num = NULL ;
if ( chan - > cid . cid_name )
free ( chan - > cid . cid_name ) ;
chan - > cid . cid_name = NULL ;
2005-01-05 22:40:42 +00:00
ast_set_callerid ( chan , p - > cid_num , p - > cid_name , NULL ) ;
2003-02-07 19:23:19 +00:00
res = tone_zone_play_tone ( p - > subs [ index ] . zfd , ZT_TONE_DIALRECALL ) ;
2001-10-09 02:06:21 +00:00
if ( res ) {
ast_log ( LOG_WARNING , " Unable to do dial recall on channel %s: %s \n " ,
chan - > name , strerror ( errno ) ) ;
}
len = 0 ;
memset ( exten , 0 , sizeof ( exten ) ) ;
timeout = firstdigittimeout ;
} else if ( ! strcmp ( exten , " *0 " ) ) {
struct ast_channel * nbridge =
2003-02-07 19:23:19 +00:00
p - > subs [ SUB_THREEWAY ] . owner ;
2001-10-09 02:06:21 +00:00
struct zt_pvt * pbridge = NULL ;
/* set up the private struct of the bridged one, if any */
2004-12-01 04:35:34 +00:00
if ( nbridge & & ast_bridged_channel ( nbridge ) )
2005-03-04 06:47:24 +00:00
pbridge = ast_bridged_channel ( nbridge ) - > tech_pvt ;
2004-12-01 04:35:34 +00:00
if ( nbridge & & pbridge & &
( ! strcmp ( nbridge - > type , " Zap " ) ) & &
( ! strcmp ( ast_bridged_channel ( nbridge ) - > type , " Zap " ) ) & &
2001-10-09 02:06:21 +00:00
ISTRUNK ( pbridge ) ) {
int func = ZT_FLASH ;
2003-05-19 23:33:41 +00:00
/* Clear out the dial buffer */
p - > dop . dialstr [ 0 ] = ' \0 ' ;
2001-10-09 02:06:21 +00:00
/* flash hookswitch */
2003-02-07 19:23:19 +00:00
if ( ( ioctl ( pbridge - > subs [ SUB_REAL ] . zfd , ZT_HOOK , & func ) = = - 1 ) & & ( errno ! = EINPROGRESS ) ) {
2001-10-09 02:06:21 +00:00
ast_log ( LOG_WARNING , " Unable to flash external trunk on channel %s: %s \n " ,
nbridge - > name , strerror ( errno ) ) ;
2003-02-07 19:23:19 +00:00
}
swap_subs ( p , SUB_REAL , SUB_THREEWAY ) ;
unalloc_sub ( p , SUB_THREEWAY ) ;
p - > owner = p - > subs [ SUB_REAL ] . owner ;
2004-10-23 12:19:47 +00:00
if ( ast_bridged_channel ( p - > subs [ SUB_REAL ] . owner ) )
ast_moh_stop ( ast_bridged_channel ( p - > subs [ SUB_REAL ] . owner ) ) ;
2001-10-09 02:06:21 +00:00
ast_hangup ( chan ) ;
return NULL ;
} else {
2003-02-07 19:23:19 +00:00
tone_zone_play_tone ( p - > subs [ index ] . zfd , ZT_TONE_CONGESTION ) ;
zt_wait_event ( p - > subs [ index ] . zfd ) ;
tone_zone_play_tone ( p - > subs [ index ] . zfd , - 1 ) ;
swap_subs ( p , SUB_REAL , SUB_THREEWAY ) ;
unalloc_sub ( p , SUB_THREEWAY ) ;
p - > owner = p - > subs [ SUB_REAL ] . owner ;
2001-10-09 02:06:21 +00:00
ast_hangup ( chan ) ;
return NULL ;
}
2004-10-02 00:58:31 +00:00
} else if ( ! ast_canmatch_extension ( chan , chan - > context , exten , 1 , chan - > cid . cid_num ) & &
2001-10-09 02:06:21 +00:00
( ( exten [ 0 ] ! = ' * ' ) | | ( strlen ( exten ) > 2 ) ) ) {
if ( option_debug )
2004-10-02 00:58:31 +00:00
ast_log ( LOG_DEBUG , " Can't match %s from '%s' in context %s \n " , exten , chan - > cid . cid_num ? chan - > cid . cid_num : " <Unknown Caller> " , chan - > context ) ;
2001-10-09 02:06:21 +00:00
break ;
}
2003-02-07 19:23:19 +00:00
if ( ! timeout )
timeout = gendigittimeout ;
2001-10-09 02:06:21 +00:00
if ( len & & ! ast_ignore_pattern ( chan - > context , exten ) )
2003-02-07 19:23:19 +00:00
tone_zone_play_tone ( p - > subs [ index ] . zfd , - 1 ) ;
2001-10-09 02:06:21 +00:00
}
break ;
case SIG_FXSLS :
case SIG_FXSGS :
case SIG_FXSKS :
2004-07-19 05:00:05 +00:00
# ifdef ZAPATA_PRI
2004-07-18 20:50:37 +00:00
if ( p - > pri ) {
/* This is a GR-303 trunk actually. Wait for the first ring... */
struct ast_frame * f ;
int res ;
time_t start ;
time ( & start ) ;
ast_setstate ( chan , AST_STATE_RING ) ;
while ( time ( NULL ) < start + 3 ) {
res = ast_waitfor ( chan , 1000 ) ;
if ( res ) {
f = ast_read ( chan ) ;
if ( ! f ) {
ast_log ( LOG_WARNING , " Whoa, hangup while waiting for first ring! \n " ) ;
ast_hangup ( chan ) ;
return NULL ;
} else if ( ( f - > frametype = = AST_FRAME_CONTROL ) & & ( f - > subclass = = AST_CONTROL_RING ) ) {
res = 1 ;
} else
res = 0 ;
ast_frfree ( f ) ;
if ( res ) {
ast_log ( LOG_DEBUG , " Got ring! \n " ) ;
res = 0 ;
break ;
}
}
}
}
2004-07-19 05:00:05 +00:00
# endif
2004-09-19 16:17:18 +00:00
/* If we want caller id, we're in a prering state due to a polarity reversal
* and we ' re set to use a polarity reversal to trigger the start of caller id ,
* grab the caller id and wait for ringing to start . . . */
if ( p - > use_callerid & & ( chan - > _state = = AST_STATE_PRERING & & p - > cid_start = = CID_START_POLARITY ) ) {
/* If set to use DTMF CID signalling, listen for DTMF */
if ( p - > cid_signalling = = CID_SIG_DTMF ) {
int i = 0 ;
cs = NULL ;
ast_log ( LOG_DEBUG , " Receiving DTMF cid on "
" channel %s \n " , chan - > name ) ;
zt_setlinear ( p - > subs [ index ] . zfd , 0 ) ;
res = 2000 ;
for ( ; ; ) {
struct ast_frame * f ;
res = ast_waitfor ( chan , res ) ;
if ( res < = 0 ) {
ast_log ( LOG_WARNING , " DTMFCID timed out waiting for ring. "
" Exiting simple switch \n " ) ;
ast_hangup ( chan ) ;
return NULL ;
}
f = ast_read ( chan ) ;
if ( f - > frametype = = AST_FRAME_DTMF ) {
dtmfbuf [ i + + ] = f - > subclass ;
ast_log ( LOG_DEBUG , " CID got digit '%c' \n " , f - > subclass ) ;
res = 2000 ;
}
ast_frfree ( f ) ;
if ( chan - > _state = = AST_STATE_RING | |
chan - > _state = = AST_STATE_RINGING )
break ; /* Got ring */
}
dtmfbuf [ i ] = 0 ;
zt_setlinear ( p - > subs [ index ] . zfd , p - > subs [ index ] . linear ) ;
/* Got cid and ring. */
ast_log ( LOG_DEBUG , " CID got string '%s' \n " , dtmfbuf ) ;
callerid_get_dtmf ( dtmfbuf , dtmfcid , & flags ) ;
ast_log ( LOG_DEBUG , " CID is '%s', flags %d \n " ,
dtmfcid , flags ) ;
/* If first byte is NULL, we have no cid */
if ( dtmfcid [ 0 ] )
number = dtmfcid ;
else
number = 0 ;
/* If set to use V23 Signalling, launch our FSK gubbins and listen for it */
} else if ( p - > cid_signalling = = CID_SIG_V23 ) {
cs = callerid_new ( cid_signalling ) ;
if ( cs ) {
2004-11-22 18:59:19 +00:00
samples = 0 ;
2004-09-19 16:17:18 +00:00
# if 1
bump_gains ( p ) ;
# endif
/* Take out of linear mode for Caller*ID processing */
zt_setlinear ( p - > subs [ index ] . zfd , 0 ) ;
/* First we wait and listen for the Caller*ID */
for ( ; ; ) {
i = ZT_IOMUX_READ | ZT_IOMUX_SIGEVENT ;
if ( ( res = ioctl ( p - > subs [ index ] . zfd , ZT_IOMUX , & i ) ) ) {
ast_log ( LOG_WARNING , " I/O MUX failed: %s \n " , strerror ( errno ) ) ;
callerid_free ( cs ) ;
ast_hangup ( chan ) ;
return NULL ;
}
if ( i & ZT_IOMUX_SIGEVENT ) {
res = zt_get_event ( p - > subs [ index ] . zfd ) ;
ast_log ( LOG_NOTICE , " Got event %d (%s)... \n " , res , event2str ( res ) ) ;
res = 0 ;
2004-11-19 13:45:44 +00:00
break ;
2004-09-19 16:17:18 +00:00
} else if ( i & ZT_IOMUX_READ ) {
res = read ( p - > subs [ index ] . zfd , buf , sizeof ( buf ) ) ;
if ( res < 0 ) {
if ( errno ! = ELAST ) {
ast_log ( LOG_WARNING , " read returned error: %s \n " , strerror ( errno ) ) ;
callerid_free ( cs ) ;
ast_hangup ( chan ) ;
return NULL ;
}
break ;
}
2004-11-22 18:59:19 +00:00
samples + = res ;
2004-09-19 16:17:18 +00:00
res = callerid_feed ( cs , buf , res , AST_LAW ( p ) ) ;
if ( res < 0 ) {
ast_log ( LOG_WARNING , " CallerID feed failed: %s \n " , strerror ( errno ) ) ;
break ;
} else if ( res )
break ;
2004-11-22 18:59:19 +00:00
else if ( samples > ( 8000 * 10 ) )
break ;
2004-09-19 16:17:18 +00:00
}
}
if ( res = = 1 ) {
callerid_get ( cs , & name , & number , & flags ) ;
if ( option_debug )
ast_log ( LOG_DEBUG , " CallerID number: %s, name: %s, flags=%d \n " , number , name , flags ) ;
}
if ( res < 0 ) {
ast_log ( LOG_WARNING , " CallerID returned with error on channel '%s' \n " , chan - > name ) ;
}
/* Finished with Caller*ID, now wait for a ring to make sure there really is a call coming */
res = 2000 ;
for ( ; ; ) {
struct ast_frame * f ;
res = ast_waitfor ( chan , res ) ;
if ( res < = 0 ) {
ast_log ( LOG_WARNING , " CID timed out waiting for ring. "
" Exiting simple switch \n " ) ;
ast_hangup ( chan ) ;
return NULL ;
}
f = ast_read ( chan ) ;
ast_frfree ( f ) ;
if ( chan - > _state = = AST_STATE_RING | |
chan - > _state = = AST_STATE_RINGING )
break ; /* Got ring */
}
/* We must have a ring by now, so, if configured, lets try to listen for
* distinctive ringing */
if ( p - > usedistinctiveringdetection = = 1 ) {
len = 0 ;
distMatches = 0 ;
/* Clear the current ring data array so we dont have old data in it. */
for ( receivedRingT = 0 ; receivedRingT < 3 ; receivedRingT + + ) {
curRingData [ receivedRingT ] = 0 ;
}
receivedRingT = 0 ;
counter = 0 ;
counter1 = 0 ;
/* Check to see if context is what it should be, if not set to be. */
if ( strcmp ( p - > context , p - > defcontext ) ! = 0 ) {
2005-05-15 23:26:45 +00:00
ast_copy_string ( p - > context , p - > defcontext , sizeof ( p - > context ) ) ;
ast_copy_string ( chan - > context , p - > defcontext , sizeof ( chan - > context ) ) ;
2004-09-19 16:17:18 +00:00
}
for ( ; ; ) {
i = ZT_IOMUX_READ | ZT_IOMUX_SIGEVENT ;
if ( ( res = ioctl ( p - > subs [ index ] . zfd , ZT_IOMUX , & i ) ) ) {
ast_log ( LOG_WARNING , " I/O MUX failed: %s \n " , strerror ( errno ) ) ;
callerid_free ( cs ) ;
ast_hangup ( chan ) ;
return NULL ;
}
if ( i & ZT_IOMUX_SIGEVENT ) {
res = zt_get_event ( p - > subs [ index ] . zfd ) ;
ast_log ( LOG_NOTICE , " Got event %d (%s)... \n " , res , event2str ( res ) ) ;
res = 0 ;
/* Let us detect distinctive ring */
curRingData [ receivedRingT ] = p - > ringt ;
if ( p - > ringt < RINGT / 2 )
break ;
+ + receivedRingT ; /* Increment the ringT counter so we can match it against
values in zapata . conf for distinctive ring */
} else if ( i & ZT_IOMUX_READ ) {
res = read ( p - > subs [ index ] . zfd , buf , sizeof ( buf ) ) ;
if ( res < 0 ) {
if ( errno ! = ELAST ) {
ast_log ( LOG_WARNING , " read returned error: %s \n " , strerror ( errno ) ) ;
callerid_free ( cs ) ;
ast_hangup ( chan ) ;
return NULL ;
}
break ;
}
if ( p - > ringt )
p - > ringt - - ;
if ( p - > ringt = = 1 ) {
res = - 1 ;
break ;
}
}
}
if ( option_verbose > 2 )
/* this only shows up if you have n of the dring patterns filled in */
ast_verbose ( VERBOSE_PREFIX_3 " Detected ring pattern: %d,%d,%d \n " , curRingData [ 0 ] , curRingData [ 1 ] , curRingData [ 2 ] ) ;
for ( counter = 0 ; counter < 3 ; counter + + ) {
/* Check to see if the rings we received match any of the ones in zapata.conf for this
channel */
distMatches = 0 ;
for ( counter1 = 0 ; counter1 < 3 ; counter1 + + ) {
if ( curRingData [ counter1 ] < = ( p - > drings . ringnum [ counter ] . ring [ counter1 ] + 10 ) & & curRingData [ counter1 ] > =
( p - > drings . ringnum [ counter ] . ring [ counter1 ] - 10 ) ) {
distMatches + + ;
}
}
if ( distMatches = = 3 ) {
/* The ring matches, set the context to whatever is for distinctive ring.. */
2005-05-15 23:26:45 +00:00
ast_copy_string ( p - > context , p - > drings . ringContext [ counter ] . contextData , sizeof ( p - > context ) ) ;
ast_copy_string ( chan - > context , p - > drings . ringContext [ counter ] . contextData , sizeof ( chan - > context ) ) ;
2004-09-19 16:17:18 +00:00
if ( option_verbose > 2 )
ast_verbose ( VERBOSE_PREFIX_3 " Distinctive Ring matched context %s \n " , p - > context ) ;
break ;
}
}
}
/* Restore linear mode (if appropriate) for Caller*ID processing */
zt_setlinear ( p - > subs [ index ] . zfd , p - > subs [ index ] . linear ) ;
# if 1
restore_gains ( p ) ;
# endif
} else
ast_log ( LOG_WARNING , " Unable to get caller ID space \n " ) ;
} else {
ast_log ( LOG_WARNING , " Channel %s in prering "
" state, but I have nothing to do. "
" Terminating simple switch, should be "
" restarted by the actual ring. \n " ,
chan - > name ) ;
ast_hangup ( chan ) ;
return NULL ;
}
} else if ( p - > use_callerid & & p - > cid_start = = CID_START_RING ) {
/* FSK Bell202 callerID */
cs = callerid_new ( cid_signalling ) ;
2001-10-09 02:06:21 +00:00
if ( cs ) {
# if 1
bump_gains ( p ) ;
# endif
2004-11-22 18:59:19 +00:00
samples = 0 ;
2001-10-09 02:06:21 +00:00
len = 0 ;
2004-01-12 04:28:00 +00:00
distMatches = 0 ;
/* Clear the current ring data array so we dont have old data in it. */
for ( receivedRingT = 0 ; receivedRingT < 3 ; receivedRingT + + ) {
curRingData [ receivedRingT ] = 0 ;
}
receivedRingT = 0 ;
counter = 0 ;
counter1 = 0 ;
/* Check to see if context is what it should be, if not set to be. */
if ( strcmp ( p - > context , p - > defcontext ) ! = 0 ) {
2005-05-15 23:26:45 +00:00
ast_copy_string ( p - > context , p - > defcontext , sizeof ( p - > context ) ) ;
ast_copy_string ( chan - > context , p - > defcontext , sizeof ( chan - > context ) ) ;
2004-01-12 04:28:00 +00:00
}
2003-02-07 19:23:19 +00:00
/* Take out of linear mode for Caller*ID processing */
zt_setlinear ( p - > subs [ index ] . zfd , 0 ) ;
2001-10-09 02:06:21 +00:00
for ( ; ; ) {
i = ZT_IOMUX_READ | ZT_IOMUX_SIGEVENT ;
2003-02-07 19:23:19 +00:00
if ( ( res = ioctl ( p - > subs [ index ] . zfd , ZT_IOMUX , & i ) ) ) {
2001-10-09 02:06:21 +00:00
ast_log ( LOG_WARNING , " I/O MUX failed: %s \n " , strerror ( errno ) ) ;
callerid_free ( cs ) ;
ast_hangup ( chan ) ;
return NULL ;
}
if ( i & ZT_IOMUX_SIGEVENT ) {
2003-02-07 19:23:19 +00:00
res = zt_get_event ( p - > subs [ index ] . zfd ) ;
2001-10-09 02:06:21 +00:00
ast_log ( LOG_NOTICE , " Got event %d (%s)... \n " , res , event2str ( res ) ) ;
res = 0 ;
2003-09-17 22:23:17 +00:00
/* Let us detect callerid when the telco uses distinctive ring */
2004-01-12 04:28:00 +00:00
curRingData [ receivedRingT ] = p - > ringt ;
2003-09-17 22:23:17 +00:00
if ( p - > ringt < RINGT / 2 )
break ;
2004-01-12 04:28:00 +00:00
+ + receivedRingT ; /* Increment the ringT counter so we can match it against
values in zapata . conf for distinctive ring */
2001-10-09 02:06:21 +00:00
} else if ( i & ZT_IOMUX_READ ) {
2003-02-07 19:23:19 +00:00
res = read ( p - > subs [ index ] . zfd , buf , sizeof ( buf ) ) ;
2001-10-09 02:06:21 +00:00
if ( res < 0 ) {
if ( errno ! = ELAST ) {
ast_log ( LOG_WARNING , " read returned error: %s \n " , strerror ( errno ) ) ;
callerid_free ( cs ) ;
ast_hangup ( chan ) ;
return NULL ;
}
break ;
}
if ( p - > ringt )
p - > ringt - - ;
if ( p - > ringt = = 1 ) {
res = - 1 ;
break ;
}
2004-11-22 18:59:19 +00:00
samples + = res ;
2003-02-07 19:23:19 +00:00
res = callerid_feed ( cs , buf , res , AST_LAW ( p ) ) ;
2001-10-09 02:06:21 +00:00
if ( res < 0 ) {
ast_log ( LOG_WARNING , " CallerID feed failed: %s \n " , strerror ( errno ) ) ;
break ;
} else if ( res )
break ;
2004-11-22 18:59:19 +00:00
else if ( samples > ( 8000 * 10 ) )
break ;
2001-10-09 02:06:21 +00:00
}
}
2004-03-10 08:33:07 +00:00
if ( p - > usedistinctiveringdetection = = 1 ) {
2004-01-12 04:28:00 +00:00
if ( option_verbose > 2 )
/* this only shows up if you have n of the dring patterns filled in */
ast_verbose ( VERBOSE_PREFIX_3 " Detected ring pattern: %d,%d,%d \n " , curRingData [ 0 ] , curRingData [ 1 ] , curRingData [ 2 ] ) ;
for ( counter = 0 ; counter < 3 ; counter + + ) {
/* Check to see if the rings we received match any of the ones in zapata.conf for this
channel */
distMatches = 0 ;
for ( counter1 = 0 ; counter1 < 3 ; counter1 + + ) {
if ( curRingData [ counter1 ] < = ( p - > drings . ringnum [ counter ] . ring [ counter1 ] + 10 ) & & curRingData [ counter1 ] > =
( p - > drings . ringnum [ counter ] . ring [ counter1 ] - 10 ) ) {
distMatches + + ;
}
}
if ( distMatches = = 3 ) {
/* The ring matches, set the context to whatever is for distinctive ring.. */
2005-05-15 23:26:45 +00:00
ast_copy_string ( p - > context , p - > drings . ringContext [ counter ] . contextData , sizeof ( p - > context ) ) ;
ast_copy_string ( chan - > context , p - > drings . ringContext [ counter ] . contextData , sizeof ( chan - > context ) ) ;
2004-01-12 04:28:00 +00:00
if ( option_verbose > 2 )
ast_verbose ( VERBOSE_PREFIX_3 " Distinctive Ring matched context %s \n " , p - > context ) ;
break ;
}
}
}
2001-10-09 02:06:21 +00:00
if ( res = = 1 ) {
callerid_get ( cs , & name , & number , & flags ) ;
if ( option_debug )
ast_log ( LOG_DEBUG , " CallerID number: %s, name: %s, flags=%d \n " , number , name , flags ) ;
}
2003-02-07 19:23:19 +00:00
/* Restore linear mode (if appropriate) for Caller*ID processing */
zt_setlinear ( p - > subs [ index ] . zfd , p - > subs [ index ] . linear ) ;
2001-10-09 02:06:21 +00:00
# if 1
restore_gains ( p ) ;
# endif
if ( res < 0 ) {
ast_log ( LOG_WARNING , " CallerID returned with error on channel '%s' \n " , chan - > name ) ;
}
} else
ast_log ( LOG_WARNING , " Unable to get caller ID space \n " ) ;
}
2003-10-08 21:57:43 +00:00
else
cs = NULL ;
2005-07-13 20:22:29 +00:00
if ( number | | name ) {
if ( chan - > cid . cid_num ) {
2004-10-02 00:58:31 +00:00
free ( chan - > cid . cid_num ) ;
chan - > cid . cid_num = NULL ;
2005-07-13 20:22:29 +00:00
}
if ( chan - > cid . cid_name ) {
2004-10-02 00:58:31 +00:00
free ( chan - > cid . cid_name ) ;
chan - > cid . cid_name = NULL ;
2005-07-13 20:22:29 +00:00
}
2004-10-02 00:58:31 +00:00
}
2004-10-03 14:52:33 +00:00
if ( number )
ast_shrink_phone_number ( number ) ;
2005-01-05 22:40:42 +00:00
ast_set_callerid ( chan , number , name , number ) ;
2004-10-02 00:58:31 +00:00
2003-10-08 21:57:43 +00:00
if ( cs )
callerid_free ( cs ) ;
2002-09-10 04:45:51 +00:00
ast_setstate ( chan , AST_STATE_RING ) ;
2001-10-09 02:06:21 +00:00
chan - > rings = 1 ;
p - > ringt = RINGT ;
res = ast_pbx_run ( chan ) ;
if ( res ) {
ast_hangup ( chan ) ;
ast_log ( LOG_WARNING , " PBX exited non-zero \n " ) ;
}
return NULL ;
default :
ast_log ( LOG_WARNING , " Don't know how to handle simple switch with signalling %s on channel %d \n " , sig2str ( p - > sig ) , p - > channel ) ;
2003-02-07 19:23:19 +00:00
res = tone_zone_play_tone ( p - > subs [ index ] . zfd , ZT_TONE_CONGESTION ) ;
2001-10-09 02:06:21 +00:00
if ( res < 0 )
ast_log ( LOG_WARNING , " Unable to play congestion tone on channel %d \n " , p - > channel ) ;
}
2003-02-07 19:23:19 +00:00
res = tone_zone_play_tone ( p - > subs [ index ] . zfd , ZT_TONE_CONGESTION ) ;
2001-10-09 02:06:21 +00:00
if ( res < 0 )
ast_log ( LOG_WARNING , " Unable to play congestion tone on channel %d \n " , p - > channel ) ;
ast_hangup ( chan ) ;
return NULL ;
}
2003-02-07 19:23:19 +00:00
# ifdef ZAPATA_R2
static int handle_init_r2_event ( struct zt_pvt * i , mfcr2_event_t * e )
{
struct ast_channel * chan ;
switch ( e - > e ) {
case MFCR2_EVENT_UNBLOCKED :
i - > r2blocked = 0 ;
if ( option_verbose > 2 )
ast_verbose ( VERBOSE_PREFIX_3 " R2 Channel %d unblocked \n " , i - > channel ) ;
break ;
case MFCR2_EVENT_BLOCKED :
i - > r2blocked = 1 ;
if ( option_verbose > 2 )
ast_verbose ( VERBOSE_PREFIX_3 " R2 Channel %d unblocked \n " , i - > channel ) ;
break ;
case MFCR2_EVENT_IDLE :
if ( option_verbose > 2 )
ast_verbose ( VERBOSE_PREFIX_3 " R2 Channel %d idle \n " , i - > channel ) ;
break ;
case MFCR2_EVENT_RINGING :
/* This is what Asterisk refers to as a "RING" event. For some reason they're reversed in
Steve ' s code */
/* Check for callerid, digits, etc */
i - > hasr2call = 1 ;
2004-10-31 23:17:11 +00:00
chan = zt_new ( i , AST_STATE_RING , 0 , SUB_REAL , 0 , 0 ) ;
2003-02-07 19:23:19 +00:00
if ( ! chan ) {
ast_log ( LOG_WARNING , " Unable to create channel for channel %d \n " , i - > channel ) ;
mfcr2_DropCall ( i - > r2 , NULL , UC_NETWORK_CONGESTION ) ;
i - > hasr2call = 0 ;
}
if ( ast_pbx_start ( chan ) ) {
ast_log ( LOG_WARNING , " Unable to start PBX on channel %s \n " , chan - > name ) ;
ast_hangup ( chan ) ;
}
break ;
default :
ast_log ( LOG_WARNING , " Don't know how to handle initial R2 event %s on channel %d \n " , mfcr2_event2str ( e - > e ) , i - > channel ) ;
return - 1 ;
}
return 0 ;
}
# endif
2001-10-09 02:06:21 +00:00
static int handle_init_event ( struct zt_pvt * i , int event )
{
int res ;
pthread_t threadid ;
pthread_attr_t attr ;
struct ast_channel * chan ;
pthread_attr_init ( & attr ) ;
pthread_attr_setdetachstate ( & attr , PTHREAD_CREATE_DETACHED ) ;
/* Handle an event on a given channel for the monitor thread. */
switch ( event ) {
2003-02-07 19:23:19 +00:00
case ZT_EVENT_NONE :
case ZT_EVENT_BITSCHANGED :
2004-08-21 21:41:54 +00:00
if ( i - > radio ) break ;
2003-02-07 19:23:19 +00:00
# ifdef ZAPATA_R2
if ( i - > r2 ) {
mfcr2_event_t * e ;
e = r2_get_event_bits ( i ) ;
i - > sigchecked = 1 ;
if ( e )
handle_init_r2_event ( i , e ) ;
}
# endif
break ;
case ZT_EVENT_WINKFLASH :
2001-10-09 02:06:21 +00:00
case ZT_EVENT_RINGOFFHOOK :
if ( i - > inalarm ) break ;
2004-08-21 21:41:54 +00:00
if ( i - > radio ) break ;
2001-10-09 02:06:21 +00:00
/* Got a ring/answer. What kind of channel are we? */
switch ( i - > sig ) {
case SIG_FXOLS :
case SIG_FXOGS :
case SIG_FXOKS :
2004-02-10 07:24:15 +00:00
zt_set_hook ( i - > subs [ SUB_REAL ] . zfd , ZT_OFFHOOK ) ;
2003-02-07 19:23:19 +00:00
if ( i - > cidspill ) {
/* Cancel VMWI spill */
free ( i - > cidspill ) ;
i - > cidspill = NULL ;
}
2001-10-09 02:06:21 +00:00
if ( i - > immediate ) {
zt_enable_ec ( i ) ;
/* The channel is immediately up. Start right away */
2003-02-07 19:23:19 +00:00
res = tone_zone_play_tone ( i - > subs [ SUB_REAL ] . zfd , ZT_TONE_RINGTONE ) ;
2003-11-21 18:38:42 +00:00
chan = zt_new ( i , AST_STATE_RING , 1 , SUB_REAL , 0 , 0 ) ;
2001-12-29 18:04:21 +00:00
if ( ! chan ) {
2001-10-09 02:06:21 +00:00
ast_log ( LOG_WARNING , " Unable to start PBX on channel %d \n " , i - > channel ) ;
2003-02-07 19:23:19 +00:00
res = tone_zone_play_tone ( i - > subs [ SUB_REAL ] . zfd , ZT_TONE_CONGESTION ) ;
2001-10-09 02:06:21 +00:00
if ( res < 0 )
ast_log ( LOG_WARNING , " Unable to play congestion tone on channel %d \n " , i - > channel ) ;
}
} else {
/* Check for callerid, digits, etc */
2003-11-21 18:38:42 +00:00
chan = zt_new ( i , AST_STATE_RESERVED , 0 , SUB_REAL , 0 , 0 ) ;
2001-12-29 18:04:21 +00:00
if ( chan ) {
2002-03-08 23:48:42 +00:00
if ( has_voicemail ( i ) )
2003-05-19 23:33:41 +00:00
res = tone_zone_play_tone ( i - > subs [ SUB_REAL ] . zfd , ZT_TONE_STUTTER ) ;
2002-03-08 23:48:42 +00:00
else
2003-02-07 19:23:19 +00:00
res = tone_zone_play_tone ( i - > subs [ SUB_REAL ] . zfd , ZT_TONE_DIALTONE ) ;
2001-12-29 18:04:21 +00:00
if ( res < 0 )
ast_log ( LOG_WARNING , " Unable to play dialtone on channel %d \n " , i - > channel ) ;
2004-08-08 17:15:02 +00:00
if ( ast_pthread_create ( & threadid , & attr , ss_thread , chan ) ) {
2001-12-29 18:04:21 +00:00
ast_log ( LOG_WARNING , " Unable to start simple switch thread on channel %d \n " , i - > channel ) ;
2003-02-07 19:23:19 +00:00
res = tone_zone_play_tone ( i - > subs [ SUB_REAL ] . zfd , ZT_TONE_CONGESTION ) ;
2001-12-29 18:04:21 +00:00
if ( res < 0 )
ast_log ( LOG_WARNING , " Unable to play congestion tone on channel %d \n " , i - > channel ) ;
ast_hangup ( chan ) ;
}
} else
ast_log ( LOG_WARNING , " Unable to create channel \n " ) ;
2001-10-09 02:06:21 +00:00
#if 0
printf ( " Created thread %ld detached in switch \n " , threadid ) ;
# endif
}
break ;
case SIG_FXSLS :
case SIG_FXSGS :
case SIG_FXSKS :
i - > ringt = RINGT ;
/* Fall through */
case SIG_EMWINK :
case SIG_FEATD :
2002-06-24 17:59:56 +00:00
case SIG_FEATDMF :
2004-01-16 23:40:37 +00:00
case SIG_E911 :
2002-06-24 17:59:56 +00:00
case SIG_FEATB :
2001-10-09 02:06:21 +00:00
case SIG_EM :
2004-04-16 18:00:00 +00:00
case SIG_EM_E1 :
2003-03-17 20:04:36 +00:00
case SIG_SFWINK :
case SIG_SF_FEATD :
case SIG_SF_FEATDMF :
case SIG_SF_FEATB :
case SIG_SF :
2001-10-09 02:06:21 +00:00
/* Check for callerid, digits, etc */
2003-11-21 18:38:42 +00:00
chan = zt_new ( i , AST_STATE_RING , 0 , SUB_REAL , 0 , 0 ) ;
2004-08-08 17:15:02 +00:00
if ( chan & & ast_pthread_create ( & threadid , & attr , ss_thread , chan ) ) {
2001-10-09 02:06:21 +00:00
ast_log ( LOG_WARNING , " Unable to start simple switch thread on channel %d \n " , i - > channel ) ;
2003-02-07 19:23:19 +00:00
res = tone_zone_play_tone ( i - > subs [ SUB_REAL ] . zfd , ZT_TONE_CONGESTION ) ;
2001-10-09 02:06:21 +00:00
if ( res < 0 )
ast_log ( LOG_WARNING , " Unable to play congestion tone on channel %d \n " , i - > channel ) ;
ast_hangup ( chan ) ;
2004-01-09 05:13:50 +00:00
} else if ( ! chan ) {
ast_log ( LOG_WARNING , " Cannot allocate new structure on channel %d \n " , i - > channel ) ;
2001-10-09 02:06:21 +00:00
}
#if 0
printf ( " Created thread %ld detached in switch(2) \n " , threadid ) ;
# endif
break ;
default :
ast_log ( LOG_WARNING , " Don't know how to handle ring/answer with signalling %s on channel %d \n " , sig2str ( i - > sig ) , i - > channel ) ;
2003-02-07 19:23:19 +00:00
res = tone_zone_play_tone ( i - > subs [ SUB_REAL ] . zfd , ZT_TONE_CONGESTION ) ;
2001-10-09 02:06:21 +00:00
if ( res < 0 )
ast_log ( LOG_WARNING , " Unable to play congestion tone on channel %d \n " , i - > channel ) ;
return - 1 ;
}
break ;
case ZT_EVENT_NOALARM :
i - > inalarm = 0 ;
2003-02-26 19:41:10 +00:00
ast_log ( LOG_NOTICE , " Alarm cleared on channel %d \n " , i - > channel ) ;
2001-10-09 02:06:21 +00:00
break ;
case ZT_EVENT_ALARM :
i - > inalarm = 1 ;
2003-02-28 06:00:18 +00:00
res = get_alarms ( i ) ;
ast_log ( LOG_WARNING , " Detected alarm on channel %d: %s \n " , i - > channel , alarm2str ( res ) ) ;
2001-10-09 02:06:21 +00:00
/* fall thru intentionally */
case ZT_EVENT_ONHOOK :
2004-08-21 21:41:54 +00:00
if ( i - > radio ) break ;
2001-10-09 02:06:21 +00:00
/* Back on hook. Hang up. */
switch ( i - > sig ) {
case SIG_FXOLS :
case SIG_FXOGS :
case SIG_FEATD :
2002-06-24 17:59:56 +00:00
case SIG_FEATDMF :
2004-01-16 23:40:37 +00:00
case SIG_E911 :
2002-06-24 17:59:56 +00:00
case SIG_FEATB :
2001-10-09 02:06:21 +00:00
case SIG_EM :
2004-04-16 18:00:00 +00:00
case SIG_EM_E1 :
2001-10-09 02:06:21 +00:00
case SIG_EMWINK :
2003-03-17 20:04:36 +00:00
case SIG_SF_FEATD :
case SIG_SF_FEATDMF :
case SIG_SF_FEATB :
case SIG_SF :
case SIG_SFWINK :
2001-10-09 02:06:21 +00:00
case SIG_FXSLS :
case SIG_FXSGS :
case SIG_FXSKS :
2004-06-29 11:45:51 +00:00
case SIG_GR303FXSKS :
2001-10-09 02:06:21 +00:00
zt_disable_ec ( i ) ;
2003-02-07 19:23:19 +00:00
res = tone_zone_play_tone ( i - > subs [ SUB_REAL ] . zfd , - 1 ) ;
zt_set_hook ( i - > subs [ SUB_REAL ] . zfd , ZT_ONHOOK ) ;
2001-10-09 02:06:21 +00:00
break ;
2004-06-06 23:26:29 +00:00
case SIG_GR303FXOKS :
2002-06-24 17:59:56 +00:00
case SIG_FXOKS :
zt_disable_ec ( i ) ;
/* Diddle the battery for the zhone */
# ifdef ZHONE_HACK
2003-02-07 19:23:19 +00:00
zt_set_hook ( i - > subs [ SUB_REAL ] . zfd , ZT_OFFHOOK ) ;
2002-06-24 17:59:56 +00:00
usleep ( 1 ) ;
# endif
2003-02-07 19:23:19 +00:00
res = tone_zone_play_tone ( i - > subs [ SUB_REAL ] . zfd , - 1 ) ;
zt_set_hook ( i - > subs [ SUB_REAL ] . zfd , ZT_ONHOOK ) ;
2002-06-24 17:59:56 +00:00
break ;
2003-02-26 19:41:10 +00:00
case SIG_PRI :
zt_disable_ec ( i ) ;
res = tone_zone_play_tone ( i - > subs [ SUB_REAL ] . zfd , - 1 ) ;
break ;
2001-10-09 02:06:21 +00:00
default :
2003-02-07 19:23:19 +00:00
ast_log ( LOG_WARNING , " Don't know how to handle on hook with signalling %s on channel %d \n " , sig2str ( i - > sig ) , i - > channel ) ;
res = tone_zone_play_tone ( i - > subs [ SUB_REAL ] . zfd , - 1 ) ;
2001-10-09 02:06:21 +00:00
return - 1 ;
}
break ;
2004-09-19 16:17:18 +00:00
case ZT_EVENT_POLARITY :
switch ( i - > sig ) {
case SIG_FXSLS :
case SIG_FXSKS :
case SIG_FXSGS :
if ( i - > cid_start = = CID_START_POLARITY ) {
2005-02-08 07:49:40 +00:00
i - > polarity = POLARITY_REV ;
2004-09-19 16:17:18 +00:00
ast_verbose ( VERBOSE_PREFIX_2 " Starting post polarity "
" CID detection on channel %d \n " ,
i - > channel ) ;
chan = zt_new ( i , AST_STATE_PRERING , 0 , SUB_REAL , 0 , 0 ) ;
if ( chan & & ast_pthread_create ( & threadid , & attr , ss_thread , chan ) ) {
ast_log ( LOG_WARNING , " Unable to start simple switch thread on channel %d \n " , i - > channel ) ;
}
}
break ;
default :
ast_log ( LOG_WARNING , " handle_init_event detected "
" polarity reversal on non-FXO (SIG_FXS) "
" interface %d \n " , i - > channel ) ;
}
2001-10-09 02:06:21 +00:00
}
return 0 ;
}
static void * do_monitor ( void * data )
{
2004-06-29 01:43:55 +00:00
int count , res , res2 , spoint , pollres = 0 ;
2001-10-09 02:06:21 +00:00
struct zt_pvt * i ;
2003-02-07 19:23:19 +00:00
struct zt_pvt * last = NULL ;
time_t thispass = 0 , lastpass = 0 ;
int found ;
char buf [ 1024 ] ;
2004-04-25 22:37:09 +00:00
struct pollfd * pfds = NULL ;
int lastalloc = - 1 ;
2001-10-09 02:06:21 +00:00
/* This thread monitors all the frame relay interfaces which are not yet in use
( and thus do not have a separate thread ) indefinitely */
/* From here on out, we die whenever asked */
#if 0
if ( pthread_setcanceltype ( PTHREAD_CANCEL_ASYNCHRONOUS , NULL ) ) {
ast_log ( LOG_WARNING , " Unable to set cancel type to asynchronous \n " ) ;
return NULL ;
}
ast_log ( LOG_DEBUG , " Monitor starting... \n " ) ;
# endif
for ( ; ; ) {
/* Lock the interface list */
2003-08-13 15:25:16 +00:00
if ( ast_mutex_lock ( & iflock ) ) {
2001-10-09 02:06:21 +00:00
ast_log ( LOG_ERROR , " Unable to grab interface lock \n " ) ;
return NULL ;
}
2004-04-25 22:37:09 +00:00
if ( ! pfds | | ( lastalloc ! = ifcount ) ) {
if ( pfds )
free ( pfds ) ;
2004-05-12 23:35:50 +00:00
if ( ifcount ) {
pfds = malloc ( ifcount * sizeof ( struct pollfd ) ) ;
if ( ! pfds ) {
ast_log ( LOG_WARNING , " Critical memory error. Zap dies. \n " ) ;
ast_mutex_unlock ( & iflock ) ;
return NULL ;
}
2004-04-25 22:37:09 +00:00
}
lastalloc = ifcount ;
}
/* Build the stuff we're going to poll on, that is the socket of every
2001-10-09 02:06:21 +00:00
zt_pvt that does not have an associated owner channel */
2004-04-25 22:37:09 +00:00
count = 0 ;
2001-10-09 02:06:21 +00:00
i = iflist ;
while ( i ) {
2004-06-06 23:26:29 +00:00
if ( ( i - > subs [ SUB_REAL ] . zfd > - 1 ) & & i - > sig & & ( ! i - > radio ) ) {
2003-02-07 19:23:19 +00:00
if ( ! i - > owner & & ! i - > subs [ SUB_REAL ] . owner ) {
2002-06-24 17:59:56 +00:00
/* This needs to be watched, as it lacks an owner */
2004-04-25 22:37:09 +00:00
pfds [ count ] . fd = i - > subs [ SUB_REAL ] . zfd ;
pfds [ count ] . events = POLLPRI ;
2003-02-07 19:23:19 +00:00
/* Message waiting or r2 channels also get watched for reading */
# ifdef ZAPATA_R2
if ( i - > cidspill | | i - > r2 )
# else
if ( i - > cidspill )
# endif
2004-04-25 22:37:09 +00:00
pfds [ count ] . events | = POLLIN ;
count + + ;
2002-06-24 17:59:56 +00:00
}
2001-10-09 02:06:21 +00:00
}
i = i - > next ;
}
/* Okay, now that we know what to do, release the interface lock */
2003-08-13 15:25:16 +00:00
ast_mutex_unlock ( & iflock ) ;
2001-10-09 02:06:21 +00:00
pthread_testcancel ( ) ;
2003-02-07 19:23:19 +00:00
/* Wait at least a second for something to happen */
2004-04-25 22:37:09 +00:00
res = poll ( pfds , count , 1000 ) ;
2001-10-09 02:06:21 +00:00
pthread_testcancel ( ) ;
2004-04-25 22:37:09 +00:00
/* Okay, poll has finished. Let's see what happened. */
2001-10-09 02:06:21 +00:00
if ( res < 0 ) {
if ( ( errno ! = EAGAIN ) & & ( errno ! = EINTR ) )
2004-04-25 22:37:09 +00:00
ast_log ( LOG_WARNING , " poll return %d: %s \n " , res , strerror ( errno ) ) ;
2001-10-09 02:06:21 +00:00
continue ;
}
/* Alright, lock the interface list again, and let's look and see what has
happened */
2003-08-13 15:25:16 +00:00
if ( ast_mutex_lock ( & iflock ) ) {
2001-10-09 02:06:21 +00:00
ast_log ( LOG_WARNING , " Unable to lock the interface list \n " ) ;
continue ;
}
2003-02-07 19:23:19 +00:00
found = 0 ;
2004-04-25 22:37:09 +00:00
spoint = 0 ;
2003-02-07 19:23:19 +00:00
lastpass = thispass ;
thispass = time ( NULL ) ;
2001-10-09 02:06:21 +00:00
i = iflist ;
while ( i ) {
2003-02-07 19:23:19 +00:00
if ( thispass ! = lastpass ) {
if ( ! found & & ( ( i = = last ) | | ( ( i = = iflist ) & & ! last ) ) ) {
last = i ;
if ( last ) {
#if 0
printf ( " Checking channel %d \n " , last - > channel ) ;
# endif
2004-05-05 04:23:18 +00:00
if ( ! last - > cidspill & & ! last - > owner & & ! ast_strlen_zero ( last - > mailbox ) & & ( thispass - last - > onhooktime > 3 ) & &
2003-02-07 19:23:19 +00:00
( last - > sig & __ZT_SIG_FXO ) ) {
#if 0
printf ( " Channel %d has mailbox %s \n " , last - > channel , last - > mailbox ) ;
# endif
2004-10-03 21:18:27 +00:00
res = ast_app_has_voicemail ( last - > mailbox , NULL ) ;
2003-02-07 19:23:19 +00:00
if ( last - > msgstate ! = res ) {
int x ;
ast_log ( LOG_DEBUG , " Message status for %s changed from %d to %d on %d \n " , last - > mailbox , last - > msgstate , res , last - > channel ) ;
2003-08-15 04:38:39 +00:00
x = ZT_FLUSH_BOTH ;
2003-02-07 19:23:19 +00:00
res2 = ioctl ( last - > subs [ SUB_REAL ] . zfd , ZT_FLUSH , & x ) ;
if ( res2 )
ast_log ( LOG_WARNING , " Unable to flush input on channel %d \n " , last - > channel ) ;
2004-04-04 02:02:15 +00:00
last - > cidspill = malloc ( MAX_CALLERID_SIZE ) ;
2003-02-07 19:23:19 +00:00
if ( last - > cidspill ) {
2003-11-23 23:13:27 +00:00
/* Turn on on hook transfer for 4 seconds */
x = 4000 ;
ioctl ( last - > subs [ SUB_REAL ] . zfd , ZT_ONHOOKTRANSFER , & x ) ;
2003-02-07 19:23:19 +00:00
last - > cidlen = vmwi_generate ( last - > cidspill , res , 1 , AST_LAW ( last ) ) ;
last - > cidpos = 0 ;
#if 0
printf ( " Made %d bytes of message waiting for %d \n " , last - > cidlen , res ) ;
# endif
last - > msgstate = res ;
last - > onhooktime = thispass ;
}
found + + ;
}
}
last = last - > next ;
}
}
}
2004-08-21 21:41:54 +00:00
if ( ( i - > subs [ SUB_REAL ] . zfd > - 1 ) & & i - > sig ) {
if ( i - > radio & & ! i - > owner )
{
res = zt_get_event ( i - > subs [ SUB_REAL ] . zfd ) ;
if ( res )
{
if ( option_debug )
ast_log ( LOG_DEBUG , " Monitor doohicky got event %s on radio channel %d \n " , event2str ( res ) , i - > channel ) ;
/* Don't hold iflock while handling init events */
ast_mutex_unlock ( & iflock ) ;
handle_init_event ( i , res ) ;
ast_mutex_lock ( & iflock ) ;
}
i = i - > next ;
continue ;
}
2004-04-25 22:37:09 +00:00
pollres = ast_fdisset ( pfds , i - > subs [ SUB_REAL ] . zfd , count , & spoint ) ;
if ( pollres & POLLIN ) {
2003-02-07 19:23:19 +00:00
if ( i - > owner | | i - > subs [ SUB_REAL ] . owner ) {
2004-06-06 23:26:29 +00:00
# ifdef ZAPATA_PRI
if ( ! i - > pri )
# endif
ast_log ( LOG_WARNING , " Whoa.... I'm owned but found (%d) in read... \n " , i - > subs [ SUB_REAL ] . zfd ) ;
2003-02-07 19:23:19 +00:00
i = i - > next ;
continue ;
}
# ifdef ZAPATA_R2
if ( i - > r2 ) {
/* If it's R2 signalled, we always have to check for events */
mfcr2_event_t * e ;
e = mfcr2_check_event ( i - > r2 ) ;
if ( e )
handle_init_r2_event ( i , e ) ;
else {
e = mfcr2_schedule_run ( i - > r2 ) ;
if ( e )
handle_init_r2_event ( i , e ) ;
}
i = i - > next ;
continue ;
}
# endif
if ( ! i - > cidspill ) {
ast_log ( LOG_WARNING , " Whoa.... I'm reading but have no cidspill (%d)... \n " , i - > subs [ SUB_REAL ] . zfd ) ;
i = i - > next ;
continue ;
}
res = read ( i - > subs [ SUB_REAL ] . zfd , buf , sizeof ( buf ) ) ;
if ( res > 0 ) {
/* We read some number of bytes. Write an equal amount of data */
if ( res > i - > cidlen - i - > cidpos )
res = i - > cidlen - i - > cidpos ;
res2 = write ( i - > subs [ SUB_REAL ] . zfd , i - > cidspill + i - > cidpos , res ) ;
if ( res2 > 0 ) {
i - > cidpos + = res2 ;
if ( i - > cidpos > = i - > cidlen ) {
free ( i - > cidspill ) ;
i - > cidspill = 0 ;
i - > cidpos = 0 ;
i - > cidlen = 0 ;
}
} else {
ast_log ( LOG_WARNING , " Write failed: %s \n " , strerror ( errno ) ) ;
i - > msgstate = - 1 ;
}
} else {
ast_log ( LOG_WARNING , " Read failed with %d: %s \n " , res , strerror ( errno ) ) ;
}
if ( option_debug )
ast_log ( LOG_DEBUG , " Monitor doohicky got event %s on channel %d \n " , event2str ( res ) , i - > channel ) ;
2004-06-21 03:37:13 +00:00
/* Don't hold iflock while handling init events -- race with chlock */
ast_mutex_unlock ( & iflock ) ;
2003-02-07 19:23:19 +00:00
handle_init_event ( i , res ) ;
2004-06-21 03:37:13 +00:00
ast_mutex_lock ( & iflock ) ;
2003-02-07 19:23:19 +00:00
}
# ifdef ZAPATA_R2
2004-04-25 22:37:09 +00:00
if ( ( pollres & POLLPRI ) | | ( i - > r2 & & ! i - > sigchecked ) )
2003-02-07 19:23:19 +00:00
# else
2004-04-25 22:37:09 +00:00
if ( pollres & POLLPRI )
2003-02-07 19:23:19 +00:00
# endif
{
if ( i - > owner | | i - > subs [ SUB_REAL ] . owner ) {
2004-06-06 23:26:29 +00:00
# ifdef ZAPATA_PRI
if ( ! i - > pri )
# endif
ast_log ( LOG_WARNING , " Whoa.... I'm owned but found (%d)... \n " , i - > subs [ SUB_REAL ] . zfd ) ;
2002-06-24 17:59:56 +00:00
i = i - > next ;
continue ;
}
2003-02-07 19:23:19 +00:00
res = zt_get_event ( i - > subs [ SUB_REAL ] . zfd ) ;
2002-06-24 17:59:56 +00:00
if ( option_debug )
ast_log ( LOG_DEBUG , " Monitor doohicky got event %s on channel %d \n " , event2str ( res ) , i - > channel ) ;
2004-06-21 03:37:13 +00:00
/* Don't hold iflock while handling init events */
ast_mutex_unlock ( & iflock ) ;
2002-06-24 17:59:56 +00:00
handle_init_event ( i , res ) ;
2004-06-21 03:37:13 +00:00
ast_mutex_lock ( & iflock ) ;
2001-10-09 02:06:21 +00:00
}
}
i = i - > next ;
}
2003-08-13 15:25:16 +00:00
ast_mutex_unlock ( & iflock ) ;
2001-10-09 02:06:21 +00:00
}
/* Never reached */
return NULL ;
}
static int restart_monitor ( void )
{
pthread_attr_t attr ;
pthread_attr_init ( & attr ) ;
pthread_attr_setdetachstate ( & attr , PTHREAD_CREATE_DETACHED ) ;
/* If we're supposed to be stopped -- stay stopped */
2004-03-15 07:51:22 +00:00
if ( monitor_thread = = AST_PTHREADT_STOP )
2001-10-09 02:06:21 +00:00
return 0 ;
2003-08-13 15:25:16 +00:00
if ( ast_mutex_lock ( & monlock ) ) {
2001-10-09 02:06:21 +00:00
ast_log ( LOG_WARNING , " Unable to lock monitor \n " ) ;
return - 1 ;
}
if ( monitor_thread = = pthread_self ( ) ) {
2003-08-13 15:25:16 +00:00
ast_mutex_unlock ( & monlock ) ;
2001-10-09 02:06:21 +00:00
ast_log ( LOG_WARNING , " Cannot kill myself \n " ) ;
return - 1 ;
}
2004-03-15 09:14:16 +00:00
if ( monitor_thread ! = AST_PTHREADT_NULL ) {
2002-03-08 23:48:42 +00:00
/* Just signal it to be sure it wakes up */
#if 0
2001-10-09 02:06:21 +00:00
pthread_cancel ( monitor_thread ) ;
2002-03-08 23:48:42 +00:00
# endif
2001-10-09 02:06:21 +00:00
pthread_kill ( monitor_thread , SIGURG ) ;
2002-03-08 23:48:42 +00:00
#if 0
2001-10-09 02:06:21 +00:00
pthread_join ( monitor_thread , NULL ) ;
2002-03-08 23:48:42 +00:00
# endif
} else {
/* Start a new monitor */
2004-08-08 17:15:02 +00:00
if ( ast_pthread_create ( & monitor_thread , & attr , do_monitor , NULL ) < 0 ) {
2003-08-13 15:25:16 +00:00
ast_mutex_unlock ( & monlock ) ;
2002-03-08 23:48:42 +00:00
ast_log ( LOG_ERROR , " Unable to start monitor thread. \n " ) ;
return - 1 ;
}
2001-10-09 02:06:21 +00:00
}
#if 0
printf ( " Created thread %ld detached in restart monitor \n " , monitor_thread ) ;
# endif
2003-08-13 15:25:16 +00:00
ast_mutex_unlock ( & monlock ) ;
2001-10-09 02:06:21 +00:00
return 0 ;
}
2004-06-05 06:54:52 +00:00
# ifdef ZAPATA_PRI
static int pri_resolve_span ( int * span , int channel , int offset , struct zt_spaninfo * si )
{
int x ;
int trunkgroup ;
/* Get appropriate trunk group if there is one */
trunkgroup = pris [ * span ] . mastertrunkgroup ;
if ( trunkgroup ) {
/* Select a specific trunk group */
for ( x = 0 ; x < NUM_SPANS ; x + + ) {
if ( pris [ x ] . trunkgroup = = trunkgroup ) {
* span = x ;
return 0 ;
}
}
2005-04-13 23:33:47 +00:00
ast_log ( LOG_WARNING , " Channel %d on span %d configured to use nonexistent trunk group %d \n " , channel , * span , trunkgroup ) ;
2004-06-05 06:54:52 +00:00
* span = - 1 ;
} else {
if ( pris [ * span ] . trunkgroup ) {
ast_log ( LOG_WARNING , " Unable to use span %d implicitly since it is trunk group %d (please use spanmap) \n " , * span , pris [ * span ] . trunkgroup ) ;
* span = - 1 ;
} else if ( pris [ * span ] . mastertrunkgroup ) {
ast_log ( LOG_WARNING , " Unable to use span %d implicitly since it is already part of trunk group %d \n " , * span , pris [ * span ] . mastertrunkgroup ) ;
* span = - 1 ;
} else {
if ( si - > totalchans = = 31 ) { /* if it's an E1 */
2004-06-07 03:39:18 +00:00
pris [ * span ] . dchannels [ 0 ] = 16 + offset ;
2004-06-05 06:54:52 +00:00
} else {
2004-06-07 03:39:18 +00:00
pris [ * span ] . dchannels [ 0 ] = 24 + offset ;
2004-06-05 06:54:52 +00:00
}
2004-06-07 03:39:18 +00:00
pris [ * span ] . dchanavail [ 0 ] | = DCHAN_PROVISIONED ;
2004-06-05 06:54:52 +00:00
pris [ * span ] . offset = offset ;
pris [ * span ] . span = * span + 1 ;
}
}
return 0 ;
}
2004-06-07 03:39:18 +00:00
static int pri_create_trunkgroup ( int trunkgroup , int * channels )
2004-06-05 06:54:52 +00:00
{
struct zt_spaninfo si ;
ZT_PARAMS p ;
int fd ;
int span ;
2004-06-07 03:39:18 +00:00
int ospan = 0 ;
int x , y ;
2004-06-05 06:54:52 +00:00
for ( x = 0 ; x < NUM_SPANS ; x + + ) {
if ( pris [ x ] . trunkgroup = = trunkgroup ) {
2004-06-07 03:39:18 +00:00
ast_log ( LOG_WARNING , " Trunk group %d already exists on span %d, Primary d-channel %d \n " , trunkgroup , x + 1 , pris [ x ] . dchannels [ 0 ] ) ;
2004-06-05 06:54:52 +00:00
return - 1 ;
}
}
2004-06-07 03:39:18 +00:00
for ( y = 0 ; y < NUM_DCHANS ; y + + ) {
if ( ! channels [ y ] )
break ;
memset ( & si , 0 , sizeof ( si ) ) ;
memset ( & p , 0 , sizeof ( p ) ) ;
fd = open ( " /dev/zap/channel " , O_RDWR ) ;
if ( fd < 0 ) {
ast_log ( LOG_WARNING , " Failed to open channel: %s \n " , strerror ( errno ) ) ;
return - 1 ;
}
x = channels [ y ] ;
if ( ioctl ( fd , ZT_SPECIFY , & x ) ) {
ast_log ( LOG_WARNING , " Failed to specify channel %d: %s \n " , channels [ y ] , strerror ( errno ) ) ;
2004-10-23 22:00:40 +00:00
zt_close ( fd ) ;
2004-06-07 03:39:18 +00:00
return - 1 ;
}
if ( ioctl ( fd , ZT_GET_PARAMS , & p ) ) {
ast_log ( LOG_WARNING , " Failed to get channel parameters for channel %d: %s \n " , channels [ y ] , strerror ( errno ) ) ;
return - 1 ;
}
if ( ioctl ( fd , ZT_SPANSTAT , & si ) ) {
ast_log ( LOG_WARNING , " Failed go get span information on channel %d (span %d) \n " , channels [ y ] , p . spanno ) ;
2004-10-23 22:00:40 +00:00
zt_close ( fd ) ;
2004-06-07 03:39:18 +00:00
return - 1 ;
}
span = p . spanno - 1 ;
if ( pris [ span ] . trunkgroup ) {
ast_log ( LOG_WARNING , " Span %d is already provisioned for trunk group %d \n " , span + 1 , pris [ span ] . trunkgroup ) ;
2004-10-23 22:00:40 +00:00
zt_close ( fd ) ;
2004-06-07 03:39:18 +00:00
return - 1 ;
}
if ( pris [ span ] . pvts [ 0 ] ) {
ast_log ( LOG_WARNING , " Span %d is already provisioned with channels (implicit PRI maybe?) \n " , span + 1 ) ;
2004-10-23 22:00:40 +00:00
zt_close ( fd ) ;
2004-06-07 03:39:18 +00:00
return - 1 ;
}
if ( ! y ) {
pris [ span ] . trunkgroup = trunkgroup ;
pris [ span ] . offset = channels [ y ] - p . chanpos ;
ospan = span ;
}
pris [ ospan ] . dchannels [ y ] = channels [ y ] ;
pris [ ospan ] . dchanavail [ y ] | = DCHAN_PROVISIONED ;
pris [ span ] . span = span + 1 ;
2004-10-23 22:00:40 +00:00
zt_close ( fd ) ;
2004-06-05 06:54:52 +00:00
}
return 0 ;
}
static int pri_create_spanmap ( int span , int trunkgroup , int logicalspan )
{
if ( pris [ span ] . mastertrunkgroup ) {
ast_log ( LOG_WARNING , " Span %d is already part of trunk group %d, cannot add to trunk group %d \n " , span + 1 , pris [ span ] . mastertrunkgroup , trunkgroup ) ;
return - 1 ;
}
pris [ span ] . mastertrunkgroup = trunkgroup ;
2004-06-06 22:51:37 +00:00
pris [ span ] . prilogicalspan = logicalspan ;
2004-06-06 01:54:22 +00:00
return 0 ;
2004-06-05 06:54:52 +00:00
}
# endif
2001-10-09 02:06:21 +00:00
2004-10-16 22:34:57 +00:00
static struct zt_pvt * mkintf ( int channel , int signalling , int radio , struct zt_pri * pri , int reloading )
2001-10-09 02:06:21 +00:00
{
2004-06-06 01:54:22 +00:00
/* Make a zt_pvt structure for this interface (or CRV if "pri" is specified) */
2001-10-09 02:06:21 +00:00
struct zt_pvt * tmp = NULL , * tmp2 , * prev = NULL ;
char fn [ 80 ] ;
# if 1
struct zt_bufferinfo bi ;
2002-06-24 17:59:56 +00:00
# endif
2001-10-09 02:06:21 +00:00
struct zt_spaninfo si ;
int res ;
2002-06-24 17:59:56 +00:00
int span = 0 ;
2001-10-09 02:06:21 +00:00
int here = 0 ;
2003-02-07 19:23:19 +00:00
int x ;
2004-06-06 01:54:22 +00:00
struct zt_pvt * * wlist ;
struct zt_pvt * * wend ;
2001-10-09 02:06:21 +00:00
ZT_PARAMS p ;
2002-06-24 17:59:56 +00:00
2004-06-06 01:54:22 +00:00
wlist = & iflist ;
wend = & ifend ;
# ifdef ZAPATA_PRI
if ( pri ) {
wlist = & pri - > crvs ;
wend = & pri - > crvend ;
}
# endif
tmp2 = * wlist ;
2001-10-09 02:06:21 +00:00
prev = NULL ;
while ( tmp2 ) {
2004-12-11 00:02:08 +00:00
if ( ! tmp2 - > destroy ) {
if ( tmp2 - > channel = = channel ) {
tmp = tmp2 ;
here = 1 ;
break ;
}
if ( tmp2 - > channel > channel ) {
break ;
}
2001-10-09 02:06:21 +00:00
}
prev = tmp2 ;
tmp2 = tmp2 - > next ;
}
2004-10-16 22:34:57 +00:00
if ( ! here & & ! reloading ) {
2001-10-09 02:06:21 +00:00
tmp = ( struct zt_pvt * ) malloc ( sizeof ( struct zt_pvt ) ) ;
if ( ! tmp ) {
ast_log ( LOG_ERROR , " MALLOC FAILED \n " ) ;
2004-06-22 17:42:14 +00:00
destroy_zt_pvt ( & tmp ) ;
2001-10-09 02:06:21 +00:00
return NULL ;
}
memset ( tmp , 0 , sizeof ( struct zt_pvt ) ) ;
2004-06-22 17:42:14 +00:00
ast_mutex_init ( & tmp - > lock ) ;
2004-04-25 22:37:09 +00:00
ifcount + + ;
2003-02-07 19:23:19 +00:00
for ( x = 0 ; x < 3 ; x + + )
tmp - > subs [ x ] . zfd = - 1 ;
2003-11-07 16:55:13 +00:00
tmp - > channel = channel ;
2001-10-09 02:06:21 +00:00
}
if ( tmp ) {
2004-10-16 22:34:57 +00:00
if ( ! here ) {
if ( ( channel ! = CHAN_PSEUDO ) & & ! pri ) {
snprintf ( fn , sizeof ( fn ) , " %d " , channel ) ;
/* Open non-blocking */
if ( ! here )
tmp - > subs [ SUB_REAL ] . zfd = zt_open ( fn ) ;
/* Allocate a zapata structure */
if ( tmp - > subs [ SUB_REAL ] . zfd < 0 ) {
ast_log ( LOG_ERROR , " Unable to open channel %d: %s \n here = %d, tmp->channel = %d, channel = %d \n " , channel , strerror ( errno ) , here , tmp - > channel , channel ) ;
destroy_zt_pvt ( & tmp ) ;
return NULL ;
2001-10-09 02:06:21 +00:00
}
2004-10-16 22:34:57 +00:00
memset ( & p , 0 , sizeof ( p ) ) ;
res = ioctl ( tmp - > subs [ SUB_REAL ] . zfd , ZT_GET_PARAMS , & p ) ;
if ( res < 0 ) {
ast_log ( LOG_ERROR , " Unable to get parameters \n " ) ;
2004-06-22 17:42:14 +00:00
destroy_zt_pvt ( & tmp ) ;
2001-12-29 18:04:21 +00:00
return NULL ;
2004-06-06 22:51:37 +00:00
}
2004-10-16 22:34:57 +00:00
if ( p . sigtype ! = ( signalling & 0x3ffff ) ) {
2004-11-01 01:44:11 +00:00
ast_log ( LOG_ERROR , " Signalling requested on channel %d is %s but line is in %s signalling \n " , channel , sig2str ( signalling ) , sig2str ( p . sigtype ) ) ;
2004-06-22 17:42:14 +00:00
destroy_zt_pvt ( & tmp ) ;
2004-10-16 22:34:57 +00:00
return tmp ;
}
tmp - > law = p . curlaw ;
tmp - > span = p . spanno ;
span = p . spanno - 1 ;
} else {
if ( channel = = CHAN_PSEUDO )
signalling = 0 ;
else if ( ( signalling ! = SIG_FXOKS ) & & ( signalling ! = SIG_FXSKS ) ) {
ast_log ( LOG_ERROR , " CRV's must use FXO/FXS Kewl Start (fxo_ks/fxs_ks) signalling only. \n " ) ;
2004-06-06 22:22:48 +00:00
return NULL ;
}
2004-10-16 22:34:57 +00:00
}
# ifdef ZAPATA_PRI
if ( ( signalling = = SIG_PRI ) | | ( signalling = = SIG_GR303FXOKS ) | | ( signalling = = SIG_GR303FXSKS ) ) {
int offset ;
int myswitchtype ;
int matchesdchan ;
int x , y ;
offset = 0 ;
if ( ( signalling = = SIG_PRI ) & & ioctl ( tmp - > subs [ SUB_REAL ] . zfd , ZT_AUDIOMODE , & offset ) ) {
ast_log ( LOG_ERROR , " Unable to set clear mode on clear channel %d of span %d: %s \n " , channel , p . spanno , strerror ( errno ) ) ;
destroy_zt_pvt ( & tmp ) ;
return NULL ;
2004-06-07 03:39:18 +00:00
}
2004-10-16 22:34:57 +00:00
if ( span > = NUM_SPANS ) {
ast_log ( LOG_ERROR , " Channel %d does not lie on a span I know of (%d) \n " , channel , span ) ;
destroy_zt_pvt ( & tmp ) ;
return NULL ;
} else {
si . spanno = 0 ;
if ( ioctl ( tmp - > subs [ SUB_REAL ] . zfd , ZT_SPANSTAT , & si ) = = - 1 ) {
ast_log ( LOG_ERROR , " Unable to get span status: %s \n " , strerror ( errno ) ) ;
2004-06-22 17:42:14 +00:00
destroy_zt_pvt ( & tmp ) ;
2002-06-24 17:59:56 +00:00
return NULL ;
}
2004-10-16 22:34:57 +00:00
/* Store the logical span first based upon the real span */
tmp - > logicalspan = pris [ span ] . prilogicalspan ;
pri_resolve_span ( & span , channel , ( channel - p . chanpos ) , & si ) ;
if ( span < 0 ) {
ast_log ( LOG_WARNING , " Channel %d: Unable to find locate channel/trunk group! \n " , channel ) ;
2004-06-22 17:42:14 +00:00
destroy_zt_pvt ( & tmp ) ;
2002-06-24 17:59:56 +00:00
return NULL ;
}
2004-10-16 22:34:57 +00:00
if ( signalling = = SIG_PRI )
myswitchtype = switchtype ;
else
myswitchtype = PRI_SWITCH_GR303_TMC ;
/* Make sure this isn't a d-channel */
matchesdchan = 0 ;
for ( x = 0 ; x < NUM_SPANS ; x + + ) {
for ( y = 0 ; y < NUM_DCHANS ; y + + ) {
if ( pris [ x ] . dchannels [ y ] = = tmp - > channel ) {
matchesdchan = 1 ;
break ;
}
}
2002-06-24 17:59:56 +00:00
}
2004-10-16 22:34:57 +00:00
offset = p . chanpos ;
if ( ! matchesdchan ) {
if ( pris [ span ] . nodetype & & ( pris [ span ] . nodetype ! = pritype ) ) {
ast_log ( LOG_ERROR , " Span %d is already a %s node \n " , span + 1 , pri_node2str ( pris [ span ] . nodetype ) ) ;
destroy_zt_pvt ( & tmp ) ;
return NULL ;
}
if ( pris [ span ] . switchtype & & ( pris [ span ] . switchtype ! = myswitchtype ) ) {
ast_log ( LOG_ERROR , " Span %d is already a %s switch \n " , span + 1 , pri_switch2str ( pris [ span ] . switchtype ) ) ;
destroy_zt_pvt ( & tmp ) ;
return NULL ;
}
if ( ( pris [ span ] . dialplan ) & & ( pris [ span ] . dialplan ! = dialplan ) ) {
2005-03-03 17:00:57 +00:00
ast_log ( LOG_ERROR , " Span %d is already a %s dialing plan \n " , span + 1 , dialplan2str ( pris [ span ] . dialplan ) ) ;
2004-10-16 22:34:57 +00:00
destroy_zt_pvt ( & tmp ) ;
return NULL ;
}
if ( ! ast_strlen_zero ( pris [ span ] . idledial ) & & strcmp ( pris [ span ] . idledial , idledial ) ) {
ast_log ( LOG_ERROR , " Span %d already has idledial '%s'. \n " , span + 1 , idledial ) ;
destroy_zt_pvt ( & tmp ) ;
return NULL ;
}
if ( ! ast_strlen_zero ( pris [ span ] . idleext ) & & strcmp ( pris [ span ] . idleext , idleext ) ) {
ast_log ( LOG_ERROR , " Span %d already has idleext '%s'. \n " , span + 1 , idleext ) ;
destroy_zt_pvt ( & tmp ) ;
return NULL ;
}
if ( pris [ span ] . minunused & & ( pris [ span ] . minunused ! = minunused ) ) {
ast_log ( LOG_ERROR , " Span %d already has minunused of %d. \n " , span + 1 , minunused ) ;
destroy_zt_pvt ( & tmp ) ;
return NULL ;
}
if ( pris [ span ] . minidle & & ( pris [ span ] . minidle ! = minidle ) ) {
ast_log ( LOG_ERROR , " Span %d already has minidle of %d. \n " , span + 1 , minidle ) ;
destroy_zt_pvt ( & tmp ) ;
return NULL ;
}
if ( pris [ span ] . numchans > = MAX_CHANNELS ) {
ast_log ( LOG_ERROR , " Unable to add channel %d: Too many channels in trunk group %d! \n " , channel ,
pris [ span ] . trunkgroup ) ;
destroy_zt_pvt ( & tmp ) ;
return NULL ;
}
pris [ span ] . nodetype = pritype ;
pris [ span ] . switchtype = myswitchtype ;
pris [ span ] . nsf = nsf ;
pris [ span ] . dialplan = dialplan ;
pris [ span ] . localdialplan = localdialplan ;
pris [ span ] . pvts [ pris [ span ] . numchans + + ] = tmp ;
pris [ span ] . minunused = minunused ;
pris [ span ] . minidle = minidle ;
pris [ span ] . overlapdial = overlapdial ;
2005-05-12 15:05:25 +00:00
pris [ span ] . facilityenable = facilityenable ;
2005-05-15 23:26:45 +00:00
ast_copy_string ( pris [ span ] . idledial , idledial , sizeof ( pris [ span ] . idledial ) ) ;
ast_copy_string ( pris [ span ] . idleext , idleext , sizeof ( pris [ span ] . idleext ) ) ;
ast_copy_string ( pris [ span ] . internationalprefix , internationalprefix , sizeof ( pris [ span ] . internationalprefix ) ) ;
ast_copy_string ( pris [ span ] . nationalprefix , nationalprefix , sizeof ( pris [ span ] . nationalprefix ) ) ;
ast_copy_string ( pris [ span ] . localprefix , localprefix , sizeof ( pris [ span ] . localprefix ) ) ;
ast_copy_string ( pris [ span ] . privateprefix , privateprefix , sizeof ( pris [ span ] . privateprefix ) ) ;
ast_copy_string ( pris [ span ] . unknownprefix , unknownprefix , sizeof ( pris [ span ] . unknownprefix ) ) ;
2005-02-04 06:12:32 +00:00
pris [ span ] . resetinterval = resetinterval ;
2004-10-16 22:34:57 +00:00
tmp - > pri = & pris [ span ] ;
tmp - > prioffset = offset ;
tmp - > call = NULL ;
} else {
ast_log ( LOG_ERROR , " Channel %d is reserved for D-channel. \n " , offset ) ;
2004-06-22 17:42:14 +00:00
destroy_zt_pvt ( & tmp ) ;
2004-06-05 06:54:52 +00:00
return NULL ;
}
2001-10-09 02:06:21 +00:00
}
2004-10-16 22:34:57 +00:00
} else {
tmp - > prioffset = 0 ;
2001-10-09 02:06:21 +00:00
}
2003-02-07 19:23:19 +00:00
# endif
# ifdef ZAPATA_R2
2004-10-16 22:34:57 +00:00
if ( signalling = = SIG_R2 ) {
if ( r2prot < 0 ) {
ast_log ( LOG_WARNING , " R2 Country not specified for channel %d -- Assuming China \n " , tmp - > channel ) ;
tmp - > r2prot = MFCR2_PROT_CHINA ;
} else
tmp - > r2prot = r2prot ;
tmp - > r2 = mfcr2_new ( tmp - > subs [ SUB_REAL ] . zfd , tmp - > r2prot , 1 ) ;
if ( ! tmp - > r2 ) {
ast_log ( LOG_WARNING , " Unable to create r2 call :( \n " ) ;
zt_close ( tmp - > subs [ SUB_REAL ] . zfd ) ;
destroy_zt_pvt ( & tmp ) ;
return NULL ;
}
} else {
if ( tmp - > r2 )
mfcr2_free ( tmp - > r2 ) ;
tmp - > r2 = NULL ;
2003-02-07 19:23:19 +00:00
}
2004-10-16 22:34:57 +00:00
# endif
2003-02-07 19:23:19 +00:00
} else {
2004-10-16 22:34:57 +00:00
signalling = tmp - > sig ;
2005-04-27 23:44:24 +00:00
radio = tmp - > radio ;
2004-10-16 22:34:57 +00:00
memset ( & p , 0 , sizeof ( p ) ) ;
if ( tmp - > subs [ SUB_REAL ] . zfd > - 1 )
res = ioctl ( tmp - > subs [ SUB_REAL ] . zfd , ZT_GET_PARAMS , & p ) ;
2001-10-09 02:06:21 +00:00
}
/* Adjust starttime on loopstart and kewlstart trunks to reasonable values */
if ( ( signalling = = SIG_FXSKS ) | | ( signalling = = SIG_FXSLS ) | |
2004-04-16 18:00:00 +00:00
( signalling = = SIG_EM ) | | ( signalling = = SIG_EM_E1 ) | | ( signalling = = SIG_EMWINK ) | |
2005-04-22 19:10:35 +00:00
( signalling = = SIG_FEATD ) | | ( signalling = = SIG_FEATDMF ) | | ( signalling = = SIG_FEATDMF_TA ) | |
2004-01-16 23:40:37 +00:00
( signalling = = SIG_FEATB ) | | ( signalling = = SIG_E911 ) | |
2003-03-17 20:04:36 +00:00
( signalling = = SIG_SF ) | | ( signalling = = SIG_SFWINK ) | |
( signalling = = SIG_SF_FEATD ) | | ( signalling = = SIG_SF_FEATDMF ) | |
( signalling = = SIG_SF_FEATB ) ) {
2001-10-09 02:06:21 +00:00
p . starttime = 250 ;
2004-03-24 08:36:36 +00:00
} else if ( radio ) {
/* XXX Waiting to hear back from Jim if these should be adjustable XXX */
2003-02-07 19:23:19 +00:00
p . channo = channel ;
p . rxwinktime = 1 ;
p . rxflashtime = 1 ;
p . starttime = 1 ;
p . debouncetime = 5 ;
2004-03-24 08:36:36 +00:00
}
if ( ! radio ) {
p . channo = channel ;
/* Override timing settings based on config file */
if ( cur_prewink > = 0 )
p . prewinktime = cur_prewink ;
if ( cur_preflash > = 0 )
p . preflashtime = cur_preflash ;
if ( cur_wink > = 0 )
p . winktime = cur_wink ;
if ( cur_flash > = 0 )
p . flashtime = cur_flash ;
if ( cur_start > = 0 )
p . starttime = cur_start ;
if ( cur_rxwink > = 0 )
p . rxwinktime = cur_rxwink ;
if ( cur_rxflash > = 0 )
p . rxflashtime = cur_rxflash ;
if ( cur_debounce > = 0 )
p . debouncetime = cur_debounce ;
}
2005-07-19 13:30:37 +00:00
2004-06-06 01:54:22 +00:00
/* dont set parms on a pseudo-channel (or CRV) */
2004-05-31 16:04:10 +00:00
if ( tmp - > subs [ SUB_REAL ] . zfd > = 0 )
{
res = ioctl ( tmp - > subs [ SUB_REAL ] . zfd , ZT_SET_PARAMS , & p ) ;
if ( res < 0 ) {
ast_log ( LOG_ERROR , " Unable to set parameters \n " ) ;
2004-06-22 17:42:14 +00:00
destroy_zt_pvt ( & tmp ) ;
2004-05-31 16:04:10 +00:00
return NULL ;
}
2001-10-09 02:06:21 +00:00
}
# if 1
2003-02-07 19:23:19 +00:00
if ( ! here & & ( tmp - > subs [ SUB_REAL ] . zfd > - 1 ) ) {
memset ( & bi , 0 , sizeof ( bi ) ) ;
res = ioctl ( tmp - > subs [ SUB_REAL ] . zfd , ZT_GET_BUFINFO , & bi ) ;
2001-10-09 02:06:21 +00:00
if ( ! res ) {
bi . txbufpolicy = ZT_POLICY_IMMEDIATE ;
bi . rxbufpolicy = ZT_POLICY_IMMEDIATE ;
2003-10-24 18:22:45 +00:00
bi . numbufs = numbufs ;
2003-02-07 19:23:19 +00:00
res = ioctl ( tmp - > subs [ SUB_REAL ] . zfd , ZT_SET_BUFINFO , & bi ) ;
2001-10-09 02:06:21 +00:00
if ( res < 0 ) {
ast_log ( LOG_WARNING , " Unable to set buffer policy on channel %d \n " , channel ) ;
}
} else
ast_log ( LOG_WARNING , " Unable to check buffer policy on channel %d \n " , channel ) ;
}
# endif
tmp - > immediate = immediate ;
2005-06-23 14:51:52 +00:00
tmp - > transfertobusy = transfertobusy ;
2001-10-09 02:06:21 +00:00
tmp - > sig = signalling ;
2003-02-07 19:23:19 +00:00
tmp - > radio = radio ;
tmp - > firstradio = 0 ;
2001-10-09 02:06:21 +00:00
if ( ( signalling = = SIG_FXOKS ) | | ( signalling = = SIG_FXOLS ) | | ( signalling = = SIG_FXOGS ) )
tmp - > permcallwaiting = callwaiting ;
else
tmp - > permcallwaiting = 0 ;
/* Flag to destroy the channel must be cleared on new mkif. Part of changes for reload to work */
tmp - > destroy = 0 ;
2004-01-12 04:28:00 +00:00
tmp - > drings = drings ;
2004-03-10 08:33:07 +00:00
tmp - > usedistinctiveringdetection = usedistinctiveringdetection ;
2001-10-09 02:06:21 +00:00
tmp - > callwaitingcallerid = callwaitingcallerid ;
tmp - > threewaycalling = threewaycalling ;
2001-12-29 18:04:21 +00:00
tmp - > adsi = adsi ;
2001-10-09 02:06:21 +00:00
tmp - > permhidecallerid = hidecallerid ;
2003-02-07 19:23:19 +00:00
tmp - > callreturn = callreturn ;
2001-10-09 02:06:21 +00:00
tmp - > echocancel = echocancel ;
2003-10-27 17:16:08 +00:00
tmp - > echotraining = echotraining ;
2004-09-13 23:07:50 +00:00
tmp - > pulse = pulse ;
2002-09-10 04:45:51 +00:00
tmp - > echocanbridged = echocanbridged ;
2003-02-07 19:23:19 +00:00
tmp - > busydetect = busydetect ;
2003-03-06 06:00:17 +00:00
tmp - > busycount = busycount ;
2005-08-08 00:08:48 +00:00
tmp - > busy_tonelength = busy_tonelength ;
tmp - > busy_quietlength = busy_quietlength ;
2003-02-07 19:23:19 +00:00
tmp - > callprogress = callprogress ;
2002-03-08 23:48:42 +00:00
tmp - > cancallforward = cancallforward ;
2003-02-07 19:23:19 +00:00
tmp - > dtmfrelax = relaxdtmf ;
2001-10-09 02:06:21 +00:00
tmp - > callwaiting = tmp - > permcallwaiting ;
tmp - > hidecallerid = tmp - > permhidecallerid ;
tmp - > channel = channel ;
tmp - > stripmsd = stripmsd ;
tmp - > use_callerid = use_callerid ;
2004-09-19 16:17:18 +00:00
tmp - > cid_signalling = cid_signalling ;
tmp - > cid_start = cid_start ;
2003-12-18 16:01:08 +00:00
tmp - > zaptrcallerid = zaptrcallerid ;
2003-09-05 04:00:57 +00:00
tmp - > restrictcid = restrictcid ;
2003-10-01 15:59:26 +00:00
tmp - > use_callingpres = use_callingpres ;
2004-08-31 13:47:23 +00:00
tmp - > priindication_oob = priindication_oob ;
2004-12-15 19:59:53 +00:00
tmp - > emdigitwait = cur_emdigitwait ;
2004-09-07 01:56:18 +00:00
if ( tmp - > usedistinctiveringdetection ) {
if ( ! tmp - > use_callerid ) {
ast_log ( LOG_NOTICE , " Distinctive Ring detect requires 'usecallerid' be on \n " ) ;
tmp - > use_callerid = 1 ;
}
}
2004-08-31 13:47:23 +00:00
2005-05-15 23:26:45 +00:00
ast_copy_string ( tmp - > accountcode , accountcode , sizeof ( tmp - > accountcode ) ) ;
2001-12-29 18:04:21 +00:00
tmp - > amaflags = amaflags ;
2001-10-09 02:06:21 +00:00
if ( ! here ) {
tmp - > confno = - 1 ;
2003-02-07 19:23:19 +00:00
tmp - > propconfno = - 1 ;
2001-10-09 02:06:21 +00:00
}
2004-12-09 22:39:14 +00:00
tmp - > canpark = canpark ;
2001-10-09 02:06:21 +00:00
tmp - > transfer = transfer ;
2005-05-15 23:26:45 +00:00
ast_copy_string ( tmp - > defcontext , context , sizeof ( tmp - > defcontext ) ) ;
ast_copy_string ( tmp - > language , language , sizeof ( tmp - > language ) ) ;
ast_copy_string ( tmp - > musicclass , musicclass , sizeof ( tmp - > musicclass ) ) ;
ast_copy_string ( tmp - > context , context , sizeof ( tmp - > context ) ) ;
ast_copy_string ( tmp - > cid_num , cid_num , sizeof ( tmp - > cid_num ) ) ;
2005-02-04 06:12:32 +00:00
tmp - > cid_ton = 0 ;
2005-05-15 23:26:45 +00:00
ast_copy_string ( tmp - > cid_name , cid_name , sizeof ( tmp - > cid_name ) ) ;
ast_copy_string ( tmp - > mailbox , mailbox , sizeof ( tmp - > mailbox ) ) ;
2003-02-07 19:23:19 +00:00
tmp - > msgstate = - 1 ;
2001-10-09 02:06:21 +00:00
tmp - > group = cur_group ;
tmp - > callgroup = cur_callergroup ;
tmp - > pickupgroup = cur_pickupgroup ;
tmp - > rxgain = rxgain ;
tmp - > txgain = txgain ;
2004-02-15 07:35:32 +00:00
tmp - > tonezone = tonezone ;
2003-02-07 19:23:19 +00:00
tmp - > onhooktime = time ( NULL ) ;
if ( tmp - > subs [ SUB_REAL ] . zfd > - 1 ) {
set_actual_gain ( tmp - > subs [ SUB_REAL ] . zfd , 0 , tmp - > rxgain , tmp - > txgain , tmp - > law ) ;
if ( tmp - > dsp )
ast_dsp_digitmode ( tmp - > dsp , DSP_DIGITMODE_DTMF | tmp - > dtmfrelax ) ;
update_conf ( tmp ) ;
2002-06-24 17:59:56 +00:00
if ( ! here ) {
2003-02-07 19:23:19 +00:00
if ( ( signalling ! = SIG_PRI ) & & ( signalling ! = SIG_R2 ) )
2002-06-24 17:59:56 +00:00
/* Hang it up to be sure it's good */
2003-02-07 19:23:19 +00:00
zt_set_hook ( tmp - > subs [ SUB_REAL ] . zfd , ZT_ONHOOK ) ;
2002-06-24 17:59:56 +00:00
}
2004-02-15 07:35:32 +00:00
ioctl ( tmp - > subs [ SUB_REAL ] . zfd , ZT_SETTONEZONE , & tmp - > tonezone ) ;
2003-08-26 02:38:24 +00:00
# ifdef ZAPATA_PRI
2003-08-25 20:39:07 +00:00
/* the dchannel is down so put the channel in alarm */
2004-06-07 03:39:18 +00:00
if ( tmp - > pri & & ! pri_is_up ( tmp - > pri ) )
2003-08-25 20:39:07 +00:00
tmp - > inalarm = 1 ;
else
tmp - > inalarm = 0 ;
2003-08-26 02:38:24 +00:00
# endif
2003-02-07 19:23:19 +00:00
memset ( & si , 0 , sizeof ( si ) ) ;
if ( ioctl ( tmp - > subs [ SUB_REAL ] . zfd , ZT_SPANSTAT , & si ) = = - 1 ) {
2002-06-24 17:59:56 +00:00
ast_log ( LOG_ERROR , " Unable to get span status: %s \n " , strerror ( errno ) ) ;
2004-06-22 17:42:14 +00:00
destroy_zt_pvt ( & tmp ) ;
2002-06-24 17:59:56 +00:00
return NULL ;
}
if ( si . alarms ) tmp - > inalarm = 1 ;
2001-10-09 02:06:21 +00:00
}
2004-06-23 01:27:44 +00:00
2004-11-17 06:18:33 +00:00
tmp - > polarityonanswerdelay = polarityonanswerdelay ;
2005-02-08 07:49:40 +00:00
tmp - > answeronpolarityswitch = answeronpolarityswitch ;
2004-11-17 06:18:33 +00:00
tmp - > hanguponpolarityswitch = hanguponpolarityswitch ;
2004-12-28 21:32:25 +00:00
tmp - > sendcalleridafter = sendcalleridafter ;
2004-11-17 06:18:33 +00:00
2004-06-23 01:27:44 +00:00
}
if ( tmp & & ! here ) {
/* nothing on the iflist */
if ( ! * wlist ) {
* wlist = tmp ;
tmp - > prev = NULL ;
tmp - > next = NULL ;
* wend = tmp ;
} else {
/* at least one member on the iflist */
struct zt_pvt * working = * wlist ;
/* check if we maybe have to put it on the begining */
if ( working - > channel > tmp - > channel ) {
tmp - > next = * wlist ;
tmp - > prev = NULL ;
2004-10-06 23:45:26 +00:00
( * wlist ) - > prev = tmp ;
2004-06-23 01:27:44 +00:00
* wlist = tmp ;
} else {
/* go through all the members and put the member in the right place */
while ( working ) {
/* in the middle */
if ( working - > next ) {
if ( working - > channel < tmp - > channel & & working - > next - > channel > tmp - > channel ) {
tmp - > next = working - > next ;
tmp - > prev = working ;
working - > next - > prev = tmp ;
working - > next = tmp ;
break ;
}
} else {
/* the last */
if ( working - > channel < tmp - > channel ) {
working - > next = tmp ;
tmp - > next = NULL ;
tmp - > prev = working ;
* wend = tmp ;
break ;
}
}
working = working - > next ;
}
}
}
2001-10-09 02:06:21 +00:00
}
return tmp ;
}
2004-06-23 03:16:58 +00:00
static inline int available ( struct zt_pvt * p , int channelmatch , int groupmatch , int * busy )
2001-10-09 02:06:21 +00:00
{
2001-12-29 18:04:21 +00:00
int res ;
ZT_PARAMS par ;
2001-10-09 02:06:21 +00:00
/* First, check group matching */
if ( ( p - > group & groupmatch ) ! = groupmatch )
return 0 ;
/* Check to see if we have a channel match */
if ( ( channelmatch > 0 ) & & ( p - > channel ! = channelmatch ) )
return 0 ;
2004-06-23 03:16:58 +00:00
/* We're at least busy at this point */
if ( ( p - > sig = = SIG_FXOKS ) | | ( p - > sig = = SIG_FXOLS ) | | ( p - > sig = = SIG_FXOGS ) ) {
if ( busy )
* busy = 1 ;
}
2002-09-10 04:45:51 +00:00
/* If do not distrub, definitely not */
if ( p - > dnd )
2004-05-15 22:50:51 +00:00
return 0 ;
/* If guard time, definitely not */
2004-08-23 17:37:24 +00:00
if ( p - > guardtime & & ( time ( NULL ) < p - > guardtime ) )
2004-05-15 22:50:51 +00:00
return 0 ;
2001-10-09 02:06:21 +00:00
/* If no owner definitely available */
2001-12-29 18:04:21 +00:00
if ( ! p - > owner ) {
/* Trust PRI */
# ifdef ZAPATA_PRI
2002-06-24 17:59:56 +00:00
if ( p - > pri ) {
if ( p - > resetting | | p - > call )
return 0 ;
else
return 1 ;
}
2003-02-07 19:23:19 +00:00
# endif
# ifdef ZAPATA_R2
/* Trust R2 as well */
if ( p - > r2 ) {
if ( p - > hasr2call | | p - > r2blocked )
return 0 ;
else
return 1 ;
}
2001-12-29 18:04:21 +00:00
# endif
2003-02-07 19:23:19 +00:00
if ( ! p - > radio )
{
2004-09-02 20:45:24 +00:00
if ( ! p - > sig | | ( p - > sig = = SIG_FXSLS ) )
return 1 ;
2003-02-07 19:23:19 +00:00
/* Check hook state */
2004-06-06 01:54:22 +00:00
if ( p - > subs [ SUB_REAL ] . zfd > - 1 )
res = ioctl ( p - > subs [ SUB_REAL ] . zfd , ZT_GET_PARAMS , & par ) ;
else {
/* Assume not off hook on CVRS */
res = 0 ;
par . rxisoffhook = 0 ;
}
2003-02-07 19:23:19 +00:00
if ( res ) {
ast_log ( LOG_WARNING , " Unable to check hook state on channel %d \n " , p - > channel ) ;
2004-09-02 20:45:24 +00:00
} else if ( ( p - > sig = = SIG_FXSKS ) | | ( p - > sig = = SIG_FXSGS ) ) {
2004-09-02 19:07:24 +00:00
/* When "onhook" that means no battery on the line, and thus
2004-09-02 20:45:24 +00:00
it is out of service . . . , if it ' s on a TDM card . . . If it ' s a channel
bank , there is no telling . . . */
if ( par . rxbits > - 1 )
return 1 ;
2004-09-02 19:07:24 +00:00
if ( par . rxisoffhook )
return 1 ;
else
2004-09-04 15:00:05 +00:00
# ifdef ZAP_CHECK_HOOKSTATE
2004-09-02 19:07:24 +00:00
return 0 ;
2004-09-04 15:00:05 +00:00
# else
return 1 ;
# endif
2003-02-07 19:23:19 +00:00
} else if ( par . rxisoffhook ) {
ast_log ( LOG_DEBUG , " Channel %d off hook, can't use \n " , p - > channel ) ;
/* Not available when the other end is off hook */
return 0 ;
}
2001-12-29 18:04:21 +00:00
}
2001-10-09 02:06:21 +00:00
return 1 ;
2001-12-29 18:04:21 +00:00
}
2001-10-09 02:06:21 +00:00
/* If it's not an FXO, forget about call wait */
if ( ( p - > sig ! = SIG_FXOKS ) & & ( p - > sig ! = SIG_FXOLS ) & & ( p - > sig ! = SIG_FXOGS ) )
return 0 ;
if ( ! p - > callwaiting ) {
/* If they don't have call waiting enabled, then for sure they're unavailable at this point */
return 0 ;
}
2003-02-07 19:23:19 +00:00
if ( p - > subs [ SUB_CALLWAIT ] . zfd > - 1 ) {
2001-10-09 02:06:21 +00:00
/* If there is already a call waiting call, then we can't take a second one */
return 0 ;
}
2002-09-10 04:45:51 +00:00
if ( ( p - > owner - > _state ! = AST_STATE_UP ) & &
( p - > owner - > _state ! = AST_STATE_RINGING ) ) {
2001-10-09 02:06:21 +00:00
/* If the current call is not up, then don't allow the call */
return 0 ;
}
2003-02-07 19:23:19 +00:00
if ( ( p - > subs [ SUB_THREEWAY ] . owner ) & & ( ! p - > subs [ SUB_THREEWAY ] . inthreeway ) ) {
2001-10-09 02:06:21 +00:00
/* Can't take a call wait when the three way calling hasn't been merged yet. */
return 0 ;
}
/* We're cool */
return 1 ;
}
2002-06-24 17:59:56 +00:00
static struct zt_pvt * chandup ( struct zt_pvt * src )
{
struct zt_pvt * p ;
ZT_BUFFERINFO bi ;
int res ;
p = malloc ( sizeof ( struct zt_pvt ) ) ;
if ( p ) {
memcpy ( p , src , sizeof ( struct zt_pvt ) ) ;
2004-06-22 17:42:14 +00:00
ast_mutex_init ( & p - > lock ) ;
2003-02-07 19:23:19 +00:00
p - > subs [ SUB_REAL ] . zfd = zt_open ( " /dev/zap/pseudo " ) ;
2002-06-24 17:59:56 +00:00
/* Allocate a zapata structure */
2003-02-07 19:23:19 +00:00
if ( p - > subs [ SUB_REAL ] . zfd < 0 ) {
2002-06-24 17:59:56 +00:00
ast_log ( LOG_ERROR , " Unable to dup channel: %s \n " , strerror ( errno ) ) ;
2004-06-22 17:42:14 +00:00
destroy_zt_pvt ( & p ) ;
2002-06-24 17:59:56 +00:00
return NULL ;
}
2003-02-07 19:23:19 +00:00
res = ioctl ( p - > subs [ SUB_REAL ] . zfd , ZT_GET_BUFINFO , & bi ) ;
2002-06-24 17:59:56 +00:00
if ( ! res ) {
bi . txbufpolicy = ZT_POLICY_IMMEDIATE ;
bi . rxbufpolicy = ZT_POLICY_IMMEDIATE ;
2003-10-24 18:22:45 +00:00
bi . numbufs = numbufs ;
2003-02-07 19:23:19 +00:00
res = ioctl ( p - > subs [ SUB_REAL ] . zfd , ZT_SET_BUFINFO , & bi ) ;
2002-06-24 17:59:56 +00:00
if ( res < 0 ) {
ast_log ( LOG_WARNING , " Unable to set buffer policy on dup channel \n " ) ;
}
} else
ast_log ( LOG_WARNING , " Unable to check buffer policy on dup channel \n " ) ;
}
p - > destroy = 1 ;
p - > next = iflist ;
iflist = p ;
return p ;
}
2004-06-06 23:26:29 +00:00
# ifdef ZAPATA_PRI
static int pri_find_empty_chan ( struct zt_pri * pri , int backwards )
{
int x ;
if ( backwards )
x = pri - > numchans ;
else
x = 0 ;
for ( ; ; ) {
if ( backwards & & ( x < 0 ) )
break ;
if ( ! backwards & & ( x > = pri - > numchans ) )
break ;
if ( pri - > pvts [ x ] & & ! pri - > pvts [ x ] - > inalarm & & ! pri - > pvts [ x ] - > owner ) {
ast_log ( LOG_DEBUG , " Found empty available channel %d/%d \n " ,
pri - > pvts [ x ] - > logicalspan , pri - > pvts [ x ] - > prioffset ) ;
return x ;
}
if ( backwards )
x - - ;
else
x + + ;
}
return - 1 ;
}
# endif
2004-10-26 22:25:43 +00:00
static struct ast_channel * zt_request ( const char * type , int format , void * data , int * cause )
2001-10-09 02:06:21 +00:00
{
int oldformat ;
int groupmatch = 0 ;
int channelmatch = - 1 ;
2003-11-18 18:09:29 +00:00
int roundrobin = 0 ;
2003-02-07 19:23:19 +00:00
int callwait = 0 ;
2004-06-23 03:16:58 +00:00
int busy = 0 ;
2001-10-09 02:06:21 +00:00
struct zt_pvt * p ;
struct ast_channel * tmp = NULL ;
char * dest = NULL ;
int x ;
char * s ;
2003-02-07 19:23:19 +00:00
char opt = 0 ;
int res = 0 , y = 0 ;
2003-08-07 03:48:00 +00:00
int backwards = 0 ;
2004-06-06 01:54:22 +00:00
# ifdef ZAPATA_PRI
int crv ;
int bearer = - 1 ;
int trunkgroup ;
struct zt_pri * pri = NULL ;
# endif
2004-07-29 02:07:03 +00:00
struct zt_pvt * exit , * start , * end ;
2004-06-06 01:54:22 +00:00
ast_mutex_t * lock ;
2001-10-09 02:06:21 +00:00
2004-06-06 01:54:22 +00:00
/* Assume we're locking the iflock */
lock = & iflock ;
2004-07-29 02:07:03 +00:00
start = iflist ;
end = ifend ;
2001-10-09 02:06:21 +00:00
/* We do signed linear */
oldformat = format ;
format & = ( AST_FORMAT_SLINEAR | AST_FORMAT_ULAW ) ;
if ( ! format ) {
ast_log ( LOG_NOTICE , " Asked to get a channel of unsupported format '%d' \n " , oldformat ) ;
return NULL ;
}
if ( data ) {
2003-09-29 20:13:54 +00:00
dest = ast_strdupa ( ( char * ) data ) ;
2001-10-09 02:06:21 +00:00
} else {
ast_log ( LOG_WARNING , " Channel requested with no data \n " ) ;
return NULL ;
}
2003-11-07 16:55:13 +00:00
if ( toupper ( dest [ 0 ] ) = = ' G ' | | toupper ( dest [ 0 ] ) = = ' R ' ) {
2001-10-09 02:06:21 +00:00
/* Retrieve the group number */
2003-02-07 19:23:19 +00:00
char * stringp = NULL ;
stringp = dest + 1 ;
s = strsep ( & stringp , " / " ) ;
if ( ( res = sscanf ( s , " %d%c%d " , & x , & opt , & y ) ) < 1 ) {
2001-10-09 02:06:21 +00:00
ast_log ( LOG_WARNING , " Unable to determine group for data %s \n " , ( char * ) data ) ;
return NULL ;
}
groupmatch = 1 < < x ;
2003-11-07 16:55:13 +00:00
if ( toupper ( dest [ 0 ] ) = = ' G ' ) {
if ( dest [ 0 ] = = ' G ' ) {
backwards = 1 ;
p = ifend ;
} else
p = iflist ;
} else {
if ( dest [ 0 ] = = ' R ' ) {
backwards = 1 ;
p = round_robin [ x ] ? round_robin [ x ] - > prev : ifend ;
if ( ! p )
p = ifend ;
} else {
p = round_robin [ x ] ? round_robin [ x ] - > next : iflist ;
if ( ! p )
p = iflist ;
}
2003-11-18 18:09:29 +00:00
roundrobin = 1 ;
2003-11-07 16:55:13 +00:00
}
2001-10-09 02:06:21 +00:00
} else {
2003-02-07 19:23:19 +00:00
char * stringp = NULL ;
stringp = dest ;
s = strsep ( & stringp , " / " ) ;
2004-06-06 20:47:51 +00:00
p = iflist ;
2002-06-24 17:59:56 +00:00
if ( ! strcasecmp ( s , " pseudo " ) ) {
/* Special case for pseudo */
x = CHAN_PSEUDO ;
2004-06-06 20:47:51 +00:00
channelmatch = x ;
2004-06-06 08:52:24 +00:00
}
# ifdef ZAPATA_PRI
else if ( ( res = sscanf ( s , " %d:%d%c%d " , & trunkgroup , & crv , & opt , & y ) ) > 1 ) {
if ( ( trunkgroup < 1 ) | | ( crv < 1 ) ) {
ast_log ( LOG_WARNING , " Unable to determine trunk group and CRV for data %s \n " , ( char * ) data ) ;
return NULL ;
}
res - - ;
for ( x = 0 ; x < NUM_SPANS ; x + + ) {
if ( pris [ x ] . trunkgroup = = trunkgroup ) {
pri = pris + x ;
lock = & pri - > lock ;
2004-07-29 02:07:03 +00:00
start = pri - > crvs ;
end = pri - > crvend ;
2004-06-06 08:52:24 +00:00
break ;
}
}
if ( ! pri ) {
ast_log ( LOG_WARNING , " Unable to find trunk group %d \n " , trunkgroup ) ;
return NULL ;
}
channelmatch = crv ;
p = pris [ x ] . crvs ;
}
# endif
else if ( ( res = sscanf ( s , " %d%c%d " , & x , & opt , & y ) ) < 1 ) {
2001-10-09 02:06:21 +00:00
ast_log ( LOG_WARNING , " Unable to determine channel for data %s \n " , ( char * ) data ) ;
return NULL ;
2004-06-06 20:47:51 +00:00
} else {
channelmatch = x ;
2001-10-09 02:06:21 +00:00
}
}
/* Search for an unowned channel */
2004-06-06 01:54:22 +00:00
if ( ast_mutex_lock ( lock ) ) {
2001-10-09 02:06:21 +00:00
ast_log ( LOG_ERROR , " Unable to lock interface list??? \n " ) ;
return NULL ;
}
2003-11-07 16:55:13 +00:00
exit = p ;
2001-10-09 02:06:21 +00:00
while ( p & & ! tmp ) {
2003-11-18 18:09:29 +00:00
if ( roundrobin )
round_robin [ x ] = p ;
2003-11-07 16:55:13 +00:00
#if 0
2004-08-23 17:37:24 +00:00
ast_verbose ( " name = %s, %d, %d, %d \n " , p - > owner ? p - > owner - > name : " <none> " , p - > channel , channelmatch , groupmatch ) ;
2003-11-07 16:55:13 +00:00
# endif
2004-06-23 03:16:58 +00:00
if ( p & & available ( p , channelmatch , groupmatch , & busy ) ) {
2001-10-09 02:06:21 +00:00
if ( option_debug )
ast_log ( LOG_DEBUG , " Using channel %d \n " , p - > channel ) ;
2004-08-21 21:41:54 +00:00
if ( p - > inalarm )
2003-11-07 16:55:13 +00:00
goto next ;
2001-10-09 02:06:21 +00:00
callwait = ( p - > owner ! = NULL ) ;
2004-06-06 01:54:22 +00:00
# ifdef ZAPATA_PRI
if ( pri & & ( p - > subs [ SUB_REAL ] . zfd < 0 ) ) {
2004-07-19 02:18:11 +00:00
if ( p - > sig ! = SIG_FXSKS ) {
/* Gotta find an actual channel to use for this
CRV if this isn ' t a callwait */
bearer = pri_find_empty_chan ( pri , 0 ) ;
if ( bearer < 0 ) {
ast_log ( LOG_NOTICE , " Out of bearer channels on span %d for call to CRV %d:%d \n " , pri - > span , trunkgroup , crv ) ;
p = NULL ;
break ;
}
pri_assign_bearer ( p , pri , pri - > pvts [ bearer ] ) ;
} else {
if ( alloc_sub ( p , 0 ) ) {
ast_log ( LOG_NOTICE , " Failed to allocate place holder pseudo channel! \n " ) ;
p = NULL ;
break ;
} else
ast_log ( LOG_DEBUG , " Allocated placeholder pseudo channel \n " ) ;
p - > pri = pri ;
2004-06-06 01:54:22 +00:00
}
}
# endif
2002-06-24 17:59:56 +00:00
if ( p - > channel = = CHAN_PSEUDO ) {
p = chandup ( p ) ;
if ( ! p ) {
break ;
}
}
2003-02-07 19:23:19 +00:00
if ( p - > owner ) {
if ( alloc_sub ( p , SUB_CALLWAIT ) ) {
p = NULL ;
break ;
}
}
2003-04-11 03:47:19 +00:00
p - > outgoing = 1 ;
2003-11-21 18:38:42 +00:00
tmp = zt_new ( p , AST_STATE_RESERVED , 0 , p - > owner ? SUB_CALLWAIT : SUB_REAL , 0 , 0 ) ;
2004-06-06 01:54:22 +00:00
# ifdef ZAPATA_PRI
if ( p - > bearer ) {
/* Log owner to bearer channel, too */
p - > bearer - > owner = tmp ;
}
# endif
2002-06-24 17:59:56 +00:00
/* Make special notes */
if ( res > 1 ) {
if ( opt = = ' c ' ) {
/* Confirm answer */
p - > confirmanswer = 1 ;
} else if ( opt = = ' r ' ) {
/* Distinctive ring */
if ( res < 3 )
ast_log ( LOG_WARNING , " Distinctive ring missing identifier in '%s' \n " , ( char * ) data ) ;
else
p - > distinctivering = y ;
2003-02-07 19:23:19 +00:00
} else if ( opt = = ' d ' ) {
/* If this is an ISDN call, make it digital */
p - > digital = 1 ;
2005-06-02 17:16:49 +00:00
if ( tmp )
tmp - > transfercapability = AST_TRANS_CAP_DIGITAL ;
2002-06-24 17:59:56 +00:00
} else {
ast_log ( LOG_WARNING , " Unknown option '%c' in '%s' \n " , opt , ( char * ) data ) ;
}
}
2001-10-09 02:06:21 +00:00
/* Note if the call is a call waiting call */
2004-06-06 01:54:22 +00:00
if ( tmp & & callwait )
2001-10-09 02:06:21 +00:00
tmp - > cdrflags | = AST_CDR_CALLWAIT ;
break ;
}
2003-11-07 16:55:13 +00:00
next :
if ( backwards ) {
2003-08-07 03:48:00 +00:00
p = p - > prev ;
2003-11-07 16:55:13 +00:00
if ( ! p )
2004-07-29 02:07:03 +00:00
p = end ;
2003-11-07 16:55:13 +00:00
} else {
2003-08-07 03:48:00 +00:00
p = p - > next ;
2003-11-07 16:55:13 +00:00
if ( ! p )
2004-07-29 02:07:03 +00:00
p = start ;
2003-11-07 16:55:13 +00:00
}
/* stop when you roll to the one that we started from */
if ( p = = exit )
break ;
2001-10-09 02:06:21 +00:00
}
2004-06-06 01:54:22 +00:00
ast_mutex_unlock ( lock ) ;
2001-10-09 02:06:21 +00:00
restart_monitor ( ) ;
2004-10-26 22:25:43 +00:00
if ( callwait | | ( ! tmp & & busy ) )
* cause = AST_CAUSE_BUSY ;
2001-10-09 02:06:21 +00:00
return tmp ;
}
# ifdef ZAPATA_PRI
2004-06-06 01:54:22 +00:00
static struct zt_pvt * pri_find_crv ( struct zt_pri * pri , int crv )
{
struct zt_pvt * p ;
p = pri - > crvs ;
while ( p ) {
if ( p - > channel = = crv )
return p ;
p = p - > next ;
}
2004-06-09 13:55:52 +00:00
return NULL ;
2004-06-06 01:54:22 +00:00
}
2001-10-09 02:06:21 +00:00
2005-05-24 15:30:10 +00:00
static int pri_find_principle ( struct zt_pri * pri , int channel )
2004-06-05 06:54:52 +00:00
{
int x ;
2005-05-24 15:30:10 +00:00
int span = PRI_SPAN ( channel ) ;
2005-05-20 19:09:21 +00:00
int spanfd ;
2005-05-24 14:19:27 +00:00
ZT_PARAMS param ;
2004-06-05 06:54:52 +00:00
int principle = - 1 ;
2005-05-24 15:30:10 +00:00
int explicit = PRI_EXPLICIT ( channel ) ;
span = PRI_SPAN ( channel ) ;
channel = PRI_CHANNEL ( channel ) ;
if ( ! explicit ) {
2005-05-20 19:09:21 +00:00
spanfd = pri_active_dchan_fd ( pri ) ;
2005-05-23 17:07:32 +00:00
if ( ioctl ( spanfd , ZT_GET_PARAMS , & param ) )
return - 1 ;
2005-05-24 14:19:27 +00:00
span = pris [ param . spanno - 1 ] . prilogicalspan ;
2005-05-20 19:09:21 +00:00
}
2004-06-05 07:07:12 +00:00
for ( x = 0 ; x < pri - > numchans ; x + + ) {
2004-06-06 22:51:37 +00:00
if ( pri - > pvts [ x ] & & ( pri - > pvts [ x ] - > prioffset = = channel ) & & ( pri - > pvts [ x ] - > logicalspan = = span ) ) {
2004-06-05 06:54:52 +00:00
principle = x ;
break ;
}
}
return principle ;
}
static int pri_fixup_principle ( struct zt_pri * pri , int principle , q931_call * c )
2001-10-09 02:06:21 +00:00
{
int x ;
2004-07-19 02:18:11 +00:00
struct zt_pvt * crv ;
2003-02-07 19:23:19 +00:00
if ( ! c ) {
2004-06-05 06:54:52 +00:00
if ( principle < 0 )
return - 1 ;
return principle ;
}
if ( ( principle > - 1 ) & &
2004-06-05 07:01:23 +00:00
( principle < pri - > numchans ) & &
2004-06-05 06:54:52 +00:00
( pri - > pvts [ principle ] ) & &
( pri - > pvts [ principle ] - > call = = c ) )
return principle ;
2004-07-19 02:18:11 +00:00
/* First, check for other bearers */
2004-06-05 07:07:12 +00:00
for ( x = 0 ; x < pri - > numchans ; x + + ) {
2004-06-05 06:54:52 +00:00
if ( ! pri - > pvts [ x ] ) continue ;
if ( pri - > pvts [ x ] - > call = = c ) {
2001-10-09 02:06:21 +00:00
/* Found our call */
2004-06-05 06:54:52 +00:00
if ( principle ! = x ) {
2001-10-09 02:06:21 +00:00
if ( option_verbose > 2 )
ast_verbose ( VERBOSE_PREFIX_3 " Moving call from channel %d to channel %d \n " ,
2004-06-05 06:54:52 +00:00
pri - > pvts [ x ] - > channel , pri - > pvts [ principle ] - > channel ) ;
if ( pri - > pvts [ principle ] - > owner ) {
2001-10-09 02:06:21 +00:00
ast_log ( LOG_WARNING , " Can't fix up channel from %d to %d because %d is already in use \n " ,
2004-06-05 06:54:52 +00:00
pri - > pvts [ x ] - > channel , pri - > pvts [ principle ] - > channel , pri - > pvts [ principle ] - > channel ) ;
return - 1 ;
2001-10-09 02:06:21 +00:00
}
/* Fix it all up now */
2004-06-05 06:54:52 +00:00
pri - > pvts [ principle ] - > owner = pri - > pvts [ x ] - > owner ;
if ( pri - > pvts [ principle ] - > owner ) {
2005-01-11 16:51:57 +00:00
snprintf ( pri - > pvts [ principle ] - > owner - > name , sizeof ( pri - > pvts [ principle ] - > owner - > name ) ,
" Zap/%d:%d-%d " , pri - > trunkgroup , pri - > pvts [ principle ] - > channel , 1 ) ;
2005-03-04 06:47:24 +00:00
pri - > pvts [ principle ] - > owner - > tech_pvt = pri - > pvts [ principle ] ;
2004-06-05 06:54:52 +00:00
pri - > pvts [ principle ] - > owner - > fds [ 0 ] = pri - > pvts [ principle ] - > subs [ SUB_REAL ] . zfd ;
pri - > pvts [ principle ] - > subs [ SUB_REAL ] . owner = pri - > pvts [ x ] - > subs [ SUB_REAL ] . owner ;
2003-02-07 19:23:19 +00:00
} else
2004-06-05 06:54:52 +00:00
ast_log ( LOG_WARNING , " Whoa, there's no owner, and we're having to fix up channel %d to channel %d \n " , pri - > pvts [ x ] - > channel , pri - > pvts [ principle ] - > channel ) ;
pri - > pvts [ principle ] - > call = pri - > pvts [ x ] - > call ;
2001-10-09 02:06:21 +00:00
/* Free up the old channel, now not in use */
2005-01-07 21:18:00 +00:00
pri - > pvts [ x ] - > subs [ SUB_REAL ] . owner = NULL ;
2004-06-05 06:54:52 +00:00
pri - > pvts [ x ] - > owner = NULL ;
pri - > pvts [ x ] - > call = NULL ;
2001-10-09 02:06:21 +00:00
}
2004-06-05 06:54:52 +00:00
return principle ;
2001-10-09 02:06:21 +00:00
}
}
2004-07-19 02:18:11 +00:00
/* Now check for a CRV with no bearer */
crv = pri - > crvs ;
while ( crv ) {
if ( crv - > call = = c ) {
/* This is our match... Perform some basic checks */
if ( crv - > bearer )
ast_log ( LOG_WARNING , " Trying to fix up call which already has a bearer which isn't the one we think it is \n " ) ;
else if ( pri - > pvts [ principle ] - > owner )
ast_log ( LOG_WARNING , " Tring to fix up a call to a bearer which already has an owner! \n " ) ;
else {
/* Looks good. Drop the pseudo channel now, clear up the assignment, and
wakeup the potential sleeper */
2004-10-23 22:00:40 +00:00
zt_close ( crv - > subs [ SUB_REAL ] . zfd ) ;
2004-07-19 02:18:11 +00:00
pri - > pvts [ principle ] - > call = crv - > call ;
pri_assign_bearer ( crv , pri , pri - > pvts [ principle ] ) ;
ast_log ( LOG_DEBUG , " Assigning bearer %d/%d to CRV %d:%d \n " ,
pri - > pvts [ principle ] - > logicalspan , pri - > pvts [ principle ] - > prioffset ,
pri - > trunkgroup , crv - > channel ) ;
2004-09-10 18:47:13 +00:00
wakeup_sub ( crv , SUB_REAL , pri ) ;
2004-07-19 02:18:11 +00:00
}
return principle ;
}
crv = crv - > next ;
}
2003-02-07 19:23:19 +00:00
ast_log ( LOG_WARNING , " Call specified, but not found? \n " ) ;
2004-06-05 06:54:52 +00:00
return - 1 ;
2001-10-09 02:06:21 +00:00
}
2002-06-24 17:59:56 +00:00
static void * do_idle_thread ( void * vchan )
{
struct ast_channel * chan = vchan ;
2005-03-04 06:47:24 +00:00
struct zt_pvt * pvt = chan - > tech_pvt ;
2002-06-24 17:59:56 +00:00
struct ast_frame * f ;
char ex [ 80 ] ;
/* Wait up to 30 seconds for an answer */
int newms , ms = 30000 ;
if ( option_verbose > 2 )
ast_verbose ( VERBOSE_PREFIX_3 " Initiating idle call on channel %s \n " , chan - > name ) ;
snprintf ( ex , sizeof ( ex ) , " %d/%s " , pvt - > channel , pvt - > pri - > idledial ) ;
if ( ast_call ( chan , ex , 0 ) ) {
ast_log ( LOG_WARNING , " Idle dial failed on '%s' to '%s' \n " , chan - > name , ex ) ;
ast_hangup ( chan ) ;
return NULL ;
}
while ( ( newms = ast_waitfor ( chan , ms ) ) > 0 ) {
f = ast_read ( chan ) ;
if ( ! f ) {
/* Got hangup */
break ;
}
if ( f - > frametype = = AST_FRAME_CONTROL ) {
switch ( f - > subclass ) {
case AST_CONTROL_ANSWER :
/* Launch the PBX */
2005-05-15 23:26:45 +00:00
ast_copy_string ( chan - > exten , pvt - > pri - > idleext , sizeof ( chan - > exten ) ) ;
ast_copy_string ( chan - > context , pvt - > pri - > idlecontext , sizeof ( chan - > context ) ) ;
2002-06-24 17:59:56 +00:00
chan - > priority = 1 ;
if ( option_verbose > 3 )
ast_verbose ( VERBOSE_PREFIX_3 " Idle channel '%s' answered, sending to %s@%s \n " , chan - > name , chan - > exten , chan - > context ) ;
ast_pbx_run ( chan ) ;
/* It's already hungup, return immediately */
return NULL ;
case AST_CONTROL_BUSY :
if ( option_verbose > 3 )
ast_verbose ( VERBOSE_PREFIX_3 " Idle channel '%s' busy, waiting... \n " , chan - > name ) ;
break ;
case AST_CONTROL_CONGESTION :
if ( option_verbose > 3 )
ast_verbose ( VERBOSE_PREFIX_3 " Idle channel '%s' congested, waiting... \n " , chan - > name ) ;
break ;
} ;
}
ast_frfree ( f ) ;
ms = newms ;
}
#if 0
printf ( " Hanging up '%s' \n " , chan - > name ) ;
# endif
/* Hangup the channel since nothing happend */
ast_hangup ( chan ) ;
return NULL ;
}
2005-05-24 15:30:10 +00:00
# ifndef PRI_NEW_SET_API
# error "Upgrade your libpri"
# endif
2005-05-23 16:56:06 +00:00
static void zt_pri_message ( struct pri * pri , char * s )
2003-02-07 19:23:19 +00:00
{
2005-05-24 15:30:10 +00:00
int x , y ;
int dchan = - 1 , span = - 1 ;
2005-07-11 19:23:02 +00:00
int dchancount = 0 ;
2005-05-24 15:30:10 +00:00
if ( pri ) {
for ( x = 0 ; x < NUM_SPANS ; x + + ) {
for ( y = 0 ; y < NUM_DCHANS ; y + + ) {
2005-07-11 19:23:02 +00:00
if ( pris [ x ] . dchans [ y ] )
dchancount + + ;
if ( pris [ x ] . dchans [ y ] = = pri )
2005-05-24 15:30:10 +00:00
dchan = y ;
}
if ( dchan > = 0 ) {
span = x ;
break ;
}
2005-07-11 19:23:02 +00:00
dchancount = 0 ;
2005-05-24 15:30:10 +00:00
}
2005-07-11 19:23:02 +00:00
if ( ( dchan > = 0 ) & & ( span > = 0 ) ) {
if ( dchancount > 1 )
ast_verbose ( " [Span %d D-Channel %d]%s " , span , dchan , s ) ;
else
ast_verbose ( " %s " , s ) ;
} else
2005-05-24 15:30:10 +00:00
ast_verbose ( " PRI debug error: could not find pri associated it with debug message output \n " ) ;
} else
ast_verbose ( " %s " , s ) ;
2005-04-22 19:10:35 +00:00
ast_mutex_lock ( & pridebugfdlock ) ;
if ( pridebugfd > = 0 )
2005-07-11 19:23:02 +00:00
write ( pridebugfd , s , strlen ( s ) ) ;
2005-04-22 19:10:35 +00:00
ast_mutex_unlock ( & pridebugfdlock ) ;
2003-02-07 19:23:19 +00:00
}
2005-05-23 16:56:06 +00:00
static void zt_pri_error ( struct pri * pri , char * s )
2003-02-07 19:23:19 +00:00
{
2005-05-24 15:30:10 +00:00
int x , y ;
int dchan = - 1 , span = - 1 ;
2005-07-11 19:23:02 +00:00
int dchancount = 0 ;
2005-05-24 15:30:10 +00:00
if ( pri ) {
for ( x = 0 ; x < NUM_SPANS ; x + + ) {
for ( y = 0 ; y < NUM_DCHANS ; y + + ) {
2005-07-11 19:23:02 +00:00
if ( pris [ x ] . dchans [ y ] )
dchancount + + ;
if ( pris [ x ] . dchans [ y ] = = pri )
2005-05-24 15:30:10 +00:00
dchan = y ;
}
if ( dchan > = 0 ) {
span = x ;
break ;
}
2005-07-11 19:23:02 +00:00
dchancount = 0 ;
2005-05-24 15:30:10 +00:00
}
2005-07-11 19:23:02 +00:00
if ( ( dchan > = 0 ) & & ( span > = 0 ) ) {
if ( dchancount > 1 )
ast_log ( LOG_WARNING , " [Span %d D-Channel %d] PRI: %s " , span , dchan , s ) ;
else
ast_verbose ( " %s " , s ) ;
} else
2005-05-24 15:30:10 +00:00
ast_verbose ( " PRI debug error: could not find pri associated it with debug message output \n " ) ;
} else
ast_log ( LOG_WARNING , " %s " , s ) ;
2005-04-22 19:10:35 +00:00
ast_mutex_lock ( & pridebugfdlock ) ;
if ( pridebugfd > = 0 )
write ( pridebugfd , s , strlen ( s ) ) ;
ast_mutex_unlock ( & pridebugfdlock ) ;
2003-02-07 19:23:19 +00:00
}
2003-03-20 05:20:19 +00:00
static int pri_check_restart ( struct zt_pri * pri )
{
do {
2004-06-05 06:54:52 +00:00
pri - > resetpos + + ;
2004-06-05 07:01:23 +00:00
} while ( ( pri - > resetpos < pri - > numchans ) & &
2004-06-05 06:54:52 +00:00
( ! pri - > pvts [ pri - > resetpos ] | |
pri - > pvts [ pri - > resetpos ] - > call | |
pri - > pvts [ pri - > resetpos ] - > resetting ) ) ;
2004-06-05 07:01:23 +00:00
if ( pri - > resetpos < pri - > numchans ) {
2003-03-20 05:20:19 +00:00
/* Mark the channel as resetting and restart it */
2004-06-05 06:54:52 +00:00
pri - > pvts [ pri - > resetpos ] - > resetting = 1 ;
pri_reset ( pri - > pri , PVT_TO_CHANNEL ( pri - > pvts [ pri - > resetpos ] ) ) ;
2003-03-20 05:20:19 +00:00
} else {
pri - > resetting = 0 ;
2003-03-20 05:49:27 +00:00
time ( & pri - > lastreset ) ;
2003-03-20 05:20:19 +00:00
}
return 0 ;
}
2004-09-10 18:58:05 +00:00
static int pri_hangup_all ( struct zt_pvt * p , struct zt_pri * pri )
2004-06-06 01:54:22 +00:00
{
int x ;
int redo ;
2004-09-10 18:58:05 +00:00
ast_mutex_unlock ( & pri - > lock ) ;
2004-06-06 01:54:22 +00:00
ast_mutex_lock ( & p - > lock ) ;
do {
redo = 0 ;
for ( x = 0 ; x < 3 ; x + + ) {
while ( p - > subs [ x ] . owner & & ast_mutex_trylock ( & p - > subs [ x ] . owner - > lock ) ) {
redo + + ;
ast_mutex_unlock ( & p - > lock ) ;
usleep ( 1 ) ;
ast_mutex_lock ( & p - > lock ) ;
}
if ( p - > subs [ x ] . owner ) {
ast_queue_hangup ( p - > subs [ x ] . owner ) ;
ast_mutex_unlock ( & p - > subs [ x ] . owner - > lock ) ;
}
}
} while ( redo ) ;
ast_mutex_unlock ( & p - > lock ) ;
2004-09-10 18:58:05 +00:00
ast_mutex_lock ( & pri - > lock ) ;
2004-06-06 01:54:22 +00:00
return 0 ;
}
2005-06-29 21:47:44 +00:00
char * redirectingreason2str ( int redirectingreason )
{
switch ( redirectingreason ) {
case 0 :
return " UNKNOWN " ;
case 1 :
return " BUSY " ;
case 2 :
return " NO_REPLY " ;
case 0xF :
return " UNCONDITIONAL " ;
default :
return " NOREDIRECT " ;
}
}
2004-06-06 01:54:22 +00:00
2001-10-09 02:06:21 +00:00
static void * pri_dchannel ( void * vpri )
{
struct zt_pri * pri = vpri ;
pri_event * e ;
2004-06-07 03:39:18 +00:00
struct pollfd fds [ NUM_DCHANS ] ;
2001-10-09 02:06:21 +00:00
int res ;
2004-06-05 06:54:52 +00:00
int chanpos = 0 ;
2001-10-09 02:06:21 +00:00
int x ;
2002-06-24 17:59:56 +00:00
int haveidles ;
int activeidles ;
int nextidle = - 1 ;
2001-10-09 02:06:21 +00:00
struct ast_channel * c ;
2004-06-07 03:39:18 +00:00
struct timeval tv , lowest , * next ;
2002-06-24 17:59:56 +00:00
struct timeval lastidle = { 0 , 0 } ;
int doidling = 0 ;
char * cc ;
char idlen [ 80 ] ;
struct ast_channel * idle ;
pthread_t p ;
time_t t ;
2004-06-07 03:39:18 +00:00
int i , which = - 1 ;
int numdchans ;
2004-10-26 22:25:43 +00:00
int cause = 0 ;
2004-06-06 01:54:22 +00:00
struct zt_pvt * crv ;
2004-05-02 03:39:17 +00:00
pthread_t threadid ;
pthread_attr_t attr ;
2004-11-07 18:59:20 +00:00
char ani2str [ 6 ] ;
2005-02-04 06:12:32 +00:00
char plancallingnum [ 256 ] ;
2005-07-12 02:33:57 +00:00
char plancallingani [ 256 ] ;
2005-02-04 06:12:32 +00:00
char calledtonstr [ 10 ] ;
2004-05-13 18:23:34 +00:00
pthread_attr_init ( & attr ) ;
pthread_attr_setdetachstate ( & attr , PTHREAD_CREATE_DETACHED ) ;
2003-02-07 19:23:19 +00:00
gettimeofday ( & lastidle , NULL ) ;
2004-05-05 04:23:18 +00:00
if ( ! ast_strlen_zero ( pri - > idledial ) & & ! ast_strlen_zero ( pri - > idleext ) ) {
2002-06-24 17:59:56 +00:00
/* Need to do idle dialing, check to be sure though */
cc = strchr ( pri - > idleext , ' @ ' ) ;
if ( cc ) {
* cc = ' \0 ' ;
cc + + ;
2005-05-15 23:26:45 +00:00
ast_copy_string ( pri - > idlecontext , cc , sizeof ( pri - > idlecontext ) ) ;
2002-06-24 17:59:56 +00:00
#if 0
/* Extensions may not be loaded yet */
if ( ! ast_exists_extension ( NULL , pri - > idlecontext , pri - > idleext , 1 , NULL ) )
ast_log ( LOG_WARNING , " Extension '%s @ %s' does not exist \n " , pri - > idleext , pri - > idlecontext ) ;
else
# endif
doidling = 1 ;
} else
ast_log ( LOG_WARNING , " Idle dial string '%s' lacks '@context' \n " , pri - > idleext ) ;
}
2001-10-09 02:06:21 +00:00
for ( ; ; ) {
2004-06-07 03:39:18 +00:00
for ( i = 0 ; i < NUM_DCHANS ; i + + ) {
if ( ! pri - > dchannels [ i ] )
break ;
fds [ i ] . fd = pri - > fds [ i ] ;
fds [ i ] . events = POLLIN | POLLPRI ;
}
numdchans = i ;
2002-06-24 17:59:56 +00:00
time ( & t ) ;
2003-08-13 15:25:16 +00:00
ast_mutex_lock ( & pri - > lock ) ;
2005-03-23 21:12:01 +00:00
if ( pri - > switchtype ! = PRI_SWITCH_GR303_TMC & & ( pri - > resetinterval > 0 ) ) {
2004-06-07 03:39:18 +00:00
if ( pri - > resetting & & pri_is_up ( pri ) ) {
2004-06-05 06:54:52 +00:00
if ( pri - > resetpos < 0 )
pri_check_restart ( pri ) ;
} else {
2005-02-04 06:12:32 +00:00
if ( ! pri - > resetting & & ( t - pri - > lastreset ) > = pri - > resetinterval ) {
2004-06-05 06:54:52 +00:00
pri - > resetting = 1 ;
pri - > resetpos = - 1 ;
}
2002-06-24 17:59:56 +00:00
}
}
/* Look for any idle channels if appropriate */
2004-06-07 03:39:18 +00:00
if ( doidling & & pri_is_up ( pri ) ) {
2002-06-24 17:59:56 +00:00
nextidle = - 1 ;
haveidles = 0 ;
activeidles = 0 ;
2004-06-05 06:54:52 +00:00
for ( x = pri - > numchans ; x > = 0 ; x - - ) {
if ( pri - > pvts [ x ] & & ! pri - > pvts [ x ] - > owner & &
! pri - > pvts [ x ] - > call ) {
2002-06-24 17:59:56 +00:00
if ( haveidles < pri - > minunused ) {
haveidles + + ;
2004-06-05 06:54:52 +00:00
} else if ( ! pri - > pvts [ x ] - > resetting ) {
2002-06-24 17:59:56 +00:00
nextidle = x ;
break ;
}
2004-06-05 06:54:52 +00:00
} else if ( pri - > pvts [ x ] & & pri - > pvts [ x ] - > owner & & pri - > pvts [ x ] - > isidlecall )
2002-06-24 17:59:56 +00:00
activeidles + + ;
}
#if 0
printf ( " nextidle: %d, haveidles: %d, minunsed: %d \n " ,
nextidle , haveidles , minunused ) ;
printf ( " nextidle: %d, haveidles: %d, ms: %ld, minunsed: %d \n " ,
2005-07-15 23:00:47 +00:00
nextidle , haveidles , ast_tvdiff_ms ( ast_tvnow ( ) , lastidle ) , minunused ) ;
2002-06-24 17:59:56 +00:00
# endif
if ( nextidle > - 1 ) {
2005-07-15 23:00:47 +00:00
if ( ast_tvdiff_ms ( ast_tvnow ( ) , lastidle ) > 1000 ) {
2002-06-24 17:59:56 +00:00
/* Don't create a new idle call more than once per second */
2004-06-05 06:54:52 +00:00
snprintf ( idlen , sizeof ( idlen ) , " %d/%s " , pri - > pvts [ nextidle ] - > channel , pri - > idledial ) ;
2004-10-26 22:25:43 +00:00
idle = zt_request ( " Zap " , AST_FORMAT_ULAW , idlen , & cause ) ;
2002-06-24 17:59:56 +00:00
if ( idle ) {
2004-06-05 06:54:52 +00:00
pri - > pvts [ nextidle ] - > isidlecall = 1 ;
2004-08-08 17:15:02 +00:00
if ( ast_pthread_create ( & p , NULL , do_idle_thread , idle ) ) {
2002-06-24 17:59:56 +00:00
ast_log ( LOG_WARNING , " Unable to start new thread for idle channel '%s' \n " , idle - > name ) ;
zt_hangup ( idle ) ;
}
} else
ast_log ( LOG_WARNING , " Unable to request channel 'Zap/%s' for idle call \n " , idlen ) ;
gettimeofday ( & lastidle , NULL ) ;
}
} else if ( ( haveidles < pri - > minunused ) & &
( activeidles > pri - > minidle ) ) {
/* Mark something for hangup if there is something
that can be hungup */
2004-06-05 07:07:12 +00:00
for ( x = pri - > numchans ; x > = 0 ; x - - ) {
2002-06-24 17:59:56 +00:00
/* find a candidate channel */
2004-06-05 06:54:52 +00:00
if ( pri - > pvts [ x ] & & pri - > pvts [ x ] - > owner & & pri - > pvts [ x ] - > isidlecall ) {
pri - > pvts [ x ] - > owner - > _softhangup | = AST_SOFTHANGUP_DEV ;
2002-06-24 17:59:56 +00:00
haveidles + + ;
/* Stop if we have enough idle channels or
can ' t spare any more active idle ones */
if ( ( haveidles > = pri - > minunused ) | |
( activeidles < = pri - > minidle ) )
break ;
}
}
}
}
2004-06-07 03:39:18 +00:00
/* Start with reasonable max */
2005-07-15 23:00:47 +00:00
lowest = ast_tv ( 60 , 0 ) ;
2004-06-07 03:39:18 +00:00
for ( i = 0 ; i < NUM_DCHANS ; i + + ) {
/* Find lowest available d-channel */
if ( ! pri - > dchannels [ i ] )
break ;
2004-06-07 15:57:18 +00:00
if ( ( next = pri_schedule_next ( pri - > dchans [ i ] ) ) ) {
2004-06-07 03:39:18 +00:00
/* We need relative time here */
2005-07-15 23:00:47 +00:00
tv = ast_tvsub ( * next , ast_tvnow ( ) ) ;
2004-06-07 03:39:18 +00:00
if ( tv . tv_sec < 0 ) {
2005-07-15 23:00:47 +00:00
tv = ast_tv ( 0 , 0 ) ;
2002-06-24 17:59:56 +00:00
}
2004-06-07 03:39:18 +00:00
if ( doidling | | pri - > resetting ) {
if ( tv . tv_sec > 1 ) {
2005-07-15 23:00:47 +00:00
tv = ast_tv ( 1 , 0 ) ;
2004-06-07 03:39:18 +00:00
}
} else {
if ( tv . tv_sec > 60 ) {
2005-07-15 23:00:47 +00:00
tv = ast_tv ( 60 , 0 ) ;
2004-06-07 03:39:18 +00:00
}
}
} else if ( doidling | | pri - > resetting ) {
/* Make sure we stop at least once per second if we're
monitoring idle channels */
2005-07-15 23:00:47 +00:00
tv = ast_tv ( 1 , 0 ) ;
2004-06-07 03:39:18 +00:00
} else {
/* Don't poll for more than 60 seconds */
2005-07-15 23:00:47 +00:00
tv = ast_tv ( 60 , 0 ) ;
2004-06-07 03:39:18 +00:00
}
2005-07-15 23:00:47 +00:00
if ( ! i | | ast_tvcmp ( tv , lowest ) < 0 ) {
lowest = tv ;
2002-06-24 17:59:56 +00:00
}
2001-12-29 18:04:21 +00:00
}
2003-08-13 15:25:16 +00:00
ast_mutex_unlock ( & pri - > lock ) ;
2002-06-24 17:59:56 +00:00
2002-03-08 23:48:42 +00:00
e = NULL ;
2004-06-07 03:39:18 +00:00
res = poll ( fds , numdchans , lowest . tv_sec * 1000 + lowest . tv_usec / 1000 ) ;
2002-06-24 17:59:56 +00:00
2003-08-13 15:25:16 +00:00
ast_mutex_lock ( & pri - > lock ) ;
2001-10-09 02:06:21 +00:00
if ( ! res ) {
2004-06-07 03:39:18 +00:00
for ( which = 0 ; which < NUM_DCHANS ; which + + ) {
if ( ! pri - > dchans [ which ] )
break ;
/* Just a timeout, run the scheduler */
e = pri_schedule_run ( pri - > dchans [ which ] ) ;
if ( e )
break ;
}
2001-10-09 02:06:21 +00:00
} else if ( res > - 1 ) {
2004-06-07 03:39:18 +00:00
for ( which = 0 ; which < NUM_DCHANS ; which + + ) {
if ( ! pri - > dchans [ which ] )
break ;
2004-06-07 15:57:18 +00:00
if ( fds [ which ] . revents & POLLPRI ) {
/* Check for an event */
x = 0 ;
res = ioctl ( pri - > fds [ which ] , ZT_GETEVENT , & x ) ;
if ( x )
2004-10-01 13:26:47 +00:00
ast_log ( LOG_NOTICE , " PRI got event: %s (%d) on %s D-channel of span %d \n " , event2str ( x ) , x , pri_order ( which ) , pri - > span ) ;
2004-06-07 15:57:18 +00:00
/* Keep track of alarm state */
if ( x = = ZT_EVENT_ALARM ) {
pri - > dchanavail [ which ] & = ~ ( DCHAN_NOTINALARM | DCHAN_UP ) ;
pri_find_dchan ( pri ) ;
} else if ( x = = ZT_EVENT_NOALARM ) {
pri - > dchanavail [ which ] | = DCHAN_NOTINALARM ;
pri_find_dchan ( pri ) ;
}
if ( option_debug )
ast_log ( LOG_DEBUG , " Got event %s (%d) on D-channel for span %d \n " , event2str ( x ) , x , pri - > span ) ;
} else if ( fds [ which ] . revents & POLLIN ) {
2004-06-07 03:39:18 +00:00
e = pri_check_event ( pri - > dchans [ which ] ) ;
}
if ( e )
break ;
}
2002-03-08 23:48:42 +00:00
} else if ( errno ! = EINTR )
ast_log ( LOG_WARNING , " pri_event returned error %d (%s) \n " , errno , strerror ( errno ) ) ;
if ( e ) {
if ( pri - > debug )
2004-06-07 03:39:18 +00:00
pri_dump_event ( pri - > dchans [ which ] , e ) ;
2005-03-22 16:26:54 +00:00
if ( e - > e ! = PRI_EVENT_DCHAN_DOWN )
pri - > dchanavail [ which ] | = DCHAN_UP ;
2002-03-08 23:48:42 +00:00
switch ( e - > e ) {
case PRI_EVENT_DCHAN_UP :
if ( option_verbose > 1 )
2004-06-07 03:39:18 +00:00
ast_verbose ( VERBOSE_PREFIX_2 " %s D-Channel on span %d up \n " , pri_order ( which ) , pri - > span ) ;
pri - > dchanavail [ which ] | = DCHAN_UP ;
2005-05-24 15:30:10 +00:00
if ( ! pri - > pri ) pri_find_dchan ( pri ) ;
2004-06-07 03:39:18 +00:00
/* Note presense of D-channel */
2003-03-20 05:49:27 +00:00
time ( & pri - > lastreset ) ;
2004-06-07 03:39:18 +00:00
2003-03-20 05:49:27 +00:00
/* Restart in 5 seconds */
2005-03-23 21:12:01 +00:00
if ( pri - > resetinterval > - 1 ) {
pri - > lastreset - = pri - > resetinterval ;
pri - > lastreset + = 5 ;
}
2003-03-20 05:49:27 +00:00
pri - > resetting = 0 ;
2003-08-25 20:39:07 +00:00
/* Take the channels from inalarm condition */
2004-06-05 07:01:23 +00:00
for ( i = 0 ; i < pri - > numchans ; i + + )
2004-06-05 06:54:52 +00:00
if ( pri - > pvts [ i ] ) {
pri - > pvts [ i ] - > inalarm = 0 ;
2003-08-25 20:39:07 +00:00
}
2002-03-08 23:48:42 +00:00
break ;
case PRI_EVENT_DCHAN_DOWN :
if ( option_verbose > 1 )
2004-06-07 03:39:18 +00:00
ast_verbose ( VERBOSE_PREFIX_2 " %s D-Channel on span %d down \n " , pri_order ( which ) , pri - > span ) ;
pri - > dchanavail [ which ] & = ~ DCHAN_UP ;
pri_find_dchan ( pri ) ;
if ( ! pri_is_up ( pri ) ) {
pri - > resetting = 0 ;
/* Hangup active channels and put them in alarm mode */
for ( i = 0 ; i < pri - > numchans ; i + + ) {
struct zt_pvt * p = pri - > pvts [ i ] ;
if ( p ) {
if ( p - > call ) {
if ( p - > pri & & p - > pri - > pri ) {
pri_hangup ( p - > pri - > pri , p - > call , - 1 ) ;
pri_destroycall ( p - > pri - > pri , p - > call ) ;
p - > call = NULL ;
} else
ast_log ( LOG_WARNING , " The PRI Call have not been destroyed \n " ) ;
}
2004-12-13 15:11:36 +00:00
if ( p - > realcall ) {
pri_hangup_all ( p - > realcall , pri ) ;
2004-06-07 03:39:18 +00:00
} else if ( p - > owner )
p - > owner - > _softhangup | = AST_SOFTHANGUP_DEV ;
p - > inalarm = 1 ;
2003-08-25 20:39:07 +00:00
}
}
}
2002-03-08 23:48:42 +00:00
break ;
case PRI_EVENT_RESTART :
2004-06-05 06:54:52 +00:00
if ( e - > restart . channel > - 1 ) {
chanpos = pri_find_principle ( pri , e - > restart . channel ) ;
if ( chanpos < 0 )
ast_log ( LOG_WARNING , " Restart requested on odd/unavailable channel number %d/%d on span %d \n " ,
PRI_SPAN ( e - > restart . channel ) , PRI_CHANNEL ( e - > restart . channel ) , pri - > span ) ;
2002-03-08 23:48:42 +00:00
else {
2001-10-09 02:06:21 +00:00
if ( option_verbose > 2 )
2004-06-10 19:00:20 +00:00
ast_verbose ( VERBOSE_PREFIX_3 " B-channel %d/%d restarted on span %d \n " ,
PRI_SPAN ( e - > restart . channel ) , PRI_CHANNEL ( e - > restart . channel ) , pri - > span ) ;
2004-06-05 06:54:52 +00:00
ast_mutex_lock ( & pri - > pvts [ chanpos ] - > lock ) ;
if ( pri - > pvts [ chanpos ] - > call ) {
pri_destroycall ( pri - > pri , pri - > pvts [ chanpos ] - > call ) ;
pri - > pvts [ chanpos ] - > call = NULL ;
2003-09-25 06:14:38 +00:00
}
2002-03-08 23:48:42 +00:00
/* Force soft hangup if appropriate */
2004-12-13 15:11:36 +00:00
if ( pri - > pvts [ chanpos ] - > realcall )
pri_hangup_all ( pri - > pvts [ chanpos ] - > realcall , pri ) ;
2004-06-06 01:54:22 +00:00
else if ( pri - > pvts [ chanpos ] - > owner )
2004-06-05 06:54:52 +00:00
pri - > pvts [ chanpos ] - > owner - > _softhangup | = AST_SOFTHANGUP_DEV ;
ast_mutex_unlock ( & pri - > pvts [ chanpos ] - > lock ) ;
2001-10-09 02:06:21 +00:00
}
2002-03-08 23:48:42 +00:00
} else {
if ( option_verbose > 2 )
2003-02-07 19:23:19 +00:00
ast_verbose ( VERBOSE_PREFIX_2 " Restart on requested on entire span %d \n " , pri - > span ) ;
2004-06-05 07:07:12 +00:00
for ( x = 0 ; x < pri - > numchans ; x + + )
2004-06-05 06:54:52 +00:00
if ( pri - > pvts [ x ] ) {
ast_mutex_lock ( & pri - > pvts [ x ] - > lock ) ;
if ( pri - > pvts [ x ] - > call ) {
pri_destroycall ( pri - > pri , pri - > pvts [ x ] - > call ) ;
pri - > pvts [ x ] - > call = NULL ;
2003-09-25 06:14:38 +00:00
}
2004-12-13 15:11:36 +00:00
if ( pri - > pvts [ chanpos ] - > realcall )
pri_hangup_all ( pri - > pvts [ chanpos ] - > realcall , pri ) ;
2004-06-06 01:54:22 +00:00
else if ( pri - > pvts [ x ] - > owner )
2004-06-05 06:54:52 +00:00
pri - > pvts [ x ] - > owner - > _softhangup | = AST_SOFTHANGUP_DEV ;
ast_mutex_unlock ( & pri - > pvts [ x ] - > lock ) ;
2003-03-19 16:44:19 +00:00
}
2002-03-08 23:48:42 +00:00
}
break ;
2005-05-16 18:48:09 +00:00
case PRI_EVENT_KEYPAD_DIGIT :
chanpos = pri_find_principle ( pri , e - > digit . channel ) ;
if ( chanpos < 0 ) {
ast_log ( LOG_WARNING , " KEYPAD_DIGITs received on unconfigured channel %d/%d span %d \n " ,
PRI_SPAN ( e - > digit . channel ) , PRI_CHANNEL ( e - > digit . channel ) , pri - > span ) ;
} else {
chanpos = pri_fixup_principle ( pri , chanpos , e - > digit . call ) ;
if ( chanpos > - 1 ) {
ast_mutex_lock ( & pri - > pvts [ chanpos ] - > lock ) ;
/* queue DTMF frame if the PBX for this call was already started (we're forwarding KEYPAD_DIGITs further on */
if ( pri - > overlapdial & & pri - > pvts [ chanpos ] - > call = = e - > digit . call & & pri - > pvts [ chanpos ] - > owner ) {
/* how to do that */
int digitlen = strlen ( e - > digit . digits ) ;
char digit ;
int i ;
for ( i = 0 ; i < digitlen ; i + + ) {
digit = e - > digit . digits [ i ] ;
{
struct ast_frame f = { AST_FRAME_DTMF , digit , } ;
zap_queue_frame ( pri - > pvts [ chanpos ] , & f , pri ) ;
}
}
}
ast_mutex_unlock ( & pri - > pvts [ chanpos ] - > lock ) ;
}
}
break ;
2003-02-12 13:59:15 +00:00
case PRI_EVENT_INFO_RECEIVED :
2004-06-05 06:54:52 +00:00
chanpos = pri_find_principle ( pri , e - > ring . channel ) ;
if ( chanpos < 0 ) {
ast_log ( LOG_WARNING , " INFO received on unconfigured channel %d/%d span %d \n " ,
PRI_SPAN ( e - > ring . channel ) , PRI_CHANNEL ( e - > ring . channel ) , pri - > span ) ;
} else {
chanpos = pri_fixup_principle ( pri , chanpos , e - > ring . call ) ;
if ( chanpos > - 1 ) {
2004-06-17 14:53:25 +00:00
ast_mutex_lock ( & pri - > pvts [ chanpos ] - > lock ) ;
2004-05-02 03:39:17 +00:00
/* queue DTMF frame if the PBX for this call was already started (we're forwarding INFORMATION further on */
2004-06-05 06:54:52 +00:00
if ( pri - > overlapdial & & pri - > pvts [ chanpos ] - > call = = e - > ring . call & & pri - > pvts [ chanpos ] - > owner ) {
2004-05-02 03:39:17 +00:00
/* how to do that */
int digitlen = strlen ( e - > ring . callednum ) ;
char digit ;
int i ;
for ( i = 0 ; i < digitlen ; i + + ) {
digit = e - > ring . callednum [ i ] ;
{
struct ast_frame f = { AST_FRAME_DTMF , digit , } ;
2004-09-10 18:47:13 +00:00
zap_queue_frame ( pri - > pvts [ chanpos ] , & f , pri ) ;
2004-05-02 03:39:17 +00:00
}
}
}
2004-06-17 14:53:25 +00:00
ast_mutex_unlock ( & pri - > pvts [ chanpos ] - > lock ) ;
2004-05-02 03:39:17 +00:00
}
}
break ;
2002-03-08 23:48:42 +00:00
case PRI_EVENT_RING :
2004-06-06 01:54:22 +00:00
crv = NULL ;
2004-06-05 06:54:52 +00:00
if ( e - > ring . channel = = - 1 )
2004-06-06 23:26:29 +00:00
chanpos = pri_find_empty_chan ( pri , 1 ) ;
2004-06-05 06:54:52 +00:00
else
chanpos = pri_find_principle ( pri , e - > ring . channel ) ;
2004-05-02 03:39:17 +00:00
/* if no channel specified find one empty */
2004-06-05 06:54:52 +00:00
if ( chanpos < 0 ) {
ast_log ( LOG_WARNING , " Ring requested on unconfigured channel %d/%d span %d \n " ,
PRI_SPAN ( e - > ring . channel ) , PRI_CHANNEL ( e - > ring . channel ) , pri - > span ) ;
2004-06-17 04:23:57 +00:00
} else {
ast_mutex_lock ( & pri - > pvts [ chanpos ] - > lock ) ;
if ( pri - > pvts [ chanpos ] - > owner ) {
if ( pri - > pvts [ chanpos ] - > call = = e - > ring . call ) {
ast_log ( LOG_WARNING , " Duplicate setup requested on channel %d/%d already in use on span %d \n " ,
PRI_SPAN ( e - > ring . channel ) , PRI_CHANNEL ( e - > ring . channel ) , pri - > span ) ;
break ;
} else {
ast_log ( LOG_WARNING , " Ring requested on channel %d/%d already in use on span %d. Hanging up owner. \n " ,
2004-06-05 06:54:52 +00:00
PRI_SPAN ( e - > ring . channel ) , PRI_CHANNEL ( e - > ring . channel ) , pri - > span ) ;
2004-12-13 15:11:36 +00:00
if ( pri - > pvts [ chanpos ] - > realcall )
pri_hangup_all ( pri - > pvts [ chanpos ] - > realcall , pri ) ;
2004-06-17 04:23:57 +00:00
else
pri - > pvts [ chanpos ] - > owner - > _softhangup | = AST_SOFTHANGUP_DEV ;
2004-06-17 04:32:10 +00:00
ast_mutex_unlock ( & pri - > pvts [ chanpos ] - > lock ) ;
2004-06-17 04:23:57 +00:00
chanpos = - 1 ;
}
2001-10-09 02:06:21 +00:00
}
2004-06-17 04:32:10 +00:00
if ( chanpos > - 1 )
ast_mutex_unlock ( & pri - > pvts [ chanpos ] - > lock ) ;
2002-03-08 23:48:42 +00:00
}
2004-06-05 06:54:52 +00:00
if ( ( chanpos < 0 ) & & ( e - > ring . flexible ) )
2004-06-06 23:26:29 +00:00
chanpos = pri_find_empty_chan ( pri , 1 ) ;
2004-06-05 06:54:52 +00:00
if ( chanpos > - 1 ) {
2004-06-17 04:23:57 +00:00
ast_mutex_lock ( & pri - > pvts [ chanpos ] - > lock ) ;
2004-06-06 01:54:22 +00:00
if ( pri - > switchtype = = PRI_SWITCH_GR303_TMC ) {
2004-06-17 04:23:57 +00:00
/* Should be safe to lock CRV AFAIK while bearer is still locked */
2004-06-06 01:54:22 +00:00
crv = pri_find_crv ( pri , pri_get_crv ( pri - > pri , e - > ring . call , NULL ) ) ;
2004-06-17 04:23:57 +00:00
if ( crv )
ast_mutex_lock ( & crv - > lock ) ;
2004-06-06 01:54:22 +00:00
if ( ! crv | | crv - > owner ) {
pri - > pvts [ chanpos ] - > call = NULL ;
if ( crv ) {
if ( crv - > owner )
crv - > owner - > _softhangup | = AST_SOFTHANGUP_DEV ;
ast_log ( LOG_WARNING , " Call received for busy CRV %d on span %d \n " , pri_get_crv ( pri - > pri , e - > ring . call , NULL ) , pri - > span ) ;
} else
ast_log ( LOG_NOTICE , " Call received for unconfigured CRV %d on span %d \n " , pri_get_crv ( pri - > pri , e - > ring . call , NULL ) , pri - > span ) ;
pri_hangup ( pri - > pri , e - > ring . call , PRI_CAUSE_INVALID_CALL_REFERENCE ) ;
2004-06-17 04:23:57 +00:00
if ( crv )
ast_mutex_unlock ( & crv - > lock ) ;
ast_mutex_unlock ( & pri - > pvts [ chanpos ] - > lock ) ;
2004-06-06 01:54:22 +00:00
break ;
}
}
2004-06-05 06:54:52 +00:00
pri - > pvts [ chanpos ] - > call = e - > ring . call ;
2004-05-02 03:39:17 +00:00
/* Get caller ID */
2005-02-04 06:12:32 +00:00
switch ( e - > ring . callingplan ) {
case PRI_INTERNATIONAL_ISDN : /* Q.931 dialplan == 0x11 international dialplan => prepend international prefix digits */
snprintf ( plancallingnum , sizeof ( plancallingnum ) , " %s%s " , pri - > internationalprefix , e - > ring . callingnum ) ;
break ;
case PRI_NATIONAL_ISDN : /* Q.931 dialplan == 0x21 national dialplan => prepend national prefix digits */
snprintf ( plancallingnum , sizeof ( plancallingnum ) , " %s%s " , pri - > nationalprefix , e - > ring . callingnum ) ;
break ;
case PRI_LOCAL_ISDN : /* Q.931 dialplan == 0x41 local dialplan => prepend local prefix digits */
snprintf ( plancallingnum , sizeof ( plancallingnum ) , " %s%s " , pri - > localprefix , e - > ring . callingnum ) ;
break ;
case PRI_PRIVATE : /* Q.931 dialplan == 0x49 private dialplan => prepend private prefix digits */
snprintf ( plancallingnum , sizeof ( plancallingnum ) , " %s%s " , pri - > privateprefix , e - > ring . callingnum ) ;
break ;
case PRI_UNKNOWN : /* Q.931 dialplan == 0x00 unknown dialplan => prepend unknown prefix digits */
snprintf ( plancallingnum , sizeof ( plancallingnum ) , " %s%s " , pri - > unknownprefix , e - > ring . callingnum ) ;
break ;
default : /* other Q.931 dialplan => don't twiddle with callingnum */
snprintf ( plancallingnum , sizeof ( plancallingnum ) , " %s " , e - > ring . callingnum ) ;
break ;
}
2004-06-05 06:54:52 +00:00
if ( pri - > pvts [ chanpos ] - > use_callerid ) {
2005-02-04 06:12:32 +00:00
ast_shrink_phone_number ( plancallingnum ) ;
2005-05-15 23:26:45 +00:00
ast_copy_string ( pri - > pvts [ chanpos ] - > cid_num , plancallingnum , sizeof ( pri - > pvts [ chanpos ] - > cid_num ) ) ;
2005-07-12 02:33:57 +00:00
# ifdef PRI_ANI
if ( ! ast_strlen_zero ( e - > ring . callingani ) ) {
switch ( e - > ring . callingplanani ) {
case PRI_INTERNATIONAL_ISDN : /* Q.931 dialplan == 0x11 international dialplan => prepend international prefix digits */
snprintf ( plancallingani , sizeof ( plancallingani ) , " %s%s " , pri - > internationalprefix , e - > ring . callingani ) ;
break ;
case PRI_NATIONAL_ISDN : /* Q.931 dialplan == 0x21 national dialplan => prepend national prefix digits */
snprintf ( plancallingani , sizeof ( plancallingani ) , " %s%s " , pri - > nationalprefix , e - > ring . callingani ) ;
break ;
case PRI_LOCAL_ISDN : /* Q.931 dialplan == 0x41 local dialplan => prepend local prefix digits */
snprintf ( plancallingani , sizeof ( plancallingani ) , " %s%s " , pri - > localprefix , e - > ring . callingani ) ;
break ;
case PRI_PRIVATE : /* Q.931 dialplan == 0x49 private dialplan => prepend private prefix digits */
snprintf ( plancallingani , sizeof ( plancallingani ) , " %s%s " , pri - > privateprefix , e - > ring . callingani ) ;
break ;
case PRI_UNKNOWN : /* Q.931 dialplan == 0x00 unknown dialplan => prepend unknown prefix digits */
snprintf ( plancallingani , sizeof ( plancallingani ) , " %s%s " , pri - > unknownprefix , e - > ring . callingani ) ;
break ;
default : /* other Q.931 dialplan => don't twiddle with callingani */
snprintf ( plancallingani , sizeof ( plancallingani ) , " %s " , e - > ring . callingani ) ;
break ;
}
ast_shrink_phone_number ( plancallingani ) ;
ast_copy_string ( pri - > pvts [ chanpos ] - > cid_ani , plancallingani , sizeof ( pri - > pvts [ chanpos ] - > cid_ani ) ) ;
}
# endif
2005-05-15 23:26:45 +00:00
ast_copy_string ( pri - > pvts [ chanpos ] - > cid_name , e - > ring . callingname , sizeof ( pri - > pvts [ chanpos ] - > cid_name ) ) ;
2005-02-04 06:12:32 +00:00
pri - > pvts [ chanpos ] - > cid_ton = e - > ring . callingplan ; /* this is the callingplan (TON/NPI), e->ring.callingplan>>4 would be the TON */
2004-10-02 00:58:31 +00:00
} else {
pri - > pvts [ chanpos ] - > cid_num [ 0 ] = ' \0 ' ;
2005-07-12 02:33:57 +00:00
pri - > pvts [ chanpos ] - > cid_ani [ 0 ] = ' \0 ' ;
2004-10-02 00:58:31 +00:00
pri - > pvts [ chanpos ] - > cid_name [ 0 ] = ' \0 ' ;
2005-02-04 06:12:32 +00:00
pri - > pvts [ chanpos ] - > cid_ton = 0 ;
2004-10-02 00:58:31 +00:00
}
2005-05-15 23:26:45 +00:00
ast_copy_string ( pri - > pvts [ chanpos ] - > rdnis , e - > ring . redirectingnum , sizeof ( pri - > pvts [ chanpos ] - > rdnis ) ) ;
2003-07-28 15:12:37 +00:00
/* If immediate=yes go to s|1 */
2004-06-05 06:54:52 +00:00
if ( pri - > pvts [ chanpos ] - > immediate ) {
2003-06-03 16:24:12 +00:00
if ( option_verbose > 2 )
2003-07-28 15:12:37 +00:00
ast_verbose ( VERBOSE_PREFIX_3 " Going to extension s|1 because of immediate=yes \n " ) ;
2004-07-16 04:40:54 +00:00
pri - > pvts [ chanpos ] - > exten [ 0 ] = ' s ' ;
pri - > pvts [ chanpos ] - > exten [ 1 ] = ' \0 ' ;
2003-06-03 16:24:12 +00:00
}
2002-03-08 23:48:42 +00:00
/* Get called number */
2004-05-05 04:23:18 +00:00
else if ( ! ast_strlen_zero ( e - > ring . callednum ) ) {
2005-05-15 23:26:45 +00:00
ast_copy_string ( pri - > pvts [ chanpos ] - > exten , e - > ring . callednum , sizeof ( pri - > pvts [ chanpos ] - > exten ) ) ;
ast_copy_string ( pri - > pvts [ chanpos ] - > dnid , e - > ring . callednum , sizeof ( pri - > pvts [ chanpos ] - > dnid ) ) ;
2004-05-02 03:39:17 +00:00
} else
2004-07-16 04:40:54 +00:00
pri - > pvts [ chanpos ] - > exten [ 0 ] = ' \0 ' ;
2005-05-11 15:03:11 +00:00
/* Set DNID on all incoming calls -- even immediate */
if ( ! ast_strlen_zero ( e - > ring . callednum ) )
2005-05-15 23:26:45 +00:00
ast_copy_string ( pri - > pvts [ chanpos ] - > dnid , e - > ring . callednum , sizeof ( pri - > pvts [ chanpos ] - > dnid ) ) ;
2003-09-13 23:57:48 +00:00
/* No number yet, but received "sending complete"? */
2004-05-05 04:23:18 +00:00
if ( e - > ring . complete & & ( ast_strlen_zero ( e - > ring . callednum ) ) ) {
2003-09-13 23:57:48 +00:00
if ( option_verbose > 2 )
ast_verbose ( VERBOSE_PREFIX_3 " Going to extension s|1 because of Complete received \n " ) ;
2004-07-16 04:40:54 +00:00
pri - > pvts [ chanpos ] - > exten [ 0 ] = ' s ' ;
pri - > pvts [ chanpos ] - > exten [ 1 ] = ' \0 ' ;
2003-09-13 23:57:48 +00:00
}
2004-05-02 03:39:17 +00:00
/* Make sure extension exists (or in overlap dial mode, can exist) */
2004-10-02 00:58:31 +00:00
if ( ( pri - > overlapdial & & ast_canmatch_extension ( NULL , pri - > pvts [ chanpos ] - > context , pri - > pvts [ chanpos ] - > exten , 1 , pri - > pvts [ chanpos ] - > cid_num ) ) | |
ast_exists_extension ( NULL , pri - > pvts [ chanpos ] - > context , pri - > pvts [ chanpos ] - > exten , 1 , pri - > pvts [ chanpos ] - > cid_num ) ) {
2002-03-08 23:48:42 +00:00
/* Setup law */
int law ;
2004-06-05 06:54:52 +00:00
if ( pri - > switchtype ! = PRI_SWITCH_GR303_TMC ) {
/* Set to audio mode at this point */
law = 1 ;
if ( ioctl ( pri - > pvts [ chanpos ] - > subs [ SUB_REAL ] . zfd , ZT_AUDIOMODE , & law ) = = - 1 )
ast_log ( LOG_WARNING , " Unable to set audio mode on channel %d to %d \n " , pri - > pvts [ chanpos ] - > channel , law ) ;
}
2002-03-08 23:48:42 +00:00
if ( e - > ring . layer1 = = PRI_LAYER_1_ALAW )
law = ZT_LAW_ALAW ;
2001-10-09 02:06:21 +00:00
else
2002-03-08 23:48:42 +00:00
law = ZT_LAW_MULAW ;
2004-06-05 06:54:52 +00:00
res = zt_setlaw ( pri - > pvts [ chanpos ] - > subs [ SUB_REAL ] . zfd , law ) ;
2002-03-08 23:48:42 +00:00
if ( res < 0 )
2004-06-05 06:54:52 +00:00
ast_log ( LOG_WARNING , " Unable to set law on channel %d \n " , pri - > pvts [ chanpos ] - > channel ) ;
res = set_actual_gain ( pri - > pvts [ chanpos ] - > subs [ SUB_REAL ] . zfd , 0 , pri - > pvts [ chanpos ] - > rxgain , pri - > pvts [ chanpos ] - > txgain , law ) ;
2003-02-07 19:23:19 +00:00
if ( res < 0 )
2004-06-05 06:54:52 +00:00
ast_log ( LOG_WARNING , " Unable to set gains on channel %d \n " , pri - > pvts [ chanpos ] - > channel ) ;
2005-05-24 15:30:10 +00:00
if ( e - > ring . complete | | ! pri - > overlapdial )
2004-05-19 15:40:01 +00:00
/* Just announce proceeding */
2004-06-05 06:54:52 +00:00
pri_proceeding ( pri - > pri , e - > ring . call , PVT_TO_CHANNEL ( pri - > pvts [ chanpos ] ) , 0 ) ;
2005-05-24 15:30:10 +00:00
else {
2004-06-05 06:54:52 +00:00
if ( pri - > switchtype ! = PRI_SWITCH_GR303_TMC )
pri_need_more_info ( pri - > pri , e - > ring . call , PVT_TO_CHANNEL ( pri - > pvts [ chanpos ] ) , 1 ) ;
else
pri_answer ( pri - > pri , e - > ring . call , PVT_TO_CHANNEL ( pri - > pvts [ chanpos ] ) , 1 ) ;
2003-09-25 06:14:38 +00:00
}
2003-10-01 15:59:26 +00:00
/* Get the use_callingpres state */
2004-06-05 06:54:52 +00:00
pri - > pvts [ chanpos ] - > callingpres = e - > ring . callingpres ;
2005-02-04 06:12:32 +00:00
2003-10-01 15:59:26 +00:00
/* Start PBX */
2004-10-02 00:58:31 +00:00
if ( pri - > overlapdial & & ast_matchmore_extension ( NULL , pri - > pvts [ chanpos ] - > context , pri - > pvts [ chanpos ] - > exten , 1 , pri - > pvts [ chanpos ] - > cid_num ) ) {
2004-05-27 16:50:07 +00:00
/* Release the PRI lock while we create the channel */
ast_mutex_unlock ( & pri - > lock ) ;
2004-06-06 01:54:22 +00:00
if ( crv ) {
/* Set bearer and such */
pri_assign_bearer ( crv , pri , pri - > pvts [ chanpos ] ) ;
c = zt_new ( crv , AST_STATE_RESERVED , 0 , SUB_REAL , law , e - > ring . ctype ) ;
pri - > pvts [ chanpos ] - > owner = & inuse ;
ast_log ( LOG_DEBUG , " Started up crv %d:%d on bearer channel %d \n " , pri - > trunkgroup , crv - > channel , crv - > bearer - > channel ) ;
} else {
c = zt_new ( pri - > pvts [ chanpos ] , AST_STATE_RESERVED , 0 , SUB_REAL , law , e - > ring . ctype ) ;
}
2005-02-04 06:12:32 +00:00
if ( ! ast_strlen_zero ( e - > ring . callingsubaddr ) ) {
2004-06-25 19:33:27 +00:00
pbx_builtin_setvar_helper ( c , " CALLINGSUBADDR " , e - > ring . callingsubaddr ) ;
}
2004-11-07 18:59:20 +00:00
if ( e - > ring . ani2 > = 0 ) {
2004-11-16 16:57:08 +00:00
snprintf ( ani2str , 5 , " %.2d " , e - > ring . ani2 ) ;
2004-11-07 18:59:20 +00:00
pbx_builtin_setvar_helper ( c , " ANI2 " , ani2str ) ;
}
2005-02-04 06:12:32 +00:00
if ( ! ast_strlen_zero ( e - > ring . useruserinfo ) ) {
pbx_builtin_setvar_helper ( c , " USERUSERINFO " , e - > ring . useruserinfo ) ;
}
snprintf ( calledtonstr , sizeof ( calledtonstr ) - 1 , " %d " , e - > ring . calledplan ) ;
pbx_builtin_setvar_helper ( c , " CALLEDTON " , calledtonstr ) ;
2005-06-29 21:47:44 +00:00
if ( e - > ring . redirectingreason > = 0 )
2005-07-13 15:13:12 +00:00
pbx_builtin_setvar_helper ( c , " PRIREDIRECTREASON " , redirectingreason2str ( e - > ring . redirectingreason ) ) ;
2004-12-15 19:59:53 +00:00
2004-05-27 16:50:07 +00:00
ast_mutex_lock ( & pri - > lock ) ;
2004-08-08 17:15:02 +00:00
if ( c & & ! ast_pthread_create ( & threadid , & attr , ss_thread , c ) ) {
2004-05-02 03:39:17 +00:00
if ( option_verbose > 2 )
2004-06-05 06:54:52 +00:00
ast_verbose ( VERBOSE_PREFIX_3 " Accepting overlap call from '%s' to '%s' on channel %d/%d, span %d \n " ,
2005-02-04 06:12:32 +00:00
plancallingnum , ! ast_strlen_zero ( pri - > pvts [ chanpos ] - > exten ) ? pri - > pvts [ chanpos ] - > exten : " <unspecified> " ,
2004-06-06 22:51:37 +00:00
pri - > pvts [ chanpos ] - > logicalspan , pri - > pvts [ chanpos ] - > prioffset , pri - > span ) ;
2004-05-02 03:39:17 +00:00
} else {
2004-06-05 06:54:52 +00:00
ast_log ( LOG_WARNING , " Unable to start PBX on channel %d/%d, span %d \n " ,
2004-06-06 22:51:37 +00:00
pri - > pvts [ chanpos ] - > logicalspan , pri - > pvts [ chanpos ] - > prioffset , pri - > span ) ;
2004-05-02 03:39:17 +00:00
if ( c )
ast_hangup ( c ) ;
else {
pri_hangup ( pri - > pri , e - > ring . call , PRI_CAUSE_SWITCH_CONGESTION ) ;
2004-06-05 06:54:52 +00:00
pri - > pvts [ chanpos ] - > call = NULL ;
2004-05-02 03:39:17 +00:00
}
}
} else {
2004-05-27 16:50:07 +00:00
ast_mutex_unlock ( & pri - > lock ) ;
/* Release PRI lock while we create the channel */
2004-06-05 06:54:52 +00:00
c = zt_new ( pri - > pvts [ chanpos ] , AST_STATE_RING , 1 , SUB_REAL , law , e - > ring . ctype ) ;
2004-05-27 16:50:07 +00:00
ast_mutex_lock ( & pri - > lock ) ;
2004-05-02 03:39:17 +00:00
if ( c ) {
2005-02-10 17:40:06 +00:00
char calledtonstr [ 10 ] ;
2004-11-07 18:59:20 +00:00
if ( e - > ring . ani2 > = 0 ) {
snprintf ( ani2str , 5 , " %d " , e - > ring . ani2 ) ;
pbx_builtin_setvar_helper ( c , " ANI2 " , ani2str ) ;
}
2005-02-04 06:12:32 +00:00
if ( ! ast_strlen_zero ( e - > ring . useruserinfo ) ) {
pbx_builtin_setvar_helper ( c , " USERUSERINFO " , e - > ring . useruserinfo ) ;
}
2005-06-29 21:47:44 +00:00
if ( e - > ring . redirectingreason > = 0 )
pbx_builtin_setvar_helper ( c , " PRIREDIRECTCAUSE " , redirectingreason2str ( e - > ring . redirectingreason ) ) ;
2005-02-04 06:12:32 +00:00
snprintf ( calledtonstr , sizeof ( calledtonstr ) - 1 , " %d " , e - > ring . calledplan ) ;
pbx_builtin_setvar_helper ( c , " CALLEDTON " , calledtonstr ) ;
2004-05-02 03:39:17 +00:00
if ( option_verbose > 2 )
2004-06-05 06:54:52 +00:00
ast_verbose ( VERBOSE_PREFIX_3 " Accepting call from '%s' to '%s' on channel %d/%d, span %d \n " ,
2005-02-04 06:12:32 +00:00
plancallingnum , pri - > pvts [ chanpos ] - > exten ,
2004-06-06 22:51:37 +00:00
pri - > pvts [ chanpos ] - > logicalspan , pri - > pvts [ chanpos ] - > prioffset , pri - > span ) ;
2004-06-05 06:54:52 +00:00
zt_enable_ec ( pri - > pvts [ chanpos ] ) ;
2004-05-02 03:39:17 +00:00
} else {
2004-06-05 06:54:52 +00:00
ast_log ( LOG_WARNING , " Unable to start PBX on channel %d/%d, span %d \n " ,
2004-06-06 22:51:37 +00:00
pri - > pvts [ chanpos ] - > logicalspan , pri - > pvts [ chanpos ] - > prioffset , pri - > span ) ;
2004-05-02 03:39:17 +00:00
pri_hangup ( pri - > pri , e - > ring . call , PRI_CAUSE_SWITCH_CONGESTION ) ;
2004-06-05 06:54:52 +00:00
pri - > pvts [ chanpos ] - > call = NULL ;
2004-05-02 03:39:17 +00:00
}
2001-10-09 02:06:21 +00:00
}
2002-03-08 23:48:42 +00:00
} else {
2004-05-02 03:39:17 +00:00
if ( option_verbose > 2 )
2004-06-05 06:54:52 +00:00
ast_verbose ( VERBOSE_PREFIX_3 " Extension '%s' in context '%s' from '%s' does not exist. Rejecting call on channel %d/%d, span %d \n " ,
2004-10-02 00:58:31 +00:00
pri - > pvts [ chanpos ] - > exten , pri - > pvts [ chanpos ] - > context , pri - > pvts [ chanpos ] - > cid_num , pri - > pvts [ chanpos ] - > logicalspan ,
2004-06-05 06:54:52 +00:00
pri - > pvts [ chanpos ] - > prioffset , pri - > span ) ;
2004-05-02 03:39:17 +00:00
pri_hangup ( pri - > pri , e - > ring . call , PRI_CAUSE_UNALLOCATED ) ;
2004-06-05 06:54:52 +00:00
pri - > pvts [ chanpos ] - > call = NULL ;
2001-10-09 02:06:21 +00:00
}
2004-06-17 04:23:57 +00:00
if ( crv )
ast_mutex_unlock ( & crv - > lock ) ;
ast_mutex_unlock ( & pri - > pvts [ chanpos ] - > lock ) ;
2002-03-08 23:48:42 +00:00
} else
2003-08-05 01:25:43 +00:00
pri_hangup ( pri - > pri , e - > ring . call , PRI_CAUSE_REQUESTED_CHAN_UNAVAIL ) ;
2002-03-08 23:48:42 +00:00
break ;
case PRI_EVENT_RINGING :
2004-06-05 06:54:52 +00:00
chanpos = pri_find_principle ( pri , e - > ringing . channel ) ;
if ( chanpos < 0 ) {
ast_log ( LOG_WARNING , " Ringing requested on unconfigured channel %d/%d span %d \n " ,
PRI_SPAN ( e - > ringing . channel ) , PRI_CHANNEL ( e - > ringing . channel ) , pri - > span ) ;
chanpos = - 1 ;
2002-03-08 23:48:42 +00:00
}
2004-06-05 06:54:52 +00:00
if ( chanpos > - 1 ) {
chanpos = pri_fixup_principle ( pri , chanpos , e - > ringing . call ) ;
if ( chanpos < 0 ) {
ast_log ( LOG_WARNING , " Ringing requested on channel %d/%d not in use on span %d \n " ,
PRI_SPAN ( e - > ringing . channel ) , PRI_CHANNEL ( e - > ringing . channel ) , pri - > span ) ;
chanpos = - 1 ;
2004-06-17 04:23:57 +00:00
} else {
ast_mutex_lock ( & pri - > pvts [ chanpos ] - > lock ) ;
if ( ast_strlen_zero ( pri - > pvts [ chanpos ] - > dop . dialstr ) ) {
zt_enable_ec ( pri - > pvts [ chanpos ] ) ;
pri - > pvts [ chanpos ] - > subs [ SUB_REAL ] . needringing = 1 ;
pri - > pvts [ chanpos ] - > proceeding = 2 ;
} else
ast_log ( LOG_DEBUG , " Deferring ringing notification because of extra digits to dial... \n " ) ;
2005-01-21 04:48:15 +00:00
# ifdef PRI_PROGRESS_MASK
if ( e - > ringing . progressmask & PRI_PROG_INBAND_AVAILABLE ) {
# else
if ( e - > ringing . progress = = 8 ) {
# endif
/* Now we can do call progress detection */
if ( pri - > pvts [ chanpos ] - > dsp & & pri - > pvts [ chanpos ] - > dsp_features ) {
/* RINGING detection isn't required because we got ALERTING signal */
ast_dsp_set_features ( pri - > pvts [ chanpos ] - > dsp , pri - > pvts [ chanpos ] - > dsp_features & ~ DSP_PROGRESS_RINGING ) ;
pri - > pvts [ chanpos ] - > dsp_features = 0 ;
}
}
2004-06-17 04:23:57 +00:00
ast_mutex_unlock ( & pri - > pvts [ chanpos ] - > lock ) ;
}
2003-02-07 19:23:19 +00:00
}
2004-06-14 21:18:52 +00:00
break ;
2004-06-14 21:40:02 +00:00
case PRI_EVENT_PROGRESS :
2003-05-19 23:33:41 +00:00
/* Get chan value if e->e is not PRI_EVNT_RINGING */
2004-06-14 21:40:02 +00:00
chanpos = pri_find_principle ( pri , e - > proceeding . channel ) ;
if ( chanpos > - 1 ) {
2005-03-27 22:48:55 +00:00
# ifdef PRI_PROGRESS_MASK
2005-07-10 16:05:59 +00:00
if ( ( ! pri - > pvts [ chanpos ] - > proceeding ) | | ( e - > proceeding . progressmask & PRI_PROG_INBAND_AVAILABLE ) ) {
2005-03-27 22:48:55 +00:00
# else
2005-07-10 16:05:59 +00:00
if ( ( ! pri - > pvts [ chanpos ] - > proceeding ) | | ( e - > proceeding . progress = = 8 ) ) {
2005-03-27 22:48:55 +00:00
# endif
2004-06-14 21:40:02 +00:00
struct ast_frame f = { AST_FRAME_CONTROL , AST_CONTROL_PROGRESS , } ;
2005-06-29 21:47:44 +00:00
if ( e - > proceeding . cause > - 1 ) {
if ( option_verbose > 2 )
ast_verbose ( VERBOSE_PREFIX_3 " PROGRESS with cause code %d received \n " , e - > proceeding . cause ) ;
/* Work around broken, out of spec USER_BUSY cause in a progress message */
if ( e - > proceeding . cause = = AST_CAUSE_USER_BUSY ) {
if ( pri - > pvts [ chanpos ] - > owner ) {
if ( option_verbose > 2 )
ast_verbose ( VERBOSE_PREFIX_3 " PROGRESS with 'user busy' received, signaling AST_CONTROL_BUSY instead of AST_CONTROL_PROGRESS \n " ) ;
pri - > pvts [ chanpos ] - > owner - > hangupcause = e - > proceeding . cause ;
f . subclass = AST_CONTROL_BUSY ;
}
}
}
2004-06-17 04:23:57 +00:00
ast_mutex_lock ( & pri - > pvts [ chanpos ] - > lock ) ;
ast_log ( LOG_DEBUG , " Queuing frame from PRI_EVENT_PROGRESS on channel %d/%d span %d \n " ,
2004-06-14 21:40:02 +00:00
pri - > pvts [ chanpos ] - > logicalspan , pri - > pvts [ chanpos ] - > prioffset , pri - > span ) ;
2005-01-21 04:48:15 +00:00
zap_queue_frame ( pri - > pvts [ chanpos ] , & f , pri ) ;
# ifdef PRI_PROGRESS_MASK
if ( e - > proceeding . progressmask & PRI_PROG_INBAND_AVAILABLE ) {
# else
if ( e - > proceeding . progress = = 8 ) {
# endif
/* Now we can do call progress detection */
if ( pri - > pvts [ chanpos ] - > dsp & & pri - > pvts [ chanpos ] - > dsp_features ) {
ast_dsp_set_features ( pri - > pvts [ chanpos ] - > dsp , pri - > pvts [ chanpos ] - > dsp_features ) ;
pri - > pvts [ chanpos ] - > dsp_features = 0 ;
}
}
2004-06-17 04:23:57 +00:00
ast_mutex_unlock ( & pri - > pvts [ chanpos ] - > lock ) ;
2004-06-14 21:40:02 +00:00
}
}
break ;
case PRI_EVENT_PROCEEDING :
chanpos = pri_find_principle ( pri , e - > proceeding . channel ) ;
2004-06-05 06:54:52 +00:00
if ( chanpos > - 1 ) {
2005-07-10 16:05:59 +00:00
if ( ! pri - > pvts [ chanpos ] - > proceeding ) {
2005-03-27 22:48:55 +00:00
struct ast_frame f = { AST_FRAME_CONTROL , AST_CONTROL_PROCEEDING , } ;
2004-06-17 04:23:57 +00:00
ast_mutex_lock ( & pri - > pvts [ chanpos ] - > lock ) ;
ast_log ( LOG_DEBUG , " Queuing frame from PRI_EVENT_PROCEEDING on channel %d/%d span %d \n " ,
2004-06-06 22:51:37 +00:00
pri - > pvts [ chanpos ] - > logicalspan , pri - > pvts [ chanpos ] - > prioffset , pri - > span ) ;
2004-09-10 18:47:13 +00:00
zap_queue_frame ( pri - > pvts [ chanpos ] , & f , pri ) ;
2005-01-21 04:48:15 +00:00
# ifdef PRI_PROGRESS_MASK
if ( e - > proceeding . progressmask & PRI_PROG_INBAND_AVAILABLE ) {
# else
if ( e - > proceeding . progress = = 8 ) {
# endif
/* Now we can do call progress detection */
if ( pri - > pvts [ chanpos ] - > dsp & & pri - > pvts [ chanpos ] - > dsp_features ) {
ast_dsp_set_features ( pri - > pvts [ chanpos ] - > dsp , pri - > pvts [ chanpos ] - > dsp_features ) ;
pri - > pvts [ chanpos ] - > dsp_features = 0 ;
}
2005-03-27 22:48:55 +00:00
/* Bring voice path up */
f . subclass = AST_CONTROL_PROGRESS ;
zap_queue_frame ( pri - > pvts [ chanpos ] , & f , pri ) ;
2005-01-21 04:48:15 +00:00
}
2004-06-17 04:23:57 +00:00
ast_mutex_unlock ( & pri - > pvts [ chanpos ] - > lock ) ;
2004-06-05 06:54:52 +00:00
}
}
2003-05-19 23:33:41 +00:00
break ;
2003-02-07 19:23:19 +00:00
case PRI_EVENT_FACNAME :
2004-06-05 06:54:52 +00:00
chanpos = pri_find_principle ( pri , e - > facname . channel ) ;
if ( chanpos < 0 ) {
ast_log ( LOG_WARNING , " Facility Name requested on unconfigured channel %d/%d span %d \n " ,
PRI_SPAN ( e - > facname . channel ) , PRI_CHANNEL ( e - > facname . channel ) , pri - > span ) ;
chanpos = - 1 ;
2003-02-07 19:23:19 +00:00
}
2004-06-05 06:54:52 +00:00
if ( chanpos > - 1 ) {
chanpos = pri_fixup_principle ( pri , chanpos , e - > facname . call ) ;
if ( chanpos < 0 ) {
ast_log ( LOG_WARNING , " Facility Name requested on channel %d/%d not in use on span %d \n " ,
PRI_SPAN ( e - > facname . channel ) , PRI_CHANNEL ( e - > facname . channel ) , pri - > span ) ;
chanpos = - 1 ;
2003-02-07 19:23:19 +00:00
} else {
/* Re-use *69 field for PRI */
2004-06-17 04:23:57 +00:00
ast_mutex_lock ( & pri - > pvts [ chanpos ] - > lock ) ;
2005-05-15 23:26:45 +00:00
ast_copy_string ( pri - > pvts [ chanpos ] - > lastcid_num , e - > facname . callingnum , sizeof ( pri - > pvts [ chanpos ] - > lastcid_num ) ) ;
ast_copy_string ( pri - > pvts [ chanpos ] - > lastcid_name , e - > facname . callingname , sizeof ( pri - > pvts [ chanpos ] - > lastcid_name ) ) ;
2004-06-05 06:54:52 +00:00
pri - > pvts [ chanpos ] - > subs [ SUB_REAL ] . needcallerid = 1 ;
zt_enable_ec ( pri - > pvts [ chanpos ] ) ;
2004-06-17 04:23:57 +00:00
ast_mutex_unlock ( & pri - > pvts [ chanpos ] - > lock ) ;
2003-02-07 19:23:19 +00:00
}
2002-03-08 23:48:42 +00:00
}
break ;
case PRI_EVENT_ANSWER :
2004-06-05 06:54:52 +00:00
chanpos = pri_find_principle ( pri , e - > answer . channel ) ;
if ( chanpos < 0 ) {
ast_log ( LOG_WARNING , " Answer on unconfigured channel %d/%d span %d \n " ,
PRI_SPAN ( e - > answer . channel ) , PRI_CHANNEL ( e - > answer . channel ) , pri - > span ) ;
chanpos = - 1 ;
2002-03-08 23:48:42 +00:00
}
2004-06-05 06:54:52 +00:00
if ( chanpos > - 1 ) {
chanpos = pri_fixup_principle ( pri , chanpos , e - > answer . call ) ;
if ( chanpos < 0 ) {
ast_log ( LOG_WARNING , " Answer requested on channel %d/%d not in use on span %d \n " ,
PRI_SPAN ( e - > answer . channel ) , PRI_CHANNEL ( e - > answer . channel ) , pri - > span ) ;
chanpos = - 1 ;
2003-02-07 19:23:19 +00:00
} else {
2004-06-17 04:23:57 +00:00
ast_mutex_lock ( & pri - > pvts [ chanpos ] - > lock ) ;
2005-05-16 19:15:56 +00:00
/* Now we can do call progress detection */
/* We changed this so it turns on the DSP no matter what... progress or no progress.
* By this time , we need DTMF detection and other features that were previously disabled
* - - Matt F */
if ( pri - > pvts [ chanpos ] - > dsp & & pri - > pvts [ chanpos ] - > dsp_features ) {
ast_dsp_set_features ( pri - > pvts [ chanpos ] - > dsp , pri - > pvts [ chanpos ] - > dsp_features ) ;
pri - > pvts [ chanpos ] - > dsp_features = 0 ;
2005-01-21 04:48:15 +00:00
}
2004-12-13 15:11:36 +00:00
if ( pri - > pvts [ chanpos ] - > realcall & & ( pri - > pvts [ chanpos ] - > realcall - > sig = = SIG_FXSKS ) ) {
2004-07-19 02:18:11 +00:00
ast_log ( LOG_DEBUG , " Starting up GR-303 trunk now that we got CONNECT... \n " ) ;
x = ZT_START ;
res = ioctl ( pri - > pvts [ chanpos ] - > subs [ SUB_REAL ] . zfd , ZT_HOOK , & x ) ;
if ( res < 0 ) {
if ( errno ! = EINPROGRESS ) {
ast_log ( LOG_WARNING , " Unable to start channel: %s \n " , strerror ( errno ) ) ;
}
}
} else if ( ! ast_strlen_zero ( pri - > pvts [ chanpos ] - > dop . dialstr ) ) {
2004-06-05 06:54:52 +00:00
pri - > pvts [ chanpos ] - > dialing = 1 ;
2003-02-07 19:23:19 +00:00
/* Send any "w" waited stuff */
2004-06-05 06:54:52 +00:00
res = ioctl ( pri - > pvts [ chanpos ] - > subs [ SUB_REAL ] . zfd , ZT_DIAL , & pri - > pvts [ chanpos ] - > dop ) ;
2003-02-07 19:23:19 +00:00
if ( res < 0 ) {
2004-06-05 06:54:52 +00:00
ast_log ( LOG_WARNING , " Unable to initiate dialing on trunk channel %d \n " , pri - > pvts [ chanpos ] - > channel ) ;
pri - > pvts [ chanpos ] - > dop . dialstr [ 0 ] = ' \0 ' ;
2003-02-07 19:23:19 +00:00
} else
2004-06-05 06:54:52 +00:00
ast_log ( LOG_DEBUG , " Sent deferred digit string: %s \n " , pri - > pvts [ chanpos ] - > dop . dialstr ) ;
pri - > pvts [ chanpos ] - > dop . dialstr [ 0 ] = ' \0 ' ;
2004-07-16 20:51:54 +00:00
} else if ( pri - > pvts [ chanpos ] - > confirmanswer ) {
ast_log ( LOG_DEBUG , " Waiting on answer confirmation on channel %d! \n " , pri - > pvts [ chanpos ] - > channel ) ;
} else {
2004-06-05 06:54:52 +00:00
pri - > pvts [ chanpos ] - > subs [ SUB_REAL ] . needanswer = 1 ;
2004-07-16 20:51:54 +00:00
/* Enable echo cancellation if it's not on already */
zt_enable_ec ( pri - > pvts [ chanpos ] ) ;
}
2004-06-17 04:23:57 +00:00
ast_mutex_unlock ( & pri - > pvts [ chanpos ] - > lock ) ;
2003-02-07 19:23:19 +00:00
}
2002-03-08 23:48:42 +00:00
}
break ;
case PRI_EVENT_HANGUP :
2004-06-05 06:54:52 +00:00
chanpos = pri_find_principle ( pri , e - > hangup . channel ) ;
if ( chanpos < 0 ) {
ast_log ( LOG_WARNING , " Hangup requested on unconfigured channel %d/%d span %d \n " ,
PRI_SPAN ( e - > hangup . channel ) , PRI_CHANNEL ( e - > hangup . channel ) , pri - > span ) ;
chanpos = - 1 ;
2002-03-08 23:48:42 +00:00
}
2004-06-05 06:54:52 +00:00
if ( chanpos > - 1 ) {
chanpos = pri_fixup_principle ( pri , chanpos , e - > hangup . call ) ;
if ( chanpos > - 1 ) {
ast_mutex_lock ( & pri - > pvts [ chanpos ] - > lock ) ;
if ( ! pri - > pvts [ chanpos ] - > alreadyhungup ) {
2003-08-07 00:47:27 +00:00
/* we're calling here zt_hangup so once we get there we need to clear p->call after calling pri_hangup */
2004-06-05 06:54:52 +00:00
pri - > pvts [ chanpos ] - > alreadyhungup = 1 ;
2004-12-13 15:11:36 +00:00
if ( pri - > pvts [ chanpos ] - > realcall )
pri_hangup_all ( pri - > pvts [ chanpos ] - > realcall , pri ) ;
2004-06-06 01:54:22 +00:00
else if ( pri - > pvts [ chanpos ] - > owner ) {
/* Queue a BUSY instead of a hangup if our cause is appropriate */
2004-08-12 22:09:18 +00:00
pri - > pvts [ chanpos ] - > owner - > hangupcause = e - > hangup . cause ;
2004-01-31 18:46:59 +00:00
switch ( e - > hangup . cause ) {
case PRI_CAUSE_USER_BUSY :
2004-06-05 06:54:52 +00:00
pri - > pvts [ chanpos ] - > subs [ SUB_REAL ] . needbusy = 1 ;
2004-01-31 18:46:59 +00:00
break ;
case PRI_CAUSE_CALL_REJECTED :
case PRI_CAUSE_NETWORK_OUT_OF_ORDER :
case PRI_CAUSE_NORMAL_CIRCUIT_CONGESTION :
case PRI_CAUSE_SWITCH_CONGESTION :
case PRI_CAUSE_DESTINATION_OUT_OF_ORDER :
case PRI_CAUSE_NORMAL_TEMPORARY_FAILURE :
2004-06-05 06:54:52 +00:00
pri - > pvts [ chanpos ] - > subs [ SUB_REAL ] . needcongestion = 1 ;
2004-01-31 18:46:59 +00:00
break ;
default :
2004-06-05 06:54:52 +00:00
pri - > pvts [ chanpos ] - > owner - > _softhangup | = AST_SOFTHANGUP_DEV ;
2004-01-31 18:46:59 +00:00
}
}
2002-06-24 17:59:56 +00:00
if ( option_verbose > 2 )
2004-06-05 06:54:52 +00:00
ast_verbose ( VERBOSE_PREFIX_3 " Channel %d/%d, span %d got hangup \n " ,
2004-06-06 22:51:37 +00:00
pri - > pvts [ chanpos ] - > logicalspan , pri - > pvts [ chanpos ] - > prioffset , pri - > span ) ;
2003-08-07 00:47:27 +00:00
} else {
2004-06-05 06:54:52 +00:00
pri_hangup ( pri - > pri , pri - > pvts [ chanpos ] - > call , e - > hangup . cause ) ;
pri - > pvts [ chanpos ] - > call = NULL ;
2001-10-09 02:06:21 +00:00
}
2002-06-24 17:59:56 +00:00
if ( e - > hangup . cause = = PRI_CAUSE_REQUESTED_CHAN_UNAVAIL ) {
if ( option_verbose > 2 )
2004-06-05 06:54:52 +00:00
ast_verbose ( VERBOSE_PREFIX_3 " Forcing restart of channel %d/%d on span %d since channel reported in use \n " ,
PRI_SPAN ( e - > hangup . channel ) , PRI_CHANNEL ( e - > hangup . channel ) , pri - > span ) ;
pri_reset ( pri - > pri , PVT_TO_CHANNEL ( pri - > pvts [ chanpos ] ) ) ;
pri - > pvts [ chanpos ] - > resetting = 1 ;
2002-06-24 17:59:56 +00:00
}
2005-04-05 20:23:26 +00:00
if ( e - > hangup . aoc_units > - 1 )
if ( option_verbose > 2 )
2005-04-29 17:00:33 +00:00
ast_verbose ( VERBOSE_PREFIX_3 " Channel %d/%d, span %d received AOC-E charging %d unit%s \n " ,
2005-04-05 20:23:26 +00:00
pri - > pvts [ chanpos ] - > logicalspan , pri - > pvts [ chanpos ] - > prioffset , pri - > span , ( int ) e - > hangup . aoc_units , ( e - > hangup . aoc_units = = 1 ) ? " " : " s " ) ;
2004-06-05 06:54:52 +00:00
ast_mutex_unlock ( & pri - > pvts [ chanpos ] - > lock ) ;
2002-03-08 23:48:42 +00:00
} else {
2004-06-05 06:54:52 +00:00
ast_log ( LOG_WARNING , " Hangup on bad channel %d/%d on span %d \n " ,
PRI_SPAN ( e - > hangup . channel ) , PRI_CHANNEL ( e - > hangup . channel ) , pri - > span ) ;
2003-08-07 00:47:27 +00:00
}
}
break ;
# ifndef PRI_EVENT_HANGUP_REQ
# error please update libpri
# endif
case PRI_EVENT_HANGUP_REQ :
2004-06-05 06:54:52 +00:00
chanpos = pri_find_principle ( pri , e - > hangup . channel ) ;
if ( chanpos < 0 ) {
ast_log ( LOG_WARNING , " Hangup REQ requested on unconfigured channel %d/%d span %d \n " ,
PRI_SPAN ( e - > hangup . channel ) , PRI_CHANNEL ( e - > hangup . channel ) , pri - > span ) ;
chanpos = - 1 ;
2003-08-07 00:47:27 +00:00
}
2004-06-05 06:54:52 +00:00
if ( chanpos > - 1 ) {
chanpos = pri_fixup_principle ( pri , chanpos , e - > hangup . call ) ;
if ( chanpos > - 1 ) {
ast_mutex_lock ( & pri - > pvts [ chanpos ] - > lock ) ;
2004-12-13 15:11:36 +00:00
if ( pri - > pvts [ chanpos ] - > realcall )
pri_hangup_all ( pri - > pvts [ chanpos ] - > realcall , pri ) ;
2004-06-06 01:54:22 +00:00
else if ( pri - > pvts [ chanpos ] - > owner ) {
2004-08-12 22:09:18 +00:00
pri - > pvts [ chanpos ] - > owner - > hangupcause = e - > hangup . cause ;
2004-01-31 19:38:22 +00:00
switch ( e - > hangup . cause ) {
case PRI_CAUSE_USER_BUSY :
2004-06-05 06:54:52 +00:00
pri - > pvts [ chanpos ] - > subs [ SUB_REAL ] . needbusy = 1 ;
2004-03-22 19:47:25 +00:00
break ;
2004-01-31 19:38:22 +00:00
case PRI_CAUSE_CALL_REJECTED :
case PRI_CAUSE_NETWORK_OUT_OF_ORDER :
case PRI_CAUSE_NORMAL_CIRCUIT_CONGESTION :
case PRI_CAUSE_SWITCH_CONGESTION :
case PRI_CAUSE_DESTINATION_OUT_OF_ORDER :
case PRI_CAUSE_NORMAL_TEMPORARY_FAILURE :
2004-06-05 06:54:52 +00:00
pri - > pvts [ chanpos ] - > subs [ SUB_REAL ] . needcongestion = 1 ;
2004-01-31 19:38:22 +00:00
break ;
default :
2004-06-05 06:54:52 +00:00
pri - > pvts [ chanpos ] - > owner - > _softhangup | = AST_SOFTHANGUP_DEV ;
2004-01-31 19:38:22 +00:00
}
2003-08-07 00:47:27 +00:00
if ( option_verbose > 2 )
2005-04-05 20:23:26 +00:00
ast_verbose ( VERBOSE_PREFIX_3 " Channel %d/%d, span %d got hangup request \n " , PRI_SPAN ( e - > hangup . channel ) , PRI_CHANNEL ( e - > hangup . channel ) , pri - > span ) ;
if ( e - > hangup . aoc_units > - 1 )
if ( option_verbose > 2 )
2005-04-29 17:00:33 +00:00
ast_verbose ( VERBOSE_PREFIX_3 " Channel %d/%d, span %d received AOC-E charging %d unit%s \n " ,
2005-04-05 20:23:26 +00:00
pri - > pvts [ chanpos ] - > logicalspan , pri - > pvts [ chanpos ] - > prioffset , pri - > span , ( int ) e - > hangup . aoc_units , ( e - > hangup . aoc_units = = 1 ) ? " " : " s " ) ;
2003-09-25 06:14:38 +00:00
} else {
2004-06-05 06:54:52 +00:00
pri_hangup ( pri - > pri , pri - > pvts [ chanpos ] - > call , e - > hangup . cause ) ;
pri - > pvts [ chanpos ] - > call = NULL ;
2003-08-07 00:47:27 +00:00
}
if ( e - > hangup . cause = = PRI_CAUSE_REQUESTED_CHAN_UNAVAIL ) {
if ( option_verbose > 2 )
2004-06-05 06:54:52 +00:00
ast_verbose ( VERBOSE_PREFIX_3 " Forcing restart of channel %d/%d span %d since channel reported in use \n " ,
PRI_SPAN ( e - > hangup . channel ) , PRI_CHANNEL ( e - > hangup . channel ) , pri - > span ) ;
pri_reset ( pri - > pri , PVT_TO_CHANNEL ( pri - > pvts [ chanpos ] ) ) ;
pri - > pvts [ chanpos ] - > resetting = 1 ;
2003-08-07 00:47:27 +00:00
}
2004-06-05 06:54:52 +00:00
ast_mutex_unlock ( & pri - > pvts [ chanpos ] - > lock ) ;
2003-08-07 00:47:27 +00:00
} else {
2004-06-05 06:54:52 +00:00
ast_log ( LOG_WARNING , " Hangup REQ on bad channel %d/%d on span %d \n " , PRI_SPAN ( e - > hangup . channel ) , PRI_CHANNEL ( e - > hangup . channel ) , pri - > span ) ;
2001-10-09 02:06:21 +00:00
}
2002-03-08 23:48:42 +00:00
}
break ;
case PRI_EVENT_HANGUP_ACK :
2004-06-05 06:54:52 +00:00
chanpos = pri_find_principle ( pri , e - > hangup . channel ) ;
if ( chanpos < 0 ) {
ast_log ( LOG_WARNING , " Hangup ACK requested on unconfigured channel number %d/%d span %d \n " ,
PRI_SPAN ( e - > hangup . channel ) , PRI_CHANNEL ( e - > hangup . channel ) , pri - > span ) ;
chanpos = - 1 ;
2002-03-08 23:48:42 +00:00
}
2004-06-05 06:54:52 +00:00
if ( chanpos > - 1 ) {
chanpos = pri_fixup_principle ( pri , chanpos , e - > hangup . call ) ;
if ( chanpos > - 1 ) {
ast_mutex_lock ( & pri - > pvts [ chanpos ] - > lock ) ;
pri - > pvts [ chanpos ] - > call = NULL ;
pri - > pvts [ chanpos ] - > resetting = 0 ;
if ( pri - > pvts [ chanpos ] - > owner ) {
2002-06-24 17:59:56 +00:00
if ( option_verbose > 2 )
2004-06-05 06:54:52 +00:00
ast_verbose ( VERBOSE_PREFIX_3 " Channel %d/%d, span %d got hangup ACK \n " , PRI_SPAN ( e - > hangup . channel ) , PRI_CHANNEL ( e - > hangup . channel ) , pri - > span ) ;
2001-10-09 02:06:21 +00:00
}
2004-06-05 06:54:52 +00:00
ast_mutex_unlock ( & pri - > pvts [ chanpos ] - > lock ) ;
2001-10-09 02:06:21 +00:00
}
}
2002-03-08 23:48:42 +00:00
break ;
case PRI_EVENT_CONFIG_ERR :
ast_log ( LOG_WARNING , " PRI Error: %s \n " , e - > err . err ) ;
break ;
2002-06-24 17:59:56 +00:00
case PRI_EVENT_RESTART_ACK :
2004-06-05 06:54:52 +00:00
chanpos = pri_find_principle ( pri , e - > restartack . channel ) ;
if ( chanpos < 0 ) {
2003-02-07 19:23:19 +00:00
/* Sometime switches (e.g. I421 / British Telecom) don't give us the
channel number , so we have to figure it out . . . This must be why
everybody resets exactly a channel at a time . */
2004-06-05 07:07:12 +00:00
for ( x = 0 ; x < pri - > numchans ; x + + ) {
2004-06-05 06:54:52 +00:00
if ( pri - > pvts [ x ] & & pri - > pvts [ x ] - > resetting ) {
chanpos = x ;
ast_mutex_lock ( & pri - > pvts [ chanpos ] - > lock ) ;
2004-06-06 22:51:37 +00:00
ast_log ( LOG_DEBUG , " Assuming restart ack is really for channel %d/%d span %d \n " , pri - > pvts [ chanpos ] - > logicalspan ,
2004-06-05 06:54:52 +00:00
pri - > pvts [ chanpos ] - > prioffset , pri - > span ) ;
2004-12-13 15:11:36 +00:00
if ( pri - > pvts [ chanpos ] - > realcall )
pri_hangup_all ( pri - > pvts [ chanpos ] - > realcall , pri ) ;
2004-06-06 01:54:22 +00:00
else if ( pri - > pvts [ chanpos ] - > owner ) {
2004-06-06 22:51:37 +00:00
ast_log ( LOG_WARNING , " Got restart ack on channel %d/%d with owner on span %d \n " , pri - > pvts [ chanpos ] - > logicalspan ,
2004-06-05 06:54:52 +00:00
pri - > pvts [ chanpos ] - > prioffset , pri - > span ) ;
pri - > pvts [ chanpos ] - > owner - > _softhangup | = AST_SOFTHANGUP_DEV ;
2003-02-07 19:23:19 +00:00
}
2004-06-05 06:54:52 +00:00
pri - > pvts [ chanpos ] - > resetting = 0 ;
2003-02-07 19:23:19 +00:00
if ( option_verbose > 2 )
2004-06-06 22:51:37 +00:00
ast_verbose ( VERBOSE_PREFIX_3 " B-channel %d/%d successfully restarted on span %d \n " , pri - > pvts [ chanpos ] - > logicalspan ,
2004-06-05 06:54:52 +00:00
pri - > pvts [ chanpos ] - > prioffset , pri - > span ) ;
ast_mutex_unlock ( & pri - > pvts [ chanpos ] - > lock ) ;
2003-03-20 05:20:19 +00:00
if ( pri - > resetting )
pri_check_restart ( pri ) ;
2003-02-07 19:23:19 +00:00
break ;
}
}
2004-06-05 06:54:52 +00:00
if ( chanpos < 0 ) {
ast_log ( LOG_WARNING , " Restart ACK requested on strange channel %d/%d span %d \n " ,
PRI_SPAN ( e - > restartack . channel ) , PRI_CHANNEL ( e - > restartack . channel ) , pri - > span ) ;
2003-02-07 19:23:19 +00:00
}
2004-06-05 06:54:52 +00:00
chanpos = - 1 ;
2003-02-07 19:23:19 +00:00
}
2004-06-05 06:54:52 +00:00
if ( chanpos > - 1 ) {
if ( pri - > pvts [ chanpos ] ) {
ast_mutex_lock ( & pri - > pvts [ chanpos ] - > lock ) ;
2004-12-13 15:11:36 +00:00
if ( pri - > pvts [ chanpos ] - > realcall )
pri_hangup_all ( pri - > pvts [ chanpos ] - > realcall , pri ) ;
2004-06-06 01:54:22 +00:00
else if ( pri - > pvts [ chanpos ] - > owner ) {
2004-06-05 06:54:52 +00:00
ast_log ( LOG_WARNING , " Got restart ack on channel %d/%d span %d with owner \n " ,
PRI_SPAN ( e - > restartack . channel ) , PRI_CHANNEL ( e - > restartack . channel ) , pri - > span ) ;
pri - > pvts [ chanpos ] - > owner - > _softhangup | = AST_SOFTHANGUP_DEV ;
2003-02-07 19:23:19 +00:00
}
2004-06-05 06:54:52 +00:00
pri - > pvts [ chanpos ] - > resetting = 0 ;
2003-02-07 19:23:19 +00:00
if ( option_verbose > 2 )
2004-06-06 22:51:37 +00:00
ast_verbose ( VERBOSE_PREFIX_3 " B-channel %d/%d successfully restarted on span %d \n " , pri - > pvts [ chanpos ] - > logicalspan ,
2004-06-05 06:54:52 +00:00
pri - > pvts [ chanpos ] - > prioffset , pri - > span ) ;
ast_mutex_unlock ( & pri - > pvts [ chanpos ] - > lock ) ;
2003-03-20 05:49:27 +00:00
if ( pri - > resetting )
pri_check_restart ( pri ) ;
2002-06-24 17:59:56 +00:00
}
}
break ;
2003-05-19 23:33:41 +00:00
case PRI_EVENT_SETUP_ACK :
2004-06-05 06:54:52 +00:00
chanpos = pri_find_principle ( pri , e - > setup_ack . channel ) ;
if ( chanpos < 0 ) {
ast_log ( LOG_WARNING , " Received SETUP_ACKNOWLEDGE on unconfigured channel %d/%d span %d \n " ,
PRI_SPAN ( e - > setup_ack . channel ) , PRI_CHANNEL ( e - > setup_ack . channel ) , pri - > span ) ;
2003-05-19 23:33:41 +00:00
} else {
2004-06-17 04:23:57 +00:00
ast_mutex_lock ( & pri - > pvts [ chanpos ] - > lock ) ;
2004-06-05 06:54:52 +00:00
pri - > pvts [ chanpos ] - > setup_ack = 1 ;
2004-06-20 06:53:53 +00:00
/* Send any queued digits */
for ( x = 0 ; x < strlen ( pri - > pvts [ chanpos ] - > dialdest ) ; x + + ) {
ast_log ( LOG_DEBUG , " Sending pending digit '%c' \n " , pri - > pvts [ chanpos ] - > dialdest [ x ] ) ;
pri_information ( pri - > pri , pri - > pvts [ chanpos ] - > call ,
pri - > pvts [ chanpos ] - > dialdest [ x ] ) ;
}
2004-06-17 04:23:57 +00:00
ast_mutex_unlock ( & pri - > pvts [ chanpos ] - > lock ) ;
2003-05-19 23:33:41 +00:00
}
2003-05-15 22:16:26 +00:00
break ;
2005-01-17 12:37:55 +00:00
case PRI_EVENT_NOTIFY :
chanpos = pri_find_principle ( pri , e - > notify . channel ) ;
if ( chanpos < 0 ) {
ast_log ( LOG_WARNING , " Received NOTIFY on unconfigured channel %d/%d span %d \n " ,
PRI_SPAN ( e - > notify . channel ) , PRI_CHANNEL ( e - > notify . channel ) , pri - > span ) ;
} else {
struct ast_frame f = { AST_FRAME_CONTROL , } ;
ast_mutex_lock ( & pri - > pvts [ chanpos ] - > lock ) ;
switch ( e - > notify . info ) {
case PRI_NOTIFY_REMOTE_HOLD :
f . subclass = AST_CONTROL_HOLD ;
zap_queue_frame ( pri - > pvts [ chanpos ] , & f , pri ) ;
break ;
case PRI_NOTIFY_REMOTE_RETRIEVAL :
f . subclass = AST_CONTROL_UNHOLD ;
zap_queue_frame ( pri - > pvts [ chanpos ] , & f , pri ) ;
break ;
}
ast_mutex_unlock ( & pri - > pvts [ chanpos ] - > lock ) ;
}
break ;
2002-03-08 23:48:42 +00:00
default :
ast_log ( LOG_DEBUG , " Event: %d \n " , e - > e ) ;
2001-10-09 02:06:21 +00:00
}
2004-06-07 03:39:18 +00:00
}
2003-08-13 15:25:16 +00:00
ast_mutex_unlock ( & pri - > lock ) ;
2001-10-09 02:06:21 +00:00
}
/* Never reached */
return NULL ;
}
static int start_pri ( struct zt_pri * pri )
{
2002-03-08 23:48:42 +00:00
int res , x ;
2001-10-09 02:06:21 +00:00
ZT_PARAMS p ;
ZT_BUFFERINFO bi ;
2004-06-07 03:39:18 +00:00
struct zt_spaninfo si ;
int i ;
for ( i = 0 ; i < NUM_DCHANS ; i + + ) {
if ( ! pri - > dchannels [ i ] )
break ;
pri - > fds [ i ] = open ( " /dev/zap/channel " , O_RDWR , 0600 ) ;
x = pri - > dchannels [ i ] ;
if ( ( pri - > fds [ i ] < 0 ) | | ( ioctl ( pri - > fds [ i ] , ZT_SPECIFY , & x ) = = - 1 ) ) {
ast_log ( LOG_ERROR , " Unable to open D-channel %d (%s) \n " , x , strerror ( errno ) ) ;
return - 1 ;
}
res = ioctl ( pri - > fds [ i ] , ZT_GET_PARAMS , & p ) ;
if ( res ) {
2004-10-23 22:00:40 +00:00
zt_close ( pri - > fds [ i ] ) ;
2004-06-07 03:39:18 +00:00
pri - > fds [ i ] = - 1 ;
ast_log ( LOG_ERROR , " Unable to get parameters for D-channel %d (%s) \n " , x , strerror ( errno ) ) ;
return - 1 ;
}
if ( p . sigtype ! = ZT_SIG_HDLCFCS ) {
2004-10-23 22:00:40 +00:00
zt_close ( pri - > fds [ i ] ) ;
2004-06-07 03:39:18 +00:00
pri - > fds [ i ] = - 1 ;
ast_log ( LOG_ERROR , " D-channel %d is not in HDLC/FCS mode. See /etc/zaptel.conf \n " , x ) ;
return - 1 ;
}
memset ( & si , 0 , sizeof ( si ) ) ;
res = ioctl ( pri - > fds [ i ] , ZT_SPANSTAT , & si ) ;
if ( res ) {
2004-10-23 22:00:40 +00:00
zt_close ( pri - > fds [ i ] ) ;
2004-06-07 03:39:18 +00:00
pri - > fds [ i ] = - 1 ;
ast_log ( LOG_ERROR , " Unable to get span state for D-channel %d (%s) \n " , x , strerror ( errno ) ) ;
}
if ( ! si . alarms )
pri - > dchanavail [ i ] | = DCHAN_NOTINALARM ;
else
pri - > dchanavail [ i ] & = ~ DCHAN_NOTINALARM ;
bi . txbufpolicy = ZT_POLICY_IMMEDIATE ;
bi . rxbufpolicy = ZT_POLICY_IMMEDIATE ;
bi . numbufs = 16 ;
bi . bufsize = 1024 ;
if ( ioctl ( pri - > fds [ i ] , ZT_SET_BUFINFO , & bi ) ) {
ast_log ( LOG_ERROR , " Unable to set appropriate buffering on channel %d \n " , x ) ;
2004-10-23 22:00:40 +00:00
zt_close ( pri - > fds [ i ] ) ;
2004-06-07 03:39:18 +00:00
pri - > fds [ i ] = - 1 ;
return - 1 ;
}
pri - > dchans [ i ] = pri_new ( pri - > fds [ i ] , pri - > nodetype , pri - > switchtype ) ;
/* Force overlap dial if we're doing GR-303! */
if ( pri - > switchtype = = PRI_SWITCH_GR303_TMC )
pri - > overlapdial = 1 ;
pri_set_overlapdial ( pri - > dchans [ i ] , pri - > overlapdial ) ;
/* Enslave to master if appropriate */
if ( i )
pri_enslave ( pri - > dchans [ 0 ] , pri - > dchans [ i ] ) ;
if ( ! pri - > dchans [ i ] ) {
2004-10-23 22:00:40 +00:00
zt_close ( pri - > fds [ i ] ) ;
2004-06-07 03:39:18 +00:00
pri - > fds [ i ] = - 1 ;
ast_log ( LOG_ERROR , " Unable to create PRI structure \n " ) ;
return - 1 ;
}
pri_set_debug ( pri - > dchans [ i ] , DEFAULT_PRI_DEBUG ) ;
2004-06-26 05:20:42 +00:00
pri_set_nsf ( pri - > dchans [ i ] , pri - > nsf ) ;
2004-10-02 15:01:37 +00:00
# ifdef PRI_GETSET_TIMERS
for ( x = 0 ; x < PRI_MAX_TIMERS ; x + + ) {
if ( pritimers [ x ] ! = 0 )
pri_set_timer ( pri - > dchans [ i ] , x , pritimers [ x ] ) ;
}
# endif
2001-10-09 02:06:21 +00:00
}
2004-06-07 03:39:18 +00:00
/* Assume primary is the one we use */
pri - > pri = pri - > dchans [ 0 ] ;
2004-06-05 06:54:52 +00:00
pri - > resetpos = - 1 ;
2004-08-08 17:15:02 +00:00
if ( ast_pthread_create ( & pri - > master , NULL , pri_dchannel , pri ) ) {
2004-06-07 03:39:18 +00:00
for ( i = 0 ; i < NUM_DCHANS ; i + + ) {
if ( ! pri - > dchannels [ i ] )
break ;
2004-10-23 22:00:40 +00:00
zt_close ( pri - > fds [ i ] ) ;
2004-06-07 03:39:18 +00:00
pri - > fds [ i ] = - 1 ;
}
2001-10-09 02:06:21 +00:00
ast_log ( LOG_ERROR , " Unable to spawn D-channel: %s \n " , strerror ( errno ) ) ;
return - 1 ;
}
return 0 ;
}
2004-08-07 19:27:54 +00:00
static char * complete_span_helper ( char * line , char * word , int pos , int state , int rpos )
2001-10-09 02:06:21 +00:00
{
int span = 1 ;
char tmp [ 50 ] ;
2004-08-07 19:27:54 +00:00
if ( pos ! = rpos )
return 0 ;
2001-10-09 02:06:21 +00:00
while ( span < = NUM_SPANS ) {
2004-03-03 03:54:25 +00:00
if ( span > state & & pris [ span - 1 ] . pri )
2001-10-09 02:06:21 +00:00
break ;
span + + ;
}
if ( span < = NUM_SPANS ) {
snprintf ( tmp , sizeof ( tmp ) , " %d " , span ) ;
return strdup ( tmp ) ;
} else
return NULL ;
}
2004-08-07 19:27:54 +00:00
static char * complete_span_4 ( char * line , char * word , int pos , int state )
{
return complete_span_helper ( line , word , pos , state , 3 ) ;
}
static char * complete_span_5 ( char * line , char * word , int pos , int state )
{
return complete_span_helper ( line , word , pos , state , 4 ) ;
}
2005-04-22 19:10:35 +00:00
static int handle_pri_set_debug_file ( int fd , int argc , char * * argv )
{
int myfd ;
if ( ! strncasecmp ( argv [ 1 ] , " set " , 3 ) ) {
if ( argc < 5 )
return RESULT_SHOWUSAGE ;
if ( ! argv [ 4 ] | | ast_strlen_zero ( argv [ 4 ] ) )
return RESULT_SHOWUSAGE ;
myfd = open ( argv [ 4 ] , O_CREAT | O_WRONLY ) ;
if ( myfd < 0 ) {
ast_cli ( fd , " Unable to open '%s' for writing \n " , argv [ 4 ] ) ;
return RESULT_SUCCESS ;
}
ast_mutex_lock ( & pridebugfdlock ) ;
if ( pridebugfd > = 0 )
close ( pridebugfd ) ;
pridebugfd = myfd ;
2005-05-15 23:26:45 +00:00
ast_copy_string ( pridebugfilename , argv [ 4 ] , sizeof ( pridebugfilename ) ) ;
2005-05-10 21:52:43 +00:00
2005-04-22 19:10:35 +00:00
ast_mutex_unlock ( & pridebugfdlock ) ;
ast_cli ( fd , " PRI debug output will be sent to '%s' \n " , argv [ 4 ] ) ;
} else {
/* Assume it is unset */
ast_mutex_lock ( & pridebugfdlock ) ;
close ( pridebugfd ) ;
pridebugfd = - 1 ;
ast_cli ( fd , " PRI debug output to file disabled \n " ) ;
ast_mutex_unlock ( & pridebugfdlock ) ;
}
return RESULT_SUCCESS ;
}
2001-10-09 02:06:21 +00:00
static int handle_pri_debug ( int fd , int argc , char * argv [ ] )
{
int span ;
2004-06-07 03:39:18 +00:00
int x ;
2002-03-08 23:48:42 +00:00
if ( argc < 4 ) {
return RESULT_SHOWUSAGE ;
}
2001-10-09 02:06:21 +00:00
span = atoi ( argv [ 3 ] ) ;
if ( ( span < 1 ) | | ( span > NUM_SPANS ) ) {
ast_cli ( fd , " Invalid span %s. Should be a number %d to %d \n " , argv [ 3 ] , 1 , NUM_SPANS ) ;
return RESULT_SUCCESS ;
}
if ( ! pris [ span - 1 ] . pri ) {
ast_cli ( fd , " No PRI running on span %d \n " , span ) ;
return RESULT_SUCCESS ;
}
2004-06-07 03:39:18 +00:00
for ( x = 0 ; x < NUM_DCHANS ; x + + ) {
if ( pris [ span - 1 ] . dchans [ x ] )
pri_set_debug ( pris [ span - 1 ] . dchans [ x ] , PRI_DEBUG_Q931_DUMP | PRI_DEBUG_Q931_STATE ) ;
}
2001-10-09 02:06:21 +00:00
ast_cli ( fd , " Enabled debugging on span %d \n " , span ) ;
return RESULT_SUCCESS ;
}
2003-02-07 19:23:19 +00:00
2003-08-26 02:38:24 +00:00
static int handle_pri_no_debug ( int fd , int argc , char * argv [ ] )
{
int span ;
2004-06-07 03:39:18 +00:00
int x ;
2003-08-26 02:38:24 +00:00
if ( argc < 5 )
return RESULT_SHOWUSAGE ;
span = atoi ( argv [ 4 ] ) ;
if ( ( span < 1 ) | | ( span > NUM_SPANS ) ) {
ast_cli ( fd , " Invalid span %s. Should be a number %d to %d \n " , argv [ 4 ] , 1 , NUM_SPANS ) ;
return RESULT_SUCCESS ;
}
if ( ! pris [ span - 1 ] . pri ) {
ast_cli ( fd , " No PRI running on span %d \n " , span ) ;
return RESULT_SUCCESS ;
}
2004-06-07 03:39:18 +00:00
for ( x = 0 ; x < NUM_DCHANS ; x + + ) {
if ( pris [ span - 1 ] . dchans [ x ] )
pri_set_debug ( pris [ span - 1 ] . dchans [ x ] , 0 ) ;
}
2003-08-26 02:38:24 +00:00
ast_cli ( fd , " Disabled debugging on span %d \n " , span ) ;
return RESULT_SUCCESS ;
}
static int handle_pri_really_debug ( int fd , int argc , char * argv [ ] )
{
int span ;
2004-06-07 03:39:18 +00:00
int x ;
2003-08-26 02:38:24 +00:00
if ( argc < 5 )
return RESULT_SHOWUSAGE ;
span = atoi ( argv [ 4 ] ) ;
if ( ( span < 1 ) | | ( span > NUM_SPANS ) ) {
ast_cli ( fd , " Invalid span %s. Should be a number %d to %d \n " , argv [ 4 ] , 1 , NUM_SPANS ) ;
return RESULT_SUCCESS ;
}
if ( ! pris [ span - 1 ] . pri ) {
ast_cli ( fd , " No PRI running on span %d \n " , span ) ;
return RESULT_SUCCESS ;
}
2004-06-07 03:39:18 +00:00
for ( x = 0 ; x < NUM_DCHANS ; x + + ) {
if ( pris [ span - 1 ] . dchans [ x ] )
pri_set_debug ( pris [ span - 1 ] . dchans [ x ] , ( PRI_DEBUG_Q931_DUMP | PRI_DEBUG_Q921_DUMP | PRI_DEBUG_Q921_RAW | PRI_DEBUG_Q921_STATE ) ) ;
}
2003-08-26 02:38:24 +00:00
ast_cli ( fd , " Enabled EXTENSIVE debugging on span %d \n " , span ) ;
return RESULT_SUCCESS ;
}
2004-07-16 04:40:54 +00:00
static void build_status ( char * s , size_t len , int status , int active )
2004-06-07 03:39:18 +00:00
{
2004-07-16 04:40:54 +00:00
if ( ! s | | len < 1 ) {
return ;
}
s [ 0 ] = ' \0 ' ;
2004-06-07 03:39:18 +00:00
if ( status & DCHAN_PROVISIONED )
2004-07-16 04:40:54 +00:00
strncat ( s , " Provisioned, " , len - strlen ( s ) - 1 ) ;
2004-06-07 03:39:18 +00:00
if ( ! ( status & DCHAN_NOTINALARM ) )
2004-07-16 04:40:54 +00:00
strncat ( s , " In Alarm, " , len - strlen ( s ) - 1 ) ;
2004-06-07 03:39:18 +00:00
if ( status & DCHAN_UP )
2004-07-16 04:40:54 +00:00
strncat ( s , " Up " , len - strlen ( s ) - 1 ) ;
2004-06-07 03:39:18 +00:00
else
2004-07-16 04:40:54 +00:00
strncat ( s , " Down " , len - strlen ( s ) - 1 ) ;
2004-06-07 03:39:18 +00:00
if ( active )
2004-07-16 04:40:54 +00:00
strncat ( s , " , Active " , len - strlen ( s ) - 1 ) ;
2004-06-07 03:39:18 +00:00
else
2004-07-16 04:40:54 +00:00
strncat ( s , " , Standby " , len - strlen ( s ) - 1 ) ;
s [ len - 1 ] = ' \0 ' ;
2004-06-07 03:39:18 +00:00
}
2004-03-15 05:57:47 +00:00
static int handle_pri_show_span ( int fd , int argc , char * argv [ ] )
{
int span ;
2004-06-07 03:39:18 +00:00
int x ;
char status [ 256 ] ;
2004-03-15 05:57:47 +00:00
if ( argc < 4 )
return RESULT_SHOWUSAGE ;
span = atoi ( argv [ 3 ] ) ;
if ( ( span < 1 ) | | ( span > NUM_SPANS ) ) {
ast_cli ( fd , " Invalid span %s. Should be a number %d to %d \n " , argv [ 4 ] , 1 , NUM_SPANS ) ;
return RESULT_SUCCESS ;
}
if ( ! pris [ span - 1 ] . pri ) {
ast_cli ( fd , " No PRI running on span %d \n " , span ) ;
return RESULT_SUCCESS ;
}
2004-06-07 03:39:18 +00:00
for ( x = 0 ; x < NUM_DCHANS ; x + + ) {
if ( pris [ span - 1 ] . dchannels [ x ] ) {
2004-10-28 01:56:49 +00:00
# ifdef PRI_DUMP_INFO_STR
2004-10-26 02:57:18 +00:00
char * info_str = NULL ;
2004-10-28 01:56:49 +00:00
# endif
2004-06-07 03:39:18 +00:00
ast_cli ( fd , " %s D-channel: %d \n " , pri_order ( x ) , pris [ span - 1 ] . dchannels [ x ] ) ;
2004-07-16 04:40:54 +00:00
build_status ( status , sizeof ( status ) , pris [ span - 1 ] . dchanavail [ x ] , pris [ span - 1 ] . dchans [ x ] = = pris [ span - 1 ] . pri ) ;
2004-06-07 03:39:18 +00:00
ast_cli ( fd , " Status: %s \n " , status ) ;
2004-10-26 02:57:18 +00:00
# ifdef PRI_DUMP_INFO_STR
info_str = pri_dump_info_str ( pris [ span - 1 ] . pri ) ;
if ( info_str ) {
ast_cli ( fd , " %s " , info_str ) ;
free ( info_str ) ;
}
# else
2004-06-07 03:39:18 +00:00
pri_dump_info ( pris [ span - 1 ] . pri ) ;
2004-10-26 02:57:18 +00:00
# endif
2004-06-07 03:39:18 +00:00
ast_cli ( fd , " \n " ) ;
}
}
2004-03-15 05:57:47 +00:00
return RESULT_SUCCESS ;
}
2005-05-10 21:52:43 +00:00
static int handle_pri_show_debug ( int fd , int argc , char * argv [ ] )
{
int x ;
int span ;
int count = 0 ;
int debug = 0 ;
for ( span = 0 ; span < NUM_SPANS ; span + + ) {
if ( pris [ span ] . pri ) {
for ( x = 0 ; x < NUM_DCHANS ; x + + ) {
debug = 0 ;
if ( pris [ span ] . dchans [ x ] ) {
debug = pri_get_debug ( pris [ span ] . dchans [ x ] ) ;
ast_cli ( fd , " Span %d: Debug: %s \t Intense: %s \n " , span + 1 , ( debug & PRI_DEBUG_Q931_STATE ) ? " Yes " : " No " , ( debug & PRI_DEBUG_Q921_RAW ) ? " Yes " : " No " ) ;
count + + ;
}
}
}
}
ast_mutex_lock ( & pridebugfdlock ) ;
if ( pridebugfd > = 0 )
ast_cli ( fd , " Logging PRI debug to file %s \n " , pridebugfilename ) ;
ast_mutex_unlock ( & pridebugfdlock ) ;
if ( ! count )
ast_cli ( fd , " No debug set or no PRI running \n " ) ;
return RESULT_SUCCESS ;
}
2003-08-26 02:38:24 +00:00
static char pri_debug_help [ ] =
" Usage: pri debug span <span> \n "
" Enables debugging on a given PRI span \n " ;
static char pri_no_debug_help [ ] =
" Usage: pri no debug span <span> \n "
" Disables debugging on a given PRI span \n " ;
static char pri_really_debug_help [ ] =
" Usage: pri intensive debug span <span> \n "
" Enables debugging down to the Q.921 level \n " ;
2004-03-15 05:57:47 +00:00
static char pri_show_span_help [ ] =
" Usage: pri show span <span> \n "
" Displays PRI Information \n " ;
2005-06-03 03:24:37 +00:00
static struct ast_cli_entry zap_pri_cli [ ] = {
{ { " pri " , " debug " , " span " , NULL } , handle_pri_debug ,
" Enables PRI debugging on a span " , pri_debug_help , complete_span_4 } ,
{ { " pri " , " no " , " debug " , " span " , NULL } , handle_pri_no_debug ,
" Disables PRI debugging on a span " , pri_no_debug_help , complete_span_5 } ,
{ { " pri " , " intense " , " debug " , " span " , NULL } , handle_pri_really_debug ,
" Enables REALLY INTENSE PRI debugging " , pri_really_debug_help , complete_span_5 } ,
{ { " pri " , " show " , " span " , NULL } , handle_pri_show_span ,
" Displays PRI Information " , pri_show_span_help , complete_span_4 } ,
{ { " pri " , " show " , " debug " , NULL } , handle_pri_show_debug ,
" Displays current PRI debug settings " } ,
{ { " pri " , " set " , " debug " , " file " , NULL } , handle_pri_set_debug_file ,
" Sends PRI debug output to the specified file " } ,
{ { " pri " , " unset " , " debug " , " file " , NULL } , handle_pri_set_debug_file ,
" Ends PRI debug output to file " } ,
} ;
2005-04-22 19:10:35 +00:00
2003-08-26 02:38:24 +00:00
# endif /* ZAPATA_PRI */
2003-02-07 19:23:19 +00:00
# ifdef ZAPATA_R2
static int handle_r2_no_debug ( int fd , int argc , char * argv [ ] )
{
int chan ;
struct zt_pvt * tmp = NULL ; ;
if ( argc < 5 )
return RESULT_SHOWUSAGE ;
chan = atoi ( argv [ 4 ] ) ;
if ( ( chan < 1 ) | | ( chan > NUM_SPANS ) ) {
2003-09-27 02:45:37 +00:00
ast_cli ( fd , " Invalid channel %s. Should be a number greater than 0 \n " , argv [ 4 ] ) ;
2003-02-07 19:23:19 +00:00
return RESULT_SUCCESS ;
}
tmp = iflist ;
while ( tmp ) {
if ( tmp - > channel = = chan ) {
if ( tmp - > r2 ) {
mfcr2_set_debug ( tmp - > r2 , 0 ) ;
ast_cli ( fd , " Disabled R2 debugging on channel %d \n " , chan ) ;
return RESULT_SUCCESS ;
}
break ;
}
tmp = tmp - > next ;
}
if ( tmp )
ast_cli ( fd , " No R2 running on channel %d \n " , chan ) ;
else
ast_cli ( fd , " No such zap channel %d \n " , chan ) ;
return RESULT_SUCCESS ;
}
static int handle_r2_debug ( int fd , int argc , char * argv [ ] )
{
int chan ;
struct zt_pvt * tmp = NULL ; ;
if ( argc < 4 ) {
return RESULT_SHOWUSAGE ;
}
chan = atoi ( argv [ 3 ] ) ;
if ( ( chan < 1 ) | | ( chan > NUM_SPANS ) ) {
2003-09-27 02:45:37 +00:00
ast_cli ( fd , " Invalid channel %s. Should be a number greater than 0 \n " , argv [ 3 ] ) ;
2003-02-07 19:23:19 +00:00
return RESULT_SUCCESS ;
}
tmp = iflist ;
while ( tmp ) {
if ( tmp - > channel = = chan ) {
if ( tmp - > r2 ) {
mfcr2_set_debug ( tmp - > r2 , 0xFFFFFFFF ) ;
ast_cli ( fd , " Enabled R2 debugging on channel %d \n " , chan ) ;
return RESULT_SUCCESS ;
}
break ;
}
tmp = tmp - > next ;
}
if ( tmp )
ast_cli ( fd , " No R2 running on channel %d \n " , chan ) ;
else
ast_cli ( fd , " No such zap channel %d \n " , chan ) ;
return RESULT_SUCCESS ;
}
static char r2_debug_help [ ] =
" Usage: r2 debug channel <channel> \n "
" Enables R2 protocol level debugging on a given channel \n " ;
static char r2_no_debug_help [ ] =
" Usage: r2 no debug channel <channel> \n "
" Enables R2 protocol level debugging on a given channel \n " ;
2005-06-03 03:24:37 +00:00
static struct ast_cli_entry zap_r2_cli [ ] = {
{ { " r2 " , " debug " , " channel " , NULL } , handle_r2_debug ,
" Enables R2 debugging on a channel " , r2_debug_help } ,
{ { " r2 " , " no " , " debug " , " channel " , NULL } , handle_r2_no_debug ,
" Disables R2 debugging on a channel " , r2_no_debug_help } ,
} ;
2003-02-07 19:23:19 +00:00
# endif
2001-10-09 02:06:21 +00:00
static int zap_destroy_channel ( int fd , int argc , char * * argv )
{
int channel = 0 ;
struct zt_pvt * tmp = NULL ;
struct zt_pvt * prev = NULL ;
if ( argc ! = 4 ) {
return RESULT_SHOWUSAGE ;
}
channel = atoi ( argv [ 3 ] ) ;
tmp = iflist ;
while ( tmp ) {
if ( tmp - > channel = = channel ) {
destroy_channel ( prev , tmp , 1 ) ;
return RESULT_SUCCESS ;
}
prev = tmp ;
tmp = tmp - > next ;
}
return RESULT_FAILURE ;
}
static int zap_show_channels ( int fd , int argc , char * * argv )
{
2004-06-02 16:35:06 +00:00
# define FORMAT "%7s %-10.10s %-15.15s %-10.10s %-20.20s\n"
# define FORMAT2 "%7s %-10.10s %-15.15s %-10.10s %-20.20s\n"
2001-10-09 02:06:21 +00:00
struct zt_pvt * tmp = NULL ;
2004-07-16 04:40:54 +00:00
char tmps [ 20 ] = " " ;
2004-06-06 01:54:22 +00:00
ast_mutex_t * lock ;
struct zt_pvt * start ;
# ifdef ZAPATA_PRI
int trunkgroup ;
struct zt_pri * pri = NULL ;
int x ;
# endif
lock = & iflock ;
start = iflist ;
2001-10-09 02:06:21 +00:00
2004-06-06 01:54:22 +00:00
# ifdef ZAPATA_PRI
if ( argc = = 4 ) {
if ( ( trunkgroup = atoi ( argv [ 3 ] ) ) < 1 )
return RESULT_SHOWUSAGE ;
for ( x = 0 ; x < NUM_SPANS ; x + + ) {
if ( pris [ x ] . trunkgroup = = trunkgroup ) {
pri = pris + x ;
break ;
}
}
if ( pri ) {
start = pri - > crvs ;
lock = & pri - > lock ;
} else {
ast_cli ( fd , " No such trunk group %d \n " , trunkgroup ) ;
return RESULT_FAILURE ;
}
} else
# endif
2001-10-09 02:06:21 +00:00
if ( argc ! = 3 )
return RESULT_SHOWUSAGE ;
2004-06-06 01:54:22 +00:00
ast_mutex_lock ( lock ) ;
# ifdef ZAPATA_PRI
ast_cli ( fd , FORMAT2 , pri ? " CRV " : " Chan " , " Extension " , " Context " , " Language " , " MusicOnHold " ) ;
# else
2004-01-09 05:26:27 +00:00
ast_cli ( fd , FORMAT2 , " Chan " , " Extension " , " Context " , " Language " , " MusicOnHold " ) ;
2004-06-06 01:54:22 +00:00
# endif
2001-10-09 02:06:21 +00:00
2004-06-06 01:54:22 +00:00
tmp = start ;
2001-10-09 02:06:21 +00:00
while ( tmp ) {
2004-06-02 16:35:06 +00:00
if ( tmp - > channel > 0 ) {
2004-07-16 04:40:54 +00:00
snprintf ( tmps , sizeof ( tmps ) , " %d " , tmp - > channel ) ;
2004-06-02 16:35:06 +00:00
} else
2005-05-15 23:26:45 +00:00
ast_copy_string ( tmps , " pseudo " , sizeof ( tmps ) ) ;
2004-06-02 16:35:06 +00:00
ast_cli ( fd , FORMAT , tmps , tmp - > exten , tmp - > context , tmp - > language , tmp - > musicclass ) ;
2001-10-09 02:06:21 +00:00
tmp = tmp - > next ;
}
2004-06-06 01:54:22 +00:00
ast_mutex_unlock ( lock ) ;
2001-10-09 02:06:21 +00:00
return RESULT_SUCCESS ;
# undef FORMAT
# undef FORMAT2
}
static int zap_show_channel ( int fd , int argc , char * * argv )
{
int channel ;
struct zt_pvt * tmp = NULL ;
2003-02-07 19:23:19 +00:00
ZT_CONFINFO ci ;
2004-04-06 15:50:18 +00:00
ZT_PARAMS ps ;
2003-02-07 19:23:19 +00:00
int x ;
2004-06-06 01:54:22 +00:00
ast_mutex_t * lock ;
struct zt_pvt * start ;
# ifdef ZAPATA_PRI
char * c ;
int trunkgroup ;
struct zt_pri * pri = NULL ;
# endif
lock = & iflock ;
start = iflist ;
2001-10-09 02:06:21 +00:00
if ( argc ! = 4 )
return RESULT_SHOWUSAGE ;
2004-06-06 01:54:22 +00:00
# ifdef ZAPATA_PRI
if ( ( c = strchr ( argv [ 3 ] , ' : ' ) ) ) {
if ( sscanf ( argv [ 3 ] , " %d:%d " , & trunkgroup , & channel ) ! = 2 )
return RESULT_SHOWUSAGE ;
if ( ( trunkgroup < 1 ) | | ( channel < 1 ) )
return RESULT_SHOWUSAGE ;
for ( x = 0 ; x < NUM_SPANS ; x + + ) {
if ( pris [ x ] . trunkgroup = = trunkgroup ) {
pri = pris + x ;
break ;
}
}
if ( pri ) {
start = pri - > crvs ;
lock = & pri - > lock ;
} else {
ast_cli ( fd , " No such trunk group %d \n " , trunkgroup ) ;
return RESULT_FAILURE ;
}
} else
# endif
channel = atoi ( argv [ 3 ] ) ;
2001-10-09 02:06:21 +00:00
2004-06-06 01:54:22 +00:00
ast_mutex_lock ( lock ) ;
tmp = start ;
2001-10-09 02:06:21 +00:00
while ( tmp ) {
if ( tmp - > channel = = channel ) {
2004-06-06 01:54:22 +00:00
# ifdef ZAPATA_PRI
if ( pri )
ast_cli ( fd , " Trunk/CRV: %d/%d \n " , trunkgroup , tmp - > channel ) ;
else
# endif
2001-10-09 02:06:21 +00:00
ast_cli ( fd , " Channel: %d \n " , tmp - > channel ) ;
2003-02-07 19:23:19 +00:00
ast_cli ( fd , " File Descriptor: %d \n " , tmp - > subs [ SUB_REAL ] . zfd ) ;
2001-10-09 02:06:21 +00:00
ast_cli ( fd , " Span: %d \n " , tmp - > span ) ;
ast_cli ( fd , " Extension: %s \n " , tmp - > exten ) ;
2004-06-26 18:38:19 +00:00
ast_cli ( fd , " Dialing: %s \n " , tmp - > dialing ? " yes " : " no " ) ;
2001-10-09 02:06:21 +00:00
ast_cli ( fd , " Context: %s \n " , tmp - > context ) ;
2004-10-02 00:58:31 +00:00
ast_cli ( fd , " Caller ID: %s \n " , tmp - > cid_num ) ;
2005-02-04 06:12:32 +00:00
ast_cli ( fd , " Calling TON: %d \n " , tmp - > cid_ton ) ;
2004-10-02 00:58:31 +00:00
ast_cli ( fd , " Caller ID name: %s \n " , tmp - > cid_name ) ;
2001-10-09 02:06:21 +00:00
ast_cli ( fd , " Destroy: %d \n " , tmp - > destroy ) ;
2004-08-21 21:41:54 +00:00
ast_cli ( fd , " InAlarm: %d \n " , tmp - > inalarm ) ;
2001-10-09 02:06:21 +00:00
ast_cli ( fd , " Signalling Type: %s \n " , sig2str ( tmp - > sig ) ) ;
2005-04-27 23:44:24 +00:00
ast_cli ( fd , " Radio: %d \n " , tmp - > radio ) ;
2003-02-07 19:23:19 +00:00
ast_cli ( fd , " Owner: %s \n " , tmp - > owner ? tmp - > owner - > name : " <None> " ) ;
ast_cli ( fd , " Real: %s%s%s \n " , tmp - > subs [ SUB_REAL ] . owner ? tmp - > subs [ SUB_REAL ] . owner - > name : " <None> " , tmp - > subs [ SUB_REAL ] . inthreeway ? " (Confed) " : " " , tmp - > subs [ SUB_REAL ] . linear ? " (Linear) " : " " ) ;
ast_cli ( fd , " Callwait: %s%s%s \n " , tmp - > subs [ SUB_CALLWAIT ] . owner ? tmp - > subs [ SUB_CALLWAIT ] . owner - > name : " <None> " , tmp - > subs [ SUB_CALLWAIT ] . inthreeway ? " (Confed) " : " " , tmp - > subs [ SUB_CALLWAIT ] . linear ? " (Linear) " : " " ) ;
ast_cli ( fd , " Threeway: %s%s%s \n " , tmp - > subs [ SUB_THREEWAY ] . owner ? tmp - > subs [ SUB_THREEWAY ] . owner - > name : " <None> " , tmp - > subs [ SUB_THREEWAY ] . inthreeway ? " (Confed) " : " " , tmp - > subs [ SUB_THREEWAY ] . linear ? " (Linear) " : " " ) ;
ast_cli ( fd , " Confno: %d \n " , tmp - > confno ) ;
ast_cli ( fd , " Propagated Conference: %d \n " , tmp - > propconfno ) ;
ast_cli ( fd , " Real in conference: %d \n " , tmp - > inconference ) ;
ast_cli ( fd , " DSP: %s \n " , tmp - > dsp ? " yes " : " no " ) ;
ast_cli ( fd , " Relax DTMF: %s \n " , tmp - > dtmfrelax ? " yes " : " no " ) ;
ast_cli ( fd , " Dialing/CallwaitCAS: %d/%d \n " , tmp - > dialing , tmp - > callwaitcas ) ;
ast_cli ( fd , " Default law: %s \n " , tmp - > law = = ZT_LAW_MULAW ? " ulaw " : tmp - > law = = ZT_LAW_ALAW ? " alaw " : " unknown " ) ;
ast_cli ( fd , " Fax Handled: %s \n " , tmp - > faxhandled ? " yes " : " no " ) ;
ast_cli ( fd , " Pulse phone: %s \n " , tmp - > pulsedial ? " yes " : " no " ) ;
2003-03-10 20:39:12 +00:00
ast_cli ( fd , " Echo Cancellation: %d taps%s, currently %s \n " , tmp - > echocancel , tmp - > echocanbridged ? " " : " unless TDM bridged " , tmp - > echocanon ? " ON " : " OFF " ) ;
2003-02-07 19:23:19 +00:00
if ( tmp - > master )
ast_cli ( fd , " Master Channel: %d \n " , tmp - > master - > channel ) ;
for ( x = 0 ; x < MAX_SLAVES ; x + + ) {
if ( tmp - > slaves [ x ] )
ast_cli ( fd , " Slave Channel: %d \n " , tmp - > slaves [ x ] - > channel ) ;
}
# ifdef ZAPATA_PRI
if ( tmp - > pri ) {
ast_cli ( fd , " PRI Flags: " ) ;
if ( tmp - > resetting )
ast_cli ( fd , " Resetting " ) ;
if ( tmp - > call )
ast_cli ( fd , " Call " ) ;
2004-07-19 02:18:11 +00:00
if ( tmp - > bearer )
ast_cli ( fd , " Bearer " ) ;
2003-02-07 19:23:19 +00:00
ast_cli ( fd , " \n " ) ;
2004-06-06 22:51:37 +00:00
if ( tmp - > logicalspan )
ast_cli ( fd , " PRI Logical Span: %d \n " , tmp - > logicalspan ) ;
2004-06-06 01:54:22 +00:00
else
2004-06-06 22:51:37 +00:00
ast_cli ( fd , " PRI Logical Span: Implicit \n " ) ;
2003-02-07 19:23:19 +00:00
}
2004-06-05 06:54:52 +00:00
2003-02-07 19:23:19 +00:00
# endif
# ifdef ZAPATA_R2
if ( tmp - > r2 ) {
ast_cli ( fd , " R2 Flags: " ) ;
if ( tmp - > r2blocked )
ast_cli ( fd , " Blocked " ) ;
if ( tmp - > hasr2call )
ast_cli ( fd , " Call " ) ;
ast_cli ( fd , " \n " ) ;
}
# endif
memset ( & ci , 0 , sizeof ( ci ) ) ;
2004-06-06 01:54:22 +00:00
ps . channo = tmp - > channel ;
if ( tmp - > subs [ SUB_REAL ] . zfd > - 1 ) {
if ( ! ioctl ( tmp - > subs [ SUB_REAL ] . zfd , ZT_GETCONF , & ci ) ) {
ast_cli ( fd , " Actual Confinfo: Num/%d, Mode/0x%04x \n " , ci . confno , ci . confmode ) ;
}
2003-05-19 23:33:41 +00:00
# ifdef ZT_GETCONFMUTE
2004-06-06 01:54:22 +00:00
if ( ! ioctl ( tmp - > subs [ SUB_REAL ] . zfd , ZT_GETCONFMUTE , & x ) ) {
ast_cli ( fd , " Actual Confmute: %s \n " , x ? " Yes " : " No " ) ;
}
2003-05-19 23:33:41 +00:00
# endif
2004-06-06 01:54:22 +00:00
if ( ioctl ( tmp - > subs [ SUB_REAL ] . zfd , ZT_GET_PARAMS , & ps ) < 0 ) {
ast_log ( LOG_WARNING , " Failed to get parameters on channel %d \n " , tmp - > channel ) ;
} else {
2004-11-05 17:10:28 +00:00
ast_cli ( fd , " Hookstate (FXS only): %s \n " , ps . rxisoffhook ? " Offhook " : " Onhook " ) ;
2004-06-06 01:54:22 +00:00
}
2004-04-06 15:50:18 +00:00
}
2004-06-06 01:54:22 +00:00
ast_mutex_unlock ( lock ) ;
2004-04-07 14:11:49 +00:00
return RESULT_SUCCESS ;
2001-10-09 02:06:21 +00:00
}
tmp = tmp - > next ;
}
ast_cli ( fd , " Unable to find given channel %d \n " , channel ) ;
2004-06-06 01:54:22 +00:00
ast_mutex_unlock ( lock ) ;
2001-10-09 02:06:21 +00:00
return RESULT_FAILURE ;
}
2004-02-23 05:02:24 +00:00
static char zap_show_cadences_help [ ] =
" Usage: zap show cadences \n "
" Shows all cadences currently defined \n " ;
static int handle_zap_show_cadences ( int fd , int argc , char * argv [ ] )
{
int i , j ;
for ( i = 0 ; i < num_cadence ; i + + ) {
char output [ 1024 ] ;
char tmp [ 16 ] , tmp2 [ 64 ] ;
2004-07-16 04:40:54 +00:00
snprintf ( tmp , sizeof ( tmp ) , " r%d: " , i + 1 ) ;
2004-02-23 05:02:24 +00:00
term_color ( output , tmp , COLOR_GREEN , COLOR_BLACK , sizeof ( output ) ) ;
for ( j = 0 ; j < 16 ; j + + ) {
if ( cadences [ i ] . ringcadence [ j ] = = 0 )
break ;
2004-07-16 04:40:54 +00:00
snprintf ( tmp , sizeof ( tmp ) , " %d " , cadences [ i ] . ringcadence [ j ] ) ;
2004-02-23 05:02:24 +00:00
if ( cidrings [ i ] * 2 - 1 = = j )
term_color ( tmp2 , tmp , COLOR_MAGENTA , COLOR_BLACK , sizeof ( tmp2 ) - 1 ) ;
else
term_color ( tmp2 , tmp , COLOR_GREEN , COLOR_BLACK , sizeof ( tmp2 ) - 1 ) ;
if ( j ! = 0 )
2004-07-16 04:40:54 +00:00
strncat ( output , " , " , sizeof ( output ) - strlen ( output ) - 1 ) ;
strncat ( output , tmp2 , sizeof ( output ) - strlen ( output ) - 1 ) ;
2004-02-23 05:02:24 +00:00
}
ast_cli ( fd , " %s \n " , output ) ;
}
return 0 ;
}
2005-05-16 14:41:05 +00:00
/* Based on irqmiss.c */
static int zap_show_status ( int fd , int argc , char * argv [ ] ) {
# define FORMAT "%-40.40s %-10.10s %10d %10d %10d\n"
# define FORMAT2 "%-40.40s %-10.10s %-10.10s %-10.10s %-10.10s\n"
int span ;
int res ;
char alarms [ 50 ] ;
int ctl ;
ZT_SPANINFO s ;
ctl = open ( " /dev/zap/ctl " , O_RDWR ) ;
if ( ctl < 0 ) {
fprintf ( stderr , " Unable to open /dev/zap/ctl: %s \n " , strerror ( errno ) ) ;
2005-06-24 02:37:32 +00:00
ast_cli ( fd , " No Zaptel interface found. \n " ) ;
2005-05-16 14:41:05 +00:00
return RESULT_FAILURE ;
}
ast_cli ( fd , FORMAT2 , " Description " , " Alarms " , " IRQ " , " bpviol " , " CRC4 " ) ;
for ( span = 1 ; span < ZT_MAX_SPANS ; + + span ) {
s . spanno = span ;
res = ioctl ( ctl , ZT_SPANSTAT , & s ) ;
if ( res ) {
continue ;
}
alarms [ 0 ] = ' \0 ' ;
if ( s . alarms > 0 ) {
if ( s . alarms & ZT_ALARM_BLUE )
strcat ( alarms , " BLU/ " ) ;
if ( s . alarms & ZT_ALARM_YELLOW )
strcat ( alarms , " YEL/ " ) ;
if ( s . alarms & ZT_ALARM_RED )
strcat ( alarms , " RED/ " ) ;
if ( s . alarms & ZT_ALARM_LOOPBACK )
strcat ( alarms , " LB/ " ) ;
if ( s . alarms & ZT_ALARM_RECOVER )
strcat ( alarms , " REC/ " ) ;
if ( s . alarms & ZT_ALARM_NOTOPEN )
strcat ( alarms , " NOP/ " ) ;
if ( ! strlen ( alarms ) )
strcat ( alarms , " UUU/ " ) ;
if ( strlen ( alarms ) ) {
/* Strip trailing / */
alarms [ strlen ( alarms ) - 1 ] = ' \0 ' ;
}
} else {
if ( s . numchans )
strcpy ( alarms , " OK " ) ;
else
strcpy ( alarms , " UNCONFIGURED " ) ;
}
ast_cli ( fd , FORMAT , s . desc , alarms , s . irqmisses , s . bpvcount , s . crc4count ) ;
}
close ( ctl ) ;
return RESULT_SUCCESS ;
2005-07-15 16:13:26 +00:00
# undef FORMAT
# undef FORMAT2
2005-05-16 14:41:05 +00:00
}
2001-10-09 02:06:21 +00:00
static char show_channels_usage [ ] =
" Usage: zap show channels \n "
" Shows a list of available channels \n " ;
static char show_channel_usage [ ] =
" Usage: zap show channel <chan num> \n "
" Detailed information about a given channel \n " ;
2004-10-16 22:34:57 +00:00
2005-05-16 14:41:05 +00:00
static char zap_show_status_usage [ ] =
" Usage: zap show status \n "
" Shows a list of Zaptel cards with status \n " ;
2001-10-09 02:06:21 +00:00
static char destroy_channel_usage [ ] =
" Usage: zap destroy channel <chan num> \n "
" DON'T USE THIS UNLESS YOU KNOW WHAT YOU ARE DOING. Immediately removes a given channel, whether it is in use or not \n " ;
2005-06-03 03:24:37 +00:00
static struct ast_cli_entry zap_cli [ ] = {
{ { " zap " , " show " , " cadences " , NULL } , handle_zap_show_cadences ,
" List cadences " , zap_show_cadences_help } ,
{ { " zap " , " show " , " channels " , NULL } , zap_show_channels ,
" Show active zapata channels " , show_channels_usage } ,
{ { " zap " , " show " , " channel " , NULL } , zap_show_channel ,
" Show information on a channel " , show_channel_usage } ,
{ { " zap " , " destroy " , " channel " , NULL } , zap_destroy_channel ,
" Destroy a channel " , destroy_channel_usage } ,
{ { " zap " , " show " , " status " , NULL } , zap_show_status ,
" Show all Zaptel cards status " , zap_show_status_usage } ,
} ;
2005-05-16 14:41:05 +00:00
2003-11-12 00:13:22 +00:00
# define TRANSFER 0
# define HANGUP 1
static int zap_fake_event ( struct zt_pvt * p , int mode )
{
if ( p ) {
switch ( mode ) {
case TRANSFER :
p - > fake_event = ZT_EVENT_WINKFLASH ;
break ;
case HANGUP :
p - > fake_event = ZT_EVENT_ONHOOK ;
break ;
default :
ast_log ( LOG_WARNING , " I don't know how to handle transfer event with this: %d on channel %s \n " , mode , p - > owner - > name ) ;
}
}
return 0 ;
}
static struct zt_pvt * find_channel ( int channel )
{
struct zt_pvt * p = iflist ;
while ( p ) {
if ( p - > channel = = channel ) {
break ;
}
p = p - > next ;
}
return p ;
}
2004-06-26 14:31:09 +00:00
static int action_zapdndon ( struct mansession * s , struct message * m )
{
struct zt_pvt * p = NULL ;
char * channel = astman_get_header ( m , " ZapChannel " ) ;
if ( ast_strlen_zero ( channel ) ) {
astman_send_error ( s , m , " No channel specified " ) ;
return 0 ;
}
p = find_channel ( atoi ( channel ) ) ;
if ( ! p ) {
astman_send_error ( s , m , " No such channel " ) ;
return 0 ;
}
p - > dnd = 1 ;
astman_send_ack ( s , m , " DND Enabled " ) ;
return 0 ;
}
static int action_zapdndoff ( struct mansession * s , struct message * m )
{
struct zt_pvt * p = NULL ;
char * channel = astman_get_header ( m , " ZapChannel " ) ;
if ( ast_strlen_zero ( channel ) ) {
astman_send_error ( s , m , " No channel specified " ) ;
return 0 ;
}
p = find_channel ( atoi ( channel ) ) ;
if ( ! p ) {
astman_send_error ( s , m , " No such channel " ) ;
return 0 ;
}
p - > dnd = 0 ;
astman_send_ack ( s , m , " DND Disabled " ) ;
return 0 ;
}
2003-11-12 00:13:22 +00:00
static int action_transfer ( struct mansession * s , struct message * m )
{
struct zt_pvt * p = NULL ;
char * channel = astman_get_header ( m , " ZapChannel " ) ;
2004-05-05 04:23:18 +00:00
if ( ast_strlen_zero ( channel ) ) {
2003-11-12 00:13:22 +00:00
astman_send_error ( s , m , " No channel specified " ) ;
return 0 ;
}
p = find_channel ( atoi ( channel ) ) ;
if ( ! p ) {
astman_send_error ( s , m , " No such channel " ) ;
return 0 ;
}
zap_fake_event ( p , TRANSFER ) ;
astman_send_ack ( s , m , " ZapTransfer " ) ;
return 0 ;
}
static int action_transferhangup ( struct mansession * s , struct message * m )
{
struct zt_pvt * p = NULL ;
char * channel = astman_get_header ( m , " ZapChannel " ) ;
2004-05-05 04:23:18 +00:00
if ( ast_strlen_zero ( channel ) ) {
2003-11-12 00:13:22 +00:00
astman_send_error ( s , m , " No channel specified " ) ;
return 0 ;
}
p = find_channel ( atoi ( channel ) ) ;
if ( ! p ) {
astman_send_error ( s , m , " No such channel " ) ;
return 0 ;
}
zap_fake_event ( p , HANGUP ) ;
astman_send_ack ( s , m , " ZapHangup " ) ;
return 0 ;
}
static int action_zapdialoffhook ( struct mansession * s , struct message * m )
{
struct zt_pvt * p = NULL ;
char * channel = astman_get_header ( m , " ZapChannel " ) ;
char * number = astman_get_header ( m , " Number " ) ;
int i ;
2004-05-05 04:23:18 +00:00
if ( ast_strlen_zero ( channel ) ) {
2003-11-12 00:13:22 +00:00
astman_send_error ( s , m , " No channel specified " ) ;
return 0 ;
}
2004-05-05 04:23:18 +00:00
if ( ast_strlen_zero ( number ) ) {
2003-11-12 00:13:22 +00:00
astman_send_error ( s , m , " No number specified " ) ;
return 0 ;
}
p = find_channel ( atoi ( channel ) ) ;
if ( ! p ) {
astman_send_error ( s , m , " No such channel " ) ;
return 0 ;
}
2004-07-28 18:38:29 +00:00
if ( ! p - > owner ) {
astman_send_error ( s , m , " Channel does not have it's owner " ) ;
return 0 ;
}
2003-11-12 00:13:22 +00:00
for ( i = 0 ; i < strlen ( number ) ; i + + ) {
struct ast_frame f = { AST_FRAME_DTMF , number [ i ] } ;
2004-09-10 18:47:13 +00:00
zap_queue_frame ( p , & f , NULL ) ;
2003-11-12 00:13:22 +00:00
}
astman_send_ack ( s , m , " ZapDialOffhook " ) ;
return 0 ;
}
2003-12-09 19:39:47 +00:00
2004-07-31 20:43:24 +00:00
static int action_zapshowchannels ( struct mansession * s , struct message * m )
{
struct zt_pvt * tmp = NULL ;
char * id = astman_get_header ( m , " ActionID " ) ;
char idText [ 256 ] = " " ;
astman_send_ack ( s , m , " Zapata channel status will follow " ) ;
if ( id & & ! ast_strlen_zero ( id ) )
snprintf ( idText , sizeof ( idText ) - 1 , " ActionID: %s \r \n " , id ) ;
ast_mutex_lock ( & iflock ) ;
tmp = iflist ;
while ( tmp ) {
if ( tmp - > channel > 0 ) {
int alarm = get_alarms ( tmp ) ;
2004-09-10 15:11:38 +00:00
ast_mutex_lock ( & s - > lock ) ;
2004-07-31 20:43:24 +00:00
ast_cli ( s - > fd ,
" Event: ZapShowChannels \r \n "
" Channel: %d \r \n "
" Signalling: %s \r \n "
" Context: %s \r \n "
2005-04-27 04:03:49 +00:00
" DND: %s \r \n "
2004-07-31 20:43:24 +00:00
" Alarm: %s \r \n "
" %s "
" \r \n " ,
tmp - > channel , sig2str ( tmp - > sig ) , tmp - > context ,
2005-04-27 04:03:49 +00:00
tmp - > dnd ? " Enabled " : " Disabled " ,
2004-07-31 20:43:24 +00:00
alarm2str ( alarm ) , idText ) ;
2004-09-10 15:11:38 +00:00
ast_mutex_unlock ( & s - > lock ) ;
2004-07-31 20:43:24 +00:00
}
tmp = tmp - > next ;
}
ast_mutex_unlock ( & iflock ) ;
2004-09-10 15:11:38 +00:00
ast_mutex_lock ( & s - > lock ) ;
2004-07-31 20:43:24 +00:00
ast_cli ( s - > fd ,
" Event: ZapShowChannelsComplete \r \n "
" %s "
" \r \n " ,
idText ) ;
2004-09-10 15:11:38 +00:00
ast_mutex_unlock ( & s - > lock ) ;
2004-07-31 20:43:24 +00:00
return 0 ;
}
2003-12-09 23:55:17 +00:00
static int __unload_module ( void )
2003-12-09 19:39:47 +00:00
{
2004-01-15 19:48:37 +00:00
int x = 0 ;
2003-12-09 19:39:47 +00:00
struct zt_pvt * p , * pl ;
2004-01-15 19:48:37 +00:00
# ifdef ZAPATA_PRI
2004-04-17 23:48:19 +00:00
int i ;
2004-01-15 19:48:37 +00:00
for ( i = 0 ; i < NUM_SPANS ; i + + ) {
2004-06-09 08:46:32 +00:00
if ( pris [ i ] . master ! = AST_PTHREADT_NULL )
pthread_cancel ( pris [ i ] . master ) ;
2004-01-15 19:48:37 +00:00
}
2005-06-03 03:24:37 +00:00
ast_cli_unregister_multiple ( zap_pri_cli , sizeof ( zap_pri_cli ) / sizeof ( zap_pri_cli [ 0 ] ) ) ;
2004-01-15 19:48:37 +00:00
# endif
# ifdef ZAPATA_R2
2005-06-03 03:24:37 +00:00
ast_cli_unregister_multiple ( zap_r2_cli , sizeof ( zap_r2_cli ) / sizeof ( zap_r2_cli [ 0 ] ) ) ;
2004-01-15 19:48:37 +00:00
# endif
2005-06-03 03:24:37 +00:00
ast_cli_unregister_multiple ( zap_cli , sizeof ( zap_cli ) / sizeof ( zap_cli [ 0 ] ) ) ;
2004-01-15 19:48:37 +00:00
ast_manager_unregister ( " ZapDialOffhook " ) ;
ast_manager_unregister ( " ZapHangup " ) ;
ast_manager_unregister ( " ZapTransfer " ) ;
2004-07-30 18:42:46 +00:00
ast_manager_unregister ( " ZapDNDoff " ) ;
ast_manager_unregister ( " ZapDNDon " ) ;
2004-07-31 20:43:24 +00:00
ast_manager_unregister ( " ZapShowChannels " ) ;
2005-03-04 06:47:24 +00:00
ast_channel_unregister ( & zap_tech ) ;
2003-12-09 19:39:47 +00:00
if ( ! ast_mutex_lock ( & iflock ) ) {
/* Hangup all interfaces if they have an owner */
p = iflist ;
while ( p ) {
if ( p - > owner )
ast_softhangup ( p - > owner , AST_SOFTHANGUP_APPUNLOAD ) ;
p = p - > next ;
}
ast_mutex_unlock ( & iflock ) ;
} else {
ast_log ( LOG_WARNING , " Unable to lock the monitor \n " ) ;
return - 1 ;
}
if ( ! ast_mutex_lock ( & monlock ) ) {
2004-06-23 01:27:44 +00:00
if ( monitor_thread & & ( monitor_thread ! = AST_PTHREADT_STOP ) & & ( monitor_thread ! = AST_PTHREADT_NULL ) ) {
2003-12-09 19:39:47 +00:00
pthread_cancel ( monitor_thread ) ;
pthread_kill ( monitor_thread , SIGURG ) ;
pthread_join ( monitor_thread , NULL ) ;
}
2004-03-15 07:51:22 +00:00
monitor_thread = AST_PTHREADT_STOP ;
2003-12-09 19:39:47 +00:00
ast_mutex_unlock ( & monlock ) ;
} else {
ast_log ( LOG_WARNING , " Unable to lock the monitor \n " ) ;
return - 1 ;
}
if ( ! ast_mutex_lock ( & iflock ) ) {
/* Destroy all the interfaces and free their memory */
p = iflist ;
while ( p ) {
/* Free any callerid */
if ( p - > cidspill )
free ( p - > cidspill ) ;
/* Close the zapata thingy */
if ( p - > subs [ SUB_REAL ] . zfd > - 1 )
zt_close ( p - > subs [ SUB_REAL ] . zfd ) ;
pl = p ;
p = p - > next ;
2004-01-15 19:48:37 +00:00
x + + ;
2003-12-09 19:39:47 +00:00
/* Free associated memory */
2004-06-22 17:42:14 +00:00
if ( pl )
destroy_zt_pvt ( & pl ) ;
2004-01-15 19:48:37 +00:00
ast_verbose ( VERBOSE_PREFIX_3 " Unregistered channel %d \n " , x ) ;
2003-12-09 19:39:47 +00:00
}
iflist = NULL ;
2004-04-25 22:37:09 +00:00
ifcount = 0 ;
2003-12-09 19:39:47 +00:00
ast_mutex_unlock ( & iflock ) ;
} else {
ast_log ( LOG_WARNING , " Unable to lock the monitor \n " ) ;
return - 1 ;
}
2004-01-15 19:48:37 +00:00
# ifdef ZAPATA_PRI
for ( i = 0 ; i < NUM_SPANS ; i + + ) {
2004-06-23 01:27:44 +00:00
if ( pris [ i ] . master & & ( pris [ i ] . master ! = AST_PTHREADT_NULL ) )
pthread_join ( pris [ i ] . master , NULL ) ;
2004-06-07 03:39:18 +00:00
zt_close ( pris [ i ] . fds [ i ] ) ;
2004-01-15 19:48:37 +00:00
}
# endif
2003-12-09 19:39:47 +00:00
return 0 ;
}
int unload_module ( )
{
2004-06-22 17:42:14 +00:00
# ifdef ZAPATA_PRI
int y ;
for ( y = 0 ; y < NUM_SPANS ; y + + )
ast_mutex_destroy ( & pris [ y ] . lock ) ;
# endif
2003-12-09 23:55:17 +00:00
return __unload_module ( ) ;
2003-12-09 19:39:47 +00:00
}
2004-10-16 22:34:57 +00:00
static int setup_zap ( int reload )
2001-10-09 02:06:21 +00:00
{
struct ast_config * cfg ;
struct ast_variable * v ;
struct zt_pvt * tmp ;
char * chan ;
2003-02-07 19:23:19 +00:00
char * c ;
2004-01-12 04:28:00 +00:00
char * ringc ;
2001-10-09 02:06:21 +00:00
int start , finish , x ;
int y ;
2004-06-02 16:35:06 +00:00
int found_pseudo = 0 ;
2003-02-07 19:23:19 +00:00
int cur_radio = 0 ;
2001-10-09 02:06:21 +00:00
# ifdef ZAPATA_PRI
2004-06-05 06:54:52 +00:00
int spanno ;
2004-06-07 03:39:18 +00:00
int i ;
2004-06-05 06:54:52 +00:00
int logicalspan ;
int trunkgroup ;
2004-06-07 03:39:18 +00:00
int dchannels [ NUM_DCHANS ] ;
2004-06-06 01:54:22 +00:00
struct zt_pri * pri ;
2001-10-09 02:06:21 +00:00
# endif
2003-12-09 19:39:47 +00:00
2005-01-25 06:10:20 +00:00
cfg = ast_config_load ( config ) ;
2001-10-09 02:06:21 +00:00
/* We *must* have a config file otherwise stop immediately */
if ( ! cfg ) {
ast_log ( LOG_ERROR , " Unable to load config %s \n " , config ) ;
return - 1 ;
}
2003-08-13 15:25:16 +00:00
if ( ast_mutex_lock ( & iflock ) ) {
2001-10-09 02:06:21 +00:00
/* It's a little silly to lock it, but we mind as well just to be sure */
ast_log ( LOG_ERROR , " Unable to lock interface list??? \n " ) ;
return - 1 ;
}
2004-06-05 06:54:52 +00:00
# ifdef ZAPATA_PRI
2004-12-11 00:02:08 +00:00
if ( ! reload ) {
/* Process trunkgroups first */
v = ast_variable_browse ( cfg , " trunkgroups " ) ;
while ( v ) {
if ( ! strcasecmp ( v - > name , " trunkgroup " ) ) {
trunkgroup = atoi ( v - > value ) ;
if ( trunkgroup > 0 ) {
if ( ( c = strchr ( v - > value , ' , ' ) ) ) {
i = 0 ;
memset ( dchannels , 0 , sizeof ( dchannels ) ) ;
while ( c & & ( i < NUM_DCHANS ) ) {
dchannels [ i ] = atoi ( c + 1 ) ;
if ( dchannels [ i ] < 0 ) {
ast_log ( LOG_WARNING , " D-channel for trunk group %d must be a postiive number at line %d of zapata.conf \n " , trunkgroup , v - > lineno ) ;
} else
i + + ;
c = strchr ( c + 1 , ' , ' ) ;
}
if ( i ) {
if ( pri_create_trunkgroup ( trunkgroup , dchannels ) ) {
ast_log ( LOG_WARNING , " Unable to create trunk group %d with Primary D-channel %d at line %d of zapata.conf \n " , trunkgroup , dchannels [ 0 ] , v - > lineno ) ;
} else if ( option_verbose > 1 )
ast_verbose ( VERBOSE_PREFIX_2 " Created trunk group %d with Primary D-channel %d and %d backup%s \n " , trunkgroup , dchannels [ 0 ] , i - 1 , ( i = = 1 ) ? " " : " s " ) ;
2004-06-07 03:39:18 +00:00
} else
2004-12-11 00:02:08 +00:00
ast_log ( LOG_WARNING , " Trunk group %d lacks any valid D-channels at line %d of zapata.conf \n " , trunkgroup , v - > lineno ) ;
2004-06-05 06:54:52 +00:00
} else
2004-12-11 00:02:08 +00:00
ast_log ( LOG_WARNING , " Trunk group %d lacks a primary D-channel at line %d of zapata.conf \n " , trunkgroup , v - > lineno ) ;
2004-06-05 06:54:52 +00:00
} else
2004-12-11 00:02:08 +00:00
ast_log ( LOG_WARNING , " Trunk group identifier must be a positive integer at line %d of zapata.conf \n " , v - > lineno ) ;
} else if ( ! strcasecmp ( v - > name , " spanmap " ) ) {
spanno = atoi ( v - > value ) ;
if ( spanno > 0 ) {
if ( ( c = strchr ( v - > value , ' , ' ) ) ) {
trunkgroup = atoi ( c + 1 ) ;
if ( trunkgroup > 0 ) {
if ( ( c = strchr ( c + 1 , ' , ' ) ) )
logicalspan = atoi ( c + 1 ) ;
else
logicalspan = 0 ;
if ( logicalspan > = 0 ) {
if ( pri_create_spanmap ( spanno - 1 , trunkgroup , logicalspan ) ) {
ast_log ( LOG_WARNING , " Failed to map span %d to trunk group %d (logical span %d) \n " , spanno , trunkgroup , logicalspan ) ;
} else if ( option_verbose > 1 )
ast_verbose ( VERBOSE_PREFIX_2 " Mapped span %d to trunk group %d (logical span %d) \n " , spanno , trunkgroup , logicalspan ) ;
} else
ast_log ( LOG_WARNING , " Logical span must be a postive number, or '0' (for unspecified) at line %d of zapata.conf \n " , v - > lineno ) ;
2004-06-05 06:54:52 +00:00
} else
2004-12-11 00:02:08 +00:00
ast_log ( LOG_WARNING , " Trunk group must be a postive number at line %d of zapata.conf \n " , v - > lineno ) ;
2004-06-05 06:54:52 +00:00
} else
2004-12-11 00:02:08 +00:00
ast_log ( LOG_WARNING , " Missing trunk group for span map at line %d of zapata.conf \n " , v - > lineno ) ;
2004-06-05 06:54:52 +00:00
} else
2004-12-11 00:02:08 +00:00
ast_log ( LOG_WARNING , " Span number must be a postive integer at line %d of zapata.conf \n " , v - > lineno ) ;
} else {
ast_log ( LOG_NOTICE , " Ignoring unknown keyword '%s' in trunkgroups \n " , v - > name ) ;
}
v = v - > next ;
2004-06-05 06:54:52 +00:00
}
}
# endif
2001-10-09 02:06:21 +00:00
v = ast_variable_browse ( cfg , " channels " ) ;
while ( v ) {
/* Create the interface list */
2004-06-06 01:54:22 +00:00
if ( ! strcasecmp ( v - > name , " channel " )
# ifdef ZAPATA_PRI
| | ! strcasecmp ( v - > name , " crv " )
# endif
) {
2004-10-16 22:34:57 +00:00
if ( reload = = 0 ) {
if ( cur_signalling < 0 ) {
ast_log ( LOG_ERROR , " Signalling must be specified before any channels are. \n " ) ;
2005-01-25 06:10:20 +00:00
ast_config_destroy ( cfg ) ;
2004-10-16 22:34:57 +00:00
ast_mutex_unlock ( & iflock ) ;
return - 1 ;
}
2001-10-09 02:06:21 +00:00
}
2003-02-07 19:23:19 +00:00
c = v - > value ;
2004-10-16 22:34:57 +00:00
2004-06-06 01:54:22 +00:00
# ifdef ZAPATA_PRI
pri = NULL ;
if ( ! strcasecmp ( v - > name , " crv " ) ) {
if ( sscanf ( c , " %d:%n " , & trunkgroup , & y ) ! = 1 ) {
ast_log ( LOG_WARNING , " CRV must begin with trunkgroup followed by a colon at line %d \n " , v - > lineno ) ;
2005-01-25 06:10:20 +00:00
ast_config_destroy ( cfg ) ;
2004-06-06 01:54:22 +00:00
ast_mutex_unlock ( & iflock ) ;
return - 1 ;
}
if ( trunkgroup < 1 ) {
ast_log ( LOG_WARNING , " CRV trunk group must be a postive number at line %d \n " , v - > lineno ) ;
2005-01-25 06:10:20 +00:00
ast_config_destroy ( cfg ) ;
2004-06-06 01:54:22 +00:00
ast_mutex_unlock ( & iflock ) ;
return - 1 ;
}
c + = y ;
for ( y = 0 ; y < NUM_SPANS ; y + + ) {
if ( pris [ y ] . trunkgroup = = trunkgroup ) {
pri = pris + y ;
break ;
}
}
if ( ! pri ) {
ast_log ( LOG_WARNING , " No such trunk group %d at CRV declaration at line %d \n " , trunkgroup , v - > lineno ) ;
2005-01-25 06:10:20 +00:00
ast_config_destroy ( cfg ) ;
2004-06-06 01:54:22 +00:00
ast_mutex_unlock ( & iflock ) ;
return - 1 ;
}
}
# endif
2003-02-07 19:23:19 +00:00
chan = strsep ( & c , " , " ) ;
2001-10-09 02:06:21 +00:00
while ( chan ) {
if ( sscanf ( chan , " %d-%d " , & start , & finish ) = = 2 ) {
/* Range */
} else if ( sscanf ( chan , " %d " , & start ) ) {
/* Just one */
finish = start ;
2002-06-24 17:59:56 +00:00
} else if ( ! strcasecmp ( chan , " pseudo " ) ) {
finish = start = CHAN_PSEUDO ;
2004-06-02 16:35:06 +00:00
found_pseudo = 1 ;
2001-10-09 02:06:21 +00:00
} else {
ast_log ( LOG_ERROR , " Syntax error parsing '%s' at '%s' \n " , v - > value , chan ) ;
2005-01-25 06:10:20 +00:00
ast_config_destroy ( cfg ) ;
2003-08-13 15:25:16 +00:00
ast_mutex_unlock ( & iflock ) ;
2001-10-09 02:06:21 +00:00
return - 1 ;
}
if ( finish < start ) {
ast_log ( LOG_WARNING , " Sillyness: %d < %d \n " , start , finish ) ;
x = finish ;
finish = start ;
start = x ;
}
for ( x = start ; x < = finish ; x + + ) {
2004-06-06 01:54:22 +00:00
# ifdef ZAPATA_PRI
2004-10-16 22:34:57 +00:00
tmp = mkintf ( x , cur_signalling , cur_radio , pri , reload ) ;
# else
tmp = mkintf ( x , cur_signalling , cur_radio , NULL , reload ) ;
2004-06-06 01:54:22 +00:00
# endif
2004-01-15 19:48:37 +00:00
2001-10-09 02:06:21 +00:00
if ( tmp ) {
2004-06-06 01:54:22 +00:00
if ( option_verbose > 2 ) {
# ifdef ZAPATA_PRI
if ( pri )
2004-10-16 22:34:57 +00:00
ast_verbose ( VERBOSE_PREFIX_3 " %s CRV %d:%d, %s signalling \n " , reload ? " Reconfigured " : " Registered " , trunkgroup , x , sig2str ( tmp - > sig ) ) ;
2004-06-06 01:54:22 +00:00
else
# endif
2004-10-16 22:34:57 +00:00
ast_verbose ( VERBOSE_PREFIX_3 " %s channel %d, %s signalling \n " , reload ? " Reconfigured " : " Registered " , x , sig2str ( tmp - > sig ) ) ;
2004-06-06 01:54:22 +00:00
}
2001-10-09 02:06:21 +00:00
} else {
2004-10-16 22:34:57 +00:00
if ( reload = = 1 )
ast_log ( LOG_ERROR , " Unable to reconfigure channel '%s' \n " , v - > value ) ;
else
ast_log ( LOG_ERROR , " Unable to register channel '%s' \n " , v - > value ) ;
2005-01-25 06:10:20 +00:00
ast_config_destroy ( cfg ) ;
2003-08-13 15:25:16 +00:00
ast_mutex_unlock ( & iflock ) ;
2001-10-09 02:06:21 +00:00
return - 1 ;
}
}
2003-02-07 19:23:19 +00:00
chan = strsep ( & c , " , " ) ;
2001-10-09 02:06:21 +00:00
}
2004-01-12 04:28:00 +00:00
} else if ( ! strcasecmp ( v - > name , " usedistinctiveringdetection " ) ) {
2004-03-11 05:10:23 +00:00
if ( ast_true ( v - > value ) )
usedistinctiveringdetection = 1 ;
2004-01-12 04:28:00 +00:00
} else if ( ! strcasecmp ( v - > name , " dring1context " ) ) {
2005-05-15 23:26:45 +00:00
ast_copy_string ( drings . ringContext [ 0 ] . contextData , v - > value , sizeof ( drings . ringContext [ 0 ] . contextData ) ) ;
2004-01-12 04:28:00 +00:00
} else if ( ! strcasecmp ( v - > name , " dring2context " ) ) {
2005-05-15 23:26:45 +00:00
ast_copy_string ( drings . ringContext [ 1 ] . contextData , v - > value , sizeof ( drings . ringContext [ 1 ] . contextData ) ) ;
2004-01-12 04:28:00 +00:00
} else if ( ! strcasecmp ( v - > name , " dring3context " ) ) {
2005-05-15 23:26:45 +00:00
ast_copy_string ( drings . ringContext [ 2 ] . contextData , v - > value , sizeof ( drings . ringContext [ 2 ] . contextData ) ) ;
2004-01-12 04:28:00 +00:00
} else if ( ! strcasecmp ( v - > name , " dring1 " ) ) {
ringc = v - > value ;
sscanf ( ringc , " %d,%d,%d " , & drings . ringnum [ 0 ] . ring [ 0 ] , & drings . ringnum [ 0 ] . ring [ 1 ] , & drings . ringnum [ 0 ] . ring [ 2 ] ) ;
} else if ( ! strcasecmp ( v - > name , " dring2 " ) ) {
ringc = v - > value ;
sscanf ( ringc , " %d,%d,%d " , & drings . ringnum [ 1 ] . ring [ 0 ] , & drings . ringnum [ 1 ] . ring [ 1 ] , & drings . ringnum [ 1 ] . ring [ 2 ] ) ;
} else if ( ! strcasecmp ( v - > name , " dring3 " ) ) {
ringc = v - > value ;
sscanf ( ringc , " %d,%d,%d " , & drings . ringnum [ 2 ] . ring [ 0 ] , & drings . ringnum [ 2 ] . ring [ 1 ] , & drings . ringnum [ 2 ] . ring [ 2 ] ) ;
2001-10-09 02:06:21 +00:00
} else if ( ! strcasecmp ( v - > name , " usecallerid " ) ) {
use_callerid = ast_true ( v - > value ) ;
2004-09-19 16:17:18 +00:00
} else if ( ! strcasecmp ( v - > name , " cidsignalling " ) ) {
if ( ! strcasecmp ( v - > value , " bell " ) )
cid_signalling = CID_SIG_BELL ;
else if ( ! strcasecmp ( v - > value , " v23 " ) )
cid_signalling = CID_SIG_V23 ;
else if ( ! strcasecmp ( v - > value , " dtmf " ) )
cid_signalling = CID_SIG_DTMF ;
else if ( ast_true ( v - > value ) )
cid_signalling = CID_SIG_BELL ;
} else if ( ! strcasecmp ( v - > name , " cidstart " ) ) {
if ( ! strcasecmp ( v - > value , " ring " ) )
cid_start = CID_START_RING ;
else if ( ! strcasecmp ( v - > value , " polarity " ) )
cid_start = CID_START_POLARITY ;
else if ( ast_true ( v - > value ) )
cid_start = CID_START_RING ;
2001-10-09 02:06:21 +00:00
} else if ( ! strcasecmp ( v - > name , " threewaycalling " ) ) {
threewaycalling = ast_true ( v - > value ) ;
2002-03-08 23:48:42 +00:00
} else if ( ! strcasecmp ( v - > name , " cancallforward " ) ) {
cancallforward = ast_true ( v - > value ) ;
2003-02-07 19:23:19 +00:00
} else if ( ! strcasecmp ( v - > name , " relaxdtmf " ) ) {
if ( ast_true ( v - > value ) )
relaxdtmf = DSP_DIGITMODE_RELAXDTMF ;
else
relaxdtmf = 0 ;
2002-03-08 23:48:42 +00:00
} else if ( ! strcasecmp ( v - > name , " mailbox " ) ) {
2005-05-15 23:26:45 +00:00
ast_copy_string ( mailbox , v - > value , sizeof ( mailbox ) ) ;
2001-12-29 18:04:21 +00:00
} else if ( ! strcasecmp ( v - > name , " adsi " ) ) {
adsi = ast_true ( v - > value ) ;
2001-10-09 02:06:21 +00:00
} else if ( ! strcasecmp ( v - > name , " transfer " ) ) {
transfer = ast_true ( v - > value ) ;
2004-12-09 22:39:14 +00:00
} else if ( ! strcasecmp ( v - > name , " canpark " ) ) {
canpark = ast_true ( v - > value ) ;
2002-09-10 04:45:51 +00:00
} else if ( ! strcasecmp ( v - > name , " echocancelwhenbridged " ) ) {
echocanbridged = ast_true ( v - > value ) ;
2003-02-07 19:23:19 +00:00
} else if ( ! strcasecmp ( v - > name , " busydetect " ) ) {
busydetect = ast_true ( v - > value ) ;
2003-03-06 06:00:17 +00:00
} else if ( ! strcasecmp ( v - > name , " busycount " ) ) {
busycount = atoi ( v - > value ) ;
2005-08-08 00:08:48 +00:00
} else if ( ! strcasecmp ( v - > name , " busypattern " ) ) {
if ( sscanf ( v - > value , " %d,%d " , & busy_tonelength , & busy_quietlength ) ! = 2 ) {
ast_log ( LOG_ERROR , " busypattern= expects busypattern=tonelength,quietlength \n " ) ;
}
2003-02-07 19:23:19 +00:00
} else if ( ! strcasecmp ( v - > name , " callprogress " ) ) {
2004-06-07 23:38:39 +00:00
if ( ast_true ( v - > value ) )
callprogress | = 1 ;
else
callprogress & = ~ 1 ;
} else if ( ! strcasecmp ( v - > name , " faxdetect " ) ) {
2004-06-08 22:34:25 +00:00
if ( ! strcasecmp ( v - > value , " incoming " ) ) {
callprogress | = 4 ;
callprogress & = ~ 2 ;
} else if ( ! strcasecmp ( v - > value , " outgoing " ) ) {
callprogress & = ~ 4 ;
2004-06-07 23:38:39 +00:00
callprogress | = 2 ;
2004-06-08 22:34:25 +00:00
} else if ( ! strcasecmp ( v - > value , " both " ) | | ast_true ( v - > value ) )
callprogress | = 6 ;
2004-06-07 23:38:39 +00:00
else
2004-06-08 22:34:25 +00:00
callprogress & = ~ 6 ;
2001-10-09 02:06:21 +00:00
} else if ( ! strcasecmp ( v - > name , " echocancel " ) ) {
2004-05-05 04:23:18 +00:00
if ( v - > value & & ! ast_strlen_zero ( v - > value ) ) {
2002-03-08 23:48:42 +00:00
y = atoi ( v - > value ) ;
2003-03-24 20:33:33 +00:00
} else
2002-03-08 23:48:42 +00:00
y = 0 ;
if ( ( y = = 32 ) | | ( y = = 64 ) | | ( y = = 128 ) | | ( y = = 256 ) )
echocancel = y ;
2003-03-24 20:33:33 +00:00
else {
2002-03-08 23:48:42 +00:00
echocancel = ast_true ( v - > value ) ;
2003-03-24 20:33:33 +00:00
if ( echocancel )
echocancel = 128 ;
}
2003-10-27 17:16:08 +00:00
} else if ( ! strcasecmp ( v - > name , " echotraining " ) ) {
2005-04-29 17:00:33 +00:00
if ( sscanf ( v - > value , " %d " , & y ) = = 1 ) {
2004-06-23 22:00:04 +00:00
if ( ( y < 10 ) | | ( y > 4000 ) ) {
ast_log ( LOG_WARNING , " Echo training time must be within the range of 10 to 2000 ms at line %d \n " , v - > lineno ) ;
} else {
echotraining = y ;
}
} else if ( ast_true ( v - > value ) ) {
echotraining = 400 ;
} else
echotraining = 0 ;
2001-10-09 02:06:21 +00:00
} else if ( ! strcasecmp ( v - > name , " hidecallerid " ) ) {
hidecallerid = ast_true ( v - > value ) ;
2004-09-13 23:07:50 +00:00
} else if ( ! strcasecmp ( v - > name , " pulsedial " ) ) {
pulse = ast_true ( v - > value ) ;
2003-02-07 19:23:19 +00:00
} else if ( ! strcasecmp ( v - > name , " callreturn " ) ) {
callreturn = ast_true ( v - > value ) ;
2001-10-09 02:06:21 +00:00
} else if ( ! strcasecmp ( v - > name , " callwaiting " ) ) {
callwaiting = ast_true ( v - > value ) ;
} else if ( ! strcasecmp ( v - > name , " callwaitingcallerid " ) ) {
callwaitingcallerid = ast_true ( v - > value ) ;
} else if ( ! strcasecmp ( v - > name , " context " ) ) {
2005-05-15 23:26:45 +00:00
ast_copy_string ( context , v - > value , sizeof ( context ) ) ;
2001-10-09 02:06:21 +00:00
} else if ( ! strcasecmp ( v - > name , " language " ) ) {
2005-05-15 23:26:45 +00:00
ast_copy_string ( language , v - > value , sizeof ( language ) ) ;
2004-03-30 21:23:16 +00:00
} else if ( ! strcasecmp ( v - > name , " progzone " ) ) {
2005-05-15 23:26:45 +00:00
ast_copy_string ( progzone , v - > value , sizeof ( progzone ) ) ;
2002-06-24 17:59:56 +00:00
} else if ( ! strcasecmp ( v - > name , " musiconhold " ) ) {
2005-05-15 23:26:45 +00:00
ast_copy_string ( musicclass , v - > value , sizeof ( musicclass ) ) ;
2001-10-09 02:06:21 +00:00
} else if ( ! strcasecmp ( v - > name , " stripmsd " ) ) {
stripmsd = atoi ( v - > value ) ;
2003-10-24 18:22:45 +00:00
} else if ( ! strcasecmp ( v - > name , " jitterbuffers " ) ) {
numbufs = atoi ( v - > value ) ;
2001-10-09 02:06:21 +00:00
} else if ( ! strcasecmp ( v - > name , " group " ) ) {
2003-04-09 04:00:43 +00:00
cur_group = ast_get_group ( v - > value ) ;
2001-10-09 02:06:21 +00:00
} else if ( ! strcasecmp ( v - > name , " callgroup " ) ) {
2003-04-09 04:00:43 +00:00
cur_callergroup = ast_get_group ( v - > value ) ;
2001-10-09 02:06:21 +00:00
} else if ( ! strcasecmp ( v - > name , " pickupgroup " ) ) {
2003-04-09 04:00:43 +00:00
cur_pickupgroup = ast_get_group ( v - > value ) ;
2001-10-09 02:06:21 +00:00
} else if ( ! strcasecmp ( v - > name , " immediate " ) ) {
immediate = ast_true ( v - > value ) ;
2005-06-23 14:51:52 +00:00
} else if ( ! strcasecmp ( v - > name , " transfertobusy " ) ) {
transfertobusy = ast_true ( v - > value ) ;
2001-10-09 02:06:21 +00:00
} else if ( ! strcasecmp ( v - > name , " rxgain " ) ) {
if ( sscanf ( v - > value , " %f " , & rxgain ) ! = 1 ) {
ast_log ( LOG_WARNING , " Invalid rxgain: %s \n " , v - > value ) ;
}
} else if ( ! strcasecmp ( v - > name , " txgain " ) ) {
if ( sscanf ( v - > value , " %f " , & txgain ) ! = 1 ) {
ast_log ( LOG_WARNING , " Invalid txgain: %s \n " , v - > value ) ;
}
2004-02-15 07:35:32 +00:00
} else if ( ! strcasecmp ( v - > name , " tonezone " ) ) {
if ( sscanf ( v - > value , " %d " , & tonezone ) ! = 1 ) {
ast_log ( LOG_WARNING , " Invalid tonezone: %s \n " , v - > value ) ;
}
2001-10-09 02:06:21 +00:00
} else if ( ! strcasecmp ( v - > name , " callerid " ) ) {
2004-10-02 00:58:31 +00:00
if ( ! strcasecmp ( v - > value , " asreceived " ) ) {
cid_num [ 0 ] = ' \0 ' ;
cid_name [ 0 ] = ' \0 ' ;
} else {
ast_callerid_split ( v - > value , cid_name , sizeof ( cid_name ) , cid_num , sizeof ( cid_num ) ) ;
}
2003-12-17 23:39:16 +00:00
} else if ( ! strcasecmp ( v - > name , " useincomingcalleridonzaptransfer " ) ) {
2003-12-18 16:01:08 +00:00
zaptrcallerid = ast_true ( v - > value ) ;
2003-09-05 04:00:57 +00:00
} else if ( ! strcasecmp ( v - > name , " restrictcid " ) ) {
restrictcid = ast_true ( v - > value ) ;
2003-10-01 15:59:26 +00:00
} else if ( ! strcasecmp ( v - > name , " usecallingpres " ) ) {
use_callingpres = ast_true ( v - > value ) ;
2001-12-29 18:04:21 +00:00
} else if ( ! strcasecmp ( v - > name , " accountcode " ) ) {
2005-05-15 23:26:45 +00:00
ast_copy_string ( accountcode , v - > value , sizeof ( accountcode ) ) ;
2001-12-29 18:04:21 +00:00
} else if ( ! strcasecmp ( v - > name , " amaflags " ) ) {
y = ast_cdr_amaflags2int ( v - > value ) ;
if ( y < 0 )
ast_log ( LOG_WARNING , " Invalid AMA flags: %s at line %d \n " , v - > value , v - > lineno ) ;
else
amaflags = y ;
2004-10-16 22:34:57 +00:00
} else if ( ! reload ) {
if ( ! strcasecmp ( v - > name , " signalling " ) ) {
if ( ! strcasecmp ( v - > value , " em " ) ) {
cur_signalling = SIG_EM ;
} else if ( ! strcasecmp ( v - > value , " em_e1 " ) ) {
cur_signalling = SIG_EM_E1 ;
} else if ( ! strcasecmp ( v - > value , " em_w " ) ) {
cur_signalling = SIG_EMWINK ;
cur_radio = 0 ;
} else if ( ! strcasecmp ( v - > value , " fxs_ls " ) ) {
cur_signalling = SIG_FXSLS ;
cur_radio = 0 ;
} else if ( ! strcasecmp ( v - > value , " fxs_gs " ) ) {
cur_signalling = SIG_FXSGS ;
cur_radio = 0 ;
} else if ( ! strcasecmp ( v - > value , " fxs_ks " ) ) {
cur_signalling = SIG_FXSKS ;
cur_radio = 0 ;
} else if ( ! strcasecmp ( v - > value , " fxo_ls " ) ) {
cur_signalling = SIG_FXOLS ;
cur_radio = 0 ;
} else if ( ! strcasecmp ( v - > value , " fxo_gs " ) ) {
cur_signalling = SIG_FXOGS ;
cur_radio = 0 ;
} else if ( ! strcasecmp ( v - > value , " fxo_ks " ) ) {
cur_signalling = SIG_FXOKS ;
cur_radio = 0 ;
} else if ( ! strcasecmp ( v - > value , " fxs_rx " ) ) {
cur_signalling = SIG_FXSKS ;
cur_radio = 1 ;
} else if ( ! strcasecmp ( v - > value , " fxo_rx " ) ) {
cur_signalling = SIG_FXOLS ;
cur_radio = 1 ;
} else if ( ! strcasecmp ( v - > value , " fxs_tx " ) ) {
cur_signalling = SIG_FXSLS ;
cur_radio = 1 ;
} else if ( ! strcasecmp ( v - > value , " fxo_tx " ) ) {
cur_signalling = SIG_FXOGS ;
cur_radio = 1 ;
} else if ( ! strcasecmp ( v - > value , " em_rx " ) ) {
cur_signalling = SIG_EM ;
cur_radio = 1 ;
} else if ( ! strcasecmp ( v - > value , " em_tx " ) ) {
cur_signalling = SIG_EM ;
cur_radio = 1 ;
} else if ( ! strcasecmp ( v - > value , " em_rxtx " ) ) {
cur_signalling = SIG_EM ;
cur_radio = 2 ;
} else if ( ! strcasecmp ( v - > value , " em_txrx " ) ) {
cur_signalling = SIG_EM ;
cur_radio = 2 ;
} else if ( ! strcasecmp ( v - > value , " sf " ) ) {
cur_signalling = SIG_SF ;
cur_radio = 0 ;
} else if ( ! strcasecmp ( v - > value , " sf_w " ) ) {
cur_signalling = SIG_SFWINK ;
cur_radio = 0 ;
} else if ( ! strcasecmp ( v - > value , " sf_featd " ) ) {
cur_signalling = SIG_FEATD ;
cur_radio = 0 ;
} else if ( ! strcasecmp ( v - > value , " sf_featdmf " ) ) {
cur_signalling = SIG_FEATDMF ;
cur_radio = 0 ;
} else if ( ! strcasecmp ( v - > value , " sf_featb " ) ) {
cur_signalling = SIG_SF_FEATB ;
cur_radio = 0 ;
} else if ( ! strcasecmp ( v - > value , " sf " ) ) {
cur_signalling = SIG_SF ;
cur_radio = 0 ;
} else if ( ! strcasecmp ( v - > value , " sf_rx " ) ) {
cur_signalling = SIG_SF ;
cur_radio = 1 ;
} else if ( ! strcasecmp ( v - > value , " sf_tx " ) ) {
cur_signalling = SIG_SF ;
cur_radio = 1 ;
} else if ( ! strcasecmp ( v - > value , " sf_rxtx " ) ) {
cur_signalling = SIG_SF ;
cur_radio = 2 ;
} else if ( ! strcasecmp ( v - > value , " sf_txrx " ) ) {
cur_signalling = SIG_SF ;
cur_radio = 2 ;
} else if ( ! strcasecmp ( v - > value , " featd " ) ) {
cur_signalling = SIG_FEATD ;
cur_radio = 0 ;
} else if ( ! strcasecmp ( v - > value , " featdmf " ) ) {
cur_signalling = SIG_FEATDMF ;
cur_radio = 0 ;
2005-04-22 19:10:35 +00:00
} else if ( ! strcasecmp ( v - > value , " featdmf_ta " ) ) {
cur_signalling = SIG_FEATDMF_TA ;
cur_radio = 0 ;
2004-10-16 22:34:57 +00:00
} else if ( ! strcasecmp ( v - > value , " e911 " ) ) {
cur_signalling = SIG_E911 ;
cur_radio = 0 ;
} else if ( ! strcasecmp ( v - > value , " featb " ) ) {
cur_signalling = SIG_FEATB ;
cur_radio = 0 ;
2001-10-09 02:06:21 +00:00
# ifdef ZAPATA_PRI
2004-10-16 22:34:57 +00:00
} else if ( ! strcasecmp ( v - > value , " pri_net " ) ) {
cur_radio = 0 ;
cur_signalling = SIG_PRI ;
pritype = PRI_NETWORK ;
} else if ( ! strcasecmp ( v - > value , " pri_cpe " ) ) {
cur_signalling = SIG_PRI ;
cur_radio = 0 ;
pritype = PRI_CPE ;
} else if ( ! strcasecmp ( v - > value , " gr303fxoks_net " ) ) {
cur_signalling = SIG_GR303FXOKS ;
cur_radio = 0 ;
pritype = PRI_NETWORK ;
} else if ( ! strcasecmp ( v - > value , " gr303fxsks_cpe " ) ) {
cur_signalling = SIG_GR303FXSKS ;
cur_radio = 0 ;
pritype = PRI_CPE ;
2001-10-09 02:06:21 +00:00
# endif
2003-02-07 19:23:19 +00:00
# ifdef ZAPATA_R2
2004-10-16 22:34:57 +00:00
} else if ( ! strcasecmp ( v - > value , " r2 " ) ) {
cur_signalling = SIG_R2 ;
cur_radio = 0 ;
# endif
} else {
ast_log ( LOG_ERROR , " Unknown signalling method '%s' \n " , v - > value ) ;
}
2003-02-07 19:23:19 +00:00
# ifdef ZAPATA_R2
2004-10-16 22:34:57 +00:00
} else if ( ! strcasecmp ( v - > name , " r2country " ) ) {
r2prot = str2r2prot ( v - > value ) ;
if ( r2prot < 0 ) {
ast_log ( LOG_WARNING , " Unknown R2 Country '%s' at line %d. \n " , v - > value , v - > lineno ) ;
}
2003-02-07 19:23:19 +00:00
# endif
2001-10-09 02:06:21 +00:00
# ifdef ZAPATA_PRI
2004-10-16 22:34:57 +00:00
} else if ( ! strcasecmp ( v - > name , " pridialplan " ) ) {
if ( ! strcasecmp ( v - > value , " national " ) ) {
dialplan = PRI_NATIONAL_ISDN + 1 ;
} else if ( ! strcasecmp ( v - > value , " unknown " ) ) {
dialplan = PRI_UNKNOWN + 1 ;
} else if ( ! strcasecmp ( v - > value , " private " ) ) {
dialplan = PRI_PRIVATE + 1 ;
} else if ( ! strcasecmp ( v - > value , " international " ) ) {
dialplan = PRI_INTERNATIONAL_ISDN + 1 ;
} else if ( ! strcasecmp ( v - > value , " local " ) ) {
dialplan = PRI_LOCAL_ISDN + 1 ;
2005-03-03 17:00:57 +00:00
} else if ( ! strcasecmp ( v - > value , " dynamic " ) ) {
dialplan = - 1 ;
2004-10-16 22:34:57 +00:00
} else {
ast_log ( LOG_WARNING , " Unknown PRI dialplan '%s' at line %d. \n " , v - > value , v - > lineno ) ;
}
} else if ( ! strcasecmp ( v - > name , " prilocaldialplan " ) ) {
if ( ! strcasecmp ( v - > value , " national " ) ) {
localdialplan = PRI_NATIONAL_ISDN + 1 ;
} else if ( ! strcasecmp ( v - > value , " unknown " ) ) {
localdialplan = PRI_UNKNOWN + 1 ;
} else if ( ! strcasecmp ( v - > value , " private " ) ) {
localdialplan = PRI_PRIVATE + 1 ;
} else if ( ! strcasecmp ( v - > value , " international " ) ) {
localdialplan = PRI_INTERNATIONAL_ISDN + 1 ;
} else if ( ! strcasecmp ( v - > value , " local " ) ) {
localdialplan = PRI_LOCAL_ISDN + 1 ;
2005-03-03 17:00:57 +00:00
} else if ( ! strcasecmp ( v - > value , " dynamic " ) ) {
localdialplan = - 1 ;
2004-10-16 22:34:57 +00:00
} else {
ast_log ( LOG_WARNING , " Unknown PRI dialplan '%s' at line %d. \n " , v - > value , v - > lineno ) ;
}
} else if ( ! strcasecmp ( v - > name , " switchtype " ) ) {
if ( ! strcasecmp ( v - > value , " national " ) )
switchtype = PRI_SWITCH_NI2 ;
else if ( ! strcasecmp ( v - > value , " ni1 " ) )
switchtype = PRI_SWITCH_NI1 ;
else if ( ! strcasecmp ( v - > value , " dms100 " ) )
switchtype = PRI_SWITCH_DMS100 ;
else if ( ! strcasecmp ( v - > value , " 4ess " ) )
switchtype = PRI_SWITCH_ATT4ESS ;
else if ( ! strcasecmp ( v - > value , " 5ess " ) )
switchtype = PRI_SWITCH_LUCENT5E ;
else if ( ! strcasecmp ( v - > value , " euroisdn " ) )
switchtype = PRI_SWITCH_EUROISDN_E1 ;
2004-10-28 16:11:04 +00:00
else if ( ! strcasecmp ( v - > value , " qsig " ) )
switchtype = PRI_SWITCH_QSIG ;
2004-10-02 15:01:37 +00:00
else {
2004-10-16 22:34:57 +00:00
ast_log ( LOG_ERROR , " Unknown switchtype '%s' \n " , v - > value ) ;
2005-01-25 06:10:20 +00:00
ast_config_destroy ( cfg ) ;
2004-10-16 22:34:57 +00:00
ast_mutex_unlock ( & iflock ) ;
return - 1 ;
2004-10-02 15:01:37 +00:00
}
2004-10-16 22:34:57 +00:00
} else if ( ! strcasecmp ( v - > name , " nsf " ) ) {
if ( ! strcasecmp ( v - > value , " sdn " ) )
nsf = PRI_NSF_SDN ;
else if ( ! strcasecmp ( v - > value , " megacom " ) )
nsf = PRI_NSF_MEGACOM ;
else if ( ! strcasecmp ( v - > value , " accunet " ) )
nsf = PRI_NSF_ACCUNET ;
else if ( ! strcasecmp ( v - > value , " none " ) )
nsf = PRI_NSF_NONE ;
else {
ast_log ( LOG_WARNING , " Unknown network-specific facility '%s' \n " , v - > value ) ;
nsf = PRI_NSF_NONE ;
}
} else if ( ! strcasecmp ( v - > name , " priindication " ) ) {
if ( ! strcasecmp ( v - > value , " outofband " ) )
priindication_oob = 1 ;
else if ( ! strcasecmp ( v - > value , " inband " ) )
priindication_oob = 0 ;
else
ast_log ( LOG_WARNING , " '%s' is not a valid pri indication value, should be 'inband' or 'outofband' at line %d \n " ,
v - > value , v - > lineno ) ;
2005-02-04 06:12:32 +00:00
} else if ( ! strcasecmp ( v - > name , " internationalprefix " ) ) {
2005-05-15 23:26:45 +00:00
ast_copy_string ( internationalprefix , v - > value , sizeof ( internationalprefix ) ) ;
2005-02-04 06:12:32 +00:00
} else if ( ! strcasecmp ( v - > name , " nationalprefix " ) ) {
2005-05-15 23:26:45 +00:00
ast_copy_string ( nationalprefix , v - > value , sizeof ( nationalprefix ) ) ;
2005-02-04 06:12:32 +00:00
} else if ( ! strcasecmp ( v - > name , " localprefix " ) ) {
2005-05-15 23:26:45 +00:00
ast_copy_string ( localprefix , v - > value , sizeof ( localprefix ) ) ;
2005-02-04 06:12:32 +00:00
} else if ( ! strcasecmp ( v - > name , " privateprefix " ) ) {
2005-05-15 23:26:45 +00:00
ast_copy_string ( privateprefix , v - > value , sizeof ( privateprefix ) ) ;
2005-02-04 06:12:32 +00:00
} else if ( ! strcasecmp ( v - > name , " unknownprefix " ) ) {
2005-05-15 23:26:45 +00:00
ast_copy_string ( unknownprefix , v - > value , sizeof ( unknownprefix ) ) ;
2005-02-04 06:12:32 +00:00
} else if ( ! strcasecmp ( v - > name , " resetinterval " ) ) {
2005-03-23 21:12:01 +00:00
if ( ! strcasecmp ( v - > value , " never " ) )
resetinterval = - 1 ;
else if ( atoi ( v - > value ) > = 60 )
2005-02-04 06:12:32 +00:00
resetinterval = atoi ( v - > value ) ;
else
2005-03-23 21:12:01 +00:00
ast_log ( LOG_WARNING , " '%s' is not a valid reset interval, should be >= 60 seconds or 'never' at line %d \n " ,
2005-02-04 06:12:32 +00:00
v - > value , v - > lineno ) ;
2004-10-16 22:34:57 +00:00
} else if ( ! strcasecmp ( v - > name , " minunused " ) ) {
minunused = atoi ( v - > value ) ;
} else if ( ! strcasecmp ( v - > name , " idleext " ) ) {
2005-05-15 23:26:45 +00:00
ast_copy_string ( idleext , v - > value , sizeof ( idleext ) ) ;
2004-10-16 22:34:57 +00:00
} else if ( ! strcasecmp ( v - > name , " idledial " ) ) {
2005-05-15 23:26:45 +00:00
ast_copy_string ( idledial , v - > value , sizeof ( idledial ) ) ;
2004-10-16 22:34:57 +00:00
} else if ( ! strcasecmp ( v - > name , " overlapdial " ) ) {
overlapdial = ast_true ( v - > value ) ;
} else if ( ! strcasecmp ( v - > name , " pritimer " ) ) {
# ifdef PRI_GETSET_TIMERS
char * timerc ;
int timer , timeridx ;
c = v - > value ;
timerc = strsep ( & c , " , " ) ;
if ( timerc ) {
timer = atoi ( c ) ;
if ( ! timer )
ast_log ( LOG_WARNING , " '%s' is not a valid value for an ISDN timer \n " , timerc ) ;
else {
2005-05-01 18:47:53 +00:00
if ( ( timeridx = pri_timer2idx ( timerc ) ) > = 0 )
2004-10-16 22:34:57 +00:00
pritimers [ timeridx ] = timer ;
else
ast_log ( LOG_WARNING , " '%s' is not a valid ISDN timer \n " , timerc ) ;
}
} else
ast_log ( LOG_WARNING , " '%s' is not a valid ISDN timer configuration string \n " , v - > value ) ;
2005-05-12 15:05:25 +00:00
2005-05-12 21:11:42 +00:00
} else if ( ! strcasecmp ( v - > name , " facilityenable " ) ) {
2005-05-12 15:05:25 +00:00
facilityenable = ast_true ( v - > value ) ;
2005-05-12 20:45:32 +00:00
# endif /* PRI_GETSET_TIMERS */
# endif /* ZAPATA_PRI */
2004-10-16 22:34:57 +00:00
} else if ( ! strcasecmp ( v - > name , " cadence " ) ) {
/* setup to scan our argument */
int element_count , c [ 16 ] = { 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 } ;
int i ;
struct zt_ring_cadence new_cadence ;
int cid_location = - 1 ;
int firstcadencepos = 0 ;
char original_args [ 80 ] ;
int cadence_is_ok = 1 ;
2005-05-15 23:26:45 +00:00
ast_copy_string ( original_args , v - > value , sizeof ( original_args ) ) ;
2004-10-16 22:34:57 +00:00
/* 16 cadences allowed (8 pairs) */
element_count = sscanf ( v - > value , " %d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d " , & c [ 0 ] , & c [ 1 ] , & c [ 2 ] , & c [ 3 ] , & c [ 4 ] , & c [ 5 ] , & c [ 6 ] , & c [ 7 ] , & c [ 8 ] , & c [ 9 ] , & c [ 10 ] , & c [ 11 ] , & c [ 12 ] , & c [ 13 ] , & c [ 14 ] , & c [ 15 ] ) ;
/* Cadence must be even (on/off) */
if ( element_count % 2 = = 1 ) {
ast_log ( LOG_ERROR , " Must be a silence duration for each ring duration: %s \n " , original_args ) ;
2004-09-30 15:26:04 +00:00
cadence_is_ok = 0 ;
2004-10-16 22:34:57 +00:00
}
/* Ring cadences cannot be negative */
for ( i = 0 ; i < element_count ; i + + ) {
if ( c [ i ] = = 0 ) {
ast_log ( LOG_ERROR , " Ring or silence duration cannot be zero: %s \n " , original_args ) ;
cadence_is_ok = 0 ;
break ;
} else if ( c [ i ] < 0 ) {
if ( i % 2 = = 1 ) {
/* Silence duration, negative possibly okay */
if ( cid_location = = - 1 ) {
cid_location = i ;
c [ i ] * = - 1 ;
} else {
ast_log ( LOG_ERROR , " CID location specified twice: %s \n " , original_args ) ;
cadence_is_ok = 0 ;
break ;
}
2004-09-30 15:26:04 +00:00
} else {
2004-10-16 22:34:57 +00:00
if ( firstcadencepos = = 0 ) {
firstcadencepos = i ; /* only recorded to avoid duplicate specification */
/* duration will be passed negative to the zaptel driver */
} else {
ast_log ( LOG_ERROR , " First cadence position specified twice: %s \n " , original_args ) ;
cadence_is_ok = 0 ;
break ;
}
2004-09-30 15:26:04 +00:00
}
2004-02-23 05:02:24 +00:00
}
}
2004-10-16 22:34:57 +00:00
/* Substitute our scanned cadence */
for ( i = 0 ; i < 16 ; i + + ) {
new_cadence . ringcadence [ i ] = c [ i ] ;
}
if ( cadence_is_ok ) {
/* ---we scanned it without getting annoyed; now some sanity checks--- */
if ( element_count < 2 ) {
ast_log ( LOG_ERROR , " Minimum cadence is ring,pause: %s \n " , original_args ) ;
2004-02-23 05:02:24 +00:00
} else {
2004-10-16 22:34:57 +00:00
if ( cid_location = = - 1 ) {
/* user didn't say; default to first pause */
cid_location = 1 ;
} else {
/* convert element_index to cidrings value */
cid_location = ( cid_location + 1 ) / 2 ;
}
/* ---we like their cadence; try to install it--- */
if ( ! user_has_defined_cadences + + )
/* this is the first user-defined cadence; clear the default user cadences */
num_cadence = 0 ;
if ( ( num_cadence + 1 ) > = NUM_CADENCE_MAX )
ast_log ( LOG_ERROR , " Already %d cadences; can't add another: %s \n " , NUM_CADENCE_MAX , original_args ) ;
else {
cadences [ num_cadence ] = new_cadence ;
cidrings [ num_cadence + + ] = cid_location ;
if ( option_verbose > 2 )
ast_verbose ( VERBOSE_PREFIX_3 " cadence 'r%d' added: %s \n " , num_cadence , original_args ) ;
}
2004-02-23 05:02:24 +00:00
}
}
2004-10-16 22:34:57 +00:00
} else if ( ! strcasecmp ( v - > name , " prewink " ) ) {
cur_prewink = atoi ( v - > value ) ;
} else if ( ! strcasecmp ( v - > name , " preflash " ) ) {
cur_preflash = atoi ( v - > value ) ;
} else if ( ! strcasecmp ( v - > name , " wink " ) ) {
cur_wink = atoi ( v - > value ) ;
} else if ( ! strcasecmp ( v - > name , " flash " ) ) {
cur_flash = atoi ( v - > value ) ;
} else if ( ! strcasecmp ( v - > name , " start " ) ) {
cur_start = atoi ( v - > value ) ;
} else if ( ! strcasecmp ( v - > name , " rxwink " ) ) {
cur_rxwink = atoi ( v - > value ) ;
} else if ( ! strcasecmp ( v - > name , " rxflash " ) ) {
cur_rxflash = atoi ( v - > value ) ;
} else if ( ! strcasecmp ( v - > name , " debounce " ) ) {
cur_debounce = atoi ( v - > value ) ;
2004-12-15 19:59:53 +00:00
} else if ( ! strcasecmp ( v - > name , " emdigitwait " ) ) {
cur_emdigitwait = atoi ( v - > value ) ;
2005-07-19 13:30:37 +00:00
} else if ( ! strcasecmp ( v - > name , " toneduration " ) ) {
2005-07-22 18:07:53 +00:00
int toneduration ;
int ctlfd ;
int res ;
struct zt_dialparams dps ;
ctlfd = open ( " /dev/zap/ctl " , O_RDWR ) ;
if ( ctlfd = = - 1 ) {
ast_log ( LOG_ERROR , " Unable to open /dev/zap/ctl to set toneduration \n " ) ;
return - 1 ;
}
toneduration = atoi ( v - > value ) ;
if ( toneduration > - 1 ) {
dps . dtmf_tonelen = dps . mfv1_tonelen = toneduration ;
res = ioctl ( ctlfd , ZT_SET_DIALPARAMS , & dps ) ;
if ( res < 0 ) {
ast_log ( LOG_ERROR , " Invalid tone duration: %d ms \n " , toneduration ) ;
2005-07-22 18:28:19 +00:00
return - 1 ;
2005-07-22 18:07:53 +00:00
}
}
close ( ctlfd ) ;
2004-11-17 06:18:33 +00:00
} else if ( ! strcasecmp ( v - > name , " polarityonanswerdelay " ) ) {
polarityonanswerdelay = atoi ( v - > value ) ;
2005-02-08 07:49:40 +00:00
} else if ( ! strcasecmp ( v - > name , " answeronpolarityswitch " ) ) {
answeronpolarityswitch = ast_true ( v - > value ) ;
2004-11-17 06:18:33 +00:00
} else if ( ! strcasecmp ( v - > name , " hanguponpolarityswitch " ) ) {
hanguponpolarityswitch = ast_true ( v - > value ) ;
2004-12-28 21:32:25 +00:00
} else if ( ! strcasecmp ( v - > name , " sendcalleridafter " ) ) {
sendcalleridafter = atoi ( v - > value ) ;
2005-04-22 19:10:35 +00:00
} else if ( ! strcasecmp ( v - > name , " defaultcic " ) ) {
2005-05-15 23:26:45 +00:00
ast_copy_string ( defaultcic , v - > value , sizeof ( defaultcic ) ) ;
2005-04-22 19:10:35 +00:00
} else if ( ! strcasecmp ( v - > name , " defaultozz " ) ) {
2005-05-15 23:26:45 +00:00
ast_copy_string ( defaultozz , v - > value , sizeof ( defaultozz ) ) ;
2004-10-16 22:34:57 +00:00
}
} else
2003-03-12 06:00:18 +00:00
ast_log ( LOG_WARNING , " Ignoring %s \n " , v - > name ) ;
2001-10-09 02:06:21 +00:00
v = v - > next ;
}
2004-10-17 05:05:22 +00:00
if ( ! found_pseudo & & reload = = 0 ) {
2004-06-03 22:40:13 +00:00
/* Make sure pseudo isn't a member of any groups if
we ' re automatically making it . */
cur_group = 0 ;
cur_callergroup = 0 ;
cur_pickupgroup = 0 ;
2004-10-16 22:34:57 +00:00
tmp = mkintf ( CHAN_PSEUDO , cur_signalling , cur_radio , NULL , reload ) ;
2004-06-02 16:35:06 +00:00
if ( tmp ) {
if ( option_verbose > 2 )
ast_verbose ( VERBOSE_PREFIX_3 " Automatically generated pseudo channel \n " ) ;
} else {
ast_log ( LOG_WARNING , " Unable to register pseudo channel! \n " ) ;
}
}
2003-08-13 15:25:16 +00:00
ast_mutex_unlock ( & iflock ) ;
2005-01-25 06:10:20 +00:00
ast_config_destroy ( cfg ) ;
2001-10-09 02:06:21 +00:00
# ifdef ZAPATA_PRI
2004-10-16 22:44:53 +00:00
if ( ! reload ) {
for ( x = 0 ; x < NUM_SPANS ; x + + ) {
if ( pris [ x ] . pvts [ 0 ] ) {
if ( start_pri ( pris + x ) ) {
ast_log ( LOG_ERROR , " Unable to start D-channel on span %d \n " , x + 1 ) ;
return - 1 ;
2005-05-24 15:30:10 +00:00
} else if ( option_verbose > 1 )
2004-10-16 22:44:53 +00:00
ast_verbose ( VERBOSE_PREFIX_2 " Starting D-Channel on span %d \n " , x + 1 ) ;
}
2001-10-09 02:06:21 +00:00
}
}
2003-12-09 19:39:47 +00:00
# endif
/* And start the monitor for the first time */
restart_monitor ( ) ;
return 0 ;
}
int load_module ( void )
{
int res ;
# ifdef ZAPATA_PRI
2004-06-07 03:39:18 +00:00
int y , i ;
2003-12-09 19:39:47 +00:00
memset ( pris , 0 , sizeof ( pris ) ) ;
for ( y = 0 ; y < NUM_SPANS ; y + + ) {
2004-06-22 17:42:14 +00:00
ast_mutex_init ( & pris [ y ] . lock ) ;
2003-12-09 19:39:47 +00:00
pris [ y ] . offset = - 1 ;
2004-06-09 08:46:32 +00:00
pris [ y ] . master = AST_PTHREADT_NULL ;
2004-06-07 03:39:18 +00:00
for ( i = 0 ; i < NUM_DCHANS ; i + + )
pris [ y ] . fds [ i ] = - 1 ;
2003-12-09 19:39:47 +00:00
}
pri_set_error ( zt_pri_error ) ;
pri_set_message ( zt_pri_message ) ;
# endif
2004-10-16 22:34:57 +00:00
res = setup_zap ( 0 ) ;
2003-12-09 19:39:47 +00:00
/* Make sure we can register our Zap channel type */
2004-01-15 19:48:37 +00:00
if ( res ) {
return - 1 ;
}
2005-03-04 06:47:24 +00:00
if ( ast_channel_register ( & zap_tech ) ) {
2003-12-09 19:39:47 +00:00
ast_log ( LOG_ERROR , " Unable to register channel class %s \n " , type ) ;
2003-12-09 23:55:17 +00:00
__unload_module ( ) ;
2003-12-09 19:39:47 +00:00
return - 1 ;
}
# ifdef ZAPATA_PRI
2005-06-03 03:24:37 +00:00
ast_cli_register_multiple ( zap_pri_cli , sizeof ( zap_pri_cli ) / sizeof ( zap_pri_cli [ 0 ] ) ) ;
2003-02-07 19:23:19 +00:00
# endif
# ifdef ZAPATA_R2
2005-06-03 03:24:37 +00:00
ast_cli_register_multiple ( zap_r2_cli , sizeof ( zap_r2_cli ) / sizeof ( zap_r2_cli [ 0 ] ) ) ;
2001-10-09 02:06:21 +00:00
# endif
2005-06-03 03:24:37 +00:00
ast_cli_register_multiple ( zap_cli , sizeof ( zap_cli ) / sizeof ( zap_cli [ 0 ] ) ) ;
2005-05-16 14:41:05 +00:00
2003-11-07 16:55:13 +00:00
memset ( round_robin , 0 , sizeof ( round_robin ) ) ;
2003-11-12 00:13:22 +00:00
ast_manager_register ( " ZapTransfer " , 0 , action_transfer , " Transfer Zap Channel " ) ;
ast_manager_register ( " ZapHangup " , 0 , action_transferhangup , " Hangup Zap Channel " ) ;
ast_manager_register ( " ZapDialOffhook " , 0 , action_zapdialoffhook , " Dial over Zap channel while offhook " ) ;
2005-04-22 19:10:35 +00:00
ast_manager_register ( " ZapDNDon " , 0 , action_zapdndon , " Toggle Zap channel Do Not Disturb status ON " ) ;
ast_manager_register ( " ZapDNDoff " , 0 , action_zapdndoff , " Toggle Zap channel Do Not Disturb status OFF " ) ;
2004-07-31 20:43:24 +00:00
ast_manager_register ( " ZapShowChannels " , 0 , action_zapshowchannels , " Show status zapata channels " ) ;
2001-10-09 02:06:21 +00:00
2003-12-09 19:39:47 +00:00
return res ;
2001-10-09 02:06:21 +00:00
}
2005-03-28 20:48:24 +00:00
static int zt_sendtext ( struct ast_channel * c , const char * text )
2001-12-29 18:04:21 +00:00
{
# define END_SILENCE_LEN 400
2002-06-24 17:59:56 +00:00
# define HEADER_MS 50
# define TRAILER_MS 5
# define HEADER_LEN ((HEADER_MS + TRAILER_MS) * 8)
# define ASCII_BYTES_PER_CHAR 80
2001-12-29 18:04:21 +00:00
unsigned char * buf , * mybuf ;
2005-03-04 06:47:24 +00:00
struct zt_pvt * p = c - > tech_pvt ;
2004-04-25 22:37:09 +00:00
struct pollfd fds [ 1 ] ;
2002-06-24 17:59:56 +00:00
int size , res , fd , len , x ;
int bytes = 0 ;
/* Initial carrier (imaginary) */
float cr = 1.0 ;
float ci = 0.0 ;
float scont = 0.0 ;
2003-02-07 19:23:19 +00:00
int index ;
2002-06-24 17:59:56 +00:00
2003-02-07 19:23:19 +00:00
index = zt_get_index ( c , p , 0 ) ;
if ( index < 0 ) {
ast_log ( LOG_WARNING , " Huh? I don't exist? \n " ) ;
return - 1 ;
}
2002-09-10 04:45:51 +00:00
if ( ! text [ 0 ] ) return ( 0 ) ; /* if nothing to send, dont */
2002-06-24 17:59:56 +00:00
if ( ( ! p - > tdd ) & & ( ! p - > mate ) ) return ( 0 ) ; /* if not in TDD mode, just return */
if ( p - > mate )
buf = malloc ( ( ( strlen ( text ) + 1 ) * ASCII_BYTES_PER_CHAR ) + END_SILENCE_LEN + HEADER_LEN ) ;
2002-09-10 04:45:51 +00:00
else
buf = malloc ( ( ( strlen ( text ) + 1 ) * TDD_BYTES_PER_CHAR ) + END_SILENCE_LEN ) ;
2001-12-29 18:04:21 +00:00
if ( ! buf ) {
ast_log ( LOG_ERROR , " MALLOC FAILED \n " ) ;
return - 1 ;
}
mybuf = buf ;
2002-06-24 17:59:56 +00:00
if ( p - > mate ) {
2003-02-07 19:23:19 +00:00
int codec = AST_LAW ( p ) ;
2002-06-24 17:59:56 +00:00
for ( x = 0 ; x < HEADER_MS ; x + + ) { /* 50 ms of Mark */
PUT_CLID_MARKMS ;
}
/* Put actual message */
for ( x = 0 ; text [ x ] ; x + + ) {
PUT_CLID ( text [ x ] ) ;
}
for ( x = 0 ; x < TRAILER_MS ; x + + ) { /* 5 ms of Mark */
PUT_CLID_MARKMS ;
}
len = bytes ;
buf = mybuf ;
}
else {
len = tdd_generate ( p - > tdd , buf , text ) ;
if ( len < 1 ) {
2004-06-13 21:25:10 +00:00
ast_log ( LOG_ERROR , " TDD generate (len %d) failed!! \n " , ( int ) strlen ( text ) ) ;
2002-06-24 17:59:56 +00:00
free ( mybuf ) ;
return - 1 ;
}
2001-12-29 18:04:21 +00:00
}
memset ( buf + len , 0x7f , END_SILENCE_LEN ) ;
len + = END_SILENCE_LEN ;
2003-02-07 19:23:19 +00:00
fd = p - > subs [ index ] . zfd ;
2001-12-29 18:04:21 +00:00
while ( len ) {
if ( ast_check_hangup ( c ) ) {
free ( mybuf ) ;
return - 1 ;
}
size = len ;
if ( size > READ_SIZE )
size = READ_SIZE ;
2004-04-25 22:37:09 +00:00
fds [ 0 ] . fd = fd ;
fds [ 0 ] . events = POLLOUT | POLLPRI ;
res = poll ( fds , 1 , - 1 ) ;
2001-12-29 18:04:21 +00:00
if ( ! res ) {
2004-04-25 22:37:09 +00:00
ast_log ( LOG_DEBUG , " poll (for write) ret. 0 on channel %d \n " , p - > channel ) ;
2001-12-29 18:04:21 +00:00
continue ;
}
/* if got exception */
2004-04-25 22:37:09 +00:00
if ( fds [ 0 ] . revents & POLLPRI ) return - 1 ;
if ( ! ( fds [ 0 ] . revents & POLLOUT ) ) {
2001-12-29 18:04:21 +00:00
ast_log ( LOG_DEBUG , " write fd not ready on channel %d \n " , p - > channel ) ;
continue ;
}
res = write ( fd , buf , size ) ;
if ( res ! = size ) {
if ( res = = - 1 ) {
free ( mybuf ) ;
return - 1 ;
}
if ( option_debug )
ast_log ( LOG_DEBUG , " Write returned %d (%s) on channel %d \n " , res , strerror ( errno ) , p - > channel ) ;
break ;
}
len - = size ;
buf + = size ;
}
free ( mybuf ) ;
return ( 0 ) ;
}
2004-10-16 22:34:57 +00:00
2001-10-09 02:06:21 +00:00
int reload ( void )
{
2004-10-16 22:34:57 +00:00
int res = 0 ;
res = setup_zap ( 1 ) ;
if ( res ) {
ast_log ( LOG_WARNING , " Reload of chan_zap.so is unsuccessful! \n " ) ;
2001-10-09 02:06:21 +00:00
return - 1 ;
}
return 0 ;
}
2004-10-16 22:34:57 +00:00
2001-10-09 02:06:21 +00:00
int usecount ( )
{
2005-06-24 02:15:04 +00:00
return usecnt ;
2001-10-09 02:06:21 +00:00
}
char * description ( )
{
2005-03-04 06:47:24 +00:00
return ( char * ) desc ;
2001-10-09 02:06:21 +00:00
}
char * key ( )
{
return ASTERISK_GPL_KEY ;
}
2004-09-13 23:07:50 +00:00