Wed Aug 18 22:33:45 2010

Asterisk developer's documentation


chan_dahdi.c

Go to the documentation of this file.
00001 /*
00002  * Asterisk -- An open source telephony toolkit.
00003  *
00004  * Copyright (C) 1999 - 2006, Digium, Inc.
00005  *
00006  * Mark Spencer <markster@digium.com>
00007  *
00008  * See http://www.asterisk.org for more information about
00009  * the Asterisk project. Please do not directly contact
00010  * any of the maintainers of this project for assistance;
00011  * the project provides a web site, mailing lists and IRC
00012  * channels for your use.
00013  *
00014  * This program is free software, distributed under the terms of
00015  * the GNU General Public License Version 2. See the LICENSE file
00016  * at the top of the source tree.
00017  */
00018 
00019 /*! \file
00020  *
00021  * \brief DAHDI for Pseudo TDM
00022  *
00023  * \author Mark Spencer <markster@digium.com>
00024  * 
00025  * Connects to the DAHDI telephony library as well as 
00026  * libpri. Libpri is optional and needed only if you are
00027  * going to use ISDN connections.
00028  *
00029  * You need to install libraries before you attempt to compile
00030  * and install the DAHDI channel.
00031  *
00032  * \par See also
00033  * \arg \ref Config_dahdi
00034  *
00035  * \ingroup channel_drivers
00036  *
00037  * \todo Deprecate the "musiconhold" configuration option post 1.4
00038  */
00039 
00040 /*** MODULEINFO
00041    <depend>res_smdi</depend>
00042    <depend>dahdi</depend>
00043    <depend>tonezone</depend>
00044    <use>pri</use>
00045    <use>ss7</use>
00046  ***/
00047 
00048 #include "asterisk.h"
00049 
00050 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 261452 $")
00051 
00052 #if defined(__NetBSD__) || defined(__FreeBSD__)
00053 #include <pthread.h>
00054 #include <signal.h>
00055 #else
00056 #include <sys/signal.h>
00057 #endif
00058 #include <sys/ioctl.h>
00059 #include <math.h>
00060 #include <ctype.h>
00061 
00062 #include <dahdi/user.h>
00063 #include <dahdi/tonezone.h>
00064 
00065 #ifdef HAVE_PRI
00066 #include <libpri.h>
00067 #endif
00068 
00069 #ifdef HAVE_SS7
00070 #include <libss7.h>
00071 #endif
00072 
00073 #include "asterisk/lock.h"
00074 #include "asterisk/channel.h"
00075 #include "asterisk/config.h"
00076 #include "asterisk/module.h"
00077 #include "asterisk/pbx.h"
00078 #include "asterisk/file.h"
00079 #include "asterisk/ulaw.h"
00080 #include "asterisk/alaw.h"
00081 #include "asterisk/callerid.h"
00082 #include "asterisk/adsi.h"
00083 #include "asterisk/cli.h"
00084 #include "asterisk/cdr.h"
00085 #include "asterisk/features.h"
00086 #include "asterisk/musiconhold.h"
00087 #include "asterisk/say.h"
00088 #include "asterisk/tdd.h"
00089 #include "asterisk/app.h"
00090 #include "asterisk/dsp.h"
00091 #include "asterisk/astdb.h"
00092 #include "asterisk/manager.h"
00093 #include "asterisk/causes.h"
00094 #include "asterisk/term.h"
00095 #include "asterisk/utils.h"
00096 #include "asterisk/transcap.h"
00097 #include "asterisk/stringfields.h"
00098 #include "asterisk/abstract_jb.h"
00099 #include "asterisk/smdi.h"
00100 #include "asterisk/astobj.h"
00101 #include "asterisk/event.h"
00102 #include "asterisk/devicestate.h"
00103 
00104 #define SMDI_MD_WAIT_TIMEOUT 1500 /* 1.5 seconds */
00105 
00106 static const char *lbostr[] = {
00107 "0 db (CSU)/0-133 feet (DSX-1)",
00108 "133-266 feet (DSX-1)",
00109 "266-399 feet (DSX-1)",
00110 "399-533 feet (DSX-1)",
00111 "533-655 feet (DSX-1)",
00112 "-7.5db (CSU)",
00113 "-15db (CSU)",
00114 "-22.5db (CSU)"
00115 };
00116 
00117 /*! Global jitterbuffer configuration - by default, jb is disabled */
00118 static struct ast_jb_conf default_jbconf =
00119 {
00120    .flags = 0,
00121    .max_size = -1,
00122    .resync_threshold = -1,
00123    .impl = "",
00124    .target_extra = -1,
00125 };
00126 static struct ast_jb_conf global_jbconf;
00127 
00128 /* define this to send PRI user-user information elements */
00129 #undef SUPPORT_USERUSER
00130 
00131 /*! 
00132  * \note Define ZHONE_HACK to cause us to go off hook and then back on hook when
00133  * the user hangs up to reset the state machine so ring works properly.
00134  * This is used to be able to support kewlstart by putting the zhone in
00135  * groundstart mode since their forward disconnect supervision is entirely
00136  * broken even though their documentation says it isn't and their support
00137  * is entirely unwilling to provide any assistance with their channel banks
00138  * even though their web site says they support their products for life.
00139  */
00140 /* #define ZHONE_HACK */
00141 
00142 /*! \note
00143  * Define if you want to check the hook state for an FXO (FXS signalled) interface
00144  * before dialing on it.  Certain FXO interfaces always think they're out of
00145  * service with this method however.
00146  */
00147 /* #define DAHDI_CHECK_HOOKSTATE */
00148 
00149 /*! \brief Typically, how many rings before we should send Caller*ID */
00150 #define DEFAULT_CIDRINGS 1
00151 
00152 #define CHANNEL_PSEUDO -12
00153 
00154 #define AST_LAW(p) (((p)->law == DAHDI_LAW_ALAW) ? AST_FORMAT_ALAW : AST_FORMAT_ULAW)
00155 
00156 
00157 /*! \brief Signaling types that need to use MF detection should be placed in this macro */
00158 #define NEED_MFDETECT(p) (((p)->sig == SIG_FEATDMF) || ((p)->sig == SIG_FEATDMF_TA) || ((p)->sig == SIG_E911) || ((p)->sig == SIG_FGC_CAMA) || ((p)->sig == SIG_FGC_CAMAMF) || ((p)->sig == SIG_FEATB)) 
00159 
00160 static const char tdesc[] = "DAHDI Telephony Driver"
00161 #ifdef HAVE_PRI
00162                " w/PRI"
00163 #endif
00164 #ifdef HAVE_SS7
00165           " w/SS7"
00166 #endif
00167 ;
00168 
00169 static const char config[] = "chan_dahdi.conf";
00170 
00171 #define SIG_EM    DAHDI_SIG_EM
00172 #define SIG_EMWINK   (0x0100000 | DAHDI_SIG_EM)
00173 #define SIG_FEATD (0x0200000 | DAHDI_SIG_EM)
00174 #define  SIG_FEATDMF (0x0400000 | DAHDI_SIG_EM)
00175 #define  SIG_FEATB   (0x0800000 | DAHDI_SIG_EM)
00176 #define  SIG_E911 (0x1000000 | DAHDI_SIG_EM)
00177 #define  SIG_FEATDMF_TA (0x2000000 | DAHDI_SIG_EM)
00178 #define  SIG_FGC_CAMA   (0x4000000 | DAHDI_SIG_EM)
00179 #define  SIG_FGC_CAMAMF (0x8000000 | DAHDI_SIG_EM)
00180 #define SIG_FXSLS DAHDI_SIG_FXSLS
00181 #define SIG_FXSGS DAHDI_SIG_FXSGS
00182 #define SIG_FXSKS DAHDI_SIG_FXSKS
00183 #define SIG_FXOLS DAHDI_SIG_FXOLS
00184 #define SIG_FXOGS DAHDI_SIG_FXOGS
00185 #define SIG_FXOKS DAHDI_SIG_FXOKS
00186 #define SIG_PRI      DAHDI_SIG_CLEAR
00187 #define SIG_BRI      (0x2000000 | DAHDI_SIG_CLEAR)
00188 #define SIG_BRI_PTMP (0X4000000 | DAHDI_SIG_CLEAR)
00189 #define SIG_SS7      (0x1000000 | DAHDI_SIG_CLEAR)
00190 #define  SIG_SF      DAHDI_SIG_SF
00191 #define SIG_SFWINK   (0x0100000 | DAHDI_SIG_SF)
00192 #define SIG_SF_FEATD (0x0200000 | DAHDI_SIG_SF)
00193 #define  SIG_SF_FEATDMF (0x0400000 | DAHDI_SIG_SF)
00194 #define  SIG_SF_FEATB   (0x0800000 | DAHDI_SIG_SF)
00195 #define SIG_EM_E1 DAHDI_SIG_EM_E1
00196 #define SIG_GR303FXOKS  (0x0100000 | DAHDI_SIG_FXOKS)
00197 #define SIG_GR303FXSKS  (0x0100000 | DAHDI_SIG_FXSKS)
00198 
00199 #ifdef LOTS_OF_SPANS
00200 #define NUM_SPANS DAHDI_MAX_SPANS
00201 #else
00202 #define NUM_SPANS       32
00203 #endif
00204 #define NUM_DCHANS      4  /*!< No more than 4 d-channels */
00205 #define MAX_CHANNELS 672      /*!< No more than a DS3 per trunk group */
00206 
00207 #define CHAN_PSEUDO  -2
00208 
00209 #define DCHAN_PROVISIONED (1 << 0)
00210 #define DCHAN_NOTINALARM  (1 << 1)
00211 #define DCHAN_UP          (1 << 2)
00212 
00213 #define DCHAN_AVAILABLE (DCHAN_PROVISIONED | DCHAN_NOTINALARM | DCHAN_UP)
00214 
00215 /* Overlap dialing option types */
00216 #define DAHDI_OVERLAPDIAL_NONE 0
00217 #define DAHDI_OVERLAPDIAL_OUTGOING 1
00218 #define DAHDI_OVERLAPDIAL_INCOMING 2
00219 #define DAHDI_OVERLAPDIAL_BOTH (DAHDI_OVERLAPDIAL_INCOMING|DAHDI_OVERLAPDIAL_OUTGOING)
00220 
00221 
00222 #define CALLPROGRESS_PROGRESS    1
00223 #define CALLPROGRESS_FAX_OUTGOING   2
00224 #define CALLPROGRESS_FAX_INCOMING   4
00225 #define CALLPROGRESS_FAX      (CALLPROGRESS_FAX_INCOMING | CALLPROGRESS_FAX_OUTGOING)
00226 
00227 static char defaultcic[64] = "";
00228 static char defaultozz[64] = "";
00229 
00230 static char parkinglot[AST_MAX_EXTENSION] = "";    /*!< Default parking lot for this channel */
00231 
00232 /*! Run this script when the MWI state changes on an FXO line, if mwimonitor is enabled */
00233 static char mwimonitornotify[PATH_MAX] = "";
00234 static int  mwisend_rpas = 0;
00235 
00236 static char progzone[10] = "";
00237 
00238 static int usedistinctiveringdetection = 0;
00239 static int distinctiveringaftercid = 0;
00240 
00241 static int numbufs = 4;
00242 
00243 static int mwilevel = 512;
00244 
00245 #ifdef HAVE_PRI
00246 static struct ast_channel inuse;
00247 #ifdef PRI_GETSET_TIMERS
00248 static int pritimers[PRI_MAX_TIMERS];
00249 #endif
00250 static int pridebugfd = -1;
00251 static char pridebugfilename[1024] = "";
00252 #endif
00253 
00254 /*! \brief Wait up to 16 seconds for first digit (FXO logic) */
00255 static int firstdigittimeout = 16000;
00256 
00257 /*! \brief How long to wait for following digits (FXO logic) */
00258 static int gendigittimeout = 8000;
00259 
00260 /*! \brief How long to wait for an extra digit, if there is an ambiguous match */
00261 static int matchdigittimeout = 3000;
00262 
00263 /*! \brief Protect the interface list (of dahdi_pvt's) */
00264 AST_MUTEX_DEFINE_STATIC(iflock);
00265 
00266 
00267 static int ifcount = 0;
00268 
00269 #ifdef HAVE_PRI
00270 AST_MUTEX_DEFINE_STATIC(pridebugfdlock);
00271 #endif
00272 
00273 /*! \brief Protect the monitoring thread, so only one process can kill or start it, and not
00274    when it's doing something critical. */
00275 AST_MUTEX_DEFINE_STATIC(monlock);
00276 
00277 /*! \brief This is the thread for the monitor which checks for input on the channels
00278    which are not currently in use. */
00279 static pthread_t monitor_thread = AST_PTHREADT_NULL;
00280 static ast_cond_t mwi_thread_complete;
00281 static ast_cond_t ss_thread_complete;
00282 AST_MUTEX_DEFINE_STATIC(mwi_thread_lock);
00283 AST_MUTEX_DEFINE_STATIC(ss_thread_lock);
00284 AST_MUTEX_DEFINE_STATIC(restart_lock);
00285 static int mwi_thread_count = 0;
00286 static int ss_thread_count = 0;
00287 static int num_restart_pending = 0;
00288 
00289 static int restart_monitor(void);
00290 
00291 static enum ast_bridge_result dahdi_bridge(struct ast_channel *c0, struct ast_channel *c1, int flags, struct ast_frame **fo, struct ast_channel **rc, int timeoutms);
00292 
00293 static int dahdi_sendtext(struct ast_channel *c, const char *text);
00294 
00295 static void mwi_event_cb(const struct ast_event *event, void *userdata)
00296 {
00297    /* This module does not handle MWI in an event-based manner.  However, it
00298     * subscribes to MWI for each mailbox that is configured so that the core
00299     * knows that we care about it.  Then, chan_dahdi will get the MWI from the
00300     * event cache instead of checking the mailbox directly. */
00301 }
00302 
00303 /*! \brief Avoid the silly dahdi_getevent which ignores a bunch of events */
00304 static inline int dahdi_get_event(int fd)
00305 {
00306    int j;
00307    if (ioctl(fd, DAHDI_GETEVENT, &j) == -1)
00308       return -1;
00309    return j;
00310 }
00311 
00312 /*! \brief Avoid the silly dahdi_waitevent which ignores a bunch of events */
00313 static inline int dahdi_wait_event(int fd)
00314 {
00315    int i, j = 0;
00316    i = DAHDI_IOMUX_SIGEVENT;
00317    if (ioctl(fd, DAHDI_IOMUX, &i) == -1)
00318       return -1;
00319    if (ioctl(fd, DAHDI_GETEVENT, &j) == -1)
00320       return -1;
00321    return j;
00322 }
00323 
00324 /*! Chunk size to read -- we use 20ms chunks to make things happy. */
00325 #define READ_SIZE 160
00326 
00327 #define MASK_AVAIL      (1 << 0) /*!< Channel available for PRI use */
00328 #define MASK_INUSE      (1 << 1) /*!< Channel currently in use */
00329 
00330 #define CALLWAITING_SILENT_SAMPLES  ( (300 * 8) / READ_SIZE) /*!< 300 ms */
00331 #define CALLWAITING_REPEAT_SAMPLES  ( (10000 * 8) / READ_SIZE) /*!< 10,000 ms */
00332 #define CIDCW_EXPIRE_SAMPLES     ( (500 * 8) / READ_SIZE) /*!< 500 ms */
00333 #define MIN_MS_SINCE_FLASH       ( (2000) )  /*!< 2000 ms */
00334 #define DEFAULT_RINGT            ( (8000 * 8) / READ_SIZE) /*!< 8,000 ms */
00335 
00336 struct dahdi_pvt;
00337 
00338 /*!
00339  * \brief Configured ring timeout base.
00340  * \note Value computed from "ringtimeout" read in from chan_dahdi.conf if it exists.
00341  */
00342 static int ringt_base = DEFAULT_RINGT;
00343 
00344 #ifdef HAVE_SS7
00345 
00346 #define LINKSTATE_INALARM  (1 << 0)
00347 #define LINKSTATE_STARTING (1 << 1)
00348 #define LINKSTATE_UP    (1 << 2)
00349 #define LINKSTATE_DOWN     (1 << 3)
00350 
00351 #define SS7_NAI_DYNAMIC    -1
00352 
00353 #define LINKSET_FLAG_EXPLICITACM (1 << 0)
00354 
00355 struct dahdi_ss7 {
00356    pthread_t master;                /*!< Thread of master */
00357    ast_mutex_t lock;
00358    int fds[NUM_DCHANS];
00359    int numsigchans;
00360    int linkstate[NUM_DCHANS];
00361    int numchans;
00362    int type;
00363    enum {
00364       LINKSET_STATE_DOWN = 0,
00365       LINKSET_STATE_UP
00366    } state;
00367    char called_nai;                 /*!< Called Nature of Address Indicator */
00368    char calling_nai;                /*!< Calling Nature of Address Indicator */
00369    char internationalprefix[10];             /*!< country access code ('00' for european dialplans) */
00370    char nationalprefix[10];               /*!< area access code ('0' for european dialplans) */
00371    char subscriberprefix[20];             /*!< area access code + area code ('0'+area code for european dialplans) */
00372    char unknownprefix[20];                /*!< for unknown dialplans */
00373    struct ss7 *ss7;
00374    struct dahdi_pvt *pvts[MAX_CHANNELS];           /*!< Member channel pvt structs */
00375    int flags;                    /*!< Linkset flags */
00376 };
00377 
00378 static struct dahdi_ss7 linksets[NUM_SPANS];
00379 
00380 static int cur_ss7type = -1;
00381 static int cur_linkset = -1;
00382 static int cur_pointcode = -1;
00383 static int cur_cicbeginswith = -1;
00384 static int cur_adjpointcode = -1;
00385 static int cur_networkindicator = -1;
00386 static int cur_defaultdpc = -1;
00387 #endif /* HAVE_SS7 */
00388 
00389 #ifdef HAVE_PRI
00390 
00391 #define PVT_TO_CHANNEL(p) (((p)->prioffset) | ((p)->logicalspan << 8) | (p->pri->mastertrunkgroup ? 0x10000 : 0))
00392 #define PRI_CHANNEL(p) ((p) & 0xff)
00393 #define PRI_SPAN(p) (((p) >> 8) & 0xff)
00394 #define PRI_EXPLICIT(p) (((p) >> 16) & 0x01)
00395 
00396 struct dahdi_pri {
00397    pthread_t master;                /*!< Thread of master */
00398    ast_mutex_t lock;                /*!< Mutex */
00399    char idleext[AST_MAX_EXTENSION];          /*!< Where to idle extra calls */
00400    char idlecontext[AST_MAX_CONTEXT];           /*!< What context to use for idle */
00401    char idledial[AST_MAX_EXTENSION];            /*!< What to dial before dumping */
00402    int minunused;                   /*!< Min # of channels to keep empty */
00403    int minidle;                     /*!< Min # of "idling" calls to keep active */
00404    int nodetype;                    /*!< Node type */
00405    int switchtype;                     /*!< Type of switch to emulate */
00406    int nsf;                   /*!< Network-Specific Facilities */
00407    int dialplan;                    /*!< Dialing plan */
00408    int localdialplan;                  /*!< Local dialing plan */
00409    char internationalprefix[10];             /*!< country access code ('00' for european dialplans) */
00410    char nationalprefix[10];               /*!< area access code ('0' for european dialplans) */
00411    char localprefix[20];                  /*!< area access code + area code ('0'+area code for european dialplans) */
00412    char privateprefix[20];                /*!< for private dialplans */
00413    char unknownprefix[20];                /*!< for unknown dialplans */
00414    int dchannels[NUM_DCHANS];             /*!< What channel are the dchannels on */
00415    int trunkgroup;                     /*!< What our trunkgroup is */
00416    int mastertrunkgroup;                  /*!< What trunk group is our master */
00417    int prilogicalspan;                 /*!< Logical span number within trunk group */
00418    int numchans;                    /*!< Num of channels we represent */
00419    int overlapdial;                 /*!< In overlap dialing mode */
00420    int facilityenable;                 /*!< Enable facility IEs */
00421    struct pri *dchans[NUM_DCHANS];              /*!< Actual d-channels */
00422    int dchanavail[NUM_DCHANS];               /*!< Whether each channel is available */
00423    struct pri *pri;                 /*!< Currently active D-channel */
00424    /*! \brief TRUE if to dump PRI event info (Tested but never set) */
00425    int debug;
00426    int fds[NUM_DCHANS];                /*!< FD's for d-channels */
00427    /*! \brief Value set but not used */
00428    int offset;
00429    /*! \brief Span number put into user output messages */
00430    int span;
00431    /*! \brief TRUE if span is being reset/restarted */
00432    int resetting;
00433    /*! \brief Current position during a reset (-1 if not started) */
00434    int resetpos;
00435 #ifdef HAVE_PRI_INBANDDISCONNECT
00436    unsigned int inbanddisconnect:1;          /*!< Should we support inband audio after receiving DISCONNECT? */
00437 #endif
00438    time_t lastreset;                /*!< time when unused channels were last reset */
00439    long resetinterval;                 /*!< Interval (in seconds) for resetting unused channels */
00440    /*! \brief ISDN signalling type (SIG_PRI, SIG_BRI, SIG_BRI_PTMP, etc...) */
00441    int sig;
00442    struct dahdi_pvt *pvts[MAX_CHANNELS];           /*!< Member channel pvt structs */
00443    struct dahdi_pvt *crvs;                /*!< Member CRV structs */
00444    struct dahdi_pvt *crvend;                 /*!< Pointer to end of CRV structs */
00445 };
00446 
00447 
00448 static struct dahdi_pri pris[NUM_SPANS];
00449 
00450 #if 0
00451 #define DEFAULT_PRI_DEBUG (PRI_DEBUG_Q931_DUMP | PRI_DEBUG_Q921_DUMP | PRI_DEBUG_Q921_RAW | PRI_DEBUG_Q921_STATE)
00452 #else
00453 #define DEFAULT_PRI_DEBUG 0
00454 #endif
00455 
00456 static inline void pri_rel(struct dahdi_pri *pri)
00457 {
00458    ast_mutex_unlock(&pri->lock);
00459 }
00460 
00461 #else
00462 /*! Shut up the compiler */
00463 struct dahdi_pri;
00464 #endif
00465 
00466 #define SUB_REAL  0        /*!< Active call */
00467 #define SUB_CALLWAIT 1        /*!< Call-Waiting call on hold */
00468 #define SUB_THREEWAY 2        /*!< Three-way call */
00469 
00470 /* Polarity states */
00471 #define POLARITY_IDLE   0
00472 #define POLARITY_REV    1
00473 
00474 
00475 struct distRingData {
00476    int ring[3];
00477    int range;
00478 };
00479 struct ringContextData {
00480    char contextData[AST_MAX_CONTEXT];
00481 };
00482 struct dahdi_distRings {
00483    struct distRingData ringnum[3];
00484    struct ringContextData ringContext[3];
00485 };
00486 
00487 static char *subnames[] = {
00488    "Real",
00489    "Callwait",
00490    "Threeway"
00491 };
00492 
00493 struct dahdi_subchannel {
00494    int dfd;
00495    struct ast_channel *owner;
00496    int chan;
00497    short buffer[AST_FRIENDLY_OFFSET/2 + READ_SIZE];
00498    struct ast_frame f;     /*!< One frame for each channel.  How did this ever work before? */
00499    unsigned int needringing:1;
00500    unsigned int needbusy:1;
00501    unsigned int needcongestion:1;
00502    unsigned int needcallerid:1;
00503    unsigned int needanswer:1;
00504    unsigned int needflash:1;
00505    unsigned int needhold:1;
00506    unsigned int needunhold:1;
00507    unsigned int linear:1;
00508    unsigned int inthreeway:1;
00509    struct dahdi_confinfo curconf;
00510 };
00511 
00512 #define CONF_USER_REAL     (1 << 0)
00513 #define CONF_USER_THIRDCALL   (1 << 1)
00514 
00515 #define MAX_SLAVES   4
00516 
00517 static struct dahdi_pvt {
00518    ast_mutex_t lock;             /*!< Channel private lock. */
00519    struct ast_channel *owner;       /*!< Our current active owner (if applicable) */
00520                      /*!< Up to three channels can be associated with this call */
00521       
00522    struct dahdi_subchannel sub_unused;    /*!< Just a safety precaution */
00523    struct dahdi_subchannel subs[3];       /*!< Sub-channels */
00524    struct dahdi_confinfo saveconf;        /*!< Saved conference info */
00525 
00526    struct dahdi_pvt *slaves[MAX_SLAVES];     /*!< Slave to us (follows our conferencing) */
00527    struct dahdi_pvt *master;           /*!< Master to us (we follow their conferencing) */
00528    int inconference;          /*!< If our real should be in the conference */
00529    
00530    int buf_no;             /*!< Number of buffers */
00531    int buf_policy;            /*!< Buffer policy */
00532    int sig;             /*!< Signalling style */
00533    /*!
00534     * \brief Nonzero if the signaling type is sent over a radio.
00535     * \note Set to a couple of nonzero values but it is only tested like a boolean.
00536     */
00537    int radio;
00538    int outsigmod;             /*!< Outbound Signalling style (modifier) */
00539    int oprmode;               /*!< "Operator Services" mode */
00540    struct dahdi_pvt *oprpeer;          /*!< "Operator Services" peer tech_pvt ptr */
00541    /*! \brief Amount of gain to increase during caller id */
00542    float cid_rxgain;
00543    /*! \brief Rx gain set by chan_dahdi.conf */
00544    float rxgain;
00545    /*! \brief Tx gain set by chan_dahdi.conf */
00546    float txgain;
00547    int tonezone;              /*!< tone zone for this chan, or -1 for default */
00548    struct dahdi_pvt *next;          /*!< Next channel in list */
00549    struct dahdi_pvt *prev;          /*!< Prev channel in list */
00550 
00551    /* flags */
00552 
00553    /*!
00554     * \brief TRUE if ADSI (Analog Display Services Interface) available
00555     * \note Set from the "adsi" value read in from chan_dahdi.conf
00556     */
00557    unsigned int adsi:1;
00558    /*!
00559     * \brief TRUE if we can use a polarity reversal to mark when an outgoing
00560     * call is answered by the remote party.
00561     * \note Set from the "answeronpolarityswitch" value read in from chan_dahdi.conf
00562     */
00563    unsigned int answeronpolarityswitch:1;
00564    /*!
00565     * \brief TRUE if busy detection is enabled.
00566     * (Listens for the beep-beep busy pattern.)
00567     * \note Set from the "busydetect" value read in from chan_dahdi.conf
00568     */
00569    unsigned int busydetect:1;
00570    /*!
00571     * \brief TRUE if call return is enabled.
00572     * (*69, if your dialplan doesn't catch this first)
00573     * \note Set from the "callreturn" value read in from chan_dahdi.conf
00574     */
00575    unsigned int callreturn:1;
00576    /*!
00577     * \brief TRUE if busy extensions will hear the call-waiting tone
00578     * and can use hook-flash to switch between callers.
00579     * \note Can be disabled by dialing *70.
00580     * \note Initialized with the "callwaiting" value read in from chan_dahdi.conf
00581     */
00582    unsigned int callwaiting:1;
00583    /*!
00584     * \brief TRUE if send caller ID for Call Waiting
00585     * \note Set from the "callwaitingcallerid" value read in from chan_dahdi.conf
00586     */
00587    unsigned int callwaitingcallerid:1;
00588    /*!
00589     * \brief TRUE if support for call forwarding enabled.
00590     * Dial *72 to enable call forwarding.
00591     * Dial *73 to disable call forwarding.
00592     * \note Set from the "cancallforward" value read in from chan_dahdi.conf
00593     */
00594    unsigned int cancallforward:1;
00595    /*!
00596     * \brief TRUE if support for call parking is enabled.
00597     * \note Set from the "canpark" value read in from chan_dahdi.conf
00598     */
00599    unsigned int canpark:1;
00600    /*! \brief TRUE if to wait for a DTMF digit to confirm answer */
00601    unsigned int confirmanswer:1;
00602    /*!
00603     * \brief TRUE if the channel is to be destroyed on hangup.
00604     * (Used by pseudo channels.)
00605     */
00606    unsigned int destroy:1;
00607    unsigned int didtdd:1;           /*!< flag to say its done it once */
00608    /*! \brief TRUE if analog type line dialed no digits in Dial() */
00609    unsigned int dialednone:1;
00610    /*! \brief TRUE if in the process of dialing digits or sending something. */
00611    unsigned int dialing:1;
00612    /*! \brief TRUE if the transfer capability of the call is digital. */
00613    unsigned int digital:1;
00614    /*! \brief TRUE if Do-Not-Disturb is enabled. */
00615    unsigned int dnd:1;
00616    /*! \brief XXX BOOLEAN Purpose??? */
00617    unsigned int echobreak:1;
00618    /*!
00619     * \brief TRUE if echo cancellation enabled when bridged.
00620     * \note Initialized with the "echocancelwhenbridged" value read in from chan_dahdi.conf
00621     * \note Disabled if the echo canceller is not setup.
00622     */
00623    unsigned int echocanbridged:1;
00624    /*! \brief TRUE if echo cancellation is turned on. */
00625    unsigned int echocanon:1;
00626    /*! \brief TRUE if a fax tone has already been handled. */
00627    unsigned int faxhandled:1;
00628    /*! \brief TRUE if over a radio and dahdi_read() has been called. */
00629    unsigned int firstradio:1;
00630    /*!
00631     * \brief TRUE if the call will be considered "hung up" on a polarity reversal.
00632     * \note Set from the "hanguponpolarityswitch" value read in from chan_dahdi.conf
00633     */
00634    unsigned int hanguponpolarityswitch:1;
00635    /*! \brief TRUE if DTMF detection needs to be done by hardware. */
00636    unsigned int hardwaredtmf:1;
00637    /*!
00638     * \brief TRUE if the outgoing caller ID is blocked/hidden.
00639     * \note Caller ID can be disabled by dialing *67.
00640     * \note Caller ID can be enabled by dialing *82.
00641     * \note Initialized with the "hidecallerid" value read in from chan_dahdi.conf
00642     */
00643    unsigned int hidecallerid:1;
00644    /*!
00645     * \brief TRUE if hide just the name not the number for legacy PBX use.
00646     * \note Only applies to PRI channels.
00647     * \note Set from the "hidecalleridname" value read in from chan_dahdi.conf
00648     */
00649    unsigned int hidecalleridname:1;
00650    /*! \brief TRUE if DTMF detection is disabled. */
00651    unsigned int ignoredtmf:1;
00652    /*!
00653     * \brief TRUE if the channel should be answered immediately
00654     * without attempting to gather any digits.
00655     * \note Set from the "immediate" value read in from chan_dahdi.conf
00656     */
00657    unsigned int immediate:1;
00658    /*! \brief TRUE if in an alarm condition. */
00659    unsigned int inalarm:1;
00660    /*! \brief TRUE if TDD in MATE mode */
00661    unsigned int mate:1;
00662    /*! \brief TRUE if we originated the call leg. */
00663    unsigned int outgoing:1;
00664    /* unsigned int overlapdial:1;         unused and potentially confusing */
00665    /*!
00666     * \brief TRUE if busy extensions will hear the call-waiting tone
00667     * and can use hook-flash to switch between callers.
00668     * \note Set from the "callwaiting" value read in from chan_dahdi.conf
00669     */
00670    unsigned int permcallwaiting:1;
00671    /*!
00672     * \brief TRUE if the outgoing caller ID is blocked/restricted/hidden.
00673     * \note Set from the "hidecallerid" value read in from chan_dahdi.conf
00674     */
00675    unsigned int permhidecallerid:1;
00676    /*!
00677     * \brief TRUE if PRI congestion/busy indications are sent out-of-band.
00678     * \note Set from the "priindication" value read in from chan_dahdi.conf
00679     */
00680    unsigned int priindication_oob:1;
00681    /*!
00682     * \brief TRUE if PRI B channels are always exclusively selected.
00683     * \note Set from the "priexclusive" value read in from chan_dahdi.conf
00684     */
00685    unsigned int priexclusive:1;
00686    /*!
00687     * \brief TRUE if we will pulse dial.
00688     * \note Set from the "pulsedial" value read in from chan_dahdi.conf
00689     */
00690    unsigned int pulse:1;
00691    /*! \brief TRUE if a pulsed digit was detected. (Pulse dial phone detected) */
00692    unsigned int pulsedial:1;
00693    unsigned int restartpending:1;      /*!< flag to ensure counted only once for restart */
00694    /*!
00695     * \brief TRUE if caller ID is restricted.
00696     * \note Set but not used.  Should be deleted.  Redundant with permhidecallerid.
00697     * \note Set from the "restrictcid" value read in from chan_dahdi.conf
00698     */
00699    unsigned int restrictcid:1;
00700    /*!
00701     * \brief TRUE if three way calling is enabled
00702     * \note Set from the "threewaycalling" value read in from chan_dahdi.conf
00703     */
00704    unsigned int threewaycalling:1;
00705    /*!
00706     * \brief TRUE if call transfer is enabled
00707     * \note For FXS ports (either direct analog or over T1/E1):
00708     *   Support flash-hook call transfer
00709     * \note For digital ports using ISDN PRI protocols:
00710     *   Support switch-side transfer (called 2BCT, RLT or other names)
00711     * \note Set from the "transfer" value read in from chan_dahdi.conf
00712     */
00713    unsigned int transfer:1;
00714    /*!
00715     * \brief TRUE if caller ID is used on this channel.
00716     * \note PRI and SS7 spans will save caller ID from the networking peer.
00717     * \note FXS ports will generate the caller ID spill.
00718     * \note FXO ports will listen for the caller ID spill.
00719     * \note Set from the "usecallerid" value read in from chan_dahdi.conf
00720     */
00721    unsigned int use_callerid:1;
00722    /*!
00723     * \brief TRUE if we will use the calling presentation setting
00724     * from the Asterisk channel for outgoing calls.
00725     * \note Only applies to PRI and SS7 channels.
00726     * \note Set from the "usecallingpres" value read in from chan_dahdi.conf
00727     */
00728    unsigned int use_callingpres:1;
00729    /*!
00730     * \brief TRUE if distinctive rings are to be detected.
00731     * \note For FXO lines
00732     * \note Set indirectly from the "usedistinctiveringdetection" value read in from chan_dahdi.conf
00733     */
00734    unsigned int usedistinctiveringdetection:1;
00735    /*!
00736     * \brief TRUE if we should use the callerid from incoming call on dahdi transfer.
00737     * \note Set from the "useincomingcalleridondahditransfer" value read in from chan_dahdi.conf
00738     */
00739    unsigned int dahditrcallerid:1;
00740    /*!
00741     * \brief TRUE if allowed to flash-transfer to busy channels.
00742     * \note Set from the "transfertobusy" value read in from chan_dahdi.conf
00743     */
00744    unsigned int transfertobusy:1;
00745    /*!
00746     * \brief TRUE if the FXO port monitors for neon type MWI indications from the other end.
00747     * \note Set if the "mwimonitor" value read in contains "neon" from chan_dahdi.conf
00748     */
00749    unsigned int mwimonitor_neon:1;
00750    /*!
00751     * \brief TRUE if the FXO port monitors for fsk type MWI indications from the other end.
00752     * \note Set if the "mwimonitor" value read in contains "fsk" from chan_dahdi.conf
00753     */
00754    unsigned int mwimonitor_fsk:1;
00755    /*!
00756     * \brief TRUE if the FXO port monitors for rpas precursor to fsk MWI indications from the other end.
00757     * \note RPAS - Ring Pulse Alert Signal
00758     * \note Set if the "mwimonitor" value read in contains "rpas" from chan_dahdi.conf
00759     */
00760    unsigned int mwimonitor_rpas:1;
00761    /*! \brief TRUE if an MWI monitor thread is currently active */
00762    unsigned int mwimonitoractive:1;
00763    /*! \brief TRUE if a MWI message sending thread is active */
00764    unsigned int mwisendactive:1;
00765    /*!
00766     * \brief TRUE if channel is out of reset and ready
00767     * \note Set but not used.
00768     */
00769    unsigned int inservice:1;
00770    /*!
00771     * \brief TRUE if the channel is locally blocked.
00772     * \note Applies to SS7 channels.
00773     */
00774    unsigned int locallyblocked:1;
00775    /*!
00776     * \brief TRUE if the channel is remotely blocked.
00777     * \note Applies to SS7 channels.
00778     */
00779    unsigned int remotelyblocked:1;
00780 #if defined(HAVE_PRI) || defined(HAVE_SS7)
00781    /*!
00782     * \brief XXX BOOLEAN Purpose???
00783     * \note Applies to SS7 channels.
00784     */
00785    unsigned int rlt:1;
00786    /*! \brief TRUE if channel is alerting/ringing */
00787    unsigned int alerting:1;
00788    /*! \brief TRUE if the call has already gone/hungup */
00789    unsigned int alreadyhungup:1;
00790    /*!
00791     * \brief TRUE if this is an idle call
00792     * \note Applies to PRI channels.
00793     */
00794    unsigned int isidlecall:1;
00795    /*!
00796     * \brief TRUE if call is in a proceeding state.
00797     * The call has started working its way through the network.
00798     */
00799    unsigned int proceeding:1;
00800    /*! \brief TRUE if the call has seen progress through the network. */
00801    unsigned int progress:1;
00802    /*!
00803     * \brief TRUE if this channel is being reset/restarted
00804     * \note Applies to PRI channels.
00805     */
00806    unsigned int resetting:1;
00807    /*!
00808     * \brief TRUE if this channel has received a SETUP_ACKNOWLEDGE
00809     * \note Applies to PRI channels.
00810     */
00811    unsigned int setup_ack:1;
00812 #endif
00813    /*!
00814     * \brief TRUE if SMDI (Simplified Message Desk Interface) is enabled
00815     * \note Set from the "usesmdi" value read in from chan_dahdi.conf
00816     */
00817    unsigned int use_smdi:1;
00818    /*! \brief The serial port to listen for SMDI data on */
00819    struct ast_smdi_interface *smdi_iface;
00820 
00821    /*! \brief Distinctive Ring data */
00822    struct dahdi_distRings drings;
00823 
00824    /*!
00825     * \brief The configured context for incoming calls.
00826     * \note The "context" string read in from chan_dahdi.conf
00827     */
00828    char context[AST_MAX_CONTEXT];
00829    /*!
00830     * \brief Saved context string.
00831     */
00832    char defcontext[AST_MAX_CONTEXT];
00833    /*! \brief Extension to use in the dialplan. */
00834    char exten[AST_MAX_EXTENSION];
00835    /*!
00836     * \brief Language configured for calls.
00837     * \note The "language" string read in from chan_dahdi.conf
00838     */
00839    char language[MAX_LANGUAGE];
00840    /*!
00841     * \brief The configured music-on-hold class to use for calls.
00842     * \note The "musicclass" or "mohinterpret" or "musiconhold" string read in from chan_dahdi.conf
00843     */
00844    char mohinterpret[MAX_MUSICCLASS];
00845    /*!
00846     * \brief Suggested music-on-hold class for peer channel to use for calls.
00847     * \note The "mohsuggest" string read in from chan_dahdi.conf
00848     */
00849    char mohsuggest[MAX_MUSICCLASS];
00850    char parkinglot[AST_MAX_EXTENSION]; /*!< Parking lot for this channel */
00851 #if defined(PRI_ANI) || defined(HAVE_SS7)
00852    /*! \brief Automatic Number Identification number (Alternate PRI caller ID number) */
00853    char cid_ani[AST_MAX_EXTENSION];
00854 #endif
00855    /*! \brief Automatic Number Identification code from PRI */
00856    int cid_ani2;
00857    /*! \brief Caller ID number from an incoming call. */
00858    char cid_num[AST_MAX_EXTENSION];
00859    /*! \brief Caller ID Q.931 TON/NPI field values.  Set by PRI. Zero otherwise. */
00860    int cid_ton;
00861    /*! \brief Caller ID name from an incoming call. */
00862    char cid_name[AST_MAX_EXTENSION];
00863    /*! \brief Last Caller ID number from an incoming call. */
00864    char lastcid_num[AST_MAX_EXTENSION];
00865    /*! \brief Last Caller ID name from an incoming call. */
00866    char lastcid_name[AST_MAX_EXTENSION];
00867    char *origcid_num;            /*!< malloced original callerid */
00868    char *origcid_name;           /*!< malloced original callerid */
00869    /*! \brief Call waiting number. */
00870    char callwait_num[AST_MAX_EXTENSION];
00871    /*! \brief Call waiting name. */
00872    char callwait_name[AST_MAX_EXTENSION];
00873    /*! \brief Redirecting Directory Number Information Service (RDNIS) number */
00874    char rdnis[AST_MAX_EXTENSION];
00875    /*! \brief Dialed Number Identifier */
00876    char dnid[AST_MAX_EXTENSION];
00877    /*!
00878     * \brief Bitmapped groups this belongs to.
00879     * \note The "group" bitmapped group string read in from chan_dahdi.conf
00880     */
00881    ast_group_t group;
00882    /*! \brief Active PCM encoding format: DAHDI_LAW_ALAW or DAHDI_LAW_MULAW */
00883    int law;
00884    int confno;             /*!< Our conference */
00885    int confusers;             /*!< Who is using our conference */
00886    int propconfno;               /*!< Propagated conference number */
00887    /*!
00888     * \brief Bitmapped call groups this belongs to.
00889     * \note The "callgroup" bitmapped group string read in from chan_dahdi.conf
00890     */
00891    ast_group_t callgroup;
00892    /*!
00893     * \brief Bitmapped pickup groups this belongs to.
00894     * \note The "pickupgroup" bitmapped group string read in from chan_dahdi.conf
00895     */
00896    ast_group_t pickupgroup;
00897    /*!
00898     * \brief Channel variable list with associated values to set when a channel is created.
00899     * \note The "setvar" strings read in from chan_dahdi.conf
00900     */
00901    struct ast_variable *vars;
00902    int channel;               /*!< Channel Number or CRV */
00903    int span;               /*!< Span number */
00904    time_t guardtime;          /*!< Must wait this much time before using for new call */
00905    int cid_signalling;           /*!< CID signalling type bell202 or v23 */
00906    int cid_start;             /*!< CID start indicator, polarity or ring */
00907    int callingpres;           /*!< The value of callling presentation that we're going to use when placing a PRI call */
00908    int callwaitingrepeat;           /*!< How many samples to wait before repeating call waiting */
00909    int cidcwexpire;           /*!< When to expire our muting for CID/CW */
00910    /*! \brief Analog caller ID waveform sample buffer */
00911    unsigned char *cidspill;
00912    /*! \brief Position in the cidspill buffer to send out next. */
00913    int cidpos;
00914    /*! \brief Length of the cidspill buffer containing samples. */
00915    int cidlen;
00916    /*! \brief Ring timeout timer?? */
00917    int ringt;
00918    /*!
00919     * \brief Ring timeout base.
00920     * \note Value computed indirectly from "ringtimeout" read in from chan_dahdi.conf
00921     */
00922    int ringt_base;
00923    /*!
00924     * \brief Number of most significant digits/characters to strip from the dialed number.
00925     * \note Feature is deprecated.  Use dialplan logic.
00926     * \note The characters are stripped before the PRI TON/NPI prefix
00927     * characters are processed.
00928     */
00929    int stripmsd;
00930    /*! \brief BOOLEAN. XXX Meaning what?? */
00931    int callwaitcas;
00932    /*! \brief Number of call waiting rings. */
00933    int callwaitrings;
00934    /*! \brief Echo cancel parameters. */
00935    struct {
00936       struct dahdi_echocanparams head;
00937       struct dahdi_echocanparam params[DAHDI_MAX_ECHOCANPARAMS];
00938    } echocancel;
00939    /*!
00940     * \brief Echo training time. 0 = disabled
00941     * \note Set from the "echotraining" value read in from chan_dahdi.conf
00942     */
00943    int echotraining;
00944    /*! \brief Filled with 'w'.  XXX Purpose?? */
00945    char echorest[20];
00946    /*!
00947     * \brief Number of times to see "busy" tone before hanging up.
00948     * \note Set from the "busycount" value read in from chan_dahdi.conf
00949     */
00950    int busycount;
00951    /*!
00952     * \brief If your country has a busy tone with the same length tone and silence (as many countries do), consider using this option in order to compare tone and silence lengths
00953     * \note Set from the "busycompare" value read in from chan_dahdi.conf
00954     */
00955    int busycompare;
00956    /*!
00957     * \brief Lenght of "tone" in ms.
00958     * \note Set from the "busypattern" value read in from chan_dahdi.conf
00959     */
00960    int busytonelength;
00961    /*!
00962     * \brief Lenght of "silence" in ms.
00963     * \note Set from the "busypattern" value read in from chan_dahdi.conf
00964     */
00965    int busyquietlength;
00966    /*!
00967     * \brief  Maximun percentage difference allowed between measured and actual pattern
00968     * \note Set from the "busyfuzziness" value read in from chan_dahdi.conf
00969     */
00970    int busyfuzziness;
00971    /*!
00972     * \brief Maximun signal average level considered as silence in this channel
00973     * \note Set from the "silencethreshold" value read in from chan_dahdi.conf
00974     */
00975    int silencethreshold;
00976    /*!
00977     * \brief Bitmapped call progress detection flags. CALLPROGRESS_xxx values.
00978     * \note Bits set from the "callprogress" and "faxdetect" values read in from chan_dahdi.conf
00979     */
00980    int callprogress;
00981    struct timeval flashtime;        /*!< Last flash-hook time */
00982    /*! \brief Opaque DSP configuration structure. */
00983    struct ast_dsp *dsp;
00984    //int cref;             /*!< Call reference number (Not used) */
00985    /*! \brief DAHDI dial operation command struct for ioctl() call. */
00986    struct dahdi_dialoperation dop;
00987    int whichwink;             /*!< SIG_FEATDMF_TA Which wink are we on? */
00988    /*! \brief Second part of SIG_FEATDMF_TA wink operation. */
00989    char finaldial[64];
00990    char accountcode[AST_MAX_ACCOUNT_CODE];      /*!< Account code */
00991    int amaflags;              /*!< AMA Flags */
00992    struct tdd_state *tdd;           /*!< TDD flag */
00993    /*! \brief Accumulated call forwarding number. */
00994    char call_forward[AST_MAX_EXTENSION];
00995    /*!
00996     * \brief Voice mailbox location.
00997     * \note Set from the "mailbox" string read in from chan_dahdi.conf
00998     */
00999    char mailbox[AST_MAX_EXTENSION];
01000    /*! \brief Opaque event subscription parameters for message waiting indication support. */
01001    struct ast_event_sub *mwi_event_sub;
01002    /*! \brief Delayed dialing for E911.  Overlap digits for ISDN. */
01003    char dialdest[256];
01004    /*! \brief Time the interface went on-hook. */
01005    int onhooktime;
01006    /*! \brief -1 = unknown, 0 = no messages, 1 = new messages available */
01007    int msgstate;
01008    int distinctivering;          /*!< Which distinctivering to use */
01009    int cidrings;              /*!< Which ring to deliver CID on */
01010    int dtmfrelax;             /*!< whether to run in relaxed DTMF mode */
01011    /*! \brief Holding place for event injected from outside normal operation. */
01012    int fake_event;
01013    /*!
01014     * \brief Minimal time period (ms) between the answer polarity
01015     * switch and hangup polarity switch.
01016     */
01017    int polarityonanswerdelay;
01018    /*! \brief Start delay time if polarityonanswerdelay is nonzero. */
01019    struct timeval polaritydelaytv;
01020    /*!
01021     * \brief Send caller ID after this many rings.
01022     * \note Set from the "sendcalleridafter" value read in from chan_dahdi.conf
01023     */
01024    int sendcalleridafter;
01025 #ifdef HAVE_PRI
01026    /*! \brief DAHDI PRI control parameters */
01027    struct dahdi_pri *pri;
01028    /*! \brief XXX Purpose??? */
01029    struct dahdi_pvt *bearer;
01030    /*! \brief XXX Purpose??? */
01031    struct dahdi_pvt *realcall;
01032    /*! \brief Opaque libpri call control structure */
01033    q931_call *call;
01034    /*! \brief Channel number in span. */
01035    int prioffset;
01036    /*! \brief Logical span number within trunk group */
01037    int logicalspan;
01038 #endif   
01039    /*! \brief Current line interface polarity. POLARITY_IDLE, POLARITY_REV */
01040    int polarity;
01041    /*! \brief DSP feature flags: DSP_FEATURE_xxx */
01042    int dsp_features;
01043 #ifdef HAVE_SS7
01044    /*! \brief SS7 control parameters */
01045    struct dahdi_ss7 *ss7;
01046    /*! \brief Opaque libss7 call control structure */
01047    struct isup_call *ss7call;
01048    char charge_number[50];
01049    char gen_add_number[50];
01050    char gen_dig_number[50];
01051    char orig_called_num[50];
01052    char redirecting_num[50];
01053    char generic_name[50];
01054    unsigned char gen_add_num_plan;
01055    unsigned char gen_add_nai;
01056    unsigned char gen_add_pres_ind;
01057    unsigned char gen_add_type;
01058    unsigned char gen_dig_type;
01059    unsigned char gen_dig_scheme;
01060    char jip_number[50];
01061    unsigned char lspi_type;
01062    unsigned char lspi_scheme;
01063    unsigned char lspi_context;
01064    char lspi_ident[50];
01065    unsigned int call_ref_ident;
01066    unsigned int call_ref_pc;
01067    unsigned char calling_party_cat;
01068    int transcap;
01069    int cic;                   /*!< CIC associated with channel */
01070    unsigned int dpc;                /*!< CIC's DPC */
01071    unsigned int loopedback:1;
01072 #endif
01073    /*! \brief DTMF digit in progress.  0 when no digit in progress. */
01074    char begindigit;
01075    /*! \brief TRUE if confrence is muted. */
01076    int muting;
01077 } *iflist = NULL, *ifend = NULL;
01078 
01079 /*! \brief Channel configuration from chan_dahdi.conf .
01080  * This struct is used for parsing the [channels] section of chan_dahdi.conf.
01081  * Generally there is a field here for every possible configuration item.
01082  *
01083  * The state of fields is saved along the parsing and whenever a 'channel'
01084  * statement is reached, the current dahdi_chan_conf is used to configure the 
01085  * channel (struct dahdi_pvt)
01086  *
01087  * \see dahdi_chan_init for the default values.
01088  */
01089 struct dahdi_chan_conf {
01090    struct dahdi_pvt chan;
01091 #ifdef HAVE_PRI
01092    struct dahdi_pri pri;
01093 #endif
01094 
01095 #ifdef HAVE_SS7
01096    struct dahdi_ss7 ss7;
01097 #endif
01098    struct dahdi_params timing;
01099    int is_sig_auto; /*!< Use channel signalling from DAHDI? */
01100 
01101    /*!
01102     * \brief The serial port to listen for SMDI data on
01103     * \note Set from the "smdiport" string read in from chan_dahdi.conf
01104     */
01105    char smdi_port[SMDI_MAX_FILENAME_LEN];
01106 };
01107 
01108 /*! returns a new dahdi_chan_conf with default values (by-value) */
01109 static struct dahdi_chan_conf dahdi_chan_conf_default(void) {
01110    /* recall that if a field is not included here it is initialized
01111     * to 0 or equivalent
01112     */
01113    struct dahdi_chan_conf conf = {
01114 #ifdef HAVE_PRI
01115       .pri = {
01116          .nsf = PRI_NSF_NONE,
01117          .switchtype = PRI_SWITCH_NI2,
01118          .dialplan = PRI_UNKNOWN + 1,
01119          .localdialplan = PRI_NATIONAL_ISDN + 1,
01120          .nodetype = PRI_CPE,
01121 
01122          .minunused = 2,
01123          .idleext = "",
01124          .idledial = "",
01125          .internationalprefix = "",
01126          .nationalprefix = "",
01127          .localprefix = "",
01128          .privateprefix = "",
01129          .unknownprefix = "",
01130          .resetinterval = -1,
01131       },
01132 #endif
01133 #ifdef HAVE_SS7
01134       .ss7 = {
01135          .called_nai = SS7_NAI_NATIONAL,
01136          .calling_nai = SS7_NAI_NATIONAL,
01137          .internationalprefix = "",
01138          .nationalprefix = "",
01139          .subscriberprefix = "",
01140          .unknownprefix = ""
01141       },
01142 #endif
01143       .chan = {
01144          .context = "default",
01145          .cid_num = "",
01146          .cid_name = "",
01147          .mohinterpret = "default",
01148          .mohsuggest = "",
01149          .parkinglot = "",
01150          .transfertobusy = 1,
01151 
01152          .cid_signalling = CID_SIG_BELL,
01153          .cid_start = CID_START_RING,
01154          .dahditrcallerid = 0,
01155          .use_callerid = 1,
01156          .sig = -1,
01157          .outsigmod = -1,
01158 
01159          .cid_rxgain = +5.0,
01160 
01161          .tonezone = -1,
01162 
01163          .echocancel.head.tap_length = 1,
01164 
01165          .busycount = 3,
01166          .busycompare = 0,
01167          .busytonelength = 0,
01168          .busyquietlength = 0,
01169          .busyfuzziness = 0,
01170          .silencethreshold = 0,
01171 
01172          .accountcode = "",
01173 
01174          .mailbox = "",
01175 
01176 
01177          .polarityonanswerdelay = 600,
01178 
01179          .sendcalleridafter = DEFAULT_CIDRINGS,
01180       
01181          .buf_policy = DAHDI_POLICY_IMMEDIATE,
01182          .buf_no = numbufs
01183       },
01184       .timing = {
01185          .prewinktime = -1,
01186          .preflashtime = -1,
01187          .winktime = -1,
01188          .flashtime = -1,
01189          .starttime = -1,
01190          .rxwinktime = -1,
01191          .rxflashtime = -1,
01192          .debouncetime = -1
01193       },
01194       .is_sig_auto = 1,
01195       .smdi_port = "/dev/ttyS0",
01196    };
01197 
01198    return conf;
01199 }
01200 
01201 
01202 static struct ast_channel *dahdi_request(const char *type, int format, void *data, int *cause);
01203 static int dahdi_digit_begin(struct ast_channel *ast, char digit);
01204 static int dahdi_digit_end(struct ast_channel *ast, char digit, unsigned int duration);
01205 static int dahdi_sendtext(struct ast_channel *c, const char *text);
01206 static int dahdi_call(struct ast_channel *ast, char *rdest, int timeout);
01207 static int dahdi_hangup(struct ast_channel *ast);
01208 static int dahdi_answer(struct ast_channel *ast);
01209 static struct ast_frame *dahdi_read(struct ast_channel *ast);
01210 static int dahdi_write(struct ast_channel *ast, struct ast_frame *frame);
01211 static struct ast_frame *dahdi_exception(struct ast_channel *ast);
01212 static int dahdi_indicate(struct ast_channel *chan, int condition, const void *data, size_t datalen);
01213 static int dahdi_fixup(struct ast_channel *oldchan, struct ast_channel *newchan);
01214 static int dahdi_setoption(struct ast_channel *chan, int option, void *data, int datalen);
01215 static int dahdi_func_read(struct ast_channel *chan, const char *function, char *data, char *buf, size_t len);
01216 static struct dahdi_pvt *handle_init_event(struct dahdi_pvt *i, int event);
01217 
01218 static const struct ast_channel_tech dahdi_tech = {
01219    .type = "DAHDI",
01220    .description = tdesc,
01221    .capabilities = AST_FORMAT_SLINEAR | AST_FORMAT_ULAW | AST_FORMAT_ALAW,
01222    .requester = dahdi_request,
01223    .send_digit_begin = dahdi_digit_begin,
01224    .send_digit_end = dahdi_digit_end,
01225    .send_text = dahdi_sendtext,
01226    .call = dahdi_call,
01227    .hangup = dahdi_hangup,
01228    .answer = dahdi_answer,
01229    .read = dahdi_read,
01230    .write = dahdi_write,
01231    .bridge = dahdi_bridge,
01232    .exception = dahdi_exception,
01233    .indicate = dahdi_indicate,
01234    .fixup = dahdi_fixup,
01235    .setoption = dahdi_setoption,
01236    .func_channel_read = dahdi_func_read,
01237 };
01238 
01239 #ifdef HAVE_PRI
01240 #define GET_CHANNEL(p) ((p)->bearer ? (p)->bearer->channel : p->channel)
01241 #else
01242 #define GET_CHANNEL(p) ((p)->channel)
01243 #endif
01244 
01245 struct dahdi_pvt *round_robin[32];
01246 
01247 #ifdef HAVE_PRI
01248 static inline int pri_grab(struct dahdi_pvt *pvt, struct dahdi_pri *pri)
01249 {
01250    int res;
01251    /* Grab the lock first */
01252    do {
01253       res = ast_mutex_trylock(&pri->lock);
01254       if (res) {
01255          DEADLOCK_AVOIDANCE(&pvt->lock);
01256       }
01257    } while (res);
01258    /* Then break the poll */
01259    if (pri->master != AST_PTHREADT_NULL)
01260       pthread_kill(pri->master, SIGURG);
01261    return 0;
01262 }
01263 #endif
01264 
01265 #ifdef HAVE_SS7
01266 static inline void ss7_rel(struct dahdi_ss7 *ss7)
01267 {
01268    ast_mutex_unlock(&ss7->lock);
01269 }
01270 
01271 static inline int ss7_grab(struct dahdi_pvt *pvt, struct dahdi_ss7 *pri)
01272 {
01273    int res;
01274    /* Grab the lock first */
01275    do {
01276       res = ast_mutex_trylock(&pri->lock);
01277       if (res) {
01278          DEADLOCK_AVOIDANCE(&pvt->lock);
01279       }
01280    } while (res);
01281    /* Then break the poll */
01282    if (pri->master != AST_PTHREADT_NULL)
01283       pthread_kill(pri->master, SIGURG);
01284    return 0;
01285 }
01286 #endif
01287 #define NUM_CADENCE_MAX 25
01288 static int num_cadence = 4;
01289 static int user_has_defined_cadences = 0;
01290 
01291 static struct dahdi_ring_cadence cadences[NUM_CADENCE_MAX] = {
01292    { { 125, 125, 2000, 4000 } },       /*!< Quick chirp followed by normal ring */
01293    { { 250, 250, 500, 1000, 250, 250, 500, 4000 } }, /*!< British style ring */
01294    { { 125, 125, 125, 125, 125, 4000 } }, /*!< Three short bursts */
01295    { { 1000, 500, 2500, 5000 } },   /*!< Long ring */
01296 };
01297 
01298 /*! \brief cidrings says in which pause to transmit the cid information, where the first pause
01299  * is 1, the second pause is 2 and so on.
01300  */
01301 
01302 static int cidrings[NUM_CADENCE_MAX] = {
01303    2,                            /*!< Right after first long ring */
01304    4,                            /*!< Right after long part */
01305    3,                            /*!< After third chirp */
01306    2,                            /*!< Second spell */
01307 };
01308 
01309 /* ETSI EN300 659-1 specifies the ring pulse between 200 and 300 mS */
01310 static struct dahdi_ring_cadence AS_RP_cadence = {{250, 10000}};
01311 
01312 #define ISTRUNK(p) ((p->sig == SIG_FXSLS) || (p->sig == SIG_FXSKS) || \
01313          (p->sig == SIG_FXSGS) || (p->sig == SIG_PRI))
01314 
01315 #define CANBUSYDETECT(p) (ISTRUNK(p) || (p->sig & (SIG_EM | SIG_EM_E1 | SIG_SF)) /* || (p->sig & __DAHDI_SIG_FXO) */)
01316 #define CANPROGRESSDETECT(p) (ISTRUNK(p) || (p->sig & (SIG_EM | SIG_EM_E1 | SIG_SF)) /* || (p->sig & __DAHDI_SIG_FXO) */)
01317 
01318 static int dahdi_get_index(struct ast_channel *ast, struct dahdi_pvt *p, int nullok)
01319 {
01320    int res;
01321    if (p->subs[SUB_REAL].owner == ast)
01322       res = 0;
01323    else if (p->subs[SUB_CALLWAIT].owner == ast)
01324       res = 1;
01325    else if (p->subs[SUB_THREEWAY].owner == ast)
01326       res = 2;
01327    else {
01328       res = -1;
01329       if (!nullok)
01330          ast_log(LOG_WARNING, "Unable to get index, and nullok is not asserted\n");
01331    }
01332    return res;
01333 }
01334 
01335 static void wakeup_sub(struct dahdi_pvt *p, int a, struct dahdi_pri *pri)
01336 {
01337 #ifdef HAVE_PRI
01338    if (pri)
01339       ast_mutex_unlock(&pri->lock);
01340 #endif         
01341    for (;;) {
01342       if (p->subs[a].owner) {
01343          if (ast_channel_trylock(p->subs[a].owner)) {
01344             DEADLOCK_AVOIDANCE(&p->lock);
01345          } else {
01346             ast_queue_frame(p->subs[a].owner, &ast_null_frame);
01347             ast_channel_unlock(p->subs[a].owner);
01348             break;
01349          }
01350       } else
01351          break;
01352    }
01353 #ifdef HAVE_PRI
01354    if (pri)
01355       ast_mutex_lock(&pri->lock);
01356 #endif         
01357 }
01358 
01359 static void dahdi_queue_frame(struct dahdi_pvt *p, struct ast_frame *f, void *data)
01360 {
01361 #ifdef HAVE_PRI
01362    struct dahdi_pri *pri = (struct dahdi_pri*) data;
01363 #endif
01364 #ifdef HAVE_SS7
01365    struct dahdi_ss7 *ss7 = (struct dahdi_ss7*) data;
01366 #endif
01367    /* We must unlock the PRI to avoid the possibility of a deadlock */
01368 #if defined(HAVE_PRI) || defined(HAVE_SS7)
01369    if (data) {
01370       switch (p->sig) {
01371 #ifdef HAVE_PRI
01372       case SIG_BRI:
01373       case SIG_BRI_PTMP:
01374       case SIG_PRI:
01375          ast_mutex_unlock(&pri->lock);
01376          break;
01377 #endif
01378 #ifdef HAVE_SS7
01379       case SIG_SS7:
01380          ast_mutex_unlock(&ss7->lock);
01381          break;
01382 #endif
01383       default:
01384          break;
01385       }
01386    }
01387 #endif      
01388    for (;;) {
01389       if (p->owner) {
01390          if (ast_channel_trylock(p->owner)) {
01391             DEADLOCK_AVOIDANCE(&p->lock);
01392          } else {
01393             ast_queue_frame(p->owner, f);
01394             ast_channel_unlock(p->owner);
01395             break;
01396          }
01397       } else
01398          break;
01399    }
01400 #if defined(HAVE_PRI) || defined(HAVE_SS7)
01401    if (data) {
01402       switch (p->sig) {
01403 #ifdef HAVE_PRI
01404       case SIG_BRI:
01405       case SIG_BRI_PTMP:
01406       case SIG_PRI:
01407          ast_mutex_lock(&pri->lock);
01408          break;
01409 #endif
01410 #ifdef HAVE_SS7
01411       case SIG_SS7:
01412          ast_mutex_lock(&ss7->lock);
01413          break;
01414 #endif
01415       default:
01416          break;
01417       }
01418    }
01419 
01420 #endif      
01421 }
01422 
01423 static int restore_gains(struct dahdi_pvt *p);
01424 
01425 static void swap_subs(struct dahdi_pvt *p, int a, int b)
01426 {
01427    int tchan;
01428    int tinthreeway;
01429    struct ast_channel *towner;
01430 
01431    ast_debug(1, "Swapping %d and %d\n", a, b);
01432 
01433    tchan = p->subs[a].chan;
01434    towner = p->subs[a].owner;
01435    tinthreeway = p->subs[a].inthreeway;
01436 
01437    p->subs[a].chan = p->subs[b].chan;
01438    p->subs[a].owner = p->subs[b].owner;
01439    p->subs[a].inthreeway = p->subs[b].inthreeway;
01440 
01441    p->subs[b].chan = tchan;
01442    p->subs[b].owner = towner;
01443    p->subs[b].inthreeway = tinthreeway;
01444 
01445    if (p->subs[a].owner) 
01446       ast_channel_set_fd(p->subs[a].owner, 0, p->subs[a].dfd);
01447    if (p->subs[b].owner) 
01448       ast_channel_set_fd(p->subs[b].owner, 0, p->subs[b].dfd);
01449    wakeup_sub(p, a, NULL);
01450    wakeup_sub(p, b, NULL);
01451 }
01452 
01453 static int dahdi_open(char *fn)
01454 {
01455    int fd;
01456    int isnum;
01457    int chan = 0;
01458    int bs;
01459    int x;
01460    isnum = 1;
01461    for (x = 0; x < strlen(fn); x++) {
01462       if (!isdigit(fn[x])) {
01463          isnum = 0;
01464          break;
01465       }
01466    }
01467    if (isnum) {
01468       chan = atoi(fn);
01469       if (chan < 1) {
01470          ast_log(LOG_WARNING, "Invalid channel number '%s'\n", fn);
01471          return -1;
01472       }
01473       fn = "/dev/dahdi/channel";
01474    }
01475    fd = open(fn, O_RDWR | O_NONBLOCK);
01476    if (fd < 0) {
01477       ast_log(LOG_WARNING, "Unable to open '%s': %s\n", fn, strerror(errno));
01478       return -1;
01479    }
01480    if (chan) {
01481       if (ioctl(fd, DAHDI_SPECIFY, &chan)) {
01482          x = errno;
01483          close(fd);
01484          errno = x;
01485          ast_log(LOG_WARNING, "Unable to specify channel %d: %s\n", chan, strerror(errno));
01486          return -1;
01487       }
01488    }
01489    bs = READ_SIZE;
01490    if (ioctl(fd, DAHDI_SET_BLOCKSIZE, &bs) == -1) {
01491       ast_log(LOG_WARNING, "Unable to set blocksize '%d': %s\n", bs,  strerror(errno));
01492       x = errno;
01493       close(fd);
01494       errno = x;
01495       return -1;
01496    }
01497    return fd;
01498 }
01499 
01500 static void dahdi_close(int fd)
01501 {
01502    if (fd > 0)
01503       close(fd);
01504 }
01505 
01506 static void dahdi_close_sub(struct dahdi_pvt *chan_pvt, int sub_num)
01507 {
01508    dahdi_close(chan_pvt->subs[sub_num].dfd);
01509    chan_pvt->subs[sub_num].dfd = -1;
01510 }
01511 
01512 #ifdef HAVE_PRI
01513 static void dahdi_close_pri_fd(struct dahdi_pri *pri, int fd_num)
01514 {
01515    dahdi_close(pri->fds[fd_num]);
01516    pri->fds[fd_num] = -1;
01517 }
01518 #endif
01519 
01520 #ifdef HAVE_SS7
01521 static void dahdi_close_ss7_fd(struct dahdi_ss7 *ss7, int fd_num)
01522 {
01523    dahdi_close(ss7->fds[fd_num]);
01524    ss7->fds[fd_num] = -1;
01525 }
01526 #endif
01527 
01528 static int dahdi_setlinear(int dfd, int linear)
01529 {
01530    int res;
01531    res = ioctl(dfd, DAHDI_SETLINEAR, &linear);
01532    if (res)
01533       return res;
01534    return 0;
01535 }
01536 
01537 
01538 static int alloc_sub(struct dahdi_pvt *p, int x)
01539 {
01540    struct dahdi_bufferinfo bi;
01541    int res;
01542    if (p->subs[x].dfd >= 0) {
01543       ast_log(LOG_WARNING, "%s subchannel of %d already in use\n", subnames[x], p->channel);
01544       return -1;
01545    }
01546 
01547    p->subs[x].dfd = dahdi_open("/dev/dahdi/pseudo");
01548    if (p->subs[x].dfd <= -1) {
01549       ast_log(LOG_WARNING, "Unable to open pseudo channel: %s\n", strerror(errno));
01550       return -1;
01551    }
01552 
01553    res = ioctl(p->subs[x].dfd, DAHDI_GET_BUFINFO, &bi);
01554    if (!res) {
01555       bi.txbufpolicy = p->buf_policy;
01556       bi.rxbufpolicy = p->buf_policy;
01557       bi.numbufs = p->buf_no;
01558       res = ioctl(p->subs[x].dfd, DAHDI_SET_BUFINFO, &bi);
01559       if (res < 0) {
01560          ast_log(LOG_WARNING, "Unable to set buffer policy on channel %d: %s\n", x, strerror(errno));
01561       }
01562    } else 
01563       ast_log(LOG_WARNING, "Unable to check buffer policy on channel %d: %s\n", x, strerror(errno));
01564 
01565    if (ioctl(p->subs[x].dfd, DAHDI_CHANNO, &p->subs[x].chan) == 1) {
01566       ast_log(LOG_WARNING, "Unable to get channel number for pseudo channel on FD %d: %s\n", p->subs[x].dfd, strerror(errno));
01567       dahdi_close_sub(p, x);
01568       p->subs[x].dfd = -1;
01569       return -1;
01570    }
01571    ast_debug(1, "Allocated %s subchannel on FD %d channel %d\n", subnames[x], p->subs[x].dfd, p->subs[x].chan);
01572    return 0;
01573 }
01574 
01575 static int unalloc_sub(struct dahdi_pvt *p, int x)
01576 {
01577    if (!x) {
01578       ast_log(LOG_WARNING, "Trying to unalloc the real channel %d?!?\n", p->channel);
01579       return -1;
01580    }
01581    ast_debug(1, "Released sub %d of channel %d\n", x, p->channel);
01582    dahdi_close_sub(p, x);
01583    p->subs[x].linear = 0;
01584    p->subs[x].chan = 0;
01585    p->subs[x].owner = NULL;
01586    p->subs[x].inthreeway = 0;
01587    p->polarity = POLARITY_IDLE;
01588    memset(&p->subs[x].curconf, 0, sizeof(p->subs[x].curconf));
01589    return 0;
01590 }
01591 
01592 static int digit_to_dtmfindex(char digit)
01593 {
01594    if (isdigit(digit))
01595       return DAHDI_TONE_DTMF_BASE + (digit - '0');
01596    else if (digit >= 'A' && digit <= 'D')
01597       return DAHDI_TONE_DTMF_A + (digit - 'A');
01598    else if (digit >= 'a' && digit <= 'd')
01599       return DAHDI_TONE_DTMF_A + (digit - 'a');
01600    else if (digit == '*')
01601       return DAHDI_TONE_DTMF_s;
01602    else if (digit == '#')
01603       return DAHDI_TONE_DTMF_p;
01604    else
01605       return -1;
01606 }
01607 
01608 static int dahdi_digit_begin(struct ast_channel *chan, char digit)
01609 {
01610    struct dahdi_pvt *pvt;
01611    int idx;
01612    int dtmf = -1;
01613    
01614    pvt = chan->tech_pvt;
01615 
01616    ast_mutex_lock(&pvt->lock);
01617 
01618    idx = dahdi_get_index(chan, pvt, 0);
01619 
01620    if ((idx != SUB_REAL) || !pvt->owner)
01621       goto out;
01622 
01623 #ifdef HAVE_PRI
01624    if (((pvt->sig == SIG_PRI) || (pvt->sig == SIG_BRI) || (pvt->sig == SIG_BRI_PTMP)) 
01625          && (chan->_state == AST_STATE_DIALING) && !pvt->proceeding) {
01626       if (pvt->setup_ack) {
01627          if (!pri_grab(pvt, pvt->pri)) {
01628             pri_information(pvt->pri->pri, pvt->call, digit);
01629             pri_rel(pvt->pri);
01630          } else
01631             ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", pvt->span);
01632       } else if (strlen(pvt->dialdest) < sizeof(pvt->dialdest) - 1) {
01633          int res;
01634          ast_debug(1, "Queueing digit '%c' since setup_ack not yet received\n", digit);
01635          res = strlen(pvt->dialdest);
01636          pvt->dialdest[res++] = digit;
01637          pvt->dialdest[res] = '\0';
01638       }
01639       goto out;
01640    }
01641 #endif
01642    if ((dtmf = digit_to_dtmfindex(digit)) == -1)
01643       goto out;
01644 
01645    if (pvt->pulse || ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SENDTONE, &dtmf)) {
01646       int res;
01647       struct dahdi_dialoperation zo = {
01648          .op = DAHDI_DIAL_OP_APPEND,
01649       };
01650 
01651       zo.dialstr[0] = 'T';
01652       zo.dialstr[1] = digit;
01653       zo.dialstr[2] = '\0';
01654       if ((res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_DIAL, &zo)))
01655          ast_log(LOG_WARNING, "Couldn't dial digit %c: %s\n", digit, strerror(errno));
01656       else
01657          pvt->dialing = 1;
01658    } else {
01659       ast_debug(1, "Started VLDTMF digit '%c'\n", digit);
01660       pvt->dialing = 1;
01661       pvt->begindigit = digit;
01662    }
01663 
01664 out:
01665    ast_mutex_unlock(&pvt->lock);
01666 
01667    return 0;
01668 }
01669 
01670 static int dahdi_digit_end(struct ast_channel *chan, char digit, unsigned int duration)
01671 {
01672    struct dahdi_pvt *pvt;
01673    int res = 0;
01674    int idx;
01675    int x;
01676    
01677    pvt = chan->tech_pvt;
01678 
01679    ast_mutex_lock(&pvt->lock);
01680    
01681    idx = dahdi_get_index(chan, pvt, 0);
01682 
01683    if ((idx != SUB_REAL) || !pvt->owner || pvt->pulse)
01684       goto out;
01685 
01686 #ifdef HAVE_PRI
01687    /* This means that the digit was already sent via PRI signalling */
01688    if (((pvt->sig == SIG_PRI) || (pvt->sig == SIG_BRI) || (pvt->sig == SIG_BRI_PTMP))
01689          && !pvt->begindigit)
01690       goto out;
01691 #endif
01692 
01693    if (pvt->begindigit) {
01694       x = -1;
01695       ast_debug(1, "Ending VLDTMF digit '%c'\n", digit);
01696       res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SENDTONE, &x);
01697       pvt->dialing = 0;
01698       pvt->begindigit = 0;
01699    }
01700 
01701 out:
01702    ast_mutex_unlock(&pvt->lock);
01703 
01704    return res;
01705 }
01706 
01707 static char *events[] = {
01708    "No event",
01709    "On hook",
01710    "Ring/Answered",
01711    "Wink/Flash",
01712    "Alarm",
01713    "No more alarm",
01714    "HDLC Abort",
01715    "HDLC Overrun",
01716    "HDLC Bad FCS",
01717    "Dial Complete",
01718    "Ringer On",
01719    "Ringer Off",
01720    "Hook Transition Complete",
01721    "Bits Changed",
01722    "Pulse Start",
01723    "Timer Expired",
01724    "Timer Ping",
01725    "Polarity Reversal",
01726    "Ring Begin",
01727 };
01728 
01729 static struct {
01730    int alarm;
01731    char *name;
01732 } alarms[] = {
01733    { DAHDI_ALARM_RED, "Red Alarm" },
01734    { DAHDI_ALARM_YELLOW, "Yellow Alarm" },
01735    { DAHDI_ALARM_BLUE, "Blue Alarm" },
01736    { DAHDI_ALARM_RECOVER, "Recovering" },
01737    { DAHDI_ALARM_LOOPBACK, "Loopback" },
01738    { DAHDI_ALARM_NOTOPEN, "Not Open" },
01739    { DAHDI_ALARM_NONE, "None" },
01740 };
01741 
01742 static char *alarm2str(int alm)
01743 {
01744    int x;
01745    for (x = 0; x < ARRAY_LEN(alarms); x++) {
01746       if (alarms[x].alarm & alm)
01747          return alarms[x].name;
01748    }
01749    return alm ? "Unknown Alarm" : "No Alarm";
01750 }
01751 
01752 static char *event2str(int event)
01753 {
01754    static char buf[256];
01755    if ((event < (ARRAY_LEN(events))) && (event > -1))
01756       return events[event];
01757    sprintf(buf, "Event %d", event); /* safe */
01758    return buf;
01759 }
01760 
01761 #ifdef HAVE_PRI
01762 static char *dialplan2str(int dialplan)
01763 {
01764    if (dialplan == -1 || dialplan == -2) {
01765       return("Dynamically set dialplan in ISDN");
01766    }
01767    return (pri_plan2str(dialplan));
01768 }
01769 #endif
01770 
01771 static char *dahdi_sig2str(int sig)
01772 {
01773    static char buf[256];
01774    switch (sig) {
01775    case SIG_EM:
01776       return "E & M Immediate";
01777    case SIG_EMWINK:
01778       return "E & M Wink";
01779    case SIG_EM_E1:
01780       return "E & M E1";
01781    case SIG_FEATD:
01782       return "Feature Group D (DTMF)";
01783    case SIG_FEATDMF:
01784       return "Feature Group D (MF)";
01785    case SIG_FEATDMF_TA:
01786       return "Feature Groud D (MF) Tandem Access";
01787    case SIG_FEATB:
01788       return "Feature Group B (MF)";
01789    case SIG_E911:
01790       return "E911 (MF)";
01791    case SIG_FGC_CAMA:
01792       return "FGC/CAMA (Dialpulse)";
01793    case SIG_FGC_CAMAMF:
01794       return "FGC/CAMA (MF)";
01795    case SIG_FXSLS:
01796       return "FXS Loopstart";
01797    case SIG_FXSGS:
01798       return "FXS Groundstart";
01799    case SIG_FXSKS:
01800       return "FXS Kewlstart";
01801    case SIG_FXOLS:
01802       return "FXO Loopstart";
01803    case SIG_FXOGS:
01804       return "FXO Groundstart";
01805    case SIG_FXOKS:
01806       return "FXO Kewlstart";
01807    case SIG_PRI:
01808       return "ISDN PRI";
01809    case SIG_BRI:
01810       return "ISDN BRI Point to Point";
01811    case SIG_BRI_PTMP:
01812       return "ISDN BRI Point to MultiPoint";
01813    case SIG_SS7:
01814       return "SS7";
01815    case SIG_SF:
01816       return "SF (Tone) Immediate";
01817    case SIG_SFWINK:
01818       return "SF (Tone) Wink";
01819    case SIG_SF_FEATD:
01820       return "SF (Tone) with Feature Group D (DTMF)";
01821    case SIG_SF_FEATDMF:
01822       return "SF (Tone) with Feature Group D (MF)";
01823    case SIG_SF_FEATB:
01824       return "SF (Tone) with Feature Group B (MF)";
01825    case SIG_GR303FXOKS:
01826       return "GR-303 with FXOKS";
01827    case SIG_GR303FXSKS:
01828       return "GR-303 with FXSKS";
01829    case 0:
01830       return "Pseudo";
01831    default:
01832       snprintf(buf, sizeof(buf), "Unknown signalling %d", sig);
01833       return buf;
01834    }
01835 }
01836 
01837 #define sig2str dahdi_sig2str
01838 
01839 static int conf_add(struct dahdi_pvt *p, struct dahdi_subchannel *c, int idx, int slavechannel)
01840 {
01841    /* If the conference already exists, and we're already in it
01842       don't bother doing anything */
01843    struct dahdi_confinfo zi;
01844    
01845    memset(&zi, 0, sizeof(zi));
01846    zi.chan = 0;
01847 
01848    if (slavechannel > 0) {
01849       /* If we have only one slave, do a digital mon */
01850       zi.confmode = DAHDI_CONF_DIGITALMON;
01851       zi.confno = slavechannel;
01852    } else {
01853       if (!idx) {
01854          /* Real-side and pseudo-side both participate in conference */
01855          zi.confmode = DAHDI_CONF_REALANDPSEUDO | DAHDI_CONF_TALKER | DAHDI_CONF_LISTENER |
01856             DAHDI_CONF_PSEUDO_TALKER | DAHDI_CONF_PSEUDO_LISTENER;
01857       } else
01858          zi.confmode = DAHDI_CONF_CONF | DAHDI_CONF_TALKER | DAHDI_CONF_LISTENER;
01859       zi.confno = p->confno;
01860    }
01861    if ((zi.confno == c->curconf.confno) && (zi.confmode == c->curconf.confmode))
01862       return 0;
01863    if (c->dfd < 0)
01864       return 0;
01865    if (ioctl(c->dfd, DAHDI_SETCONF, &zi)) {
01866       ast_log(LOG_WARNING, "Failed to add %d to conference %d/%d: %s\n", c->dfd, zi.confmode, zi.confno, strerror(errno));
01867       return -1;
01868    }
01869    if (slavechannel < 1) {
01870       p->confno = zi.confno;
01871    }
01872    memcpy(&c->curconf, &zi, sizeof(c->curconf));
01873    ast_debug(1, "Added %d to conference %d/%d\n", c->dfd, c->curconf.confmode, c->curconf.confno);
01874    return 0;
01875 }
01876 
01877 static int isourconf(struct dahdi_pvt *p, struct dahdi_subchannel *c)
01878 {
01879    /* If they're listening to our channel, they're ours */  
01880    if ((p->channel == c->curconf.confno) && (c->curconf.confmode == DAHDI_CONF_DIGITALMON))
01881       return 1;
01882    /* If they're a talker on our (allocated) conference, they're ours */
01883    if ((p->confno > 0) && (p->confno == c->curconf.confno) && (c->curconf.confmode & DAHDI_CONF_TALKER))
01884       return 1;
01885    return 0;
01886 }
01887 
01888 static int conf_del(struct dahdi_pvt *p, struct dahdi_subchannel *c, int idx)
01889 {
01890    struct dahdi_confinfo zi;
01891    if (/* Can't delete if there's no dfd */
01892       (c->dfd < 0) ||
01893       /* Don't delete from the conference if it's not our conference */
01894       !isourconf(p, c)
01895       /* Don't delete if we don't think it's conferenced at all (implied) */
01896       ) return 0;
01897    memset(&zi, 0, sizeof(zi));
01898    if (ioctl(c->dfd, DAHDI_SETCONF, &zi)) {
01899       ast_log(LOG_WARNING, "Failed to drop %d from conference %d/%d: %s\n", c->dfd, c->curconf.confmode, c->curconf.confno, strerror(errno));
01900       return -1;
01901    }
01902    ast_debug(1, "Removed %d from conference %d/%d\n", c->dfd, c->curconf.confmode, c->curconf.confno);
01903    memcpy(&c->curconf, &zi, sizeof(c->curconf));
01904    return 0;
01905 }
01906 
01907 static int isslavenative(struct dahdi_pvt *p, struct dahdi_pvt **out)
01908 {
01909    int x;
01910    int useslavenative;
01911    struct dahdi_pvt *slave = NULL;
01912    /* Start out optimistic */
01913    useslavenative = 1;
01914    /* Update conference state in a stateless fashion */
01915    for (x = 0; x < 3; x++) {
01916       /* Any three-way calling makes slave native mode *definitely* out
01917          of the question */
01918       if ((p->subs[x].dfd > -1) && p->subs[x].inthreeway)
01919          useslavenative = 0;
01920    }
01921    /* If we don't have any 3-way calls, check to see if we have
01922       precisely one slave */
01923    if (useslavenative) {
01924       for (x = 0; x < MAX_SLAVES; x++) {
01925          if (p->slaves[x]) {
01926             if (slave) {
01927                /* Whoops already have a slave!  No 
01928                   slave native and stop right away */
01929                slave = NULL;
01930                useslavenative = 0;
01931                break;
01932             } else {
01933                /* We have one slave so far */
01934                slave = p->slaves[x];
01935             }
01936          }
01937       }
01938    }
01939    /* If no slave, slave native definitely out */
01940    if (!slave)
01941       useslavenative = 0;
01942    else if (slave->law != p->law) {
01943       useslavenative = 0;
01944       slave = NULL;
01945    }
01946    if (out)
01947       *out = slave;
01948    return useslavenative;
01949 }
01950 
01951 static int reset_conf(struct dahdi_pvt *p)
01952 {
01953    p->confno = -1;
01954    memset(&p->subs[SUB_REAL].curconf, 0, sizeof(p->subs[SUB_REAL].curconf));
01955    if (p->subs[SUB_REAL].dfd > -1) {
01956       struct dahdi_confinfo zi;
01957 
01958       memset(&zi, 0, sizeof(zi));
01959       if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &zi))
01960          ast_log(LOG_WARNING, "Failed to reset conferencing on channel %d: %s\n", p->channel, strerror(errno));
01961    }
01962    return 0;
01963 }
01964 
01965 static int update_conf(struct dahdi_pvt *p)
01966 {
01967    int needconf = 0;
01968    int x;
01969    int useslavenative;
01970    struct dahdi_pvt *slave = NULL;
01971 
01972    useslavenative = isslavenative(p, &slave);
01973    /* Start with the obvious, general stuff */
01974    for (x = 0; x < 3; x++) {
01975       /* Look for three way calls */
01976       if ((p->subs[x].dfd > -1) && p->subs[x].inthreeway) {
01977          conf_add(p, &p->subs[x], x, 0);
01978          needconf++;
01979       } else {
01980          conf_del(p, &p->subs[x], x);
01981       }
01982    }
01983    /* If we have a slave, add him to our conference now. or DAX
01984       if this is slave native */
01985    for (x = 0; x < MAX_SLAVES; x++) {
01986       if (p->slaves[x]) {
01987          if (useslavenative)
01988             conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p));
01989          else {
01990             conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, 0);
01991             needconf++;
01992          }
01993       }
01994    }
01995    /* If we're supposed to be in there, do so now */
01996    if (p->inconference && !p->subs[SUB_REAL].inthreeway) {
01997       if (useslavenative)
01998          conf_add(p, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(slave));
01999       else {
02000          conf_add(p, &p->subs[SUB_REAL], SUB_REAL, 0);
02001          needconf++;
02002       }
02003    }
02004    /* If we have a master, add ourselves to his conference */
02005    if (p->master) {
02006       if (isslavenative(p->master, NULL)) {
02007          conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p->master));
02008       } else {
02009          conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, 0);
02010       }
02011    }
02012    if (!needconf) {
02013       /* Nobody is left (or should be left) in our conference.
02014          Kill it. */
02015       p->confno = -1;
02016    }
02017    ast_debug(1, "Updated conferencing on %d, with %d conference users\n", p->channel, needconf);
02018    return 0;
02019 }
02020 
02021 static void dahdi_enable_ec(struct dahdi_pvt *p)
02022 {
02023    int x;
02024    int res;
02025    if (!p)
02026       return;
02027    if (p->echocanon) {
02028       ast_debug(1, "Echo cancellation already on\n");
02029       return;
02030    }
02031    if (p->digital) {
02032       ast_debug(1, "Echo cancellation isn't required on digital connection\n");
02033       return;
02034    }
02035    if (p->echocancel.head.tap_length) {
02036       if ((p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP) || (p->sig == SIG_PRI) || (p->sig == SIG_SS7)) {
02037          x = 1;
02038          res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &x);
02039          if (res)
02040             ast_log(LOG_WARNING, "Unable to enable audio mode on channel %d (%s)\n", p->channel, strerror(errno));
02041       }
02042       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL_PARAMS, &p->echocancel);
02043       if (res)  {
02044          ast_log(LOG_WARNING, "Unable to enable echo cancellation on channel %d (%s)\n", p->channel, strerror(errno));
02045       } else {
02046          p->echocanon = 1;
02047          ast_debug(1, "Enabled echo cancellation on channel %d\n", p->channel);
02048       }
02049    } else
02050       ast_debug(1, "No echo cancellation requested\n");
02051 }
02052 
02053 static void dahdi_train_ec(struct dahdi_pvt *p)
02054 {
02055    int x;
02056    int res;
02057    
02058    if (p && p->echocanon && p->echotraining) {
02059       x = p->echotraining;
02060       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOTRAIN, &x);
02061       if (res)
02062          ast_log(LOG_WARNING, "Unable to request echo training on channel %d: %s\n", p->channel, strerror(errno));
02063       else
02064          ast_debug(1, "Engaged echo training on channel %d\n", p->channel);
02065    } else {
02066       ast_debug(1, "No echo training requested\n");
02067    }
02068 }
02069 
02070 static void dahdi_disable_ec(struct dahdi_pvt *p)
02071 {
02072    int res;
02073 
02074    if (p->echocanon) {
02075       struct dahdi_echocanparams ecp = { .tap_length = 0 };
02076 
02077       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL_PARAMS, &ecp);
02078 
02079       if (res)
02080          ast_log(LOG_WARNING, "Unable to disable echo cancellation on channel %d: %s\n", p->channel, strerror(errno));
02081       else
02082          ast_debug(1, "Disabled echo cancellation on channel %d\n", p->channel);
02083    }
02084 
02085    p->echocanon = 0;
02086 }
02087 
02088 static void fill_txgain(struct dahdi_gains *g, float gain, int law)
02089 {
02090    int j;
02091    int k;
02092    float linear_gain = pow(10.0, gain / 20.0);
02093 
02094    switch (law) {
02095    case DAHDI_LAW_ALAW:
02096       for (j = 0; j < ARRAY_LEN(g->txgain); j++) {
02097          if (gain) {
02098             k = (int) (((float) AST_ALAW(j)) * linear_gain);
02099             if (k > 32767) k = 32767;
02100             if (k < -32767) k = -32767;
02101             g->txgain[j] = AST_LIN2A(k);
02102          } else {
02103             g->txgain[j] = j;
02104          }
02105       }
02106       break;
02107    case DAHDI_LAW_MULAW:
02108       for (j = 0; j < ARRAY_LEN(g->txgain); j++) {
02109          if (gain) {
02110             k = (int) (((float) AST_MULAW(j)) * linear_gain);
02111             if (k > 32767) k = 32767;
02112             if (k < -32767) k = -32767;
02113             g->txgain[j] = AST_LIN2MU(k);
02114          } else {
02115             g->txgain[j] = j;
02116          }
02117       }
02118       break;
02119    }
02120 }
02121 
02122 static void fill_rxgain(struct dahdi_gains *g, float gain, int law)
02123 {
02124    int j;
02125    int k;
02126    float linear_gain = pow(10.0, gain / 20.0);
02127 
02128    switch (law) {
02129    case DAHDI_LAW_ALAW:
02130       for (j = 0; j < ARRAY_LEN(g->rxgain); j++) {
02131          if (gain) {
02132             k = (int) (((float) AST_ALAW(j)) * linear_gain);
02133             if (k > 32767) k = 32767;
02134             if (k < -32767) k = -32767;
02135             g->rxgain[j] = AST_LIN2A(k);
02136          } else {
02137             g->rxgain[j] = j;
02138          }
02139       }
02140       break;
02141    case DAHDI_LAW_MULAW:
02142       for (j = 0; j < ARRAY_LEN(g->rxgain); j++) {
02143          if (gain) {
02144             k = (int) (((float) AST_MULAW(j)) * linear_gain);
02145             if (k > 32767) k = 32767;
02146             if (k < -32767) k = -32767;
02147             g->rxgain[j] = AST_LIN2MU(k);
02148          } else {
02149             g->rxgain[j] = j;
02150          }
02151       }
02152       break;
02153    }
02154 }
02155 
02156 static int set_actual_txgain(int fd, int chan, float gain, int law)
02157 {
02158    struct dahdi_gains g;
02159    int res;
02160 
02161    memset(&g, 0, sizeof(g));
02162    g.chan = chan;
02163    res = ioctl(fd, DAHDI_GETGAINS, &g);
02164    if (res) {
02165       ast_debug(1, "Failed to read gains: %s\n", strerror(errno));
02166       return res;
02167    }
02168 
02169    fill_txgain(&g, gain, law);
02170 
02171    return ioctl(fd, DAHDI_SETGAINS, &g);
02172 }
02173 
02174 static int set_actual_rxgain(int fd, int chan, float gain, int law)
02175 {
02176    struct dahdi_gains g;
02177    int res;
02178 
02179    memset(&g, 0, sizeof(g));
02180    g.chan = chan;
02181    res = ioctl(fd, DAHDI_GETGAINS, &g);
02182    if (res) {
02183       ast_debug(1, "Failed to read gains: %s\n", strerror(errno));
02184       return res;
02185    }
02186 
02187    fill_rxgain(&g, gain, law);
02188 
02189    return ioctl(fd, DAHDI_SETGAINS, &g);
02190 }
02191 
02192 static int set_actual_gain(int fd, int chan, float rxgain, float txgain, int law)
02193 {
02194    return set_actual_txgain(fd, chan, txgain, law) | set_actual_rxgain(fd, chan, rxgain, law);
02195 }
02196 
02197 static int bump_gains(struct dahdi_pvt *p)
02198 {
02199    int res;
02200 
02201    /* Bump receive gain by value stored in cid_rxgain */
02202    res = set_actual_gain(p->subs[SUB_REAL].dfd, 0, p->rxgain + p->cid_rxgain, p->txgain, p->law);
02203    if (res) {
02204       ast_log(LOG_WARNING, "Unable to bump gain: %s\n", strerror(errno));
02205       return -1;
02206    }
02207 
02208    return 0;
02209 }
02210 
02211 static int restore_gains(struct dahdi_pvt *p)
02212 {
02213    int res;
02214 
02215    res = set_actual_gain(p->subs[SUB_REAL].dfd, 0, p->rxgain, p->txgain, p->law);
02216    if (res) {
02217       ast_log(LOG_WARNING, "Unable to restore gains: %s\n", strerror(errno));
02218       return -1;
02219    }
02220 
02221    return 0;
02222 }
02223 
02224 static inline int dahdi_set_hook(int fd, int hs)
02225 {
02226    int x, res;
02227 
02228    x = hs;
02229    res = ioctl(fd, DAHDI_HOOK, &x);
02230 
02231    if (res < 0) {
02232       if (errno == EINPROGRESS)
02233          return 0;
02234       ast_log(LOG_WARNING, "DAHDI hook failed returned %d (trying %d): %s\n", res, hs, strerror(errno));
02235       /* will expectedly fail if phone is off hook during operation, such as during a restart */
02236    }
02237 
02238    return res;
02239 }
02240 
02241 static inline int dahdi_confmute(struct dahdi_pvt *p, int muted)
02242 {
02243    int x, y, res;
02244    x = muted;
02245    if ((p->sig == SIG_PRI) || (p->sig == SIG_SS7) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP)) {
02246       y = 1;
02247       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &y);
02248       if (res)
02249          ast_log(LOG_WARNING, "Unable to set audio mode on %d: %s\n", p->channel, strerror(errno));
02250    }
02251    res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_CONFMUTE, &x);
02252    if (res < 0)
02253       ast_log(LOG_WARNING, "DAHDI confmute(%d) failed on channel %d: %s\n", muted, p->channel, strerror(errno));
02254    return res;
02255 }
02256 
02257 static int save_conference(struct dahdi_pvt *p)
02258 {
02259    struct dahdi_confinfo c;
02260    int res;
02261    if (p->saveconf.confmode) {
02262       ast_log(LOG_WARNING, "Can't save conference -- already in use\n");
02263       return -1;
02264    }
02265    p->saveconf.chan = 0;
02266    res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GETCONF, &p->saveconf);
02267    if (res) {
02268       ast_log(LOG_WARNING, "Unable to get conference info: %s\n", strerror(errno));
02269       p->saveconf.confmode = 0;
02270       return -1;
02271    }
02272    memset(&c, 0, sizeof(c));
02273    c.confmode = DAHDI_CONF_NORMAL;
02274    res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &c);
02275    if (res) {
02276       ast_log(LOG_WARNING, "Unable to set conference info: %s\n", strerror(errno));
02277       return -1;
02278    }
02279    ast_debug(1, "Disabled conferencing\n");
02280    return 0;
02281 }
02282 
02283 /*!
02284  * \brief Send MWI state change
02285  *
02286  * \arg mailbox_full This is the mailbox associated with the FXO line that the
02287  *      MWI state has changed on.
02288  * \arg thereornot This argument should simply be set to 1 or 0, to indicate
02289  *      whether there are messages waiting or not.
02290  *
02291  *  \return nothing
02292  *
02293  * This function does two things:
02294  *
02295  * 1) It generates an internal Asterisk event notifying any other module that
02296  *    cares about MWI that the state of a mailbox has changed.
02297  *
02298  * 2) It runs the script specified by the mwimonitornotify option to allow
02299  *    some custom handling of the state change.
02300  */
02301 static void notify_message(char *mailbox_full, int thereornot)
02302 {
02303    char s[sizeof(mwimonitornotify) + 80];
02304    struct ast_event *event;
02305    char *mailbox, *context;
02306 
02307    /* Strip off @default */
02308    context = mailbox = ast_strdupa(mailbox_full);
02309    strsep(&context, "@");
02310    if (ast_strlen_zero(context))
02311       context = "default";
02312 
02313    if (!(event = ast_event_new(AST_EVENT_MWI,
02314          AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mailbox,
02315          AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, context,
02316          AST_EVENT_IE_NEWMSGS, AST_EVENT_IE_PLTYPE_UINT, thereornot,
02317          AST_EVENT_IE_OLDMSGS, AST_EVENT_IE_PLTYPE_UINT, thereornot,
02318          AST_EVENT_IE_END))) {
02319       return;
02320    }
02321 
02322    ast_event_queue_and_cache(event);
02323 
02324    if (!ast_strlen_zero(mailbox) && !ast_strlen_zero(mwimonitornotify)) {
02325       snprintf(s, sizeof(s), "%s %s %d", mwimonitornotify, mailbox, thereornot);
02326       ast_safe_system(s);
02327    }
02328 }
02329 
02330 static int restore_conference(struct dahdi_pvt *p)
02331 {
02332    int res;
02333    if (p->saveconf.confmode) {
02334       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &p->saveconf);
02335       p->saveconf.confmode = 0;
02336       if (res) {
02337          ast_log(LOG_WARNING, "Unable to restore conference info: %s\n", strerror(errno));
02338          return -1;
02339       }
02340    }
02341    ast_debug(1, "Restored conferencing\n");
02342    return 0;
02343 }
02344 
02345 static int send_callerid(struct dahdi_pvt *p);
02346 
02347 static int send_cwcidspill(struct dahdi_pvt *p)
02348 {
02349    p->callwaitcas = 0;
02350    p->cidcwexpire = 0;
02351    if (!(p->cidspill = ast_malloc(MAX_CALLERID_SIZE)))
02352       return -1;
02353    p->cidlen = ast_callerid_callwaiting_generate(p->cidspill, p->callwait_name, p->callwait_num, AST_LAW(p));
02354    /* Make sure we account for the end */
02355    p->cidlen += READ_SIZE * 4;
02356    p->cidpos = 0;
02357    send_callerid(p);
02358    ast_verb(3, "CPE supports Call Waiting Caller*ID.  Sending '%s/%s'\n", p->callwait_name, p->callwait_num);
02359    return 0;
02360 }
02361 
02362 static int has_voicemail(struct dahdi_pvt *p)
02363 {
02364    int new_msgs;
02365    struct ast_event *event;
02366    char *mailbox, *context;
02367 
02368    mailbox = context = ast_strdupa(p->mailbox);
02369    strsep(&context, "@");
02370    if (ast_strlen_zero(context))
02371       context = "default";
02372 
02373    event = ast_event_get_cached(AST_EVENT_MWI,
02374       AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mailbox,
02375       AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, context,
02376       AST_EVENT_IE_END);
02377 
02378    if (event) {
02379       new_msgs = ast_event_get_ie_uint(event, AST_EVENT_IE_NEWMSGS);
02380       ast_event_destroy(event);
02381    } else
02382       new_msgs = ast_app_has_voicemail(p->mailbox, NULL);
02383 
02384    return new_msgs;
02385 }
02386 
02387 static int send_callerid(struct dahdi_pvt *p)
02388 {
02389    /* Assumes spill in p->cidspill, p->cidlen in length and we're p->cidpos into it */
02390    int res;
02391    /* Take out of linear mode if necessary */
02392    if (p->subs[SUB_REAL].linear) {
02393       p->subs[SUB_REAL].linear = 0;
02394       dahdi_setlinear(p->subs[SUB_REAL].dfd, 0);
02395    }
02396    while (p->cidpos < p->cidlen) {
02397       res = write(p->subs[SUB_REAL].dfd, p->cidspill + p->cidpos, p->cidlen - p->cidpos);
02398       if (res < 0) {
02399          if (errno == EAGAIN)
02400             return 0;
02401          else {
02402             ast_log(LOG_WARNING, "write failed: %s\n", strerror(errno));
02403             return -1;
02404          }
02405       }
02406       if (!res)
02407          return 0;
02408       p->cidpos += res;
02409    }
02410    ast_free(p->cidspill);
02411    p->cidspill = NULL;
02412    if (p->callwaitcas) {
02413       /* Wait for CID/CW to expire */
02414       p->cidcwexpire = CIDCW_EXPIRE_SAMPLES;
02415    } else
02416       restore_conference(p);
02417    return 0;
02418 }
02419 
02420 static int dahdi_callwait(struct ast_channel *ast)
02421 {
02422    struct dahdi_pvt *p = ast->tech_pvt;
02423    p->callwaitingrepeat = CALLWAITING_REPEAT_SAMPLES;
02424    if (p->cidspill) {
02425       ast_log(LOG_WARNING, "Spill already exists?!?\n");
02426       ast_free(p->cidspill);
02427    }
02428    if (!(p->cidspill = ast_malloc(2400 /* SAS */ + 680 /* CAS */ + READ_SIZE * 4)))
02429       return -1;
02430    save_conference(p);
02431    /* Silence */
02432    memset(p->cidspill, 0x7f, 2400 + 600 + READ_SIZE * 4);
02433    if (!p->callwaitrings && p->callwaitingcallerid) {
02434       ast_gen_cas(p->cidspill, 1, 2400 + 680, AST_LAW(p));
02435       p->callwaitcas = 1;
02436       p->cidlen = 2400 + 680 + READ_SIZE * 4;
02437    } else {
02438       ast_gen_cas(p->cidspill, 1, 2400, AST_LAW(p));
02439       p->callwaitcas = 0;
02440       p->cidlen = 2400 + READ_SIZE * 4;
02441    }
02442    p->cidpos = 0;
02443    send_callerid(p);
02444    
02445    return 0;
02446 }
02447 
02448 #ifdef HAVE_SS7
02449 static unsigned char cid_pres2ss7pres(int cid_pres)
02450 {
02451     return (cid_pres >> 5) & 0x03;
02452 }
02453 
02454 static unsigned char cid_pres2ss7screen(int cid_pres)
02455 {
02456    return cid_pres & 0x03;
02457 }
02458 #endif
02459 
02460 static int dahdi_call(struct ast_channel *ast, char *rdest, int timeout)
02461 {
02462    struct dahdi_pvt *p = ast->tech_pvt;
02463    int x, res, idx,mysig;
02464    char *c, *n, *l;
02465 #ifdef HAVE_PRI
02466    char *s = NULL;
02467 #endif
02468    char dest[256]; /* must be same length as p->dialdest */
02469    ast_mutex_lock(&p->lock);
02470    ast_copy_string(dest, rdest, sizeof(dest));
02471    ast_copy_string(p->dialdest, rdest, sizeof(p->dialdest));
02472    if ((ast->_state == AST_STATE_BUSY)) {
02473       p->subs[SUB_REAL].needbusy = 1;
02474       ast_mutex_unlock(&p->lock);
02475       return 0;
02476    }
02477    if ((ast->_state != AST_STATE_DOWN) && (ast->_state != AST_STATE_RESERVED)) {
02478       ast_log(LOG_WARNING, "dahdi_call called on %s, neither down nor reserved\n", ast->name);
02479       ast_mutex_unlock(&p->lock);
02480       return -1;
02481    }
02482    p->dialednone = 0;
02483    if ((p->radio || (p->oprmode < 0)))  /* if a radio channel, up immediately */
02484    {
02485       /* Special pseudo -- automatically up */
02486       ast_setstate(ast, AST_STATE_UP); 
02487       ast_mutex_unlock(&p->lock);
02488       return 0;
02489    }
02490    x = DAHDI_FLUSH_READ | DAHDI_FLUSH_WRITE;
02491    res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_FLUSH, &x);
02492    if (res)
02493       ast_log(LOG_WARNING, "Unable to flush input on channel %d: %s\n", p->channel, strerror(errno));
02494    p->outgoing = 1;
02495 
02496    if (IS_DIGITAL(ast->transfercapability)){
02497       set_actual_gain(p->subs[SUB_REAL].dfd, 0, 0, 0, p->law);
02498    } else {
02499       set_actual_gain(p->subs[SUB_REAL].dfd, 0, p->rxgain, p->txgain, p->law);
02500    }  
02501 
02502    mysig = p->sig;
02503    if (p->outsigmod > -1)
02504       mysig = p->outsigmod;
02505 
02506    switch (mysig) {
02507    case SIG_FXOLS:
02508    case SIG_FXOGS:
02509    case SIG_FXOKS:
02510       if (p->owner == ast) {
02511          /* Normal ring, on hook */
02512          
02513          /* Don't send audio while on hook, until the call is answered */
02514          p->dialing = 1;
02515          if (p->use_callerid) {
02516             /* Generate the Caller-ID spill if desired */
02517             if (p->cidspill) {
02518                ast_log(LOG_WARNING, "cidspill already exists??\n");
02519                ast_free(p->cidspill);
02520             }
02521             p->callwaitcas = 0;
02522             if ((p->cidspill = ast_malloc(MAX_CALLERID_SIZE))) {
02523                p->cidlen = ast_callerid_generate(p->cidspill, ast->cid.cid_name, ast->cid.cid_num, AST_LAW(p));
02524                p->cidpos = 0;
02525                send_callerid(p);
02526             }
02527          }
02528          /* Choose proper cadence */
02529          if ((p->distinctivering > 0) && (p->distinctivering <= num_cadence)) {
02530             if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCADENCE, &cadences[p->distinctivering - 1]))
02531                ast_log(LOG_WARNING, "Unable to set distinctive ring cadence %d on '%s': %s\n", p->distinctivering, ast->name, strerror(errno));
02532             p->cidrings = cidrings[p->distinctivering - 1];
02533          } else {
02534             if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCADENCE, NULL))
02535                ast_log(LOG_WARNING, "Unable to reset default ring on '%s': %s\n", ast->name, strerror(errno));
02536             p->cidrings = p->sendcalleridafter;
02537          }
02538 
02539          /* nick@dccinc.com 4/3/03 mods to allow for deferred dialing */
02540          c = strchr(dest, '/');
02541          if (c)
02542             c++;
02543          if (c && (strlen(c) < p->stripmsd)) {
02544             ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd);
02545             c = NULL;
02546          }
02547          if (c) {
02548             p->dop.op = DAHDI_DIAL_OP_REPLACE;
02549             snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "Tw%s", c);
02550             ast_debug(1, "FXO: setup deferred dialstring: %s\n", c);
02551          } else {
02552             p->dop.dialstr[0] = '\0';
02553          }
02554          x = DAHDI_RING;
02555          if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x) && (errno != EINPROGRESS)) {
02556             ast_log(LOG_WARNING, "Unable to ring phone: %s\n", strerror(errno));
02557             ast_mutex_unlock(&p->lock);
02558             return -1;
02559          }
02560          p->dialing = 1;
02561       } else {
02562          /* Call waiting call */
02563          p->callwaitrings = 0;
02564          if (ast->cid.cid_num)
02565             ast_copy_string(p->callwait_num, ast->cid.cid_num, sizeof(p->callwait_num));
02566          else
02567             p->callwait_num[0] = '\0';
02568          if (ast->cid.cid_name)
02569             ast_copy_string(p->callwait_name, ast->cid.cid_name, sizeof(p->callwait_name));
02570          else
02571             p->callwait_name[0] = '\0';
02572          /* Call waiting tone instead */
02573          if (dahdi_callwait(ast)) {
02574             ast_mutex_unlock(&p->lock);
02575             return -1;
02576          }
02577          /* Make ring-back */
02578          if (tone_zone_play_tone(p->subs[SUB_CALLWAIT].dfd, DAHDI_TONE_RINGTONE))
02579             ast_log(LOG_WARNING, "Unable to generate call-wait ring-back on channel %s\n", ast->name);
02580             
02581       }
02582       n = ast->cid.cid_name;
02583       l = ast->cid.cid_num;
02584       if (l)
02585          ast_copy_string(p->lastcid_num, l, sizeof(p->lastcid_num));
02586       else
02587          p->lastcid_num[0] = '\0';
02588       if (n)
02589          ast_copy_string(p->lastcid_name, n, sizeof(p->lastcid_name));
02590       else
02591          p->lastcid_name[0] = '\0';
02592       ast_setstate(ast, AST_STATE_RINGING);
02593       idx = dahdi_get_index(ast, p, 0);
02594       if (idx > -1) {
02595          p->subs[idx].needringing = 1;
02596       }
02597       break;
02598    case SIG_FXSLS:
02599    case SIG_FXSGS:
02600    case SIG_FXSKS:
02601       if (p->answeronpolarityswitch || p->hanguponpolarityswitch) {
02602          ast_debug(1, "Ignore possible polarity reversal on line seizure\n");
02603          p->polaritydelaytv = ast_tvnow();
02604       }
02605       /* fall through */
02606    case SIG_EMWINK:
02607    case SIG_EM:
02608    case SIG_EM_E1:
02609    case SIG_FEATD:
02610    case SIG_FEATDMF:
02611    case SIG_E911:
02612    case SIG_FGC_CAMA:
02613    case SIG_FGC_CAMAMF:
02614    case SIG_FEATB:
02615    case SIG_SFWINK:
02616    case SIG_SF:
02617    case SIG_SF_FEATD:
02618    case SIG_SF_FEATDMF:
02619    case SIG_FEATDMF_TA:
02620    case SIG_SF_FEATB:
02621       c = strchr(dest, '/');
02622       if (c)
02623          c++;
02624       else
02625          c = "";
02626       if (strlen(c) < p->stripmsd) {
02627          ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd);
02628          ast_mutex_unlock(&p->lock);
02629          return -1;
02630       }
02631 #ifdef HAVE_PRI
02632       /* Start the trunk, if not GR-303 */
02633       if (!p->pri) {
02634 #endif
02635          x = DAHDI_START;
02636          res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
02637          if (res < 0) {
02638             if (errno != EINPROGRESS) {
02639                ast_log(LOG_WARNING, "Unable to start channel: %s\n", strerror(errno));
02640                ast_mutex_unlock(&p->lock);
02641                return -1;
02642             }
02643          }
02644 #ifdef HAVE_PRI
02645       }
02646 #endif
02647       ast_debug(1, "Dialing '%s'\n", c);
02648       p->dop.op = DAHDI_DIAL_OP_REPLACE;
02649 
02650       c += p->stripmsd;
02651 
02652       switch (mysig) {
02653       case SIG_FEATD:
02654          l = ast->cid.cid_num;
02655          if (l) 
02656             snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "T*%s*%s*", l, c);
02657          else
02658             snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "T**%s*", c);
02659          break;
02660       case SIG_FEATDMF:
02661          l = ast->cid.cid_num;
02662          if (l) 
02663             snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*00%s#*%s#", l, c);
02664          else
02665             snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*02#*%s#", c);
02666          break;
02667       case SIG_FEATDMF_TA:
02668       {
02669          const char *cic, *ozz;
02670 
02671          /* If you have to go through a Tandem Access point you need to use this */
02672          ozz = pbx_builtin_getvar_helper(p->owner, "FEATDMF_OZZ");
02673          if (!ozz)
02674             ozz = defaultozz;
02675          cic = pbx_builtin_getvar_helper(p->owner, "FEATDMF_CIC");
02676          if (!cic)
02677             cic = defaultcic;
02678          if (!ozz || !cic) {
02679             ast_log(LOG_WARNING, "Unable to dial channel of type feature group D MF tandem access without CIC or OZZ set\n");
02680             ast_mutex_unlock(&p->lock);
02681             return -1;
02682          }
02683          snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*%s%s#", ozz, cic);
02684          snprintf(p->finaldial, sizeof(p->finaldial), "M*%s#", c);
02685          p->whichwink = 0;
02686       }
02687          break;
02688       case SIG_E911:
02689          ast_copy_string(p->dop.dialstr, "M*911#", sizeof(p->dop.dialstr));
02690          break;
02691       case SIG_FGC_CAMA:
02692          snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "P%s", c);
02693          break;
02694       case SIG_FGC_CAMAMF:
02695       case SIG_FEATB:
02696          snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*%s#", c);
02697          break;
02698       default:
02699          if (p->pulse)
02700             snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "P%sw", c);
02701          else
02702             snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "T%sw", c);
02703          break;
02704       }
02705 
02706       if (p->echotraining && (strlen(p->dop.dialstr) > 4)) {
02707          memset(p->echorest, 'w', sizeof(p->echorest) - 1);
02708          strcpy(p->echorest + (p->echotraining / 400) + 1, p->dop.dialstr + strlen(p->dop.dialstr) - 2);
02709          p->echorest[sizeof(p->echorest) - 1] = '\0';
02710          p->echobreak = 1;
02711          p->dop.dialstr[strlen(p->dop.dialstr)-2] = '\0';
02712       } else
02713          p->echobreak = 0;
02714       if (!res) {
02715          if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop)) {
02716             int saveerr = errno;
02717 
02718             x = DAHDI_ONHOOK;
02719             ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
02720             ast_log(LOG_WARNING, "Dialing failed on channel %d: %s\n", p->channel, strerror(saveerr));
02721             ast_mutex_unlock(&p->lock);
02722             return -1;
02723          }
02724       } else
02725          ast_debug(1, "Deferring dialing...\n");
02726 
02727       p->dialing = 1;
02728       if (ast_strlen_zero(c))
02729          p->dialednone = 1;
02730       ast_setstate(ast, AST_STATE_DIALING);
02731       break;
02732    case 0:
02733       /* Special pseudo -- automatically up*/
02734       ast_setstate(ast, AST_STATE_UP);
02735       break;      
02736    case SIG_PRI:
02737    case SIG_BRI:
02738    case SIG_BRI_PTMP:
02739    case SIG_SS7:
02740       /* We'll get it in a moment -- but use dialdest to store pre-setup_ack digits */
02741       p->dialdest[0] = '\0';
02742       p->dialing = 1;
02743       break;
02744    default:
02745       ast_debug(1, "not yet implemented\n");
02746       ast_mutex_unlock(&p->lock);
02747       return -1;
02748    }
02749 #ifdef HAVE_SS7
02750    if (p->ss7) {
02751       char ss7_called_nai;
02752       int called_nai_strip;
02753       char ss7_calling_nai;
02754       int calling_nai_strip;
02755       const char *charge_str = NULL;
02756       const char *gen_address = NULL;
02757       const char *gen_digits = NULL;
02758       const char *gen_dig_type = NULL;
02759       const char *gen_dig_scheme = NULL;
02760       const char *gen_name = NULL;
02761       const char *jip_digits = NULL;
02762       const char *lspi_ident = NULL;
02763       const char *rlt_flag = NULL;
02764       const char *call_ref_id = NULL;
02765       const char *call_ref_pc = NULL;
02766       const char *send_far = NULL;
02767 
02768       c = strchr(dest, '/');
02769       if (c) {
02770          c++;
02771       } else {
02772          c = "";
02773       }
02774       if (strlen(c) < p->stripmsd) {
02775          ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd);
02776          ast_mutex_unlock(&p->lock);
02777          return -1;
02778       }
02779 
02780       if (!p->hidecallerid) {
02781          l = ast->cid.cid_num;
02782       } else {
02783          l = NULL;
02784       }
02785 
02786       if (ss7_grab(p, p->ss7)) {
02787          ast_log(LOG_WARNING, "Failed to grab SS7!\n");
02788          ast_mutex_unlock(&p->lock);
02789          return -1;
02790       }
02791       p->digital = IS_DIGITAL(ast->transfercapability);
02792       p->ss7call = isup_new_call(p->ss7->ss7);
02793 
02794       if (!p->ss7call) {
02795          ss7_rel(p->ss7);
02796          ast_mutex_unlock(&p->lock);
02797          ast_log(LOG_ERROR, "Unable to allocate new SS7 call!\n");
02798          return -1;
02799       }
02800 
02801       called_nai_strip = 0;
02802       ss7_called_nai = p->ss7->called_nai;
02803       if (ss7_called_nai == SS7_NAI_DYNAMIC) { /* compute dynamically */
02804          if (strncmp(c + p->stripmsd, p->ss7->internationalprefix, strlen(p->ss7->internationalprefix)) == 0) {
02805             called_nai_strip = strlen(p->ss7->internationalprefix);
02806             ss7_called_nai = SS7_NAI_INTERNATIONAL;
02807          } else if (strncmp(c + p->stripmsd, p->ss7->nationalprefix, strlen(p->ss7->nationalprefix)) == 0) {
02808             called_nai_strip = strlen(p->ss7->nationalprefix);
02809             ss7_called_nai = SS7_NAI_NATIONAL;
02810          } else {
02811             ss7_called_nai = SS7_NAI_SUBSCRIBER;
02812          }
02813       }
02814       isup_set_called(p->ss7call, c + p->stripmsd + called_nai_strip, ss7_called_nai, p->ss7->ss7);
02815 
02816       calling_nai_strip = 0;
02817       ss7_calling_nai = p->ss7->calling_nai;
02818       if ((l != NULL) && (ss7_calling_nai == SS7_NAI_DYNAMIC)) { /* compute dynamically */
02819          if (strncmp(l, p->ss7->internationalprefix, strlen(p->ss7->internationalprefix)) == 0) {
02820             calling_nai_strip = strlen(p->ss7->internationalprefix);
02821             ss7_calling_nai = SS7_NAI_INTERNATIONAL;
02822          } else if (strncmp(l, p->ss7->nationalprefix, strlen(p->ss7->nationalprefix)) == 0) {
02823             calling_nai_strip = strlen(p->ss7->nationalprefix);
02824             ss7_calling_nai = SS7_NAI_NATIONAL;
02825          } else {
02826             ss7_calling_nai = SS7_NAI_SUBSCRIBER;
02827          }
02828       }
02829       isup_set_calling(p->ss7call, l ? (l + calling_nai_strip) : NULL, ss7_calling_nai,
02830          p->use_callingpres ? cid_pres2ss7pres(ast->cid.cid_pres) : (l ? SS7_PRESENTATION_ALLOWED : SS7_PRESENTATION_RESTRICTED),
02831          p->use_callingpres ? cid_pres2ss7screen(ast->cid.cid_pres) : SS7_SCREENING_USER_PROVIDED );
02832 
02833       isup_set_oli(p->ss7call, ast->cid.cid_ani2);
02834       isup_init_call(p->ss7->ss7, p->ss7call, p->cic, p->dpc);
02835 
02836       ast_channel_lock(ast);
02837       /* Set the charge number if it is set */
02838       charge_str = pbx_builtin_getvar_helper(ast, "SS7_CHARGE_NUMBER");
02839       if (charge_str)
02840          isup_set_charge(p->ss7call, charge_str, SS7_ANI_CALLING_PARTY_SUB_NUMBER, 0x10);
02841       
02842       gen_address = pbx_builtin_getvar_helper(ast, "SS7_GENERIC_ADDRESS");
02843       if (gen_address)
02844          isup_set_gen_address(p->ss7call, gen_address, p->gen_add_nai,p->gen_add_pres_ind, p->gen_add_num_plan,p->gen_add_type); /* need to add some types here for NAI,PRES,TYPE */
02845       
02846       gen_digits = pbx_builtin_getvar_helper(ast, "SS7_GENERIC_DIGITS");
02847       gen_dig_type = pbx_builtin_getvar_helper(ast, "SS7_GENERIC_DIGTYPE");
02848       gen_dig_scheme = pbx_builtin_getvar_helper(ast, "SS7_GENERIC_DIGSCHEME");
02849       if (gen_digits)
02850          isup_set_gen_digits(p->ss7call, gen_digits, atoi(gen_dig_type), atoi(gen_dig_scheme)); 
02851       
02852       gen_name = pbx_builtin_getvar_helper(ast, "SS7_GENERIC_NAME");
02853       if (gen_name)
02854          isup_set_generic_name(p->ss7call, gen_name, GEN_NAME_TYPE_CALLING_NAME, GEN_NAME_AVAIL_AVAILABLE, GEN_NAME_PRES_ALLOWED);
02855 
02856       jip_digits = pbx_builtin_getvar_helper(ast, "SS7_JIP");
02857       if (jip_digits)
02858          isup_set_jip_digits(p->ss7call, jip_digits);
02859       
02860       lspi_ident = pbx_builtin_getvar_helper(ast, "SS7_LSPI_IDENT");
02861       if (lspi_ident)
02862          isup_set_lspi(p->ss7call, lspi_ident, 0x18, 0x7, 0x00); 
02863       
02864       rlt_flag = pbx_builtin_getvar_helper(ast, "SS7_RLT_ON");
02865       if ((rlt_flag) && ((strncmp("NO", rlt_flag, strlen(rlt_flag))) != 0 )) {
02866          isup_set_lspi(p->ss7call, rlt_flag, 0x18, 0x7, 0x00); /* Setting for Nortel DMS-250/500 */
02867       }
02868       
02869       call_ref_id = pbx_builtin_getvar_helper(ast, "SS7_CALLREF_IDENT");
02870       call_ref_pc = pbx_builtin_getvar_helper(ast, "SS7_CALLREF_PC");
02871       if (call_ref_id && call_ref_pc) {
02872          isup_set_callref(p->ss7call, atoi(call_ref_id),
02873                 call_ref_pc ? atoi(call_ref_pc) : 0);
02874       }
02875       
02876       send_far = pbx_builtin_getvar_helper(ast, "SS7_SEND_FAR");
02877       if ((send_far) && ((strncmp("NO", send_far, strlen(send_far))) != 0 ))
02878          (isup_far(p->ss7->ss7, p->ss7call));
02879       
02880       ast_channel_unlock(ast);
02881 
02882       isup_iam(p->ss7->ss7, p->ss7call);
02883       ast_setstate(ast, AST_STATE_DIALING);
02884       ss7_rel(p->ss7);
02885    }
02886 #endif /* HAVE_SS7 */
02887 #ifdef HAVE_PRI
02888    if (p->pri) {
02889       struct pri_sr *sr;
02890 #ifdef SUPPORT_USERUSER
02891       const char *useruser;
02892 #endif
02893       int pridialplan;
02894       int dp_strip;
02895       int prilocaldialplan;
02896       int ldp_strip;
02897       int exclusive;
02898       const char *rr_str;
02899       int redirect_reason;
02900 
02901       c = strchr(dest, '/');
02902       if (c) {
02903          c++;
02904       } else {
02905          c = "";
02906       }
02907 
02908       l = NULL;
02909       n = NULL;
02910       if (!p->hidecallerid) {
02911          l = ast->cid.cid_num;
02912          if (!p->hidecalleridname) {
02913             n = ast->cid.cid_name;
02914          }
02915       }
02916 
02917       if (strlen(c) < p->stripmsd) {
02918          ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd);
02919          ast_mutex_unlock(&p->lock);
02920          return -1;
02921       }
02922       if (mysig != SIG_FXSKS) {
02923          p->dop.op = DAHDI_DIAL_OP_REPLACE;
02924          s = strchr(c + p->stripmsd, 'w');
02925          if (s) {
02926             if (strlen(s) > 1)
02927                snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "T%s", s);
02928             else
02929                p->dop.dialstr[0] = '\0';
02930             *s = '\0';
02931          } else {
02932             p->dop.dialstr[0] = '\0';
02933          }
02934       }
02935       if (pri_grab(p, p->pri)) {
02936          ast_log(LOG_WARNING, "Failed to grab PRI!\n");
02937          ast_mutex_unlock(&p->lock);
02938          return -1;
02939       }
02940       if (!(p->call = pri_new_call(p->pri->pri))) {
02941          ast_log(LOG_WARNING, "Unable to create call on channel %d\n", p->channel);
02942          pri_rel(p->pri);
02943          ast_mutex_unlock(&p->lock);
02944          return -1;
02945       }
02946       if (!(sr = pri_sr_new())) {
02947          ast_log(LOG_WARNING, "Failed to allocate setup request channel %d\n", p->channel);
02948          pri_rel(p->pri);
02949          ast_mutex_unlock(&p->lock);
02950       }
02951       if (p->bearer || (mysig == SIG_FXSKS)) {
02952          if (p->bearer) {
02953             ast_debug(1, "Oooh, I have a bearer on %d (%d:%d)\n", PVT_TO_CHANNEL(p->bearer), p->bearer->logicalspan, p->bearer->channel);
02954             p->bearer->call = p->call;
02955          } else
02956             ast_debug(1, "I'm being setup with no bearer right now...\n");
02957 
02958          pri_set_crv(p->pri->pri, p->call, p->channel, 0);
02959       }
02960       p->digital = IS_DIGITAL(ast->transfercapability);
02961 
02962       /* Should the picked channel be used exclusively? */
02963       if (p->priexclusive || p->pri->nodetype == PRI_NETWORK) {
02964          exclusive = 1;
02965       } else {
02966          exclusive = 0;
02967       }
02968       
02969       pri_sr_set_channel(sr, p->bearer ? PVT_TO_CHANNEL(p->bearer) : PVT_TO_CHANNEL(p), exclusive, 1);
02970       pri_sr_set_bearer(sr, p->digital ? PRI_TRANS_CAP_DIGITAL : ast->transfercapability, 
02971                (p->digital ? -1 : 
02972                   ((p->law == DAHDI_LAW_ALAW) ? PRI_LAYER_1_ALAW : PRI_LAYER_1_ULAW)));
02973       if (p->pri->facilityenable)
02974          pri_facility_enable(p->pri->pri);
02975 
02976       ast_verb(3, "Requested transfer capability: 0x%.2x - %s\n", ast->transfercapability, ast_transfercapability2str(ast->transfercapability));
02977       dp_strip = 0;
02978       pridialplan = p->pri->dialplan - 1;
02979       if (pridialplan == -2 || pridialplan == -3) { /* compute dynamically */
02980          if (strncmp(c + p->stripmsd, p->pri->internationalprefix, strlen(p->pri->internationalprefix)) == 0) {
02981             if (pridialplan == -2) {
02982                dp_strip = strlen(p->pri->internationalprefix);
02983             }
02984             pridialplan = PRI_INTERNATIONAL_ISDN;
02985          } else if (strncmp(c + p->stripmsd, p->pri->nationalprefix, strlen(p->pri->nationalprefix)) == 0) {
02986             if (pridialplan == -2) {
02987                dp_strip = strlen(p->pri->nationalprefix);
02988             }
02989             pridialplan = PRI_NATIONAL_ISDN;
02990          } else {
02991             pridialplan = PRI_LOCAL_ISDN;
02992          }
02993       }
02994       while (c[p->stripmsd] > '9' && c[p->stripmsd] != '*' && c[p->stripmsd] != '#') {
02995          switch (c[p->stripmsd]) {
02996          case 'U':
02997             pridialplan = (PRI_TON_UNKNOWN << 4) | (pridialplan & 0xf);
02998             break;
02999          case 'I':
03000             pridialplan = (PRI_TON_INTERNATIONAL << 4) | (pridialplan & 0xf);
03001             break;
03002          case 'N':
03003             pridialplan = (PRI_TON_NATIONAL << 4) | (pridialplan & 0xf);
03004             break;
03005          case 'L':
03006             pridialplan = (PRI_TON_NET_SPECIFIC << 4) | (pridialplan & 0xf);
03007             break;
03008          case 'S':
03009             pridialplan = (PRI_TON_SUBSCRIBER << 4) | (pridialplan & 0xf);
03010             break;
03011          case 'V':
03012             pridialplan = (PRI_TON_ABBREVIATED << 4) | (pridialplan & 0xf);
03013             break;
03014          case 'R':
03015             pridialplan = (PRI_TON_RESERVED << 4) | (pridialplan & 0xf);
03016             break;
03017          case 'u':
03018             pridialplan = PRI_NPI_UNKNOWN | (pridialplan & 0xf0);
03019             break;
03020          case 'e':
03021             pridialplan = PRI_NPI_E163_E164 | (pridialplan & 0xf0);
03022             break;
03023          case 'x':
03024             pridialplan = PRI_NPI_X121 | (pridialplan & 0xf0);
03025             break;
03026          case 'f':
03027             pridialplan = PRI_NPI_F69 | (pridialplan & 0xf0);
03028             break;
03029          case 'n':
03030             pridialplan = PRI_NPI_NATIONAL | (pridialplan & 0xf0);
03031             break;
03032          case 'p':
03033             pridialplan = PRI_NPI_PRIVATE | (pridialplan & 0xf0);
03034             break;
03035          case 'r':
03036             pridialplan = PRI_NPI_RESERVED | (pridialplan & 0xf0);
03037             break;
03038          default:
03039             if (isalpha(c[p->stripmsd])) {
03040                ast_log(LOG_WARNING, "Unrecognized pridialplan %s modifier: %c\n",
03041                   c[p->stripmsd] > 'Z' ? "NPI" : "TON", c[p->stripmsd]);
03042             }
03043             break;
03044          }
03045          c++;
03046       }
03047       pri_sr_set_called(sr, c + p->stripmsd + dp_strip, pridialplan, s ? 1 : 0);
03048 
03049       ldp_strip = 0;
03050       prilocaldialplan = p->pri->localdialplan - 1;
03051       if ((l != NULL) && (prilocaldialplan == -2 || prilocaldialplan == -3)) { /* compute dynamically */
03052          if (strncmp(l, p->pri->internationalprefix, strlen(p->pri->internationalprefix)) == 0) {
03053             if (prilocaldialplan == -2) {
03054                ldp_strip = strlen(p->pri->internationalprefix);
03055             }
03056             prilocaldialplan = PRI_INTERNATIONAL_ISDN;
03057          } else if (strncmp(l, p->pri->nationalprefix, strlen(p->pri->nationalprefix)) == 0) {
03058             if (prilocaldialplan == -2) {
03059                ldp_strip = strlen(p->pri->nationalprefix);
03060             }
03061             prilocaldialplan = PRI_NATIONAL_ISDN;
03062          } else {
03063             prilocaldialplan = PRI_LOCAL_ISDN;
03064          }
03065       }
03066       if (l != NULL) {
03067          while (*l > '9' && *l != '*' && *l != '#') {
03068             switch (*l) {
03069             case 'U':
03070                prilocaldialplan = (PRI_TON_UNKNOWN << 4) | (prilocaldialplan & 0xf);
03071                break;
03072             case 'I':
03073                prilocaldialplan = (PRI_TON_INTERNATIONAL << 4) | (prilocaldialplan & 0xf);
03074                break;
03075             case 'N':
03076                prilocaldialplan = (PRI_TON_NATIONAL << 4) | (prilocaldialplan & 0xf);
03077                break;
03078             case 'L':
03079                prilocaldialplan = (PRI_TON_NET_SPECIFIC << 4) | (prilocaldialplan & 0xf);
03080                break;
03081             case 'S':
03082                prilocaldialplan = (PRI_TON_SUBSCRIBER << 4) | (prilocaldialplan & 0xf);
03083                break;
03084             case 'V':
03085                prilocaldialplan = (PRI_TON_ABBREVIATED << 4) | (prilocaldialplan & 0xf);
03086                break;
03087             case 'R':
03088                prilocaldialplan = (PRI_TON_RESERVED << 4) | (prilocaldialplan & 0xf);
03089                break;
03090             case 'u':
03091                prilocaldialplan = PRI_NPI_UNKNOWN | (prilocaldialplan & 0xf0);
03092                break;
03093             case 'e':
03094                prilocaldialplan = PRI_NPI_E163_E164 | (prilocaldialplan & 0xf0);
03095                break;
03096             case 'x':
03097                prilocaldialplan = PRI_NPI_X121 | (prilocaldialplan & 0xf0);
03098                break;
03099             case 'f':
03100                prilocaldialplan = PRI_NPI_F69 | (prilocaldialplan & 0xf0);
03101                break;
03102             case 'n':
03103                prilocaldialplan = PRI_NPI_NATIONAL | (prilocaldialplan & 0xf0);
03104                break;
03105             case 'p':
03106                prilocaldialplan = PRI_NPI_PRIVATE | (prilocaldialplan & 0xf0);
03107                break;
03108             case 'r':
03109                prilocaldialplan = PRI_NPI_RESERVED | (prilocaldialplan & 0xf0);
03110                break;
03111             default:
03112                if (isalpha(*l)) {
03113                   ast_log(LOG_WARNING,
03114                      "Unrecognized prilocaldialplan %s modifier: %c\n",
03115                      *l > 'Z' ? "NPI" : "TON", *l);
03116                }
03117                break;
03118             }
03119             l++;
03120          }
03121       }
03122       pri_sr_set_caller(sr, l ? (l + ldp_strip) : NULL, n, prilocaldialplan,
03123          p->use_callingpres ? ast->cid.cid_pres : (l ? PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN : PRES_NUMBER_NOT_AVAILABLE));
03124       if ((rr_str = pbx_builtin_getvar_helper(ast, "PRIREDIRECTREASON"))) {
03125          if (!strcasecmp(rr_str, "UNKNOWN"))
03126             redirect_reason = 0;
03127          else if (!strcasecmp(rr_str, "BUSY"))
03128             redirect_reason = 1;
03129          else if (!strcasecmp(rr_str, "NO_REPLY") || !strcasecmp(rr_str, "NOANSWER"))
03130          /* the NOANSWER is to match diversion-reason from chan_sip, (which never reads PRIREDIRECTREASON) */
03131             redirect_reason = 2;
03132          else if (!strcasecmp(rr_str, "UNCONDITIONAL"))
03133             redirect_reason = 15;
03134          else
03135             redirect_reason = PRI_REDIR_UNCONDITIONAL;
03136       } else
03137          redirect_reason = PRI_REDIR_UNCONDITIONAL;
03138       pri_sr_set_redirecting(sr, ast->cid.cid_rdnis, p->pri->localdialplan - 1, PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN, redirect_reason);
03139 
03140 #ifdef SUPPORT_USERUSER
03141       /* User-user info */
03142       useruser = pbx_builtin_getvar_helper(p->owner, "USERUSERINFO");
03143 
03144       if (useruser)
03145          pri_sr_set_useruser(sr, useruser);
03146 #endif
03147 
03148       if (pri_setup(p->pri->pri, p->call, sr)) {
03149          ast_log(LOG_WARNING, "Unable to setup call to %s (using %s)\n", 
03150             c + p->stripmsd + dp_strip, dialplan2str(p->pri->dialplan));
03151          pri_rel(p->pri);
03152          ast_mutex_unlock(&p->lock);
03153          pri_sr_free(sr);
03154          return -1;
03155       }
03156       pri_sr_free(sr);
03157       ast_setstate(ast, AST_STATE_DIALING);
03158       pri_rel(p->pri);
03159    }
03160 #endif      
03161    ast_mutex_unlock(&p->lock);
03162    return 0;
03163 }
03164 
03165 static void destroy_dahdi_pvt(struct dahdi_pvt **pvt)
03166 {
03167    struct dahdi_pvt *p = *pvt;
03168    /* Remove channel from the list */
03169    if (p->prev)
03170       p->prev->next = p->next;
03171    if (p->next)
03172       p->next->prev = p->prev;
03173    if (p->use_smdi)
03174       ast_smdi_interface_unref(p->smdi_iface);
03175    if (p->mwi_event_sub)
03176       ast_event_unsubscribe(p->mwi_event_sub);
03177    if (p->vars) {
03178       ast_variables_destroy(p->vars);
03179    }
03180    ast_mutex_destroy(&p->lock);
03181    dahdi_close_sub(p, SUB_REAL);
03182    if (p->owner)
03183       p->owner->tech_pvt = NULL;
03184    free(p);
03185    *pvt = NULL;
03186 }
03187 
03188 static int destroy_channel(struct dahdi_pvt *prev, struct dahdi_pvt *cur, int now)
03189 {
03190    int owned = 0;
03191    int i = 0;
03192 
03193    if (!now) {
03194       if (cur->owner) {
03195          owned = 1;
03196       }
03197 
03198       for (i = 0; i < 3; i++) {
03199          if (cur->subs[i].owner) {
03200             owned = 1;
03201          }
03202       }
03203       if (!owned) {
03204          if (prev) {
03205             prev->next = cur->next;
03206             if (prev->next)
03207                prev->next->prev = prev;
03208             else
03209                ifend = prev;
03210          } else {
03211             iflist = cur->next;
03212             if (iflist)
03213                iflist->prev = NULL;
03214             else
03215                ifend = NULL;
03216          }
03217          destroy_dahdi_pvt(&cur);
03218       }
03219    } else {
03220       if (prev) {
03221          prev->next = cur->next;
03222          if (prev->next)
03223             prev->next->prev = prev;
03224          else
03225             ifend = prev;
03226       } else {
03227          iflist = cur->next;
03228          if (iflist)
03229             iflist->prev = NULL;
03230          else
03231             ifend = NULL;
03232       }
03233       destroy_dahdi_pvt(&cur);
03234    }
03235    return 0;
03236 }
03237 
03238 static void destroy_all_channels(void)
03239 {
03240    int x;
03241    struct dahdi_pvt *p, *pl;
03242 
03243    while (num_restart_pending) {
03244       usleep(1);
03245    }
03246 
03247    ast_mutex_lock(&iflock);
03248    /* Destroy all the interfaces and free their memory */
03249    p = iflist;
03250    while (p) {
03251       /* Free any callerid */
03252       if (p->cidspill)
03253          ast_free(p->cidspill);
03254       pl = p;
03255       p = p->next;
03256       x = pl->channel;
03257       /* Free associated memory */
03258       if (pl)
03259          destroy_dahdi_pvt(&pl);
03260       if (option_verbose > 2) 
03261          ast_verbose(VERBOSE_PREFIX_2 "Unregistered channel %d\n", x);
03262    }
03263    iflist = NULL;
03264    ifcount = 0;
03265    ast_mutex_unlock(&iflock);
03266 }
03267 
03268 #ifdef HAVE_PRI
03269 static char *dahdi_send_keypad_facility_app = "DAHDISendKeypadFacility";
03270 
03271 static char *dahdi_send_keypad_facility_synopsis = "Send digits out of band over a PRI";
03272 
03273 static char *dahdi_send_keypad_facility_descrip = 
03274 "  DAHDISendKeypadFacility(): This application will send the given string of digits in a Keypad Facility\n"
03275 "  IE over the current channel.\n";
03276 
03277 static int dahdi_send_keypad_facility_exec(struct ast_channel *chan, void *data)
03278 {
03279    /* Data will be our digit string */
03280    struct dahdi_pvt *p;
03281    char *digits = (char *) data;
03282 
03283    if (ast_strlen_zero(digits)) {
03284       ast_debug(1, "No digit string sent to application!\n");
03285       return -1;
03286    }
03287 
03288    p = (struct dahdi_pvt *)chan->tech_pvt;
03289 
03290    if (!p) {
03291       ast_debug(1, "Unable to find technology private\n");
03292       return -1;
03293    }
03294 
03295    ast_mutex_lock(&p->lock);
03296 
03297    if (!p->pri || !p->call) {
03298       ast_debug(1, "Unable to find pri or call on channel!\n");
03299       ast_mutex_unlock(&p->lock);
03300       return -1;
03301    }
03302 
03303    if (!pri_grab(p, p->pri)) {
03304       pri_keypad_facility(p->pri->pri, p->call, digits);
03305       pri_rel(p->pri);
03306    } else {
03307       ast_debug(1, "Unable to grab pri to send keypad facility!\n");
03308       ast_mutex_unlock(&p->lock);
03309       return -1;
03310    }
03311 
03312    ast_mutex_unlock(&p->lock);
03313 
03314    return 0;
03315 }
03316 
03317 static int pri_is_up(struct dahdi_pri *pri)
03318 {
03319    int x;
03320    for (x = 0; x < NUM_DCHANS; x++) {
03321       if (pri->dchanavail[x] == DCHAN_AVAILABLE)
03322          return 1;
03323    }
03324    return 0;
03325 }
03326 
03327 static int pri_assign_bearer(struct dahdi_pvt *crv, struct dahdi_pri *pri, struct dahdi_pvt *bearer)
03328 {
03329    bearer->owner = &inuse;
03330    bearer->realcall = crv;
03331    crv->subs[SUB_REAL].dfd = bearer->subs[SUB_REAL].dfd;
03332    if (crv->subs[SUB_REAL].owner)
03333       ast_channel_set_fd(crv->subs[SUB_REAL].owner, 0, crv->subs[SUB_REAL].dfd);
03334    crv->bearer = bearer;
03335    crv->call = bearer->call;
03336    crv->pri = pri;
03337    return 0;
03338 }
03339 
03340 static char *pri_order(int level)
03341 {
03342    switch (level) {
03343    case 0:
03344       return "Primary";
03345    case 1:
03346       return "Secondary";
03347    case 2:
03348       return "Tertiary";
03349    case 3:
03350       return "Quaternary";
03351    default:
03352       return "<Unknown>";
03353    }     
03354 }
03355 
03356 /* Returns fd of the active dchan */
03357 static int pri_active_dchan_fd(struct dahdi_pri *pri)
03358 {
03359    int x = -1;
03360 
03361    for (x = 0; x < NUM_DCHANS; x++) {
03362       if ((pri->dchans[x] == pri->pri))
03363          break;
03364    }
03365 
03366    return pri->fds[x];
03367 }
03368 
03369 static int pri_find_dchan(struct dahdi_pri *pri)
03370 {
03371    int oldslot = -1;
03372    struct pri *old;
03373    int newslot = -1;
03374    int x;
03375    old = pri->pri;
03376    for (x = 0; x < NUM_DCHANS; x++) {
03377       if ((pri->dchanavail[x] == DCHAN_AVAILABLE) && (newslot < 0))
03378          newslot = x;
03379       if (pri->dchans[x] == old) {
03380          oldslot = x;
03381       }
03382    }
03383    if (newslot < 0) {
03384       newslot = 0;
03385       ast_log(LOG_WARNING, "No D-channels available!  Using Primary channel %d as D-channel anyway!\n",
03386          pri->dchannels[newslot]);
03387    }
03388    if (old && (oldslot != newslot))
03389       ast_log(LOG_NOTICE, "Switching from from d-channel %d to channel %d!\n",
03390          pri->dchannels[oldslot], pri->dchannels[newslot]);
03391    pri->pri = pri->dchans[newslot];
03392    return 0;
03393 }
03394 #endif
03395 
03396 static int dahdi_hangup(struct ast_channel *ast)
03397 {
03398    int res;
03399    int idx,x, law;
03400    /*static int restore_gains(struct dahdi_pvt *p);*/
03401    struct dahdi_pvt *p = ast->tech_pvt;
03402    struct dahdi_pvt *tmp = NULL;
03403    struct dahdi_pvt *prev = NULL;
03404    struct dahdi_params par;
03405 
03406    ast_debug(1, "dahdi_hangup(%s)\n", ast->name);
03407    if (!ast->tech_pvt) {
03408       ast_log(LOG_WARNING, "Asked to hangup channel not connected\n");
03409       return 0;
03410    }
03411    
03412    ast_mutex_lock(&p->lock);
03413    
03414    idx = dahdi_get_index(ast, p, 1);
03415 
03416    if ((p->sig == SIG_PRI) || (p->sig == SIG_SS7) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP)) {
03417       x = 1;
03418       ast_channel_setoption(ast,AST_OPTION_AUDIO_MODE,&x,sizeof(char),0);
03419       p->cid_num[0] = '\0';
03420       p->cid_name[0] = '\0';
03421    }
03422 
03423    x = 0;
03424    dahdi_confmute(p, 0);
03425    p->muting = 0;
03426    restore_gains(p);
03427    if (p->origcid_num) {
03428       ast_copy_string(p->cid_num, p->origcid_num, sizeof(p->cid_num));
03429       ast_free(p->origcid_num);
03430       p->origcid_num = NULL;
03431    }  
03432    if (p->origcid_name) {
03433       ast_copy_string(p->cid_name, p->origcid_name, sizeof(p->cid_name));
03434       ast_free(p->origcid_name);
03435       p->origcid_name = NULL;
03436    }  
03437    if (p->dsp)
03438       ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
03439    p->exten[0] = '\0';
03440 
03441    ast_debug(1, "Hangup: channel: %d index = %d, normal = %d, callwait = %d, thirdcall = %d\n",
03442       p->channel, idx, p->subs[SUB_REAL].dfd, p->subs[SUB_CALLWAIT].dfd, p->subs[SUB_THREEWAY].dfd);
03443    p->ignoredtmf = 0;
03444    
03445    if (idx > -1) {
03446       /* Real channel, do some fixup */
03447       p->subs[idx].owner = NULL;
03448       p->subs[idx].needanswer = 0;
03449       p->subs[idx].needflash = 0;
03450       p->subs[idx].needringing = 0;
03451       p->subs[idx].needbusy = 0;
03452       p->subs[idx].needcongestion = 0;
03453       p->subs[idx].linear = 0;
03454       p->subs[idx].needcallerid = 0;
03455       p->polarity = POLARITY_IDLE;
03456       dahdi_setlinear(p->subs[idx].dfd, 0);
03457       if (idx == SUB_REAL) {
03458          if ((p->subs[SUB_CALLWAIT].dfd > -1) && (p->subs[SUB_THREEWAY].dfd > -1)) {
03459             ast_debug(1, "Normal call hung up with both three way call and a call waiting call in place?\n");
03460             if (p->subs[SUB_CALLWAIT].inthreeway) {
03461                /* We had flipped over to answer a callwait and now it's gone */
03462                ast_debug(1, "We were flipped over to the callwait, moving back and unowning.\n");
03463                /* Move to the call-wait, but un-own us until they flip back. */
03464                swap_subs(p, SUB_CALLWAIT, SUB_REAL);
03465                unalloc_sub(p, SUB_CALLWAIT);
03466                p->owner = NULL;
03467             } else {
03468                /* The three way hung up, but we still have a call wait */
03469                ast_debug(1, "We were in the threeway and have a callwait still.  Ditching the threeway.\n");
03470                swap_subs(p, SUB_THREEWAY, SUB_REAL);
03471                unalloc_sub(p, SUB_THREEWAY);
03472                if (p->subs[SUB_REAL].inthreeway) {
03473                   /* This was part of a three way call.  Immediately make way for
03474                      another call */
03475                   ast_debug(1, "Call was complete, setting owner to former third call\n");
03476                   p->owner = p->subs[SUB_REAL].owner;
03477                } else {
03478                   /* This call hasn't been completed yet...  Set owner to NULL */
03479                   ast_debug(1, "Call was incomplete, setting owner to NULL\n");
03480                   p->owner = NULL;
03481                }
03482                p->subs[SUB_REAL].inthreeway = 0;
03483             }
03484          } else if (p->subs[SUB_CALLWAIT].dfd > -1) {
03485             /* Move to the call-wait and switch back to them. */
03486             swap_subs(p, SUB_CALLWAIT, SUB_REAL);
03487             unalloc_sub(p, SUB_CALLWAIT);
03488             p->owner = p->subs[SUB_REAL].owner;
03489             if (p->owner->_state != AST_STATE_UP)
03490                p->subs[SUB_REAL].needanswer = 1;
03491             if (ast_bridged_channel(p->subs[SUB_REAL].owner))
03492                ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
03493          } else if (p->subs[SUB_THREEWAY].dfd > -1) {
03494             swap_subs(p, SUB_THREEWAY, SUB_REAL);
03495             unalloc_sub(p, SUB_THREEWAY);
03496             if (p->subs[SUB_REAL].inthreeway) {
03497                /* This was part of a three way call.  Immediately make way for
03498                   another call */
03499                ast_debug(1, "Call was complete, setting owner to former third call\n");
03500                p->owner = p->subs[SUB_REAL].owner;
03501             } else {
03502                /* This call hasn't been completed yet...  Set owner to NULL */
03503                ast_debug(1, "Call was incomplete, setting owner to NULL\n");
03504                p->owner = NULL;
03505             }
03506             p->subs[SUB_REAL].inthreeway = 0;
03507          }
03508       } else if (idx == SUB_CALLWAIT) {
03509          /* Ditch the holding callwait call, and immediately make it availabe */
03510          if (p->subs[SUB_CALLWAIT].inthreeway) {
03511             /* This is actually part of a three way, placed on hold.  Place the third part
03512                on music on hold now */
03513             if (p->subs[SUB_THREEWAY].owner && ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
03514                ast_queue_control_data(p->subs[SUB_THREEWAY].owner, AST_CONTROL_HOLD, 
03515                   S_OR(p->mohsuggest, NULL),
03516                   !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
03517             }
03518             p->subs[SUB_THREEWAY].inthreeway = 0;
03519             /* Make it the call wait now */
03520             swap_subs(p, SUB_CALLWAIT, SUB_THREEWAY);
03521             unalloc_sub(p, SUB_THREEWAY);
03522          } else
03523             unalloc_sub(p, SUB_CALLWAIT);
03524       } else if (idx == SUB_THREEWAY) {
03525          if (p->subs[SUB_CALLWAIT].inthreeway) {
03526             /* The other party of the three way call is currently in a call-wait state.
03527                Start music on hold for them, and take the main guy out of the third call */
03528             if (p->subs[SUB_CALLWAIT].owner && ast_bridged_channel(p->subs[SUB_CALLWAIT].owner)) {
03529                ast_queue_control_data(p->subs[SUB_CALLWAIT].owner, AST_CONTROL_HOLD, 
03530                   S_OR(p->mohsuggest, NULL),
03531                   !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
03532             }
03533             p->subs[SUB_CALLWAIT].inthreeway = 0;
03534          }
03535          p->subs[SUB_REAL].inthreeway = 0;
03536          /* If this was part of a three way call index, let us make
03537             another three way call */
03538          unalloc_sub(p, SUB_THREEWAY);
03539       } else {
03540          /* This wasn't any sort of call, but how are we an index? */
03541          ast_log(LOG_WARNING, "Index found but not any type of call?\n");
03542       }
03543    }
03544 
03545    if (!p->subs[SUB_REAL].owner && !p->subs[SUB_CALLWAIT].owner && !p->subs[SUB_THREEWAY].owner) {
03546       p->owner = NULL;
03547       p->ringt = 0;
03548       p->distinctivering = 0;
03549       p->confirmanswer = 0;
03550       p->cidrings = 1;
03551       p->outgoing = 0;
03552       p->digital = 0;
03553       p->faxhandled = 0;
03554       p->pulsedial = 0;
03555       p->onhooktime = time(NULL);
03556 #if defined(HAVE_PRI) || defined(HAVE_SS7)
03557       p->proceeding = 0;
03558       p->dialing = 0;
03559       p->progress = 0;
03560       p->alerting = 0;
03561       p->setup_ack = 0;
03562       p->rlt = 0;
03563 #endif      
03564       if (p->dsp) {
03565          ast_dsp_free(p->dsp);
03566          p->dsp = NULL;
03567       }
03568 
03569       law = DAHDI_LAW_DEFAULT;
03570       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETLAW, &law);
03571       if (res < 0) 
03572          ast_log(LOG_WARNING, "Unable to set law on channel %d to default: %s\n", p->channel, strerror(errno));
03573       /* Perform low level hangup if no owner left */
03574 #ifdef HAVE_SS7
03575       if (p->ss7) {
03576          if (p->ss7call) {
03577             if (!ss7_grab(p, p->ss7)) {
03578                if (!p->alreadyhungup) {
03579                   const char *cause = pbx_builtin_getvar_helper(ast,"SS7_CAUSE");
03580                   int icause = ast->hangupcause ? ast->hangupcause : -1;
03581 
03582                   if (cause) {
03583                      if (atoi(cause))
03584                         icause = atoi(cause);
03585                   }
03586                   isup_rel(p->ss7->ss7, p->ss7call, icause);
03587                   ss7_rel(p->ss7);
03588                   p->alreadyhungup = 1;
03589                } else
03590                   ast_log(LOG_WARNING, "Trying to hangup twice!\n");
03591             } else {
03592                ast_log(LOG_WARNING, "Unable to grab SS7 on CIC %d\n", p->cic);
03593                res = -1;
03594             }
03595          }
03596       }
03597 #endif
03598 #ifdef HAVE_PRI
03599       if (p->pri) {
03600 #ifdef SUPPORT_USERUSER
03601          const char *useruser = pbx_builtin_getvar_helper(ast,"USERUSERINFO");
03602 #endif
03603 
03604          /* Make sure we have a call (or REALLY have a call in the case of a PRI) */
03605          if (p->call && (!p->bearer || (p->bearer->call == p->call))) {
03606             if (!pri_grab(p, p->pri)) {
03607                if (p->alreadyhungup) {
03608                   ast_debug(1, "Already hungup...  Calling hangup once, and clearing call\n");
03609 
03610 #ifdef SUPPORT_USERUSER
03611                   pri_call_set_useruser(p->call, useruser);
03612 #endif
03613 
03614                   pri_hangup(p->pri->pri, p->call, -1);
03615                   p->call = NULL;
03616                   if (p->bearer) 
03617                      p->bearer->call = NULL;
03618                } else {
03619                   const char *cause = pbx_builtin_getvar_helper(ast,"PRI_CAUSE");
03620                   int icause = ast->hangupcause ? ast->hangupcause : -1;
03621                   ast_debug(1, "Not yet hungup...  Calling hangup once with icause, and clearing call\n");
03622 
03623 #ifdef SUPPORT_USERUSER
03624                   pri_call_set_useruser(p->call, useruser);
03625 #endif
03626 
03627                   p->alreadyhungup = 1;
03628                   if (p->bearer)
03629                      p->bearer->alreadyhungup = 1;
03630                   if (cause) {
03631                      if (atoi(cause))
03632                         icause = atoi(cause);
03633                   }
03634                   pri_hangup(p->pri->pri, p->call, icause);
03635                }
03636                if (res < 0) 
03637                   ast_log(LOG_WARNING, "pri_disconnect failed\n");
03638                pri_rel(p->pri);        
03639             } else {
03640                ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
03641                res = -1;
03642             }
03643          } else {
03644             if (p->bearer)
03645                ast_debug(1, "Bearer call is %p, while ours is still %p\n", p->bearer->call, p->call);
03646             p->call = NULL;
03647             res = 0;
03648          }
03649       }
03650 #endif
03651       if (p->sig && ((p->sig != SIG_PRI) && (p->sig != SIG_SS7) && (p->sig != SIG_BRI) && (p->sig != SIG_BRI_PTMP)))
03652          res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
03653       if (res < 0) {
03654          ast_log(LOG_WARNING, "Unable to hangup line %s\n", ast->name);
03655       }
03656       switch (p->sig) {
03657       case SIG_FXOGS:
03658       case SIG_FXOLS:
03659       case SIG_FXOKS:
03660          memset(&par, 0, sizeof(par));
03661          res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par);
03662          if (!res) {
03663 #if 0
03664             ast_debug(1, "Hanging up channel %d, offhook = %d\n", p->channel, par.rxisoffhook);
03665 #endif
03666             /* If they're off hook, try playing congestion */
03667             if ((par.rxisoffhook) && (!(p->radio || (p->oprmode < 0))))
03668                tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
03669             else
03670                tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
03671          }
03672          break;
03673       case SIG_FXSGS:
03674       case SIG_FXSLS:
03675       case SIG_FXSKS:
03676          /* Make sure we're not made available for at least two seconds assuming
03677             we were actually used for an inbound or outbound call. */
03678          if (ast->_state != AST_STATE_RESERVED) {
03679             time(&p->guardtime);
03680             p->guardtime += 2;
03681          }
03682          break;
03683       default:
03684          tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
03685       }
03686       if (p->cidspill)
03687          ast_free(p->cidspill);
03688       if (p->sig)
03689          dahdi_disable_ec(p);
03690       x = 0;
03691       ast_channel_setoption(ast,AST_OPTION_TONE_VERIFY,&x,sizeof(char),0);
03692       ast_channel_setoption(ast,AST_OPTION_TDD,&x,sizeof(char),0);
03693       p->didtdd = 0;
03694       p->cidspill = NULL;
03695       p->callwaitcas = 0;
03696       p->callwaiting = p->permcallwaiting;
03697       p->hidecallerid = p->permhidecallerid;
03698       p->dialing = 0;
03699       p->rdnis[0] = '\0';
03700       update_conf(p);
03701       reset_conf(p);
03702       /* Restore data mode */
03703       if ((p->sig == SIG_PRI) || (p->sig == SIG_SS7) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP)) {
03704          x = 0;
03705          ast_channel_setoption(ast,AST_OPTION_AUDIO_MODE,&x,sizeof(char),0);
03706       }
03707 #ifdef HAVE_PRI
03708       if (p->bearer) {
03709          ast_debug(1, "Freeing up bearer channel %d\n", p->bearer->channel);
03710          /* Free up the bearer channel as well, and
03711             don't use its file descriptor anymore */
03712          update_conf(p->bearer);
03713          reset_conf(p->bearer);
03714          p->bearer->owner = NULL;
03715          p->bearer->realcall = NULL;
03716          p->bearer = NULL;
03717          p->subs[SUB_REAL].dfd = -1;
03718          p->pri = NULL;
03719       }
03720 #endif
03721       if (num_restart_pending == 0)
03722          restart_monitor();
03723    }
03724 
03725    p->callwaitingrepeat = 0;
03726    p->cidcwexpire = 0;
03727    p->oprmode = 0;
03728    ast->tech_pvt = NULL;
03729    ast_mutex_unlock(&p->lock);
03730    ast_module_unref(ast_module_info->self);
03731    ast_verb(3, "Hungup '%s'\n", ast->name);
03732 
03733    ast_mutex_lock(&iflock);
03734 
03735    if (p->restartpending) {
03736       num_restart_pending--;
03737    }
03738 
03739    tmp = iflist;
03740    prev = NULL;
03741    if (p->destroy) {
03742       while (tmp) {
03743          if (tmp == p) {
03744             destroy_channel(prev, tmp, 0);
03745             break;
03746          } else {
03747             prev = tmp;
03748             tmp = tmp->next;
03749          }
03750       }
03751    }
03752    ast_mutex_unlock(&iflock);
03753    return 0;
03754 }
03755 
03756 static int dahdi_answer(struct ast_channel *ast)
03757 {
03758    struct dahdi_pvt *p = ast->tech_pvt;
03759    int res = 0;
03760    int idx;
03761    int oldstate = ast->_state;
03762    ast_setstate(ast, AST_STATE_UP);
03763    ast_mutex_lock(&p->lock);
03764    idx = dahdi_get_index(ast, p, 0);
03765    if (idx < 0)
03766       idx = SUB_REAL;
03767    /* nothing to do if a radio channel */
03768    if ((p->radio || (p->oprmode < 0))) {
03769       ast_mutex_unlock(&p->lock);
03770       return 0;
03771    }
03772    switch (p->sig) {
03773    case SIG_FXSLS:
03774    case SIG_FXSGS:
03775    case SIG_FXSKS:
03776       p->ringt = 0;
03777       /* Fall through */
03778    case SIG_EM:
03779    case SIG_EM_E1:
03780    case SIG_EMWINK:
03781    case SIG_FEATD:
03782    case SIG_FEATDMF:
03783    case SIG_FEATDMF_TA:
03784    case SIG_E911:
03785    case SIG_FGC_CAMA:
03786    case SIG_FGC_CAMAMF:
03787    case SIG_FEATB:
03788    case SIG_SF:
03789    case SIG_SFWINK:
03790    case SIG_SF_FEATD:
03791    case SIG_SF_FEATDMF:
03792    case SIG_SF_FEATB:
03793    case SIG_FXOLS:
03794    case SIG_FXOGS:
03795    case SIG_FXOKS:
03796       /* Pick up the line */
03797       ast_debug(1, "Took %s off hook\n", ast->name);
03798       if (p->hanguponpolarityswitch) {
03799          p->polaritydelaytv = ast_tvnow();
03800       }
03801       res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
03802       tone_zone_play_tone(p->subs[idx].dfd, -1);
03803       p->dialing = 0;
03804       if ((idx == SUB_REAL) && p->subs[SUB_THREEWAY].inthreeway) {
03805          if (oldstate == AST_STATE_RINGING) {
03806             ast_debug(1, "Finally swapping real and threeway\n");
03807             tone_zone_play_tone(p->subs[SUB_THREEWAY].dfd, -1);
03808             swap_subs(p, SUB_THREEWAY, SUB_REAL);
03809             p->owner = p->subs[SUB_REAL].owner;
03810          }
03811       }
03812       if (p->sig & __DAHDI_SIG_FXS) {
03813          dahdi_enable_ec(p);
03814          dahdi_train_ec(p);
03815       }
03816       break;
03817 #ifdef HAVE_PRI
03818    case SIG_BRI:
03819    case SIG_BRI_PTMP:
03820    case SIG_PRI:
03821       /* Send a pri acknowledge */
03822       if (!pri_grab(p, p->pri)) {
03823          p->proceeding = 1;
03824          p->dialing = 0;
03825          res = pri_answer(p->pri->pri, p->call, 0, !p->digital);
03826          pri_rel(p->pri);
03827       } else {
03828          ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
03829          res = -1;
03830       }
03831       break;
03832 #endif
03833 #ifdef HAVE_SS7
03834    case SIG_SS7:
03835       if (!ss7_grab(p, p->ss7)) {
03836          p->proceeding = 1;
03837          res = isup_anm(p->ss7->ss7, p->ss7call);
03838          ss7_rel(p->ss7);
03839       } else {
03840          ast_log(LOG_WARNING, "Unable to grab SS7 on span %d\n", p->span);
03841          res = -1;
03842       }
03843       break;
03844 #endif
03845    case 0:
03846       ast_mutex_unlock(&p->lock);
03847       return 0;
03848    default:
03849       ast_log(LOG_WARNING, "Don't know how to answer signalling %d (channel %d)\n", p->sig, p->channel);
03850       res = -1;
03851    }
03852    ast_mutex_unlock(&p->lock);
03853    return res;
03854 }
03855 
03856 static int dahdi_setoption(struct ast_channel *chan, int option, void *data, int datalen)
03857 {
03858    char *cp;
03859    signed char *scp;
03860    int x;
03861    int idx;
03862    struct dahdi_pvt *p = chan->tech_pvt, *pp;
03863    struct oprmode *oprmode;
03864    
03865 
03866    /* all supported options require data */
03867    if (!data || (datalen < 1)) {
03868       errno = EINVAL;
03869       return -1;
03870    }
03871 
03872    switch (option) {
03873    case AST_OPTION_TXGAIN:
03874       scp = (signed char *) data;
03875       idx = dahdi_get_index(chan, p, 0);
03876       if (idx < 0) {
03877          ast_log(LOG_WARNING, "No index in TXGAIN?\n");
03878          return -1;
03879       }
03880       ast_debug(1, "Setting actual tx gain on %s to %f\n", chan->name, p->txgain + (float) *scp);
03881       return set_actual_txgain(p->subs[idx].dfd, 0, p->txgain + (float) *scp, p->law);
03882    case AST_OPTION_RXGAIN:
03883       scp = (signed char *) data;
03884       idx = dahdi_get_index(chan, p, 0);
03885       if (idx < 0) {
03886          ast_log(LOG_WARNING, "No index in RXGAIN?\n");
03887          return -1;
03888       }
03889       ast_debug(1, "Setting actual rx gain on %s to %f\n", chan->name, p->rxgain + (float) *scp);
03890       return set_actual_rxgain(p->subs[idx].dfd, 0, p->rxgain + (float) *scp, p->law);
03891    case AST_OPTION_TONE_VERIFY:
03892       if (!p->dsp)
03893          break;
03894       cp = (char *) data;
03895       switch (*cp) {
03896       case 1:
03897          ast_debug(1, "Set option TONE VERIFY, mode: MUTECONF(1) on %s\n",chan->name);
03898          ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MUTECONF | p->dtmfrelax);  /* set mute mode if desired */
03899          break;
03900       case 2:
03901          ast_debug(1, "Set option TONE VERIFY, mode: MUTECONF/MAX(2) on %s\n",chan->name);
03902          ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MUTECONF | DSP_DIGITMODE_MUTEMAX | p->dtmfrelax);  /* set mute mode if desired */
03903          break;
03904       default:
03905          ast_debug(1, "Set option TONE VERIFY, mode: OFF(0) on %s\n",chan->name);
03906          ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);  /* set mute mode if desired */
03907          break;
03908       }
03909       break;
03910    case AST_OPTION_TDD:
03911       /* turn on or off TDD */
03912       cp = (char *) data;
03913       p->mate = 0;
03914       if (!*cp) { /* turn it off */
03915          ast_debug(1, "Set option TDD MODE, value: OFF(0) on %s\n",chan->name);
03916          if (p->tdd)
03917             tdd_free(p->tdd);
03918          p->tdd = 0;
03919          break;
03920       }
03921       ast_debug(1, "Set option TDD MODE, value: %s(%d) on %s\n",
03922          (*cp == 2) ? "MATE" : "ON", (int) *cp, chan->name);
03923       dahdi_disable_ec(p);
03924       /* otherwise, turn it on */
03925       if (!p->didtdd) { /* if havent done it yet */
03926          unsigned char mybuf[41000];/*! \todo XXX This is an abuse of the stack!! */
03927          unsigned char *buf;
03928          int size, res, fd, len;
03929          struct pollfd fds[1];
03930 
03931          buf = mybuf;
03932          memset(buf, 0x7f, sizeof(mybuf)); /* set to silence */
03933          ast_tdd_gen_ecdisa(buf + 16000, 16000);  /* put in tone */
03934          len = 40000;
03935          idx = dahdi_get_index(chan, p, 0);
03936          if (idx < 0) {
03937             ast_log(LOG_WARNING, "No index in TDD?\n");
03938             return -1;
03939          }
03940          fd = p->subs[idx].dfd;
03941          while (len) {
03942             if (ast_check_hangup(chan))
03943                return -1;
03944             size = len;
03945             if (size > READ_SIZE)
03946                size = READ_SIZE;
03947             fds[0].fd = fd;
03948             fds[0].events = POLLPRI | POLLOUT;
03949             fds[0].revents = 0;
03950             res = poll(fds, 1, -1);
03951             if (!res) {
03952                ast_debug(1, "poll (for write) ret. 0 on channel %d\n", p->channel);
03953                continue;
03954             }
03955             /* if got exception */
03956             if (fds[0].revents & POLLPRI)
03957                return -1;
03958             if (!(fds[0].revents & POLLOUT)) {
03959                ast_debug(1, "write fd not ready on channel %d\n", p->channel);
03960                continue;
03961             }
03962             res = write(fd, buf, size);
03963             if (res != size) {
03964                if (res == -1) return -1;
03965                ast_debug(1, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel);
03966                break;
03967             }
03968             len -= size;
03969             buf += size;
03970          }
03971          p->didtdd = 1; /* set to have done it now */    
03972       }
03973       if (*cp == 2) { /* Mate mode */
03974          if (p->tdd)
03975             tdd_free(p->tdd);
03976          p->tdd = 0;
03977          p->mate = 1;
03978          break;
03979       }     
03980       if (!p->tdd) { /* if we dont have one yet */
03981          p->tdd = tdd_new(); /* allocate one */
03982       }     
03983       break;
03984    case AST_OPTION_RELAXDTMF:  /* Relax DTMF decoding (or not) */
03985       if (!p->dsp)
03986          break;
03987       cp = (char *) data;
03988       ast_debug(1, "Set option RELAX DTMF, value: %s(%d) on %s\n",
03989          *cp ? "ON" : "OFF", (int) *cp, chan->name);
03990       ast_dsp_set_digitmode(p->dsp, ((*cp) ? DSP_DIGITMODE_RELAXDTMF : DSP_DIGITMODE_DTMF) | p->dtmfrelax);
03991       break;
03992    case AST_OPTION_AUDIO_MODE:  /* Set AUDIO mode (or not) */
03993       cp = (char *) data;
03994       if (!*cp) {    
03995          ast_debug(1, "Set option AUDIO MODE, value: OFF(0) on %s\n", chan->name);
03996          x = 0;
03997          dahdi_disable_ec(p);
03998       } else {    
03999          ast_debug(1, "Set option AUDIO MODE, value: ON(1) on %s\n", chan->name);
04000          x = 1;
04001       }
04002       if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &x) == -1)
04003          ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d: %s\n", p->channel, x, strerror(errno));
04004       break;
04005    case AST_OPTION_OPRMODE:  /* Operator services mode */
04006       oprmode = (struct oprmode *) data;
04007       pp = oprmode->peer->tech_pvt;
04008       p->oprmode = pp->oprmode = 0;
04009       /* setup peers */
04010       p->oprpeer = pp;
04011       pp->oprpeer = p;
04012       /* setup modes, if any */
04013       if (oprmode->mode) 
04014       {
04015          pp->oprmode = oprmode->mode;
04016          p->oprmode = -oprmode->mode;
04017       }
04018       ast_debug(1, "Set Operator Services mode, value: %d on %s/%s\n",
04019          oprmode->mode, chan->name,oprmode->peer->name);
04020       break;
04021    case AST_OPTION_ECHOCAN:
04022       cp = (char *) data;
04023       if (*cp) {
04024          ast_debug(1, "Enabling echo cancelation on %s\n", chan->name);
04025          dahdi_enable_ec(p);
04026       } else {
04027          ast_debug(1, "Disabling echo cancelation on %s\n", chan->name);
04028          dahdi_disable_ec(p);
04029       }
04030       break;
04031    }
04032    errno = 0;
04033 
04034    return 0;
04035 }
04036 
04037 static int dahdi_func_read(struct ast_channel *chan, const char *function, char *data, char *buf, size_t len)
04038 {
04039    struct dahdi_pvt *p = chan->tech_pvt;
04040    
04041    if (!strcasecmp(data, "rxgain")) {
04042       ast_mutex_lock(&p->lock);
04043       snprintf(buf, len, "%f", p->rxgain);
04044       ast_mutex_unlock(&p->lock);   
04045    } else if (!strcasecmp(data, "txgain")) {
04046       ast_mutex_lock(&p->lock);
04047       snprintf(buf, len, "%f", p->txgain);
04048       ast_mutex_unlock(&p->lock);   
04049    } else {
04050       ast_copy_string(buf, "", len);
04051    }
04052    return 0;
04053 }
04054 
04055 
04056 static void dahdi_unlink(struct dahdi_pvt *slave, struct dahdi_pvt *master, int needlock)
04057 {
04058    /* Unlink a specific slave or all slaves/masters from a given master */
04059    int x;
04060    int hasslaves;
04061    if (!master)
04062       return;
04063    if (needlock) {
04064       ast_mutex_lock(&master->lock);
04065       if (slave) {
04066          while (ast_mutex_trylock(&slave->lock)) {
04067             DEADLOCK_AVOIDANCE(&master->lock);
04068          }
04069       }
04070    }
04071    hasslaves = 0;
04072    for (x = 0; x < MAX_SLAVES; x++) {
04073       if (master->slaves[x]) {
04074          if (!slave || (master->slaves[x] == slave)) {
04075             /* Take slave out of the conference */
04076             ast_debug(1, "Unlinking slave %d from %d\n", master->slaves[x]->channel, master->channel);
04077             conf_del(master, &master->slaves[x]->subs[SUB_REAL], SUB_REAL);
04078             conf_del(master->slaves[x], &master->subs[SUB_REAL], SUB_REAL);
04079             master->slaves[x]->master = NULL;
04080             master->slaves[x] = NULL;
04081          } else
04082             hasslaves = 1;
04083       }
04084       if (!hasslaves)
04085          master->inconference = 0;
04086    }
04087    if (!slave) {
04088       if (master->master) {
04089          /* Take master out of the conference */
04090          conf_del(master->master, &master->subs[SUB_REAL], SUB_REAL);
04091          conf_del(master, &master->master->subs[SUB_REAL], SUB_REAL);
04092          hasslaves = 0;
04093          for (x = 0; x < MAX_SLAVES; x++) {
04094             if (master->master->slaves[x] == master)
04095                master->master->slaves[x] = NULL;
04096             else if (master->master->slaves[x])
04097                hasslaves = 1;
04098          }
04099          if (!hasslaves)
04100             master->master->inconference = 0;
04101       }
04102       master->master = NULL;
04103    }
04104    update_conf(master);
04105    if (needlock) {
04106       if (slave)
04107          ast_mutex_unlock(&slave->lock);
04108       ast_mutex_unlock(&master->lock);
04109    }
04110 }
04111 
04112 static void dahdi_link(struct dahdi_pvt *slave, struct dahdi_pvt *master) {
04113    int x;
04114    if (!slave || !master) {
04115       ast_log(LOG_WARNING, "Tried to link to/from NULL??\n");
04116       return;
04117    }
04118    for (x = 0; x < MAX_SLAVES; x++) {
04119       if (!master->slaves[x]) {
04120          master->slaves[x] = slave;
04121          break;
04122       }
04123    }
04124    if (x >= MAX_SLAVES) {
04125       ast_log(LOG_WARNING, "Replacing slave %d with new slave, %d\n", master->slaves[MAX_SLAVES - 1]->channel, slave->channel);
04126       master->slaves[MAX_SLAVES - 1] = slave;
04127    }
04128    if (slave->master) 
04129       ast_log(LOG_WARNING, "Replacing master %d with new master, %d\n", slave->master->channel, master->channel);
04130    slave->master = master;
04131    
04132    ast_debug(1, "Making %d slave to master %d at %d\n", slave->channel, master->channel, x);
04133 }
04134 
04135 static void disable_dtmf_detect(struct dahdi_pvt *p)
04136 {
04137    int val;
04138 
04139    p->ignoredtmf = 1;
04140 
04141    val = 0;
04142    ioctl(p->subs[SUB_REAL].dfd, DAHDI_TONEDETECT, &val);
04143 
04144    if (!p->hardwaredtmf && p->dsp) {
04145       p->dsp_features &= ~DSP_FEATURE_DIGIT_DETECT;
04146       ast_dsp_set_features(p->dsp, p->dsp_features);
04147    }
04148 }
04149 
04150 static void enable_dtmf_detect(struct dahdi_pvt *p)
04151 {
04152    int val;
04153 
04154    if (p->channel == CHAN_PSEUDO)
04155       return;
04156 
04157    p->ignoredtmf = 0;
04158 
04159    val = DAHDI_TONEDETECT_ON | DAHDI_TONEDETECT_MUTE;
04160    ioctl(p->subs[SUB_REAL].dfd, DAHDI_TONEDETECT, &val);
04161 
04162    if (!p->hardwaredtmf && p->dsp) {
04163       p->dsp_features |= DSP_FEATURE_DIGIT_DETECT;
04164       ast_dsp_set_features(p->dsp, p->dsp_features);
04165    }
04166 }
04167 
04168 static enum ast_bridge_result dahdi_bridge(struct ast_channel *c0, struct ast_channel *c1, int flags, struct ast_frame **fo, struct ast_channel **rc, int timeoutms)
04169 {
04170    struct ast_channel *who;
04171    struct dahdi_pvt *p0, *p1, *op0, *op1;
04172    struct dahdi_pvt *master = NULL, *slave = NULL;
04173    struct ast_frame *f;
04174    int inconf = 0;
04175    int nothingok = 1;
04176    int ofd0, ofd1;
04177    int oi0, oi1, i0 = -1, i1 = -1, t0, t1;
04178    int os0 = -1, os1 = -1;
04179    int priority = 0;
04180    struct ast_channel *oc0, *oc1;
04181    enum ast_bridge_result res;
04182 
04183 #ifdef PRI_2BCT
04184    int triedtopribridge = 0;
04185 #endif
04186 
04187    /* For now, don't attempt to native bridge if either channel needs DTMF detection.
04188       There is code below to handle it properly until DTMF is actually seen,
04189       but due to currently unresolved issues it's ignored...
04190    */
04191 
04192    if (flags & (AST_BRIDGE_DTMF_CHANNEL_0 | AST_BRIDGE_DTMF_CHANNEL_1))
04193       return AST_BRIDGE_FAILED_NOWARN;
04194 
04195    ast_channel_lock(c0);
04196    while (ast_channel_trylock(c1)) {
04197       CHANNEL_DEADLOCK_AVOIDANCE(c0);
04198    }
04199 
04200    p0 = c0->tech_pvt;
04201    p1 = c1->tech_pvt;
04202    /* cant do pseudo-channels here */
04203    if (!p0 || (!p0->sig) || !p1 || (!p1->sig)) {
04204       ast_channel_unlock(c0);
04205       ast_channel_unlock(c1);
04206       return AST_BRIDGE_FAILED_NOWARN;
04207    }
04208 
04209    oi0 = dahdi_get_index(c0, p0, 0);
04210    oi1 = dahdi_get_index(c1, p1, 0);
04211    if ((oi0 < 0) || (oi1 < 0)) {
04212       ast_channel_unlock(c0);
04213       ast_channel_unlock(c1);
04214       return AST_BRIDGE_FAILED;
04215    }
04216 
04217    op0 = p0 = c0->tech_pvt;
04218    op1 = p1 = c1->tech_pvt;
04219    ofd0 = c0->fds[0];
04220    ofd1 = c1->fds[0];
04221    oc0 = p0->owner;
04222    oc1 = p1->owner;
04223 
04224    if (ast_mutex_trylock(&p0->lock)) {
04225       /* Don't block, due to potential for deadlock */
04226       ast_channel_unlock(c0);
04227       ast_channel_unlock(c1);
04228       ast_log(LOG_NOTICE, "Avoiding deadlock...\n");
04229       return AST_BRIDGE_RETRY;
04230    }
04231    if (ast_mutex_trylock(&p1->lock)) {
04232       /* Don't block, due to potential for deadlock */
04233       ast_mutex_unlock(&p0->lock);
04234       ast_channel_unlock(c0);
04235       ast_channel_unlock(c1);
04236       ast_log(LOG_NOTICE, "Avoiding deadlock...\n");
04237       return AST_BRIDGE_RETRY;
04238    }
04239 
04240    if ((oi0 == SUB_REAL) && (oi1 == SUB_REAL)) {
04241       if (p0->owner && p1->owner) {
04242          /* If we don't have a call-wait in a 3-way, and we aren't in a 3-way, we can be master */
04243          if (!p0->subs[SUB_CALLWAIT].inthreeway && !p1->subs[SUB_REAL].inthreeway) {
04244             master = p0;
04245             slave = p1;
04246             inconf = 1;
04247          } else if (!p1->subs[SUB_CALLWAIT].inthreeway && !p0->subs[SUB_REAL].inthreeway) {
04248             master = p1;
04249             slave = p0;
04250             inconf = 1;
04251          } else {
04252             ast_log(LOG_WARNING, "Huh?  Both calls are callwaits or 3-ways?  That's clever...?\n");
04253             ast_log(LOG_WARNING, "p0: chan %d/%d/CW%d/3W%d, p1: chan %d/%d/CW%d/3W%d\n",
04254                p0->channel,
04255                oi0, (p0->subs[SUB_CALLWAIT].dfd > -1) ? 1 : 0,
04256                p0->subs[SUB_REAL].inthreeway, p0->channel,
04257                oi0, (p1->subs[SUB_CALLWAIT].dfd > -1) ? 1 : 0,
04258                p1->subs[SUB_REAL].inthreeway);
04259          }
04260          nothingok = 0;
04261       }
04262    } else if ((oi0 == SUB_REAL) && (oi1 == SUB_THREEWAY)) {
04263       if (p1->subs[SUB_THREEWAY].inthreeway) {
04264          master = p1;
04265          slave = p0;
04266          nothingok = 0;
04267       }
04268    } else if ((oi0 == SUB_THREEWAY) && (oi1 == SUB_REAL)) {
04269       if (p0->subs[SUB_THREEWAY].inthreeway) {
04270          master = p0;
04271          slave = p1;
04272          nothingok = 0;
04273       }
04274    } else if ((oi0 == SUB_REAL) && (oi1 == SUB_CALLWAIT)) {
04275       /* We have a real and a call wait.  If we're in a three way call, put us in it, otherwise, 
04276          don't put us in anything */
04277       if (p1->subs[SUB_CALLWAIT].inthreeway) {
04278          master = p1;
04279          slave = p0;
04280          nothingok = 0;
04281       }
04282    } else if ((oi0 == SUB_CALLWAIT) && (oi1 == SUB_REAL)) {
04283       /* Same as previous */
04284       if (p0->subs[SUB_CALLWAIT].inthreeway) {
04285          master = p0;
04286          slave = p1;
04287          nothingok = 0;
04288       }
04289    }
04290    ast_debug(1, "master: %d, slave: %d, nothingok: %d\n",
04291       master ? master->channel : 0, slave ? slave->channel : 0, nothingok);
04292    if (master && slave) {
04293       /* Stop any tones, or play ringtone as appropriate.  If they're bridged
04294          in an active threeway call with a channel that is ringing, we should
04295          indicate ringing. */
04296       if ((oi1 == SUB_THREEWAY) && 
04297           p1->subs[SUB_THREEWAY].inthreeway && 
04298           p1->subs[SUB_REAL].owner && 
04299           p1->subs[SUB_REAL].inthreeway && 
04300           (p1->subs[SUB_REAL].owner->_state == AST_STATE_RINGING)) {
04301          ast_debug(1, "Playing ringback on %s since %s is in a ringing three-way\n", c0->name, c1->name);
04302          tone_zone_play_tone(p0->subs[oi0].dfd, DAHDI_TONE_RINGTONE);
04303          os1 = p1->subs[SUB_REAL].owner->_state;
04304       } else {
04305          ast_debug(1, "Stopping tones on %d/%d talking to %d/%d\n", p0->channel, oi0, p1->channel, oi1);
04306          tone_zone_play_tone(p0->subs[oi0].dfd, -1);
04307       }
04308       if ((oi0 == SUB_THREEWAY) && 
04309           p0->subs[SUB_THREEWAY].inthreeway && 
04310           p0->subs[SUB_REAL].owner && 
04311           p0->subs[SUB_REAL].inthreeway && 
04312           (p0->subs[SUB_REAL].owner->_state == AST_STATE_RINGING)) {
04313          ast_debug(1, "Playing ringback on %s since %s is in a ringing three-way\n", c1->name, c0->name);
04314          tone_zone_play_tone(p1->subs[oi1].dfd, DAHDI_TONE_RINGTONE);
04315          os0 = p0->subs[SUB_REAL].owner->_state;
04316       } else {
04317          ast_debug(1, "Stopping tones on %d/%d talking to %d/%d\n", p1->channel, oi1, p0->channel, oi0);
04318          tone_zone_play_tone(p1->subs[oi0].dfd, -1);
04319       }
04320       if ((oi0 == SUB_REAL) && (oi1 == SUB_REAL)) {
04321          if (!p0->echocanbridged || !p1->echocanbridged) {
04322             /* Disable echo cancellation if appropriate */
04323             dahdi_disable_ec(p0);
04324             dahdi_disable_ec(p1);
04325          }
04326       }
04327       dahdi_link(slave, master);
04328       master->inconference = inconf;
04329    } else if (!nothingok)
04330       ast_log(LOG_WARNING, "Can't link %d/%s with %d/%s\n", p0->channel, subnames[oi0], p1->channel, subnames[oi1]);
04331 
04332    update_conf(p0);
04333    update_conf(p1);
04334    t0 = p0->subs[SUB_REAL].inthreeway;
04335    t1 = p1->subs[SUB_REAL].inthreeway;
04336 
04337    ast_mutex_unlock(&p0->lock);
04338    ast_mutex_unlock(&p1->lock);
04339 
04340    ast_channel_unlock(c0);
04341    ast_channel_unlock(c1);
04342 
04343    /* Native bridge failed */
04344    if ((!master || !slave) && !nothingok) {
04345       dahdi_enable_ec(p0);
04346       dahdi_enable_ec(p1);
04347       return AST_BRIDGE_FAILED;
04348    }
04349    
04350    ast_verb(3, "Native bridging %s and %s\n", c0->name, c1->name);
04351 
04352    if (!(flags & AST_BRIDGE_DTMF_CHANNEL_0) && (oi0 == SUB_REAL))
04353       disable_dtmf_detect(op0);
04354 
04355    if (!(flags & AST_BRIDGE_DTMF_CHANNEL_1) && (oi1 == SUB_REAL))
04356       disable_dtmf_detect(op1);
04357 
04358    for (;;) {
04359       struct ast_channel *c0_priority[2] = {c0, c1};
04360       struct ast_channel *c1_priority[2] = {c1, c0};
04361 
04362       /* Here's our main loop...  Start by locking things, looking for private parts, 
04363          and then balking if anything is wrong */
04364       
04365       ast_channel_lock(c0);
04366       while (ast_channel_trylock(c1)) {
04367          CHANNEL_DEADLOCK_AVOIDANCE(c0);
04368       }
04369 
04370       p0 = c0->tech_pvt;
04371       p1 = c1->tech_pvt;
04372 
04373       if (op0 == p0)
04374          i0 = dahdi_get_index(c0, p0, 1);
04375       if (op1 == p1)
04376          i1 = dahdi_get_index(c1, p1, 1);
04377 
04378       ast_channel_unlock(c0);
04379       ast_channel_unlock(c1);
04380 
04381       if (!timeoutms || 
04382           (op0 != p0) ||
04383           (op1 != p1) || 
04384           (ofd0 != c0->fds[0]) || 
04385           (ofd1 != c1->fds[0]) ||
04386           (p0->subs[SUB_REAL].owner && (os0 > -1) && (os0 != p0->subs[SUB_REAL].owner->_state)) || 
04387           (p1->subs[SUB_REAL].owner && (os1 > -1) && (os1 != p1->subs[SUB_REAL].owner->_state)) || 
04388           (oc0 != p0->owner) || 
04389           (oc1 != p1->owner) ||
04390           (t0 != p0->subs[SUB_REAL].inthreeway) ||
04391           (t1 != p1->subs[SUB_REAL].inthreeway) ||
04392           (oi0 != i0) ||
04393           (oi1 != i1)) {
04394          ast_debug(1, "Something changed out on %d/%d to %d/%d, returning -3 to restart\n",
04395             op0->channel, oi0, op1->channel, oi1);
04396          res = AST_BRIDGE_RETRY;
04397          goto return_from_bridge;
04398       }
04399 
04400 #ifdef PRI_2BCT
04401       if (!triedtopribridge) {
04402          triedtopribridge = 1;
04403          if (p0->pri && p0->pri == p1->pri && p0->transfer && p1->transfer) {
04404             ast_mutex_lock(&p0->pri->lock);
04405             if (p0->call && p1->call) {
04406                pri_channel_bridge(p0->call, p1->call);
04407             }
04408             ast_mutex_unlock(&p0->pri->lock);
04409          }
04410       }
04411 #endif
04412 
04413       who = ast_waitfor_n(priority ? c0_priority : c1_priority, 2, &timeoutms);
04414       if (!who) {
04415          ast_debug(1, "Ooh, empty read...\n");
04416          continue;
04417       }
04418       f = ast_read(who);
04419       if (!f || (f->frametype == AST_FRAME_CONTROL)) {
04420          *fo = f;
04421          *rc = who;
04422          res = AST_BRIDGE_COMPLETE;
04423          goto return_from_bridge;
04424       }
04425       if (f->frametype == AST_FRAME_DTMF) {
04426          if ((who == c0) && p0->pulsedial) {
04427             ast_write(c1, f);
04428          } else if ((who == c1) && p1->pulsedial) {
04429             ast_write(c0, f);
04430          } else {
04431             *fo = f;
04432             *rc = who;
04433             res = AST_BRIDGE_COMPLETE;
04434             goto return_from_bridge;
04435          }
04436       }
04437       ast_frfree(f);
04438       
04439       /* Swap who gets priority */
04440       priority = !priority;
04441    }
04442 
04443 return_from_bridge:
04444    if (op0 == p0)
04445       dahdi_enable_ec(p0);
04446 
04447    if (op1 == p1)
04448       dahdi_enable_ec(p1);
04449 
04450    if (!(flags & AST_BRIDGE_DTMF_CHANNEL_0) && (oi0 == SUB_REAL))
04451       enable_dtmf_detect(op0);
04452 
04453    if (!(flags & AST_BRIDGE_DTMF_CHANNEL_1) && (oi1 == SUB_REAL))
04454       enable_dtmf_detect(op1);
04455 
04456    dahdi_unlink(slave, master, 1);
04457 
04458    return res;
04459 }
04460 
04461 static int dahdi_fixup(struct ast_channel *oldchan, struct ast_channel *newchan)
04462 {
04463    struct dahdi_pvt *p = newchan->tech_pvt;
04464    int x;
04465    ast_mutex_lock(&p->lock);
04466    ast_debug(1, "New owner for channel %d is %s\n", p->channel, newchan->name);
04467    if (p->owner == oldchan) {
04468       p->owner = newchan;
04469    }
04470    for (x = 0; x < 3; x++)
04471       if (p->subs[x].owner == oldchan) {
04472          if (!x)
04473             dahdi_unlink(NULL, p, 0);
04474          p->subs[x].owner = newchan;
04475       }
04476    if (newchan->_state == AST_STATE_RINGING) 
04477       dahdi_indicate(newchan, AST_CONTROL_RINGING, NULL, 0);
04478    update_conf(p);
04479    ast_mutex_unlock(&p->lock);
04480    return 0;
04481 }
04482 
04483 static int dahdi_ring_phone(struct dahdi_pvt *p)
04484 {
04485    int x;
04486    int res;
04487    /* Make sure our transmit state is on hook */
04488    x = 0;
04489    x = DAHDI_ONHOOK;
04490    res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
04491    do {
04492       x = DAHDI_RING;
04493       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
04494       if (res) {
04495          switch (errno) {
04496          case EBUSY:
04497          case EINTR:
04498             /* Wait just in case */
04499             usleep(10000);
04500             continue;
04501          case EINPROGRESS:
04502             res = 0;
04503             break;
04504          default:
04505             ast_log(LOG_WARNING, "Couldn't ring the phone: %s\n", strerror(errno));
04506             res = 0;
04507          }
04508       }
04509    } while (res);
04510    return res;
04511 }
04512 
04513 static void *ss_thread(void *data);
04514 
04515 static struct ast_channel *dahdi_new(struct dahdi_pvt *, int, int, int, int, int);
04516 
04517 static int attempt_transfer(struct dahdi_pvt *p)
04518 {
04519    /* In order to transfer, we need at least one of the channels to
04520       actually be in a call bridge.  We can't conference two applications
04521       together (but then, why would we want to?) */
04522    if (ast_bridged_channel(p->subs[SUB_REAL].owner)) {
04523       /* The three-way person we're about to transfer to could still be in MOH, so
04524          stop if now if appropriate */
04525       if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner))
04526          ast_queue_control(p->subs[SUB_THREEWAY].owner, AST_CONTROL_UNHOLD);
04527       if (p->subs[SUB_REAL].owner->_state == AST_STATE_RINGING) {
04528          ast_indicate(ast_bridged_channel(p->subs[SUB_REAL].owner), AST_CONTROL_RINGING);
04529       }
04530       if (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_RING) {
04531          tone_zone_play_tone(p->subs[SUB_THREEWAY].dfd, DAHDI_TONE_RINGTONE);
04532       }
04533        if (ast_channel_masquerade(p->subs[SUB_THREEWAY].owner, ast_bridged_channel(p->subs[SUB_REAL].owner))) {
04534          ast_log(LOG_WARNING, "Unable to masquerade %s as %s\n",
04535                ast_bridged_channel(p->subs[SUB_REAL].owner)->name, p->subs[SUB_THREEWAY].owner->name);
04536          return -1;
04537       }
04538       /* Orphan the channel after releasing the lock */
04539       ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
04540       unalloc_sub(p, SUB_THREEWAY);
04541    } else if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
04542       ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
04543       if (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_RINGING) {
04544          ast_indicate(ast_bridged_channel(p->subs[SUB_THREEWAY].owner), AST_CONTROL_RINGING);
04545       }
04546       if (p->subs[SUB_REAL].owner->_state == AST_STATE_RING) {
04547          tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
04548       }
04549       if (ast_channel_masquerade(p->subs[SUB_REAL].owner, ast_bridged_channel(p->subs[SUB_THREEWAY].owner))) {
04550          ast_log(LOG_WARNING, "Unable to masquerade %s as %s\n",
04551                ast_bridged_channel(p->subs[SUB_THREEWAY].owner)->name, p->subs[SUB_REAL].owner->name);
04552          return -1;
04553       }
04554       /* Three-way is now the REAL */
04555       swap_subs(p, SUB_THREEWAY, SUB_REAL);
04556       ast_channel_unlock(p->subs[SUB_REAL].owner);
04557       unalloc_sub(p, SUB_THREEWAY);
04558       /* Tell the caller not to hangup */
04559       return 1;
04560    } else {
04561       ast_debug(1, "Neither %s nor %s are in a bridge, nothing to transfer\n",
04562          p->subs[SUB_REAL].owner->name, p->subs[SUB_THREEWAY].owner->name);
04563       p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
04564       return -1;
04565    }
04566    return 0;
04567 }
04568 
04569 static int check_for_conference(struct dahdi_pvt *p)
04570 {
04571    struct dahdi_confinfo ci;
04572    /* Fine if we already have a master, etc */
04573    if (p->master || (p->confno > -1))
04574       return 0;
04575    memset(&ci, 0, sizeof(ci));
04576    if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_GETCONF, &ci)) {
04577       ast_log(LOG_WARNING, "Failed to get conference info on channel %d: %s\n", p->channel, strerror(errno));
04578       return 0;
04579    }
04580    /* If we have no master and don't have a confno, then 
04581       if we're in a conference, it's probably a MeetMe room or
04582       some such, so don't let us 3-way out! */
04583    if ((p->subs[SUB_REAL].curconf.confno != ci.confno) || (p->subs[SUB_REAL].curconf.confmode != ci.confmode)) {
04584       ast_verb(3, "Avoiding 3-way call when in an external conference\n");
04585       return 1;
04586    }
04587    return 0;
04588 }
04589 
04590 /*! Checks channel for alarms
04591  * \param p a channel to check for alarms.
04592  * \returns the alarms on the span to which the channel belongs, or alarms on
04593  *          the channel if no span alarms.
04594  */
04595 static int get_alarms(struct dahdi_pvt *p)
04596 {
04597    int res;
04598    struct dahdi_spaninfo zi;
04599    struct dahdi_params params;
04600 
04601    memset(&zi, 0, sizeof(zi));
04602    zi.spanno = p->span;
04603 
04604    if ((res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SPANSTAT, &zi)) >= 0) {
04605       if (zi.alarms != DAHDI_ALARM_NONE)
04606          return zi.alarms;
04607    } else {
04608       ast_log(LOG_WARNING, "Unable to determine alarm on channel %d: %s\n", p->channel, strerror(errno));
04609       return 0;
04610    }
04611 
04612    /* No alarms on the span. Check for channel alarms. */
04613    memset(&params, 0, sizeof(params));
04614    if ((res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &params)) >= 0)
04615       return params.chan_alarms;
04616 
04617    ast_log(LOG_WARNING, "Unable to determine alarm on channel %d\n", p->channel);
04618 
04619    return DAHDI_ALARM_NONE;
04620 }
04621 
04622 static void dahdi_handle_dtmfup(struct ast_channel *ast, int idx, struct ast_frame **dest)
04623 {
04624    struct dahdi_pvt *p = ast->tech_pvt;
04625    struct ast_frame *f = *dest;
04626 
04627    ast_debug(1, "DTMF digit: %c on %s\n", f->subclass, ast->name);
04628 
04629    if (p->confirmanswer) {
04630       ast_debug(1, "Confirm answer on %s!\n", ast->name);
04631       /* Upon receiving a DTMF digit, consider this an answer confirmation instead
04632          of a DTMF digit */
04633       p->subs[idx].f.frametype = AST_FRAME_CONTROL;
04634       p->subs[idx].f.subclass = AST_CONTROL_ANSWER;
04635       *dest = &p->subs[idx].f;
04636       /* Reset confirmanswer so DTMF's will behave properly for the duration of the call */
04637       p->confirmanswer = 0;
04638    } else if (p->callwaitcas) {
04639       if ((f->subclass == 'A') || (f->subclass == 'D')) {
04640          ast_debug(1, "Got some DTMF, but it's for the CAS\n");
04641          if (p->cidspill)
04642             ast_free(p->cidspill);
04643          send_cwcidspill(p);
04644       }
04645       p->callwaitcas = 0;
04646       p->subs[idx].f.frametype = AST_FRAME_NULL;
04647       p->subs[idx].f.subclass = 0;
04648       *dest = &p->subs[idx].f;
04649    } else if (f->subclass == 'f') {
04650       /* Fax tone -- Handle and return NULL */
04651       if ((p->callprogress & CALLPROGRESS_FAX) && !p->faxhandled) {
04652          p->faxhandled = 1;
04653          if (strcmp(ast->exten, "fax")) {
04654             const char *target_context = S_OR(ast->macrocontext, ast->context);
04655 
04656             /* We need to unlock 'ast' here because ast_exists_extension has the
04657              * potential to start autoservice on the channel. Such action is prone
04658              * to deadlock.
04659              */
04660             ast_mutex_unlock(&p->lock);
04661             ast_channel_unlock(ast);
04662             if (ast_exists_extension(ast, target_context, "fax", 1, ast->cid.cid_num)) {
04663                ast_channel_lock(ast);
04664                ast_mutex_lock(&p->lock);
04665                ast_verb(3, "Redirecting %s to fax extension\n", ast->name);
04666                /* Save the DID/DNIS when we transfer the fax call to a "fax" extension */
04667                pbx_builtin_setvar_helper(ast, "FAXEXTEN", ast->exten);
04668                if (ast_async_goto(ast, target_context, "fax", 1))
04669                   ast_log(LOG_WARNING, "Failed to async goto '%s' into fax of '%s'\n", ast->name, target_context);
04670             } else {
04671                ast_channel_lock(ast);
04672                ast_mutex_lock(&p->lock);
04673                ast_log(LOG_NOTICE, "Fax detected, but no fax extension\n");
04674             }
04675          } else {
04676             ast_debug(1, "Already in a fax extension, not redirecting\n");
04677          }
04678       } else {
04679          ast_debug(1, "Fax already handled\n");
04680       }
04681       dahdi_confmute(p, 0);
04682       p->subs[idx].f.frametype = AST_FRAME_NULL;
04683       p->subs[idx].f.subclass = 0;
04684       *dest = &p->subs[idx].f;
04685    }
04686 }
04687          
04688 static void handle_alarms(struct dahdi_pvt *p, int alms)
04689 {
04690    const char *alarm_str = alarm2str(alms);
04691 
04692    ast_log(LOG_WARNING, "Detected alarm on channel %d: %s\n", p->channel, alarm_str);
04693    manager_event(EVENT_FLAG_SYSTEM, "Alarm",
04694             "Alarm: %s\r\n"
04695             "Channel: %d\r\n",
04696             alarm_str, p->channel);
04697 }
04698 
04699 static struct ast_frame *dahdi_handle_event(struct ast_channel *ast)
04700 {
04701    int res, x;
04702    int idx, mysig;
04703    char *c;
04704    struct dahdi_pvt *p = ast->tech_pvt;
04705    pthread_t threadid;
04706    struct ast_channel *chan;
04707    struct ast_frame *f;
04708 
04709    idx = dahdi_get_index(ast, p, 0);
04710    mysig = p->sig;
04711    if (p->outsigmod > -1)
04712       mysig = p->outsigmod;
04713    p->subs[idx].f.frametype = AST_FRAME_NULL;
04714    p->subs[idx].f.subclass = 0;
04715    p->subs[idx].f.datalen = 0;
04716    p->subs[idx].f.samples = 0;
04717    p->subs[idx].f.mallocd = 0;
04718    p->subs[idx].f.offset = 0;
04719    p->subs[idx].f.src = "dahdi_handle_event";
04720    p->subs[idx].f.data.ptr = NULL;
04721    f = &p->subs[idx].f;
04722 
04723    if (idx < 0)
04724       return &p->subs[idx].f;
04725    if (p->fake_event) {
04726       res = p->fake_event;
04727       p->fake_event = 0;
04728    } else
04729       res = dahdi_get_event(p->subs[idx].dfd);
04730 
04731    ast_debug(1, "Got event %s(%d) on channel %d (index %d)\n", event2str(res), res, p->channel, idx);
04732 
04733    if (res & (DAHDI_EVENT_PULSEDIGIT | DAHDI_EVENT_DTMFUP)) {
04734       p->pulsedial =  (res & DAHDI_EVENT_PULSEDIGIT) ? 1 : 0;
04735       ast_debug(1, "Detected %sdigit '%c'\n", p->pulsedial ? "pulse ": "", res & 0xff);
04736 #ifdef HAVE_PRI
04737       if (!p->proceeding && ((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP)) && p->pri && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)) {
04738          /* absorb event */
04739       } else {
04740 #endif
04741          dahdi_confmute(p, 0);
04742          p->subs[idx].f.frametype = AST_FRAME_DTMF_END;
04743          p->subs[idx].f.subclass = res & 0xff;
04744 #ifdef HAVE_PRI
04745       }
04746 #endif
04747       dahdi_handle_dtmfup(ast, idx, &f);
04748       return f;
04749    }
04750 
04751    if (res & DAHDI_EVENT_DTMFDOWN) {
04752       ast_debug(1, "DTMF Down '%c'\n", res & 0xff);
04753       /* Mute conference */
04754       dahdi_confmute(p, 1);
04755       p->subs[idx].f.frametype = AST_FRAME_DTMF_BEGIN;
04756       p->subs[idx].f.subclass = res & 0xff;
04757       return &p->subs[idx].f;
04758    }
04759 
04760    switch (res) {
04761       case DAHDI_EVENT_EC_DISABLED:
04762          ast_verb(3, "Channel %d echo canceler disabled due to CED detection\n", p->channel);
04763          p->echocanon = 0;
04764          break;
04765       case DAHDI_EVENT_BITSCHANGED:
04766          ast_log(LOG_WARNING, "Received bits changed on %s signalling?\n", sig2str(p->sig));
04767       case DAHDI_EVENT_PULSE_START:
04768          /* Stop tone if there's a pulse start and the PBX isn't started */
04769          if (!ast->pbx)
04770             tone_zone_play_tone(p->subs[idx].dfd, -1);
04771          break;   
04772       case DAHDI_EVENT_DIALCOMPLETE:
04773          if (p->inalarm) break;
04774          if ((p->radio || (p->oprmode < 0))) break;
04775          if (ioctl(p->subs[idx].dfd,DAHDI_DIALING,&x) == -1) {
04776             ast_log(LOG_DEBUG, "DAHDI_DIALING ioctl failed on %s: %s\n",ast->name, strerror(errno));
04777             return NULL;
04778          }
04779          if (!x) { /* if not still dialing in driver */
04780             dahdi_enable_ec(p);
04781             if (p->echobreak) {
04782                dahdi_train_ec(p);
04783                ast_copy_string(p->dop.dialstr, p->echorest, sizeof(p->dop.dialstr));
04784                p->dop.op = DAHDI_DIAL_OP_REPLACE;
04785                res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
04786                p->echobreak = 0;
04787             } else {
04788                p->dialing = 0;
04789                if ((mysig == SIG_E911) || (mysig == SIG_FGC_CAMA) || (mysig == SIG_FGC_CAMAMF)) {
04790                   /* if thru with dialing after offhook */
04791                   if (ast->_state == AST_STATE_DIALING_OFFHOOK) {
04792                      ast_setstate(ast, AST_STATE_UP);
04793                      p->subs[idx].f.frametype = AST_FRAME_CONTROL;
04794                      p->subs[idx].f.subclass = AST_CONTROL_ANSWER;
04795                      break;
04796                   } else { /* if to state wait for offhook to dial rest */
04797                      /* we now wait for off hook */
04798                      ast_setstate(ast,AST_STATE_DIALING_OFFHOOK);
04799                   }
04800                }
04801                if (ast->_state == AST_STATE_DIALING) {
04802                   if ((p->callprogress & CALLPROGRESS_PROGRESS) && CANPROGRESSDETECT(p) && p->dsp && p->outgoing) {
04803                      ast_debug(1, "Done dialing, but waiting for progress detection before doing more...\n");
04804                   } else if (p->confirmanswer || (!p->dialednone && ((mysig == SIG_EM) || (mysig == SIG_EM_E1) ||  (mysig == SIG_EMWINK) || (mysig == SIG_FEATD) || (mysig == SIG_FEATDMF_TA) || (mysig == SIG_FEATDMF) || (mysig == SIG_E911) || (mysig == SIG_FGC_CAMA) || (mysig == SIG_FGC_CAMAMF) || (mysig == SIG_FEATB) || (mysig == SIG_SF) || (mysig == SIG_SFWINK) || (mysig == SIG_SF_FEATD) || (mysig == SIG_SF_FEATDMF) || (mysig == SIG_SF_FEATB)))) {
04805                      ast_setstate(ast, AST_STATE_RINGING);
04806                   } else if (!p->answeronpolarityswitch) {
04807                      ast_setstate(ast, AST_STATE_UP);
04808                      p->subs[idx].f.frametype = AST_FRAME_CONTROL;
04809                      p->subs[idx].f.subclass = AST_CONTROL_ANSWER;
04810                      /* If aops=0 and hops=1, this is necessary */
04811                      p->polarity = POLARITY_REV;
04812                   } else {
04813                      /* Start clean, so we can catch the change to REV polarity when party answers */
04814                      p->polarity = POLARITY_IDLE;
04815                   }
04816                }
04817             }
04818          }
04819          break;
04820       case DAHDI_EVENT_ALARM:
04821 #ifdef HAVE_PRI
04822          if ((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP)) {
04823             if (!p->pri || !p->pri->pri || (pri_get_timer(p->pri->pri, PRI_TIMER_T309) < 0)) {
04824                /* T309 is not enabled : hangup calls when alarm occurs */
04825                if (p->call) {
04826                   if (p->pri && p->pri->pri) {
04827                      if (!pri_grab(p, p->pri)) {
04828                         pri_hangup(p->pri->pri, p->call, -1);
04829                         pri_destroycall(p->pri->pri, p->call);
04830                         p->call = NULL;
04831                         pri_rel(p->pri);
04832                      } else
04833                         ast_log(LOG_WARNING, "Failed to grab PRI!\n");
04834                   } else
04835                      ast_log(LOG_WARNING, "The PRI Call has not been destroyed\n");
04836                }
04837                if (p->owner)
04838                   p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
04839             }
04840          }
04841          if (p->bearer)
04842             p->bearer->inalarm = 1;
04843          else
04844 #endif
04845          p->inalarm = 1;
04846          res = get_alarms(p);
04847          handle_alarms(p, res);
04848 #ifdef HAVE_PRI
04849          if (!p->pri || !p->pri->pri || pri_get_timer(p->pri->pri, PRI_TIMER_T309) < 0) {
04850             /* fall through intentionally */
04851          } else {
04852             break;
04853          }
04854 #endif
04855 #ifdef HAVE_SS7
04856          if (p->sig == SIG_SS7)
04857             break;
04858 #endif
04859       case DAHDI_EVENT_ONHOOK:
04860          if (p->radio) {
04861             p->subs[idx].f.frametype = AST_FRAME_CONTROL;
04862             p->subs[idx].f.subclass = AST_CONTROL_RADIO_UNKEY;
04863             break;
04864          }
04865          if (p->oprmode < 0)
04866          {
04867             if (p->oprmode != -1) break;
04868             if ((p->sig == SIG_FXOLS) || (p->sig == SIG_FXOKS) || (p->sig == SIG_FXOGS))
04869             {
04870                /* Make sure it starts ringing */
04871                dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RINGOFF);
04872                dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RING);
04873                save_conference(p->oprpeer);
04874                tone_zone_play_tone(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
04875             }
04876             break;
04877          }
04878          switch (p->sig) {
04879          case SIG_FXOLS:
04880          case SIG_FXOGS:
04881          case SIG_FXOKS:
04882             p->onhooktime = time(NULL);
04883             p->msgstate = -1;
04884             /* Check for some special conditions regarding call waiting */
04885             if (idx == SUB_REAL) {
04886                /* The normal line was hung up */
04887                if (p->subs[SUB_CALLWAIT].owner) {
04888                   /* There's a call waiting call, so ring the phone, but make it unowned in the mean time */
04889                   swap_subs(p, SUB_CALLWAIT, SUB_REAL);
04890                   ast_verb(3, "Channel %d still has (callwait) call, ringing phone\n", p->channel);
04891                   unalloc_sub(p, SUB_CALLWAIT); 
04892 #if 0
04893                   p->subs[idx].needanswer = 0;
04894                   p->subs[idx].needringing = 0;
04895 #endif                  
04896                   p->callwaitingrepeat = 0;
04897                   p->cidcwexpire = 0;
04898                   p->owner = NULL;
04899                   /* Don't start streaming audio yet if the incoming call isn't up yet */
04900                   if (p->subs[SUB_REAL].owner->_state != AST_STATE_UP)
04901                      p->dialing = 1;
04902                   dahdi_ring_phone(p);
04903                } else if (p->subs[SUB_THREEWAY].owner) {
04904                   unsigned int mssinceflash;
04905                   /* Here we have to retain the lock on both the main channel, the 3-way channel, and
04906                      the private structure -- not especially easy or clean */
04907                   while (p->subs[SUB_THREEWAY].owner && ast_channel_trylock(p->subs[SUB_THREEWAY].owner)) {
04908                      /* Yuck, didn't get the lock on the 3-way, gotta release everything and re-grab! */
04909                      DLA_UNLOCK(&p->lock);
04910                      CHANNEL_DEADLOCK_AVOIDANCE(ast);
04911                      /* We can grab ast and p in that order, without worry.  We should make sure
04912                         nothing seriously bad has happened though like some sort of bizarre double
04913                         masquerade! */
04914                      DLA_LOCK(&p->lock);
04915                      if (p->owner != ast) {
04916                         ast_log(LOG_WARNING, "This isn't good...\n");
04917                         return NULL;
04918                      }
04919                   }
04920                   if (!p->subs[SUB_THREEWAY].owner) {
04921                      ast_log(LOG_NOTICE, "Whoa, threeway disappeared kinda randomly.\n");
04922                      return NULL;
04923                   }
04924                   mssinceflash = ast_tvdiff_ms(ast_tvnow(), p->flashtime);
04925                   ast_debug(1, "Last flash was %d ms ago\n", mssinceflash);
04926                   if (mssinceflash < MIN_MS_SINCE_FLASH) {
04927                      /* It hasn't been long enough since the last flashook.  This is probably a bounce on 
04928                         hanging up.  Hangup both channels now */
04929                      if (p->subs[SUB_THREEWAY].owner)
04930                         ast_queue_hangup_with_cause(p->subs[SUB_THREEWAY].owner, AST_CAUSE_NO_ANSWER);
04931                      p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
04932                      ast_debug(1, "Looks like a bounced flash, hanging up both calls on %d\n", p->channel);
04933                      ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
04934                   } else if ((ast->pbx) || (ast->_state == AST_STATE_UP)) {
04935                      if (p->transfer) {
04936                         /* In any case this isn't a threeway call anymore */
04937                         p->subs[SUB_REAL].inthreeway = 0;
04938                         p->subs[SUB_THREEWAY].inthreeway = 0;
04939                         /* Only attempt transfer if the phone is ringing; why transfer to busy tone eh? */
04940                         if (!p->transfertobusy && ast->_state == AST_STATE_BUSY) {
04941                            ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
04942                            /* Swap subs and dis-own channel */
04943                            swap_subs(p, SUB_THREEWAY, SUB_REAL);
04944                            p->owner = NULL;
04945                            /* Ring the phone */
04946                            dahdi_ring_phone(p);
04947                         } else {
04948                            if ((res = attempt_transfer(p)) < 0) {
04949                               p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
04950                               if (p->subs[SUB_THREEWAY].owner)
04951                                  ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
04952                            } else if (res) {
04953                               /* Don't actually hang up at this point */
04954                               if (p->subs[SUB_THREEWAY].owner)
04955                                  ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
04956                               break;
04957                            }
04958                         }
04959                      } else {
04960                         p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
04961                         if (p->subs[SUB_THREEWAY].owner)
04962                            ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
04963                      }
04964                   } else {
04965                      ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
04966                      /* Swap subs and dis-own channel */
04967                      swap_subs(p, SUB_THREEWAY, SUB_REAL);
04968                      p->owner = NULL;
04969                      /* Ring the phone */
04970                      dahdi_ring_phone(p);
04971                   }
04972                }
04973             } else {
04974                ast_log(LOG_WARNING, "Got a hangup and my index is %d?\n", idx);
04975             }
04976             /* Fall through */
04977          default:
04978             dahdi_disable_ec(p);
04979             return NULL;
04980          }
04981          break;
04982       case DAHDI_EVENT_RINGOFFHOOK:
04983          if (p->inalarm) break;
04984          if (p->oprmode < 0)
04985          {
04986             if ((p->sig == SIG_FXOLS) || (p->sig == SIG_FXOKS) || (p->sig == SIG_FXOGS))
04987             {
04988                /* Make sure it stops ringing */
04989                dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RINGOFF);
04990                tone_zone_play_tone(p->oprpeer->subs[SUB_REAL].dfd, -1);
04991                restore_conference(p->oprpeer);
04992             }
04993             break;
04994          }
04995          if (p->radio)
04996          {
04997             p->subs[idx].f.frametype = AST_FRAME_CONTROL;
04998             p->subs[idx].f.subclass = AST_CONTROL_RADIO_KEY;
04999             break;
05000          }
05001          /* for E911, its supposed to wait for offhook then dial
05002             the second half of the dial string */
05003          if (((mysig == SIG_E911) || (mysig == SIG_FGC_CAMA) || (mysig == SIG_FGC_CAMAMF)) && (ast->_state == AST_STATE_DIALING_OFFHOOK)) {
05004             c = strchr(p->dialdest, '/');
05005             if (c)
05006                c++;
05007             else
05008                c = p->dialdest;
05009             if (*c) snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*0%s#", c);
05010             else ast_copy_string(p->dop.dialstr,"M*2#", sizeof(p->dop.dialstr));
05011             if (strlen(p->dop.dialstr) > 4) {
05012                memset(p->echorest, 'w', sizeof(p->echorest) - 1);
05013                strcpy(p->echorest + (p->echotraining / 401) + 1, p->dop.dialstr + strlen(p->dop.dialstr) - 2);
05014                p->echorest[sizeof(p->echorest) - 1] = '\0';
05015                p->echobreak = 1;
05016                p->dop.dialstr[strlen(p->dop.dialstr)-2] = '\0';
05017             } else
05018                p->echobreak = 0;
05019             if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop)) {
05020                int saveerr = errno;
05021 
05022                x = DAHDI_ONHOOK;
05023                ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
05024                ast_log(LOG_WARNING, "Dialing failed on channel %d: %s\n", p->channel, strerror(saveerr));
05025                return NULL;
05026                }
05027             p->dialing = 1;
05028             return &p->subs[idx].f;
05029          }
05030          switch (p->sig) {
05031          case SIG_FXOLS:
05032          case SIG_FXOGS:
05033          case SIG_FXOKS:
05034             switch (ast->_state) {
05035             case AST_STATE_RINGING:
05036                dahdi_enable_ec(p);
05037                dahdi_train_ec(p);
05038                p->subs[idx].f.frametype = AST_FRAME_CONTROL;
05039                p->subs[idx].f.subclass = AST_CONTROL_ANSWER;
05040                /* Make sure it stops ringing */
05041                p->subs[SUB_REAL].needringing = 0;
05042                dahdi_set_hook(p->subs[idx].dfd, DAHDI_OFFHOOK);
05043                ast_debug(1, "channel %d answered\n", p->channel);
05044                if (p->cidspill) {
05045                   /* Cancel any running CallerID spill */
05046                   ast_free(p->cidspill);
05047                   p->cidspill = NULL;
05048                }
05049                p->dialing = 0;
05050                p->callwaitcas = 0;
05051                if (p->confirmanswer) {
05052                   /* Ignore answer if "confirm answer" is enabled */
05053                   p->subs[idx].f.frametype = AST_FRAME_NULL;
05054                   p->subs[idx].f.subclass = 0;
05055                } else if (!ast_strlen_zero(p->dop.dialstr)) {
05056                   /* nick@dccinc.com 4/3/03 - fxo should be able to do deferred dialing */
05057                   res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
05058                   if (res < 0) {
05059                      ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno));
05060                      p->dop.dialstr[0] = '\0';
05061                      return NULL;
05062                   } else {
05063                      ast_debug(1, "Sent FXO deferred digit string: %s\n", p->dop.dialstr);
05064                      p->subs[idx].f.frametype = AST_FRAME_NULL;
05065                      p->subs[idx].f.subclass = 0;
05066                      p->dialing = 1;
05067                   }
05068                   p->dop.dialstr[0] = '\0';
05069                   ast_setstate(ast, AST_STATE_DIALING);
05070                } else
05071                   ast_setstate(ast, AST_STATE_UP);
05072                return &p->subs[idx].f;
05073             case AST_STATE_DOWN:
05074                ast_setstate(ast, AST_STATE_RING);
05075                ast->rings = 1;
05076                p->subs[idx].f.frametype = AST_FRAME_CONTROL;
05077                p->subs[idx].f.subclass = AST_CONTROL_OFFHOOK;
05078                ast_debug(1, "channel %d picked up\n", p->channel);
05079                return &p->subs[idx].f;
05080             case AST_STATE_UP:
05081                /* Make sure it stops ringing */
05082                dahdi_set_hook(p->subs[idx].dfd, DAHDI_OFFHOOK);
05083                /* Okay -- probably call waiting*/
05084                if (ast_bridged_channel(p->owner))
05085                   ast_queue_control(p->owner, AST_CONTROL_UNHOLD);
05086                p->subs[idx].needunhold = 1;
05087                break;
05088             case AST_STATE_RESERVED:
05089                /* Start up dialtone */
05090                if (has_voicemail(p))
05091                   res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_STUTTER);
05092                else
05093                   res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_DIALTONE);
05094                break;
05095             default:
05096                ast_log(LOG_WARNING, "FXO phone off hook in weird state %d??\n", ast->_state);
05097             }
05098             break;
05099          case SIG_FXSLS:
05100          case SIG_FXSGS:
05101          case SIG_FXSKS:
05102             if (ast->_state == AST_STATE_RING) {
05103                p->ringt = p->ringt_base;
05104             }
05105 
05106             /* If we get a ring then we cannot be in 
05107              * reversed polarity. So we reset to idle */
05108             ast_debug(1, "Setting IDLE polarity due "
05109                "to ring. Old polarity was %d\n", 
05110                p->polarity);
05111             p->polarity = POLARITY_IDLE;
05112 
05113             /* Fall through */
05114          case SIG_EM:
05115          case SIG_EM_E1:
05116          case SIG_EMWINK:
05117          case SIG_FEATD:
05118          case SIG_FEATDMF:
05119          case SIG_FEATDMF_TA:
05120          case SIG_E911:
05121          case SIG_FGC_CAMA:
05122          case SIG_FGC_CAMAMF:
05123          case SIG_FEATB:
05124          case SIG_SF:
05125          case SIG_SFWINK:
05126          case SIG_SF_FEATD:
05127          case SIG_SF_FEATDMF:
05128          case SIG_SF_FEATB:
05129             if (ast->_state == AST_STATE_PRERING)
05130                ast_setstate(ast, AST_STATE_RING);
05131             if ((ast->_state == AST_STATE_DOWN) || (ast->_state == AST_STATE_RING)) {
05132                ast_debug(1, "Ring detected\n");
05133                p->subs[idx].f.frametype = AST_FRAME_CONTROL;
05134                p->subs[idx].f.subclass = AST_CONTROL_RING;
05135             } else if (p->outgoing && ((ast->_state == AST_STATE_RINGING) || (ast->_state == AST_STATE_DIALING))) {
05136                ast_debug(1, "Line answered\n");
05137                if (p->confirmanswer) {
05138                   p->subs[idx].f.frametype = AST_FRAME_NULL;
05139                   p->subs[idx].f.subclass = 0;
05140                } else {
05141                   p->subs[idx].f.frametype = AST_FRAME_CONTROL;
05142                   p->subs[idx].f.subclass = AST_CONTROL_ANSWER;
05143                   ast_setstate(ast, AST_STATE_UP);
05144                }
05145             } else if (ast->_state != AST_STATE_RING)
05146                ast_log(LOG_WARNING, "Ring/Off-hook in strange state %d on channel %d\n", ast->_state, p->channel);
05147             break;
05148          default:
05149             ast_log(LOG_WARNING, "Don't know how to handle ring/off hook for signalling %d\n", p->sig);
05150          }
05151          break;
05152       case DAHDI_EVENT_RINGBEGIN:
05153          switch (p->sig) {
05154          case SIG_FXSLS:
05155          case SIG_FXSGS:
05156          case SIG_FXSKS:
05157             if (ast->_state == AST_STATE_RING) {
05158                p->ringt = p->ringt_base;
05159             }
05160             break;
05161          }
05162          break;
05163       case DAHDI_EVENT_RINGEROFF:
05164          if (p->inalarm) break;
05165          if ((p->radio || (p->oprmode < 0))) break;
05166          ast->rings++;
05167          if ((ast->rings > p->cidrings) && (p->cidspill)) {
05168             ast_log(LOG_WARNING, "Didn't finish Caller-ID spill.  Cancelling.\n");
05169             ast_free(p->cidspill);
05170             p->cidspill = NULL;
05171             p->callwaitcas = 0;
05172          }
05173          p->subs[idx].f.frametype = AST_FRAME_CONTROL;
05174          p->subs[idx].f.subclass = AST_CONTROL_RINGING;
05175          break;
05176       case DAHDI_EVENT_RINGERON:
05177          break;
05178       case DAHDI_EVENT_NOALARM:
05179          p->inalarm = 0;
05180 #ifdef HAVE_PRI
05181          /* Extremely unlikely but just in case */
05182          if (p->bearer)
05183             p->bearer->inalarm = 0;
05184 #endif            
05185          ast_log(LOG_NOTICE, "Alarm cleared on channel %d\n", p->channel);
05186          manager_event(EVENT_FLAG_SYSTEM, "AlarmClear",
05187                         "Channel: %d\r\n", p->channel);
05188          break;
05189       case DAHDI_EVENT_WINKFLASH:
05190          if (p->inalarm) break;
05191          if (p->radio) break;
05192          if (p->oprmode < 0) break;
05193          if (p->oprmode > 1)
05194          {
05195             struct dahdi_params par;
05196 
05197             memset(&par, 0, sizeof(par));
05198             if (ioctl(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par) != -1)
05199             {
05200                if (!par.rxisoffhook)
05201                {
05202                   /* Make sure it stops ringing */
05203                   dahdi_set_hook(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_RINGOFF);
05204                   dahdi_set_hook(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_RING);
05205                   save_conference(p);
05206                   tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
05207                }
05208             }
05209             break;
05210          }
05211          /* Remember last time we got a flash-hook */
05212          p->flashtime = ast_tvnow();
05213          switch (mysig) {
05214          case SIG_FXOLS:
05215          case SIG_FXOGS:
05216          case SIG_FXOKS:
05217             ast_debug(1, "Winkflash, index: %d, normal: %d, callwait: %d, thirdcall: %d\n",
05218                idx, p->subs[SUB_REAL].dfd, p->subs[SUB_CALLWAIT].dfd, p->subs[SUB_THREEWAY].dfd);
05219             p->callwaitcas = 0;
05220 
05221             if (idx != SUB_REAL) {
05222                ast_log(LOG_WARNING, "Got flash hook with index %d on channel %d?!?\n", idx, p->channel);
05223                goto winkflashdone;
05224             }
05225             
05226             if (p->subs[SUB_CALLWAIT].owner) {
05227                /* Swap to call-wait */
05228                swap_subs(p, SUB_REAL, SUB_CALLWAIT);
05229                tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
05230                p->owner = p->subs[SUB_REAL].owner;
05231                ast_debug(1, "Making %s the new owner\n", p->owner->name);
05232                if (p->owner->_state == AST_STATE_RINGING) {
05233                   ast_setstate(p->owner, AST_STATE_UP);
05234                   p->subs[SUB_REAL].needanswer = 1;
05235                }
05236                p->callwaitingrepeat = 0;
05237                p->cidcwexpire = 0;
05238                /* Start music on hold if appropriate */
05239                if (!p->subs[SUB_CALLWAIT].inthreeway && ast_bridged_channel(p->subs[SUB_CALLWAIT].owner)) {
05240                   ast_queue_control_data(p->subs[SUB_CALLWAIT].owner, AST_CONTROL_HOLD,
05241                      S_OR(p->mohsuggest, NULL),
05242                      !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
05243                }
05244                p->subs[SUB_CALLWAIT].needhold = 1;
05245                if (ast_bridged_channel(p->subs[SUB_REAL].owner)) {
05246                   ast_queue_control_data(p->subs[SUB_REAL].owner, AST_CONTROL_HOLD,
05247                      S_OR(p->mohsuggest, NULL),
05248                      !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
05249                }
05250                p->subs[SUB_REAL].needunhold = 1;
05251             } else if (!p->subs[SUB_THREEWAY].owner) {
05252                if (!p->threewaycalling) {
05253                   /* Just send a flash if no 3-way calling */
05254                   p->subs[SUB_REAL].needflash = 1;
05255                   goto winkflashdone;
05256                } else if (!check_for_conference(p)) {
05257                   char cid_num[256];
05258                   char cid_name[256];
05259 
05260                   cid_num[0] = 0;
05261                   cid_name[0] = 0;
05262                   if (p->dahditrcallerid && p->owner) {
05263                      if (p->owner->cid.cid_num)
05264                         ast_copy_string(cid_num, p->owner->cid.cid_num, sizeof(cid_num));
05265                      if (p->owner->cid.cid_name)
05266                         ast_copy_string(cid_name, p->owner->cid.cid_name, sizeof(cid_name));
05267                   }
05268                   /* XXX This section needs much more error checking!!! XXX */
05269                   /* Start a 3-way call if feasible */
05270                   if (!((ast->pbx) ||
05271                         (ast->_state == AST_STATE_UP) ||
05272                         (ast->_state == AST_STATE_RING))) {
05273                      ast_debug(1, "Flash when call not up or ringing\n");
05274                      goto winkflashdone;
05275                   }
05276                   if (alloc_sub(p, SUB_THREEWAY)) {
05277                      ast_log(LOG_WARNING, "Unable to allocate three-way subchannel\n");
05278                      goto winkflashdone;
05279                   }
05280                   /* Make new channel */
05281                   chan = dahdi_new(p, AST_STATE_RESERVED, 0, SUB_THREEWAY, 0, 0);
05282                   if (p->dahditrcallerid) {
05283                      if (!p->origcid_num)
05284                         p->origcid_num = ast_strdup(p->cid_num);
05285                      if (!p->origcid_name)
05286                         p->origcid_name = ast_strdup(p->cid_name);
05287                      ast_copy_string(p->cid_num, cid_num, sizeof(p->cid_num));
05288                      ast_copy_string(p->cid_name, cid_name, sizeof(p->cid_name));
05289                   }
05290                   /* Swap things around between the three-way and real call */
05291                   swap_subs(p, SUB_THREEWAY, SUB_REAL);
05292                   /* Disable echo canceller for better dialing */
05293                   dahdi_disable_ec(p);
05294                   res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_DIALRECALL);
05295                   if (res)
05296                      ast_log(LOG_WARNING, "Unable to start dial recall tone on channel %d\n", p->channel);
05297                   p->owner = chan;
05298                   if (!chan) {
05299                      ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", p->channel);
05300                   } else if (ast_pthread_create_detached(&threadid, NULL, ss_thread, chan)) {
05301                      ast_log(LOG_WARNING, "Unable to start simple switch on channel %d\n", p->channel);
05302                      res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
05303                      dahdi_enable_ec(p);
05304                      ast_hangup(chan);
05305                   } else {
05306                      struct ast_channel *other = ast_bridged_channel(p->subs[SUB_THREEWAY].owner);
05307                      int way3bridge = 0, cdr3way = 0;
05308                      
05309                      if (!other) {
05310                         other = ast_bridged_channel(p->subs[SUB_REAL].owner);
05311                      } else
05312                         way3bridge = 1;
05313                      
05314                      if (p->subs[SUB_THREEWAY].owner->cdr)
05315                         cdr3way = 1;
05316                      
05317                      ast_verb(3, "Started three way call on channel %d\n", p->channel);
05318 
05319                      /* Start music on hold if appropriate */
05320                      if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
05321                         ast_queue_control_data(p->subs[SUB_THREEWAY].owner, AST_CONTROL_HOLD,
05322                            S_OR(p->mohsuggest, NULL),
05323                            !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
05324                      }
05325                      p->subs[SUB_THREEWAY].needhold = 1;
05326                   }
05327                }
05328             } else {
05329                /* Already have a 3 way call */
05330                if (p->subs[SUB_THREEWAY].inthreeway) {
05331                   /* Call is already up, drop the last person */
05332                   ast_debug(1, "Got flash with three way call up, dropping last call on %d\n", p->channel);
05333                   /* If the primary call isn't answered yet, use it */
05334                   if ((p->subs[SUB_REAL].owner->_state != AST_STATE_UP) && (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_UP)) {
05335                      /* Swap back -- we're dropping the real 3-way that isn't finished yet*/
05336                      swap_subs(p, SUB_THREEWAY, SUB_REAL);
05337                      p->owner = p->subs[SUB_REAL].owner;
05338                   }
05339                   /* Drop the last call and stop the conference */
05340                   ast_verb(3, "Dropping three-way call on %s\n", p->subs[SUB_THREEWAY].owner->name);
05341                   p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
05342                   p->subs[SUB_REAL].inthreeway = 0;
05343                   p->subs[SUB_THREEWAY].inthreeway = 0;
05344                } else {
05345                   /* Lets see what we're up to */
05346                   if (((ast->pbx) || (ast->_state == AST_STATE_UP)) && 
05347                       (p->transfertobusy || (ast->_state != AST_STATE_BUSY))) {
05348                      int otherindex = SUB_THREEWAY;
05349                      struct ast_channel *other = ast_bridged_channel(p->subs[SUB_THREEWAY].owner);
05350                      int way3bridge = 0, cdr3way = 0;
05351                      
05352                      if (!other) {
05353                         other = ast_bridged_channel(p->subs[SUB_REAL].owner);
05354                      } else
05355                         way3bridge = 1;
05356                      
05357                      if (p->subs[SUB_THREEWAY].owner->cdr)
05358                         cdr3way = 1;
05359 
05360                      ast_verb(3, "Building conference on call on %s and %s\n", p->subs[SUB_THREEWAY].owner->name, p->subs[SUB_REAL].owner->name);
05361                      /* Put them in the threeway, and flip */
05362                      p->subs[SUB_THREEWAY].inthreeway = 1;
05363                      p->subs[SUB_REAL].inthreeway = 1;
05364                      if (ast->_state == AST_STATE_UP) {
05365                         swap_subs(p, SUB_THREEWAY, SUB_REAL);
05366                         otherindex = SUB_REAL;
05367                      }
05368                      if (p->subs[otherindex].owner && ast_bridged_channel(p->subs[otherindex].owner))
05369                         ast_queue_control(p->subs[otherindex].owner, AST_CONTROL_UNHOLD);
05370                      p->subs[otherindex].needunhold = 1;
05371                      p->owner = p->subs[SUB_REAL].owner;
05372                      if (ast->_state == AST_STATE_RINGING) {
05373                         ast_debug(1, "Enabling ringtone on real and threeway\n");
05374                         res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
05375                         res = tone_zone_play_tone(p->subs[SUB_THREEWAY].dfd, DAHDI_TONE_RINGTONE);
05376                      }
05377                   } else {
05378                      ast_verb(3, "Dumping incomplete call on on %s\n", p->subs[SUB_THREEWAY].owner->name);
05379                      swap_subs(p, SUB_THREEWAY, SUB_REAL);
05380                      p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
05381                      p->owner = p->subs[SUB_REAL].owner;
05382                      if (p->subs[SUB_REAL].owner && ast_bridged_channel(p->subs[SUB_REAL].owner))
05383                         ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
05384                      p->subs[SUB_REAL].needunhold = 1;
05385                      dahdi_enable_ec(p);
05386                   }
05387                      
05388                }
05389             }
05390          winkflashdone:              
05391             update_conf(p);
05392             break;
05393          case SIG_EM:
05394          case SIG_EM_E1:
05395          case SIG_FEATD:
05396          case SIG_SF:
05397          case SIG_SFWINK:
05398          case SIG_SF_FEATD:
05399          case SIG_FXSLS:
05400          case SIG_FXSGS:
05401             if (option_debug) {
05402                if (p->dialing)
05403                   ast_debug(1, "Ignoring wink on channel %d\n", p->channel);
05404                else
05405                   ast_debug(1, "Got wink in weird state %d on channel %d\n", ast->_state, p->channel);
05406             }
05407             break;
05408          case SIG_FEATDMF_TA:
05409             switch (p->whichwink) {
05410             case 0:
05411                ast_debug(1, "ANI2 set to '%d' and ANI is '%s'\n", p->owner->cid.cid_ani2, p->owner->cid.cid_ani);
05412                snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*%d%s#", p->owner->cid.cid_ani2, p->owner->cid.cid_ani);
05413                break;
05414             case 1:
05415                ast_copy_string(p->dop.dialstr, p->finaldial, sizeof(p->dop.dialstr));
05416                break;
05417             case 2:
05418                ast_log(LOG_WARNING, "Received unexpected wink on channel of type SIG_FEATDMF_TA\n");
05419                return NULL;
05420             }
05421             p->whichwink++;
05422             /* Fall through */
05423          case SIG_FEATDMF:
05424          case SIG_E911:
05425          case SIG_FGC_CAMAMF:
05426          case SIG_FGC_CAMA:
05427          case SIG_FEATB:
05428          case SIG_SF_FEATDMF:
05429          case SIG_SF_FEATB:
05430          case SIG_EMWINK:
05431             /* FGD MF and EMWINK *Must* wait for wink */
05432             if (!ast_strlen_zero(p->dop.dialstr)) {
05433                res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
05434                if (res < 0) {
05435                   ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno));
05436                   p->dop.dialstr[0] = '\0';
05437                   return NULL;
05438                } else 
05439                   ast_debug(1, "Sent deferred digit string: %s\n", p->dop.dialstr);
05440             }
05441             p->dop.dialstr[0] = '\0';
05442             break;
05443          default:
05444             ast_log(LOG_WARNING, "Don't know how to handle ring/off hook for signalling %d\n", p->sig);
05445          }
05446          break;
05447       case DAHDI_EVENT_HOOKCOMPLETE:
05448          if (p->inalarm) break;
05449          if ((p->radio || (p->oprmode < 0))) break;
05450          switch (mysig) {
05451          case SIG_FXSLS:  /* only interesting for FXS */
05452          case SIG_FXSGS:
05453          case SIG_FXSKS:
05454          case SIG_EM:
05455          case SIG_EM_E1:
05456          case SIG_EMWINK:
05457          case SIG_FEATD:
05458          case SIG_SF:
05459          case SIG_SFWINK:
05460          case SIG_SF_FEATD:
05461             if (!ast_strlen_zero(p->dop.dialstr)) {
05462                res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
05463                if (res < 0) {
05464                   ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno));
05465                   p->dop.dialstr[0] = '\0';
05466                   return NULL;
05467                } else 
05468                   ast_debug(1, "Sent deferred digit string: %s\n", p->dop.dialstr);
05469             }
05470             p->dop.dialstr[0] = '\0';
05471             p->dop.op = DAHDI_DIAL_OP_REPLACE;
05472             break;
05473          case SIG_FEATDMF:
05474          case SIG_FEATDMF_TA:
05475          case SIG_E911:
05476          case SIG_FGC_CAMA:
05477          case SIG_FGC_CAMAMF:
05478          case SIG_FEATB:
05479          case SIG_SF_FEATDMF:
05480          case SIG_SF_FEATB:
05481             ast_debug(1, "Got hook complete in MF FGD, waiting for wink now on channel %d\n",p->channel);
05482             break;
05483          default:
05484             break;
05485          }
05486          break;
05487       case DAHDI_EVENT_POLARITY:
05488          /*
05489           * If we get a Polarity Switch event, this could be
05490           * due to line seizure, remote end connect or remote end disconnect.
05491           *
05492           * Check to see if we should change the polarity state and
05493           * mark the channel as UP or if this is an indication
05494           * of remote end disconnect.
05495           */
05496 
05497          if (p->polarityonanswerdelay > 0) {
05498             /* check if event is not too soon after OffHook or Answer */
05499                if (ast_tvdiff_ms(ast_tvnow(), p->polaritydelaytv) > p->polarityonanswerdelay) {
05500                switch (ast->_state) {
05501                case AST_STATE_DIALING:       /*!< Digits (or equivalent) have been dialed */
05502                case AST_STATE_RINGING:       /*!< Remote end is ringing */
05503                   if (p->answeronpolarityswitch) {
05504                      ast_debug(1, "Answering on polarity switch! channel %d\n", p->channel);
05505                      ast_setstate(p->owner, AST_STATE_UP);
05506                      p->polarity = POLARITY_REV;
05507                      if (p->hanguponpolarityswitch) {
05508                         p->polaritydelaytv = ast_tvnow();
05509                      }
05510                   } else {
05511                      ast_debug(1, "Ignore Answer on polarity switch, channel %d\n", p->channel);
05512                   }
05513                   break;
05514                case AST_STATE_UP:         /*!< Line is up */
05515                case AST_STATE_RING:       /*!< Line is ringing */
05516                   if (p->hanguponpolarityswitch) {
05517                      ast_debug(1, "HangingUp on polarity switch! channel %d\n", p->channel);
05518                      ast_softhangup(p->owner, AST_SOFTHANGUP_EXPLICIT);
05519                      p->polarity = POLARITY_IDLE;
05520                   } else {
05521                      ast_debug(1, "Ignore Hangup on polarity switch, channel %d\n", p->channel);
05522                   }
05523                   break;
05524 
05525                case AST_STATE_DOWN:       /*!< Channel is down and available */
05526                case AST_STATE_RESERVED:      /*!< Channel is down, but reserved */
05527                case AST_STATE_OFFHOOK:       /*!< Channel is off hook */
05528                case AST_STATE_BUSY:       /*!< Line is busy */
05529                case AST_STATE_DIALING_OFFHOOK:     /*!< Digits (or equivalent) have been dialed while offhook */
05530                case AST_STATE_PRERING:       /*!< Channel has detected an incoming call and is waiting for ring */
05531                default:
05532                   if (p->answeronpolarityswitch || p->hanguponpolarityswitch) {
05533                      ast_debug(1, "Ignoring Polarity switch on channel %d, state %d\n", p->channel, ast->_state);
05534                   }
05535 
05536                }
05537 
05538             } else {
05539                /* event is too soon after OffHook or Answer */
05540                switch (ast->_state) {
05541                case AST_STATE_DIALING:       /*!< Digits (or equivalent) have been dialed */
05542                case AST_STATE_RINGING:       /*!< Remote end is ringing */
05543                   if (p->answeronpolarityswitch) {
05544                      ast_debug(1, "Polarity switch detected but NOT answering (too close to OffHook event) on channel %d, state %d\n", p->channel, ast->_state);
05545                   }
05546                   break;
05547 
05548                case AST_STATE_UP:         /*!< Line is up */
05549                case AST_STATE_RING:       /*!< Line is ringing */
05550                   if (p->hanguponpolarityswitch) {
05551                      ast_debug(1, "Polarity switch detected but NOT hanging up (too close to Answer event) on channel %d, state %d\n", p->channel, ast->_state);
05552                   }
05553                   break;
05554 
05555                default: 
05556                   if (p->answeronpolarityswitch || p->hanguponpolarityswitch) {
05557                      ast_debug(1, "Polarity switch detected (too close to previous event) on channel %d, state %d\n", p->channel, ast->_state);
05558                   }
05559                }
05560             }
05561          }
05562                         /* Added more log_debug information below to provide a better indication of what is going on */
05563          ast_debug(1, "Polarity Reversal event occured - DEBUG 2: channel %d, state %d, pol= %d, aonp= %d, honp= %d, pdelay= %d, tv= %d\n", p->channel, ast->_state, p->polarity, p->answeronpolarityswitch, p->hanguponpolarityswitch, p->polarityonanswerdelay, ast_tvdiff_ms(ast_tvnow(), p->polaritydelaytv) );
05564          break;
05565       default:
05566          ast_debug(1, "Dunno what to do with event %d on channel %d\n", res, p->channel);
05567    }
05568    return &p->subs[idx].f;
05569 }
05570 
05571 static struct ast_frame *__dahdi_exception(struct ast_channel *ast)
05572 {
05573    struct dahdi_pvt *p = ast->tech_pvt;
05574    int res;
05575    int usedindex=-1;
05576    int idx;
05577    struct ast_frame *f;
05578 
05579 
05580    idx = dahdi_get_index(ast, p, 1);
05581    
05582    p->subs[idx].f.frametype = AST_FRAME_NULL;
05583    p->subs[idx].f.datalen = 0;
05584    p->subs[idx].f.samples = 0;
05585    p->subs[idx].f.mallocd = 0;
05586    p->subs[idx].f.offset = 0;
05587    p->subs[idx].f.subclass = 0;
05588    p->subs[idx].f.delivery = ast_tv(0,0);
05589    p->subs[idx].f.src = "dahdi_exception";
05590    p->subs[idx].f.data.ptr = NULL;
05591    
05592    
05593    if ((!p->owner) && (!(p->radio || (p->oprmode < 0)))) {
05594       /* If nobody owns us, absorb the event appropriately, otherwise
05595          we loop indefinitely.  This occurs when, during call waiting, the
05596          other end hangs up our channel so that it no longer exists, but we
05597          have neither FLASH'd nor ONHOOK'd to signify our desire to
05598          change to the other channel. */
05599       if (p->fake_event) {
05600          res = p->fake_event;
05601          p->fake_event = 0;
05602       } else
05603          res = dahdi_get_event(p->subs[SUB_REAL].dfd);
05604       /* Switch to real if there is one and this isn't something really silly... */
05605       if ((res != DAHDI_EVENT_RINGEROFF) && (res != DAHDI_EVENT_RINGERON) &&
05606          (res != DAHDI_EVENT_HOOKCOMPLETE)) {
05607          ast_debug(1, "Restoring owner of channel %d on event %d\n", p->channel, res);
05608          p->owner = p->subs[SUB_REAL].owner;
05609          if (p->owner && ast_bridged_channel(p->owner))
05610             ast_queue_control(p->owner, AST_CONTROL_UNHOLD);
05611          p->subs[SUB_REAL].needunhold = 1;
05612       }
05613       switch (res) {
05614       case DAHDI_EVENT_ONHOOK:
05615          dahdi_disable_ec(p);
05616          if (p->owner) {
05617             ast_verb(3, "Channel %s still has call, ringing phone\n", p->owner->name);
05618             dahdi_ring_phone(p);
05619             p->callwaitingrepeat = 0;
05620             p->cidcwexpire = 0;
05621          } else
05622             ast_log(LOG_WARNING, "Absorbed on hook, but nobody is left!?!?\n");
05623          update_conf(p);
05624          break;
05625       case DAHDI_EVENT_RINGOFFHOOK:
05626          dahdi_enable_ec(p);
05627          dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
05628          if (p->owner && (p->owner->_state == AST_STATE_RINGING)) {
05629             p->subs[SUB_REAL].needanswer = 1;
05630             p->dialing = 0;
05631          }
05632          break;
05633       case DAHDI_EVENT_HOOKCOMPLETE:
05634       case DAHDI_EVENT_RINGERON:
05635       case DAHDI_EVENT_RINGEROFF:
05636          /* Do nothing */
05637          break;
05638       case DAHDI_EVENT_WINKFLASH:
05639          p->flashtime = ast_tvnow();
05640          if (p->owner) {
05641             ast_verb(3, "Channel %d flashed to other channel %s\n", p->channel, p->owner->name);
05642             if (p->owner->_state != AST_STATE_UP) {
05643                /* Answer if necessary */
05644                usedindex = dahdi_get_index(p->owner, p, 0);
05645                if (usedindex > -1) {
05646                   p->subs[usedindex].needanswer = 1;
05647                }
05648                ast_setstate(p->owner, AST_STATE_UP);
05649             }
05650             p->callwaitingrepeat = 0;
05651             p->cidcwexpire = 0;
05652             if (ast_bridged_channel(p->owner))
05653                ast_queue_control(p->owner, AST_CONTROL_UNHOLD);
05654             p->subs[SUB_REAL].needunhold = 1;
05655          } else
05656             ast_log(LOG_WARNING, "Absorbed on hook, but nobody is left!?!?\n");
05657          update_conf(p);
05658          break;
05659       default:
05660          ast_log(LOG_WARNING, "Don't know how to absorb event %s\n", event2str(res));
05661       }
05662       f = &p->subs[idx].f;
05663       return f;
05664    }
05665    if (!(p->radio || (p->oprmode < 0))) 
05666       ast_debug(1, "Exception on %d, channel %d\n", ast->fds[0],p->channel);
05667    /* If it's not us, return NULL immediately */
05668    if (ast != p->owner) {
05669       ast_log(LOG_WARNING, "We're %s, not %s\n", ast->name, p->owner->name);
05670       f = &p->subs[idx].f;
05671       return f;
05672    }
05673    f = dahdi_handle_event(ast);
05674    return f;
05675 }
05676 
05677 static struct ast_frame *dahdi_exception(struct ast_channel *ast)
05678 {
05679    struct dahdi_pvt *p = ast->tech_pvt;
05680    struct ast_frame *f;
05681    ast_mutex_lock(&p->lock);
05682    f = __dahdi_exception(ast);
05683    ast_mutex_unlock(&p->lock);
05684    return f;
05685 }
05686 
05687 static struct ast_frame  *dahdi_read(struct ast_channel *ast)
05688 {
05689    struct dahdi_pvt *p = ast->tech_pvt;
05690    int res;
05691    int idx;
05692    void *readbuf;
05693    struct ast_frame *f;
05694 
05695    while (ast_mutex_trylock(&p->lock)) {
05696       CHANNEL_DEADLOCK_AVOIDANCE(ast);
05697    }
05698 
05699    idx = dahdi_get_index(ast, p, 0);
05700    
05701    /* Hang up if we don't really exist */
05702    if (idx < 0)   {
05703       ast_log(LOG_WARNING, "We dont exist?\n");
05704       ast_mutex_unlock(&p->lock);
05705       return NULL;
05706    }
05707    
05708    if ((p->radio || (p->oprmode < 0)) && p->inalarm) {
05709       ast_mutex_unlock(&p->lock);
05710       return NULL;
05711    }
05712 
05713    p->subs[idx].f.frametype = AST_FRAME_NULL;
05714    p->subs[idx].f.datalen = 0;
05715    p->subs[idx].f.samples = 0;
05716    p->subs[idx].f.mallocd = 0;
05717    p->subs[idx].f.offset = 0;
05718    p->subs[idx].f.subclass = 0;
05719    p->subs[idx].f.delivery = ast_tv(0,0);
05720    p->subs[idx].f.src = "dahdi_read";
05721    p->subs[idx].f.data.ptr = NULL;
05722    
05723    /* make sure it sends initial key state as first frame */
05724    if ((p->radio || (p->oprmode < 0)) && (!p->firstradio))
05725    {
05726       struct dahdi_params ps;
05727 
05728       memset(&ps, 0, sizeof(ps));
05729       ps.channo = p->channel;
05730       if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &ps) < 0) {
05731          ast_mutex_unlock(&p->lock);
05732          return NULL;
05733       }
05734       p->firstradio = 1;
05735       p->subs[idx].f.frametype = AST_FRAME_CONTROL;
05736       if (ps.rxisoffhook)
05737       {
05738          p->subs[idx].f.subclass = AST_CONTROL_RADIO_KEY;
05739       }
05740       else
05741       {
05742          p->subs[idx].f.subclass = AST_CONTROL_RADIO_UNKEY;
05743       }
05744       ast_mutex_unlock(&p->lock);
05745       return &p->subs[idx].f;
05746    }
05747    if (p->ringt == 1) {
05748       ast_mutex_unlock(&p->lock);
05749       return NULL;
05750    }
05751    else if (p->ringt > 0) 
05752       p->ringt--;
05753 
05754    if (p->subs[idx].needringing) {
05755       /* Send ringing frame if requested */
05756       p->subs[idx].needringing = 0;
05757       p->subs[idx].f.frametype = AST_FRAME_CONTROL;
05758       p->subs[idx].f.subclass = AST_CONTROL_RINGING;
05759       ast_setstate(ast, AST_STATE_RINGING);
05760       ast_mutex_unlock(&p->lock);
05761       return &p->subs[idx].f;
05762    }
05763 
05764    if (p->subs[idx].needbusy) {
05765       /* Send busy frame if requested */
05766       p->subs[idx].needbusy = 0;
05767       p->subs[idx].f.frametype = AST_FRAME_CONTROL;
05768       p->subs[idx].f.subclass = AST_CONTROL_BUSY;
05769       ast_mutex_unlock(&p->lock);
05770       return &p->subs[idx].f;
05771    }
05772 
05773    if (p->subs[idx].needcongestion) {
05774       /* Send congestion frame if requested */
05775       p->subs[idx].needcongestion = 0;
05776       p->subs[idx].f.frametype = AST_FRAME_CONTROL;
05777       p->subs[idx].f.subclass = AST_CONTROL_CONGESTION;
05778       ast_mutex_unlock(&p->lock);
05779       return &p->subs[idx].f;
05780    }
05781 
05782    if (p->subs[idx].needcallerid) {
05783       ast_set_callerid(ast, S_OR(p->lastcid_num, NULL),
05784                      S_OR(p->lastcid_name, NULL),
05785                      S_OR(p->lastcid_num, NULL)
05786                      );
05787       p->subs[idx].needcallerid = 0;
05788    }
05789    
05790    if (p->subs[idx].needanswer) {
05791       /* Send answer frame if requested */
05792       p->subs[idx].needanswer = 0;
05793       p->subs[idx].f.frametype = AST_FRAME_CONTROL;
05794       p->subs[idx].f.subclass = AST_CONTROL_ANSWER;
05795       ast_mutex_unlock(&p->lock);
05796       return &p->subs[idx].f;
05797    }  
05798    
05799    if (p->subs[idx].needflash) {
05800       /* Send answer frame if requested */
05801       p->subs[idx].needflash = 0;
05802       p->subs[idx].f.frametype = AST_FRAME_CONTROL;
05803       p->subs[idx].f.subclass = AST_CONTROL_FLASH;
05804       ast_mutex_unlock(&p->lock);
05805       return &p->subs[idx].f;
05806    }  
05807    
05808    if (p->subs[idx].needhold) {
05809       /* Send answer frame if requested */
05810       p->subs[idx].needhold = 0;
05811       p->subs[idx].f.frametype = AST_FRAME_CONTROL;
05812       p->subs[idx].f.subclass = AST_CONTROL_HOLD;
05813       ast_mutex_unlock(&p->lock);
05814       ast_debug(1, "Sending hold on '%s'\n", ast->name);
05815       return &p->subs[idx].f;
05816    }  
05817    
05818    if (p->subs[idx].needunhold) {
05819       /* Send answer frame if requested */
05820       p->subs[idx].needunhold = 0;
05821       p->subs[idx].f.frametype = AST_FRAME_CONTROL;
05822       p->subs[idx].f.subclass = AST_CONTROL_UNHOLD;
05823       ast_mutex_unlock(&p->lock);
05824       ast_debug(1, "Sending unhold on '%s'\n", ast->name);
05825       return &p->subs[idx].f;
05826    }  
05827    
05828    if (ast->rawreadformat == AST_FORMAT_SLINEAR) {
05829       if (!p->subs[idx].linear) {
05830          p->subs[idx].linear = 1;
05831          res = dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
05832          if (res) 
05833             ast_log(LOG_WARNING, "Unable to set channel %d (index %d) to linear mode.\n", p->channel, idx);
05834       }
05835    } else if ((ast->rawreadformat == AST_FORMAT_ULAW) ||
05836          (ast->rawreadformat == AST_FORMAT_ALAW)) {
05837       if (p->subs[idx].linear) {
05838          p->subs[idx].linear = 0;
05839          res = dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
05840          if (res) 
05841             ast_log(LOG_WARNING, "Unable to set channel %d (index %d) to companded mode.\n", p->channel, idx);
05842       }
05843    } else {
05844       ast_log(LOG_WARNING, "Don't know how to read frames in format %s\n", ast_getformatname(ast->rawreadformat));
05845       ast_mutex_unlock(&p->lock);
05846       return NULL;
05847    }
05848    readbuf = ((unsigned char *)p->subs[idx].buffer) + AST_FRIENDLY_OFFSET;
05849    CHECK_BLOCKING(ast);
05850    res = read(p->subs[idx].dfd, readbuf, p->subs[idx].linear ? READ_SIZE * 2 : READ_SIZE);
05851    ast_clear_flag(ast, AST_FLAG_BLOCKING);
05852    /* Check for hangup */
05853    if (res < 0) {
05854       f = NULL;
05855       if (res == -1)  {
05856          if (errno == EAGAIN) {
05857             /* Return "NULL" frame if there is nobody there */
05858             ast_mutex_unlock(&p->lock);
05859             return &p->subs[idx].f;
05860          } else if (errno == ELAST) {
05861             f = __dahdi_exception(ast);
05862          } else
05863             ast_log(LOG_WARNING, "dahdi_rec: %s\n", strerror(errno));
05864       }
05865       ast_mutex_unlock(&p->lock);
05866       return f;
05867    }
05868    if (res != (p->subs[idx].linear ? READ_SIZE * 2 : READ_SIZE)) {
05869       ast_debug(1, "Short read (%d/%d), must be an event...\n", res, p->subs[idx].linear ? READ_SIZE * 2 : READ_SIZE);
05870       f = __dahdi_exception(ast);
05871       ast_mutex_unlock(&p->lock);
05872       return f;
05873    }
05874    if (p->tdd) { /* if in TDD mode, see if we receive that */
05875       int c;
05876 
05877       c = tdd_feed(p->tdd,readbuf,READ_SIZE);
05878       if (c < 0) {
05879          ast_debug(1,"tdd_feed failed\n");
05880          ast_mutex_unlock(&p->lock);
05881          return NULL;
05882       }
05883       if (c) { /* if a char to return */
05884          p->subs[idx].f.subclass = 0;
05885          p->subs[idx].f.frametype = AST_FRAME_TEXT;
05886          p->subs[idx].f.mallocd = 0;
05887          p->subs[idx].f.offset = AST_FRIENDLY_OFFSET;
05888          p->subs[idx].f.data.ptr = p->subs[idx].buffer + AST_FRIENDLY_OFFSET;
05889          p->subs[idx].f.datalen = 1;
05890          *((char *) p->subs[idx].f.data.ptr) = c;
05891          ast_mutex_unlock(&p->lock);
05892          return &p->subs[idx].f;
05893       }
05894    }
05895    /* Ensure the CW timer decrements only on a single subchannel */
05896    if (p->callwaitingrepeat && dahdi_get_index(ast, p, 1) == SUB_REAL) {
05897       p->callwaitingrepeat--;
05898    }
05899    if (p->cidcwexpire)
05900       p->cidcwexpire--;
05901    /* Repeat callwaiting */
05902    if (p->callwaitingrepeat == 1) {
05903       p->callwaitrings++;
05904       dahdi_callwait(ast);
05905    }
05906    /* Expire CID/CW */
05907    if (p->cidcwexpire == 1) {
05908       ast_verb(3, "CPE does not support Call Waiting Caller*ID.\n");
05909       restore_conference(p);
05910    }
05911    if (p->subs[idx].linear) {
05912       p->subs[idx].f.datalen = READ_SIZE * 2;
05913    } else 
05914       p->subs[idx].f.datalen = READ_SIZE;
05915 
05916    /* Handle CallerID Transmission */
05917    if ((p->owner == ast) && p->cidspill &&((ast->_state == AST_STATE_UP) || (ast->rings == p->cidrings))) {
05918       send_callerid(p);
05919    }
05920 
05921    p->subs[idx].f.frametype = AST_FRAME_VOICE;
05922    p->subs[idx].f.subclass = ast->rawreadformat;
05923    p->subs[idx].f.samples = READ_SIZE;
05924    p->subs[idx].f.mallocd = 0;
05925    p->subs[idx].f.offset = AST_FRIENDLY_OFFSET;
05926    p->subs[idx].f.data.ptr = p->subs[idx].buffer + AST_FRIENDLY_OFFSET / sizeof(p->subs[idx].buffer[0]);
05927 #if 0
05928    ast_debug(1, "Read %d of voice on %s\n", p->subs[idx].f.datalen, ast->name);
05929 #endif   
05930    if (p->dialing || /* Transmitting something */
05931       (idx && (ast->_state != AST_STATE_UP)) || /* Three-way or callwait that isn't up */
05932       ((idx == SUB_CALLWAIT) && !p->subs[SUB_CALLWAIT].inthreeway) /* Inactive and non-confed call-wait */
05933       ) {
05934       /* Whoops, we're still dialing, or in a state where we shouldn't transmit....
05935          don't send anything */
05936       p->subs[idx].f.frametype = AST_FRAME_NULL;
05937       p->subs[idx].f.subclass = 0;
05938       p->subs[idx].f.samples = 0;
05939       p->subs[idx].f.mallocd = 0;
05940       p->subs[idx].f.offset = 0;
05941       p->subs[idx].f.data.ptr = NULL;
05942       p->subs[idx].f.datalen= 0;
05943    }
05944    if (p->dsp && (!p->ignoredtmf || p->callwaitcas || p->busydetect  || p->callprogress) && !idx) {
05945       /* Perform busy detection. etc on the dahdi line */
05946       int mute;
05947 
05948       f = ast_dsp_process(ast, p->dsp, &p->subs[idx].f);
05949 
05950       /* Check if DSP code thinks we should be muting this frame and mute the conference if so */
05951       mute = ast_dsp_was_muted(p->dsp);
05952       if (p->muting != mute) {
05953          p->muting = mute;
05954          dahdi_confmute(p, mute);
05955       }
05956 
05957       if (f) {
05958          if ((f->frametype == AST_FRAME_CONTROL) && (f->subclass == AST_CONTROL_BUSY)) {
05959             if ((ast->_state == AST_STATE_UP) && !p->outgoing) {
05960                /* Treat this as a "hangup" instead of a "busy" on the assumption that
05961                   a busy  */
05962                f = NULL;
05963             }
05964          } else if (f->frametype == AST_FRAME_DTMF) {
05965 #ifdef HAVE_PRI
05966             if (!p->proceeding && ((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP)) && p->pri && 
05967                 ((!p->outgoing && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)) ||
05968                  (p->outgoing && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_OUTGOING)))) {
05969                /* Don't accept in-band DTMF when in overlap dial mode */
05970                f->frametype = AST_FRAME_NULL;
05971                f->subclass = 0;
05972             }
05973 #endif            
05974             /* DSP clears us of being pulse */
05975             p->pulsedial = 0;
05976          }
05977       }
05978    } else 
05979       f = &p->subs[idx].f; 
05980 
05981    if (f && (f->frametype == AST_FRAME_DTMF))
05982       dahdi_handle_dtmfup(ast, idx, &f);
05983 
05984    /* If we have a fake_event, trigger exception to handle it */
05985    if (p->fake_event)
05986       ast_set_flag(ast, AST_FLAG_EXCEPTION);
05987 
05988    ast_mutex_unlock(&p->lock);
05989    return f;
05990 }
05991 
05992 static int my_dahdi_write(struct dahdi_pvt *p, unsigned char *buf, int len, int idx, int linear)
05993 {
05994    int sent=0;
05995    int size;
05996    int res;
05997    int fd;
05998    fd = p->subs[idx].dfd;
05999    while (len) {
06000       size = len;
06001       if (size > (linear ? READ_SIZE * 2 : READ_SIZE))
06002          size = (linear ? READ_SIZE * 2 : READ_SIZE);
06003       res = write(fd, buf, size);
06004       if (res != size) {
06005          ast_debug(1, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel);
06006          return sent;
06007       }
06008       len -= size;
06009       buf += size;
06010    }
06011    return sent;
06012 }
06013 
06014 static int dahdi_write(struct ast_channel *ast, struct ast_frame *frame)
06015 {
06016    struct dahdi_pvt *p = ast->tech_pvt;
06017    int res;
06018    int idx;
06019    idx = dahdi_get_index(ast, p, 0);
06020    if (idx < 0) {
06021       ast_log(LOG_WARNING, "%s doesn't really exist?\n", ast->name);
06022       return -1;
06023    }
06024 
06025 #if 0
06026 #ifdef HAVE_PRI
06027    ast_mutex_lock(&p->lock);
06028    if (!p->proceeding && p->sig==SIG_PRI && p->pri && !p->outgoing) {
06029       if (p->pri->pri) {      
06030          if (!pri_grab(p, p->pri)) {
06031                pri_progress(p->pri->pri,p->call, PVT_TO_CHANNEL(p), !p->digital);
06032                pri_rel(p->pri);
06033          } else
06034                ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
06035       }
06036       p->proceeding=1;
06037    }
06038    ast_mutex_unlock(&p->lock);
06039 #endif
06040 #endif
06041    /* Write a frame of (presumably voice) data */
06042    if (frame->frametype != AST_FRAME_VOICE) {
06043       if (frame->frametype != AST_FRAME_IMAGE)
06044          ast_log(LOG_WARNING, "Don't know what to do with frame type '%d'\n", frame->frametype);
06045       return 0;
06046    }
06047    if ((frame->subclass != AST_FORMAT_SLINEAR) && 
06048        (frame->subclass != AST_FORMAT_ULAW) &&
06049        (frame->subclass != AST_FORMAT_ALAW)) {
06050       ast_log(LOG_WARNING, "Cannot handle frames in %d format\n", frame->subclass);
06051       return -1;
06052    }
06053    if (p->dialing) {
06054       ast_debug(1, "Dropping frame since I'm still dialing on %s...\n",ast->name);
06055       return 0;
06056    }
06057    if (!p->owner) {
06058       ast_debug(1, "Dropping frame since there is no active owner on %s...\n",ast->name);
06059       return 0;
06060    }
06061    if (p->cidspill) {
06062       ast_debug(1, "Dropping frame since I've still got a callerid spill\n");
06063       return 0;
06064    }
06065    /* Return if it's not valid data */
06066    if (!frame->data.ptr || !frame->datalen)
06067       return 0;
06068 
06069    if (frame->subclass == AST_FORMAT_SLINEAR) {
06070       if (!p->subs[idx].linear) {
06071          p->subs[idx].linear = 1;
06072          res = dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
06073          if (res)
06074             ast_log(LOG_WARNING, "Unable to set linear mode on channel %d\n", p->channel);
06075       }
06076       res = my_dahdi_write(p, (unsigned char *)frame->data.ptr, frame->datalen, idx, 1);
06077    } else {
06078       /* x-law already */
06079       if (p->subs[idx].linear) {
06080          p->subs[idx].linear = 0;
06081          res = dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
06082          if (res)
06083             ast_log(LOG_WARNING, "Unable to set companded mode on channel %d\n", p->channel);
06084       }
06085       res = my_dahdi_write(p, (unsigned char *)frame->data.ptr, frame->datalen, idx, 0);
06086    }
06087    if (res < 0) {
06088       ast_log(LOG_WARNING, "write failed: %s\n", strerror(errno));
06089       return -1;
06090    } 
06091    return 0;
06092 }
06093 
06094 static int dahdi_indicate(struct ast_channel *chan, int condition, const void *data, size_t datalen)
06095 {
06096    struct dahdi_pvt *p = chan->tech_pvt;
06097    int res=-1;
06098    int idx;
06099    int func = DAHDI_FLASH;
06100    ast_mutex_lock(&p->lock);
06101    idx = dahdi_get_index(chan, p, 0);
06102    ast_debug(1, "Requested indication %d on channel %s\n", condition, chan->name);
06103    if (idx == SUB_REAL) {
06104       switch (condition) {
06105       case AST_CONTROL_BUSY:
06106 #ifdef HAVE_PRI
06107          if (p->priindication_oob && ((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP))) {
06108             chan->hangupcause = AST_CAUSE_USER_BUSY;
06109             chan->_softhangup |= AST_SOFTHANGUP_DEV;
06110             res = 0;
06111          } else if (!p->progress && 
06112                ((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP))
06113                && p->pri && !p->outgoing) {
06114             if (p->pri->pri) {      
06115                if (!pri_grab(p, p->pri)) {
06116                   pri_progress(p->pri->pri,p->call, PVT_TO_CHANNEL(p), 1);
06117                   pri_rel(p->pri);
06118                }
06119                else
06120                   ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
06121             }
06122             p->progress = 1;
06123             res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_BUSY);
06124          } else
06125 #endif
06126             res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_BUSY);
06127          break;
06128       case AST_CONTROL_RINGING:
06129 #ifdef HAVE_PRI
06130          if ((!p->alerting) && ((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP)) 
06131                && p->pri && !p->outgoing && (chan->_state != AST_STATE_UP)) {
06132             if (p->pri->pri) {      
06133                if (!pri_grab(p, p->pri)) {
06134                   pri_acknowledge(p->pri->pri,p->call, PVT_TO_CHANNEL(p), !p->digital);
06135                   pri_rel(p->pri);
06136                }
06137                else
06138                   ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
06139             }
06140             p->alerting = 1;
06141          }
06142 
06143 #endif
06144 #ifdef HAVE_SS7
06145          if ((!p->alerting) && (p->sig == SIG_SS7) && p->ss7 && !p->outgoing && (chan->_state != AST_STATE_UP)) {
06146             if (p->ss7->ss7) {
06147                ss7_grab(p, p->ss7);
06148                
06149                if ((isup_far(p->ss7->ss7, p->ss7call)) != -1)
06150                   p->rlt = 1;
06151                if (p->rlt != 1) /* No need to send CPG if call will be RELEASE */
06152                   isup_cpg(p->ss7->ss7, p->ss7call, CPG_EVENT_ALERTING);
06153                p->alerting = 1;
06154                ss7_rel(p->ss7);
06155             }
06156          }
06157 #endif
06158             
06159          res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_RINGTONE);
06160          
06161          if (chan->_state != AST_STATE_UP) {
06162             if ((chan->_state != AST_STATE_RING) ||
06163                ((p->sig != SIG_FXSKS) &&
06164              (p->sig != SIG_FXSLS) &&
06165              (p->sig != SIG_FXSGS)))
06166             ast_setstate(chan, AST_STATE_RINGING);
06167          }
06168          break;
06169       case AST_CONTROL_PROCEEDING:
06170          ast_debug(1,"Received AST_CONTROL_PROCEEDING on %s\n",chan->name);
06171 #ifdef HAVE_PRI
06172          if (!p->proceeding && ((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP))
06173                && p->pri && !p->outgoing) {
06174             if (p->pri->pri) {      
06175                if (!pri_grab(p, p->pri)) {
06176                   pri_proceeding(p->pri->pri,p->call, PVT_TO_CHANNEL(p), !p->digital);
06177                   pri_rel(p->pri);
06178                }
06179                else
06180                   ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
06181             }
06182             p->proceeding = 1;
06183             p->dialing = 0;
06184          }
06185 #endif
06186 #ifdef HAVE_SS7
06187          /* This IF sends the FAR for an answered ALEG call */
06188          if (chan->_state == AST_STATE_UP && (p->rlt != 1) && (p->sig == SIG_SS7)){
06189             if ((isup_far(p->ss7->ss7, p->ss7call)) != -1)
06190                p->rlt = 1; 
06191          }
06192             
06193          if (!p->proceeding && p->sig == SIG_SS7 && p->ss7 && !p->outgoing) {
06194             if (p->ss7->ss7) {
06195                ss7_grab(p, p->ss7);
06196                isup_acm(p->ss7->ss7, p->ss7call);
06197                p->proceeding = 1;
06198                ss7_rel(p->ss7);
06199 
06200             }
06201          }
06202 #endif
06203          /* don't continue in ast_indicate */
06204          res = 0;
06205          break;
06206       case AST_CONTROL_PROGRESS:
06207          ast_debug(1,"Received AST_CONTROL_PROGRESS on %s\n",chan->name);
06208 #ifdef HAVE_PRI
06209          p->digital = 0;   /* Digital-only calls isn't allows any inband progress messages */
06210          if (!p->progress && ((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP))
06211                && p->pri && !p->outgoing) {
06212             if (p->pri->pri) {      
06213                if (!pri_grab(p, p->pri)) {
06214                   pri_progress(p->pri->pri,p->call, PVT_TO_CHANNEL(p), 1);
06215                   pri_rel(p->pri);
06216                }
06217                else
06218                   ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
06219             }
06220             p->progress = 1;
06221          }
06222 #endif
06223 #ifdef HAVE_SS7
06224          if (!p->progress && p->sig==SIG_SS7 && p->ss7 && !p->outgoing) {
06225             if (p->ss7->ss7) {
06226                ss7_grab(p, p->ss7);
06227                isup_cpg(p->ss7->ss7, p->ss7call, CPG_EVENT_INBANDINFO);
06228                p->progress = 1;
06229                ss7_rel(p->ss7);
06230                /* enable echo canceler here on SS7 calls */
06231                dahdi_enable_ec(p);
06232 
06233             }
06234          }
06235 #endif
06236          /* don't continue in ast_indicate */
06237          res = 0;
06238          break;
06239       case AST_CONTROL_CONGESTION:
06240          chan->hangupcause = AST_CAUSE_CONGESTION;
06241 #ifdef HAVE_PRI
06242          if (p->priindication_oob && ((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP))) {
06243             chan->hangupcause = AST_CAUSE_SWITCH_CONGESTION;
06244             chan->_softhangup |= AST_SOFTHANGUP_DEV;
06245             res = 0;
06246          } else if (!p->progress && ((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP)) 
06247                && p->pri && !p->outgoing) {
06248             if (p->pri) {     
06249                if (!pri_grab(p, p->pri)) {
06250                   pri_progress(p->pri->pri,p->call, PVT_TO_CHANNEL(p), 1);
06251                   pri_rel(p->pri);
06252                } else
06253                   ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
06254             }
06255             p->progress = 1;
06256             res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
06257          } else
06258 #endif
06259             res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
06260          break;
06261       case AST_CONTROL_HOLD:
06262 #ifdef HAVE_PRI
06263          if (p->pri && !strcasecmp(p->mohinterpret, "passthrough")) {
06264             if (!pri_grab(p, p->pri)) {
06265                res = pri_notify(p->pri->pri, p->call, p->prioffset, PRI_NOTIFY_REMOTE_HOLD);
06266                pri_rel(p->pri);
06267             } else
06268                   ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);       
06269          } else
06270 #endif
06271             ast_moh_start(chan, data, p->mohinterpret);
06272          break;
06273       case AST_CONTROL_UNHOLD:
06274 #ifdef HAVE_PRI
06275          if (p->pri && !strcasecmp(p->mohinterpret, "passthrough")) {
06276             if (!pri_grab(p, p->pri)) {
06277                res = pri_notify(p->pri->pri, p->call, p->prioffset, PRI_NOTIFY_REMOTE_RETRIEVAL);
06278                pri_rel(p->pri);
06279             } else
06280                   ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);       
06281          } else
06282 #endif
06283             ast_moh_stop(chan);
06284          break;
06285       case AST_CONTROL_RADIO_KEY:
06286          if (p->radio) 
06287              res =  dahdi_set_hook(p->subs[idx].dfd, DAHDI_OFFHOOK);
06288          res = 0;
06289          break;
06290       case AST_CONTROL_RADIO_UNKEY:
06291          if (p->radio)
06292              res =  dahdi_set_hook(p->subs[idx].dfd, DAHDI_RINGOFF);
06293          res = 0;
06294          break;
06295       case AST_CONTROL_FLASH:
06296          /* flash hookswitch */
06297          if (ISTRUNK(p) && (p->sig != SIG_PRI)) {
06298             /* Clear out the dial buffer */
06299             p->dop.dialstr[0] = '\0';
06300             if ((ioctl(p->subs[SUB_REAL].dfd,DAHDI_HOOK,&func) == -1) && (errno != EINPROGRESS)) {
06301                ast_log(LOG_WARNING, "Unable to flash external trunk on channel %s: %s\n", 
06302                   chan->name, strerror(errno));
06303             } else
06304                res = 0;
06305          } else
06306             res = 0;
06307          break;
06308       case AST_CONTROL_SRCUPDATE:
06309          res = 0;
06310          break;
06311       case -1:
06312          res = tone_zone_play_tone(p->subs[idx].dfd, -1);
06313          break;
06314       }
06315    } else
06316       res = 0;
06317    ast_mutex_unlock(&p->lock);
06318    return res;
06319 }
06320 
06321 static struct ast_channel *dahdi_new(struct dahdi_pvt *i, int state, int startpbx, int idx, int law, int transfercapability)
06322 {
06323    struct ast_channel *tmp;
06324    int deflaw;
06325    int res;
06326    int x,y;
06327    int features;
06328    struct ast_str *chan_name;
06329    struct ast_variable *v;
06330    struct dahdi_params ps;
06331    if (i->subs[idx].owner) {
06332       ast_log(LOG_WARNING, "Channel %d already has a %s call\n", i->channel,subnames[idx]);
06333       return NULL;
06334    }
06335    y = 1;
06336    chan_name = ast_str_alloca(32);
06337    do {
06338 #ifdef HAVE_PRI
06339       if (i->bearer || (i->pri && (i->sig == SIG_FXSKS)))
06340          ast_str_set(&chan_name, 0, "%d:%d-%d", i->pri->trunkgroup, i->channel, y);
06341       else
06342 #endif
06343       if (i->channel == CHAN_PSEUDO)
06344          ast_str_set(&chan_name, 0, "pseudo-%ld", ast_random());
06345       else  
06346          ast_str_set(&chan_name, 0, "%d-%d", i->channel, y);
06347       for (x = 0; x < 3; x++) {
06348          if ((idx != x) && i->subs[x].owner && !strcasecmp(chan_name->str, i->subs[x].owner->name + 6))
06349             break;
06350       }
06351       y++;
06352    } while (x < 3);
06353    tmp = ast_channel_alloc(0, state, i->cid_num, i->cid_name, i->accountcode, i->exten, i->context, i->amaflags, "DAHDI/%s", chan_name->str);
06354    if (!tmp)
06355       return NULL;
06356    tmp->tech = &dahdi_tech;
06357    memset(&ps, 0, sizeof(ps));
06358    ps.channo = i->channel;
06359    res = ioctl(i->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &ps);
06360    if (res) {
06361       ast_log(LOG_WARNING, "Unable to get parameters, assuming MULAW: %s\n", strerror(errno));
06362       ps.curlaw = DAHDI_LAW_MULAW;
06363    }
06364    if (ps.curlaw == DAHDI_LAW_ALAW)
06365       deflaw = AST_FORMAT_ALAW;
06366    else
06367       deflaw = AST_FORMAT_ULAW;
06368    if (law) {
06369       if (law == DAHDI_LAW_ALAW)
06370          deflaw = AST_FORMAT_ALAW;
06371       else
06372          deflaw = AST_FORMAT_ULAW;
06373    }
06374    ast_channel_set_fd(tmp, 0, i->subs[idx].dfd);
06375    tmp->nativeformats = deflaw;
06376    /* Start out assuming ulaw since it's smaller :) */
06377    tmp->rawreadformat = deflaw;
06378    tmp->readformat = deflaw;
06379    tmp->rawwriteformat = deflaw;
06380    tmp->writeformat = deflaw;
06381    i->subs[idx].linear = 0;
06382    dahdi_setlinear(i->subs[idx].dfd, i->subs[idx].linear);
06383    features = 0;
06384    if (idx == SUB_REAL) {
06385       if (i->busydetect && CANBUSYDETECT(i))
06386          features |= DSP_FEATURE_BUSY_DETECT;
06387       if ((i->callprogress & CALLPROGRESS_PROGRESS) && CANPROGRESSDETECT(i))
06388          features |= DSP_FEATURE_CALL_PROGRESS;
06389       if ((!i->outgoing && (i->callprogress & CALLPROGRESS_FAX_INCOMING)) || 
06390           (i->outgoing && (i->callprogress & CALLPROGRESS_FAX_OUTGOING))) {
06391          features |= DSP_FEATURE_FAX_DETECT;
06392       }
06393       x = DAHDI_TONEDETECT_ON | DAHDI_TONEDETECT_MUTE;
06394       if (ioctl(i->subs[idx].dfd, DAHDI_TONEDETECT, &x)) {
06395          i->hardwaredtmf = 0;
06396          features |= DSP_FEATURE_DIGIT_DETECT;
06397       } else if (NEED_MFDETECT(i)) {
06398          i->hardwaredtmf = 1;
06399          features |= DSP_FEATURE_DIGIT_DETECT;
06400       }
06401    }
06402    if (features) {
06403       if (i->dsp) {
06404          ast_debug(1, "Already have a dsp on %s?\n", tmp->name);
06405       } else {
06406          if (i->channel != CHAN_PSEUDO)
06407             i->dsp = ast_dsp_new();
06408          else
06409             i->dsp = NULL;
06410          if (i->dsp) {
06411             i->dsp_features = features;
06412 #if defined(HAVE_PRI) || defined(HAVE_SS7)
06413             /* We cannot do progress detection until receives PROGRESS message */
06414             if (i->outgoing && ((i->sig == SIG_PRI) || (i->sig == SIG_BRI) || (i->sig == SIG_BRI_PTMP) || (i->sig == SIG_SS7))) {
06415                /* Remember requested DSP features, don't treat
06416                   talking as ANSWER */
06417                i->dsp_features = features & ~DSP_PROGRESS_TALK;
06418                features = 0;
06419             }
06420 #endif
06421             ast_dsp_set_features(i->dsp, features);
06422             ast_dsp_set_digitmode(i->dsp, DSP_DIGITMODE_DTMF | i->dtmfrelax);
06423             if (!ast_strlen_zero(progzone))
06424                ast_dsp_set_call_progress_zone(i->dsp, progzone);
06425             if (i->busydetect && CANBUSYDETECT(i)) {
06426                if(i->silencethreshold > 0)
06427                   ast_dsp_set_threshold(i->dsp, i->silencethreshold);
06428                ast_dsp_set_busy_count(i->dsp, i->busycount);
06429                if(i->busytonelength > 0)
06430                   ast_dsp_set_busy_pattern(i->dsp, i->busytonelength, i->busyquietlength, i->busyfuzziness);
06431                if((i->busytonelength == i->busyquietlength) && i->busycompare)
06432                   ast_dsp_set_busy_compare(i->dsp, i->busycompare);
06433             }
06434          }
06435       }
06436    }
06437       
06438    if (state == AST_STATE_RING)
06439       tmp->rings = 1;
06440    tmp->tech_pvt = i;
06441    if ((i->sig == SIG_FXOKS) || (i->sig == SIG_FXOGS) || (i->sig == SIG_FXOLS)) {
06442       /* Only FXO signalled stuff can be picked up */
06443       tmp->callgroup = i->callgroup;
06444       tmp->pickupgroup = i->pickupgroup;
06445    }
06446    if (!ast_strlen_zero(i->parkinglot))
06447       ast_string_field_set(tmp, parkinglot, i->parkinglot);
06448    if (!ast_strlen_zero(i->language))
06449       ast_string_field_set(tmp, language, i->language);
06450    if (!i->owner)
06451       i->owner = tmp;
06452    if (!ast_strlen_zero(i->accountcode))
06453       ast_string_field_set(tmp, accountcode, i->accountcode);
06454    if (i->amaflags)
06455       tmp->amaflags = i->amaflags;
06456    i->subs[idx].owner = tmp;
06457    ast_copy_string(tmp->context, i->context, sizeof(tmp->context));
06458    ast_string_field_set(tmp, call_forward, i->call_forward);
06459    /* If we've been told "no ADSI" then enforce it */
06460    if (!i->adsi)
06461       tmp->adsicpe = AST_ADSI_UNAVAILABLE;
06462    if (!ast_strlen_zero(i->exten))
06463       ast_copy_string(tmp->exten, i->exten, sizeof(tmp->exten));
06464    if (!ast_strlen_zero(i->rdnis))
06465       tmp->cid.cid_rdnis = ast_strdup(i->rdnis);
06466    if (!ast_strlen_zero(i->dnid))
06467       tmp->cid.cid_dnid = ast_strdup(i->dnid);
06468 
06469    /* Don't use ast_set_callerid() here because it will
06470     * generate a needless NewCallerID event */
06471 #ifdef PRI_ANI
06472    if (!ast_strlen_zero(i->cid_ani))
06473       tmp->cid.cid_ani = ast_strdup(i->cid_ani);
06474    else  
06475       tmp->cid.cid_ani = ast_strdup(i->cid_num);
06476 #else
06477    tmp->cid.cid_ani = ast_strdup(i->cid_num);
06478 #endif
06479    tmp->cid.cid_pres = i->callingpres;
06480    tmp->cid.cid_ton = i->cid_ton;
06481    tmp->cid.cid_ani2 = i->cid_ani2;
06482 #if defined(HAVE_PRI) || defined(HAVE_SS7)
06483    tmp->transfercapability = transfercapability;
06484    pbx_builtin_setvar_helper(tmp, "TRANSFERCAPABILITY", ast_transfercapability2str(transfercapability));
06485    if (transfercapability & AST_TRANS_CAP_DIGITAL)
06486       i->digital = 1;
06487    /* Assume calls are not idle calls unless we're told differently */
06488    i->isidlecall = 0;
06489    i->alreadyhungup = 0;
06490 #endif
06491    /* clear the fake event in case we posted one before we had ast_channel */
06492    i->fake_event = 0;
06493    /* Assure there is no confmute on this channel */
06494    dahdi_confmute(i, 0);
06495    i->muting = 0;
06496    /* Configure the new channel jb */
06497    ast_jb_configure(tmp, &global_jbconf);
06498 
06499    ast_devstate_changed_literal(ast_state_chan2dev(state), tmp->name);
06500 
06501    for (v = i->vars ; v ; v = v->next)
06502                 pbx_builtin_setvar_helper(tmp, v->name, v->value);
06503 
06504    if (startpbx) {
06505       if (ast_pbx_start(tmp)) {
06506          ast_log(LOG_WARNING, "Unable to start PBX on %s\n", tmp->name);
06507          ast_hangup(tmp);
06508          i->owner = NULL;
06509          return NULL;
06510       }
06511    }
06512 
06513    ast_module_ref(ast_module_info->self);
06514    return tmp;
06515 }
06516 
06517 
06518 static int my_getsigstr(struct ast_channel *chan, char *str, const char *term, int ms)
06519 {
06520    char c;
06521 
06522    *str = 0; /* start with empty output buffer */
06523    for (;;)
06524    {
06525       /* Wait for the first digit (up to specified ms). */
06526       c = ast_waitfordigit(chan, ms);
06527       /* if timeout, hangup or error, return as such */
06528       if (c < 1)
06529          return c;
06530       *str++ = c;
06531       *str = 0;
06532       if (strchr(term, c))
06533          return 1;
06534    }
06535 }
06536 
06537 static int dahdi_wink(struct dahdi_pvt *p, int idx)
06538 {
06539    int j;
06540    dahdi_set_hook(p->subs[idx].dfd, DAHDI_WINK);
06541    for (;;)
06542    {
06543          /* set bits of interest */
06544       j = DAHDI_IOMUX_SIGEVENT;
06545           /* wait for some happening */
06546       if (ioctl(p->subs[idx].dfd,DAHDI_IOMUX,&j) == -1) return(-1);
06547          /* exit loop if we have it */
06548       if (j & DAHDI_IOMUX_SIGEVENT) break;
06549    }
06550      /* get the event info */
06551    if (ioctl(p->subs[idx].dfd,DAHDI_GETEVENT,&j) == -1) return(-1);
06552    return 0;
06553 }
06554 
06555 /*! \brief enable or disable the chan_dahdi Do-Not-Disturb mode for a DAHDI channel
06556  * \param dahdichan "Physical" DAHDI channel (e.g: DAHDI/5)
06557  * \param on 1 to enable, 0 to disable
06558  *
06559  * chan_dahdi has a DND (Do Not Disturb) mode for each dahdichan (physical 
06560  * DAHDI channel). Use this to enable or disable it.
06561  *
06562  * \bug the use of the word "channel" for those dahdichans is really confusing.
06563  */
06564 static void dahdi_dnd(struct dahdi_pvt *dahdichan, int on)
06565 {
06566    /* Do not disturb */
06567    dahdichan->dnd = on;
06568    ast_verb(3, "%s DND on channel %d\n", 
06569          on? "Enabled" : "Disabled",
06570          dahdichan->channel);
06571    manager_event(EVENT_FLAG_SYSTEM, "DNDState",
06572          "Channel: DAHDI/%d\r\n"
06573          "Status: %s\r\n", dahdichan->channel,
06574          on? "enabled" : "disabled");
06575 }
06576 
06577 static void *ss_thread(void *data)
06578 {
06579    struct ast_channel *chan = data;
06580    struct dahdi_pvt *p = chan->tech_pvt;
06581    char exten[AST_MAX_EXTENSION] = "";
06582    char exten2[AST_MAX_EXTENSION] = "";
06583    unsigned char buf[256];
06584    char dtmfcid[300];
06585    char dtmfbuf[300];
06586    struct callerid_state *cs = NULL;
06587    char *name = NULL, *number = NULL;
06588    int distMatches;
06589    int curRingData[3];
06590    int receivedRingT;
06591    int counter1;
06592    int counter;
06593    int samples = 0;
06594    struct ast_smdi_md_message *smdi_msg = NULL;
06595    int flags = 0;
06596    int i;
06597    int timeout;
06598    int getforward = 0;
06599    char *s1, *s2;
06600    int len = 0;
06601    int res;
06602    int idx;
06603 
06604    ast_mutex_lock(&ss_thread_lock);
06605    ss_thread_count++;
06606    ast_mutex_unlock(&ss_thread_lock);
06607    /* in the bizarre case where the channel has become a zombie before we
06608       even get started here, abort safely
06609    */
06610    if (!p) {
06611       ast_log(LOG_WARNING, "Channel became a zombie before simple switch could be started (%s)\n", chan->name);
06612       ast_hangup(chan);
06613       goto quit;
06614    }
06615    ast_verb(3, "Starting simple switch on '%s'\n", chan->name);
06616    idx = dahdi_get_index(chan, p, 1);
06617    if (idx < 0) {
06618       ast_log(LOG_WARNING, "Huh?\n");
06619       ast_hangup(chan);
06620       goto quit;
06621    }
06622    if (p->dsp)
06623       ast_dsp_digitreset(p->dsp);
06624    switch (p->sig) {
06625 #ifdef HAVE_PRI
06626    case SIG_PRI:
06627    case SIG_BRI:
06628    case SIG_BRI_PTMP:
06629       /* Now loop looking for an extension */
06630       ast_copy_string(exten, p->exten, sizeof(exten));
06631       len = strlen(exten);
06632       res = 0;
06633       while ((len < AST_MAX_EXTENSION-1) && ast_matchmore_extension(chan, chan->context, exten, 1, p->cid_num)) {
06634          if (len && !ast_ignore_pattern(chan->context, exten))
06635             tone_zone_play_tone(p->subs[idx].dfd, -1);
06636          else
06637             tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALTONE);
06638          if (ast_exists_extension(chan, chan->context, exten, 1, p->cid_num))
06639             timeout = matchdigittimeout;
06640          else
06641             timeout = gendigittimeout;
06642          res = ast_waitfordigit(chan, timeout);
06643          if (res < 0) {
06644             ast_debug(1, "waitfordigit returned < 0...\n");
06645             ast_hangup(chan);
06646             goto quit;
06647          } else if (res) {
06648             exten[len++] = res;
06649             exten[len] = '\0';
06650          } else
06651             break;
06652       }
06653       /* if no extension was received ('unspecified') on overlap call, use the 's' extension */
06654       if (ast_strlen_zero(exten)) {
06655          ast_verb(3, "Going to extension s|1 because of empty extension received on overlap call\n");
06656          exten[0] = 's';
06657          exten[1] = '\0';
06658       }
06659       tone_zone_play_tone(p->subs[idx].dfd, -1);
06660       if (ast_exists_extension(chan, chan->context, exten, 1, p->cid_num)) {
06661          /* Start the real PBX */
06662          ast_copy_string(chan->exten, exten, sizeof(chan->exten));
06663          if (p->dsp) {
06664             ast_dsp_digitreset(p->dsp);
06665          }
06666          if (p->pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING) {
06667             if (p->pri->pri) {      
06668                if (!pri_grab(p, p->pri)) {
06669                   pri_proceeding(p->pri->pri, p->call, PVT_TO_CHANNEL(p), 0);
06670                   p->proceeding = 1;
06671                   pri_rel(p->pri);
06672                } else {
06673                   ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
06674                }
06675             }
06676          }
06677          dahdi_enable_ec(p);
06678          ast_setstate(chan, AST_STATE_RING);
06679          res = ast_pbx_run(chan);
06680          if (res) {
06681             ast_log(LOG_WARNING, "PBX exited non-zero!\n");
06682          }
06683       } else {
06684          ast_debug(1, "No such possible extension '%s' in context '%s'\n", exten, chan->context);
06685          chan->hangupcause = AST_CAUSE_UNALLOCATED;
06686          ast_hangup(chan);
06687          p->exten[0] = '\0';
06688          /* Since we send release complete here, we won't get one */
06689          p->call = NULL;
06690       }
06691       goto quit;
06692       break;
06693 #endif
06694    case SIG_FEATD:
06695    case SIG_FEATDMF:
06696    case SIG_FEATDMF_TA:
06697    case SIG_E911:
06698    case SIG_FGC_CAMAMF:
06699    case SIG_FEATB:
06700    case SIG_EMWINK:
06701    case SIG_SF_FEATD:
06702    case SIG_SF_FEATDMF:
06703    case SIG_SF_FEATB:
06704    case SIG_SFWINK:
06705       if (dahdi_wink(p, idx)) 
06706          goto quit;
06707       /* Fall through */
06708    case SIG_EM:
06709    case SIG_EM_E1:
06710    case SIG_SF:
06711    case SIG_FGC_CAMA:
06712       res = tone_zone_play_tone(p->subs[idx].dfd, -1);
06713       if (p->dsp)
06714          ast_dsp_digitreset(p->dsp);
06715       /* set digit mode appropriately */
06716       if (p->dsp) {
06717          if (NEED_MFDETECT(p))
06718             ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MF | p->dtmfrelax); 
06719          else 
06720             ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
06721       }
06722       memset(dtmfbuf, 0, sizeof(dtmfbuf));
06723       /* Wait for the first digit only if immediate=no */
06724       if (!p->immediate)
06725          /* Wait for the first digit (up to 5 seconds). */
06726          res = ast_waitfordigit(chan, 5000);
06727       else
06728          res = 0;
06729       if (res > 0) {
06730          /* save first char */
06731          dtmfbuf[0] = res;
06732          switch (p->sig) {
06733          case SIG_FEATD:
06734          case SIG_SF_FEATD:
06735             res = my_getsigstr(chan, dtmfbuf + 1, "*", 3000);
06736             if (res > 0)
06737                res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "*", 3000);
06738             if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
06739             break;
06740          case SIG_FEATDMF_TA:
06741             res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
06742             if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
06743             if (dahdi_wink(p, idx)) goto quit;
06744             dtmfbuf[0] = 0;
06745             /* Wait for the first digit (up to 5 seconds). */
06746             res = ast_waitfordigit(chan, 5000);
06747             if (res <= 0) break;
06748             dtmfbuf[0] = res;
06749             /* fall through intentionally */
06750          case SIG_FEATDMF:
06751          case SIG_E911:
06752          case SIG_FGC_CAMAMF:
06753          case SIG_SF_FEATDMF:
06754             res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
06755             /* if international caca, do it again to get real ANO */
06756             if ((p->sig == SIG_FEATDMF) && (dtmfbuf[1] != '0') && (strlen(dtmfbuf) != 14))
06757             {
06758                if (dahdi_wink(p, idx)) goto quit;
06759                dtmfbuf[0] = 0;
06760                /* Wait for the first digit (up to 5 seconds). */
06761                res = ast_waitfordigit(chan, 5000);
06762                if (res <= 0) break;
06763                dtmfbuf[0] = res;
06764                res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
06765             }
06766             if (res > 0) {
06767                /* if E911, take off hook */
06768                if (p->sig == SIG_E911)
06769                   dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
06770                res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "#", 3000);
06771             }
06772             if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
06773             break;
06774          case SIG_FEATB:
06775          case SIG_SF_FEATB:
06776             res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
06777             if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
06778             break;
06779          case SIG_EMWINK:
06780             /* if we received a '*', we are actually receiving Feature Group D
06781                dial syntax, so use that mode; otherwise, fall through to normal
06782                mode
06783             */
06784             if (res == '*') {
06785                res = my_getsigstr(chan, dtmfbuf + 1, "*", 3000);
06786                if (res > 0)
06787                   res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "*", 3000);
06788                if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
06789                break;
06790             }
06791          default:
06792             /* If we got the first digit, get the rest */
06793             len = 1;
06794             dtmfbuf[len] = '\0';
06795             while ((len < AST_MAX_EXTENSION-1) && ast_matchmore_extension(chan, chan->context, dtmfbuf, 1, p->cid_num)) {
06796                if (ast_exists_extension(chan, chan->context, dtmfbuf, 1, p->cid_num)) {
06797                   timeout = matchdigittimeout;
06798                } else {
06799                   timeout = gendigittimeout;
06800                }
06801                res = ast_waitfordigit(chan, timeout);
06802                if (res < 0) {
06803                   ast_debug(1, "waitfordigit returned < 0...\n");
06804                   ast_hangup(chan);
06805                   goto quit;
06806                } else if (res) {
06807                   dtmfbuf[len++] = res;
06808                   dtmfbuf[len] = '\0';
06809                } else {
06810                   break;
06811                }
06812             }
06813             break;
06814          }
06815       }
06816       if (res == -1) {
06817          ast_log(LOG_WARNING, "getdtmf on channel %d: %s\n", p->channel, strerror(errno));
06818          ast_hangup(chan);
06819          goto quit;
06820       } else if (res < 0) {
06821          ast_debug(1, "Got hung up before digits finished\n");
06822          ast_hangup(chan);
06823          goto quit;
06824       }
06825 
06826       if (p->sig == SIG_FGC_CAMA) {
06827          char anibuf[100];
06828 
06829          if (ast_safe_sleep(chan,1000) == -1) {
06830                            ast_hangup(chan);
06831                            goto quit;
06832          }
06833                         dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
06834                         ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MF | p->dtmfrelax);
06835                         res = my_getsigstr(chan, anibuf, "#", 10000);
06836                         if ((res > 0) && (strlen(anibuf) > 2)) {
06837             if (anibuf[strlen(anibuf) - 1] == '#')
06838                anibuf[strlen(anibuf) - 1] = 0;
06839             ast_set_callerid(chan, anibuf + 2, NULL, anibuf + 2);
06840          }
06841                         ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
06842       }
06843 
06844       ast_copy_string(exten, dtmfbuf, sizeof(exten));
06845       if (ast_strlen_zero(exten))
06846          ast_copy_string(exten, "s", sizeof(exten));
06847       if (p->sig == SIG_FEATD || p->sig == SIG_EMWINK) {
06848          /* Look for Feature Group D on all E&M Wink and Feature Group D trunks */
06849          if (exten[0] == '*') {
06850             char *stringp=NULL;
06851             ast_copy_string(exten2, exten, sizeof(exten2));
06852             /* Parse out extension and callerid */
06853             stringp=exten2 +1;
06854             s1 = strsep(&stringp, "*");
06855             s2 = strsep(&stringp, "*");
06856             if (s2) {
06857                if (!ast_strlen_zero(p->cid_num))
06858                   ast_set_callerid(chan, p->cid_num, NULL, p->cid_num);
06859                else
06860                   ast_set_callerid(chan, s1, NULL, s1);
06861                ast_copy_string(exten, s2, sizeof(exten));
06862             } else
06863                ast_copy_string(exten, s1, sizeof(exten));
06864          } else if (p->sig == SIG_FEATD)
06865             ast_log(LOG_WARNING, "Got a non-Feature Group D input on channel %d.  Assuming E&M Wink instead\n", p->channel);
06866       }
06867       if ((p->sig == SIG_FEATDMF) || (p->sig == SIG_FEATDMF_TA)) {
06868          if (exten[0] == '*') {
06869             char *stringp=NULL;
06870             ast_copy_string(exten2, exten, sizeof(exten2));
06871             /* Parse out extension and callerid */
06872             stringp=exten2 +1;
06873             s1 = strsep(&stringp, "#");
06874             s2 = strsep(&stringp, "#");
06875             if (s2) {
06876                if (!ast_strlen_zero(p->cid_num))
06877                   ast_set_callerid(chan, p->cid_num, NULL, p->cid_num);
06878                else
06879                   if (*(s1 + 2))
06880                      ast_set_callerid(chan, s1 + 2, NULL, s1 + 2);
06881                ast_copy_string(exten, s2 + 1, sizeof(exten));
06882             } else
06883                ast_copy_string(exten, s1 + 2, sizeof(exten));
06884          } else
06885             ast_log(LOG_WARNING, "Got a non-Feature Group D input on channel %d.  Assuming E&M Wink instead\n", p->channel);
06886       }
06887       if ((p->sig == SIG_E911) || (p->sig == SIG_FGC_CAMAMF)) {
06888          if (exten[0] == '*') {
06889             char *stringp=NULL;
06890             ast_copy_string(exten2, exten, sizeof(exten2));
06891             /* Parse out extension and callerid */
06892             stringp=exten2 +1;
06893             s1 = strsep(&stringp, "#");
06894             s2 = strsep(&stringp, "#");
06895             if (s2 && (*(s2 + 1) == '0')) {
06896                if (*(s2 + 2))
06897                   ast_set_callerid(chan, s2 + 2, NULL, s2 + 2);
06898             }
06899             if (s1)  ast_copy_string(exten, s1, sizeof(exten));
06900             else ast_copy_string(exten, "911", sizeof(exten));
06901          } else
06902             ast_log(LOG_WARNING, "Got a non-E911/FGC CAMA input on channel %d.  Assuming E&M Wink instead\n", p->channel);
06903       }
06904       if (p->sig == SIG_FEATB) {
06905          if (exten[0] == '*') {
06906             char *stringp=NULL;
06907             ast_copy_string(exten2, exten, sizeof(exten2));
06908             /* Parse out extension and callerid */
06909             stringp=exten2 +1;
06910             s1 = strsep(&stringp, "#");
06911             ast_copy_string(exten, exten2 + 1, sizeof(exten));
06912          } else
06913             ast_log(LOG_WARNING, "Got a non-Feature Group B input on channel %d.  Assuming E&M Wink instead\n", p->channel);
06914       }
06915       if ((p->sig == SIG_FEATDMF) || (p->sig == SIG_FEATDMF_TA)) {
06916          dahdi_wink(p, idx);
06917                         /* some switches require a minimum guard time between
06918                            the last FGD wink and something that answers
06919                            immediately. This ensures it */
06920                         if (ast_safe_sleep(chan,100)) goto quit;
06921       }
06922       dahdi_enable_ec(p);
06923       if (NEED_MFDETECT(p)) {
06924          if (p->dsp) {
06925             if (!p->hardwaredtmf)
06926                ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax); 
06927             else {
06928                ast_dsp_free(p->dsp);
06929                p->dsp = NULL;
06930             }
06931          }
06932       }
06933 
06934       if (ast_exists_extension(chan, chan->context, exten, 1, chan->cid.cid_num)) {
06935          ast_copy_string(chan->exten, exten, sizeof(chan->exten));
06936          if (p->dsp) ast_dsp_digitreset(p->dsp);
06937          res = ast_pbx_run(chan);
06938          if (res) {
06939             ast_log(LOG_WARNING, "PBX exited non-zero\n");
06940             res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
06941          }
06942          goto quit;
06943       } else {
06944          ast_verb(2, "Unknown extension '%s' in context '%s' requested\n", exten, chan->context);
06945          sleep(2);
06946          res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_INFO);
06947          if (res < 0)
06948             ast_log(LOG_WARNING, "Unable to start special tone on %d\n", p->channel);
06949          else
06950             sleep(1);
06951          res = ast_streamfile(chan, "ss-noservice", chan->language);
06952          if (res >= 0)
06953             ast_waitstream(chan, "");
06954          res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
06955          ast_hangup(chan);
06956          goto quit;
06957       }
06958       break;
06959    case SIG_FXOLS:
06960    case SIG_FXOGS:
06961    case SIG_FXOKS:
06962       /* Read the first digit */
06963       timeout = firstdigittimeout;
06964       /* If starting a threeway call, never timeout on the first digit so someone
06965          can use flash-hook as a "hold" feature */
06966       if (p->subs[SUB_THREEWAY].owner) 
06967          timeout = 999999;
06968       while (len < AST_MAX_EXTENSION-1) {
06969          /* Read digit unless it's supposed to be immediate, in which case the
06970             only answer is 's' */
06971          if (p->immediate) 
06972             res = 's';
06973          else
06974             res = ast_waitfordigit(chan, timeout);
06975          timeout = 0;
06976          if (res < 0) {
06977             ast_debug(1, "waitfordigit returned < 0...\n");
06978             res = tone_zone_play_tone(p->subs[idx].dfd, -1);
06979             ast_hangup(chan);
06980             goto quit;
06981          } else if (res)  {
06982             ast_debug(1,"waitfordigit returned '%c' (%d), timeout = %d\n", res, res, timeout);
06983             exten[len++]=res;
06984             exten[len] = '\0';
06985          }
06986          if (!ast_ignore_pattern(chan->context, exten))
06987             tone_zone_play_tone(p->subs[idx].dfd, -1);
06988          else
06989             tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALTONE);
06990          if (ast_exists_extension(chan, chan->context, exten, 1, p->cid_num) && strcmp(exten, ast_parking_ext())) {
06991             if (!res || !ast_matchmore_extension(chan, chan->context, exten, 1, p->cid_num)) {
06992                if (getforward) {
06993                   /* Record this as the forwarding extension */
06994                   ast_copy_string(p->call_forward, exten, sizeof(p->call_forward)); 
06995                   ast_verb(3, "Setting call forward to '%s' on channel %d\n", p->call_forward, p->channel);
06996                   res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
06997                   if (res)
06998                      break;
06999                   usleep(500000);
07000                   res = tone_zone_play_tone(p->subs[idx].dfd, -1);
07001                   sleep(1);
07002                   memset(exten, 0, sizeof(exten));
07003                   res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALTONE);
07004                   len = 0;
07005                   getforward = 0;
07006                } else  {
07007                   res = tone_zone_play_tone(p->subs[idx].dfd, -1);
07008                   ast_copy_string(chan->exten, exten, sizeof(chan->exten));
07009                   if (!ast_strlen_zero(p->cid_num)) {
07010                      if (!p->hidecallerid)
07011                         ast_set_callerid(chan, p->cid_num, NULL, p->cid_num); 
07012                      else
07013                         ast_set_callerid(chan, NULL, NULL, p->cid_num); 
07014                   }
07015                   if (!ast_strlen_zero(p->cid_name)) {
07016                      if (!p->hidecallerid)
07017                         ast_set_callerid(chan, NULL, p->cid_name, NULL);
07018                   }
07019                   ast_setstate(chan, AST_STATE_RING);
07020                   dahdi_enable_ec(p);
07021                   res = ast_pbx_run(chan);
07022                   if (res) {
07023                      ast_log(LOG_WARNING, "PBX exited non-zero\n");
07024                      res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
07025                   }
07026                   goto quit;
07027                }
07028             } else {
07029                /* It's a match, but they just typed a digit, and there is an ambiguous match,
07030                   so just set the timeout to matchdigittimeout and wait some more */
07031                timeout = matchdigittimeout;
07032             }
07033          } else if (res == 0) {
07034             ast_debug(1, "not enough digits (and no ambiguous match)...\n");
07035             res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
07036             dahdi_wait_event(p->subs[idx].dfd);
07037             ast_hangup(chan);
07038             goto quit;
07039          } else if (p->callwaiting && !strcmp(exten, "*70")) {
07040             ast_verb(3, "Disabling call waiting on %s\n", chan->name);
07041             /* Disable call waiting if enabled */
07042             p->callwaiting = 0;
07043             res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
07044             if (res) {
07045                ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n", 
07046                   chan->name, strerror(errno));
07047             }
07048             len = 0;
07049             ioctl(p->subs[idx].dfd,DAHDI_CONFDIAG,&len);
07050             memset(exten, 0, sizeof(exten));
07051             timeout = firstdigittimeout;
07052                
07053          } else if (!strcmp(exten,ast_pickup_ext())) {
07054             /* Scan all channels and see if there are any
07055              * ringing channels that have call groups
07056              * that equal this channels pickup group  
07057              */
07058             if (idx == SUB_REAL) {
07059                /* Switch us from Third call to Call Wait */
07060                if (p->subs[SUB_THREEWAY].owner) {
07061                   /* If you make a threeway call and the *8# a call, it should actually 
07062                      look like a callwait */
07063                   alloc_sub(p, SUB_CALLWAIT);   
07064                   swap_subs(p, SUB_CALLWAIT, SUB_THREEWAY);
07065                   unalloc_sub(p, SUB_THREEWAY);
07066                }
07067                dahdi_enable_ec(p);
07068                if (ast_pickup_call(chan)) {
07069                   ast_debug(1, "No call pickup possible...\n");
07070                   res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
07071                   dahdi_wait_event(p->subs[idx].dfd);
07072                }
07073                ast_hangup(chan);
07074                goto quit;
07075             } else {
07076                ast_log(LOG_WARNING, "Huh?  Got *8# on call not on real\n");
07077                ast_hangup(chan);
07078                goto quit;
07079             }
07080             
07081          } else if (!p->hidecallerid && !strcmp(exten, "*67")) {
07082             ast_verb(3, "Disabling Caller*ID on %s\n", chan->name);
07083             /* Disable Caller*ID if enabled */
07084             p->hidecallerid = 1;
07085             if (chan->cid.cid_num)
07086                ast_free(chan->cid.cid_num);
07087             chan->cid.cid_num = NULL;
07088             if (chan->cid.cid_name)
07089                ast_free(chan->cid.cid_name);
07090             chan->cid.cid_name = NULL;
07091             res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
07092             if (res) {
07093                ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n", 
07094                   chan->name, strerror(errno));
07095             }
07096             len = 0;
07097             memset(exten, 0, sizeof(exten));
07098             timeout = firstdigittimeout;
07099          } else if (p->callreturn && !strcmp(exten, "*69")) {
07100             res = 0;
07101             if (!ast_strlen_zero(p->lastcid_num)) {
07102                res = ast_say_digit_str(chan, p->lastcid_num, "", chan->language);
07103             }
07104             if (!res)
07105                res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
07106             break;
07107          } else if (!strcmp(exten, "*78")) {
07108             dahdi_dnd(p, 1);
07109             /* Do not disturb */
07110             res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
07111             getforward = 0;
07112             memset(exten, 0, sizeof(exten));
07113             len = 0;
07114          } else if (!strcmp(exten, "*79")) {
07115             dahdi_dnd(p, 0);
07116             /* Do not disturb */
07117             res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
07118             getforward = 0;
07119             memset(exten, 0, sizeof(exten));
07120             len = 0;
07121          } else if (p->cancallforward && !strcmp(exten, "*72")) {
07122             res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
07123             getforward = 1;
07124             memset(exten, 0, sizeof(exten));
07125             len = 0;
07126          } else if (p->cancallforward && !strcmp(exten, "*73")) {
07127             ast_verb(3, "Cancelling call forwarding on channel %d\n", p->channel);
07128             res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
07129             memset(p->call_forward, 0, sizeof(p->call_forward));
07130             getforward = 0;
07131             memset(exten, 0, sizeof(exten));
07132             len = 0;
07133          } else if ((p->transfer || p->canpark) && !strcmp(exten, ast_parking_ext()) && 
07134                   p->subs[SUB_THREEWAY].owner &&
07135                   ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
07136             /* This is a three way call, the main call being a real channel, 
07137                and we're parking the first call. */
07138             ast_masq_park_call(ast_bridged_channel(p->subs[SUB_THREEWAY].owner), chan, 0, NULL);
07139             ast_verb(3, "Parking call to '%s'\n", chan->name);
07140             break;
07141          } else if (!ast_strlen_zero(p->lastcid_num) && !strcmp(exten, "*60")) {
07142             ast_verb(3, "Blacklisting number %s\n", p->lastcid_num);
07143             res = ast_db_put("blacklist", p->lastcid_num, "1");
07144             if (!res) {
07145                res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
07146                memset(exten, 0, sizeof(exten));
07147                len = 0;
07148             }
07149          } else if (p->hidecallerid && !strcmp(exten, "*82")) {
07150             ast_verb(3, "Enabling Caller*ID on %s\n", chan->name);
07151             /* Enable Caller*ID if enabled */
07152             p->hidecallerid = 0;
07153             if (chan->cid.cid_num)
07154                ast_free(chan->cid.cid_num);
07155             chan->cid.cid_num = NULL;
07156             if (chan->cid.cid_name)
07157                ast_free(chan->cid.cid_name);
07158             chan->cid.cid_name = NULL;
07159             ast_set_callerid(chan, p->cid_num, p->cid_name, NULL);
07160             res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
07161             if (res) {
07162                ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n", 
07163                   chan->name, strerror(errno));
07164             }
07165             len = 0;
07166             memset(exten, 0, sizeof(exten));
07167             timeout = firstdigittimeout;
07168          } else if (!strcmp(exten, "*0")) {
07169             struct ast_channel *nbridge = 
07170                p->subs[SUB_THREEWAY].owner;
07171             struct dahdi_pvt *pbridge = NULL;
07172               /* set up the private struct of the bridged one, if any */
07173             if (nbridge && ast_bridged_channel(nbridge)) 
07174                pbridge = ast_bridged_channel(nbridge)->tech_pvt;
07175             if (nbridge && pbridge && 
07176                 (nbridge->tech == &dahdi_tech) && 
07177                 (ast_bridged_channel(nbridge)->tech == &dahdi_tech) &&
07178                 ISTRUNK(pbridge)) {
07179                int func = DAHDI_FLASH;
07180                /* Clear out the dial buffer */
07181                p->dop.dialstr[0] = '\0';
07182                /* flash hookswitch */
07183                if ((ioctl(pbridge->subs[SUB_REAL].dfd,DAHDI_HOOK,&func) == -1) && (errno != EINPROGRESS)) {
07184                   ast_log(LOG_WARNING, "Unable to flash external trunk on channel %s: %s\n", 
07185                      nbridge->name, strerror(errno));
07186                }
07187                swap_subs(p, SUB_REAL, SUB_THREEWAY);
07188                unalloc_sub(p, SUB_THREEWAY);
07189                p->owner = p->subs[SUB_REAL].owner;
07190                if (ast_bridged_channel(p->subs[SUB_REAL].owner))
07191                   ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
07192                ast_hangup(chan);
07193                goto quit;
07194             } else {
07195                tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
07196                dahdi_wait_event(p->subs[idx].dfd);
07197                tone_zone_play_tone(p->subs[idx].dfd, -1);
07198                swap_subs(p, SUB_REAL, SUB_THREEWAY);
07199                unalloc_sub(p, SUB_THREEWAY);
07200                p->owner = p->subs[SUB_REAL].owner;
07201                ast_hangup(chan);
07202                goto quit;
07203             }              
07204          } else if (!ast_canmatch_extension(chan, chan->context, exten, 1, chan->cid.cid_num) &&
07205                      ((exten[0] != '*') || (strlen(exten) > 2))) {
07206             ast_debug(1, "Can't match %s from '%s' in context %s\n", exten, chan->cid.cid_num ? chan->cid.cid_num : "<Unknown Caller>", chan->context);
07207             break;
07208          }
07209          if (!timeout)
07210             timeout = gendigittimeout;
07211          if (len && !ast_ignore_pattern(chan->context, exten))
07212             tone_zone_play_tone(p->subs[idx].dfd, -1);
07213       }
07214       break;
07215    case SIG_FXSLS:
07216    case SIG_FXSGS:
07217    case SIG_FXSKS:
07218 #ifdef HAVE_PRI
07219       if (p->pri) {
07220          /* This is a GR-303 trunk actually.  Wait for the first ring... */
07221          struct ast_frame *f;
07222          int res;
07223          time_t start;
07224 
07225          time(&start);
07226          ast_setstate(chan, AST_STATE_RING);
07227          while (time(NULL) < start + 3) {
07228             res = ast_waitfor(chan, 1000);
07229             if (res) {
07230                f = ast_read(chan);
07231                if (!f) {
07232                   ast_log(LOG_WARNING, "Whoa, hangup while waiting for first ring!\n");
07233                   ast_hangup(chan);
07234                   goto quit;
07235                } else if ((f->frametype == AST_FRAME_CONTROL) && (f->subclass == AST_CONTROL_RING)) {
07236                   res = 1;
07237                } else
07238                   res = 0;
07239                ast_frfree(f);
07240                if (res) {
07241                   ast_debug(1, "Got ring!\n");
07242                   res = 0;
07243                   break;
07244                }
07245             }
07246          }
07247       }
07248 #endif
07249       /* check for SMDI messages */
07250       if (p->use_smdi && p->smdi_iface) {
07251          smdi_msg = ast_smdi_md_message_wait(p->smdi_iface, SMDI_MD_WAIT_TIMEOUT);
07252 
07253          if (smdi_msg != NULL) {
07254             ast_copy_string(chan->exten, smdi_msg->fwd_st, sizeof(chan->exten));
07255 
07256             if (smdi_msg->type == 'B')
07257                pbx_builtin_setvar_helper(chan, "_SMDI_VM_TYPE", "b");
07258             else if (smdi_msg->type == 'N')
07259                pbx_builtin_setvar_helper(chan, "_SMDI_VM_TYPE", "u");
07260 
07261             ast_debug(1, "Received SMDI message on %s\n", chan->name);
07262          } else {
07263             ast_log(LOG_WARNING, "SMDI enabled but no SMDI message present\n");
07264          }
07265       }
07266 
07267       if (p->use_callerid && (p->cid_signalling == CID_SIG_SMDI && smdi_msg)) {
07268             number = smdi_msg->calling_st;
07269 
07270       /* If we want caller id, we're in a prering state due to a polarity reversal
07271        * and we're set to use a polarity reversal to trigger the start of caller id,
07272        * grab the caller id and wait for ringing to start... */
07273       } else if (p->use_callerid && (chan->_state == AST_STATE_PRERING && (p->cid_start == CID_START_POLARITY || p->cid_start == CID_START_POLARITY_IN))) {
07274          /* If set to use DTMF CID signalling, listen for DTMF */
07275          if (p->cid_signalling == CID_SIG_DTMF) {
07276             int k = 0;
07277             cs = NULL;
07278             ast_debug(1, "Receiving DTMF cid on channel %s\n", chan->name);
07279             dahdi_setlinear(p->subs[idx].dfd, 0);
07280             /*
07281              * We are the only party interested in the Rx stream since
07282              * we have not answered yet.  We don't need or even want DTMF
07283              * emulation.  The DTMF digits can come so fast that emulation
07284              * can drop some of them.
07285              */
07286             ast_set_flag(chan, AST_FLAG_END_DTMF_ONLY);
07287             res = 4000;/* This is a typical OFF time between rings. */
07288             for (;;) {
07289                struct ast_frame *f;
07290                res = ast_waitfor(chan, res);
07291                if (res <= 0) {
07292                   /*
07293                    * We do not need to restore the dahdi_setlinear()
07294                    * or AST_FLAG_END_DTMF_ONLY flag settings since we
07295                    * are hanging up the channel.
07296                    */
07297                   ast_log(LOG_WARNING, "DTMFCID timed out waiting for ring. "
07298                      "Exiting simple switch\n");
07299                   ast_hangup(chan);
07300                   goto quit;
07301                } 
07302                f = ast_read(chan);
07303                if (!f)
07304                   break;
07305                if (f->frametype == AST_FRAME_DTMF) {
07306                   if (k < ARRAY_LEN(dtmfbuf) - 1) {
07307                      dtmfbuf[k++] = f->subclass;
07308                   }
07309                   ast_debug(1, "CID got digit '%c'\n", f->subclass);
07310                   res = 4000;/* This is a typical OFF time between rings. */
07311                }
07312                ast_frfree(f);
07313                if (chan->_state == AST_STATE_RING ||
07314                    chan->_state == AST_STATE_RINGING) 
07315                   break; /* Got ring */
07316             }
07317             ast_clear_flag(chan, AST_FLAG_END_DTMF_ONLY);
07318             dtmfbuf[k] = '\0';
07319             dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
07320             /* Got cid and ring. */
07321             ast_debug(1, "CID got string '%s'\n", dtmfbuf);
07322             callerid_get_dtmf(dtmfbuf, dtmfcid, &flags);
07323             ast_debug(1, "CID is '%s', flags %d\n", dtmfcid, flags);
07324             /* If first byte is NULL, we have no cid */
07325             if (!ast_strlen_zero(dtmfcid)) 
07326                number = dtmfcid;
07327             else
07328                number = NULL;
07329          /* If set to use V23 Signalling, launch our FSK gubbins and listen for it */
07330          } else if ((p->cid_signalling == CID_SIG_V23) || (p->cid_signalling == CID_SIG_V23_JP)) {
07331             cs = callerid_new(p->cid_signalling);
07332             if (cs) {
07333                samples = 0;
07334 #if 1
07335                bump_gains(p);
07336 #endif
07337                /* Take out of linear mode for Caller*ID processing */
07338                dahdi_setlinear(p->subs[idx].dfd, 0);
07339                
07340                /* First we wait and listen for the Caller*ID */
07341                for (;;) {  
07342                   i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
07343                   if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) {
07344                      ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
07345                      callerid_free(cs);
07346                      ast_hangup(chan);
07347                      goto quit;
07348                   }
07349                   if (i & DAHDI_IOMUX_SIGEVENT) {
07350                      res = dahdi_get_event(p->subs[idx].dfd);
07351                      ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
07352                      if (res == DAHDI_EVENT_NOALARM) {
07353                         p->inalarm = 0;
07354                      }
07355 
07356                      if (p->cid_signalling == CID_SIG_V23_JP) {
07357                         if (res == DAHDI_EVENT_RINGBEGIN) {
07358                            res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
07359                            usleep(1);
07360                         }
07361                      } else {
07362                         res = 0;
07363                         break;
07364                      }
07365                   } else if (i & DAHDI_IOMUX_READ) {
07366                      res = read(p->subs[idx].dfd, buf, sizeof(buf));
07367                      if (res < 0) {
07368                         if (errno != ELAST) {
07369                            ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
07370                            callerid_free(cs);
07371                            ast_hangup(chan);
07372                            goto quit;
07373                         }
07374                         break;
07375                      }
07376                      samples += res;
07377 
07378                      if  (p->cid_signalling == CID_SIG_V23_JP) {
07379                         res = callerid_feed_jp(cs, buf, res, AST_LAW(p));
07380                      } else {
07381                         res = callerid_feed(cs, buf, res, AST_LAW(p));
07382                      }
07383                      if (res < 0) {
07384                         /*
07385                          * The previous diagnostic message output likely
07386                          * explains why it failed.
07387                          */
07388                         ast_log(LOG_WARNING,
07389                            "Failed to decode CallerID on channel '%s'\n",
07390                            chan->name);
07391                         break;
07392                      } else if (res)
07393                         break;
07394                      else if (samples > (8000 * 10))
07395                         break;
07396                   }
07397                }
07398                if (res == 1) {
07399                   callerid_get(cs, &name, &number, &flags);
07400                   ast_log(LOG_NOTICE, "CallerID number: %s, name: %s, flags=%d\n", number, name, flags);
07401                }
07402 
07403                if (p->cid_signalling == CID_SIG_V23_JP) {
07404                   res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
07405                   usleep(1);
07406                }
07407 
07408                /* Finished with Caller*ID, now wait for a ring to make sure there really is a call coming */
07409                res = 4000;/* This is a typical OFF time between rings. */
07410                for (;;) {
07411                   struct ast_frame *f;
07412                   res = ast_waitfor(chan, res);
07413                   if (res <= 0) {
07414                      ast_log(LOG_WARNING, "CID timed out waiting for ring. "
07415                         "Exiting simple switch\n");
07416                      ast_hangup(chan);
07417                      goto quit;
07418                   } 
07419                   if (!(f = ast_read(chan))) {
07420                      ast_log(LOG_WARNING, "Hangup received waiting for ring. Exiting simple switch\n");
07421                      ast_hangup(chan);
07422                      goto quit;
07423                   }
07424                   ast_frfree(f);
07425                   if (chan->_state == AST_STATE_RING ||
07426                       chan->_state == AST_STATE_RINGING) 
07427                      break; /* Got ring */
07428                }
07429    
07430                /* We must have a ring by now, so, if configured, lets try to listen for
07431                 * distinctive ringing */ 
07432                if (p->usedistinctiveringdetection) {
07433                   len = 0;
07434                   distMatches = 0;
07435                   /* Clear the current ring data array so we dont have old data in it. */
07436                   for (receivedRingT = 0; receivedRingT < ARRAY_LEN(curRingData); receivedRingT++)
07437                      curRingData[receivedRingT] = 0;
07438                   receivedRingT = 0;
07439                   counter = 0;
07440                   counter1 = 0;
07441                   /* Check to see if context is what it should be, if not set to be. */
07442                   if (strcmp(p->context,p->defcontext) != 0) {
07443                      ast_copy_string(p->context, p->defcontext, sizeof(p->context));
07444                      ast_copy_string(chan->context,p->defcontext,sizeof(chan->context));
07445                   }
07446       
07447                   for (;;) {  
07448                      i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
07449                      if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) {
07450                         ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
07451                         callerid_free(cs);
07452                         ast_hangup(chan);
07453                         goto quit;
07454                      }
07455                      if (i & DAHDI_IOMUX_SIGEVENT) {
07456                         res = dahdi_get_event(p->subs[idx].dfd);
07457                         ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
07458                         if (res == DAHDI_EVENT_NOALARM) {
07459                            p->inalarm = 0;
07460                         }
07461                         res = 0;
07462                         /* Let us detect distinctive ring */
07463       
07464                         curRingData[receivedRingT] = p->ringt;
07465       
07466                         if (p->ringt < p->ringt_base/2)
07467                            break;
07468                         /* Increment the ringT counter so we can match it against
07469                            values in chan_dahdi.conf for distinctive ring */
07470                         if (++receivedRingT == ARRAY_LEN(curRingData))
07471                            break;
07472                      } else if (i & DAHDI_IOMUX_READ) {
07473                         res = read(p->subs[idx].dfd, buf, sizeof(buf));
07474                         if (res < 0) {
07475                            if (errno != ELAST) {
07476                               ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
07477                               callerid_free(cs);
07478                               ast_hangup(chan);
07479                               goto quit;
07480                            }
07481                            break;
07482                         }
07483                         if (p->ringt) 
07484                            p->ringt--;
07485                         if (p->ringt == 1) {
07486                            res = -1;
07487                            break;
07488                         }
07489                      }
07490                   }
07491                      /* this only shows up if you have n of the dring patterns filled in */
07492                   ast_verb(3, "Detected ring pattern: %d,%d,%d\n",curRingData[0],curRingData[1],curRingData[2]);
07493                   for (counter = 0; counter < 3; counter++) {
07494                      /* Check to see if the rings we received match any of the ones in chan_dahdi.conf for this
07495                      channel */
07496                      distMatches = 0;
07497                      for (counter1 = 0; counter1 < 3; counter1++) {
07498                         ast_verb(3, "Ring pattern check range: %d\n", p->drings.ringnum[counter].range);
07499                         if (p->drings.ringnum[counter].ring[counter1] == -1) {
07500                            ast_verb(3, "Pattern ignore (-1) detected, so matching pattern %d regardless.\n",
07501                            curRingData[counter1]);
07502                            distMatches++;
07503                         }
07504                         else if (curRingData[counter1] <= (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range) &&
07505                             curRingData[counter1] >= (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range)) {
07506                            ast_verb(3, "Ring pattern matched in range: %d to %d\n",
07507                            (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range),
07508                            (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range));
07509                            distMatches++;
07510                         }
07511                      }
07512 
07513                      if (distMatches == 3) {
07514                         /* The ring matches, set the context to whatever is for distinctive ring.. */
07515                         ast_copy_string(p->context, p->drings.ringContext[counter].contextData, sizeof(p->context));
07516                         ast_copy_string(chan->context, p->drings.ringContext[counter].contextData, sizeof(chan->context));
07517                         ast_verb(3, "Distinctive Ring matched context %s\n",p->context);
07518                         break;
07519                      }
07520                   }
07521                }
07522                /* Restore linear mode (if appropriate) for Caller*ID processing */
07523                dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
07524 #if 1
07525                restore_gains(p);
07526 #endif            
07527             } else
07528                ast_log(LOG_WARNING, "Unable to get caller ID space\n");       
07529          } else {
07530             ast_log(LOG_WARNING, "Channel %s in prering "
07531                "state, but I have nothing to do. "
07532                "Terminating simple switch, should be "
07533                "restarted by the actual ring.\n", 
07534                chan->name);
07535             ast_hangup(chan);
07536             goto quit;
07537          }
07538       } else if (p->use_callerid && p->cid_start == CID_START_RING) {
07539                         if (p->cid_signalling == CID_SIG_DTMF) {
07540                                 int k = 0;
07541                                 cs = NULL;
07542                                 dahdi_setlinear(p->subs[idx].dfd, 0);
07543                                 res = 2000;
07544                                 for (;;) {
07545                                         struct ast_frame *f;
07546                                         res = ast_waitfor(chan, res);
07547                                         if (res <= 0) {
07548                                                 ast_log(LOG_WARNING, "DTMFCID timed out waiting for ring. "
07549                                                                 "Exiting simple switch\n");
07550                                                 ast_hangup(chan);
07551                                                 return NULL;
07552                                         }
07553                                         f = ast_read(chan);
07554                                         if (f->frametype == AST_FRAME_DTMF) {
07555                                                 dtmfbuf[k++] = f->subclass;
07556                                                 ast_log(LOG_DEBUG, "CID got digit '%c'\n", f->subclass);
07557                                                 res = 2000;
07558                                         }
07559                                         ast_frfree(f);
07560 
07561                                         if (p->ringt_base == p->ringt)
07562                                                 break;
07563 
07564                                 }
07565                                 dtmfbuf[k] = '\0';
07566                                 dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
07567                                 /* Got cid and ring. */
07568                                 callerid_get_dtmf(dtmfbuf, dtmfcid, &flags);
07569                                 ast_log(LOG_DEBUG, "CID is '%s', flags %d\n",
07570                                                 dtmfcid, flags);
07571                                 /* If first byte is NULL, we have no cid */
07572                                 if (!ast_strlen_zero(dtmfcid))
07573                                         number = dtmfcid;
07574                                 else
07575                                         number = NULL;
07576                                 /* If set to use V23 Signalling, launch our FSK gubbins and listen for it */
07577                         } else {
07578          /* FSK Bell202 callerID */
07579          cs = callerid_new(p->cid_signalling);
07580          if (cs) {
07581 #if 1
07582             bump_gains(p);
07583 #endif            
07584             samples = 0;
07585             len = 0;
07586             distMatches = 0;
07587             /* Clear the current ring data array so we dont have old data in it. */
07588             for (receivedRingT = 0; receivedRingT < ARRAY_LEN(curRingData); receivedRingT++)
07589                curRingData[receivedRingT] = 0;
07590             receivedRingT = 0;
07591             counter = 0;
07592             counter1 = 0;
07593             /* Check to see if context is what it should be, if not set to be. */
07594             if (strcmp(p->context,p->defcontext) != 0) {
07595                ast_copy_string(p->context, p->defcontext, sizeof(p->context));
07596                ast_copy_string(chan->context,p->defcontext,sizeof(chan->context));
07597             }
07598 
07599             /* Take out of linear mode for Caller*ID processing */
07600             dahdi_setlinear(p->subs[idx].dfd, 0);
07601             for (;;) {  
07602                i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
07603                if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) {
07604                   ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
07605                   callerid_free(cs);
07606                   ast_hangup(chan);
07607                   goto quit;
07608                }
07609                if (i & DAHDI_IOMUX_SIGEVENT) {
07610                   res = dahdi_get_event(p->subs[idx].dfd);
07611                   ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
07612                   if (res == DAHDI_EVENT_NOALARM) {
07613                      p->inalarm = 0;
07614                   }
07615                   /* If we get a PR event, they hung up while processing calerid */
07616                   if ( res == DAHDI_EVENT_POLARITY && p->hanguponpolarityswitch && p->polarity == POLARITY_REV) {
07617                      ast_log(LOG_DEBUG, "Hanging up due to polarity reversal on channel %d while detecting callerid\n", p->channel);
07618                      p->polarity = POLARITY_IDLE;
07619                      callerid_free(cs);
07620                      ast_hangup(chan);
07621                      goto quit;
07622                   }
07623                   res = 0;
07624                   /* Let us detect callerid when the telco uses distinctive ring */
07625 
07626                   curRingData[receivedRingT] = p->ringt;
07627 
07628                   if (p->ringt < p->ringt_base/2)
07629                      break;
07630                   /* Increment the ringT counter so we can match it against
07631                      values in chan_dahdi.conf for distinctive ring */
07632                   if (++receivedRingT == ARRAY_LEN(curRingData))
07633                      break;
07634                } else if (i & DAHDI_IOMUX_READ) {
07635                   res = read(p->subs[idx].dfd, buf, sizeof(buf));
07636                   if (res < 0) {
07637                      if (errno != ELAST) {
07638                         ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
07639                         callerid_free(cs);
07640                         ast_hangup(chan);
07641                         goto quit;
07642                      }
07643                      break;
07644                   }
07645                   if (p->ringt) 
07646                      p->ringt--;
07647                   if (p->ringt == 1) {
07648                      res = -1;
07649                      break;
07650                   }
07651                   samples += res;
07652                   res = callerid_feed(cs, buf, res, AST_LAW(p));
07653                   if (res < 0) {
07654                      /*
07655                       * The previous diagnostic message output likely
07656                       * explains why it failed.
07657                       */
07658                      ast_log(LOG_WARNING,
07659                         "Failed to decode CallerID on channel '%s'\n",
07660                         chan->name);
07661                      break;
07662                   } else if (res)
07663                      break;
07664                   else if (samples > (8000 * 10))
07665                      break;
07666                }
07667             }
07668             if (res == 1) {
07669                callerid_get(cs, &name, &number, &flags);
07670                ast_debug(1, "CallerID number: %s, name: %s, flags=%d\n", number, name, flags);
07671             }
07672             if (distinctiveringaftercid == 1) {
07673                /* Clear the current ring data array so we dont have old data in it. */
07674                for (receivedRingT = 0; receivedRingT < 3; receivedRingT++) {
07675                   curRingData[receivedRingT] = 0;
07676                }
07677                receivedRingT = 0;
07678                ast_verb(3, "Detecting post-CID distinctive ring\n");
07679                for (;;) {
07680                   i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
07681                   if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i)))    {
07682                      ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
07683                      callerid_free(cs);
07684                      ast_hangup(chan);
07685                      goto quit;
07686                   }
07687                   if (i & DAHDI_IOMUX_SIGEVENT) {
07688                      res = dahdi_get_event(p->subs[idx].dfd);
07689                      ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
07690                      if (res == DAHDI_EVENT_NOALARM) {
07691                         p->inalarm = 0;
07692                      }
07693                      res = 0;
07694                      /* Let us detect callerid when the telco uses distinctive ring */
07695 
07696                      curRingData[receivedRingT] = p->ringt;
07697 
07698                      if (p->ringt < p->ringt_base/2)
07699                         break;
07700                      /* Increment the ringT counter so we can match it against
07701                         values in chan_dahdi.conf for distinctive ring */
07702                      if (++receivedRingT == ARRAY_LEN(curRingData))
07703                         break;
07704                   } else if (i & DAHDI_IOMUX_READ) {
07705                      res = read(p->subs[idx].dfd, buf, sizeof(buf));
07706                      if (res < 0) {
07707                         if (errno != ELAST) {
07708                            ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
07709                            callerid_free(cs);
07710                            ast_hangup(chan);
07711                            goto quit;
07712                         }
07713                         break;
07714                      }
07715                   if (p->ringt)
07716                      p->ringt--;
07717                      if (p->ringt == 1) {
07718                         res = -1;
07719                         break;
07720                      }
07721                   }
07722                }
07723             }
07724             if (p->usedistinctiveringdetection) {
07725                   /* this only shows up if you have n of the dring patterns filled in */
07726                ast_verb(3, "Detected ring pattern: %d,%d,%d\n",curRingData[0],curRingData[1],curRingData[2]);
07727 
07728                for (counter = 0; counter < 3; counter++) {
07729                   /* Check to see if the rings we received match any of the ones in chan_dahdi.conf for this
07730                   channel */
07731                      /* this only shows up if you have n of the dring patterns filled in */
07732                   ast_verb(3, "Checking %d,%d,%d\n",
07733                         p->drings.ringnum[counter].ring[0],
07734                         p->drings.ringnum[counter].ring[1],
07735                         p->drings.ringnum[counter].ring[2]);
07736                   distMatches = 0;
07737                   for (counter1 = 0; counter1 < 3; counter1++) {
07738                      ast_verb(3, "Ring pattern check range: %d\n", p->drings.ringnum[counter].range);
07739                      if (p->drings.ringnum[counter].ring[counter1] == -1) {
07740                         ast_verb(3, "Pattern ignore (-1) detected, so matching pattern %d regardless.\n",
07741                         curRingData[counter1]);
07742                         distMatches++;
07743                      }
07744                      else if (curRingData[counter1] <= (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range) &&
07745                          curRingData[counter1] >= (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range)) {
07746                         ast_verb(3, "Ring pattern matched in range: %d to %d\n",
07747                         (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range),
07748                         (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range));
07749                         distMatches++;
07750                      }
07751                   }
07752                   if (distMatches == 3) {
07753                      /* The ring matches, set the context to whatever is for distinctive ring.. */
07754                      ast_copy_string(p->context, p->drings.ringContext[counter].contextData, sizeof(p->context));
07755                      ast_copy_string(chan->context, p->drings.ringContext[counter].contextData, sizeof(chan->context));
07756                      ast_verb(3, "Distinctive Ring matched context %s\n",p->context);
07757                      break;
07758                   }
07759                }
07760             }
07761             /* Restore linear mode (if appropriate) for Caller*ID processing */
07762             dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
07763 #if 1
07764             restore_gains(p);
07765 #endif            
07766             if (res < 0) {
07767                ast_log(LOG_WARNING, "CallerID returned with error on channel '%s'\n", chan->name);
07768             }
07769          } else
07770             ast_log(LOG_WARNING, "Unable to get caller ID space\n");
07771       }
07772       }
07773       else
07774          cs = NULL;
07775 
07776       if (number)
07777          ast_shrink_phone_number(number);
07778       ast_set_callerid(chan, number, name, number);
07779 
07780       if (smdi_msg)
07781          ASTOBJ_UNREF(smdi_msg, ast_smdi_md_message_destroy);
07782 
07783       if (cs)
07784          callerid_free(cs);
07785       /* If the CID had Message waiting payload, assume that this for MWI only and hangup the call */
07786       if (flags & CID_MSGWAITING) {
07787          ast_log(LOG_NOTICE, "MWI: Channel %d message waiting!\n", p->channel);
07788          notify_message(p->mailbox, 1);
07789          /* If generated using Ring Pulse Alert, then ring has been answered as a call and needs to be hungup */
07790          if (p->mwimonitor_rpas) {
07791             ast_hangup(chan);
07792             return NULL;
07793          }
07794       } else if (flags & CID_NOMSGWAITING) {
07795          ast_log(LOG_NOTICE, "MWI: Channel %d no message waiting!\n", p->channel);
07796          notify_message(p->mailbox, 0);
07797          /* If generated using Ring Pulse Alert, then ring has been answered as a call and needs to be hungup */
07798          if (p->mwimonitor_rpas) {
07799             ast_hangup(chan);
07800             return NULL;
07801          }
07802       }
07803 
07804       ast_setstate(chan, AST_STATE_RING);
07805       chan->rings = 1;
07806       p->ringt = p->ringt_base;
07807       res = ast_pbx_run(chan);
07808       if (res) {
07809          ast_hangup(chan);
07810          ast_log(LOG_WARNING, "PBX exited non-zero\n");
07811       }
07812       goto quit;
07813    default:
07814       ast_log(LOG_WARNING, "Don't know how to handle simple switch with signalling %s on channel %d\n", sig2str(p->sig), p->channel);
07815       res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
07816       if (res < 0)
07817             ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", p->channel);
07818    }
07819    res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
07820    if (res < 0)
07821          ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", p->channel);
07822    ast_hangup(chan);
07823 quit:
07824    ast_mutex_lock(&ss_thread_lock);
07825    ss_thread_count--;
07826    ast_cond_signal(&ss_thread_complete);
07827    ast_mutex_unlock(&ss_thread_lock);
07828    return NULL;
07829 }
07830 
07831 struct mwi_thread_data {
07832    struct dahdi_pvt *pvt;
07833    unsigned char buf[READ_SIZE];
07834    size_t len;
07835 };
07836 
07837 static int calc_energy(const unsigned char *buf, int len, int law)
07838 {
07839    int x;
07840    int sum = 0;
07841 
07842    if (!len)
07843       return 0;
07844 
07845    for (x = 0; x < len; x++)
07846       sum += abs(law == AST_FORMAT_ULAW ? AST_MULAW(buf[x]) : AST_ALAW(buf[x]));
07847 
07848    return sum / len;
07849 }
07850 
07851 static void *mwi_thread(void *data)
07852 {
07853    struct mwi_thread_data *mtd = data;
07854    struct callerid_state *cs;
07855    pthread_t threadid;
07856    int samples = 0;
07857    char *name, *number;
07858    int flags;
07859    int i, res;
07860    unsigned int spill_done = 0;
07861    int spill_result = -1;
07862    
07863    if (!(cs = callerid_new(mtd->pvt->cid_signalling))) {
07864       mtd->pvt->mwimonitoractive = 0;
07865 
07866       return NULL;
07867    }
07868    
07869    callerid_feed(cs, mtd->buf, mtd->len, AST_LAW(mtd->pvt));
07870 
07871    bump_gains(mtd->pvt);
07872 
07873    for (;;) {  
07874       i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
07875       if ((res = ioctl(mtd->pvt->subs[SUB_REAL].dfd, DAHDI_IOMUX, &i))) {
07876          ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
07877          goto quit;
07878       }
07879 
07880       if (i & DAHDI_IOMUX_SIGEVENT) {
07881          struct ast_channel *chan;
07882 
07883          /* If we get an event, screen out events that we do not act on.
07884           * Otherwise, cancel and go to the simple switch to let it deal with it.
07885           */
07886          res = dahdi_get_event(mtd->pvt->subs[SUB_REAL].dfd);
07887 
07888          switch (res) {
07889          case DAHDI_EVENT_NEONMWI_ACTIVE:
07890          case DAHDI_EVENT_NEONMWI_INACTIVE:
07891          case DAHDI_EVENT_NONE:
07892          case DAHDI_EVENT_BITSCHANGED:
07893             break;
07894          case DAHDI_EVENT_NOALARM:
07895             mtd->pvt->inalarm = 0;
07896             ast_log(LOG_NOTICE, "Alarm cleared on channel %d\n", mtd->pvt->channel);
07897             manager_event(EVENT_FLAG_SYSTEM, "AlarmClear",
07898                "Channel: %d\r\n", mtd->pvt->channel);
07899             break;
07900          case DAHDI_EVENT_ALARM:
07901             mtd->pvt->inalarm = 1;
07902             res = get_alarms(mtd->pvt);
07903             handle_alarms(mtd->pvt, res);
07904             break; /* What to do on channel alarm ???? -- fall thru intentionally?? */
07905          default:
07906             ast_log(LOG_NOTICE, "Got event %d (%s)...  Passing along to ss_thread\n", res, event2str(res));
07907             callerid_free(cs);
07908             
07909             restore_gains(mtd->pvt);
07910             mtd->pvt->ringt = mtd->pvt->ringt_base;
07911 
07912             if ((chan = dahdi_new(mtd->pvt, AST_STATE_RING, 0, SUB_REAL, 0, 0))) {
07913                if (ast_pthread_create_detached(&threadid, NULL, ss_thread, chan)) {
07914                   ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", mtd->pvt->channel);
07915                   res = tone_zone_play_tone(mtd->pvt->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
07916                   if (res < 0)
07917                      ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", mtd->pvt->channel);
07918                   ast_hangup(chan);
07919                   goto quit;
07920                }
07921                goto quit_no_clean;
07922 
07923             } else {
07924                ast_log(LOG_WARNING, "Could not create channel to handle call\n");
07925             }
07926          }
07927       } else if (i & DAHDI_IOMUX_READ) {
07928          if ((res = read(mtd->pvt->subs[SUB_REAL].dfd, mtd->buf, sizeof(mtd->buf))) < 0) {
07929             if (errno != ELAST) {
07930                ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
07931                goto quit;
07932             }
07933             break;
07934          }
07935          samples += res;
07936          if (!spill_done) {
07937             if ((spill_result = callerid_feed(cs, mtd->buf, res, AST_LAW(mtd->pvt))) < 0) {
07938                /*
07939                 * The previous diagnostic message output likely
07940                 * explains why it failed.
07941                 */
07942                ast_log(LOG_WARNING, "Failed to decode CallerID\n");
07943                break;
07944             } else if (spill_result) {
07945                spill_done = 1;
07946             }
07947          } else {
07948             /* keep reading data until the energy level drops below the threshold
07949                so we don't get another 'trigger' on the remaining carrier signal
07950             */
07951             if (calc_energy(mtd->buf, res, AST_LAW(mtd->pvt)) <= mwilevel)
07952                break;
07953          }
07954          if (samples > (8000 * 4)) /*Termination case - time to give up*/
07955             break;
07956       }
07957    }
07958 
07959    if (spill_result == 1) {
07960       callerid_get(cs, &name, &number, &flags);
07961       if (flags & CID_MSGWAITING) {
07962          ast_log(LOG_NOTICE, "mwi: Have Messages on channel %d\n", mtd->pvt->channel);
07963          notify_message(mtd->pvt->mailbox, 1);
07964       } else if (flags & CID_NOMSGWAITING) {
07965          ast_log(LOG_NOTICE, "mwi: No Messages on channel %d\n", mtd->pvt->channel);
07966          notify_message(mtd->pvt->mailbox, 0);
07967       } else {
07968          ast_log(LOG_NOTICE, "mwi: Status unknown on channel %d\n", mtd->pvt->channel);
07969       }
07970    }
07971 
07972 
07973 quit:
07974    callerid_free(cs);
07975 
07976    restore_gains(mtd->pvt);
07977 
07978 quit_no_clean:
07979    mtd->pvt->mwimonitoractive = 0;
07980 
07981    ast_free(mtd);
07982 
07983    return NULL;
07984 }
07985 
07986 /* States for sending MWI message
07987  * First three states are required for send Ring Pulse Alert Signal 
07988  */
07989 enum mwisend_states {
07990    MWI_SEND_SA,
07991  MWI_SEND_SA_WAIT,
07992  MWI_SEND_PAUSE,
07993  MWI_SEND_SPILL,
07994  MWI_SEND_CLEANUP,
07995  MWI_SEND_DONE
07996 };
07997 
07998 static void *mwi_send_thread(void *data)
07999 {
08000    struct mwi_thread_data *mtd = data;
08001    struct timeval timeout_basis, suspend, now;
08002    int x, i, res;
08003    int num_read;
08004    enum mwisend_states mwi_send_state = MWI_SEND_SPILL; /*Assume FSK only */
08005 
08006    ast_mutex_lock(&mwi_thread_lock);
08007    mwi_thread_count++;
08008    ast_mutex_unlock(&mwi_thread_lock);
08009 
08010    /* Determine how this spill is to be sent */
08011    if(mwisend_rpas) {
08012       mwi_send_state = MWI_SEND_SA;
08013    }
08014 
08015    gettimeofday(&timeout_basis, NULL);
08016    
08017    mtd->pvt->cidspill = ast_calloc(1, MAX_CALLERID_SIZE);
08018    if (!mtd->pvt->cidspill) {
08019       mtd->pvt->mwisendactive = 0;
08020       ast_free(mtd);
08021       return NULL;
08022    }
08023    x = DAHDI_FLUSH_BOTH;
08024    res = ioctl(mtd->pvt->subs[SUB_REAL].dfd, DAHDI_FLUSH, &x);
08025    x = 3000;
08026    ioctl(mtd->pvt->subs[SUB_REAL].dfd, DAHDI_ONHOOKTRANSFER, &x);
08027    mtd->pvt->cidlen = vmwi_generate(mtd->pvt->cidspill, has_voicemail(mtd->pvt), CID_MWI_TYPE_MDMF_FULL,
08028                             AST_LAW(mtd->pvt), mtd->pvt->cid_name, mtd->pvt->cid_num, 0);
08029    mtd->pvt->cidpos = 0;
08030 
08031    while (MWI_SEND_DONE != mwi_send_state) {
08032       num_read = 0;
08033       gettimeofday(&now, NULL);
08034       if ( 10 < (now.tv_sec - timeout_basis.tv_sec)) {
08035          ast_log(LOG_WARNING, "MWI Send TIMEOUT in state %d\n", mwi_send_state);
08036          goto quit;
08037       }
08038 
08039       i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
08040       if ((res = ioctl(mtd->pvt->subs[SUB_REAL].dfd, DAHDI_IOMUX, &i))) {
08041          ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
08042          goto quit;
08043       }
08044 
08045       if (i & DAHDI_IOMUX_SIGEVENT) {
08046          /* If we get an event, screen out events that we do not act on.
08047          * Otherwise, let handle_init_event determine what is needed
08048          */
08049          res = dahdi_get_event(mtd->pvt->subs[SUB_REAL].dfd);
08050          switch (res) {
08051             case DAHDI_EVENT_RINGEROFF:
08052                if(mwi_send_state == MWI_SEND_SA_WAIT) {
08053                   if (dahdi_set_hook(mtd->pvt->subs[SUB_REAL].dfd, DAHDI_RINGOFF) ) {
08054                      ast_log(LOG_WARNING, "Unable to finsh RP-AS: %s\n", strerror(errno));
08055                      goto quit;
08056                   }
08057                   mwi_send_state = MWI_SEND_PAUSE;
08058                   gettimeofday(&suspend, NULL);
08059                }
08060                break;
08061             case DAHDI_EVENT_RINGERON:
08062             case DAHDI_EVENT_HOOKCOMPLETE:
08063                break;
08064             default:
08065                /* Got to the default init event handler */
08066                if (0 < handle_init_event(mtd->pvt, res)) {
08067                   /* I've spawned a thread, get out */
08068                   goto quit;
08069                }
08070                break;
08071          }
08072       } else if (i & DAHDI_IOMUX_READ) {
08073          if ((num_read = read(mtd->pvt->subs[SUB_REAL].dfd, mtd->buf, sizeof(mtd->buf))) < 0) {
08074             if (errno != ELAST) {
08075                ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
08076                goto quit;
08077             }
08078             break;
08079          }
08080       }
08081       /* Perform mwi send action */
08082       switch ( mwi_send_state) {
08083          case MWI_SEND_SA:
08084             /* Send the Ring Pulse Signal Alert */
08085             res = ioctl(mtd->pvt->subs[SUB_REAL].dfd, DAHDI_SETCADENCE, &AS_RP_cadence);
08086             if (res) {
08087                ast_log(LOG_WARNING, "Unable to set RP-AS ring cadence: %s\n", strerror(errno));
08088                goto quit;
08089             }
08090             dahdi_set_hook(mtd->pvt->subs[SUB_REAL].dfd, DAHDI_RING);
08091             mwi_send_state = MWI_SEND_SA_WAIT;
08092             break;
08093             case MWI_SEND_SA_WAIT:  /* do nothing until I get RINGEROFF event */
08094                break;
08095                case MWI_SEND_PAUSE:  /* Wait between alert and spill - min of 500 mS*/
08096                   gettimeofday(&now, NULL);
08097                   if ((int)(now.tv_sec - suspend.tv_sec) * 1000000 + (int)now.tv_usec - (int)suspend.tv_usec > 500000) {
08098                      mwi_send_state = MWI_SEND_SPILL;
08099                   }
08100                   break;
08101          case MWI_SEND_SPILL:
08102             /* We read some number of bytes.  Write an equal amount of data */
08103             if(0 < num_read) {
08104                if (num_read > mtd->pvt->cidlen - mtd->pvt->cidpos)
08105                   num_read = mtd->pvt->cidlen - mtd->pvt->cidpos;
08106                res = write(mtd->pvt->subs[SUB_REAL].dfd, mtd->pvt->cidspill + mtd->pvt->cidpos, num_read);
08107                if (res > 0) {
08108                   mtd->pvt->cidpos += res;
08109                   if (mtd->pvt->cidpos >= mtd->pvt->cidlen) {
08110                      ast_free(mtd->pvt->cidspill);
08111                      mtd->pvt->cidspill = NULL;
08112                      mtd->pvt->cidpos = 0;
08113                      mtd->pvt->cidlen = 0;
08114                      mwi_send_state = MWI_SEND_CLEANUP;
08115                   }
08116                } else {
08117                   ast_log(LOG_WARNING, "MWI Send Write failed: %s\n", strerror(errno));
08118                   goto quit;
08119                }
08120             }
08121             break;
08122          case MWI_SEND_CLEANUP:
08123             /* For now, do nothing */
08124             mwi_send_state = MWI_SEND_DONE;
08125             break;
08126          default:
08127             /* Should not get here, punt*/
08128             goto quit;
08129             break;
08130       }
08131    }
08132 
08133 quit:
08134    if(mtd->pvt->cidspill) {
08135       ast_free(mtd->pvt->cidspill);
08136       mtd->pvt->cidspill = NULL;
08137    }
08138    mtd->pvt->mwisendactive = 0;
08139    ast_free(mtd);
08140 
08141    ast_mutex_lock(&mwi_thread_lock);
08142    mwi_thread_count--;
08143    ast_cond_signal(&mwi_thread_complete);
08144    ast_mutex_unlock(&mwi_thread_lock);
08145 
08146    return NULL;
08147 }
08148 
08149 
08150 /* destroy a DAHDI channel, identified by its number */
08151 static int dahdi_destroy_channel_bynum(int channel)
08152 {
08153    struct dahdi_pvt *tmp = NULL;
08154    struct dahdi_pvt *prev = NULL;
08155 
08156    tmp = iflist;
08157    while (tmp) {
08158       if (tmp->channel == channel) {
08159          int x = DAHDI_FLASH;
08160          ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_HOOK, &x); /* important to create an event for dahdi_wait_event to register so that all ss_threads terminate */
08161          destroy_channel(prev, tmp, 1);
08162          ast_module_unref(ast_module_info->self);
08163          return RESULT_SUCCESS;
08164       }
08165       prev = tmp;
08166       tmp = tmp->next;
08167    }
08168    return RESULT_FAILURE;
08169 }
08170 
08171 static struct dahdi_pvt *handle_init_event(struct dahdi_pvt *i, int event)
08172 {
08173    int res;
08174    pthread_t threadid;
08175    struct ast_channel *chan;
08176 
08177    /* Handle an event on a given channel for the monitor thread. */
08178 
08179    switch (event) {
08180    case DAHDI_EVENT_NONE:
08181    case DAHDI_EVENT_BITSCHANGED:
08182       break;
08183    case DAHDI_EVENT_WINKFLASH:
08184    case DAHDI_EVENT_RINGOFFHOOK:
08185       if (i->inalarm) break;
08186       if (i->radio) break;
08187       /* Got a ring/answer.  What kind of channel are we? */
08188       switch (i->sig) {
08189       case SIG_FXOLS:
08190       case SIG_FXOGS:
08191       case SIG_FXOKS:
08192          res = dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
08193          if (res && (errno == EBUSY))
08194             break;
08195          if (i->cidspill) {
08196             /* Cancel VMWI spill */
08197             ast_free(i->cidspill);
08198             i->cidspill = NULL;
08199          }
08200          if (i->immediate) {
08201             dahdi_enable_ec(i);
08202             /* The channel is immediately up.  Start right away */
08203             res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
08204             chan = dahdi_new(i, AST_STATE_RING, 1, SUB_REAL, 0, 0);
08205             if (!chan) {
08206                ast_log(LOG_WARNING, "Unable to start PBX on channel %d\n", i->channel);
08207                res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
08208                if (res < 0)
08209                   ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
08210             }
08211          } else {
08212             /* Check for callerid, digits, etc */
08213             chan = dahdi_new(i, AST_STATE_RESERVED, 0, SUB_REAL, 0, 0);
08214             if (chan) {
08215                if (has_voicemail(i))
08216                   res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_STUTTER);
08217                else
08218                   res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_DIALTONE);
08219                if (res < 0) 
08220                   ast_log(LOG_WARNING, "Unable to play dialtone on channel %d, do you have defaultzone and loadzone defined?\n", i->channel);
08221                if (ast_pthread_create_detached(&threadid, NULL, ss_thread, chan)) {
08222                   ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
08223                   res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
08224                   if (res < 0)
08225                      ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
08226                   ast_hangup(chan);
08227                }
08228             } else
08229                ast_log(LOG_WARNING, "Unable to create channel\n");
08230          }
08231          break;
08232       case SIG_FXSLS:
08233       case SIG_FXSGS:
08234       case SIG_FXSKS:
08235             i->ringt = i->ringt_base;
08236             /* Fall through */
08237       case SIG_EMWINK:
08238       case SIG_FEATD:
08239       case SIG_FEATDMF:
08240       case SIG_FEATDMF_TA:
08241       case SIG_E911:
08242       case SIG_FGC_CAMA:
08243       case SIG_FGC_CAMAMF:
08244       case SIG_FEATB:
08245       case SIG_EM:
08246       case SIG_EM_E1:
08247       case SIG_SFWINK:
08248       case SIG_SF_FEATD:
08249       case SIG_SF_FEATDMF:
08250       case SIG_SF_FEATB:
08251       case SIG_SF:
08252          /* Check for callerid, digits, etc */
08253          if (i->cid_start == CID_START_POLARITY_IN) {
08254             chan = dahdi_new(i, AST_STATE_PRERING, 0, SUB_REAL, 0, 0);
08255          } else {
08256             chan = dahdi_new(i, AST_STATE_RING, 0, SUB_REAL, 0, 0);
08257          }
08258 
08259          if (!chan) {
08260             ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", i->channel);
08261          } else if (ast_pthread_create_detached(&threadid, NULL, ss_thread, chan)) {
08262             ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
08263             res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
08264             if (res < 0) {
08265                ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
08266             }
08267             ast_hangup(chan);
08268          }
08269          break;
08270       default:
08271          ast_log(LOG_WARNING, "Don't know how to handle ring/answer with signalling %s on channel %d\n", sig2str(i->sig), i->channel);
08272          res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
08273          if (res < 0)
08274                ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
08275          return NULL;
08276       }
08277       break;
08278    case DAHDI_EVENT_NOALARM:
08279       i->inalarm = 0;
08280       ast_log(LOG_NOTICE, "Alarm cleared on channel %d\n", i->channel);
08281       manager_event(EVENT_FLAG_SYSTEM, "AlarmClear",
08282          "Channel: %d\r\n", i->channel);
08283       break;
08284    case DAHDI_EVENT_ALARM:
08285       i->inalarm = 1;
08286       res = get_alarms(i);
08287       handle_alarms(i, res);
08288       /* fall thru intentionally */
08289    case DAHDI_EVENT_ONHOOK:
08290       if (i->radio)
08291          break;
08292       /* Back on hook.  Hang up. */
08293       switch (i->sig) {
08294       case SIG_FXOLS:
08295       case SIG_FXOGS:
08296       case SIG_FEATD:
08297       case SIG_FEATDMF:
08298       case SIG_FEATDMF_TA:
08299       case SIG_E911:
08300       case SIG_FGC_CAMA:
08301       case SIG_FGC_CAMAMF:
08302       case SIG_FEATB:
08303       case SIG_EM:
08304       case SIG_EM_E1:
08305       case SIG_EMWINK:
08306       case SIG_SF_FEATD:
08307       case SIG_SF_FEATDMF:
08308       case SIG_SF_FEATB:
08309       case SIG_SF:
08310       case SIG_SFWINK:
08311       case SIG_FXSLS:
08312       case SIG_FXSGS:
08313       case SIG_FXSKS:
08314       case SIG_GR303FXSKS:
08315          dahdi_disable_ec(i);
08316          res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
08317          dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
08318          break;
08319       case SIG_GR303FXOKS:
08320       case SIG_FXOKS:
08321          dahdi_disable_ec(i);
08322          /* Diddle the battery for the zhone */
08323 #ifdef ZHONE_HACK
08324          dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
08325          usleep(1);
08326 #endif         
08327          res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
08328          dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
08329          break;
08330       case SIG_PRI:
08331       case SIG_SS7:
08332       case SIG_BRI:
08333       case SIG_BRI_PTMP:
08334          dahdi_disable_ec(i);
08335          res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
08336          break;
08337       default:
08338          ast_log(LOG_WARNING, "Don't know how to handle on hook with signalling %s on channel %d\n", sig2str(i->sig), i->channel);
08339          res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
08340          return NULL;
08341       }
08342       break;
08343    case DAHDI_EVENT_POLARITY:
08344       switch (i->sig) {
08345       case SIG_FXSLS:
08346       case SIG_FXSKS:
08347       case SIG_FXSGS:
08348          /* We have already got a PR before the channel was 
08349             created, but it wasn't handled. We need polarity 
08350             to be REV for remote hangup detection to work. 
08351             At least in Spain */
08352          if (i->hanguponpolarityswitch)
08353             i->polarity = POLARITY_REV;
08354          if (i->cid_start == CID_START_POLARITY || i->cid_start == CID_START_POLARITY_IN) {
08355             i->polarity = POLARITY_REV;
08356             ast_verb(2, "Starting post polarity "
08357                    "CID detection on channel %d\n",
08358                    i->channel);
08359             chan = dahdi_new(i, AST_STATE_PRERING, 0, SUB_REAL, 0, 0);
08360             if (!chan) {
08361                ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", i->channel);
08362             } else if (ast_pthread_create_detached(&threadid, NULL, ss_thread, chan)) {
08363                ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
08364             }
08365          }
08366          break;
08367       default:
08368          ast_log(LOG_WARNING, "handle_init_event detected "
08369             "polarity reversal on non-FXO (SIG_FXS) "
08370             "interface %d\n", i->channel);
08371       }
08372       break;
08373    case DAHDI_EVENT_REMOVED: /* destroy channel, will actually do so in do_monitor */
08374       ast_log(LOG_NOTICE, 
08375             "Got DAHDI_EVENT_REMOVED. Destroying channel %d\n", 
08376             i->channel);
08377       return i;
08378    case DAHDI_EVENT_NEONMWI_ACTIVE:
08379       if (i->mwimonitor_neon) {
08380          notify_message(i->mailbox, 1);
08381          ast_log(LOG_NOTICE, "NEON MWI set for channel %d, mailbox %s \n", i->channel, i->mailbox);
08382       }
08383       break;
08384    case DAHDI_EVENT_NEONMWI_INACTIVE:
08385       if (i->mwimonitor_neon) {
08386          notify_message(i->mailbox, 0);
08387          ast_log(LOG_NOTICE, "NEON MWI cleared for channel %d, mailbox %s\n", i->channel, i->mailbox);
08388       }
08389       break;
08390    }
08391    return NULL;
08392 }
08393 
08394 static void *do_monitor(void *data)
08395 {
08396    int count, res, res2, spoint, pollres=0;
08397    struct dahdi_pvt *i;
08398    struct dahdi_pvt *last = NULL;
08399    struct dahdi_pvt *doomed;
08400    time_t thispass = 0, lastpass = 0;
08401    int found;
08402    char buf[1024];
08403    struct pollfd *pfds=NULL;
08404    int lastalloc = -1;
08405    /* This thread monitors all the frame relay interfaces which are not yet in use
08406       (and thus do not have a separate thread) indefinitely */
08407    /* From here on out, we die whenever asked */
08408 #if 0
08409    if (pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL)) {
08410       ast_log(LOG_WARNING, "Unable to set cancel type to asynchronous\n");
08411       return NULL;
08412    }
08413    ast_debug(1, "Monitor starting...\n");
08414 #endif
08415    pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
08416 
08417    for (;;) {
08418       /* Lock the interface list */
08419       ast_mutex_lock(&iflock);
08420       if (!pfds || (lastalloc != ifcount)) {
08421          if (pfds) {
08422             ast_free(pfds);
08423             pfds = NULL;
08424          }
08425          if (ifcount) {
08426             if (!(pfds = ast_calloc(1, ifcount * sizeof(*pfds)))) {
08427                ast_mutex_unlock(&iflock);
08428                return NULL;
08429             }
08430          }
08431          lastalloc = ifcount;
08432       }
08433       /* Build the stuff we're going to poll on, that is the socket of every
08434          dahdi_pvt that does not have an associated owner channel */
08435       count = 0;
08436       i = iflist;
08437       while (i) {
08438          if ((i->subs[SUB_REAL].dfd > -1) && i->sig && (!i->radio)) {
08439             if (!i->owner && !i->subs[SUB_REAL].owner && !i->mwimonitoractive && !i->mwisendactive) {
08440                /* This needs to be watched, as it lacks an owner */
08441                pfds[count].fd = i->subs[SUB_REAL].dfd;
08442                pfds[count].events = POLLPRI;
08443                pfds[count].revents = 0;
08444                /* If we are monitoring for VMWI or sending CID, we need to
08445                   read from the channel as well */
08446                if (i->cidspill || i->mwimonitor_fsk)
08447                   pfds[count].events |= POLLIN;
08448                count++;
08449             }
08450          }
08451          i = i->next;
08452       }
08453       /* Okay, now that we know what to do, release the interface lock */
08454       ast_mutex_unlock(&iflock);
08455       
08456       pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
08457       pthread_testcancel();
08458       /* Wait at least a second for something to happen */
08459       res = poll(pfds, count, 1000);
08460       pthread_testcancel();
08461       pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
08462 
08463       /* Okay, poll has finished.  Let's see what happened.  */
08464       if (res < 0) {
08465          if ((errno != EAGAIN) && (errno != EINTR))
08466             ast_log(LOG_WARNING, "poll return %d: %s\n", res, strerror(errno));
08467          continue;
08468       }
08469       /* Alright, lock the interface list again, and let's look and see what has
08470          happened */
08471       ast_mutex_lock(&iflock);
08472       found = 0;
08473       spoint = 0;
08474       lastpass = thispass;
08475       thispass = time(NULL);
08476       i = iflist;
08477       doomed = NULL;
08478       for (i = iflist;; i = i->next) {
08479          if (doomed) {
08480             int res;
08481             res = dahdi_destroy_channel_bynum(doomed->channel);
08482             if (!res) {
08483                ast_log(LOG_WARNING, "Couldn't find channel to destroy, hopefully another destroy operation just happened.\n");
08484             }
08485             doomed = NULL;
08486          }
08487          if (!i) {
08488             break;
08489          }
08490 
08491          if (thispass != lastpass) {
08492             if (!found && ((i == last) || ((i == iflist) && !last))) {
08493                last = i;
08494                if (last) {
08495                   if (!last->mwisendactive &&    last->sig & __DAHDI_SIG_FXO) {
08496                      res = has_voicemail(last);
08497                      if (last->msgstate != res) {
08498 
08499                         /* This channel has a new voicemail state,
08500                         * initiate a thread to send an MWI message
08501                         */
08502                         pthread_attr_t attr;
08503                         pthread_t threadid;
08504                         struct mwi_thread_data *mtd;
08505                         res2 = ioctl(last->subs[SUB_REAL].dfd, DAHDI_VMWI, &res);
08506                         if (res2) {
08507                            /* TODO: This message will ALWAYS be generated on some cards; any way to restrict it to those cards where it is interesting? */
08508                            ast_debug(3, "Unable to control message waiting led on channel %d: %s\n", last->channel, strerror(errno));
08509                         }
08510                         pthread_attr_init(&attr);
08511                         pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
08512                         if ((mtd = ast_calloc(1, sizeof(*mtd)))) {
08513                            last->msgstate = res;
08514                            mtd->pvt = last;
08515                            last->mwisendactive = 1;
08516                            if (ast_pthread_create_background(&threadid, &attr, mwi_send_thread, mtd)) {
08517                               ast_log(LOG_WARNING, "Unable to start mwi send thread on channel %d\n", last->channel);
08518                               ast_free(mtd);
08519                               last->mwisendactive = 0;
08520                            }
08521                         }
08522                         found ++;
08523                      }
08524                   }
08525                   last = last->next;
08526                }
08527             }
08528          }
08529          if ((i->subs[SUB_REAL].dfd > -1) && i->sig) {
08530             if (i->radio && !i->owner)
08531             {
08532                res = dahdi_get_event(i->subs[SUB_REAL].dfd);
08533                if (res)
08534                {
08535                   ast_debug(1, "Monitor doohicky got event %s on radio channel %d\n", event2str(res), i->channel);
08536                   /* Don't hold iflock while handling init events */
08537                   ast_mutex_unlock(&iflock);
08538                   doomed = handle_init_event(i, res);
08539                   ast_mutex_lock(&iflock);   
08540                }
08541                continue;
08542             }              
08543             pollres = ast_fdisset(pfds, i->subs[SUB_REAL].dfd, count, &spoint);
08544             if (pollres & POLLIN) {
08545                if (i->owner || i->subs[SUB_REAL].owner) {
08546 #ifdef HAVE_PRI
08547                   if (!i->pri)
08548 #endif                  
08549                      ast_log(LOG_WARNING, "Whoa....  I'm owned but found (%d) in read...\n", i->subs[SUB_REAL].dfd);
08550                   continue;
08551                }
08552                if (!i->cidspill && !i->mwimonitor_fsk) {
08553                   ast_log(LOG_WARNING, "Whoa....  I'm reading but have no cidspill (%d)...\n", i->subs[SUB_REAL].dfd);
08554                   continue;
08555                }
08556                res = read(i->subs[SUB_REAL].dfd, buf, sizeof(buf));
08557                if (res > 0) {
08558                   if (i->mwimonitor_fsk) {
08559                      if (calc_energy((unsigned char *) buf, res, AST_LAW(i)) > mwilevel) {
08560                         pthread_attr_t attr;
08561                         pthread_t threadid;
08562                         struct mwi_thread_data *mtd;
08563 
08564                         pthread_attr_init(&attr);
08565                         pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
08566 
08567                         ast_log(LOG_DEBUG, "Maybe some MWI on port %d!\n", i->channel);
08568                         if ((mtd = ast_calloc(1, sizeof(*mtd)))) {
08569                            mtd->pvt = i;
08570                            memcpy(mtd->buf, buf, res);
08571                            mtd->len = res;
08572                            if (ast_pthread_create_background(&threadid, &attr, mwi_thread, mtd)) {
08573                               ast_log(LOG_WARNING, "Unable to start mwi thread on channel %d\n", i->channel);
08574                               ast_free(mtd);
08575                            }
08576                            i->mwimonitoractive = 1;
08577                         }
08578                      }
08579                   }
08580                } else {
08581                   ast_log(LOG_WARNING, "Read failed with %d: %s\n", res, strerror(errno));
08582                }
08583             }
08584             if (pollres & POLLPRI) {
08585                if (i->owner || i->subs[SUB_REAL].owner) {
08586 #ifdef HAVE_PRI
08587                   if (!i->pri)
08588 #endif                  
08589                      ast_log(LOG_WARNING, "Whoa....  I'm owned but found (%d)...\n", i->subs[SUB_REAL].dfd);
08590                   continue;
08591                }
08592                res = dahdi_get_event(i->subs[SUB_REAL].dfd);
08593                ast_debug(1, "Monitor doohicky got event %s on channel %d\n", event2str(res), i->channel);
08594                /* Don't hold iflock while handling init events */
08595                ast_mutex_unlock(&iflock);
08596                doomed = handle_init_event(i, res);
08597                ast_mutex_lock(&iflock);   
08598             }
08599          }
08600       }
08601       ast_mutex_unlock(&iflock);
08602    }
08603    /* Never reached */
08604    return NULL;
08605    
08606 }
08607 
08608 static int restart_monitor(void)
08609 {
08610    /* If we're supposed to be stopped -- stay stopped */
08611    if (monitor_thread == AST_PTHREADT_STOP)
08612       return 0;
08613    ast_mutex_lock(&monlock);
08614    if (monitor_thread == pthread_self()) {
08615       ast_mutex_unlock(&monlock);
08616       ast_log(LOG_WARNING, "Cannot kill myself\n");
08617       return -1;
08618    }
08619    if (monitor_thread != AST_PTHREADT_NULL) {
08620       /* Wake up the thread */
08621       pthread_kill(monitor_thread, SIGURG);
08622    } else {
08623       /* Start a new monitor */
08624       if (ast_pthread_create_background(&monitor_thread, NULL, do_monitor, NULL) < 0) {
08625          ast_mutex_unlock(&monlock);
08626          ast_log(LOG_ERROR, "Unable to start monitor thread.\n");
08627          return -1;
08628       }
08629    }
08630    ast_mutex_unlock(&monlock);
08631    return 0;
08632 }
08633 
08634 #ifdef HAVE_PRI
08635 static int pri_resolve_span(int *span, int channel, int offset, struct dahdi_spaninfo *si)
08636 {
08637    int x;
08638    int trunkgroup;
08639    /* Get appropriate trunk group if there is one */
08640    trunkgroup = pris[*span].mastertrunkgroup;
08641    if (trunkgroup) {
08642       /* Select a specific trunk group */
08643       for (x = 0; x < NUM_SPANS; x++) {
08644          if (pris[x].trunkgroup == trunkgroup) {
08645             *span = x;
08646             return 0;
08647          }
08648       }
08649       ast_log(LOG_WARNING, "Channel %d on span %d configured to use nonexistent trunk group %d\n", channel, *span, trunkgroup);
08650       *span = -1;
08651    } else {
08652       if (pris[*span].trunkgroup) {
08653          ast_log(LOG_WARNING, "Unable to use span %d implicitly since it is trunk group %d (please use spanmap)\n", *span, pris[*span].trunkgroup);
08654          *span = -1;
08655       } else if (pris[*span].mastertrunkgroup) {
08656          ast_log(LOG_WARNING, "Unable to use span %d implicitly since it is already part of trunk group %d\n", *span, pris[*span].mastertrunkgroup);
08657          *span = -1;
08658       } else {
08659          if (si->totalchans == 31) {
08660             /* E1 */
08661             pris[*span].dchannels[0] = 16 + offset;
08662          } else if (si->totalchans == 24) {
08663             /* T1 or J1 */
08664             pris[*span].dchannels[0] = 24 + offset;
08665          } else if (si->totalchans == 3) {
08666             /* BRI */
08667             pris[*span].dchannels[0] = 3 + offset;
08668          } else {
08669             ast_log(LOG_WARNING, "Unable to use span %d, since the D-channel cannot be located (unexpected span size of %d channels)\n", *span, si->totalchans);
08670             *span = -1;
08671             return 0;
08672          }
08673          pris[*span].dchanavail[0] |= DCHAN_PROVISIONED;
08674          pris[*span].offset = offset;
08675          pris[*span].span = *span + 1;
08676       }
08677    }
08678    return 0;
08679 }
08680 
08681 static int pri_create_trunkgroup(int trunkgroup, int *channels)
08682 {
08683    struct dahdi_spaninfo si;
08684    struct dahdi_params p;
08685    int fd;
08686    int span;
08687    int ospan=0;
08688    int x,y;
08689    for (x = 0; x < NUM_SPANS; x++) {
08690       if (pris[x].trunkgroup == trunkgroup) {
08691          ast_log(LOG_WARNING, "Trunk group %d already exists on span %d, Primary d-channel %d\n", trunkgroup, x + 1, pris[x].dchannels[0]);
08692          return -1;
08693       }
08694    }
08695    for (y = 0; y < NUM_DCHANS; y++) {
08696       if (!channels[y]) 
08697          break;
08698       memset(&si, 0, sizeof(si));
08699       memset(&p, 0, sizeof(p));
08700       fd = open("/dev/dahdi/channel", O_RDWR);
08701       if (fd < 0) {
08702          ast_log(LOG_WARNING, "Failed to open channel: %s\n", strerror(errno));
08703          return -1;
08704       }
08705       x = channels[y];
08706       if (ioctl(fd, DAHDI_SPECIFY, &x)) {
08707          ast_log(LOG_WARNING, "Failed to specify channel %d: %s\n", channels[y], strerror(errno));
08708          close(fd);
08709          return -1;
08710       }
08711       if (ioctl(fd, DAHDI_GET_PARAMS, &p)) {
08712          ast_log(LOG_WARNING, "Failed to get channel parameters for channel %d: %s\n", channels[y], strerror(errno));
08713          return -1;
08714       }
08715       if (ioctl(fd, DAHDI_SPANSTAT, &si)) {
08716          ast_log(LOG_WARNING, "Failed go get span information on channel %d (span %d): %s\n", channels[y], p.spanno, strerror(errno));
08717          close(fd);
08718          return -1;
08719       }
08720       span = p.spanno - 1;
08721       if (pris[span].trunkgroup) {
08722          ast_log(LOG_WARNING, "Span %d is already provisioned for trunk group %d\n", span + 1, pris[span].trunkgroup);
08723          close(fd);
08724          return -1;
08725       }
08726       if (pris[span].pvts[0]) {
08727          ast_log(LOG_WARNING, "Span %d is already provisioned with channels (implicit PRI maybe?)\n", span + 1);
08728          close(fd);
08729          return -1;
08730       }
08731       if (!y) {
08732          pris[span].trunkgroup = trunkgroup;
08733          pris[span].offset = channels[y] - p.chanpos;
08734          ospan = span;
08735       }
08736       pris[ospan].dchannels[y] = channels[y];
08737       pris[ospan].dchanavail[y] |= DCHAN_PROVISIONED;
08738       pris[span].span = span + 1;
08739       close(fd);
08740    }
08741    return 0;   
08742 }
08743 
08744 static int pri_create_spanmap(int span, int trunkgroup, int logicalspan)
08745 {
08746    if (pris[span].mastertrunkgroup) {
08747       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);
08748       return -1;
08749    }
08750    pris[span].mastertrunkgroup = trunkgroup;
08751    pris[span].prilogicalspan = logicalspan;
08752    return 0;
08753 }
08754 
08755 #endif
08756 
08757 #ifdef HAVE_SS7
08758 
08759 static unsigned int parse_pointcode(const char *pcstring)
08760 {
08761    unsigned int code1, code2, code3;
08762    int numvals;
08763 
08764    numvals = sscanf(pcstring, "%30d-%30d-%30d", &code1, &code2, &code3);
08765    if (numvals == 1)
08766       return code1;
08767    if (numvals == 3)
08768       return (code1 << 16) | (code2 << 8) | code3;
08769 
08770    return 0;
08771 }
08772 
08773 static struct dahdi_ss7 * ss7_resolve_linkset(int linkset)
08774 {
08775    if ((linkset < 0) || (linkset >= NUM_SPANS))
08776       return NULL;
08777    else
08778       return &linksets[linkset - 1];
08779 }
08780 #endif /* HAVE_SS7 */
08781 
08782 /* converts a DAHDI sigtype to signalling as can be configured from
08783  * chan_dahdi.conf.
08784  * While both have basically the same values, this will later be the
08785  * place to add filters and sanity checks
08786  */
08787 static int sigtype_to_signalling(int sigtype)
08788 {
08789         return sigtype;
08790 }
08791 
08792 static struct dahdi_pvt *mkintf(int channel, const struct dahdi_chan_conf *conf, struct dahdi_pri *pri, int reloading)
08793 {
08794    /* Make a dahdi_pvt structure for this interface (or CRV if "pri" is specified) */
08795    struct dahdi_pvt *tmp = NULL, *tmp2,  *prev = NULL;
08796    char fn[80];
08797    struct dahdi_bufferinfo bi;
08798 
08799    int res;
08800    int span = 0;
08801    int here = 0;
08802    int x;
08803    struct dahdi_pvt **wlist;
08804    struct dahdi_pvt **wend;
08805    struct dahdi_params p;
08806 
08807    wlist = &iflist;
08808    wend = &ifend;
08809 
08810 #ifdef HAVE_PRI
08811    if (pri) {
08812       wlist = &pri->crvs;
08813       wend = &pri->crvend;
08814    }
08815 #endif
08816 
08817    tmp2 = *wlist;
08818    prev = NULL;
08819 
08820    while (tmp2) {
08821       if (!tmp2->destroy) {
08822          if (tmp2->channel == channel) {
08823             tmp = tmp2;
08824             here = 1;
08825             break;
08826          }
08827          if (tmp2->channel > channel) {
08828             break;
08829          }
08830       }
08831       prev = tmp2;
08832       tmp2 = tmp2->next;
08833    }
08834 
08835    if (!here && reloading != 1) {
08836       if (!(tmp = ast_calloc(1, sizeof(*tmp)))) {
08837          if (tmp)
08838             free(tmp);
08839          return NULL;
08840       }
08841       ast_mutex_init(&tmp->lock);
08842       ifcount++;
08843       for (x = 0; x < 3; x++)
08844          tmp->subs[x].dfd = -1;
08845       tmp->channel = channel;
08846       tmp->priindication_oob = conf->chan.priindication_oob;
08847    }
08848 
08849    if (tmp) {
08850       int chan_sig = conf->chan.sig;
08851       if (!here) {
08852          if ((channel != CHAN_PSEUDO) && !pri) {
08853             int count = 0;
08854             snprintf(fn, sizeof(fn), "%d", channel);
08855             /* Open non-blocking */
08856             tmp->subs[SUB_REAL].dfd = dahdi_open(fn);
08857             while (tmp->subs[SUB_REAL].dfd < 0 && reloading == 2 && count < 1000) { /* the kernel may not call dahdi_release fast enough for the open flagbit to be cleared in time */
08858                usleep(1);
08859                tmp->subs[SUB_REAL].dfd = dahdi_open(fn);
08860                count++;
08861             }
08862             /* Allocate a DAHDI structure */
08863             if (tmp->subs[SUB_REAL].dfd < 0) {
08864                ast_log(LOG_ERROR, "Unable to open channel %d: %s\nhere = %d, tmp->channel = %d, channel = %d\n", channel, strerror(errno), here, tmp->channel, channel);
08865                destroy_dahdi_pvt(&tmp);
08866                return NULL;
08867             }
08868             memset(&p, 0, sizeof(p));
08869             res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &p);
08870             if (res < 0) {
08871                ast_log(LOG_ERROR, "Unable to get parameters: %s\n", strerror(errno));
08872                destroy_dahdi_pvt(&tmp);
08873                return NULL;
08874             }
08875             if (conf->is_sig_auto)
08876                chan_sig = sigtype_to_signalling(p.sigtype);
08877             if (p.sigtype != (chan_sig & 0x3ffff)) {
08878                ast_log(LOG_ERROR, "Signalling requested on channel %d is %s but line is in %s signalling\n", channel, sig2str(chan_sig), sig2str(p.sigtype));
08879                destroy_dahdi_pvt(&tmp);
08880                return NULL;
08881             }
08882             tmp->law = p.curlaw;
08883             tmp->span = p.spanno;
08884             span = p.spanno - 1;
08885          } else {
08886             if (channel == CHAN_PSEUDO)
08887                chan_sig = 0;
08888             else if ((chan_sig != SIG_FXOKS) && (chan_sig != SIG_FXSKS)) {
08889                ast_log(LOG_ERROR, "CRV's must use FXO/FXS Kewl Start (fxo_ks/fxs_ks) signalling only.\n");
08890                return NULL;
08891             }
08892          }
08893 #ifdef HAVE_SS7
08894          if (chan_sig == SIG_SS7) {
08895             struct dahdi_ss7 *ss7;
08896             int clear = 0;
08897             if (ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &clear)) {
08898                ast_log(LOG_ERROR, "Unable to set clear mode on clear channel %d of span %d: %s\n", channel, p.spanno, strerror(errno));
08899                destroy_dahdi_pvt(&tmp);
08900                return NULL;
08901             }
08902 
08903             ss7 = ss7_resolve_linkset(cur_linkset);
08904             if (!ss7) {
08905                ast_log(LOG_ERROR, "Unable to find linkset %d\n", cur_linkset);
08906                destroy_dahdi_pvt(&tmp);
08907                return NULL;
08908             }
08909             if (cur_cicbeginswith < 0) {
08910                ast_log(LOG_ERROR, "Need to set cicbeginswith for the channels!\n");
08911                destroy_dahdi_pvt(&tmp);
08912                return NULL;
08913             }
08914 
08915             tmp->cic = cur_cicbeginswith++;
08916 
08917             /* DB: Add CIC's DPC information */
08918             tmp->dpc = cur_defaultdpc;
08919 
08920             tmp->ss7 = ss7;
08921             tmp->ss7call = NULL;
08922             ss7->pvts[ss7->numchans++] = tmp;
08923 
08924             ast_copy_string(ss7->internationalprefix, conf->ss7.internationalprefix, sizeof(ss7->internationalprefix));
08925             ast_copy_string(ss7->nationalprefix, conf->ss7.nationalprefix, sizeof(ss7->nationalprefix));
08926             ast_copy_string(ss7->subscriberprefix, conf->ss7.subscriberprefix, sizeof(ss7->subscriberprefix));
08927             ast_copy_string(ss7->unknownprefix, conf->ss7.unknownprefix, sizeof(ss7->unknownprefix));
08928 
08929             ss7->called_nai = conf->ss7.called_nai;
08930             ss7->calling_nai = conf->ss7.calling_nai;
08931          }
08932 #endif
08933 #ifdef HAVE_PRI
08934          if ((chan_sig == SIG_PRI) || (chan_sig == SIG_BRI) || (chan_sig == SIG_BRI_PTMP) || (chan_sig == SIG_GR303FXOKS) || (chan_sig == SIG_GR303FXSKS)) {
08935             int offset;
08936             int myswitchtype;
08937             int matchesdchan;
08938             int x,y;
08939             offset = 0;
08940             if (((chan_sig == SIG_PRI) || (chan_sig == SIG_BRI) || (chan_sig == SIG_BRI_PTMP)) 
08941                   && ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &offset)) {
08942                ast_log(LOG_ERROR, "Unable to set clear mode on clear channel %d of span %d: %s\n", channel, p.spanno, strerror(errno));
08943                destroy_dahdi_pvt(&tmp);
08944                return NULL;
08945             }
08946             if (span >= NUM_SPANS) {
08947                ast_log(LOG_ERROR, "Channel %d does not lie on a span I know of (%d)\n", channel, span);
08948                destroy_dahdi_pvt(&tmp);
08949                return NULL;
08950             } else {
08951                struct dahdi_spaninfo si;
08952                si.spanno = 0;
08953                if (ioctl(tmp->subs[SUB_REAL].dfd,DAHDI_SPANSTAT,&si) == -1) {
08954                   ast_log(LOG_ERROR, "Unable to get span status: %s\n", strerror(errno));
08955                   destroy_dahdi_pvt(&tmp);
08956                   return NULL;
08957                }
08958                /* Store the logical span first based upon the real span */
08959                tmp->logicalspan = pris[span].prilogicalspan;
08960                pri_resolve_span(&span, channel, (channel - p.chanpos), &si);
08961                if (span < 0) {
08962                   ast_log(LOG_WARNING, "Channel %d: Unable to find locate channel/trunk group!\n", channel);
08963                   destroy_dahdi_pvt(&tmp);
08964                   return NULL;
08965                }
08966                if ((chan_sig == SIG_PRI) ||
08967                      (chan_sig == SIG_BRI) ||
08968                      (chan_sig == SIG_BRI_PTMP))
08969                   myswitchtype = conf->pri.switchtype;
08970                else
08971                   myswitchtype = PRI_SWITCH_GR303_TMC;
08972                /* Make sure this isn't a d-channel */
08973                matchesdchan=0;
08974                for (x = 0; x < NUM_SPANS; x++) {
08975                   for (y = 0; y < NUM_DCHANS; y++) {
08976                      if (pris[x].dchannels[y] == tmp->channel) {
08977                         matchesdchan = 1;
08978                         break;
08979                      }
08980                   }
08981                }
08982                offset = p.chanpos;
08983                if (!matchesdchan) {
08984                   if (pris[span].nodetype && (pris[span].nodetype != conf->pri.nodetype)) {
08985                      ast_log(LOG_ERROR, "Span %d is already a %s node\n", span + 1, pri_node2str(pris[span].nodetype));
08986                      destroy_dahdi_pvt(&tmp);
08987                      return NULL;
08988                   }
08989                   if (pris[span].switchtype && (pris[span].switchtype != myswitchtype)) {
08990                      ast_log(LOG_ERROR, "Span %d is already a %s switch\n", span + 1, pri_switch2str(pris[span].switchtype));
08991                      destroy_dahdi_pvt(&tmp);
08992                      return NULL;
08993                   }
08994                   if ((pris[span].dialplan) && (pris[span].dialplan != conf->pri.dialplan)) {
08995                      ast_log(LOG_ERROR, "Span %d is already a %s dialing plan\n", span + 1, dialplan2str(pris[span].dialplan));
08996                      destroy_dahdi_pvt(&tmp);
08997                      return NULL;
08998                   }
08999                   if (!ast_strlen_zero(pris[span].idledial) && strcmp(pris[span].idledial, conf->pri.idledial)) {
09000                      ast_log(LOG_ERROR, "Span %d already has idledial '%s'.\n", span + 1, conf->pri.idledial);
09001                      destroy_dahdi_pvt(&tmp);
09002                      return NULL;
09003                   }
09004                   if (!ast_strlen_zero(pris[span].idleext) && strcmp(pris[span].idleext, conf->pri.idleext)) {
09005                      ast_log(LOG_ERROR, "Span %d already has idleext '%s'.\n", span + 1, conf->pri.idleext);
09006                      destroy_dahdi_pvt(&tmp);
09007                      return NULL;
09008                   }
09009                   if (pris[span].minunused && (pris[span].minunused != conf->pri.minunused)) {
09010                      ast_log(LOG_ERROR, "Span %d already has minunused of %d.\n", span + 1, conf->pri.minunused);
09011                      destroy_dahdi_pvt(&tmp);
09012                      return NULL;
09013                   }
09014                   if (pris[span].minidle && (pris[span].minidle != conf->pri.minidle)) {
09015                      ast_log(LOG_ERROR, "Span %d already has minidle of %d.\n", span + 1, conf->pri.minidle);
09016                      destroy_dahdi_pvt(&tmp);
09017                      return NULL;
09018                   }
09019                   if (pris[span].numchans >= MAX_CHANNELS) {
09020                      ast_log(LOG_ERROR, "Unable to add channel %d: Too many channels in trunk group %d!\n", channel,
09021                         pris[span].trunkgroup);
09022                      destroy_dahdi_pvt(&tmp);
09023                      return NULL;
09024                   }
09025 
09026                   pris[span].sig = chan_sig;
09027                   pris[span].nodetype = conf->pri.nodetype;
09028                   pris[span].switchtype = myswitchtype;
09029                   pris[span].nsf = conf->pri.nsf;
09030                   pris[span].dialplan = conf->pri.dialplan;
09031                   pris[span].localdialplan = conf->pri.localdialplan;
09032                   pris[span].pvts[pris[span].numchans++] = tmp;
09033                   pris[span].minunused = conf->pri.minunused;
09034                   pris[span].minidle = conf->pri.minidle;
09035                   pris[span].overlapdial = conf->pri.overlapdial;
09036 #ifdef HAVE_PRI_INBANDDISCONNECT
09037                   pris[span].inbanddisconnect = conf->pri.inbanddisconnect;
09038 #endif
09039                   pris[span].facilityenable = conf->pri.facilityenable;
09040                   ast_copy_string(pris[span].idledial, conf->pri.idledial, sizeof(pris[span].idledial));
09041                   ast_copy_string(pris[span].idleext, conf->pri.idleext, sizeof(pris[span].idleext));
09042                   ast_copy_string(pris[span].internationalprefix, conf->pri.internationalprefix, sizeof(pris[span].internationalprefix));
09043                   ast_copy_string(pris[span].nationalprefix, conf->pri.nationalprefix, sizeof(pris[span].nationalprefix));
09044                   ast_copy_string(pris[span].localprefix, conf->pri.localprefix, sizeof(pris[span].localprefix));
09045                   ast_copy_string(pris[span].privateprefix, conf->pri.privateprefix, sizeof(pris[span].privateprefix));
09046                   ast_copy_string(pris[span].unknownprefix, conf->pri.unknownprefix, sizeof(pris[span].unknownprefix));
09047                   pris[span].resetinterval = conf->pri.resetinterval;
09048                   
09049                   tmp->pri = &pris[span];
09050                   tmp->prioffset = offset;
09051                   tmp->call = NULL;
09052                } else {
09053                   ast_log(LOG_ERROR, "Channel %d is reserved for D-channel.\n", offset);
09054                   destroy_dahdi_pvt(&tmp);
09055                   return NULL;
09056                }
09057             }
09058          } else {
09059             tmp->prioffset = 0;
09060          }
09061 #endif
09062       } else {
09063          chan_sig = tmp->sig;
09064          if (tmp->subs[SUB_REAL].dfd > -1) {
09065             memset(&p, 0, sizeof(p));
09066             res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &p);
09067          }
09068       }
09069       /* Adjust starttime on loopstart and kewlstart trunks to reasonable values */
09070       switch (chan_sig) {
09071       case SIG_FXSKS:
09072       case SIG_FXSLS:
09073       case SIG_EM:
09074       case SIG_EM_E1:
09075       case SIG_EMWINK:
09076       case SIG_FEATD:
09077       case SIG_FEATDMF:
09078       case SIG_FEATDMF_TA:
09079       case SIG_FEATB:
09080       case SIG_E911:
09081       case SIG_SF:
09082       case SIG_SFWINK:
09083       case SIG_FGC_CAMA:
09084       case SIG_FGC_CAMAMF:
09085       case SIG_SF_FEATD:
09086       case SIG_SF_FEATDMF:
09087       case SIG_SF_FEATB:
09088          p.starttime = 250;
09089          break;
09090       }
09091 
09092       if (tmp->radio) {
09093          /* XXX Waiting to hear back from Jim if these should be adjustable XXX */
09094          p.channo = channel;
09095          p.rxwinktime = 1;
09096          p.rxflashtime = 1;
09097          p.starttime = 1;
09098          p.debouncetime = 5;
09099       }
09100       if (!tmp->radio) {
09101          p.channo = channel;
09102          /* Override timing settings based on config file */
09103          if (conf->timing.prewinktime >= 0)
09104             p.prewinktime = conf->timing.prewinktime;
09105          if (conf->timing.preflashtime >= 0)
09106             p.preflashtime = conf->timing.preflashtime;
09107          if (conf->timing.winktime >= 0)
09108             p.winktime = conf->timing.winktime;
09109          if (conf->timing.flashtime >= 0)
09110             p.flashtime = conf->timing.flashtime;
09111          if (conf->timing.starttime >= 0)
09112             p.starttime = conf->timing.starttime;
09113          if (conf->timing.rxwinktime >= 0)
09114             p.rxwinktime = conf->timing.rxwinktime;
09115          if (conf->timing.rxflashtime >= 0)
09116             p.rxflashtime = conf->timing.rxflashtime;
09117          if (conf->timing.debouncetime >= 0)
09118             p.debouncetime = conf->timing.debouncetime;
09119       }
09120 
09121       /* dont set parms on a pseudo-channel (or CRV) */
09122       if (tmp->subs[SUB_REAL].dfd >= 0)
09123       {
09124          res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_SET_PARAMS, &p);
09125          if (res < 0) {
09126             ast_log(LOG_ERROR, "Unable to set parameters: %s\n", strerror(errno));
09127             destroy_dahdi_pvt(&tmp);
09128             return NULL;
09129          }
09130       }
09131 #if 1
09132       if (!here && (tmp->subs[SUB_REAL].dfd > -1)) {
09133          memset(&bi, 0, sizeof(bi));
09134          res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_BUFINFO, &bi);
09135          if (!res) {
09136             bi.txbufpolicy = conf->chan.buf_policy;
09137             bi.rxbufpolicy = conf->chan.buf_policy;
09138             bi.numbufs = conf->chan.buf_no;
09139             res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi);
09140             if (res < 0) {
09141                ast_log(LOG_WARNING, "Unable to set buffer policy on channel %d: %s\n", channel, strerror(errno));
09142             }
09143          } else
09144             ast_log(LOG_WARNING, "Unable to check buffer policy on channel %d: %s\n", channel, strerror(errno));
09145       }
09146 #endif
09147       tmp->immediate = conf->chan.immediate;
09148       tmp->transfertobusy = conf->chan.transfertobusy;
09149       if (chan_sig & __DAHDI_SIG_FXS) {
09150          tmp->mwimonitor_fsk = conf->chan.mwimonitor_fsk;
09151          tmp->mwimonitor_neon = conf->chan.mwimonitor_neon;
09152          tmp->mwimonitor_rpas = conf->chan.mwimonitor_rpas;
09153       }
09154       tmp->sig = chan_sig;
09155       tmp->outsigmod = conf->chan.outsigmod;
09156       tmp->ringt_base = ringt_base;
09157       tmp->firstradio = 0;
09158       if ((chan_sig == SIG_FXOKS) || (chan_sig == SIG_FXOLS) || (chan_sig == SIG_FXOGS))
09159          tmp->permcallwaiting = conf->chan.callwaiting;
09160       else
09161          tmp->permcallwaiting = 0;
09162       /* Flag to destroy the channel must be cleared on new mkif.  Part of changes for reload to work */
09163       tmp->destroy = 0;
09164       tmp->drings = conf->chan.drings;
09165 
09166       /* 10 is a nice default. */
09167       if (tmp->drings.ringnum[0].range == 0)
09168          tmp->drings.ringnum[0].range = 10;
09169       if (tmp->drings.ringnum[1].range == 0)
09170          tmp->drings.ringnum[1].range = 10;
09171       if (tmp->drings.ringnum[2].range == 0)
09172          tmp->drings.ringnum[2].range = 10;
09173 
09174       tmp->usedistinctiveringdetection = usedistinctiveringdetection;
09175       tmp->callwaitingcallerid = conf->chan.callwaitingcallerid;
09176       tmp->threewaycalling = conf->chan.threewaycalling;
09177       tmp->adsi = conf->chan.adsi;
09178       tmp->use_smdi = conf->chan.use_smdi;
09179       tmp->permhidecallerid = conf->chan.hidecallerid;
09180       tmp->hidecalleridname = conf->chan.hidecalleridname;
09181       tmp->callreturn = conf->chan.callreturn;
09182       tmp->echocancel = conf->chan.echocancel;
09183       tmp->echotraining = conf->chan.echotraining;
09184       tmp->pulse = conf->chan.pulse;
09185       if (tmp->echocancel.head.tap_length) {
09186          tmp->echocanbridged = conf->chan.echocanbridged;
09187       } else {
09188          if (conf->chan.echocanbridged)
09189             ast_log(LOG_NOTICE, "echocancelwhenbridged requires echocancel to be enabled; ignoring\n");
09190          tmp->echocanbridged = 0;
09191       }
09192       tmp->busydetect = conf->chan.busydetect;
09193       tmp->busycount = conf->chan.busycount;
09194       tmp->busycompare = conf->chan.busycompare;
09195       tmp->busytonelength = conf->chan.busytonelength;
09196       tmp->busyquietlength = conf->chan.busyquietlength;
09197       tmp->busyfuzziness = conf->chan.busyfuzziness;
09198       tmp->silencethreshold = conf->chan.silencethreshold;
09199       tmp->callprogress = conf->chan.callprogress;
09200       tmp->cancallforward = conf->chan.cancallforward;
09201       tmp->dtmfrelax = conf->chan.dtmfrelax;
09202       tmp->callwaiting = tmp->permcallwaiting;
09203       tmp->hidecallerid = tmp->permhidecallerid;
09204       tmp->channel = channel;
09205       tmp->stripmsd = conf->chan.stripmsd;
09206       tmp->use_callerid = conf->chan.use_callerid;
09207       tmp->cid_signalling = conf->chan.cid_signalling;
09208       tmp->cid_start = conf->chan.cid_start;
09209       tmp->dahditrcallerid = conf->chan.dahditrcallerid;
09210       tmp->restrictcid = conf->chan.restrictcid;
09211       tmp->use_callingpres = conf->chan.use_callingpres;
09212       tmp->priexclusive = conf->chan.priexclusive;
09213       if (tmp->usedistinctiveringdetection) {
09214          if (!tmp->use_callerid) {
09215             ast_log(LOG_NOTICE, "Distinctive Ring detect requires 'usecallerid' be on\n");
09216             tmp->use_callerid = 1;
09217          }
09218       }
09219 
09220       if (tmp->cid_signalling == CID_SIG_SMDI) {
09221          if (!tmp->use_smdi) {
09222             ast_log(LOG_WARNING, "SMDI callerid requires SMDI to be enabled, enabling...\n");
09223             tmp->use_smdi = 1;
09224          }
09225       }
09226       if (tmp->use_smdi) {
09227          tmp->smdi_iface = ast_smdi_interface_find(conf->smdi_port);
09228          if (!(tmp->smdi_iface)) {
09229             ast_log(LOG_ERROR, "Invalid SMDI port specfied, disabling SMDI support\n");
09230             tmp->use_smdi = 0;
09231          }
09232       }
09233 
09234       ast_copy_string(tmp->accountcode, conf->chan.accountcode, sizeof(tmp->accountcode));
09235       tmp->amaflags = conf->chan.amaflags;
09236       if (!here) {
09237          tmp->confno = -1;
09238          tmp->propconfno = -1;
09239       }
09240       tmp->canpark = conf->chan.canpark;
09241       tmp->transfer = conf->chan.transfer;
09242       ast_copy_string(tmp->defcontext,conf->chan.context,sizeof(tmp->defcontext));
09243       ast_copy_string(tmp->language, conf->chan.language, sizeof(tmp->language));
09244       ast_copy_string(tmp->mohinterpret, conf->chan.mohinterpret, sizeof(tmp->mohinterpret));
09245       ast_copy_string(tmp->mohsuggest, conf->chan.mohsuggest, sizeof(tmp->mohsuggest));
09246       ast_copy_string(tmp->context, conf->chan.context, sizeof(tmp->context));
09247       ast_copy_string(tmp->parkinglot, conf->chan.parkinglot, sizeof(tmp->parkinglot));
09248       tmp->cid_ton = 0;
09249       switch (tmp->sig) {
09250       case SIG_PRI:
09251       case SIG_BRI:
09252       case SIG_BRI_PTMP:
09253       case SIG_SS7:
09254          tmp->cid_num[0] = '\0';
09255          tmp->cid_name[0] = '\0';
09256          break;
09257       default:
09258          ast_copy_string(tmp->cid_num, conf->chan.cid_num, sizeof(tmp->cid_num));
09259          ast_copy_string(tmp->cid_name, conf->chan.cid_name, sizeof(tmp->cid_name));
09260          break;
09261       }
09262       ast_copy_string(tmp->mailbox, conf->chan.mailbox, sizeof(tmp->mailbox));
09263       if (channel != CHAN_PSEUDO && !ast_strlen_zero(tmp->mailbox)) {
09264          char *mailbox, *context;
09265          mailbox = context = ast_strdupa(tmp->mailbox);
09266          strsep(&context, "@");
09267          if (ast_strlen_zero(context))
09268             context = "default";
09269          tmp->mwi_event_sub = ast_event_subscribe(AST_EVENT_MWI, mwi_event_cb, NULL,
09270             AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mailbox,
09271             AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, context,
09272             AST_EVENT_IE_NEWMSGS, AST_EVENT_IE_PLTYPE_EXISTS,
09273             AST_EVENT_IE_END);
09274       }
09275       tmp->msgstate = -1;
09276       tmp->group = conf->chan.group;
09277       tmp->callgroup = conf->chan.callgroup;
09278       tmp->pickupgroup= conf->chan.pickupgroup;
09279       if (conf->chan.vars) {
09280          struct ast_variable *v, *tmpvar;
09281                    for (v = conf->chan.vars ; v ; v = v->next) {
09282                          if ((tmpvar = ast_variable_new(v->name, v->value, v->file))) {
09283                                   tmpvar->next = tmp->vars;
09284                                    tmp->vars = tmpvar;
09285                            }
09286                   }
09287       }
09288       tmp->cid_rxgain = conf->chan.cid_rxgain;
09289       tmp->rxgain = conf->chan.rxgain;
09290       tmp->txgain = conf->chan.txgain;
09291       tmp->tonezone = conf->chan.tonezone;
09292       tmp->onhooktime = time(NULL);
09293       if (tmp->subs[SUB_REAL].dfd > -1) {
09294          set_actual_gain(tmp->subs[SUB_REAL].dfd, 0, tmp->rxgain, tmp->txgain, tmp->law);
09295          if (tmp->dsp)
09296             ast_dsp_set_digitmode(tmp->dsp, DSP_DIGITMODE_DTMF | tmp->dtmfrelax);
09297          update_conf(tmp);
09298          if (!here) {
09299             if ((chan_sig != SIG_BRI) && (chan_sig != SIG_BRI_PTMP) && (chan_sig != SIG_PRI) && (chan_sig != SIG_SS7))
09300                /* Hang it up to be sure it's good */
09301                dahdi_set_hook(tmp->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
09302          }
09303          ioctl(tmp->subs[SUB_REAL].dfd,DAHDI_SETTONEZONE,&tmp->tonezone);
09304 #ifdef HAVE_PRI
09305          /* the dchannel is down so put the channel in alarm */
09306          if (tmp->pri && !pri_is_up(tmp->pri))
09307             tmp->inalarm = 1;
09308 #endif            
09309          if ((res = get_alarms(tmp)) != DAHDI_ALARM_NONE) {
09310             tmp->inalarm = 1;
09311             handle_alarms(tmp, res);
09312          }
09313       }
09314 
09315       tmp->polarityonanswerdelay = conf->chan.polarityonanswerdelay;
09316       tmp->answeronpolarityswitch = conf->chan.answeronpolarityswitch;
09317       tmp->hanguponpolarityswitch = conf->chan.hanguponpolarityswitch;
09318       tmp->sendcalleridafter = conf->chan.sendcalleridafter;
09319       if (!here) {
09320          tmp->locallyblocked = tmp->remotelyblocked = 0;
09321          if ((chan_sig == SIG_PRI) || (chan_sig == SIG_BRI) || (chan_sig == SIG_BRI_PTMP) || (chan_sig == SIG_SS7))
09322             tmp->inservice = 0;
09323          else /* We default to in service on protocols that don't have a reset */
09324             tmp->inservice = 1;
09325       }
09326    }
09327    if (tmp && !here) {
09328       /* nothing on the iflist */
09329       if (!*wlist) {
09330          *wlist = tmp;
09331          tmp->prev = NULL;
09332          tmp->next = NULL;
09333          *wend = tmp;
09334       } else {
09335          /* at least one member on the iflist */
09336          struct dahdi_pvt *working = *wlist;
09337 
09338          /* check if we maybe have to put it on the begining */
09339          if (working->channel > tmp->channel) {
09340             tmp->next = *wlist;
09341             tmp->prev = NULL;
09342             (*wlist)->prev = tmp;
09343             *wlist = tmp;
09344          } else {
09345          /* go through all the members and put the member in the right place */
09346             while (working) {
09347                /* in the middle */
09348                if (working->next) {
09349                   if (working->channel < tmp->channel && working->next->channel > tmp->channel) {
09350                      tmp->next = working->next;
09351                      tmp->prev = working;
09352                      working->next->prev = tmp;
09353                      working->next = tmp;
09354                      break;
09355                   }
09356                } else {
09357                /* the last */
09358                   if (working->channel < tmp->channel) {
09359                      working->next = tmp;
09360                      tmp->next = NULL;
09361                      tmp->prev = working;
09362                      *wend = tmp;
09363                      break;
09364                   }
09365                }
09366                working = working->next;
09367             }
09368          }
09369       }
09370    }
09371    return tmp;
09372 }
09373 
09374 static inline int available(struct dahdi_pvt *p, int channelmatch, ast_group_t groupmatch, int *busy, int *channelmatched, int *groupmatched)
09375 {
09376    int res;
09377    struct dahdi_params par;
09378 
09379    /* First, check group matching */
09380    if (groupmatch) {
09381       if ((p->group & groupmatch) != groupmatch)
09382          return 0;
09383       *groupmatched = 1;
09384    }
09385    /* Check to see if we have a channel match */
09386    if (channelmatch != -1) {
09387       if (p->channel != channelmatch)
09388          return 0;
09389       *channelmatched = 1;
09390    }
09391    /* We're at least busy at this point */
09392    if (busy) {
09393       if ((p->sig == SIG_FXOKS) || (p->sig == SIG_FXOLS) || (p->sig == SIG_FXOGS))
09394          *busy = 1;
09395    }
09396    /* If do not disturb, definitely not */
09397    if (p->dnd)
09398       return 0;
09399    /* If guard time, definitely not */
09400    if (p->guardtime && (time(NULL) < p->guardtime)) 
09401       return 0;
09402 
09403    if (p->locallyblocked || p->remotelyblocked)
09404       return 0;
09405       
09406    /* If no owner definitely available */
09407    if (!p->owner) {
09408 #ifdef HAVE_PRI
09409       /* Trust PRI */
09410       if (p->pri) {
09411          if (p->resetting || p->call)
09412             return 0;
09413          else
09414             return 1;
09415       }
09416 #endif
09417 #ifdef HAVE_SS7
09418       /* Trust SS7 */
09419       if (p->ss7) {
09420          if (p->ss7call)
09421             return 0;
09422          else
09423             return 1;
09424       }
09425 #endif
09426       if (!(p->radio || (p->oprmode < 0)))
09427       {
09428          if (!p->sig || (p->sig == SIG_FXSLS))
09429             return 1;
09430          /* Check hook state */
09431          if (p->subs[SUB_REAL].dfd > -1) {
09432             memset(&par, 0, sizeof(par));
09433             res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par);
09434          } else {
09435             /* Assume not off hook on CVRS */
09436             res = 0;
09437             par.rxisoffhook = 0;
09438          }
09439          if (res) {
09440             ast_log(LOG_WARNING, "Unable to check hook state on channel %d: %s\n", p->channel, strerror(errno));
09441          } else if ((p->sig == SIG_FXSKS) || (p->sig == SIG_FXSGS)) {
09442             /* When "onhook" that means no battery on the line, and thus
09443               it is out of service..., if it's on a TDM card... If it's a channel
09444               bank, there is no telling... */
09445             if (par.rxbits > -1)
09446                return 1;
09447             if (par.rxisoffhook)
09448                return 1;
09449             else
09450                return 0;
09451          } else if (par.rxisoffhook) {
09452             ast_debug(1, "Channel %d off hook, can't use\n", p->channel);
09453             /* Not available when the other end is off hook */
09454 #ifdef DAHDI_CHECK_HOOKSTATE
09455             return 0;
09456 #else
09457             return 1;
09458 #endif
09459          }
09460       }
09461       return 1;
09462    }
09463 
09464    /* If it's not an FXO, forget about call wait */
09465    if ((p->sig != SIG_FXOKS) && (p->sig != SIG_FXOLS) && (p->sig != SIG_FXOGS)) 
09466       return 0;
09467 
09468    if (!p->callwaiting) {
09469       /* If they don't have call waiting enabled, then for sure they're unavailable at this point */
09470       return 0;
09471    }
09472 
09473    if (p->subs[SUB_CALLWAIT].dfd > -1) {
09474       /* If there is already a call waiting call, then we can't take a second one */
09475       return 0;
09476    }
09477    
09478    if ((p->owner->_state != AST_STATE_UP) &&
09479        ((p->owner->_state != AST_STATE_RINGING) || p->outgoing)) {
09480       /* If the current call is not up, then don't allow the call */
09481       return 0;
09482    }
09483    if ((p->subs[SUB_THREEWAY].owner) && (!p->subs[SUB_THREEWAY].inthreeway)) {
09484       /* Can't take a call wait when the three way calling hasn't been merged yet. */
09485       return 0;
09486    }
09487    /* We're cool */
09488    return 1;
09489 }
09490 
09491 static struct dahdi_pvt *chandup(struct dahdi_pvt *src)
09492 {
09493    struct dahdi_pvt *p;
09494    struct dahdi_bufferinfo bi;
09495    int res;
09496    
09497    if ((p = ast_malloc(sizeof(*p)))) {
09498       memcpy(p, src, sizeof(struct dahdi_pvt));
09499       ast_mutex_init(&p->lock);
09500       p->subs[SUB_REAL].dfd = dahdi_open("/dev/dahdi/pseudo");
09501       /* Allocate a dahdi structure */
09502       if (p->subs[SUB_REAL].dfd < 0) {
09503          ast_log(LOG_ERROR, "Unable to dup channel: %s\n",  strerror(errno));
09504          destroy_dahdi_pvt(&p);
09505          return NULL;
09506       }
09507       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_BUFINFO, &bi);
09508       if (!res) {
09509          bi.txbufpolicy = src->buf_policy;
09510          bi.rxbufpolicy = src->buf_policy;
09511          bi.numbufs = src->buf_no;
09512          res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi);
09513          if (res < 0) {
09514             ast_log(LOG_WARNING, "Unable to set buffer policy on dup channel: %s\n", strerror(errno));
09515          }
09516       } else
09517          ast_log(LOG_WARNING, "Unable to check buffer policy on dup channel: %s\n", strerror(errno));
09518    }
09519    p->destroy = 1;
09520    p->next = iflist;
09521    p->prev = NULL;
09522    iflist = p;
09523    if (iflist->next)
09524       iflist->next->prev = p;
09525    return p;
09526 }
09527    
09528 
09529 #ifdef HAVE_PRI
09530 static int pri_find_empty_chan(struct dahdi_pri *pri, int backwards)
09531 {
09532    int x;
09533    if (backwards)
09534       x = pri->numchans;
09535    else
09536       x = 0;
09537    for (;;) {
09538       if (backwards && (x < 0))
09539          break;
09540       if (!backwards && (x >= pri->numchans))
09541          break;
09542       if (pri->pvts[x] && !pri->pvts[x]->inalarm && !pri->pvts[x]->owner) {
09543          ast_debug(1, "Found empty available channel %d/%d\n", 
09544             pri->pvts[x]->logicalspan, pri->pvts[x]->prioffset);
09545          return x;
09546       }
09547       if (backwards)
09548          x--;
09549       else
09550          x++;
09551    }
09552    return -1;
09553 }
09554 #endif
09555 
09556 static struct ast_channel *dahdi_request(const char *type, int format, void *data, int *cause)
09557 {
09558    ast_group_t groupmatch = 0;
09559    int channelmatch = -1;
09560    int roundrobin = 0;
09561    int callwait = 0;
09562    int busy = 0;
09563    struct dahdi_pvt *p;
09564    struct ast_channel *tmp = NULL;
09565    char *dest=NULL;
09566    int x;
09567    char *s;
09568    char opt=0;
09569    int res=0, y=0;
09570    int backwards = 0;
09571 #ifdef HAVE_PRI
09572    int crv;
09573    int bearer = -1;
09574    int trunkgroup;
09575    struct dahdi_pri *pri=NULL;
09576 #endif   
09577    struct dahdi_pvt *exitpvt, *start, *end;
09578    ast_mutex_t *lock;
09579    int channelmatched = 0;
09580    int groupmatched = 0;
09581    
09582    /*
09583     * data is ---v
09584     * Dial(DAHDI/pseudo[/extension])
09585     * Dial(DAHDI/<channel#>[c|r<cadance#>|d][/extension])
09586     * Dial(DAHDI/<trunk_group#>:<crv#>[c|r<cadance#>|d][/extension])
09587     * Dial(DAHDI/(g|G|r|R)<group#(0-63)>[c|r<cadance#>|d][/extension])
09588     *
09589     * g - channel group allocation search forward
09590     * G - channel group allocation search backward
09591     * r - channel group allocation round robin search forward
09592     * R - channel group allocation round robin search backward
09593     *
09594     * c - Wait for DTMF digit to confirm answer
09595     * r<cadance#> - Set distintive ring cadance number
09596     * d - Force bearer capability for ISDN/SS7 call to digital.
09597     */
09598 
09599    /* Assume we're locking the iflock */
09600    lock = &iflock;
09601    start = iflist;
09602    end = ifend;
09603    if (data) {
09604       dest = ast_strdupa((char *)data);
09605    } else {
09606       ast_log(LOG_WARNING, "Channel requested with no data\n");
09607       return NULL;
09608    }
09609    if (toupper(dest[0]) == 'G' || toupper(dest[0])=='R') {
09610       /* Retrieve the group number */
09611       char *stringp;
09612 
09613       stringp = dest + 1;
09614       s = strsep(&stringp, "/");
09615       if ((res = sscanf(s, "%30d%1c%30d", &x, &opt, &y)) < 1) {
09616          ast_log(LOG_WARNING, "Unable to determine group for data %s\n", (char *)data);
09617          return NULL;
09618       }
09619       groupmatch = ((ast_group_t) 1 << x);
09620       if (toupper(dest[0]) == 'G') {
09621          if (dest[0] == 'G') {
09622             backwards = 1;
09623             p = ifend;
09624          } else
09625             p = iflist;
09626       } else {
09627          if (dest[0] == 'R') {
09628             backwards = 1;
09629             p = round_robin[x]?round_robin[x]->prev:ifend;
09630             if (!p)
09631                p = ifend;
09632          } else {
09633             p = round_robin[x]?round_robin[x]->next:iflist;
09634             if (!p)
09635                p = iflist;
09636          }
09637          roundrobin = 1;
09638       }
09639    } else {
09640       char *stringp;
09641 
09642       stringp = dest;
09643       s = strsep(&stringp, "/");
09644       p = iflist;
09645       if (!strcasecmp(s, "pseudo")) {
09646          /* Special case for pseudo */
09647          x = CHAN_PSEUDO;
09648          channelmatch = x;
09649       } 
09650 #ifdef HAVE_PRI
09651       else if ((res = sscanf(s, "%30d:%30d%1c%30d", &trunkgroup, &crv, &opt, &y)) > 1) {
09652          if ((trunkgroup < 1) || (crv < 1)) {
09653             ast_log(LOG_WARNING, "Unable to determine trunk group and CRV for data %s\n", (char *)data);
09654             return NULL;
09655          }
09656          res--;
09657          for (x = 0; x < NUM_SPANS; x++) {
09658             if (pris[x].trunkgroup == trunkgroup) {
09659                pri = pris + x;
09660                lock = &pri->lock;
09661                start = pri->crvs;
09662                end = pri->crvend;
09663                break;
09664             }
09665          }
09666          if (!pri) {
09667             ast_log(LOG_WARNING, "Unable to find trunk group %d\n", trunkgroup);
09668             return NULL;
09669          }
09670          channelmatch = crv;
09671          p = pris[x].crvs;
09672       }
09673 #endif
09674       else if ((res = sscanf(s, "%30d%1c%30d", &x, &opt, &y)) < 1) {
09675          ast_log(LOG_WARNING, "Unable to determine channel for data %s\n", (char *)data);
09676          return NULL;
09677       } else {
09678          channelmatch = x;
09679       }
09680    }
09681    /* Search for an unowned channel */
09682    ast_mutex_lock(lock);
09683    exitpvt = p;
09684    while (p && !tmp) {
09685       if (roundrobin)
09686          round_robin[x] = p;
09687 #if 0
09688       ast_verbose("name = %s, %d, %d, %llu\n",p->owner ? p->owner->name : "<none>", p->channel, channelmatch, groupmatch);
09689 #endif
09690 
09691       if (p && available(p, channelmatch, groupmatch, &busy, &channelmatched, &groupmatched)) {
09692          ast_debug(1, "Using channel %d\n", p->channel);
09693          if (p->inalarm) 
09694             goto next;
09695 
09696          callwait = (p->owner != NULL);
09697 #ifdef HAVE_PRI
09698          if (pri && (p->subs[SUB_REAL].dfd < 0)) {
09699             if (p->sig != SIG_FXSKS) {
09700                /* Gotta find an actual channel to use for this
09701                   CRV if this isn't a callwait */
09702                bearer = pri_find_empty_chan(pri, 0);
09703                if (bearer < 0) {
09704                   ast_log(LOG_NOTICE, "Out of bearer channels on span %d for call to CRV %d:%d\n", pri->span, trunkgroup, crv);
09705                   p = NULL;
09706                   break;
09707                }
09708                pri_assign_bearer(p, pri, pri->pvts[bearer]);
09709             } else {
09710                if (alloc_sub(p, 0)) {
09711                   ast_log(LOG_NOTICE, "Failed to allocate place holder pseudo channel!\n");
09712                   p = NULL;
09713                   break;
09714                } else
09715                   ast_debug(1, "Allocated placeholder pseudo channel\n");
09716 
09717                p->pri = pri;
09718             }
09719          }
09720 #endif         
09721          if (p->channel == CHAN_PSEUDO) {
09722             p = chandup(p);
09723             if (!p) {
09724                break;
09725             }
09726          }
09727          if (p->owner) {
09728             if (alloc_sub(p, SUB_CALLWAIT)) {
09729                p = NULL;
09730                break;
09731             }
09732          }
09733          p->outgoing = 1;
09734          tmp = dahdi_new(p, AST_STATE_RESERVED, 0, p->owner ? SUB_CALLWAIT : SUB_REAL, 0, 0);
09735          if (!tmp) {
09736             p->outgoing = 0;
09737          }
09738 #ifdef HAVE_PRI
09739          if (p->bearer) {
09740             /* Log owner to bearer channel, too */
09741             p->bearer->owner = tmp;
09742          }
09743 #endif         
09744          /* Make special notes */
09745          if (res > 1) {
09746             if (opt == 'c') {
09747                /* Confirm answer */
09748                p->confirmanswer = 1;
09749             } else if (opt == 'r') {
09750                /* Distinctive ring */
09751                if (res < 3)
09752                   ast_log(LOG_WARNING, "Distinctive ring missing identifier in '%s'\n", (char *)data);
09753                else
09754                   p->distinctivering = y;
09755             } else if (opt == 'd') {
09756                /* If this is an ISDN call, make it digital */
09757                p->digital = 1;
09758                if (tmp)
09759                   tmp->transfercapability = AST_TRANS_CAP_DIGITAL;
09760             } else {
09761                ast_log(LOG_WARNING, "Unknown option '%c' in '%s'\n", opt, (char *)data);
09762             }
09763          }
09764          /* Note if the call is a call waiting call */
09765          if (tmp && callwait)
09766             tmp->cdrflags |= AST_CDR_CALLWAIT;
09767          break;
09768       }
09769 next:
09770       if (backwards) {
09771          p = p->prev;
09772          if (!p)
09773             p = end;
09774       } else {
09775          p = p->next;
09776          if (!p)
09777             p = start;
09778       }
09779       /* stop when you roll to the one that we started from */
09780       if (p == exitpvt)
09781          break;
09782    }
09783    ast_mutex_unlock(lock);
09784    restart_monitor();
09785    if (callwait)
09786       *cause = AST_CAUSE_BUSY;
09787    else if (!tmp) {
09788       if (channelmatched) {
09789          if (busy)
09790             *cause = AST_CAUSE_BUSY;
09791       } else if (groupmatched) {
09792          *cause = AST_CAUSE_CONGESTION;
09793       }
09794    }
09795       
09796    return tmp;
09797 }
09798 
09799 #if defined(HAVE_PRI) || defined(HAVE_SS7)
09800 static int dahdi_setlaw(int dfd, int law)
09801 {
09802    return ioctl(dfd, DAHDI_SETLAW, &law);
09803 }
09804 #endif
09805 
09806 #ifdef HAVE_SS7
09807 
09808 static int ss7_find_cic(struct dahdi_ss7 *linkset, int cic, unsigned int dpc)
09809 {
09810    int i;
09811    int winner = -1;
09812    for (i = 0; i < linkset->numchans; i++) {
09813       if (linkset->pvts[i] && (linkset->pvts[i]->dpc == dpc && linkset->pvts[i]->cic == cic)) {
09814          winner = i;
09815          break;
09816       }
09817    }
09818    return winner;
09819 }
09820 
09821 static void ss7_handle_cqm(struct dahdi_ss7 *linkset, int startcic, int endcic, unsigned int dpc)
09822 {
09823    unsigned char status[32];
09824    struct dahdi_pvt *p = NULL;
09825    int i, offset;
09826 
09827    for (i = 0; i < linkset->numchans; i++) {
09828       if (linkset->pvts[i] && (linkset->pvts[i]->dpc == dpc && ((linkset->pvts[i]->cic >= startcic) && (linkset->pvts[i]->cic <= endcic)))) {
09829          p = linkset->pvts[i];
09830          offset = p->cic - startcic;
09831          status[offset] = 0;
09832          if (p->locallyblocked)
09833             status[offset] |= (1 << 0) | (1 << 4);
09834          if (p->remotelyblocked)
09835             status[offset] |= (1 << 1) | (1 << 5);
09836          if (p->ss7call) {
09837             if (p->outgoing)
09838                status[offset] |= (1 << 3);
09839             else
09840                status[offset] |= (1 << 2);
09841          } else
09842             status[offset] |= 0x3 << 2;
09843       }
09844    }
09845 
09846    if (p)
09847       isup_cqr(linkset->ss7, startcic, endcic, dpc, status);
09848    else
09849       ast_log(LOG_WARNING, "Could not find any equipped circuits within CQM CICs\n");
09850    
09851 }
09852 
09853 static inline void ss7_block_cics(struct dahdi_ss7 *linkset, int startcic, int endcic, unsigned int dpc, unsigned char state[], int block)
09854 {
09855    int i;
09856 
09857    for (i = 0; i < linkset->numchans; i++) {
09858       if (linkset->pvts[i] && (linkset->pvts[i]->dpc == dpc && ((linkset->pvts[i]->cic >= startcic) && (linkset->pvts[i]->cic <= endcic)))) {
09859          if (state) {
09860             if (state[i])
09861                linkset->pvts[i]->remotelyblocked = block;
09862          } else
09863             linkset->pvts[i]->remotelyblocked = block;
09864       }
09865    }
09866 }
09867 
09868 static void ss7_inservice(struct dahdi_ss7 *linkset, int startcic, int endcic, unsigned int dpc)
09869 {
09870    int i;
09871 
09872    for (i = 0; i < linkset->numchans; i++) {
09873       if (linkset->pvts[i] && (linkset->pvts[i]->dpc == dpc && ((linkset->pvts[i]->cic >= startcic) && (linkset->pvts[i]->cic <= endcic))))
09874          linkset->pvts[i]->inservice = 1;
09875    }
09876 }
09877 
09878 static void ss7_reset_linkset(struct dahdi_ss7 *linkset)
09879 {
09880    int i, startcic = -1, endcic, dpc;
09881 
09882    if (linkset->numchans <= 0)
09883       return;
09884 
09885    startcic = linkset->pvts[0]->cic;
09886    /* DB: CIC's DPC fix */
09887    dpc = linkset->pvts[0]->dpc;
09888 
09889    for (i = 0; i < linkset->numchans; i++) {
09890       if (linkset->pvts[i+1] && linkset->pvts[i+1]->dpc == dpc && ((linkset->pvts[i+1]->cic - linkset->pvts[i]->cic) == 1) && (linkset->pvts[i]->cic - startcic < 31)) {
09891          continue;
09892       } else {
09893          endcic = linkset->pvts[i]->cic;
09894          ast_verbose("Resetting CICs %d to %d\n", startcic, endcic);
09895          isup_grs(linkset->ss7, startcic, endcic, dpc);
09896 
09897          /* DB: CIC's DPC fix */
09898          if (linkset->pvts[i+1]) {
09899             startcic = linkset->pvts[i+1]->cic;
09900             dpc = linkset->pvts[i+1]->dpc;
09901          }
09902       }
09903    }
09904 }
09905 
09906 static void dahdi_loopback(struct dahdi_pvt *p, int enable)
09907 {
09908    if (p->loopedback != enable) {
09909       if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_LOOPBACK, &enable)) {
09910          ast_log(LOG_WARNING, "Unable to set loopback on channel %d: %s\n", p->channel, strerror(errno));
09911          return;
09912       }
09913       p->loopedback = enable;
09914    }
09915 }
09916 
09917 /* XXX: This function is assumed to be called with the private channel lock and linkset lock held */
09918 static void ss7_start_call(struct dahdi_pvt *p, struct dahdi_ss7 *linkset)
09919 {
09920    struct ss7 *ss7 = linkset->ss7;
09921    int res;
09922    int law = 1;
09923    struct ast_channel *c;
09924    char tmp[256];
09925 
09926    if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &law) == -1)
09927       ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d: %s\n", p->channel, law, strerror(errno));
09928    
09929    if (linkset->type == SS7_ITU)
09930       law = DAHDI_LAW_ALAW;
09931    else
09932       law = DAHDI_LAW_MULAW;
09933 
09934    res = dahdi_setlaw(p->subs[SUB_REAL].dfd, law);
09935    if (res < 0) 
09936       ast_log(LOG_WARNING, "Unable to set law on channel %d\n", p->channel);
09937    
09938    if (!(linkset->flags & LINKSET_FLAG_EXPLICITACM)) {
09939       p->proceeding = 1;
09940       isup_acm(ss7, p->ss7call);
09941    }
09942 
09943    ast_mutex_unlock(&linkset->lock);
09944    c = dahdi_new(p, AST_STATE_RING, 1, SUB_REAL, law, 0);
09945 
09946    if (!c) {
09947       ast_log(LOG_WARNING, "Unable to start PBX on CIC %d\n", p->cic);
09948       /* Holding this lock is assumed entering the function */
09949       ast_mutex_lock(&linkset->lock);
09950       return;
09951    } else
09952       ast_verb(3, "Accepting call to '%s' on CIC %d\n", p->exten, p->cic);
09953 
09954    dahdi_enable_ec(p);
09955 
09956    /* We only reference these variables in the context of the ss7_linkset function
09957     * when receiving either and IAM or a COT message.  Since they are only accessed
09958     * from this context, we should be safe to unlock around them */
09959 
09960    ast_mutex_unlock(&p->lock);
09961 
09962    if (!ast_strlen_zero(p->charge_number)) {
09963       pbx_builtin_setvar_helper(c, "SS7_CHARGE_NUMBER", p->charge_number);
09964       /* Clear this after we set it */
09965       p->charge_number[0] = 0;
09966    }
09967    if (!ast_strlen_zero(p->gen_add_number)) {
09968       pbx_builtin_setvar_helper(c, "SS7_GENERIC_ADDRESS", p->gen_add_number);
09969       /* Clear this after we set it */
09970       p->gen_add_number[0] = 0;
09971    }
09972    if (!ast_strlen_zero(p->jip_number)) {
09973       pbx_builtin_setvar_helper(c, "SS7_JIP", p->jip_number);
09974       /* Clear this after we set it */
09975       p->jip_number[0] = 0;
09976    }
09977    if (!ast_strlen_zero(p->gen_dig_number)) {
09978       pbx_builtin_setvar_helper(c, "SS7_GENERIC_DIGITS", p->gen_dig_number);
09979       /* Clear this after we set it */
09980       p->gen_dig_number[0] = 0;
09981    }
09982    if (!ast_strlen_zero(p->orig_called_num)) {
09983       pbx_builtin_setvar_helper(c, "SS7_ORIG_CALLED_NUM", p->orig_called_num);
09984       /* Clear this after we set it */
09985       p->orig_called_num[0] = 0;
09986    }
09987 
09988    snprintf(tmp, sizeof(tmp), "%d", p->gen_dig_type);
09989    pbx_builtin_setvar_helper(c, "SS7_GENERIC_DIGTYPE", tmp);
09990    /* Clear this after we set it */
09991    p->gen_dig_type = 0;
09992 
09993    snprintf(tmp, sizeof(tmp), "%d", p->gen_dig_scheme);
09994    pbx_builtin_setvar_helper(c, "SS7_GENERIC_DIGSCHEME", tmp);
09995    /* Clear this after we set it */
09996    p->gen_dig_scheme = 0;
09997 
09998    if (!ast_strlen_zero(p->lspi_ident)) {
09999       pbx_builtin_setvar_helper(c, "SS7_LSPI_IDENT", p->lspi_ident);
10000       /* Clear this after we set it */
10001       p->lspi_ident[0] = 0;
10002    }
10003 
10004    snprintf(tmp, sizeof(tmp), "%d", p->call_ref_ident);
10005    pbx_builtin_setvar_helper(c, "SS7_CALLREF_IDENT", tmp);
10006    /* Clear this after we set it */
10007    p->call_ref_ident = 0;
10008 
10009    snprintf(tmp, sizeof(tmp), "%d", p->call_ref_pc);
10010    pbx_builtin_setvar_helper(c, "SS7_CALLREF_PC", tmp);
10011    /* Clear this after we set it */
10012    p->call_ref_pc = 0;
10013 
10014    snprintf(tmp, sizeof(tmp), "%d", p->calling_party_cat);
10015    pbx_builtin_setvar_helper(c, "SS7_CALLING_PARTY_CATEGORY", tmp);
10016    /* Clear this after we set it */
10017    p->calling_party_cat = 0;
10018 
10019    if (!ast_strlen_zero(p->redirecting_num)) {
10020       pbx_builtin_setvar_helper(c, "SS7_REDIRECTING_NUMBER", p->redirecting_num);
10021       /* Clear this after we set it */
10022       p->redirecting_num[0] = 0;
10023    }
10024    if (!ast_strlen_zero(p->generic_name)) {
10025       pbx_builtin_setvar_helper(c, "SS7_GENERIC_NAME", p->generic_name);
10026       /* Clear this after we set it */
10027       p->generic_name[0] = 0;
10028    }
10029 
10030    ast_mutex_lock(&p->lock);
10031    ast_mutex_lock(&linkset->lock);
10032 }
10033 
10034 static void ss7_apply_plan_to_number(char *buf, size_t size, const struct dahdi_ss7 *ss7, const char *number, const unsigned nai)
10035 {
10036    if (ast_strlen_zero(number)) { /* make sure a number exists so prefix isn't placed on an empty string */
10037       if (size) {
10038          *buf = '\0';
10039       }
10040       return;
10041    }
10042    switch (nai) {
10043    case SS7_NAI_INTERNATIONAL:
10044       snprintf(buf, size, "%s%s", ss7->internationalprefix, number);
10045       break;
10046    case SS7_NAI_NATIONAL:
10047       snprintf(buf, size, "%s%s", ss7->nationalprefix, number);
10048       break;
10049    case SS7_NAI_SUBSCRIBER:
10050       snprintf(buf, size, "%s%s", ss7->subscriberprefix, number);
10051       break;
10052    case SS7_NAI_UNKNOWN:
10053       snprintf(buf, size, "%s%s", ss7->unknownprefix, number);
10054       break;
10055    default:
10056       snprintf(buf, size, "%s", number);
10057       break;
10058    }
10059 }
10060 static int ss7_pres_scr2cid_pres(char presentation_ind, char screening_ind)
10061 {
10062     return ((presentation_ind & 0x3) << 5) | (screening_ind & 0x3);
10063 }
10064 
10065 static void *ss7_linkset(void *data)
10066 {
10067    int res, i;
10068    struct timeval *next = NULL, tv;
10069    struct dahdi_ss7 *linkset = (struct dahdi_ss7 *) data;
10070    struct ss7 *ss7 = linkset->ss7;
10071    ss7_event *e = NULL;
10072    struct dahdi_pvt *p;
10073    int chanpos;
10074    struct pollfd pollers[NUM_DCHANS];
10075    int cic;
10076    unsigned int dpc;
10077    int nextms = 0;
10078 
10079    ss7_start(ss7);
10080 
10081    while(1) {
10082       ast_mutex_lock(&linkset->lock);
10083       if ((next = ss7_schedule_next(ss7))) {
10084          tv = ast_tvnow();
10085          tv.tv_sec = next->tv_sec - tv.tv_sec;
10086          tv.tv_usec = next->tv_usec - tv.tv_usec;
10087          if (tv.tv_usec < 0) {
10088             tv.tv_usec += 1000000;
10089             tv.tv_sec -= 1;
10090          }
10091          if (tv.tv_sec < 0) {
10092             tv.tv_sec = 0;
10093             tv.tv_usec = 0;
10094          }
10095          nextms = tv.tv_sec * 1000;
10096          nextms += tv.tv_usec / 1000;
10097       }
10098       ast_mutex_unlock(&linkset->lock);
10099 
10100       for (i = 0; i < linkset->numsigchans; i++) {
10101          pollers[i].fd = linkset->fds[i];
10102          pollers[i].events = ss7_pollflags(ss7, linkset->fds[i]);
10103          pollers[i].revents = 0;
10104       }
10105 
10106       res = poll(pollers, linkset->numsigchans, nextms);
10107       if ((res < 0) && (errno != EINTR)) {
10108          ast_log(LOG_ERROR, "poll(%s)\n", strerror(errno));
10109       } else if (!res) {
10110          ast_mutex_lock(&linkset->lock);
10111          ss7_schedule_run(ss7);
10112          ast_mutex_unlock(&linkset->lock);
10113          continue;
10114       }
10115 
10116       ast_mutex_lock(&linkset->lock);
10117       for (i = 0; i < linkset->numsigchans; i++) {
10118          if (pollers[i].revents & POLLPRI) {
10119             int x;
10120             if (ioctl(pollers[i].fd, DAHDI_GETEVENT, &x)) {
10121                ast_log(LOG_ERROR, "Error in exception retrieval!\n");
10122             }
10123             switch (x) {
10124             case DAHDI_EVENT_OVERRUN:
10125                ast_debug(1, "Overrun detected!\n");
10126                break;
10127             case DAHDI_EVENT_BADFCS:
10128                ast_debug(1, "Bad FCS\n");
10129                break;
10130             case DAHDI_EVENT_ABORT:
10131                ast_debug(1, "HDLC Abort\n");
10132                break;
10133             case DAHDI_EVENT_ALARM:
10134                ast_log(LOG_ERROR, "Alarm on link!\n");
10135                linkset->linkstate[i] |= (LINKSTATE_DOWN | LINKSTATE_INALARM);
10136                linkset->linkstate[i] &= ~LINKSTATE_UP;
10137                ss7_link_alarm(ss7, pollers[i].fd);
10138                break;
10139             case DAHDI_EVENT_NOALARM:
10140                ast_log(LOG_ERROR, "Alarm cleared on link\n");
10141                linkset->linkstate[i] &= ~(LINKSTATE_INALARM | LINKSTATE_DOWN);
10142                linkset->linkstate[i] |= LINKSTATE_STARTING;
10143                ss7_link_noalarm(ss7, pollers[i].fd);
10144                break;
10145             default:
10146                ast_log(LOG_ERROR, "Got exception %d!\n", x);
10147                break;
10148             }
10149          }
10150 
10151          if (pollers[i].revents & POLLIN) {
10152             ast_mutex_lock(&linkset->lock);
10153             res = ss7_read(ss7, pollers[i].fd);
10154             ast_mutex_unlock(&linkset->lock);
10155          }
10156 
10157          if (pollers[i].revents & POLLOUT) {
10158             ast_mutex_lock(&linkset->lock);
10159             res = ss7_write(ss7, pollers[i].fd);
10160             ast_mutex_unlock(&linkset->lock);
10161             if (res < 0) {
10162                ast_debug(1, "Error in write %s\n", strerror(errno));
10163             }
10164          }
10165       }
10166 
10167       while ((e = ss7_check_event(ss7))) {
10168          switch (e->e) {
10169          case SS7_EVENT_UP:
10170             if (linkset->state != LINKSET_STATE_UP) {
10171                ast_verbose("--- SS7 Up ---\n");
10172                ss7_reset_linkset(linkset);
10173             }
10174             linkset->state = LINKSET_STATE_UP;
10175             break;
10176          case SS7_EVENT_DOWN:
10177             ast_verbose("--- SS7 Down ---\n");
10178             linkset->state = LINKSET_STATE_DOWN;
10179             for (i = 0; i < linkset->numchans; i++) {
10180                struct dahdi_pvt *p = linkset->pvts[i];
10181                if (p)
10182                   p->inalarm = 1;
10183             }
10184             break;
10185          case MTP2_LINK_UP:
10186             ast_verbose("MTP2 link up (SLC %d)\n", e->gen.data);
10187             break;
10188          case MTP2_LINK_DOWN:
10189             ast_log(LOG_WARNING, "MTP2 link down (SLC %d)\n", e->gen.data);
10190             break;
10191          case ISUP_EVENT_CPG:
10192             chanpos = ss7_find_cic(linkset, e->cpg.cic, e->cpg.opc);
10193             if (chanpos < 0) {
10194                ast_log(LOG_WARNING, "CPG on unconfigured CIC %d\n", e->cpg.cic);
10195                break;
10196             }
10197             p = linkset->pvts[chanpos];
10198             ast_mutex_lock(&p->lock);
10199             switch (e->cpg.event) {
10200             case CPG_EVENT_ALERTING:
10201                p->alerting = 1;
10202                p->subs[SUB_REAL].needringing = 1;
10203                break;
10204             case CPG_EVENT_PROGRESS:
10205             case CPG_EVENT_INBANDINFO:
10206                {
10207                   struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_PROGRESS, };
10208                   ast_debug(1, "Queuing frame PROGRESS on CIC %d\n", p->cic);
10209                   dahdi_queue_frame(p, &f, linkset);
10210                   p->progress = 1;
10211                   p->dialing = 0;
10212                   if (p->dsp && p->dsp_features) {
10213                           ast_dsp_set_features(p->dsp, p->dsp_features);
10214                           p->dsp_features = 0;
10215                   }
10216                }
10217                break;
10218             default:
10219                ast_debug(1, "Do not handle CPG with event type 0x%x\n", e->cpg.event);
10220             }
10221 
10222             ast_mutex_unlock(&p->lock);
10223             break;
10224          case ISUP_EVENT_RSC:
10225             ast_verbose("Resetting CIC %d\n", e->rsc.cic);
10226             chanpos = ss7_find_cic(linkset, e->rsc.cic, e->rsc.opc);
10227             if (chanpos < 0) {
10228                ast_log(LOG_WARNING, "RSC on unconfigured CIC %d\n", e->rsc.cic);
10229                break;
10230             }
10231             p = linkset->pvts[chanpos];
10232             ast_mutex_lock(&p->lock);
10233             p->inservice = 1;
10234             p->remotelyblocked = 0;
10235             dpc = p->dpc;
10236             isup_set_call_dpc(e->rsc.call, dpc);
10237             if (p->ss7call)
10238                p->ss7call = NULL;
10239             if (p->owner)
10240                p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
10241             ast_mutex_unlock(&p->lock);
10242             isup_rlc(ss7, e->rsc.call);
10243             break;
10244          case ISUP_EVENT_GRS:
10245             ast_debug(1, "Got Reset for CICs %d to %d: Acknowledging\n", e->grs.startcic, e->grs.endcic);
10246             chanpos = ss7_find_cic(linkset, e->grs.startcic, e->grs.opc);
10247             if (chanpos < 0) {
10248                ast_log(LOG_WARNING, "GRS on unconfigured CIC %d\n", e->grs.startcic);
10249                break;
10250             }
10251             p = linkset->pvts[chanpos];
10252             isup_gra(ss7, e->grs.startcic, e->grs.endcic, e->grs.opc);
10253             ss7_block_cics(linkset, e->grs.startcic, e->grs.endcic, e->grs.opc, NULL, 0);
10254             break;
10255          case ISUP_EVENT_CQM:
10256             ast_debug(1, "Got Circuit group query message from CICs %d to %d\n", e->cqm.startcic, e->cqm.endcic);
10257             ss7_handle_cqm(linkset, e->cqm.startcic, e->cqm.endcic, e->cqm.opc);
10258             break;
10259          case ISUP_EVENT_GRA:
10260             ast_verbose("Got reset acknowledgement from CIC %d to %d.\n", e->gra.startcic, e->gra.endcic);
10261             ss7_inservice(linkset, e->gra.startcic, e->gra.endcic, e->gra.opc);
10262             ss7_block_cics(linkset, e->gra.startcic, e->gra.endcic, e->gra.opc, e->gra.status, 1);
10263             break;
10264          case ISUP_EVENT_IAM:
10265             ast_debug(1, "Got IAM for CIC %d and called number %s, calling number %s\n", e->iam.cic, e->iam.called_party_num, e->iam.calling_party_num);
10266             chanpos = ss7_find_cic(linkset, e->iam.cic, e->iam.opc);
10267             if (chanpos < 0) {
10268                ast_log(LOG_WARNING, "IAM on unconfigured CIC %d\n", e->iam.cic);
10269                isup_rel(ss7, e->iam.call, -1);
10270                break;
10271             }
10272             p = linkset->pvts[chanpos];
10273             ast_mutex_lock(&p->lock);
10274             if (p->owner) {
10275                if (p->ss7call == e->iam.call) {
10276                   ast_mutex_unlock(&p->lock);
10277                   ast_log(LOG_WARNING, "Duplicate IAM requested on CIC %d\n", e->iam.cic);
10278                   break;
10279                } else {
10280                   ast_mutex_unlock(&p->lock);
10281                   ast_log(LOG_WARNING, "Ring requested on CIC %d already in use!\n", e->iam.cic);
10282                   break;
10283                }
10284             }
10285 
10286             dpc = p->dpc;
10287             p->ss7call = e->iam.call;
10288             isup_set_call_dpc(p->ss7call, dpc);
10289 
10290             if ((p->use_callerid) && (!ast_strlen_zero(e->iam.calling_party_num))) {
10291                ss7_apply_plan_to_number(p->cid_num, sizeof(p->cid_num), linkset, e->iam.calling_party_num, e->iam.calling_nai);
10292                p->callingpres = ss7_pres_scr2cid_pres(e->iam.presentation_ind, e->iam.screening_ind);
10293             } else
10294                p->cid_num[0] = 0;
10295 
10296             if (p->immediate) {
10297                p->exten[0] = 's';
10298                p->exten[1] = '\0';
10299             } else if (!ast_strlen_zero(e->iam.called_party_num)) {
10300                char *st;
10301                ss7_apply_plan_to_number(p->exten, sizeof(p->exten), linkset, e->iam.called_party_num, e->iam.called_nai);
10302                st = strchr(p->exten, '#');
10303                if (st)
10304                   *st = '\0';
10305                } else
10306                   p->exten[0] = '\0';
10307 
10308             p->cid_ani[0] = '\0';
10309             if ((p->use_callerid) && (!ast_strlen_zero(e->iam.generic_name)))
10310                ast_copy_string(p->cid_name, e->iam.generic_name, sizeof(p->cid_name));
10311             else
10312                p->cid_name[0] = '\0';
10313             
10314             p->cid_ani2 = e->iam.oli_ani2;
10315             p->cid_ton = 0;
10316             ast_copy_string(p->charge_number, e->iam.charge_number, sizeof(p->charge_number));
10317             ast_copy_string(p->gen_add_number, e->iam.gen_add_number, sizeof(p->gen_add_number));
10318             p->gen_add_type = e->iam.gen_add_type;
10319             p->gen_add_nai = e->iam.gen_add_nai;
10320             p->gen_add_pres_ind = e->iam.gen_add_pres_ind;
10321             p->gen_add_num_plan = e->iam.gen_add_num_plan;
10322             ast_copy_string(p->gen_dig_number, e->iam.gen_dig_number, sizeof(p->gen_dig_number));
10323             p->gen_dig_type = e->iam.gen_dig_type;
10324             p->gen_dig_scheme = e->iam.gen_dig_scheme;
10325             ast_copy_string(p->jip_number, e->iam.jip_number, sizeof(p->jip_number));
10326             ast_copy_string(p->orig_called_num, e->iam.orig_called_num, sizeof(p->orig_called_num));
10327             ast_copy_string(p->redirecting_num, e->iam.redirecting_num, sizeof(p->redirecting_num));
10328             ast_copy_string(p->generic_name, e->iam.generic_name, sizeof(p->generic_name));
10329             p->calling_party_cat = e->iam.calling_party_cat;
10330                
10331             /* Set DNID */
10332             if (!ast_strlen_zero(e->iam.called_party_num))
10333                ss7_apply_plan_to_number(p->dnid, sizeof(p->dnid), linkset, e->iam.called_party_num, e->iam.called_nai);
10334             
10335             if (ast_exists_extension(NULL, p->context, p->exten, 1, p->cid_num)) {
10336 
10337                if (e->iam.cot_check_required) {
10338                   dahdi_loopback(p, 1);
10339                } else
10340                   ss7_start_call(p, linkset);
10341             } else {
10342                ast_debug(1, "Call on CIC for unconfigured extension %s\n", p->exten);
10343                p->alreadyhungup = 1;
10344                isup_rel(ss7, e->iam.call, AST_CAUSE_UNALLOCATED);
10345             }
10346             ast_mutex_unlock(&p->lock);
10347             break;
10348          case ISUP_EVENT_COT:
10349             chanpos = ss7_find_cic(linkset, e->cot.cic, e->cot.opc);
10350             if (chanpos < 0) {
10351                ast_log(LOG_WARNING, "COT on unconfigured CIC %d\n", e->cot.cic);
10352                isup_rel(ss7, e->cot.call, -1);
10353                break;
10354             }
10355             p = linkset->pvts[chanpos];
10356 
10357             ast_mutex_lock(&p->lock);
10358 
10359             if (p->loopedback) {
10360                dahdi_loopback(p, 0);
10361                ss7_start_call(p, linkset);
10362             }
10363 
10364             ast_mutex_unlock(&p->lock);
10365 
10366             break;
10367          case ISUP_EVENT_CCR:
10368             ast_debug(1, "Got CCR request on CIC %d\n", e->ccr.cic);
10369             chanpos = ss7_find_cic(linkset, e->ccr.cic, e->ccr.opc);
10370             if (chanpos < 0) {
10371                ast_log(LOG_WARNING, "CCR on unconfigured CIC %d\n", e->ccr.cic);
10372                break;
10373             }
10374 
10375             p = linkset->pvts[chanpos];
10376 
10377             ast_mutex_lock(&p->lock);
10378             dahdi_loopback(p, 1);
10379             ast_mutex_unlock(&p->lock);
10380 
10381             isup_lpa(linkset->ss7, e->ccr.cic, p->dpc);
10382             break;
10383          case ISUP_EVENT_CVT:
10384             ast_debug(1, "Got CVT request on CIC %d\n", e->cvt.cic);
10385             chanpos = ss7_find_cic(linkset, e->cvt.cic, e->cvt.opc);
10386             if (chanpos < 0) {
10387                ast_log(LOG_WARNING, "CVT on unconfigured CIC %d\n", e->cvt.cic);
10388                break;
10389             }
10390             
10391             p = linkset->pvts[chanpos];
10392             
10393             ast_mutex_lock(&p->lock);
10394             dahdi_loopback(p, 1);
10395             ast_mutex_unlock(&p->lock);
10396             
10397             isup_cvr(linkset->ss7, e->cvt.cic, p->dpc);
10398             break;
10399          case ISUP_EVENT_REL:
10400             chanpos = ss7_find_cic(linkset, e->rel.cic, e->rel.opc);
10401             if (chanpos < 0) {
10402                ast_log(LOG_WARNING, "REL on unconfigured CIC %d\n", e->rel.cic);
10403                break;
10404             }
10405             p = linkset->pvts[chanpos];
10406             ast_mutex_lock(&p->lock);
10407             if (p->owner) {
10408                p->owner->hangupcause = e->rel.cause;
10409                p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
10410             } else if (!p->restartpending)
10411                ast_log(LOG_WARNING, "REL on channel (CIC %d) without owner!\n", p->cic);
10412 
10413             /* End the loopback if we have one */
10414             dahdi_loopback(p, 0);
10415 
10416             isup_rlc(ss7, e->rel.call);
10417             p->ss7call = NULL;
10418 
10419             ast_mutex_unlock(&p->lock);
10420             break;
10421          case ISUP_EVENT_ACM:
10422             chanpos = ss7_find_cic(linkset, e->acm.cic, e->acm.opc);
10423             if (chanpos < 0) {
10424                ast_log(LOG_WARNING, "ACM on unconfigured CIC %d\n", e->acm.cic);
10425                isup_rel(ss7, e->acm.call, -1);
10426                break;
10427             } else {
10428                struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_PROCEEDING, };
10429 
10430                p = linkset->pvts[chanpos];
10431 
10432                ast_debug(1, "Queueing frame from SS7_EVENT_ACM on CIC %d\n", p->cic);
10433                
10434                if (e->acm.call_ref_ident > 0) {
10435                   p->rlt = 1; /* Setting it but not using it here*/
10436                }
10437 
10438                ast_mutex_lock(&p->lock);
10439                dahdi_queue_frame(p, &f, linkset);
10440                p->proceeding = 1;
10441                p->dialing = 0;
10442                /* Send alerting if subscriber is free */
10443                if (e->acm.called_party_status_ind == 1) {
10444                   p->alerting = 1;
10445                   p->subs[SUB_REAL].needringing = 1;
10446                }
10447                ast_mutex_unlock(&p->lock);
10448             }
10449             break;
10450          case ISUP_EVENT_CGB:
10451             chanpos = ss7_find_cic(linkset, e->cgb.startcic, e->cgb.opc);
10452             if (chanpos < 0) {
10453                ast_log(LOG_WARNING, "CGB on unconfigured CIC %d\n", e->cgb.startcic);
10454                break;
10455             }
10456             p = linkset->pvts[chanpos];
10457             ss7_block_cics(linkset, e->cgb.startcic, e->cgb.endcic, e->cgb.opc, e->cgb.status, 1);
10458             isup_cgba(linkset->ss7, e->cgb.startcic, e->cgb.endcic, e->cgb.opc, e->cgb.status, e->cgb.type);
10459             break;
10460          case ISUP_EVENT_CGU:
10461             chanpos = ss7_find_cic(linkset, e->cgu.startcic, e->cgu.opc);
10462             if (chanpos < 0) {
10463                ast_log(LOG_WARNING, "CGU on unconfigured CIC %d\n", e->cgu.startcic);
10464                break;
10465             }
10466             p = linkset->pvts[chanpos];
10467             ss7_block_cics(linkset, e->cgu.startcic, e->cgu.endcic, e->cgu.opc, e->cgu.status, 0);
10468             isup_cgua(linkset->ss7, e->cgu.startcic, e->cgu.endcic, e->cgu.opc, e->cgu.status, e->cgu.type);
10469             break;
10470          case ISUP_EVENT_UCIC:
10471             chanpos = ss7_find_cic(linkset, e->ucic.cic, e->ucic.opc);
10472             if (chanpos < 0) {
10473                ast_log(LOG_WARNING, "UCIC on unconfigured CIC %d\n", e->ucic.cic);
10474                break;
10475             }
10476             p = linkset->pvts[chanpos];
10477             ast_debug(1, "Unequiped Circuit Id Code on CIC %d\n", e->ucic.cic);
10478             ast_mutex_lock(&p->lock);
10479             p->remotelyblocked = 1;
10480             p->inservice = 0;
10481             ast_mutex_unlock(&p->lock);         //doesn't require a SS7 acknowledgement
10482             break;
10483          case ISUP_EVENT_BLO:
10484             chanpos = ss7_find_cic(linkset, e->blo.cic, e->blo.opc);
10485             if (chanpos < 0) {
10486                ast_log(LOG_WARNING, "BLO on unconfigured CIC %d\n", e->blo.cic);
10487                break;
10488             }
10489             p = linkset->pvts[chanpos];
10490             ast_debug(1, "Blocking CIC %d\n", e->blo.cic);
10491             ast_mutex_lock(&p->lock);
10492             p->remotelyblocked = 1;
10493             ast_mutex_unlock(&p->lock);
10494             isup_bla(linkset->ss7, e->blo.cic, p->dpc);
10495             break;
10496          case ISUP_EVENT_BLA:
10497             chanpos = ss7_find_cic(linkset, e->bla.cic, e->bla.opc);
10498             if (chanpos < 0) {
10499                ast_log(LOG_WARNING, "BLA on unconfigured CIC %d\n", e->bla.cic);
10500                break;
10501             }
10502             ast_debug(1, "Blocking CIC %d\n", e->bla.cic);
10503             p = linkset->pvts[chanpos];
10504             ast_mutex_lock(&p->lock);
10505             p->locallyblocked = 1;
10506             ast_mutex_unlock(&p->lock);
10507             break;
10508          case ISUP_EVENT_UBL:
10509             chanpos = ss7_find_cic(linkset, e->ubl.cic, e->ubl.opc);
10510             if (chanpos < 0) {
10511                ast_log(LOG_WARNING, "UBL on unconfigured CIC %d\n", e->ubl.cic);
10512                break;
10513             }
10514             p = linkset->pvts[chanpos];
10515             ast_debug(1, "Unblocking CIC %d\n", e->ubl.cic);
10516             ast_mutex_lock(&p->lock);
10517             p->remotelyblocked = 0;
10518             ast_mutex_unlock(&p->lock);
10519             isup_uba(linkset->ss7, e->ubl.cic, p->dpc);
10520             break;
10521          case ISUP_EVENT_UBA:
10522             chanpos = ss7_find_cic(linkset, e->uba.cic, e->uba.opc);
10523             if (chanpos < 0) {
10524                ast_log(LOG_WARNING, "UBA on unconfigured CIC %d\n", e->uba.cic);
10525                break;
10526             }
10527             p = linkset->pvts[chanpos];
10528             ast_debug(1, "Unblocking CIC %d\n", e->uba.cic);
10529             ast_mutex_lock(&p->lock);
10530             p->locallyblocked = 0;
10531             ast_mutex_unlock(&p->lock);
10532             break;
10533          case ISUP_EVENT_CON:
10534          case ISUP_EVENT_ANM:
10535             if (e->e == ISUP_EVENT_CON)
10536                cic = e->con.cic;
10537             else
10538                cic = e->anm.cic;
10539 
10540             chanpos = ss7_find_cic(linkset, cic, (e->e == ISUP_EVENT_ANM) ? e->anm.opc : e->con.opc);
10541             if (chanpos < 0) {
10542                ast_log(LOG_WARNING, "ANM/CON on unconfigured CIC %d\n", cic);
10543                isup_rel(ss7, (e->e == ISUP_EVENT_ANM) ? e->anm.call : e->con.call, -1);
10544                break;
10545             } else {
10546                p = linkset->pvts[chanpos];
10547                ast_mutex_lock(&p->lock);
10548                p->subs[SUB_REAL].needanswer = 1;
10549                if (p->dsp && p->dsp_features) {
10550                        ast_dsp_set_features(p->dsp, p->dsp_features);
10551                        p->dsp_features = 0;
10552                }
10553                dahdi_enable_ec(p);
10554                ast_mutex_unlock(&p->lock);
10555             }
10556             break;
10557          case ISUP_EVENT_RLC:
10558             chanpos = ss7_find_cic(linkset, e->rlc.cic, e->rlc.opc);
10559             if (chanpos < 0) {
10560                ast_log(LOG_WARNING, "RLC on unconfigured CIC %d\n", e->rlc.cic);
10561                break;
10562             } else {
10563                p = linkset->pvts[chanpos];
10564                ast_mutex_lock(&p->lock);
10565                if (p->alreadyhungup)
10566                   p->ss7call = NULL;
10567                else
10568                   ast_log(LOG_NOTICE, "Received RLC out and we haven't sent REL.  Ignoring.\n");
10569                ast_mutex_unlock(&p->lock);
10570                }
10571                break;
10572          case ISUP_EVENT_FAA:
10573             chanpos = ss7_find_cic(linkset, e->faa.cic, e->faa.opc);
10574             if (chanpos < 0) {
10575                ast_log(LOG_WARNING, "FAA on unconfigured CIC %d\n", e->faa.cic);
10576                break;
10577             } else {
10578                p = linkset->pvts[chanpos];
10579                ast_debug(1, "FAA received on CIC %d\n", e->faa.cic);
10580                ast_mutex_lock(&p->lock);
10581                if (p->alreadyhungup){
10582                   p->ss7call = NULL;
10583                   ast_log(LOG_NOTICE, "Received FAA and we haven't sent FAR.  Ignoring.\n");
10584                }
10585                ast_mutex_unlock(&p->lock);
10586             }
10587             break;
10588          default:
10589             ast_debug(1, "Unknown event %s\n", ss7_event2str(e->e));
10590             break;
10591          }
10592       }
10593       ast_mutex_unlock(&linkset->lock);
10594    }
10595 
10596    return 0;
10597 }
10598 
10599 static void dahdi_ss7_message(struct ss7 *ss7, char *s)
10600 {
10601 #if 0
10602    int i;
10603 
10604    for (i = 0; i < NUM_SPANS; i++)
10605       if (linksets[i].ss7 == ss7)
10606          break;
10607 
10608    ast_verbose("[%d] %s", i+1, s);
10609 #else
10610    ast_verbose("%s", s);
10611 #endif
10612 }
10613 
10614 static void dahdi_ss7_error(struct ss7 *ss7, char *s)
10615 {
10616 #if 0
10617    int i;
10618 
10619    for (i = 0; i < NUM_SPANS; i++)
10620       if (linksets[i].ss7 == ss7)
10621          break;
10622 
10623 #else
10624    ast_log(LOG_ERROR, "%s", s);
10625 #endif
10626 }
10627 
10628 #endif /* HAVE_SS7 */
10629 
10630 #ifdef HAVE_PRI
10631 static struct dahdi_pvt *pri_find_crv(struct dahdi_pri *pri, int crv)
10632 {
10633    struct dahdi_pvt *p;
10634    p = pri->crvs;
10635    while (p) {
10636       if (p->channel == crv)
10637          return p;
10638       p = p->next;
10639    }
10640    return NULL;
10641 }
10642 
10643 
10644 static int pri_find_principle(struct dahdi_pri *pri, int channel)
10645 {
10646    int x;
10647    int span = PRI_SPAN(channel);
10648    int spanfd;
10649    struct dahdi_params param;
10650    int principle = -1;
10651    int explicit = PRI_EXPLICIT(channel);
10652    channel = PRI_CHANNEL(channel);
10653 
10654    if (!explicit) {
10655       spanfd = pri_active_dchan_fd(pri);
10656       memset(&param, 0, sizeof(param));
10657       if (ioctl(spanfd, DAHDI_GET_PARAMS, &param))
10658          return -1;
10659       span = pris[param.spanno - 1].prilogicalspan;
10660    }
10661 
10662    for (x = 0; x < pri->numchans; x++) {
10663       if (pri->pvts[x] && (pri->pvts[x]->prioffset == channel) && (pri->pvts[x]->logicalspan == span)) {
10664          principle = x;
10665          break;
10666       }
10667    }
10668    
10669    return principle;
10670 }
10671 
10672 static int pri_fixup_principle(struct dahdi_pri *pri, int principle, q931_call *c)
10673 {
10674    int x;
10675    struct dahdi_pvt *crv;
10676    if (!c) {
10677       if (principle < 0)
10678          return -1;
10679       return principle;
10680    }
10681    if ((principle > -1) && 
10682       (principle < pri->numchans) && 
10683       (pri->pvts[principle]) && 
10684       (pri->pvts[principle]->call == c))
10685       return principle;
10686    /* First, check for other bearers */
10687    for (x = 0; x < pri->numchans; x++) {
10688       if (!pri->pvts[x])
10689          continue;
10690       if (pri->pvts[x]->call == c) {
10691          /* Found our call */
10692          if (principle != x) {
10693             struct dahdi_pvt *new = pri->pvts[principle], *old = pri->pvts[x];
10694 
10695             ast_verb(3, "Moving call from channel %d to channel %d\n",
10696                 old->channel, new->channel);
10697             if (new->owner) {
10698                ast_log(LOG_WARNING, "Can't fix up channel from %d to %d because %d is already in use\n",
10699                   old->channel, new->channel, new->channel);
10700                return -1;
10701             }
10702             /* Fix it all up now */
10703             new->owner = old->owner;
10704             old->owner = NULL;
10705             if (new->owner) {
10706                ast_string_field_build(new->owner, name, 
10707                             "DAHDI/%d:%d-%d", pri->trunkgroup,
10708                             new->channel, 1);
10709                new->owner->tech_pvt = new;
10710                ast_channel_set_fd(new->owner, 0, new->subs[SUB_REAL].dfd);
10711                new->subs[SUB_REAL].owner = old->subs[SUB_REAL].owner;
10712                old->subs[SUB_REAL].owner = NULL;
10713             } else
10714                ast_log(LOG_WARNING, "Whoa, there's no  owner, and we're having to fix up channel %d to channel %d\n", old->channel, new->channel);
10715             new->call = old->call;
10716             old->call = NULL;
10717 
10718             /* Copy any DSP that may be present */
10719             new->dsp = old->dsp;
10720             new->dsp_features = old->dsp_features;
10721             old->dsp = NULL;
10722             old->dsp_features = 0;
10723          }
10724          return principle;
10725       }
10726    }
10727    /* Now check for a CRV with no bearer */
10728    crv = pri->crvs;
10729    while (crv) {
10730       if (crv->call == c) {
10731          /* This is our match...  Perform some basic checks */
10732          if (crv->bearer)
10733             ast_log(LOG_WARNING, "Trying to fix up call which already has a bearer which isn't the one we think it is\n");
10734          else if (pri->pvts[principle]->owner) 
10735             ast_log(LOG_WARNING, "Tring to fix up a call to a bearer which already has an owner!\n");
10736          else {
10737             /* Looks good.  Drop the pseudo channel now, clear up the assignment, and
10738                wakeup the potential sleeper */
10739             dahdi_close_sub(crv, SUB_REAL);
10740             pri->pvts[principle]->call = crv->call;
10741             pri_assign_bearer(crv, pri, pri->pvts[principle]);
10742             ast_debug(1, "Assigning bearer %d/%d to CRV %d:%d\n",
10743                pri->pvts[principle]->logicalspan, pri->pvts[principle]->prioffset,
10744                pri->trunkgroup, crv->channel);
10745             wakeup_sub(crv, SUB_REAL, pri);
10746          }
10747          return principle;
10748       }
10749       crv = crv->next;
10750    }
10751    ast_log(LOG_WARNING, "Call specified, but not found?\n");
10752    return -1;
10753 }
10754 
10755 static void *do_idle_thread(void *vchan)
10756 {
10757    struct ast_channel *chan = vchan;
10758    struct dahdi_pvt *pvt = chan->tech_pvt;
10759    struct ast_frame *f;
10760    char ex[80];
10761    /* Wait up to 30 seconds for an answer */
10762    int newms, ms = 30000;
10763    ast_verb(3, "Initiating idle call on channel %s\n", chan->name);
10764    snprintf(ex, sizeof(ex), "%d/%s", pvt->channel, pvt->pri->idledial);
10765    if (ast_call(chan, ex, 0)) {
10766       ast_log(LOG_WARNING, "Idle dial failed on '%s' to '%s'\n", chan->name, ex);
10767       ast_hangup(chan);
10768       return NULL;
10769    }
10770    while ((newms = ast_waitfor(chan, ms)) > 0) {
10771       f = ast_read(chan);
10772       if (!f) {
10773          /* Got hangup */
10774          break;
10775       }
10776       if (f->frametype == AST_FRAME_CONTROL) {
10777          switch (f->subclass) {
10778          case AST_CONTROL_ANSWER:
10779             /* Launch the PBX */
10780             ast_copy_string(chan->exten, pvt->pri->idleext, sizeof(chan->exten));
10781             ast_copy_string(chan->context, pvt->pri->idlecontext, sizeof(chan->context));
10782             chan->priority = 1;
10783             ast_verb(4, "Idle channel '%s' answered, sending to %s@%s\n", chan->name, chan->exten, chan->context);
10784             ast_pbx_run(chan);
10785             /* It's already hungup, return immediately */
10786             return NULL;
10787          case AST_CONTROL_BUSY:
10788             ast_verb(4, "Idle channel '%s' busy, waiting...\n", chan->name);
10789             break;
10790          case AST_CONTROL_CONGESTION:
10791             ast_verb(4, "Idle channel '%s' congested, waiting...\n", chan->name);
10792             break;
10793          };
10794       }
10795       ast_frfree(f);
10796       ms = newms;
10797    }
10798    /* Hangup the channel since nothing happend */
10799    ast_hangup(chan);
10800    return NULL;
10801 }
10802 
10803 #ifndef PRI_RESTART
10804 #error "Upgrade your libpri"
10805 #endif
10806 static void dahdi_pri_message(struct pri *pri, char *s)
10807 {
10808    int x, y;
10809    int dchan = -1, span = -1;
10810    int dchancount = 0;
10811 
10812    if (pri) {
10813       for (x = 0; x < NUM_SPANS; x++) {
10814          for (y = 0; y < NUM_DCHANS; y++) {
10815             if (pris[x].dchans[y])
10816                dchancount++;
10817 
10818             if (pris[x].dchans[y] == pri)
10819                dchan = y;
10820          }
10821          if (dchan >= 0) {
10822             span = x;
10823             break;
10824          }
10825          dchancount = 0;
10826       }
10827       if (dchancount > 1 && (span > -1))
10828          ast_verbose("[Span %d D-Channel %d]%s", span, dchan, s);
10829       else
10830          ast_verbose("%s", s);
10831    } else
10832       ast_verbose("%s", s);
10833 
10834    ast_mutex_lock(&pridebugfdlock);
10835 
10836    if (pridebugfd >= 0) {
10837       if (write(pridebugfd, s, strlen(s)) < 0) {
10838          ast_log(LOG_WARNING, "write() failed: %s\n", strerror(errno));
10839       }
10840    }
10841 
10842    ast_mutex_unlock(&pridebugfdlock);
10843 }
10844 
10845 static void dahdi_pri_error(struct pri *pri, char *s)
10846 {
10847    int x, y;
10848    int dchan = -1, span = -1;
10849    int dchancount = 0;
10850 
10851    if (pri) {
10852       for (x = 0; x < NUM_SPANS; x++) {
10853          for (y = 0; y < NUM_DCHANS; y++) {
10854             if (pris[x].dchans[y])
10855                dchancount++;
10856 
10857             if (pris[x].dchans[y] == pri)
10858                dchan = y;
10859          }
10860          if (dchan >= 0) {
10861             span = x;
10862             break;
10863          }
10864          dchancount = 0;
10865       }
10866       if ((dchancount > 1) && (span > -1))
10867          ast_log(LOG_ERROR, "[Span %d D-Channel %d] PRI: %s", span, dchan, s);
10868       else
10869          ast_log(LOG_ERROR, "%s", s);
10870    } else
10871       ast_log(LOG_ERROR, "%s", s);
10872 
10873    ast_mutex_lock(&pridebugfdlock);
10874 
10875    if (pridebugfd >= 0) {
10876       if (write(pridebugfd, s, strlen(s)) < 0) {
10877          ast_log(LOG_WARNING, "write() failed: %s\n", strerror(errno));
10878       }
10879    }
10880 
10881    ast_mutex_unlock(&pridebugfdlock);
10882 }
10883 
10884 static int pri_check_restart(struct dahdi_pri *pri)
10885 {
10886    do {
10887       pri->resetpos++;
10888    } while ((pri->resetpos < pri->numchans) &&
10889        (!pri->pvts[pri->resetpos] ||
10890         pri->pvts[pri->resetpos]->call ||
10891         pri->pvts[pri->resetpos]->resetting));
10892    if (pri->resetpos < pri->numchans) {
10893       /* Mark the channel as resetting and restart it */
10894       pri->pvts[pri->resetpos]->resetting = 1;
10895       pri_reset(pri->pri, PVT_TO_CHANNEL(pri->pvts[pri->resetpos]));
10896    } else {
10897       pri->resetting = 0;
10898       time(&pri->lastreset);
10899    }
10900    return 0;
10901 }
10902 
10903 static int pri_hangup_all(struct dahdi_pvt *p, struct dahdi_pri *pri)
10904 {
10905    int x;
10906    int redo;
10907    ast_mutex_unlock(&pri->lock);
10908    ast_mutex_lock(&p->lock);
10909    do {
10910       redo = 0;
10911       for (x = 0; x < 3; x++) {
10912          while (p->subs[x].owner && ast_channel_trylock(p->subs[x].owner)) {
10913             redo++;
10914             DEADLOCK_AVOIDANCE(&p->lock);
10915          }
10916          if (p->subs[x].owner) {
10917             ast_queue_hangup_with_cause(p->subs[x].owner, AST_CAUSE_PRE_EMPTED);
10918             ast_channel_unlock(p->subs[x].owner);
10919          }
10920       }
10921    } while (redo);
10922    ast_mutex_unlock(&p->lock);
10923    ast_mutex_lock(&pri->lock);
10924    return 0;
10925 }
10926 
10927 static char * redirectingreason2str(int redirectingreason)
10928 {
10929    switch (redirectingreason) {
10930    case 0:
10931       return "UNKNOWN";
10932    case 1:
10933       return "BUSY";
10934    case 2:
10935       return "NO_REPLY";
10936    case 0xF:
10937       return "UNCONDITIONAL";
10938    default:
10939       return "NOREDIRECT";
10940    }
10941 }
10942 
10943 static void apply_plan_to_number(char *buf, size_t size, const struct dahdi_pri *pri, const char *number, const int plan)
10944 {
10945    if (pri->dialplan == -2) { /* autodetect the TON but leave the number untouched */
10946       snprintf(buf, size, "%s", number);
10947       return;
10948    }
10949    if (ast_strlen_zero(number)) { /* make sure a number exists so prefix isn't placed on an empty string */
10950       if (size) {
10951          *buf = '\0';
10952       }
10953       return;
10954    }
10955    switch (plan) {
10956    case PRI_INTERNATIONAL_ISDN:     /* Q.931 dialplan == 0x11 international dialplan => prepend international prefix digits */
10957       snprintf(buf, size, "%s%s", pri->internationalprefix, number);
10958       break;
10959    case PRI_NATIONAL_ISDN:       /* Q.931 dialplan == 0x21 national dialplan => prepend national prefix digits */
10960       snprintf(buf, size, "%s%s", pri->nationalprefix, number);
10961       break;
10962    case PRI_LOCAL_ISDN:       /* Q.931 dialplan == 0x41 local dialplan => prepend local prefix digits */
10963       snprintf(buf, size, "%s%s", pri->localprefix, number);
10964       break;
10965    case PRI_PRIVATE:       /* Q.931 dialplan == 0x49 private dialplan => prepend private prefix digits */
10966       snprintf(buf, size, "%s%s", pri->privateprefix, number);
10967       break;
10968    case PRI_UNKNOWN:       /* Q.931 dialplan == 0x00 unknown dialplan => prepend unknown prefix digits */
10969       snprintf(buf, size, "%s%s", pri->unknownprefix, number);
10970       break;
10971    default:          /* other Q.931 dialplan => don't twiddle with callingnum */
10972       snprintf(buf, size, "%s", number);
10973       break;
10974    }
10975 }
10976 
10977 
10978 static void *pri_dchannel(void *vpri)
10979 {
10980    struct dahdi_pri *pri = vpri;
10981    pri_event *e;
10982    struct pollfd fds[NUM_DCHANS];
10983    int res;
10984    int chanpos = 0;
10985    int x;
10986    int haveidles;
10987    int activeidles;
10988    int nextidle = -1;
10989    struct ast_channel *c;
10990    struct timeval tv, lowest, *next;
10991    struct timeval lastidle = ast_tvnow();
10992    int doidling=0;
10993    char *cc;
10994    char idlen[80];
10995    struct ast_channel *idle;
10996    pthread_t p;
10997    time_t t;
10998    int i, which=-1;
10999    int numdchans;
11000    int cause=0;
11001    struct dahdi_pvt *crv;
11002    pthread_t threadid;
11003    char ani2str[6];
11004    char plancallingnum[256];
11005    char plancallingani[256];
11006    char calledtonstr[10];
11007    
11008    pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
11009 
11010    gettimeofday(&lastidle, NULL);
11011    if (!ast_strlen_zero(pri->idledial) && !ast_strlen_zero(pri->idleext)) {
11012       /* Need to do idle dialing, check to be sure though */
11013       cc = strchr(pri->idleext, '@');
11014       if (cc) {
11015          *cc = '\0';
11016          cc++;
11017          ast_copy_string(pri->idlecontext, cc, sizeof(pri->idlecontext));
11018 #if 0
11019          /* Extensions may not be loaded yet */
11020          if (!ast_exists_extension(NULL, pri->idlecontext, pri->idleext, 1, NULL))
11021             ast_log(LOG_WARNING, "Extension '%s @ %s' does not exist\n", pri->idleext, pri->idlecontext);
11022          else
11023 #endif
11024             doidling = 1;
11025       } else
11026          ast_log(LOG_WARNING, "Idle dial string '%s' lacks '@context'\n", pri->idleext);
11027    }
11028    for (;;) {
11029       for (i = 0; i < NUM_DCHANS; i++) {
11030          if (!pri->dchannels[i])
11031             break;
11032          fds[i].fd = pri->fds[i];
11033          fds[i].events = POLLIN | POLLPRI;
11034          fds[i].revents = 0;
11035       }
11036       numdchans = i;
11037       time(&t);
11038       ast_mutex_lock(&pri->lock);
11039       if (pri->switchtype != PRI_SWITCH_GR303_TMC && (pri->resetinterval > 0)) {
11040          if (pri->resetting && pri_is_up(pri)) {
11041             if (pri->resetpos < 0)
11042                pri_check_restart(pri);
11043          } else {
11044             if (!pri->resetting  && (t - pri->lastreset) >= pri->resetinterval) {
11045                pri->resetting = 1;
11046                pri->resetpos = -1;
11047             }
11048          }
11049       }
11050       /* Look for any idle channels if appropriate */
11051       if (doidling && pri_is_up(pri)) {
11052          nextidle = -1;
11053          haveidles = 0;
11054          activeidles = 0;
11055          for (x = pri->numchans; x >= 0; x--) {
11056             if (pri->pvts[x] && !pri->pvts[x]->owner && 
11057                 !pri->pvts[x]->call) {
11058                if (haveidles < pri->minunused) {
11059                   haveidles++;
11060                } else if (!pri->pvts[x]->resetting) {
11061                   nextidle = x;
11062                   break;
11063                }
11064             } else if (pri->pvts[x] && pri->pvts[x]->owner && pri->pvts[x]->isidlecall)
11065                activeidles++;
11066          }
11067          if (nextidle > -1) {
11068             if (ast_tvdiff_ms(ast_tvnow(), lastidle) > 1000) {
11069                /* Don't create a new idle call more than once per second */
11070                snprintf(idlen, sizeof(idlen), "%d/%s", pri->pvts[nextidle]->channel, pri->idledial);
11071                idle = dahdi_request("DAHDI", AST_FORMAT_ULAW, idlen, &cause);
11072                if (idle) {
11073                   pri->pvts[nextidle]->isidlecall = 1;
11074                   if (ast_pthread_create_background(&p, NULL, do_idle_thread, idle)) {
11075                      ast_log(LOG_WARNING, "Unable to start new thread for idle channel '%s'\n", idle->name);
11076                      dahdi_hangup(idle);
11077                   }
11078                } else
11079                   ast_log(LOG_WARNING, "Unable to request channel 'DAHDI/%s' for idle call\n", idlen);
11080                lastidle = ast_tvnow();
11081             }
11082          } else if ((haveidles < pri->minunused) &&
11083                (activeidles > pri->minidle)) {
11084             /* Mark something for hangup if there is something 
11085                that can be hungup */
11086             for (x = pri->numchans; x >= 0; x--) {
11087                /* find a candidate channel */
11088                if (pri->pvts[x] && pri->pvts[x]->owner && pri->pvts[x]->isidlecall) {
11089                   pri->pvts[x]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
11090                   haveidles++;
11091                   /* Stop if we have enough idle channels or
11092                     can't spare any more active idle ones */
11093                   if ((haveidles >= pri->minunused) ||
11094                       (activeidles <= pri->minidle))
11095                      break;
11096                } 
11097             }
11098          }
11099       }
11100       /* Start with reasonable max */
11101       lowest = ast_tv(60, 0);
11102       for (i = 0; i < NUM_DCHANS; i++) {
11103          /* Find lowest available d-channel */
11104          if (!pri->dchannels[i])
11105             break;
11106          if ((next = pri_schedule_next(pri->dchans[i]))) {
11107             /* We need relative time here */
11108             tv = ast_tvsub(*next, ast_tvnow());
11109             if (tv.tv_sec < 0) {
11110                tv = ast_tv(0,0);
11111             }
11112             if (doidling || pri->resetting) {
11113                if (tv.tv_sec > 1) {
11114                   tv = ast_tv(1, 0);
11115                }
11116             } else {
11117                if (tv.tv_sec > 60) {
11118                   tv = ast_tv(60, 0);
11119                }
11120             }
11121          } else if (doidling || pri->resetting) {
11122             /* Make sure we stop at least once per second if we're
11123                monitoring idle channels */
11124             tv = ast_tv(1,0);
11125          } else {
11126             /* Don't poll for more than 60 seconds */
11127             tv = ast_tv(60, 0);
11128          }
11129          if (!i || ast_tvcmp(tv, lowest) < 0) {
11130             lowest = tv;
11131          }
11132       }
11133       ast_mutex_unlock(&pri->lock);
11134 
11135       pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
11136       pthread_testcancel();
11137       e = NULL;
11138       res = poll(fds, numdchans, lowest.tv_sec * 1000 + lowest.tv_usec / 1000);
11139       pthread_testcancel();
11140       pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
11141 
11142       ast_mutex_lock(&pri->lock);
11143       if (!res) {
11144          for (which = 0; which < NUM_DCHANS; which++) {
11145             if (!pri->dchans[which])
11146                break;
11147             /* Just a timeout, run the scheduler */
11148             e = pri_schedule_run(pri->dchans[which]);
11149             if (e)
11150                break;
11151          }
11152       } else if (res > -1) {
11153          for (which = 0; which < NUM_DCHANS; which++) {
11154             if (!pri->dchans[which])
11155                break;
11156             if (fds[which].revents & POLLPRI) {
11157                /* Check for an event */
11158                x = 0;
11159                res = ioctl(pri->fds[which], DAHDI_GETEVENT, &x);
11160                if (x) {
11161                   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);
11162                   manager_event(EVENT_FLAG_SYSTEM, "PRIEvent",
11163                      "PRIEvent: %s\r\n"
11164                      "PRIEventCode: %d\r\n"
11165                      "D-channel: %s\r\n"
11166                      "Span: %d\r\n",
11167                      event2str(x),
11168                      x,
11169                      pri_order(which),
11170                      pri->span
11171                      );
11172                }
11173                /* Keep track of alarm state */  
11174                if (x == DAHDI_EVENT_ALARM) {
11175                   pri->dchanavail[which] &= ~(DCHAN_NOTINALARM | DCHAN_UP);
11176                   pri_find_dchan(pri);
11177                } else if (x == DAHDI_EVENT_NOALARM) {
11178                   pri->dchanavail[which] |= DCHAN_NOTINALARM;
11179                   pri_restart(pri->dchans[which]);
11180                }
11181             
11182                ast_debug(1, "Got event %s (%d) on D-channel for span %d\n", event2str(x), x, pri->span);
11183             } else if (fds[which].revents & POLLIN) {
11184                e = pri_check_event(pri->dchans[which]);
11185             }
11186             if (e)
11187                break;
11188          }
11189       } else if (errno != EINTR)
11190          ast_log(LOG_WARNING, "pri_event returned error %d (%s)\n", errno, strerror(errno));
11191 
11192       if (e) {
11193          if (pri->debug)
11194             pri_dump_event(pri->dchans[which], e);
11195 
11196          if (e->e != PRI_EVENT_DCHAN_DOWN) {
11197             if (!(pri->dchanavail[which] & DCHAN_UP)) {
11198                ast_verb(2, "%s D-Channel on span %d up\n", pri_order(which), pri->span);
11199             }
11200             pri->dchanavail[which] |= DCHAN_UP;
11201          } else if (pri->sig != SIG_BRI_PTMP) {
11202             if (pri->dchanavail[which] & DCHAN_UP) {
11203                ast_verb(2, "%s D-Channel on span %d down\n", pri_order(which), pri->span);
11204             }
11205             pri->dchanavail[which] &= ~DCHAN_UP;
11206          }
11207 
11208          if ((e->e != PRI_EVENT_DCHAN_UP) && (e->e != PRI_EVENT_DCHAN_DOWN) && (pri->pri != pri->dchans[which]))
11209             /* Must be an NFAS group that has the secondary dchan active */
11210             pri->pri = pri->dchans[which];
11211 
11212          switch (e->e) {
11213          case PRI_EVENT_DCHAN_UP:
11214             if (!pri->pri) pri_find_dchan(pri);
11215 
11216             /* Note presense of D-channel */
11217             time(&pri->lastreset);
11218 
11219             /* Restart in 5 seconds */
11220             if (pri->resetinterval > -1) {
11221                pri->lastreset -= pri->resetinterval;
11222                pri->lastreset += 5;
11223             }
11224             pri->resetting = 0;
11225             /* Take the channels from inalarm condition */
11226             for (i = 0; i < pri->numchans; i++)
11227                if (pri->pvts[i]) {
11228                   pri->pvts[i]->inalarm = 0;
11229                }
11230             break;
11231          case PRI_EVENT_DCHAN_DOWN:
11232             pri_find_dchan(pri);
11233             if (!pri_is_up(pri)) {
11234                pri->resetting = 0;
11235                /* Hangup active channels and put them in alarm mode */
11236                for (i = 0; i < pri->numchans; i++) {
11237                   struct dahdi_pvt *p = pri->pvts[i];
11238                   if (p) {
11239                      if (!p->pri || !p->pri->pri || pri_get_timer(p->pri->pri, PRI_TIMER_T309) < 0) {
11240                         /* T309 is not enabled : hangup calls when alarm occurs */
11241                         if (p->call) {
11242                            if (p->pri && p->pri->pri) {
11243                               pri_hangup(p->pri->pri, p->call, -1);
11244                               pri_destroycall(p->pri->pri, p->call);
11245                               p->call = NULL;
11246                            } else
11247                               ast_log(LOG_WARNING, "The PRI Call have not been destroyed\n");
11248                         }
11249                         if (p->realcall) {
11250                            pri_hangup_all(p->realcall, pri);
11251                         } else if (p->owner)
11252                            p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
11253                      }
11254                      p->inalarm = 1;
11255                   }
11256                }
11257             }
11258             break;
11259          case PRI_EVENT_RESTART:
11260             if (e->restart.channel > -1) {
11261                chanpos = pri_find_principle(pri, e->restart.channel);
11262                if (chanpos < 0)
11263                   ast_log(LOG_WARNING, "Restart requested on odd/unavailable channel number %d/%d on span %d\n", 
11264                      PRI_SPAN(e->restart.channel), PRI_CHANNEL(e->restart.channel), pri->span);
11265                else {
11266                   ast_verb(3, "B-channel %d/%d restarted on span %d\n",
11267                         PRI_SPAN(e->restart.channel), PRI_CHANNEL(e->restart.channel), pri->span);
11268                   ast_mutex_lock(&pri->pvts[chanpos]->lock);
11269                   if (pri->pvts[chanpos]->call) {
11270                      pri_destroycall(pri->pri, pri->pvts[chanpos]->call);
11271                      pri->pvts[chanpos]->call = NULL;
11272                   }
11273                   /* Force soft hangup if appropriate */
11274                   if (pri->pvts[chanpos]->realcall) 
11275                      pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
11276                   else if (pri->pvts[chanpos]->owner)
11277                      pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
11278                   ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11279                }
11280             } else {
11281                ast_verb(3, "Restart on requested on entire span %d\n", pri->span);
11282                for (x = 0; x < pri->numchans; x++)
11283                   if (pri->pvts[x]) {
11284                      ast_mutex_lock(&pri->pvts[x]->lock);
11285                      if (pri->pvts[x]->call) {
11286                         pri_destroycall(pri->pri, pri->pvts[x]->call);
11287                         pri->pvts[x]->call = NULL;
11288                      }
11289                      if (pri->pvts[x]->realcall) 
11290                         pri_hangup_all(pri->pvts[x]->realcall, pri);
11291                      else if (pri->pvts[x]->owner)
11292                         pri->pvts[x]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
11293                      ast_mutex_unlock(&pri->pvts[x]->lock);
11294                   }
11295             }
11296             break;
11297          case PRI_EVENT_KEYPAD_DIGIT:
11298             chanpos = pri_find_principle(pri, e->digit.channel);
11299             if (chanpos < 0) {
11300                ast_log(LOG_WARNING, "KEYPAD_DIGITs received on unconfigured channel %d/%d span %d\n", 
11301                   PRI_SPAN(e->digit.channel), PRI_CHANNEL(e->digit.channel), pri->span);
11302             } else {
11303                chanpos = pri_fixup_principle(pri, chanpos, e->digit.call);
11304                if (chanpos > -1) {
11305                   ast_mutex_lock(&pri->pvts[chanpos]->lock);
11306                   /* queue DTMF frame if the PBX for this call was already started (we're forwarding KEYPAD_DIGITs further on */
11307                   if ((pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING) && pri->pvts[chanpos]->call==e->digit.call && pri->pvts[chanpos]->owner) {
11308                      /* how to do that */
11309                      int digitlen = strlen(e->digit.digits);
11310                      char digit;
11311                      int i;               
11312                      for (i = 0; i < digitlen; i++) { 
11313                         digit = e->digit.digits[i];
11314                         {
11315                            struct ast_frame f = { AST_FRAME_DTMF, digit, };
11316                            dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
11317                         }
11318                      }
11319                   }
11320                   ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11321                }
11322             }
11323             break;
11324             
11325          case PRI_EVENT_INFO_RECEIVED:
11326             chanpos = pri_find_principle(pri, e->ring.channel);
11327             if (chanpos < 0) {
11328                ast_log(LOG_WARNING, "INFO received on unconfigured channel %d/%d span %d\n", 
11329                   PRI_SPAN(e->ring.channel), PRI_CHANNEL(e->ring.channel), pri->span);
11330             } else {
11331                chanpos = pri_fixup_principle(pri, chanpos, e->ring.call);
11332                if (chanpos > -1) {
11333                   ast_mutex_lock(&pri->pvts[chanpos]->lock);
11334                   /* queue DTMF frame if the PBX for this call was already started (we're forwarding INFORMATION further on */
11335                   if ((pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING) && pri->pvts[chanpos]->call==e->ring.call && pri->pvts[chanpos]->owner) {
11336                      /* how to do that */
11337                      int digitlen = strlen(e->ring.callednum);
11338                      char digit;
11339                      int i;               
11340                      for (i = 0; i < digitlen; i++) { 
11341                         digit = e->ring.callednum[i];
11342                         {
11343                            struct ast_frame f = { AST_FRAME_DTMF, digit, };
11344                            dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
11345                         }
11346                      }
11347                   }
11348                   ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11349                }
11350             }
11351             break;
11352          case PRI_EVENT_RING:
11353             crv = NULL;
11354             if (e->ring.channel == -1)
11355                chanpos = pri_find_empty_chan(pri, 1);
11356             else
11357                chanpos = pri_find_principle(pri, e->ring.channel);
11358             /* if no channel specified find one empty */
11359             if (chanpos < 0) {
11360                ast_log(LOG_WARNING, "Ring requested on unconfigured channel %d/%d span %d\n", 
11361                   PRI_SPAN(e->ring.channel), PRI_CHANNEL(e->ring.channel), pri->span);
11362             } else {
11363                ast_mutex_lock(&pri->pvts[chanpos]->lock);
11364                if (pri->pvts[chanpos]->owner) {
11365                   if (pri->pvts[chanpos]->call == e->ring.call) {
11366                      ast_log(LOG_WARNING, "Duplicate setup requested on channel %d/%d already in use on span %d\n", 
11367                         PRI_SPAN(e->ring.channel), PRI_CHANNEL(e->ring.channel), pri->span);
11368                      ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11369                      break;
11370                   } else {
11371                      /* This is where we handle initial glare */
11372                      ast_debug(1, "Ring requested on channel %d/%d already in use or previously requested on span %d.  Attempting to renegotiate channel.\n", 
11373                      PRI_SPAN(e->ring.channel), PRI_CHANNEL(e->ring.channel), pri->span);
11374                      ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11375                      chanpos = -1;
11376                   }
11377                }
11378                if (chanpos > -1)
11379                   ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11380             }
11381             if ((chanpos < 0) && (e->ring.flexible))
11382                chanpos = pri_find_empty_chan(pri, 1);
11383             if (chanpos > -1) {
11384                ast_mutex_lock(&pri->pvts[chanpos]->lock);
11385                if (pri->switchtype == PRI_SWITCH_GR303_TMC) {
11386                   /* Should be safe to lock CRV AFAIK while bearer is still locked */
11387                   crv = pri_find_crv(pri, pri_get_crv(pri->pri, e->ring.call, NULL));
11388                   if (crv)
11389                      ast_mutex_lock(&crv->lock);
11390                   if (!crv || crv->owner) {
11391                      pri->pvts[chanpos]->call = NULL;
11392                      if (crv) {
11393                         if (crv->owner)
11394                            crv->owner->_softhangup |= AST_SOFTHANGUP_DEV;
11395                         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);
11396                      } else
11397                         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);
11398                      pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_INVALID_CALL_REFERENCE);
11399                      if (crv)
11400                         ast_mutex_unlock(&crv->lock);
11401                      ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11402                      break;
11403                   }
11404                }
11405                pri->pvts[chanpos]->call = e->ring.call;
11406                apply_plan_to_number(plancallingnum, sizeof(plancallingnum), pri, e->ring.callingnum, e->ring.callingplan);
11407                if (pri->pvts[chanpos]->use_callerid) {
11408                   ast_shrink_phone_number(plancallingnum);
11409                   ast_copy_string(pri->pvts[chanpos]->cid_num, plancallingnum, sizeof(pri->pvts[chanpos]->cid_num));
11410 #ifdef PRI_ANI
11411                   if (!ast_strlen_zero(e->ring.callingani)) {
11412                      apply_plan_to_number(plancallingani, sizeof(plancallingani), pri, e->ring.callingani, e->ring.callingplanani);
11413                      ast_shrink_phone_number(plancallingani);
11414                      ast_copy_string(pri->pvts[chanpos]->cid_ani, plancallingani, sizeof(pri->pvts[chanpos]->cid_ani));
11415                   } else {
11416                      pri->pvts[chanpos]->cid_ani[0] = '\0';
11417                   }
11418 #endif
11419                   ast_copy_string(pri->pvts[chanpos]->cid_name, e->ring.callingname, sizeof(pri->pvts[chanpos]->cid_name));
11420                   pri->pvts[chanpos]->cid_ton = e->ring.callingplan; /* this is the callingplan (TON/NPI), e->ring.callingplan>>4 would be the TON */
11421                } else {
11422                   pri->pvts[chanpos]->cid_num[0] = '\0';
11423                   pri->pvts[chanpos]->cid_ani[0] = '\0';
11424                   pri->pvts[chanpos]->cid_name[0] = '\0';
11425                   pri->pvts[chanpos]->cid_ton = 0;
11426                }
11427                apply_plan_to_number(pri->pvts[chanpos]->rdnis, sizeof(pri->pvts[chanpos]->rdnis), pri,
11428                           e->ring.redirectingnum, e->ring.callingplanrdnis);
11429                /* If immediate=yes go to s|1 */
11430                if (pri->pvts[chanpos]->immediate) {
11431                   ast_verb(3, "Going to extension s|1 because of immediate=yes\n");
11432                   pri->pvts[chanpos]->exten[0] = 's';
11433                   pri->pvts[chanpos]->exten[1] = '\0';
11434                }
11435                /* Get called number */
11436                else if (!ast_strlen_zero(e->ring.callednum)) {
11437                   ast_copy_string(pri->pvts[chanpos]->exten, e->ring.callednum, sizeof(pri->pvts[chanpos]->exten));
11438                   ast_copy_string(pri->pvts[chanpos]->dnid, e->ring.callednum, sizeof(pri->pvts[chanpos]->dnid));
11439                } else if (pri->overlapdial)
11440                   pri->pvts[chanpos]->exten[0] = '\0';
11441                else {
11442                   /* Some PRI circuits are set up to send _no_ digits.  Handle them as 's'. */
11443                   pri->pvts[chanpos]->exten[0] = 's';
11444                   pri->pvts[chanpos]->exten[1] = '\0';
11445                }
11446                /* Set DNID on all incoming calls -- even immediate */
11447                if (!ast_strlen_zero(e->ring.callednum))
11448                   ast_copy_string(pri->pvts[chanpos]->dnid, e->ring.callednum, sizeof(pri->pvts[chanpos]->dnid));
11449                /* No number yet, but received "sending complete"? */
11450                if (e->ring.complete && (ast_strlen_zero(e->ring.callednum))) {
11451                   ast_verb(3, "Going to extension s|1 because of Complete received\n");
11452                   pri->pvts[chanpos]->exten[0] = 's';
11453                   pri->pvts[chanpos]->exten[1] = '\0';
11454                }
11455 
11456                /* Make sure extension exists (or in overlap dial mode, can exist) */
11457                if (((pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING) && ast_canmatch_extension(NULL, pri->pvts[chanpos]->context, pri->pvts[chanpos]->exten, 1, pri->pvts[chanpos]->cid_num)) ||
11458                   ast_exists_extension(NULL, pri->pvts[chanpos]->context, pri->pvts[chanpos]->exten, 1, pri->pvts[chanpos]->cid_num)) {
11459                   /* Setup law */
11460                   int law;
11461                   if (pri->switchtype != PRI_SWITCH_GR303_TMC) {
11462                      /* Set to audio mode at this point */
11463                      law = 1;
11464                      if (ioctl(pri->pvts[chanpos]->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &law) == -1)
11465                         ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d: %s\n", pri->pvts[chanpos]->channel, law, strerror(errno));
11466                   }
11467                   if (e->ring.layer1 == PRI_LAYER_1_ALAW)
11468                      law = DAHDI_LAW_ALAW;
11469                   else
11470                      law = DAHDI_LAW_MULAW;
11471                   res = dahdi_setlaw(pri->pvts[chanpos]->subs[SUB_REAL].dfd, law);
11472                   if (res < 0) 
11473                      ast_log(LOG_WARNING, "Unable to set law on channel %d\n", pri->pvts[chanpos]->channel);
11474                   res = set_actual_gain(pri->pvts[chanpos]->subs[SUB_REAL].dfd, 0, pri->pvts[chanpos]->rxgain, pri->pvts[chanpos]->txgain, law);
11475                   if (res < 0)
11476                      ast_log(LOG_WARNING, "Unable to set gains on channel %d\n", pri->pvts[chanpos]->channel);
11477                   if (e->ring.complete || !(pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)) {
11478                      /* Just announce proceeding */
11479                      pri->pvts[chanpos]->proceeding = 1;
11480                      pri_proceeding(pri->pri, e->ring.call, PVT_TO_CHANNEL(pri->pvts[chanpos]), 0);
11481                   } else {
11482                      if (pri->switchtype != PRI_SWITCH_GR303_TMC) 
11483                         pri_need_more_info(pri->pri, e->ring.call, PVT_TO_CHANNEL(pri->pvts[chanpos]), 1);
11484                      else
11485                         pri_answer(pri->pri, e->ring.call, PVT_TO_CHANNEL(pri->pvts[chanpos]), 1);
11486                   }
11487                   /* Get the use_callingpres state */
11488                   pri->pvts[chanpos]->callingpres = e->ring.callingpres;
11489                
11490                   /* Start PBX */
11491                   if (!e->ring.complete
11492                      && (pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)
11493                      && ast_matchmore_extension(NULL, pri->pvts[chanpos]->context, pri->pvts[chanpos]->exten, 1, pri->pvts[chanpos]->cid_num)) {
11494                      /*
11495                       * Release the PRI lock while we create the channel
11496                       * so other threads can send D channel messages.
11497                       */
11498                      ast_mutex_unlock(&pri->lock);
11499                      if (crv) {
11500                         /* Set bearer and such */
11501                         pri_assign_bearer(crv, pri, pri->pvts[chanpos]);
11502                         c = dahdi_new(crv, AST_STATE_RESERVED, 0, SUB_REAL, law, e->ring.ctype);
11503                         pri->pvts[chanpos]->owner = &inuse;
11504                         ast_debug(1, "Started up crv %d:%d on bearer channel %d\n", pri->trunkgroup, crv->channel, crv->bearer->channel);
11505                      } else {
11506                         c = dahdi_new(pri->pvts[chanpos], AST_STATE_RESERVED, 0, SUB_REAL, law, e->ring.ctype);
11507                      }
11508                      ast_mutex_lock(&pri->lock);
11509                      if (c) {
11510                         if (!ast_strlen_zero(e->ring.callingsubaddr)) {
11511                            pbx_builtin_setvar_helper(c, "CALLINGSUBADDR", e->ring.callingsubaddr);
11512                         }
11513                         if (e->ring.ani2 >= 0) {
11514                            snprintf(ani2str, sizeof(ani2str), "%d", e->ring.ani2);
11515                            pbx_builtin_setvar_helper(c, "ANI2", ani2str);
11516                            pri->pvts[chanpos]->cid_ani2 = e->ring.ani2;
11517                         }
11518 
11519 #ifdef SUPPORT_USERUSER
11520                         if (!ast_strlen_zero(e->ring.useruserinfo)) {
11521                            pbx_builtin_setvar_helper(c, "USERUSERINFO", e->ring.useruserinfo);
11522                         }
11523 #endif
11524 
11525                         snprintf(calledtonstr, sizeof(calledtonstr), "%d", e->ring.calledplan);
11526                         pbx_builtin_setvar_helper(c, "CALLEDTON", calledtonstr);
11527                         if (e->ring.redirectingreason >= 0)
11528                            pbx_builtin_setvar_helper(c, "PRIREDIRECTREASON", redirectingreason2str(e->ring.redirectingreason));
11529                      }
11530                      if (c && !ast_pthread_create_detached(&threadid, NULL, ss_thread, c)) {
11531                         ast_verb(3, "Accepting overlap call from '%s' to '%s' on channel %d/%d, span %d\n",
11532                            plancallingnum, S_OR(pri->pvts[chanpos]->exten, "<unspecified>"),
11533                            pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span);
11534                      } else {
11535                         ast_log(LOG_WARNING, "Unable to start PBX on channel %d/%d, span %d\n",
11536                            pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span);
11537                         if (c)
11538                            ast_hangup(c);
11539                         else {
11540                            pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_SWITCH_CONGESTION);
11541                            pri->pvts[chanpos]->call = NULL;
11542                         }
11543                      }
11544                   } else {
11545                      /*
11546                       * Release the PRI lock while we create the channel
11547                       * so other threads can send D channel messages.
11548                       */
11549                      ast_mutex_unlock(&pri->lock);
11550                      c = dahdi_new(pri->pvts[chanpos], AST_STATE_RING, 0, SUB_REAL, law, e->ring.ctype);
11551                      ast_mutex_lock(&pri->lock);
11552                      if (c) {
11553                         /*
11554                          * It is reasonably safe to set the following
11555                          * channel variables while the PRI and DAHDI private
11556                          * structures are locked.  The PBX has not been
11557                          * started yet and it is unlikely that any other task
11558                          * will do anything with the channel we have just
11559                          * created.
11560                          */
11561                         if (!ast_strlen_zero(e->ring.callingsubaddr)) {
11562                            pbx_builtin_setvar_helper(c, "CALLINGSUBADDR", e->ring.callingsubaddr);
11563                         }
11564                         if (e->ring.ani2 >= 0) {
11565                            snprintf(ani2str, sizeof(ani2str), "%d", e->ring.ani2);
11566                            pbx_builtin_setvar_helper(c, "ANI2", ani2str);
11567                            pri->pvts[chanpos]->cid_ani2 = e->ring.ani2;
11568                         }
11569 
11570 #ifdef SUPPORT_USERUSER
11571                         if (!ast_strlen_zero(e->ring.useruserinfo)) {
11572                            pbx_builtin_setvar_helper(c, "USERUSERINFO", e->ring.useruserinfo);
11573                         }
11574 #endif
11575 
11576                         if (e->ring.redirectingreason >= 0)
11577                            pbx_builtin_setvar_helper(c, "PRIREDIRECTREASON", redirectingreason2str(e->ring.redirectingreason));
11578 
11579                         snprintf(calledtonstr, sizeof(calledtonstr), "%d", e->ring.calledplan);
11580                         pbx_builtin_setvar_helper(c, "CALLEDTON", calledtonstr);
11581                      }
11582                      if (c && !ast_pbx_start(c)) {
11583                         ast_verb(3, "Accepting call from '%s' to '%s' on channel %d/%d, span %d\n",
11584                            plancallingnum, pri->pvts[chanpos]->exten,
11585                            pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span);
11586 
11587                         dahdi_enable_ec(pri->pvts[chanpos]);
11588                      } else {
11589                         ast_log(LOG_WARNING, "Unable to start PBX on channel %d/%d, span %d\n",
11590                            pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span);
11591                         if (c) {
11592                            ast_hangup(c);
11593                         } else {
11594                            pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_SWITCH_CONGESTION);
11595                            pri->pvts[chanpos]->call = NULL;
11596                         }
11597                      }
11598                   }
11599                } else {
11600                   ast_verb(3, "Extension '%s' in context '%s' from '%s' does not exist.  Rejecting call on channel %d/%d, span %d\n",
11601                      pri->pvts[chanpos]->exten, pri->pvts[chanpos]->context, pri->pvts[chanpos]->cid_num, pri->pvts[chanpos]->logicalspan,
11602                      pri->pvts[chanpos]->prioffset, pri->span);
11603                   pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_UNALLOCATED);
11604                   pri->pvts[chanpos]->call = NULL;
11605                   pri->pvts[chanpos]->exten[0] = '\0';
11606                }
11607                if (crv)
11608                   ast_mutex_unlock(&crv->lock);
11609                ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11610             } else {
11611                if (e->ring.flexible)
11612                   pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_NORMAL_CIRCUIT_CONGESTION);
11613                else
11614                   pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_REQUESTED_CHAN_UNAVAIL);
11615             }
11616             break;
11617          case PRI_EVENT_RINGING:
11618             chanpos = pri_find_principle(pri, e->ringing.channel);
11619             if (chanpos < 0) {
11620                ast_log(LOG_WARNING, "Ringing requested on unconfigured channel %d/%d span %d\n", 
11621                   PRI_SPAN(e->ringing.channel), PRI_CHANNEL(e->ringing.channel), pri->span);
11622             } else {
11623                chanpos = pri_fixup_principle(pri, chanpos, e->ringing.call);
11624                if (chanpos < 0) {
11625                   ast_log(LOG_WARNING, "Ringing requested on channel %d/%d not in use on span %d\n", 
11626                      PRI_SPAN(e->ringing.channel), PRI_CHANNEL(e->ringing.channel), pri->span);
11627                } else {
11628                   ast_mutex_lock(&pri->pvts[chanpos]->lock);
11629                   if (ast_strlen_zero(pri->pvts[chanpos]->dop.dialstr)) {
11630                      dahdi_enable_ec(pri->pvts[chanpos]);
11631                      pri->pvts[chanpos]->subs[SUB_REAL].needringing = 1;
11632                      pri->pvts[chanpos]->alerting = 1;
11633                   } else
11634                      ast_debug(1, "Deferring ringing notification because of extra digits to dial...\n");
11635 
11636 #ifdef PRI_PROGRESS_MASK
11637                   if (e->ringing.progressmask & PRI_PROG_INBAND_AVAILABLE) {
11638 #else
11639                   if (e->ringing.progress == 8) {
11640 #endif
11641                      /* Now we can do call progress detection */
11642                      if (pri->pvts[chanpos]->dsp && pri->pvts[chanpos]->dsp_features) {
11643                         /* RINGING detection isn't required because we got ALERTING signal */
11644                         ast_dsp_set_features(pri->pvts[chanpos]->dsp, pri->pvts[chanpos]->dsp_features & ~DSP_PROGRESS_RINGING);
11645                         pri->pvts[chanpos]->dsp_features = 0;
11646                      }
11647                   }
11648 
11649 #ifdef SUPPORT_USERUSER
11650                   if (!ast_strlen_zero(e->ringing.useruserinfo)) {
11651                      struct ast_channel *owner = pri->pvts[chanpos]->owner;
11652                      ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11653                      pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->ringing.useruserinfo);
11654                      ast_mutex_lock(&pri->pvts[chanpos]->lock);
11655                   }
11656 #endif
11657 
11658                   ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11659                }
11660             }
11661             break;
11662          case PRI_EVENT_PROGRESS:
11663             /* Get chan value if e->e is not PRI_EVNT_RINGING */
11664             chanpos = pri_find_principle(pri, e->proceeding.channel);
11665             if (chanpos > -1) {
11666 #ifdef PRI_PROGRESS_MASK
11667                if ((!pri->pvts[chanpos]->progress) || (e->proceeding.progressmask & PRI_PROG_INBAND_AVAILABLE)) {
11668 #else
11669                if ((!pri->pvts[chanpos]->progress) || (e->proceeding.progress == 8)) {
11670 #endif
11671                   struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_PROGRESS, };
11672 
11673                   if (e->proceeding.cause > -1) {
11674                      ast_verb(3, "PROGRESS with cause code %d received\n", e->proceeding.cause);
11675 
11676                      /* Work around broken, out of spec USER_BUSY cause in a progress message */
11677                      if (e->proceeding.cause == AST_CAUSE_USER_BUSY) {
11678                         if (pri->pvts[chanpos]->owner) {
11679                            ast_verb(3, "PROGRESS with 'user busy' received, signalling AST_CONTROL_BUSY instead of AST_CONTROL_PROGRESS\n");
11680 
11681                            pri->pvts[chanpos]->owner->hangupcause = e->proceeding.cause;
11682                            f.subclass = AST_CONTROL_BUSY;
11683                         }
11684                      }
11685                   }
11686                   
11687                   ast_mutex_lock(&pri->pvts[chanpos]->lock);
11688                   ast_debug(1, "Queuing frame from PRI_EVENT_PROGRESS on channel %d/%d span %d\n",
11689                      pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset,pri->span);
11690                   dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
11691 #ifdef PRI_PROGRESS_MASK
11692                   if (e->proceeding.progressmask & PRI_PROG_INBAND_AVAILABLE) {
11693 #else
11694                   if (e->proceeding.progress == 8) {
11695 #endif
11696                      /* Now we can do call progress detection */
11697                      if (pri->pvts[chanpos]->dsp && pri->pvts[chanpos]->dsp_features) {
11698                         ast_dsp_set_features(pri->pvts[chanpos]->dsp, pri->pvts[chanpos]->dsp_features);
11699                         pri->pvts[chanpos]->dsp_features = 0;
11700                      }
11701                      /* Bring voice path up */
11702                      f.subclass = AST_CONTROL_PROGRESS;
11703                      dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
11704                   }
11705                   pri->pvts[chanpos]->progress = 1;
11706                   pri->pvts[chanpos]->dialing = 0;
11707                   ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11708                }
11709             }
11710             break;
11711          case PRI_EVENT_PROCEEDING:
11712             chanpos = pri_find_principle(pri, e->proceeding.channel);
11713             if (chanpos > -1) {
11714                if (!pri->pvts[chanpos]->proceeding) {
11715                   struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_PROCEEDING, };
11716                   
11717                   ast_mutex_lock(&pri->pvts[chanpos]->lock);
11718                   ast_debug(1, "Queuing frame from PRI_EVENT_PROCEEDING on channel %d/%d span %d\n",
11719                      pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset,pri->span);
11720                   dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
11721 #ifdef PRI_PROGRESS_MASK
11722                   if (e->proceeding.progressmask & PRI_PROG_INBAND_AVAILABLE) {
11723 #else
11724                   if (e->proceeding.progress == 8) {
11725 #endif
11726                      /* Now we can do call progress detection */
11727                      if (pri->pvts[chanpos]->dsp && pri->pvts[chanpos]->dsp_features) {
11728                         ast_dsp_set_features(pri->pvts[chanpos]->dsp, pri->pvts[chanpos]->dsp_features);
11729                         pri->pvts[chanpos]->dsp_features = 0;
11730                      }
11731                      /* Bring voice path up */
11732                      f.subclass = AST_CONTROL_PROGRESS;
11733                      dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
11734                   }
11735                   pri->pvts[chanpos]->proceeding = 1;
11736                   pri->pvts[chanpos]->dialing = 0;
11737                   ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11738                }
11739             }
11740             break;
11741          case PRI_EVENT_FACNAME:
11742             chanpos = pri_find_principle(pri, e->facname.channel);
11743             if (chanpos < 0) {
11744                ast_log(LOG_WARNING, "Facility Name requested on unconfigured channel %d/%d span %d\n", 
11745                   PRI_SPAN(e->facname.channel), PRI_CHANNEL(e->facname.channel), pri->span);
11746             } else {
11747                chanpos = pri_fixup_principle(pri, chanpos, e->facname.call);
11748                if (chanpos < 0) {
11749                   ast_log(LOG_WARNING, "Facility Name requested on channel %d/%d not in use on span %d\n", 
11750                      PRI_SPAN(e->facname.channel), PRI_CHANNEL(e->facname.channel), pri->span);
11751                } else {
11752                   /* Re-use *69 field for PRI */
11753                   ast_mutex_lock(&pri->pvts[chanpos]->lock);
11754                   ast_copy_string(pri->pvts[chanpos]->lastcid_num, e->facname.callingnum, sizeof(pri->pvts[chanpos]->lastcid_num));
11755                   ast_copy_string(pri->pvts[chanpos]->lastcid_name, e->facname.callingname, sizeof(pri->pvts[chanpos]->lastcid_name));
11756                   pri->pvts[chanpos]->subs[SUB_REAL].needcallerid =1;
11757                   dahdi_enable_ec(pri->pvts[chanpos]);
11758                   ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11759                }
11760             }
11761             break;            
11762          case PRI_EVENT_ANSWER:
11763             chanpos = pri_find_principle(pri, e->answer.channel);
11764             if (chanpos < 0) {
11765                ast_log(LOG_WARNING, "Answer on unconfigured channel %d/%d span %d\n", 
11766                   PRI_SPAN(e->answer.channel), PRI_CHANNEL(e->answer.channel), pri->span);
11767             } else {
11768                chanpos = pri_fixup_principle(pri, chanpos, e->answer.call);
11769                if (chanpos < 0) {
11770                   ast_log(LOG_WARNING, "Answer requested on channel %d/%d not in use on span %d\n", 
11771                      PRI_SPAN(e->answer.channel), PRI_CHANNEL(e->answer.channel), pri->span);
11772                } else {
11773                   ast_mutex_lock(&pri->pvts[chanpos]->lock);
11774                   /* Now we can do call progress detection */
11775 
11776                   /* We changed this so it turns on the DSP no matter what... progress or no progress.
11777                    * By this time, we need DTMF detection and other features that were previously disabled
11778                    * -- Matt F */
11779                   if (pri->pvts[chanpos]->dsp && pri->pvts[chanpos]->dsp_features) {
11780                      ast_dsp_set_features(pri->pvts[chanpos]->dsp, pri->pvts[chanpos]->dsp_features);
11781                      pri->pvts[chanpos]->dsp_features = 0;
11782                   }
11783                   if (pri->pvts[chanpos]->realcall && (pri->pvts[chanpos]->realcall->sig == SIG_FXSKS)) {
11784                      ast_debug(1, "Starting up GR-303 trunk now that we got CONNECT...\n");
11785                      x = DAHDI_START;
11786                      res = ioctl(pri->pvts[chanpos]->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
11787                      if (res < 0) {
11788                         if (errno != EINPROGRESS) {
11789                            ast_log(LOG_WARNING, "Unable to start channel: %s\n", strerror(errno));
11790                         }
11791                      }
11792                   } else if (!ast_strlen_zero(pri->pvts[chanpos]->dop.dialstr)) {
11793                      pri->pvts[chanpos]->dialing = 1;
11794                      /* Send any "w" waited stuff */
11795                      res = ioctl(pri->pvts[chanpos]->subs[SUB_REAL].dfd, DAHDI_DIAL, &pri->pvts[chanpos]->dop);
11796                      if (res < 0) {
11797                         ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", pri->pvts[chanpos]->channel, strerror(errno));
11798                         pri->pvts[chanpos]->dop.dialstr[0] = '\0';
11799                      } else
11800                         ast_debug(1, "Sent deferred digit string: %s\n", pri->pvts[chanpos]->dop.dialstr);
11801 
11802                      pri->pvts[chanpos]->dop.dialstr[0] = '\0';
11803                   } else if (pri->pvts[chanpos]->confirmanswer) {
11804                      ast_debug(1, "Waiting on answer confirmation on channel %d!\n", pri->pvts[chanpos]->channel);
11805                   } else {
11806                      pri->pvts[chanpos]->dialing = 0;
11807                      pri->pvts[chanpos]->subs[SUB_REAL].needanswer =1;
11808                      /* Enable echo cancellation if it's not on already */
11809                      dahdi_enable_ec(pri->pvts[chanpos]);
11810                   }
11811 
11812 #ifdef SUPPORT_USERUSER
11813                   if (!ast_strlen_zero(e->answer.useruserinfo)) {
11814                      struct ast_channel *owner = pri->pvts[chanpos]->owner;
11815                      ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11816                      pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->answer.useruserinfo);
11817                      ast_mutex_lock(&pri->pvts[chanpos]->lock);
11818                   }
11819 #endif
11820 
11821                   ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11822                }
11823             }
11824             break;            
11825          case PRI_EVENT_HANGUP:
11826             chanpos = pri_find_principle(pri, e->hangup.channel);
11827             if (chanpos < 0) {
11828                ast_log(LOG_WARNING, "Hangup requested on unconfigured channel %d/%d span %d\n", 
11829                   PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
11830             } else {
11831                chanpos = pri_fixup_principle(pri, chanpos, e->hangup.call);
11832                if (chanpos > -1) {
11833                   ast_mutex_lock(&pri->pvts[chanpos]->lock);
11834                   if (!pri->pvts[chanpos]->alreadyhungup) {
11835                      /* we're calling here dahdi_hangup so once we get there we need to clear p->call after calling pri_hangup */
11836                      pri->pvts[chanpos]->alreadyhungup = 1;
11837                      if (pri->pvts[chanpos]->realcall) 
11838                         pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
11839                      else if (pri->pvts[chanpos]->owner) {
11840                         /* Queue a BUSY instead of a hangup if our cause is appropriate */
11841                         pri->pvts[chanpos]->owner->hangupcause = e->hangup.cause;
11842                         switch (pri->pvts[chanpos]->owner->_state) {
11843                         case AST_STATE_BUSY:
11844                         case AST_STATE_UP:
11845                            pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
11846                            break;
11847                         default:
11848                            switch (e->hangup.cause) {
11849                            case PRI_CAUSE_USER_BUSY:
11850                               pri->pvts[chanpos]->subs[SUB_REAL].needbusy =1;
11851                               break;
11852                            case PRI_CAUSE_CALL_REJECTED:
11853                            case PRI_CAUSE_NETWORK_OUT_OF_ORDER:
11854                            case PRI_CAUSE_NORMAL_CIRCUIT_CONGESTION:
11855                            case PRI_CAUSE_SWITCH_CONGESTION:
11856                            case PRI_CAUSE_DESTINATION_OUT_OF_ORDER:
11857                            case PRI_CAUSE_NORMAL_TEMPORARY_FAILURE:
11858                               pri->pvts[chanpos]->subs[SUB_REAL].needcongestion =1;
11859                               break;
11860                            default:
11861                               pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
11862                            }
11863                            break;
11864                         }
11865                      }
11866                      ast_verb(3, "Channel %d/%d, span %d got hangup, cause %d\n",
11867                            pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span, e->hangup.cause);
11868                   } else {
11869                      pri_hangup(pri->pri, pri->pvts[chanpos]->call, e->hangup.cause);
11870                      pri->pvts[chanpos]->call = NULL;
11871                   }
11872                   if (e->hangup.cause == PRI_CAUSE_REQUESTED_CHAN_UNAVAIL) {
11873                      ast_verb(3, "Forcing restart of channel %d/%d on span %d since channel reported in use\n",
11874                            PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
11875                      pri_reset(pri->pri, PVT_TO_CHANNEL(pri->pvts[chanpos]));
11876                      pri->pvts[chanpos]->resetting = 1;
11877                   }
11878                   if (e->hangup.aoc_units > -1)
11879                      ast_verb(3, "Channel %d/%d, span %d received AOC-E charging %d unit%s\n",
11880                            pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span, (int)e->hangup.aoc_units, (e->hangup.aoc_units == 1) ? "" : "s");
11881 
11882 #ifdef SUPPORT_USERUSER
11883                   if (pri->pvts[chanpos]->owner && !ast_strlen_zero(e->hangup.useruserinfo)) {
11884                      struct ast_channel *owner = pri->pvts[chanpos]->owner;
11885                      ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11886                      pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->hangup.useruserinfo);
11887                      ast_mutex_lock(&pri->pvts[chanpos]->lock);
11888                   }
11889 #endif
11890 
11891                   ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11892                } else {
11893                   ast_log(LOG_WARNING, "Hangup on bad channel %d/%d on span %d\n", 
11894                      PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
11895                }
11896             } 
11897             break;
11898 #ifndef PRI_EVENT_HANGUP_REQ
11899 #error please update libpri
11900 #endif
11901          case PRI_EVENT_HANGUP_REQ:
11902             chanpos = pri_find_principle(pri, e->hangup.channel);
11903             if (chanpos < 0) {
11904                ast_log(LOG_WARNING, "Hangup REQ requested on unconfigured channel %d/%d span %d\n", 
11905                   PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
11906             } else {
11907                chanpos = pri_fixup_principle(pri, chanpos, e->hangup.call);
11908                if (chanpos > -1) {
11909                   ast_mutex_lock(&pri->pvts[chanpos]->lock);
11910                   if (pri->pvts[chanpos]->realcall) 
11911                      pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
11912                   else if (pri->pvts[chanpos]->owner) {
11913                      pri->pvts[chanpos]->owner->hangupcause = e->hangup.cause;
11914                      switch (pri->pvts[chanpos]->owner->_state) {
11915                      case AST_STATE_BUSY:
11916                      case AST_STATE_UP:
11917                         pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
11918                         break;
11919                      default:
11920                         switch (e->hangup.cause) {
11921                            case PRI_CAUSE_USER_BUSY:
11922                               pri->pvts[chanpos]->subs[SUB_REAL].needbusy =1;
11923                               break;
11924                            case PRI_CAUSE_CALL_REJECTED:
11925                            case PRI_CAUSE_NETWORK_OUT_OF_ORDER:
11926                            case PRI_CAUSE_NORMAL_CIRCUIT_CONGESTION:
11927                            case PRI_CAUSE_SWITCH_CONGESTION:
11928                            case PRI_CAUSE_DESTINATION_OUT_OF_ORDER:
11929                            case PRI_CAUSE_NORMAL_TEMPORARY_FAILURE:
11930                               pri->pvts[chanpos]->subs[SUB_REAL].needcongestion =1;
11931                               break;
11932                            default:
11933                               pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
11934                         }
11935                         break;
11936                      }
11937                      ast_verb(3, "Channel %d/%d, span %d got hangup request, cause %d\n", PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span, e->hangup.cause);
11938                      if (e->hangup.aoc_units > -1)
11939                         ast_verb(3, "Channel %d/%d, span %d received AOC-E charging %d unit%s\n",
11940                               pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span, (int)e->hangup.aoc_units, (e->hangup.aoc_units == 1) ? "" : "s");
11941                   } else {
11942                      pri_hangup(pri->pri, pri->pvts[chanpos]->call, e->hangup.cause);
11943                      pri->pvts[chanpos]->call = NULL;
11944                   }
11945                   if (e->hangup.cause == PRI_CAUSE_REQUESTED_CHAN_UNAVAIL) {
11946                      ast_verb(3, "Forcing restart of channel %d/%d span %d since channel reported in use\n",
11947                            PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
11948                      pri_reset(pri->pri, PVT_TO_CHANNEL(pri->pvts[chanpos]));
11949                      pri->pvts[chanpos]->resetting = 1;
11950                   }
11951 
11952 #ifdef SUPPORT_USERUSER
11953                   if (!ast_strlen_zero(e->hangup.useruserinfo)) {
11954                      struct ast_channel *owner = pri->pvts[chanpos]->owner;
11955                      ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11956                      pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->hangup.useruserinfo);
11957                      ast_mutex_lock(&pri->pvts[chanpos]->lock);
11958                   }
11959 #endif
11960 
11961                   ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11962                } else {
11963                   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);
11964                }
11965             } 
11966             break;
11967          case PRI_EVENT_HANGUP_ACK:
11968             chanpos = pri_find_principle(pri, e->hangup.channel);
11969             if (chanpos < 0) {
11970                ast_log(LOG_WARNING, "Hangup ACK requested on unconfigured channel number %d/%d span %d\n", 
11971                   PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
11972             } else {
11973                chanpos = pri_fixup_principle(pri, chanpos, e->hangup.call);
11974                if (chanpos > -1) {
11975                   ast_mutex_lock(&pri->pvts[chanpos]->lock);
11976                   pri->pvts[chanpos]->call = NULL;
11977                   pri->pvts[chanpos]->resetting = 0;
11978                   if (pri->pvts[chanpos]->owner) {
11979                      ast_verb(3, "Channel %d/%d, span %d got hangup ACK\n", PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
11980                   }
11981 
11982 #ifdef SUPPORT_USERUSER
11983                   if (!ast_strlen_zero(e->hangup.useruserinfo)) {
11984                      struct ast_channel *owner = pri->pvts[chanpos]->owner;
11985                      ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11986                      pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->hangup.useruserinfo);
11987                      ast_mutex_lock(&pri->pvts[chanpos]->lock);
11988                   }
11989 #endif
11990 
11991                   ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11992                }
11993             }
11994             break;
11995          case PRI_EVENT_CONFIG_ERR:
11996             ast_log(LOG_WARNING, "PRI Error on span %d: %s\n", pri->trunkgroup, e->err.err);
11997             break;
11998          case PRI_EVENT_RESTART_ACK:
11999             chanpos = pri_find_principle(pri, e->restartack.channel);
12000             if (chanpos < 0) {
12001                /* Sometime switches (e.g. I421 / British Telecom) don't give us the
12002                   channel number, so we have to figure it out...  This must be why
12003                   everybody resets exactly a channel at a time. */
12004                for (x = 0; x < pri->numchans; x++) {
12005                   if (pri->pvts[x] && pri->pvts[x]->resetting) {
12006                      chanpos = x;
12007                      ast_mutex_lock(&pri->pvts[chanpos]->lock);
12008                      ast_debug(1, "Assuming restart ack is really for channel %d/%d span %d\n", pri->pvts[chanpos]->logicalspan, 
12009                         pri->pvts[chanpos]->prioffset, pri->span);
12010                      if (pri->pvts[chanpos]->realcall) 
12011                         pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
12012                      else if (pri->pvts[chanpos]->owner) {
12013                         ast_log(LOG_WARNING, "Got restart ack on channel %d/%d with owner on span %d\n", pri->pvts[chanpos]->logicalspan, 
12014                            pri->pvts[chanpos]->prioffset, pri->span);
12015                         pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
12016                      }
12017                      pri->pvts[chanpos]->resetting = 0;
12018                      ast_verb(3, "B-channel %d/%d successfully restarted on span %d\n", pri->pvts[chanpos]->logicalspan,
12019                            pri->pvts[chanpos]->prioffset, pri->span);
12020                      ast_mutex_unlock(&pri->pvts[chanpos]->lock);
12021                      if (pri->resetting)
12022                         pri_check_restart(pri);
12023                      break;
12024                   }
12025                }
12026                if (chanpos < 0) {
12027                   ast_log(LOG_WARNING, "Restart ACK requested on strange channel %d/%d span %d\n", 
12028                      PRI_SPAN(e->restartack.channel), PRI_CHANNEL(e->restartack.channel), pri->span);
12029                }
12030             } else {
12031                if (pri->pvts[chanpos]) {
12032                   ast_mutex_lock(&pri->pvts[chanpos]->lock);
12033                   if (pri->pvts[chanpos]->realcall) 
12034                      pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
12035                   else if (pri->pvts[chanpos]->owner) {
12036                      ast_log(LOG_WARNING, "Got restart ack on channel %d/%d span %d with owner\n",
12037                         PRI_SPAN(e->restartack.channel), PRI_CHANNEL(e->restartack.channel), pri->span);
12038                      pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
12039                   }
12040                   pri->pvts[chanpos]->resetting = 0;
12041                   pri->pvts[chanpos]->inservice = 1;
12042                   ast_verb(3, "B-channel %d/%d successfully restarted on span %d\n", pri->pvts[chanpos]->logicalspan,
12043                            pri->pvts[chanpos]->prioffset, pri->span);
12044                   ast_mutex_unlock(&pri->pvts[chanpos]->lock);
12045                   if (pri->resetting)
12046                      pri_check_restart(pri);
12047                }
12048             }
12049             break;
12050          case PRI_EVENT_SETUP_ACK:
12051             chanpos = pri_find_principle(pri, e->setup_ack.channel);
12052             if (chanpos < 0) {
12053                ast_log(LOG_WARNING, "Received SETUP_ACKNOWLEDGE on unconfigured channel %d/%d span %d\n", 
12054                   PRI_SPAN(e->setup_ack.channel), PRI_CHANNEL(e->setup_ack.channel), pri->span);
12055             } else {
12056                chanpos = pri_fixup_principle(pri, chanpos, e->setup_ack.call);
12057                if (chanpos > -1) {
12058                   ast_mutex_lock(&pri->pvts[chanpos]->lock);
12059                   pri->pvts[chanpos]->setup_ack = 1;
12060                   /* Send any queued digits */
12061                   for (x = 0;x < strlen(pri->pvts[chanpos]->dialdest); x++) {
12062                      ast_debug(1, "Sending pending digit '%c'\n", pri->pvts[chanpos]->dialdest[x]);
12063                      pri_information(pri->pri, pri->pvts[chanpos]->call, 
12064                         pri->pvts[chanpos]->dialdest[x]);
12065                   }
12066                   ast_mutex_unlock(&pri->pvts[chanpos]->lock);
12067                } else
12068                   ast_log(LOG_WARNING, "Unable to move channel %d!\n", e->setup_ack.channel);
12069             }
12070             break;
12071          case PRI_EVENT_NOTIFY:
12072             chanpos = pri_find_principle(pri, e->notify.channel);
12073             if (chanpos < 0) {
12074                ast_log(LOG_WARNING, "Received NOTIFY on unconfigured channel %d/%d span %d\n",
12075                   PRI_SPAN(e->notify.channel), PRI_CHANNEL(e->notify.channel), pri->span);
12076             } else {
12077                struct ast_frame f = { AST_FRAME_CONTROL, };
12078                ast_mutex_lock(&pri->pvts[chanpos]->lock);
12079                switch (e->notify.info) {
12080                case PRI_NOTIFY_REMOTE_HOLD:
12081                   f.subclass = AST_CONTROL_HOLD;
12082                   dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
12083                   break;
12084                case PRI_NOTIFY_REMOTE_RETRIEVAL:
12085                   f.subclass = AST_CONTROL_UNHOLD;
12086                   dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
12087                   break;
12088                }
12089                ast_mutex_unlock(&pri->pvts[chanpos]->lock);
12090             }
12091             break;
12092          default:
12093             ast_debug(1, "Event: %d\n", e->e);
12094          }
12095       }  
12096       ast_mutex_unlock(&pri->lock);
12097    }
12098    /* Never reached */
12099    return NULL;
12100 }
12101 
12102 static int start_pri(struct dahdi_pri *pri)
12103 {
12104    int res, x;
12105    struct dahdi_params p;
12106    struct dahdi_bufferinfo bi;
12107    struct dahdi_spaninfo si;
12108    int i;
12109    
12110    for (i = 0; i < NUM_DCHANS; i++) {
12111       if (!pri->dchannels[i])
12112          break;
12113       pri->fds[i] = open("/dev/dahdi/channel", O_RDWR);
12114       x = pri->dchannels[i];
12115       if ((pri->fds[i] < 0) || (ioctl(pri->fds[i],DAHDI_SPECIFY,&x) == -1)) {
12116          ast_log(LOG_ERROR, "Unable to open D-channel %d (%s)\n", x, strerror(errno));
12117          return -1;
12118       }
12119       memset(&p, 0, sizeof(p));
12120       res = ioctl(pri->fds[i], DAHDI_GET_PARAMS, &p);
12121       if (res) {
12122          dahdi_close_pri_fd(pri, i);
12123          ast_log(LOG_ERROR, "Unable to get parameters for D-channel %d (%s)\n", x, strerror(errno));
12124          return -1;
12125       }
12126       if ((p.sigtype != DAHDI_SIG_HDLCFCS) && (p.sigtype != DAHDI_SIG_HARDHDLC)) {
12127          dahdi_close_pri_fd(pri, i);
12128          ast_log(LOG_ERROR, "D-channel %d is not in HDLC/FCS mode.\n", x);
12129          return -1;
12130       }
12131       memset(&si, 0, sizeof(si));
12132       res = ioctl(pri->fds[i], DAHDI_SPANSTAT, &si);
12133       if (res) {
12134          dahdi_close_pri_fd(pri, i);
12135          ast_log(LOG_ERROR, "Unable to get span state for D-channel %d (%s)\n", x, strerror(errno));
12136       }
12137       if (!si.alarms)
12138          pri->dchanavail[i] |= DCHAN_NOTINALARM;
12139       else
12140          pri->dchanavail[i] &= ~DCHAN_NOTINALARM;
12141       memset(&bi, 0, sizeof(bi));
12142       bi.txbufpolicy = DAHDI_POLICY_IMMEDIATE;
12143       bi.rxbufpolicy = DAHDI_POLICY_IMMEDIATE;
12144       bi.numbufs = 32;
12145       bi.bufsize = 1024;
12146       if (ioctl(pri->fds[i], DAHDI_SET_BUFINFO, &bi)) {
12147          ast_log(LOG_ERROR, "Unable to set appropriate buffering on channel %d: %s\n", x, strerror(errno));
12148          dahdi_close_pri_fd(pri, i);
12149          return -1;
12150       }
12151       switch (pri->sig) {
12152          case SIG_BRI:
12153             pri->dchans[i] = pri_new_bri(pri->fds[i], 1, pri->nodetype, pri->switchtype);
12154             break;
12155          case SIG_BRI_PTMP:
12156             pri->dchans[i] = pri_new_bri(pri->fds[i], 0, pri->nodetype, pri->switchtype);
12157             break;
12158          default:
12159             pri->dchans[i] = pri_new(pri->fds[i], pri->nodetype, pri->switchtype);
12160       }
12161       /* Force overlap dial if we're doing GR-303! */
12162       if (pri->switchtype == PRI_SWITCH_GR303_TMC)
12163          pri->overlapdial |= DAHDI_OVERLAPDIAL_BOTH;
12164       pri_set_overlapdial(pri->dchans[i],(pri->overlapdial & DAHDI_OVERLAPDIAL_OUTGOING)?1:0);
12165 #ifdef HAVE_PRI_INBANDDISCONNECT
12166       pri_set_inbanddisconnect(pri->dchans[i], pri->inbanddisconnect);
12167 #endif
12168       /* Enslave to master if appropriate */
12169       if (i)
12170          pri_enslave(pri->dchans[0], pri->dchans[i]);
12171       if (!pri->dchans[i]) {
12172          dahdi_close_pri_fd(pri, i);
12173          ast_log(LOG_ERROR, "Unable to create PRI structure\n");
12174          return -1;
12175       }
12176       pri_set_debug(pri->dchans[i], DEFAULT_PRI_DEBUG);
12177       pri_set_nsf(pri->dchans[i], pri->nsf);
12178 #ifdef PRI_GETSET_TIMERS
12179       for (x = 0; x < PRI_MAX_TIMERS; x++) {
12180          if (pritimers[x] != 0)
12181             pri_set_timer(pri->dchans[i], x, pritimers[x]);
12182       }
12183 #endif
12184    }
12185    /* Assume primary is the one we use */
12186    pri->pri = pri->dchans[0];
12187    pri->resetpos = -1;
12188    if (ast_pthread_create_background(&pri->master, NULL, pri_dchannel, pri)) {
12189       for (i = 0; i < NUM_DCHANS; i++) {
12190          if (!pri->dchannels[i])
12191             break;
12192          dahdi_close_pri_fd(pri, i);
12193       }
12194       ast_log(LOG_ERROR, "Unable to spawn D-channel: %s\n", strerror(errno));
12195       return -1;
12196    }
12197    return 0;
12198 }
12199 
12200 static char *complete_span_helper(const char *line, const char *word, int pos, int state, int rpos)
12201 {
12202    int which, span;
12203    char *ret = NULL;
12204 
12205    if (pos != rpos)
12206       return ret;
12207 
12208    for (which = span = 0; span < NUM_SPANS; span++) {
12209       if (pris[span].pri && ++which > state) {
12210          if (asprintf(&ret, "%d", span + 1) < 0) { /* user indexes start from 1 */
12211             ast_log(LOG_WARNING, "asprintf() failed: %s\n", strerror(errno));
12212          }
12213          break;
12214       }
12215    }
12216    return ret;
12217 }
12218 
12219 static char *complete_span_4(const char *line, const char *word, int pos, int state)
12220 {
12221    return complete_span_helper(line,word,pos,state,3);
12222 }
12223 
12224 static char *complete_span_5(const char *line, const char *word, int pos, int state)
12225 {
12226    return complete_span_helper(line,word,pos,state,4);
12227 }
12228 
12229 static char *handle_pri_unset_debug_file(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
12230 {
12231    switch (cmd) {
12232    case CLI_INIT:
12233       e->command = "pri unset debug file";
12234       e->usage = "Usage: pri unset debug file\n"
12235             "       Stop sending debug output to the previously \n"
12236                  "       specified file\n";
12237       return NULL;
12238    case CLI_GENERATE:
12239       return NULL;   
12240    }
12241    /* Assume it is unset */
12242    ast_mutex_lock(&pridebugfdlock);
12243    close(pridebugfd);
12244    pridebugfd = -1;
12245    ast_cli(a->fd, "PRI debug output to file disabled\n");
12246    ast_mutex_unlock(&pridebugfdlock);
12247    return CLI_SUCCESS;
12248 }
12249 
12250 static char *handle_pri_set_debug_file(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
12251 {
12252    int myfd;
12253    switch (cmd) {
12254    case CLI_INIT:
12255       e->command = "pri set debug file";
12256       e->usage = "Usage: pri set debug file [output-file]\n"
12257             "       Sends PRI debug output to the specified output file\n";
12258       return NULL;
12259    case CLI_GENERATE:
12260       return NULL;   
12261    }
12262    if (a->argc < 5)
12263       return CLI_SHOWUSAGE;
12264 
12265    if (ast_strlen_zero(a->argv[4]))
12266       return CLI_SHOWUSAGE;
12267 
12268    myfd = open(a->argv[4], O_CREAT|O_WRONLY, AST_FILE_MODE);
12269    if (myfd < 0) {
12270       ast_cli(a->fd, "Unable to open '%s' for writing\n", a->argv[4]);
12271       return CLI_SUCCESS;
12272    }
12273 
12274    ast_mutex_lock(&pridebugfdlock);
12275 
12276    if (pridebugfd >= 0)
12277       close(pridebugfd);
12278 
12279    pridebugfd = myfd;
12280    ast_copy_string(pridebugfilename,a->argv[4],sizeof(pridebugfilename));
12281    ast_mutex_unlock(&pridebugfdlock);
12282    ast_cli(a->fd, "PRI debug output will be sent to '%s'\n", a->argv[4]);
12283    return CLI_SUCCESS;
12284 }
12285 
12286 static char *handle_pri_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
12287 {
12288    int span;
12289    int x;
12290    switch (cmd) {
12291    case CLI_INIT: 
12292       e->command = "pri debug span";
12293       e->usage = 
12294          "Usage: pri debug span <span>\n"
12295          "       Enables debugging on a given PRI span\n";
12296       return NULL;
12297    case CLI_GENERATE:   
12298       return complete_span_4(a->line, a->word, a->pos, a->n);
12299    }
12300    if (a->argc < 4) {
12301       return CLI_SHOWUSAGE;
12302    }
12303    span = atoi(a->argv[3]);
12304    if ((span < 1) || (span > NUM_SPANS)) {
12305       ast_cli(a->fd, "Invalid span %s.  Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
12306       return CLI_SUCCESS;
12307    }
12308    if (!pris[span-1].pri) {
12309       ast_cli(a->fd, "No PRI running on span %d\n", span);
12310       return CLI_SUCCESS;
12311    }
12312    for (x = 0; x < NUM_DCHANS; x++) {
12313       if (pris[span-1].dchans[x])
12314          pri_set_debug(pris[span-1].dchans[x], PRI_DEBUG_APDU |
12315                                                PRI_DEBUG_Q931_DUMP | PRI_DEBUG_Q931_STATE |
12316                                                PRI_DEBUG_Q921_STATE);
12317    }
12318    ast_cli(a->fd, "Enabled debugging on span %d\n", span);
12319    return CLI_SUCCESS;
12320 }
12321 
12322 
12323 
12324 static char *handle_pri_no_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
12325 {
12326    int span;
12327    int x;
12328    switch (cmd) {
12329    case CLI_INIT:
12330       e->command = "pri no debug span";
12331       e->usage = 
12332          "Usage: pri no debug span <span>\n"
12333          "       Disables debugging on a given PRI span\n";
12334       return NULL;
12335    case CLI_GENERATE:
12336       return complete_span_5(a->line, a->word, a->pos, a->n);
12337    }
12338    if (a->argc < 5)
12339       return CLI_SHOWUSAGE;
12340 
12341    span = atoi(a->argv[4]);
12342    if ((span < 1) || (span > NUM_SPANS)) {
12343       ast_cli(a->fd, "Invalid span %s.  Should be a number %d to %d\n", a->argv[4], 1, NUM_SPANS);
12344       return CLI_SUCCESS;
12345    }
12346    if (!pris[span-1].pri) {
12347       ast_cli(a->fd, "No PRI running on span %d\n", span);
12348       return CLI_SUCCESS;
12349    }
12350    for (x = 0; x < NUM_DCHANS; x++) {
12351       if (pris[span-1].dchans[x])
12352          pri_set_debug(pris[span-1].dchans[x], 0);
12353    }
12354    ast_cli(a->fd, "Disabled debugging on span %d\n", span);
12355    return CLI_SUCCESS;
12356 }
12357 
12358 static char *handle_pri_really_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
12359 {
12360    int span;
12361    int x;
12362    switch (cmd) {
12363    case CLI_INIT:
12364       e->command = "pri intensive debug span";
12365       e->usage = 
12366          "Usage: pri intensive debug span <span>\n"
12367          "       Enables debugging down to the Q.921 level\n";
12368       return NULL;
12369    case CLI_GENERATE:
12370       return complete_span_5(a->line, a->word, a->pos, a->n);
12371    }
12372 
12373    if (a->argc < 5)
12374       return CLI_SHOWUSAGE;
12375    span = atoi(a->argv[4]);
12376    if ((span < 1) || (span > NUM_SPANS)) {
12377       ast_cli(a->fd, "Invalid span %s.  Should be a number %d to %d\n", a->argv[4], 1, NUM_SPANS);
12378       return CLI_SUCCESS;
12379    }
12380    if (!pris[span-1].pri) {
12381       ast_cli(a->fd, "No PRI running on span %d\n", span);
12382       return CLI_SUCCESS;
12383    }
12384    for (x = 0; x < NUM_DCHANS; x++) {
12385       if (pris[span-1].dchans[x])
12386          pri_set_debug(pris[span-1].dchans[x], PRI_DEBUG_APDU |
12387                                                PRI_DEBUG_Q931_DUMP | PRI_DEBUG_Q931_STATE |
12388                                                PRI_DEBUG_Q921_RAW | PRI_DEBUG_Q921_DUMP | PRI_DEBUG_Q921_STATE);
12389    }
12390    ast_cli(a->fd, "Enabled EXTENSIVE debugging on span %d\n", span);
12391    return CLI_SUCCESS;
12392 }
12393 
12394 static void build_status(char *s, size_t len, int status, int active)
12395 {
12396    if (!s || len < 1) {
12397       return;
12398    }
12399    s[0] = '\0';
12400    if (status & DCHAN_PROVISIONED)
12401       strncat(s, "Provisioned, ", len - strlen(s) - 1);
12402    if (!(status & DCHAN_NOTINALARM))
12403       strncat(s, "In Alarm, ", len - strlen(s) - 1);
12404    if (status & DCHAN_UP)
12405       strncat(s, "Up", len - strlen(s) - 1);
12406    else
12407       strncat(s, "Down", len - strlen(s) - 1);
12408    if (active)
12409       strncat(s, ", Active", len - strlen(s) - 1);
12410    else
12411       strncat(s, ", Standby", len - strlen(s) - 1);
12412    s[len - 1] = '\0';
12413 }
12414 
12415 static char *handle_pri_show_spans(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
12416 {
12417    int span;
12418    int x;
12419    char status[256];
12420 
12421    switch (cmd) {
12422    case CLI_INIT:
12423       e->command = "pri show spans";
12424       e->usage = 
12425          "Usage: pri show spans\n"
12426          "       Displays PRI Information\n";
12427       return NULL;
12428    case CLI_GENERATE:
12429       return NULL;   
12430    }
12431 
12432    if (a->argc != 3)
12433       return CLI_SHOWUSAGE;
12434 
12435    for (span = 0; span < NUM_SPANS; span++) {
12436       if (pris[span].pri) {
12437          for (x = 0; x < NUM_DCHANS; x++) {
12438             if (pris[span].dchannels[x]) {
12439                build_status(status, sizeof(status), pris[span].dchanavail[x], pris[span].dchans[x] == pris[span].pri);
12440                ast_cli(a->fd, "PRI span %d/%d: %s\n", span + 1, x, status);
12441             }
12442          }
12443       }
12444    }
12445    return CLI_SUCCESS;
12446 }
12447 
12448 static char *handle_pri_show_span(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
12449 {
12450    int span;
12451    int x;
12452    char status[256];
12453    switch (cmd) {
12454    case CLI_INIT: 
12455       e->command = "pri show span";
12456       e->usage = 
12457          "Usage: pri show span <span>\n"
12458          "       Displays PRI Information on a given PRI span\n";
12459       return NULL;
12460    case CLI_GENERATE:
12461       return complete_span_4(a->line, a->word, a->pos, a->n);
12462    }
12463 
12464    if (a->argc < 4)
12465       return CLI_SHOWUSAGE;
12466    span = atoi(a->argv[3]);
12467    if ((span < 1) || (span > NUM_SPANS)) {
12468       ast_cli(a->fd, "Invalid span '%s'.  Should be a number from %d to %d\n", a->argv[3], 1, NUM_SPANS);
12469       return CLI_SUCCESS;
12470    }
12471    if (!pris[span-1].pri) {
12472       ast_cli(a->fd, "No PRI running on span %d\n", span);
12473       return CLI_SUCCESS;
12474    }
12475    for (x = 0; x < NUM_DCHANS; x++) {
12476       if (pris[span-1].dchannels[x]) {
12477 #ifdef PRI_DUMP_INFO_STR
12478          char *info_str = NULL;
12479 #endif
12480          ast_cli(a->fd, "%s D-channel: %d\n", pri_order(x), pris[span-1].dchannels[x]);
12481          build_status(status, sizeof(status), pris[span-1].dchanavail[x], pris[span-1].dchans[x] == pris[span-1].pri);
12482          ast_cli(a->fd, "Status: %s\n", status);
12483 #ifdef PRI_DUMP_INFO_STR
12484          info_str = pri_dump_info_str(pris[span-1].pri);
12485          if (info_str) {
12486             ast_cli(a->fd, "%s", info_str);
12487             ast_free(info_str);
12488          }
12489 #else
12490          pri_dump_info(pris[span-1].pri);
12491 #endif
12492          ast_cli(a->fd, "Overlap Recv: %s\n\n", (pris[span-1].overlapdial & DAHDI_OVERLAPDIAL_INCOMING)?"Yes":"No");
12493       }
12494    }
12495    return CLI_SUCCESS;
12496 }
12497 
12498 static char *handle_pri_show_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
12499 {
12500    int x;
12501    int span;
12502    int count=0;
12503    int debug=0;
12504 
12505    switch (cmd) {
12506    case CLI_INIT: 
12507       e->command = "pri show debug";
12508       e->usage = 
12509          "Usage: pri show debug\n"
12510          "  Show the debug state of pri spans\n";
12511       return NULL;
12512    case CLI_GENERATE:
12513       return NULL;   
12514    }
12515 
12516    for (span = 0; span < NUM_SPANS; span++) {
12517            if (pris[span].pri) {
12518          for (x = 0; x < NUM_DCHANS; x++) {
12519             debug = 0;
12520                if (pris[span].dchans[x]) {
12521                   debug = pri_get_debug(pris[span].dchans[x]);
12522                ast_cli(a->fd, "Span %d: Debug: %s\tIntense: %s\n", span+1, (debug&PRI_DEBUG_Q931_STATE)? "Yes" : "No" ,(debug&PRI_DEBUG_Q921_RAW)? "Yes" : "No" );
12523                count++;
12524             }
12525          }
12526       }
12527 
12528    }
12529    ast_mutex_lock(&pridebugfdlock);
12530    if (pridebugfd >= 0) 
12531       ast_cli(a->fd, "Logging PRI debug to file %s\n", pridebugfilename);
12532    ast_mutex_unlock(&pridebugfdlock);
12533        
12534    if (!count) 
12535       ast_cli(a->fd, "No debug set or no PRI running\n");
12536    return CLI_SUCCESS;
12537 }
12538 
12539 static char *handle_pri_version(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
12540 {
12541    switch (cmd) {
12542    case CLI_INIT:
12543       e->command = "pri show version";
12544       e->usage = 
12545          "Usage: pri show version\n"
12546          "Show libpri version information\n";
12547       return NULL;
12548    case CLI_GENERATE:
12549       return NULL;
12550    }
12551 
12552    ast_cli(a->fd, "libpri version: %s\n", pri_get_version());
12553 
12554    return CLI_SUCCESS;
12555 }
12556 
12557 static struct ast_cli_entry dahdi_pri_cli[] = {
12558    AST_CLI_DEFINE(handle_pri_debug, "Enables PRI debugging on a span"),
12559    AST_CLI_DEFINE(handle_pri_no_debug, "Disables PRI debugging on a span"),
12560    AST_CLI_DEFINE(handle_pri_really_debug, "Enables REALLY INTENSE PRI debugging"),
12561    AST_CLI_DEFINE(handle_pri_show_spans, "Displays PRI Information"),
12562    AST_CLI_DEFINE(handle_pri_show_span, "Displays PRI Information"),
12563    AST_CLI_DEFINE(handle_pri_show_debug, "Displays current PRI debug settings"),
12564    AST_CLI_DEFINE(handle_pri_set_debug_file, "Sends PRI debug output to the specified file"),
12565    AST_CLI_DEFINE(handle_pri_unset_debug_file, "Ends PRI debug output to file"),
12566    AST_CLI_DEFINE(handle_pri_version, "Displays libpri version"),
12567 };
12568 
12569 #endif /* HAVE_PRI */
12570 
12571 static char *dahdi_destroy_channel(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
12572 {
12573    int channel;
12574    int ret;
12575    switch (cmd) {
12576    case CLI_INIT:
12577       e->command = "dahdi destroy channel";
12578       e->usage = 
12579          "Usage: dahdi destroy channel <chan num>\n"
12580          "  DON'T USE THIS UNLESS YOU KNOW WHAT YOU ARE DOING.  Immediately removes a given channel, whether it is in use or not\n";
12581       return NULL;
12582    case CLI_GENERATE:
12583       return NULL;   
12584    }
12585    if (a->argc != 4)
12586       return CLI_SHOWUSAGE;
12587    
12588    channel = atoi(a->argv[3]);
12589    ret = dahdi_destroy_channel_bynum(channel);
12590    return ( RESULT_SUCCESS == ret ) ? CLI_SUCCESS : CLI_FAILURE;
12591 }
12592 
12593 static void dahdi_softhangup_all(void)
12594 {
12595    struct dahdi_pvt *p;
12596 retry:
12597    ast_mutex_lock(&iflock);
12598     for (p = iflist; p; p = p->next) {
12599       ast_mutex_lock(&p->lock);
12600         if (p->owner && !p->restartpending) {
12601          if (ast_channel_trylock(p->owner)) {
12602             if (option_debug > 2)
12603                ast_verbose("Avoiding deadlock\n");
12604             /* Avoid deadlock since you're not supposed to lock iflock or pvt before a channel */
12605             ast_mutex_unlock(&p->lock);
12606             ast_mutex_unlock(&iflock);
12607             goto retry;
12608          }
12609          if (option_debug > 2)
12610             ast_verbose("Softhanging up on %s\n", p->owner->name);
12611          ast_softhangup_nolock(p->owner, AST_SOFTHANGUP_EXPLICIT);
12612          p->restartpending = 1;
12613          num_restart_pending++;
12614          ast_channel_unlock(p->owner);
12615       }
12616       ast_mutex_unlock(&p->lock);
12617     }
12618    ast_mutex_unlock(&iflock);
12619 }
12620 
12621 static int setup_dahdi(int reload);
12622 static int dahdi_restart(void)
12623 {
12624 #if defined(HAVE_PRI) || defined(HAVE_SS7)
12625    int i, j;
12626 #endif
12627    int cancel_code;
12628    struct dahdi_pvt *p;
12629 
12630    ast_mutex_lock(&restart_lock);
12631 
12632    ast_verb(1, "Destroying channels and reloading DAHDI configuration.\n");
12633    dahdi_softhangup_all();
12634    ast_verb(4, "Initial softhangup of all DAHDI channels complete.\n");
12635 
12636 #if defined(HAVE_PRI)
12637    for (i = 0; i < NUM_SPANS; i++) {
12638       if (pris[i].master && (pris[i].master != AST_PTHREADT_NULL)) {
12639          cancel_code = pthread_cancel(pris[i].master);
12640          pthread_kill(pris[i].master, SIGURG);
12641          ast_debug(4, "Waiting to join thread of span %d with pid=%p, cancel_code=%d\n", i, (void *) pris[i].master, cancel_code);
12642          pthread_join(pris[i].master, NULL);
12643          ast_debug(4, "Joined thread of span %d\n", i);
12644       }
12645    }
12646 #endif
12647 
12648 #if defined(HAVE_SS7)
12649    for (i = 0; i < NUM_SPANS; i++) {
12650       if (linksets[i].master && (linksets[i].master != AST_PTHREADT_NULL)) {
12651          cancel_code = pthread_cancel(linksets[i].master);
12652          pthread_kill(linksets[i].master, SIGURG);
12653          ast_debug(4, "Waiting to join thread of span %d with pid=%p, cancel_code=%d\n", i, (void *) linksets[i].master, cancel_code);
12654          pthread_join(linksets[i].master, NULL);
12655          ast_debug(4, "Joined thread of span %d\n", i);
12656       }
12657     }
12658 #endif
12659 
12660    ast_mutex_lock(&monlock);
12661    if (monitor_thread && (monitor_thread != AST_PTHREADT_STOP) && (monitor_thread != AST_PTHREADT_NULL)) {
12662       cancel_code = pthread_cancel(monitor_thread);
12663       pthread_kill(monitor_thread, SIGURG);
12664       ast_debug(4, "Waiting to join monitor thread with pid=%p, cancel_code=%d\n", (void *) monitor_thread, cancel_code);
12665       pthread_join(monitor_thread, NULL);
12666       ast_debug(4, "Joined monitor thread\n");
12667    }
12668    monitor_thread = AST_PTHREADT_NULL; /* prepare to restart thread in setup_dahdi once channels are reconfigured */
12669 
12670    ast_mutex_lock(&mwi_thread_lock);
12671    while (mwi_thread_count > 0) {
12672       ast_debug(3, "Waiting on %d mwi_send_thread(s) to finish\n", mwi_thread_count);
12673       ast_cond_wait(&mwi_thread_complete, &mwi_thread_lock);
12674    }
12675    ast_mutex_unlock(&mwi_thread_lock);
12676    ast_mutex_lock(&ss_thread_lock);
12677    while (ss_thread_count > 0) { /* let ss_threads finish and run dahdi_hangup before dahvi_pvts are destroyed */
12678       int x = DAHDI_FLASH;
12679       ast_debug(3, "Waiting on %d ss_thread(s) to finish\n", ss_thread_count);
12680 
12681       for (p = iflist; p; p = p->next) {
12682          if (p->owner)
12683             ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x); /* important to create an event for dahdi_wait_event to register so that all ss_threads terminate */      
12684          }
12685          ast_cond_wait(&ss_thread_complete, &ss_thread_lock);
12686       }
12687 
12688    /* ensure any created channels before monitor threads were stopped are hungup */
12689    dahdi_softhangup_all();
12690    ast_verb(4, "Final softhangup of all DAHDI channels complete.\n");
12691    destroy_all_channels();
12692    ast_debug(1, "Channels destroyed. Now re-reading config. %d active channels remaining.\n", ast_active_channels());
12693 
12694    ast_mutex_unlock(&monlock);
12695 
12696 #ifdef HAVE_PRI
12697    for (i = 0; i < NUM_SPANS; i++) {
12698       for (j = 0; j < NUM_DCHANS; j++)
12699          dahdi_close_pri_fd(&(pris[i]), j);
12700    }
12701 
12702    memset(pris, 0, sizeof(pris));
12703    for (i = 0; i < NUM_SPANS; i++) {
12704       ast_mutex_init(&pris[i].lock);
12705       pris[i].offset = -1;
12706       pris[i].master = AST_PTHREADT_NULL;
12707       for (j = 0; j < NUM_DCHANS; j++)
12708          pris[i].fds[j] = -1;
12709       }
12710    pri_set_error(dahdi_pri_error);
12711    pri_set_message(dahdi_pri_message);
12712 #endif
12713 #ifdef HAVE_SS7
12714    for (i = 0; i < NUM_SPANS; i++) {
12715       for (j = 0; j < NUM_DCHANS; j++)
12716          dahdi_close_ss7_fd(&(linksets[i]), j);
12717    }
12718 
12719    memset(linksets, 0, sizeof(linksets));
12720    for (i = 0; i < NUM_SPANS; i++) {
12721       ast_mutex_init(&linksets[i].lock);
12722       linksets[i].master = AST_PTHREADT_NULL;
12723       for (j = 0; j < NUM_DCHANS; j++)
12724          linksets[i].fds[j] = -1;
12725    }
12726    ss7_set_error(dahdi_ss7_error);
12727    ss7_set_message(dahdi_ss7_message);
12728 #endif
12729 
12730    if (setup_dahdi(2) != 0) {
12731       ast_log(LOG_WARNING, "Reload channels from dahdi config failed!\n");
12732       ast_mutex_unlock(&ss_thread_lock);
12733       return 1;
12734    }
12735    ast_mutex_unlock(&ss_thread_lock);
12736    ast_mutex_unlock(&restart_lock);
12737    return 0;
12738 }
12739 
12740 static char *dahdi_restart_cmd(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
12741 {
12742    switch (cmd) {
12743    case CLI_INIT:
12744       e->command = "dahdi restart";
12745       e->usage = 
12746          "Usage: dahdi restart\n"
12747          "  Restarts the DAHDI channels: destroys them all and then\n"
12748          "  re-reads them from chan_dahdi.conf.\n"
12749          "  Note that this will STOP any running CALL on DAHDI channels.\n"
12750          "";
12751       return NULL;
12752    case CLI_GENERATE:
12753       return NULL;
12754    }
12755    if (a->argc != 2)
12756       return CLI_SHOWUSAGE;
12757 
12758    if (dahdi_restart() != 0)
12759       return CLI_FAILURE;
12760    return CLI_SUCCESS;
12761 }
12762 
12763 static int action_dahdirestart(struct mansession *s, const struct message *m)
12764 {
12765    if (dahdi_restart() != 0) {
12766       astman_send_error(s, m, "Failed rereading DAHDI configuration");
12767       return 1;
12768    }
12769    astman_send_ack(s, m, "DAHDIRestart: Success");
12770    return 0;
12771 }
12772 
12773 static char *dahdi_show_channels(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
12774 {
12775 #define FORMAT "%7s %-10.10s %-15.15s %-10.10s %-20.20s %-10.10s %-10.10s\n"
12776 #define FORMAT2 "%7s %-10.10s %-15.15s %-10.10s %-20.20s %-10.10s %-10.10s\n"
12777    unsigned int targetnum = 0;
12778    int filtertype = 0;
12779    struct dahdi_pvt *tmp = NULL;
12780    char tmps[20] = "";
12781    char statestr[20] = "";
12782    char blockstr[20] = "";
12783    ast_mutex_t *lock;
12784    struct dahdi_pvt *start;
12785 #ifdef HAVE_PRI
12786    int trunkgroup;
12787    struct dahdi_pri *pri = NULL;
12788    int x;
12789 #endif
12790    switch (cmd) {
12791    case CLI_INIT:
12792       e->command = "dahdi show channels [trunkgroup|group|context]";
12793       e->usage = 
12794          "Usage: dahdi show channels [ trunkgroup <trunkgroup> | group <group> | context <context> ]\n"
12795          "  Shows a list of available channels with optional filtering\n"
12796          "  <group> must be a number between 0 and 63\n";
12797       return NULL;
12798    case CLI_GENERATE:
12799       return NULL;   
12800    }
12801 
12802    lock = &iflock;
12803    start = iflist;
12804 
12805    /* syntax: dahdi show channels [ group <group> | context <context> | trunkgroup <trunkgroup> ] */
12806 
12807    if (!((a->argc == 3) || (a->argc == 5)))
12808       return CLI_SHOWUSAGE;
12809 
12810    if (a->argc == 5) {
12811 #ifdef HAVE_PRI
12812       if (!strcasecmp(a->argv[3], "trunkgroup")) {
12813          /* this option requires no special handling, so leave filtertype to zero */
12814          if ((trunkgroup = atoi(a->argv[4])) < 1)
12815             return CLI_SHOWUSAGE;
12816          for (x = 0; x < NUM_SPANS; x++) {
12817             if (pris[x].trunkgroup == trunkgroup) {
12818                pri = pris + x;
12819                break;
12820             }
12821          }
12822          if (pri) {
12823             start = pri->crvs;
12824             lock = &pri->lock;
12825          } else {
12826             ast_cli(a->fd, "No such trunk group %d\n", trunkgroup);
12827             return CLI_FAILURE;
12828          }
12829       } else
12830 #endif   
12831       if (!strcasecmp(a->argv[3], "group")) {
12832          targetnum = atoi(a->argv[4]);
12833          if ((targetnum < 0) || (targetnum > 63))
12834             return CLI_SHOWUSAGE;
12835          targetnum = 1 << targetnum;
12836          filtertype = 1;
12837       } else if (!strcasecmp(a->argv[3], "context")) {
12838          filtertype = 2;
12839       }
12840    }
12841 
12842    ast_mutex_lock(lock);
12843 #ifdef HAVE_PRI
12844    ast_cli(a->fd, FORMAT2, pri ? "CRV" : "Chan", "Extension", "Context", "Language", "MOH Interpret", "Blocked", "State");
12845 #else
12846    ast_cli(a->fd, FORMAT2, "Chan", "Extension", "Context", "Language", "MOH Interpret", "Blocked", "State");
12847 #endif   
12848    
12849    tmp = start;
12850    while (tmp) {
12851       if (filtertype) {
12852          switch(filtertype) {
12853          case 1: /* dahdi show channels group <group> */
12854             if (!(tmp->group & targetnum)) {
12855                tmp = tmp->next;
12856                continue;
12857             }
12858             break;
12859          case 2: /* dahdi show channels context <context> */
12860             if (strcasecmp(tmp->context, a->argv[4])) {
12861                tmp = tmp->next;
12862                continue;
12863             }
12864             break;
12865          default:
12866             ;
12867          }
12868       }
12869       if (tmp->channel > 0) {
12870          snprintf(tmps, sizeof(tmps), "%d", tmp->channel);
12871       } else
12872          ast_copy_string(tmps, "pseudo", sizeof(tmps));
12873 
12874       if (tmp->locallyblocked)
12875          blockstr[0] = 'L';
12876       else
12877          blockstr[0] = ' ';
12878 
12879       if (tmp->remotelyblocked)
12880          blockstr[1] = 'R';
12881       else
12882          blockstr[1] = ' ';
12883 
12884       blockstr[2] = '\0';
12885 
12886       snprintf(statestr, sizeof(statestr), "%s", "In Service");
12887 
12888       ast_cli(a->fd, FORMAT, tmps, tmp->exten, tmp->context, tmp->language, tmp->mohinterpret, blockstr, statestr);
12889       tmp = tmp->next;
12890    }
12891    ast_mutex_unlock(lock);
12892    return CLI_SUCCESS;
12893 #undef FORMAT
12894 #undef FORMAT2
12895 }
12896 
12897 static char *dahdi_show_channel(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
12898 {
12899    int channel;
12900    struct dahdi_pvt *tmp = NULL;
12901    struct dahdi_confinfo ci;
12902    struct dahdi_params ps;
12903    int x;
12904    ast_mutex_t *lock;
12905    struct dahdi_pvt *start;
12906 #ifdef HAVE_PRI
12907    char *c;
12908    int trunkgroup;
12909    struct dahdi_pri *pri=NULL;
12910 #endif
12911    switch (cmd) {
12912    case CLI_INIT:
12913       e->command = "dahdi show channel";
12914       e->usage = 
12915          "Usage: dahdi show channel <chan num>\n"
12916          "  Detailed information about a given channel\n";
12917       return NULL;
12918    case CLI_GENERATE:
12919       return NULL;   
12920    }
12921 
12922    lock = &iflock;
12923    start = iflist;
12924 
12925    if (a->argc != 4)
12926       return CLI_SHOWUSAGE;
12927 #ifdef HAVE_PRI
12928    if ((c = strchr(a->argv[3], ':'))) {
12929       if (sscanf(a->argv[3], "%30d:%30d", &trunkgroup, &channel) != 2)
12930          return CLI_SHOWUSAGE;
12931       if ((trunkgroup < 1) || (channel < 1))
12932          return CLI_SHOWUSAGE;
12933       for (x = 0; x < NUM_SPANS; x++) {
12934          if (pris[x].trunkgroup == trunkgroup) {
12935             pri = pris + x;
12936             break;
12937          }
12938       }
12939       if (pri) {
12940          start = pri->crvs;
12941          lock = &pri->lock;
12942       } else {
12943          ast_cli(a->fd, "No such trunk group %d\n", trunkgroup);
12944          return CLI_FAILURE;
12945       }
12946    } else
12947 #endif
12948       channel = atoi(a->argv[3]);
12949 
12950    ast_mutex_lock(lock);
12951    tmp = start;
12952    while (tmp) {
12953       if (tmp->channel == channel) {
12954 #ifdef HAVE_PRI
12955          if (pri) 
12956             ast_cli(a->fd, "Trunk/CRV: %d/%d\n", trunkgroup, tmp->channel);
12957          else
12958 #endif         
12959          ast_cli(a->fd, "Channel: %d\n", tmp->channel);
12960          ast_cli(a->fd, "File Descriptor: %d\n", tmp->subs[SUB_REAL].dfd);
12961          ast_cli(a->fd, "Span: %d\n", tmp->span);
12962          ast_cli(a->fd, "Extension: %s\n", tmp->exten);
12963          ast_cli(a->fd, "Dialing: %s\n", tmp->dialing ? "yes" : "no");
12964          ast_cli(a->fd, "Context: %s\n", tmp->context);
12965          ast_cli(a->fd, "Caller ID: %s\n", tmp->cid_num);
12966          ast_cli(a->fd, "Calling TON: %d\n", tmp->cid_ton);
12967          ast_cli(a->fd, "Caller ID name: %s\n", tmp->cid_name);
12968          ast_cli(a->fd, "Mailbox: %s\n", S_OR(tmp->mailbox, "none"));
12969          if (tmp->vars) {
12970             struct ast_variable *v;
12971             ast_cli(a->fd, "Variables:\n");
12972             for (v = tmp->vars ; v ; v = v->next)
12973                ast_cli(a->fd, "       %s = %s\n", v->name, v->value);
12974          }
12975          ast_cli(a->fd, "Destroy: %d\n", tmp->destroy);
12976          ast_cli(a->fd, "InAlarm: %d\n", tmp->inalarm);
12977          ast_cli(a->fd, "Signalling Type: %s\n", sig2str(tmp->sig));
12978          ast_cli(a->fd, "Radio: %d\n", tmp->radio);
12979          ast_cli(a->fd, "Owner: %s\n", tmp->owner ? tmp->owner->name : "<None>");
12980          ast_cli(a->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)" : "");
12981          ast_cli(a->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)" : "");
12982          ast_cli(a->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)" : "");
12983          ast_cli(a->fd, "Confno: %d\n", tmp->confno);
12984          ast_cli(a->fd, "Propagated Conference: %d\n", tmp->propconfno);
12985          ast_cli(a->fd, "Real in conference: %d\n", tmp->inconference);
12986          ast_cli(a->fd, "DSP: %s\n", tmp->dsp ? "yes" : "no");
12987          ast_cli(a->fd, "Busy Detection: %s\n", tmp->busydetect ? "yes" : "no");
12988          if (tmp->busydetect) {
12989 #if defined(BUSYDETECT_TONEONLY)
12990             ast_cli(a->fd, "    Busy Detector Helper: BUSYDETECT_TONEONLY\n");
12991 #elif defined(BUSYDETECT_COMPARE_TONE_AND_SILENCE)
12992             ast_cli(a->fd, "    Busy Detector Helper: BUSYDETECT_COMPARE_TONE_AND_SILENCE\n");
12993 #endif
12994 #ifdef BUSYDETECT_DEBUG
12995             ast_cli(a->fd, "    Busy Detector Debug: Enabled\n");
12996 #endif
12997             ast_cli(a->fd, "    Busy Count: %d\n", tmp->busycount);
12998             ast_cli(a->fd, "    Busy Pattern: %d,%d\n", tmp->busytonelength, tmp->busyquietlength);
12999          }
13000          ast_cli(a->fd, "TDD: %s\n", tmp->tdd ? "yes" : "no");
13001          ast_cli(a->fd, "Relax DTMF: %s\n", tmp->dtmfrelax ? "yes" : "no");
13002          ast_cli(a->fd, "Dialing/CallwaitCAS: %d/%d\n", tmp->dialing, tmp->callwaitcas);
13003          ast_cli(a->fd, "Default law: %s\n", tmp->law == DAHDI_LAW_MULAW ? "ulaw" : tmp->law == DAHDI_LAW_ALAW ? "alaw" : "unknown");
13004          ast_cli(a->fd, "Fax Handled: %s\n", tmp->faxhandled ? "yes" : "no");
13005          ast_cli(a->fd, "Pulse phone: %s\n", tmp->pulsedial ? "yes" : "no");
13006          ast_cli(a->fd, "DND: %s\n", tmp->dnd ? "yes" : "no");
13007          ast_cli(a->fd, "Echo Cancellation:\n");
13008 
13009          if (tmp->echocancel.head.tap_length) {
13010             ast_cli(a->fd, "\t%d taps\n", tmp->echocancel.head.tap_length);
13011             for (x = 0; x < tmp->echocancel.head.param_count; x++) {
13012                ast_cli(a->fd, "\t\t%s: %ud\n", tmp->echocancel.params[x].name, tmp->echocancel.params[x].value);
13013             }
13014             ast_cli(a->fd, "\t%scurrently %s\n", tmp->echocanbridged ? "" : "(unless TDM bridged) ", tmp->echocanon ? "ON" : "OFF");
13015          } else {
13016             ast_cli(a->fd, "\tnone\n");
13017          }
13018          if (tmp->master)
13019             ast_cli(a->fd, "Master Channel: %d\n", tmp->master->channel);
13020          for (x = 0; x < MAX_SLAVES; x++) {
13021             if (tmp->slaves[x])
13022                ast_cli(a->fd, "Slave Channel: %d\n", tmp->slaves[x]->channel);
13023          }
13024 #ifdef HAVE_SS7
13025          if (tmp->ss7) {
13026             ast_cli(a->fd, "CIC: %d\n", tmp->cic);
13027          }
13028 #endif
13029 #ifdef HAVE_PRI
13030          if (tmp->pri) {
13031             ast_cli(a->fd, "PRI Flags: ");
13032             if (tmp->resetting)
13033                ast_cli(a->fd, "Resetting ");
13034             if (tmp->call)
13035                ast_cli(a->fd, "Call ");
13036             if (tmp->bearer)
13037                ast_cli(a->fd, "Bearer ");
13038             ast_cli(a->fd, "\n");
13039             if (tmp->logicalspan) 
13040                ast_cli(a->fd, "PRI Logical Span: %d\n", tmp->logicalspan);
13041             else
13042                ast_cli(a->fd, "PRI Logical Span: Implicit\n");
13043          }
13044             
13045 #endif
13046          memset(&ci, 0, sizeof(ci));
13047          ps.channo = tmp->channel;
13048          if (tmp->subs[SUB_REAL].dfd > -1) {
13049             memset(&ci, 0, sizeof(ci));
13050             if (!ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GETCONF, &ci)) {
13051                ast_cli(a->fd, "Actual Confinfo: Num/%d, Mode/0x%04x\n", ci.confno, ci.confmode);
13052             }
13053             if (!ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GETCONFMUTE, &x)) {
13054                ast_cli(a->fd, "Actual Confmute: %s\n", x ? "Yes" : "No");
13055             }
13056             memset(&ps, 0, sizeof(ps));
13057             if (ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &ps) < 0) {
13058                ast_log(LOG_WARNING, "Failed to get parameters on channel %d: %s\n", tmp->channel, strerror(errno));
13059             } else {
13060                ast_cli(a->fd, "Hookstate (FXS only): %s\n", ps.rxisoffhook ? "Offhook" : "Onhook");
13061             }
13062          }
13063          if (ISTRUNK(tmp)) {
13064             ast_cli(a->fd, "Call Progress: %s\n", tmp->callprogress ? "yes" : "no");  
13065             if (!ast_strlen_zero(progzone))
13066                ast_cli(a->fd, "Progress Zone: %s\n", progzone);
13067             ast_cli(a->fd, "Busy Detect: %s\n", tmp->busydetect ? "yes" : "no");  
13068             if(tmp->busydetect) {
13069                ast_cli(a->fd, "Busy Count: %d\n", tmp->busycount);
13070                if(tmp->busytonelength > 0) {
13071                   ast_cli(a->fd, "Busy Pattern:\n");
13072                   ast_cli(a->fd, " -- Tone Length: %6d ms\n", tmp->busytonelength);
13073                   if (tmp->busyquietlength > 0) 
13074                      ast_cli(a->fd, " -- Quiet Length: %6d ms\n", tmp->busyquietlength);
13075                   else 
13076                      ast_cli(a->fd, " -- Detect Tone Only\n");
13077                   if(tmp->busyfuzziness > 0)
13078                      ast_cli(a->fd, "Busy Pattern Fuziness: %d\n", tmp->busyfuzziness);
13079                }
13080             }
13081          }
13082          ast_mutex_unlock(lock);
13083          return CLI_SUCCESS;
13084       }
13085       tmp = tmp->next;
13086    }
13087    
13088    ast_cli(a->fd, "Unable to find given channel %d\n", channel);
13089    ast_mutex_unlock(lock);
13090    return CLI_FAILURE;
13091 }
13092 
13093 static char *handle_dahdi_show_cadences(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
13094 {
13095    int i, j;
13096    switch (cmd) {
13097    case CLI_INIT:
13098       e->command = "dahdi show cadences";
13099       e->usage = 
13100          "Usage: dahdi show cadences\n"
13101          "       Shows all cadences currently defined\n";
13102       return NULL;
13103    case CLI_GENERATE:
13104       return NULL;   
13105    }
13106    for (i = 0; i < num_cadence; i++) {
13107       char output[1024];
13108       char tmp[16], tmp2[64];
13109       snprintf(tmp, sizeof(tmp), "r%d: ", i + 1);
13110       term_color(output, tmp, COLOR_GREEN, COLOR_BLACK, sizeof(output));
13111 
13112       for (j = 0; j < 16; j++) {
13113          if (cadences[i].ringcadence[j] == 0)
13114             break;
13115          snprintf(tmp, sizeof(tmp), "%d", cadences[i].ringcadence[j]);
13116          if (cidrings[i] * 2 - 1 == j)
13117             term_color(tmp2, tmp, COLOR_MAGENTA, COLOR_BLACK, sizeof(tmp2) - 1);
13118          else
13119             term_color(tmp2, tmp, COLOR_GREEN, COLOR_BLACK, sizeof(tmp2) - 1);
13120          if (j != 0)
13121             strncat(output, ",", sizeof(output) - strlen(output) - 1);
13122          strncat(output, tmp2, sizeof(output) - strlen(output) - 1);
13123       }
13124       ast_cli(a->fd,"%s\n",output);
13125    }
13126    return CLI_SUCCESS;
13127 }
13128 
13129 /* Based on irqmiss.c */
13130 static char *dahdi_show_status(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) 
13131 {
13132    #define FORMAT "%-40.40s %-7.7s %-6d %-6d %-6d %-3.3s %-4.4s %-8.8s %s\n"
13133    #define FORMAT2 "%-40.40s %-7.7s %-6.6s %-6.6s %-6.6s %-3.3s %-4.4s %-8.8s %s\n"
13134    int span;
13135    int res;
13136    char alarmstr[50];
13137 
13138    int ctl;
13139    struct dahdi_spaninfo s;
13140 
13141    switch (cmd) {
13142    case CLI_INIT:
13143       e->command = "dahdi show status";
13144       e->usage = 
13145          "Usage: dahdi show status\n"
13146          "       Shows a list of DAHDI cards with status\n";
13147       return NULL;
13148    case CLI_GENERATE:
13149       return NULL;   
13150    }
13151    ctl = open("/dev/dahdi/ctl", O_RDWR);
13152    if (ctl < 0) {
13153       ast_cli(a->fd, "No DAHDI found. Unable to open /dev/dahdi/ctl: %s\n", strerror(errno));
13154       return CLI_FAILURE;
13155    }
13156    ast_cli(a->fd, FORMAT2, "Description", "Alarms", "IRQ", "bpviol", "CRC4", "Framing", "Coding", "Options", "LBO");
13157 
13158    for (span = 1; span < DAHDI_MAX_SPANS; ++span) {
13159       s.spanno = span;
13160       res = ioctl(ctl, DAHDI_SPANSTAT, &s);
13161       if (res) {
13162          continue;
13163       }
13164       alarmstr[0] = '\0';
13165       if (s.alarms > 0) {
13166          if (s.alarms & DAHDI_ALARM_BLUE)
13167             strcat(alarmstr, "BLU/");
13168          if (s.alarms & DAHDI_ALARM_YELLOW)
13169             strcat(alarmstr, "YEL/");
13170          if (s.alarms & DAHDI_ALARM_RED)
13171             strcat(alarmstr, "RED/");
13172          if (s.alarms & DAHDI_ALARM_LOOPBACK)
13173             strcat(alarmstr, "LB/");
13174          if (s.alarms & DAHDI_ALARM_RECOVER)
13175             strcat(alarmstr, "REC/");
13176          if (s.alarms & DAHDI_ALARM_NOTOPEN)
13177             strcat(alarmstr, "NOP/");
13178          if (!strlen(alarmstr))
13179             strcat(alarmstr, "UUU/");
13180          if (strlen(alarmstr)) {
13181             /* Strip trailing / */
13182             alarmstr[strlen(alarmstr) - 1] = '\0';
13183          }
13184       } else {
13185          if (s.numchans)
13186             strcpy(alarmstr, "OK");
13187          else
13188             strcpy(alarmstr, "UNCONFIGURED");
13189       }
13190 
13191       ast_cli(a->fd, FORMAT, s.desc, alarmstr, s.irqmisses, s.bpvcount, s.crc4count
13192             , s.lineconfig & DAHDI_CONFIG_D4 ? "D4" :
13193               s.lineconfig & DAHDI_CONFIG_ESF ? "ESF" :
13194               s.lineconfig & DAHDI_CONFIG_CCS ? "CCS" :
13195               "CAS"
13196             , s.lineconfig & DAHDI_CONFIG_B8ZS ? "B8ZS" :
13197               s.lineconfig & DAHDI_CONFIG_HDB3 ? "HDB3" :
13198               s.lineconfig & DAHDI_CONFIG_AMI ? "AMI" :
13199               "Unk"
13200             , s.lineconfig & DAHDI_CONFIG_CRC4 ?
13201               s.lineconfig & DAHDI_CONFIG_NOTOPEN ? "CRC4/YEL" : "CRC4" : "YEL"
13202             , lbostr[s.lbo]
13203          );
13204    }
13205    close(ctl);
13206 
13207    return CLI_SUCCESS;
13208 #undef FORMAT
13209 #undef FORMAT2
13210 }
13211 
13212 static char *dahdi_show_version(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
13213 {
13214    int pseudo_fd = -1;
13215    struct dahdi_versioninfo vi;
13216 
13217    switch (cmd) {
13218    case CLI_INIT:
13219       e->command = "dahdi show version";
13220       e->usage = 
13221          "Usage: dahdi show version\n"
13222          "       Shows the DAHDI version in use\n";
13223       return NULL;
13224    case CLI_GENERATE:
13225       return NULL;
13226    }
13227    if ((pseudo_fd = open("/dev/dahdi/ctl", O_RDONLY)) < 0) {
13228       ast_cli(a->fd, "Failed to open control file to get version.\n");
13229       return CLI_SUCCESS;
13230    }
13231 
13232    strcpy(vi.version, "Unknown");
13233    strcpy(vi.echo_canceller, "Unknown");
13234 
13235    if (ioctl(pseudo_fd, DAHDI_GETVERSION, &vi))
13236       ast_cli(a->fd, "Failed to get DAHDI version: %s\n", strerror(errno));
13237    else
13238       ast_cli(a->fd, "DAHDI Version: %s Echo Canceller: %s\n", vi.version, vi.echo_canceller);
13239 
13240    close(pseudo_fd);
13241 
13242    return CLI_SUCCESS;
13243 }
13244 
13245 static char *dahdi_set_hwgain(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
13246 {
13247    int channel;
13248    int gain;
13249    int tx;
13250    struct dahdi_hwgain hwgain;
13251    struct dahdi_pvt *tmp = NULL;
13252 
13253    switch (cmd) {
13254    case CLI_INIT:
13255       e->command = "dahdi set hwgain";
13256       e->usage = 
13257          "Usage: dahdi set hwgain <rx|tx> <chan#> <gain>\n"
13258          "  Sets the hardware gain on a a given channel, overriding the\n"
13259          "   value provided at module loadtime, whether the channel is in\n"
13260          "   use or not.  Changes take effect immediately.\n"
13261          "   <rx|tx> which direction do you want to change (relative to our module)\n"
13262          "   <chan num> is the channel number relative to the device\n"
13263          "   <gain> is the gain in dB (e.g. -3.5 for -3.5dB)\n";
13264       return NULL;
13265    case CLI_GENERATE:
13266       return NULL;   
13267    }
13268 
13269    if (a->argc != 6)
13270       return CLI_SHOWUSAGE;
13271    
13272    if (!strcasecmp("rx", a->argv[3]))
13273       tx = 0; /* rx */
13274    else if (!strcasecmp("tx", a->argv[3]))
13275       tx = 1; /* tx */
13276    else
13277       return CLI_SHOWUSAGE;
13278 
13279    channel = atoi(a->argv[4]);
13280    gain = atof(a->argv[5])*10.0;
13281 
13282    ast_mutex_lock(&iflock);
13283 
13284    for (tmp = iflist; tmp; tmp = tmp->next) {
13285 
13286       if (tmp->channel != channel)
13287          continue;
13288 
13289       if (tmp->subs[SUB_REAL].dfd == -1)
13290          break;
13291 
13292       hwgain.newgain = gain;
13293       hwgain.tx = tx;
13294       if (ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_SET_HWGAIN, &hwgain) < 0) {
13295          ast_cli(a->fd, "Unable to set the hardware gain for channel %d: %s\n", channel, strerror(errno));
13296          ast_mutex_unlock(&iflock);
13297          return CLI_FAILURE;
13298       }
13299       ast_cli(a->fd, "hardware %s gain set to %d (%.1f dB) on channel %d\n",
13300          tx ? "tx" : "rx", gain, (float)gain/10.0, channel);
13301       break;
13302    }
13303 
13304    ast_mutex_unlock(&iflock);
13305 
13306    if (tmp)
13307       return CLI_SUCCESS;
13308 
13309    ast_cli(a->fd, "Unable to find given channel %d\n", channel);
13310    return CLI_FAILURE;
13311 
13312 }
13313 
13314 static char *dahdi_set_swgain(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
13315 {
13316    int channel;
13317    float gain;
13318    int tx;
13319    int res;
13320    ast_mutex_t *lock;
13321    struct dahdi_pvt *tmp = NULL;
13322 
13323    switch (cmd) {
13324    case CLI_INIT:
13325       e->command = "dahdi set swgain";
13326       e->usage = 
13327          "Usage: dahdi set swgain <rx|tx> <chan#> <gain>\n"
13328          "  Sets the software gain on a a given channel, overriding the\n"
13329          "   value provided at module loadtime, whether the channel is in\n"
13330          "   use or not.  Changes take effect immediately.\n"
13331          "   <rx|tx> which direction do you want to change (relative to our module)\n"
13332          "   <chan num> is the channel number relative to the device\n"
13333          "   <gain> is the gain in dB (e.g. -3.5 for -3.5dB)\n";
13334       return NULL;
13335    case CLI_GENERATE:
13336       return NULL;   
13337    }
13338 
13339    lock = &iflock;
13340 
13341    if (a->argc != 6)
13342       return CLI_SHOWUSAGE;
13343    
13344    if (!strcasecmp("rx", a->argv[3]))
13345       tx = 0; /* rx */
13346    else if (!strcasecmp("tx", a->argv[3]))
13347       tx = 1; /* tx */
13348    else
13349       return CLI_SHOWUSAGE;
13350 
13351    channel = atoi(a->argv[4]);
13352    gain = atof(a->argv[5]);
13353 
13354    ast_mutex_lock(lock);
13355    for (tmp = iflist; tmp; tmp = tmp->next) {
13356 
13357       if (tmp->channel != channel)
13358          continue;
13359 
13360       if (tmp->subs[SUB_REAL].dfd == -1)
13361          break;
13362 
13363       if (tx)
13364          res = set_actual_txgain(tmp->subs[SUB_REAL].dfd, channel, gain, tmp->law);
13365       else
13366          res = set_actual_rxgain(tmp->subs[SUB_REAL].dfd, channel, gain, tmp->law);
13367 
13368       if (res) {
13369          ast_cli(a->fd, "Unable to set the software gain for channel %d\n", channel);
13370          ast_mutex_unlock(lock);
13371          return CLI_FAILURE;
13372       }
13373 
13374       ast_cli(a->fd, "software %s gain set to %.1f on channel %d\n",
13375          tx ? "tx" : "rx", gain, channel);
13376       break;
13377    }
13378    ast_mutex_unlock(lock);
13379 
13380    if (tmp)
13381       return CLI_SUCCESS;
13382 
13383    ast_cli(a->fd, "Unable to find given channel %d\n", channel);
13384    return CLI_FAILURE;
13385 
13386 }
13387 
13388 static char *dahdi_set_dnd(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
13389 {
13390    int channel;
13391    int on;
13392    struct dahdi_pvt *dahdi_chan = NULL;
13393 
13394    switch (cmd) {
13395    case CLI_INIT:
13396       e->command = "dahdi set dnd";
13397       e->usage = 
13398          "Usage: dahdi set dnd <chan#> <on|off>\n"
13399          "  Sets/resets DND (Do Not Disturb) mode on a channel.\n"
13400          "  Changes take effect immediately.\n"
13401          "  <chan num> is the channel number\n"
13402          "  <on|off> Enable or disable DND mode?\n"
13403          ;
13404       return NULL;
13405    case CLI_GENERATE:
13406       return NULL;   
13407    }
13408 
13409    if (a->argc != 5)
13410       return CLI_SHOWUSAGE;
13411 
13412    if ((channel = atoi(a->argv[3])) <= 0) {
13413       ast_cli(a->fd, "Expected channel number, got '%s'\n", a->argv[3]);
13414       return CLI_SHOWUSAGE;
13415    }
13416    
13417    if (ast_true(a->argv[4]))
13418       on = 1;
13419    else if (ast_false(a->argv[4]))
13420       on = 0;
13421    else {
13422       ast_cli(a->fd, "Expected 'on' or 'off', got '%s'\n", a->argv[4]);
13423       return CLI_SHOWUSAGE;
13424    }
13425 
13426    ast_mutex_lock(&iflock);
13427    for (dahdi_chan = iflist; dahdi_chan; dahdi_chan = dahdi_chan->next) {
13428       if (dahdi_chan->channel != channel)
13429          continue;
13430 
13431       /* Found the channel. Actually set it */
13432       dahdi_dnd(dahdi_chan, on);
13433       break;
13434    }
13435    ast_mutex_unlock(&iflock);
13436 
13437    if (!dahdi_chan) {
13438       ast_cli(a->fd, "Unable to find given channel %d\n", channel);
13439       return CLI_FAILURE;
13440    }
13441 
13442    return CLI_SUCCESS;
13443 }
13444 
13445 static struct ast_cli_entry dahdi_cli[] = {
13446    AST_CLI_DEFINE(handle_dahdi_show_cadences, "List cadences"),
13447    AST_CLI_DEFINE(dahdi_show_channels, "Show active DAHDI channels"),
13448    AST_CLI_DEFINE(dahdi_show_channel, "Show information on a channel"),
13449    AST_CLI_DEFINE(dahdi_destroy_channel, "Destroy a channel"),
13450    AST_CLI_DEFINE(dahdi_restart_cmd, "Fully restart DAHDI channels"),
13451    AST_CLI_DEFINE(dahdi_show_status, "Show all DAHDI cards status"),
13452    AST_CLI_DEFINE(dahdi_show_version, "Show the DAHDI version in use"),
13453    AST_CLI_DEFINE(dahdi_set_hwgain, "Set hardware gain on a channel"),
13454    AST_CLI_DEFINE(dahdi_set_swgain, "Set software gain on a channel"),
13455    AST_CLI_DEFINE(dahdi_set_dnd, "Sets/resets DND (Do Not Disturb) mode on a channel"),
13456 };
13457 
13458 #define TRANSFER  0
13459 #define HANGUP    1
13460 
13461 static int dahdi_fake_event(struct dahdi_pvt *p, int mode)
13462 {
13463    if (p) {
13464       switch (mode) {
13465          case TRANSFER:
13466             p->fake_event = DAHDI_EVENT_WINKFLASH;
13467             break;
13468          case HANGUP:
13469             p->fake_event = DAHDI_EVENT_ONHOOK;
13470             break;
13471          default:
13472             ast_log(LOG_WARNING, "I don't know how to handle transfer event with this: %d on channel %s\n",mode, p->owner->name);   
13473       }
13474    }
13475    return 0;
13476 }
13477 static struct dahdi_pvt *find_channel(int channel)
13478 {
13479    struct dahdi_pvt *p = iflist;
13480    while (p) {
13481       if (p->channel == channel) {
13482          break;
13483       }
13484       p = p->next;
13485    }
13486    return p;
13487 }
13488 
13489 static int action_dahdidndon(struct mansession *s, const struct message *m)
13490 {
13491    struct dahdi_pvt *p = NULL;
13492    const char *channel = astman_get_header(m, "DAHDIChannel");
13493 
13494    if (ast_strlen_zero(channel)) {
13495       astman_send_error(s, m, "No channel specified");
13496       return 0;
13497    }
13498    p = find_channel(atoi(channel));
13499    if (!p) {
13500       astman_send_error(s, m, "No such channel");
13501       return 0;
13502    }
13503    p->dnd = 1;
13504    astman_send_ack(s, m, "DND Enabled");
13505    return 0;
13506 }
13507 
13508 static int action_dahdidndoff(struct mansession *s, const struct message *m)
13509 {
13510    struct dahdi_pvt *p = NULL;
13511    const char *channel = astman_get_header(m, "DAHDIChannel");
13512 
13513    if (ast_strlen_zero(channel)) {
13514       astman_send_error(s, m, "No channel specified");
13515       return 0;
13516    }
13517    p = find_channel(atoi(channel));
13518    if (!p) {
13519       astman_send_error(s, m, "No such channel");
13520       return 0;
13521    }
13522    p->dnd = 0;
13523    astman_send_ack(s, m, "DND Disabled");
13524    return 0;
13525 }
13526 
13527 static int action_transfer(struct mansession *s, const struct message *m)
13528 {
13529    struct dahdi_pvt *p = NULL;
13530    const char *channel = astman_get_header(m, "DAHDIChannel");
13531 
13532    if (ast_strlen_zero(channel)) {
13533       astman_send_error(s, m, "No channel specified");
13534       return 0;
13535    }
13536    p = find_channel(atoi(channel));
13537    if (!p) {
13538       astman_send_error(s, m, "No such channel");
13539       return 0;
13540    }
13541    dahdi_fake_event(p,TRANSFER);
13542    astman_send_ack(s, m, "DAHDITransfer");
13543    return 0;
13544 }
13545 
13546 static int action_transferhangup(struct mansession *s, const struct message *m)
13547 {
13548    struct dahdi_pvt *p = NULL;
13549    const char *channel = astman_get_header(m, "DAHDIChannel");
13550 
13551    if (ast_strlen_zero(channel)) {
13552       astman_send_error(s, m, "No channel specified");
13553       return 0;
13554    }
13555    p = find_channel(atoi(channel));
13556    if (!p) {
13557       astman_send_error(s, m, "No such channel");
13558       return 0;
13559    }
13560    dahdi_fake_event(p,HANGUP);
13561    astman_send_ack(s, m, "DAHDIHangup");
13562    return 0;
13563 }
13564 
13565 static int action_dahdidialoffhook(struct mansession *s, const struct message *m)
13566 {
13567    struct dahdi_pvt *p = NULL;
13568    const char *channel = astman_get_header(m, "DAHDIChannel");
13569    const char *number = astman_get_header(m, "Number");
13570    int i;
13571 
13572    if (ast_strlen_zero(channel)) {
13573       astman_send_error(s, m, "No channel specified");
13574       return 0;
13575    }
13576    if (ast_strlen_zero(number)) {
13577       astman_send_error(s, m, "No number specified");
13578       return 0;
13579    }
13580    p = find_channel(atoi(channel));
13581    if (!p) {
13582       astman_send_error(s, m, "No such channel");
13583       return 0;
13584    }
13585    if (!p->owner) {
13586       astman_send_error(s, m, "Channel does not have it's owner");
13587       return 0;
13588    }
13589    for (i = 0; i < strlen(number); i++) {
13590       struct ast_frame f = { AST_FRAME_DTMF, number[i] };
13591       dahdi_queue_frame(p, &f, NULL); 
13592    }
13593    astman_send_ack(s, m, "DAHDIDialOffhook");
13594    return 0;
13595 }
13596 
13597 static int action_dahdishowchannels(struct mansession *s, const struct message *m)
13598 {
13599    struct dahdi_pvt *tmp = NULL;
13600    const char *id = astman_get_header(m, "ActionID");
13601    const char *dahdichannel = astman_get_header(m, "DAHDIChannel");
13602    char idText[256] = "";
13603    int channels = 0;
13604    int dahdichanquery = -1;
13605    if (!ast_strlen_zero(dahdichannel)) {
13606       dahdichanquery = atoi(dahdichannel);
13607    }
13608 
13609    astman_send_ack(s, m, "DAHDI channel status will follow");
13610    if (!ast_strlen_zero(id))
13611       snprintf(idText, sizeof(idText), "ActionID: %s\r\n", id);
13612 
13613    ast_mutex_lock(&iflock);
13614    
13615    tmp = iflist;
13616    while (tmp) {
13617       if (tmp->channel > 0) {
13618          int alm = get_alarms(tmp);
13619 
13620          /* If a specific channel is queried for, only deliver status for that channel */
13621          if (dahdichanquery > 0 && tmp->channel != dahdichanquery)
13622             continue;
13623 
13624          channels++;
13625          if (tmp->owner) {
13626             /* Add data if we have a current call */
13627             astman_append(s,
13628                "Event: DAHDIShowChannels\r\n"
13629                "DAHDIChannel: %d\r\n"
13630                "Channel: %s\r\n"
13631                "Uniqueid: %s\r\n"
13632                "AccountCode: %s\r\n"
13633                "Signalling: %s\r\n"
13634                "SignallingCode: %d\r\n"
13635                "Context: %s\r\n"
13636                "DND: %s\r\n"
13637                "Alarm: %s\r\n"
13638                "%s"
13639                "\r\n",
13640                tmp->channel, 
13641                tmp->owner->name,
13642                tmp->owner->uniqueid,
13643                tmp->owner->accountcode,
13644                sig2str(tmp->sig), 
13645                tmp->sig,
13646                tmp->context, 
13647                tmp->dnd ? "Enabled" : "Disabled",
13648                alarm2str(alm), idText);
13649          } else {
13650             astman_append(s,
13651                "Event: DAHDIShowChannels\r\n"
13652                "DAHDIChannel: %d\r\n"
13653                "Signalling: %s\r\n"
13654                "SignallingCode: %d\r\n"
13655                "Context: %s\r\n"
13656                "DND: %s\r\n"
13657                "Alarm: %s\r\n"
13658                "%s"
13659                "\r\n",
13660                tmp->channel, sig2str(tmp->sig), tmp->sig, 
13661                tmp->context, 
13662                tmp->dnd ? "Enabled" : "Disabled",
13663                alarm2str(alm), idText);
13664          }
13665       } 
13666 
13667       tmp = tmp->next;
13668    }
13669 
13670    ast_mutex_unlock(&iflock);
13671    
13672    astman_append(s, 
13673       "Event: DAHDIShowChannelsComplete\r\n"
13674       "%s"
13675       "Items: %d\r\n"
13676       "\r\n", 
13677       idText,
13678       channels);
13679    return 0;
13680 }
13681 
13682 #ifdef HAVE_SS7
13683 static int linkset_addsigchan(int sigchan)
13684 {
13685    struct dahdi_ss7 *link;
13686    int res;
13687    int curfd;
13688    struct dahdi_params p;
13689    struct dahdi_bufferinfo bi;
13690    struct dahdi_spaninfo si;
13691 
13692 
13693    link = ss7_resolve_linkset(cur_linkset);
13694    if (!link) {
13695       ast_log(LOG_ERROR, "Invalid linkset number.  Must be between 1 and %d\n", NUM_SPANS + 1);
13696       return -1;
13697    }
13698 
13699    if (cur_ss7type < 0) {
13700       ast_log(LOG_ERROR, "Unspecified or invalid ss7type\n");
13701       return -1;
13702    }
13703 
13704    if (!link->ss7)
13705       link->ss7 = ss7_new(cur_ss7type);
13706 
13707    if (!link->ss7) {
13708       ast_log(LOG_ERROR, "Can't create new SS7!\n");
13709       return -1;
13710    }
13711 
13712    link->type = cur_ss7type;
13713 
13714    if (cur_pointcode < 0) {
13715       ast_log(LOG_ERROR, "Unspecified pointcode!\n");
13716       return -1;
13717    } else
13718       ss7_set_pc(link->ss7, cur_pointcode);
13719 
13720    if (sigchan < 0) {
13721       ast_log(LOG_ERROR, "Invalid sigchan!\n");
13722       return -1;
13723    } else {
13724       if (link->numsigchans >= NUM_DCHANS) {
13725          ast_log(LOG_ERROR, "Too many sigchans on linkset %d\n", cur_linkset);
13726          return -1;
13727       }
13728       curfd = link->numsigchans;
13729 
13730       link->fds[curfd] = open("/dev/dahdi/channel", O_RDWR, 0600);
13731       if ((link->fds[curfd] < 0) || (ioctl(link->fds[curfd],DAHDI_SPECIFY,&sigchan) == -1)) {
13732          ast_log(LOG_ERROR, "Unable to open SS7 sigchan %d (%s)\n", sigchan, strerror(errno));
13733          return -1;
13734       }
13735       memset(&p, 0, sizeof(p));
13736       res = ioctl(link->fds[curfd], DAHDI_GET_PARAMS, &p);
13737       if (res) {
13738          dahdi_close_ss7_fd(link, curfd);
13739          ast_log(LOG_ERROR, "Unable to get parameters for sigchan %d (%s)\n", sigchan, strerror(errno));
13740          return -1;
13741       }
13742       if ((p.sigtype != DAHDI_SIG_HDLCFCS) && (p.sigtype != DAHDI_SIG_HARDHDLC) && (p.sigtype != DAHDI_SIG_MTP2)) {
13743          dahdi_close_ss7_fd(link, curfd);
13744          ast_log(LOG_ERROR, "sigchan %d is not in HDLC/FCS mode.\n", sigchan);
13745          return -1;
13746       }
13747 
13748       memset(&bi, 0, sizeof(bi));
13749       bi.txbufpolicy = DAHDI_POLICY_IMMEDIATE;
13750       bi.rxbufpolicy = DAHDI_POLICY_IMMEDIATE;
13751       bi.numbufs = 32;
13752       bi.bufsize = 512;
13753 
13754       if (ioctl(link->fds[curfd], DAHDI_SET_BUFINFO, &bi)) {
13755          ast_log(LOG_ERROR, "Unable to set appropriate buffering on channel %d: %s\n", sigchan, strerror(errno));
13756          dahdi_close_ss7_fd(link, curfd);
13757          return -1;
13758       }
13759 
13760       if (p.sigtype == DAHDI_SIG_MTP2)
13761          ss7_add_link(link->ss7, SS7_TRANSPORT_DAHDIMTP2, link->fds[curfd]);
13762       else
13763          ss7_add_link(link->ss7, SS7_TRANSPORT_DAHDIDCHAN, link->fds[curfd]);
13764 
13765       link->numsigchans++;
13766 
13767       memset(&si, 0, sizeof(si));
13768       res = ioctl(link->fds[curfd], DAHDI_SPANSTAT, &si);
13769       if (res) {
13770          dahdi_close_ss7_fd(link, curfd);
13771          ast_log(LOG_ERROR, "Unable to get span state for sigchan %d (%s)\n", sigchan, strerror(errno));
13772       }
13773 
13774       if (!si.alarms) {
13775          link->linkstate[curfd] = LINKSTATE_DOWN;
13776          ss7_link_noalarm(link->ss7, link->fds[curfd]);
13777       } else {
13778          link->linkstate[curfd] = LINKSTATE_DOWN | LINKSTATE_INALARM;
13779          ss7_link_alarm(link->ss7, link->fds[curfd]);
13780       }
13781    }
13782 
13783    if (cur_adjpointcode < 0) {
13784       ast_log(LOG_ERROR, "Unspecified adjpointcode!\n");
13785       return -1;
13786    } else {
13787       ss7_set_adjpc(link->ss7, link->fds[curfd], cur_adjpointcode);
13788    }
13789 
13790    if (cur_defaultdpc < 0) {
13791       ast_log(LOG_ERROR, "Unspecified defaultdpc!\n");
13792       return -1;
13793    }
13794 
13795    if (cur_networkindicator < 0) {
13796       ast_log(LOG_ERROR, "Invalid networkindicator!\n");
13797       return -1;
13798    } else
13799       ss7_set_network_ind(link->ss7, cur_networkindicator);
13800 
13801    return 0;
13802 }
13803 
13804 static char *handle_ss7_no_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
13805 {
13806    int span;
13807    switch (cmd) {
13808    case CLI_INIT:
13809       e->command = "ss7 no debug linkset";
13810       e->usage = 
13811          "Usage: ss7 no debug linkset <span>\n"
13812          "       Disables debugging on a given SS7 linkset\n";
13813       return NULL;
13814    case CLI_GENERATE:
13815       return NULL;
13816    }
13817    if (a->argc < 5)
13818       return CLI_SHOWUSAGE;
13819    span = atoi(a->argv[4]);
13820    if ((span < 1) || (span > NUM_SPANS)) {
13821       ast_cli(a->fd, "Invalid linkset %s.  Should be a number from %d to %d\n", a->argv[4], 1, NUM_SPANS);
13822       return CLI_SUCCESS;
13823    }
13824    if (!linksets[span-1].ss7) {
13825       ast_cli(a->fd, "No SS7 running on linkset %d\n", span);
13826       return CLI_SUCCESS;
13827    }
13828    if (linksets[span-1].ss7)
13829       ss7_set_debug(linksets[span-1].ss7, 0);
13830 
13831    ast_cli(a->fd, "Disabled debugging on linkset %d\n", span);
13832    return CLI_SUCCESS;
13833 }
13834 
13835 static char *handle_ss7_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
13836 {
13837    int span;
13838    switch (cmd) {
13839    case CLI_INIT:
13840       e->command = "ss7 debug linkset";
13841       e->usage = 
13842          "Usage: ss7 debug linkset <linkset>\n"
13843          "       Enables debugging on a given SS7 linkset\n";
13844       return NULL;
13845    case CLI_GENERATE:
13846       return NULL;
13847    }
13848    if (a->argc < 4)
13849       return CLI_SHOWUSAGE;
13850    span = atoi(a->argv[3]);
13851    if ((span < 1) || (span > NUM_SPANS)) {
13852       ast_cli(a->fd, "Invalid linkset %s.  Should be a number from %d to %d\n", a->argv[3], 1, NUM_SPANS);
13853       return CLI_SUCCESS;
13854    }
13855    if (!linksets[span-1].ss7) {
13856       ast_cli(a->fd, "No SS7 running on linkset %d\n", span);
13857       return CLI_SUCCESS;
13858    }
13859    if (linksets[span-1].ss7)
13860       ss7_set_debug(linksets[span-1].ss7, SS7_DEBUG_MTP2 | SS7_DEBUG_MTP3 | SS7_DEBUG_ISUP);
13861 
13862    ast_cli(a->fd, "Enabled debugging on linkset %d\n", span);
13863    return CLI_SUCCESS;
13864 }
13865 
13866 static char *handle_ss7_block_cic(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
13867 {
13868    int linkset, cic;
13869    int blocked = -1, i;
13870    switch (cmd) {
13871    case CLI_INIT:
13872       e->command = "ss7 block cic";
13873       e->usage = 
13874          "Usage: ss7 block cic <linkset> <CIC>\n"
13875          "       Sends a remote blocking request for the given CIC on the specified linkset\n";
13876       return NULL;
13877    case CLI_GENERATE:
13878       return NULL;
13879    }
13880    if (a->argc == 5)
13881       linkset = atoi(a->argv[3]);
13882    else
13883       return CLI_SHOWUSAGE;
13884 
13885    if ((linkset < 1) || (linkset > NUM_SPANS)) {
13886       ast_cli(a->fd, "Invalid linkset %s.  Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
13887       return CLI_SUCCESS;
13888    }
13889 
13890    if (!linksets[linkset-1].ss7) {
13891       ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
13892       return CLI_SUCCESS;
13893    }
13894 
13895    cic = atoi(a->argv[4]);
13896 
13897    if (cic < 1) {
13898       ast_cli(a->fd, "Invalid CIC specified!\n");
13899       return CLI_SUCCESS;
13900    }
13901 
13902    for (i = 0; i < linksets[linkset-1].numchans; i++) {
13903       if (linksets[linkset-1].pvts[i]->cic == cic) {
13904          blocked = linksets[linkset-1].pvts[i]->locallyblocked;
13905          if (!blocked) {
13906             ast_mutex_lock(&linksets[linkset-1].lock);
13907             isup_blo(linksets[linkset-1].ss7, cic, linksets[linkset-1].pvts[i]->dpc);
13908             ast_mutex_unlock(&linksets[linkset-1].lock);
13909          }
13910       }
13911    }
13912 
13913    if (blocked < 0) {
13914       ast_cli(a->fd, "Invalid CIC specified!\n");
13915       return CLI_SUCCESS;
13916    }
13917 
13918    if (!blocked)
13919       ast_cli(a->fd, "Sent blocking request for linkset %d on CIC %d\n", linkset, cic);
13920    else
13921       ast_cli(a->fd, "CIC %d already locally blocked\n", cic);
13922 
13923    /* Break poll on the linkset so it sends our messages */
13924    pthread_kill(linksets[linkset-1].master, SIGURG);
13925 
13926    return CLI_SUCCESS;
13927 }
13928 
13929 static char *handle_ss7_block_linkset(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
13930 {
13931    int linkset;
13932    int i;
13933    switch (cmd) {
13934    case CLI_INIT:
13935       e->command = "ss7 block linkset";
13936       e->usage = 
13937          "Usage: ss7 block linkset <linkset number>\n"
13938          "       Sends a remote blocking request for all CICs on the given linkset\n";
13939       return NULL;
13940    case CLI_GENERATE:
13941       return NULL;
13942    }
13943    if (a->argc == 4)
13944       linkset = atoi(a->argv[3]);
13945    else
13946       return CLI_SHOWUSAGE;
13947 
13948    if ((linkset < 1) || (linkset > NUM_SPANS)) {
13949       ast_cli(a->fd, "Invalid linkset %s.  Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
13950       return CLI_SUCCESS;
13951    }
13952 
13953    if (!linksets[linkset-1].ss7) {
13954       ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
13955       return CLI_SUCCESS;
13956    }
13957 
13958    for (i = 0; i < linksets[linkset-1].numchans; i++) {
13959       ast_cli(a->fd, "Sending remote blocking request on CIC %d\n", linksets[linkset-1].pvts[i]->cic);
13960       ast_mutex_lock(&linksets[linkset-1].lock);
13961       isup_blo(linksets[linkset-1].ss7, linksets[linkset-1].pvts[i]->cic, linksets[linkset-1].pvts[i]->dpc);
13962       ast_mutex_unlock(&linksets[linkset-1].lock);
13963    }
13964 
13965    /* Break poll on the linkset so it sends our messages */
13966    pthread_kill(linksets[linkset-1].master, SIGURG);
13967 
13968    return CLI_SUCCESS;
13969 }
13970 
13971 static char *handle_ss7_unblock_cic(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
13972 {
13973    int linkset, cic;
13974    int i, blocked = -1;
13975    switch (cmd) {
13976    case CLI_INIT:
13977       e->command = "ss7 unblock cic";
13978       e->usage = 
13979          "Usage: ss7 unblock cic <linkset> <CIC>\n"
13980          "       Sends a remote unblocking request for the given CIC on the specified linkset\n";
13981       return NULL;
13982    case CLI_GENERATE:
13983       return NULL;
13984    }
13985 
13986    if (a->argc == 5)
13987       linkset = atoi(a->argv[3]);
13988    else
13989       return CLI_SHOWUSAGE;
13990 
13991    if ((linkset < 1) || (linkset > NUM_SPANS)) {
13992       ast_cli(a->fd, "Invalid linkset %s.  Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
13993       return CLI_SUCCESS;
13994    }
13995 
13996    if (!linksets[linkset-1].ss7) {
13997       ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
13998       return CLI_SUCCESS;
13999    }
14000 
14001    cic = atoi(a->argv[4]);
14002 
14003    if (cic < 1) {
14004       ast_cli(a->fd, "Invalid CIC specified!\n");
14005       return CLI_SUCCESS;
14006    }
14007 
14008    for (i = 0; i < linksets[linkset-1].numchans; i++) {
14009       if (linksets[linkset-1].pvts[i]->cic == cic) {
14010          blocked = linksets[linkset-1].pvts[i]->locallyblocked;
14011          if (blocked) {
14012             ast_mutex_lock(&linksets[linkset-1].lock);
14013             isup_ubl(linksets[linkset-1].ss7, cic, linksets[linkset-1].pvts[i]->dpc);
14014             ast_mutex_unlock(&linksets[linkset-1].lock);
14015          }
14016       }
14017    }
14018 
14019    if (blocked > 0)
14020       ast_cli(a->fd, "Sent unblocking request for linkset %d on CIC %d\n", linkset, cic);
14021 
14022    /* Break poll on the linkset so it sends our messages */
14023    pthread_kill(linksets[linkset-1].master, SIGURG);
14024 
14025    return CLI_SUCCESS;
14026 }
14027 
14028 static char *handle_ss7_unblock_linkset(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14029 {
14030    int linkset;
14031    int i;
14032    switch (cmd) {
14033    case CLI_INIT:
14034       e->command = "ss7 unblock linkset";
14035       e->usage = 
14036          "Usage: ss7 unblock linkset <linkset number>\n"
14037          "       Sends a remote unblocking request for all CICs on the specified linkset\n";
14038       return NULL;
14039    case CLI_GENERATE:
14040       return NULL;
14041    }
14042 
14043    if (a->argc == 4)
14044       linkset = atoi(a->argv[3]);
14045    else
14046       return CLI_SHOWUSAGE;
14047 
14048    if ((linkset < 1) || (linkset > NUM_SPANS)) {
14049       ast_cli(a->fd, "Invalid linkset %s.  Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
14050       return CLI_SUCCESS;
14051    }
14052 
14053    if (!linksets[linkset-1].ss7) {
14054       ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
14055       return CLI_SUCCESS;
14056    }
14057 
14058    for (i = 0; i < linksets[linkset-1].numchans; i++) {
14059       ast_cli(a->fd, "Sending remote unblock request on CIC %d\n", linksets[linkset-1].pvts[i]->cic);
14060       ast_mutex_lock(&linksets[linkset-1].lock);
14061       isup_ubl(linksets[linkset-1].ss7, linksets[linkset-1].pvts[i]->cic, linksets[linkset-1].pvts[i]->dpc);
14062       ast_mutex_unlock(&linksets[linkset-1].lock);
14063    }
14064 
14065    /* Break poll on the linkset so it sends our messages */
14066    pthread_kill(linksets[linkset-1].master, SIGURG);
14067 
14068    return CLI_SUCCESS;
14069 }
14070 
14071 static char *handle_ss7_show_linkset(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14072 {
14073    int linkset;
14074    struct dahdi_ss7 *ss7;
14075    switch (cmd) {
14076    case CLI_INIT:
14077       e->command = "ss7 show linkset";
14078       e->usage = 
14079          "Usage: ss7 show linkset <span>\n"
14080          "       Shows the status of an SS7 linkset.\n";
14081       return NULL;
14082    case CLI_GENERATE:
14083       return NULL;
14084    }
14085 
14086    if (a->argc < 4)
14087       return CLI_SHOWUSAGE;
14088    linkset = atoi(a->argv[3]);
14089    if ((linkset < 1) || (linkset > NUM_SPANS)) {
14090       ast_cli(a->fd, "Invalid linkset %s.  Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
14091       return CLI_SUCCESS;
14092    }
14093    if (!linksets[linkset-1].ss7) {
14094       ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
14095       return CLI_SUCCESS;
14096    }
14097    if (linksets[linkset-1].ss7)
14098       ss7 = &linksets[linkset-1];
14099 
14100    ast_cli(a->fd, "SS7 linkset %d status: %s\n", linkset, (ss7->state == LINKSET_STATE_UP) ? "Up" : "Down");
14101 
14102    return CLI_SUCCESS;
14103 }
14104 
14105 static char *handle_ss7_version(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14106 {
14107    switch (cmd) {
14108    case CLI_INIT:
14109       e->command = "ss7 show version";
14110       e->usage = 
14111          "Usage: ss7 show version\n"
14112          "  Show the libss7 version\n";
14113       return NULL;
14114    case CLI_GENERATE:
14115       return NULL;
14116    }
14117 
14118    ast_cli(a->fd, "libss7 version: %s\n", ss7_get_version());
14119 
14120    return CLI_SUCCESS;
14121 }
14122 
14123 static struct ast_cli_entry dahdi_ss7_cli[] = {
14124    AST_CLI_DEFINE(handle_ss7_debug, "Enables SS7 debugging on a linkset"), 
14125    AST_CLI_DEFINE(handle_ss7_no_debug, "Disables SS7 debugging on a linkset"), 
14126    AST_CLI_DEFINE(handle_ss7_block_cic, "Blocks the given CIC"),
14127    AST_CLI_DEFINE(handle_ss7_unblock_cic, "Unblocks the given CIC"),
14128    AST_CLI_DEFINE(handle_ss7_block_linkset, "Blocks all CICs on a linkset"),
14129    AST_CLI_DEFINE(handle_ss7_unblock_linkset, "Unblocks all CICs on a linkset"),
14130    AST_CLI_DEFINE(handle_ss7_show_linkset, "Shows the status of a linkset"),
14131    AST_CLI_DEFINE(handle_ss7_version, "Displays libss7 version"),
14132 };
14133 #endif /* HAVE_SS7 */
14134 
14135 static int __unload_module(void)
14136 {
14137    struct dahdi_pvt *p;
14138 #if defined(HAVE_PRI) || defined(HAVE_SS7)
14139    int i, j;
14140 #endif
14141 
14142 #ifdef HAVE_PRI
14143    for (i = 0; i < NUM_SPANS; i++) {
14144       if (pris[i].master != AST_PTHREADT_NULL) 
14145          pthread_cancel(pris[i].master);
14146    }
14147    ast_cli_unregister_multiple(dahdi_pri_cli, ARRAY_LEN(dahdi_pri_cli));
14148    ast_unregister_application(dahdi_send_keypad_facility_app);
14149 #endif
14150 #if defined(HAVE_SS7)
14151    for (i = 0; i < NUM_SPANS; i++) {
14152       if (linksets[i].master != AST_PTHREADT_NULL)
14153          pthread_cancel(linksets[i].master);
14154       }
14155    ast_cli_unregister_multiple(dahdi_ss7_cli, sizeof(dahdi_ss7_cli) / sizeof(struct ast_cli_entry));
14156 #endif
14157 
14158    ast_cli_unregister_multiple(dahdi_cli, sizeof(dahdi_cli) / sizeof(struct ast_cli_entry));
14159    ast_manager_unregister( "DAHDIDialOffhook" );
14160    ast_manager_unregister( "DAHDIHangup" );
14161    ast_manager_unregister( "DAHDITransfer" );
14162    ast_manager_unregister( "DAHDIDNDoff" );
14163    ast_manager_unregister( "DAHDIDNDon" );
14164    ast_manager_unregister("DAHDIShowChannels");
14165    ast_manager_unregister("DAHDIRestart");
14166    ast_channel_unregister(&dahdi_tech);
14167    ast_mutex_lock(&iflock);
14168    /* Hangup all interfaces if they have an owner */
14169    p = iflist;
14170    while (p) {
14171       if (p->owner)
14172          ast_softhangup(p->owner, AST_SOFTHANGUP_APPUNLOAD);
14173       p = p->next;
14174    }
14175    ast_mutex_unlock(&iflock);
14176    ast_mutex_lock(&monlock);
14177    if (monitor_thread && (monitor_thread != AST_PTHREADT_STOP) && (monitor_thread != AST_PTHREADT_NULL)) {
14178       pthread_cancel(monitor_thread);
14179       pthread_kill(monitor_thread, SIGURG);
14180       pthread_join(monitor_thread, NULL);
14181    }
14182    monitor_thread = AST_PTHREADT_STOP;
14183    ast_mutex_unlock(&monlock);
14184 
14185    destroy_all_channels();
14186 
14187 #if defined(HAVE_PRI)
14188    for (i = 0; i < NUM_SPANS; i++) {
14189       if (pris[i].master && (pris[i].master != AST_PTHREADT_NULL))
14190          pthread_join(pris[i].master, NULL);
14191       for (j = 0; j < NUM_DCHANS; j++) {
14192          dahdi_close_pri_fd(&(pris[i]), j);
14193       }
14194    }
14195 #endif
14196 
14197 #if defined(HAVE_SS7)
14198    for (i = 0; i < NUM_SPANS; i++) {
14199       if (linksets[i].master && (linksets[i].master != AST_PTHREADT_NULL))
14200          pthread_join(linksets[i].master, NULL);
14201       for (j = 0; j < NUM_DCHANS; j++) {
14202          dahdi_close_ss7_fd(&(linksets[i]), j);
14203       }
14204    }
14205 #endif
14206 
14207    ast_cond_destroy(&mwi_thread_complete);
14208    ast_cond_destroy(&ss_thread_complete);
14209    return 0;
14210 }
14211 
14212 static int unload_module(void)
14213 {
14214 #if defined(HAVE_PRI) || defined(HAVE_SS7)
14215    int y;
14216 #endif
14217 #ifdef HAVE_PRI
14218    for (y = 0; y < NUM_SPANS; y++)
14219       ast_mutex_destroy(&pris[y].lock);
14220 #endif
14221 #ifdef HAVE_SS7
14222    for (y = 0; y < NUM_SPANS; y++)
14223       ast_mutex_destroy(&linksets[y].lock);
14224 #endif /* HAVE_SS7 */
14225    return __unload_module();
14226 }
14227 
14228 static int build_channels(struct dahdi_chan_conf *conf, int iscrv, const char *value, int reload, int lineno, int *found_pseudo)
14229 {
14230    char *c, *chan;
14231    int x, start, finish;
14232    struct dahdi_pvt *tmp;
14233 #ifdef HAVE_PRI
14234    struct dahdi_pri *pri;
14235    int trunkgroup, y;
14236 #endif
14237    
14238    if ((reload == 0) && (conf->chan.sig < 0) && !conf->is_sig_auto) {
14239       ast_log(LOG_ERROR, "Signalling must be specified before any channels are.\n");
14240       return -1;
14241    }
14242 
14243    c = ast_strdupa(value);
14244 
14245 #ifdef HAVE_PRI
14246    pri = NULL;
14247    if (iscrv) {
14248       if (sscanf(c, "%30d:%n", &trunkgroup, &y) != 1) {
14249          ast_log(LOG_WARNING, "CRV must begin with trunkgroup followed by a colon at line %d.\n", lineno);
14250          return -1;
14251       }
14252       if (trunkgroup < 1) {
14253          ast_log(LOG_WARNING, "CRV trunk group must be a positive number at line %d.\n", lineno);
14254          return -1;
14255       }
14256       c += y;
14257       for (y = 0; y < NUM_SPANS; y++) {
14258          if (pris[y].trunkgroup == trunkgroup) {
14259             pri = pris + y;
14260             break;
14261          }
14262       }
14263       if (!pri) {
14264          ast_log(LOG_WARNING, "No such trunk group %d at CRV declaration at line %d.\n", trunkgroup, lineno);
14265          return -1;
14266       }
14267    }
14268 #endif         
14269 
14270    while ((chan = strsep(&c, ","))) {
14271       if (sscanf(chan, "%30d-%30d", &start, &finish) == 2) {
14272          /* Range */
14273       } else if (sscanf(chan, "%30d", &start)) {
14274          /* Just one */
14275          finish = start;
14276       } else if (!strcasecmp(chan, "pseudo")) {
14277          finish = start = CHAN_PSEUDO;
14278          if (found_pseudo)
14279             *found_pseudo = 1;
14280       } else {
14281          ast_log(LOG_ERROR, "Syntax error parsing '%s' at '%s'\n", value, chan);
14282          return -1;
14283       }
14284       if (finish < start) {
14285          ast_log(LOG_WARNING, "Sillyness: %d < %d\n", start, finish);
14286          x = finish;
14287          finish = start;
14288          start = x;
14289       }
14290 
14291       for (x = start; x <= finish; x++) {
14292 #ifdef HAVE_PRI
14293          tmp = mkintf(x, conf, pri, reload);
14294 #else       
14295          tmp = mkintf(x, conf, NULL, reload);
14296 #endif         
14297 
14298          if (tmp) {
14299 #ifdef HAVE_PRI
14300                if (pri)
14301                ast_verb(3, "%s CRV %d:%d, %s signalling\n", reload ? "Reconfigured" : "Registered", trunkgroup, x, sig2str(tmp->sig));
14302                else
14303 #endif
14304                ast_verb(3, "%s channel %d, %s signalling\n", reload ? "Reconfigured" : "Registered", x, sig2str(tmp->sig));
14305          } else {
14306             ast_log(LOG_ERROR, "Unable to %s channel '%s'\n",
14307                (reload == 1) ? "reconfigure" : "register", value);
14308             return -1;
14309          }
14310       }
14311    }
14312 
14313    return 0;
14314 }
14315 
14316 /** The length of the parameters list of 'dahdichan'. 
14317  * \todo Move definition of MAX_CHANLIST_LEN to a proper place. */
14318 #define MAX_CHANLIST_LEN 80
14319 
14320 static void process_echocancel(struct dahdi_chan_conf *confp, const char *data, unsigned int line)
14321 {
14322    char *parse = ast_strdupa(data);
14323    char *params[DAHDI_MAX_ECHOCANPARAMS + 1];
14324    unsigned int param_count;
14325    unsigned int x;
14326 
14327    if (!(param_count = ast_app_separate_args(parse, ',', params, ARRAY_LEN(params))))
14328       return;
14329 
14330    memset(&confp->chan.echocancel, 0, sizeof(confp->chan.echocancel));
14331 
14332    /* first parameter is tap length, process it here */
14333 
14334    x = ast_strlen_zero(params[0]) ? 0 : atoi(params[0]);
14335    
14336    if ((x == 32) || (x == 64) || (x == 128) || (x == 256) || (x == 512) || (x == 1024))
14337       confp->chan.echocancel.head.tap_length = x;
14338    else if ((confp->chan.echocancel.head.tap_length = ast_true(params[0])))
14339       confp->chan.echocancel.head.tap_length = 128;
14340 
14341    /* now process any remaining parameters */
14342 
14343    for (x = 1; x < param_count; x++) {
14344       struct {
14345          char *name;
14346          char *value;
14347       } param;
14348 
14349       if (ast_app_separate_args(params[x], '=', (char **) &param, 2) < 1) {
14350          ast_log(LOG_WARNING, "Invalid echocancel parameter supplied at line %d: '%s'\n", line, params[x]);
14351          continue;
14352       }
14353 
14354       if (ast_strlen_zero(param.name) || (strlen(param.name) > sizeof(confp->chan.echocancel.params[0].name)-1)) {
14355          ast_log(LOG_WARNING, "Invalid echocancel parameter supplied at line %d: '%s'\n", line, param.name);
14356          continue;
14357       }
14358 
14359       strcpy(confp->chan.echocancel.params[confp->chan.echocancel.head.param_count].name, param.name);
14360 
14361       if (param.value) {
14362          if (sscanf(param.value, "%30d", &confp->chan.echocancel.params[confp->chan.echocancel.head.param_count].value) != 1) {
14363             ast_log(LOG_WARNING, "Invalid echocancel parameter value supplied at line %d: '%s'\n", line, param.value);
14364             continue;
14365          }
14366       }
14367       confp->chan.echocancel.head.param_count++;
14368    }
14369 }
14370 
14371 /*! process_dahdi() - ignore keyword 'channel' and similar */
14372 #define PROC_DAHDI_OPT_NOCHAN  (1 << 0) 
14373 /*! process_dahdi() - No warnings on non-existing cofiguration keywords */
14374 #define PROC_DAHDI_OPT_NOWARN  (1 << 1) 
14375 
14376 static int process_dahdi(struct dahdi_chan_conf *confp, const char *cat, struct ast_variable *v, int reload, int options)
14377 {
14378    struct dahdi_pvt *tmp;
14379    int y;
14380    int found_pseudo = 0;
14381    char dahdichan[MAX_CHANLIST_LEN] = {};
14382 
14383    for (; v; v = v->next) {
14384       if (!ast_jb_read_conf(&global_jbconf, v->name, v->value))
14385          continue;
14386 
14387       /* must have parkinglot in confp before build_channels is called */
14388       if (!strcasecmp(v->name, "parkinglot")) {
14389          ast_copy_string(confp->chan.parkinglot, v->value, sizeof(confp->chan.parkinglot));
14390       }
14391 
14392       /* Create the interface list */
14393       if (!strcasecmp(v->name, "channel")
14394 #ifdef HAVE_PRI
14395           || !strcasecmp(v->name, "crv")
14396 #endif         
14397          ) {
14398          int iscrv;
14399          if (options & PROC_DAHDI_OPT_NOCHAN) {
14400             ast_log(LOG_WARNING, "Channel '%s' ignored.\n", v->value);
14401             continue;
14402          }
14403          iscrv = !strcasecmp(v->name, "crv");
14404          if (build_channels(confp, iscrv, v->value, reload, v->lineno, &found_pseudo))
14405                return -1;
14406          ast_log(LOG_DEBUG, "Channel '%s' configured.\n", v->value);
14407       } else if (!strcasecmp(v->name, "buffers")) {
14408          int res;
14409          char policy[21] = "";
14410 
14411          res = sscanf(v->value, "%30d,%20s", &confp->chan.buf_no, policy);
14412          if (res != 2) {
14413             ast_log(LOG_WARNING, "Parsing buffers option data failed, using defaults.\n");
14414             confp->chan.buf_no = numbufs;
14415             continue;
14416          }
14417          if (confp->chan.buf_no < 0)
14418             confp->chan.buf_no = numbufs;
14419          if (!strcasecmp(policy, "full")) {
14420             confp->chan.buf_policy = DAHDI_POLICY_WHEN_FULL;
14421          } else if (!strcasecmp(policy, "immediate")) {
14422             confp->chan.buf_policy = DAHDI_POLICY_IMMEDIATE;
14423          } else {
14424             ast_log(LOG_WARNING, "Invalid policy name given (%s).\n", policy);
14425          }
14426       } else if (!strcasecmp(v->name, "dahdichan")) {
14427          ast_copy_string(dahdichan, v->value, sizeof(dahdichan));
14428       } else if (!strcasecmp(v->name, "usedistinctiveringdetection")) {
14429          usedistinctiveringdetection = ast_true(v->value);
14430       } else if (!strcasecmp(v->name, "distinctiveringaftercid")) {
14431          distinctiveringaftercid = ast_true(v->value);
14432       } else if (!strcasecmp(v->name, "dring1context")) {
14433          ast_copy_string(confp->chan.drings.ringContext[0].contextData,v->value,sizeof(confp->chan.drings.ringContext[0].contextData));
14434       } else if (!strcasecmp(v->name, "dring2context")) {
14435          ast_copy_string(confp->chan.drings.ringContext[1].contextData,v->value,sizeof(confp->chan.drings.ringContext[1].contextData));
14436       } else if (!strcasecmp(v->name, "dring3context")) {
14437          ast_copy_string(confp->chan.drings.ringContext[2].contextData,v->value,sizeof(confp->chan.drings.ringContext[2].contextData));
14438       } else if (!strcasecmp(v->name, "dring1range")) {
14439          confp->chan.drings.ringnum[0].range = atoi(v->value);
14440       } else if (!strcasecmp(v->name, "dring2range")) {
14441          confp->chan.drings.ringnum[1].range = atoi(v->value);
14442       } else if (!strcasecmp(v->name, "dring3range")) {
14443          confp->chan.drings.ringnum[2].range = atoi(v->value);
14444       } else if (!strcasecmp(v->name, "dring1")) {
14445          sscanf(v->value, "%30d,%30d,%30d", &confp->chan.drings.ringnum[0].ring[0], &confp->chan.drings.ringnum[0].ring[1], &confp->chan.drings.ringnum[0].ring[2]);
14446       } else if (!strcasecmp(v->name, "dring2")) {
14447          sscanf(v->value, "%30d,%30d,%30d", &confp->chan.drings.ringnum[1].ring[0], &confp->chan.drings.ringnum[1].ring[1], &confp->chan.drings.ringnum[1].ring[2]);
14448       } else if (!strcasecmp(v->name, "dring3")) {
14449          sscanf(v->value, "%30d,%30d,%30d", &confp->chan.drings.ringnum[2].ring[0], &confp->chan.drings.ringnum[2].ring[1], &confp->chan.drings.ringnum[2].ring[2]);
14450       } else if (!strcasecmp(v->name, "usecallerid")) {
14451          confp->chan.use_callerid = ast_true(v->value);
14452       } else if (!strcasecmp(v->name, "cidsignalling")) {
14453          if (!strcasecmp(v->value, "bell"))
14454             confp->chan.cid_signalling = CID_SIG_BELL;
14455          else if (!strcasecmp(v->value, "v23"))
14456             confp->chan.cid_signalling = CID_SIG_V23;
14457          else if (!strcasecmp(v->value, "dtmf"))
14458             confp->chan.cid_signalling = CID_SIG_DTMF;
14459          else if (!strcasecmp(v->value, "smdi"))
14460             confp->chan.cid_signalling = CID_SIG_SMDI;
14461          else if (!strcasecmp(v->value, "v23_jp"))
14462             confp->chan.cid_signalling = CID_SIG_V23_JP;
14463          else if (ast_true(v->value))
14464             confp->chan.cid_signalling = CID_SIG_BELL;
14465       } else if (!strcasecmp(v->name, "cidstart")) {
14466          if (!strcasecmp(v->value, "ring"))
14467             confp->chan.cid_start = CID_START_RING;
14468          else if (!strcasecmp(v->value, "polarity_in"))
14469             confp->chan.cid_start = CID_START_POLARITY_IN;
14470          else if (!strcasecmp(v->value, "polarity"))
14471             confp->chan.cid_start = CID_START_POLARITY;
14472          else if (ast_true(v->value))
14473             confp->chan.cid_start = CID_START_RING;
14474       } else if (!strcasecmp(v->name, "threewaycalling")) {
14475          confp->chan.threewaycalling = ast_true(v->value);
14476       } else if (!strcasecmp(v->name, "cancallforward")) {
14477          confp->chan.cancallforward = ast_true(v->value);
14478       } else if (!strcasecmp(v->name, "relaxdtmf")) {
14479          if (ast_true(v->value)) 
14480             confp->chan.dtmfrelax = DSP_DIGITMODE_RELAXDTMF;
14481          else
14482             confp->chan.dtmfrelax = 0;
14483       } else if (!strcasecmp(v->name, "mailbox")) {
14484          ast_copy_string(confp->chan.mailbox, v->value, sizeof(confp->chan.mailbox));
14485       } else if (!strcasecmp(v->name, "hasvoicemail")) {
14486          if (ast_true(v->value) && ast_strlen_zero(confp->chan.mailbox)) {
14487             ast_copy_string(confp->chan.mailbox, cat, sizeof(confp->chan.mailbox));
14488          }
14489       } else if (!strcasecmp(v->name, "adsi")) {
14490          confp->chan.adsi = ast_true(v->value);
14491       } else if (!strcasecmp(v->name, "usesmdi")) {
14492          confp->chan.use_smdi = ast_true(v->value);
14493       } else if (!strcasecmp(v->name, "smdiport")) {
14494          ast_copy_string(confp->smdi_port, v->value, sizeof(confp->smdi_port));
14495       } else if (!strcasecmp(v->name, "transfer")) {
14496          confp->chan.transfer = ast_true(v->value);
14497       } else if (!strcasecmp(v->name, "canpark")) {
14498          confp->chan.canpark = ast_true(v->value);
14499       } else if (!strcasecmp(v->name, "echocancelwhenbridged")) {
14500          confp->chan.echocanbridged = ast_true(v->value);
14501       } else if (!strcasecmp(v->name, "busydetect")) {
14502          confp->chan.busydetect = ast_true(v->value);
14503       } else if (!strcasecmp(v->name, "busycount")) {
14504          confp->chan.busycount = atoi(v->value);
14505       } else if (!strcasecmp(v->name, "silencethreshold")) {
14506          confp->chan.silencethreshold = atoi(v->value);
14507       } else if (!strcasecmp(v->name, "busycompare")) {
14508          confp->chan.busycompare = ast_true(v->value);
14509       } else if (!strcasecmp(v->name, "busypattern")) {
14510          if (sscanf(v->value, "%30d,%30d", &confp->chan.busytonelength, &confp->chan.busyquietlength) != 2) {
14511             ast_log(LOG_ERROR, "busypattern= expects busypattern=tonelength,quietlength at line %d.\n", v->lineno);
14512          }
14513          int count = sscanf(v->value, "%d,%d", &confp->chan.busytonelength, &confp->chan.busyquietlength);
14514          if (count == 1)
14515             confp->chan.busyquietlength = 0;
14516          else if (count < 1)
14517             ast_log(LOG_ERROR, "busypattern= expects busypattern=tonelength[,quietlength] at line %d.\n", v->lineno);
14518       } else if (!strcasecmp(v->name, "busyfuzziness")) {
14519          confp->chan.busyfuzziness = atoi(v->value);
14520       } else if (!strcasecmp(v->name, "callprogress")) {
14521          confp->chan.callprogress &= ~CALLPROGRESS_PROGRESS;
14522          if (ast_true(v->value))
14523             confp->chan.callprogress |= CALLPROGRESS_PROGRESS;
14524       } else if (!strcasecmp(v->name, "faxdetect")) {
14525          confp->chan.callprogress &= ~CALLPROGRESS_FAX;
14526          if (!strcasecmp(v->value, "incoming")) {
14527             confp->chan.callprogress |= CALLPROGRESS_FAX_INCOMING;
14528          } else if (!strcasecmp(v->value, "outgoing")) {
14529             confp->chan.callprogress |= CALLPROGRESS_FAX_OUTGOING;
14530          } else if (!strcasecmp(v->value, "both") || ast_true(v->value))
14531             confp->chan.callprogress |= CALLPROGRESS_FAX_INCOMING | CALLPROGRESS_FAX_OUTGOING;
14532       } else if (!strcasecmp(v->name, "echocancel")) {
14533          process_echocancel(confp, v->value, v->lineno);
14534       } else if (!strcasecmp(v->name, "echotraining")) {
14535          if (sscanf(v->value, "%30d", &y) == 1) {
14536             if ((y < 10) || (y > 4000)) {
14537                ast_log(LOG_WARNING, "Echo training time must be within the range of 10 to 4000 ms at line %d.\n", v->lineno);             
14538             } else {
14539                confp->chan.echotraining = y;
14540             }
14541          } else if (ast_true(v->value)) {
14542             confp->chan.echotraining = 400;
14543          } else
14544             confp->chan.echotraining = 0;
14545       } else if (!strcasecmp(v->name, "hidecallerid")) {
14546          confp->chan.hidecallerid = ast_true(v->value);
14547       } else if (!strcasecmp(v->name, "hidecalleridname")) {
14548          confp->chan.hidecalleridname = ast_true(v->value);
14549       } else if (!strcasecmp(v->name, "pulsedial")) {
14550          confp->chan.pulse = ast_true(v->value);
14551       } else if (!strcasecmp(v->name, "callreturn")) {
14552          confp->chan.callreturn = ast_true(v->value);
14553       } else if (!strcasecmp(v->name, "callwaiting")) {
14554          confp->chan.callwaiting = ast_true(v->value);
14555       } else if (!strcasecmp(v->name, "callwaitingcallerid")) {
14556          confp->chan.callwaitingcallerid = ast_true(v->value);
14557       } else if (!strcasecmp(v->name, "context")) {
14558          ast_copy_string(confp->chan.context, v->value, sizeof(confp->chan.context));
14559       } else if (!strcasecmp(v->name, "language")) {
14560          ast_copy_string(confp->chan.language, v->value, sizeof(confp->chan.language));
14561       } else if (!strcasecmp(v->name, "progzone")) {
14562          ast_copy_string(progzone, v->value, sizeof(progzone));
14563       } else if (!strcasecmp(v->name, "mohinterpret") 
14564          ||!strcasecmp(v->name, "musiconhold") || !strcasecmp(v->name, "musicclass")) {
14565          ast_copy_string(confp->chan.mohinterpret, v->value, sizeof(confp->chan.mohinterpret));
14566       } else if (!strcasecmp(v->name, "mohsuggest")) {
14567          ast_copy_string(confp->chan.mohsuggest, v->value, sizeof(confp->chan.mohsuggest));
14568       } else if (!strcasecmp(v->name, "parkinglot")) {
14569          ast_copy_string(parkinglot, v->value, sizeof(parkinglot));
14570       } else if (!strcasecmp(v->name, "stripmsd")) {
14571          ast_log(LOG_NOTICE, "Configuration option \"%s\" has been deprecated. Please use dialplan instead\n", v->name);
14572          confp->chan.stripmsd = atoi(v->value);
14573       } else if (!strcasecmp(v->name, "jitterbuffers")) {
14574          numbufs = atoi(v->value);
14575       } else if (!strcasecmp(v->name, "group")) {
14576          confp->chan.group = ast_get_group(v->value);
14577       } else if (!strcasecmp(v->name, "callgroup")) {
14578          if (!strcasecmp(v->value, "none"))
14579             confp->chan.callgroup = 0;
14580          else
14581             confp->chan.callgroup = ast_get_group(v->value);
14582       } else if (!strcasecmp(v->name, "pickupgroup")) {
14583          if (!strcasecmp(v->value, "none"))
14584             confp->chan.pickupgroup = 0;
14585          else
14586             confp->chan.pickupgroup = ast_get_group(v->value);
14587       } else if (!strcasecmp(v->name, "setvar")) {
14588          char *varname = ast_strdupa(v->value), *varval = NULL;
14589          struct ast_variable *tmpvar;
14590          if (varname && (varval = strchr(varname, '='))) {
14591             *varval++ = '\0';
14592             if ((tmpvar = ast_variable_new(varname, varval, ""))) {
14593                tmpvar->next = confp->chan.vars;
14594                confp->chan.vars = tmpvar;
14595             }
14596          }
14597       } else if (!strcasecmp(v->name, "immediate")) {
14598          confp->chan.immediate = ast_true(v->value);
14599       } else if (!strcasecmp(v->name, "transfertobusy")) {
14600          confp->chan.transfertobusy = ast_true(v->value);
14601       } else if (!strcasecmp(v->name, "mwimonitor")) {
14602          confp->chan.mwimonitor_neon = 0;
14603          confp->chan.mwimonitor_fsk  = 0;
14604          confp->chan.mwimonitor_rpas = 0;
14605          if (strcasestr(v->value, "fsk")) {
14606             confp->chan.mwimonitor_fsk = 1;
14607          }
14608          if (strcasestr(v->value, "rpas")) {
14609             confp->chan.mwimonitor_rpas = 1;
14610          }
14611          if (strcasestr(v->value, "neon")) {
14612             confp->chan.mwimonitor_neon = 1;
14613          }
14614          /* If set to true or yes, assume that simple fsk is desired */
14615          if (ast_true(v->value)) {
14616             confp->chan.mwimonitor_fsk = 1;
14617          } 
14618       } else if (!strcasecmp(v->name, "cid_rxgain")) {
14619          if (sscanf(v->value, "%30f", &confp->chan.cid_rxgain) != 1) {
14620             ast_log(LOG_WARNING, "Invalid cid_rxgain: %s at line %d.\n", v->value, v->lineno);
14621          }
14622       } else if (!strcasecmp(v->name, "rxgain")) {
14623          if (sscanf(v->value, "%30f", &confp->chan.rxgain) != 1) {
14624             ast_log(LOG_WARNING, "Invalid rxgain: %s at line %d.\n", v->value, v->lineno);
14625          }
14626       } else if (!strcasecmp(v->name, "txgain")) {
14627          if (sscanf(v->value, "%30f", &confp->chan.txgain) != 1) {
14628             ast_log(LOG_WARNING, "Invalid txgain: %s at line %d.\n", v->value, v->lineno);
14629          }
14630       } else if (!strcasecmp(v->name, "tonezone")) {
14631          if (sscanf(v->value, "%30d", &confp->chan.tonezone) != 1) {
14632             ast_log(LOG_WARNING, "Invalid tonezone: %s at line %d.\n", v->value, v->lineno);
14633          }
14634       } else if (!strcasecmp(v->name, "callerid")) {
14635          if (!strcasecmp(v->value, "asreceived")) {
14636             confp->chan.cid_num[0] = '\0';
14637             confp->chan.cid_name[0] = '\0';
14638          } else {
14639             ast_callerid_split(v->value, confp->chan.cid_name, sizeof(confp->chan.cid_name), confp->chan.cid_num, sizeof(confp->chan.cid_num));
14640          } 
14641       } else if (!strcasecmp(v->name, "fullname")) {
14642          ast_copy_string(confp->chan.cid_name, v->value, sizeof(confp->chan.cid_name));
14643       } else if (!strcasecmp(v->name, "cid_number")) {
14644          ast_copy_string(confp->chan.cid_num, v->value, sizeof(confp->chan.cid_num));
14645       } else if (!strcasecmp(v->name, "useincomingcalleridondahditransfer")) {
14646          confp->chan.dahditrcallerid = ast_true(v->value);
14647       } else if (!strcasecmp(v->name, "restrictcid")) {
14648          confp->chan.restrictcid = ast_true(v->value);
14649       } else if (!strcasecmp(v->name, "usecallingpres")) {
14650          confp->chan.use_callingpres = ast_true(v->value);
14651       } else if (!strcasecmp(v->name, "accountcode")) {
14652          ast_copy_string(confp->chan.accountcode, v->value, sizeof(confp->chan.accountcode));
14653       } else if (!strcasecmp(v->name, "amaflags")) {
14654          y = ast_cdr_amaflags2int(v->value);
14655          if (y < 0) 
14656             ast_log(LOG_WARNING, "Invalid AMA flags: %s at line %d.\n", v->value, v->lineno);
14657          else
14658             confp->chan.amaflags = y;
14659       } else if (!strcasecmp(v->name, "polarityonanswerdelay")) {
14660          confp->chan.polarityonanswerdelay = atoi(v->value);
14661       } else if (!strcasecmp(v->name, "answeronpolarityswitch")) {
14662          confp->chan.answeronpolarityswitch = ast_true(v->value);
14663       } else if (!strcasecmp(v->name, "hanguponpolarityswitch")) {
14664          confp->chan.hanguponpolarityswitch = ast_true(v->value);
14665       } else if (!strcasecmp(v->name, "sendcalleridafter")) {
14666          confp->chan.sendcalleridafter = atoi(v->value);
14667       } else if (!strcasecmp(v->name, "mwimonitornotify")) {
14668          ast_copy_string(mwimonitornotify, v->value, sizeof(mwimonitornotify));
14669       } else if (!strcasecmp(v->name, "mwisendtype")) {
14670          if (!strcasecmp(v->value, "rpas")) { /* Ring Pulse Alert Signal */
14671             mwisend_rpas = 1;
14672          } else {
14673             mwisend_rpas = 0;
14674          }
14675       } else if (reload != 1) {
14676           if (!strcasecmp(v->name, "signalling") || !strcasecmp(v->name, "signaling")) {
14677             int orig_radio = confp->chan.radio;
14678             int orig_outsigmod = confp->chan.outsigmod;
14679             int orig_auto = confp->is_sig_auto;
14680 
14681             confp->chan.radio = 0;
14682             confp->chan.outsigmod = -1;
14683             confp->is_sig_auto = 0;
14684             if (!strcasecmp(v->value, "em")) {
14685                confp->chan.sig = SIG_EM;
14686             } else if (!strcasecmp(v->value, "em_e1")) {
14687                confp->chan.sig = SIG_EM_E1;
14688             } else if (!strcasecmp(v->value, "em_w")) {
14689                confp->chan.sig = SIG_EMWINK;
14690             } else if (!strcasecmp(v->value, "fxs_ls")) {
14691                confp->chan.sig = SIG_FXSLS;
14692             } else if (!strcasecmp(v->value, "fxs_gs")) {
14693                confp->chan.sig = SIG_FXSGS;
14694             } else if (!strcasecmp(v->value, "fxs_ks")) {
14695                confp->chan.sig = SIG_FXSKS;
14696             } else if (!strcasecmp(v->value, "fxo_ls")) {
14697                confp->chan.sig = SIG_FXOLS;
14698             } else if (!strcasecmp(v->value, "fxo_gs")) {
14699                confp->chan.sig = SIG_FXOGS;
14700             } else if (!strcasecmp(v->value, "fxo_ks")) {
14701                confp->chan.sig = SIG_FXOKS;
14702             } else if (!strcasecmp(v->value, "fxs_rx")) {
14703                confp->chan.sig = SIG_FXSKS;
14704                confp->chan.radio = 1;
14705             } else if (!strcasecmp(v->value, "fxo_rx")) {
14706                confp->chan.sig = SIG_FXOLS;
14707                confp->chan.radio = 1;
14708             } else if (!strcasecmp(v->value, "fxs_tx")) {
14709                confp->chan.sig = SIG_FXSLS;
14710                confp->chan.radio = 1;
14711             } else if (!strcasecmp(v->value, "fxo_tx")) {
14712                confp->chan.sig = SIG_FXOGS;
14713                confp->chan.radio = 1;
14714             } else if (!strcasecmp(v->value, "em_rx")) {
14715                confp->chan.sig = SIG_EM;
14716                confp->chan.radio = 1;
14717             } else if (!strcasecmp(v->value, "em_tx")) {
14718                confp->chan.sig = SIG_EM;
14719                confp->chan.radio = 1;
14720             } else if (!strcasecmp(v->value, "em_rxtx")) {
14721                confp->chan.sig = SIG_EM;
14722                confp->chan.radio = 2;
14723             } else if (!strcasecmp(v->value, "em_txrx")) {
14724                confp->chan.sig = SIG_EM;
14725                confp->chan.radio = 2;
14726             } else if (!strcasecmp(v->value, "sf")) {
14727                confp->chan.sig = SIG_SF;
14728             } else if (!strcasecmp(v->value, "sf_w")) {
14729                confp->chan.sig = SIG_SFWINK;
14730             } else if (!strcasecmp(v->value, "sf_featd")) {
14731                confp->chan.sig = SIG_FEATD;
14732             } else if (!strcasecmp(v->value, "sf_featdmf")) {
14733                confp->chan.sig = SIG_FEATDMF;
14734             } else if (!strcasecmp(v->value, "sf_featb")) {
14735                confp->chan.sig = SIG_SF_FEATB;
14736             } else if (!strcasecmp(v->value, "sf")) {
14737                confp->chan.sig = SIG_SF;
14738             } else if (!strcasecmp(v->value, "sf_rx")) {
14739                confp->chan.sig = SIG_SF;
14740                confp->chan.radio = 1;
14741             } else if (!strcasecmp(v->value, "sf_tx")) {
14742                confp->chan.sig = SIG_SF;
14743                confp->chan.radio = 1;
14744             } else if (!strcasecmp(v->value, "sf_rxtx")) {
14745                confp->chan.sig = SIG_SF;
14746                confp->chan.radio = 2;
14747             } else if (!strcasecmp(v->value, "sf_txrx")) {
14748                confp->chan.sig = SIG_SF;
14749                confp->chan.radio = 2;
14750             } else if (!strcasecmp(v->value, "featd")) {
14751                confp->chan.sig = SIG_FEATD;
14752             } else if (!strcasecmp(v->value, "featdmf")) {
14753                confp->chan.sig = SIG_FEATDMF;
14754             } else if (!strcasecmp(v->value, "featdmf_ta")) {
14755                confp->chan.sig = SIG_FEATDMF_TA;
14756             } else if (!strcasecmp(v->value, "e911")) {
14757                confp->chan.sig = SIG_E911;
14758             } else if (!strcasecmp(v->value, "fgccama")) {
14759                confp->chan.sig = SIG_FGC_CAMA;
14760             } else if (!strcasecmp(v->value, "fgccamamf")) {
14761                confp->chan.sig = SIG_FGC_CAMAMF;
14762             } else if (!strcasecmp(v->value, "featb")) {
14763                confp->chan.sig = SIG_FEATB;
14764 #ifdef HAVE_PRI
14765             } else if (!strcasecmp(v->value, "pri_net")) {
14766                confp->chan.sig = SIG_PRI;
14767                confp->pri.nodetype = PRI_NETWORK;
14768             } else if (!strcasecmp(v->value, "pri_cpe")) {
14769                confp->chan.sig = SIG_PRI;
14770                confp->pri.nodetype = PRI_CPE;
14771             } else if (!strcasecmp(v->value, "bri_cpe")) {
14772                confp->chan.sig = SIG_BRI;
14773                confp->pri.nodetype = PRI_CPE;
14774             } else if (!strcasecmp(v->value, "bri_net")) {
14775                confp->chan.sig = SIG_BRI;
14776                confp->pri.nodetype = PRI_NETWORK;
14777             } else if (!strcasecmp(v->value, "bri_cpe_ptmp")) {
14778                confp->chan.sig = SIG_BRI_PTMP;
14779                confp->pri.nodetype = PRI_CPE;
14780             } else if (!strcasecmp(v->value, "bri_net_ptmp")) {
14781                ast_log(LOG_WARNING, "How cool would it be if someone implemented this mode!  For now, sucks for you. (line %d)\n", v->lineno);
14782             } else if (!strcasecmp(v->value, "gr303fxoks_net")) {
14783                confp->chan.sig = SIG_GR303FXOKS;
14784                confp->pri.nodetype = PRI_NETWORK;
14785             } else if (!strcasecmp(v->value, "gr303fxsks_cpe")) {
14786                confp->chan.sig = SIG_GR303FXSKS;
14787                confp->pri.nodetype = PRI_CPE;
14788 #endif
14789 #ifdef HAVE_SS7
14790             } else if (!strcasecmp(v->value, "ss7")) {
14791                confp->chan.sig = SIG_SS7;
14792 #endif
14793             } else if (!strcasecmp(v->value, "auto")) {
14794                confp->is_sig_auto = 1;
14795             } else {
14796                confp->chan.outsigmod = orig_outsigmod;
14797                confp->chan.radio = orig_radio;
14798                confp->is_sig_auto = orig_auto;
14799                ast_log(LOG_ERROR, "Unknown signalling method '%s' at line %d.\n", v->value, v->lineno);
14800             }
14801           } else if (!strcasecmp(v->name, "outsignalling") || !strcasecmp(v->name, "outsignaling")) {
14802             if (!strcasecmp(v->value, "em")) {
14803                confp->chan.outsigmod = SIG_EM;
14804             } else if (!strcasecmp(v->value, "em_e1")) {
14805                confp->chan.outsigmod = SIG_EM_E1;
14806             } else if (!strcasecmp(v->value, "em_w")) {
14807                confp->chan.outsigmod = SIG_EMWINK;
14808             } else if (!strcasecmp(v->value, "sf")) {
14809                confp->chan.outsigmod = SIG_SF;
14810             } else if (!strcasecmp(v->value, "sf_w")) {
14811                confp->chan.outsigmod = SIG_SFWINK;
14812             } else if (!strcasecmp(v->value, "sf_featd")) {
14813                confp->chan.outsigmod = SIG_FEATD;
14814             } else if (!strcasecmp(v->value, "sf_featdmf")) {
14815                confp->chan.outsigmod = SIG_FEATDMF;
14816             } else if (!strcasecmp(v->value, "sf_featb")) {
14817                confp->chan.outsigmod = SIG_SF_FEATB;
14818             } else if (!strcasecmp(v->value, "sf")) {
14819                confp->chan.outsigmod = SIG_SF;
14820             } else if (!strcasecmp(v->value, "featd")) {
14821                confp->chan.outsigmod = SIG_FEATD;
14822             } else if (!strcasecmp(v->value, "featdmf")) {
14823                confp->chan.outsigmod = SIG_FEATDMF;
14824             } else if (!strcasecmp(v->value, "featdmf_ta")) {
14825                confp->chan.outsigmod = SIG_FEATDMF_TA;
14826             } else if (!strcasecmp(v->value, "e911")) {
14827                confp->chan.outsigmod = SIG_E911;
14828             } else if (!strcasecmp(v->value, "fgccama")) {
14829                confp->chan.outsigmod = SIG_FGC_CAMA;
14830             } else if (!strcasecmp(v->value, "fgccamamf")) {
14831                confp->chan.outsigmod = SIG_FGC_CAMAMF;
14832             } else if (!strcasecmp(v->value, "featb")) {
14833                confp->chan.outsigmod = SIG_FEATB;
14834             } else {
14835                ast_log(LOG_ERROR, "Unknown signalling method '%s' at line %d.\n", v->value, v->lineno);
14836             }
14837 #ifdef HAVE_PRI
14838          } else if (!strcasecmp(v->name, "pridialplan")) {
14839             if (!strcasecmp(v->value, "national")) {
14840                confp->pri.dialplan = PRI_NATIONAL_ISDN + 1;
14841             } else if (!strcasecmp(v->value, "unknown")) {
14842                confp->pri.dialplan = PRI_UNKNOWN + 1;
14843             } else if (!strcasecmp(v->value, "private")) {
14844                confp->pri.dialplan = PRI_PRIVATE + 1;
14845             } else if (!strcasecmp(v->value, "international")) {
14846                confp->pri.dialplan = PRI_INTERNATIONAL_ISDN + 1;
14847             } else if (!strcasecmp(v->value, "local")) {
14848                confp->pri.dialplan = PRI_LOCAL_ISDN + 1;
14849             } else if (!strcasecmp(v->value, "dynamic")) {
14850                confp->pri.dialplan = -1;
14851             } else if (!strcasecmp(v->value, "redundant")) {
14852                confp->pri.dialplan = -2;
14853             } else {
14854                ast_log(LOG_WARNING, "Unknown PRI dialplan '%s' at line %d.\n", v->value, v->lineno);
14855             }
14856          } else if (!strcasecmp(v->name, "prilocaldialplan")) {
14857             if (!strcasecmp(v->value, "national")) {
14858                confp->pri.localdialplan = PRI_NATIONAL_ISDN + 1;
14859             } else if (!strcasecmp(v->value, "unknown")) {
14860                confp->pri.localdialplan = PRI_UNKNOWN + 1;
14861             } else if (!strcasecmp(v->value, "private")) {
14862                confp->pri.localdialplan = PRI_PRIVATE + 1;
14863             } else if (!strcasecmp(v->value, "international")) {
14864                confp->pri.localdialplan = PRI_INTERNATIONAL_ISDN + 1;
14865             } else if (!strcasecmp(v->value, "local")) {
14866                confp->pri.localdialplan = PRI_LOCAL_ISDN + 1;
14867             } else if (!strcasecmp(v->value, "dynamic")) {
14868                confp->pri.localdialplan = -1;
14869             } else if (!strcasecmp(v->value, "redundant")) {
14870                confp->pri.localdialplan = -2;
14871             } else {
14872                ast_log(LOG_WARNING, "Unknown PRI localdialplan '%s' at line %d.\n", v->value, v->lineno);
14873             }
14874          } else if (!strcasecmp(v->name, "switchtype")) {
14875             if (!strcasecmp(v->value, "national")) 
14876                confp->pri.switchtype = PRI_SWITCH_NI2;
14877             else if (!strcasecmp(v->value, "ni1"))
14878                confp->pri.switchtype = PRI_SWITCH_NI1;
14879             else if (!strcasecmp(v->value, "dms100"))
14880                confp->pri.switchtype = PRI_SWITCH_DMS100;
14881             else if (!strcasecmp(v->value, "4ess"))
14882                confp->pri.switchtype = PRI_SWITCH_ATT4ESS;
14883             else if (!strcasecmp(v->value, "5ess"))
14884                confp->pri.switchtype = PRI_SWITCH_LUCENT5E;
14885             else if (!strcasecmp(v->value, "euroisdn"))
14886                confp->pri.switchtype = PRI_SWITCH_EUROISDN_E1;
14887             else if (!strcasecmp(v->value, "qsig"))
14888                confp->pri.switchtype = PRI_SWITCH_QSIG;
14889             else {
14890                ast_log(LOG_ERROR, "Unknown switchtype '%s' at line %d.\n", v->value, v->lineno);
14891                return -1;
14892             }
14893          } else if (!strcasecmp(v->name, "nsf")) {
14894             if (!strcasecmp(v->value, "sdn"))
14895                confp->pri.nsf = PRI_NSF_SDN;
14896             else if (!strcasecmp(v->value, "megacom"))
14897                confp->pri.nsf = PRI_NSF_MEGACOM;
14898             else if (!strcasecmp(v->value, "tollfreemegacom"))
14899                confp->pri.nsf = PRI_NSF_TOLL_FREE_MEGACOM;           
14900             else if (!strcasecmp(v->value, "accunet"))
14901                confp->pri.nsf = PRI_NSF_ACCUNET;
14902             else if (!strcasecmp(v->value, "none"))
14903                confp->pri.nsf = PRI_NSF_NONE;
14904             else {
14905                ast_log(LOG_WARNING, "Unknown network-specific facility '%s' at line %d.\n", v->value, v->lineno);
14906                confp->pri.nsf = PRI_NSF_NONE;
14907             }
14908          } else if (!strcasecmp(v->name, "priindication")) {
14909             if (!strcasecmp(v->value, "outofband"))
14910                confp->chan.priindication_oob = 1;
14911             else if (!strcasecmp(v->value, "inband"))
14912                confp->chan.priindication_oob = 0;
14913             else
14914                ast_log(LOG_WARNING, "'%s' is not a valid pri indication value, should be 'inband' or 'outofband' at line %d.\n",
14915                   v->value, v->lineno);
14916          } else if (!strcasecmp(v->name, "priexclusive")) {
14917             confp->chan.priexclusive = ast_true(v->value);
14918          } else if (!strcasecmp(v->name, "internationalprefix")) {
14919             ast_copy_string(confp->pri.internationalprefix, v->value, sizeof(confp->pri.internationalprefix));
14920          } else if (!strcasecmp(v->name, "nationalprefix")) {
14921             ast_copy_string(confp->pri.nationalprefix, v->value, sizeof(confp->pri.nationalprefix));
14922          } else if (!strcasecmp(v->name, "localprefix")) {
14923             ast_copy_string(confp->pri.localprefix, v->value, sizeof(confp->pri.localprefix));
14924          } else if (!strcasecmp(v->name, "privateprefix")) {
14925             ast_copy_string(confp->pri.privateprefix, v->value, sizeof(confp->pri.privateprefix));
14926          } else if (!strcasecmp(v->name, "unknownprefix")) {
14927             ast_copy_string(confp->pri.unknownprefix, v->value, sizeof(confp->pri.unknownprefix));
14928          } else if (!strcasecmp(v->name, "resetinterval")) {
14929             if (!strcasecmp(v->value, "never"))
14930                confp->pri.resetinterval = -1;
14931             else if (atoi(v->value) >= 60)
14932                confp->pri.resetinterval = atoi(v->value);
14933             else
14934                ast_log(LOG_WARNING, "'%s' is not a valid reset interval, should be >= 60 seconds or 'never' at line %d.\n",
14935                   v->value, v->lineno);
14936          } else if (!strcasecmp(v->name, "minunused")) {
14937             confp->pri.minunused = atoi(v->value);
14938          } else if (!strcasecmp(v->name, "minidle")) {
14939             confp->pri.minidle = atoi(v->value); 
14940          } else if (!strcasecmp(v->name, "idleext")) {
14941             ast_copy_string(confp->pri.idleext, v->value, sizeof(confp->pri.idleext));
14942          } else if (!strcasecmp(v->name, "idledial")) {
14943             ast_copy_string(confp->pri.idledial, v->value, sizeof(confp->pri.idledial));
14944          } else if (!strcasecmp(v->name, "overlapdial")) {
14945             if (ast_true(v->value)) {
14946                confp->pri.overlapdial = DAHDI_OVERLAPDIAL_BOTH;
14947             } else if (!strcasecmp(v->value, "incoming")) {
14948                confp->pri.overlapdial = DAHDI_OVERLAPDIAL_INCOMING;
14949             } else if (!strcasecmp(v->value, "outgoing")) {
14950                confp->pri.overlapdial = DAHDI_OVERLAPDIAL_OUTGOING;
14951             } else if (!strcasecmp(v->value, "both") || ast_true(v->value)) {
14952                confp->pri.overlapdial = DAHDI_OVERLAPDIAL_BOTH;
14953             } else {
14954                confp->pri.overlapdial = DAHDI_OVERLAPDIAL_NONE;
14955             }
14956 #ifdef HAVE_PRI_INBANDDISCONNECT
14957          } else if (!strcasecmp(v->name, "inbanddisconnect")) {
14958             confp->pri.inbanddisconnect = ast_true(v->value);
14959 #endif
14960          } else if (!strcasecmp(v->name, "pritimer")) {
14961 #ifdef PRI_GETSET_TIMERS
14962             char tmp[20];
14963             char *timerc;
14964             char *c;
14965             int timer;
14966             int timeridx;
14967 
14968             ast_copy_string(tmp, v->value, sizeof(tmp));
14969             c = tmp;
14970             timerc = strsep(&c, ",");
14971             if (!ast_strlen_zero(timerc) && !ast_strlen_zero(c)) {
14972                timeridx = pri_timer2idx(timerc);
14973                timer = atoi(c);
14974                if (timeridx < 0 || PRI_MAX_TIMERS <= timeridx) {
14975                   ast_log(LOG_WARNING,
14976                      "'%s' is not a valid ISDN timer at line %d.\n", timerc,
14977                      v->lineno);
14978                } else if (!timer) {
14979                   ast_log(LOG_WARNING,
14980                      "'%s' is not a valid value for ISDN timer '%s' at line %d.\n",
14981                      c, timerc, v->lineno);
14982                } else {
14983                   pritimers[timeridx] = timer;
14984                }
14985             } else {
14986                ast_log(LOG_WARNING,
14987                   "'%s' is not a valid ISDN timer configuration string at line %d.\n",
14988                   v->value, v->lineno);
14989             }
14990 
14991          } else if (!strcasecmp(v->name, "facilityenable")) {
14992             confp->pri.facilityenable = ast_true(v->value);
14993 #endif /* PRI_GETSET_TIMERS */
14994 #endif /* HAVE_PRI */
14995 #ifdef HAVE_SS7
14996          } else if (!strcasecmp(v->name, "ss7type")) {
14997             if (!strcasecmp(v->value, "itu")) {
14998                cur_ss7type = SS7_ITU;
14999             } else if (!strcasecmp(v->value, "ansi")) {
15000                cur_ss7type = SS7_ANSI;
15001             } else
15002                ast_log(LOG_WARNING, "'%s' is an unknown ss7 switch type at line %d.!\n", v->value, v->lineno);
15003          } else if (!strcasecmp(v->name, "linkset")) {
15004             cur_linkset = atoi(v->value);
15005          } else if (!strcasecmp(v->name, "pointcode")) {
15006             cur_pointcode = parse_pointcode(v->value);
15007          } else if (!strcasecmp(v->name, "adjpointcode")) {
15008             cur_adjpointcode = parse_pointcode(v->value);
15009          } else if (!strcasecmp(v->name, "defaultdpc")) {
15010             cur_defaultdpc = parse_pointcode(v->value);
15011          } else if (!strcasecmp(v->name, "cicbeginswith")) {
15012             cur_cicbeginswith = atoi(v->value);
15013          } else if (!strcasecmp(v->name, "networkindicator")) {
15014             if (!strcasecmp(v->value, "national"))
15015                cur_networkindicator = SS7_NI_NAT;
15016             else if (!strcasecmp(v->value, "national_spare"))
15017                cur_networkindicator = SS7_NI_NAT_SPARE;
15018             else if (!strcasecmp(v->value, "international"))
15019                cur_networkindicator = SS7_NI_INT;
15020             else if (!strcasecmp(v->value, "international_spare"))
15021                cur_networkindicator = SS7_NI_INT_SPARE;
15022             else
15023                cur_networkindicator = -1;
15024          } else if (!strcasecmp(v->name, "ss7_internationalprefix")) {
15025             ast_copy_string(confp->ss7.internationalprefix, v->value, sizeof(confp->ss7.internationalprefix));
15026          } else if (!strcasecmp(v->name, "ss7_nationalprefix")) {
15027             ast_copy_string(confp->ss7.nationalprefix, v->value, sizeof(confp->ss7.nationalprefix));
15028          } else if (!strcasecmp(v->name, "ss7_subscriberprefix")) {
15029             ast_copy_string(confp->ss7.subscriberprefix, v->value, sizeof(confp->ss7.subscriberprefix));
15030          } else if (!strcasecmp(v->name, "ss7_unknownprefix")) {
15031             ast_copy_string(confp->ss7.unknownprefix, v->value, sizeof(confp->ss7.unknownprefix));
15032          } else if (!strcasecmp(v->name, "ss7_called_nai")) {
15033             if (!strcasecmp(v->value, "national")) {
15034                confp->ss7.called_nai = SS7_NAI_NATIONAL;
15035             } else if (!strcasecmp(v->value, "international")) {
15036                confp->ss7.called_nai = SS7_NAI_INTERNATIONAL;
15037             } else if (!strcasecmp(v->value, "subscriber")) {
15038                confp->ss7.called_nai = SS7_NAI_SUBSCRIBER;
15039             } else if (!strcasecmp(v->value, "dynamic")) {
15040                confp->ss7.called_nai = SS7_NAI_DYNAMIC;
15041             } else {
15042                ast_log(LOG_WARNING, "Unknown SS7 called_nai '%s' at line %d.\n", v->value, v->lineno);
15043             }
15044          } else if (!strcasecmp(v->name, "ss7_calling_nai")) {
15045             if (!strcasecmp(v->value, "national")) {
15046                confp->ss7.calling_nai = SS7_NAI_NATIONAL;
15047             } else if (!strcasecmp(v->value, "international")) {
15048                confp->ss7.calling_nai = SS7_NAI_INTERNATIONAL;
15049             } else if (!strcasecmp(v->value, "subscriber")) {
15050                confp->ss7.calling_nai = SS7_NAI_SUBSCRIBER;
15051             } else if (!strcasecmp(v->value, "dynamic")) {
15052                confp->ss7.calling_nai = SS7_NAI_DYNAMIC;
15053             } else {
15054                ast_log(LOG_WARNING, "Unknown SS7 calling_nai '%s' at line %d.\n", v->value, v->lineno);
15055             }
15056          } else if (!strcasecmp(v->name, "sigchan")) {
15057             int sigchan, res;
15058             sigchan = atoi(v->value);
15059             res = linkset_addsigchan(sigchan);
15060             if (res < 0)
15061                return -1;
15062 
15063          } else if (!strcasecmp(v->name, "ss7_explicitacm")) {
15064             struct dahdi_ss7 *link;
15065             link = ss7_resolve_linkset(cur_linkset);
15066             if (!link) {
15067                ast_log(LOG_ERROR, "Invalid linkset number.  Must be between 1 and %d\n", NUM_SPANS + 1);
15068                return -1;
15069             }
15070             if (ast_true(v->value))
15071                link->flags |= LINKSET_FLAG_EXPLICITACM;
15072 
15073 #endif /* HAVE_SS7 */
15074          } else if (!strcasecmp(v->name, "cadence")) {
15075             /* setup to scan our argument */
15076             int element_count, c[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
15077             int i;
15078             struct dahdi_ring_cadence new_cadence;
15079             int cid_location = -1;
15080             int firstcadencepos = 0;
15081             char original_args[80];
15082             int cadence_is_ok = 1;
15083 
15084             ast_copy_string(original_args, v->value, sizeof(original_args));
15085             /* 16 cadences allowed (8 pairs) */
15086             element_count = sscanf(v->value, "%30d,%30d,%30d,%30d,%30d,%30d,%30d,%30d,%30d,%30d,%30d,%30d,%30d,%30d,%30d,%30d", &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]);
15087    
15088             /* Cadence must be even (on/off) */
15089             if (element_count % 2 == 1) {
15090                ast_log(LOG_ERROR, "Must be a silence duration for each ring duration: %s at line %d.\n", original_args, v->lineno);
15091                cadence_is_ok = 0;
15092             }
15093    
15094             /* Ring cadences cannot be negative */
15095             for (i = 0; i < element_count; i++) {
15096                if (c[i] == 0) {
15097                   ast_log(LOG_ERROR, "Ring or silence duration cannot be zero: %s at line %d.\n", original_args, v->lineno);
15098                   cadence_is_ok = 0;
15099                   break;
15100                } else if (c[i] < 0) {
15101                   if (i % 2 == 1) {
15102                      /* Silence duration, negative possibly okay */
15103                      if (cid_location == -1) {
15104                         cid_location = i;
15105                         c[i] *= -1;
15106                      } else {
15107                         ast_log(LOG_ERROR, "CID location specified twice: %s at line %d.\n", original_args, v->lineno);
15108                         cadence_is_ok = 0;
15109                         break;
15110                      }
15111                   } else {
15112                      if (firstcadencepos == 0) {
15113                         firstcadencepos = i; /* only recorded to avoid duplicate specification */
15114                                  /* duration will be passed negative to the DAHDI driver */
15115                      } else {
15116                          ast_log(LOG_ERROR, "First cadence position specified twice: %s at line %d.\n", original_args, v->lineno);
15117                         cadence_is_ok = 0;
15118                         break;
15119                      }
15120                   }
15121                }
15122             }
15123    
15124             /* Substitute our scanned cadence */
15125             for (i = 0; i < 16; i++) {
15126                new_cadence.ringcadence[i] = c[i];
15127             }
15128    
15129             if (cadence_is_ok) {
15130                /* ---we scanned it without getting annoyed; now some sanity checks--- */
15131                if (element_count < 2) {
15132                   ast_log(LOG_ERROR, "Minimum cadence is ring,pause: %s at line %d.\n", original_args, v->lineno);
15133                } else {
15134                   if (cid_location == -1) {
15135                      /* user didn't say; default to first pause */
15136                      cid_location = 1;
15137                   } else {
15138                      /* convert element_index to cidrings value */
15139                      cid_location = (cid_location + 1) / 2;
15140                   }
15141                   /* ---we like their cadence; try to install it--- */
15142                   if (!user_has_defined_cadences++)
15143                      /* this is the first user-defined cadence; clear the default user cadences */
15144                      num_cadence = 0;
15145                   if ((num_cadence+1) >= NUM_CADENCE_MAX)
15146                      ast_log(LOG_ERROR, "Already %d cadences; can't add another: %s at line %d.\n", NUM_CADENCE_MAX, original_args, v->lineno);
15147                   else {
15148                      cadences[num_cadence] = new_cadence;
15149                      cidrings[num_cadence++] = cid_location;
15150                      ast_verb(3, "cadence 'r%d' added: %s\n",num_cadence,original_args);
15151                   }
15152                }
15153             }
15154          } else if (!strcasecmp(v->name, "ringtimeout")) {
15155             ringt_base = (atoi(v->value) * 8) / READ_SIZE;
15156          } else if (!strcasecmp(v->name, "prewink")) {
15157             confp->timing.prewinktime = atoi(v->value);
15158          } else if (!strcasecmp(v->name, "preflash")) {
15159             confp->timing.preflashtime = atoi(v->value);
15160          } else if (!strcasecmp(v->name, "wink")) {
15161             confp->timing.winktime = atoi(v->value);
15162          } else if (!strcasecmp(v->name, "flash")) {
15163             confp->timing.flashtime = atoi(v->value);
15164          } else if (!strcasecmp(v->name, "start")) {
15165             confp->timing.starttime = atoi(v->value);
15166          } else if (!strcasecmp(v->name, "rxwink")) {
15167             confp->timing.rxwinktime = atoi(v->value);
15168          } else if (!strcasecmp(v->name, "rxflash")) {
15169             confp->timing.rxflashtime = atoi(v->value);
15170          } else if (!strcasecmp(v->name, "debounce")) {
15171             confp->timing.debouncetime = atoi(v->value);
15172          } else if (!strcasecmp(v->name, "toneduration")) {
15173             int toneduration;
15174             int ctlfd;
15175             int res;
15176             struct dahdi_dialparams dps;
15177 
15178             ctlfd = open("/dev/dahdi/ctl", O_RDWR);
15179             if (ctlfd == -1) {
15180                ast_log(LOG_ERROR, "Unable to open /dev/dahdi/ctl to set toneduration at line %d.\n", v->lineno);
15181                return -1;
15182             }
15183 
15184             toneduration = atoi(v->value);
15185             if (toneduration > -1) {
15186                memset(&dps, 0, sizeof(dps));
15187 
15188                dps.dtmf_tonelen = dps.mfv1_tonelen = toneduration;
15189                res = ioctl(ctlfd, DAHDI_SET_DIALPARAMS, &dps);
15190                if (res < 0) {
15191                   ast_log(LOG_ERROR, "Invalid tone duration: %d ms at line %d: %s\n", toneduration, v->lineno, strerror(errno));
15192                   return -1;
15193                }
15194             }
15195             close(ctlfd);
15196          } else if (!strcasecmp(v->name, "defaultcic")) {
15197             ast_copy_string(defaultcic, v->value, sizeof(defaultcic));
15198          } else if (!strcasecmp(v->name, "defaultozz")) {
15199             ast_copy_string(defaultozz, v->value, sizeof(defaultozz));
15200          } else if (!strcasecmp(v->name, "mwilevel")) {
15201             mwilevel = atoi(v->value);
15202          }
15203       } else if (!(options & PROC_DAHDI_OPT_NOWARN) )
15204          ast_log(LOG_WARNING, "Ignoring any changes to '%s' (on reload) at line %d.\n", v->name, v->lineno);
15205    }
15206    if (dahdichan[0]) { 
15207       /* The user has set 'dahdichan' */
15208       /*< \todo pass proper line number instead of 0 */
15209       if (build_channels(confp, 0, dahdichan, reload, 0, &found_pseudo)) {
15210          return -1;
15211       }
15212    }
15213    /*< \todo why check for the pseudo in the per-channel section.
15214     * Any actual use for manual setup of the pseudo channel? */
15215    if (!found_pseudo && reload != 1) {
15216       /* use the default configuration for a channel, so
15217          that any settings from real configured channels
15218          don't "leak" into the pseudo channel config
15219       */
15220       struct dahdi_chan_conf conf = dahdi_chan_conf_default();
15221 
15222       tmp = mkintf(CHAN_PSEUDO, &conf, NULL, reload);
15223 
15224       if (tmp) {
15225          ast_verb(3, "Automatically generated pseudo channel\n");
15226       } else {
15227          ast_log(LOG_WARNING, "Unable to register pseudo channel!\n");
15228       }
15229    }
15230    return 0;
15231 }
15232       
15233 static int setup_dahdi(int reload)
15234 {
15235    struct ast_config *cfg, *ucfg;
15236    struct ast_variable *v;
15237    struct dahdi_chan_conf base_conf = dahdi_chan_conf_default();
15238    struct dahdi_chan_conf conf;
15239    struct ast_flags config_flags = { reload == 1 ? CONFIG_FLAG_FILEUNCHANGED : 0 };
15240    const char *cat;
15241    int res;
15242 
15243 #ifdef HAVE_PRI
15244    char *c;
15245    int spanno;
15246    int i;
15247    int logicalspan;
15248    int trunkgroup;
15249    int dchannels[NUM_DCHANS];
15250 #endif
15251 
15252    cfg = ast_config_load(config, config_flags);
15253 
15254    /* Error if we have no config file */
15255    if (!cfg) {
15256       ast_log(LOG_ERROR, "Unable to load config %s\n", config);
15257       return 0;
15258    } else if (cfg == CONFIG_STATUS_FILEUNCHANGED) {
15259       ucfg = ast_config_load("users.conf", config_flags);
15260       if (ucfg == CONFIG_STATUS_FILEUNCHANGED)
15261          return 0;
15262       ast_clear_flag(&config_flags, CONFIG_FLAG_FILEUNCHANGED);
15263       cfg = ast_config_load(config, config_flags);
15264    } else {
15265       ast_clear_flag(&config_flags, CONFIG_FLAG_FILEUNCHANGED);
15266       ucfg = ast_config_load("users.conf", config_flags);
15267    }
15268 
15269    /* It's a little silly to lock it, but we mind as well just to be sure */
15270    ast_mutex_lock(&iflock);
15271 #ifdef HAVE_PRI
15272    if (reload != 1) {
15273       /* Process trunkgroups first */
15274       v = ast_variable_browse(cfg, "trunkgroups");
15275       while (v) {
15276          if (!strcasecmp(v->name, "trunkgroup")) {
15277             trunkgroup = atoi(v->value);
15278             if (trunkgroup > 0) {
15279                if ((c = strchr(v->value, ','))) {
15280                   i = 0;
15281                   memset(dchannels, 0, sizeof(dchannels));
15282                   while (c && (i < NUM_DCHANS)) {
15283                      dchannels[i] = atoi(c + 1);
15284                      if (dchannels[i] < 0) {
15285                         ast_log(LOG_WARNING, "D-channel for trunk group %d must be a postiive number at line %d of chan_dahdi.conf\n", trunkgroup, v->lineno);
15286                      } else
15287                         i++;
15288                      c = strchr(c + 1, ',');
15289                   }
15290                   if (i) {
15291                      if (pri_create_trunkgroup(trunkgroup, dchannels)) {
15292                         ast_log(LOG_WARNING, "Unable to create trunk group %d with Primary D-channel %d at line %d of chan_dahdi.conf\n", trunkgroup, dchannels[0], v->lineno);
15293                   } else
15294                         ast_verb(2, "Created trunk group %d with Primary D-channel %d and %d backup%s\n", trunkgroup, dchannels[0], i - 1, (i == 1) ? "" : "s");
15295                   } else
15296                      ast_log(LOG_WARNING, "Trunk group %d lacks any valid D-channels at line %d of chan_dahdi.conf\n", trunkgroup, v->lineno);
15297                } else
15298                   ast_log(LOG_WARNING, "Trunk group %d lacks a primary D-channel at line %d of chan_dahdi.conf\n", trunkgroup, v->lineno);
15299             } else
15300                ast_log(LOG_WARNING, "Trunk group identifier must be a positive integer at line %d of chan_dahdi.conf\n", v->lineno);
15301          } else if (!strcasecmp(v->name, "spanmap")) {
15302             spanno = atoi(v->value);
15303             if (spanno > 0) {
15304                if ((c = strchr(v->value, ','))) {
15305                   trunkgroup = atoi(c + 1);
15306                   if (trunkgroup > 0) {
15307                      if ((c = strchr(c + 1, ','))) 
15308                         logicalspan = atoi(c + 1);
15309                      else
15310                         logicalspan = 0;
15311                      if (logicalspan >= 0) {
15312                         if (pri_create_spanmap(spanno - 1, trunkgroup, logicalspan)) {
15313                            ast_log(LOG_WARNING, "Failed to map span %d to trunk group %d (logical span %d)\n", spanno, trunkgroup, logicalspan);
15314                      } else
15315                            ast_verb(2, "Mapped span %d to trunk group %d (logical span %d)\n", spanno, trunkgroup, logicalspan);
15316                      } else
15317                         ast_log(LOG_WARNING, "Logical span must be a postive number, or '0' (for unspecified) at line %d of chan_dahdi.conf\n", v->lineno);
15318                   } else
15319                      ast_log(LOG_WARNING, "Trunk group must be a postive number at line %d of chan_dahdi.conf\n", v->lineno);
15320                } else
15321                   ast_log(LOG_WARNING, "Missing trunk group for span map at line %d of chan_dahdi.conf\n", v->lineno);
15322             } else
15323                ast_log(LOG_WARNING, "Span number must be a postive integer at line %d of chan_dahdi.conf\n", v->lineno);
15324          } else {
15325             ast_log(LOG_NOTICE, "Ignoring unknown keyword '%s' in trunkgroups\n", v->name);
15326          }
15327          v = v->next;
15328       }
15329    }
15330 #endif
15331    
15332    /* Copy the default jb config over global_jbconf */
15333    memcpy(&global_jbconf, &default_jbconf, sizeof(global_jbconf));
15334 
15335    mwimonitornotify[0] = '\0';
15336 
15337    v = ast_variable_browse(cfg, "channels");
15338    if ((res = process_dahdi(&base_conf, "", v, reload, 0))) {
15339       ast_mutex_unlock(&iflock);
15340       ast_config_destroy(cfg);
15341       if (ucfg) {
15342          ast_config_destroy(ucfg);
15343       }
15344       return res;
15345    }
15346 
15347    /* Now get configuration from all normal sections in chan_dahdi.conf: */
15348    for (cat = ast_category_browse(cfg, NULL); cat ; cat = ast_category_browse(cfg, cat)) {
15349       /* [channels] and [trunkgroups] are used. Let's also reserve
15350        * [globals] and [general] for future use
15351        */
15352       if (!strcasecmp(cat, "general") || 
15353           !strcasecmp(cat, "trunkgroups") ||
15354           !strcasecmp(cat, "globals") ||
15355           !strcasecmp(cat, "channels")) {
15356          continue;
15357       }
15358 
15359       memcpy(&conf, &base_conf, sizeof(conf));
15360 
15361       if ((res = process_dahdi(&conf, cat, ast_variable_browse(cfg, cat), reload, PROC_DAHDI_OPT_NOCHAN))) {
15362          ast_mutex_unlock(&iflock);
15363          ast_config_destroy(cfg);
15364          if (ucfg) {
15365             ast_config_destroy(ucfg);
15366          }
15367          return res;
15368       }
15369    }
15370 
15371    ast_config_destroy(cfg);
15372 
15373    if (ucfg) {
15374       const char *chans;
15375 
15376       process_dahdi(&base_conf, "", ast_variable_browse(ucfg, "general"), 1, 0);
15377 
15378       for (cat = ast_category_browse(ucfg, NULL); cat ; cat = ast_category_browse(ucfg, cat)) {
15379          if (!strcasecmp(cat, "general")) {
15380             continue;
15381          }
15382 
15383          chans = ast_variable_retrieve(ucfg, cat, "dahdichan");
15384 
15385          if (ast_strlen_zero(chans)) {
15386             continue;
15387          }
15388 
15389          memcpy(&conf, &base_conf, sizeof(conf));
15390 
15391          if ((res = process_dahdi(&conf, cat, ast_variable_browse(ucfg, cat), reload, PROC_DAHDI_OPT_NOCHAN | PROC_DAHDI_OPT_NOWARN))) {
15392             ast_config_destroy(ucfg);
15393             ast_mutex_unlock(&iflock);
15394             return res;
15395          }
15396       }
15397       ast_config_destroy(ucfg);
15398    }
15399    ast_mutex_unlock(&iflock);
15400 
15401 #ifdef HAVE_PRI
15402    if (reload != 1) {
15403       int x;
15404       for (x = 0; x < NUM_SPANS; x++) {
15405          if (pris[x].pvts[0]) {
15406             if (start_pri(pris + x)) {
15407                ast_log(LOG_ERROR, "Unable to start D-channel on span %d\n", x + 1);
15408                return -1;
15409             } else
15410                ast_verb(2, "Starting D-Channel on span %d\n", x + 1);
15411          }
15412       }
15413    }
15414 #endif
15415 #ifdef HAVE_SS7
15416    if (reload != 1) {
15417       int x;
15418       for (x = 0; x < NUM_SPANS; x++) {
15419          if (linksets[x].ss7) {
15420             if (ast_pthread_create(&linksets[x].master, NULL, ss7_linkset, &linksets[x])) {
15421                ast_log(LOG_ERROR, "Unable to start SS7 linkset on span %d\n", x + 1);
15422                return -1;
15423             } else
15424                ast_verb(2, "Starting SS7 linkset on span %d\n", x + 1);
15425          }
15426       }
15427    }
15428 #endif
15429    /* And start the monitor for the first time */
15430    restart_monitor();
15431    return 0;
15432 }
15433 
15434 static int load_module(void)
15435 {
15436    int res;
15437 #if defined(HAVE_PRI) || defined(HAVE_SS7)
15438    int y, i;
15439 #endif
15440 
15441 #ifdef HAVE_PRI
15442    memset(pris, 0, sizeof(pris));
15443    for (y = 0; y < NUM_SPANS; y++) {
15444       ast_mutex_init(&pris[y].lock);
15445       pris[y].offset = -1;
15446       pris[y].master = AST_PTHREADT_NULL;
15447       for (i = 0; i < NUM_DCHANS; i++)
15448          pris[y].fds[i] = -1;
15449    }
15450    pri_set_error(dahdi_pri_error);
15451    pri_set_message(dahdi_pri_message);
15452    ast_register_application(dahdi_send_keypad_facility_app, dahdi_send_keypad_facility_exec,
15453          dahdi_send_keypad_facility_synopsis, dahdi_send_keypad_facility_descrip);
15454 #endif
15455 #ifdef HAVE_SS7
15456    memset(linksets, 0, sizeof(linksets));
15457    for (y = 0; y < NUM_SPANS; y++) {
15458       ast_mutex_init(&linksets[y].lock);
15459       linksets[y].master = AST_PTHREADT_NULL;
15460       for (i = 0; i < NUM_DCHANS; i++)
15461          linksets[y].fds[i] = -1;
15462    }
15463    ss7_set_error(dahdi_ss7_error);
15464    ss7_set_message(dahdi_ss7_message);
15465 #endif /* HAVE_SS7 */
15466    res = setup_dahdi(0);
15467    /* Make sure we can register our DAHDI channel type */
15468    if (res)
15469       return AST_MODULE_LOAD_DECLINE;
15470    if (ast_channel_register(&dahdi_tech)) {
15471       ast_log(LOG_ERROR, "Unable to register channel class 'DAHDI'\n");
15472       __unload_module();
15473       return AST_MODULE_LOAD_FAILURE;
15474    }
15475 #ifdef HAVE_PRI
15476    ast_string_field_init(&inuse, 16);
15477    ast_string_field_set(&inuse, name, "GR-303InUse");
15478    ast_cli_register_multiple(dahdi_pri_cli, ARRAY_LEN(dahdi_pri_cli));
15479 #endif   
15480 #ifdef HAVE_SS7
15481    ast_cli_register_multiple(dahdi_ss7_cli, ARRAY_LEN(dahdi_ss7_cli));
15482 #endif
15483 
15484    ast_cli_register_multiple(dahdi_cli, ARRAY_LEN(dahdi_cli));
15485    
15486    memset(round_robin, 0, sizeof(round_robin));
15487    ast_manager_register( "DAHDITransfer", 0, action_transfer, "Transfer DAHDI Channel" );
15488    ast_manager_register( "DAHDIHangup", 0, action_transferhangup, "Hangup DAHDI Channel" );
15489    ast_manager_register( "DAHDIDialOffhook", 0, action_dahdidialoffhook, "Dial over DAHDI channel while offhook" );
15490    ast_manager_register( "DAHDIDNDon", 0, action_dahdidndon, "Toggle DAHDI channel Do Not Disturb status ON" );
15491    ast_manager_register( "DAHDIDNDoff", 0, action_dahdidndoff, "Toggle DAHDI channel Do Not Disturb status OFF" );
15492    ast_manager_register("DAHDIShowChannels", 0, action_dahdishowchannels, "Show status DAHDI channels");
15493    ast_manager_register("DAHDIRestart", 0, action_dahdirestart, "Fully Restart DAHDI channels (terminates calls)");
15494 
15495    ast_cond_init(&mwi_thread_complete, NULL);
15496    ast_cond_init(&ss_thread_complete, NULL);
15497 
15498    return res;
15499 }
15500 
15501 static int dahdi_sendtext(struct ast_channel *c, const char *text)
15502 {
15503 #define  END_SILENCE_LEN 400
15504 #define  HEADER_MS 50
15505 #define  TRAILER_MS 5
15506 #define  HEADER_LEN ((HEADER_MS + TRAILER_MS) * 8)
15507 #define  ASCII_BYTES_PER_CHAR 80
15508 
15509    unsigned char *buf,*mybuf;
15510    struct dahdi_pvt *p = c->tech_pvt;
15511    struct pollfd fds[1];
15512    int size,res,fd,len,x;
15513    int bytes=0;
15514    /* Initial carrier (imaginary) */
15515    float cr = 1.0;
15516    float ci = 0.0;
15517    float scont = 0.0;
15518    int idx;
15519 
15520    idx = dahdi_get_index(c, p, 0);
15521    if (idx < 0) {
15522       ast_log(LOG_WARNING, "Huh?  I don't exist?\n");
15523       return -1;
15524    }
15525    if (!text[0]) return(0); /* if nothing to send, dont */
15526    if ((!p->tdd) && (!p->mate)) return(0);  /* if not in TDD mode, just return */
15527    if (p->mate) 
15528       buf = ast_malloc(((strlen(text) + 1) * ASCII_BYTES_PER_CHAR) + END_SILENCE_LEN + HEADER_LEN);
15529    else
15530       buf = ast_malloc(((strlen(text) + 1) * TDD_BYTES_PER_CHAR) + END_SILENCE_LEN);
15531    if (!buf)
15532       return -1;
15533    mybuf = buf;
15534    if (p->mate) {
15535       int codec = AST_LAW(p);
15536       for (x = 0; x < HEADER_MS; x++) {   /* 50 ms of Mark */
15537          PUT_CLID_MARKMS;
15538       }
15539       /* Put actual message */
15540       for (x = 0; text[x]; x++) {
15541          PUT_CLID(text[x]);
15542       }
15543       for (x = 0; x < TRAILER_MS; x++) {  /* 5 ms of Mark */
15544          PUT_CLID_MARKMS;
15545       }
15546       len = bytes;
15547       buf = mybuf;
15548    } else {
15549       len = tdd_generate(p->tdd, buf, text);
15550       if (len < 1) {
15551          ast_log(LOG_ERROR, "TDD generate (len %d) failed!!\n", (int)strlen(text));
15552          ast_free(mybuf);
15553          return -1;
15554       }
15555    }
15556    memset(buf + len, 0x7f, END_SILENCE_LEN);
15557    len += END_SILENCE_LEN;
15558    fd = p->subs[idx].dfd;
15559    while (len) {
15560       if (ast_check_hangup(c)) {
15561          ast_free(mybuf);
15562          return -1;
15563       }
15564       size = len;
15565       if (size > READ_SIZE)
15566          size = READ_SIZE;
15567       fds[0].fd = fd;
15568       fds[0].events = POLLOUT | POLLPRI;
15569       fds[0].revents = 0;
15570       res = poll(fds, 1, -1);
15571       if (!res) {
15572          ast_debug(1, "poll (for write) ret. 0 on channel %d\n", p->channel);
15573          continue;
15574       }
15575         /* if got exception */
15576       if (fds[0].revents & POLLPRI) {
15577          ast_free(mybuf);
15578          return -1;
15579       }
15580       if (!(fds[0].revents & POLLOUT)) {
15581          ast_debug(1, "write fd not ready on channel %d\n", p->channel);
15582          continue;
15583       }
15584       res = write(fd, buf, size);
15585       if (res != size) {
15586          if (res == -1) {
15587             ast_free(mybuf);
15588             return -1;
15589          }
15590          ast_debug(1, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel);
15591          break;
15592       }
15593       len -= size;
15594       buf += size;
15595    }
15596    ast_free(mybuf);
15597    return(0);
15598 }
15599 
15600 
15601 static int reload(void)
15602 {
15603    int res = 0;
15604 
15605    res = setup_dahdi(1);
15606    if (res) {
15607       ast_log(LOG_WARNING, "Reload of chan_dahdi.so is unsuccessful!\n");
15608       return -1;
15609    }
15610    return 0;
15611 }
15612 
15613 /* This is a workaround so that menuselect displays a proper description
15614  * AST_MODULE_INFO(, , "DAHDI Telephony"
15615  */
15616 
15617 #ifdef HAVE_PRI
15618 #ifdef HAVE_SS7
15619 #define tdesc "DAHDI Telephony w/PRI & SS7"
15620 #else
15621 #define tdesc "DAHDI Telephony w/PRI"
15622 #endif
15623 #else
15624 #ifdef HAVE_SS7
15625 #define tdesc "DAHDI Telephony w/SS7"
15626 #else
15627 #define tdesc "DAHDI Telephony"
15628 #endif
15629 #endif
15630 
15631 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, tdesc,
15632       .load = load_module,
15633       .unload = unload_module,
15634       .reload = reload,
15635           );
15636 
15637 

Generated on Wed Aug 18 22:33:46 2010 for Asterisk - the Open Source PBX by  doxygen 1.4.7